Commit Graph

16 Commits (8aa3257fa23e668f54c9fa76c805b3674fd181cf)

Author SHA1 Message Date
HomeOS Bootstrap d10172ac26 feat(automations): trigger→condition→action engine with cooldown + dry-run
- AutomationEngine: state_change + time triggers, cooldown debounce, dry-run
  logs instead of switching (H5), actions switch via DeviceCommandService
  (source=automation, audited H1) or notify via log.
- EvaluateAutomations: queued listener on DeviceStateChanged (keeps ingest
  fast, H2). automations:tick command scheduled every minute for time rules.
- CreateAutomation modal (wire-elements) wired to Automations index; DE/EN
  keys (R16). dry_run column migration + model cast.
- AutomationTest: 6 cases (trigger match, mismatch, cooldown, dry-run,
  time tick, disabled). Full suite 23 green; 11/11 tabs clean (R12).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 01:11:02 +02:00
HomeOS Bootstrap 124e667a0a Tablet control panel: touch tiles, drag-reorder, light colour modal
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>
2026-07-18 00:58:24 +02:00
HomeOS Bootstrap a4edbbf801 Fix R15: provision a per-device MQTT credential when assigning a device
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>
2026-07-18 00:50:53 +02:00
HomeOS Bootstrap af951d9f91 Charts: Chart.js MQTT + host traffic on the Host page
- metrics table + Metric model; metrics:sample command (scheduled every minute,
  pruned to 24h) records MQTT throughput (a Redis counter the ingest jobs bump)
  and host CPU load + memory% from /proc.
- Chart.js line-chart Alpine island (themed from CSS tokens, dual axis) on the
  Host page shows MQTT/min, CPU load and memory %. wire:ignore so the 10s health
  poll doesn't re-init it. Nav check 10/10 clean (0 console errors).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 00:40:32 +02:00
HomeOS Bootstrap b85d2f60fe Phase 5: UniFi presence — poll, person↔client mapping
- 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>
2026-07-18 00:31:32 +02:00
HomeOS Bootstrap f50a665735 Phase 4: network discovery — sidecar, ingest, "Neue Geräte" + assign
- Python discovery sidecar (zeroconf mDNS over host network) publishes findings
  to homeos/discovery/<source>/<id> as the sidecar user. Compose service with
  network_mode: host + NET_RAW. Verified live: it found real devices on the LAN
  (a printer and Shellys) via mDNS.
- Listener also subscribes homeos/discovery/#; IngestDiscoveryMessage upserts
  discovery_findings (preserving assigned/ignored) and broadcasts DeviceDiscovered
  on the private discovery channel.
- "Neue Geräte" page lists findings live with Assign (modal → creates a Device
  and links the finding) and Ignore/Restore. Per-device broker credentials are
  provisioned at onboarding (noted in the assign hint).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 00:25:17 +02:00
HomeOS Bootstrap 5cde2786aa All sidebar tabs are real pages (zero console errors)
Persons & Anwesenheit, Netzwerk & Discovery, Automationen, Einstellungen and
Zugang & Face-ID are now working Livewire pages (were dead "In Kürze" buttons).
Adds persons / discovery_findings / automations tables + models; authorizes the
presence + discovery broadcast channels; silences MQTT debug-log spam. Nav check
10/10 tabs clean (200, 0 console errors, 0 failed requests).

Deeper behaviour (presence polling, discovery sidecar, automation engine) lands
in the respective phase; the pages + schema are in place and render live.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 00:16:16 +02:00
HomeOS Bootstrap cc81e309b3 Fenster & Türen page: contact/motion sensor overview
Activates the windows nav tab. Summary banner (how many open) + per-room sensor
list with open/closed state and battery, live via Echo. Nav check 5/5 clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 00:07:44 +02:00
HomeOS Bootstrap f4d8f27db4 Rooms pages: index (per-room status) + show (devices with live control)
Activates the Räume nav tab. Index lists rooms with online/lights/open counts;
show lists a room's devices with entity chips and switch/light toggles (through
DeviceCommandService), live via Echo. Zero console errors (nav check: 4/4 clean).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 00:05:30 +02:00
HomeOS Bootstrap aceb140aac Fix mobile sidebar readability; rework device list for scale
- Sidebar drawer is now opaque (.sidebar-tint solid), so on mobile the bright
  content no longer bleeds through and it stays readable.
