<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://249263431.github.io/60GHz-Radar-SDK/feed.xml" rel="self" type="application/atom+xml" /><link href="https://249263431.github.io/60GHz-Radar-SDK/" rel="alternate" type="text/html" /><updated>2026-10-18T08:14:18+00:00</updated><id>https://249263431.github.io/60GHz-Radar-SDK/feed.xml</id><title type="html">60GHz mmWave Radar SDK</title><subtitle>SDK and documentation for 60GHz mmWave radar sensors.</subtitle><entry><title type="html">Connect Your 60GHz mmWave Radar to Home Assistant (Verified Walkthrough)</title><link href="https://249263431.github.io/60GHz-Radar-SDK/integration/2026/10/18/home-assistant-radar-integration.html" rel="alternate" type="text/html" title="Connect Your 60GHz mmWave Radar to Home Assistant (Verified Walkthrough)" /><published>2026-10-18T01:00:00+00:00</published><updated>2026-10-18T01:00:00+00:00</updated><id>https://249263431.github.io/60GHz-Radar-SDK/integration/2026/10/18/home-assistant-radar-integration</id><content type="html" xml:base="https://249263431.github.io/60GHz-Radar-SDK/integration/2026/10/18/home-assistant-radar-integration.html"><![CDATA[<h1 id="connect-your-60ghz-mmwave-radar-to-home-assistant-verified-walkthrough">Connect Your 60GHz mmWave Radar to Home Assistant (Verified Walkthrough)</h1>

<p>If you bought one of our 60GHz mmWave radars — fall detection, presence, or sleep monitoring — and configured it for MQTT, the next natural step is to get that data into a dashboard you can actually see. Home Assistant (HA) is the obvious choice: it speaks MQTT natively, runs locally (your data never leaves your home), and is free and open source.</p>

<p>This guide is different from most tutorials. Every step below was run on a real Windows 11 machine with WSL2 and Home Assistant Core <strong>2025.1.4</strong>, against a live radar talking to an Apache Artemis broker. No “should work in theory” — it is verified.</p>

<h2 id="the-big-picture">The big picture</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>60GHz Radar  --MQTT--&gt;  Broker (Artemis / Mosquitto)  --MQTT--&gt;  Home Assistant
</code></pre></div></div>

<p>Three actors:</p>

<ul>
  <li><strong>The radar</strong> publishes JSON over MQTT on two topics.</li>
  <li><strong>The broker</strong> (Artemis in our setup, Mosquitto works too) is the middleman. The radar does <em>not</em> talk to HA directly — it talks to the broker.</li>
  <li><strong>Home Assistant</strong> subscribes to the broker and turns the JSON into entities you can see and act on.</li>
</ul>

<p>If you have not set up the broker + radar MQTT side yet, do that first (see our MQTT architecture article and the product setup guide). This article starts from “I already have a working broker and my radar is publishing data.”</p>

<h2 id="before-you-start">Before you start</h2>

<p>You need:</p>

<ol>
  <li>A broker reachable on your network (e.g. <code class="language-plaintext highlighter-rouge">192.168.1.2:1883</code>) with a username and password.</li>
  <li>Your radar configured for MQTT (broker IP, port 1883, credentials) — covered in the setup guide.</li>
  <li>The device’s <strong>DeviceID</strong>. Good news: on our radars the DeviceID <em>is</em> the device MAC address, which is also the MQTT ClientID, and it is printed on the back of the device. No manual registration needed.</li>
</ol>

<p>The topics look like this (replace <code class="language-plaintext highlighter-rouge">{DeviceID}</code> with the number on the device back):</p>

<ul>
  <li>Report (radar → you): <code class="language-plaintext highlighter-rouge">/Radar60FL/{DeviceID}/sys/property/post</code></li>
  <li>Command (you → radar): <code class="language-plaintext highlighter-rouge">/Radar60FL/{DeviceID}/sys/property/set</code></li>
</ul>

<p><code class="language-plaintext highlighter-rouge">Radar60FL</code> is the prefix for the 60GHz fall radar. Sleep = <code class="language-plaintext highlighter-rouge">Radar60SP</code>, presence = <code class="language-plaintext highlighter-rouge">RadarHP</code>, and so on.</p>

<h2 id="what-is-home-assistant-briefly">What is Home Assistant, briefly</h2>

<p>HA is an open-source home automation hub. You run it on a box at home (Raspberry Pi, mini-PC, or even a Windows laptop via WSL2). It pulls data from hundreds of device types and shows everything in one dashboard. Because it is local-first, nothing is sent to the cloud.</p>

<p>Three ways to install it:</p>

<ul>
  <li><strong>HA OS</strong> — a dedicated image for Raspberry Pi / x86 mini-PCs. Easiest for pure users.</li>
  <li><strong>Docker</strong> — one container, but you need to be comfortable with Docker.</li>
  <li><strong>HA Core</strong> — run the Python app directly. This is what we verified, and it is the lightest path on Windows with <strong>no Docker</strong>. This guide uses HA Core on WSL2.</li>
</ul>

<h2 id="install-ha-core-on-wsl2-verified">Install HA Core on WSL2 (verified)</h2>

<p>WSL2 (Windows Subsystem for Linux) lets you run a real Linux on Windows — and HA Core is happiest on Linux.</p>

<p>If WSL2 is not enabled yet, in an <strong>administrator</strong> PowerShell:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">wsl</span><span class="w"> </span><span class="nt">--install</span><span class="w">
</span></code></pre></div></div>

<p>Reboot when prompted. Ubuntu will set itself up and ask you for a Linux username and password.</p>

<p>Then, inside the Ubuntu terminal:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt update <span class="o">&amp;&amp;</span> <span class="nb">sudo </span>apt upgrade <span class="nt">-y</span>
<span class="nb">sudo </span>apt <span class="nb">install</span> <span class="nt">-y</span> python3-venv python3-dev build-essential libssl-dev libffi-dev libjpeg-dev zlib1g-dev pkg-config

python3 <span class="nt">-m</span> venv ~/hassenv
<span class="nb">source</span> ~/hassenv/bin/activate
pip <span class="nb">install</span> <span class="nt">--upgrade</span> pip
pip <span class="nb">install </span>homeassistant
</code></pre></div></div>

<p>The last step downloads a lot of packages — give it a few minutes. When it finishes, start HA:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hass
</code></pre></div></div>

<p>First launch initializes the config and database and takes several minutes. You’ll know it is up when port 8123 responds. Open <strong>http://localhost:8123</strong> in your Windows browser and create your admin account.</p>

<blockquote>
  <p>We tested on Ubuntu 24.04 with Python 3.12 and Home Assistant Core <strong>2025.1.4</strong>. HA requires Python 3.12+, so use a current Ubuntu.</p>
</blockquote>

<p>To keep HA running after you close the terminal, start it detached:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>setsid <span class="nb">nohup </span>hass <span class="o">&gt;</span> ~/hass.log 2&gt;&amp;1 &lt; /dev/null &amp;
</code></pre></div></div>

<h2 id="connect-home-assistant-to-your-broker">Connect Home Assistant to your broker</h2>

<ol>
  <li><strong>Settings → Devices &amp; Services → Add Integration</strong>, search <strong>MQTT</strong>.</li>
  <li>Enter your broker details:
    <ul>
      <li>Broker: <code class="language-plaintext highlighter-rouge">192.168.1.2</code> (your broker’s IP)</li>
      <li>Port: <code class="language-plaintext highlighter-rouge">1883</code></li>
      <li>Username / Password: your broker credentials</li>
    </ul>
  </li>
  <li>Save.</li>
</ol>

<p>You can confirm the link from the broker side: Artemis’ console will now show a new connection from Home Assistant.</p>

<h2 id="configure-the-radar-sensors-the-important-part">Configure the radar sensors (the important part)</h2>

<p>Out of the box, HA does not know what <code class="language-plaintext highlighter-rouge">fallStatus</code> means. We declare sensors in <code class="language-plaintext highlighter-rouge">configuration.yaml</code> (in your HA config folder, <code class="language-plaintext highlighter-rouge">~/.homeassistant/configuration.yaml</code> on Linux).</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">mqtt</span><span class="pi">:</span>
  <span class="na">sensor</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Bathroom</span><span class="nv"> </span><span class="s">Fall</span><span class="nv"> </span><span class="s">Status"</span>
      <span class="na">unique_id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">radar60fl_fallstatus"</span>
      <span class="na">state_topic</span><span class="pi">:</span> <span class="s2">"</span><span class="s">/Radar60FL/{DeviceID}/sys/property/post"</span>
      <span class="na">value_template</span><span class="pi">:</span> <span class="pi">&gt;</span>
        <span class="s">{% if value_json.params.fallStatus is defined %}</span>
          <span class="s">{{ value_json.params.fallStatus }}</span>
        <span class="s">{% else %}</span>
          <span class="s">{{ this.state }}</span>
        <span class="s">{% endif %}</span>

    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Bathroom</span><span class="nv"> </span><span class="s">Presence"</span>
      <span class="na">unique_id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">radar60fl_presence"</span>
      <span class="na">state_topic</span><span class="pi">:</span> <span class="s2">"</span><span class="s">/Radar60FL/{DeviceID}/sys/property/post"</span>
      <span class="na">value_template</span><span class="pi">:</span> <span class="pi">&gt;</span>
        <span class="s">{% if value_json.params.someoneExists is defined %}</span>
          <span class="s">{{ value_json.params.someoneExists }}</span>
        <span class="s">{% else %}</span>
          <span class="s">{{ this.state }}</span>
        <span class="s">{% endif %}</span>
</code></pre></div></div>

<p>Replace <code class="language-plaintext highlighter-rouge">{DeviceID}</code> with the number printed on your device.</p>

<p><strong>Why the <code class="language-plaintext highlighter-rouge">if defined … else this.state</code> pattern is mandatory here.</strong> The radar does not send every field in every message. Sometimes it publishes <code class="language-plaintext highlighter-rouge">{"params":{"someoneExists":"1"}}</code>, sometimes <code class="language-plaintext highlighter-rouge">{"params":{"fallStatus":"1"}}</code>, and often just a couple of fields. If you wrote <code class="language-plaintext highlighter-rouge">{{ value_json.params.fallStatus }}</code> directly, every message that lacks <code class="language-plaintext highlighter-rouge">fallStatus</code> would blank the sensor out. The template above keeps the last known value when the field is absent — this is the standard, stable way to handle sparse MQTT payloads.</p>

<p>After editing, reload without a full restart:</p>

<ul>
  <li><strong>Developer Tools → YAML → MQTT: Reload</strong> (or call the <code class="language-plaintext highlighter-rouge">mqtt.reload</code> service).</li>
</ul>

<h2 id="see-your-radar-data-in-the-ui">See your radar data in the UI</h2>

<p>Four ways, fastest first:</p>

<ol>
  <li><strong>Developer Tools → States.</strong> Type <code class="language-plaintext highlighter-rouge">bathroom</code> in the entity filter. You’ll see <code class="language-plaintext highlighter-rouge">sensor.bathroom_fall_status</code> and <code class="language-plaintext highlighter-rouge">sensor.bathroom_presence</code> with live values and last-updated time. Walk in front of the radar and watch <code class="language-plaintext highlighter-rouge">presence</code> flip.</li>
  <li><strong>The default Overview dashboard.</strong> New sensor entities auto-appear as cards. You should see “Bathroom Fall Status” and “Bathroom Presence” on the home screen.</li>
  <li><strong>Raw MQTT.</strong> Settings → Devices &amp; Services → MQTT → Configure → Listen to a topic → enter <code class="language-plaintext highlighter-rouge">/Radar60FL/{DeviceID}/#</code> → Start Listening. You’ll see the raw JSON stream — great for discovering every field your model reports.</li>
  <li><strong>A history graph.</strong> Edit the Overview dashboard, add a History card on <code class="language-plaintext highlighter-rouge">sensor.bathroom_presence</code>, and you get a “who-was-here” square-wave over the day — great for demos.</li>
</ol>

<h2 id="pitfalls-we-actually-hit-so-you-dont-have-to">Pitfalls we actually hit (so you don’t have to)</h2>

<ul>
  <li><strong>Don’t use the web UI “Restart Home Assistant” button</strong> when running HA Core from the command line. There is no supervisor to bring it back, so it stops and stays stopped. Use the <code class="language-plaintext highlighter-rouge">setsid nohup hass … &amp;</code> command above instead. (We learned this the hard way.)</li>
  <li><strong>Two harmless log errors on WSL2:</strong> <code class="language-plaintext highlighter-rouge">aiodns … getaddrinfo()</code> and <code class="language-plaintext highlighter-rouge">libpcap is not available</code>. Both are environment quirks (DNS resolver / DHCP discovery) and do not affect the web UI or MQTT. Ignore them.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">fall_status</code> shows <code class="language-plaintext highlighter-rouge">unknown</code> at first — that is normal.</strong> <code class="language-plaintext highlighter-rouge">fallStatus</code> is only reported on a fall <em>event</em>, not continuously. Query it once with a <code class="language-plaintext highlighter-rouge">get</code> command: publish <code class="language-plaintext highlighter-rouge">{"version":"1.0","method":"get","params":{"fallStatus":""}}</code> to the <code class="language-plaintext highlighter-rouge">/set</code> topic, and it fills in with <code class="language-plaintext highlighter-rouge">0</code>.</li>
  <li><strong>HA will not auto-start after a PC reboot.</strong> Re-run the <code class="language-plaintext highlighter-rouge">setsid nohup hass … &amp;</code> command. For a permanent setup, HA OS or Docker (with restart policies) is the better long-term home.</li>
</ul>

<h2 id="wrapping-up">Wrapping up</h2>

<p>That is the whole chain, verified end to end: <strong>radar → broker → Home Assistant → dashboard</strong>, with real values flowing. From here you can build dashboards, alert on falls, or trigger other smart-home devices — all locally.</p>

