Commit graph

5 commits

Author SHA1 Message Date
915fc0039c Add weather compensation tiers for occupied aircon defaults
Warm/hot/heatwave tiers (ascending peak_above_c thresholds) override the
global ac_occupied template when today's forecast peak clears one, picked
once at the occupied-state transition so a guest's later manual adjustment
is never stomped. New lib/weather.js fetches the peak via Met Office
DataHub (if configured in settings) or Open-Meteo (no key needed) as a
fallback, TTL-cached with a stale-fallback window on fetch failure.
Zone-level per-field overrides still apply on top of a picked tier.

Thresholds/templates live in hvac_defaults.ac_occupied_tiers (existing
JSONB config blob, no migration) and are editable on the Settings page's
new Weather Compensation table. Hotel lat/lon and the optional Met Office
API key live centrally in the settings app (hotel_location/met_office
integrations), not hvac-local, for reuse by other apps later.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 11:01:41 +00:00
48ffebc08d Widen booking fetch window, resolve governing booking per-night, add turnover icons/nights to dashboard
Backend:
- fetchBookings() window widened from today-only to yesterday..+7 days, so a
  departing booking (arrived any number of nights ago) and upcoming bookings are
  both in view — the previous today-only fetch couldn't see a departing guest's
  arrival date at all.
- New resolveGoverningBooking(): replaces the single-booking-per-site pick with a
  two-tier resolution — (1) any non-cancelled booking whose stay covers today,
  preferring one not yet marked 'departed' (so a departing guest keeps governing
  blue->purple right up until checkout is confirmed, even with a same-day arrival
  also active); (2) otherwise the soonest upcoming booking, purely for colour
  ('booked' ahead of its own prep window). Also computes booking_kind
  (arrival/departure/stayover), current/total night count, and a has_next_booking
  turnover hint (for departure days with another booking already lined up).
- determineRoomState() no longer forces 'vacant' for a future-dated arrival — that
  case is now handled by resolveGoverningBooking() deciding whether a booking is
  relevant to today at all; once picked as governing it always resolves to at
  least 'booked'.
- zone_state table: new booking_kind/current_night/total_nights/has_next_booking
  columns, persisted every poll alongside room_state and exposed via GET /api/status.

Frontend:
- ZoneCard: room name is now followed by a takeoff (departure) / landing (arrival)
  / bed (stayover) icon plus a current/total nights figure, sourced from the new
  status fields. A departure additionally shows a landing icon when has_next_booking,
  hinting at a same-day turnover before the room's actually marked departed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 10:21:16 +00:00
d10e4884b8 Add global occupied/vacant default templates with per-room overrides
Settings gains a 'Default Templates' section: arrival-prep/departure-prep offsets,
a default aircon template (on/off, mode, setpoint, fan speed x occupied/vacant), and
default TRV setpoints. Every room can individually override any of these fields via
per-field 'Override' toggles in its Schedule modal, falling back to the global
default when not overridden.

Backend:
- zones table: occupied_temp/vacant_temp/heating_offset_min/cooling_offset_min are
  now nullable (NULL = inherit default); existing values preserved as explicit
  per-room overrides, so no room's behaviour changes on deploy. 8 new nullable
  ac_occupied_*/ac_vacant_* override columns.
- New 'hvac_defaults' config key (generic config store) holds the global template.
- scheduler.js: resolves each field as zone-override ?? global-default, and now
  also drives AC state automatically on occupancy transitions (previously AC was
  100% manual) via the same command path the manual control panel uses.
- lib/ac-control.js: factored the mhi_mqtt/mhi_modbus command logic out of
  routes/override.js so the scheduler and the manual control route share one path.
- zones.js PATCH: explicit-null-clears-override semantics for the 12 overridable
  fields (distinct from omitting the key, which leaves the value unchanged).

Frontend:
- Settings.tsx: new Default Templates section matching the requested layout.
- ZoneDetailModal.tsx: per-field Override checkboxes for offsets, AC
  occupied/vacant template, and TRV occupied/vacant setpoints.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 09:48:28 +00:00
0929285651 Redesign dashboard zone card with live temps, AC status, and per-radiator state
Adds actual room-temperature capture for TRVs over MQTT and a background
Modbus poller for AC mode/fan/lock/room-temp, so the dashboard tile can show
real setpoint-vs-actual readings, an AC status block, and up to 3 radiator
icons per zone instead of just the setpoint.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-27 20:25:50 +00:00
276c04f8c6 Scaffold Phase 1 hvac app — NewBook-driven room TRV heating scheduler
Ports the state machine, retry/backoff, and guest-override detection from
the retired homeassistant-newbook-heating-component, without depending on
Home Assistant. Backend (Fastify/pg) + frontend (React/Vite/TS) following
standard stack conventions; LXC 128 (127 was already taken by utilities).

MHI/Midea/Daikin/boiler drivers and the shared MQTT broker (LXC 104) are
later phases/infra, not included here.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 18:00:42 +00:00