Skip to main content

dataEVT

ReferenceAudience: API consumerUse: interpret the reader's tag-read (and barcode) output

Overview​

dataEVT is the reader's tag-data event — the device publishes it autonomously while an inventory is running, carrying the RFID tag reads (and any barcode reads) it produces. It is device-emitted (no command is in the payload path), but it only flows once you start an inventory with control_operation START, using whatever the set_operating_mode profile configured. It is read-only tag output.

Each event is a small envelope — type (the active profile), timestamp, and a data object holding a tagData[] array (and/or a barcodeData[] array). Reads are batched — the contract declares no limit on records per event — and the operating mode's tagMetaDataToEnable flags gate which fields each tag carries — of a record's twenty declared fields, only two are always there. See Field Support.

dataEVT is published on the DATA endpoint's data topic (e.g. <tenantId>/DATA/clients/data1event/<serial> for DATA1), not the event topic (alerts / heartBeatEVT) or the rfid topic (mqttConnEVT). Receiving it requires an active DATA1 endpoint (config_endpoint, epType: DATA1, activate: true). The contract also declares a second data channel, DATA2, but it is currently not supported.

Details​

PropertyValue
Event TypeTag-data (and barcode) read output
TriggerInventory (started with control_operation START; stops on STOP)
Applies ToEndpoint: Data (DATA). Reader: RFD40 series, RFD90 series
CredentialsNone device-side; a RESERVED-bank read can expose a tag's access and kill passwords (see Notes)
Interaction PatternPublish / Subscribe (device-emitted, unsolicited; no request/response, no response.code)
Relatedalerts, heartBeatEVT, mqttConnEVT, set_operating_mode

When to Use​

Consume dataEVT to receive the tags an active inventory finds — it is the reader's sole tag-output stream:

  • Collect tag reads — subscribe to the DATA endpoint's data topic and process each event's data.tagData[] (the always-present EPCid plus any enabled memory-bank and telemetry fields).
  • Collect barcode reads — the same stream carries data.barcodeData[] when a barcode is scanned during the operation.
  • Read access-operation results — when accessOperations are armed, each read's accessResults[] reports the outcome of the configured READ/WRITE/LOCK/KILL.

dataEVT is device-emitted — there is no request/response and no polling equivalent; you cannot fetch a tag read on demand. Configure it first with set_operating_mode, start the stream with control_operation START, and stop it with STOP. If it is already running and nothing arrives, work through Emission.

Topic Mapping​

dataEVT is device-emitted and has no cmnd/resp topics. It is published on the DATA endpoint's data topic.

MessageDirectionTopicNote
EventReader → App<tenantId>/DATA/clients/data1event/<serial>The first data channel's tag stream.
EventReader → App<tenantId>/DATA/clients/data2event/<serial>The second data channel. Currently not supported: the reader does not yet support a DATA2 endpoint, so nothing is published here.

Topics follow the pattern <tenantId>/<topic>/<serial> — the tenant id assigned to you at provisioning (a slot you fill in, never a literal), the base topic you configure on the endpoint, and the reader's serial number, which the reader appends itself in its model-prefixed form (for example RFD40-212735201D0053). App → Reader means your app publishes and the reader subscribes; Reader → App means the reader publishes and your app subscribes.

The exact middle segment is the topic configured in the DATA endpoint's publishTopics[1] — the slot, not the topic text, is what routes tag data. See Emission.

See Topics and Channels.

Key Fields​

Every dataEVT payload field below is read-only device output; the final Emission gate bullet is a request-side control (what arms the stream), not a payload field.

  • type (event) — the active operating-mode profile echoed on the read (e.g. BALANCED_PERFORMANCE); the reader emits the same profile on every event of a run.
  • timestamp (event) — ISO-8601 time the event was generated; the only required top-level field.
  • data.tagData[] (event) — the batch of RFID reads. Each read always carries EPCid (hex tag identifier) plus the required eventNum (per-record sequence number).
  • EPC / TID / USER / RESERVED (event) — memory-bank contents as hex, each present only when its bank is enabled; a RESERVED read can expose the tag's access/kill passwords (see Notes).
  • peakRssi / phase / channel / seenCount (event) — per-read telemetry: RSSI in dBm, phase in degrees, the raw channel value, and the seen-count — each gated by its tagMetaDataToEnable flag.
  • accessResults[] (event) — one string per armed access operation (READ/WRITE/LOCK/KILL); present only when accessOperations are configured.
  • data.barcodeData[] (event) — barcode reads (decodedBarcode, symbology) when a barcode is scanned during the operation.
  • Emission gate (request) — the stream flows only when an endpoint, an operating mode and a running inventory all line up. No active inventory, no dataEVT. The full chain, with a check at each link, is Emission.

