-
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.
- Loading branch information
Showing
8 changed files
with
497 additions
and
4 deletions.
There are no files selected for viewing
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
94 changes: 94 additions & 0 deletions
94
core/sdk/src/main/java/com/viam/sdk/core/component/servo/Servo.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,94 @@ | ||
package com.viam.sdk.core.component.servo; | ||
|
||
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; | ||
|
||
|
||
/** | ||
* Servo represents a physical servo | ||
*/ | ||
public abstract class Servo extends Component { | ||
public static final Subtype SUBTYPE = new Subtype( | ||
Subtype.NAMESPACE_RDK, | ||
Subtype.RESOURCE_TYPE_COMPONENT, | ||
"servo"); | ||
|
||
public Servo(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 Servo fromRobot(final RobotClient robot, final String name) { | ||
return robot.getResource(Servo.class, named(name)); | ||
} | ||
|
||
/** | ||
* Move the servo to the provided angle. | ||
* @param angle the desired angle of the servo in degrees | ||
*/ | ||
public abstract void move(int angle, Struct extra); | ||
|
||
/** | ||
* Move the servo to the provided angle. | ||
* @param angle the desired angle of the servo in degrees | ||
*/ | ||
public void move(int angle){ | ||
move(angle, Struct.getDefaultInstance()); | ||
} | ||
|
||
/** | ||
* Get the current angle (degrees) of the servo. | ||
* @return the current angle of the servo in degrees | ||
*/ | ||
public abstract int getPosition(Struct extra); | ||
|
||
/** | ||
* Get the current angle (degrees) of the servo. | ||
* @return the current angle of the servo in degrees | ||
*/ | ||
public int getPosition(){ | ||
return getPosition(Struct.getDefaultInstance()); | ||
} | ||
|
||
/** | ||
* Stop the servo. It is assumed that the servo stops immediately. | ||
*/ | ||
public abstract void stop(Struct extra); | ||
|
||
/** | ||
* Stop the servo. It is assumed that the servo stops immediately. | ||
*/ | ||
public void stop(){ | ||
stop(Struct.getDefaultInstance()); | ||
} | ||
|
||
|
||
/** | ||
* Get if the servo is currently moving. | ||
* @return whether the servo is moving | ||
*/ | ||
public abstract boolean isMoving(); | ||
|
||
|
||
} | ||
|
68 changes: 68 additions & 0 deletions
68
core/sdk/src/main/java/com/viam/sdk/core/component/servo/ServoRPCClient.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,68 @@ | ||
package com.viam.sdk.core.component.servo; | ||
|
||
import com.google.protobuf.Struct; | ||
import com.google.protobuf.Value; | ||
import com.viam.common.v1.Common; | ||
import com.viam.component.servo.v1.ServoServiceGrpc; | ||
|
||
import com.viam.sdk.core.rpc.Channel; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
|
||
public class ServoRPCClient extends Servo{ | ||
private final ServoServiceGrpc.ServoServiceBlockingStub client; | ||
|
||
public ServoRPCClient(final String name, final Channel chan) { | ||
super(name); | ||
final ServoServiceGrpc.ServoServiceBlockingStub client = ServoServiceGrpc.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 void move(int angle, Struct extra) { | ||
com.viam.component.servo.v1.Servo.MoveRequest moveRequest = com.viam.component.servo.v1.Servo.MoveRequest.newBuilder().setName(this.getName().getName()).setAngleDeg(angle).setExtra(extra).build(); | ||
client.move(moveRequest); | ||
} | ||
|
||
@Override | ||
public int getPosition(Struct extra) { | ||
com.viam.component.servo.v1.Servo.GetPositionRequest getPositionRequest = com.viam.component.servo.v1.Servo.GetPositionRequest.newBuilder().setName(this.getName().getName()).setExtra(extra).build(); | ||
return client.getPosition(getPositionRequest).getPositionDeg(); | ||
} | ||
|
||
|
||
@Override | ||
public void stop(Struct extra) { | ||
com.viam.component.servo.v1.Servo.StopRequest stopRequest = com.viam.component.servo.v1.Servo.StopRequest.newBuilder().setName(this.getName().getName()).setExtra(extra).build(); | ||
client.stop(stopRequest); | ||
} | ||
|
||
@Override | ||
public boolean isMoving() { | ||
com.viam.component.servo.v1.Servo.IsMovingRequest isMovingRequest = com.viam.component.servo.v1.Servo.IsMovingRequest.newBuilder().setName(this.getName().getName()).build(); | ||
return client.isMoving(isMovingRequest).getIsMoving(); | ||
} | ||
|
||
@Override | ||
public List<Common.Geometry> getGeometries(Optional<Struct> extra){ | ||
Common.GetGeometriesRequest.Builder builder = Common.GetGeometriesRequest.newBuilder().setName(this.getName().getName()); | ||
extra.ifPresent(builder::setExtra); | ||
return client.getGeometries(builder.build()).getGeometriesList(); | ||
|
||
} | ||
} | ||
|
76 changes: 76 additions & 0 deletions
76
core/sdk/src/main/java/com/viam/sdk/core/component/servo/ServoRPCService.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,76 @@ | ||
package com.viam.sdk.core.component.servo; | ||
import com.google.protobuf.Struct; | ||
import com.viam.common.v1.Common; | ||
import com.viam.component.servo.v1.ServoServiceGrpc; | ||
import com.viam.sdk.core.resource.ResourceRPCService; | ||
import com.viam.sdk.core.resource.ResourceManager; | ||
import io.grpc.stub.StreamObserver; | ||
|
||
import java.util.List; | ||
import java.util.Optional; | ||
|
||
|
||
public class ServoRPCService extends ServoServiceGrpc.ServoServiceImplBase implements ResourceRPCService<Servo> { | ||
|
||
private final ResourceManager manager; | ||
public ServoRPCService(ResourceManager manager) { this.manager = manager; } | ||
@Override | ||
public Class<Servo> getResourceClass() { | ||
return Servo.class; | ||
} | ||
|
||
@Override | ||
public ResourceManager getManager() { | ||
return manager; | ||
} | ||
|
||
@Override | ||
public void move(com.viam.component.servo.v1.Servo.MoveRequest request, StreamObserver<com.viam.component.servo.v1.Servo.MoveResponse> responseObserver) { | ||
Servo servo = getResource(Servo.named(request.getName())); | ||
servo.move(request.getAngleDeg(), request.getExtra()); | ||
responseObserver.onNext(com.viam.component.servo.v1.Servo.MoveResponse.newBuilder().build()); | ||
responseObserver.onCompleted(); | ||
} | ||
|
||
@Override | ||
public void stop(com.viam.component.servo.v1.Servo.StopRequest request, StreamObserver<com.viam.component.servo.v1.Servo.StopResponse> responseObserver) { | ||
Servo servo = getResource(Servo.named(request.getName())); | ||
servo.stop(); | ||
responseObserver.onNext(com.viam.component.servo.v1.Servo.StopResponse.newBuilder().build()); | ||
responseObserver.onCompleted(); | ||
} | ||
|
||
@Override | ||
public void getPosition(com.viam.component.servo.v1.Servo.GetPositionRequest request, StreamObserver<com.viam.component.servo.v1.Servo.GetPositionResponse> responseObserver) { | ||
Servo servo = getResource(Servo.named(request.getName())); | ||
int position = servo.getPosition(request.getExtra()); | ||
responseObserver.onNext(com.viam.component.servo.v1.Servo.GetPositionResponse.newBuilder().setPositionDeg(position).build()); | ||
responseObserver.onCompleted(); | ||
} | ||
|
||
@Override | ||
public void isMoving(com.viam.component.servo.v1.Servo.IsMovingRequest request, StreamObserver<com.viam.component.servo.v1.Servo.IsMovingResponse> responseObserver) { | ||
Servo servo = getResource(Servo.named(request.getName())); | ||
boolean isMoving = servo.isMoving(); | ||
responseObserver.onNext(com.viam.component.servo.v1.Servo.IsMovingResponse.newBuilder().setIsMoving(isMoving).build()); | ||
responseObserver.onCompleted(); | ||
} | ||
|
||
@Override | ||
public void getGeometries(com.viam.common.v1.Common.GetGeometriesRequest request, | ||
StreamObserver<com.viam.common.v1.Common.GetGeometriesResponse> responseObserver){ | ||
Servo servo = getResource(Servo.named(request.getName())); | ||
List<Common.Geometry> geometries = servo.getGeometries(Optional.ofNullable(request.getExtra())); | ||
responseObserver.onNext(Common.GetGeometriesResponse.newBuilder().addAllGeometries(geometries).build()); | ||
responseObserver.onCompleted(); | ||
} | ||
@Override | ||
public void doCommand(Common.DoCommandRequest request, | ||
StreamObserver<Common.DoCommandResponse> responseObserver) { | ||
|
||
Servo servo = getResource(Servo.named(request.getName())); | ||
Struct result = servo.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
92 changes: 92 additions & 0 deletions
92
core/sdk/src/test/kotlin/com/viam/sdk/core/component/servo/ServoRPCClientTest.kt
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,92 @@ | ||
package com.viam.sdk.core.component.servo | ||
|
||
import com.google.protobuf.Struct | ||
import com.google.protobuf.Value | ||
import com.viam.common.v1.Common.Geometry | ||
import com.viam.sdk.core.resource.ResourceManager | ||
import com.viam.sdk.core.rpc.BasicManagedChannel | ||
import io.grpc.inprocess.InProcessChannelBuilder | ||
import io.grpc.inprocess.InProcessServerBuilder | ||
import io.grpc.testing.GrpcCleanupRule | ||
import org.junit.Rule | ||
import org.junit.jupiter.api.Assertions.assertEquals | ||
import org.junit.jupiter.api.Assertions.assertFalse | ||
import org.junit.jupiter.api.BeforeEach | ||
import org.junit.jupiter.api.Test | ||
import org.mockito.Mockito.* | ||
import java.util.* | ||
|
||
class ServoRPCClientTest { | ||
private lateinit var servo: Servo | ||
private lateinit var client: ServoRPCClient | ||
|
||
@JvmField | ||
@Rule | ||
val grpcCleanupRule: GrpcCleanupRule = GrpcCleanupRule() | ||
|
||
@BeforeEach | ||
fun setup() { | ||
servo = mock( | ||
Servo::class.java, withSettings().useConstructor("mock-servo").defaultAnswer( | ||
CALLS_REAL_METHODS | ||
) | ||
) | ||
val resourceManager = ResourceManager(listOf(servo)) | ||
val service = ServoRPCService(resourceManager) | ||
val serviceName = InProcessServerBuilder.generateName() | ||
grpcCleanupRule.register( | ||
InProcessServerBuilder.forName(serviceName).directExecutor().addService(service).build().start() | ||
) | ||
val channel = grpcCleanupRule.register(InProcessChannelBuilder.forName(serviceName).directExecutor().build()) | ||
client = ServoRPCClient("mock-servo", BasicManagedChannel(channel)) | ||
} | ||
|
||
@Test | ||
fun move(){ | ||
val extra = | ||
Struct.newBuilder().putAllFields(mapOf("foo" to Value.newBuilder().setStringValue("bar").build())).build() | ||
client.move(20, extra) | ||
verify(servo).move(20, extra) | ||
|
||
} | ||
|
||
@Test | ||
fun stop() { | ||
client.stop() | ||
verify(servo).stop(Struct.getDefaultInstance()) | ||
} | ||
|
||
@Test | ||
fun isMoving() { | ||
`when`(servo.isMoving()).thenReturn(false) | ||
val isMoving = client.isMoving() | ||
verify(servo).isMoving() | ||
assertFalse(isMoving) | ||
} | ||
|
||
@Test | ||
fun getGeometries() { | ||
doReturn(listOf<Geometry>()).`when`(servo).getGeometries(any()) | ||
client.getGeometries(Optional.empty()) | ||
verify(servo).getGeometries(any()) | ||
} | ||
|
||
@Test | ||
fun getPosition() { | ||
`when`(servo.getPosition(any(Struct::class.java) ?: Struct.getDefaultInstance())).thenReturn(80) | ||
val pos = client.getPosition() | ||
verify(servo).getPosition(Struct.getDefaultInstance()) | ||
assertEquals(80, pos) | ||
} | ||
|
||
@Test | ||
fun doCommand() { | ||
val command = mapOf("foo" to Value.newBuilder().setStringValue("bar").build()) | ||
doReturn(Struct.newBuilder().putAllFields(command).build()).`when`(servo).doCommand(anyMap()) | ||
val response = client.doCommand(command) | ||
verify(servo).doCommand(command) | ||
assertEquals(command, response.fieldsMap) | ||
} | ||
|
||
|
||
} |
Oops, something went wrong.