- Devices index reworked for ~50 devices: live search (name/model/vendor),
  room + online/offline filters (URL-persisted), grouped by room with counts —
  scannable instead of one long list.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 23:30:15 +02:00
HomeOS Bootstrap ea9e35883b Phase 3: MQTT ingest — Mosquitto bus, Shelly driver, live device state
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>
2026-07-17 22:51:14 +02:00
HomeOS Bootstrap 1520b95f8f Fix R15: include room-less devices in home status
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>
2026-07-17 21:58:35 +02:00
HomeOS Bootstrap f00a1ac069 Warnings → modal, device detail page, stable mock online state
- 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>
2026-07-17 21:52:57 +02:00
HomeOS Bootstrap fcb6daa6ab Home dashboard + Host tab: device state & warnings, server status split out
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>
2026-07-17 21:20:38 +02:00
HomeOS Bootstrap d4f667437c Dashboard: live service health + fault surfacing; declutter sidebar
Addresses user feedback on Phase 1:
- Dashboard reoriented from static stack facts to LIVE operational status.
  New health banner surfaces faults prominently (green when all online;
  amber/red with a pluralized problem count when a service is down).
  Service tiles probe DB, Redis, Reverb (socket) and Horizon in real time
  with latency; versions moved to a small, de-emphasized "System" block.
  wire:poll.10s + a refresh button keep it live. Verified: stopping Reverb
  flips the banner to "Ein Dienst mit Störung" and the Echtzeit tile to
  Offline/nicht erreichbar (screenshotted), healthy state restores clean.
- Sidebar decluttered: removed the wrapping "In Kürze" count badges;
  coming-soon items are now dimmed (still show lock icons where gated).

R12 re-verified in headless Chromium: 15/15 assertions, 0 console errors,
0 failed requests, breakpoints 375/768/1280. 7 feature tests still green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 21:06:20 +02:00
HomeOS Bootstrap beac04ec51 Phase 1: bootstrap — Docker stack, Laravel 13, design system, auth
Foundation for HomeOS (handoff §13.1). Verified in a real browser (R12):
HTTP 200, zero console errors, zero failed requests, breakpoints 1280/768/375,
no leaked template/lang literals. Feature test suite green (7 passing).

Stack (locked, handoff §12): Laravel 13, Livewire v3 (class-based, no Volt),
Tailwind v4 (@theme, no config), PostgreSQL 17 + TimescaleDB, Redis + Horizon,
Reverb (private channels, proxied same-origin via nginx), Vite. Everything runs
in containers (R8); one app image shared by app/horizon/scheduler/reverb.

- docker: app (php-fpm 8.4 + nginx + supervisor), db (timescale pg17), redis,
  reverb, horizon, scheduler; env-driven ports; HOST_UID/GID from id nexxo
- design system ported verbatim from design-mockup.html into @theme (§8);
  self-hosted Plus Jakarta Sans + IBM Plex Mono woff2 (R14)
- Blade component kit: icon, panel, kpi, status-dot/pill, badge, toggle,
  room-card, device-chip, sidebar, topbar; app + guest layouts (mobile drawer)
- auth: class-based Livewire Login (throttled) + Dashboard; English routes,
  German UI; full DE/EN localization (R16)
- rules.md + CLAUDE.md; admin user seeded from gitignored .env

Deferred by design: php-mqtt/laravel-client (Phase 3), mosquitto/mqtt-listener
(Phase 3), discovery sidecar (Phase 4).

R15 (Codex review) pending user `codex login`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 21:06:20 +02:00