Emission​

Every command in this chain can return code: 0 while the stream stays silent. The response-code catalogue is a closed 39-member set and not one member describes a data endpoint that is missing, inactive or wrongly addressed — so a silent stream produces no error to read. Silence is the signal, and this section is the checklist.

Work down it in order. Each link has something you can verify.

1. Subscribe Before You Start​

Tag data is published with retain: false on all three telemetry channels, so anything published before your subscription is live is gone and is never redelivered. A client that sends START and then subscribes sees an empty stream that is not a configuration fault at all.

2. A DATA Endpoint Must Exist​

epType is a closed six-member enum — MGMT, MGMT_EVT, CTRL, DATA1, DATA2, MDM — and only the data types carry tag and barcode data. DATA2 is currently not supported, so create a DATA1 endpoint with config_endpoint using operation: add.

Verify: get_endpoint_config and read the returned activeEndpoints.

3. It Must Be Activated​

activate is a boolean and its default is false, so an endpoint you did not explicitly activate is not carrying anything. Send activate: true for the data endpoint of type DATA1 — on the add, or with an update if the endpoint was saved dormant. The reader checks the parameters and, if they are valid, connects the endpoint without a reboot. A CONNECTED mqttConnEVT on the endpoint’s connection-state topic confirms it.

The trap that produces a silent stream

publishTopics is a three-slot positional array, and it is the position that routes — slot 0 is command replies, slot 1 is asynchronous events, slot 2 is the connection event and the Last Will. On a data endpoint slot 1 carries the tag data. The conventional names resp / event / rfid are a convention and are not auto-detected.

So a single-entry payload — one topic, in slot 0 — lands in the reply slot and streams nothing. The endpoint is created, the command succeeds, and no tag data ever arrives. A DATA endpoint needs two entries: a filler in slot 0 and the tag-data topic in slot 1.

4. An Operating Mode Must Be Configured, and It Does Not Survive a Reboot​

Set the profile and the metadata flags with set_operating_mode. Two things to know:

  • The mode is not persistent. A reboot discards it and the reader returns to its default operating mode (see set_operating_mode), so re-apply the mode after any reboot.
  • Do not configure FAST_READ. The contract states that data events are not currently supported under that profile, and describes the profile itself as not currently supported — pick another profile.

5. Start the Inventory​

The reader does not transmit until its regulatory region is set, and the region is set outside MQTT with 123RFID Desktop or 123RFID Mobile. Confirm it with get_current_region, then send control_operation START. Stop with STOP.

Check what the mode has armed before you send START

START executes whatever set_operating_mode last configured, including destructive accessOperations — see the caution in Notes and Caveats before starting a production inventory.

Still Silent?​

Two causes that look like a broken stream and are not:

  • An INCLUDE post filter that matches nothing. A filter reporting only matching tags will report none if the pattern matches none. Read it back with get_post_filter — see Shaping.
  • A reconfiguration that was refused. Code 35 rejects a change to an active endpoint and advises deactivating it first. The contract does not document how to deactivate an endpoint directly, so instead of updating the active endpoint in place, do one of the following:
    • Delete the endpoint, then add it again with the new settings.
    • Activate a different endpoint first, then update the original endpoint.

One thing not to rely on: watching for an mqttConnEVT as proof the endpoint came up. A connection event shows a session, not that tag data is routed to slot 1, so use get_endpoint_config instead.

Telemetry Payload​

The envelope is type, timestamp (the only required field), and data. Pick a read-detail level below; the Example and Schema update together — from a base tag batch, to reads enriched with EPC/TID and reader telemetry, to access-operation results and a barcode read. Use the Schema tab for the full field reference and the Example tab for the concrete batch.

