LLRP Motorola 9500不发送读取标记事件

时间:2016-02-04 18:49:43

标签: java rfid llrp

我们正在尝试使用LLRP工具包代码连接FX9500。我们希望一旦进入范围就会收到读取标记。从消息看起来所有添加/设置配置都已正确完成,但无法接收事件。

附加了正在交换的消息的代码和XML输出。 XML消息位于:http://gadgetnapps.blogspot.in/2016/02/llrp-xml-messages.html

提前致谢。

    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 个答案:

答案 0 :(得分:1)

你必须在startRoSpec之后编写报告,然后才能获得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");

您可以从https://github.com/kaansey/JAVA-LLRP-RFIDTags

上课