zaber.motion.gateway.Events 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.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.HashMap;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
import com.google.protobuf.Parser;
import com.sun.jna.Pointer;
import io.reactivex.Observable;
import io.reactivex.subjects.PublishSubject;
import io.reactivex.subjects.Subject;
import zaber.motion.exceptions.LibraryIntegrationException;
import zaber.motion.gateway.GoLibraryLoader.NativeLibrary;
import zaber.motion.protobufs.Main.AlertEvent;
import zaber.motion.protobufs.Main.BinaryReplyOnlyEvent;
import zaber.motion.protobufs.Main.DisconnectedEvent;
import zaber.motion.protobufs.Main.Event;
import zaber.motion.protobufs.Main.TestEvent;
import zaber.motion.protobufs.Main.UnknownBinaryResponseEvent;
import zaber.motion.protobufs.Main.UnknownResponseEvent;
class DaemonThreadFactory implements ThreadFactory {
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(runnable);
thread.setDaemon(true);
thread.setName("ZaberMotionEventExecutorThread");
return thread;
}
}
public final class Events {
private Events() {
}
private static Map eventParsers = initializeParserMap();
private static Subject eventObservable = PublishSubject.create();
private static Executor executor = Executors.newSingleThreadExecutor(new DaemonThreadFactory());
private static NativeLibrary.Func handleEvent = new NativeLibrary.Func() {
@Override
@SuppressWarnings("checkstyle:magicnumber")
public void invoke(Pointer response) {
int size = Serialization.getSizeFromByteArrayLE(response.getByteArray(0, Serialization.SIZE_TYPE_SIZE), 0);
byte[] responseArray = response.getByteArray(0, size);
executor.execute(() -> processEvent(responseArray));
}
};
public static void setEventHandler(NativeLibrary library) {
library.setEventHandler((long) 0, handleEvent);
}
private static void processEvent(byte[] rawResponse) {
List messages = Serialization.deserialize(rawResponse);
Event event = null;
Parser eventParser = null;
try {
event = Event.parseFrom(messages.get(0));
} catch (InvalidProtocolBufferException e) {
throw new LibraryIntegrationException("Cannot parse event from library", e);
}
String eventName = event.getEvent();
eventParser = eventParsers.get(eventName);
boolean hasEventData = messages.size() > 1;
boolean hasParser = (eventParser != null);
if (hasEventData != hasParser) {
throw new LibraryIntegrationException("Parser not provided or event has no data for " + eventName);
}
Message eventDataProto = null;
if (hasEventData) {
try {
eventDataProto = (Message) eventParser.parseFrom(messages.get(1));
} catch (InvalidProtocolBufferException e) {
throw new LibraryIntegrationException("Cannot parse event from library", e);
}
}
SdkEvent eventObject = new SdkEvent(event.getEvent(), eventDataProto);
eventObservable.onNext(eventObject);
}
private static Map initializeParserMap() {
Map parsers = new HashMap<>();
parsers.put("test/event", TestEvent.parser());
parsers.put("interface/unknown_response", UnknownResponseEvent.parser());
parsers.put("binary/interface/unknown_response", UnknownBinaryResponseEvent.parser());
parsers.put("interface/alert", AlertEvent.parser());
parsers.put("binary/interface/reply_only", BinaryReplyOnlyEvent.parser());
parsers.put("interface/disconnected", DisconnectedEvent.parser());
return parsers;
}
public static Observable getEventObservable() {
return eventObservable;
}
}