LLRP vs Native SDK: An RFID Reader Manufacturer's Integration Decision Table
Which LLRP? Version box
A datasheet line that just says “LLRP” does not tell you which edition a reader’s firmware implements. The number that settles it is the Version field in the header of every LLRP message, mapped in Table 3 of the current standard.
| Edition | Date on the document | Publisher | Version field |
|---|---|---|---|
| LLRP 1.0.1, Ratified Standard with Approved Fixed Errata | 13 August 2007 | EPCglobal | 1 |
| LLRP 1.1, Ratified Standard | 13 October 2010 | EPCglobal | 2 |
| GS1 LLRP Standard, Release 2.0, Ratified | Jan 2021 | GS1 | 3 |
One trap: the change log inside Release 2.0 lists the 2010 document as release 1.0, the EPCglobal edition, followed by 2.0 (Dec 2020, eBallot WR 19-274). GS1’s “1.0” is EPCglobal’s 1.1, not 1.0.1, so when a supplier writes “LLRP 1.0”, ask for the Version value the reader returns.
Section 18 explains why older clients keep working: future versions may not add mandatory parameters or fields to existing messages, change existing fields or alter version negotiation. New functionality arrives only as optional parameters, extension points, extended enumerations, reserved bits, new messages or custom extensions. An older edition costs features, not compatibility.
What changed across 1.0.1, 1.1 and 2.0
Built by searching the three ratified texts for each feature; a dash means absent.
| Feature | 1.0.1 | 1.1 | 2.0 |
|---|---|---|---|
Version negotiation: GET_SUPPORTED_VERSION, SET_PROTOCOL_VERSION | — | Added | Yes |
LoopSpec inside a ROSpec | — | Added | Yes |
| Gen2 BlockPermalock OpSpec | — | Added | Yes |
Time-based report triggers (ROReportTrigger 3–6) | — | Added | Yes |
Unique-tag stop triggers (TagObservationTrigger 3–4) | — | Added | Yes |
Report upon N inventory rounds (ROReportTrigger 7) | — | — | Added |
| Gen2 crypto OpSpecs: Authenticate, AuthComm, SecureComm, ReadBuffer, Untraceable, KeyUpdate, TagPrivilege; Challenge in the inventory command | — | — | Added, each optional |
Communications Standard values in RegulatoryCapabilities | 0–9 | 0–34 | 0–38, some deprecated |
| Minimum TLS version when TLS is used | TLS 1.0 | TLS 1.0 | TLS 1.3 |
Each 2.0 crypto operation is a MAY, advertised through C1G2LLRPCapabilities flags such as CanSupportAuthenticate, CanSupportSecureComm and CanSupportUntraceable; the standard spells out that a reader reporting CanSupportUntraceable false must reject an ADD_ACCESSSPEC containing that OpSpec. “Supports LLRP 2.0” and “supports Gen2 tag authentication over LLRP” are separate claims.
Under section 9.1.1 the client opens with GET_SUPPORTED_VERSION at Version 2; a reader that answers M_UnsupportedVersion is treated as 1.0.1 only. The agreed version holds for the whole connection (section 19.1.3).
Tender clause
“The reader shall implement GS1 LLRP Release 2.0 (Version field 3) [or LLRP 1.1, Version field 2]. The following optional capabilities are mandatory: [for example CanSupportBlockPermalock, HasUTCClockCapability]. With the offer, the bidder shall submit the GET_SUPPORTED_VERSION_RESPONSE and the complete GET_READER_CAPABILITIES_RESPONSE (RequestedData = 0, All) captured from the offered firmware.”
What LLRP standardises: an annotated ROSpec and AccessSpec
Worked example: a dock door with a photo-eye on input 1 and two antennas. A ROSpec moves from Disabled (0, after ADD_ROSPEC) to Inactive (1, after ENABLE_ROSPEC) to Active (2, on its start trigger). It is shown as JSON with the abstract specification’s parameter names; on the wire it is the section 16 binary encoding.
{
"ROSpec": {
"ROSpecID": 101, "Priority": 0, "CurrentState": 0,
"ROBoundarySpec": {
"ROSpecStartTrigger": { "ROSpecStartTriggerType": 3,
"GPITriggerValue": { "GPIPortNum": 1, "GPIEvent": true, "Timeout": 0 } },
"ROSpecStopTrigger": { "ROSpecStopTriggerType": 2, "DurationTriggerValue": 0,
"GPITriggerValue": { "GPIPortNum": 1, "GPIEvent": false, "Timeout": 15000 } }
},
"AISpec": {
"AntennaIDs": [1, 2],
"AISpecStopTrigger": { "AISpecStopTriggerType": 0, "DurationTrigger": 0 },
"InventoryParameterSpec": {
"InventoryParameterSpecID": 1, "ProtocolID": 1,
"AntennaConfiguration": { "AntennaID": 0,
"C1G2InventoryCommand": { "TagInventoryStateAware": false,
"C1G2SingulationControl": { "Session": 1, "TagPopulation": 40, "TagTransitTime": 3000 } } }
}
},
"ROReportSpec": { "ROReportTrigger": 6, "N": 500,
"TagReportContentSelector": { "EnableAntennaID": true, "EnablePeakRSSI": true,
"EnableChannelIndex": true, "EnableFirstSeenTimestamp": true,
"EnableLastSeenTimestamp": true, "EnableTagSeenCount": true } }
}
}
| Field | Meaning here | Decided by |
|---|---|---|
ROSpecStartTriggerType: 3, port 1, true | Starts when the photo-eye input goes true; a reader with no GPIs must reject the ROSpec | Client; the reader maps the electrical edge |
ROSpecStopTriggerType: 2, timeout 15000 | Stops when input 1 returns false, or after 15 s as a fail-safe | Client |
AntennaIDs: [1, 2] | Two antenna inventory operations (2 antennas × 1 InventoryParameterSpec) | Reader sets order and timing |
TagPopulation: 40, TagTransitTime: 3000 | Estimates: about 40 tags in view, each for about 3 s | Hints; the reader picks the algorithm |
ROReportTrigger: 6, N: 500 | A report every 500 ms or at ROSpec end; value 6 needs Version 2 or 3 | Client |
The AccessSpec reads the TID bank of every tag the ROSpec singulates:
{
"AccessSpec": {
"AccessSpecID": 201, "AntennaID": 0, "ProtocolID": 1,
"CurrentState": false, "ROSpecID": 101,
"AccessSpecStopTrigger": { "AccessSpecStopTriggerType": 1, "OperationCountValue": 100 },
"AccessCommand": {
"C1G2TagSpec": { "C1G2TargetTag": { "MB": 1, "Match": true, "Pointer": 0,
"TagMask": "", "TagData": "" } },
"C1G2Read": { "OpSpecID": 1, "AccessPassword": 0, "MB": 2, "WordPtr": 0, "WordCount": 0 }
},
"AccessReportSpec": { "AccessReportTrigger": 1 }
}
}
It stays disabled until ENABLE_ACCESSSPEC, applies to ROSpec 101 on all antennas, and matches every tag because the target mask has zero length. MB: 2 is TID; WordCount: 0 reads to the end of the bank, which suits TIDs of differing length. The spec deletes itself after 100 executions. If several AccessSpecs match a tag, only the first enabled one in creation order runs, and its OpSpecs stop at the first failure.
Knobs LLRP exposes, and knobs the reader keeps
The client controls triggers, antenna sets, session, select filters, RF mode and power (both by index) and report contents. The reader keeps antenna sequencing inside an AISpec, the singulation algorithm, the reader-defined RF mode table and the meaning of an observation, which the standard calls “vendor specific”. Two compliant readers given the same ROSpec share a protocol contract, not a read pattern.
Section 10.2.2 sets the floor: one ROSpec, one AISpec per ROSpec, one InventoryParameterSpec per AISpec, one AccessSpec and one OpSpec per AccessSpec. Beyond that, read MaxNumROSpecs and MaxNumAccessSpecs from the capabilities. The standard defines one encoding, binary; LTK’s XML and the JSON used by llrpjs and EdgeX are toolkit conventions mapped onto it.
Region and power as LLRP sees them
LLRP reports the regulatory mode rather than setting it. RegulatoryCapabilities, inside GET_READER_CAPABILITIES_RESPONSE, carries a Country Code (ISO 3166 numeric, 0 for unspecified) and a Communications Standard value describing the device’s current operational mode. It is not a member of SET_READER_CONFIG.
| Value | Regulation as listed in 2.0 | MHz | Power | First appears |
|---|---|---|---|---|
| 1 | United States FCC 15.247 | 902–928 | 4 W EIRP, FHSS | 1.0.1 (as US FCC Part 15) |
| 11 | ETSI 302-208 Lower Band | 865–868 | 2 W ERP | 1.1 (as ETSI 302-208 2W without LBT) |
| 35 | Japan | 916.7–920.9 | 4 W EIRP | 2.0 |
| 36 | Japan | 916.7–923.5 | 0.5 W EIRP, LBT | 2.0 |
| 37 | Brazil | 915–928 | 4 W EIRP, FHSS | 2.0 |
| 38 | New Zealand | 920–928 | 6 W EIRP, FHSS | 2.0 |
No row names India. India’s G.S.R. 853(E) of 10 December 2021 permits RFID interrogators at 2 W e.r.p. in 865–868 MHz, only on four channels centred at 865.7, 866.3, 866.9 and 867.5 MHz, matching the band edges and power of value 11. Inference, not text from the standard: an India-configured reader would most plausibly report Country Code 356 with value 11, and a US FCC-band reader 840 with value 1. Check the reader’s own response.
TransmitPowerLevelTable entries are in dBm × 100, conducted at the reader’s connector, so 3000 means 30.00 dBm conducted. RFTransmitter carries an index into that table, not a dBm value. Radiated power then depends on antenna gain and cable loss, as worked in our reader power-budget guide; per-region profiles are in the RAIN regional settings table. RFTransmitter also carries HopTableID for hopping regions and ChannelIndex into the FixedFrequencyTable for non-hopping ones.
Region is therefore set through a vendor extension, a device-management interface or at the factory. For an export order, ask which, and request the capabilities response from a unit configured for the destination.
Control path vs management path
Section 3 of the standard splits the work below filtering and collection into a data path, a management path and a control path. LLRP is built for the control path and adds device status, error reporting and capability discovery.
SET_READER_CONFIG accepts a closed list: ReaderEventNotificationSpec, AntennaProperties, AntennaConfiguration, ROReportSpec, AccessReportSpec, KeepaliveSpec, GPOWriteData, GPIPortCurrentState, EventsAndReports and custom parameters. Section 13.1.3 applies those values for the duration of the connection; section 19 makes keeping them across connections a MAY.
Firmware, IP addressing, time source, certificates and hostname belong to the management path; EdgeX’s LLRP device service notes that hostname is not available through LLRP. EPCglobal standardised this layer once: Discovery, Configuration and Initialization (DCI) for Reader Operations, Ratified Standard 1.0, June 10, 2009, defined an Access Controller to discover readers, configure them and download firmware. Today it is a web console, a vendor API or a fleet tool.
For Identium readers that layer is ReaderSense Edge + MDM: the on-reader application handles the data path with local storage, HTTP or WebSocket upload and MQTT, and the MDM console handles fleet health, configuration push and firmware updates over an outbound connection from each reader.
Connections, ports and security
Section 19.1.1 requires readers and clients both to initiate and to accept LLRP TCP connections, so a reader behind a site NAT can dial out to a reachable client. Whichever side dials, the reader speaks first with a ConnectionAttemptEvent reporting success.
Section 19.1.2 allows one established connection per reader IP address and TCP port; a second client is normally sent a connection-failure event and closed. Each LLRP session belongs to one application.
IANA registers llrp on port 5084 and encrypted-llrp on 5085, with TCP and UDP entries dated 2006-11; the standard names them as defaults and allows other ports.
| Edition | Section | TLS in LLRP | Minimum version |
|---|---|---|---|
| 1.0.1 | 18.2.1 | Optional (MAY) | TLS 1.0, TLS 1.1 recommended |
| 1.1 | 20.2.1 | Optional (MAY) | TLS 1.0, TLS 1.1 recommended |
| 2.0 | 19.2.1 | Optional (MAY), default port 5085 | TLS 1.3 |
RFC 8996 (March 2021, BCP 195) deprecated TLS 1.0 and 1.1 and moved them to Historic status, so a 1.x reader can comply fully with its own edition while offering only a retired TLS version. If transport encryption matters, specify Release 2.0 TLS on 5085 and have the handshake demonstrated, or encrypt the onward channel. The product-security law behind these questions is covered in our Cyber Resilience Act guide.
An architecture that fits the one-client rule
| Hop | Interface |
|---|---|
| Reader to middleware | One LLRP connection or one native SDK session |
| Middleware to consumers | MQTT topics or HTTP webhooks; WMS, dashboards and analytics each subscribe |
| Reader with on-reader middleware | The first hop runs inside the reader, which publishes over HTTP or MQTT itself |
Where portability ends: extensions, form factors and SDKs
Section 8 gives vendors a sanctioned door: CUSTOM_MESSAGE and the Custom Parameter, each keyed to an IANA Private Enterprise Number plus a subtype. Readers return an error for custom parameters they do not support; clients may ignore them.
| Data | Standard LLRP 2.0 | Usual route beyond the standard |
|---|---|---|
| EPC, antenna, channel, first and last seen, seen count | EPC data, AntennaID, ChannelIndex, FirstSeenTimestamp, LastSeenTimestamp, TagSeenCount | Standard |
| Signal strength | PeakRSSI: signed integer in whole dBm, −128 to +127 (14.2.3.7) | Finer resolution via a custom parameter or native SDK |
| RF phase angle, Doppler frequency | No field in the 2.0 text | Custom parameter or native SDK; sllurp’s protocol table decodes both as vendor custom parameters |
| Inventory search behaviour | Session, C1G2Filter, TagInventoryStateAware | Vendor search modes via custom parameters or SDK |
| Reader health such as temperature | No field; standard events cover GPI, antenna, ROSpec, buffer level and reader exceptions | Management interface, custom parameters or SDK |
LLRP is defined only over TCP (section 19). Handhelds, USB desktop readers and embedded modules on serial or Bluetooth use the maker’s native SDK, or the RAIN Alliance’s Reader Communication Interface: RCI V4.0 (August 2020) is JSON (ISO/IEC 21778) over a point-to-point serial stream such as RS-232, Bluetooth or TCP/IP, defaults to 115,200 bit/s 8N1 on serial, and is designed to work from a plain serial terminal.
Identium’s integration scope: native SDKs for Android, Windows and Flutter; a C# desktop demo for bench work; and ReaderSense, middleware that runs on the reader itself and pushes tag events over HTTP or MQTT to your systems. The reader classes are on our handheld, fixed and integrated reader pages.
Open-source toolkits by language
Facts as each project documents them, in no order of merit.
| Toolkit | Language | Licence | LLRP editions, as documented |
|---|---|---|---|
| LLRP Toolkit (LTK) | C, C#, C++, Java, Perl | Apache 2.0 | Built from LTK’s llrp-1x0-def.xml definition (per llrpjs); check each binding for 1.1 |
| llrpjs | Node.js (TypeScript) | MIT | Uses llrp-1x0-def.xml; JSON mapped one-to-one from LTK XML |
| pyllrp | Python | MIT | README points to the 1.0.1 standard; bundles one vendor’s extension set |
| sllurp | Python | GPL-3.0 | Encoder defaults the Version field to 1 (1.0.1) |
| EdgeX device-rfid-llrp-go | Go | Apache-2.0 | 1.0.1 and 1.1, negotiation handled by the service |
| LlrpSdk (LLRPCSharp), 2.0.5 on NuGet | C# on .NET 10 | MIT | 1.0.1, 1.1 and 2.0 adapters |
LlrpSdk is the one library here implementing Release 2.0, and its own support table records 2.0 physical-reader interoperability as not yet accepted. The practical baseline today is a 1.0.1 client that negotiates up to 1.1 where the reader offers it; prove any 2.0-only feature, TLS 1.3 included, on the bench with the exact reader and firmware you will deploy.
The 10-row decision table, tender wording and acceptance checklist
| Requirement | Recommended interface | Deciding clause or source | Ask the supplier |
|---|---|---|---|
| Middleware already speaks LLRP | LLRP, version pinned | Table 3; s. 9.1.1 | Version returned, plus the full capabilities response |
| Portable Gen2 control across reader makes | Standard LLRP parameters only | s. 18; s. 10.2.2 | Which required functions need custom parameters? |
| RF phase, Doppler or sub-dBm RSSI | Native SDK or documented LLRP extension | s. 14.2.3.7; s. 8 | Field, unit, resolution and carrying interface |
| Several applications per reader | One connection into middleware, then MQTT or HTTP fan-out | s. 19.1.2 | Does the reader publish to a broker itself? |
| USB, serial or Bluetooth device | Native SDK or RAIN RCI JSON | s. 19 (TCP only); RCI V4.0 | SDK platforms, licence, RCI support |
| Firmware, network, time, certificates, region | Device-management layer | s. 13.1.3 member list; DCI 1.0 | How each is set across 100 readers, by what API |
| Encrypted reader link | LLRP 2.0 TLS on 5085, or TLS on the push channel | s. 19.2.1; RFC 8996 | Negotiated TLS version, shown in a capture |
| Gen2 tag authentication | LLRP 2.0 crypto OpSpecs where flags are true, else native SDK | C1G2LLRPCapabilities | Which CanSupport flags are true? |
| Reading and buffering with no host after reboot | On-reader middleware | s. 19 (state across connections is a MAY) | After a power cycle with no client, does it resume, and where does data go? |
| Swap reader hardware later | Standard LLRP subset behind your own middleware | s. 18; LLRP 1.1 Conformance | Which test case requirements were run, with logs? |
Tender wording
“The reader interface shall be one of: (a) LLRP at the stated version, using only standard parameters for the functions in Schedule X; (b) a native SDK for the stated platforms, with licence terms; or (c) reader-resident middleware publishing over MQTT or HTTP to a documented schema. Firmware, network, time, certificates and region shall be managed through a documented interface.” Our UHF RFID tender template has the surrounding clauses.
Acceptance checklist mapped to the LLRP 1.1 conformance TCRs
The LLRP 1.1 Conformance Requirements Document (approved October 13, 2010) defines TCR-1 to TCR-15, with TCR-12 omitted. Run each against the delivered firmware:
- TCR-1 TCP connections: both directions succeed; a second connection is refused.
- TCR-2 Protocol version management.
- TCR-3 Get reader capabilities: archive the response against the tender.
- TCR-4 Custom messages and parameters: unsupported ones return an error.
- TCR-5 Errors and status codes.
- TCR-6 Read operations and reporting, with your ROSpec.
- TCR-7 Reader operations in loop (
LoopSpec). - TCR-8 Access operations and reporting, with the TID AccessSpec.
- TCR-9 Tag observations and count-based triggering.
- TCR-10 Immediate triggering.
- TCR-11 AISpec stop trigger.
- TCR-13 Polled reporting (
GET_REPORT). - TCR-14 Keepalives.
- TCR-15 Lock and kill, on sacrificial tags.
By its own scope statement, the conformance programme does not set out to test performance, reliability or scalability. Add a separate RF acceptance test at the real portal with your tags, travel speed and pass/fail rules, using our missed-reads and stray-reads guide.
Frequently asked questions
What is the latest version of LLRP?
GS1 LLRP Standard Release 2.0, ratified January 2021, Version field 3. The earlier EPCglobal editions are LLRP 1.1 of 13 October 2010 (Version 2) and LLRP 1.0.1 of 13 August 2007 (Version 1). GS1’s change log calls the 2010 edition release 1.0, so check the Version value a reader returns.
Is LLRP still used for RFID readers?
Yes. Open-source LLRP clients such as EdgeX Foundry’s Go device service and the Python library sllurp received commits in 2026, a .NET SDK covering all three editions reached 2.0.5 on NuGet, and ports 5084 and 5085 remain registered to LLRP with IANA.
What port does LLRP use?
TCP 5084 for plain LLRP and 5085 for TLS-protected LLRP, both registered with IANA. The standard names them as defaults and allows other ports.
Can more than one application connect to an LLRP reader at the same time?
Section 19.1.2 allows one established connection per reader IP address and TCP port, and a second client is normally refused. Connect one middleware instance and fan the data out over MQTT or HTTP.
Does LLRP support TLS encryption?
TLS is optional in every edition. LLRP 1.0.1 and 1.1 set the floor at TLS 1.0; Release 2.0 requires at least TLS 1.3, default port 5085. RFC 8996 deprecated TLS 1.0 and 1.1 in March 2021, so specify Release 2.0 TLS for an encrypted LLRP link.
Can you set an RFID reader's region over LLRP?
LLRP reports region rather than setting it. RegulatoryCapabilities carries an ISO 3166 country code and a Communications Standard value, and it is not a member of SET_READER_CONFIG. Region is set through a vendor extension, a device-management interface or at the factory.
When should I use a reader SDK instead of LLRP?
Use a native SDK for USB, serial or Bluetooth devices (LLRP is TCP only), for data outside the standard such as RF phase, Doppler or sub-dBm RSSI, and for device management. Use on-reader middleware when the reader must keep pushing data with no host attached. Use LLRP when networked fixed readers feed middleware that already speaks it.
Sources
- GS1 Low Level Reader Protocol (LLRP) Standard, Release 2.0, Ratified, Jan 2021 (archived copy of ref.gs1.org/standards/llrp/2.0.0/)
- EPCglobal Low Level Reader Protocol (LLRP) Version 1.1, Ratified Standard, October 13, 2010 (archived)
- EPCglobal Low Level Reader Protocol (LLRP) Version 1.0.1, Ratified Standard with Approved Fixed Errata, August 13, 2007 (archived)
- EPCglobal LLRP 1.1 Conformance Requirements Document, Approved October 13, 2010 (archived)
- EPCglobal Discovery, Configuration, and Initialization (DCI) for Reader Operations, Ratified Standard 1.0, June 10, 2009 (archived)
- IANA Service Name and Transport Protocol Port Number Registry: llrp 5084, encrypted-llrp 5085
- RFC 8996, Deprecating TLS 1.0 and TLS 1.1 (BCP 195), March 2021
- RAIN RFID Alliance, RAIN Reader Communication Interface (RCI) Guideline V.4.0, August 2020
- Gazette of India, G.S.R. 853(E), 10 December 2021: Use of Low Power Equipment in the Frequency Band 865-868 MHz for Short Range Devices (Exemption from Licence) Rules, 2021
- UN Statistics Division, Standard country or area codes (M49): India 356, United States 840
- EdgeX Foundry device-rfid-llrp-go (README: discovery on port 5084, hostname not available through LLRP; Apache-2.0)
- EdgeX Foundry, Hacker's Guide to LLRP (1.0.1 and 1.1 with version negotiation)
- sllurp llrp_proto.py (RF phase angle and Doppler decoded as vendor custom parameters)
- sllurp repository (GPL-3.0)
- pyllrp repository (MIT)
- llrpjs repository (MIT; uses LTK llrp-1x0-def.xml, JSON mapped from LTK XML)
- LLRP Toolkit on SourceForge (C, C#, C++, Java, Perl; Apache License V2.0)
- llrp.org, LLRP Toolkit home
- LLRPCSharp repository (LlrpSdk; LLRP 1.0.1, 1.1, 2.0 support table; MIT)
- NuGet, LlrpSdk 2.0.5