v0.8.13
This commit is contained in:
@@ -1,609 +1,401 @@
|
||||
# GREE Controller
|
||||
|
||||
> Identifier convention: project-owned namespace identifiers use `gree_controller`. Home Assistant uses `gree_controller`, UI storage uses `gree_controller_*`, and environment variables use `GREE_CONTROLLER_*`.
|
||||
Self-hosted controller for GREE-compatible air conditioners with a local Web UI, thermostat zones, schedules, Home Assistant integration, history, notifications and a documented HTTP/WebSocket API.
|
||||
|
||||
Standalone local GREE air-conditioner controller written in Rust. It runs on a regular Linux host or an LXC container and provides a mobile-first web interface without depending on the vendor cloud.
|
||||
**Current release: 0.8.13**
|
||||
|
||||
Current version: **0.8.10**.
|
||||
> [Full API reference](docs/API.md) — authentication, every endpoint, request bodies, response models, WebSocket events and examples.
|
||||
|
||||
## Highlights
|
||||
## What it does
|
||||
|
||||
- local GREE discovery over UDP/7000,
|
||||
- V1 AES-128-ECB and V2 AES-128-GCM discovery/bind/status/command transport,
|
||||
- automatic ECB/GCM detection from discovery responses and bind fallback,
|
||||
- power, HVAC mode, target temperature, fan, vertical/horizontal swing, quiet, turbo and display light,
|
||||
- capability discovery and control for optional GREE X-FAN, Air, Health and native Sleep features,
|
||||
- SQLite state/history/event storage,
|
||||
- automatic SQLite history compaction plus optional InfluxDB 1.x/2.x long-term archive,
|
||||
- smart thermostat zones with global house Heat/Cool/Off mode and per-zone overrides,
|
||||
- setpoint modulation that keeps indoor units powered during normal operation instead of repeatedly cycling power,
|
||||
- Comfort/Sleep/Away profiles, temporary overrides and one-tap **Sleep**,
|
||||
- named climate groups (for example Upstairs/Downstairs) with independent power, Heat/Cool/house-follow mode and profile control, including automation targets,
|
||||
- editable weekly schedules plus Family/Child room/Bedroom/Workday/Always-comfort templates,
|
||||
- temperature/time automations for advanced exceptions,
|
||||
- per-zone optional Home Assistant room-temperature sensors with GREE fallback,
|
||||
- optional Home Assistant outdoor-temperature assist for setpoint/fan decisions,
|
||||
- opt-in support for self-signed/invalid HTTPS certificates on the outbound HA sensor connection,
|
||||
- combined zone temperature using configurable GREE/external sensor weighting and discrepancy protection,
|
||||
- REST API and WebSocket updates,
|
||||
- responsive PWA optimized for phones,
|
||||
- dashboard automation-plan blocks showing current zone decisions and upcoming schedule changes,
|
||||
- Node-RED-style live automation flow board with sensor → thermostat → decision → unit command nodes, group/unit filtering, standalone-tab view and browser full-screen mode,
|
||||
- configurable night mode with quiet hours, maximum fan speed and optional GREE Quiet/native Sleep requests,
|
||||
- configurable event-log retention and presentation-only Home Assistant sensor aliases used by history charts/selectors,
|
||||
- settings import/export and an optional live debug overlay with API logs and decrypted GREE frame payloads,
|
||||
- JSON-based UI localization loaded from embedded `lang/*.json` language packs,
|
||||
- light, dark and system appearance modes stored in a browser cookie,
|
||||
- optional Bearer-token authentication,
|
||||
- simulator mode for development without physical hardware,
|
||||
- Debian/Ubuntu LXC systemd installer,
|
||||
- Home Assistant custom integration that proxies device `climate` commands, exposes full zone thermostat entities and publishes every climate group as a separate HA device with power, mode, profile and control-plan entities,
|
||||
- migration mapping generator for retaining existing HA entity IDs such as `climate.klima_salon`.
|
||||
- Discovers and binds GREE Wi-Fi units on the LAN, including mixed protocol generations.
|
||||
- Provides direct technical device control and a separate thermostat layer built around zones.
|
||||
- Supports cooling/heating profiles: Comfort, Sleep, Away and custom quick targets.
|
||||
- Coordinates house, group and per-zone control without silently fighting physical/manual overrides.
|
||||
- Supports schedules, automations, night mode and temporary Quick Thermostat sessions.
|
||||
- Can use GREE sensors, Home Assistant room sensors or a weighted combination.
|
||||
- Stores recent history in SQLite and can archive/query long-term history in InfluxDB 1.x or 2.x.
|
||||
- Exposes native Home Assistant entities through the bundled custom integration.
|
||||
- Includes PWA-capable responsive UI, Polish/English localization and live diagnostics.
|
||||
- Can run in Simulation mode without physical air conditioners. A large warning is shown whenever simulation is enabled.
|
||||
|
||||
See [`BUILD_REPORT.md`](BUILD_REPORT.md) for package validation details and [`docs/LXC.md`](docs/LXC.md) for the LXC deployment/update workflow.
|
||||
## UI overview
|
||||
|
||||
## Quick start
|
||||
The interface is intentionally split by responsibility:
|
||||
|
||||
On Debian, Ubuntu or an LXC container:
|
||||
| Area | Purpose |
|
||||
| --- | --- |
|
||||
| Dashboard | Whole-house summary and Quick Thermostat controls. |
|
||||
| Devices | Discovery, binding and direct/technical GREE device control. |
|
||||
| Zones | Thermostat configuration, profiles, sensors and control ownership. |
|
||||
| Groups | Climate group membership and group power/mode/preset control. |
|
||||
| Schedules | Weekly thermostat schedules and ready-made templates. |
|
||||
| Automations | Time/temperature triggered device or group actions. |
|
||||
| History | Overview, zones, devices and HA sensors with precise chart tooltips and zoom. |
|
||||
| Simulation | Simulated units for safe testing. |
|
||||
| Night mode | Quiet/Sleep/fan limits during an overnight window. |
|
||||
| Home Assistant | Sensor connection, aliases and restricted integration tokens. |
|
||||
| Settings → Application | Simulation, notifications, metrics/logs, InfluxDB, debug and backup. |
|
||||
| Settings → GREE | Controller identity, polling/discovery, GREE commands and live GREE traffic. |
|
||||
| Events | Operational event log and diagnostics. |
|
||||
|
||||
The top bar uses the same compact language and theme controls on desktop and mobile. The live debug overlay can be filtered to **All**, **Requests** or **GREE** frames.
|
||||
|
||||
## Quick start for development
|
||||
|
||||
Requirements are installed automatically on supported Debian/Ubuntu environments unless `--no-install` is used.
|
||||
|
||||
```bash
|
||||
unzip gree-controller-v0.8.10.zip
|
||||
cd gree-controller
|
||||
chmod +x scripts/*.sh
|
||||
cp .env.example .env
|
||||
./scripts/dev.sh
|
||||
```
|
||||
|
||||
`scripts/dev.sh` installs missing build tools when possible, installs stable Rust with `rustup` when required, creates `.env`, builds the application and starts the web panel.
|
||||
|
||||
Default address:
|
||||
|
||||
```text
|
||||
http://HOST_ADDRESS:8787
|
||||
```
|
||||
|
||||
The first empty database can be seeded with **Living Room (simulator)** so the UI, history, zones and automations can be tested without an AC.
|
||||
|
||||
### Development commands
|
||||
Useful development commands:
|
||||
|
||||
```bash
|
||||
./scripts/dev.sh --check
|
||||
./scripts/dev.sh --release
|
||||
./scripts/dev.sh --reset
|
||||
./scripts/dev.sh --host 0.0.0.0 --port 8787
|
||||
./scripts/dev.sh --no-install
|
||||
./scripts/dev.sh --check # format, tests, build and HTTP smoke test
|
||||
./scripts/dev.sh --release # optimized local build
|
||||
./scripts/dev.sh --reset # recreate the local SQLite database
|
||||
./scripts/smoke.sh # API smoke test against an isolated simulated instance
|
||||
```
|
||||
|
||||
## Web interface
|
||||
The default panel is available at `http://127.0.0.1:8787` when the process is bound locally.
|
||||
|
||||
The UI is mobile-first and uses no external CDN.
|
||||
## LXC / systemd installation
|
||||
|
||||
Language selector:
|
||||
The production scripts target Debian/Ubuntu systemd hosts and LXC containers.
|
||||
|
||||
- English is the required default/fallback language,
|
||||
- Polish is included,
|
||||
- additional languages are discovered automatically from `lang/*.json` at build time.
|
||||
|
||||
The selected language is stored in the `gree_controller_language` cookie. The UI contains no hard-coded list of supported languages. To add a language, copy `lang/en.json`, translate the `translations` values, set the `meta` fields, save it as `<code>.json`, and rebuild. For example, `lang/de.json` becomes an additional language after `cargo build` / `./scripts/dev.sh`. Missing translation keys fall back to English.
|
||||
|
||||
See [`docs/LOCALIZATION.md`](docs/LOCALIZATION.md) for the language-pack format and validation rules.
|
||||
|
||||
Appearance selector:
|
||||
|
||||
- System,
|
||||
- Light,
|
||||
- Dark.
|
||||
|
||||
The selected appearance is stored in the `gree_controller_theme` cookie. The current UI keeps the classic GREE Controller interface: large rounded cards, circular thermostat controls, compact desktop navigation and mobile bottom navigation. It keeps the newer neutral dark/light palette and green accent (`#3ecf8e` in dark mode and `#24b47e` in light mode).
|
||||
|
||||
### Static offline CSS
|
||||
|
||||
The interface is plain static CSS. `web/styles.css` is committed with the project and embedded directly into the Rust binary. There is no frontend package manager, CDN, or CSS build step. Edit `web/styles.css` and `web/index.html` directly, then rebuild the Rust application.
|
||||
|
||||
|
||||
## Connecting a physical GREE device
|
||||
|
||||
1. Put the controller and AC in a network where UDP/7000 traffic is allowed.
|
||||
2. Open the web interface and select **Discover**.
|
||||
3. Start with **Auto (V1 + V2)** and 3 scan passes. The controller recognizes ECB responses and GCM responses carrying a `tag` and automatically binds discovered units.
|
||||
4. If required, repeat discovery using **V1 AES-ECB** or **V2 AES-GCM** to isolate a model family.
|
||||
5. New devices immediately open a naming step so you can enter room-friendly names such as **Salon** or **Sypialnia**. They can also be renamed later from **Devices -> Rename**. Re-discovery preserves your custom name.
|
||||
6. If LXC/VLAN broadcast does not pass, add the unit manually with IP and MAC/CID.
|
||||
|
||||
Version 0.3.7 additionally uses forgiving GREE Base64 decoding for non-canonical GCM tags seen on real Wi-Fi modules, automatically selects the directly connected local IPv4 interface for unicast GREE traffic, and refreshes the short bind window with a subnet broadcast immediately before bind. A single lost UDP response no longer marks a device offline; three consecutive communication failures are required.
|
||||
|
||||
## LXC/systemd installation and updates
|
||||
|
||||
All operator scripts are under `scripts/`. On a clean Debian/Ubuntu LXC container:
|
||||
### First installation
|
||||
|
||||
```bash
|
||||
chmod +x scripts/*.sh
|
||||
sudo ./scripts/install.sh
|
||||
```
|
||||
|
||||
The installer installs build dependencies/Rust when required, runs the Rust tests, builds a release binary, creates the `gree-controller` service account, stores runtime data in `/var/lib/gree-controller`, installs the binary under `/opt/gree-controller`, creates `/etc/gree-controller.env`, generates an administrator token and enables the systemd service. Existing `/etc/gree-controller.env` is preserved.
|
||||
Optional flags:
|
||||
|
||||
For a later release, unpack the new source archive and run:
|
||||
```bash
|
||||
sudo ./scripts/install.sh --skip-tests
|
||||
sudo ./scripts/install.sh --no-start
|
||||
```
|
||||
|
||||
Installed layout:
|
||||
|
||||
| Path | Purpose |
|
||||
| --- | --- |
|
||||
| `/opt/gree-controller/gree-controller` | Release binary. |
|
||||
| `/etc/gree-controller.env` | Environment configuration; mode `0600`. |
|
||||
| `/var/lib/gree-controller/gree-controller.db` | SQLite database. |
|
||||
| `/etc/systemd/system/gree-controller.service` | systemd unit. |
|
||||
| `/var/backups/gree-controller/` | Update backups used for rollback. |
|
||||
|
||||
### Update
|
||||
|
||||
Run from the extracted source tree of the new release:
|
||||
|
||||
```bash
|
||||
sudo ./scripts/update.sh
|
||||
```
|
||||
|
||||
The update is designed for LXC testing and production-style upgrades: compilation/tests happen before the running service is stopped; then the script backs up the installed binary, service unit, environment file and stopped SQLite database under `/var/backups/gree-controller/<timestamp>/`. After replacement it checks `/api/health`. A failed startup triggers automatic rollback to the previous binary, unit and database backup.
|
||||
The updater builds/tests first, stops the old service, backs up the binary/unit/environment/database, installs the release, checks `/api/health` and rolls back automatically if startup fails.
|
||||
|
||||
Service helpers:
|
||||
### Service helper
|
||||
|
||||
```bash
|
||||
./scripts/service.sh status
|
||||
sudo ./scripts/service.sh restart
|
||||
./scripts/service.sh logs
|
||||
./scripts/service.sh health
|
||||
./scripts/service.sh logs
|
||||
sudo ./scripts/service.sh restart
|
||||
```
|
||||
|
||||
Use `--skip-tests` with `install.sh` or `update.sh` only when you explicitly want to skip `cargo test --all-targets`. `scripts/install-lxc.sh` remains as a compatibility alias to `scripts/install.sh`.
|
||||
`./scripts/install-lxc.sh` remains as a compatibility alias to `install.sh`.
|
||||
|
||||
## Environment configuration
|
||||
## Configuration
|
||||
|
||||
| Variable | Default | Purpose |
|
||||
|---|---:|---|
|
||||
| `GREE_CONTROLLER_BIND` | `0.0.0.0:8787` | HTTP/WebSocket bind address |
|
||||
| `GREE_CONTROLLER_DATABASE` | `./data/gree-controller.db` | SQLite file |
|
||||
| `GREE_CONTROLLER_APP_TOKEN` | empty | Bearer token; empty disables API authentication |
|
||||
| `GREE_CONTROLLER_SIMULATE` | `false` | Enables simulator seeding for development/testing |
|
||||
| `GREE_CONTROLLER_AUTO_SEED` | `false` | Seeds a simulator into an empty database when simulation is enabled |
|
||||
| `GREE_CONTROLLER_POLL_INTERVAL_SECONDS` | `15` | Device polling interval |
|
||||
| `GREE_CONTROLLER_ZONE_INTERVAL_SECONDS` | `5` | Zone-control interval |
|
||||
| `GREE_CONTROLLER_DISCOVERY_TIMEOUT_MS` | `3000` | UDP discovery timeout |
|
||||
| `GREE_CONTROLLER_DISCOVERY_BROADCAST` | `255.255.255.255:7000` | Discovery broadcast target |
|
||||
| `GREE_CONTROLLER_GREE_INTERFACE` | empty | Optional Linux interface used for all GREE UDP traffic, e.g. `eth1` |
|
||||
| `GREE_CONTROLLER_ID` | `gree-controller` | Controller instance identifier used for logs/metadata; the GREE wire protocol uses the standard `cid=app` |
|
||||
| `GREE_CONTROLLER_HOUSE_MODE` | `cool` | Initial seasonal house mode: `cool`, `heat` or `off` |
|
||||
| `GREE_CONTROLLER_OUTDOOR_ASSIST_ENABLED` | `true` | Initial outdoor-temperature assist state |
|
||||
| `GREE_CONTROLLER_HISTORY_RETENTION_DAYS` | `30` | Local SQLite retention before pruning |
|
||||
| `GREE_CONTROLLER_HISTORY_COMPACTION_ENABLED` | `true` | Compact old local samples to chart-oriented resolution |
|
||||
| `GREE_CONTROLLER_SUPPRESS_DEVICE_BEEP` | `false` | Send only changed fields and request GREE buzzer suppression where supported |
|
||||
| `GREE_CONTROLLER_INFLUX_ENABLED` | inferred from URL | Enable optional long-term InfluxDB archive |
|
||||
| `GREE_CONTROLLER_INFLUX_VERSION` | `2` | `1` for InfluxDB 1.x or `2` for InfluxDB 2.x |
|
||||
| `GREE_CONTROLLER_INFLUX_URL` / `INFLUXDB_URL` | empty | InfluxDB base URL |
|
||||
| `GREE_CONTROLLER_INFLUX_THRESHOLD_DAYS` | `30` | Read history older than this age from InfluxDB |
|
||||
| `GREE_CONTROLLER_INFLUX_DATABASE` | `gree_controller` | InfluxDB 1.x database |
|
||||
| `GREE_CONTROLLER_INFLUX_USERNAME` / `GREE_CONTROLLER_INFLUX_PASSWORD` | empty | Optional InfluxDB 1.x credentials |
|
||||
| `GREE_CONTROLLER_INFLUX_ORG` / `GREE_CONTROLLER_INFLUX_BUCKET` / `GREE_CONTROLLER_INFLUX_TOKEN` | empty | InfluxDB 2.x organization, bucket and token |
|
||||
| `GREE_CONTROLLER_DEBUG_OVERLAY` | `false` | Show the live debug window on every web view |
|
||||
| `GREE_CONTROLLER_DEBUG_GREE_FRAMES` | `false` | Stream decrypted GREE request/response payloads into debug |
|
||||
| `HA_URL` | empty | Optional Home Assistant URL |
|
||||
| `HA_TOKEN` | empty | Optional Home Assistant Long-Lived Access Token |
|
||||
| `HA_ENTITY_ID` | empty | Optional default HA room-temperature sensor |
|
||||
| `HA_OUTDOOR_ENTITY_ID` | empty | Optional HA outdoor-temperature sensor |
|
||||
| `HA_ALLOW_INVALID_TLS` | `false` | Opt in to invalid/self-signed HA HTTPS certificates |
|
||||
Copy `.env.example` for the full supported example. Command-line arguments exist for the core `Config` options, while most day-to-day runtime settings are also editable in the Web UI and persisted in SQLite.
|
||||
|
||||
Settings changed from the web panel are stored in SQLite. Explicit history/debug/Influx environment variables override their persisted values at process startup. Supplying an Influx URL enables the archive unless `GREE_CONTROLLER_INFLUX_ENABLED=false` is explicitly set. `GREE_CONTROLLER_APP_TOKEN` is loaded at process startup.
|
||||
Environment values explicitly supplied for supported runtime overrides win over the persisted value after restart.
|
||||
|
||||
Web UI organization: **Settings** contains controller/application and technical storage/debug options, while **Night mode** and **Home Assistant / Sensors** are separate pages under More. Disabled zones continue reporting room temperature even though thermostat control is stopped.
|
||||
### Core variables
|
||||
|
||||
## Climate history
|
||||
| Variable | Default | Description |
|
||||
| --- | --- | --- |
|
||||
| `GREE_CONTROLLER_BIND` | `0.0.0.0:8787` | HTTP/WebSocket listen address. |
|
||||
| `GREE_CONTROLLER_DATABASE` | `./data/gree-controller.db` | SQLite database path. |
|
||||
| `GREE_CONTROLLER_APP_TOKEN` | empty | Optional administrator API/Web UI token. Empty means trusted-LAN mode. |
|
||||
| `GREE_CONTROLLER_BASE_PATH` | empty | Optional reverse-proxy prefix such as `/gree`. |
|
||||
| `GREE_CONTROLLER_ID` | `gree-controller` | GREE client/controller identifier. |
|
||||
| `GREE_CONTROLLER_SIMULATE` | `false` | Initial Simulation mode. |
|
||||
| `GREE_CONTROLLER_AUTO_SEED` | `false` | Seed simulated sample data when applicable. |
|
||||
| `GREE_CONTROLLER_POLL_INTERVAL_SECONDS` | `15` | Device polling interval. |
|
||||
| `GREE_CONTROLLER_ZONE_INTERVAL_SECONDS` | `5` | Thermostat control interval. |
|
||||
| `GREE_CONTROLLER_DISCOVERY_TIMEOUT_MS` | `3000` | Discovery timeout. |
|
||||
| `GREE_CONTROLLER_DISCOVERY_BROADCAST` | `255.255.255.255:7000` | GREE discovery target. |
|
||||
| `GREE_CONTROLLER_GREE_INTERFACE` | auto | Optional interface name or local IP used for GREE UDP traffic. |
|
||||
|
||||
History is collected independently for physical GREE devices, control zones, and configured Home Assistant temperature sensors. Device samples continue to use the long-standing `readings` table, so upgrading does not require waiting for a new zone-history table to fill. When rich `zone_readings` are not available yet, the API automatically reconstructs a compatible zone timeline from existing device readings.
|
||||
Additional environment variables cover history retention, debug, night mode, Home Assistant and InfluxDB. See [`.env.example`](.env.example).
|
||||
|
||||
The History area has linkable sub-pages:
|
||||
## Connecting physical GREE units
|
||||
|
||||
- `/history/overview` — all GREE indoor temperatures, available GREE/HA outdoor temperatures, and all zone control temperatures,
|
||||
- `/history/zones` — all zones or one detailed zone with GREE, HA room, control, target and device-setpoint series,
|
||||
- `/history/devices` — indoor temperature, available `OutEnvTem`, and target for every GREE unit,
|
||||
- `/history/sensors` — configured Home Assistant room/outdoor temperature sensors,
|
||||
- `/history/custom` — compose arbitrary series, save chart definitions in the browser and copy a URL that recreates the chart.
|
||||
1. Place the controller host on a network that can reach the air-conditioner Wi-Fi modules by UDP.
|
||||
2. Open **Devices** and start discovery.
|
||||
3. Auto protocol mode is recommended; the controller accepts both supported GREE encryption generations.
|
||||
4. Newly discovered devices are bound automatically when possible. Manual bind is also available.
|
||||
5. Create a thermostat zone for each unit you want the thermostat engine to own.
|
||||
|
||||
A zone timeline includes GREE indoor temperature, optional HA room temperature, calculated control temperature, active profile target, actual setpoint sent to the AC, available outdoor temperature, demand, power, mode and fan speed. HA sensor samples and zone samples are throttled to at least 15 seconds (or the configured device poll interval, whichever is longer). Local samples older than 24 hours are compacted to 10-minute resolution and samples older than 7 days to 30-minute resolution. When InfluxDB is configured, older queries are merged from InfluxDB with recent SQLite history. The maintenance task backfills compacted legacy samples into InfluxDB and deletes an old SQLite sample only after the archive write succeeds, so an unavailable archive does not cause local data loss.
|
||||
Discovery uses UDP broadcast, so routed/VLAN networks must explicitly permit or relay the required traffic.
|
||||
|
||||
All main UI views also use browser URLs (`/dashboard`, `/devices`, `/zones`, `/groups`, `/schedules`, `/automations`, `/simulation`, `/settings`, `/events`) so refresh, browser Back/Forward, bookmarks and direct links work normally.
|
||||
### Multi-NIC / dedicated GREE interface
|
||||
|
||||
## Per-zone room temperature sensors
|
||||
For a host with separate management and GREE networks, set for example:
|
||||
|
||||
Each control zone can pair one GREE indoor unit with its own optional room sensor from Home Assistant. This is intentionally configured per zone, so rooms do not share a global temperature source.
|
||||
|
||||
Example:
|
||||
|
||||
```text
|
||||
Living room -> GREE Living Room + sensor.living_room_temperature
|
||||
Bedroom -> GREE Bedroom + sensor.bedroom_temperature
|
||||
Office -> GREE Office + sensor.office_temperature
|
||||
```bash
|
||||
GREE_CONTROLLER_GREE_INTERFACE=eth1
|
||||
```
|
||||
|
||||
Zone temperature strategies:
|
||||
or a local address:
|
||||
|
||||
- **GREE only** — use the AC internal sensor.
|
||||
- **GREE + room sensor** — recommended; calculate a weighted control temperature from both sensors. The default room-sensor weight is 40%.
|
||||
- **Room sensor only** — use the assigned HA room sensor, with automatic fallback to GREE if HA or the entity becomes unavailable.
|
||||
```bash
|
||||
GREE_CONTROLLER_GREE_INTERFACE=192.168.50.2
|
||||
```
|
||||
|
||||
For combined control, `max_sensor_difference` protects against an obviously incorrect external measurement. If the two sensors differ by more than the configured threshold (default `3.0°C`), the zone uses the GREE temperature and logs a sensor-discrepancy event.
|
||||
The controller will use that interface for GREE UDP traffic while keeping the HTTP UI on `GREE_CONTROLLER_BIND`.
|
||||
|
||||
The zone API exposes `device_temperature`, `external_temperature`, `current_temperature` (the actual control temperature) and `control_temperature_source` for diagnostics. Existing SQLite zone records remain compatible because the new fields have defaults and are stored in the existing JSON payload.
|
||||
Diagnostics:
|
||||
|
||||
Zone cards are fast thermostats: `- / +`, **Auto schedule / Comfort / Sleep / Away**, **Global / Heat / Cool**, and local thermostat **ON/OFF** are available without opening the edit dialog. Local ON/OFF is thermostat ownership, not direct/pilot control: a locally started zone can bypass a disabled climate-group power gate while still using its room sensor, hysteresis, selected target/profile, Smart Fan and GREE setpoint modulation. **Resume automation** removes that local power override and returns the zone to group/schedule ownership; if its group is off, the unit then stays off. Only a real physical/remote change or the technical Devices command path creates `device_manual_override`. Controller-originated GREE transitions are tracked through the short device settling window so group/thermostat commands are not misclassified as remote takeover. Temporary thermostat overrides otherwise end at the next schedule boundary; when a local thermostat is explicitly active, its selected manual target/profile is retained until Auto/Resume is chosen.
|
||||
```bash
|
||||
sudo ./scripts/configure-gree-network.sh
|
||||
./scripts/network-debug.sh
|
||||
```
|
||||
|
||||
## Smart thermostat and schedules
|
||||
The hardened systemd unit allows `AF_NETLINK`, which is required for interface discovery on multi-NIC Linux/LXC systems.
|
||||
|
||||
Version 0.4.0 is designed around a simple rule: during normal heating/cooling, keep the indoor unit powered and modulate its target instead of repeatedly switching the unit OFF and ON. When a room is satisfied, cooling moves the device target above the comfort target and heating moves it below the comfort target. When hysteresis requests conditioning again, the working target is restored. Smart Quiet and standby Low fan are transition hints rather than commands that are blindly reasserted every adjustment interval, avoiding unnecessary beeps when the room and device setpoint are already stable. **House Off** is now a no-control state for inherited zones, so manual device operation is not overwritten; whole-house master power on/off is available separately and can authoritatively keep every unit off without changing the selected thermostat mode. Disabled zones are excluded from normal house/group/automation control; their physical unit remains available for explicit technical control from the Devices view.
|
||||
## Thermostat model
|
||||
|
||||
Choose one seasonal **global mode** — Cooling in summer, Heating in winter, or Off. Zones inherit this global mode by default, while a zone may explicitly override Heat/Cool when required. In **Mode policy**, leave **Follow global mode** unchanged when the zone should inherit the mode selected globally in GREE Controller; **Cooling only** / **Heating only** are deliberate per-zone overrides. Each zone has separate Comfort/Sleep/Away temperatures for cooling and heating.
|
||||
### Devices vs zones
|
||||
|
||||
Schedules store profiles rather than duplicating temperatures. Ready-made **Family**, **Child room**, **Bedroom**, **Workday** and **Always comfort** templates generate ordinary editable schedule entries. For example, a child room template can enter Sleep earlier; if the child goes to bed even earlier, press **Sleep** and that zone remains in Sleep until its next schedule boundary (or until manually cleared when no future boundary exists). Whole-house **Comfort all / Sleep all / Away all / Auto schedule** actions are also available.
|
||||
A **Device** is the physical GREE unit. Device commands are direct/technical commands.
|
||||
|
||||
The optional HA outdoor sensor is an assist signal only. It never replaces the room-control temperature. In extreme weather it can make the active device setpoint slightly more assertive and let Smart Fan increase airflow. When cooling is actually controlled from a valid external/combined room sensor, demand also forces the next lower whole-degree unit target (typically 0.5–1.0°C below the room target); the correction is disabled on GREE fallback and is not stacked above the outdoor-assist maximum.
|
||||
A **Zone** is the thermostat owner for a device. It decides demand from room temperature, setpoint, hysteresis, schedules, group/house gates, manual ownership and safety lockouts.
|
||||
|
||||
At startup, thermostat, schedule and automation commands are held until one complete live device poll has finished. This prevents a restart from issuing commands based only on stale persisted device state while still preserving all saved zone, group, schedule, override and device configuration.
|
||||
This distinction is important: direct device control intentionally behaves differently from thermostat control.
|
||||
|
||||
### Control ownership
|
||||
|
||||
The zone state exposes who currently owns control (`control_owner`, `control_source`, timestamps and reason). Physical remote/direct device actions can create a manual-device takeover so normal schedules do not immediately overwrite the user. Explicit zone thermostat control hands ownership back to the thermostat engine when appropriate.
|
||||
|
||||
Whole-house master OFF remains authoritative and powers managed devices down.
|
||||
|
||||
### Profiles and schedules
|
||||
|
||||
Each zone stores separate cooling and heating temperatures for:
|
||||
|
||||
- Comfort
|
||||
- Sleep
|
||||
- Away
|
||||
- Custom/manual target
|
||||
|
||||
Schedules select profiles or a custom target for selected ISO weekdays (`1=Monday`, `7=Sunday`). Overnight windows are supported. Overlapping enabled schedules for the same zone are rejected.
|
||||
|
||||
Quick preset/setpoint overrides normally hand control back at the next schedule boundary. Temporary Quick Thermostat adds explicit start/finish rules such as duration, exact time, temperature reached/stable or next schedule boundary.
|
||||
|
||||
## Home Assistant
|
||||
|
||||
There are two independent HA directions:
|
||||
There are two independent Home Assistant directions.
|
||||
|
||||
1. **HA as an optional sensor source**: the Rust controller can read a selected HA sensor and use it for a zone.
|
||||
2. **HA as a client of GREE Controller**: the included custom integration creates `climate` entities whose commands are sent to this Rust application.
|
||||
### 1. Home Assistant as a temperature source
|
||||
|
||||
For the HA client connection, open **More -> Home Assistant / Sensors** in GREE Controller and press **Create new token**. The secret is shown once. Paste that token into the Home Assistant `GREE Controller` integration together with the controller URL. Managed HA tokens are stored as SHA-256 hashes and are scoped to the dedicated HA device/control-plan/house-control/zone-control API; they cannot change controller settings or manage other tokens.
|
||||
|
||||
The outbound HA sensor client also supports local HTTPS endpoints such as `https://192.168.50.25`. If the server uses a self-signed, expired or hostname-mismatched certificate, enable **Home Assistant / Sensors -> Allow invalid/self-signed HTTPS certificate**. This disables certificate/hostname validation only for the controller's outbound Home Assistant sensor client and should only be used on a trusted LAN.
|
||||
|
||||
The second option is designed to replace the built-in/default GREE integration without changing automation/dashboard references.
|
||||
|
||||
Example migration target:
|
||||
Configure **Home Assistant / Sensors** in the Web UI or use:
|
||||
|
||||
```text
|
||||
old: climate.klima_salon -> built-in GREE integration
|
||||
new: climate.klima_salon -> GREE Controller custom integration -> Rust API -> AC
|
||||
HA_URL=
|
||||
HA_TOKEN=
|
||||
HA_ENTITY_ID=
|
||||
HA_OUTDOOR_ENTITY_ID=
|
||||
HA_SENSOR_STALE_AFTER_SECONDS=300
|
||||
HA_ALLOW_INVALID_TLS=false
|
||||
```
|
||||
|
||||
Generate an entity mapping:
|
||||
Per zone, `sensor_source` can be:
|
||||
|
||||
```bash
|
||||
./scripts/generate_ha_migration.py \
|
||||
--entity climate.klima_salon \
|
||||
--device gree-aabbccddeeff
|
||||
```
|
||||
- `device` — GREE indoor sensor,
|
||||
- `home_assistant` — configured HA room sensor,
|
||||
- `combined` — weighted GREE + HA value.
|
||||
|
||||
Or validate against the controller and automatically use its only device:
|
||||
Stale/unavailable external data falls back to the GREE sensor when possible. The optional outdoor sensor is only an assist signal; it never replaces room temperature.
|
||||
|
||||
```bash
|
||||
./scripts/generate_ha_migration.py \
|
||||
--entity climate.klima_salon \
|
||||
--controller-url http://192.168.1.20:8787 \
|
||||
--controller-token YOUR_CONTROLLER_TOKEN
|
||||
```
|
||||
### 2. GREE Controller entities inside Home Assistant
|
||||
|
||||
The generated file must be copied to:
|
||||
Bundled integration directory:
|
||||
|
||||
```text
|
||||
/config/gree_controller_entities.json
|
||||
home-assistant/custom_components/gree_controller/
|
||||
```
|
||||
|
||||
Full installation and safe takeover procedure: [`home-assistant/README.md`](home-assistant/README.md) and [`docs/HOME_ASSISTANT_MIGRATION.md`](docs/HOME_ASSISTANT_MIGRATION.md).
|
||||
Copy `gree_controller` to Home Assistant's `custom_components` directory, restart Home Assistant and add **GREE Controller** from Integrations.
|
||||
|
||||
## API
|
||||
Create a restricted token in **Home Assistant / Sensors → Access tokens**. The token secret is displayed only once and the database stores only its SHA-256 hash. The integration uses a restricted `/api/integrations/home-assistant/*` surface rather than administrator endpoints.
|
||||
|
||||
Important endpoints:
|
||||
The integration exposes physical device climate controls, thermostat zone climate entities, whole-house controls, groups and optional unit capabilities. Prefer zone thermostat entities for normal comfort control; physical device entities are direct/manual controls.
|
||||
|
||||
```text
|
||||
GET /api/health
|
||||
GET /api/bootstrap
|
||||
POST /api/discovery
|
||||
GET /api/devices
|
||||
POST /api/devices
|
||||
GET /api/devices/:id
|
||||
PATCH /api/devices/:id
|
||||
POST /api/devices/:id/bind
|
||||
POST /api/devices/:id/poll
|
||||
POST /api/devices/:id/command
|
||||
GET /api/zones
|
||||
POST /api/zones
|
||||
POST /api/zones/:id/control
|
||||
POST /api/zones/:id/schedule-template
|
||||
GET /api/groups
|
||||
POST /api/groups
|
||||
GET /api/groups/:id
|
||||
PUT /api/groups/:id
|
||||
DELETE /api/groups/:id
|
||||
POST /api/groups/:id/control
|
||||
POST /api/house/control
|
||||
POST /api/house/power
|
||||
POST /api/house/preset
|
||||
GET /api/schedules
|
||||
POST /api/schedules
|
||||
GET /api/automations
|
||||
POST /api/automations
|
||||
GET /api/readings
|
||||
GET /api/history
|
||||
GET /api/control-plan
|
||||
GET /api/events
|
||||
GET /api/settings
|
||||
PUT /api/settings
|
||||
GET /api/settings/export
|
||||
POST /api/settings/import
|
||||
GET /api/debug
|
||||
PUT /api/debug
|
||||
GET /api/access-tokens
|
||||
POST /api/access-tokens
|
||||
DELETE /api/access-tokens/{id}
|
||||
POST /api/integrations/home-assistant/test
|
||||
GET /api/integrations/home-assistant/devices
|
||||
POST /api/integrations/home-assistant/devices/{id}/command
|
||||
GET /api/integrations/home-assistant/control-plan
|
||||
GET /api/integrations/home-assistant/groups
|
||||
POST /api/integrations/home-assistant/groups/{id}/control
|
||||
POST /api/integrations/home-assistant/house/control
|
||||
POST /api/integrations/home-assistant/house/preset
|
||||
POST /api/integrations/home-assistant/house/power
|
||||
POST /api/integrations/home-assistant/zones/{id}/control
|
||||
WS /ws
|
||||
```
|
||||
|
||||
Example command:
|
||||
For entity-ID migration tooling:
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:8787/api/devices/sim-salon/command \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer YOUR_TOKEN' \
|
||||
-d '{"power":true,"mode":"cool","target_temperature":22,"fan_speed":3}'
|
||||
python3 scripts/generate_ha_migration.py --help
|
||||
```
|
||||
|
||||
`/api/health` is public. The normal controller API and Web UI require `GREE_CONTROLLER_APP_TOKEN` only when that administrator token is configured. The dedicated `/api/integrations/home-assistant/*` client endpoints always require either a generated HA access token or the administrator token. WebSocket accepts only the administrator token using `?token=...`.
|
||||
The generated mapping example is under `home-assistant/generated/`.
|
||||
|
||||
More examples: [`docs/API.md`](docs/API.md).
|
||||
## History and InfluxDB
|
||||
|
||||
SQLite is the local hot store. History compaction reduces older local sample density while preserving the resolutions needed by charts. Retention is configurable from the UI or environment.
|
||||
|
||||
Optional InfluxDB writes samples in parallel and can serve the older part of long history queries:
|
||||
|
||||
- InfluxDB 1.x: URL, database, optional username/password.
|
||||
- InfluxDB 2.x: URL, organization, bucket and token.
|
||||
|
||||
If an Influx query fails, the API returns available SQLite data and can include a `storage_warning` rather than discarding the whole history response.
|
||||
|
||||
See [`GET /api/history`](docs/API.md#history-and-readings) for scopes and bucket behavior.
|
||||
|
||||
## Notifications
|
||||
|
||||
Optional notifications support:
|
||||
|
||||
- Pushover
|
||||
- Slack webhook
|
||||
- Discord webhook
|
||||
|
||||
Modes can report problems only or problems plus important state changes. Individual categories include sensor freshness/errors, communication failures, target timeout, automation/control errors and other warnings. Cooldown and failure thresholds are configurable.
|
||||
|
||||
## Debugging
|
||||
|
||||
Enable **Settings → Application → On-screen debug**.
|
||||
|
||||
The overlay has three filters:
|
||||
|
||||
- **All** — request diagnostics, application events and GREE frames,
|
||||
- **Requests** — HTTP method/path/status/duration,
|
||||
- **GREE** — sanitized protocol frames when GREE frame logging is enabled.
|
||||
|
||||
Binding/encryption keys are not intentionally exposed in GREE debug frames.
|
||||
|
||||
For Linux/network issues also use:
|
||||
|
||||
```bash
|
||||
./scripts/network-debug.sh
|
||||
./scripts/service.sh logs
|
||||
```
|
||||
|
||||
## Backup and restore
|
||||
|
||||
**Settings → Application → Configuration backup** exports settings, devices, zones, groups, schedules and automations.
|
||||
|
||||
The export intentionally does **not** contain metric history, event history or generated API-token records. It **does contain** GREE binding keys and configured integration secrets, so store it like a credential file.
|
||||
|
||||
Import replaces application configuration while preserving local metric/event history and generated access-token records. Runtime ownership/timers are sanitized and live device state is re-polled before automatic control resumes.
|
||||
|
||||
## Reverse proxy and sub-path deployment
|
||||
|
||||
For a root deployment, proxy HTTP and WebSocket traffic to the controller normally.
|
||||
|
||||
For a sub-path, configure:
|
||||
|
||||
```bash
|
||||
GREE_CONTROLLER_BASE_PATH=/gree
|
||||
```
|
||||
|
||||
Then serve the application under `/gree/`. The proxy must preserve WebSocket upgrade headers. A typical nginx location is:
|
||||
|
||||
```nginx
|
||||
location /gree/ {
|
||||
proxy_pass http://127.0.0.1:8787/gree/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
```
|
||||
|
||||
If your proxy strips the prefix, keep its upstream/base-path handling consistent. Do not publish the controller directly to an untrusted network without authentication and TLS at the proxy/VPN layer.
|
||||
|
||||
## Security
|
||||
|
||||
- The application does not terminate TLS. Use HTTPS reverse proxy or VPN on untrusted networks.
|
||||
- Do not expose port 8787 directly to the public Internet.
|
||||
- Use a long random `GREE_CONTROLLER_APP_TOKEN`.
|
||||
- Protect `.env`, `/etc/gree-controller.env`, SQLite data and HA tokens.
|
||||
- The controller sends device commands only to configured local-network devices.
|
||||
The default empty `GREE_CONTROLLER_APP_TOKEN` is intended for a trusted LAN only. Set a long random token when the interface is reachable by other networks.
|
||||
|
||||
## Backup
|
||||
Implemented safeguards include:
|
||||
|
||||
For a systemd installation:
|
||||
- optional bearer administrator authentication,
|
||||
- separate restricted generated tokens for Home Assistant,
|
||||
- hashed generated-token storage,
|
||||
- secrets omitted from normal settings responses,
|
||||
- restrictive security headers and no permissive CORS,
|
||||
- API responses marked `no-store`,
|
||||
- hardened systemd service,
|
||||
- safe device power-off behavior when thermostat ownership is removed,
|
||||
- startup synchronization before the thermostat engine begins issuing commands.
|
||||
|
||||
For remote access, prefer a VPN or authenticated TLS reverse proxy. Treat configuration exports and `/etc/gree-controller.env` as secrets.
|
||||
|
||||
## Localization
|
||||
|
||||
Language packs are JSON files under `lang/`. The build validates/embeds them and generates the public language catalog.
|
||||
|
||||
To add a language:
|
||||
|
||||
1. Copy `lang/en.json` to `lang/<code>.json`.
|
||||
2. Update `meta.code`, names and locale.
|
||||
3. Keep the same translation keys as the reference pack.
|
||||
4. Rebuild the Rust binary.
|
||||
|
||||
Runtime assets are available at `/lang/index.json` and `/lang/<code>.json`.
|
||||
|
||||
## API
|
||||
|
||||
The HTTP API is the same backend used by the Web UI. It includes devices, zones, groups, house control, schedules, automations, history, control plan, events, settings, backup/restore, debug, tokens and integration tests.
|
||||
|
||||
Start here:
|
||||
|
||||
**[docs/API.md — complete API reference](docs/API.md)**
|
||||
|
||||
Public health check:
|
||||
|
||||
```bash
|
||||
systemctl stop gree-controller
|
||||
cp /var/lib/gree-controller/gree-controller.db /safe/backup/location/
|
||||
systemctl start gree-controller
|
||||
curl http://127.0.0.1:8787/api/health
|
||||
```
|
||||
|
||||
Development data is stored under `data/` by default.
|
||||
Authenticated example when an app token is configured:
|
||||
|
||||
```bash
|
||||
curl -H 'Authorization: Bearer YOUR_TOKEN' \
|
||||
http://127.0.0.1:8787/api/system/info
|
||||
```
|
||||
|
||||
## Project layout
|
||||
|
||||
```text
|
||||
src/api.rs HTTP API, WebSocket, embedded web assets
|
||||
src/db.rs SQLite persistence and row/domain mapping
|
||||
src/queries.rs all SQLite schema and SQL statements
|
||||
src/engine.rs polling, zones, schedules and automations
|
||||
src/protocol/ GREE UDP/AES discovery, bind, status, command
|
||||
src/home_assistant.rs optional HA sensor client
|
||||
web/ mobile-first bilingual PWA
|
||||
home-assistant/custom_components/ HA custom integration
|
||||
scripts/install.sh first LXC/systemd installation
|
||||
scripts/update.sh safe LXC/systemd update with backup/rollback
|
||||
scripts/service.sh service status/start/stop/restart/logs/health
|
||||
scripts/dev.sh development build/run/check workflow
|
||||
scripts/generate_ha_migration.py legacy HA entity-ID mapping generator
|
||||
scripts/smoke.sh API smoke test
|
||||
systemd/ systemd service unit
|
||||
src/ Rust backend, GREE protocol and thermostat engine
|
||||
web/ Embedded Web UI / PWA
|
||||
lang/ Runtime language packs
|
||||
home-assistant/ Home Assistant custom integration and migration output
|
||||
scripts/ Development, install, update, service and diagnostics
|
||||
systemd/ Production service unit
|
||||
docs/API.md Complete API documentation
|
||||
.env.example Environment reference
|
||||
```
|
||||
|
||||
The application is intentionally self-contained: static assets and language packs are embedded into the binary at build time; SQLite is the default data store; no external frontend build chain is required.
|
||||
|
||||
## Validation before release
|
||||
|
||||
Recommended full check on a host with Rust installed:
|
||||
|
||||
```bash
|
||||
./scripts/dev.sh --check
|
||||
```
|
||||
|
||||
This runs formatting checks, Rust tests, a build and an isolated simulated API smoke test.
|
||||
|
||||
## License
|
||||
|
||||
MIT. This project uses a community-reconstructed local device protocol and is not an official product of GREE Electric Appliances Inc.
|
||||
|
||||
|
||||
## Multi-NIC / dedicated GREE interface
|
||||
|
||||
For LXC hosts with a management NIC and a separate GREE/VLAN NIC, bind GREE UDP traffic explicitly to the GREE interface:
|
||||
|
||||
```env
|
||||
GREE_CONTROLLER_GREE_INTERFACE=eth1
|
||||
GREE_CONTROLLER_DISCOVERY_BROADCAST=auto
|
||||
GREE_CONTROLLER_SIMULATE=false
|
||||
GREE_CONTROLLER_AUTO_SEED=false
|
||||
```
|
||||
|
||||
`GREE_CONTROLLER_GREE_INTERFACE` is resolved to the interface current IPv4 address whenever a UDP socket is created, so DHCP address changes do not require hard-coding the source IP. `GREE_CONTROLLER_DISCOVERY_BROADCAST=auto` derives the subnet broadcast from the selected interface and overrides an older runtime value stored in SQLite.
|
||||
|
||||
Run `sudo ./scripts/network-debug.sh eth1 10.87.65.127` to verify addressing and routing.
|
||||
|
||||
### v0.3.7 LXC networking fix
|
||||
|
||||
The systemd service explicitly allows `AF_NETLINK`. This is required by Linux `getifaddrs()` when resolving `GREE_CONTROLLER_GREE_INTERFACE` on multi-NIC LXC installations. Without it, older releases could fail with `Address family not supported by protocol (os error 97)` even though the configured interface was correct.
|
||||
|
||||
### v0.3.8 legacy V1 device compatibility
|
||||
|
||||
GREE protocol identifiers are now emitted as canonical lowercase hexadecimal in `tcid` and `pack.mac`. This improves compatibility with older V1 Wi-Fi modules (including devices in the `502cc6...` family) that can answer discovery but silently ignore bind/status packets when MAC casing differs from their discovery identity. Stored device IDs and friendly names are not changed.
|
||||
|
||||
### v0.4.0 smart thermostat
|
||||
|
||||
Zones now use setpoint modulation, global seasonal house mode, cooling/heating Comfort/Sleep/Away profiles, temporary per-zone overrides, ready-made editable schedule templates, whole-house preset actions and optional outdoor-temperature assist. The UI also uses theme-aware thin scrollbars and can opt in to invalid/self-signed certificates for the outbound Home Assistant sensor connection. Existing zones remain readable; a legacy zone keeps its previous setpoint as its comfort target until it is edited and saved with the new profile fields.
|
||||
|
||||
|
||||
## 0.7.1 quick-control visual consistency
|
||||
|
||||
- Unified dashboard Quick Thermostats and Quick Manual Control under shared `quick-control-*` CSS classes instead of separate dashboard-ID overrides.
|
||||
- Standardized compact option buttons, gaps and row grids across presets, HVAC modes, fan speeds and quick unit toggles.
|
||||
- Kept full Zones and Devices pages at their existing larger control sizes; the compact style applies only to dashboard quick controls.
|
||||
- Renamed the compact zone mode from House to Global to make its meaning explicit: the zone inherits the global Heating/Cooling mode selected in GREE Controller.
|
||||
- Renamed Sleep now to Sleep in quick thermostat presets.
|
||||
- Advanced the PWA cache key to `gree-controller-v071-quick-controls`.
|
||||
|
||||
## 0.7.2 zone configuration separation
|
||||
|
||||
- The **Zones** view is now configuration-only: no live +/- temperature, preset or mode buttons are shown there.
|
||||
- Current zone status remains visible as read-only context, together with mode policy, sensor strategy, hysteresis and Smart Fan configuration.
|
||||
- The **Control** button opens the Dashboard, expands **Quick thermostats** and scrolls to the matching zone.
|
||||
- The zone form no longer exposes the legacy/base `setpoint` as a live-looking control; profile temperatures remain configurable.
|
||||
- Live zone temperature, preset, mode and enable/disable controls remain available in **Dashboard -> Quick thermostats**.
|
||||
|
||||
## 0.7.3 Home Assistant climate groups
|
||||
|
||||
- Added climate groups to the restricted Home Assistant API.
|
||||
- Each configured group is exposed as its own Home Assistant device with **Power**, **Thermostat mode**, **Work profile** and **Control plan** entities.
|
||||
- Group mode options are **Global**, **Cooling** and **Heating**; Global means the member zones inherit the controller-wide Heating/Cooling selection.
|
||||
- Group profile options are **Auto schedule**, **Comfort**, **Sleep** and **Away**.
|
||||
- The group control-plan sensor reports member zones, online unit count, current average temperature, demand count and upcoming member schedule events.
|
||||
- Mixed member modes/profiles are reported without inventing a false common value; choosing a group option normalizes all member zones through the existing group-control engine.
|
||||
- Group commands use the restricted Home Assistant access token and the dedicated `/api/integrations/home-assistant/groups/*` endpoints.
|
||||
- After adding/removing/renaming groups, reload the GREE Controller integration in Home Assistant so its entity/device registry is rebuilt.
|
||||
|
||||
## 0.7.6 Home Assistant command-state stability
|
||||
|
||||
- Physical-unit commands now tolerate the short GREE firmware settling window after a successful command ACK before publishing a contradictory status. This prevents stale immediate polls from producing visible `ON -> OFF -> ON` state bounce.
|
||||
- The Home Assistant coordinator keeps a just-accepted device command as a short-lived pending value while refreshing controller metadata. An overlapping stale read cannot temporarily roll back the HA climate/feature state; normal factual polling resumes automatically after the bounded guard window.
|
||||
|
||||
## 0.7.5 group power state visibility
|
||||
|
||||
- Group **ON/OFF** buttons now use the same strong active-state highlight as group mode and profile controls, so the current power gate is immediately visible.
|
||||
- Simulator summary wording now uses **Zones with demand** / **Strefy z zapotrzebowaniem** instead of the less natural comfort-request wording.
|
||||
|
||||
## 0.7.4 manual remote override
|
||||
|
||||
- Physical GREE changes detected during polling for power, HVAC mode, target temperature and meaningful fan-speed changes now enter a per-zone **Manual control / remote** takeover state.
|
||||
- While takeover is active, thermostat modulation, schedules, groups and direct-device automations observe the zone but do not overwrite the unit.
|
||||
- The pre-takeover climate state is remembered. If the user returns the unit to that operational state, takeover clears automatically and **Resume automation** is no longer shown. If the unit was OFF before takeover, returning it to OFF is enough even when the remote retained a different dormant setpoint. Otherwise takeover expires at the next schedule transition when available; without one it remains until **Resume automation** or another explicit quick-thermostat action.
|
||||
- Technical climate control from the Devices view uses the same takeover semantics, while unrelated controls such as panel light do not pause the thermostat.
|
||||
- Disabled zones remain outside normal group/automation ownership; their unit can be operated manually.
|
||||
- **Turn all off** remains authoritative: it clears all takeovers, disables groups and powers off enabled units. Whole-house/group ON paths do not wake zones currently protected by manual takeover.
|
||||
- The UI and control-plan API expose the takeover state and its optional expiry.
|
||||
|
||||
|
||||
## 0.7.7 Quick-control label fit
|
||||
|
||||
- Adjusted the five-column quick-device mode row so longer Polish labels such as **Chłodzenie** and **Osuszanie** receive more width without reducing the whole row font size.
|
||||
- The change is limited to the dashboard quick-device mode row; thermostat/group layouts are unchanged.
|
||||
- Rotated the PWA cache key so browsers fetch the corrected stylesheet after upgrade.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 0.8.10 Dashboard sections and notification filters
|
||||
|
||||
- Dashboard is split into three horizontal tabs: **Main**, **Thermostats** and **Manual control**. Each tab opens one normal vertically scrolling section instead of nested disclosure panels.
|
||||
- Main keeps the summary, global power/house climate and control plan; Thermostats contains group controls and zone thermostats; Manual control contains direct unit controls.
|
||||
- The top toolbar shows the live powered-unit count (`active/total`), and **Discover** moved from the global toolbar to the Devices page.
|
||||
- Runtime control ownership timestamps now include both date and time.
|
||||
- Notification settings now expose per-category delivery switches. Stale Home Assistant readings have their own `ha.sensor_stale` category and can be suppressed without disabling other sensor, communication, automation or thermostat alerts.
|
||||
- Rotated the PWA cache key so upgraded clients fetch the new dashboard and settings UI.
|
||||
|
||||
## 0.8.9 Remote-takeover diagnostics
|
||||
|
||||
- Reverted the v0.8.8 two-poll confirmation heuristic for unexpected GREE states; unexpected states outside the known controller-command/baseline settling envelope are again acted on immediately.
|
||||
- Added `device.remote_control_detected` diagnostics for poll-detected manual/pilot takeover, including raw/detected fields, before/after physical state, active controller settling commands/baselines and remaining settling-window time, plus current zone/Temporary Quick Thermostat ownership state.
|
||||
- Retains the v0.8.8 narrow-screen Temporary Quick Thermostat modal layout fix.
|
||||
|
||||
## 0.8.8 Poll-takeover confirmation and mobile modal fit
|
||||
|
||||
- A single unexpected GREE poll snapshot inside the controller-command settling window no longer immediately becomes a physical/pilot takeover. The same unexpected physical state must persist into the next poll, so one transient mixed/out-of-order frame cannot break a scheduled Temporary Quick Thermostat start.
|
||||
- Genuine direct/remote changes are still recognized after confirmation; deferred candidates are not lost when the next poll has no before/after delta.
|
||||
- On narrow screens the Temporary Quick Thermostat **End and return to automation** button is placed below the active-session text and uses the full modal width.
|
||||
- Rotated the PWA cache key so the corrected mobile stylesheet is fetched after upgrade.
|
||||
|
||||
## 0.8.7 Temporary-session state cleanup
|
||||
|
||||
- `activated_at` is now the only source of truth for Temporary Quick Thermostat ownership.
|
||||
- Removed the legacy `generation=0` / `local_thermostat_power` activation fallback from the backend and Web UI.
|
||||
- Removed the Temporary-session `generation` compatibility field and its legacy-only test path.
|
||||
- Kept ordinary Quick Thermostat state only as an independent lower-priority owner restored after Temporary hand-back.
|
||||
|
||||
## 0.8.6 Control-logic audit remediation
|
||||
|
||||
- Separates ordinary Quick Thermostat handback state from Temporary Quick Thermostat lifecycle and makes fresh-session activation depend on `activated_at`.
|
||||
- Hardens ownership priority so direct/manual takeover outranks temporary completion and pauses temporary hold/runtime accounting.
|
||||
- Freezes active Temporary mode/target while deferring house/group climate changes until handback.
|
||||
- Prevents unmanaged whole-house/group power-on, closes generic Settings/import bypasses, and safely stops devices before disable/detach.
|
||||
- Makes thermostat-managed device automations durable zone-state changes instead of competing one-shot device frames.
|
||||
- Adds schedule/time-automation deadlines to the common wakeup path and refreshes temporary schedule-boundary deadlines after schedule edits.
|
||||
- Aligns Web UI/API lifecycle handling for active delayed/at sessions and exposes scheduled/waiting-master/paused-manual/active states.
|
||||
|
||||
## 0.8.5 Temporary temperature-condition activation fix
|
||||
|
||||
- Fixed `temperature_stable` / `temperature_reached` evaluation for sessions already marked active through `activated_at`.
|
||||
- Kept delayed sessions protected from evaluating or completing before their scheduled start.
|
||||
- Preserved migration compatibility with active v0.8.3 sessions by also accepting existing local Quick Thermostat ownership as an activation marker.
|
||||
- Fixes the two v0.8.4 regression tests that stopped `scripts/update.sh` before service replacement.
|
||||
|
||||
## 0.8.4 Scheduled Temporary Quick Thermostat start and ownership hardening
|
||||
|
||||
- Temporary Quick Thermostat can start immediately, after a configurable delay, or at a specific local date/time.
|
||||
- Delayed sessions do not take thermostat ownership early: normal schedules and automations continue until the effective start instant.
|
||||
- Duration, safety timeout and next-schedule-boundary finish rules are calculated from the effective start, not from the time the session is configured.
|
||||
- Active temporary ownership keeps its requested target across schedule transitions and schedule edits; direct device automations and group climate changes cannot overwrite it while it is active.
|
||||
- A local Quick Thermostat can run using the zone's local Heat/Cool mode even when the inherited house climate mode is set to **Do not control**; the separate whole-house master power remains authoritative.
|
||||
- Cancelling a not-yet-started session only removes that session and does not clear unrelated quick-control state.
|
||||
|
||||
## 0.8.3 Temporary Quick Thermostat sessions
|
||||
|
||||
- Adds a separate persisted timed Quick Thermostat session without reusing the existing 15-minute local-OFF hand-back timer.
|
||||
- Supports ending after a duration, at a date/time, after reaching a temperature, after continuously holding a temperature condition, or at the next schedule boundary.
|
||||
- Temperature conditions support within/at-or-below/at-or-above operators, tolerance and an optional safety timeout.
|
||||
- Active sessions show their countdown/status directly on the Quick Thermostat card and restore the previous automation-enabled state when finished.
|
||||
- Moves the zone automation enabled switch out of Quick Thermostat controls so automation availability and temporary thermostat ownership are visually separate.
|
||||
|
||||
## 0.8.2 UI/i18n and Home Assistant sensor freshness
|
||||
|
||||
- fixes ownership translations that were accidentally stored outside the language-pack `translations` object,
|
||||
- adds a configurable Home Assistant sensor freshness limit in the Home Assistant / Sensors settings page (default 5 minutes),
|
||||
- keeps legacy non-default per-zone stale limits as API-level overrides,
|
||||
- prevents taller Quick Thermostat / Direct Device cards from stretching neighbouring dashboard cards,
|
||||
- adds build-time validation for misplaced language-pack keys.
|
||||
|
||||
## 0.8.0 Control ownership and thermostat safety
|
||||
|
||||
- Adds an explicit zone control-ownership model (`control_owner`, command source, since/resume/reason) shared by the engine, API, Web UI and Home Assistant control plan.
|
||||
- Distinguishes direct Web, direct Home Assistant and external/remote takeovers. Quick Thermostat commands explicitly return ownership to the thermostat.
|
||||
- Adds per-zone operation mutexes plus an optional monotonic `revision` check for conflict-safe zone updates without breaking older clients that do not send a revision.
|
||||
- Recomputes both thermostat override and physical-device manual takeover deadlines after schedule edits.
|
||||
- Rejects stale Home Assistant temperature samples (default 300 seconds per zone) and falls back to the GREE sensor through the existing fallback path.
|
||||
- Enforces automatic HVAC compressor protection: minimum OFF time before restart and an OFF delay when automatically changing Heat/Cool modes. Direct/manual commands and global safety OFF remain authoritative.
|
||||
- Extends control-plan with desired vs actual HVAC state, ownership, block reason and lockout deadline.
|
||||
- Shows the current control owner and timing in the Web dashboard. Home Assistant zone climate exposes the same diagnostics; the physical climate is named `Direct control` to make its semantics explicit.
|
||||
|
||||
## 0.7.13 Quick-thermostat race protection and GREE frame counters
|
||||
|
||||
- Quick thermostat actions from Web/Home Assistant are serialized with device polling, so a poll running at the same time cannot restore an older `device_manual_override` snapshot after the thermostat deliberately takes control back.
|
||||
- Recent controller-originated climate transitions keep a bounded settling history of both requested and pre-command values. Delayed or out-of-order GREE status frames can pass through those known states without being misclassified as physical/pilot takeover.
|
||||
- In Dashboard -> Quick thermostats, **Global** is disabled when the whole-house thermostat mode is **Do not control**. Heat/Cool remain available as explicit per-zone overrides.
|
||||
- Settings now shows live UDP receive counters, both total and per configured air conditioner, since controller startup. Counters are independent of the debug-frame overlay and update over WebSocket.
|
||||
|
||||
## 0.7.12 Timed quick-thermostat hand-back
|
||||
|
||||
- Switching a single Quick Thermostat **OFF** now starts a 15-minute local-OFF window instead of leaving the zone outside automation indefinitely.
|
||||
- The Web UI shows a live `MM:SS` countdown and a **Resume now** action during that window.
|
||||
- At expiry, only local quick-thermostat ownership and its temporary quick profile/setpoint are cleared. The controller does not restore a stale physical ON/OFF state; it recalculates the current group, house mode, schedule, profile, room temperature and hysteresis.
|
||||
- Every fresh local **OFF** action creates a new backend-owned 15-minute deadline; switching the local thermostat back **ON** cancels it.
|
||||
- A physical/direct `device_manual_override` remains separate and temporarily suspends expiry of an existing local-OFF hand-back. Returning the unit to its previous OFF state re-arms a fresh 15-minute countdown from that moment.
|
||||
- Persisted local-OFF state from 0.7.10/0.7.11 receives a fresh 15-minute hand-back deadline on the first controller cycle after upgrade.
|
||||
|
||||
## 0.7.11 Cleanup and Rust test fix
|
||||
|
||||
- Removed the obsolete `/api/zones/{id}/manual-power` compatibility endpoint and its handler; local thermostat power has one canonical API path: `/api/zones/{id}/control`.
|
||||
- Renamed dashboard internals from `manual-power` terminology to `local-thermostat-power` to match the actual control model.
|
||||
- Fixed the Rust ownership error in `local_thermostat_ownership_blocks_direct_automation` by borrowing the test zone via `std::slice::from_ref`, so the test no longer moves `zone` while borrowing `zone.device_id`.
|
||||
|
||||
## 0.7.10 Local quick-thermostat ownership
|
||||
|
||||
- Quick thermostat ON/OFF now controls a dedicated local thermostat state instead of using remote/manual-device semantics.
|
||||
- A locally started zone bypasses its disabled group power gate but keeps full thermostat regulation: room sensor, hysteresis, profile/target, Smart Fan and GREE setpoint modulation.
|
||||
- **Resume automation** clears local thermostat ownership and returns the zone to group/schedule control.
|
||||
- Physical remote/direct device changes remain the only source of `device_manual_override`; explicit thermostat actions can take ownership back.
|
||||
- Controller-originated GREE changes that appear after the device settling window are correlated with the pending controller command, preventing group ON and thermostat commands from falsely showing **Manual control / remote**.
|
||||
- Home Assistant zone climate ON/OFF now uses the same local thermostat power semantics instead of technically disabling the zone.
|
||||
|
||||
## 0.7.9 Zone profile control and Home Assistant stability
|
||||
|
||||
- Quick thermostat profile/mode/target/enable actions now wake the thermostat regulator immediately instead of waiting for the next fixed zone interval.
|
||||
- A manual/remote takeover keeps the configured thermostat profile target visible; the physical GREE target is reported separately as the device setpoint. This prevents standby setpoints such as 25 C from being shown as the Sleep/Comfort target.
|
||||
- Control-plan `enabled` now represents the configured per-zone switch. A new `effective_enabled` field reports group gating, so Home Assistant zone switches/climate entities no longer bounce back to Off solely because a climate group is disabled.
|
||||
- Home Assistant zone controls use a short pending-state guard, matching the existing physical-device anti-bounce protection.
|
||||
- Every zone now exposes a **Work profile** select and the zone `climate` entity supports preset modes: Auto schedule, Comfort, Sleep and Away.
|
||||
|
||||
## 0.7.8 Zone status wording and unit power
|
||||
|
||||
- Zone runtime status now says **Zapotrzebowanie aktywne** when the thermostat is requesting work and **Cel osiągnięty** when the target/hysteresis condition is satisfied; **Komfort** remains only the preset name. Paused control is shown as **Oczekiwanie**, and missing control temperature as **Brak pomiaru**.
|
||||
- Quick thermostats use one contextual **Włącz jednostkę / Wyłącz jednostkę** control instead of the redundant **Jednostka · pilot** caption and separate ON/OFF buttons.
|
||||
- Direct unit power still behaves as manual/remote takeover and does not enable the whole group.
|
||||
See [LICENSE](LICENSE).
|
||||
|
||||
Reference in New Issue
Block a user