diff --git a/plugins/PuckDetection.java b/plugins/PuckDetection.java new file mode 100644 index 0000000..58b6aaa --- /dev/null +++ b/plugins/PuckDetection.java @@ -0,0 +1,128 @@ + +import ch.psi.pshell.device.DeviceBase; +import ch.psi.utils.Arr; +import ch.psi.utils.State; +import java.io.IOException; +import java.util.ArrayList; +import java.util.logging.Level; + + +public class PuckDetection extends DeviceBase{ + public static final int PUCKS_NUMBER = 30; + final String server; + + public PuckDetection(String name, String server){ + super(name); + this.server = server.startsWith("tcp://") ? server : "tcp://" + server; + } + + + public static class PuckState{ + boolean online; + boolean mecSwitch; + boolean indSwitch; + + void clear(){ + online = false; + mecSwitch = false; + indSwitch = false; + } + void set(boolean mecSwitch, boolean indSwitch){ + online = true; + this.mecSwitch = mecSwitch; + this.indSwitch = indSwitch; + } + } + + PuckState[] pucks; + public PuckState[] getPucks(){ + return pucks; + } + + //From 1 to PUCKS_NUMBER + public PuckState getPuck(int id) throws Exception{ + assertInitialized(); + if ((id<=0) || (id>PUCKS_NUMBER)){ + throw new Exception("invalid puck id: "+ id); + } + return pucks[id-1]; + } + + + Thread thread; + + @Override + protected void doInitialize() throws IOException, InterruptedException{ + doClose(); + super.doInitialize(); + pucks = new PuckState[PUCKS_NUMBER]; + thread = new Thread(new Runnable() { + @Override + public void run() { + subscriberTask(); + } + }); + thread.setDaemon(true); + thread.start(); + } + + + void subscriberTask(){ + try{ + setState(State.Ready); + org.zeromq.ZMQ.Context context = org.zeromq.ZMQ.context(1); + org.zeromq.ZMQ.Socket subscriber = context.socket(org.zeromq.ZMQ.SUB); + subscriber.connect(server); + subscriber.subscribe("Status".getBytes()); + try{ + while (!Thread.currentThread().isInterrupted()) { + String type = subscriber.recvStr(); + String contents = subscriber.recvStr(); + processMessage(contents); + } + } finally{ + for (PuckState puck:pucks){ + puck.clear(); + } + subscriber.close(); + context.term(); + } + } catch (Exception ex){ + getLogger().log(Level.INFO, null, ex); + } + setState(State.Offline); + } + + void processMessage(String msg){ + ArrayList present = new ArrayList<>(); + for (String line:msg.split("\t")){ + try{ + line = line.trim(); + String[] tokens = line.split(" "); + int id = Integer.valueOf(tokens[0].substring(1)); + present.add(id); + PuckState puck = getPuck(id); + if (tokens.length<3){ + puck.clear(); + } else { + puck.set(tokens[1].equals("1"),tokens[2].equals("1")); + } + } catch (Exception ex){ + getLogger().log(Level.INFO, null, ex); + } + } + for (int i=1; i<= PUCKS_NUMBER; i++){ + if (!Arr.containsEqual(present.toArray(), i)){ + pucks[i-1].clear(); + } + } + } + + @Override + protected void doClose(){ + if (thread!=null){ + thread.interrupt(); + thread = null; + } + } +}