Telemetry payload
Example: base tag data (abridged)
{
"type": "BALANCED_PERFORMANCE",
"timestamp": "2026-06-16T06:03:36.894Z",
"data": {
"tagData": [
{
"EPCid": "E28011B0A506007D3DD07C0F",
"eventNum": 41,
"peakRssi": -73,
"seenCount": 256
},
{
"EPCid": "311100000000000000000000",
"eventNum": 42,
"peakRssi": -50,
"seenCount": 256
},
{
"EPCid": "11113333880600890630DBEC",
"eventNum": 43,
"peakRssi": -53,
"seenCount": 256
},
{
"EPCid": "000011C1A5000062F7952926",
"eventNum": 44,
"peakRssi": -65,
"seenCount": 256
},
{
"EPCid": "E200001B880600870630DBEB",
"eventNum": 45,
"peakRssi": -44,
"seenCount": 256
},
{
"EPCid": "1111333300004001B043ACB2",
"eventNum": 46,
"peakRssi": -36,
"seenCount": 256
},
{
"EPCid": "11113333333344445555AAAA",
"eventNum": 47,
"peakRssi": -32,
"seenCount": 256
},
{
"EPCid": "11113333A5000062F798E5B6",
"eventNum": 48,
"peakRssi": -34,
"seenCount": 256
},
{
"EPCid": "11113333333344445555AAAA",
"eventNum": 49,
"peakRssi": -36,
"seenCount": 256
},
{
"EPCid": "11115555222233334444A9B6",
"eventNum": 50,
"peakRssi": -43,
"seenCount": 256
},
{
"EPCid": "111133332222333344445555",
"eventNum": 51,
"peakRssi": -44,
"seenCount": 256
},
{
"EPCid": "111133332222333344445550",
"eventNum": 52,
"peakRssi": -43,
"seenCount": 256
},
{
"EPCid": "FFFFEEEE3435363742426666",
"eventNum": 53,
"peakRssi": -51,
"seenCount": 256
},
{
"EPCid": "11113333333344445555AAAA",
"eventNum": 54,
"peakRssi": -46,
"seenCount": 256
},
{
"EPCid": "11113333880600900630DBF1",
"eventNum": 55,
"peakRssi": -52,
"seenCount": 256
},
{
"EPCid": "E200001B880600840630DBE2",
"eventNum": 56,
"peakRssi": -57,
"seenCount": 256
},
{
"EPCid": "111133332222333344445555",
"eventNum": 57,
"peakRssi": -63,
"seenCount": 256
},
{
"EPCid": "111133332222333344445555",
"eventNum": 58,
"peakRssi": -63,
"seenCount": 256
},
{
"EPCid": "111133332222333344445555",
"eventNum": 59,
"peakRssi": -62,
"seenCount": 256
},
{
"EPCid": "E200001B880600870630DBEB",
"eventNum": 60,
"peakRssi": -44,
"seenCount": 256
},
{
"EPCid": "000011C1A5000062F7952926",
"eventNum": 61,
"peakRssi": -66,
"seenCount": 256
},
{
"EPCid": "11113333B22FB22FB22FB22F",
"eventNum": 62,
"peakRssi": -65,
"seenCount": 256
},
{
"EPCid": "AAAABBBB11112222CCCCDDDD",
"eventNum": 63,
"peakRssi": -60,
"seenCount": 256
},
{
"EPCid": "BEDD11112222333344445555",
"eventNum": 64,
"peakRssi": -45,
"seenCount": 256
},
{
"EPCid": "311100000000000000000000",
"eventNum": 65,
"peakRssi": -51,
"seenCount": 256
},
{
"EPCid": "11113333880600890630DBEC",
"eventNum": 66,
"peakRssi": -53,
"seenCount": 256
},
{
"EPCid": "1111FB63AC1F3841DADA00000000CAFEDADACAFEDADACAFE00001111",
"eventNum": 67,
"peakRssi": -57,
"seenCount": 256
},
{
"EPCid": "E28011B0A506007D3DD07D01",
"eventNum": 68,
"peakRssi": -72,
"seenCount": 256
},
{
"EPCid": "E28011B0A506007D3DD07C0F",
"eventNum": 69,
"peakRssi": -69,
"seenCount": 256
},
{
"EPCid": "E28011B0A506007D3DD07D00",
"eventNum": 70,
"peakRssi": -70,
"seenCount": 256
},
{
"EPCid": "11115555222233334444A9B6",
"eventNum": 71,
"peakRssi": -41,
"seenCount": 256
},
{
"EPCid": "111133332222333344445550",
"eventNum": 72,
"peakRssi": -45,
"seenCount": 256
},
{
"EPCid": "311100000000000000000000",
"eventNum": 73,
"peakRssi": -65,
"seenCount": 256
},
{
"EPCid": "111133332222333344445555",
"eventNum": 74,
"peakRssi": -61,
"seenCount": 256
},
{
"EPCid": "A1B22222BBBB",
"eventNum": 75,
"peakRssi": -65,
"seenCount": 256
}
]
}
}