<p>For the broker + radar MQTT setup and the full list of reportable fields per model, see our MQTT architecture article and the product setup guide on the docs site.</p>]]></content><author><name></name></author><category term="integration" /><category term="home assistant" /><category term="mqtt" /><category term="radar" /><category term="integration" /><category term="dashboard" /><category term="home automation" /><summary type="html"><![CDATA[Connect Your 60GHz mmWave Radar to Home Assistant (Verified Walkthrough)]]></summary></entry><entry><title type="html">Connect Your 60GHz Fall Detection Radar to Home Assistant (Verified Walkthrough)</title><link href="https://249263431.github.io/60GHz-Radar-SDK/integration/2026/10/18/fall-radar-home-assistant.html" rel="alternate" type="text/html" title="Connect Your 60GHz Fall Detection Radar to Home Assistant (Verified Walkthrough)" /><published>2026-10-18T00:00:00+00:00</published><updated>2026-10-18T00:00:00+00:00</updated><id>https://249263431.github.io/60GHz-Radar-SDK/integration/2026/10/18/fall-radar-home-assistant</id><content type="html" xml:base="https://249263431.github.io/60GHz-Radar-SDK/integration/2026/10/18/fall-radar-home-assistant.html"><![CDATA[<h1 id="connect-your-60ghz-fall-detection-radar-to-home-assistant-verified-walkthrough">Connect Your 60GHz Fall Detection Radar to Home Assistant (Verified Walkthrough)</h1>

<p>If you bought our 60GHz fall detection radar and configured it for MQTT, the next step is to get that fall alarm and presence data into a dashboard — and, more importantly, into an alert you can actually rely on. Home Assistant (HA) is the obvious choice: it speaks MQTT natively, runs locally (your data never leaves your home), and is free and open source.</p>

<p>This is the radar we verified end to end. Every step below was run on a real Windows 11 machine with WSL2 and Home Assistant Core <strong>2025.1.4</strong>, against a live fall radar talking to an Apache Artemis broker. The two sensors in this guide were confirmed returning real values (<code class="language-plaintext highlighter-rouge">fall_status = 0</code>, <code class="language-plaintext highlighter-rouge">presence = 1</code>). No “should work in theory” — it is proven.</p>

<h2 id="the-big-picture">The big picture</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>60GHz Fall Radar  --MQTT--&gt;  Broker (Artemis / Mosquitto)  --MQTT--&gt;  Home Assistant
</code></pre></div></div>

<p>Three actors: the radar publishes JSON over MQTT, the broker is the middleman (the radar does <em>not</em> talk to HA directly), and HA subscribes and turns the JSON into entities. If you have not set up the broker + radar MQTT side yet, do that first (see our MQTT architecture article and the fall radar setup guide).</p>

<h2 id="before-you-start">Before you start</h2>

<p>You need:</p>

<ol>
  <li>A broker reachable on your network (e.g. <code class="language-plaintext highlighter-rouge">192.168.1.2:1883</code>) with a username and password.</li>
  <li>Your fall radar configured for MQTT (broker IP, port 1883, credentials) — covered in the setup guide.</li>
  <li>The device’s <strong>DeviceID</strong>. On our radars the DeviceID <em>is</em> the device MAC address, which is also the MQTT ClientID, and it is printed on the back of the device. No manual registration needed.</li>
</ol>

<p>The fall radar uses the prefix <code class="language-plaintext highlighter-rouge">Radar60FL</code>:</p>

<ul>
  <li>Report (radar → you): <code class="language-plaintext highlighter-rouge">/Radar60FL/{DeviceID}/sys/property/post</code></li>
  <li>Command (you → radar): <code class="language-plaintext highlighter-rouge">/Radar60FL/{DeviceID}/sys/property/set</code></li>
</ul>

<h2 id="what-is-home-assistant-briefly">What is Home Assistant, briefly</h2>

<p>HA is an open-source home automation hub. You run it on a box at home (Raspberry Pi, mini-PC, or even a Windows laptop via WSL2). It pulls data from hundreds of device types and shows everything in one dashboard. Because it is local-first, nothing is sent to the cloud.</p>

<p>Three ways to install it:</p>

<ul>
  <li><strong>HA OS</strong> — a dedicated image for Raspberry Pi / x86 mini-PCs. Easiest for pure users.</li>
  <li><strong>Docker</strong> — one container, but you need to be comfortable with Docker.</li>
  <li><strong>HA Core</strong> — run the Python app directly. This is what we verified, and it is the lightest path on Windows with <strong>no Docker</strong>. This guide uses HA Core on WSL2.</li>
</ul>

<h2 id="install-ha-core-on-wsl2-verified">Install HA Core on WSL2 (verified)</h2>

<p>WSL2 (Windows Subsystem for Linux) lets you run a real Linux on Windows — and HA Core is happiest on Linux.</p>

<p>If WSL2 is not enabled yet, in an <strong>administrator</strong> PowerShell:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">wsl</span><span class="w"> </span><span class="nt">--install</span><span class="w">
</span></code></pre></div></div>

<p>Reboot when prompted. Ubuntu will set itself up and ask you for a Linux username and password.</p>

<p>Then, inside the Ubuntu terminal:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt update <span class="o">&amp;&amp;</span> <span class="nb">sudo </span>apt upgrade <span class="nt">-y</span>
<span class="nb">sudo </span>apt <span class="nb">install</span> <span class="nt">-y</span> python3-venv python3-dev build-essential libssl-dev libffi-dev libjpeg-dev zlib1g-dev pkg-config

python3 <span class="nt">-m</span> venv ~/hassenv
<span class="nb">source</span> ~/hassenv/bin/activate
pip <span class="nb">install</span> <span class="nt">--upgrade</span> pip
pip <span class="nb">install </span>homeassistant
</code></pre></div></div>

<p>The last step downloads a lot of packages — give it a few minutes. When it finishes, start HA:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hass
</code></pre></div></div>

<p>First launch initializes the config and database and takes several minutes. You’ll know it is up when port 8123 responds. Open <strong>http://localhost:8123</strong> in your Windows browser and create your admin account.</p>

<blockquote>
  <p>We tested on Ubuntu 24.04 with Python 3.12 and Home Assistant Core <strong>2025.1.4</strong>. HA requires Python 3.12+, so use a current Ubuntu.</p>
</blockquote>

<p>To keep HA running after you close the terminal, start it detached:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>setsid <span class="nb">nohup </span>hass <span class="o">&gt;</span> ~/hass.log 2&gt;&amp;1 &lt; /dev/null &amp;
</code></pre></div></div>

<h2 id="connect-home-assistant-to-your-broker">Connect Home Assistant to your broker</h2>

<ol>
  <li><strong>Settings → Devices &amp; Services → Add Integration</strong>, search <strong>MQTT</strong>.</li>
  <li>Enter your broker details:
    <ul>
      <li>Broker: <code class="language-plaintext highlighter-rouge">192.168.1.2</code> (your broker’s IP)</li>
      <li>Port: <code class="language-plaintext highlighter-rouge">1883</code></li>
      <li>Username / Password: your broker credentials</li>
    </ul>
  </li>
  <li>Save.</li>
</ol>

<p>You can confirm the link from the broker side: Artemis’ console will now show a new connection from Home Assistant.</p>

<h2 id="configure-the-fall-radar-sensors-the-important-part">Configure the fall-radar sensors (the important part)</h2>

<p>The fall radar reports <code class="language-plaintext highlighter-rouge">fallStatus</code> (0 = no fall, 1 = fall — the primary alarm), <code class="language-plaintext highlighter-rouge">someoneExists</code> (presence), <code class="language-plaintext highlighter-rouge">sceneMode</code> (1 living room, 2 bedroom, 3 bathroom), <code class="language-plaintext highlighter-rouge">motionStatus</code>, <code class="language-plaintext highlighter-rouge">fallPosition</code>, <code class="language-plaintext highlighter-rouge">residentStatus</code>, and more. We declare the ones we want as MQTT sensors in <code class="language-plaintext highlighter-rouge">configuration.yaml</code> (in your HA config folder, <code class="language-plaintext highlighter-rouge">~/.homeassistant/configuration.yaml</code> on Linux).</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">mqtt</span><span class="pi">:</span>
  <span class="na">sensor</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Bathroom</span><span class="nv"> </span><span class="s">Fall</span><span class="nv"> </span><span class="s">Status"</span>
      <span class="na">unique_id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">radar60fl_fallstatus"</span>
      <span class="na">state_topic</span><span class="pi">:</span> <span class="s2">"</span><span class="s">/Radar60FL/{DeviceID}/sys/property/post"</span>
      <span class="na">value_template</span><span class="pi">:</span> <span class="pi">&gt;</span>
        <span class="s">{% if value_json.params.fallStatus is defined %}</span>
          <span class="s">{{ value_json.params.fallStatus }}</span>
        <span class="s">{% else %}</span>
          <span class="s">{{ this.state }}</span>
        <span class="s">{% endif %}</span>

    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Bathroom</span><span class="nv"> </span><span class="s">Presence"</span>
      <span class="na">unique_id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">radar60fl_presence"</span>
      <span class="na">state_topic</span><span class="pi">:</span> <span class="s2">"</span><span class="s">/Radar60FL/{DeviceID}/sys/property/post"</span>
      <span class="na">value_template</span><span class="pi">:</span> <span class="pi">&gt;</span>
        <span class="s">{% if value_json.params.someoneExists is defined %}</span>
          <span class="s">{{ value_json.params.someoneExists }}</span>
        <span class="s">{% else %}</span>
          <span class="s">{{ this.state }}</span>
        <span class="s">{% endif %}</span>

    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Bathroom</span><span class="nv"> </span><span class="s">Scene</span><span class="nv"> </span><span class="s">Mode"</span>
      <span class="na">unique_id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">radar60fl_scene"</span>
      <span class="na">state_topic</span><span class="pi">:</span> <span class="s2">"</span><span class="s">/Radar60FL/{DeviceID}/sys/property/post"</span>
      <span class="na">value_template</span><span class="pi">:</span> <span class="pi">&gt;</span>
        <span class="s">{% if value_json.params.sceneMode is defined %}</span>
          <span class="s">{{ value_json.params.sceneMode }}</span>
        <span class="s">{% else %}</span>
          <span class="s">{{ this.state }}</span>
        <span class="s">{% endif %}</span>
</code></pre></div></div>

<p>Replace <code class="language-plaintext highlighter-rouge">{DeviceID}</code> with the number printed on your device.</p>

<p><strong>Why the <code class="language-plaintext highlighter-rouge">if defined … else this.state</code> pattern is mandatory here.</strong> The radar does not send every field in every message. Sometimes it publishes <code class="language-plaintext highlighter-rouge">{"params":{"someoneExists":"1"}}</code>, sometimes <code class="language-plaintext highlighter-rouge">{"params":{"fallStatus":"1"}}</code>, and often just a couple of fields. If you wrote <code class="language-plaintext highlighter-rouge">{{ value_json.params.fallStatus }}</code> directly, every message that lacks <code class="language-plaintext highlighter-rouge">fallStatus</code> would blank the sensor out. The template keeps the last known value when the field is absent — the standard, stable way to handle sparse MQTT payloads.</p>

<p>After editing, reload without a full restart:</p>

<ul>
  <li><strong>Developer Tools → YAML → MQTT: Reload</strong> (or call the <code class="language-plaintext highlighter-rouge">mqtt.reload</code> service).</li>
</ul>

<h2 id="see-your-fall-data-in-the-ui">See your fall data in the UI</h2>

<p>Four ways, fastest first:</p>

<ol>
  <li><strong>Developer Tools → States.</strong> Type <code class="language-plaintext highlighter-rouge">bathroom</code> in the entity filter. You’ll see the three sensors above with live values and last-updated time. Walk into the room and watch <code class="language-plaintext highlighter-rouge">Presence</code> flip.</li>
  <li><strong>The default Overview dashboard.</strong> New sensor entities auto-appear as cards.</li>
  <li><strong>Raw MQTT.</strong> Settings → Devices &amp; Services → MQTT → Configure → Listen to a topic → enter <code class="language-plaintext highlighter-rouge">/Radar60FL/{DeviceID}/#</code> → Start Listening. Great for discovering every field your model reports.</li>
  <li><strong>A history graph.</strong> Edit the Overview dashboard, add a History card on <code class="language-plaintext highlighter-rouge">sensor.bathroom_presence</code>, and you get an occupancy square-wave over the day — useful for showing when a room was used.</li>
</ol>

<h2 id="pitfalls-we-actually-hit-so-you-dont-have-to">Pitfalls we actually hit (so you don’t have to)</h2>

<ul>
  <li><strong>Don’t use the web UI “Restart Home Assistant” button</strong> when running HA Core from the command line. There is no supervisor to bring it back, so it stops and stays stopped. Use the <code class="language-plaintext highlighter-rouge">setsid nohup hass … &amp;</code> command above instead. (We learned this the hard way.)</li>
  <li><strong>Two harmless log errors on WSL2:</strong> <code class="language-plaintext highlighter-rouge">aiodns … getaddrinfo()</code> and <code class="language-plaintext highlighter-rouge">libpcap is not available</code>. Both are environment quirks (DNS resolver / DHCP discovery) and do not affect the web UI or MQTT. Ignore them.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">fall_status</code> shows <code class="language-plaintext highlighter-rouge">unknown</code> at first — that is normal.</strong> <code class="language-plaintext highlighter-rouge">fallStatus</code> is only reported on a fall <em>event</em>, not continuously. Query it once with a <code class="language-plaintext highlighter-rouge">get</code> command — publish <code class="language-plaintext highlighter-rouge">{"version":"1.0","method":"get","params":{"fallStatus":""}}</code> to the <code class="language-plaintext highlighter-rouge">/set</code> topic — and it fills in with <code class="language-plaintext highlighter-rouge">0</code>.</li>
  <li><strong>HA will not auto-start after a PC reboot.</strong> Re-run the <code class="language-plaintext highlighter-rouge">setsid nohup hass … &amp;</code> command. For a permanent setup, HA OS or Docker (with restart policies) is the better long-term home.</li>
</ul>

<h2 id="wrapping-up">Wrapping up</h2>

<p>That is the chain we proved end to end — <strong>radar → broker → Home Assistant → dashboard</strong> — with real <code class="language-plaintext highlighter-rouge">fall_status</code> and <code class="language-plaintext highlighter-rouge">presence</code> values flowing. From here you can push a phone notification when <code class="language-plaintext highlighter-rouge">fall_status</code> goes to <code class="language-plaintext highlighter-rouge">1</code>, or log daily room occupancy, all locally.</p>

