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
| Property | Value |
|---|---|
| Event Type | Tag-data (and barcode) read output |
| Trigger | Inventory (started with control_operation START; stops on STOP) |
| Applies To | Endpoint: Data (DATA). Reader: RFD40 series, RFD90 series |
| Credentials | None device-side; a RESERVED-bank read can expose a tag's access and kill passwords (see Notes) |
| Interaction Pattern | Publish / Subscribe (device-emitted, unsolicited; no request/response, no response.code) |
| Related | alerts, 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-presentEPCidplus 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
accessOperationsare armed, each read'saccessResults[]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.
| Message | Direction | Topic | Note |
|---|---|---|---|
| Event | Reader → App | <tenantId>/DATA/clients/data1event/<serial> | The first data channel's tag stream. |
| Event | Reader → 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 carriesEPCid(hex tag identifier) plus the requiredeventNum(per-record sequence number).EPC/TID/USER/RESERVED(event) — memory-bank contents as hex, each present only when its bank is enabled; aRESERVEDread 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 itstagMetaDataToEnableflag.accessResults[](event) — one string per armed access operation (READ/WRITE/LOCK/KILL); present only whenaccessOperationsare 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.
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.
STARTSTART 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
INCLUDEpost filter that matches nothing. A filter reporting only matching tags will report none if the pattern matches none. Read it back withget_post_filter— see Shaping. - A reconfiguration that was refused. Code
35rejects 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.
- Example
- Schema
| Field | Type | Enum / Units | Example | Description |
|---|---|---|---|---|
type | enum | FAST_READCYCLE_COUNTDENSE_READERSOPTIMAL_BATTERYBALANCED_PERFORMANCEADVANCED | BALANCED_PERFORMANCE | The active operating-mode profile in effect for this read (echoes the profile set by set_operating_mode). |
timestamp* | string | — | 2026-06-16T06:03:36.894Z | ISO-8601 time the event was generated. The only required top-level field. |
data | object | — | — | Read payload — RFID tag reads and/or barcode reads. |
tagData, nesting level 2 | array | — | — | RFID tag reads (batched; the contract declares no per-event record limit). Which fields appear is gated by the operating mode tagMetaDataToEnable flags; EPCid is always present. |
EPCid*, nesting level 3 | string | — | 000011C1A5000062F7952926 | EPC Identifier — the always-present tag identifier, as a hex string. |
EPC, nesting level 3 | string | — | D98A3000AAAABBBB11112222CCCCDDDD | EPC memory-bank contents (present when EPC metadata is enabled). |
TID, nesting level 3 | string | — | e20060030178529d | TID memory-bank contents (present when TID is enabled). |
USER, nesting level 3 | string | — | 12343333123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678 | USER memory-bank contents (present when USER is enabled). |
RESERVED, nesting level 3 | string | — | 12343333123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678 | RESERVED memory-bank contents (present when read via an access op). ⚠️ May contain the tag access / kill passwords — see Notes. |
PC, nesting level 3 | string | — | 3000 | PC bits of the inventoried tag (when PC is enabled). |
CRC, nesting level 3 | string | — | b06a | CRC bits. |
channel, nesting level 3 | number | — | 926750 | The channel the reader used when the tag was inventoried. ⚠️ Emitted as a raw channel value/index, NOT a MHz frequency despite the schema label — see Telemetry Semantics. Present only in the per-read shape. |
eventNum*, nesting level 3 | number | — | 13 | Per-read event sequence number. Required, like EPCid. |
format, nesting level 3 | string | — | epc | Format of the tag data (EPCid). Declared as optional, and not observed on the wire. |
peakRssi, nesting level 3 | number | — | -59 | RSSI in dBm (when RSSI is enabled). With aggregation, the peak RSSI since the last report. |
phase, nesting level 3 | number | — | 0 | Phase in degrees (when PHASE is enabled). Present only in the per-read shape. |
seenCount, nesting level 3 | number | — | 256 | Times the tag was inventoried since the previous report (when the SEENCOUNT flag is enabled via set_operating_mode); always 1 in the per-read shape. |
XPC, nesting level 3 | string | — | — | XPC bits of the inventoried tag, if present. |
accessResults, nesting level 3 | array | — | ["READ-EPC-Success", …] | Results of the configured access operations (one string per op). Present only when access ops are configured via set_operating_mode — see Telemetry Semantics. |
userDefined, nesting level 3 | string | — | — | A user-defined string included on every event (when configured). |
firstSeenTime, nesting level 3 | number | — | — | Timestamp the tag was first seen (ms since epoch). |
lastSeenTime, nesting level 3 | number | — | — | Timestamp the tag was last seen (ms since epoch). |
MAC, nesting level 3 | string | — | AC:3F:A4:00:2B:15 | MAC address of the reader (when MAC is enabled). |
HOSTNAME, nesting level 3 | string | — | RFD40-211545201D0034 | Hostname of the reader (when HOSTNAME is enabled). |
barcodeData, nesting level 2 | array | — | — | Contains a collection of barcode data events. |
symbology, nesting level 3 | string | — | 0x03 | The specific encoding standard and geometric format used to represent data in the barcode. It is represented in hexadecimal format. |
decodedBarcode*, nesting level 3 | string | — | PWR-BGA24V78W1WW 183213949 | The decoded string value from the scanned barcode. |
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:
| Switch | Field it enables |
|---|---|
RSSI | peakRssi |
PHASE | phase |
CHANNEL | channel |
SEENCOUNT | seenCount |
EPC | EPC — or EPCid; see below |
PC, XPC, CRC, TID, USER, MAC, HOSTNAME | the 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.
accessResultsarrives with configured access operations, not with metadata flags. It is populated only when you armaccessOperations(READ/WRITE/LOCK/KILL). A bank read enabled purely throughtagMetaDataToEnablesurfaces as theEPC/TID/USERmetadata fields instead — which is why you can see bank contents with noaccessResultsat all. For how to read the strings, see Telemetry Semantics.- Which field the
EPCswitch controls is not documented. It could enableEPCorEPCid. Their descriptions differ —EPCis the memory bank's contents,EPCidthe item identifier — andEPCidis required on every record anyway. Code againstEPCidand treatEPCas 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,peakRssiandseenCountappear 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
tagMetaDataToEnableinset_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
dataEVTarrives in one of two shapes. Per-read: every individual read is reported, sochannelandphaseare present andseenCountis1. Aggregated: reads are combined and reported at intervals, sochannelandphaseare absent,seenCountcounts the reads since the previous report, andpeakRssiis 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 ofchannelis the discriminator. - Despite the schema describing
channelas a value "in MHz", the device emits a raw channel value/index (e.g.9216), not a ~900 MHz frequency. Treatchannelas an opaque channel index; do not interpret it as megahertz.channel(andphase) are present only in the per-read shape. - Reading
accessResultsstrings. 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 bareSUCCESSfor writes. The shape is one string per armed operation, in the order the operations were configured. typeechoes the profile.typecarries 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 isFAST_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 withepType(DATA1/DATA2, which is currently not supported). The contract declares both and never states the correspondence, soDATA_EP1toDATA1is 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.
EPCidis 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
eventNumcontinuity 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,peakRssiandseenCount. - Tag data with additional details — EPC and TID memory plus
channel,phase,MACandHOSTNAME, with theirtagMetaDataToEnableflags on. In this per-read shapechannelandphaseare present andseenCountis1. - Tag events for access operations — a configured
READof the EPC, TID and RESERVED banks, with the outcomes inaccessResults. - Barcode data event — a scanned barcode, reported in
data.barcodeData[]instead oftagData. Barcode reads were not exercised live; this is the contract's example.
Notes and Caveats
RESERVED bank reads expose tag passwordsThe 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.)
STOPis not instantaneous for buffered reads.control_operationSTOPhalts the radio, but a buffered in-flightdataEVTbatch may still be delivered a few seconds afterSTOP(≈3–5 s observed on RFD40). Do not treat adataEVTarriving shortly afterSTOPas an error, and do not stop listening the instant you sendSTOP.
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