SENSOR FINDINGS - Presence Radar - 2026-10-16
==============================================
Read-only measurement. Nothing was edited, restarted, armed or flashed.
Measured 13:10 to 13:53 local. The app was restarted twice by someone else
(13:39 and 13:53), so baselines were relearned at 13:39.

How much data each conclusion rests on
--------------------------------------
- RAW  : my own 2-second polling of every node, 13:41 to 13:52 = 11 min, ~330 readings per node.
- HIST : history.db copy, 13:10 to 13:52 = 42 min (2711 rows). Mixes pre- and post-relearn.
- LONG : history.db since 12:27 (when the multi-node setup began) = about 85 min.
- Radars/PIR/PAX event counts use today's events (09:47 on) unless stated.
Caveat: the owner moved nodes today. I could not see where people were.
Radars A and B were quiet for all of 13:40-13:52, so I treat that stretch as an empty room.

1. Wi-Fi CSI links (raw: 11 min polling)
----------------------------------------
"Score" = how much the Wi-Fi signal wobbles. "pps" = packets per second the node hears.
p50/p90/p99 = the middle value / the value 90% / 99% of readings stay under.

| Node           | RSSI med (min..max) | pps med (min..max) | pps <20 | s p50 | s p90 | s p99 | s max | p99 / p50 |
|----------------|---------------------|--------------------|---------|-------|-------|-------|-------|-----------|
| c3-000001      | -45 (-46..-44)      | 34 (6..174)        | 8%      | 10.15 | 11.61 | 13.87 | 16.0  | 1.4x      |
| c6-000007      | -71 (-71..-70)      | 104 (3..246)       | <1%     | 0.82  | 1.88  | 10.11 | 12.2  | 12x       |
| c6-000006      | -68 (-69..-67)      | 122 (2..274)       | <1%     | 0.12  | 1.19  | 6.46  | 8.1   | 54x       |
| c6-000008      | -80 (-81..-80)      | 17 (10..34)        | 67%     | 7.0   | 8.1   | 14.4  | 14.4  | n/a       |
| esp32-000003   | -52 (-53..-51)      | 54 (16..340)       | <1%     | 0.91  | 1.22  | 1.96  | 2.4   | 2.2x      |

c6-000008: only 6 of 324 polls answered, so its numbers rest on 6 readings.
"Tight" quiet distribution = p99 / p50 small. Only c3 and the CYD are tight.

Behaviour in the app (HIST/LONG)
--------------------------------
| Node          | Learned base -> threshold (now)  | Time in "motion" | Episodes (13:10-13:52) | Median / max episode | Fired alone* | App-side "lost" or restart events today |
|---------------|----------------------------------|------------------|------------------------|----------------------|--------------|------------------------------------------|
| c3-000001     | 6.8 -> 27.4 (was 23..37)         | 0% (0 of 87 min) | 0                      | -                    | 0            | 2 lost today (10:13..) plus many earlier |
| c6-000007     | 0.05 -> 0.4 (the minimum floor)  | 49% of 82 min    | 11 (13:10-13:42)       | 43 s / 285 s         | 8 of 11      | 4 reboots 13:26, 13:32, 13:34, 13:51; 11 "lost" |
| c6-000006     | 0.07 -> 0.4 (the minimum floor)  | 97% of 81 min    | 3 (one lasted 26 min)  | 142 s / 1594 s       | 2 of 3       | 3 lost, 1 restart 12:34 |
| c6-000008     | none learned (offline)           | 0%               | 0                      | -                    | -            | 11 "lost", reachable ~2 min in 85 |
| esp32-000003  | 0.77 -> 2.9                      | 6% of 70 min     | 5                      | 26 s / 114 s         | 4 of 5       | 4 lost (12:43-12:47), none since |
*"Alone" = mmWave A, mmWave B and PIR all quiet for the whole episode.
After the 13:39 relearn (HIST 13:40-13:51, 11 min) both C6 links sat in "motion" 100% of the time
at the 0.4 floor, in one stuck episode of 658 s, while A, B and PIR reported nothing.
Raw scores above the 0.4 floor: c6-000006 49% of readings, c6-000007 57%, esp32 100% (its own limit is 2.9, so no alarm),
c3 99% (its limit is 27, so no alarm).