<p>For the full list of reportable fall-radar fields and the install notes, see the fall radar guide and our MQTT architecture article.</p>]]></content><author><name></name></author><category term="integration" /><category term="home assistant" /><category term="mqtt" /><category term="integration" /><category term="fall radar" /><category term="dashboard" /><summary type="html"><![CDATA[Connect Your 60GHz Fall Detection Radar to Home Assistant (Verified Walkthrough)]]></summary></entry><entry><title type="html">Connect Your 60GHz Presence Radar to Home Assistant (Verified Walkthrough)</title><link href="https://249263431.github.io/60GHz-Radar-SDK/integration/2026/10/18/presence-radar-home-assistant.html" rel="alternate" type="text/html" title="Connect Your 60GHz Presence Radar to Home Assistant (Verified Walkthrough)" /><published>2026-10-18T00:00:00+00:00</published><updated>2026-10-18T00:00:00+00:00</updated><id>https://249263431.github.io/60GHz-Radar-SDK/integration/2026/10/18/presence-radar-home-assistant</id><content type="html" xml:base="https://249263431.github.io/60GHz-Radar-SDK/integration/2026/10/18/presence-radar-home-assistant.html"><![CDATA[<h1 id="connect-your-60ghz-presence-radar-to-home-assistant-verified-walkthrough">Connect Your 60GHz Presence Radar to Home Assistant (Verified Walkthrough)</h1>

<p>If you bought our 60GHz presence (human-occupancy) radar and configured it for MQTT, the next step is to get that occupancy, movement, and scene data into a dashboard you can act on. Home Assistant (HA) is the obvious choice: it speaks MQTT natively, runs locally (your data never leaves your home), and is free and open source.</p>

<p>This guide uses the same, verified method as our fall-radar HA walkthrough. Every step below was run on a real Windows 11 machine with WSL2 and Home Assistant Core <strong>2025.1.4</strong>, against a live radar talking to an Apache Artemis broker. No “should work in theory” — it is the same MQTT integration we already proved end to end. The presence radar differs from the fall and sleep radars in one important way (its reports are split across two topics), and that difference is covered below.</p>

<h2 id="the-big-picture">The big picture</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>60GHz Presence Radar  --MQTT--&gt;  Broker (Artemis / Mosquitto)  --MQTT--&gt;  Home Assistant
</code></pre></div></div>

<p>Three actors, same as the other radars: the radar publishes JSON over MQTT, the broker is the middleman, and HA subscribes and turns the JSON into entities. If you have not set up the broker + radar MQTT side yet, do that first (see our MQTT architecture article and the presence radar setup guide).</p>

<h2 id="before-you-start">Before you start</h2>

<p>You need:</p>

<ol>
  <li>A broker reachable on your network (e.g. <code class="language-plaintext highlighter-rouge">192.168.1.2:1883</code>) with a username and password.</li>
  <li>Your presence radar configured for MQTT (broker IP, port 1883, credentials) — covered in the setup guide.</li>
  <li>The device’s <strong>DeviceID</strong>. On our radars the DeviceID <em>is</em> the device MAC address, which is also the MQTT ClientID, and it is printed on the back of the device. No manual registration needed.</li>
</ol>

<p>The presence radar uses the prefix <code class="language-plaintext highlighter-rouge">RadarHP</code>. Unlike the fall/sleep radars, it does <strong>not</strong> use a single <code class="language-plaintext highlighter-rouge">/sys/property/post</code> topic. Instead it splits its output across two report topics:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">/RadarHP/{DeviceID}/sys/active/post</code> — fast-changing values (<code class="language-plaintext highlighter-rouge">environ</code>, <code class="language-plaintext highlighter-rouge">movementSigns</code>, <code class="language-plaintext highlighter-rouge">keepAway</code>)</li>
  <li><code class="language-plaintext highlighter-rouge">/RadarHP/{DeviceID}/sys/passive/post</code> — configuration values (<code class="language-plaintext highlighter-rouge">sceneMode</code>, <code class="language-plaintext highlighter-rouge">thresholdGear</code>, <code class="language-plaintext highlighter-rouge">forceIntoUnmannedGear</code>)</li>
  <li>(plus <code class="language-plaintext highlighter-rouge">/sys/online/post</code> for online/offline, and <code class="language-plaintext highlighter-rouge">/sys/property/set</code> for your commands)</li>
</ul>

<p>So each sensor must subscribe to the topic where its field is reported.</p>

<h2 id="what-is-home-assistant-briefly">What is Home Assistant, briefly</h2>

<p>HA is an open-source home automation hub. You run it on a box at home (Raspberry Pi, mini-PC, or even a Windows laptop via WSL2). It pulls data from hundreds of device types and shows everything in one dashboard. Because it is local-first, nothing is sent to the cloud.</p>

<p>Three ways to install it:</p>

<ul>
  <li><strong>HA OS</strong> — a dedicated image for Raspberry Pi / x86 mini-PCs. Easiest for pure users.</li>
  <li><strong>Docker</strong> — one container, but you need to be comfortable with Docker.</li>
  <li><strong>HA Core</strong> — run the Python app directly. This is what we verified, and it is the lightest path on Windows with <strong>no Docker</strong>. This guide uses HA Core on WSL2.</li>
</ul>

<h2 id="install-ha-core-on-wsl2-verified">Install HA Core on WSL2 (verified)</h2>

<p>WSL2 (Windows Subsystem for Linux) lets you run a real Linux on Windows — and HA Core is happiest on Linux.</p>

<p>If WSL2 is not enabled yet, in an <strong>administrator</strong> PowerShell:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">wsl</span><span class="w"> </span><span class="nt">--install</span><span class="w">
</span></code></pre></div></div>

<p>Reboot when prompted. Ubuntu will set itself up and ask you for a Linux username and password.</p>

<p>Then, inside the Ubuntu terminal:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt update <span class="o">&amp;&amp;</span> <span class="nb">sudo </span>apt upgrade <span class="nt">-y</span>
<span class="nb">sudo </span>apt <span class="nb">install</span> <span class="nt">-y</span> python3-venv python3-dev build-essential libssl-dev libffi-dev libjpeg-dev zlib1g-dev pkg-config

python3 <span class="nt">-m</span> venv ~/hassenv
<span class="nb">source</span> ~/hassenv/bin/activate
pip <span class="nb">install</span> <span class="nt">--upgrade</span> pip
pip <span class="nb">install </span>homeassistant
</code></pre></div></div>

<p>The last step downloads a lot of packages — give it a few minutes. When it finishes, start HA:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hass
</code></pre></div></div>

<p>First launch initializes the config and database and takes several minutes. You’ll know it is up when port 8123 responds. Open <strong>http://localhost:8123</strong> in your Windows browser and create your admin account.</p>

<blockquote>
  <p>We tested on Ubuntu 24.04 with Python 3.12 and Home Assistant Core <strong>2025.1.4</strong>. HA requires Python 3.12+, so use a current Ubuntu.</p>
</blockquote>

<p>To keep HA running after you close the terminal, start it detached:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>setsid <span class="nb">nohup </span>hass <span class="o">&gt;</span> ~/hass.log 2&gt;&amp;1 &lt; /dev/null &amp;
</code></pre></div></div>

<h2 id="connect-home-assistant-to-your-broker">Connect Home Assistant to your broker</h2>

<ol>
  <li><strong>Settings → Devices &amp; Services → Add Integration</strong>, search <strong>MQTT</strong>.</li>
  <li>Enter your broker details:
    <ul>
      <li>Broker: <code class="language-plaintext highlighter-rouge">192.168.1.2</code> (your broker’s IP)</li>
      <li>Port: <code class="language-plaintext highlighter-rouge">1883</code></li>
      <li>Username / Password: your broker credentials</li>
    </ul>
  </li>
  <li>Save.</li>
</ol>

<p>You can confirm the link from the broker side: Artemis’ console will now show a new connection from Home Assistant.</p>

<h2 id="configure-the-presence-radar-sensors-the-important-part">Configure the presence-radar sensors (the important part)</h2>

<p>The presence radar reports occupancy as <code class="language-plaintext highlighter-rouge">environ</code> (0 unoccupied, 1 occupied still, 2 occupied moving), body movement as <code class="language-plaintext highlighter-rouge">movementSigns</code> (0–100), and the scene mode as <code class="language-plaintext highlighter-rouge">sceneMode</code>. Because the reports are split across two topics, point each sensor at the right one. We declare the sensors in <code class="language-plaintext highlighter-rouge">configuration.yaml</code> (in your HA config folder, <code class="language-plaintext highlighter-rouge">~/.homeassistant/configuration.yaml</code> on Linux).</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">mqtt</span><span class="pi">:</span>
  <span class="na">sensor</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Room</span><span class="nv"> </span><span class="s">Occupancy"</span>
      <span class="na">unique_id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">radarhp_occupancy"</span>
      <span class="na">state_topic</span><span class="pi">:</span> <span class="s2">"</span><span class="s">/RadarHP/{DeviceID}/sys/active/post"</span>
      <span class="na">value_template</span><span class="pi">:</span> <span class="pi">&gt;</span>
        <span class="s">{% if value_json.params.environ is defined %}</span>
          <span class="s">{{ value_json.params.environ }}</span>
        <span class="s">{% else %}</span>
          <span class="s">{{ this.state }}</span>
        <span class="s">{% endif %}</span>

    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Body</span><span class="nv"> </span><span class="s">Movement"</span>
      <span class="na">unique_id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">radarhp_movement"</span>
      <span class="na">state_topic</span><span class="pi">:</span> <span class="s2">"</span><span class="s">/RadarHP/{DeviceID}/sys/active/post"</span>
      <span class="na">value_template</span><span class="pi">:</span> <span class="pi">&gt;</span>
        <span class="s">{% if value_json.params.movementSigns is defined %}</span>
          <span class="s">{{ value_json.params.movementSigns }}</span>
        <span class="s">{% else %}</span>
          <span class="s">{{ this.state }}</span>
        <span class="s">{% endif %}</span>

    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Scene</span><span class="nv"> </span><span class="s">Mode"</span>
      <span class="na">unique_id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">radarhp_scene"</span>
      <span class="na">state_topic</span><span class="pi">:</span> <span class="s2">"</span><span class="s">/RadarHP/{DeviceID}/sys/passive/post"</span>
      <span class="na">value_template</span><span class="pi">:</span> <span class="pi">&gt;</span>
        <span class="s">{% if value_json.params.sceneMode is defined %}</span>
          <span class="s">{{ value_json.params.sceneMode }}</span>
        <span class="s">{% else %}</span>
          <span class="s">{{ this.state }}</span>
        <span class="s">{% endif %}</span>
</code></pre></div></div>

<p>Replace <code class="language-plaintext highlighter-rouge">{DeviceID}</code> with the number printed on your device.</p>

<p><strong>Why the <code class="language-plaintext highlighter-rouge">if defined … else this.state</code> pattern is mandatory here.</strong> The presence radar does not send every field in every message — <code class="language-plaintext highlighter-rouge">environ</code> and <code class="language-plaintext highlighter-rouge">movementSigns</code> change often and arrive on <code class="language-plaintext highlighter-rouge">/sys/active/post</code>, while <code class="language-plaintext highlighter-rouge">sceneMode</code> changes rarely and arrives on <code class="language-plaintext highlighter-rouge">/sys/passive/post</code>. If you wrote <code class="language-plaintext highlighter-rouge">{{ value_json.params.environ }}</code> directly, every message on the other topic (or any message without that field) would blank the sensor. The template keeps the last known value when the field is absent — the standard, stable way to handle sparse MQTT payloads across multiple topics.</p>

<p>After editing, reload without a full restart:</p>

<ul>
  <li><strong>Developer Tools → YAML → MQTT: Reload</strong> (or call the <code class="language-plaintext highlighter-rouge">mqtt.reload</code> service).</li>
</ul>

<h2 id="see-your-presence-data-in-the-ui">See your presence data in the UI</h2>

<p>Four ways, fastest first:</p>

<ol>
  <li><strong>Developer Tools → States.</strong> Type <code class="language-plaintext highlighter-rouge">room</code> (or <code class="language-plaintext highlighter-rouge">radarhp</code>) in the entity filter. You’ll see the three sensors above with live values and last-updated time. Walk into the room and watch <code class="language-plaintext highlighter-rouge">Room Occupancy</code> flip from <code class="language-plaintext highlighter-rouge">0</code> to <code class="language-plaintext highlighter-rouge">1</code>/<code class="language-plaintext highlighter-rouge">2</code>.</li>
  <li><strong>The default Overview dashboard.</strong> New sensor entities auto-appear as cards.</li>
  <li><strong>Raw MQTT.</strong> Settings → Devices &amp; Services → MQTT → Configure → Listen to a topic → enter <code class="language-plaintext highlighter-rouge">/RadarHP/{DeviceID}/#</code> → Start Listening. Great for discovering every field your model reports across both topics.</li>
  <li><strong>A history graph.</strong> Edit the Overview dashboard, add a History card on <code class="language-plaintext highlighter-rouge">sensor.room_occupancy</code>, and you get an occupancy square-wave over the day — perfect for showing when a room was used.</li>
</ol>

<h2 id="pitfalls-we-actually-hit-so-you-dont-have-to">Pitfalls we actually hit (so you don’t have to)</h2>

<ul>
  <li><strong>Don’t use the web UI “Restart Home Assistant” button</strong> when running HA Core from the command line. There is no supervisor to bring it back, so it stops and stays stopped. Use the <code class="language-plaintext highlighter-rouge">setsid nohup hass … &amp;</code> command above instead. (We learned this the hard way.)</li>
  <li><strong>Two harmless log errors on WSL2:</strong> <code class="language-plaintext highlighter-rouge">aiodns … getaddrinfo()</code> and <code class="language-plaintext highlighter-rouge">libpcap is not available</code>. Both are environment quirks (DNS resolver / DHCP discovery) and do not affect the web UI or MQTT. Ignore them.</li>
  <li><strong>The presence radar’s <code class="language-plaintext highlighter-rouge">control</code> command uses the opposite convention</strong> from the 60GHz fall/sleep radars: a value of <code class="language-plaintext highlighter-rouge">1</code> <em>allows</em> a report, <code class="language-plaintext highlighter-rouge">0</code> forbids it. This only matters if you send commands; for receiving data, just subscribe to the topics above.</li>
  <li><strong>HA will not auto-start after a PC reboot.</strong> Re-run the <code class="language-plaintext highlighter-rouge">setsid nohup hass … &amp;</code> command. For a permanent setup, HA OS or Docker (with restart policies) is the better long-term home.</li>
</ul>

<h2 id="wrapping-up">Wrapping up</h2>

<p>That is the same verified chain — <strong>radar → broker → Home Assistant → dashboard</strong> — now feeding presence and occupancy. From here you can drive occupancy-based lighting or fan control, alert when a room is occupied for too long, or log daily usage, all locally.</p>

