-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
RSDK-8714: add Powersensor wrappers (#62)
- Loading branch information
1 parent
ecac847
commit e10bc20
Showing
9 changed files
with
799 additions
and
0 deletions.
There are no files selected for viewing
84 changes: 84 additions & 0 deletions
84
core/sdk/src/main/java/com/viam/sdk/core/component/powersensor/PowerSensor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package com.viam.sdk.core.component.powersensor; | ||
|
||
import com.google.protobuf.Struct; | ||
import com.viam.common.v1.Common; | ||
import com.viam.sdk.core.component.Component; | ||
import com.viam.sdk.core.resource.Resource; | ||
import com.viam.sdk.core.resource.Subtype; | ||
import com.viam.sdk.core.robot.RobotClient; | ||
|
||
import java.util.Map.Entry; | ||
|
||
|
||
import java.util.Map; | ||
import java.util.Optional; | ||
|
||
/** | ||
* PowerSensor reports information about voltage, current and power. | ||
*/ | ||
public abstract class PowerSensor extends Component { | ||
public static final Subtype SUBTYPE = new Subtype( | ||
Subtype.NAMESPACE_RDK, | ||
Subtype.RESOURCE_TYPE_COMPONENT, | ||
"power_sensor"); | ||
|
||
public PowerSensor(final String name) { | ||
super(SUBTYPE, named(name)); | ||
} | ||
|
||
/** | ||
* Get the ResourceName of the component | ||
* | ||
* @param name the name of the component | ||
* @return the component's ResourceName | ||
*/ | ||
public static Common.ResourceName named(final String name) { | ||
return Resource.named(SUBTYPE, name); | ||
} | ||
|
||
/** | ||
* Get the component with the provided name from the provided robot. | ||
* | ||
* @param robot the RobotClient | ||
* @param name the name of the component | ||
* @return the component | ||
*/ | ||
public static PowerSensor fromRobot(final RobotClient robot, final String name) { | ||
return robot.getResource(PowerSensor.class, named(name)); | ||
} | ||
|
||
/** | ||
* Return the voltage reading of a specified device and whether it is AC or DC. | ||
* | ||
* @return the pair where the first double representing the voltage reading in V, the second bool indicating whether the voltage is AC (`true`) or DC | ||
* (`false`). | ||
*/ | ||
public abstract Entry<Double, Boolean> getVoltage(Optional<Struct> extra); | ||
|
||
/** | ||
* Return the current of a specified device and whether it is AC or DC. | ||
* | ||
* @return the pair where the first double representing the current reading in V, the second bool indicating whether the current is AC (`true`) or DC | ||
* * (`false`). | ||
*/ | ||
public abstract Entry<Double, Boolean> getCurrent(Optional<Struct> extra); | ||
|
||
/** | ||
* Return the power reading in watts. | ||
* | ||
* @return the power reading in watts | ||
*/ | ||
public abstract double getPower(Optional<Struct> extra); | ||
|
||
|
||
/** | ||
* Get the measurements or readings that this power sensor provides. If a sensor is not configured correctly or fails to read a | ||
* piece of data, it will not appear in the readings dictionary. | ||
* | ||
* @return The readings for the PowerSensor. Object should be of type Vector3, GeoPoint, Orientation, or any Value type. Includes voltage in volts (float), current in | ||
* amperes (float), is_ac (bool), and power in watts (float). | ||
*/ | ||
public abstract Map<String, Object> getReadings(Optional<Struct> extra); | ||
|
||
|
||
} |
66 changes: 66 additions & 0 deletions
66
core/sdk/src/main/java/com/viam/sdk/core/component/powersensor/PowerSensorRPCClient.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package com.viam.sdk.core.component.powersensor; | ||
|
||
import com.google.protobuf.Struct; | ||
import com.google.protobuf.Value; | ||
import com.viam.common.v1.Common; | ||
import com.viam.component.powersensor.v1.PowerSensorServiceGrpc; | ||
import com.viam.component.powersensor.v1.Powersensor; | ||
import com.viam.sdk.core.rpc.Channel; | ||
import com.viam.sdk.core.util.Utils; | ||
|
||
import java.util.Map; | ||
import java.util.Map.Entry; | ||
import java.util.Optional; | ||
|
||
public class PowerSensorRPCClient extends PowerSensor { | ||
private final PowerSensorServiceGrpc.PowerSensorServiceBlockingStub client; | ||
|
||
public PowerSensorRPCClient(final String name, final Channel chan) { | ||
super(name); | ||
final PowerSensorServiceGrpc.PowerSensorServiceBlockingStub client = PowerSensorServiceGrpc.newBlockingStub(chan); | ||
if (chan.getCallCredentials().isPresent()) { | ||
this.client = client.withCallCredentials(chan.getCallCredentials().get()); | ||
} else { | ||
this.client = client; | ||
} | ||
} | ||
|
||
@Override | ||
public Struct doCommand(final Map<String, Value> command) { | ||
return client.doCommand(Common.DoCommandRequest.newBuilder(). | ||
setName(getName().getName()). | ||
setCommand(Struct.newBuilder().putAllFields(command).build()). | ||
build()).getResult(); | ||
} | ||
|
||
@Override | ||
public Entry<Double, Boolean> getVoltage(Optional<Struct> extra) { | ||
Powersensor.GetVoltageRequest.Builder builder = com.viam.component.powersensor.v1.Powersensor.GetVoltageRequest.newBuilder().setName(this.getName().getName()); | ||
extra.ifPresent(builder::setExtra); | ||
Powersensor.GetVoltageResponse response = client.getVoltage(builder.build()); | ||
return Map.entry(response.getVolts(), response.getIsAc()); | ||
} | ||
|
||
@Override | ||
public Map.Entry<Double, Boolean> getCurrent(Optional<Struct> extra) { | ||
Powersensor.GetCurrentRequest.Builder builder = com.viam.component.powersensor.v1.Powersensor.GetCurrentRequest.newBuilder().setName(this.getName().getName()); | ||
extra.ifPresent(builder::setExtra); | ||
Powersensor.GetCurrentResponse response = client.getCurrent(builder.build()); | ||
return Map.entry(response.getAmperes(), response.getIsAc()); | ||
} | ||
|
||
@Override | ||
public double getPower(Optional<Struct> extra) { | ||
Powersensor.GetPowerRequest.Builder builder = com.viam.component.powersensor.v1.Powersensor.GetPowerRequest.newBuilder().setName(this.getName().getName()); | ||
extra.ifPresent(builder::setExtra); | ||
return client.getPower(builder.build()).getWatts(); | ||
} | ||
|
||
@Override | ||
public Map<String, Object> getReadings(Optional<Struct> extra) { | ||
Common.GetReadingsRequest.Builder builder = Common.GetReadingsRequest.newBuilder().setName(this.getName().getName()); | ||
extra.ifPresent(builder::setExtra); | ||
return Utils.sensorReadingsValueToNative(client.getReadings(builder.build()).getReadingsMap()); | ||
|
||
} | ||
} |
78 changes: 78 additions & 0 deletions
78
core/sdk/src/main/java/com/viam/sdk/core/component/powersensor/PowerSensorRPCService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package com.viam.sdk.core.component.powersensor; | ||
|
||
import com.google.protobuf.Struct; | ||
import com.google.protobuf.Value; | ||
import com.viam.common.v1.Common; | ||
import com.viam.component.powersensor.v1.PowerSensorServiceGrpc; | ||
import com.viam.component.powersensor.v1.Powersensor; | ||
import com.viam.sdk.core.resource.ResourceManager; | ||
import com.viam.sdk.core.resource.ResourceRPCService; | ||
import com.viam.sdk.core.util.Utils; | ||
import io.grpc.stub.StreamObserver; | ||
|
||
import java.util.Map; | ||
import java.util.Map.Entry; | ||
import java.util.Optional; | ||
|
||
public class PowerSensorRPCService extends PowerSensorServiceGrpc.PowerSensorServiceImplBase implements ResourceRPCService<PowerSensor> { | ||
|
||
private final ResourceManager manager; | ||
|
||
public PowerSensorRPCService(ResourceManager manager) { | ||
this.manager = manager; | ||
} | ||
|
||
@Override | ||
public Class<PowerSensor> getResourceClass() { | ||
return PowerSensor.class; | ||
} | ||
|
||
@Override | ||
public ResourceManager getManager() { | ||
return manager; | ||
} | ||
|
||
|
||
@Override | ||
public void getVoltage(Powersensor.GetVoltageRequest request, StreamObserver<Powersensor.GetVoltageResponse> responseObserver) { | ||
PowerSensor powerSensor = getResource(PowerSensor.named(request.getName())); | ||
Entry<Double, Boolean> voltage = powerSensor.getVoltage(Optional.of(request.getExtra())); | ||
responseObserver.onNext(com.viam.component.powersensor.v1.Powersensor.GetVoltageResponse.newBuilder().setVolts(voltage.getKey()).setIsAc(voltage.getValue()).build()); | ||
responseObserver.onCompleted(); | ||
} | ||
|
||
@Override | ||
public void getCurrent(Powersensor.GetCurrentRequest request, StreamObserver<Powersensor.GetCurrentResponse> responseObserver) { | ||
PowerSensor powerSensor = getResource(PowerSensor.named(request.getName())); | ||
Entry<Double, Boolean> current = powerSensor.getCurrent(Optional.of(request.getExtra())); | ||
responseObserver.onNext(com.viam.component.powersensor.v1.Powersensor.GetCurrentResponse.newBuilder().setAmperes(current.getKey()).setIsAc(current.getValue()).build()); | ||
responseObserver.onCompleted(); | ||
} | ||
|
||
@Override | ||
public void getPower(Powersensor.GetPowerRequest request, StreamObserver<Powersensor.GetPowerResponse> responseObserver) { | ||
PowerSensor powerSensor = getResource(PowerSensor.named(request.getName())); | ||
double power = powerSensor.getPower(Optional.of(request.getExtra())); | ||
responseObserver.onNext(com.viam.component.powersensor.v1.Powersensor.GetPowerResponse.newBuilder().setWatts(power).build()); | ||
responseObserver.onCompleted(); | ||
} | ||
|
||
@Override | ||
public void getReadings(Common.GetReadingsRequest request, StreamObserver<Common.GetReadingsResponse> responseObserver) { | ||
PowerSensor powerSensor = getResource(PowerSensor.named(request.getName())); | ||
Map<String, Value> readings = Utils.sensorReadingsNativeToValue(powerSensor.getReadings(Optional.of(request.getExtra()))); | ||
responseObserver.onNext(Common.GetReadingsResponse.newBuilder().putAllReadings(readings).build()); | ||
responseObserver.onCompleted(); | ||
} | ||
@Override | ||
public void doCommand(Common.DoCommandRequest request, | ||
StreamObserver<Common.DoCommandResponse> responseObserver) { | ||
|
||
PowerSensor powerSensor = getResource(PowerSensor.named(request.getName())); | ||
Struct result = powerSensor.doCommand(request.getCommand().getFieldsMap()); | ||
responseObserver.onNext(Common.DoCommandResponse.newBuilder().setResult(result).build()); | ||
responseObserver.onCompleted(); | ||
} | ||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
131 changes: 131 additions & 0 deletions
131
core/sdk/src/main/java/com/viam/sdk/core/util/Utils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
package com.viam.sdk.core.util; | ||
|
||
import com.google.protobuf.*; | ||
import com.viam.common.v1.Common; | ||
|
||
import java.util.*; | ||
|
||
public class Utils { | ||
public static Object valueToNative(Value v) { | ||
switch (v.getKindCase()) { | ||
case STRUCT_VALUE: { | ||
Map<String, Value> structMap = v.getStructValue().getFieldsMap(); | ||
if (structMap.get("_type") != null) { | ||
switch (structMap.get("_type").getStringValue()) { | ||
case ("vector3"): { | ||
return Common.Vector3.newBuilder().setX(structMap.get("x").getNumberValue()).setY(structMap.get("y").getNumberValue()).setZ(structMap.get("z").getNumberValue()).build(); | ||
} | ||
case ("geopoint"): { | ||
return Common.GeoPoint.newBuilder().setLatitude(structMap.get("lat").getNumberValue()).setLongitude(structMap.get("lng").getNumberValue()).build(); | ||
} | ||
case ("orientation_vector_degrees"): { | ||
return Common.Orientation.newBuilder().setOX(structMap.get("ox").getNumberValue()).setOY(structMap.get("oy").getNumberValue()).setOZ(structMap.get("oz").getNumberValue()).setTheta(structMap.get("theta").getNumberValue()).build(); | ||
} | ||
} | ||
|
||
} else { | ||
Map<String, Object> nativeMap = new HashMap<>(); | ||
for (Map.Entry<String, Value> entry : structMap.entrySet()) { | ||
nativeMap.put(entry.getKey(), valueToNative(entry.getValue())); | ||
} | ||
return nativeMap; | ||
|
||
} | ||
|
||
|
||
} | ||
case LIST_VALUE: { | ||
List<Object> list = new ArrayList<>(); | ||
for (Value val : v.getListValue().getValuesList()) { | ||
list.add(valueToNative(val)); | ||
} | ||
return list; | ||
|
||
} | ||
case BOOL_VALUE: | ||
return v.getBoolValue(); | ||
case NUMBER_VALUE: | ||
return v.getNumberValue(); | ||
case STRING_VALUE: | ||
return v.getStringValue(); | ||
case NULL_VALUE: | ||
return v.getNullValue(); | ||
default: | ||
return v; | ||
} | ||
|
||
|
||
} | ||
|
||
public static Value nativeToValue(Object obj) throws IllegalArgumentException { | ||
if (obj instanceof Common.Vector3) { | ||
Struct struct = Struct.newBuilder() | ||
.putFields("x", Value.newBuilder().setNumberValue(((Common.Vector3) obj).getX()).build()) | ||
.putFields("y", Value.newBuilder().setNumberValue(((Common.Vector3) obj).getY()).build()) | ||
.putFields("z", Value.newBuilder().setNumberValue(((Common.Vector3) obj).getZ()).build()) | ||
.putFields("_type", Value.newBuilder().setStringValue("vector3").build()) | ||
.build(); | ||
return Value.newBuilder().setStructValue(struct).build(); | ||
|
||
} else if (obj instanceof Common.GeoPoint) { | ||
Struct struct = Struct.newBuilder() | ||
.putFields("lat", Value.newBuilder().setNumberValue(((Common.GeoPoint) obj).getLatitude()).build()) | ||
.putFields("lng", Value.newBuilder().setNumberValue(((Common.GeoPoint) obj).getLongitude()).build()) | ||
.putFields("_type", Value.newBuilder().setStringValue("geopoint").build()) | ||
.build(); | ||
return Value.newBuilder().setStructValue(struct).build(); | ||
} else if (obj instanceof Common.Orientation) { | ||
Struct struct = Struct.newBuilder() | ||
.putFields("ox", Value.newBuilder().setNumberValue(((Common.Orientation) obj).getOX()).build()) | ||
.putFields("oy", Value.newBuilder().setNumberValue(((Common.Orientation) obj).getOY()).build()) | ||
.putFields("oz", Value.newBuilder().setNumberValue(((Common.Orientation) obj).getOZ()).build()) | ||
.putFields("theta", Value.newBuilder().setNumberValue(((Common.Orientation) obj).getTheta()).build()) | ||
.putFields("_type", Value.newBuilder().setStringValue("orientation_vector_degrees").build()) | ||
.build(); | ||
return Value.newBuilder().setStructValue(struct).build(); | ||
|
||
} else if (obj instanceof Number) { | ||
return Value.newBuilder().setNumberValue((double) obj).build(); | ||
} else if (obj instanceof String) { | ||
return Value.newBuilder().setStringValue((String) obj).build(); | ||
} else if(obj instanceof byte[]){ | ||
return Value.newBuilder().setStringValue(new String((byte[]) obj)).build(); | ||
}else if (obj instanceof Boolean) { | ||
return Value.newBuilder().setBoolValue((Boolean) obj).build(); | ||
} else if (obj instanceof List) { | ||
ListValue.Builder listBuilder = ListValue.newBuilder(); | ||
for (Object o : (List<Object>) obj) { | ||
listBuilder.addValues(nativeToValue(o)); | ||
} | ||
return Value.newBuilder().setListValue(listBuilder.build()).build(); | ||
} else if (obj instanceof Map) { | ||
Struct.Builder structBuilder = Struct.newBuilder(); | ||
for (Map.Entry<Object, Object> entry : ((Map<Object, Object>) obj).entrySet()) { | ||
if(!(entry.getKey() instanceof String)) throw new IllegalArgumentException(); | ||
else structBuilder.putFields((String) entry.getKey(), nativeToValue(entry.getValue())); | ||
} | ||
return Value.newBuilder().setStructValue(structBuilder.build()).build(); | ||
|
||
} | ||
else throw new IllegalArgumentException(); | ||
} | ||
|
||
public static Map<String, Value> sensorReadingsNativeToValue(Map<String, Object> readings) { | ||
Map<String, Value> valueMap = new HashMap<>(); | ||
for (Map.Entry<String, Object> entry : readings.entrySet()) { | ||
valueMap.put(entry.getKey(), nativeToValue(entry.getValue())); | ||
} | ||
return valueMap; | ||
} | ||
|
||
public static Map<String, Object> sensorReadingsValueToNative(Map<String, Value> readings) { | ||
Map<String, Object> map = new HashMap<>(); | ||
for (Map.Entry<String, Value> entry : readings.entrySet()) { | ||
map.put(entry.getKey(), valueToNative(entry.getValue())); | ||
|
||
} | ||
return map; | ||
} | ||
|
||
|
||
} |
Oops, something went wrong.