LLRP Motorola 9500 Not sending read tag event

1.1k views Asked by At

We are trying to connect FX9500 using LLRP tool kit code. We would like to receive read tag as soon as they come into range. From messages it looks like all add/set config are done properly, but can't receive events.

Attached are code and XML output of messages being exchanged. XML Messages are at : http://gadgetnapps.blogspot.in/2016/02/llrp-xml-messages.html

Thanks in advance.

    public class LLRPHelloWorld {
    private static String ipAddress = null;
    private static int readerPort = -1;
    private Socket connection;
    private DataOutputStream out;
    private static int ROSPEC_ID = 999;
    private static Logger logger;
    private ReadThread rt = null;
    static AppCtx ctxMain;

    public static void rfidMain(String ipAdString, int port, AppCtx ctx) {
        logger = Logger.getLogger(LLRPHelloWorld.class);
        ipAddress = ipAdString;
        readerPort = port;
        ctxMain = ctx; 
        try {
            new LLRPHelloWorld();
            logger.info("LLRP Hello World has terminated");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * The constructor creates a connection to the reader and sends LLRP
     * messages. It first sends a GET_READER_CAPABILIITIES message and a
     * SET_READER_CONFIG message. Then it creates an ROSpec with null start and
     * stop triggers. After it enables and starts the ROSpec. It waits for a few
     * seconds to receive tag reads before it disables and deletes the ROSpec.
     * Finally it ends the LLRP connection.
     * 
     * @param ctx
     * 
     * @throws IOException
     */
    public LLRPHelloWorld() throws IOException {

        // Try to establish a connection to the reader
        connection = new Socket(ipAddress, readerPort);
        out = new DataOutputStream(connection.getOutputStream());

        // Start up the ReaderThread to read messages form socket to Console
        rt = new ReadThread(connection);
        rt.start();

        // Wait for the NotificationEvent the Reader sends whenever a
        // connection attempt is made
        pause(250);
        LLRPMessage m = rt.getNextMessage();
        READER_EVENT_NOTIFICATION readerEventNotification = (READER_EVENT_NOTIFICATION) m;

        ReaderEventNotificationData red = readerEventNotification
                .getReaderEventNotificationData();
        if (red.getConnectionAttemptEvent() != null) {
            logger.info("Connection attempt was successful");
        } else {
            logger.error("Connection attempt was unsucessful");
            System.exit(-1);
        }

        // Create a GET_READER_CAPABILITIES Message and send it to the reader
        GET_READER_CAPABILITIES getReaderCap = new GET_READER_CAPABILITIES();
        getReaderCap.setRequestedData(new GetReaderCapabilitiesRequestedData(
                GetReaderCapabilitiesRequestedData.All));
        write(getReaderCap, "GET_READER_CAPABILITIES");
        pause(250);

        // Create a SET_READER_CONFIG Message and send it to the reader
        SET_READER_CONFIG setReaderConfig = createSetReaderConfig();
        write(setReaderConfig, "SET_READER_CONFIG");
        pause(250);

        // CREATE an ADD_ROSPEC Message and send it to the reader
        ADD_ROSPEC addROSpec = new ADD_ROSPEC();
        addROSpec.setROSpec(createROSpec());
        write(addROSpec, "ADD_ROSPEC");
        pause(250);

        // Create an ENABLE_ROSPEC message and send it to the reader
        ENABLE_ROSPEC enableROSpec = new ENABLE_ROSPEC();
        enableROSpec.setROSpecID(new UnsignedInteger(ROSPEC_ID));
        write(enableROSpec, "ENABLE_ROSPEC");
        pause(250);

        boolean flg = true;
        START_ROSPEC startROSpec = new START_ROSPEC();
        startROSpec.setROSpecID(new UnsignedInteger(ROSPEC_ID));
        write(startROSpec, "START_ROSPEC");
        while (flg) {
            // Create a START_ROSPEC message and send it to the reader
            LLRPMessage msg = rt.getNextMessage();
            try {
                System.err.println(msg+"--->"+msg.toXMLString());
            } catch (InvalidLLRPMessageException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
//          pause(4000);
//          System.err.println("main test 4s");

            // Create a STOP_ROSPEC message and send it to the reader
//          STOP_ROSPEC stopROSpec = new STOP_ROSPEC();
//          stopROSpec.setROSpecID(new UnsignedInteger(ROSPEC_ID));
//          write(stopROSpec, "STOP_ROSPEC");
//          
//          pause(4000);
//          startROSpec = new START_ROSPEC();
//          startROSpec.setROSpecID(new UnsignedInteger(ROSPEC_ID));
//          write(startROSpec, "START_ROSPEC");
//          
        }
        // Create a DISABLE_ROSPEC message and send it to the reader
        DISABLE_ROSPEC disableROSpec = new DISABLE_ROSPEC();
        disableROSpec.setROSpecID(new UnsignedInteger(ROSPEC_ID));
        write(disableROSpec, "DISABLE_ROSPEC");
        pause(250);

        // Create a DELTE_ROSPEC message and send it to the reader
        DELETE_ROSPEC deleteROSpec = new DELETE_ROSPEC();
        deleteROSpec.setROSpecID(new UnsignedInteger(ROSPEC_ID));
        write(deleteROSpec, "DELETE_ROSPEC");
        pause(250);

        // wait for one second before closing the connection
        pause(1000);

        // Create a CLOSE_CONNECTION message and send it to the reader
        CLOSE_CONNECTION cc = new CLOSE_CONNECTION();
        write(cc, "CloseConnection");

        synchronized (rt) {
            try {
                logger.debug("Wait for the Reader to close the Connection");
                rt.wait();
//              KEEPALIVE_ACK
            } catch (InterruptedException e) {
                // Quit the Program
            }
        }

    }

    /**
     * This method creates a ROSpec with null start and stop triggers
     * 
     * @return
     */
    private ROSpec createROSpec() {

        // create a new rospec
        ROSpec roSpec = new ROSpec();
        roSpec.setPriority(new UnsignedByte(0));
        roSpec.setCurrentState(new ROSpecState(ROSpecState.Disabled));//rathi
        roSpec.setROSpecID(new UnsignedInteger(ROSPEC_ID));

        // set up ROBoundary (start and stop triggers)
        ROBoundarySpec roBoundarySpec = new ROBoundarySpec();

        ROSpecStartTrigger startTrig = new ROSpecStartTrigger();
        startTrig.setROSpecStartTriggerType(new ROSpecStartTriggerType(
                ROSpecStartTriggerType.Immediate));
//      PeriodicTriggerValue pt =new PeriodicTriggerValue();
//      pt.setPeriod(new UnsignedInteger(1));
//      pt.setOffset(new UnsignedInteger(0));
//      startTrig.setPeriodicTriggerValue(pt);
        roBoundarySpec.setROSpecStartTrigger(startTrig);

        ROSpecStopTrigger stopTrig = new ROSpecStopTrigger();
        stopTrig.setDurationTriggerValue(new UnsignedInteger(0));
        stopTrig.setROSpecStopTriggerType(new ROSpecStopTriggerType(
                ROSpecStopTriggerType.Null));
        roBoundarySpec.setROSpecStopTrigger(stopTrig);

        roSpec.setROBoundarySpec(roBoundarySpec);

        // Add an AISpec
        AISpec aispec = new AISpec();

        // set AI Stop trigger to null
        AISpecStopTrigger aiStopTrigger = new AISpecStopTrigger();
        aiStopTrigger.setAISpecStopTriggerType(new AISpecStopTriggerType(
                AISpecStopTriggerType.Null));//null
        aiStopTrigger.setDurationTrigger(new UnsignedInteger(0));
        aispec.setAISpecStopTrigger(aiStopTrigger);

        UnsignedShortArray antennaIDs = new UnsignedShortArray();
        antennaIDs.add(new UnsignedShort(0));
        aispec.setAntennaIDs(antennaIDs);

        InventoryParameterSpec inventoryParam = new InventoryParameterSpec();
        inventoryParam.setProtocolID(new AirProtocols(
                AirProtocols.EPCGlobalClass1Gen2));
        inventoryParam.setInventoryParameterSpecID(new UnsignedShort(1));
        aispec.addToInventoryParameterSpecList(inventoryParam);

        roSpec.addToSpecParameterList(aispec);

        return roSpec;
    }

    /**
     * This method creates a SET_READER_CONFIG method
     * 
     * @return
     */
    private SET_READER_CONFIG createSetReaderConfig() {
        SET_READER_CONFIG setReaderConfig = new SET_READER_CONFIG();

        // Create a default RoReportSpec so that reports are sent at the end of
        // ROSpecs

        ROReportSpec roReportSpec = new ROReportSpec();
        roReportSpec.setN(new UnsignedShort(0));
        roReportSpec.setROReportTrigger(new ROReportTriggerType(
                ROReportTriggerType.Upon_N_Tags_Or_End_Of_ROSpec));
//Enable keep alive 
//      KeepaliveSpec ka = new KeepaliveSpec();
//      KeepaliveTriggerType ktype = new KeepaliveTriggerType();
//      ktype.set(KeepaliveTriggerType.Periodic);
//      ka.setPeriodicTriggerValue(new UnsignedInteger(100));
//      ka.setKeepaliveTriggerType(ktype);
//      setReaderConfig.setKeepaliveSpec(ka);
//       
        TagReportContentSelector tagReportContentSelector = new TagReportContentSelector();
        tagReportContentSelector.setEnableAccessSpecID(new Bit(0));
        tagReportContentSelector.setEnableAntennaID(new Bit(1));
        tagReportContentSelector.setEnableChannelIndex(new Bit(0));
        tagReportContentSelector.setEnableFirstSeenTimestamp(new Bit(0));
        tagReportContentSelector.setEnableInventoryParameterSpecID(new Bit(1));
        tagReportContentSelector.setEnableLastSeenTimestamp(new Bit(0));
        tagReportContentSelector.setEnablePeakRSSI(new Bit(0));
        tagReportContentSelector.setEnableROSpecID(new Bit(1));
        tagReportContentSelector.setEnableSpecIndex(new Bit(0));
        tagReportContentSelector.setEnableTagSeenCount(new Bit(0));
        // tagReport.
        C1G2EPCMemorySelector epcMemSel = new C1G2EPCMemorySelector();
        epcMemSel.setEnableCRC(new Bit(0));
        epcMemSel.setEnablePCBits(new Bit(0));
        tagReportContentSelector
                .addToAirProtocolEPCMemorySelectorList(epcMemSel);
        roReportSpec.setTagReportContentSelector(tagReportContentSelector);
        setReaderConfig.setROReportSpec(roReportSpec);

        // Set default AccessReportSpec

        AccessReportSpec accessReportSpec = new AccessReportSpec();
        accessReportSpec.setAccessReportTrigger(new AccessReportTriggerType(
                AccessReportTriggerType.End_Of_AccessSpec));
        setReaderConfig.setAccessReportSpec(accessReportSpec);

        // Set up reporting for AISpec events, ROSpec events, and GPI Events

        ReaderEventNotificationSpec eventNoteSpec = new ReaderEventNotificationSpec();

        EventNotificationState noteState = new EventNotificationState();
        noteState.setEventType(new NotificationEventType(
                NotificationEventType.AISpec_Event));
        noteState.setNotificationState(new Bit(1));
        eventNoteSpec.addToEventNotificationStateList(noteState);

        noteState = new EventNotificationState();
        noteState.setEventType(new NotificationEventType(
                NotificationEventType.ROSpec_Event));
        noteState.setNotificationState(new Bit(1));
        eventNoteSpec.addToEventNotificationStateList(noteState);

        noteState = new EventNotificationState();
        noteState.setEventType(new NotificationEventType(
                NotificationEventType.GPI_Event));
        noteState.setNotificationState(new Bit(1));
        eventNoteSpec.addToEventNotificationStateList(noteState);

        noteState = new EventNotificationState();
        noteState.setEventType(new NotificationEventType(
                NotificationEventType.Antenna_Event));
        noteState.setNotificationState(new Bit(1));
        eventNoteSpec.addToEventNotificationStateList(noteState);

        setReaderConfig.setReaderEventNotificationSpec(eventNoteSpec);

        setReaderConfig.setResetToFactoryDefault(new Bit(0));

        return setReaderConfig;

    }

    /**
     * This method causes the calling thread to sleep for a specified number of
     * milliseconds
     * 
     * @param ms
     */
    private void pause(long ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * Send a llrp message to the reader
     * 
     * @param msg
     *            Message to be send
     * @param message
     *            Description for output purposes
     */
    private void write(LLRPMessage msg, String message) {
        try {
            logger.info(" Sending message: \n" + msg.toXMLString());
            out.write(msg.encodeBinary());
        } catch (IOException e) {
            logger.error("Couldn't send Command ", e);
        } catch (InvalidLLRPMessageException e) {
            logger.error("Couldn't send Command", e);
        }
    }

    /**
     * 
     * This class is a allows LLRP messages to be read on a separate thread
     * 
     * @author Kyle Neumeier
     * @author Andreas Huebner
     *
     */
    class ReadThread extends Thread {

        /**
         * The incoming data stream from the LLRP reader connection
         */
        private DataInputStream inStream = null;

        /**
         * The socket for the connection to the LLRP Reader
         */
        private Socket socket = null;

        /**
         * A queue to store incoming LLRP Messages
         */
        private LinkedBlockingQueue<LLRPMessage> queue = null;

        /**
         * Thread for constant reading of the stream
         * 
         * @param inStream
         */
        public ReadThread(Socket socket) {
            this.socket = socket;
            this.queue = new LinkedBlockingQueue<LLRPMessage>();
            try {
                this.inStream = new DataInputStream(socket.getInputStream());
            } catch (IOException e) {
                logger.error("Cannot get input stream", e);
            }
        }

        @Override
        public void run() {
            int i = 0;
            super.run();
            if (socket.isConnected()) {
                while (!socket.isClosed()) {
                    LLRPMessage message = null;
                    try {
                        message = read();
                        if (message != null) {
                            queue.put(message);
                             logger.info("Received Message: \n"
                             + message);//.toXMLString());
                            if (message instanceof org.llrp.ltk.generated.messages.RO_ACCESS_REPORT) {
                                // logger.info("Received Message: \n"
                                // + message.toXMLString());
                                RO_ACCESS_REPORT re = (RO_ACCESS_REPORT) message;
                                java.util.List<TagReportData> list = re
                                        .getTagReportDataList();
                                for (TagReportData tagReportData : list) {
                                    if (tagReportData.getEPCParameter() instanceof EPC_96) {
                                        EPC_96 epc = (EPC_96) tagReportData
                                                .getEPCParameter();
                                        System.err
                                                .println("=====================================>>>>>>>>>>>>>>>>>"
                                                        + epc.getEPC());
                                        // sendWebMessage(epc.getEPC(),i++);
                                    }
                                }
                            }
                        } else {
                            logger.info("closing socket");
                            socket.close();
                        }

                    } catch (IOException e) {
                        logger.error("Error while reading message", e);
                    } catch (InvalidLLRPMessageException e) {
                        logger.error("Error while reading message", e);
                    } catch (InterruptedException e) {
                        logger.error("Error while reading message", e);
                    }
                }
            }

        }

        private void sendWebMessage(Integer96_HEX epc, int i)
                throws InterruptedException {
            WebMessage cmd = new WebMessage();
            String url;
            if (i % 2 == 0)
                url = ctxMain.getWorker().getAddLogUrl() + "/" + epc;
            else
                url = ctxMain.getWorker().getTransationUrl() + "/" + epc;

            cmd.setUrl(url);
            System.out.println(" id " + url);
            cmd.setMessage(new String("{}"));

            ctxMain.sendWebMessage(cmd);

        }

        /**
         * Read everything from the stream until the socket is closed
         * 
         * @throws InvalidLLRPMessageException
         */
        public LLRPMessage read() throws IOException,
                InvalidLLRPMessageException {
            LLRPMessage m = null;
            // The message header
            byte[] first = new byte[6];

            // the complete message
            byte[] msg;

            // Read in the message header. If -1 is read, there is no more
            // data available, so close the socket
            if (inStream.read(first, 0, 6) == -1) {
                return null;
            }
            int msgLength = 0;

            try {
                // calculate message length
                msgLength = calculateLLRPMessageLength(first);
            } catch (IllegalArgumentException e) {
                throw new IOException("Incorrect Message Length");
            }

            /*
             * the rest of bytes of the message will be stored in here before
             * they are put in the accumulator. If the message is short, all
             * messageLength-6 bytes will be read in here at once. If it is
             * long, the data might not be available on the socket all at once,
             * so it make take a couple of iterations to read in all the bytes
             */
            byte[] temp = new byte[msgLength - 6];

            // all the rest of the bytes will be put into the accumulator
            ArrayList<Byte> accumulator = new ArrayList<Byte>();

            // add the first six bytes to the accumulator so that it will
            // contain all the bytes at the end
            for (byte b : first) {
                accumulator.add(b);
            }

            // the number of bytes read on the last call to read()
            int numBytesRead = 0;

            // read from the input stream and put bytes into the accumulator
            // while there are still bytes left to read on the socket and
            // the entire message has not been read
            while (((msgLength - accumulator.size()) != 0)
                    && numBytesRead != -1) {

                numBytesRead = inStream.read(temp, 0,
                        msgLength - accumulator.size());

                for (int i = 0; i < numBytesRead; i++) {
                    accumulator.add(temp[i]);
                }
            }

            if ((msgLength - accumulator.size()) != 0) {
                throw new IOException("Error: Discrepency between message size"
                        + " in header and actual number of bytes read");
            }

            msg = new byte[msgLength];

            // copy all bytes in the accumulator to the msg byte array
            for (int i = 0; i < accumulator.size(); i++) {
                msg[i] = accumulator.get(i);
            }

            // turn the byte array into an LLRP Message Object
            m = LLRPMessageFactory.createLLRPMessage(msg);
            return m;
        }

        /**
         * Send in the first 6 bytes of an LLRP Message
         * 
         * @param bytes
         * @return
         */
        private int calculateLLRPMessageLength(byte[] bytes)
                throws IllegalArgumentException {
            long msgLength = 0;
            int num1 = 0;
            int num2 = 0;
            int num3 = 0;
            int num4 = 0;

            num1 = ((unsignedByteToInt(bytes[2])));
            num1 = num1 << 32;
            if (num1 > 127) {
                throw new RuntimeException(
                        "Cannot construct a message greater than "
                                + "2147483647 bytes (2^31 - 1), due to the fact that there are "
                                + "no unsigned ints in java");
            }

            num2 = ((unsignedByteToInt(bytes[3])));
            num2 = num2 << 16;

            num3 = ((unsignedByteToInt(bytes[4])));
            num3 = num3 << 8;

            num4 = (unsignedByteToInt(bytes[5]));

            msgLength = num1 + num2 + num3 + num4;

            if (msgLength < 0) {
                throw new IllegalArgumentException(
                        "LLRP message length is less than 0");
            } else {
                return (int) msgLength;
            }
        }

        /**
         * From http://www.rgagnon.com/javadetails/java-0026.html
         * 
         * @param b
         * @return
         */
        private int unsignedByteToInt(byte b) {
            return (int) b & 0xFF;
        }

        /**
         * Receive the next Message
         * 
         * @return returns the Message form the Queue and removes it. It blocks
         *         if there is no Message.
         */
        public LLRPMessage getNextMessage() {
            LLRPMessage m = null;
            try {
                m = queue.take();
            } catch (InterruptedException e) {
                // nothing
            }
            return m;
        }
    }

}
1

There are 1 answers

0
Kaan Seyitogullari On

You have to need write report after the startRoSpec then you get tagids.

> START_ROSPEC startROSpec = new START_ROSPEC();
> startROSpec.setROSpecID(new UnsignedInteger(ROSPEC_ID));
> write(startROSpec, "START_ROSPEC"); //wait for five seconds for tag
> reads pause(5000);

ENABLE_EVENTS_AND_REPORTS report = new ENABLE_EVENTS_AND_REPORTS();
write(report, "ENABLE_EVENTS_AND_REPORTS");

You can get class from : https://github.com/kaansey/JAVA-LLRP-RFIDTags