<p>For the full list of reportable presence fields and the install notes, see the presence radar guide and our MQTT architecture article.</p>]]></content><author><name></name></author><category term="integration" /><category term="home assistant" /><category term="mqtt" /><category term="integration" /><category term="presence radar" /><category term="dashboard" /><summary type="html"><![CDATA[Connect Your 60GHz Presence Radar to Home Assistant (Verified Walkthrough)]]></summary></entry><entry><title type="html">Why Does a mmWave Radar’s “Position” Drift? Coordinate Jitter in Elderly Care and Whole-Home Sensing</title><link href="https://249263431.github.io/60GHz-Radar-SDK/fundamentals/2026/10/18/radar-position-drift.html" rel="alternate" type="text/html" title="Why Does a mmWave Radar’s “Position” Drift? Coordinate Jitter in Elderly Care and Whole-Home Sensing" /><published>2026-10-18T00:00:00+00:00</published><updated>2026-10-18T00:00:00+00:00</updated><id>https://249263431.github.io/60GHz-Radar-SDK/fundamentals/2026/10/18/radar-position-drift</id><content type="html" xml:base="https://249263431.github.io/60GHz-Radar-SDK/fundamentals/2026/10/18/radar-position-drift.html"><![CDATA[<!-- filename: 2026-10-18-radar-position-drift.md -->

<p>If you have ever watched the raw position readout from a 60 GHz mmWave radar — for example while building an elderly-monitoring or whole-home sensing system — you may have noticed something strange. The coordinates of a person seem to “drift.” Someone standing 10 cm from the edge of the bed may appear to be lying in it. Someone standing outside a window may be reported as inside. The system toggles between “in bed” and “got up” even when the person only shifted a little.</p>

<p>This article explains why that happens, where the jitter comes from, and how a well-designed radar deals with it. The short version: the “point” a radar outputs is not a fixed coordinate. It is a value that trembles every second. Understanding that is the first step to using radar correctly for care.</p>

<h2 id="how-a-radar-measures-position">How a radar measures position</h2>

<p>A mmWave radar does not see a person the way a camera does. It senses distance and motion with radio waves, and it samples continuously.</p>

<ul>
  <li>It splits each second into at least 10 slices, each 0.1 s.</li>
  <li>Each 0.1 s slice is divided again into 32 to 64 sub-samples — the “chirps” the chip emits.</li>
  <li>The radar averages those 32–64 sub-samples to estimate, for one frame, whether the target is approaching or receding and how large the motion amplitude is.</li>
  <li>It then aggregates frames over time, locally or up to the cloud, to build a trajectory.</li>
</ul>

<p>So the position you see is an averaged, time-aggregated statistic — not a single clean measurement.</p>

<h2 id="why-the-value-drifts-noise">Why the value drifts: noise</h2>

<p>Two kinds of noise make each frame’s distance value inconsistent.</p>

<p><strong>Power and chip noise.</strong> Battery ripple and the chip’s own noise floor mean the per-frame distance is never exactly the same twice.</p>

<p><strong>Taking the maximum.</strong> To stay robust against noise, many implementations pick the peak or maximum value inside a window. The side effect is that, instead of centering on the true distance, the reported value swings back and forth by a few centimeters around it. At a true distance of 2 m, you may see it wander by several centimeters.</p>

<p>A good analogy is a laser toy “shooting” at a person: tut-tut-tut, you keep aiming at the same spot, but the toy itself vibrates, so each dot lands a little differently. The reflections come back scattered, and the computed position spreads into a patch instead of a single point.</p>

<h2 id="the-angle-drifts-too">The angle drifts too</h2>

<p>It is not only distance. The left–right angle (angle of arrival) and the elevation angle are also affected by phase mismatch between the transmit and receive antennas and by vibration.</p>

<p>Here is the catch: the farther the person is, the more a tiny angular error is magnified into a large lateral offset. That is why someone standing 10 cm from the bed edge can appear to drift into the bed when they are a bit farther away — the angular error, multiplied by distance, lands them “inside.”</p>

<p>The height dimension is relatively more stable, but it still suffers from transmit/receive inconsistency.</p>

<h2 id="why-the-drift-matters">Why the drift matters</h2>

<p>This is not cosmetic. Wrong coordinates directly break the features people buy radar for:</p>

<ul>
  <li><strong>False bed-entry / get-up detection.</strong> If the point drifts across the bed boundary, the system thinks the person got in or out of bed when they only moved slightly.</li>
  <li><strong>False region alarms.</strong> Someone shown as inside a window when they are outside can trigger fall or activity false alarms.</li>
  <li>For any application built on posture recognition or zone triggers, a jittery single point is a hard limitation.</li>
</ul>

<h2 id="how-we-fix-it-multi-dimensional-fusion">How we fix it: multi-dimensional fusion</h2>

<p>The key idea is simple: a single point is unreliable, so stop trusting a single point. Add more dimensions and let them constrain each other.</p>

<ul>
  <li><strong>Height dimension</strong> — a person is taller than furniture; height helps separate a standing human from a chair or a wall reflection.</li>
  <li><strong>Projection area dimension</strong> — lying, sitting, and standing produce different silhouette areas.</li>
  <li><strong>Time dimension</strong> — trajectory continuity, speed, and state history smooth out per-frame jitter.</li>
  <li><strong>Phase algorithms</strong> correct the left–right and elevation angles.</li>
</ul>

<p>The result: a good radar does not make the point “more accurate” in isolation. It uses more dimensions to <em>constrain</em> the trembling point. What the radar finally outputs to the outside world is still, at its core, that trembling thing — but wrapped in enough context that the application sees a stable, sensible state.</p>

<h2 id="practical-takeaways-for-developers">Practical takeaways for developers</h2>

<p>If you build on top of a radar SDK:</p>

<ul>
  <li><strong>Do not consume the raw single-frame (x, y) coordinate for critical decisions.</strong> Use the SDK’s already-fused outputs: posture, zone, trajectory.</li>
  <li><strong>Add hysteresis and filtering.</strong> A buffer zone around bed or zone boundaries prevents flip-flopping from tiny drifts.</li>
  <li><strong>Prefer the fused results over the bare point.</strong> Our SDK already performs the multi-dimensional fusion; rely on the posture and zone events rather than the raw coordinate.</li>
  <li>See also: <a href="https://249263431.github.io/60GHz-Radar-SDK/guide/2026/10/16/sleep-radar-installation-position.html">Sleep radar installation position</a> and <a href="https://249263431.github.io/60GHz-Radar-SDK/fundamentals/2026/10/17/radar-architecture-mqtt-vs-uart.html">MQTT vs UART architecture</a>.</li>
</ul>

<h2 id="wrapping-up">Wrapping up</h2>

<p>Position drift is an inherent phenomenon of physics plus sampling — not a bug you can fully eliminate. The right response is not to chase a perfect point, but to understand it and design around it. Once you treat the radar’s output as a trembling estimate and fuse multiple dimensions, elderly monitoring and whole-home sensing become stable and trustworthy.</p>]]></content><author><name></name></author><category term="fundamentals" /><category term="mmwave radar" /><category term="position drift" /><category term="coordinate jitter" /><category term="elderly monitoring" /><category term="whole-home sensing" /><category term="angle of arrival" /><category term="sensor fusion" /><category term="noise" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Connect Your 60GHz Sleep Radar to Home Assistant (Verified Walkthrough)</title><link href="https://249263431.github.io/60GHz-Radar-SDK/integration/2026/10/18/sleep-radar-home-assistant.html" rel="alternate" type="text/html" title="Connect Your 60GHz Sleep Radar to Home Assistant (Verified Walkthrough)" /><published>2026-10-18T00:00:00+00:00</published><updated>2026-10-18T00:00:00+00:00</updated><id>https://249263431.github.io/60GHz-Radar-SDK/integration/2026/10/18/sleep-radar-home-assistant</id><content type="html" xml:base="https://249263431.github.io/60GHz-Radar-SDK/integration/2026/10/18/sleep-radar-home-assistant.html"><![CDATA[<h1 id="connect-your-60ghz-sleep-radar-to-home-assistant-verified-walkthrough">Connect Your 60GHz Sleep Radar to Home Assistant (Verified Walkthrough)</h1>

<p>If you bought our 60GHz sleep monitoring radar and configured it for MQTT, the next step is to get that data — breathing rate, heart rate, sleep stage, in-bed status — into a dashboard you can actually watch. Home Assistant (HA) is the obvious choice: it speaks MQTT natively, runs locally (your data never leaves your home), and is free and open source.</p>

<p>This guide uses the same, verified method as our fall-radar HA walkthrough. Every step below was run on a real Windows 11 machine with WSL2 and Home Assistant Core <strong>2025.1.4</strong>, against a live radar talking to an Apache Artemis broker. No “should work in theory” — it is the same MQTT integration we already proved end to end.</p>

<h2 id="the-big-picture">The big picture</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>60GHz Sleep Radar  --MQTT--&gt;  Broker (Artemis / Mosquitto)  --MQTT--&gt;  Home Assistant
</code></pre></div></div>

<p>Three actors, same as the fall radar: the radar publishes JSON over MQTT, the broker is the middleman, and HA subscribes and turns the JSON into entities. If you have not set up the broker + radar MQTT side yet, do that first (see our MQTT architecture article and the sleep radar setup guide).</p>

<h2 id="before-you-start">Before you start</h2>

<p>You need:</p>

<ol>
  <li>A broker reachable on your network (e.g. <code class="language-plaintext highlighter-rouge">192.168.1.2:1883</code>) with a username and password.</li>
  <li>Your sleep radar configured for MQTT (broker IP, port 1883, credentials) — covered in the setup guide.</li>
  <li>The device’s <strong>DeviceID</strong>. On our radars the DeviceID <em>is</em> the device MAC address, which is also the MQTT ClientID, and it is printed on the back of the device. No manual registration needed.</li>
</ol>

<p>The sleep radar uses the prefix <code class="language-plaintext highlighter-rouge">Radar60SP</code>:</p>

<ul>
  <li>Report (radar → you): <code class="language-plaintext highlighter-rouge">/Radar60SP/{DeviceID}/sys/property/post</code></li>
  <li>Command (you → radar): <code class="language-plaintext highlighter-rouge">/Radar60SP/{DeviceID}/sys/property/set</code></li>
</ul>

<h2 id="what-is-home-assistant-briefly">What is Home Assistant, briefly</h2>

<p>HA is an open-source home automation hub. You run it on a box at home (Raspberry Pi, mini-PC, or even a Windows laptop via WSL2). It pulls data from hundreds of device types and shows everything in one dashboard. Because it is local-first, nothing is sent to the cloud.</p>

<p>Three ways to install it:</p>

<ul>
  <li><strong>HA OS</strong> — a dedicated image for Raspberry Pi / x86 mini-PCs. Easiest for pure users.</li>
  <li><strong>Docker</strong> — one container, but you need to be comfortable with Docker.</li>
  <li><strong>HA Core</strong> — run the Python app directly. This is what we verified, and it is the lightest path on Windows with <strong>no Docker</strong>. This guide uses HA Core on WSL2.</li>
</ul>

<h2 id="install-ha-core-on-wsl2-verified">Install HA Core on WSL2 (verified)</h2>

<p>WSL2 (Windows Subsystem for Linux) lets you run a real Linux on Windows — and HA Core is happiest on Linux.</p>

<p>If WSL2 is not enabled yet, in an <strong>administrator</strong> PowerShell:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">wsl</span><span class="w"> </span><span class="nt">--install</span><span class="w">
</span></code></pre></div></div>

<p>Reboot when prompted. Ubuntu will set itself up and ask you for a Linux username and password.</p>

<p>Then, inside the Ubuntu terminal:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt update <span class="o">&amp;&amp;</span> <span class="nb">sudo </span>apt upgrade <span class="nt">-y</span>
<span class="nb">sudo </span>apt <span class="nb">install</span> <span class="nt">-y</span> python3-venv python3-dev build-essential libssl-dev libffi-dev libjpeg-dev zlib1g-dev pkg-config

python3 <span class="nt">-m</span> venv ~/hassenv
<span class="nb">source</span> ~/hassenv/bin/activate
pip <span class="nb">install</span> <span class="nt">--upgrade</span> pip
pip <span class="nb">install </span>homeassistant
</code></pre></div></div>

<p>The last step downloads a lot of packages — give it a few minutes. When it finishes, start HA:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hass
</code></pre></div></div>

<p>First launch initializes the config and database and takes several minutes. You’ll know it is up when port 8123 responds. Open <strong>http://localhost:8123</strong> in your Windows browser and create your admin account.</p>

<blockquote>
  <p>We tested on Ubuntu 24.04 with Python 3.12 and Home Assistant Core <strong>2025.1.4</strong>. HA requires Python 3.12+, so use a current Ubuntu.</p>
</blockquote>

<p>To keep HA running after you close the terminal, start it detached:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>setsid <span class="nb">nohup </span>hass <span class="o">&gt;</span> ~/hass.log 2&gt;&amp;1 &lt; /dev/null &amp;
</code></pre></div></div>

<h2 id="connect-home-assistant-to-your-broker">Connect Home Assistant to your broker</h2>

<ol>
  <li><strong>Settings → Devices &amp; Services → Add Integration</strong>, search <strong>MQTT</strong>.</li>
  <li>Enter your broker details:
    <ul>
      <li>Broker: <code class="language-plaintext highlighter-rouge">192.168.1.2</code> (your broker’s IP)</li>
      <li>Port: <code class="language-plaintext highlighter-rouge">1883</code></li>
      <li>Username / Password: your broker credentials</li>
    </ul>
  </li>
  <li>Save.</li>
</ol>

<p>You can confirm the link from the broker side: Artemis’ console will now show a new connection from Home Assistant.</p>

<h2 id="configure-the-sleep-radar-sensors-the-important-part">Configure the sleep-radar sensors (the important part)</h2>