2. Zigbee sensors and PAX (events since 09:47; HIST window 13:10-13:52)
----------------------------------------------------------------------
| Device        | Online | Last report       | Events per hour on/off pairs (09h..13h) | Alone (radar-tune, today) | Link / battery |
|---------------|--------|-------------------|-----------------------------------------|---------------------------|----------------|
| mmWave A 5.8G | yes, not stale | 0-3 s ago | 1,4,3,5,4  | 0 of 19 fires   | LQI 156 of 255 |
| mmWave B 24G  | yes, not stale | 0-1 s ago | 1,2,4,8,6  | 0 of 23 fires   | LQI 196 of 255 |
| PIR SNZB-03   | yes    | no report since 11:16 | 0,1,3,0,0 on-events (4 total, all 10:56-11:16) | 0 of 4 | battery 100% |
| PAX counter   | yes, updating | every 10-30 s | 19,129,67,60,59,106,106 changes per hour (07h..13h) | n/a | USB link ok |

- A and B run together. In 42 min A was on 3.9 min, B 2.4 min. They fired together at 13:13 and 13:28
  (the same moments as each other), so they are probably seeing real people. Runs last 25-130 s.
- A fired without B for about 1.7 min, B without A about 0.2 min (HIST). Neither fired alone in the fusion sense.
- PIR saw none of the 3 radar-confirmed visits in 13:10-13:52. It last fired 11:16, 2.5 hours ago.
- PAX flips between 2 and 3 every 10-30 s ("Wi-Fi 0 / Wi-Fi 1"; BLE stays at 2).
  One phone-like device appears and vanishes. Count was 2 for 75% and 3 for 24% of the last hour.
  The alert limit is 3, so this chatter can touch it.
- Zigbee radio: online on channel 20 with no drops today; A/B report timing warning
  "occupancy UNSUP_CLUSTER_COMMAND, polling as backup" is normal for these sensors.

3. Cross-check: who fires with whom
-----------------------------------
Minutes in the same state, HIST 13:10-13:52 (42 min):
| Combination                                   | Minutes |
|-----------------------------------------------|---------|
| Both C6 links "motion", nothing else          | 22.8    |
| Only c6-000006 "motion", nothing else         | 10.9    |
| c6-000006 + CYD, nothing else                 | 2.8     |
| Any radar (A/B) on, with C6 links             | about 4.5 |
| Everything quiet                              | 0.8     |

- The two C6 links moved together: 100% of the shorter link's motion overlaps the other.
  In the raw 11-min test, 24 of the 32 loudest 10-second buckets of c6-000006 were also the loudest of c6-000007.
  Chance would give about 3. They also share the minutes 13:42:50, 13:47:20 and 13:52:30.
  This is shared interference or a shared cause (same power/location), not two people moving, because
  the radars saw nothing in most of those minutes.
- c3 shared 9-11 of 32 buckets with the C6 links (weak link, a bit above chance; the quiet-room gap is tiny).
- The CYD shared only 5-6 of 32 with anyone. It is independent.
- Sensors that agree on real people: A and B (13:13, 13:28). C6 links rise at those times too, but they also rise at all other times.

