Home Assistant is one way to consume radar data, and it is a good one — see the integration overview. But if you are building a product, a care platform, or simply a small service of your own, you will read the broker directly. Nothing in the radar’s output is Home Assistant specific: it is JSON over MQTT, on topics you already know.

This article is the contract layer — what the messages look like, what arrives when, and which MQTT settings actually matter. It assumes a broker is running (see the Artemis setup guide) and that at least one radar is configured (see the setup guide).

Two payload shapes

Finished units publish a JSON property protocol on their report topic. The DeviceID in the path is the device’s MAC address, printed on the label and shown on the configuration page — see Running Several Radars in One Home for the difference between DeviceID and ClientID.

{"version": "1.0", "method": "post", "params": {"someoneExists": "1"}}

Two things to internalise: the values arrive as strings, and only the fields that changed are present.

A UART-only module behind your own gateway publishes whatever your firmware sends. The ESP32-S3 gateway publishes a flat payload:

{"breath": 22, "sleep": 1}

Because you own that code, you also own the contract — but the advice below applies to it just the same.

What arrives when, and why that matters

The radars do not send every field in every message. The cadences are documented per model in the product guides; the pattern is always the same:

Data Typical cadence
Presence, motion status On change, within about 0.5 s
Breathing rate, heart rate Every 3 s
Body movement Every 1 s (finished) / every 5 s (module)
Sleep stage Every 10 min while in bed
Sleep score and report Once, when the sleep session ends
Fall status and position On a fall event

The consequence is the single most important rule in this article:

Never assume a field is present. Read only what arrived, and keep the last known value for everything else.

A consumer written as payload["params"]["heartRateValue"] will throw on the first message that carries only presence. That is exactly the failure the Home Assistant guides avoid with their if defined … else this.state pattern, and it applies to your own code in the same way.

Topic patterns

Some models publish extra topics worth knowing. The presence radar, for example, reports online/offline on /RadarHP/<DeviceID>/sys/online/post and its version on .../sys/version/post — use those for device health instead of inferring it from whether data happens to be arriving.

MQTT settings that matter

A minimal consumer

Python with paho-mqtt, keeping last-known values and reconnecting:

import json
import time
import paho.mqtt.client as mqtt

BROKER = "192.168.1.2"
PORT = 1883
USERNAME = "backend"
PASSWORD = "..."
TOPIC = "/Radar60SP/<MAC>/sys/property/post"

state = {}

def on_connect(client, userdata, flags, rc):
    client.subscribe(TOPIC, qos=1)

def on_message(client, userdata, msg):
    try:
        payload = json.loads(msg.payload.decode())
    except ValueError:
        return
    params = payload.get("params", {})
    # Sparse payload: only the fields that changed are present.
    if "breathValue" in params:
        state["breath"] = params["breathValue"]
    if "heartRateValue" in params:
        state["heart"] = params["heartRateValue"]
    if "sleepStatus" in params:
        state["stage"] = params["sleepStatus"]
    if "getIntoBed" in params:
        state["in_bed"] = params["getIntoBed"]
    state["updated"] = time.time()

client = mqtt.Client(client_id="radar-backend-01", clean_session=False)
client.username_pw_set(USERNAME, PASSWORD)
client.on_connect = on_connect
client.on_message = on_message
client.will_set("radar/backend/status", "offline", qos=1, retain=True)

while True:
    try:
        client.connect(BROKER, PORT, keepalive=60)
        client.publish("radar/backend/status", "online", qos=1, retain=True)
        client.loop_forever()
    except OSError:
        time.sleep(5)

That is the whole shape: subscribe, merge what arrived, reconnect. Replace <MAC> with the DeviceID from the device label, and keep one state dict per device if you have several.

From here

What you do with state is your product, not the radar’s job. The fall radar detects and reports; escalating to a notification is step five of the alarm chain and belongs to your system — see Building an Aging-in-Place Care System with Three 60GHz Radars for one worked escalation design.

Where to go next

Finished radars and modules are on Tindie.