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