House Pulse · v3 · Floor-plan Strip

The bookshelf knows someone's in the stairwell.

The bedroom strip's 300 addressable LEDs wrap the shelf frame and map the apartment. Rooms, presence, and countdowns each hold their own place on the perimeter — and the right-hand edge fills as a returning guest's phone climbs back into Wi-Fi range.

RENDERER ON 12 SEGMENTS 300 LEDS SHIPPED TO MAIN #31 IDENTITY CONSOLE #40 ROLLBACK ONE TOGGLE
Simulation · press play

Watch a guest come home

This runs the actual signal maths the system uses — the percentage below is computed live in the page by the same formula Home Assistant evaluates. Eight beats, from an empty flat to a guest settled on the sofa. Step it manually if you'd rather read than watch.

Live schematic of the bookshelf LED perimeter The bookshelf frame with the LED strip mapped onto it: a status band along the bottom, a guest counter and arrival gauge up the right side, an eight-room floor plan across the top, and the entry and alert countdown gauge part-way down the left side. Segments change colour as the simulation advances. door STATUS TINT · seg 0 guests · seg 1 ARRIVAL · seg 2 BED lair OFFICE LIVING kit STORE hall ENTRY ENTRY / ALERT · seg 11 0 84 164 248 300·end
Radio · Speedport client
no untrusted client associated
—dBm → 0%
percent = clamp(round((rssi + 90) × 1.8), 0, 100) = 0
Lifted from the Speedport's own devices.js so Pulse reports the identical number the router's Connected-devices page shows.
Pulse state
sensor.house_pulse_status quiet
network_company off
unknown_clients 0
arriving_signal 0 %
timer (entry / alert) idle
22:14Quiet
Loading…
What this is — and what it isn't. This is not radar and it does not detect strangers. It works because a returning guest's phone already knows the home Wi-Fi and re-associates the moment it's in range — from the stairwell, the lift, the landing. The router reports that client's RSSI, and because the phone carries no house_pulse_known label, Pulse counts it as company and tracks its signal climbing. A person who has never been here is invisible to it. The trick isn't detection; it's reading a signal the router was already publishing.
Base — dim amber, breathing
Every room's resting state. The apartment is quiet.
Presence — violet glow
Office or bedroom presence, storage motion, or living-room media playing.
Countdown — copper fill
Entry timer (15 min) draining on the door-side gauge.
Alert — red pulse
Whole top span goes red; the gauge drains fast (~45 s).
Guests — violet pixels
One LED per untrusted Wi-Fi client at the right base, cap 8.
Blip — brief flash
Door/window opens amber; front-door knock flashes copper at the entry corner.
Zone by zone

What each part of the frame is saying

ZoneSegmentsReadsHow it looks
Bottom band seg 0 · 0–84 The old whole-strip status, kept as a familiar anchor. quiet company entry alert
Top span seg 3–10 · 164–248 The rooms, in walk order. Entry at the door corner, bedroom above the arrival gauge. Amber breathe base · presence · living glows on media · storage flickers like a candle · all-red on alert
Left vertical seg 11 · 248–300 The entry / alert countdown. Door side. Copper bar draining over 15 min; red & fast over ~45 s on alert. Fills from the mid-air end.
Right vertical seg 2 · 92–164 Best signal % among untrusted clients — someone inbound. A violet bar that rises with the signal.
Right base seg 1 · 84–92 Untrusted devices on the network right now. One violet pixel per unknown client, up to 8.
Shipped since the last version of this page

Five changes, two of them real bugs

The floor-plan layer merged to main as #31. What followed was mostly the system telling me where it was wrong — and one case where it had been silently wrong for a full night.

