control_operation
ReferenceAudience: API consumerUse: start or stop the RFID radio (or the scanner) on demand
Overview
control_operation starts or stops a reader subsystem on demand. You pick a controlType (RFID — the radio inventory engine, or SCANNER — the barcode scanner) and an operation (START or STOP). For RFID, START begins an inventory cycle using the currently configured operating mode and the device streams tag reads as dataEVT events until you STOP (or the operating-mode stop conditions are met). It is a state-changing control-plane (CTRL) command, and it is reversible — a START is undone by a STOP.
This is a CTRL-endpoint command, published on the control endpoint (<tenantId>/CTRL/clients/cmnd/<serial>) and answered only there (not on the MGMT/MDM channel). Returning a response requires an active CTRL endpoint (config_endpoint, epType: CTRL, activate: true). Receiving the tag stream that START triggers also requires an active DATA1 endpoint (<tenantId>/DATA/clients/data1event/<serial>; see the data endpoint topic mapping).
Set the regulatory region first. Before you start an RFID inventory, make sure the reader’s regulatory region is configured: the reader does not transmit until it is, and the region is set outside MQTT with 123RFID Desktop or 123RFID Mobile. Use get_current_region to verify the current region.
A START executes whatever the operating mode has armed — including destructive access operations. See the danger callout in Notes and Caveats.
A first inventory, once the region is set, the operating mode is configured and you have subscribed to the DATA1 topic:
Details
| Property | Value |
|---|---|
| Interaction Pattern | Request / Response (app publishes a command; device publishes the correlated reply) |
| State Change | STATE-CHANGING (starts / stops the radio or scanner) |
| Reversibility | REVERSIBLE (a START is undone by a STOP) |
| Supported Operations | START, STOP |
| Required Request Fields | command, requestId (ctrlOprPayload is optional in the contract; inside it, controlType and operation are required) |
| Applies To | Endpoint: Control (CTRL). Reader: RFD40 series, RFD90 series |
| API Version | V1.1 (API Version Reporting) |
| Related | set_operating_mode, get_operating_mode, get_status, reboot |
When to Use
Use control_operation to drive the radio (or scanner) on demand:
- Start an inventory —
controlType: RFID,operation: STARTbegins reading tags with the current operating mode; the device streamsdataEVTevents over the DATA endpoint. - Stop an inventory —
operation: STOPhalts the radio; the tag stream ceases. - Control the scanner —
controlType: SCANNERstarts / stops the barcode scanner instead of the radio.
Configure how the reader reads with set_operating_mode first, then START — control_operation itself has no tuning parameters. If the inventory state is uncertain, check it with get_status before sending START.
Topic Mapping
control_operation is the one command that drives both planes: the command travels over CTRL, while the device publishes the tag events a START triggers over DATA.
| Plane | Message | Direction | Topic | Note |
|---|---|---|---|---|
| CONTROL | Request | App → Reader | <tenantId>/CTRL/clients/cmnd/<serial> | On the control endpoint. Requires an active CTRL endpoint. |
| CONTROL | Response | Reader → App | <tenantId>/CTRL/clients/resp/<serial> | Correlated reply; the in-payload requestId links the twin topics. |
| DATA | Event | Reader → App | <tenantId>/DATA/clients/data1event/<serial> | The dataEVT stream a RFID START triggers. Requires an active DATA1 endpoint to receive it. |
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 command is answered only on the CTRL endpoint; the tag stream is published on the DATA1 endpoint's configured publish topic (data1event by default). DATA2 is currently not supported.
See Topics and Channels.
Key Fields
ctrlOprPayload.controlType(request) —RFID(radio inventory engine) orSCANNER(barcode scanner).ctrlOprPayload.operation(request) —START(begin) orSTOP(halt).response.code(response) — read this to determine success vs failure. The contract requires it; note the reported success-path omission (see Success without a code). See Response Codes.
Request Payload
The envelope is command, requestId, and the ctrlOprPayload (controlType + operation). Pick an operation below; the Example and Schema update together. Use the Schema tab for the full field reference and the Example tab for the concrete payload.
- Example
- Schema
| Field | Type | Enum / Units | Example | Description |
|---|---|---|---|---|
command* | enum | control_operation | control_operation | Fixed command name (pinned by the schema enum). |
requestId* | string | — | abc123 | A unique identifier for the request; echoed back in the response. |
ctrlOprPayload | object | — | — | The control operation to perform. Optional in the contract; when present, the contract requires both controlType and operation within it. |
controlType*, nesting level 2 | enum | RFIDSCANNER | RFID | Which reader subsystem to control — RFID (the radio inventory engine) or SCANNER (the barcode scanner). Required within the payload. |
operation*, nesting level 2 | enum | STARTSTOP | START | START begins the operation for the selected subsystem; STOP halts it. Required within the payload. |
Request Semantics
Modes. ctrlOprPayload.operation selects the action for the chosen controlType:
START— begin the operation. ForRFID, this starts an inventory cycle using the current operating mode and streamsdataEVTevents over the DATA endpoint.STOP— halt the active operation. ForRFID, the tag stream ceases (a single in-flight read may still be flushed shortly after — see Notes).
A STOP when no operation is active returns code 12 ("No Radio Operation in Progress") — this is not a failure, the device is already idle. A START while an inventory is already running returns code 11 ("Inventory in progress").
SCANNERuses the same request envelope asRFID.ctrlOprPayloaddeclares onecontrolType(RFID|SCANNER) and oneoperation(START|STOP), both required, with no scanner-specific field and no separate payload — a scanner request differs from an RFID request only in thecontrolTypevalue. Decoded barcodes are declared on the DATA plane, not in this command's response: thedataEVTdata object carriesbarcodeData[](decodedBarcode, plussymbology, the barcode type as a hexadecimal string such as0x03) alongsidetagData[]. Codes11and12above are radio-scoped — the contract describes them as an RFID inventory already running and no radio operation active — and the schema defines no scanner-specific response code, leaving code23for acontrolTypeoroperationoutside its enum. Physical-trigger behavior and per-model scanner coverage are outside the schema and are not documented here — see Scan Barcodes.
Response Payload
control_operation returns a status-only envelope — command, requestId, apiVersion, and response. The tag reads arrive separately as dataEVT events on the DATA endpoint; the response carries no data echo.
- Example
- Schema
| Field | Type | Enum / Units | Example | Description |
|---|---|---|---|---|
command* | string | — | control_operation | Echoes the executed command. |
requestId* | string | — | abc123 | Echoes the request's requestId — pairs reply to request. |
apiVersion* | enum | V1.0V1.1V1.2V1.21V1.22 | V1.1 | API version reported by this command. Emitted per-handler, not device-wide. |
response* | object | — | — | Status-only result — control_operation echoes no configuration. |
code*, nesting level 2 | integer | 0–101 | 0 | 0 = Success; non-zero = error. Required by the contract. Readers have been reported to omit it on success — see Response Payload and Response Codes below. |
description*, nesting level 2 | string | — | Success | Human-readable status. |
The contract requires response.code. Readers have been reported to omit it on a successful reply, returning just response: { "description": "Success" } — treat that as success too. See Success without a code.
As reported, a successful START or STOP can arrive with code omitted. This form does not validate against the contract; the reply with code: 0 above is the documented form:
Response Codes
control_operation returns response.code. The codes applicable to this command are below; for the full table see the Response Codes and Correlation and Request/Response Pairing.
| Code | Description |
|---|---|
0 | Success — the radio (or scanner) started or stopped. (Readers have been reported to omit code on this reply — see above.) |
11 | Inventory in progress (IOT_ERROR_INVENTORY_IN_PROGRESS) — a START was sent while an RFID inventory is already running. Stop the current inventory first; if the state is uncertain, check get_status. |
12 | No Radio Operation in Progress (IOT_ERROR_NO_RADIO_OP_IN_PROGRESS) — a STOP was sent while the radio is already idle. Not a failure — no action required. Unique to this command. |
23 | Invalid enum value (IOT_ERROR_INVALID_ENUM) — controlType or operation is outside its allowed set. |
101 | Default error — generic catch-all. |
Examples
Publish control_operation over the CTRL endpoint; the device replies with the status envelope under Response Payload. The Operation dropdown under Request Payload shows the START and STOP requests. The examples below show what the dropdown does not: the tag stream that START triggers, and the two common error responses.
A RFID START triggers a dataEVT stream on the DATA endpoint. Each event's type echoes the active operating-mode profile, and the mode's tagMetaDataToEnable flags gate which tagData fields appear (here the default mode reports EPCid / eventNum / peakRssi / seenCount only):
A STOP issued while the radio is already idle returns code 12 (not a failure):
A START issued while an inventory is already running returns code 11:
Notes and Caveats
STARTcontrol_operation has no tuning parameters; a START runs whatever set_operating_mode last configured. If destructive access operations (WRITE / LOCK / KILL) are armed, START executes them on every tag in range — KILL and PERMANENT_LOCK are irreversible. Confirm the operating mode is read-only (no armed accessOperations) before starting a production inventory. See set_operating_mode § Notes and Caveats.
STARTdrives two planes; the tag stream requires a DATA endpoint. The command round-trip is on the CTRL endpoint, but the tag reads aRFIDSTARTproduces are published asdataEVTevents on the DATA endpoint (<tenantId>/DATA/clients/data1event/<serial>forDATA1_EP). To receive them, aDATA1endpoint must be active — activate one withconfig_endpoint.dataEVT.typeechoes the active operating-mode profile, and the mode'stagMetaDataToEnableflags gate whichtagDatafields appear (EPCidis always present).STOPis immediate at the radio, but a trailing read may still flush. ASTOPstops the radio right away, yet a single in-flight / buffered read may still be delivered on the DATA plane a couple of seconds after theSTOP(≈2.9 s observed on RFD40) before the stream fully ceases. Do not treat one trailingdataEVTafter aSTOPas continued inventory.- Configure the mode before you
START. Set profiles, power, triggers,selectfilters, and access operations withset_operating_modefirst, thenSTART;control_operationitself sets none of these. The operating mode is volatile: it resets to the default (BALANCED_PERFORMANCE, no armed access operations) onreboot, so re-apply it after a reboot before starting. - An attached terminal has priority. Apps on a terminal attached to the reader, whether Android, iOS or Windows, always have priority over MQTT commands, and a user can start an inventory from the terminal while the reader is connected to the broker. What the reader replies to a
control_operationthat a terminal app overrides is not specified in the available sources. See The Reader Is Its Own MQTT Client.
control_operation is reversible (START ↔ STOP) and carries no credentials — the tag EPCid values in the resulting dataEVT stream are identifiers read off physical tags, not secrets. SCANNER control follows the same request/response shape as RFID (verified paths are RFID START/STOP on RFD40). For the concept-level view, see Inventory Control.
Related: 📕 set_operating_mode · 📕 get_operating_mode · 📕 get_status · 📕 dataEVT · 📕 Inventory Control · 📘 Scan Barcodes · 📕 Response Codes