<p>The sleep radar reports a rich set of fields: <code class="language-plaintext highlighter-rouge">getIntoBed</code> (in/out of bed), <code class="language-plaintext highlighter-rouge">sleepStatus</code> (stage), <code class="language-plaintext highlighter-rouge">heartRateValue</code>, <code class="language-plaintext highlighter-rouge">breathValue</code>, <code class="language-plaintext highlighter-rouge">sleepScore</code>, <code class="language-plaintext highlighter-rouge">sleepComprehensiveStatus</code>, and more. We declare the ones we want as MQTT sensors in <code class="language-plaintext highlighter-rouge">configuration.yaml</code> (in your HA config folder, <code class="language-plaintext highlighter-rouge">~/.homeassistant/configuration.yaml</code> on Linux).</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">mqtt</span><span class="pi">:</span>
  <span class="na">sensor</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Bed</span><span class="nv"> </span><span class="s">In-Bed</span><span class="nv"> </span><span class="s">Status"</span>
      <span class="na">unique_id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">radar60sp_inbed"</span>
      <span class="na">state_topic</span><span class="pi">:</span> <span class="s2">"</span><span class="s">/Radar60SP/{DeviceID}/sys/property/post"</span>
      <span class="na">value_template</span><span class="pi">:</span> <span class="pi">&gt;</span>
        <span class="s">{% if value_json.params.getIntoBed is defined %}</span>
          <span class="s">{{ value_json.params.getIntoBed }}</span>
        <span class="s">{% else %}</span>
          <span class="s">{{ this.state }}</span>
        <span class="s">{% endif %}</span>

    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Bed</span><span class="nv"> </span><span class="s">Heart</span><span class="nv"> </span><span class="s">Rate"</span>
      <span class="na">unique_id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">radar60sp_hr"</span>
      <span class="na">state_topic</span><span class="pi">:</span> <span class="s2">"</span><span class="s">/Radar60SP/{DeviceID}/sys/property/post"</span>
      <span class="na">value_template</span><span class="pi">:</span> <span class="pi">&gt;</span>
        <span class="s">{% if value_json.params.heartRateValue is defined %}</span>
          <span class="s">{{ value_json.params.heartRateValue }}</span>
        <span class="s">{% else %}</span>
          <span class="s">{{ this.state }}</span>
        <span class="s">{% endif %}</span>

    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Bed</span><span class="nv"> </span><span class="s">Breathing</span><span class="nv"> </span><span class="s">Rate"</span>
      <span class="na">unique_id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">radar60sp_br"</span>
      <span class="na">state_topic</span><span class="pi">:</span> <span class="s2">"</span><span class="s">/Radar60SP/{DeviceID}/sys/property/post"</span>
      <span class="na">value_template</span><span class="pi">:</span> <span class="pi">&gt;</span>
        <span class="s">{% if value_json.params.breathValue is defined %}</span>
          <span class="s">{{ value_json.params.breathValue }}</span>
        <span class="s">{% else %}</span>
          <span class="s">{{ this.state }}</span>
        <span class="s">{% endif %}</span>

    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Bed</span><span class="nv"> </span><span class="s">Sleep</span><span class="nv"> </span><span class="s">Score"</span>
      <span class="na">unique_id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">radar60sp_score"</span>
      <span class="na">state_topic</span><span class="pi">:</span> <span class="s2">"</span><span class="s">/Radar60SP/{DeviceID}/sys/property/post"</span>
      <span class="na">value_template</span><span class="pi">:</span> <span class="pi">&gt;</span>
        <span class="s">{% if value_json.params.sleepScore is defined %}</span>
          <span class="s">{{ value_json.params.sleepScore }}</span>
        <span class="s">{% else %}</span>
          <span class="s">{{ this.state }}</span>
        <span class="s">{% endif %}</span>
</code></pre></div></div>

<p>Replace <code class="language-plaintext highlighter-rouge">{DeviceID}</code> with the number printed on your device.</p>

<p><strong>Why the <code class="language-plaintext highlighter-rouge">if defined … else this.state</code> pattern is mandatory here.</strong> The sleep radar does not send every field in every message. Heart rate and breathing arrive every 3 s, the sleep stage every 10 minutes, the score only when the session ends. If you wrote <code class="language-plaintext highlighter-rouge">{{ value_json.params.heartRateValue }}</code> directly, every message without that field would blank the sensor. The template keeps the last known value when the field is absent — the standard, stable way to handle sparse MQTT payloads.</p>

<p>After editing, reload without a full restart:</p>

<ul>
  <li><strong>Developer Tools → YAML → MQTT: Reload</strong> (or call the <code class="language-plaintext highlighter-rouge">mqtt.reload</code> service).</li>
</ul>

<h2 id="see-your-sleep-data-in-the-ui">See your sleep data in the UI</h2>

<p>Four ways, fastest first:</p>

<ol>
  <li><strong>Developer Tools → States.</strong> Type <code class="language-plaintext highlighter-rouge">bed</code> in the entity filter. You’ll see the four sensors above with live values and last-updated time. Lie down and watch <code class="language-plaintext highlighter-rouge">In-Bed Status</code> flip.</li>
  <li><strong>The default Overview dashboard.</strong> New sensor entities auto-appear as cards.</li>
  <li><strong>Raw MQTT.</strong> Settings → Devices &amp; Services → MQTT → Configure → Listen to a topic → enter <code class="language-plaintext highlighter-rouge">/Radar60SP/{DeviceID}/#</code> → Start Listening. Great for discovering every field your model reports.</li>
  <li><strong>A history graph.</strong> Edit the Overview dashboard, add a History card on <code class="language-plaintext highlighter-rouge">sensor.bed_heart_rate</code> (and breathing), and you get an overnight curve — great for demos and for checking sleep quality.</li>
</ol>

<h2 id="pitfalls-we-actually-hit-so-you-dont-have-to">Pitfalls we actually hit (so you don’t have to)</h2>

<ul>
  <li><strong>Don’t use the web UI “Restart Home Assistant” button</strong> when running HA Core from the command line. There is no supervisor to bring it back, so it stops and stays stopped. Use the <code class="language-plaintext highlighter-rouge">setsid nohup hass … &amp;</code> command above instead. (We learned this the hard way.)</li>
  <li><strong>Two harmless log errors on WSL2:</strong> <code class="language-plaintext highlighter-rouge">aiodns … getaddrinfo()</code> and <code class="language-plaintext highlighter-rouge">libpcap is not available</code>. Both are environment quirks (DNS resolver / DHCP discovery) and do not affect the web UI or MQTT. Ignore them.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">sleep_score</code> shows <code class="language-plaintext highlighter-rouge">unknown</code> at first — that is normal.</strong> The score is only published when a sleep session ends (and only for sessions of 4–12 hours). It fills in after the first complete night; query it once with a <code class="language-plaintext highlighter-rouge">get</code> if you want to seed it.</li>
  <li><strong>HA will not auto-start after a PC reboot.</strong> Re-run the <code class="language-plaintext highlighter-rouge">setsid nohup hass … &amp;</code> command. For a permanent setup, HA OS or Docker (with restart policies) is the better long-term home.</li>
</ul>

<h2 id="wrapping-up">Wrapping up</h2>

<p>That is the same verified chain — <strong>radar → broker → Home Assistant → dashboard</strong> — now feeding sleep metrics. From here you can graph heart and breathing rate across the night, alert when the bed stays empty too long, or log the nightly sleep score, all locally.</p>

<p>For the full list of reportable sleep fields and the install notes, see the sleep radar guide and our MQTT architecture article.</p>]]></content><author><name></name></author><category term="integration" /><category term="home assistant" /><category term="mqtt" /><category term="integration" /><category term="sleep radar" /><category term="dashboard" /><summary type="html"><![CDATA[Connect Your 60GHz Sleep Radar to Home Assistant (Verified Walkthrough)]]></summary></entry><entry><title type="html">Sleep Sensing in Wearables: Principles, Vendor Approaches, and Where mmWave Radar Fits</title><link href="https://249263431.github.io/60GHz-Radar-SDK/fundamentals/2026/10/18/sleep-sensing-wearables.html" rel="alternate" type="text/html" title="Sleep Sensing in Wearables: Principles, Vendor Approaches, and Where mmWave Radar Fits" /><published>2026-10-18T00:00:00+00:00</published><updated>2026-10-18T00:00:00+00:00</updated><id>https://249263431.github.io/60GHz-Radar-SDK/fundamentals/2026/10/18/sleep-sensing-wearables</id><content type="html" xml:base="https://249263431.github.io/60GHz-Radar-SDK/fundamentals/2026/10/18/sleep-sensing-wearables.html"><![CDATA[<!-- filename: 2026-10-18-sleep-sensing-wearables.md -->

<p>Sleep tracking has quietly become a baseline feature across modern wearables. But how do these devices actually know you’re asleep — and how accurate is that claim? This article walks through the three measurement principles behind consumer sleep sensing, how the major vendors implement them, the problems that still aren’t solved, and where mmWave radar offers a fundamentally different angle.</p>

<h2 id="the-three-core-measurement-principles">The three core measurement principles</h2>

<p><strong>1. Accelerometer (motion).</strong> An accelerometer measures acceleration, which in practice means it senses changes in your motion. The amplitude and duration of movement within a given time tell the device whether you’re active or still. Long stretches without movement are interpreted as sleep.</p>

<p><strong>2. Heart rate / optical sensing (PPG).</strong> Most wearables shine a light into your skin. As blood flows, it changes how much light is reflected back; each pulse of blood corresponds to one heartbeat. From the heart-rate stream the device can derive heart-rate variability (HRV) and, by watching how your heart rate speeds up and slows down, estimate your breathing amplitude.</p>

<p><strong>3. Acoustic sensing.</strong> A microphone can pick up snoring, steady breathing, and wheezing. Listening to sound gives clues about breathing quality and potential interruptions.</p>

<h2 id="how-wearables-are-built-around-these">How wearables are built around these</h2>

<p>Vendors weight these signals differently:</p>

<ul>
  <li><strong>Accelerometer-first — Xiaomi, Apple.</strong> These rely mostly on motion: how long it’s been since your last movement, and how large those movements were. They average this into a sleep duration. (You may not keep your arm perfectly still while asleep, so the accelerometer essentially computes an average.)</li>
  <li><strong>Heart-rate-first — Huawei, VIVO.</strong> They watch HR/HRV changes to derive breathing amplitude and produce a sleep-quality score.</li>
  <li><strong>Fusion — Samsung, Honor, Garmin, OPPO.</strong> These combine accelerometer and heart rate, and sometimes sound, into a single picture.</li>
</ul>

<p>Everyone is converging toward fusion, and devices increasingly pair with phones. A same-brand watch knows when you’re actively using your phone, so it won’t mistake that for sleep.</p>

<h2 id="the-hard-problems">The hard problems</h2>

<p>Even with fusion, consumer sleep tracking hits walls:</p>

<ul>
  <li><strong>Light vs. deep sleep is the core difficulty.</strong> The pattern that separates them isn’t obvious in wrist-scale signals, so staging is probabilistic.</li>
  <li><strong>REM (rapid eye movement) is estimated, not measured.</strong> Devices infer it rather than observe it directly.</li>
  <li><strong>Form factor matters.</strong> Rings such as Oura press tightly against the skin and sit closer to a blood vessel, giving a cleaner heart-rate signal. Watches can be worn loose or tight; pressure can blanch the skin and disrupt the optical reflection, causing dropouts.</li>
  <li><strong>The gold standard is PSG (polysomnography).</strong> It records the body’s electrical signals directly. Every consumer method falls short of its accuracy.</li>
</ul>

<h2 id="where-mmwave-radar-fits">Where mmWave radar fits</h2>

<p>mmWave radar’s principle is similar to the accelerometer approach — it detects motion amplitude and timing (you move, it knows) — but contactlessly, without anything on your body.</p>

<ul>
  <li><strong>Breathing is measured directly and more accurately.</strong> Wearables can only <em>compute</em> breathing because the wrist has no respiration of its own. mmWave observes chest displacement, so the respiration signal is stronger and more reliable.</li>
  <li><strong>Continuous, no-wear monitoring.</strong> Because nothing needs to be worn or charged, it can watch over long periods and learn life patterns: prolonged lying down, how many times you got up at night, and so on. For elderly or unwell users who spend most of the day in bed, it can gently flag a change in routine.</li>
  <li><strong>Limitation.</strong> It only works when you’re inside the monitored space — analogous to “no watch means no measurement.”</li>
</ul>

<h2 id="takeaways">Takeaways</h2>

<p>Sleep is mostly about breathing — sleep well and you breathe steadily and amply. Health is mostly about heart rate. Different tools emphasize different things, and each technology has distinct strengths that suit different users.</p>

<p>No consumer method matches PSG. mmWave radar is best understood as a contactless, continuous complement that emphasizes respiration and daily routine — a different instrument for a different need.</p>]]></content><author><name></name></author><category term="fundamentals" /><category term="wearables" /><category term="sleep tracking" /><category term="mmwave radar" /><category term="PPG" /><category term="accelerometer" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Where mmWave Radar Is Used: From Parking Spaces to Oil Tanks</title><link href="https://249263431.github.io/60GHz-Radar-SDK/fundamentals/2026/10/17/mmwave-radar-applications.html" rel="alternate" type="text/html" title="Where mmWave Radar Is Used: From Parking Spaces to Oil Tanks" /><published>2026-10-17T22:00:00+00:00</published><updated>2026-10-17T22:00:00+00:00</updated><id>https://249263431.github.io/60GHz-Radar-SDK/fundamentals/2026/10/17/mmwave-radar-applications</id><content type="html" xml:base="https://249263431.github.io/60GHz-Radar-SDK/fundamentals/2026/10/17/mmwave-radar-applications.html"><![CDATA[<!-- filename: 2026-10-18-mmwave-radar-applications.md -->

<p>When most people first hear about 60 GHz mmWave radar, they picture one thing: a small module mounted on a wall, telling a smart home system whether someone is in the room.</p>

<p>That is a real application, but it is a narrow one. The same sensing principle — transmit a frequency-modulated chirp, measure the round-trip time for range and the Doppler shift for velocity — is also used to measure the fuel level in a storage tank, hold a drone at a fixed altitude, time a car at an intersection, and map crop types from orbit.</p>

<p>The physics does not change between these applications. What changes is the frequency band, the antenna design, the beamwidth, and above all what the signal processing looks for in the returned signal.</p>

<p>This article walks through the main application families, and ends with an honest note about the one slice we build for.</p>

<h2 id="automotive-and-traffic">Automotive and Traffic</h2>

<p><strong>Autonomous driving and driver assistance.</strong> Radar measures the range and relative velocity of vehicles, cyclists, and pedestrians directly, rather than inferring them from pixels. This is the main reason radar stays dependable in rain, fog, glare, and darkness — conditions where a camera’s input degrades sharply. A vision system and a radar are usually fused, because they fail in different conditions.</p>

