Registration-table mode missed roof-AP clients (same SSID, bridged);
switched the mikrotik integration to force_dhcp + arp_ping so both APs
are covered. wes_phone_wifi verified end-to-end (tracker home → Pi
sensor on → bridged home on). Lindsey's tracker pending her next
association.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Chateau API bound to the Pi only, read-only homeassistant user,
mikrotik integration live. Phone trackers get enabled+renamed on first
association (documented in HANDOFF).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Water heater = occupancy truth. New Pi package campsite_presence.yaml:
rv_occupied + phones_on_campsite_wifi template sensors (wifi one stays
unavailable until the MikroTik integration lands — load-bearing for the
dead-man trigger), MQTT bridging home, a local notify-only dead-man
(heater on, no phones on WiFi 3h), and disabled pre-staged lot-light
automations for the future shed Shelly.
dsi_fault_alert.yaml gains the Octavia MQTT relay (campsite/octavia/say)
so home HA — which has no file access — can speak through the verified
webhook path.
Home-side (UI-managed, not in repo): quick failsafe (both out of the
enlarged 150m campsite zone 25 min → fans/lights off + summary ping) and
heater failsafe (2h → heater off with bridge round-trip confirmation).
Both verified live; fan states snapshot-restored after the test.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New Pi package (repo copy canbus/ha/dsi_fault_alert.yaml): when the CAN
node's DSI-lockout binary sensor holds 'on' for 10s, fire the server-
alerts Discord webhook (@here, appropriately rude), with a cleared
message when it recovers. Webhook URL lives in the Pi's HA secrets.yaml
(!secret discord_server_alerts_webhook), not the repo.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The campsite HAOS Pi now runs the ESPHome CAN node natively ("OneControl
CAN", *.onecontrol_can_*); the BLE integration is fully torn out (config
entry, custom_components on the Pi, stale MQTT registry orphans) and the
camper dashboard rewritten — water-pump tile dropped on purpose (pump is
panel-only), awning + fault sensors added.
New canbus/ha/mqtt_bridge_onecontrol.yaml (deployed to the Pi as
packages/mqtt_bridge.yaml) bridges the CAN entities to the home broker
via MQTT Discovery, same pattern as the gazebo bridge. Kept the old
unique_ids so home entity ids and recorder history carried over; added
an availability topic and explicit command-topic allowlists (3 switches
+ awning — a future debug entity must not become remotely controllable
for free). Round-trip verified from home HA.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Per updated policy:
- Water heater (node 95): new switch entity + on/off state read-back.
- Awning (node 75): new cover entity (open=op01 / close=op02 / stop=op00), with
current_operation published from the page-3 motion byte (C2/C3/C0). First
actuation must be attended; single-shot commands can't run the motor away.
- Water pump (node 61): added to command_guard denylist (winterizing-only,
panel/app only) alongside slides/jacks. Guard re-tested 8/8 (host g++).
Switch/cover comments + HANDOFF safety notes and remaining-work updated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per policy, the firmware must never command a slide or jack. command_guard.h adds
command_blocked(node, type): refuses any motor-class (0x21) node except the
awning (0x75), with an explicit slide/jack denylist (6A/7F/9C) that holds even
before a node's page-2 identity is observed.
Enforced in two independent places — the command-entry script (send_load_command)
and the actual transmit point (on_frame, right before TX) — so loosening one
can't open the other. Adding a slide/jack switch entity cannot actuate it. Node
device class is learned from page-2 broadcasts (g_node_type). Predicate
unit-tested 9/9 (host g++). Switch comments + HANDOFF safety notes updated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>