mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-28 19:01:34 +00:00
Волна 3 эпика #674. ARCHITECTURE.md 2330 → 653 строки: система координат прототипа 1489×1053, разделы Hidden Isometric Stage 2/4 (текущее — ISOMETRIC.md, история — ADR 122/570), хроники «Additions v1.28–v1.41» и «Audit follow-ups» сняты; подсистемы — короткое описание со ссылкой на канонический документ. Устаревшее исправлено по коду: дерево Layout (store.py, frontend_registration, весь список модулей), хранилища (config, layout, virtual_lights, trails), ленивые локали de и fr, таблица WS API (31 + 3 команды, #256-проекция, space/delete, files/cleanup без keep, контент через /api/houseplan/content), DevItem без несуществующих полей, отказ help/feedback по support_api. Всё ещё верное и не записанное в другом месте перенесено в канонические документы: DEVICE-PRESENTATION (заметки реализации, Action authority, черновик диалога), RADAR (карта реализации), VACUUM (владение кодом), CANVAS (icon_size, --hp-cell-visual-scale, барьер записи координат), FILTERING (#44, каталог), DECOR-EDITOR §7 (инварианты бэкенда ассетов), WALL-THICKNESS (§1 идентичность и нулевые стены, §2 кэши, §4 hover/туннели/острова, §6 удаление комнаты, §9 failed-core, §11 завершение цепочки и комната по грани), ISOMETRIC (isoPlaneMatrix, iso-overlays, створки, служебные атрибуты), LIGHT (Glow над заливкой #55, формула и screen-смешение), CONFIG-COMPATIBILITY (манифест схемы #33, Masonry-слоты #561, квадратный холст v1.48, устаревшие URL контента, layout/set #356), SCOPE (таблица владельцев при сборке файлов), WARM-REMOUNT §5 (холодная загрузка и визуальная непрерывность), UX-MODES (порядок стартового пространства), PDF-EXPORT (граница реализации), FURNITURE (adopt, BOOT_MAX_MS). Раздел TESTING «Backend quality gates (#42)» и строка DEVELOPMENT о bundle-freshness — из того же разбора, в предыдущем коммите. Issue: #680 User-Visible: no Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
144 lines
8.2 KiB
Markdown
144 lines
8.2 KiB
Markdown
# Presence radars
|
|
|
|
Stage 1 of [#485](https://github.com/Matysh/houseplan-card/issues/485)
|
|
projects current Home Assistant radar observations onto one House Plan room.
|
|
It is intentionally a visualization and setup feature: House Plan does not
|
|
identify people, record tracks, configure hardware zones or create derived Home
|
|
Assistant entities at this stage.
|
|
|
|
## What appears on the plan
|
|
|
|
- Cartesian or polar coordinates become small live target dots.
|
|
- A distance-only source becomes an arc or full range circle. It is not
|
|
presented as an exact person position.
|
|
- Known zone states may be presented as occupied/clear state; unknown geometry
|
|
is never invented.
|
|
- Presence-only sources report presence and health but do not fabricate a dot.
|
|
- Coordinates, arcs and known zone geometry are clipped to the selected room's
|
|
real polygon, including concave rooms. A missing room is an error and never
|
|
falls back to another room or to its bounding box.
|
|
|
|
The layer is pointer-transparent. Small verified jumps may transition smoothly;
|
|
large jumps, source gaps, slot changes, calibration changes and non-convex room
|
|
contours never animate through an unverified path. Reduced-motion mode disables
|
|
target motion. The diagnostic trail is limited to eight seconds and exists only
|
|
inside the current browser session.
|
|
|
|
## Supported input profiles
|
|
|
|
| Profile | Required source data | Result |
|
|
|---|---|---|
|
|
| ESPHome LD2450 | One to three exact X/Y sensor pairs, millimetres | Target dots; `x=0,y=0` together means an absent target, while one zero axis is a valid coordinate |
|
|
| Cartesian | One to eight exact X/Y pairs, explicit unit, axis order and directions | Target dots |
|
|
| Polar | One to eight exact distance/angle pairs, explicit length/angle units and angle convention | Target dots |
|
|
| Distance only | One or two exact distances, explicit unit and known/entered direction/FOV | Honest range arcs |
|
|
| Zone states | Exact occupancy/count entities | Read-only states; outlines only when geometry is actually known |
|
|
| Presence only | Exact binary presence entity | Presence and health without a position |
|
|
|
|
An optional global availability entity and per-target/range presence gates may
|
|
make absence explicit. Numeric zero remains data unless the selected adapter
|
|
defines an exact pair rule such as LD2450's `(0,0)`. Empty strings,
|
|
`unknown`, `unavailable`, NaN and infinity are never converted to zero.
|
|
|
|
## Configure a radar
|
|
|
|
1. Add or open the real device marker in the **Device editor**.
|
|
2. For a recognized radar, open **Presence on the plan**. For custom hardware,
|
|
use **Additional actions → This is a presence radar**.
|
|
3. Enable the radar, choose the room and verify every exact source. For generic
|
|
profiles, specify units and coordinate conventions explicitly.
|
|
4. Use **Check live data** before calibration. Correct unavailable, stale,
|
|
partial or contradictory values in Home Assistant or the source mapping.
|
|
5. Enter the physical mounting point, heading, range and field of view manually,
|
|
or use **Configure on plan**. The latter records the mount and a point straight
|
|
ahead. Coordinate profiles then measure two separated reference positions.
|
|
6. Optionally check a third position. Its error is diagnostic and does not alter
|
|
the solved transform.
|
|
7. Apply the setup, then use the ordinary marker **Save**. Until that final Save,
|
|
Cancel, Escape, page hide or a config revision conflict discards the draft.
|
|
|
|
The physical mount is not the decorative icon position. Moving the icon later
|
|
does not move or recalibrate the radar. Changing the radar source/profile,
|
|
coordinate convention, room or physical installation invalidates an accepted
|
|
calibration; display-only switches do not.
|
|
|
|
Use a desktop browser for calibration. Touch View/kiosk remains fully supported,
|
|
but precise editor setup on touch is best effort.
|
|
|
|
## Health meanings
|
|
|
|
| Status | Meaning |
|
|
|---|---|
|
|
| Current data received | Complete, fresh source data was normalized |
|
|
| No targets detected | An explicit absence was reported |
|
|
| Some coordinate data is out of date | One or more paired values exceeded the freshness/skew contract |
|
|
| Presence reported; current position unavailable | Presence is true but no honest current coordinate is available |
|
|
| Sensor data unavailable | A required source or availability gate is unavailable |
|
|
| Installation needs setup | Sources exist but physical mapping is incomplete |
|
|
| Sources report conflicting values | Fresh sources contradict each other, for example a zero target count with current target coordinates |
|
|
|
|
Coordinate/range reports have short server leases and disappear when they are
|
|
not refreshed. Reopening a tab, reconnecting or changing a source/calibration
|
|
starts a new ordering epoch; an old frame cannot resurrect a target.
|
|
|
|
## Privacy, permissions and storage
|
|
|
|
House Plan subscribes only to the exact configured entity IDs. Read delivery is
|
|
filtered through the current Home Assistant user's entity permissions; setup
|
|
requires House Plan write permission. Payload sizes, subscriptions and update
|
|
rates are bounded.
|
|
|
|
Saved configuration contains source entity IDs, selected room, physical mount,
|
|
orientation, units and calibration — not observations. Raw source values,
|
|
measurement samples, live targets, trails and health frames are runtime memory
|
|
only. They do not enter plan export/import, support diagnostics, uploaded files,
|
|
browser storage or Home Assistant history through House Plan. Home Assistant and
|
|
the source integration may independently keep their normal entity history.
|
|
|
|
Virtualized plan imports intentionally drop hardware-specific radar bindings.
|
|
Unknown future radar versions remain preserved but inert until supported.
|
|
|
|
## Implementation map
|
|
|
|
- Persistence: `marker.radar` is saved only by the ordinary revisioned config
|
|
transaction. `radar_validation.py` validates only a changed known version;
|
|
untouched future versions stay inert. `settings.radar.show_live` is a display
|
|
preference and never authorizes discovery, recording or hardware writes.
|
|
- Backend: one `RadarCoordinator` (`radar.py`) per integration entry owns exact
|
|
HA source listeners, report-time freshness, independent-pair skew,
|
|
source/calibration epochs, projection, real-room clipping and bounded public
|
|
frames; it reconciles on config revision and closes all listeners/timers on
|
|
unload. The explicit profile/source-role inventory (`occupancy_entity`,
|
|
`count_entity`, `availability_entity`; Cartesian `x_entity`/`y_entity`; polar
|
|
`distance_entity`/`angle_entity`; range/zone `entity_id`; slot/range
|
|
`presence_entity`) is the single authority for live listeners, setup listeners
|
|
and per-entity read ACLs; unknown future fields never become sources by naming
|
|
convention. Only the backend interprets raw HA states.
|
|
- Eager View: `radar-model.ts` (frame validation/ordering/leasing),
|
|
`radar-live.ts` (one active-space subscription and lifecycle),
|
|
`radar-render.ts` (pointer-transparent SVG below ordinary device markers).
|
|
Range segments arrive already clipped; an empty list is authoritative and never
|
|
falls back to an unclipped arc. Transition eligibility is a server fact: only a
|
|
current same-slot step of at most 100 cm in a convex room may animate.
|
|
- Lazy editor: `radar-editor.ts` (recognition/draft round-trip),
|
|
`editors/radar-section.ts` (marker dialog), `radar-setup.ts` (session-only
|
|
on-plan wizard). A two-reference result changes only the open draft; the
|
|
ordinary marker Save is the only write.
|
|
|
|
## Troubleshooting
|
|
|
|
- **The section is absent:** only positively recognized hardware or an already
|
|
saved radar gets the main section. Use the manual action for a custom real
|
|
device. Virtual markers cannot own a radar binding.
|
|
- **The source list is incomplete:** ensure the entity is enabled and readable
|
|
by the current Home Assistant user. Manual mapping can use exact entities from
|
|
different devices.
|
|
- **Targets are missing:** inspect health first. Verify units, axis signs, room,
|
|
mount and heading. For LD2450, do not treat `x=0` or `y=0` alone as absence.
|
|
- **A target stops at the room boundary:** this is the intended safety clip.
|
|
- **Calibration is noisy:** repeat with one stationary person, separated
|
|
references and no second reported target.
|
|
|
|
The normative engineering contract is
|
|
[`docs/specs/485-radar-presence-stage1.md`](specs/485-radar-presence-stage1.md).
|