403 lines
16 KiB
Markdown
403 lines
16 KiB
Markdown
# 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.
|
|
|
|
**Current release: 0.8.21**
|
|
|
|
> [Full API reference](docs/API.md) — authentication, every endpoint, request bodies, response models, WebSocket events and examples.
|
|
|
|
## What it does
|
|
|
|
- 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.
|
|
|
|
## UI overview
|
|
|
|
The interface is intentionally split by responsibility:
|
|
|
|
| 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/custom-temperature 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
|
|
cp .env.example .env
|
|
./scripts/dev.sh
|
|
```
|
|
|
|
Useful development commands:
|
|
|
|
```bash
|
|
./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
|
|
```
|
|
|
|
The default panel is available at `http://127.0.0.1:8787` when the process is bound locally.
|
|
|
|
## LXC / systemd installation
|
|
|
|
The production scripts target Debian/Ubuntu systemd hosts and LXC containers.
|
|
|
|
### First installation
|
|
|
|
```bash
|
|
sudo ./scripts/install.sh
|
|
```
|
|
|
|
Optional flags:
|
|
|
|
```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 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 helper
|
|
|
|
```bash
|
|
./scripts/service.sh status
|
|
./scripts/service.sh health
|
|
./scripts/service.sh logs
|
|
sudo ./scripts/service.sh restart
|
|
```
|
|
|
|
`./scripts/install-lxc.sh` remains as a compatibility alias to `install.sh`.
|
|
|
|
## Configuration
|
|
|
|
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.
|
|
|
|
Environment values explicitly supplied for supported runtime overrides win over the persisted value after restart.
|
|
|
|
### Core variables
|
|
|
|
| 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. |
|
|
|
|
Additional environment variables cover history retention, debug, night mode, Home Assistant and InfluxDB. See [`.env.example`](.env.example).
|
|
|
|
## Connecting physical GREE units
|
|
|
|
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.
|
|
|
|
Discovery uses UDP broadcast, so routed/VLAN networks must explicitly permit or relay the required traffic.
|
|
|
|
### Multi-NIC / dedicated GREE interface
|
|
|
|
For a host with separate management and GREE networks, set for example:
|
|
|
|
```bash
|
|
GREE_CONTROLLER_GREE_INTERFACE=eth1
|
|
```
|
|
|
|
or a local address:
|
|
|
|
```bash
|
|
GREE_CONTROLLER_GREE_INTERFACE=192.168.50.2
|
|
```
|
|
|
|
The controller will use that interface for GREE UDP traffic while keeping the HTTP UI on `GREE_CONTROLLER_BIND`.
|
|
|
|
Diagnostics:
|
|
|
|
```bash
|
|
sudo ./scripts/configure-gree-network.sh
|
|
./scripts/network-debug.sh
|
|
```
|
|
|
|
The hardened systemd unit allows `AF_NETLINK`, which is required for interface discovery on multi-NIC Linux/LXC systems.
|
|
|
|
## Thermostat model
|
|
|
|
### Devices vs zones
|
|
|
|
A **Device** is the physical GREE unit. Device commands are direct/technical commands.
|
|
|
|
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.
|
|
|
|
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 Home Assistant directions.
|
|
|
|
### 1. Home Assistant as a temperature source
|
|
|
|
Configure **Home Assistant / Sensors** in the Web UI or use:
|
|
|
|
```text
|
|
HA_URL=
|
|
HA_TOKEN=
|
|
HA_ENTITY_ID=
|
|
HA_OUTDOOR_ENTITY_ID=
|
|
HA_SENSOR_STALE_AFTER_SECONDS=300
|
|
HA_ALLOW_INVALID_TLS=false
|
|
```
|
|
|
|
Per zone, `sensor_source` can be:
|
|
|
|
- `device` — GREE indoor sensor,
|
|
- `home_assistant` — configured HA room sensor,
|
|
- `combined` — weighted GREE + HA value.
|
|
|
|
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.
|
|
|
|
### 2. GREE Controller entities inside Home Assistant
|
|
|
|
Bundled integration directory:
|
|
|
|
```text
|
|
home-assistant/custom_components/gree_controller/
|
|
```
|
|
|
|
Copy `gree_controller` to Home Assistant's `custom_components` directory, restart Home Assistant and add **GREE Controller** from Integrations.
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
For entity-ID migration tooling:
|
|
|
|
```bash
|
|
python3 scripts/generate_ha_migration.py --help
|
|
```
|
|
|
|
The generated mapping example is under `home-assistant/generated/`.
|
|
|
|
## 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 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.
|
|
|
|
Implemented safeguards include:
|
|
|
|
- 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
|
|
curl http://127.0.0.1:8787/api/health
|
|
```
|
|
|
|
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/ Rust backend, GREE protocol and thermostat engine
|
|
web/ Embedded Web UI / PWA
|
|
web/js/ Frontend JS source modules bundled by build.rs
|
|
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. `build.rs` concatenates the ordered files from `web/js/` into one generated application bundle and exposes it under a content-hashed URL.
|
|
|
|
## 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
|
|
|
|
See [LICENSE](LICENSE).
|