# 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 ## Scope Version 0.3.6 fixes real-device binding failures observed on a mixed five-unit GREE network in a multi-NIC LXC. ### Protocol fixes - 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. ### Multi-NIC behavior - 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`). ## 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 | 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. ## Recommended LXC test ```bash 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:` rather than `0.0.0.0:`. ## 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.