Field Support​

A tag record declares twenty fields. Two are always there, twelve are switched, and six have no switch at all.

Always present: EPCid and eventNum, the two fields the schema marks required. Everything else is conditional.

Switched by tagMetaDataToEnable in set_operating_mode. The switch names are ALL-CAPS on purpose — they mirror the EPC Gen2 air-protocol spelling and are wire-fixed — and four of the twelve do not match the field they enable:

SwitchField it enables
RSSIpeakRssi
PHASEphase
CHANNELchannel
SEENCOUNTseenCount
EPCEPC — or EPCid; see below
PC, XPC, CRC, TID, USER, MAC, HOSTNAMEthe identically named field

Six fields have no switch: RESERVED, firstSeenTime, lastSeenTime, accessResults, userDefined, format. The contract does not say which of them firmware can control. Two of them do arrive in practice — RESERVED and accessResults both appear when accessOperations are configured — so the absence of a switch is not the same as the absence of the field.

  • accessResults arrives with configured access operations, not with metadata flags. It is populated only when you arm accessOperations (READ/WRITE/LOCK/KILL). A bank read enabled purely through tagMetaDataToEnable surfaces as the EPC/TID/USER metadata fields instead — which is why you can see bank contents with no accessResults at all. For how to read the strings, see Telemetry Semantics.
  • Which field the EPC switch controls is not documented. It could enable EPC or EPCid. Their descriptions differ — EPC is the memory bank's contents, EPCid the item identifier — and EPCid is required on every record anyway. Code against EPCid and treat EPC as bank content you asked for.
  • No switch declares a default, and the contract does not say which metadata the device reports when you ask for none. What the contract's examples show is narrow and consistent: EPCid, eventNum, peakRssi and seenCount appear in 40 of 40 example records. Treat that as the observed floor, not a guarantee, and treat every other field as optional.

Telemetry Semantics​

What each record carries. Two things determine the content of a dataEVT record — which fields are switched on, and which of the two reporting shapes you are receiving:

  • Which fields are present is governed by tagMetaDataToEnable in set_operating_mode. The full switch-to-field mapping, the two always-present fields and the six with no switch at all are in Field Support.
  • Two reporting shapes — and no command in this API selects between them. A dataEVT arrives in one of two shapes. Per-read: every individual read is reported, so channel and phase are present and seenCount is 1. Aggregated: reads are combined and reported at intervals, so channel and phase are absent, seenCount counts the reads since the previous report, and peakRssi is the peak since that report. The reader's firmware governs which shape you get; the contract declares no field for it and no operation carries one, so treat the shape as something you detect, not something you set — the presence of channel is the discriminator.
  • Despite the schema describing channel as a value "in MHz", the device emits a raw channel value/index (e.g. 9216), not a ~900 MHz frequency. Treat channel as an opaque channel index; do not interpret it as megahertz. channel (and phase) are present only in the per-read shape.
  • Reading accessResults strings. When the array is present (see Field Support for when that is), each string is one operation's outcome — READ-EPC-Success, or an error, or a bare SUCCESS for writes. The shape is one string per armed operation, in the order the operations were configured.
  • type echoes the profile. type carries the active operating-mode profile (e.g. BALANCED_PERFORMANCE), and the reader emits the same value on every event of a run — so it identifies the run, not the record. One value you will not see here is FAST_READ; Emission explains why, and why you should not configure it. How much arrives per event is Volume and Limits.

Shaping​

tagMetaDataToEnable changes what each record carries. Post filters change which records exist. That is the whole distinction, and it is the one worth keeping straight.

A post filter is applied after inventory, on the stream's way out, and it is the only control that changes which tag records reach a data endpoint. Configure it with set_post_filter and read it back with get_post_filter — the rule shape, the match methods and the INCLUDE/EXCLUDE semantics are documented there and not repeated here.

