Codex R15 flagged two P1 correctness bugs in AutomationEngine:
- Conditions were never evaluated — a trigger→condition→action rule ran its
actions unconditionally. Now every stored condition must match current
entity state (AND) before actions run; a false condition does NOT touch the
cooldown clock, so the rule stays armed for its next legitimate trigger.
- Cooldown was read-check-then-save, so concurrent queue workers on a burst of
state changes could all pass the check and each fire. Now claimed with a
single conditional UPDATE — exactly one worker wins the race (H5).
+3 tests (condition true/false, cooldown-not-armed-on-failed-condition).
AutomationTest 9 green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New "Steuerung" page for tablet control:
- Large touch tiles for every light/switch — tap toggles (through
DeviceCommandService), highlighted when on, live via Echo.
- Drag-to-reorder via SortableJS (handle per tile); order persisted to
entities.panel_sort.
- Lights get a colour/brightness modal → Light.Set (brightness + rgb) on the
Shelly, with preset swatches + a custom colour picker. Driver contract gains
setLight(); command service audits it (H1).
Nav check 11/11 tabs clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Assigning a Shelly now issues a real broker credential so the physical device can
connect (onboarding was incomplete before):
- MqttCredentialProvisioner writes a mosquitto-compatible PBKDF2-SHA512 ($7$)
password line (in PHP) for username = the device's topic prefix, and touches a
reload trigger. A small wrapper in the mosquitto container (docker/mosquitto/
config/entrypoint.sh) SIGHUPs mosquitto so it re-reads the passwd live — no
restart. Verified: a provisioned device authenticates and publishes to its own
prefix (bound by the pattern %u ACL).
- The credential is shown once on the device page after assignment (enter it into
the Shelly). passwd is app-owned + world-readable so the web request can write it.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- UnifiClient service (art-of-wifi/unifi-api-client) talks to the local UDM with a
read-only account (self-signed cert, verify_ssl off). Verified live: logged in
and read 32 active clients.
- presence:poll command (scheduled every minute, withoutOverlapping): "home"
immediately on association, "away" only after an 8-min debounce so iPhone WLAN
sleep can't cause false-aways. Broadcasts PresenceChanged on the presence channel.
- Persons page: "Person hinzufügen" modal picks the representing device straight
from the live UniFi client list (falls back to manual MAC entry if UniFi is down);
the sweep then tracks that person's presence. mac + last_seen_home_at on persons.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Real bidirectional MQTT so devices are live, not mock (handoff §13.3):
- Mosquitto 2 broker (auth + per-client ACLs for laravel/shelly/sidecar from day
one); passwd generated by docker/mosquitto/gen-passwd.sh (gitignored).
- mqtt-listener daemon: subscribes `+/status/#`, parse + dispatch only (H2),
exponential reconnect backoff, graceful SIGTERM. php-mqtt/laravel-client.
- Ingest path (H4): IngestShellyMessage resolves device by mqtt_prefix, upserts
device_states, refreshes last_seen, broadcasts DeviceStateChanged
(ShouldBroadcastNow) on the private `home` channel.
- Control path (H1): DeviceDriver contract + ShellyMqttDriver (command topic +
Shelly.Reboot RPC) behind DeviceCommandService, which audits every command to
the new `commands` table. Device detail toggles + restart route through it;
flash reflects the real result.
- Live UI: dashboard + device pages listen via Echo (#[On('echo-private:home,
.DeviceStateChanged')]) and re-render instantly.
- Vendor specifics isolated in Support/Mqtt + Support/Drivers (H3).
Verified end-to-end in a real browser: publishing an MQTT status turned a light
"An" on the dashboard in 3.0s with no reload, 0 console errors. R12 30/30;
15 feature tests green (incl. ingest + command audit). README/bootstrap document
the broker passwd step.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Document that production must set APP_ENV=production + APP_DEBUG=false (else
exceptions leak and the demo household seeds); note it in .env.example too.
- HomeStatus::warnings now iterates devices → entities using the already-loaded
device, instead of $entity->device, removing an N+1 on dashboard render.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
HomeStatus aggregated from Room, so a device with room_id = null (a supported
state, e.g. after picking "no room") vanished from dashboard totals, KPIs and
warnings. Aggregate from all devices instead; the dashboard groups them by room
with a trailing "Ohne Raum" group so nothing disappears. Added a feature test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Warnings no longer clutter the dashboard: a compact "Warnungen (n)" button in
the topbar opens a themed wire-elements/modal (R5) listing all messages. Dark
modal wrapper overridden; HomeStatus service shared by dashboard + modal.
- Device detail page (/devices/{uuid}, UUID route key): edit name, room and
active state; view info + live capabilities; Neustart (with confirm modal) and
"Update prüfen" as mock commands (Phase 3 routes them through the real driver).
Devices index (/devices) added; "Geräte" nav activated; dashboard device rows
and index link to the detail. Generic Confirm modal + x-detail component.
- Mock devices no longer rot: online is now "active and (no last_seen or seen
<10min)", so the demo stays healthy; the one offline device keeps a stale
timestamp. Full DE/EN i18n for devices + modal copy.
Verified: R12 30/30 in headless Chromium (0 console errors, 0 failed requests);
10 feature tests green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reworks the dashboard into a home-control view per user feedback (it is not a
server dashboard):
- Dashboard now shows home data — rooms with live device state (lights on/off,
power draw, window/door contacts, battery %), a home summary (devices online,
lights on, open contacts, low batteries), and a Warnings panel that only lists
what needs attention (offline device, open window, low battery, degraded host
service). No server internals on the dashboard.
- Server/service health (DB, Redis, Reverb, Horizon) + version info moved to a
dedicated "Host & Dienste" page (new nav item under System); dashboard surfaces
a host problem only as a warning that links there.
- New domain slice (handoff §3, mock-first §13.2): rooms/devices/entities/
device_states migrations + models (UUID route keys, R11) + DemoHomeSeeder with
Shelly-like devices incl. deliberate faults. Extracted SystemHealth service.
- Sidebar decluttered further; new x-entity-state component; full DE/EN i18n.
- Fixed R15 findings: .env.example now ships matching non-empty dev defaults for
DB_PASSWORD and Reverb keys so a fresh `cp .env.example .env` boots cleanly.
Verified: R12 21/21 in headless Chromium (0 console errors, 0 failed requests,
breakpoints 375/768/1280); 10 feature tests green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>