<p><strong>Traffic monitoring.</strong> Roadside radar measures the speed of passing vehicles and detects which lanes are occupied. Because it measures velocity through the Doppler shift rather than by comparing frames, it does not need to track an object across images to know how fast it is moving. The output feeds signal controllers and enforcement systems.</p>

<p><strong>Parking.</strong> Per-space sensors detect whether a bay is occupied. Radar suits this because it can be mounted above or beside the space, is unaffected by lighting or weather, and does not require a clear line of sight in the way a camera does.</p>

<h2 id="industrial-level-measurement">Industrial Level Measurement</h2>

<p>Large storage tanks — fuel, chemicals, water — are commonly measured with radar mounted at the top of the tank. The radar measures the distance to the liquid surface, and the level follows from the known tank geometry.</p>

<p>The reason radar is preferred here is that it is <strong>non-contact</strong>. Nothing touches the product, which matters when the contents are corrosive, hot, pressurised, or need to stay sealed. It is also unaffected by vapour, dust, temperature gradients, or the colour and transparency of the liquid. Precision at the millimetre level is achievable, and at the scale of a large tank, a millimetre of level error translates into a meaningful volume error, so that precision is worth paying for.</p>

<h2 id="security-screening">Security Screening</h2>

<p>Human tissue and metal return measurably different signals. Their dielectric properties and reflectivity differ, so the phase of the reflected signal changes depending on what the wave bounced off. Phase-sensitive radar exploits this difference to detect concealed items.</p>

<p>This is worth calling out as a separate family because it is a fundamentally different signal-processing problem from presence detection. Presence detection asks “is there a target that moves.” Screening asks “what is this target made of.” Those need different features extracted from the same returned signal.</p>

<h2 id="drones-and-light-vehicles">Drones and Light Vehicles</h2>

<p><strong>Drones.</strong> Radar is used for altitude hold, obstacle avoidance, and — in more capable systems — imaging radar that forms a coarse representation of the surrounding environment. The advantage over optical or ultrasonic sensing is operation in dust, fog, and darkness, plus direct velocity measurement.</p>

<p><strong>E-bikes and motorcycles.</strong> Rear-facing radar provides approach and blind-spot warning for two-wheeled vehicles, where the rider cannot simply glance over a shoulder the way a car driver can.</p>

<h2 id="weather-and-agriculture">Weather and Agriculture</h2>

<p><strong>Weather.</strong> Radar measures precipitation — including rain density — by analysing the returned energy from hydrometeors across a volume.</p>

<p><strong>Agriculture.</strong> The reflection signature of a dense insect swarm differs from that of bare soil or an individual plant. Radar can estimate pest density, including locust swarms, from the characteristics of the return. It is a coarse estimate, not a species-level identification, but it covers areas that are impractical to survey by hand.</p>

<h2 id="satellite-and-remote-sensing">Satellite and Remote Sensing</h2>

<p>Orbital radar observes surface structure and can distinguish classes of vegetation by their reflection characteristics. This is remote sensing rather than proximity sensing, but it is the same principle: transmit, receive, and interpret what came back.</p>

<h2 id="underwater-the-most-common-misconception">Underwater: The Most Common Misconception</h2>

<p>This one comes up regularly, so it is worth addressing directly. The question is usually some version of: <em>can radar detect fish, or animals, underwater?</em></p>

<p><strong>No. Underwater detection uses sonar, which is acoustic, not electromagnetic.</strong></p>

<p>Sound propagates through water; radio energy does not travel far in it. Water absorbs electromagnetic waves very rapidly, and in practical terms a radar submerged in water propagates only a very short distance before the signal is gone. If the target is underwater, the sensor is a sound-based one, and the signal processing works on acoustic echoes and their characteristics.</p>

<p>This is not a limitation of any particular radar — it is the medium. The moment the target is below the water surface, radar is the wrong tool.</p>

<h2 id="indoor-presence-counting-posture-and-breathing">Indoor Presence, Counting, Posture, and Breathing</h2>

<p>And then there is the slice we build for: rooms.</p>

<p>In an indoor setting the useful questions are narrow and specific:</p>

<ul>
  <li>Is anyone in this room?</li>
  <li>How many people are there?</li>
  <li>What is the person’s posture — standing, sitting, lying?</li>
  <li>Are they breathing, and at what rate?</li>
</ul>

<p>These are answered with the same hardware used in the applications above, but tuned completely differently: short range, wide field of view, fine velocity resolution, and signal processing built around human-scale motion rather than vehicles or liquid surfaces.</p>

<p>Two properties make radar the right choice indoors. It works in complete darkness, because it generates its own illumination. And it produces no image at all — no lens, no video, nothing identifiable — which is why it is acceptable in bedrooms and bathrooms where a camera would not be.</p>

<h2 id="why-we-only-build-one-slice">Why We Only Build One Slice</h2>

<p>Every application above is its own engineering discipline. Automotive radar has to survive vibration, temperature extremes, and functional-safety certification. Tank-level radar has to be certified for hazardous atmospheres. Screening radar is a materials-classification problem. Drone radar is constrained by size and power in a way that wall-mounted sensors are not.</p>

<p>Doing all of them well is not realistic. Doing one of them properly is. We build indoor sensing modules, and we refer the other enquiries elsewhere.</p>

<h2 id="summary">Summary</h2>

<table>
  <thead>
    <tr>
      <th>Application</th>
      <th>What the radar measures</th>
      <th>Why radar fits</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Automotive / ADAS</td>
      <td>Range and relative velocity of road users</td>
      <td>Works in rain, fog, darkness</td>
    </tr>
    <tr>
      <td>Traffic enforcement</td>
      <td>Vehicle speed, lane occupancy</td>
      <td>Velocity comes from Doppler, not frame tracking</td>
    </tr>
    <tr>
      <td>Parking</td>
      <td>Bay occupancy</td>
      <td>Lighting- and weather-independent</td>
    </tr>
    <tr>
      <td>Tank level</td>
      <td>Distance to liquid surface</td>
      <td>Non-contact, millimetre precision</td>
    </tr>
    <tr>
      <td>Security screening</td>
      <td>Material differences via phase</td>
      <td>Metal and tissue reflect differently</td>
    </tr>
    <tr>
      <td>Drones</td>
      <td>Altitude, obstacles</td>
      <td>Operates in dust and darkness</td>
    </tr>
    <tr>
      <td>Two-wheelers</td>
      <td>Rear approach</td>
      <td>Direct velocity measurement</td>
    </tr>
    <tr>
      <td>Weather</td>
      <td>Rain density</td>
      <td>Volume measurement</td>
    </tr>
    <tr>
      <td>Agriculture</td>
      <td>Pest / swarm density</td>
      <td>Covers large areas</td>
    </tr>
    <tr>
      <td>Satellite</td>
      <td>Surface and vegetation type</td>
      <td>Works through cloud cover</td>
    </tr>
    <tr>
      <td>Underwater</td>
      <td><strong>Not applicable</strong></td>
      <td>Use sonar; radio waves do not propagate in water</td>
    </tr>
    <tr>
      <td>Indoor</td>
      <td>Presence, count, posture, breathing</td>
      <td>Darkness-capable, no camera, no image</td>
    </tr>
  </tbody>
</table>

<p>The technology is one. The applications are many, and they share almost nothing beyond the basic transmit-and-receive principle. Knowing which one you need — and which one you are buying — matters more than knowing the frequency.</p>]]></content><author><name></name></author><category term="fundamentals" /><category term="mmwave radar" /><category term="applications" /><category term="level measurement" /><category term="parking" /><category term="sonar" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">mmWave Radar vs. a Camera: What Each One Actually Measures</title><link href="https://249263431.github.io/60GHz-Radar-SDK/fundamentals/2026/10/17/mmwave-radar-vs-camera.html" rel="alternate" type="text/html" title="mmWave Radar vs. a Camera: What Each One Actually Measures" /><published>2026-10-17T22:00:00+00:00</published><updated>2026-10-17T22:00:00+00:00</updated><id>https://249263431.github.io/60GHz-Radar-SDK/fundamentals/2026/10/17/mmwave-radar-vs-camera</id><content type="html" xml:base="https://249263431.github.io/60GHz-Radar-SDK/fundamentals/2026/10/17/mmwave-radar-vs-camera.html"><![CDATA[<!-- filename: 2026-10-18-mmwave-radar-vs-camera.md -->

<p>The first question we get asked about indoor sensing is almost always the same: <em>why not just use a camera?</em></p>

<p>It is a fair question. A camera is cheaper, familiar, and produces output a human can look at and understand immediately. But a camera and a mmWave radar do not measure the same thing, and each is clearly better at a different job.</p>

<p>The short version: <strong>a camera tells you roughly what a person looks like and what posture they are in. A radar measures motion far too small for a camera to register at all.</strong> Understanding that distinction is what determines which one you need.</p>

<h2 id="what-a-camera-measures">What a Camera Measures</h2>

<p>A camera records reflected visible light. From those pixels you get shape, colour, texture, and — with modern processing — a rough skeletal pose.</p>

<p>The strength of this is that the output is rich and directly interpretable. If you want to know whether a person is roughly standing, sitting, or lying down, a camera gives you that more clearly and more cheaply than a radar does. You can look at the frame and confirm it yourself, which makes cameras easy to install and easy to debug.</p>

<p>The weakness is that everything downstream depends on light and on a clear line of sight. A camera needs illumination, or infrared in the dark. It needs a lens that stays clean. It stops working behind steam, smoke, or a blanket. And it produces identifiable video, which is exactly why installing one in a bedroom or a bathroom is a non-starter for most people.</p>

<h2 id="what-mmwave-radar-measures">What mmWave Radar Measures</h2>

<p>Radar transmits radio energy and listens for what comes back. From the returned signal it extracts three things:</p>

<ul>
  <li><strong>Range</strong> — distance to the target, from the round-trip time of the chirp.</li>
  <li><strong>Velocity</strong> — radial motion, from the Doppler shift.</li>
  <li><strong>Micro-motion</strong> — very small displacements, from the phase of the returned signal.</li>
</ul>

<p>The third one is the one that matters for indoor sensing, and it is the one a camera cannot do.</p>

<h2 id="the-decisive-difference-micro-motion">The Decisive Difference: Micro-Motion</h2>

<p>A 60 GHz radar resolves movement down to a fraction of a millimetre. That is not a marginal improvement over a camera — it is a different regime entirely.</p>

<p>Breathing moves the chest wall by an amount well within that resolution, and the heartbeat moves it by less — but still by enough to be measured. A person lying still under a blanket produces no visible change whatsoever in a video frame, while a radar pointed at the same person measures the chest movement continuously, through the blanket, in complete darkness.</p>

<p>This is the entire reason sleep monitoring — breathing rate, heart rate, sleep staging — is a radar application and not a camera application. It is not that radar is a better camera. It is that the quantity being measured is invisible to a camera.</p>

<h2 id="where-the-camera-is-genuinely-better">Where the Camera Is Genuinely Better</h2>

<p>It is worth being blunt about this, because the marketing in this category often is not.</p>

<p><strong>Radar is not a camera replacement for seeing shape.</strong> The return from a human body is a sparse set of reflection points, not a picture. If your question is “roughly what posture is this person in,” or “what is in the room,” a camera answers it more directly and more reliably.</p>

<p>Radar does not identify who a person is. It does not read facial expressions. It does not tell you what object someone is holding. It cannot show you the room. If any of those are requirements, you need a camera, or both sensors together.</p>

<p>A realistic way to think about it: radar tells you <em>that</em> something is moving and <em>how</em> it is moving at a very fine resolution. A camera tells you <em>what</em> it is.</p>

<h2 id="practical-differences">Practical Differences</h2>

<table>
  <thead>
    <tr>
      <th>Factor</th>
      <th>mmWave radar</th>
      <th>Camera</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Complete darkness</td>
      <td>Works — generates its own signal</td>
      <td>Needs light or infrared</td>
    </tr>
    <tr>
      <td>Privacy</td>
      <td>No image, no lens, nothing identifiable</td>
      <td>Produces identifiable video</td>
    </tr>
    <tr>
      <td>Through blankets, steam, smoke</td>
      <td>Sees through them</td>
      <td>Blocked</td>
    </tr>
    <tr>
      <td>Identifies a person</td>
      <td>No</td>
      <td>Yes</td>
    </tr>
    <tr>
      <td>Rough posture</td>
      <td>Inferred, coarser</td>
      <td>Clearer and more direct</td>
    </tr>
    <tr>
      <td>Breathing / heart rate</td>
      <td>Measurable</td>
      <td>Not measurable</td>
    </tr>
    <tr>
      <td>Output</td>
      <td>Abstract data (range, velocity, phase)</td>
      <td>An image a human can read</td>
    </tr>
    <tr>
      <td>Typical cost</td>
      <td>Higher per unit</td>
      <td>Lower per unit</td>
    </tr>
    <tr>
      <td>Debugging</td>
      <td>Harder — output is not visual</td>
      <td>Easy — look at the frame</td>
    </tr>
  </tbody>
</table>

<h2 id="how-to-choose">How to Choose</h2>

<p>The decision usually comes down to two questions.</p>

<p><strong>First, is privacy or darkness a requirement?</strong> If the sensor goes in a bedroom, a bathroom, or anywhere a camera would not be acceptable, the choice is made for you. Radar produces no image, which is the whole argument.</p>

<p><strong>Second, what is the smallest motion you need to detect?</strong> If the answer is breathing, heartbeat, or a person lying still, only radar can measure it. If the answer is “a person walked into the room” or “someone is sitting at the table,” a camera does that job more cheaply, and radar does it without the privacy problem.</p>

<p>For fall detection, sleep monitoring, and presence sensing in private spaces, radar is the practical answer. For “show me what is happening in the room,” it is not.</p>

<h2 id="what-neither-one-is">What Neither One Is</h2>

<p>One more thing worth stating plainly: radar does not identify individuals and does not produce images. It measures motion, distance, and presence. A consumer radar that reports breathing rate or sleep stages is a wellness device — it is not a medical instrument, and it does not diagnose anything.</p>

<h2 id="summary">Summary</h2>

<ul>
  <li>A camera is better at <strong>shape and rough posture</strong>, and costs less. Its output is directly interpretable.</li>
  <li>A radar is better at <strong>motion too small to see</strong> — breathing, heartbeat, a person lying still — and at sensing <strong>in darkness, through materials, without producing an image</strong>.</li>
  <li>Radar does not replace a camera for seeing what is in a room, and a camera cannot do what radar does for micro-motion.</li>
  <li>For bedrooms and bathrooms, the deciding factor is usually that <strong>radar produces no image at all</strong>.</li>