Three things to know from the dataEVT side, because the contract leaves them open:

  • The endpoint vocabularies differ and are not mapped. Filters scope to dataEpType (DATA_EP1 / DATA_EP2); endpoints are configured with epType (DATA1 / DATA2, which is currently not supported). The contract declares both and never states the correspondence, so DATA_EP1 to DATA1 is the necessary reading rather than a documented one.
  • The pattern matches the tag ID, and the contract does not name which payload field that is. EPCid is the only always-present identifier, so it is the reasonable assumption — confirm against firmware before relying on it. Nothing ties post filtering to barcode reads on the same stream.
  • Do not use eventNum continuity as a loss detector while a filter is installed. Nothing in the contract says whether a suppressed read still consumes a sequence number. See Delivery and Loss.

Also undocumented, and worth a read-back rather than an assumption: whether filters survive a reboot, how many rules an endpoint accepts, and what happens when two rules on one endpoint disagree.

Delivery and Loss​

dataEVT carries no response or code — it is device-emitted, so the command response-code table does not apply and no response code is defined for any event. The only thing that tells you something went wrong is what fails to arrive.

Tag data travels at the QoS you set on the data endpoint’s tag-data topic, publishTopics[1].qos: 0 or 1, the two levels the reader supports. The reader’s default endpoint configurations use 0, and the channels declare retain: false. At QoS 0, loss is normal rather than exceptional. At either level, nothing is replayed to a subscriber that was not listening. Delivery and Retry Semantics has the full treatment. QoS 1 changes the transport guarantee without making the reader re-send anything it already dropped.

eventNum is the only ordering signal on the wire. It is a per-record sequence counter, and the contract documents no wrap-around, no reset rule and no scope — so do not assume the counter restarts between runs, or that it does not. A break in the sequence is a prompt to investigate, not proof of loss: it cannot distinguish a dropped publish from a record the reader never emitted. And a batch arriving shortly after STOP is a late buffered batch, not a gap — see Notes and Caveats.

Volume and Limits​

Firmware caps a whole dataEVT message at 6144 bytes, and there is no record-count limit. The current contract states neither limit; the byte cap is a firmware limit that the device owners confirmed, and firmware notes it can be increased to support batching, so treat it as a current-build number. An over-size message is dropped by the reader, with no error, and the connection stays up: the symptom is a message that never arrives. Size a buffer against 6144 bytes and a variable record count — not against a tag count. The serialisation is not stated: any tags-per-event arithmetic assumes minified JSON.

The declared controls live on the endpoint as batching: reportingInterval (1000–60000 ms) and maxPayloadSizePerReport (1024–5120 bytes); a 0 in either falls back to the minimum. A report is flushed on whichever comes first, and the contract does not document which wins when both thresholds are near. Send both members together — whether setting one and omitting the other leaves the other at its default is undocumented. The contract's examples use 1000 / 1024.

Examples​

Every contract example is in the Read detail dropdown under Telemetry Payload, and which fields appear reflects the operating-mode configuration:

  • Tag data event — the default fields only: EPCid, eventNum, peakRssi and seenCount.
  • Tag data with additional details — EPC and TID memory plus channel, phase, MAC and HOSTNAME, with their tagMetaDataToEnable flags on. In this per-read shape channel and phase are present and seenCount is 1.
  • Tag events for access operations — a configured READ of the EPC, TID and RESERVED banks, with the outcomes in accessResults.
  • Barcode data event — a scanned barcode, reported in data.barcodeData[] instead of tagData. Barcode reads were not exercised live; this is the contract's example.

Notes and Caveats​

RESERVED bank reads expose tag passwords

The RESERVED memory bank holds a tag's access and kill passwords. If you configure a READ of the RESERVED bank, those passwords appear in dataEVT as the RESERVED hex field — treat that data as sensitive. (EPCid and the other bank contents are physical-tag data, not device or broker credentials.)

  • STOP is not instantaneous for buffered reads. control_operation STOP halts the radio, but a buffered in-flight dataEVT batch may still be delivered a few seconds after STOP (≈3–5 s observed on RFD40). Do not treat a dataEVT arriving shortly after STOP as an error, and do not stop listening the instant you send STOP.

Start the stream with control_operation START and stop it with STOP. Because dataEVT reflects the operating mode, any armed destructive accessOperations (WRITE/LOCK/KILL) execute on the tags read during the run — confirm the mode is read-only before starting (see set_operating_mode § Notes). For the concept-level view, see Tag Data Stream, Choose Shared or Dedicated Data Endpoints, and dataEVT.

Related: 📕 control_operation · 📕 set_operating_mode · 📕 config_endpoint · 📕 Events · 📕 Tag Data Stream · 📘 Choose Shared or Dedicated Data Endpoints

Was this helpful?