set_operating_mode
ReferenceAudience: API consumerUse: configure the reader's RFID operating mode
Overview
set_operating_mode configures the reader's RFID operating mode — the profile, advanced RF configuration, tag access operations, radio start/stop triggers, the Gen2 query, select pre-filters, and tag-metadata reporting flags. It is a state-changing control-plane (CTRL) command. It is a partial, merging update: you send only the sub-objects you want to change and they merge into the current mode. Read the result back with get_operating_mode.
accessOperations arm destructive tag operations (WRITE / LOCK / KILL) that execute on the next inventory — KILL and PERMANENT_LOCK are irreversible. See the danger callout in Notes and Caveats before sending.
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). This requires an active CTRL endpoint (config_endpoint, epType: CTRL, activate: true); without one, you get no response.
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.
Details
| Property | Value |
|---|---|
| Interaction Pattern | Request / Response (partial-merge configuration) |
| State Change | STATE-CHANGING (arms access ops; changes RF config) |
| Reversibility | REVERSIBLE / VOLATILE (reset to default on reboot, or re-send to change) |
| Required Request Fields | command, requestId (operatingMode.operatingModes is optional in the contract; send it with the aspects to set) |
| Applies To | Endpoint: Control (CTRL). Reader: RFD40 series, RFD90 series |
| API Version | V1.1 (API Version Reporting) |
| Related | get_operating_mode, control_operation, config_endpoint, reboot |
When to Use
Use set_operating_mode to configure how the reader reads (and acts on) tags:
- Select a profile —
CYCLE_COUNT(read as many unique tags as possible),DENSE_READERS(multiple readers in proximity),OPTIMAL_BATTERY(best battery life),BALANCED_PERFORMANCE(default; balances performance and battery life), orADVANCED(custom link-profile settings viaadvancedConfigurations).FAST_READ(maximum read speed within short range) is enumerated but not currently supported. - Tune the radio — transmit power, link profile, session, dynamic power (ADVANCED).
- Compose triggers —
radioStartConditions/radioStopConditions(trigger, delay, tag/time/cycle stops). - Shape inventory — Gen2
queryand up to 32selectpre-filters. - Choose reporting —
tagMetaDataToEnableflags. - Arm tag operations —
accessOperations(READ/WRITE/ACCESS/LOCK/KILL) that run on the next inventory. Handle with care (see the danger note).
Topic Mapping
| Message | Direction | Topic | Note |
|---|---|---|---|
| Request | App → Reader | <tenantId>/CTRL/clients/cmnd/<serial> | On the control endpoint. Requires an active CTRL endpoint. |
| Response | Reader → App | <tenantId>/CTRL/clients/resp/<serial> | Correlated reply; the in-payload requestId links the twin topics. |
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.
Control commands are answered only on the CTRL endpoint.
If control commands time out, confirm a CTRL endpoint is active (get_endpoint_config → activeEndpoints) and activate one with config_endpoint if needed. The mode cannot be changed while an inventory is running (code 11).
See Topics and Channels.
Key Fields
operatingModes.profiles(request) — the RF profile;ADVANCEDrequiresadvancedConfigurations.FAST_READis the first member of the enum but is not currently supported, and data events are not supported while the sled is in it.operatingModes.accessOperations(request) — ⚠️ armed tag operations (destructive; see the danger note).operatingModes.select(request) — up to 32 Gen2 pre-filters.operatingModes.query/radioStartConditions/radioStopConditions(request) — inventory shaping and trigger semantics.operatingModes.tagMetaDataToEnable(request) — which metadata fields the reader reports on each read. The switch-to-field mapping is ondataEVT.response.code(response) — read this to determine success vs failure; the contract requires it; note the reported success-path omission (see Response Payload) and the partial-apply-on-error behavior (see Request Semantics). See Response Codes.
Request Payload
The envelope is command, requestId, and the operatingMode payload. Send only the operatingModes sub-objects you want to change. For a basic inventory, start with Profile setting: it sets only the RF profile. Set operating mode also sets advanced RF settings and arms tag access operations (READ, WRITE, ACCESS, LOCK), which run on the next inventory START; send it only when you want those operations. Pick a configuration section 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 | set_operating_mode | set_operating_mode | Fixed command name (pinned by the schema enum). |
requestId* | string | — | 1286 | A unique identifier for the request; echoed back in the response. |
operatingMode | object | — | — | The operating-mode settings to apply. Optional in the contract, as is the inner operatingModes, but a request without them carries nothing to apply. Partial: send only the sub-objects you want to change — they merge into the current mode (see Request Semantics). |
operatingModes, nesting level 2 | object | — | — | The reader operating-mode configuration. |
profiles, nesting level 3 | enum | FAST_READCYCLE_COUNTDENSE_READERSOPTIMAL_BATTERYBALANCED_PERFORMANCEADVANCED | ADVANCED | RF profile (default BALANCED_PERFORMANCE). ADVANCED requires advancedConfigurations (else code 22). FAST_READ is not currently supported (see Request Semantics). |
advancedConfigurations, nesting level 3 | object | — | — | Custom RF settings — set only when profiles is ADVANCED. For other profiles the link profile is mapped internally. |
transmitPower, nesting level 4 | number | 0–300 | 270 | Transmit power level. |
linkProfile, nesting level 4 | enum | M4_256KM2_240KM2_256KM2_320KM4_240KM4_320KFM0_0KFM0_320KM8_240KM8_256KM8_320K | M2_240K | RF link profile. |
session, nesting level 4 | enum | SESSION_0SESSION_1SESSION_2SESSION_3 | SESSION_1 | Gen2 session. |
dynamicPower, nesting level 4 | boolean | — | true | Enable dynamic power. |
inventoryProtocol, nesting level 3 | enum | GEN2GEN2XHYBRID | GEN2 | Specifies the inventory protocol to be used by the reader. |
accessOperations, nesting level 3 | array | — | — | ⚠️ Tag access operations to arm — executed on the next inventory. WRITE/LOCK/KILL are destructive (see the danger note in Notes). |
operationType, nesting level 4 | enum | READWRITEACCESSLOCKKILL | READ | The access operation. READ reads tag memory; WRITE writes tag memory; ACCESS performs an access operation using the access password; LOCK (un)locks banks; KILL permanently disables the tag. |
config, nesting level 4 | object | — | — | Operation parameters. |
memoryBank, nesting level 5 | enum | EPCTIDUSERRESERVED | EPC | Target memory bank (READ/WRITE). |
offset, nesting level 5 | integer | — | 1 | Start word position. |
length, nesting level 5 | integer | — | 2 | Word count. |
data, nesting level 5 | string | — | FFFFEEEE | Words to write (WRITE). Overlong → code 31; length mismatch → code 32. |
password, nesting level 5 | string | — | 00000000 | ⚠️ 8-hex-char (32-bit) access/lock/kill password. Default 00000000. Sensitive — mask it; the read-back never echoes it. |
lockMemBank, nesting level 5 | enum | EPCACCESS_PWDKILL_PWDTIDUSERALL | TID | Bank to (un)lock (LOCK). |
lockAction, nesting level 5 | enum | READ_AND_WRITEPERMANENT_LOCKPERMANENT_UNLOCKUNLOCK | UNLOCK | Lock action (LOCK). PERMANENT_LOCK/PERMANENT_UNLOCK are irreversible. |
radioStartConditions, nesting level 3 | object | — | — | When inventory starts. Absent → starts immediately on start. |
trigger, nesting level 4 | enum | PRESSEDRELEASEDIMMEDIATE | IMMEDIATE | Start trigger. |
startDelay, nesting level 4 | integer | — | 3000 | Delay before starting (when > 0). |
repeat, nesting level 4 | boolean | — | false | Whether the trigger can restart inventory. |
radioStopConditions, nesting level 3 | object | — | — | When inventory stops. Absent → runs until stop. |
trigger, nesting level 4 | enum | PRESSEDRELEASEDIMMEDIATE | IMMEDIATE | Stop trigger. |
tagCount, nesting level 4 | integer | — | 10 | Stop after N unique tags. |
stopTimeout, nesting level 4 | integer | — | 10000 | Stop after this duration. |
inventoryCount, nesting level 4 | integer | — | 0 | Stop after N inventory cycles. |
query, nesting level 3 | object | — | — | Gen2 query parameters. |
session, nesting level 4 | enum | SESSION_0SESSION_1SESSION_2SESSION_3 | SESSION_1 | Gen2 session. |
inventoryState, nesting level 4 | enum | STATE_ASTATE_BSTATE_AB | STATE_B | Inventory flag state (STATE_AB flips). |
slFlag, nesting level 4 | enum | ALLASSERTEDDEASSERTED | ALL | SL (select) flag filter. |
tagPopulation, nesting level 4 | integer | min 0 | 30 | Estimated tag count (tunes the Q parameter). |
select, nesting level 3 | array | — | — | Select pre-filters (max 32; exceeding → code 24). Each item requires all seven fields below. |
enable*, nesting level 4 | boolean | — | true | Enable this pre-filter. |
tagPattern*, nesting level 4 | string | — | 2222EEEEFFFF1111AAAABBBB | Bit pattern to match. Overlong → code 28. |
memoryBank*, nesting level 4 | enum | EPCTIDUSER | EPC | Memory bank to match against. |
offset*, nesting level 4 | integer | — | 32 | Start bit position. |
action*, nesting level 4 | enum | INV_A_NOT_INV_B_OR_ASRT_SL_NOT_DSRT_SLINV_A_OR_ASRT_SLNOT_INV_B_OR_NOT_DSRT_SLINV_A2BB2A_NOT_INV_A_OR_NEG_SL_NOT_ASRT_SLINV_B_NOT_INV_A_OR_DSRT_SL_NOT_ASRT_SLINV_B_OR_DSRT_SLNOT_INV_A_OR_NOT_ASRT_SLNOT_INV_A2BB2A_OR_NOT_NEG_SL | INV_B_NOT_INV_A_OR_DSRT_SL_NOT_ASRT_SL | How to set the SL/inventory flag on match/mismatch (Gen2 select action). |
target*, nesting level 4 | enum | SESSION_SLSESSION_0SESSION_1SESSION_2SESSION_3 | SESSION_1 | Session/SL flag to set. |
length*, nesting level 4 | integer | — | 16 | Number of bits to compare. |
tagMetaDataToEnable, nesting level 3 | object | — | — | Which tag-metadata fields to report on each read (booleans). No flag has a documented default. |
RSSI, nesting level 4 | boolean | — | false | Report signal strength. |
PHASE, nesting level 4 | boolean | — | false | Report phase angle. |
SEENCOUNT, nesting level 4 | boolean | — | false | Report detection count. |
CHANNEL, nesting level 4 | boolean | — | false | Report the RF channel. |
PC, nesting level 4 | boolean | — | false | Report the Protocol Control word. |
XPC, nesting level 4 | boolean | — | true | Report the Extended Protocol Control (XPC) word, if the tag has one. |
CRC, nesting level 4 | boolean | — | true | Report the tag CRC. |
EPC, nesting level 4 | boolean | — | true | Report the EPC. |
TID, nesting level 4 | boolean | — | true | Report the TID. |
USER, nesting level 4 | boolean | — | true | Report USER memory. |
MAC, nesting level 4 | boolean | — | true | Report the reader's MAC. |
HOSTNAME, nesting level 4 | boolean | — | true | Report the reader's hostname. |
Request Semantics
Merge. set_operating_mode is cumulative: it updates only the aspects present in the payload and leaves all others intact — it is not a full replacement. For example, sending only radioStartConditions changes the triggers while preserving profiles, query, select, accessOperations, and tagMetaDataToEnable. Send {profiles: "BALANCED_PERFORMANCE"} alone to reset the profile without touching anything else. Because merges accumulate, armed accessOperations persist across later partial sets until you overwrite them or reboot. Confirm the resulting merged mode with get_operating_mode.
- The singular
operatingModewrapper around the pluraloperatingModesobject is the schema-defined shape. The command'soperatingModeproperty carries a wrapper holding exactly one member,operatingModes, and every worked example nests it that way — the double nesting is intentional and unique to this command (see the Glossary). The contract marks neither levelrequiredand does not forbid unrecognized properties, so a flattened or renamed payload still validates — but it does not carry the operating mode where the schema defines it. Send the nested shape exactly as shown. - An error response can leave the mode partially applied. An error response (e.g.
101"Error in processing command") can leave the mode partially applied — always verify the result withget_operating_moderather than assuming a101changed nothing. ADVANCEDrequiresadvancedConfigurations; limits are enforced.profiles: ADVANCEDwithoutadvancedConfigurationsreturns code22.selectsupports up to 32 pre-filters (code24if exceeded); an overlongselect.tagPatternreturns28; WRITEdatathat is too large or mismatched returns31/32.FAST_READis enumerated but not currently supported, and configuringFAST_READdisables data events.
Response Payload
set_operating_mode returns a status-only envelope — command, requestId, apiVersion, and response.
- Example
- Schema
| Field | Type | Enum / Units | Example | Description |
|---|---|---|---|---|
command* | string | — | set_operating_mode | 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 — set_operating_mode 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 set 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
set_operating_mode 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 mode was applied. (Readers have been reported to omit code on this reply — see above.) |
11 | Inventory in progress (IOT_ERROR_INVENTORY_IN_PROGRESS) — the mode cannot be changed while an inventory is running. Stop it with control_operation first. |
22 | Advanced configuration not set (IOT_CTRL_ADVANCED_PROFILE_NOT_SET) — profiles: ADVANCED was sent without advancedConfigurations. |
23 | Invalid enum value (IOT_ERROR_INVALID_ENUM) — a field (e.g. profiles, operationType, a Gen2 enum) is outside its allowed set. |
24 | Max 32 prefilters limit exceeded (IOT_ERROR_PREFILTERS_LIMIT_EXCEEDED) — more than 32 select entries. |
28 | Tag match pattern length exceeded (IOT_ERROR_TAG_MATCH_PATTERN_LENGTH_EXCEEDED) — a select.tagPattern is too long. |
31 | Max write length exceeded (IOT_ERROR_MAX_WRITE_LENGTH_EXCEEDED) — a WRITE data block is too large. |
32 | Write data length mismatch (IOT_ERROR_WRITE_DATA_LENGTH_MISMATCH) — a WRITE data length does not match its length. |
101 | Default error (Error in processing command) — a generic failure. Note: a 101 can still leave the mode partially applied — read back with get_operating_mode to see what took effect. |
Examples
Publish set_operating_mode over the CTRL endpoint; the device replies with the status envelope under Response Payload. Every request example in the contract is in the Configuration section dropdown under Request Payload: the full ADVANCED configuration (Set operating mode, which arms READ, WRITE, ACCESS and LOCK operations with the default password 00000000), and one partial set per section. Profile setting is also the way to return the profile to its default.
A generic failure returns code 101 (which may still partially apply — read back to confirm):
Notes and Caveats
accessOperations (WRITE, LOCK, KILL) are stored by set_operating_mode and executed against tags on the next inventory START — not immediately. KILL permanently disables a tag; LOCK with PERMANENT_LOCK/PERMANENT_UNLOCK is irreversible; WRITE overwrites tag memory. Because partial sets merge, armed operations persist until you overwrite the accessOperations array (with a benign or empty set) or reboot. A profile-only set — or any partial set that omits accessOperations — does not clear them. Do this before running an inventory that should not trigger them. Each armed operation also carries accessOperations[].config.password, an 8-hex-char (32-bit) access/lock/kill password you send (default 00000000) — mask it in shared artifacts. The device stores it but never echoes it back (get_operating_mode returns it empty). This command carries no broker/Wi-Fi credentials.
- Volatile and CTRL-only. The operating mode resets to default on
reboot, and the command is answered only on the CTRL endpoint (see Topic Mapping). FAST_READis enumerated but not currently supported.FAST_READis the first member of theprofilesenum, and the schema glosses it as "Configures the radio for maximum read speed within short range. (Currently not supported)". The command description repeats the restriction and extends it to the event plane: "When RFD40/90 sled is configured to FAST_READ profile, data events are not currently supported. On reboot the set configurations will be lost and the device will go back to default operating mode." TreatFAST_READas unavailable, and expect nodataEVTtraffic while the sled is in that profile.
Configure with set_operating_mode, then verify with get_operating_mode (especially after a 101), and run the inventory with control_operation. For the concept-level view, see Operating Mode.
Related: 📕 get_operating_mode · 📕 control_operation · 📕 config_endpoint · 📕 reboot · 📕 Response Codes