This commit is contained in:
Mateusz Gruszczyński
2026-08-23 23:20:00 +02:00
parent 8bb12a1782
commit b23578a0c8
34 changed files with 2300 additions and 447 deletions
+47 -54
View File
@@ -1,71 +1,64 @@
# Build report — v0.3.8
## Fix in this release
- Fixed multi-NIC LXC failures where `getifaddrs()` returned `EAFNOSUPPORT` (`os error 97`).
- The systemd sandbox now allows `AF_NETLINK`, which Linux `getifaddrs()` uses to enumerate interface addresses.
- Existing hardening remains enabled (`NoNewPrivileges`, `ProtectSystem`, restricted address families).
- With `GREE_CONTROLLER_GREE_INTERFACE=eth1`, GREE UDP sockets can now resolve and bind the IPv4 address assigned to `eth1`.
## Validation
- systemd unit includes `AF_NETLINK`.
- shell scripts pass `bash -n`.
- JSON language files parse successfully.
- all SQL remains centralized in `src/queries.rs`.
- Rust compilation is not available in the packaging environment; `scripts/update.sh` runs Cargo tests/build on the target LXC before installation.
---
# GREE Controller v0.3.6 - build and validation report
# GREE Controller v0.4.1 - build and validation report
## Scope
Version 0.3.6 fixes real-device binding failures observed on a mixed five-unit GREE network in a multi-NIC LXC.
Version 0.4.1 is a Web UI redesign release. Backend HVAC logic, protocol handling, SQLite layout and Home Assistant API behavior are intentionally unchanged from v0.4.0.
### Protocol fixes
## UI redesign
- GREE AES-GCM decoding now accepts non-canonical Base64 trailing bits and optional padding. This matches the forgiving decoding behavior used by established Python GREE implementations and fixes `Invalid last symbol ... offset 21` errors from real Wi-Fi modules.
- GCM decrypted payloads discard `0xff` filler bytes used by some modules.
- ECB decoding keeps normal PKCS#7 validation but has a compatibility fallback that trims decrypted data at the last JSON `}` when a legacy module returns non-standard padding.
- Bind waits ignore late discovery packets instead of accidentally treating a `dev` packet as the bind result.
- Before each bind, the controller refreshes the short GREE bind window with a subnet broadcast scan when the device is on a directly connected IPv4 network. The same UDP socket is then used immediately for the bind request.
- ECB/GCM fallback remains enabled and successful binding persists the detected protocol and device key.
The embedded interface was rebuilt around a Supabase-inspired dashboard language while keeping original GREE Controller branding and information architecture:
### Multi-NIC behavior
- compact neutral surfaces instead of oversized cards,
- thin theme-aware borders and 6-8 px radii,
- restrained green brand accent,
- no decorative shadows or background gradients,
- full desktop sidebar for Dashboard, Devices, Zones, History, Schedules, Automations, Settings and Events,
- existing five-item bottom navigation retained on phones,
- compact inputs, selects, segmented controls and dialog controls,
- custom inline navigation SVG icons with no external icon dependency,
- themed, narrow scrollbars with transparent tracks,
- Light, Dark and System themes driven from the same CSS token set,
- updated PWA theme colors and service-worker cache version.
- If `GREE_CONTROLLER_GREE_INTERFACE` is configured, all GREE UDP sockets are bound to the current IPv4 address of that interface.
- If no GREE interface is configured, the controller now automatically selects the local IPv4 address whose subnet contains the target GREE device. For the reported LXC this resolves `10.87.65.x` traffic to the `10.87.65.27/25` interface instead of leaving the socket bound to `0.0.0.0`.
- The automatically selected subnet broadcast is also used to refresh the bind window (for example `10.87.65.127:7000`).
## Offline Tailwind tooling
Added:
- `package.json`,
- `tailwind.config.js`,
- `web/tailwind.input.css`,
- `scripts/build-web.sh`.
Tailwind is development/build tooling only. The production controller serves the committed `web/styles.css`, which is embedded in the Rust binary. The browser never contacts a Tailwind CDN and the installed LXC service does not require Node.js.
If local Tailwind dependencies are installed, `dev.sh`, `install.sh` and `update.sh` rebuild the CSS automatically. Otherwise they use the committed prebuilt CSS.
The packaging environment could not download the npm Tailwind dependency because external npm access timed out. This does not affect the shipped UI because `web/styles.css` is already present and validated. `scripts/build-web.sh --install` can install the optional local build dependency on a development host with npm access.
## Validation performed
| Check | Result |
|---|---|
| JavaScript syntax (`node --check web/app.js`) | PASS |
| EN/PL JSON parsing | PASS |
| Shell syntax (`bash -n scripts/*.sh`) | PASS |
| Python syntax for scripts and HA integration | PASS |
| SQL remains centralized in `src/queries.rs` | PASS |
| No operator `.sh`/`.py` scripts in the project root | PASS |
| Package naming remains `gree_controller` / `GREE_CONTROLLER_*` | PASS |
| ZIP integrity | performed during release packaging |
Passed:
The packaging environment does not contain the Rust toolchain, so the final Rust type-check, tests and optimized build are intentionally performed by `scripts/update.sh` on the target LXC before the installed binary is replaced.
- `web/app.js`: `node --check`,
- `web/index.html`: Python HTML parser,
- `web/styles.css`: `tinycss2` stylesheet parser,
- `lang/*.json`: JSON parsing,
- `scripts/*.sh`: `bash -n`,
- `scripts/generate_ha_migration.py`: Python bytecode compilation,
- `web/tailwind.input.css` semantic CSS section matches the committed `web/styles.css`,
- no `node_modules` directory is included,
- project-owned SQL remains centralized in `src/queries.rs`.
## Recommended LXC test
## Rust build
The packaging environment does not provide a working Cargo toolchain, so `cargo test --all-targets` and the release build were not executed here. On the target LXC, `scripts/install.sh` / `scripts/update.sh` run the Rust tests and release build before replacing the installed service.
## Expected LXC update
```bash
unzip gree-controller-v0.4.1.zip
cd gree-controller
sudo ./scripts/update.sh
sudo ./scripts/configure-gree-network.sh eth1
journalctl -u gree-controller -f
```
Expected request logs should show a concrete local address such as `10.87.65.27:<port>` rather than `0.0.0.0:<port>`.
## v0.3.8 legacy V1 bind compatibility
- Canonicalize the on-wire GREE device identifier to lowercase hexadecimal for `tcid` and inner `mac` fields.
- This specifically targets legacy V1 modules such as the `502cc6...` family which can answer discovery yet silently ignore bind packets when the identifier casing differs from the value returned by discovery.
- Database IDs, friendly names and stored MAC display values are unchanged.
- Existing V2/GCM crypto and the `eth1`/AF_NETLINK networking fixes are unchanged.
Runtime configuration and SQLite data remain under `/etc/gree-controller.env` and `/var/lib/gree-controller/` and are preserved by the updater.