401 lines
23 KiB
Markdown
401 lines
23 KiB
Markdown
# 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_*`.
|
|
|
|
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 version: **0.5.0**.
|
|
|
|
## Highlights
|
|
|
|
- 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,
|
|
- 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 now**,
|
|
- 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,
|
|
- 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 `climate` commands and exposes zone plan sensors, writable zone target-temperature numbers and zone enable switches,
|
|
- migration mapping generator for retaining existing HA entity IDs such as `climate.klima_salon`.
|
|
|
|
See [`BUILD_REPORT.md`](BUILD_REPORT.md) for package validation details and [`docs/LXC.md`](docs/LXC.md) for the LXC deployment/update workflow.
|
|
|
|
## Quick start
|
|
|
|
On Debian, Ubuntu or an LXC container:
|
|
|
|
```bash
|
|
unzip gree-controller-v0.5.0.zip
|
|
cd gree-controller
|
|
chmod +x scripts/*.sh
|
|
./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
|
|
|
|
```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
|
|
```
|
|
|
|
## Web interface
|
|
|
|
The UI is mobile-first and uses no external CDN.
|
|
|
|
Language selector:
|
|
|
|
- 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:
|
|
|
|
```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.
|
|
|
|
For a later release, unpack the new source archive and run:
|
|
|
|
```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.
|
|
|
|
Service helpers:
|
|
|
|
```bash
|
|
./scripts/service.sh status
|
|
sudo ./scripts/service.sh restart
|
|
./scripts/service.sh logs
|
|
./scripts/service.sh health
|
|
```
|
|
|
|
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`.
|
|
|
|
## Environment 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 |
|
|
|
|
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.
|
|
|
|
## Climate history
|
|
|
|
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.
|
|
|
|
The History area has linkable sub-pages:
|
|
|
|
- `/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.
|
|
|
|
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.
|
|
|
|
All main UI views also use browser URLs (`/dashboard`, `/devices`, `/zones`, `/schedules`, `/automations`, `/settings`, `/events`) so refresh, browser Back/Forward, bookmarks and direct links work normally.
|
|
|
|
## Per-zone room temperature sensors
|
|
|
|
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
|
|
```
|
|
|
|
Zone temperature strategies:
|
|
|
|
- **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.
|
|
|
|
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 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.
|
|
|
|
Zone cards are fast thermostats: `- / +`, **Auto schedule / Comfort / Sleep now / Away**, and **House / Heat / Cool** are available without opening the edit dialog. Temporary overrides automatically end at the next schedule boundary. The zone engine, not the browser, owns device commands so schedules, sensors and manual overrides cannot fight each other.
|
|
|
|
## Smart thermostat and schedules
|
|
|
|
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. **House Off** remains an explicit hard-off mode.
|
|
|
|
Choose one seasonal **House mode** — Cooling in summer, Heating in winter, or Off. Zones follow the house mode by default, while a zone may explicitly override Heat/Cool when required. Each zone has separate Comfort/Sleep/Away temperatures for cooling and heating.
|
|
|
|
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 now** and that zone remains in Sleep until its next schedule boundary. Whole-house **Comfort all / Sleep all / Away all / Auto schedule** actions are also available.
|
|
|
|
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.
|
|
|
|
## Home Assistant
|
|
|
|
There are two independent HA 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.
|
|
|
|
For the HA client connection, open **Settings -> Home Assistant integration access** 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/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://10.87.65.2`. If the server uses a self-signed, expired or hostname-mismatched certificate, enable **Settings -> 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:
|
|
|
|
```text
|
|
old: climate.klima_salon -> built-in GREE integration
|
|
new: climate.klima_salon -> GREE Controller custom integration -> Rust API -> AC
|
|
```
|
|
|
|
Generate an entity mapping:
|
|
|
|
```bash
|
|
./scripts/generate_ha_migration.py \
|
|
--entity climate.klima_salon \
|
|
--device gree-aabbccddeeff
|
|
```
|
|
|
|
Or validate against the controller and automatically use its only device:
|
|
|
|
```bash
|
|
./scripts/generate_ha_migration.py \
|
|
--entity climate.klima_salon \
|
|
--controller-url http://192.168.1.20:8787 \
|
|
--controller-token YOUR_CONTROLLER_TOKEN
|
|
```
|
|
|
|
The generated file must be copied to:
|
|
|
|
```text
|
|
/config/gree_controller_entities.json
|
|
```
|
|
|
|
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).
|
|
|
|
## API
|
|
|
|
Important endpoints:
|
|
|
|
```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
|
|
POST /api/house/control
|
|
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
|
|
POST /api/integrations/home-assistant/zones/{id}/control
|
|
WS /ws
|
|
```
|
|
|
|
Example command:
|
|
|
|
```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}'
|
|
```
|
|
|
|
`/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=...`.
|
|
|
|
More examples: [`docs/API.md`](docs/API.md).
|
|
|
|
## 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.
|
|
|
|
## Backup
|
|
|
|
For a systemd installation:
|
|
|
|
```bash
|
|
systemctl stop gree-controller
|
|
cp /var/lib/gree-controller/gree-controller.db /safe/backup/location/
|
|
systemctl start gree-controller
|
|
```
|
|
|
|
Development data is stored under `data/` by default.
|
|
|
|
## 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
|
|
```
|
|
|
|
## 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.
|