From 08d0cea0161571d669c1c37eca42036b46a2ee49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Gruszczy=C5=84ski?= Date: Sun, 23 Aug 2026 22:31:30 +0200 Subject: [PATCH] v0.3.8 --- BUILD_REPORT.md | 26 ++++++++++++++++ Cargo.lock | 2 +- Cargo.toml | 2 +- FILE_MANIFEST.sha256 | 22 +++++++++----- README.md | 14 +++++++-- docs/LXC.md | 28 ++++++++++++++++-- .../__pycache__/__init__.cpython-313.pyc | Bin 0 -> 3081 bytes .../__pycache__/api.cpython-313.pyc | Bin 0 -> 5021 bytes .../__pycache__/climate.cpython-313.pyc | Bin 0 -> 13183 bytes .../__pycache__/config_flow.cpython-313.pyc | Bin 0 -> 2824 bytes .../__pycache__/const.cpython-313.pyc | Bin 0 -> 537 bytes .../__pycache__/coordinator.cpython-313.pyc | Bin 0 -> 2371 bytes .../__pycache__/entity_map.cpython-313.pyc | Bin 0 -> 2096 bytes .../gree_controller/manifest.json | 2 +- .../generate_ha_migration.cpython-313.pyc | Bin 0 -> 10796 bytes src/protocol/gree.rs | 19 +++++++++--- systemd/gree-controller.service | 2 +- 17 files changed, 97 insertions(+), 20 deletions(-) create mode 100644 home-assistant/custom_components/gree_controller/__pycache__/__init__.cpython-313.pyc create mode 100644 home-assistant/custom_components/gree_controller/__pycache__/api.cpython-313.pyc create mode 100644 home-assistant/custom_components/gree_controller/__pycache__/climate.cpython-313.pyc create mode 100644 home-assistant/custom_components/gree_controller/__pycache__/config_flow.cpython-313.pyc create mode 100644 home-assistant/custom_components/gree_controller/__pycache__/const.cpython-313.pyc create mode 100644 home-assistant/custom_components/gree_controller/__pycache__/coordinator.cpython-313.pyc create mode 100644 home-assistant/custom_components/gree_controller/__pycache__/entity_map.cpython-313.pyc create mode 100644 scripts/__pycache__/generate_ha_migration.cpython-313.pyc diff --git a/BUILD_REPORT.md b/BUILD_REPORT.md index 0916f4b..ca07ab3 100644 --- a/BUILD_REPORT.md +++ b/BUILD_REPORT.md @@ -1,3 +1,22 @@ +# 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 @@ -43,3 +62,10 @@ 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. diff --git a/Cargo.lock b/Cargo.lock index e75ee59..6435f68 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -633,7 +633,7 @@ dependencies = [ [[package]] name = "gree-controller" -version = "0.3.6" +version = "0.3.8" dependencies = [ "aes", "aes-gcm", diff --git a/Cargo.toml b/Cargo.toml index 93e1d15..554fdca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gree-controller" -version = "0.3.6" +version = "0.3.8" edition = "2021" authors = ["GREE Controller contributors"] description = "Standalone local GREE HVAC controller with Web UI, SQLite and Home Assistant sensor support" diff --git a/FILE_MANIFEST.sha256 b/FILE_MANIFEST.sha256 index a83f605..a2ce75b 100644 --- a/FILE_MANIFEST.sha256 +++ b/FILE_MANIFEST.sha256 @@ -1,24 +1,31 @@ 6b10bf7903a32a6cdd902d990911105589690deafe7da12e5b3b9c994c1fd4f6 ./.env.example 2fe1cf4e544fead5ae58436145a5b45e7a5a105143dfd815d28e307c94d5d19b ./.gitignore -d75023129d63417a5af399567944d99a65c4570e1cef671ba2f68fdd734fd8d1 ./BUILD_REPORT.md -baad3cddff5a160ac1e5f5200838c83bd1edc2a3d4dec09b95b8858a1a4bfeb7 ./Cargo.toml +1e1867ebd5cd1633d511a4a65853da9a2ef1c018dc4e66d823e20ae032e0d1a7 ./BUILD_REPORT.md +6b2eacdaf0a8f285fd832b39617e849e992fd3f6ab094f13da9c453c0c99b79d ./Cargo.toml 19b2943504acb8f8de280f873a8dbec4bb6ebbe3870b158f5655d4fb8c298f5f ./LICENSE -349344b41f5bb6680079c5ed95f6294c9c9df6a73bdbda452d351033abf4768a ./README.md +3c552aab65ddba02d79835f2cec13c9cde5328774503c53e8461fa54bce9cc41 ./README.md a4fa9bfee9735ed8ed95ea31456e0cce503d82502ae3f550108ffca51b0f0c3d ./build.rs 37453ecce2c7290ecae5ada4249cfd36bc70fb50c479aa680b74e4f1bc707251 ./docs/API.md 234dd200e380a13ecd3e61b4ea455f6f08d64ce89382077dee80684acadb9703 ./docs/HOME_ASSISTANT_MIGRATION.md 7a88d6e76fda21e5d34ab351e26bc10dc1f8f7b3055505aefad1df7c56d65ae4 ./docs/LOCALIZATION.md -456b65737d3b4579e40edba2655c0cb1a63620d8a7bfa0f8844acf81b21fc374 ./docs/LXC.md +3d754c7120a086654f2666cac510b10a76529aa849c012a85427b0472a3ac261 ./docs/LXC.md a728ddc324613671932bd83522155b09c7503d4fbcd0d04d8e217676ea9e10e4 ./docs/PROJECT_SPEC.md 33214270b96ac4c64e3db41c11e54158792b4a87ee5668c651bad571766b591a ./home-assistant/README.md f8e8559fe10fe523ac5bc9aac25c6e26e862f679d502e8f3c39f38a0a8e40911 ./home-assistant/custom_components/gree_controller/__init__.py +9151cd32bfcea786eb8a9af9ca11af775abdc6bf23b55d6a291b76433473eb2a ./home-assistant/custom_components/gree_controller/__pycache__/__init__.cpython-313.pyc +8c3753163d45895da5856525fe3e988a38c73bce4457b1358200453cc9a9ac2c ./home-assistant/custom_components/gree_controller/__pycache__/api.cpython-313.pyc +e0d8043f39885375cfecf8e82153a257f2166e5319e975dbbb648482ec77474e ./home-assistant/custom_components/gree_controller/__pycache__/climate.cpython-313.pyc +32097fe487c1c5fb428230d35a39f62c2bc17285036604315ec80545e8c185a5 ./home-assistant/custom_components/gree_controller/__pycache__/config_flow.cpython-313.pyc +05791fb1cb4345726506a20ef5b36d355e8235b8ccd46a81a2b8ce5b42e4c3f7 ./home-assistant/custom_components/gree_controller/__pycache__/const.cpython-313.pyc +bf1a90d03325dd37a86a05b586faf387bfd5a02732fd2c0e4d998369a13ba70f ./home-assistant/custom_components/gree_controller/__pycache__/coordinator.cpython-313.pyc +cc4f2ab07b1a641bdc36f3738280fa643baac617d753863c288e5788b1c3d455 ./home-assistant/custom_components/gree_controller/__pycache__/entity_map.cpython-313.pyc e0cf725c9f84be51cdbd83a5ab12b2b8288f90b36623cb4671cefcbf04378504 ./home-assistant/custom_components/gree_controller/api.py fde31b8e020fd36be2d9d9b1e554254f5da8a1cc593240ebb8d78820154dd790 ./home-assistant/custom_components/gree_controller/climate.py 5e4aef2143e81bedb5a15dd4be5c71b64a3ab448ec6d33a20851edd098e5f529 ./home-assistant/custom_components/gree_controller/config_flow.py e1821b74859bc40773a6ee39e6ccc9650980b62af50d6426b46cdb3e3a90d200 ./home-assistant/custom_components/gree_controller/const.py 2d27d7cb67c53e819b99a0302cd0bd339c27e3e2dfc85e07d30c31f505f740b5 ./home-assistant/custom_components/gree_controller/coordinator.py 5a96fe8f5c035c34f1339370270cd078056202d09e236dec75735be11de92a7d ./home-assistant/custom_components/gree_controller/entity_map.py -23fc6d9d7136492db8dc046e3f54c65070e5f65e1c6303ecab1bac5ef686661d ./home-assistant/custom_components/gree_controller/manifest.json +4e0f31984b94f3da7fd98e3804b591bbe1c79d2c05b04b7c4fb484a4caec587e ./home-assistant/custom_components/gree_controller/manifest.json 6bddb7b4620021ecd2099a86a77ef5c7f2c2dcd3d07d5db4e7b4c4ce6d3e8c03 ./home-assistant/custom_components/gree_controller/translations/en.json 13f30e2dcdcedbd1b6c3f99c2335e0487108fd72c8e86922368b84f2fa2038ae ./home-assistant/custom_components/gree_controller/translations/pl.json 4513070521d3dda0efb0d974a86ba674494cfb2b66fe9e5cac5b1b0430dede97 ./home-assistant/generated/gree_controller_entities.example.json @@ -26,6 +33,7 @@ e1821b74859bc40773a6ee39e6ccc9650980b62af50d6426b46cdb3e3a90d200 ./home-assista c604815c850574c573315306f368a8379ab87f5e2a99aca32be3131b05070afa ./lang/en.json 0b2d174258610440d5d4c2d6c5bec5ecc2528f41946bf7d59cc2206aab50ce58 ./lang/pl.json 09caaa48f9979f209b96e6d0feebbecda053b997c470a5d80abb80b7fb06a484 ./scripts/README.md +896caae04468f743d85d011638a0683253d8271c0db8365aea9bcdc646795cf1 ./scripts/__pycache__/generate_ha_migration.cpython-313.pyc be8c4bf17723d5e2e23e774a679ca75b02ab49825a93201237bf58cdd4974136 ./scripts/common.sh 6403786610ee6d2f628193c25aee0dd058d62e904aa1a31d5f62fdaae0e94b4f ./scripts/configure-gree-network.sh 054e6862857fd1d02dabedd977d4175c2011f451aba51b5d4fc3a3363e66e80f ./scripts/dev.sh @@ -45,11 +53,11 @@ f85cb4ba6435843431d93779aa0653fd24ec8987e06ef36efde096cbea321d7a ./src/home_ass 27eca87a9078aad7a7a4ef1fc39ce7ddaffcf05466acb995d571e0a35dfe898c ./src/main.rs a5923f8fb72ebac68c13e4767dd35012041e2783167969521e757bf502fafabd ./src/models.rs 7fc31fbf8841a073a1544b8c7a6390f1a15b56087486ca0596a8418340fa232a ./src/protocol/crypto.rs -53e6fdb575da4790cdf88013073b973461fb9ace362fbe51dda95c0eaadf2365 ./src/protocol/gree.rs +b66ae7c0186b6cc3939d922b0a83f763fd670662c170c97cebca8235d99f663c ./src/protocol/gree.rs a910bd9432a393740c0f6fab52bfcb551f0ea756718d66d290fd2610767cf07c ./src/protocol/mod.rs c80164631bba476db29469fa43b28d73f68412c06bafabe2143ab8d4cd330a52 ./src/queries.rs 521070a4c63bec73372cf4873f20c5fad23c37db4df7199bcc5bf6f6e566b3f6 ./src/state.rs -52aea29e17e7ce45ea10f7783be7278ecefe976141c5823360f10f0ea2bbcf33 ./systemd/gree-controller.service +b92a6cb158b494fe145b43c7641e65f6fafff47201d7d76edbec2cfd8b94835c ./systemd/gree-controller.service 9d05fe7219a4e9806239792169417d577c56a38bea4561e4064ae4cf41418257 ./web/app.js b6bba1e1e7127d06c885a9f8fffbf0becde339e0f2464da8b4725f11ddabe433 ./web/favicon.svg 45f0ddc583cf0ee3197dda5c72209f80389291e33c72a29e7555ebaa329819de ./web/index.html diff --git a/README.md b/README.md index 366a1b0..4eb2e66 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ 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.3.6**. +Current version: **0.3.8**. ## Highlights @@ -35,7 +35,7 @@ See [`BUILD_REPORT.md`](BUILD_REPORT.md) for package validation details and [`do On Debian, Ubuntu or an LXC container: ```bash -unzip gree-controller-v0.3.6.zip +unzip gree-controller-v0.3.8.zip cd gree-controller chmod +x scripts/*.sh ./scripts/dev.sh @@ -92,7 +92,7 @@ The selected appearance is stored in the `gree_controller_theme` cookie. The int 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.6 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. +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 @@ -318,3 +318,11 @@ 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. diff --git a/docs/LXC.md b/docs/LXC.md index 4f345ae..c723fcd 100644 --- a/docs/LXC.md +++ b/docs/LXC.md @@ -118,7 +118,7 @@ When the LXC has a management interface and a dedicated GREE network, configure GREE_CONTROLLER_GREE_INTERFACE=eth1 GREE_CONTROLLER_DISCOVERY_BROADCAST=auto -This explicit interface configuration is recommended for predictable LXC deployments. Version 0.3.6 also automatically selects the directly connected local IPv4 address for a GREE device when the interface variable is omitted; for example, a target in `10.87.65.0/25` selects the local address on that subnet. +This explicit interface configuration is recommended for predictable LXC deployments. Version 0.3.7 also automatically selects the directly connected local IPv4 address for a GREE device when the interface variable is omitted; for example, a target in `10.87.65.0/25` selects the local address on that subnet. GREE_CONTROLLER_SIMULATE=false GREE_CONTROLLER_AUTO_SEED=false ``` @@ -141,6 +141,30 @@ Use `scripts/network-debug.sh` for routing diagnostics. ## Mixed GREE model generations -Version 0.3.6 can discover both AES-ECB and AES-GCM modules. In the Web UI choose **Discover -> Auto (V1 + V2)** and use 3-5 scan passes. If a family is still missing, repeat with V1-only and V2-only to see which protocol its Wi-Fi module answers with. +Version 0.3.7 can discover both AES-ECB and AES-GCM modules. In the Web UI choose **Discover -> Auto (V1 + V2)** and use 3-5 scan passes. If a family is still missing, repeat with V1-only and V2-only to see which protocol its Wi-Fi module answers with. A single command/status timeout no longer immediately flips a device offline; offline requires three consecutive communication failures. + +## Multi-NIC LXC and AF_NETLINK + +When `GREE_CONTROLLER_GREE_INTERFACE` is set, the controller enumerates IPv4 addresses with Linux `getifaddrs()`. On Linux this requires a Netlink socket. The systemd sandbox therefore allows `AF_NETLINK` in addition to `AF_UNIX`, `AF_INET`, and `AF_INET6`. + +If an older unit reports: + +```text +getifaddrs failed +Address family not supported by protocol (os error 97) +``` + +update the systemd unit or add `AF_NETLINK` to `RestrictAddressFamilies`, then run: + +```bash +systemctl daemon-reload +systemctl restart gree-controller +``` + +For a dedicated GREE NIC such as `eth1`, the expected startup/bind log should identify the IPv4 address of that interface instead of `0.0.0.0`. + +### Legacy V1 devices discovered but not binding + +Version 0.3.8 sends the GREE protocol `tcid` and inner `mac` identifiers in canonical lowercase hexadecimal. If an older `502cc6...` device is discovered on UDP/7000 but stays offline after bind timeouts, update to v0.3.8 before changing routing or firewall settings. With debug logging, `Sending GREE request` should show `wire_mac=502cc6...` in lowercase. diff --git a/home-assistant/custom_components/gree_controller/__pycache__/__init__.cpython-313.pyc b/home-assistant/custom_components/gree_controller/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..679355cfd5cced40f1569e77511ed3e0002ef188 GIT binary patch literal 3081 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 Do)B-^ literal 0 HcmV?d00001 diff --git a/home-assistant/custom_components/gree_controller/__pycache__/climate.cpython-313.pyc b/home-assistant/custom_components/gree_controller/__pycache__/climate.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cff36f24daf34a1204b94519bea517e0a7f536f0 GIT binary patch literal 13183 zcmc&aYiu0nal7~2d+?6$=aF1KB=PvBL`t@(7cIU-illSPlN6Kk<-}W(CmrvYZ;z5l zI}Pigf#f)l4aBh&7&TS2kmRJXf~JYu28fLG5uo{T=Tm$1LUM(sLE(Q?r6g5~0-gDG z_a5XiGKw}?f^)O8^Ue3|eDlrBH~T%#%d;|YEq?B6XDzi1^K-n>F0+ELkI(2B=50n` z2qUn9Zj>F-5gm`XepFBN@M{<~j2MZL(u|{~5i>DU+%(FKScqlBN~|L`VjHm&JEfaP z^F|!RL2+)>Ig(HEM+!&*y|;`Ojueq1id#pEM@mQu#ciXdBW0wV;`Y&skxEiY@x0Nh z5f^b$+%Z}`QbTG0cMAEVwIe*?DPAyIH&RdPDPB0*Fw#gGd1hMg8PQ%f{aepW@9bff zd$McV?s+l&Ov8Zc(eU&yP$$!O8V1x88lL_I>Z$adh6zROM$$Ij<~glV(!V__TEv`S zPOy@`laX{q%rMN+63osbdn(_j8?!Ksjo}$dA7;Z0=@5#A5}{Nm6Uv1Op|agXI;T7T zk7Re%Fxh`XjZjs|oHdZ$xObHGt>G!h|!VAvmx5amrjMT3SX6+=W6)9UgpLE{Cn-yikE zLsS36Sl=ODY$G?Y4gFkd1wI8Z6aX23@HNeDPo`M5umYriiR_Tx7x)4@)d?*AHNTr4PfSP zGhQ~wI%LB7DU?Mok7{_@J^t1+UPfEuVM7NKHhT3QQznOkd$7k%m&dk=0JrI-Is9Mh za-0K+_N|;A=T@56lo|`?H95eo?$L!UUam=H^}o+BUd~gnwWXlbT57xj2g6LEGU+Ag zy_|#Dlj0ItufclbR%+8T)U=?Rs@!S*g+U%$#|jewKAxR$e$tV0DQ6%x3R48zDTb zTRuP+xWtPW7b6mQyEDtw(aoeC+i$owweiM7qo-_!(6HyY$d8ON6I4aJ8#{$R6uLRop{-ESP6B0X! zxDYw7h+QNw+Q^cmIN!_$;FducWei5)ZK#(8isH%eo-FfcM0jhE$gg6om&q?UH`1B?B&V!2EU>Hg~>X-rB zi7fbLA`6QUTEkJPV-BJP+-uRbLo>X^Ww}5ZvLr^A7IDyInH&N6&G0XM9-_^s%qp{C zXPP^b?%ue&cXjB#v*60BufKY=KjExf9bRv3Umbo}-I%QIj8}Iit9#qU*pqKJHp3PxcA%J|TAU3yHojfQfsr(~IZtk;(nZZP_S!VQkeFTV21b`PJETA!2JxRu&rB1O~1kcyXRUY3+jmra*<=tzb7TRC0j zd2VYlSti zI|iFvN>jsaqGs(PUy#Nl8w?5Y#(IK=L^Di!snB% zzO>_a`ux!-@ug#rRUw4^3!-eHp#q}-X6%v}nkDF(NiP7oh=>rbq-bWakS#vnObCL3 z&nMw{J-8;b zRX2xYwLO;%_c+&jWz8kS8_rK`H5(?Trt9nD8)n8{`xx3YGq_dJE>szvhBJUby3gcF z_dO}qYt0xYXPV38O7c6I9<_ZVbBi5!8x%#gfGpCEU=YA9mSCws!m;sGE3#Rg3b}e4 z%_uXqh|P8YSY;kMi;~XTxU)9tY>Yb_lg_5Nv*~8>2er3q@6;!p5Zw-vap26-0J?Rm z0Ti^!5FtH24H`PgrpyUC;+ZL&KYD?_)UcpY@Ye%Xg3TA!bu>L_W(~_vKQ5ah;ZQIv z4!Vt`A6h{Qb>1HgVNNI;&cGg!;FM5Jxph=Y1Q)A>I@Jsa>mPD$ZZ)N(MX{9|09eq! zIg2k}h&%bD^Z1`m-faA!^;T=Ld4Ifl|DEUVdK1l~i5jjvo?aU?2 zPNml66dD-4a;vIa*Tqhy)CIfE9J@au~{hE3O-7_Vpb}Jc@L9tNA zGH6nsDI>KX*&-vg@7(f)5zNmUVfwjo*+AWi0qZQXaRI6yp%n`)x?nX#=4OLr;esEk zBMkT%TQGobXErDjiM#}AmF)}u@X{4Fc^ehD@hu=}UR0~<(&X3})6 z$$BVzP=mUq8Wj2!#h}!+XVbhOR7B*u+=i9GauM4v0f04FQ1XuJE!QQ}eP_k}N`9^J zM#uGzSjFyG`JVd)#c!T?=cTt^S~Dd|b|p*p-|YV2@U6p%g5LFt+WUniZ_d7R_N}vP zWr1#mEJb49W)dG_;!NHmA*%peL5~Sgf^< zP4o}=CMSHuedG*M4Sn9p2{Hp{=Df+4`Sbo6A4=OU0Hqkdj%`N)WO#{nXUUb7%PUuR zt@R|G?zq!^zo_b+18*IO*=xapT=|2`fAH?i+Rhuz*PCyixP2l~e;`qF@JAPa{H4G8 zQo=bFys8mF`$%Rv1|*)aNA(t zIO=q~Z)|`%U|A0p7DfM`L+wCR)zTjhMNqwNlNoByzkv-gu47oQ#QpKR(pvY81J@5E z8}`H-_S_!5TaaitnyBr+JG-6I(1PenzzDM4O30kPpLWV1pbu3ehIN@h*09%ddcdCzkW!Uo(5?p~&5NL$_VJ-!fZ01vR(em4L zkrqms-`!R%hwd7aRfF-WK~#(PXU70+Rf`pxQ#08KhPs`ZK;&d{?HDp6sRyTd)0JsT z+PZpX8z{VJEAKP6G5jyu7`L_o2c7FJQc0g+Za2{sk9grt2W8_Imx561G(xI&CL$X{ z@O36CTVO{R^+}=#xtd&@+F_H7ZD>ITRoN<#%OH@vj^Jwu-T(mGDw^sIBH<(gy0_Zm zuS>;?QR4T}Dk|O12G1;EJ+(Er73Jn$1NjpA*9=eou(9dJ#Px~$bvxE(Z=Ah;_ICN5 zp2W_+MBNMbODeAJe6RUh^V-RqVxqD;QPT6-NRSr3S9z^+Z8TBQ`6$nf>7H3j_tY2& zV_+CutzW@f!cPHFzgzu3Y-FJxq4s(V62N&_2=(e~aU`3rTpK~H?zC0L z9K$i=yWpRG)gUi|FxV3|!;fr&!Z4(nvKeZ}knsnUJibIJ5v#=p_@Frp9~$P>U7~DW z^eV{uBRyjoWj3+( zobBTcA6A$U=UISR+w;`iqG6}z7TnL~3*AR&Dn;K$yGHuGNIy;pG@pc`!#Ck~OQgwD z^a=|#?2CluhTKadi|IDVk*WZw>bkOUdEx5GwZPShgrhadwI;aMr;lOJ%Dh%q$6jM= z4c{`={mx!=kX+04nvTpjn4OgypZ%V*vwwjv>e}+6V$9W=aI_`4wglJqlwh2h$y}nC zXVE442_Wh;vgwjvu6RK|eL_#Lv{G3bG*+)?Pj@=)$h8d9#l^7Bt3#8U+pZ_QS0@dpnNi3A=7 z%Y;fftVo$H_#Wg-Wz^ek9CNV#0Axv+$WsHg6~D{9XTN4o*c#UhOW$dGt8K09=8hQO znJDZ^+Ph-*u628%nt)#oCY()|4C^-M`!w0{jdo=1;OGpL{=I~ac8FZiy%^!*^*7?pgJ=r$+nCN zK=#C`UK%GZgGb&bZA(vG2J?@hLkUa8bn;4FSSPtx*Oe&UeaW_ND~;Rg)me%}NN8|R<4LxIT_}D)BRKn8{uRYhNXaAb*V-0^}1}yh7JqwK5JfxQ? z7PtKkRM%*mn=T<^L3>$Tv!7MZSdm`=emLo4!@Uu%3)m`AZL8sod%)I2jcbtRfhvlCF;eS z_OS1>U50O)_iUrUNsz57kjZ7p0@Rn%#=L*{S;_+Mq69Bc)hft_k`j$wXx*BMUIRQ! zMaAhCPj8Ln=HKS$QJraCOsJ%K02yH|R^4`UjdGYMR(JcBkRG zspl*x7Q@qO) za|sE@WRjaqaFb8T_ka(43d}e|h7iz{{TNa?<1cu)@0>PQ+6mYfja1`&fN~T)@4aYLDim%vdVN#W-F<^w!aEui& z%(vl({15^5LNJVI927SY8n0+yjg|3&4#T5Y$b($2IK;zU3&RS zvMZCc$!aCSVXMN)KF`p=WY+0QIu^`KWUF#$lj0=`K0M($_R_@oWZ!X`yvSxakclIg zIR%00VY%Av(&A!-;AhZT<&3AKeCy=k&?%J5qsz*k^#lxq1Q5(2z*4YcRp|2xwGL_w zSMc_m2)>2jj}iO{f*T0Fjo6#yD{#SC@p zX@WpztllWhGj=^J zY2PryFGwgZ+b|=>F*Qva7R0QK)$wZ^Vl|A(@mR+i4?Wfcwt*P5Fgbn&*chC$QHf(L zr9ReiMypB$Y@?XA)){+M8eq^1O3Xzw7{@hf@XX8p2ZNAS!l+Sz zi|#=K$wROgffd0%1O*7veyyAQ2ncYZz&E>upXYo&f=QEX4n^kXppq$@qRWf$OTDDb z<5{uPQL*;)8L@WtOc=q0O5XV_HfR|JS7E}jpi`i0ocbQwwYe>xu%<`L;5Zz854mUy z3&^60FLjZHn;*kRN7RH|p8Y_)I3q67qv6VNzLM<6^I`~AzeF$_B~93V)6i6gcIAu( z!MG*w$SFf*@ukiS;v~pTxp|is;S?gCw@aN%B!xJHmk|_WL!+X-5+pPuC`GCTK4Be) zNrNw}cktfqJ3cWqG~glUk>w`{{tm(4Bf!j(EFow`a2>%b2+(_zBM8vDK&q=hCoYq7 zfYTJEvs2mUaR-#Bc8L5tJVM7LVYPKb&$8^t%-}DW`kyn72TbWNnEk)j8Cl(92EZ@v z4BPWB%+Uu->jS3e0kiJ`v*!Wx;sfO0^?<2(!0di#El66cKC)I_9ZpzxteRoH0lK zt_qjL*U!dV4t|t(Xw|x2Sbo*J_Uaw(?&;Xc({abktG4yleaY5?@z#U)S`XiI9QmmA z@U^p7XD%(hz7lUe{E_3xs%^tm%hs)1%Qp1z`_NXpVT4~8TgAQ&Gh*N?tWPX}J?UqU x=pbp1x!PjwLvh#ePuqUUP|DNC6D;F6{PgFJBQ!bx3FqkFVfx8lM}Ldye*of(m^uIe literal 0 HcmV?d00001 diff --git a/home-assistant/custom_components/gree_controller/__pycache__/config_flow.cpython-313.pyc b/home-assistant/custom_components/gree_controller/__pycache__/config_flow.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08ffd28b830fdac18405d2c9b6053fb7de061034 GIT binary patch literal 2824 zcma)8O>7&-6`tk(km8R>Q52=fflQl%ZORTQRaRsve`RFKHsw$NH?-Z-!D3A=rFF?& zdUjWdgun<|pb*d=+!T&|$e{&tXoDPb%+Ypi#D^S6Fo2YSf(A&9!axr)WS|AwL*Fd9 zq%EXq7ucCM@4b0{JMWv_3k19fp4U(O=ITQMp&#hNdE9M++50UJH<5@i5*g98#AIFA z6{9q}#AZ3n*)+GrV*z;lk~{0c9-AjD^<}--3$$DGEcvp2?9T>pz+U$)^=E@Pm<{1j zb^s5=&87o0z>-aC>p7VF+h!yMHmC}f49mv4R+3f} zQz}(e;2VlzfQ!crHRK}EGgwi24$^fsgRzcDBY3k|IBfu5woysJDRKP>((` zvd_0&nnftd;}DqIn1pccS}8F(W|*>8maDp^?5|Z!)u^zfBr*N?xst0LkUdh)uMlGP z{tnzYia~&rNOKjKD_u%O-!s!$=Q~I3S+VGHc53W%);*5a z|7%_2iauvgG2l=Il<#-w-t73ibaJNiF*JS*75Mx>PsgF0=+8kbtb+C$bCb>Sey9xC z9(1&Nv&cHue{{!CPt&0s54Oc&hufP)u2<^c+jE7f zpx4-gsKU&$6(-TY5kCtpQ&nQ-sscTtnyOr-@S`cEHumVamdp_*wGmtaY%158hPGszSK3Y|5lxw!o-nswEqlh+oy#YhC?CMd1}&-Mi*Q$DL)kd6YMS-= zRBE5E`BSr}W&yw4Wu+opRg-X*pOpIxZ z5FRMCP6TYvnBEPzj}CA*Ai}N6hC$7*sU^iAgKeBN04FU?y=E!Y#h4^t(XlD1l^&CZ z-$tJ@3AZS2LXQ16Bu;ixa5QPZ8)pF>AEOV@ z_lM$}!nSXy={vL&9=dV$laXe0q7^>A6`pE_r&{6Zt?+y^JpaXXEBwah!cJuPw)d0y z=18&?No_@Dnvt1SWOg&NGnDvdB7JB4tHj+zYvTOFQfugEn~S?HZy>xKeess|JFOKx zvK2bg2p!q=py2~s(PT54Y@~kLil(p&qn{TVFTAqLqmk4uVn@O-41}M0QF!Rq=!c_!4GrG%f9U`CQX_S~8G7q$W2eLT zc`J16v-mF02Kx6{KJ48TcKrw(1>?r4fW~Z3FWfgCPJj8{SJ&@eZ=Jc=n!fnQvBo>K8^VpXkNW?$%TlF(8wIH7FViP8 zCz-pmgQw@vJuh>5hP&tEC>@Ld|6ZIqJ3&U9;qBM-r5ziVEFTRpE5$Aa+YqSuauILMAVsTh8I1fDtTd4}NgwAKVN4Mdk^jBYxFU1b7h2 zdQDcfLtaiS8k~w(b50l_t4k literal 0 HcmV?d00001 diff --git a/home-assistant/custom_components/gree_controller/__pycache__/const.cpython-313.pyc b/home-assistant/custom_components/gree_controller/__pycache__/const.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4c64ebf62a256423ac6bfdab063f2b39bd9e51dc GIT binary patch literal 537 zcmZ8eL2uJA7*^+p&-2*%2 z&Y2&Ub-H`eRa4I^aeFyv5e((F}>1-k0JFQ-oo0Dd)xZJGbT`n3jM z0R|jk1Dl7&JCmCbV2fKH&BWf)|L;SCx9}a_#x35#ZEoWZcb0bFxp*0{QpkBJ1^mP~ zlqVFvNf3hiT5^`>l*6~IpwJg0+wfpkO1k88nXz(k-Aw2k%AVzOsr7~GEjguRaidn& zisz~&*%>V_yjzcimNJtW6@yd3%IhX~-0!LmA;)Y%hh+P)ax$~4@#9Grhv_Cdjp zS2=yfcXcQIl|Ve#%OA@yjGrL*4W3>(kE(Xz)0o NSHs7bz~ehw_ZKnHpvM3J literal 0 HcmV?d00001 diff --git a/home-assistant/custom_components/gree_controller/__pycache__/coordinator.cpython-313.pyc b/home-assistant/custom_components/gree_controller/__pycache__/coordinator.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a4267f577e0ebadf0f015364084670574534fa26 GIT binary patch literal 2371 zcmaJ?TTC2f6h3p?*&8gEaxIrB7So9>loqVCmUasZbeC=o!#0gjC*$nwGR?4q{|t@v ziKsCeW1@*oYBaI>V5(30R{JEr=wm4+&=FIkX$)^vG_BDG&p*2hv_>bHv*$MFKmR%3 zIlEa=5e9r#+uph;2mrrOq5K4k46}I?nJb_G0fkZ66q95LD^Z?HaY>%=KF_BFBA`x4 z1(G5WeO(|GOom9v=fzYw86lBmltfVuDxp+GvXWFLV`U}{$%Qg6$ ztEH(CKhBx?1V)%gv0~JoG2)J6I<8i5W!9^sM`vcUnrjShpYKJBs$tEvjO;qS6Z+PV z5Cgr+$;4;P1R*x@c0H;ev`oW~-8z&Qj%UUuRAn%pR!^rV665FMW2%xEJewX;yui@e zGx5`Dy;zDOE!BnDJc{xQ*wrZ@40e`P7{Vzm;gvuJda<+3a4~q1$Bv2$k33HTia^8+ z9A`*yFUUc!>9M4?FSlNUu`eHa4lC-{n3f`|S$4s|7L+e1p-$2@9ea>9E}6O^p_^+s zT{^!bUkXl4nb~|EnE~bsOl}z`_zYaYUT2uetuH16Wpjp|43+swAL3L}n0^FszaYW+ zgVvUB9%PQTQgjT=FYCy>7qIMn-XI=d&}IxTifZh!id84`UTn_qrb?kgE@_r5dV(`I zi{3#Mm8Pqzo~VwU9T`cClL|bQ(ELagi5Jj|y%Rj%F|3@&Piv0j34UPGOg%!Xs#~a3 zRfhsu!e_xdF^#A?fZ8Igy7f87wP#e_o|(m}7F?%0kH|r}T;1*+SnryhCyg|8$A5OL ztDJZp`Z+yF9xlLIu;NW|DcHCgty-&XUaM|cZE9O<>HNMcwbU}U5rI(CeF%iY8tz$iTR7e3XorV7XJET^Atb? z^L5w)w-;b`Fkk zIYwsF9&2XhK(YT~aT**#K}+Zg_Bh8S9+x*YM?MS`FOuMUTt{;%k&=DNguaSrz%dRCNH zfNofps$%kO=SM#_FG5p$k`yMq+ z8y0Ryr>g|V9jl4Z87hHXn>CA=_gf+0fmn08H2odwg%JN^{!%6fsIrMB&(n^OPAb!y zd3KZUDT r!n<#WcV8V{4tFkyzXxh?;oOq?zR2D<{55~0|4VyG8vX;Q)<5kZ5NTI| literal 0 HcmV?d00001 diff --git a/home-assistant/custom_components/gree_controller/__pycache__/entity_map.cpython-313.pyc b/home-assistant/custom_components/gree_controller/__pycache__/entity_map.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..66d7f546448bea6d40d46a5ac0a45fad7e6d4d00 GIT binary patch literal 2096 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 String { + device.mac.replace([':', '-'], "").to_ascii_lowercase() + } + async fn bind_attempt(&self, device: &Device, version: u8) -> Result { let target = self.device_target(device)?; let target_hint = match target { SocketAddr::V4(addr) => Some(*addr.ip()), SocketAddr::V6(_) => None }; @@ -271,7 +280,8 @@ impl GreeClient { } } - let inner = json!({"mac": device.mac, "t": "bind", "uid": 0}); + let wire_mac = Self::wire_mac(device); + let inner = json!({"mac": wire_mac, "t": "bind", "uid": 0}); let generic_key = if version == 2 { GENERIC_GREE_V2_KEY } else { GENERIC_GREE_V1_KEY }; let response = self.request_on_socket(device, &inner, generic_key, true, version, &socket).await?; let kind = response.get("t").and_then(Value::as_str).unwrap_or_default(); @@ -309,7 +319,7 @@ impl GreeClient { } async fn status_request(&self, device: &Device, key: &str, cols: &[&str]) -> Result { - let inner = json!({"cols": cols, "mac": device.mac, "t": "status"}); + let inner = json!({"cols": cols, "mac": Self::wire_mac(device), "t": "status"}); self.request(device, &inner, key, false, device.protocol_version).await } @@ -382,11 +392,12 @@ impl GreeClient { let target = self.device_target(device)?; let version = if protocol_version == 2 { 2 } else { 1 }; let inner_bytes = serde_json::to_vec(inner)?; + let wire_mac = Self::wire_mac(device); let mut outer = json!({ "cid": "app", "i": if binding { 1 } else { 0 }, "t": "pack", - "tcid": device.mac, + "tcid": wire_mac, "uid": 0 }); if version == 2 { @@ -397,7 +408,7 @@ impl GreeClient { outer["pack"] = json!(encrypt_v1(key, &inner_bytes)?); } let payload = serde_json::to_vec(&outer)?; - tracing::debug!(target=%target, local=%socket.local_addr()?, protocol=version, interface=%self.interface.as_deref().unwrap_or("auto"), binding, "Sending GREE request"); + tracing::debug!(target=%target, local=%socket.local_addr()?, protocol=version, wire_mac=%wire_mac, interface=%self.interface.as_deref().unwrap_or("auto"), binding, "Sending GREE request"); socket.send_to(&payload, target).await?; let deadline = Instant::now() + Duration::from_secs(4); diff --git a/systemd/gree-controller.service b/systemd/gree-controller.service index 6d85089..3949391 100644 --- a/systemd/gree-controller.service +++ b/systemd/gree-controller.service @@ -18,7 +18,7 @@ PrivateTmp=true ProtectSystem=strict ProtectHome=true ReadWritePaths=/var/lib/gree-controller -RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 +RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK LockPersonality=true MemoryDenyWriteExecute=true