Спецификация MQTT
This document provides a comprehensive technical guide for working with the MQTT interface of the TAC-B series industrial radar sensor.
1. General Connection Parameters and Architecture
1.1. Supported Connection Types
The device settings (parameter mqtt_connection_type) support the following connection types to the broker:
- Use Credentials (
0): Standard unencrypted TCP connection with username and password authentication. - SSL/TLS without certificate (
6): Secure SSL/TLS connection with encryption, but without mandatory verification of the broker certificate on the device side. - SSL/TLS (
2): Secure connection with server validation via CA certificate (client.crtis used as CA). - Two-way authentication (
3): Two-way SSL/TLS authentication (the device verifies the broker, and the broker verifies the device using theclient.crt/client.keypair). - Mutual authentication (
4): Mutual authentication with strict verification of the entire chain of trust (client.crt,server.crt,client.key). - WebSocket (
5): Data transmission over WebSockets (without encryption). - WebSocket Secure (
7): Secure data transmission over WebSockets with encryption. - Azure IoT (
7in themqtt_settingsenumeration, internal type_AZURE_IOT): Integration with Microsoft Azure IoT Hub via MQTT protocol using a device certificate (azure.crt) and an intermediate CA (azure-ca.crt). - AWS IoT (
8in the enumeration, internal type_AWS_IOT): Integration with Amazon Web Services IoT Core with authentication via client certificate (client.crt/client.key).
1.2. Unique Device Client ID
To avoid conflicts on the broker, the Client ID of each sensor is formed strictly according to the following scheme:
$$\text{Client ID} = \text{DEVICE_ID_PREFIX} + \text{DeviceSerialNrASCII}$$
Example: sensmax-tac-b-141000222
1.3. Basic Topic Structure
The formation of publish and subscribe topics depends on the selected integration profile (Azure IoT, AWS IoT, or standard MQTT).
Standard Broker (SensWeb or User's Own Server)
To publish data, the device uses the following template:
{mqtt_prefix}smx/device/{DeviceSerialNr}/{message_type}[/{YYYYMMDD}][/{sensor_serial}]
{mqtt_prefix}: User-defined topic prefix (frommqtt_prefixsettings). For SensWeb, it is absent (empty string).{DeviceSerialNr}: Serial number of the ESP32 controller (e.g.,141000222).{message_type}: Type of the sent packet (e.g.,single_ts,ping,5_min_data,advanced_settings,log).{YYYYMMDD}: Optionally added date (for packets requiring date pinning, e.g.,ping/20260520).{sensor_serial}: Optional serial number of a specific gate or zone (e.g.,141000222G1for Gate 1 or241000222Z1for Zone 1).
To subscribe (receive commands), the following topic is used:
{mqtt_prefix}smx/server/{DeviceSerialNr}/#
Azure IoT Hub Profile
- Subscription Topic (C2D messages):
devices/{MQTT_CLIENT_ID}/messages/devicebound/#(QoS 1 is used) - Publication Topic (D2C messages):
devices/{MQTT_CLIENT_ID}/messages/events/$.ct=application%2Fjson&$.ce=utf-8&messageType={message_type}
AWS IoT Core Profile
- Subscription Topic (Commands):
cmd/smx/{MQTT_CLIENT_ID}/#(QoS 1 is used) - Publication Topic (Data):
dt/smx/{MQTT_CLIENT_ID}/{message_type}
2. Basic JSON Message Format
All messages sent and received by the device are JSON documents. Any outgoing message from the sensor contains the following basic set of fields:
{
"messageType": "message_type",
"id": "UNIQUE_HEX_ID_OF_MESSAGE",
"collector_id": "TAC-B-141000222",
"collector_serial": "141000222",
"collector_frm": "5.5.0",
"date": "2026-05-20",
"time": "09:15:30.124"
}
Description of Basic Fields:
| Field | Type | Description |
|---|---|---|
messageType |
String | Packet type (defines the structure of nested data). |
id |
String | Unique HEX identifier of the message (a random 32-bit number in HEX format generated by the sensor). |
collector_id |
String | Identifier of the device's main controller. |
collector_serial |
String | Serial number of the device's main controller. |
collector_frm |
String | Firmware version of the installed ESP32-S3 controller. |
date |
String | Message generation date on the device in YYYY-MM-DD format. |
time |
String | Exact message generation time with milliseconds in HH:MM:SS.sss format. |
3. Outgoing Packets (Events and Data from Device to Server)
The sensor supports the publication of a wide range of data, from real-time people passage events to complex coordinate telemetry from the radar sensor.
3.1. info: Device Status on Connection
Sent once upon successful connection to the broker with the Retain flag (saved on the server).
- Publication Topic:
- SensWeb / Standalone:
{mqtt_prefix}smx/device/{collector_serial}/info - Azure IoT:
devices/{MQTT_CLIENT_ID}/messages/events/$.ct=application%2Fjson&$.ce=utf-8&messageType=info - AWS IoT:
dt/smx/{MQTT_CLIENT_ID}/info - JSON Structure:
{
"messageType": "info",
"id": "A4F23D9E",
"sensor_id": "TAC-B-141000222",
"sensor_model": "TAC-B_ETH_SENSOR",
"sensor_serial": "141000222",
"sensor_frm": "5.5.0",
"radar_frm": "304",
"supply_voltage": "12.2",
"sd_status": "ok",
"sd_total_mb": 7652,
"sd_free_mb": 7629,
"sd_used_pct": 0.29,
"date": "2026-05-20",
"time": "09:15:30.124"
}
- Specific Fields:
sensor_id- Identifier of the main controller (matchescollector_id).sensor_model- Physical model name of the device (e.g.,"TAC-B_ETH_SENSOR").sensor_serial- Serial number of the main controller.sensor_frm- Firmware version of the installed ESP32-S3 controller.radar_frm- Firmware version of the TI IWR6843AOP radar module (MSS/DSS).supply_voltage- Supply voltage of the sensor (only present in builds with theENABLE_LOW_POWER_MODEflag or for outdoor versionsDEVICE_TACB_OUTDOOR).sd_status- Status of the mounted SD card (string:"ok"or"not_mounted").sd_total_mb- Total SD card capacity in megabytes (number). If no card is present,0is sent.sd_free_mb- Free space on the SD card in megabytes (number). If no card is present,0is sent.sd_used_pct- Percentage of used space on the SD card (floating-point number mathematically rounded to the nearest hundredth, e.g.,0.29). If no card is present,0.0is sent.
3.2. ping: Gate and Zone Availability Control
Sent periodically to confirm the activity of configured gates and zones.
- Publication Topic:
- SensWeb / Standalone:
{mqtt_prefix}smx/device/{collector_serial}/ping/{YYYYMMDD}/{sensor_serial} - Azure IoT:
devices/{MQTT_CLIENT_ID}/messages/events/$.ct=application%2Fjson&$.ce=utf-8&messageType=ping - AWS IoT:
dt/smx/{MQTT_CLIENT_ID}/ping - JSON Structure:
{
"messageType": "ping",
"id": "B1E9C3A4",
"collector_id": "TAC-B-141000222",
"collector_serial": "141000222",
"collector_frm": "5.5.0",
"sensor_serial": "141000222G1",
"sensor_name": "Main Entrance",
"date": "2026-05-20",
"time": "09:20:00.005"
}
- Specific Fields:
sensor_serial- Serial number of the polled gate (*G1,*G2...) or zone (*Z1,*Z2...).sensor_name- User-defined name of the gate/zone.
3.3. single_ts: Real-Time Passage Detection Event
Published immediately when an object crosses the counting line (gate). Not sent in low-power network mode LOW_POWER_NETWORK_MODE.
- Publication Topic:
- SensWeb / Standalone:
{mqtt_prefix}smx/device/{collector_serial}/single_ts/{YYYYMMDD}/{sensor_serial} - Azure IoT:
devices/{MQTT_CLIENT_ID}/messages/events/$.ct=application%2Fjson&$.ce=utf-8&messageType=single_ts - AWS IoT:
dt/smx/{MQTT_CLIENT_ID}/single_ts - JSON Structure:
{
"messageType": "single_ts",
"id": "7D41E2F3",
"collector_id": "TAC-B-141000222",
"collector_serial": "141000222",
"collector_frm": "5.5.0",
"sensor_serial": "141000222G1",
"sensor_name": "Entrance Group 1",
"direction": "IN",
"date": "2026-05-20",
"time": "09:21:44.385",
"five-min": 112,
"in_today": 342,
"out_today": 298,
"object_id": 1405,
"object_speed": "4.2",
"object_class": "pedestrian",
"last_5min_sum": 12,
"first_entry_time": "08:00:12",
"last_entry_time": "09:21:44"
}
- Specific Fields:
direction- Crossing direction:"IN"(entrance) or"OUT"(exit).five-min- Index of the 5-minute interval in the day (from0to287).in_today/out_today- Accumulated daily total of incoming and outgoing objects through this gate.object_id- Unique sequential track ID of the object from the radar side.object_speed- Object speed at the moment of passage (km/h, rounded to tenths). Passed as a string.object_class- Recognized object class:"pedestrian","cyclist","car","adult","child","unknown".last_5min_sum- Total number of passages in the current 5-minute interval.first_entry_time/last_entry_time- Time of the first and last passage through this gate for the current day.
Specifics for Zones:
If an event is registered in the occupancy zone, additional real-time metrics are automatically injected:
"inside_now": 5,
"avg_occupancy_per_visitor": 120,
"total_zone_occupancy": 3600
}
inside_now- Number of people currently inside the zone.avg_occupancy_per_visitor- Average time spent by a single visitor in the zone (in seconds).total_zone_occupancy- Cumulative total time of people presence in the zone for the current day (in seconds).
3.4. sync_list: Current List of Gates and Zones
Sent to the broker upon device startup, configuration changes, or once a day with the Retain flag.
- Publication Topic:
- SensWeb / Standalone:
{mqtt_prefix}smx/device/{collector_serial}/sync_list - Azure IoT:
devices/{MQTT_CLIENT_ID}/messages/events/$.ct=application%2Fjson&$.ce=utf-8&messageType=sync_list - AWS IoT:
dt/smx/{MQTT_CLIENT_ID}/sync_list - JSON Structure:
{
"messageType": "sync_list",
"id": "FA10C5D2",
"collector_id": "TAC-B-141000222",
"collector_serial": "141000222",
"collector_frm": "5.5.0",
"device_list": {
"141000222G1": "Main Door",
"141000222G2": "Emergency Exit",
"241000222Z1": "Reception Area"
}
}
device_listcontains a dictionary mapping hardware addresses of gates (*G1,*G2...) and zones (*Z1,*Z2...) to their human-readable names.
3.5. settings: Standard Device Settings
Sent upon initial connection and during any changes to basic parameters with the Retain flag.
- Publication Topic:
- SensWeb / Standalone:
{mqtt_prefix}smx/device/{collector_serial}/settings - Azure IoT:
devices/{MQTT_CLIENT_ID}/messages/events/$.ct=application%2Fjson&$.ce=utf-8&messageType=settings - AWS IoT:
dt/smx/{MQTT_CLIENT_ID}/settings - JSON Structure:
{
"messageType": "settings",
"id": "C8D9E1B2",
"collector_id": "TAC-B-141000222",
"collector_serial": "141000222",
"collector_frm": "5.5.0",
"date": "2026-05-20",
"time": "09:25:00.001",
"time_zone": "UTC+03:00",
"dst": true,
"power_profile": "ImmediateDelivery",
"make_beep": true,
"reboot_schedule": "02:00",
"startup_sound": true,
"led_indication": true,
"request_settings_update": false
}
- Specific Fields:
time_zone- Time zone inUTC±HH:MMformat.dst- Flag to enable automatic daylight saving time transition.power_profile- Current power consumption profile (always"ImmediateDelivery"for Ethernet versions).make_beep- Enable buzzer sound on the sensor upon passage detection.reboot_schedule- Daily automatic reboot time in"HH:00"format (or"OFF").startup_sound- Allow melody playback when the device powers on.led_indication- Allow LED indication during crossings.request_settings_update- Request for settings update by the broker (reset tofalseafter processing).
3.6. 5_min_data: Aggregated Occupancy Statistics (Gates)
Sent upon closing of a 5-minute interval or upon history request (data_request).
- Publication Topic:
- SensWeb / Standalone:
{mqtt_prefix}smx/device/{collector_serial}/5_min_data/{YYYYMMDD}/{sensor_serial} - Azure IoT:
devices/{MQTT_CLIENT_ID}/messages/events/$.ct=application%2Fjson&$.ce=utf-8&messageType=5_min_data - AWS IoT:
dt/smx/{MQTT_CLIENT_ID}/5_min_data - JSON Structure:
{
"messageType": "5_min_data",
"id": "E1D2C3B4",
"collector_id": "TAC-B-141000222",
"collector_serial": "141000222",
"collector_frm": "5.5.0",
"sensor_serial": "141000222G1",
"sensor_name": "Checkout 1",
"date": "2026-05-20",
"direction": "IN",
"in_today": 1205,
"out_today": 1190,
"first_entry_time": "08:00:15",
"last_entry_time": "21:58:43",
"visits": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 18, 22, 15, 30]
}
- Specific Fields:
visits- An array of 288 integer elements containing the number of passages for each 5-minute interval of the current day (starting from 00:00 to 23:55).
3.7. Aggregated Zone Presence Statistics
For zones, instead of a single 5_min_data packet, an entire group of packets is sent, representing different slices of data. Each packet contains an array of 288 elements.
- Publication Topics (SensWeb / Standalone):
- Average number of people (
inside_avg):{mqtt_prefix}smx/device/{collector_serial}/inside_avg/{YYYYMMDD}/{sensor_serial} - Maximum number of people (
inside_max):{mqtt_prefix}smx/device/{collector_serial}/inside_max/{YYYYMMDD}/{sensor_serial} - First zone occupancy in seconds (
occupancy_begin):{mqtt_prefix}smx/device/{collector_serial}/occupancy_begin/{YYYYMMDD}/{sensor_serial} - Zone occupancy duration in seconds (
occupancy_duration):{mqtt_prefix}smx/device/{collector_serial}/occupancy_duration/{YYYYMMDD}/{sensor_serial} - Publication Topics (Azure IoT):
devices/{MQTT_CLIENT_ID}/messages/events/$.ct=application%2Fjson&$.ce=utf-8&messageType={inside_avg|inside_max|occupancy_begin|occupancy_duration} - Publication Topics (AWS IoT):
dt/smx/{MQTT_CLIENT_ID}/{inside_avg|inside_max|occupancy_begin|occupancy_duration}
Example of inside_avg packet:
{
"messageType": "inside_avg",
"id": "E1D2C3B5",
"collector_id": "TAC-B-141000222",
"collector_serial": "141000222",
"collector_frm": "5.5.0",
"sensor_serial": "241000222Z1",
"sensor_name": "Reception",
"date": "2026-05-20",
"inside_avg": [0, 0, 1, 2, 2, 4, 3, 1, 0, 0]
}
3.8. position: Hardware Coordinates of Targets
Sent periodically when targets are present in the scanning area of the TI IWR6843AOP radar (only for custom brokers). Depending on the short_coordinates_packet setting, it has two formats.
- Publication Topic:
- Standalone:
{mqtt_prefix}smx/device/{collector_serial}/position - Azure IoT:
devices/{MQTT_CLIENT_ID}/messages/events/$.ct=application%2Fjson&$.ce=utf-8&messageType=position - AWS IoT:
dt/smx/{MQTT_CLIENT_ID}/position
Short Format (Without Track History)
- JSON Structure:
{
"messageType": "position",
"id": "1D2E3F4A",
"collector_id": "TAC-B-141000222",
"collector_serial": "141000222",
"total_detected_objects": 2,
"object_list": {
"object0": [1405, -120, 340, 0, 12],
"object1": [1406, 45, 210, 0, 8]
}
}
- Coordinate Array Format:
[ID, X (cm), Y (cm), Z (cm), Speed (dm/s)]
Long Format (With Tracking History)
- JSON Structure:
{
"messageType": "position",
"id": "1D2E3F4B",
"collector_id": "TAC-B-141000222",
"collector_serial": "141000222",
"total_detected_objects": 1,
"object_list": {
"object0": {
"ID": 1405,
"speed": 1.2,
"X": [-140, -135, -130, -125, -120],
"Y": [360, 355, 350, 345, 340]
}
}
}
3.9. notification: System and User Notifications
Published upon critical events or when notification rules are triggered.
System Notifications (Topic: .../notifications/system)
- Power On (POWER ON):
{
"messageType": "notification",
"id": "ABC12345",
"collector_id": "TAC-B-141000222",
"collector_serial": "141000222",
"date": "2026-05-20",
"time": "09:30:15.000",
"reason": "POWER ON"
}
- Device blocked due to password brute-force (DEVICE BLOCKED):
{
"messageType": "notification",
"id": "CDE56789",
"collector_id": "TAC-B-141000222",
"collector_serial": "141000222",
"date": "2026-05-20",
"time": "09:30:15.000",
"reason": "DEVICE BLOCKED"
}
User Notifications (Topic: .../notifications/user)
Triggered by the built-in notification logic (upon activation of configured triggers for people count, speed, etc.):
{
"messageType": "notification",
"id": "EF32D12B",
"collector_id": "TAC-B-141000222",
"collector_serial": "141000222",
"date": "2026-05-20",
"time": "09:30:15.000",
"sensor_name": "Entrance Zone",
"reason": "Warning! People limit exceeded (6 people)"
}
3.10. error_notification: Error Notifications
Sent by the device when there is an invalid syntax in the incoming request or when the requested information is missing.
- Publication Topic:
{mqtt_prefix}smx/device/{collector_serial}/errors - JSON Structure:
{
"messageType": "error_notification",
"id": "E8F9A1B2",
"collector_id": "TAC-B-141000222",
"collector_serial": "141000222",
"description": "data not found"
}
- Possible values for
description: "syntax error"- Invalid format of the incoming JSON packet (parsing error or invalid data types)."data not found"- Requested historical data indata_requestis missing on the SD card."unknown command"- The device received an unknown command.
4. Incoming Commands (Device Control from Server Side)
The device constantly listens to the registered subscription topic. Commands are accepted strictly in JSON format. Before processing any command, the device verifies if the "collector_serial" key matches its hardware serial number. If the serial number does not match, the command is ignored.
[!IMPORTANT] To prevent device looping (for example, when receiving an incoming command with the
retained = 1flag set), the device completely ignores any commands arriving within the first 3 seconds after establishing the MQTT connection (parameterMQTT_IGNORE_PERIOD_ms = 3000).
4.1. sync_list: Updating Gate/Zone Names and Composition
The server sends this command to overwrite the names of gates and zones stored in the non-volatile storage (NVS) of the sensor.
- Inbound Topic:
{mqtt_prefix}smx/server/{collector_serial}/sync_list - JSON Request Format:
{
"collector_serial": "141000222",
"messageType": "sync_list",
"device_list": {
"141000222G1": "Main Entrance (New Name)",
"141000222G2": "Service Entrance",
"241000222Z1": "Sales Floor Zone"
}
}
- Sensor Behavior:
- Serial number verification is performed.
- All items in
device_listare iterated through. - Names are saved to the
ZONE_NVSNVS partition. - Hardware gates or zones that are not listed in the incoming
device_listare automatically deleted from the device's memory! - In response, the device sends the updated
sync_listpacket to the publication topic.
4.2. settings: Configuring General Settings
This command is used to remotely configure the basic parameters of the sensor.
- Inbound Topic:
{mqtt_prefix}smx/server/{collector_serial}/settings - JSON Request Format:
{
"collector_serial": "141000222",
"messageType": "settings",
"time_zone": "UTC+03:00",
"dst": true,
"make_beep": true,
"reboot_schedule": "03:00",
"startup_sound": false,
"led_indication": true,
"premium_days": 365
}
- Parameter Description and Validation:
time_zone- Sets the device's time zone. OnlyUTC±HH:MMformat is allowed (e.g.,UTC+03:00orUTC-05:00). If formatted incorrectly,_SYNTAX_ERRORis returned.dst- Flag to enable automatic daylight saving time transition (boolean).make_beep- Enable buzzer sound on the sensor upon people crossing the line (boolean).reboot_schedule- Daily automatic reboot time of the sensor in"HH:00"format. To disable reboot, send"OFF". If a value greater than"23:00"is sent, the reboot is disabled.startup_sound- Allow melody playback upon device startup (boolean).led_indication- Allow LED indicator operation upon crossings (boolean).premium_days- Number of paid subscription days (number or string). Saved inDEVICE_STATUS.PREMIUM_DAYS.
4.3. data_request: Requesting Historical Data
Used by the server to remotely download archived 5-minute data for a specific day.
- Inbound Topic:
{mqtt_prefix}smx/server/{collector_serial}/data_request - JSON Request Format:
{
"collector_serial": "141000222",
"messageType": "data_request",
"date": "20/05/26"
}
- Sensor Behavior:
- The day, month, and year are extracted from the incoming
datestring (strictlyDD/MM/YYformat is expected, e.g.,20/05/26for May 20, 2026). - Date validity is checked. If the date is invalid,
_SYNTAX_ERRORis returned. - The device searches for a binary log file for this date on the internal SD card.
- If the file is found, all recorded 5-minute intervals for that day are read sequentially for all gates/zones, and
5_min_datapackets (and/or zone packetsinside_avg,inside_max,occupancy_begin,occupancy_duration) are formed and sent. - If there is no data on the SD card, the device returns an
error_notificationpacket with the description"data not found"to the publication topic.
4.4. reset: Forced Device Reboot
Sending this command immediately triggers a software reboot of the sensor.
- Inbound Topic:
{mqtt_prefix}smx/server/{collector_serial}/reset - JSON Request Format:
{
"collector_serial": "141000222",
"messageType": "reset"
}