Files
gree-controller/docs/FLOW.md
T
2026-09-01 22:20:10 +02:00

4.6 KiB

Visual Flow architecture

Flow is an authoring/orchestration layer. It does not replace the thermostat, schedule, group or device engines.

Compilation

  • weekday + time_range -> zone_thermostat with schedule-compatible settings compiles to a native Schedule.
  • Richer DAGs compile to native Automation rows with trigger_kind = "flow".
  • Generated rows keep flow_id and flow_node_id and are read-only in the legacy editors.
  • The Flow source graph plus all of its generated schedule/automation rows are replaced in one SQLite transaction.
  • Flow updates require expected_revision; stale editor tabs receive HTTP 409.

Existing control domains remain authoritative

  • zone_thermostat writes the existing persistent Zone intent and wakes the normal thermostat cycle.
  • group_action calls the existing control_group path, including custom group targets.
  • device_action uses the existing DeviceCommand / automatic-device path.
  • Thermostat hysteresis, compressor protection, schedule hand-back, manual/local ownership and Temporary Quick Thermostat keep their existing priority.
  • GREE fan/quiet/sleep and dry/fan HVAC modes are suppressed on thermostat-assigned devices when they would fight the regulator. Device-only features such as light/turbo/swing/air/xfan/health remain available through the normal command path.

Concurrency invariants

Structural Flow writes use the global order:

configuration -> automation -> schedule -> thermostat-cycle

Thermostat/device actions then use:

automation -> schedule -> thermostat-cycle -> zone -> device

Group actions use the existing group order:

automation -> house -> thermostat-cycle -> group -> zone(s) -> device

The control loop runs thermostat arbitration and automation arbitration sequentially. Automation execution reloads the row after acquiring the automation lock and skips it when updated_at changed. Same-cycle due automations deterministically claim target devices so two rules cannot issue conflicting commands to the same unit in one pass. Polling and physical commands share per-zone/per-device locks.

Holding the automation lock across the physical action is deliberate: Flow cannot be deleted/recompiled while an already-selected action is in flight. Do not shorten this ownership window without adding an explicit execution-generation/token mechanism.

External sensor values can naturally change between condition sampling and action execution. This is normal sampled-control semantics, not a persistent-state race; safety/ownership is rechecked at the action boundary.

Home Assistant safety

ha_state, ha_numeric, ha_attribute and ha_available fail closed. Connection failures, missing attributes and non-numeric numeric states evaluate to false and appear as an error object in dry-run traces. This prevents NOT / neq branches from becoming true merely because Home Assistant is unavailable.

Diagnostics

The Flow editor exposes:

  • dry-run at an arbitrary date/time,
  • per-source overrides,
  • per-node trace,
  • would_execute and ownership/block reason,
  • Flow-scoped execution/dry-run logs,
  • import/export of versioned .flow.json source graphs.

Dry-run never mutates thermostats, devices, groups, schedules or automations.

Blocks

Condition/source blocks currently include weekday, time range, date range, application Night mode, outdoor/device/zone temperature, house mode, device state, thermostat/zone state, group state, Home Assistant state/numeric/attribute/availability and a diagnostic constant. Logic blocks are AND, OR and NOT.

Actions include thermostat zone, GREE device and climate group. Direct GREE actions expose power, HVAC mode, target temperature, fan speed, vertical/horizontal swing, quiet, turbo, light, air, xfan, health and sleep.

Built-in templates

The editor ships editable templates for:

  • workday comfort,
  • weather-aware comfort,
  • smart AND/OR demand,
  • device resilience,
  • night group control,
  • Home Assistant window guard,
  • presence comfort/eco,
  • frost protection,
  • nested OR + NOT guard,
  • application Night-mode quiet profile.

Good next stateful blocks

The next useful additions should be implemented with persisted runtime state rather than pretending they are stateless predicates:

  • for X minutes / stable-for,
  • debounce,
  • hysteresis block,
  • rising/falling edge,
  • cooldown/rate limit independent of the action,
  • delay/timer,
  • retry/backoff,
  • variables/counters,
  • reusable subflows/macros,
  • explicit priority/mutex groups for actions,
  • trace replay from historical sensor samples.

These need durable state and restart semantics before they should be exposed in the editor.