4. Verdicts
-----------
| Device         | Verdict  | Key numbers | Why |
|----------------|----------|-------------|-----|
| esp32-000003 (CYD) | GOOD | -52 dBm; pps 54; p99/p50 2.2x; 6% motion; no drops since 12:47 | In the target range, steady, independent of the others. 4 of its 5 episodes had no radar backing, so check by walking past it. |
| mmWave B (24 GHz)  | GOOD | LQI 196; 0 of 23 alone; agrees with A | Healthy and consistent. |
| mmWave A (5.8 GHz) | GOOD | LQI 156 (weaker); 0 of 19 alone; agrees with B | Healthy. LQI is lower, so keep clear of metal and keep it near the coordinator if you can. |
| c3-000001      | MARGINAL | -45 dBm; pps 34 (8% below 20, min 6); p99/p50 1.4x; 0% motion in 87 min | Stable and quiet. Signal is stronger than the -50..-65 target (not yet the -40 "too close" line). pps is barely above 30 even though the signal is strong, so the limit is the node, not the radio. Never fired in 87 min while the others fired often, so it may be under-sensitive. Test with a walk. |
| PIR SNZB-03    | MARGINAL | 0 events since 11:16; 0 of 3 radar visits seen; battery 100% | Online and healthy, but it does not see the area where the radars see people. It is a door sensor by design. Re-aim it at the walking area or accept that it only covers the doorway. |
| PAX counter    | MARGINAL | 106 changes per hour; 2<->3 flicker every 10-30 s | Working, but one device flickers on and off and hovers at the alert limit. A hint only. |
| c6-000006      | BAD      | -68 dBm; pps 122; p50 0.12 vs p99 6.46 (54x); "motion" 97% of 81 min; floor threshold 0.4 | Signal and pps are fine (the rule of thumb says good), but the quiet score is wildly unstable, so it is permanently in motion. It rises together with c6-000007, so there is shared interference or shared cause. |
| c6-000007      | BAD      | -71 dBm; pps 104; 4 reboots in 30 min; p99/p50 12x; "motion" 49% | Node resets itself repeatedly (13:26, 13:32, 13:34, 13:51), each time losing its baseline. Weakest of the working C6 signals. Rule of thumb does not explain it: signal and pps look fine, so suspect power supply, USB cable or heat, plus the same noise as c6-000006. |
| c6-000008      | BAD      | -80 dBm; pps 17 (67% below 20); 6 of 324 polls answered | Too far from the router (weaker than -75, drops packets). Effectively offline. |

Where the data contradicts the rules of thumb
- C6 links meet the signal and pps rules but are the worst performers. Stability of the score matters more than RSSI here.
- c3 is stronger than target yet has the lowest pps. A strong signal did not give more packets.
- The 0.4 minimum threshold is far below what the C6 scores do in a quiet room (p90 1.2-1.9, p99 6-10). That is a tuning issue for the other agent, not a placement issue, but placement is what drives the noise.

5. Three physical changes, in order
-----------------------------------
1. Move c6-000008 much closer to the router (aim for -55..-65 dBm), or take it out.
2. Separate the two C6 links (different spots, different power source, away from the router's cable and any USB hub or charger)
   and fix c6-000007's power (short, good USB cable, own charger). Then relearn and re-measure.
3. Re-aim the PIR at the walking area (it saw 0 of 3 radar-confirmed visits), and move c3 a little further from the router (about -55) if it is to be the quiet reference.

6. Commands used (rerun them)
-----------------------------
S=/tmp/claude-1000/-home-amnesia/ed3e8853-af02-42ed-9ff7-bdef72949e54/scratchpad
# live status (on the Pi)
ssh radar@192.168.1.154 'curl -s http://127.0.0.1:8470/status.json'
# node check from the PC (replace .172 with .189 .157 .245 .197)
curl -s -m 4 http://192.168.1.172/
# 2-second node poll for 11 min (stdlib only, GET only)
python3 $S/sample_nodes.py 660 $S/samples.csv
python3 -I $S/analyze_samples.py $S/samples.csv
# history copy, including the -wal file (needed or the copy is stale), opened read-only
mkdir -p $S/db; scp -q radar@192.168.1.154:'/home/radar/zigbee/history.db*' $S/db/
python3 -I $S/analyze_links.py $S/db/history.db 13:10 13:42   # args: DB START END (today, HH:MM)
python3 -I $S/analyze_links.py $S/db/history.db 12:50 13:42
# radar-tune and the log (on the Pi)
ssh radar@192.168.1.154 '~/.local/bin/radar-tune'
ssh radar@192.168.1.154 'grep -E "restarted|not reachable|lost" ~/zigbee/presence-radar.log'
Scripts: sample_nodes.py, analyze_samples.py, analyze_links.py in the scratchpad dir above.

Limits
- Only 11 min of raw sampling per node and one 42-min history window. The room contents are unknown.
- The "up" counter of c6-000007 read 449 s right after its 13:52 reset, the same number it read at 13:41. I could not explain this.
- The app restarted at 13:39 and 13:53, so learned baselines are minutes old.
