10 KiB
GREE Controller project specification
Product goal
Build an autonomous local GREE HVAC controller running primarily as a Rust service in a dedicated Linux/LXC environment. Home Assistant is optional: it can provide external sensor data and can consume controller devices through a thin custom integration, but it must not contain the core GREE protocol or heating logic.
Architecture
Home Assistant / Web UI / REST clients
|
REST + WebSocket
|
GREE Controller (Rust)
+--------------------------------+
| Device/state manager |
| GREE protocol UDP/AES |
| Zone/heating engine |
| Scheduler |
| Automation engine |
| SQLite |
| Mobile-first web UI |
+--------------------------------+
|
UDP/7000
|
GREE AC
Independence requirements
- GREE control must work when Home Assistant is stopped.
- Local schedules and automations must continue without HA.
- HA sensor failures must never remove basic access to the AC.
- Device state is persisted by the controller and can be restored to clients after reconnect/restart.
GREE protocol layer
The protocol implementation is isolated from application logic and covers:
- discovery,
- packet encoding/decoding,
- AES-128-ECB support,
- AES-128-GCM envelope support,
- bind/key acquisition,
- status polling,
- command transport,
- reconnect/offline handling.
The rest of the application works with generic device state and commands rather than raw protocol packets.
Device model
Each device stores:
- stable controller ID,
- MAC/CID,
- name,
- IP/port,
- protocol version,
- model/firmware when available,
- encryption key when bound,
- enabled/simulated flags,
- power and HVAC mode,
- target/current/outdoor temperature,
- fan, swing, quiet, turbo, light,
- online/last-seen/error state.
Smart thermostat, zones and schedules
The primary user model is a fast thermostat, not raw device automation. A global House mode selects the season (cool, heat, off). Zones follow it by default and can optionally override Heat/Cool. Global Off is authoritative and powers controlled units down.
During normal heating/cooling the controller minimizes unit power cycling. It keeps the indoor unit powered and uses setpoint modulation:
- when the zone requires conditioning, use the active target (optionally assisted slightly by outdoor weather),
- when the zone is satisfied, move the device setpoint to the non-demand side of the room target so the inverter/compressor can stop naturally,
- use hysteresis and a minimum adjustment interval to avoid command chatter,
- optionally adjust fan speed based on room error and outdoor extremes.
Each zone has separate seasonal profile temperatures:
- Cooling: Comfort / Sleep / Away,
- Heating: Comfort / Sleep / Away.
The zone can use the GREE internal sensor, its own Home Assistant room sensor, or a weighted combination. External room sensors are configured per zone; loss/discrepancy falls back safely to the GREE sensor.
Weekly schedules reference profiles instead of duplicating temperatures. Ready-made Family, Child room, Bedroom, Workday and Always-comfort templates create ordinary schedule rows that remain fully editable. A manual Sleep now, Comfort, Away or custom-temperature override ends automatically at the next schedule boundary. Whole-house preset actions apply the same temporary policy to every zone.
Automations remain available for advanced exceptions. Daily comfort should be implemented with zones/profiles/schedules so direct-device automation commands do not compete with the thermostat engine.
Outdoor temperature assist
A configured Home Assistant outdoor-temperature entity is optional auxiliary context. It never replaces the room-control temperature. Under strong heat/cold the engine may slightly bias the active AC target and increase Smart Fan airflow. If HA is unavailable, the smart thermostat continues without outdoor assistance.
Scheduler and automations
Schedules are weekly time windows and may cross midnight. Schedules can select Comfort/Sleep/Away or a custom setpoint. Automations support time or temperature triggers and device commands with cooldown protection; they are intended for exceptions rather than the normal daily thermostat cycle.
The automation engine runs in Rust and does not require Home Assistant YAML automation logic.
API
The controller exposes REST for configuration/commands and WebSocket for live state updates. The HA integration and web UI use the same controller API.
Home Assistant direction 1: external sensor input
The Rust application can read a specifically configured HA entity using a Long-Lived Access Token. This input is optional and is not a prerequisite for GREE control.
Home Assistant direction 2: native climate entities
A custom integration creates HA climate entities and translates HA service calls to controller API commands. It does not communicate with GREE directly.
For migrations from the default GREE integration, a mapping file can request an existing entity ID such as climate.klima_salon. The previous integration must release that ID before takeover.
Web UI
Primary use is from a phone. Requirements:
- responsive mobile-first layout,
- touch-friendly controls,
- live state updates,
- device, zone, schedule, automation, history and diagnostics screens,
- JSON-based language packs from
lang/*.json, with English as the required default/fallback and Polish included, - automatic language discovery at build time, so a new valid
<code>.jsonfile adds a language without JavaScript changes, - language stored in the
gree_controller_languagecookie, - system/light/dark appearance modes,
- appearance stored in a cookie,
- flat visual design without decorative shadows,
- no letter-logo badge next to the application name.
Storage
SQLite stores configuration, state, readings and events. PostgreSQL or other external database services are not required for the single-node deployment target.
Deployment
Primary target:
LXC / Debian or Ubuntu
/opt/gree-controller/gree-controller
/etc/gree-controller.env
/var/lib/gree-controller/gree-controller.db
systemd: gree-controller.service
A development script prepares dependencies/build/runtime configuration, and a separate installer creates the systemd deployment.
Security
- optional administrator Bearer token for the controller Web/API,
- separately generated, revocable Home Assistant client tokens stored only as SHA-256 hashes,
- Home Assistant client tokens are restricted to device read/control endpoints,
- secrets kept outside source control,
- no direct public Internet exposure,
- TLS delegated to a trusted reverse proxy/VPN when required,
- local device keys and HA token protected in environment/database files,
- invalid/self-signed HA HTTPS certificates are rejected by default; bypass is an explicit trusted-LAN opt-in.
Per-zone room sensors
A zone represents one room and normally maps one GREE indoor unit to one optional external room-temperature sensor. External sensors are not global. For example, Living Room can use sensor.living_room_temperature while Bedroom independently uses sensor.bedroom_temperature.
The zone controller supports device, combined, and home_assistant temperature strategies. Combined mode uses a configurable external-sensor weight (40% by default), validates the difference between sensors, and falls back to the GREE sensor when the external source is missing or outside the configured discrepancy limit. The local GREE measurement therefore remains available even when Home Assistant is offline.
Operational packaging conventions
- All operator-facing shell/Python utilities live under
scripts/. scripts/install.shperforms the first systemd/LXC installation.scripts/update.shperforms an in-place update with a stopped SQLite backup, health check and automatic rollback.scripts/service.shprovides common systemd operations.- Cargo's
build.rsstays at the package root because Cargo requires that location. - Every SQLite statement and schema definition is centralized in
src/queries.rs; database/domain code must not embed SQL strings elsewhere.
Web UI design system (v0.4.4)
The embedded UI uses the classic GREE Controller visual language: large rounded surfaces, circular thermostat controls, comfortable spacing, compact desktop navigation and mobile bottom navigation. Light, Dark and System themes use neutral surfaces with a restrained green accent.
The UI ships as a normal static web/styles.css file embedded into the Rust binary. There is no frontend package manager, CDN, or CSS build pipeline.
Rich zone history
Zone history stores GREE temperature, optional Home Assistant room temperature, calculated control temperature, profile target, actual device setpoint, outdoor temperature assist, power, mode, fan speed, demand, active preset and control source. The UI can compare all zones on common temperature/target charts or inspect one zone in detail.
History information architecture (v0.4.4)
History is not a single long page. It is split into URL-addressable views: Overview, Zones, GREE devices, HA sensors and Custom chart. Device history exists independently from zones, HA sensors have their own history stream, and zone history adds the thermostat/control context. A compatibility fallback maps existing GREE device readings into a zone timeline when the richer zone table is still empty.
The custom chart composer can mix GREE indoor/outdoor/target values, zone GREE/HA/control/target/device-setpoint/outdoor values, and HA temperature entities. Saved definitions persist in browser storage and a chart definition can be serialized into the /history/custom?chart=... URL for direct sharing/bookmarking.
Quick thermostat temperature nudges are optimistic in the browser and stored separately from the selected Comfort/Sleep/Away/Auto preset. Changing +/- therefore does not silently leave Auto mode.