</ul>

<p>Pick based on what you are measuring, not on which sensor sounds more advanced.</p>]]></content><author><name></name></author><category term="fundamentals" /><category term="mmwave radar" /><category term="camera" /><category term="comparison" /><category term="micro-motion" /><category term="privacy" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Two Architectures, Two Protocols: MQTT vs UART on mmWave Radar</title><link href="https://249263431.github.io/60GHz-Radar-SDK/fundamentals/2026/10/17/radar-architecture-mqtt-vs-uart.html" rel="alternate" type="text/html" title="Two Architectures, Two Protocols: MQTT vs UART on mmWave Radar" /><published>2026-10-17T22:00:00+00:00</published><updated>2026-10-17T22:00:00+00:00</updated><id>https://249263431.github.io/60GHz-Radar-SDK/fundamentals/2026/10/17/radar-architecture-mqtt-vs-uart</id><content type="html" xml:base="https://249263431.github.io/60GHz-Radar-SDK/fundamentals/2026/10/17/radar-architecture-mqtt-vs-uart.html"><![CDATA[<!-- filename: 2026-10-18-radar-architecture-mqtt-vs-uart.md -->

<p>The most common reason a radar “does not work” is not a defect. It is that the buyer followed the wrong set of instructions.</p>

<p>Our products come in two fundamentally different architectures, and they do not share a protocol. One joins your Wi-Fi network and speaks MQTT. The other has no network at all and speaks binary frames over a serial cable. Both are radar. Almost nothing else about them is the same.</p>

<p>This article explains both, tells you how to recognise which one you have, and shows what you need in order to see the first message come out of it.</p>

<h2 id="start-here-which-one-do-you-have">Start Here: Which One Do You Have?</h2>

<table>
  <thead>
    <tr>
      <th>You have</th>
      <th>How to recognise it</th>
      <th>Interface</th>
      <th>Protocol</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Finished radar</strong></td>
      <td>Enclosed housing, no exposed pin header, has Wi-Fi</td>
      <td>2.4 GHz Wi-Fi</td>
      <td>MQTT (JSON over IP)</td>
    </tr>
    <tr>
      <td><strong>Radar module</strong></td>
      <td>Bare PCB with a pin header, no Wi-Fi, no network to configure</td>
      <td>Wired UART</td>
      <td>Binary frames</td>
    </tr>
  </tbody>
</table>

<p>The fastest test: <strong>if it has a row of pins and no Wi-Fi, it is a module. If it has a case and you configure Wi-Fi, it is the finished radar.</strong></p>

<p>That distinction decides which documentation applies to you:</p>

<ul>
  <li>A <strong>module has no MQTT</strong>. It cannot reach a broker, because it has no way onto an IP network.</li>
  <li>A <strong>finished radar has no exposed serial protocol</strong>. It is not designed to be wired to a microcontroller.</li>
</ul>

<p>Do not mix the two. Reading the module instructions for a finished radar (or the reverse) is where most of the confusion starts.</p>

<h2 id="architecture-a-the-finished-radar-mqtt">Architecture A: The Finished Radar (MQTT)</h2>

<h3 id="three-things-you-need">Three things you need</h3>

<ol>
  <li><strong>A 2.4 GHz Wi-Fi network.</strong> 5 GHz and 5.8 GHz cannot be used.</li>
  <li><strong>An MQTT broker.</strong> The radar publishes everything to it.</li>
  <li><strong>An MQTT client.</strong> You read the data with it.</li>
</ol>

<h3 id="the-one-idea-that-matters-the-broker-sits-in-the-middle">The one idea that matters: the broker sits in the middle</h3>

<p>This is the part people miss. The radar does <strong>not</strong> send data to your phone, your laptop, or an app. It publishes to a broker. Everything else — your dashboard, your own script, any client you open — connects to <strong>the same broker</strong> and reads from there.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    radar  ──Wi-Fi──▶  router  ──▶  MQTT broker  ◀──  your MQTT client
                                    (Mosquitto /       (MQTT Explorer /
                                     Artemis)           mosquitto_sub /
                                                        MQTTX)

    The radar talks only to the broker.
    Your client talks only to the broker.
    They never talk to each other directly.
</code></pre></div></div>

<p>So when the radar is online but you see no data, the first question is always the same:</p>

<blockquote>
  <p><strong>Are the radar and my client pointed at the same broker?</strong></p>
</blockquote>

<p>In most cases they are not. The radar was configured with one address, and the client was opened with another — often a public test broker used during a first experiment.</p>

<h3 id="choosing-a-broker">Choosing a broker</h3>

<p>Any broker that accepts plain MQTT over TCP works. The radar is configured with a <code class="language-plaintext highlighter-rouge">tcp://</code> address, normally port 1883.</p>

<table>
  <thead>
    <tr>
      <th>Broker</th>
      <th>Good for</th>
      <th>Notes</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Eclipse Mosquitto</strong></td>
      <td>Getting started, Raspberry Pi, home servers</td>
      <td>A few megabytes, one command to install, the most widely documented broker in the IoT world. If you just want your first message to appear, start here.</td>
    </tr>
    <tr>
      <td><strong>Apache Artemis</strong></td>
      <td>Larger deployments, existing Java infrastructure</td>
      <td>A full message broker that also speaks MQTT. This is what we run and what the radar has been verified against.</td>
    </tr>
    <tr>
      <td>Managed cloud broker</td>
      <td>Production without running your own server</td>
      <td>Confirm it offers a plain TCP endpoint (port 1883), not only WebSocket</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">broker.emqx.io</code></td>
      <td>First smoke test only</td>
      <td>Public. Anyone can read your data. Never use it for a real installation.</td>
    </tr>
  </tbody>
</table>

<p><strong>Our recommendation:</strong> if you already run a broker, use it. If you are starting from nothing, install Mosquitto — it is the shortest path from “radar on the desk” to “first message on screen”.</p>

<p>The radar asks for four values, entered once through its built-in web page:</p>

<table>
  <thead>
    <tr>
      <th>Field</th>
      <th>Limit</th>
      <th>Note</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Server address</td>
      <td>Up to 64 characters</td>
      <td><code class="language-plaintext highlighter-rouge">tcp://host:1883</code></td>
    </tr>
    <tr>
      <td>ClientID</td>
      <td>Up to 32 characters</td>
      <td><strong>Must be unique per radar</strong></td>
    </tr>
    <tr>
      <td>Username</td>
      <td>Up to 32 characters</td>
      <td> </td>
    </tr>
    <tr>
      <td>Password</td>
      <td>Up to 32 characters</td>
      <td> </td>
    </tr>
  </tbody>
</table>

<p>Two radars sharing one ClientID will keep disconnecting each other. Give every unit its own.</p>

<h3 id="choosing-a-client">Choosing a client</h3>

<p>You do not need any particular client. Any MQTT client works, so pick whichever you can install most easily.</p>

<table>
  <thead>
    <tr>
      <th>Client</th>
      <th>Why you might use it</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>MQTT Explorer</strong></td>
      <td>Shows the topic tree automatically, so you can see which topics exist without typing them. The friendliest first client.</td>
    </tr>
    <tr>
      <td><strong>mosquitto_sub</strong></td>
      <td>Ships with Mosquitto, so if you installed Mosquitto as your broker you already have it. No extra download.</td>
    </tr>
    <tr>
      <td><strong>MQTTX</strong></td>
      <td>A cross-platform GUI client.</td>
    </tr>
  </tbody>
</table>

<h3 id="the-topics-the-radar-uses">The topics the radar uses</h3>

<p>The full report topic is:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;prefix&gt;/&lt;DeviceID&gt;/sys/property/post
</code></pre></div></div>

<p>The prefix depends on the model:</p>

<table>
  <thead>
    <tr>
      <th>Model</th>
      <th>Topic prefix</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>60 GHz sleep radar</td>
      <td><code class="language-plaintext highlighter-rouge">/Radar60SP/</code></td>
    </tr>
    <tr>
      <td>60 GHz fall radar</td>
      <td><code class="language-plaintext highlighter-rouge">/Radar60FL/</code></td>
    </tr>
    <tr>
      <td>24 GHz presence radar</td>
      <td><code class="language-plaintext highlighter-rouge">/RadarHP/</code></td>
    </tr>
    <tr>
      <td>24 GHz sleep radar</td>
      <td><code class="language-plaintext highlighter-rouge">/RadarSP/</code></td>
    </tr>
    <tr>
      <td>24 GHz fall radar</td>
      <td><code class="language-plaintext highlighter-rouge">/RadarFL/</code></td>
    </tr>
  </tbody>
</table>

<p>The DeviceID is the value shown on the radar’s own configuration page. A healthy radar publishes messages like:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="nl">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1.0"</span><span class="p">,</span><span class="w"> </span><span class="nl">"method"</span><span class="p">:</span><span class="w"> </span><span class="s2">"post"</span><span class="p">,</span><span class="w"> </span><span class="nl">"params"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="nl">"someoneExists"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1"</span><span class="p">}}</span><span class="w">
</span></code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">method</code> field tells you what kind of message it is: <code class="language-plaintext highlighter-rouge">post</code> is a report from the radar, <code class="language-plaintext highlighter-rouge">get</code> queries a value, and <code class="language-plaintext highlighter-rouge">set</code> changes one. The radar answers queries on the report topic.</p>

<h3 id="your-first-five-minutes">Your first five minutes</h3>

<ol>
  <li>Power the radar from a 5 V USB adapter.</li>
  <li>Hold the button for <strong>more than 10 seconds</strong>, join the <code class="language-plaintext highlighter-rouge">RadarConfig-xxxxxxxxxxxx</code> hotspot, and open <code class="language-plaintext highlighter-rouge">192.168.0.1</code> to enter the broker address, ClientID, username, and password.</li>
  <li>Install <code class="language-plaintext highlighter-rouge">BK_BLE5.apk</code>, hold the button for about <strong>5 seconds</strong> until the LED flashes, and send the radar your <strong>2.4 GHz</strong> Wi-Fi credentials over Bluetooth.</li>
  <li>Subscribe from any client. With <code class="language-plaintext highlighter-rouge">mosquitto_sub</code>:
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mosquitto_sub -h &lt;your-broker&gt; -t "/Radar60FL/#" -v
</code></pre></div>    </div>
    <p>Or open MQTT Explorer and browse the topic tree.</p>
  </li>
  <li>Within seconds you should see JSON arriving.</li>
</ol>

<p>If you can see that first message, the entire chain works. Everything after that — dashboards, automations, your own application — is built on top of a connection you have already proven. Full click-by-click steps are in the <a href="/60GHz-Radar-SDK/guide/2026/10/17/radar-setup-guide.html">setup guide</a>.</p>

<h2 id="architecture-b-the-radar-module-uart">Architecture B: The Radar Module (UART)</h2>

<h3 id="what-you-need">What you need</h3>

<ol>
  <li><strong>A USB-to-TTL serial adapter</strong> — FTDI, CH340, or CP2102. Any of them works.</li>
  <li><strong>Any serial terminal program.</strong> There is nothing special to install.</li>
  <li><strong>Four connections:</strong> VCC, GND, TX, RX.</li>
</ol>

<h3 id="the-voltage-warning">The voltage warning</h3>

<p>The module’s UART is <strong>3.3 V TTL logic level</strong>.</p>

<p>Do not connect it directly to an RS-232 port, and do not feed it 5 V logic. Either can damage the module. If your adapter has a voltage jumper, set it to 3.3 V before wiring.</p>

<h3 id="settings">Settings</h3>

<table>
  <thead>
    <tr>
      <th>Setting</th>
      <th>Value</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Baud rate</td>
      <td>115200</td>
    </tr>
    <tr>
      <td>Data bits</td>
      <td>8</td>
    </tr>
    <tr>
      <td>Stop bits</td>
      <td>1</td>
    </tr>
    <tr>
      <td>Parity</td>
      <td>None</td>
    </tr>
    <tr>
      <td>Flow control</td>
      <td>None</td>
    </tr>
  </tbody>
</table>

<p>That is the entire configuration. Any terminal that can be set to <strong>115200 / 8N1</strong> will talk to the module. There is no app, no account, and no driver beyond the one your USB-TTL adapter already needs.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    radar module            USB-TTL adapter          computer
    VCC GND TX RX  ──────▶   FTDI / CH340    ──USB──▶  any serial
                             / CP2102                   terminal
                           (3.3 V TTL, 115200 bps, 8N1)
</code></pre></div></div>

<h3 id="the-frame-format">The frame format</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Header      Control  Command  Length   Data     Checksum  Tail
0x53 0x59   1 Byte   1 Byte   2 Bytes  n Bytes  1 Byte    0x54 0x43
</code></pre></div></div>

<p>Every frame starts with <code class="language-plaintext highlighter-rouge">53 59</code> and ends with <code class="language-plaintext highlighter-rouge">54 43</code>. The checksum is the low 8 bits of the sum of the header, control byte, command byte, length bytes, and data.</p>

<p>You send a command frame, and the module answers with a report frame. The control and command bytes differ per product — the complete tables are in each product’s guide: <a href="/60GHz-Radar-SDK/product/2026/10/17/sleep-radar-guide.html">sleep radar</a>, <a href="/60GHz-Radar-SDK/product/2026/10/17/presence-radar-guide.html">presence radar</a>, and <a href="/60GHz-Radar-SDK/product/2026/10/17/fall-radar-guide.html">fall radar</a>.</p>

<h3 id="why-mqtt-is-not-available-here">Why MQTT is not available here</h3>

<p>The module has no Wi-Fi radio and no network stack. It cannot reach a broker because it has no way onto an IP network at all.</p>

<p>If you need MQTT, you have two options: use the finished radar, or put your own microcontroller between them — read the UART frames and publish them yourself. That is exactly what the finished product does internally.</p>

<h2 id="the-two-are-not-interchangeable">The Two Are Not Interchangeable</h2>

