The wonderful jumble of code that does magic things :)
Usage: ./reader [-d #] [-subVw]
-d Debuglevel (overrides config, syslog levels)
-s Debug output to stdout (overrides config)
-u Unbuffered debug output (try this if reader stops at start)
-b Daemonize to background
-w Write values to config file and exit
-V Version info
For example if you want to view logging only locally you can start with -s -d7
In typical setups libraries cannot be copied to system search paths so you much specify LD_LIBRARY_PATH accordingly. For example:
LD_LIBRARY_PATH=/cust /cust/reader
Configuration file path is hardcoded.
This is the Engine native tag data representation in JSON format. It is used by many internal functions and also exposed in STORE and MQTT. Empty/default fields are left out from the JSON.
{
"EPC": "301588F858009D4473D8D797", // Raw EPC hex data as in the tag
"URI": "urn:epc:id:sgtin:6438422.000629.19123459991", // Decoded URN format
"userdata": "01234567FFFF", // Results of tag memory read operation. May be TID or User memory
"direction": "OUT", // Results of direction detection if it was used
"filterchain": 0, // Engine internal filterchain where this tag was
"readcount": 1, // How many times the tag was read. Usually 1 since reads are individually processed
"rssi": -39, // Received signal strength, in dBm
"min_rssi": -39, // Minimum RSSI if reader supports reporting, in dBm
"peakrssi": -3900, // Maximum RSSI if supported by hardware, in mBm
"antenna": 1, // Antenna which read the tag
"freq": 3, // Hardware dependent, frequency used for tag read (Note: Q180/Q300 report read slot)
"phase": 3732, // Phase angle if supported by hardware
"dopplerfreq": 7, // Doppler frequency if supported by hardware
"readresult": 255, // Internal flag whether tag read operation was successful
"writeresult": 255, // Internal flag whether tag write operation was successful
"lockresult": 255, // Internal flag whether tag lock operation was successful
"timestamp": "2019-09-23T07:40:05.520Z", // Timestamp when tag was seen
"timestamp_first": "2019-09-23T07:40:05.520Z" //Timestamp when tag was first seen
}
Engine has one customer logic which is suitable for generic
operations. It is called “Basic”. In order to enable this you need to
specify CUSTOMER=38
in reader.ini file.
Basic logic sends all tags using VVM Asset interface (REST, HTTP POST JSON). Interface specification can be found in Turck Vilant Visibility Manager documentation.
For example, simple data is sent as
{
"assetOperations": [
{
"currentLocation": "TRANSIT",
"timestamp": "2018-09-19T12:03:21.179Z",
"id": {
"primary": "341588F50C470DE4DFC59922"
},
"operation": "MOVE",
"deviceId": "Test1"
}
]
}
If configured with BASIC_SEND_ALL_FIELDS=1 the following output is produced. Note that empty/null tag data fields are not sent.
{ "assetOperations" : [ {
"currentLocation" : "TRANSIT",
"timestamp" : "2018-09-19T12:03:54.635Z",
"id" : {
"primary" : "341588F50C470DE4DFC59922"
},
"operation" : "MOVE",
"deviceId" : "Test1",
"custom" : {
// Contents according to Engine common tag data format
"antenna" : 1,
"customdata" : "xxx",
"direction" : "OUT",
"dopplerfreq" : 4567,
"EPC" : "341588F50C6A94D74F4318BA",
"lockresult" : 3,
"min_rssi" : 206
"peakrssi" : 1212,
"readcount" : 1,
"readresult" : 1,
"rssi" : -50,
"timestamp" : "2017-06-25T23:10:25.123Z",
"timestamp_first" : "2017-06-25T23:10:25.123Z",
"userdata" : "01234567FFFF",
"writeresult" : 2,
}
}]}
/start/3
will start reading on antennas 1 and 2SERVER_URL=
The address where tag reads will be sent, typically VVM. This must include any REST service address so typically you need to add
/rest/assets/operations
to VVM base URL.
If you need authentication, see section “Sending HTTP requests”.
BASIC_FILTERMAP=
Per antenna tagfilter mapping (antenna:filterchain, comma separated). This config can be used to define logical readers with different filters For example
1:1,2:1,3:1,4:1
. If not defined for some antenna then default TAGFILTER chain is used
BASIC_OPERATION=MOVE
Operation name (e.g. CREATE/MOVE/INACTIVATE)
BASIC_SEND_RSSI=0
Whether to send RSSI in custom field
BASIC_SEND_ALL_FIELDS=0
Whether to send all tag data fields to server Value 1 sends fields under
custom
object (requires custom VVM, not supported on default VVM 8) Value 2 sends fields inadditionalInfo
field (works with default VVM 8)
ANTENNA_ACTIONS=1:Warehouse,2:Warehouse,3:TRANSIT,4:TRANSIT
or
ANTENNA_ACTIONS=1:LocA,2:Bin1@Loc1@Site1,3:Bin2@Loc1@Site1,4:Loc3@Site1
Mapping of antennas to locations. This is used as currentLocation when sending data and these are also used for direction detection zones. These locations must exist in VVM or else the sending will fail. It’s possible to also define with 3-level location hierarchy, i.e. NOTE. 3-level location values must follow order
@ @ or @ or @ @
BASIC_TAGS_TO_CSVFILE=0
If set then create tags-yyyy-mm-dd.csv file to SPOOL_PATH. Contains all read data fields:
timestamp, timestamp_first, direction/action, readcount, rssi, min_rssi, antenna, freq, PC, epc, userdata, dopplerfreq, peakrssi, readresult, writeresult, lockresult, customdata
BASIC_TRIGGER_PRE_DELAY=0
BASIC_TRIGGER_POST_DELAY=0
If GPI_TRIGGER is on these configs are used to add extra delay before reading starts and before the reading is stopped. Both values are in milliseconds.
OPERATING_MODE=2
When operating mode=2 this reader acts as a slave reader. Only tagfilter processing is done and then all tags are sent to master engine. This slave will not send any tags to VVM.
How to configure multiple readers in master - slave configuration.
SLAVE CONFIGURATION:
SERVER_URL=http://admin:engine@MASTER_READER_IP:8080/inject
OPERATING_MODE=2
MASTER CONFIGURATION as normally in basic operating mode. Note that tag reads from slave readers to master will have same antenna as they have been reading (eg. slave antenna 1 will be mapped to master reader antenna 1 in BASIC_FILTERMAP and ANTENNA_ACTIONS)
‘Basic shipment’, a customer logic that creates shipments on vvm. it
uses CUSTOMER=17X
(to be changed when released) in
reader.ini file.
Basic shipment uses two filterchains. Chain 0 is for asset tags and chain 1 is for shipment tags. Shipment tags are distinguished by parameter
VILANT_SHIPMENT_SHIPMENT_TAGHEADER
which is the case sensitive prefix in upper case of epc in hex format that a shipment tag should be encoded with.
There are 3 modes for start reading tags and 6 modes for stop reading tags, of which not all are combinable.
VILANT_SHIPMENT_STARTMODE
> 1 = On ‘Shipment’
prefixed tag (VILANT_SHIPMENT_SHIPMENT_TAGHEADER), > 2 = On gpi input
(GPI_TRIGGER), > 3 = On any asset tag
VILANT_SHIPMENT_STOPMODE
> 1 = Timeout from last
shipment tag, > 2 = Timeout from last start, > 3 = Timeout from
last asset tag, > 4 = Timeout from last new tag, > 5 = Timeout
from start gpi trigger, > 6 = End on gpi trigger
(VILANT_SHIPMENT_STOP_TRIGGER needed)
In stopmode, timeouts from a tag seen cannot be used if startmode is a gpi trigger.
READ_TIMEOUT
> Tells the time to wait for read period
to expire, after start is triggered. After READ_TIMEOUT has expired
shipment is created at tvvm.
GPI_TRIGGER
> Tells the gpi pin to use for start
reading if startmode is 2.
VILANT_SHIPMENT_STOP_TRIGGER
> Tells the gpi pin to
use for stop reading if stopmode is 6.
MY_NAME
> ‘sourceLocation’ in shipment creation rest
message
SITE
> ‘sourceLocationSite’ in shipment creation rest
message
VILANT_SHIPMENT_TARGETLOCATION
> ‘targetLocation’ in
shipment creation rest message
VILANT_SHIPMENT_TARGETBIN
> ‘targetLocationBin’ in
shipment creation rest message
VILANT_SHIPMENT_TARGETSITE
> ‘targetLocationSite’ in
shipment creation rest message
Engine software on Turck Q180/Q300 readers have support for a special
mode called Debus passhtru mode. In this mode, a debus client
can connect to reader using TCP connection. In this case, engine will
act as a passhtru proxy forwarding communication between the reader and
the client. Connections are made with TCP sockets using the port defined
with RFID.DEBUS_PASSHTRU_PORT
config parameter.
The mode can be enabled or disabled with a config
RFID.DEBUS_PASSHTRU_ENABLED
.
RFID_ENABLED_ANTENNAS config parameter is a bitmask of enabled antennas so one number tells state for all of the antennas.
Lowest bit means antenna 1, second lowest means antenna 2 and so on.
In Q180/Q300 the antennas 1-4 are the external antenna ports. Internal antenna is ports 5-8 with different polarizations: 5 RHCP, 6 LHCP, 7 horizontal, 8 vertical.
Some examples:
Config | Antenna numbers |
---|---|
1 | 1 |
2 | 2 |
3 | 1, 2 |
15 | 1, 2, 3, 4 |
16 | 5 |
240 | 5, 6, 7, 8 |
255 | 1, 2, 3, 4, 5, 6, 7, 8 |
Engine contains internal HTTP server that by default responds in port
8080 and 8081 (ssl). Both are configurable (HTTPD_PORT
/
HTTPSD_PORT
).
In Impinj R700 readers the default ports are 8088 and 8089 (ssl) due to Impinj reserving 8080 for its internal use.
Accessing any url in above ports, except for /rfid/store, requires basic authentication. There is one, hard-coded, user, ‘admin’ and a configurable password, with default value ‘engine’.
Generate internal input_changed event which will trigger in many customer logics
Command reader to change GPO port state accordingly. Note that this doesn’t respect GPO_SINK, e.g. for typical Impinj setup 0 is on
Command reader to change GPO port state accordingly on a specific IO
device. Indexing for IO devices is described in IO Devices
section.
Param can be either direction (I
or O
) or
GPO state for pin (1
or 0
). Note that this
doesn’t respect GPO_SINK, e.g. for typical Impinj setup 0 is on
NOTE: Using write interface will interrupt any operations that customer logic makes. Restoring custom logic operation, engine may need to be restarted.
The write interface have two use cases:
1) EPC writing
{
"newEpc": "310000000000000000000002",
// 'oldEpc' is optional, if not given, then reader will target first tag it sees.
"oldEpc": "310000000000000000000001",
}
2) Data writing
targetAddress
should be start of word and
newData
should have complete words (= hex string length
divisible by 4). (1 word = 2 bytes){
"filterMemoryBank": 1,
"filterAddress": 32,
"filterLengthBits": 8,
"filterData": "31",
"targetMemoryBank": 3,
"targetAddress": 0,
"newData": "ABCD"
}
Response
success
field flag. More information of the status is given
in field message
.Example success response:
{
"success": true,
"message": "Write OK. Please note that custom logic has been interrupted."
}
Example failure response:
{
"success": false,
"message": "Write failed, no tags seen. Please note that custom logic has been interrupted."
}
Allows you to inject tag reads as if they come from reader normally. Note: Tag is injected to tagfilter so rdr.read() doesn’t work
Use POST with JSON data in Engine common tag data format as described
above. Supports both single tag data and array of tags in the message.
If timestamp is specified as now
it will be replaced with
current time when processing
{
"EPC": "341588F50C6A94D74F4318BA",
"timestamp":"now",
"antenna": 3
}
// or
{
"tags":[
{
"readcount":1,
"EPC":"341588F50C6A94D74F4318BA",
"timestamp":"now"
},
{ ... }
]
}
Extra fields can be left out, they default to zero. Note that customdata is not free()’d by default and specifying it will typically cause memory leak.
Returns status of antennas and GPIO ports. Antenna state reporting is reader dependent feature and is not reliable. Antenna and GPIO names come from Engine configs.
{
"antenna": [
{
"port": 1,
"state": 1,
"name": "IN"
},
{
"port": 2,
"state": 0,
"name": "OUT"
}
],
"gpi": [
{
"port": 1,
"state": 0,
"name": "Trigger"
}
],
"gpo": [
{
"port": 1,
"state": 0,
"name": "Green light"
}
]
}
Generic reader configuration interface. This can be used to change
any parameter similarly as in reader.ini
file. GET method
returns list of all parameters and POSTing same data changes them (only
name
and value
used in POST). New parameters
are saved to reader.ini and reader is reconfigured or restarted to apply
new configs.
NOTE: When Provisioning (DM) is used it will overwrite these configs after a while.
{
"configs": [
{
"name": "MY_NAME",
"value": "FORKLIFT",
"type": "string",
"description": "Reader name/Location ID"
},
{
"name": "RFID_POWER",
"value": "1200",
"type": "string",
"description": "Transmit power. Either single number in mBm or for each antenna separated with ,"
}
]
}
Returns list of tags currently in STORE filter. This can be used for querying seen tags from Engine. Contents are in Engine common tag data format as described above.
{
"tags":[
{
"EPC":"301588F858009D4473D8D797",
"URI":"urn:epc:id:sgtin:6438422.000629.19123459991",
"filterchain":0,
"readcount":1,
"rssi":-39,
"min_rssi":-39,
"antenna":1,
"freq":3,
"phase":3732,
"dopplerfreq":7,
"peakrssi":-3900,
"readresult":255,
"writeresult":255,
"lockresult":255,
"timestamp":"2019-09-23T07:40:05.520Z",
"timestamp_first":"2019-09-23T07:40:05.520Z"
}
...
]
}
Engine provides some standard functionality over MQTT that can be further enhanced in customized logics.
MQTT_SERVER
is the address where to connect in URL
format. For example mqtt://server
or
mqtts://server:8886
. For authentication there is
MQTT_USERNAME
and MQTT_PASSWORD
. If left empty
then unauthenticated connection is made.
<id>
in topics is replaced with the ID of the
reader. ID is same what is used for license activation
/tvs/<id>/status
Periodically updated with the latest status of the reader and LWT is used to provide status: offline on disconnect.
Example contents:
{
"name": "RFID_Gate_1",
"id": "01:02:03:0a:0b:0c",
"status": "online",
"application": "Vilant Engine/Turck (38)",
"version": "2.3.45.0f78ab8",
"last_updated": "2021-11-27T09:00:00Z",
"last_tag_read": "2021-11-27T08:55:53Z",
"components": {
"DEVICE": "OK",
"Antenna1": "OK",
"Antenna2": "Error"
}
}
/tvs/<id>/reads
Preferred topic for tag reads. It is actually controlled by adding
MQTT
tagfilter into wanted filterchain with the actual
topic. Format is the Engine common tag data format as described
above.
/tvs/<id>/gpio
GPIO events for detected inputs and set outputs will be sent here.
{
"type": "output", // input or output
"dev": 0, // IO device number. 0 is the device itself
"pin": 1, // IO pin. Dependss on the hardware
"state": 1 // 0 OFF, 1 ON
}
/tvs/<id>/config
Receives Engine configurations when requested with
cmd/config/get
topic, when configs are mass changed, on
startup and on few other occasions.
Configurations are as in following example:
{
"configs": [
{
"name": "GENERAL.MY_NAME",
"shortname": "MY_NAME",
"value": "RFID_Gate_1",
"type": "string",
"description": "Reader name/Location ID"
},
{
"name": "CUSTOM.OPERATING_MODE",
"shortname": "OPERATING_MODE",
"value": 4,
"type": "integer",
"description": "Operating mode (custom logic dependent)"
}
]
}
/tvs/<id>/cmd/config/get
Will results in configurations being sent to config-topic above.
/tvs/<id>/cmd/config/set
Setting configs can be done with the same data as received from config-topic. If both name and shortname are specified shortname takes precedence.
Note: Reader will immediately take new configs into use and might reboot if required.
/tvs/<id>/cmd/rfid/start
Will start RFID reading. Note: This overrides any functionality in customized logics.
/tvs/<id>/cmd/rfid/stop
Will stop RFID reading. Note: This overrides any functionality in customized logics.
/tvs/<id>/cmd/gpio
Will control GPIO ports. Contents same as in
/tvs/<id>/gpio
topic. Specifying type: input will
generate fake input events.
All tag reads are piped through tagfilter chain where every filter has chance to inspect, modify and drop/forward tag reads. Same filter can be used multiple times with different configs. Some filter configs can create weird and nonworking results.
Tagfilter configuration is somewhat similar to other configs in
reader.ini. There is TAGFILTER-parameter which contains multiple lines.
For multiline configs Engine uses heredoc-style format so all between
<<END
and END
are considered to be part
of the config parameter.
Inside TAGFILTER parameter you can have multiple tagfilters, each one on its own line. Filters can also be specified multiple times and in any order. (Although having MIN_READCOUNT after DUPLICATE will not produce any reasonable results.)
For example
TAGFILTER=<<END
RSSI=-70
MIN_READCOUNT=10,30000ms
DUPLICATE=60000
LIGHT=1,1000ms,1
END
Means throw away tags with <-70 RSSI, then require at least 10 reads during 30 seconds, filter out duplicates from the rest and blink GPO 1 once on first tag read which goes through duplicate filter.
When filterchain contains several filters that store tag reads before passing them on to next filter, the lifetime of tag read must be considered. Each filter examines the read time of the tag. For example in
DIRECTION=5000,10000,MODE1
STORE=3000
no tags will be stored, since their age is already 5000 ms when entering store. Correct filter settings would be
DIRECTION=5000,10000,MODE1
STORE=8000
To store tags for additional 3000 ms in STORE filter.
ANTENNA=ant[,ant]
e.g. ANTENNA=3,4
Accepts reads only from given antennas. Discard others
CLONE=chain
e.g. CLONE=3
Makes a copy of the tag and sends it to specified filterchain
DIRECTION=state,flush,MODE#[,readcount][,USERMEM][,NOEXTRA][,DEBUG]
e.g. DIRECTION=2000,60000,MODE1
state
milliseconds. Depends on mode.
flush
milliseconds. At any time in the process, if
the tag is not seen since ‘flush’ msec, it is removed from
memory.
readcount
in MODE 3D how many reads is needed to
advance to next zone. Default 0
Zones come from ANTENNA_ACTIONS config parameter. For example tag reads from antennas 1+2 are from zone “IN” and reads from antennas 3+4 from zone “OUT”
MODE1
(default) when the tag is not seen for ‘state’
msec, it is passed to the next filter with the direction of the last
zone.
MODE2
similar to MODE1. In addition, requires that
first and last events come from different antenna actions. Or else
UNKNOWN direction will be reported.
MODE3
Once tag has entered the second zone, a
timeout of ‘state’ msec starts. At the end of the timeout, if the tag is
still in the second zone, it is passed to the next filter. If during the
timeout, the tag comes back to the first zone, the timeout is stopped
and nothing happens until the tag comes back to the second zone. After
event has been sent the tag is still in waiting state and new event can
be sent if tag changes zone. If NOEXTRA is specified then this will only
sent single event per tag.
MODE3D
is similar to 3D client. Requires ‘readcount’
reads and ‘state’ ms from single zone without crossreads. Event is sent
after two distinct zones are recognized. If NOEXTRA is specified then
only single event will be sent.
USERMEM
keyword will singulate tags based on user
memory instead of EPC. Tag is dropped if user memory is
missing.
DEBUG will store extra internal debugging data
DOPPLER=limit Hz[,limit ...] [,timewindow ms] [,ANTENNA] [,TID] [,NOT] [,LOG]
e.g. DOPPLER=10Hz
e.g. DOPPLER=10Hz,1000ms
e.g. DOPPLER=10Hz,5Hz,5Hz,ANTENNA
DUMPER=filename [,DECODE_6BIT] [,DECODE_VDA5500]
DUMPER=TCP:12345
e.g. DUMPER=/tmp/tags-%Y%m%d.csv
DECODE_6BIT
is specified then extra field is added
to CSV file with tag EPC decoded as 6bit ASCIIDECODE_VDA5500
is specified then extra field is
added to CSV file with tag EPC decoded as 6bit ASCII and terminated at
EOT marker ‘!’DUPLICATE=timewindow[,timewindow...] [,ANTENNA] [,FIRST] [,TID] [,NOLOG] [,COUNT]
e.g. DUPLICATE=60000
e.g. DUPLICATE=5000,FIRST
Report reads for tags in view every 5 seconds
(i.e. “Session 1” readcounts even with dual target inventory)
e.g. DUPLICATE=30000,20000,30000,20000,ANTENNA
Filter tags uniquely on all antennas with 30/20/30/20s timewindows
EPC_HEX=string [,NOT]
e.g. EPC_HEX=1234 i.e. EPC should contain 1234, at any place in the EPC
e.g. EPC_HEX=^34 i.e. EPC should start with 34
e.g. EPC_HEX=000000,NOT i.e. EPC should not contain 000000
e.g. EPC_HEX=(333|444|555) i.e. EPC should contain 333 or 444 or 555
e.g. EPC_HEX=^(333|444) i.e. EPC should start with 333 or 444
e.g. EPC_HEX=^341(333|444) i.e. EPC should start with 341 which is followed by 333 or 444
e.g. EPC_HEX=(333|444),NOT i.e. EPC should not contain 333 or 444
Each tag is validated according to the matching EPC, case
insensitive. String itself is executed as (posix) regexp so advanced
matching features can be used. A nice tuto on regex is
http://regexone.com. NOT
keyword defines that string must
not match
EPC_LEN=value
e.g. EPC_LEN=96
The tag should have the correct EPC length, in bits, to pass this filter
EPC_MANGLE=mask,replacement
e.g. EPC_MANGLE=00E0,0000 i.e. Change filter to 0
e.g. EPC_MANGLE=FF,30 i.e. Change all tags to be SGTIN-96
This filter modifies tag data during read so that for example further filters will see different tags as same.
LIGHT=gpo,duration,blink
e.g. LIGHT=1,20ms,3
Will turn ON GPO 1 3 times for 20 milliseconds
All parameters are mandatory.
LOG=log_header
e.g. LOG=After Doppler filter
Will display log line such as:
LOG After Doppler filter EPC: 123456789012345678901234 TID: (null) Ant: 1 RSSI: -55.5dBm Doppler: 0.9Hz
Search keyword: logging
MIN_READCOUNT=readcount, timewindow ms [,readcount, timewindow ms] [,ANTENNA] [,TID]
e.g. MIN_READCOUNT=10,30000ms
Require at least 10 reads within 30 seconds.
e.g. MIN_READCOUNT=10,5,10,3,10000ms,10000ms,10000ms,10000ms,ANTENNA
Per antenna readcounts. Require 10 tag events from first antenna, 5 from second etc.
Note: Specifying multiple readcounts/timewindows without ANTENNA keyword will result in strange behavior (limit checked by last seen antenna). You must also have same amount of readcounts and timewindows.
MQTT=topic
e.g. MQTT=/tvs/<ID>/reads
Pushes all seen tags to MQTT with given topic. The
<ID>
in topic is replaced with reader ID. Uses Engine
common tag data format.
REMAP_ANTENNA=1:2,2:3,3:10,4:11
Changes antenna to new defined value. Accepts pairs of old:new antenna. This is useful when sending reads to separate engine so it can differentiate incoming reads from local reads.
Note: Maximum antenna number is 32 (hardcoded, TF_MAX_ANTENNAS)
REQUIRE_USERMEM
Only lets tags pass if they contain some read user memory
RSSI=limit[,limit...] [,NOLOG] [,MAX]
e.g. RSSI=-90,NOLOG
e.g. RSSI=-50,-60,-70,-50
Requires at least given RSSI value for tags. First value used for unspecified antennas. NOLOG suppresses “tag dropped” messages. MAX reverses comparison and drops tags with too high RSSI.
To calculate peak and average RSSI during time window.
Based on DUPLICATE filter, but tags sent when they are getting old, not immediately.
RSSI_CALC=timewindow[,timewindow...] [,ANTENNA] [,FIRST] [,TID] [,NOLOG]
e.g. RSSI_CALC=60000
e.g. RSSI_CALC=5000,FIRST
Report reads for tags in view every 5 seconds
(i.e. “Session 1” readcounts even with dual target inventory)
e.g. RSSI_CALC=30000,20000,30000,20000,ANTENNA
Filter tags uniquely on all antennas with 30/20/30/20s timewindows
RSSI_FLOAT filter updates accepted RSSI levels based on seen values. This filter dynamically increases RSSI level to exclude weaker reads.
RSSI_FLOAT=lower_threshold,flushtimeout,start_limits... [,ANTENNA] [,NOLOG]
e.g. RSSI_FLOAT=2,50,-50,-51
e.g. RSSI_FLOAT=5,50,-50,-51,NOLOG
e.g. RSSI_FLOAT=3,50,-60,-70,-50,ANTENNA,NOLOG
lower_threshold
defines how much weaker a single read
can be compared to best. For instance, if threshold is set to 5 and tag
is filtered at level -50, filter would let tags with -55 RSSI to
pass.flushtimeout
defines how long a certain level is kept.
Value in milliseconds.start_limits
defines hard lower bound values for RSSI
values. Every read weaker than this level are dropped. Each antenna can
be specified separately, missing definitions will use first antenna
value.SEEN=timewindow
e.g. SEEN=10000 [,ANTENNA]
Report tag "seen" event immediately when new tag is seen
After 10 seconds without reads report "lost" event
STORE=duration [,KEEP] [,COUNT] [,DEBUG]
e.g. STORE=10000
Will store tag reads for 10s
e.g. STORE=10,COUNT
Store 10 latest reads
e.g. STORE=10000,KEEP
Store for 10s and keep in internal buffers for next fetch
e.g. STORE=10000,DEBUG
Will additionally log more info
Collect tag reads per antenna and send it to tag analytics endpoint (usually on DM). Works only when PROVISIONING_URL or TAG_ANALYTICS_URL is set. Place this handler so that you only get relevant tag reads, e.g. it should be first handler for all reads, or last one for sending only processed (passed all handlers) events to DM.
TAG_ANALYTICS=mode [,send interval s] [,LOG]
e.g. TAG_ANALYTICS=RAW,120s
Will gather tag statistics and send it every 120 seconds with analyticsDataType = RAW
e.g. TAG_ANALYTICS=PROCESSED
Will gather tag statistics and send it every 60 seconds with analyticsDataType = PROCESSED
Accept tags if there are enough reads within timewindow on same antenna and calculated deviations for reads are within configured thresholds for either phase angle, RSSI or both.
TAG_MOVEMENT=readcount,timewindow ms [,PHASE,low,high] [,RSSI,low,high] [,NOLOG]
e.g. TAG_MOVEMENT=10,3000ms,PHASE,0,20,RSSI,0,1
Allow any tag which was read at least 10 times during last 3 seconds on the same antenna and
its phase deviation is within [0..20] and RSSI deviation is within [0..1]
Note: Config must contain at least one of PHASE or RSSI keywords. Both thresholds must be supplied. Keeping timewindow too wide may slow down calculation, series limit is 1024 data points per EPC per antenna.
Read assets on the forklift forks triggered by reading location tags. When specifed amount of different locations(location tags) are passed within the configured time window, the reading is triggered and assets reading events are sent to the VVM. Locations can be downloaded from VVM or the function can be runned as stand-alone. Assets and location tags can have separate tag filters.
Customer logic 175
# Asset tag filter
TAGFILTER=<<END
DUPLICATE=60000
STORE=10000
END
# STORE timeout is the before-trigger read length
# How long to read for tags after trigger
READ_TIMEOUT=1000
# Location tag filter
TAGFILTER1=<<END
ANTENNA=1
DUPLICATE=10000
END
#Note for standalone mode:
# SERVER_URL must be empty
# Add CLONE=1 to TAGFILTER
# Add EPC_HEX to TAGFILTER1 which will match only location tags
# Add inverse EPC_HEX (i.e. with "NOT") to TAGFILTER to filter out location tags
#How often to poll VVM for locations
LOCATION_SYNC_INTERVAL=300
#Minimum amount of different location tag reads to trigger asset reading
LOCATION_TRIGGER_TAG_COUNT=2
#Location trigger tags must be seen within this time, sliding window
LOCATION_TRIGGER_TIME_WINDOW=1000
Customer logic 13
This operating logic is used for reading tags and communicating events with modbus slave devices, such as PLCs. Reading is controlled with modbus commands. Supported reading modes are continuous reading or triggered reading with defined time configurable time periods. In this mode, the engine reads commands from the holding registers and writes data into input registers.
Configure modbus slave endpoints. Default port is 502 but different ports can be used by defining port in settings
# PLC Gateway IP address / COMMUNICATIONS.GATEWAY_IP
GATEWAY_IP=
# COMMUNICATIONS.GATEWAY_PORT
#GATEWAY_PORT=502
Register setup can be adjusted with following parameters:
#Modbus read start address / CUSTOM.DC_READ_ADDRESS
DC_READ_ADDRESS=0
#Modbus write start address / CUSTOM.DC_WRITE_ADDRESS
DC_WRITE_ADDRESS=0
#1=Read modbus input registers, 0=Read modbus holding registers / CUSTOM.DC_READ_METHOD
DC_READ_METHOD=1
Modbus logic can send asset operation to vvm, provided that
SERVER_URL
is set and additionally can send variable length
data in assetExtrainfo1-field, if operating mode is 1. Also byte
endianess of extrainfo modbus registers (words) can be controlled
#0 = Normal operation,
#1 = Extended operation, where modbus register in index 3 (#4th register) describes how many
#registers, starting from index 4 (#5th register) are used for extraInfo to be sent to vvm in asset operation / CUSTOM.OPERATING_MODE
OPERATING_MODE = 0
#0 = Host byte order (does ntohs on each extrainfo register), 1 = Network byte order (does not do ntohs on each extrainfo register) / CUSTOM.DC_EXTRAINFO_BYTEORDER
DC_EXTRAINFO_BYTEORDER = 0
Tagfilterchain should include STORE to capture tag reads from the desired moment:
# Default filter (if no filtermap)
TAGFILTER=<<END
DUPLICATE=60000
STORE=60000
END
Modbus communication protocol is defined in another document. Please request communication protocol documentation from your TVS contact.
Standard sending mechanism uses message queue.
HTTP Basic authentication credentials can be defined two ways:
HTTP_USERNAME
and HTTP_PASSWORD
fields under COMMUNICATIONS
in Engine configuration. If
either username or password field is empty, then basic authentication is
not used and request is sent without authentication. Both of the fields
need to be defined to use BASIC authentication.https://username:password@example-server.com/path/to/endpoint
.The status for the queue is shown in Engine Web UI in page “Send queue”. This allows monitoring what is being sent, how many times requests have failed. Queue can also be cleared from the Web UI.
The following configuration parameters are found under
COMMUNICATIONS
tab.
SENDER_MAX_TRIES
controls how many times message is
tried to be sent. After exceeding limit, the message is dropped from
sender.
STRICT_ORDERING
controls if messages are sent in same
order as they have been added to queue. Note! Failing messages will
block sending next messages.
SENDER_INITIAL_DELAY
defines the first resending delay.
Resend delay gets doubled after each failed attempt.
Engine has generic support for extra GPIO devices. Actual usage depends on the custom logic but the devices itself are configured in common Engine configuration. Internally device 0 means the reader itself and first device in IO_DEVICES is device 1.
IO_DEVICES=10.6.0.95=TBEN-L5-16DXP,10.6.0.100=TBEN-S2-8DXP
Config parameter contains comma separated list of GPIO-devices. Each device entry contains IP=TYPE config.
Supported types:
Engine IO pins are same as in the device Modbus interface. M12 connector pin 4 is the first IO and pin 2 is the second. For example Engine pin 0 is C0 pin 4, Engine pin 1 is C0 pin 2, Engine pin 2 is C1 pin 4 and so on. More details can be seen in the device manual.
TBEN Vaux pin control is not supported at the moment.
If you want to set initial state of outputs you can use the following config:
IO_INITIAL_OUTPUT=0=000011
This means for device 0 the outputs 0-3 are turned off and 4-5 are turned on. This corresponds to Q180/Q300 having Vaux pins on and other DXP pins off. In this scenario sensors get their power from Vaux and sensor outputs can be seen in input pins.
If you connect traffic lights to reader then you probably want to
turn everything off, e.g. IO_INITIAL_OUTPUT=0=000000
Q180 and Q300 have two DXP ports for IO. They are similar to DXP ports in other Turck devices.
NOTE: If PoE power input is used then output will work only from DXP aux pins. Other output pins will toggle just fine but no actual voltage is output. Inputs work just fine.
Engine | Connector | M12 Pin | Description |
---|---|---|---|
0 | DXP 0/1 | 4 | DXP 0 |
1 | DXP 0/1 | 2 | DXP 1 |
2 | DXP 2/3 | 4 | DXP 2 |
3 | DXP 2/3 | 2 | DXP 3 |
4 | DXP 0/1 | 1 | Vaux |
5 | DXP 2/3 | 1 | Vaux |
Physical connector DXP 0/1 is mapped to Engine pin numbers 0, 1 and 4
Similarly for DXP 2/3 is mapped to Engine pins 2, 3 and 5. Turck documentation DXP Channels match Engine pin numbers. Vaux pins are added after DXP pins.
Note that input pin 0 might mean “not used” in many custom logics. For example GPI_TRIGGER=0 means triggering is not used
Since DXP pins are both input and output the inputs will “see” output as well. Currently output turning on is masked but when output is turned off it will generate input low event.
DXP ports work simultaneously as input and output ports whereas Vaux ports are output-only.
Engine will also log “DXP chan %d Aux power overcurrent” diagnostic messages. In case aux power is turned off this event is generated by hardware and can be ignored.
Impinj R700 has documented ports 0-based whereas we have decided to use 1-based indexing in Engine and in Client.
Engine | Impinj |
---|---|
1 | IN 0 |
2 | IN 1 |
1 | OUT 0 |
2 | OUT 1 |
3 | OUT 2 |
Some GPIO events can be received and sent over a websocket. Websocket
path is /gpio
(e.g. ws://reader:8080/gpio
)
Example output messages:
{ "type":"output", "dev":0, "pin":4, "state":0, "timestamp":"2021-01-13T14:35:46.484Z" }
{ "type":"output", "dev":0, "pin":5, "state":1, "timestamp":"2021-01-13T14:36:51.170Z" }
{ "type":"input", "dev":0, "pin":2, "state":1, "timestamp":"2021-01-13T14:36:56.760Z" }
{ "type":"input", "dev":0, "pin":2, "state":0, "timestamp":"2021-01-13T14:36:57.815Z" }
{ "type":"input", "dev":0, "pin":2, "state":1, "timestamp":"2021-01-13T14:36:59.862Z" }
{ "type":"input", "dev":0, "pin":2, "state":0, "timestamp":"2021-01-13T14:37:00.227Z" }
Sending similarly formatted messages (without timestamp) will cause outputs to be set and fake input messages generated.
Dev refers to IO_DEVICE number. 0 means IO ports integrated to the device.
Below is a listing of config parameters in Engine with Basic logic. Most of the configs are shared with other customer logics
#Reader configuration file
#Vilant Basic: Constant reading.
# Validated tags are sent to VVM: their currentLocation is set according to the ANTENNA_ACTIONS
#Customer logic ID (38 is Basic (standard logic))
CUSTOMER = 38
#Reader name
MY_NAME = VilantEngineBasic
#Reader site in VVM
SITE = Espoo
#===================
#=== TAG FILTER ===
#===================
# TAG FILTER Possible values:
# DUPLICATE
# RSSI
# EPC_HEX
# DOPPLER
# MIN_READCOUNT
# DIRECTION
# REQUIRE_USERMEM
# See README for details.
# Default filter (if no filtermap)
TAGFILTER=<<END
RSSI=-50
DUPLICATE=60000
END
# Per antenna tagfilter mapping (antenna:filterchain)
BASIC_FILTERMAP=1:1,2:1,3:2,4:2
TAGFILTER1=<<END
RSSI=-50
DUPLICATE=60000
END
TAGFILTER2=<<END
DOPPLER=0.5Hz
DUPLICATE=10000
END
#Describe VVM currentLocation for antennas, comma separated i.e. 1:IN,2:IN,3:OUT,4:OUT
#It's possible to also define with 3-level location hierarchy, i.e. 1:LocA,2:Bin1@Loc1@Site1,3:Bin2@Loc1@Site1,4:Loc3@Site1
#NOTE. 3-level location values must follow order <bin>@<loc>@<site> or <loc>@<site> or <bin>@<location>@
ANTENNA_ACTIONS = 1:Vilant,2:Vilant,3:TRANSIT,4:TRANSIT
#VVM operation name
BASIC_OPERATION = MOVE
#Whether to send RSSI value as custom parameter
BASIC_SEND_RSSI = 1
#Whether to send all tag data fields as custom parameters (1=send in custom fields, 2=send as additionalInfo)
BASIC_SEND_ALL_FIELDS = 0
#===================
#=== CONNECTION ===
#===================
#Where data is sent
SERVER_URL=http://demo.vilant.com/visibilitymanager/rest/assets/operations/
HTTP_USERNAME=username
HTTP_PASSWORD=password
PROVISIONING_URL = https://secure.vilant.com/dm/rest/provisioning
PROVISIONING_INTERVAL = 60
PROVISIONING_DEBUG = 0
ALIVEPING_URL = http://secure.vilant.com/I-am-alive/
ALIVE_INTERVAL = 600
#Path to local storage. This is the place where data which was not sent to VVM is saved
# For Impinj without USB: /mnt/ufs/asset
# For Impinj with USB: /mnt/usbfs/usbsda1/asset
# For other readers, check specifications
SPOOL_PATH = /mnt/ufs/asset
#HTTP server port. If 0 then http server is not started
# See README for details
HTTPD_PORT = 8080
#=====================
#=== RFID settings ===
#=====================
#Reader type: LLRP, KBRP, FAKE
RFID_DRIVER = LLRP
#Reader address (ip, hostname, serial port)
RFID_HOST = localhost
# For LLRP: port is 5084
RFID_PORT = 5084
#Transmit power (max 3000 = 30dBm)
# This can be specified per antenna. ALL antennas must be defined if per antenna values are used
RFID_POWER = 2000
#Or RFID_POWER = 2000,1500,3000,2500
#Gen2 session
RFID_SESSION = 2
#Gen2 tag population size (2^q)
RFID_POPULATION = 64
#Read user memory from tag (1=User, 2=TID, 4=XPC)
RFID_MEMORY_READ = 0
#How many words to read from tag memory
RFID_MEMORY_READ_LEN = 0
#Gen2 reader mode
# This differs per reader (see reader specs). When engine starts, the possible values is also printed in logs
RFID_READER_MODE = 5
#Which antenna(s) to use for reading (bitmask, 0=all, 12=4th and 3rd antennas, etc.)
RFID_ENABLED_ANTENNAS = 0
#Gen2 tag (radio)filter length in bits (0 disables the radio filter)
RFID_FILTER_LEN = 0
#Gen2 tag radio filter memory bank (1=EPC, 2=TID, 3=User)
RFID_FILTER_MB = 1
#Gen2 tag filter match position, bits
RFID_FILTER_START_BIT = 16
#Gen2 tag filter mask, hex bytes
RFID_FILTER_MASK =
#LLRP Receive sensitivity
RFID_RECEIVER_SENSITIVITY = 0
#Impinj low duty-cycle empty field timeout (ms), 0 to disable
IMPINJ_LOWDUTY_TIMEOUT = 0
#Impinj low duty-cycle ping interval (ms)
IMPINJ_LOWDUTY_PING = 500
#Impinj inventory search mode (0=reader selects, 1=single, 2=dual, 3=single with suppression)
IMPINJ_INVENTORY = 2
#Thingmagic target strategy (0=A, 1=B, 2=AB, 3=BA)
TM_TARGET = 2
#Thingmagic fast search mode enabled
TM_FASTSEARCH = 0
#Thingmagic antenna detection
TM_ANTENNADETECTION = 0
#======================
#=== DEBUG settings ===
#======================
#Logging output: syslog, stdout, /path/to/file, url
#Also /path/reader_%Y-%m-%d.log for auto rotation
# https://secure.vilant.com/diagnostics
DEBUG_DESTINATION = https://secure.vilant.com/diagnostics
#Debug level (standard syslog levels)
# 3: ERR
# 5: NOTICE
# 6: INFO
# 7: DEBUG
# 8: DEBUG++
DEBUGLEVEL = 7
#=====================
#=== GPIO settings ===
#=====================
#GPI read trigger for start reading.
#For all the time reading, set this to -1
#It activates when GPI is HIGH.
#It stops when level is LOW
GPI_TRIGGER = -1