zaber.motion.gateway.Call Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of motion-library Show documentation
Show all versions of motion-library Show documentation
A library that aims to provide easy-to-use API for communication with Zaber devices using Zaber ASCII Protocol.
package zaber.motion.gateway;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
import com.google.protobuf.Parser;
import com.sun.jna.Pointer;
import zaber.motion.exceptions.MotionLibException;
import zaber.motion.gateway.GoLibraryLoader.NativeLibrary;
import zaber.motion.exceptions.LibraryIntegrationException;
import zaber.motion.protobufs.Main.Request;
import zaber.motion.protobufs.Main.Response;
import zaber.motion.exceptions.ExceptionConverter;
public final class Call {
private Call() {
}
private static Set garbageCollectorProtector = Collections.synchronizedSet(new HashSet<>());
public static T callSync(String request, Message requestData,
Parser parser) throws MotionLibException {
Request.Builder builder = Request.newBuilder().setRequest(request);
Request genRequest = builder.build();
List messages = new ArrayList();
messages.add(genRequest.toByteArray());
if (requestData != null) {
messages.add(requestData.toByteArray());
}
byte[] data = Serialization.serialize(messages);
List rawResponse = new ArrayList<>(1);
NativeLibrary.Func callbackSync = new NativeLibrary.Func() {
@Override
@SuppressWarnings("checkstyle:magicnumber")
public void invoke(Pointer response) {
byte[] sizeArray = response.getByteArray(0, Serialization.SIZE_TYPE_SIZE);
int size = Serialization.getSizeFromByteArrayLE(sizeArray, 0);
rawResponse.add(response.getByteArray(0, size));
}
};
int result = NativeLibrary.INSTANCE.call(data, (long) 0, callbackSync, (char) 0);
if (result != 0) {
throw new LibraryIntegrationException("Invalid result code: " + result);
}
List responses = Serialization.deserialize(rawResponse.get(0));
return parseResponse(responses, parser);
}
public static CompletableFuture callAsync(String request, Message requestData,
Parser parser) throws MotionLibException {
Request.Builder builder = Request.newBuilder().setRequest(request);
Request genRequest = builder.build();
List messages = new ArrayList();
messages.add(genRequest.toByteArray());
if (requestData != null) {
messages.add(requestData.toByteArray());
}
byte[] data = Serialization.serialize(messages);
CompletableFuture future = new CompletableFuture<>();
NativeLibrary.Func callbackAsync = new NativeLibrary.Func() {
@Override
@SuppressWarnings("checkstyle:magicnumber")
public void invoke(Pointer response) {
byte[] sizeArray = response.getByteArray(0, Serialization.SIZE_TYPE_SIZE);
int size = Serialization.getSizeFromByteArrayLE(sizeArray, 0);
future.complete(response.getByteArray(0, size));
}
};
garbageCollectorProtector.add(callbackAsync);
int result = NativeLibrary.INSTANCE.call(data, (long) 0, callbackAsync, (char) 1);
if (result != 0) {
throw new LibraryIntegrationException("Invalid result code: " + result);
}
return future.thenApply(rawResponse -> {
garbageCollectorProtector.remove(callbackAsync);
List rawResponses = Serialization.deserialize(rawResponse);
try {
return parseResponse(rawResponses, parser);
} catch (MotionLibException e) {
throw new CompletionException(e);
}
});
}
private static T parseResponse(List messages, Parser parser)
throws MotionLibException {
try {
Response response = Response.parseFrom(messages.get(0));
if (response.getResponse() != Response.ResponseType.OK) {
if (messages.size() > 1) {
throw ExceptionConverter.convert(response.getErrorType(), response.getErrorMessage(), messages.get(1));
}
throw ExceptionConverter.convert(response.getErrorType(), response.getErrorMessage());
}
if (parser != null && messages.size() == 1) {
throw new LibraryIntegrationException("No response from library");
}
if (parser == null && messages.size() > 1) {
throw new LibraryIntegrationException("Response from library ignored");
}
if (parser != null) {
return parser.parseFrom(messages.get(1));
}
return null;
} catch (InvalidProtocolBufferException e) {
throw new LibraryIntegrationException("Cannot parse response from library", e);
}
}
}