<table>
  <thead>
    <tr>
      <th>Question</th>
      <th>Finished radar</th>
      <th>Radar module</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Joins Wi-Fi</td>
      <td>Yes</td>
      <td>No</td>
    </tr>
    <tr>
      <td>Speaks MQTT</td>
      <td>Yes</td>
      <td>No</td>
    </tr>
    <tr>
      <td>Exposes UART</td>
      <td>No</td>
      <td>Yes</td>
    </tr>
    <tr>
      <td>Needs a broker</td>
      <td>Yes</td>
      <td>No</td>
    </tr>
    <tr>
      <td>Needs a USB-TTL adapter</td>
      <td>No</td>
      <td>Yes</td>
    </tr>
    <tr>
      <td>Configured with</td>
      <td>Web page + Android app</td>
      <td>Serial commands</td>
    </tr>
    <tr>
      <td>Data format</td>
      <td>JSON</td>
      <td>Binary frames</td>
    </tr>
    <tr>
      <td>Power</td>
      <td>5 V USB</td>
      <td>3.3 V (logic)</td>
    </tr>
    <tr>
      <td>Typical use</td>
      <td>Finished installation, dashboards, automations</td>
      <td>Built into your own product</td>
    </tr>
  </tbody>
</table>

<h2 id="troubleshooting">Troubleshooting</h2>

<table>
  <thead>
    <tr>
      <th>Symptom</th>
      <th>Likely cause</th>
      <th>What to check</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Radar is online but the client shows nothing</td>
      <td>Radar and client on different brokers</td>
      <td>Compare the address in the radar’s web page with the one your client connects to</td>
    </tr>
    <tr>
      <td>Two radars keep disconnecting each other</td>
      <td>Same ClientID</td>
      <td>Give every radar a unique ClientID</td>
    </tr>
    <tr>
      <td>Wi-Fi setup always fails</td>
      <td>5 GHz network</td>
      <td>Use 2.4 GHz only, or split the bands in your router</td>
    </tr>
    <tr>
      <td>Provisioning times out</td>
      <td>Took longer than 90 seconds</td>
      <td>Hold the button again and retry</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">192.168.0.1</code> will not open</td>
      <td>Phone not connected to the <code class="language-plaintext highlighter-rouge">RadarConfig</code> hotspot</td>
      <td>Reconnect to the hotspot. It has no internet access — that is normal</td>
    </tr>
    <tr>
      <td>Serial terminal shows garbage</td>
      <td>Wrong baud rate or framing</td>
      <td>Set 115200, 8 data bits, 1 stop bit, no parity</td>
    </tr>
    <tr>
      <td>Nothing at all from the module</td>
      <td>TX/RX crossed, or wrong voltage</td>
      <td>Swap TX and RX. Confirm 3.3 V TTL, not 5 V or RS-232</td>
    </tr>
    <tr>
      <td>Trying to set MQTT on a module</td>
      <td>The module has no network</td>
      <td>Use the finished radar for MQTT</td>
    </tr>
    <tr>
      <td>App cannot find <code class="language-plaintext highlighter-rouge">Radar_BLE</code></td>
      <td>Module not in provisioning mode</td>
      <td>Hold the button for 5 seconds until the LED flashes</td>
    </tr>
  </tbody>
</table>

<h2 id="where-to-go-next">Where to Go Next</h2>

<ul>
  <li><a href="/60GHz-Radar-SDK/guide/2026/10/17/radar-setup-guide.html">How to Set Up Your mmWave Radar</a> — the click-by-click MQTT and Wi-Fi configuration</li>
  <li><a href="/60GHz-Radar-SDK/product/2026/10/17/sleep-radar-guide.html">Sleep radar guide</a> · <a href="/60GHz-Radar-SDK/product/2026/10/17/presence-radar-guide.html">Presence radar guide</a> · <a href="/60GHz-Radar-SDK/product/2026/10/17/fall-radar-guide.html">Fall radar guide</a></li>
  <li><a href="/60GHz-Radar-SDK/fundamentals/2026/10/17/how-mmwave-radar-works.html">How mmWave Radar Works</a> — the sensing principle behind all of them</li>
</ul>

<h2 id="summary">Summary</h2>

<p>Two architectures, two protocols.</p>

<p>The <strong>finished radar</strong> joins your 2.4 GHz Wi-Fi and publishes JSON to an MQTT broker. You read it with any MQTT client, and it never talks to your devices directly — the broker is always in the middle. If you see no data, check first that both ends use the same broker.</p>

<p>The <strong>radar module</strong> has no network at all. It speaks binary frames over a 3.3 V TTL UART at 115200 bps, 8N1, readable with any serial terminal and a USB-TTL adapter.</p>

<p>Identify which one you have first. Everything else in the documentation follows from that.</p>]]></content><author><name></name></author><category term="fundamentals" /><category term="architecture" /><category term="mqtt" /><category term="uart" /><category term="protocol" /><category term="mosquitto" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Why Fall Detection Is Harder Than It Looks: Three Failure Modes</title><link href="https://249263431.github.io/60GHz-Radar-SDK/fundamentals/2026/10/17/fall-detection-failure-modes.html" rel="alternate" type="text/html" title="Why Fall Detection Is Harder Than It Looks: Three Failure Modes" /><published>2026-10-17T01:00:00+00:00</published><updated>2026-10-17T01:00:00+00:00</updated><id>https://249263431.github.io/60GHz-Radar-SDK/fundamentals/2026/10/17/fall-detection-failure-modes</id><content type="html" xml:base="https://249263431.github.io/60GHz-Radar-SDK/fundamentals/2026/10/17/fall-detection-failure-modes.html"><![CDATA[<!-- filename: 2026-10-17-fall-detection-failure-modes.md -->

<p>Fall detection is one of the most requested features in elderly care sensing, and one of the least straightforward to deliver. The name suggests a single clear event — a person falls, an alarm fires — but the sensing problem behind it has three distinct failure modes, and each one behaves differently in a real room.</p>

<p>This article describes those three modes: two kinds of false alarm and one kind of missed event. It also covers a problem that sits above all of them, which is that “a fall” is not a precisely defined acceptance criterion. Understanding these four things is the difference between a fall radar that works in a deployment and one that generates complaints.</p>

<h2 id="why-the-demand-is-real">Why the Demand Is Real</h2>

<p>For an elderly person with reduced mobility — unsteady gait, a cane, limited strength, or partial loss of independence — a fall is not a health metric. It is an event where somebody needs to know, quickly, so that the person can be helped up.</p>

<p>That is a different requirement from sleep monitoring or presence detection. Nobody is harmed by a sleep score that arrives late. A person lying on a bathroom floor for forty minutes is harmed by an alarm that did not fire, and by an alarm that fired three times the previous night for no reason.</p>

<p>So the sensing requirements are strict in both directions at once: the false alarm rate has to be low enough that the alarm is believed, and the missed-event rate has to be low enough that the alarm is trusted. Those two requirements pull against each other, and that tension is the source of everything below.</p>

<h2 id="false-alarm-1-nobody-there-but-the-radar-reports-someone">False Alarm 1: Nobody There, but the Radar Reports Someone</h2>

<p>The first failure mode is an alarm raised in an empty room.</p>

<p>A bathroom is full of things that move without a person present. An open window lets a curtain or a towel move in the air flow. A leaking container drips. A toilet flushes. An extractor fan vibrates. Each of these produces a radar return, and a return from a low, stationary-looking target is exactly what a fall looks like.</p>

<p>The sequence is:</p>

<ol>
  <li>An interference source produces a return.</li>
  <li>The radar classifies the return as a target rather than clutter.</li>
  <li>The target is low and does not move.</li>
  <li>A low, stationary target is the signature the fall detector is looking for.</li>
  <li>An alarm is published, in an empty room.</li>
</ol>

<p>This is the failure mode that matters most at scale. A single false alarm is an inconvenience. A deployment of hundreds of units, each producing occasional empty-room alarms, produces a continuous stream of notifications that nobody acts on — and once occupants learn that the alarm is usually wrong, they stop responding to it, including when it is right.</p>

<p>Reducing this mode is mostly about the room, not the algorithm. Knowing whether a person is actually present — through entry and exit tracking, or through a corroborating signal — removes most of the candidates before the posture judgement runs. That is why a single-door bathroom is a much easier sensing problem than an open room, and why the scene matters as much as the sensor.</p>

<h2 id="false-alarm-2-someone-there-but-the-posture-is-misread">False Alarm 2: Someone There, but the Posture Is Misread</h2>

<p>The second failure mode is an alarm raised while a person is present and doing something entirely normal.</p>

<p>Three examples, all of them ordinary activities:</p>

<table>
  <thead>
    <tr>
      <th>Activity</th>
      <th>What the Radar Sees</th>
      <th>What It Concludes</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Squatting to wash clothes</td>
      <td>Hand and arm movement at low height, head relatively still</td>
      <td>A person struggling on the floor</td>
    </tr>
    <tr>
      <td>Mopping the floor</td>
      <td>A moving object at floor level, low and wide</td>
      <td>A low, moving target</td>
    </tr>
    <tr>
      <td>Sitting on the toilet, swinging a leg</td>
      <td>Foot movement at low height, torso still</td>
      <td>Movement near the floor without a head</td>
    </tr>
  </tbody>
</table>

<p>The common mechanism is a mismatch between what the radar weights and where the person’s mass actually is. A radar that over-weights low-level movement and under-weights the position of the torso will read a squatting person as a collapsed one, because the hands are moving and the head is not.</p>

<p>This mode is harder to remove than the first one, because the person really is there. Entry and exit tracking does not help — the person never left. What helps is judging posture from the whole target rather than from a single region: height, centroid, and the ratio of movement at different heights together, rather than any one of them alone.</p>

<h2 id="missed-events-when-there-is-no-descent">Missed Events: When There Is No Descent</h2>

<p>The third failure mode is the one nobody wants to talk about, because it is the one that matters most.</p>

<p>A fall detector’s most reliable trigger is a rapid descent: a tall target collapses into a wide, low one within about a second. That transition is distinctive, and it is what most detection chains are built around.</p>

<p>Not every fall produces it.</p>

<p>A person sitting on a toilet who slowly slides sideways and comes to rest on the floor has not descended in the radar’s sense. Their height changed, but gradually, and without the rapid motion the detector is looking for. The same applies to a slow slump against a wall, or a controlled lowering after dizziness.</p>

<p>The result is a missed event in exactly the scenario where the person is least able to get up.</p>

<p>This is a genuine limitation of the approach, not a tuning problem. A detector that requires a rapid descent will miss slow descents. A detector that does not require one will report every sitting-down and lying-down motion as a fall. There is no setting that gives both.</p>

<h2 id="why-a-fall-is-not-an-acceptance-criterion">Why “a Fall” Is Not an Acceptance Criterion</h2>

<p>Above the three failure modes sits a problem that is easier to state than to solve: nobody agrees on what counts as a fall.</p>

<p>Consider the questions a real deployment has to answer:</p>

<ul>
  <li>Lying flat on the floor is clearly a fall. Is lying prone, face down, also a fall?</li>
  <li>Is a person sitting on the floor against a wall a fall, or a rest?</li>
  <li>Is a slow slide from a seated position a fall, or a collapse?</li>
  <li>Is a person who is down and then gets up unaided a reportable event?</li>
</ul>

<p>Every one of these is a real scenario, and every one is answered differently by different vendors, different products, and different care providers. The word “fall” in a specification covers all of them and none of them.</p>

<p>The practical consequence is that two products with the same quoted capability can behave completely differently on site, and a buyer cannot tell which from the specification. It also means that a requirement written as “detects falls” cannot be verified on delivery, because there is no shared definition of the thing being verified.</p>

<p>This is why scenario-based acceptance matters more in this category than in any other sensing category. “Detects a person lying flat on the floor within 10 seconds in a 2 m × 3 m bathroom with the door closed” is testable. “Fall detection” is not.</p>

<h2 id="how-to-evaluate-a-fall-radar">How to Evaluate a Fall Radar</h2>

<p>Five checks that separate a product with real deployment experience from one with a specification sheet.</p>

<ol>
  <li><strong>Ask for a test in an empty room with interference.</strong> A running extractor fan, a hanging cloth, a dripping tap, and a toilet flush, with nobody present. If the radar alarms, the first failure mode is unaddressed.</li>
  <li><strong>Ask for a test of normal low activity.</strong> Squatting, mopping, sitting and swinging a leg. These are the second failure mode, and they are easy to demonstrate.</li>
  <li><strong>Ask specifically about slow descents.</strong> Not “does it detect falls” — ask whether it reports a person who slowly slides from a seated position to the floor. This is the question most vendors will not answer directly.</li>
  <li><strong>Ask what environment the quoted false alarm rate was measured in.</strong> A rate measured in an empty room with no interference is not a rate. Ask for the room, the installation height, and the interference sources present.</li>
  <li><strong>Write the acceptance criteria as scenarios, not capabilities.</strong> List the postures, the room, the timing, and the interference sources you expect. A product that passes a scenario list can be verified on delivery; a product that passes a capability list cannot.</li>
</ol>

<p>The fifth point is the one that changes outcomes. It moves the conversation from what the product claims to what the product does in your room.</p>

<h2 id="what-is-still-open">What Is Still Open</h2>

<p>Three things in this category do not have clean answers, and it is worth being explicit about them.</p>

<ul>
  <li><strong>Slow descents remain the hardest case.</strong> Any detector that requires a rapid descent will miss them, and relaxing that requirement raises the false alarm rate. The trade-off is inherent.</li>
  <li><strong>The boundary between a fall and a rest is genuinely ambiguous.</strong> Sitting on the floor, lying on a sofa, and sliding against a wall are all real behaviours, and no sensing approach classifies them perfectly.</li>
  <li><strong>There is no industry-standard definition of a fall.</strong> Until acceptance criteria are written as scenarios rather than capabilities, two products with the same specification will continue to behave differently on site.</li>
</ul>

<p>None of these are solved by a better algorithm alone. They are solved by matching the detection logic to the room, by writing acceptance criteria that can actually be tested, and by being explicit about which cases a given product is and is not specified for.</p>

<h2 id="summary">Summary</h2>

<p>Fall detection has three failure modes, and they are different problems with different causes. Empty-room alarms come from interference that resembles a low, stationary person. Misread postures come from weighting low-level movement over the position of the torso. Missed events come from requiring a rapid descent that a slow collapse does not produce.</p>

<p>Above all three sits the definition problem: “a fall” is not a precisely defined event, so a specification that says “detects falls” cannot be verified.</p>

<p>Evaluate a fall radar by asking for the empty-room test, the normal-activity test, and the slow-descent test, and by writing your acceptance criteria as scenarios rather than capabilities. The products that survive those four questions are the ones that have been deployed rather than only specified.</p>]]></content><author><name></name></author><category term="fundamentals" /><category term="fall detection" /><category term="false alarm" /><category term="missed detection" /><category term="acceptance criteria" /><category term="mmwave radar" /><summary type="html"><![CDATA[]]></summary></entry></feed>