#36WLED P3
A walk-in greeting
New WELCOME preset — a narrow purple Chase that runs one ~8-second lap around the shelf when bedroom presence trips. Gated behind both the ambient and floor-plan toggles, so it can never fire when Pulse Ambient is off.
fixcompany
Living-room parties were invisible
Pulse only watched office presence, storage motion and untrusted Wi-Fi — there is no mmWave sensor in the living room. A full evening with the TV and music on still read as quiet. Now binary_sensor.living_room_media_active joins the elsewhere group. The signals counter was also over-counting: sustained door-open was inflating it without being a real status driver.
featseg 6
…and the living room now lights up for it
Wired that same signal into the top span, so the living slice glows violet while media plays — not just on the state edge. Deliberately added to the reconciler as well as the trigger, so a Home Assistant restart mid-song still paints the right picture.
fixtrust
The guest who counted as furniture
Adam's iPhone and iPad carried the house_pulse_known trust label. Network company therefore stayed off all night while a guest was on the LAN — a silent false negative with no error anywhere. Fixed by tightening the rule: household gets owner_* and the trust label; frequent guests get guest_<name> and never the trust label.
#40console
An identity console, and a way to test without walking
A new admin view maps Speedport Wi-Fi client trackers to people, with live RSSI, a claim queue for unlabelled radios, and 24-hour per-person signal history. Alongside it: force-status buttons that drive the strip to any state on demand — the walk-test no longer requires waiting for a real event.
The name collision worth knowing about. Not everything with "Adam" in it is Adam. device_tracker.wiimmini_4222 is an Adam Audio monitor — a speaker brand, permanent house gear, and correctly trusted. The person's phones must stay untrusted for the guest path to work at all. Two things sharing a name, needing opposite labels: exactly the kind of distinction that has to be written down before it bites again.
Under it

How it renders — and why it doesn't drift

Two layers with one seam. The semantic layer that decides status, timers and presence is untouched by any of this. A new render layer only paints — and it never remembers what it drew, so there is no stale state to get stuck in.

Semantic layer · unchanged

house_pulse_status, the entry and alert timers, presence and motion sensors, arriving-signal and unknown-client counts. These already existed and still drive everything.

Render layer · additive

A rollback flag, three WLED presets, a reconciler and a handful of automations. Everything routes through script.pulse_strip_render_all, which repaints every segment from current state each time it's called.

The bug I caught before you saw it: applying the segment preset makes Home Assistant re-discover the per-segment entities, and the service call returns before that finishes. The first render would have painted onto entities that weren't ready yet and silently done nothing — no error, just a dark strip. Fixed by waiting for the segments to actually wake, then verifying all 12 painted on the first try.
What to expect

Living with it

It only speaks in the bedroom

Rendering happens while ambient listening is on. Elsewhere in the flat, the strip has nothing to say and stays out of it.

It greets you

Presence trips a single purple lap around the shelf, then the map takes over.

It bows out cleanly

Leave the bedroom and it collapses to one segment and restores whatever the strip was before. No residue.

It fails safe

Pull power and the controller boots dark. A Home Assistant restart mid-render reconciles itself back to the right picture.

Rollback is one toggle

Flip Pulse Strip Floorplan off and the next listen shows the classic single-colour tint — exactly like before.

Gauges self-heal

A missed write to a gauge corrects itself on the next tick or the next reconcile. No drift.

Still open

What genuinely needs your eyes

The render path, the reconciler, the gauge maths and the race fix are verified from here, and the force-status console now covers every colour state from the sofa. What's left is the part software can't check: whether the map matches the actual flat.

Forceable from the debug console
Every status colour. Quiet, company, entry and alert on demand, with the gauges driven to match. Clears itself back to live after 10 minutes.
Testing outside the bedroom. Turn on debug force-render and the strip paints even when ambient listening is off.
Needs feet on the floor
Rooms land in the right spots. Walk the top span left to right: entry, then living and office, then bedroom at the far right. Office should glow where office actually is.
The entry gauge drains the right way. The copper bar on the door side should empty from the mid-air end. If it runs the wrong way, that's a one-line flip of the seg-11 rev flag.
Blips and flickers. Open a door or window for a brief amber flash on its room; trip storage motion for the candle flicker.
The arrival bar, for real. Have someone walk in from the lift and watch the right edge climb ahead of the knock.
Reference

The pieces, by name

Render layer

  • input_boolean.pulse_strip_floorplan
  • script.pulse_strip_render_all
  • script.pulse_strip_blip
  • script.wled_bookshelf_welcome
  • automation.pulse_strip_room_signals

Identity & debug

  • sensor.house_pulse_claim_queue
  • sensor.house_pulse_identity_gaps
  • sensor.house_pulse_wifi_*
  • script.house_pulse_debug_force_status
  • auto-clears after 10m

WLED · 192.168.2.190

  • light.wled_gledopto
  • P1 PULSE_OFF (boot)
  • P2 PULSE_MAP (12 seg)
  • P3 WELCOME (chase)
Map authority is pulse-strip-map.json, not the design spec — the spec predates calibration and describes 11 segments. The real strip has a bottom run, so the map is 12. Regenerate from the map.