See More

package javaforce; import java.util.*; import org.llrp.ltk.net.*; import org.llrp.ltk.types.*; import org.llrp.ltk.util.*; import org.llrp.ltk.generated.messages.*; import org.llrp.ltk.generated.parameters.*; import org.llrp.ltk.generated.interfaces.*; import org.llrp.ltk.generated.enumerations.*; /** LLRP API to read/write RFID tags from compatible controllers. * * Uses the LLRP Toolkit: https://sourceforge.net/projects/llrp-toolkit * * Javadoc : http://llrp.org/docs/javaapidoc * * @author Peter Quiring */ public class LLRP implements LLRPEndpoint { private static final int delay = 10; private static int rospecid = 101; private static int inventoryparamid = 102; private static int accessid = 103; private static int opspecid = 104; private ROSpec rospec; private AccessSpec accessspec; private LLRPConnector llrp; private LLRPEvent events; private String ip; private int[] powerIndexes = new int[50]; private int impinj_search_mode = -1; private int period = -1; private int duration = -1; private int gpi = -1; private int mode = 1002; private int sensitivity = 1; private int session = 1; private boolean enableAccessSpec = false; private boolean wait4reply = false; private int waitTimeout = 0; public static final int IMPINJ_SEARCH_MODE_SINGLE = 1; public static final int IMPINJ_SEARCH_MODE_DUAL = 2; public static final int IMPINJ_SEARCH_MODE_FOCUS = 3; public static final int IMPINJ_SEARCH_MODE_SINGLE_RESET = 5; public static final int IMPINJ_SEARCH_MODE_DUAL_B_TO_A = 6; public boolean active; //scan is active public boolean connected; public int log; public long lastMsg; public static boolean debug; /** Connects to LLRP Controller. */ public boolean connect(String ip, int time_out_ms) { this.ip = ip; llrp = new LLRPConnector(this, ip); try { llrp.connect(time_out_ms); connected = true; return true; } catch (Exception e) { try { llrp.disconnect(); //ensure it's disconnected } catch (Exception e2) {} llrp = null; if (debug) JFLog.log(log, e); return false; } } /** Connects to LLRP Controller. time out = 30 seconds. */ public boolean connect(String ip) { return connect(ip, 30000); } /** Disconnects from LLRP Controller. */ public void disconnect() { active = false; connected = false; if (llrp != null) { llrp.disconnect(); llrp = null; } } /** If enabled causes send() to wait for reply before returning. * * Some systems/routers may merge multiple outbound packets which the controller will ignore. * This will help avoid these issues. */ public void setWaitForReply(boolean state, int timeout) { wait4reply = state; waitTimeout = timeout; } /** If enabled causes send() to wait for reply before returning. * Timeout = 5000ms */ public void setWaitForReply(boolean state) { setWaitForReply(state, 5000); } private void send(LLRPMessage msg) { long prevMsg = lastMsg; if (debug) { JFLog.log("LLRP:send:" + ip + ":" + msg); } try { llrp.send(msg); if (wait4reply) { int cnt = 0; int maxcnt = waitTimeout / delay; while (prevMsg == lastMsg) { JF.sleep(delay); cnt++; if (cnt == maxcnt) { break; } } if (prevMsg == lastMsg) { throw new Exception("send:no reply"); } } else { //small delay avoids packet merging JF.sleep(delay); } } catch (Exception e) { if (debug) JFLog.log(log, e); active = false; connected = false; disconnect(); } } /** Pings LLRP Controller to keep connection alive. * timeout = 5000ms */ public void ping() { ping(5000); } /** Pings LLRP Controller to keep connection alive. */ public void ping(int timeout) { if (llrp == null) return; try { long prevMsg = lastMsg; //some readers do not support it, but it will still "test" the connection { KEEPALIVE msg = new KEEPALIVE(); send(msg); } int cnt = 0; int maxcnt = timeout / delay; while (prevMsg == lastMsg) { JF.sleep(delay); cnt++; if (cnt == maxcnt) { break; } } if (prevMsg == lastMsg) { throw new Exception("ping:no reply"); } } catch (Exception e) { if (debug) JFLog.log(log, e); active = false; connected = false; disconnect(); } } public boolean isActive() { return active; } public boolean isConnected() { return connected; } /** Sets Event Listener to read tags. */ public void setEventsListener(LLRPEvent events) { this.events = events; } /** Sets RSSI threshold. Tags below this value are ignored. * @param value = RSSI threshold index (default = 1) */ public void setRSSIThreshold(int value) { sensitivity = value; } /** Sets power indexes for each antenna (see getPowerLevels()) * * Default = new int[] {50} * */ public void setPowerIndexes(int[] powerIndexes) { this.powerIndexes = powerIndexes; } /** Set reader mode index (0-5,1000-1005) * See : https://support.impinj.com/hc/en-us/articles/360000046899-Reader-Modes-Made-Easy * * Default = 1002 * * @param mode */ public void setModeIndex(int mode) { this.mode = mode; } /** Sets reader session (default = 1) * * @param session (0-3) * */ public void setSession(int session) { this.session = session; } /** Set period of start trigger and duration of stop trigger. * * @param period = period in ms (-1 = disabled) * @param duration = duration is ms */ public void setPeriod(int period, int duration) { this.period = period; this.duration = duration; } /** Set GPI as start trigger. * * @param port = GPI port (1-65535) */ public void setGPITrigger(int port) { gpi = port; } /** Set GPI as start trigger with duration. * * @param port = GPI port (1-65535) * @param duration = duration in ms */ public void setGPITrigger(int port, int duration) { gpi = port; this.duration = duration; } /** Set GPO port to state. * * @param port = GPO port (1-65535) * @param state = value to write */ public void setGPOState(int port, boolean state) { SET_READER_CONFIG msg = new SET_READER_CONFIG(); msg.setResetToFactoryDefault(new Bit(false)); GPOWriteData write = new GPOWriteData(); write.setGPOPortNumber(new UnsignedShort(port)); write.setGPOData(new Bit(state)); ArrayList list = new ArrayList(); list.add(write); msg.setGPOWriteDataList(list); send(msg); } /** Include an Access Spec with RO Spec during inventory scan. * * Access Spec can provide deep EPC memory reads. */ public void setEnableAccessSpec(boolean access) { this.enableAccessSpec = access; } /** Sets Impinj Search Mode (custom parameter) * @param mode = 1-6 (see IMPINJ_SEARCH_MODE_...) (-1 = disabled) */ public void setImpinjSearchMode(int mode) { impinj_search_mode = mode; } public void setLog(int log) { this.log = log; } /** Starts reading RFID tags with inventory scans. * * Use stop() to stop scanning. * * @return scanning active */ public boolean startInventoryScan() { if (llrp == null) return false; if (active) return false; active = true; try { rospec = createROSpec(); if (enableAccessSpec) { accessspec = createReadAccessSpec(rospec.getROSpecID()); } else { accessspec = null; } //reset reader { SET_READER_CONFIG msg = new SET_READER_CONFIG(); msg.setResetToFactoryDefault(new Bit(true)); // JFLog.log("reset_reader"); send(msg); } //delete all RO specs { DELETE_ROSPEC msg = new DELETE_ROSPEC(); msg.setROSpecID(new UnsignedInteger(0)); // JFLog.log("delete all RO specs"); send(msg); } //delete all Access Specs { DELETE_ACCESSSPEC msg = new DELETE_ACCESSSPEC(); msg.setAccessSpecID(new UnsignedInteger(0)); // JFLog.log("delete all ACCESS specs"); send(msg); } { SET_READER_CONFIG msg = new SET_READER_CONFIG(); msg.setResetToFactoryDefault(new Bit(false)); if (gpi != -1) { ArrayList list = new ArrayList(); for(int a=1;a<=4;a++) { GPIPortCurrentState state = new GPIPortCurrentState(); state.setConfig(new Bit(true)); state.setGPIPortNum(new UnsignedShort(a)); state.setState(new GPIPortState(GPIPortState.Low)); list.add(state); } msg.setGPIPortCurrentStateList(list); } ReaderEventNotificationSpec events = new ReaderEventNotificationSpec(); List eventsList = new ArrayList(); if (gpi != -1) { EventNotificationState gpi_events = new EventNotificationState(); gpi_events.setEventType(new NotificationEventType(NotificationEventType.GPI_Event)); gpi_events.setNotificationState(new Bit(true)); eventsList.add(gpi_events); } EventNotificationState ro_events = new EventNotificationState(); ro_events.setEventType(new NotificationEventType(NotificationEventType.ROSpec_Event)); ro_events.setNotificationState(new Bit(true)); eventsList.add(ro_events); events.setEventNotificationStateList(eventsList); msg.setReaderEventNotificationSpec(events); // JFLog.log("reset_reader"); send(msg); } if (impinj_search_mode != -1) { //enable impinj extensions CUSTOM_MESSAGE msg = new CUSTOM_MESSAGE(); msg.setVendorIdentifier(new UnsignedInteger(25882)); msg.setMessageSubtype(new UnsignedByte(21)); msg.setData(new BytesToEnd_HEX("00000000")); send(msg); } //add RO (read operation) spec { ADD_ROSPEC msg = new ADD_ROSPEC(); msg.setROSpec(rospec); // JFLog.log("add RO spec"); send(msg); } //add ACCESS spec if (enableAccessSpec) { ADD_ACCESSSPEC msg = new ADD_ACCESSSPEC(); msg.setAccessSpec(accessspec); // JFLog.log("add ACCESS spec"); send(msg); } //enable RO spec { ENABLE_ROSPEC msg = new ENABLE_ROSPEC(); msg.setROSpecID(rospec.getROSpecID()); // JFLog.log("enable RO spec"); send(msg); } //enable Access spec if (enableAccessSpec) { ENABLE_ACCESSSPEC msg = new ENABLE_ACCESSSPEC(); msg.setAccessSpecID(accessspec.getAccessSpecID()); // JFLog.log("enable ACCESS spec"); send(msg); } //start RO spec if (period == -1 && gpi == -1) { START_ROSPEC msg = new START_ROSPEC(); msg.setROSpecID(rospec.getROSpecID()); // JFLog.log("start RO spec"); send(msg); } return true; } catch (Exception e) { if (debug) JFLog.log(log, e); return false; } } /** Stop reading or writing tags. */ public void stop() { if (llrp == null) return; try { //disable RO spec if (rospec != null) { DISABLE_ROSPEC msg = new DISABLE_ROSPEC(); msg.setROSpecID(rospec.getROSpecID()); // JFLog.log("disable RO spec"); send(msg); rospec = null; } //delete RO spec { DELETE_ROSPEC msg = new DELETE_ROSPEC(); msg.setROSpecID(new UnsignedInteger(0)); // JFLog.log("delete RO spec"); send(msg); } if (accessspec != null) { DISABLE_ACCESSSPEC msg = new DISABLE_ACCESSSPEC(); msg.setAccessSpecID(accessspec.getROSpecID()); // JFLog.log("disable RO spec"); send(msg); accessspec = null; } { DELETE_ACCESSSPEC msg = new DELETE_ACCESSSPEC(); msg.setAccessSpecID(new UnsignedInteger(0)); // JFLog.log("delete Access spec"); send(msg); } active = false; } catch (Exception e) { e.printStackTrace(); active = false; connected = false; disconnect(); } } /** Write RFID Tag(s). * * Use stop() to stop writing tags. * * @param oldEPC = old EPC code * @param newEPC = new EPC code * @param wordOffset = beginning of EPC memory bank to write newEPC (default = 2) */ public boolean startWriteTag(short[] oldEPC, short[] newEPC, int wordOffset) { if (llrp == null) return false; if (active) return false; active = true; try { rospec = createROSpec(); accessspec = createWriteAccessSpec(rospec.getROSpecID(), oldEPC, newEPC, wordOffset); //reset reader { SET_READER_CONFIG msg = new SET_READER_CONFIG(); msg.setResetToFactoryDefault(new Bit(true)); // JFLog.log("reset_reader"); send(msg); } //delete all RO specs { DELETE_ROSPEC msg = new DELETE_ROSPEC(); msg.setROSpecID(new UnsignedInteger(0)); // JFLog.log("delete all RO specs"); send(msg); } //delete all Access Specs { DELETE_ACCESSSPEC msg = new DELETE_ACCESSSPEC(); msg.setAccessSpecID(new UnsignedInteger(0)); // JFLog.log("delete all ACCESS specs"); send(msg); } //add RO (read operation) spec { ADD_ROSPEC msg = new ADD_ROSPEC(); msg.setROSpec(rospec); // JFLog.log("add RO spec"); send(msg); } //add ACCESS spec { ADD_ACCESSSPEC msg = new ADD_ACCESSSPEC(); msg.setAccessSpec(accessspec); // JFLog.log("add ACCESS spec"); send(msg); } //enable RO spec { ENABLE_ROSPEC msg = new ENABLE_ROSPEC(); msg.setROSpecID(rospec.getROSpecID()); // JFLog.log("enable RO spec"); send(msg); } //enable Access spec { ENABLE_ACCESSSPEC msg = new ENABLE_ACCESSSPEC(); msg.setAccessSpecID(accessspec.getAccessSpecID()); // JFLog.log("enable ACCESS spec"); send(msg); } //start RO spec if (period == -1 && gpi == -1) { START_ROSPEC msg = new START_ROSPEC(); msg.setROSpecID(rospec.getROSpecID()); // JFLog.log("start RO spec"); send(msg); } return true; } catch (Exception e) { if (debug) JFLog.log(log, e); return false; } } /** Write RFID Tag(s). * * Use stop() to stop writing tags. * * @param oldEPC = old EPC code * @param newEPC = new EPC code * */ public boolean startWriteTag(short[] oldEPC, short[] newEPC) { return startWriteTag(oldEPC, newEPC, 2); } /** Kill RFID Tag. * * Use stop() to stop killing tag. * * @param targetEPC = target EPC code * @param password = kill password */ public boolean startKillTag(short[] targetEPC, int password) { if (llrp == null) return false; if (active) return false; active = true; try { rospec = createROSpec(); accessspec = createKillAccessSpec(rospec.getROSpecID(), targetEPC, password); //reset reader { SET_READER_CONFIG msg = new SET_READER_CONFIG(); msg.setResetToFactoryDefault(new Bit(true)); // JFLog.log("reset_reader"); send(msg); } //delete all RO specs { DELETE_ROSPEC msg = new DELETE_ROSPEC(); msg.setROSpecID(new UnsignedInteger(0)); // JFLog.log("delete all RO specs"); send(msg); } //delete all Access Specs { DELETE_ACCESSSPEC msg = new DELETE_ACCESSSPEC(); msg.setAccessSpecID(new UnsignedInteger(0)); // JFLog.log("delete all ACCESS specs"); send(msg); } //add RO (read operation) spec { ADD_ROSPEC msg = new ADD_ROSPEC(); msg.setROSpec(rospec); // JFLog.log("add RO spec"); send(msg); } //add ACCESS spec { ADD_ACCESSSPEC msg = new ADD_ACCESSSPEC(); msg.setAccessSpec(accessspec); // JFLog.log("add ACCESS spec"); send(msg); } //enable RO spec { ENABLE_ROSPEC msg = new ENABLE_ROSPEC(); msg.setROSpecID(rospec.getROSpecID()); // JFLog.log("enable RO spec"); send(msg); } //enable Access spec { ENABLE_ACCESSSPEC msg = new ENABLE_ACCESSSPEC(); msg.setAccessSpecID(accessspec.getAccessSpecID()); // JFLog.log("enable ACCESS spec"); send(msg); } //start RO spec if (period == -1 && gpi == -1) { START_ROSPEC msg = new START_ROSPEC(); msg.setROSpecID(rospec.getROSpecID()); // JFLog.log("start RO spec"); send(msg); } return true; } catch (Exception e) { if (debug) JFLog.log(log, e); return false; } } private int[] powerLevels; private boolean reading_power_levels; /** Retrieves power levels from LLRP Controller. * Power Levels are indexes into a table of dBm * 100 values. */ public int[] getPowerLevels() { if (llrp == null) return null; if (active) return null; powerLevels = null; try { //reset reader { SET_READER_CONFIG msg = new SET_READER_CONFIG(); msg.setResetToFactoryDefault(new Bit(true)); // JFLog.log("reset_reader"); send(msg); } reading_power_levels = true; { GET_READER_CAPABILITIES caps = new GET_READER_CAPABILITIES(); caps.setRequestedData(new GetReaderCapabilitiesRequestedData(GetReaderCapabilitiesRequestedData.All)); // JFLog.log("get_reader_caps"); send(caps); } int max = 12; while (powerLevels == null) { JF.sleep(1000); max--; if (max == 0) { JFLog.log(log, "LLRP:Error:getPowerLevels():timeout"); return null; } } reading_power_levels = false; return powerLevels; } catch (Exception e) { if (debug) JFLog.log(log, e); return null; } } private int[] sensitivityLevels; private boolean reading_sensitivity_levels; /** Retrieves sensitivity levels from LLRP Controller. * Sensitivity Levels are indexes into a table of dB values. */ public int[] getSensitivityLevels() { if (llrp == null) return null; if (active) return null; sensitivityLevels = null; try { //reset reader { SET_READER_CONFIG msg = new SET_READER_CONFIG(); msg.setResetToFactoryDefault(new Bit(true)); // JFLog.log("reset_reader"); send(msg); } reading_sensitivity_levels = true; { GET_READER_CAPABILITIES caps = new GET_READER_CAPABILITIES(); caps.setRequestedData(new GetReaderCapabilitiesRequestedData(GetReaderCapabilitiesRequestedData.All)); // JFLog.log("get_reader_caps"); send(caps); } int max = 12; while (sensitivityLevels == null) { JF.sleep(1000); max--; if (max == 0) { JFLog.log(log, "LLRP:Error:getSensitivityLevels():timeout"); return null; } } reading_sensitivity_levels = false; return sensitivityLevels; } catch (Exception e) { if (debug) JFLog.log(log, e); return null; } } private ROSpec createROSpec() { ROSpec rospec; ROBoundarySpec roboundaryspec; ROSpecStartTrigger rospecstarttrigger; ROSpecStopTrigger rospecstoptrigger; AISpec aispec; ROReportSpec roreportspec; rospecstarttrigger = new ROSpecStartTrigger(); if (period != -1) { rospecstarttrigger.setROSpecStartTriggerType(new ROSpecStartTriggerType(ROSpecStartTriggerType.Periodic)); PeriodicTriggerValue periodValue = new PeriodicTriggerValue(); periodValue.setPeriod(new UnsignedInteger(period)); periodValue.setOffset(new UnsignedInteger(0)); rospecstarttrigger.setPeriodicTriggerValue(periodValue); } else if (gpi != -1) { rospecstarttrigger.setROSpecStartTriggerType(new ROSpecStartTriggerType(ROSpecStartTriggerType.GPI)); GPITriggerValue gpiValue = new GPITriggerValue(); gpiValue.setGPIPortNum(new UnsignedShort(gpi)); gpiValue.setGPIEvent(new Bit(false)); //false=trigger when beam is broken:true=trigger when beam is restored gpiValue.setTimeout(new UnsignedInteger(0)); rospecstarttrigger.setGPITriggerValue(gpiValue); } else { rospecstarttrigger.setROSpecStartTriggerType(new ROSpecStartTriggerType(ROSpecStartTriggerType.Null)); } rospecstoptrigger = new ROSpecStopTrigger(); if (duration != -1) { rospecstoptrigger.setROSpecStopTriggerType(new ROSpecStopTriggerType(ROSpecStopTriggerType.Duration)); rospecstoptrigger.setDurationTriggerValue(new UnsignedInteger(duration)); } else { rospecstoptrigger.setROSpecStopTriggerType(new ROSpecStopTriggerType(ROSpecStopTriggerType.Null)); rospecstoptrigger.setDurationTriggerValue(new UnsignedInteger(0)); } roboundaryspec = new ROBoundarySpec(); roboundaryspec.setROSpecStartTrigger(rospecstarttrigger); roboundaryspec.setROSpecStopTrigger(rospecstoptrigger); roreportspec = new ROReportSpec(); roreportspec.setROReportTrigger(new ROReportTriggerType(ROReportTriggerType.Upon_N_Tags_Or_End_Of_ROSpec)); roreportspec.setN(new UnsignedShort(1)); TagReportContentSelector selector = new TagReportContentSelector(); ArrayList selectorList = new ArrayList(); C1G2EPCMemorySelector selectorEPC = new C1G2EPCMemorySelector(); selectorEPC.setEnableCRC(new Bit(true)); selectorEPC.setEnablePCBits(new Bit(true)); selectorList.add(selectorEPC); selector.setAirProtocolEPCMemorySelectorList(selectorList); selector.setEnableROSpecID(new Bit(false)); selector.setEnableSpecIndex(new Bit(false)); selector.setEnableInventoryParameterSpecID(new Bit(false)); selector.setEnableAntennaID(new Bit(true)); selector.setEnableChannelIndex(new Bit(true)); selector.setEnablePeakRSSI(new Bit(false)); selector.setEnableFirstSeenTimestamp(new Bit(true)); selector.setEnableLastSeenTimestamp(new Bit(false)); selector.setEnableTagSeenCount(new Bit(false)); selector.setEnableAccessSpecID(new Bit(true)); selector.setEnablePeakRSSI(new Bit(true)); roreportspec.setTagReportContentSelector(selector); ArrayList specParameterList = new ArrayList(); aispec = new AISpec(); UnsignedShortArray IDs = new UnsignedShortArray(); for(int a=0;a inventoryParameterSpecList = new ArrayList(); InventoryParameterSpec invspec = new InventoryParameterSpec(); invspec.setInventoryParameterSpecID(new UnsignedShort(inventoryparamid)); invspec.setProtocolID(new AirProtocols(AirProtocols.EPCGlobalClass1Gen2)); ArrayList antennaConfigurationList = new ArrayList(); ArrayList commands = new ArrayList(); C1G2InventoryCommand command = new C1G2InventoryCommand(); C1G2RFControl rfcontrol = new C1G2RFControl(); rfcontrol.setModeIndex(new UnsignedShort(mode)); rfcontrol.setTari(new UnsignedShort(0)); command.setC1G2RFControl(rfcontrol); C1G2SingulationControl singulationcontrol = new C1G2SingulationControl(); TwoBitField session_bits = new TwoBitField(); //NOTE : TwoBitField stores bits in reverse order boolean session_bit_0 = (session & 0x01) == 0x01; boolean session_bit_1 = (session & 0x02) == 0x02; if (session_bit_0) { session_bits.set(1); //set bit 1 (LSB) } if (session_bit_1) { session_bits.set(0); //set bit 0 (MSB) } singulationcontrol.setSession(session_bits); singulationcontrol.setTagPopulation(new UnsignedShort(32)); singulationcontrol.setTagTransitTime(new UnsignedInteger(0)); command.setC1G2SingulationControl(singulationcontrol); command.setTagInventoryStateAware(new Bit(false)); if (impinj_search_mode != -1) { ArrayList customList = new ArrayList(); Custom search_mode = new Custom(); search_mode.setVendorIdentifier(new UnsignedInteger(25882)); search_mode.setParameterSubtype(new UnsignedInteger(23)); search_mode.setData(new BytesToEnd_HEX(String.format("%04x", impinj_search_mode))); customList.add(search_mode); command.setCustomList(customList); } commands.add(command); for(int a=0;a accessCommandOpSpecList = new ArrayList(); C1G2Read read = new C1G2Read(); read.setAccessPassword(new UnsignedInteger(0)); read.setMB(mb); read.setOpSpecID(new UnsignedShort(opspecid)); read.setWordCount(new UnsignedShort(8)); read.setWordPointer(new UnsignedShort(2)); accessCommandOpSpecList.add(read); accessCommand.setAccessCommandOpSpecList(accessCommandOpSpecList); C1G2TagSpec tagSpec = new C1G2TagSpec(); ArrayList targetTagList = new ArrayList(); C1G2TargetTag tt = new C1G2TargetTag(); tt.setMB(mb); tt.setMatch(new Bit(false)); tt.setPointer(new UnsignedShort(2)); BitArray_HEX mask = new BitArray_HEX(128); for(int a=0;a<128;a++) { mask.set(a); } tt.setTagMask(mask); BitArray_HEX data = new BitArray_HEX(128); for(int a=0;a<128;a++) { data.set(a); } tt.setTagData(data); targetTagList.add(tt); tagSpec.setC1G2TargetTagList(targetTagList); accessCommand.setAirProtocolTagSpec(tagSpec); as.setAccessCommand(accessCommand); AccessReportSpec accessReportSpec = new AccessReportSpec(); accessReportSpec.setAccessReportTrigger(new AccessReportTriggerType(AccessReportTriggerType.Whenever_ROReport_Is_Generated)); as.setAccessReportSpec(accessReportSpec); AccessSpecStopTrigger accessSpecStopTrigger = new AccessSpecStopTrigger(); accessSpecStopTrigger.setAccessSpecStopTrigger(new AccessSpecStopTriggerType(AccessSpecStopTriggerType.Null)); accessSpecStopTrigger.setOperationCountValue(new UnsignedShort(1)); as.setAccessSpecStopTrigger(accessSpecStopTrigger); as.setAntennaID(new UnsignedShort(1)); as.setCurrentState(new AccessSpecState(AccessSpecState.Disabled)); AirProtocols airProtocols = new AirProtocols(); airProtocols.set(AirProtocols.EPCGlobalClass1Gen2); as.setProtocolID(airProtocols); as.setROSpecID(rospecid); as.setAccessSpecID(new UnsignedInteger(accessid)); return as; } private String shortArrayToHexString(short[] epc) { StringBuilder sb = new StringBuilder(); for(int a=0;a accessCommandOpSpecList = new ArrayList(); C1G2Write write = new C1G2Write(); write.setAccessPassword(new UnsignedInteger(0)); write.setMB(mb); write.setOpSpecID(new UnsignedShort(opspecid)); write.setWordPointer(new UnsignedShort(offset)); UnsignedShortArray_HEX newepchex = new UnsignedShortArray_HEX(newEPC.length); for(int a=0;a targetTagList = new ArrayList(); C1G2TargetTag tt = new C1G2TargetTag(); tt.setMB(mb); tt.setMatch(new Bit(true)); tt.setPointer(new UnsignedShort(2 * 16)); //pointer is in BITS not WORDS BitArray_HEX mask = new BitArray_HEX(oldBits); for(int a=0;a accessCommandOpSpecList = new ArrayList(); C1G2Kill kill = new C1G2Kill(); kill.setOpSpecID(new UnsignedShort(opspecid)); kill.setKillPassword(new UnsignedInteger(password)); accessCommandOpSpecList.add(kill); accessCommand.setAccessCommandOpSpecList(accessCommandOpSpecList); C1G2TagSpec tagSpec = new C1G2TagSpec(); ArrayList targetTagList = new ArrayList(); C1G2TargetTag tt = new C1G2TargetTag(); tt.setMB(mb); tt.setMatch(new Bit(true)); tt.setPointer(new UnsignedShort(2 * 16)); //pointer is in BITS not WORDS BitArray_HEX mask = new BitArray_HEX(oldBits); for(int a=0;a tags = report.getTagReportDataList(); for(TagReportData tag : tags) { String epc_scan = null; String epc_read = null; int tag_rssi = 0; PeakRSSI peak_rssi = tag.getPeakRSSI(); if (peak_rssi != null) { tag_rssi = peak_rssi.getPeakRSSI().intValue(); } epc_scan = tag.getEPCParameter().toString(); idx = epc_scan.lastIndexOf(':'); if (idx > 0) { epc_scan = epc_scan.substring(idx+1); } epc_scan = epc_scan.replaceAll(" ", "").trim(); List list = tag.getAccessCommandOpSpecResultList(); if (list.size() == 0) { if (events != null) { events.tagRead(null, 0); } } for(AccessCommandOpSpecResult res : list) { if (res instanceof C1G2ReadOpSpecResult) { C1G2ReadOpSpecResult readop = (C1G2ReadOpSpecResult)res; epc_read = readop.getReadData().toString(); idx = epc_read.lastIndexOf(':'); if (idx > 0) { epc_read = epc_read.substring(idx+1); } epc_read = epc_read.replaceAll(" ", "").trim(); } } if (events != null && (epc_read != null || epc_scan != null)) { String epc = epc_read != null && epc_read.length() > 0 ? epc_read : epc_scan; if (debug) { JFLog.log(log, "[" + System.currentTimeMillis() + "] EPC=" + epc + ":RSSI=" + tag_rssi); } events.tagRead(epc, tag_rssi); } } } else if (llrpm instanceof GET_READER_CAPABILITIES_RESPONSE) { GET_READER_CAPABILITIES_RESPONSE caps = (GET_READER_CAPABILITIES_RESPONSE)llrpm; if (reading_power_levels) { List list = caps.getRegulatoryCapabilities().getUHFBandCapabilities().getTransmitPowerLevelTableEntryList(); int[] levels = new int[list.size() + 1]; int index = 1; for(TransmitPowerLevelTableEntry entry : list) { levels[index++] = entry.getTransmitPowerValue().intValue(); } this.powerLevels = levels; } if (reading_sensitivity_levels) { List list = caps.getGeneralDeviceCapabilities().getReceiveSensitivityTableEntryList(); int[] levels = new int[list.size() + 1]; int index = 1; for(ReceiveSensitivityTableEntry entry : list) { levels[index++] = entry.getReceiveSensitivityValue().toShort(); } this.sensitivityLevels = levels; } } else if (llrpm instanceof READER_EVENT_NOTIFICATION) { READER_EVENT_NOTIFICATION event = (READER_EVENT_NOTIFICATION)llrpm; ReaderEventNotificationData data = event.getReaderEventNotificationData(); int type = 0; if (data.getGPIEvent() != null) type = 248; if (data.getROSpecEvent() != null) type = 249; switch (type) { case 248: { //GPIEVent GPIEvent gpiEvent = data.getGPIEvent(); events.gpiEvent(gpiEvent.getGPIPortNumber().toShort(), gpiEvent.getGPIEvent().toBoolean()); break; } case 249: { //ROSpec ROSpecEvent roEvent = data.getROSpecEvent(); ROSpecEventType roEventType = roEvent.getEventType(); int roType = roEventType.toInteger(); switch (roType) { case 0: events.readStarted(); break; case 1: events.readEnded(); break; } } } } else if (llrpm instanceof SET_READER_CONFIG_RESPONSE) { //TODO } else if (llrpm instanceof DELETE_ROSPEC_RESPONSE) { //TODO } else if (llrpm instanceof DELETE_ACCESSSPEC_RESPONSE) { //TODO } else if (llrpm instanceof ADD_ROSPEC_RESPONSE) { //TODO } else if (llrpm instanceof ENABLE_ROSPEC_RESPONSE) { //TODO } else if (llrpm instanceof START_ROSPEC_RESPONSE) { //TODO } else if (llrpm instanceof DISABLE_ROSPEC_RESPONSE) { //TODO } else if (llrpm instanceof ADD_ACCESSSPEC_RESPONSE) { //TODO } else if (llrpm instanceof ENABLE_ACCESSSPEC_RESPONSE) { //TODO } else if (llrpm instanceof DISABLE_ACCESSSPEC_RESPONSE) { //TODO } else if (llrpm instanceof ERROR_MESSAGE) { ERROR_MESSAGE msg = (ERROR_MESSAGE)llrpm; //TODO : handle error message } else { JFLog.log("LLRP:Unknown message:" + llrpm); } } catch (Exception e) { e.printStackTrace(); } } public void errorOccured(String msg) { JFLog.log(log, "LLRP:Error:" + ip + ":" + msg); active = false; connected = false; disconnect(); } private static void usage() { System.out.println("usage : LLRP controller_ip cmd [args]"); System.out.println("where : cmd = read | powerlevels | rssilevels | ping"); System.out.println(" : read [power=p1[,p2[,p3[,p4]]]] [rssi=threshold] [period=ms] [gpi=port] [duration=ms]"); System.out.println(" : powerlevels"); System.out.println(" : rssilevels"); System.out.println(" : ping"); } public static void main(String[] args) { if (args.length < 2) { usage(); return; } boolean main_active = true; String ctrl = args[0]; String cmd = args[1]; int[] powerLevels = new int[] {80, 80, 80, 80}; int rssi = 0; int period = 0; int duration = 0; int gpi = 0; switch (cmd) { case "read": { for(int a=2;a