This commit is contained in:
Mateusz Gruszczyński
2026-09-04 13:44:18 +02:00
parent 2882fd3523
commit 63e6e13a5d
16 changed files with 89 additions and 53 deletions
Generated
+1 -1
View File
@@ -700,7 +700,7 @@ dependencies = [
[[package]] [[package]]
name = "gree-controller" name = "gree-controller"
version = "0.13.5" version = "0.13.6"
dependencies = [ dependencies = [
"aes", "aes",
"aes-gcm", "aes-gcm",
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "gree-controller" name = "gree-controller"
version = "0.13.5" version = "0.13.6"
edition = "2021" edition = "2021"
authors = ["GREE Controller contributors"] authors = ["GREE Controller contributors"]
description = "Standalone local GREE HVAC controller with Web UI, SQLite and Home Assistant sensor support" description = "Standalone local GREE HVAC controller with Web UI, SQLite and Home Assistant sensor support"
+29 -32
View File
@@ -1,14 +1,15 @@
d56cfff4179a6511aa764a91c6ddebe21fcd35f36b7298e62d012e11f62bfeb9 ./build.rs
b0270ac12ff6e0a9c8ab4325065ddd36eb7d432dc8f59293dd86591d4fa02015 ./Cargo.lock
d6ba6362369bfa0fedab8e95bf0fe2839270dbb8a9f4c13a78bddb5450262a55 ./Cargo.toml
ceafb0ec649a7a7ea0c469501dab144743306150c15869f3a084bab3ce47f51d ./data/gree-controller.db
237eab440e33eb7f88173a143112b90c4343d9272720068640e289d63220d415 ./docs/API.md
2e1e18fd8167dabfe2469c26e85cce62486c7cb6a502c63c6f6b0cd74d5885e0 ./docs/FLOW.md
4e747f2e3e2cbe7d20b0da76556035d7bc4bd80f789f61522e1a214c56f5c35c ./docs/openapi.json
d67af429e4da9ce08e9d2f2a8472849ffbd70d135b1c5da535a076026794d04c ./.env
d67af429e4da9ce08e9d2f2a8472849ffbd70d135b1c5da535a076026794d04c ./.env.example d67af429e4da9ce08e9d2f2a8472849ffbd70d135b1c5da535a076026794d04c ./.env.example
a4ec3874a2e3ab1bad28fb40bb620f7b01f64d01ad9b699306bf70ada31227db ./.gitignore a4ec3874a2e3ab1bad28fb40bb620f7b01f64d01ad9b699306bf70ada31227db ./.gitignore
2fbfbfeb87b04b364464269c190979bab48ee79bc6abff5c7b2292c61fddc8bd ./gree-controller.zip 174b5c57813e07375723f80f92772d965b1b434c02881d916c89efac0b61ee7e ./Cargo.lock
dc8d8412b74e19f2d32570ca0ef176c0036a140e47e41d020cb4d140ad9bfe39 ./Cargo.toml
19b2943504acb8f8de280f873a8dbec4bb6ebbe3870b158f5655d4fb8c298f5f ./LICENSE
079ddac7ba983a3d679b8c748bd43c731eb078e91a40c5d8a683bd76e14f06c5 ./README.md
d56cfff4179a6511aa764a91c6ddebe21fcd35f36b7298e62d012e11f62bfeb9 ./build.rs
514065eefa7428afbcacaca7095605495f95339a2ae8b23707315dc434f9c4c5 ./docs/API.md
2e1e18fd8167dabfe2469c26e85cce62486c7cb6a502c63c6f6b0cd74d5885e0 ./docs/FLOW.md
cb62e2ea377bdf4785c139ee169eec4914e04ceac6883c0afcb4c96fe60427b0 ./docs/openapi.json
b11e581dd916676e24402112fe6896bc681abf3c94cafc85c4d3ded3f3a272a3 ./home-assistant/README.md
f8e8559fe10fe523ac5bc9aac25c6e26e862f679d502e8f3c39f38a0a8e40911 ./home-assistant/custom_components/gree_controller/__init__.py
3f6ef15ef58456376ac53fde7cace1ef359d6a6f7a64c5b575ad77ea6e55ccc4 ./home-assistant/custom_components/gree_controller/api.py 3f6ef15ef58456376ac53fde7cace1ef359d6a6f7a64c5b575ad77ea6e55ccc4 ./home-assistant/custom_components/gree_controller/api.py
71c8058f85fd9ce9f063b7a84dcf2956f23cdbbd02bd4bd99d2fbb9d177c72ad ./home-assistant/custom_components/gree_controller/climate.py 71c8058f85fd9ce9f063b7a84dcf2956f23cdbbd02bd4bd99d2fbb9d177c72ad ./home-assistant/custom_components/gree_controller/climate.py
5e4aef2143e81bedb5a15dd4be5c71b64a3ab448ec6d33a20851edd098e5f529 ./home-assistant/custom_components/gree_controller/config_flow.py 5e4aef2143e81bedb5a15dd4be5c71b64a3ab448ec6d33a20851edd098e5f529 ./home-assistant/custom_components/gree_controller/config_flow.py
@@ -16,9 +17,8 @@ b7f0873109c52be9d7f09bea3dffc416103c50085e1f0680d11661a969479898 ./home-assista
41a8958a6fe6d10e5679c95ac34832583a2a15ecfd67d09b4e094a83d06f5c47 ./home-assistant/custom_components/gree_controller/coordinator.py 41a8958a6fe6d10e5679c95ac34832583a2a15ecfd67d09b4e094a83d06f5c47 ./home-assistant/custom_components/gree_controller/coordinator.py
5a96fe8f5c035c34f1339370270cd078056202d09e236dec75735be11de92a7d ./home-assistant/custom_components/gree_controller/entity_map.py 5a96fe8f5c035c34f1339370270cd078056202d09e236dec75735be11de92a7d ./home-assistant/custom_components/gree_controller/entity_map.py
c4fb75c246db651087900ebfc2291ff41ac87652cd6194fc0b776b0005c1cbcf ./home-assistant/custom_components/gree_controller/icon.png c4fb75c246db651087900ebfc2291ff41ac87652cd6194fc0b776b0005c1cbcf ./home-assistant/custom_components/gree_controller/icon.png
f8e8559fe10fe523ac5bc9aac25c6e26e862f679d502e8f3c39f38a0a8e40911 ./home-assistant/custom_components/gree_controller/__init__.py
c4fb75c246db651087900ebfc2291ff41ac87652cd6194fc0b776b0005c1cbcf ./home-assistant/custom_components/gree_controller/logo.png c4fb75c246db651087900ebfc2291ff41ac87652cd6194fc0b776b0005c1cbcf ./home-assistant/custom_components/gree_controller/logo.png
aa1384a3152f133bd2d4f9cabe0118820d68936d43c05b2ef8af9e51e955d000 ./home-assistant/custom_components/gree_controller/manifest.json 5d8a5f7be7e11b385d7c22a10dedce418c809e5d737e3a402ee21c7e2a5ae316 ./home-assistant/custom_components/gree_controller/manifest.json
38d659d0273c0d1428679e44574a2666c605d1b3796d323b626baa40560788cf ./home-assistant/custom_components/gree_controller/number.py 38d659d0273c0d1428679e44574a2666c605d1b3796d323b626baa40560788cf ./home-assistant/custom_components/gree_controller/number.py
39c4309001b75abb56234f05662bc06e077054986876f1927937edbce528ec95 ./home-assistant/custom_components/gree_controller/select.py 39c4309001b75abb56234f05662bc06e077054986876f1927937edbce528ec95 ./home-assistant/custom_components/gree_controller/select.py
cca65482e36d48035aca178121a378fe7d578d600acff267ae81a6399c0da653 ./home-assistant/custom_components/gree_controller/sensor.py cca65482e36d48035aca178121a378fe7d578d600acff267ae81a6399c0da653 ./home-assistant/custom_components/gree_controller/sensor.py
@@ -26,11 +26,9 @@ cca65482e36d48035aca178121a378fe7d578d600acff267ae81a6399c0da653 ./home-assista
6bddb7b4620021ecd2099a86a77ef5c7f2c2dcd3d07d5db4e7b4c4ce6d3e8c03 ./home-assistant/custom_components/gree_controller/translations/en.json 6bddb7b4620021ecd2099a86a77ef5c7f2c2dcd3d07d5db4e7b4c4ce6d3e8c03 ./home-assistant/custom_components/gree_controller/translations/en.json
13f30e2dcdcedbd1b6c3f99c2335e0487108fd72c8e86922368b84f2fa2038ae ./home-assistant/custom_components/gree_controller/translations/pl.json 13f30e2dcdcedbd1b6c3f99c2335e0487108fd72c8e86922368b84f2fa2038ae ./home-assistant/custom_components/gree_controller/translations/pl.json
c5fc5c87273d82d2834a0a5a365c821a416413ed509613441e24e4dc3507c4d2 ./home-assistant/generated/gree_controller_entities.example.json c5fc5c87273d82d2834a0a5a365c821a416413ed509613441e24e4dc3507c4d2 ./home-assistant/generated/gree_controller_entities.example.json
b11e581dd916676e24402112fe6896bc681abf3c94cafc85c4d3ded3f3a272a3 ./home-assistant/README.md
bb280ce427875526f5a1e35a2fad9586615bf684929212476297d32c55a68771 ./lang/en.json
eb1616b13468caa683e6280ffd0fe00f760406cc25cf9f71751461962a23b774 ./lang/pl.json
253a0bc912786e67ea7fc92a64e4a510ad973bec343a88ccfb1f28fca3e8cf01 ./lang/README.md 253a0bc912786e67ea7fc92a64e4a510ad973bec343a88ccfb1f28fca3e8cf01 ./lang/README.md
19b2943504acb8f8de280f873a8dbec4bb6ebbe3870b158f5655d4fb8c298f5f ./LICENSE 00cd78873d3a3290419a83ea736a9ec5f0d93f590159cbf40c54d5ea6c3c89fb ./lang/en.json
a088acc585a863e204100af7f5465a5d761ba94c0afff66b5ed329e7d204ec35 ./lang/pl.json
d8459024f04ca514bd8e9d6bd3af872fb942fd85a7cdd5583f4a9d28aab6faba ./make_zip.py d8459024f04ca514bd8e9d6bd3af872fb942fd85a7cdd5583f4a9d28aab6faba ./make_zip.py
b14233a8987e53bbbdd6770386ba10fa166ec25c1e098275c173c544b37846fc ./presets/bedroom_window_night.json b14233a8987e53bbbdd6770386ba10fa166ec25c1e098275c173c544b37846fc ./presets/bedroom_window_night.json
1960841119c0b673fb2f03621b32237552fd828045304cd221401214b997c910 ./presets/device_resilience.json 1960841119c0b673fb2f03621b32237552fd828045304cd221401214b997c910 ./presets/device_resilience.json
@@ -69,9 +67,9 @@ fffa18bd989a0dcc1c5458975522517d40af4af40cc1ca30640e79d3db711053 ./presets/unoc
ae21459a261712bcb8d57594528b1648432e8d03a8a38502234829c0dbfef774 ./presets/weekend_comfort.json ae21459a261712bcb8d57594528b1648432e8d03a8a38502234829c0dbfef774 ./presets/weekend_comfort.json
fdcd9a5055d08037278b842e7ab69265345c5811f0a06867136c511d140bb191 ./presets/window_available_guard.json fdcd9a5055d08037278b842e7ab69265345c5811f0a06867136c511d140bb191 ./presets/window_available_guard.json
804f22123cd3e8db0fac791826c8dd9f758fb866c8e3b5655fb6d25d259dccf1 ./presets/workday_comfort.json 804f22123cd3e8db0fac791826c8dd9f758fb866c8e3b5655fb6d25d259dccf1 ./presets/workday_comfort.json
4c529802f159c34cab82585a537d6c193940d8ddbd14a07076bd13ba2d9fcf54 ./README.md
01952aa92b217f8eae2493b88870e2dec595100cd15c4d561ff11ae2b936c46f ./regenerate-sha.sh 01952aa92b217f8eae2493b88870e2dec595100cd15c4d561ff11ae2b936c46f ./regenerate-sha.sh
a937b937c8ac39d9b01e791b405f9c996314f5a563946bae94c3cbbefecc3411 ./scripts/api_dev_test.py c64b1c6deeb24f20af662bfce7fa3683703914987241107ce664fa2f6d1a9dcb ./scripts/README.md
0e734dd7cdb8fa6226e31a96927861b44a41e75dea27f27ff4a539002d5bcf35 ./scripts/api_dev_test.py
5bc736c7bc76ca80aaa406bb171d2aa91baf4c3aa8695dce0e09b888b6ab3146 ./scripts/common.sh 5bc736c7bc76ca80aaa406bb171d2aa91baf4c3aa8695dce0e09b888b6ab3146 ./scripts/common.sh
6403786610ee6d2f628193c25aee0dd058d62e904aa1a31d5f62fdaae0e94b4f ./scripts/configure-gree-network.sh 6403786610ee6d2f628193c25aee0dd058d62e904aa1a31d5f62fdaae0e94b4f ./scripts/configure-gree-network.sh
1d6e14e26e49aa9d3527f30a23668bf8d9c48b67e6628ef686c3155c012155de ./scripts/dev.sh 1d6e14e26e49aa9d3527f30a23668bf8d9c48b67e6628ef686c3155c012155de ./scripts/dev.sh
@@ -80,11 +78,11 @@ e4849261fd9ed1f01df96c0637c439c0c4eff8fa317b2918026167bba343af79 ./scripts/inst
bb7cd2c5b27c9dceec1d1d2846fbad9600df9c08e0ad07d13fcde97af533091c ./scripts/install.sh bb7cd2c5b27c9dceec1d1d2846fbad9600df9c08e0ad07d13fcde97af533091c ./scripts/install.sh
2af0a1390e69330acb6d62bafefafd3f33088b712867f9b1fc2f8604e2f253cd ./scripts/live_realtime_test.js 2af0a1390e69330acb6d62bafefafd3f33088b712867f9b1fc2f8604e2f253cd ./scripts/live_realtime_test.js
e00d211e3885e30d7fed1e43b44e6fdad40a67019060156c0641816a93e3365f ./scripts/network-debug.sh e00d211e3885e30d7fed1e43b44e6fdad40a67019060156c0641816a93e3365f ./scripts/network-debug.sh
c64b1c6deeb24f20af662bfce7fa3683703914987241107ce664fa2f6d1a9dcb ./scripts/README.md
01952aa92b217f8eae2493b88870e2dec595100cd15c4d561ff11ae2b936c46f ./scripts/regenerate-sha.sh 01952aa92b217f8eae2493b88870e2dec595100cd15c4d561ff11ae2b936c46f ./scripts/regenerate-sha.sh
81345b6a0b51736bdbc98fd23199b62e4c721b4e7437e02dab7ea79b97dff29a ./scripts/service.sh 81345b6a0b51736bdbc98fd23199b62e4c721b4e7437e02dab7ea79b97dff29a ./scripts/service.sh
7e8f558b284362f55f50bd7223a89754a2a4960e746a27035cc61180f4a2da6f ./scripts/smoke.sh 7e8f558b284362f55f50bd7223a89754a2a4960e746a27035cc61180f4a2da6f ./scripts/smoke.sh
b50782b3742dfbf8a319c60571c968e93fdf8547db747c759edcffae68cb98bf ./scripts/update.sh b50782b3742dfbf8a319c60571c968e93fdf8547db747c759edcffae68cb98bf ./scripts/update.sh
4b795bcb2e6b73c0dc9687325f6ffb0e6f008c6694b2a9fb8190a45a563451b2 ./src/api.rs
5027797b9cefb9f0aa04c792e2ac9a38745c6bf1ee822f50eb70574fa6f997e2 ./src/api/assets.rs 5027797b9cefb9f0aa04c792e2ac9a38745c6bf1ee822f50eb70574fa6f997e2 ./src/api/assets.rs
05c255919f7b3d81188fc5f1410be6a0037471dfc44e93bffb009f29a1e6a3fc ./src/api/auth.rs 05c255919f7b3d81188fc5f1410be6a0037471dfc44e93bffb009f29a1e6a3fc ./src/api/auth.rs
9e4fc675306e111ed3db7af9822e2925d88109c31b9e309851665a975c0bd83c ./src/api/automations.rs 9e4fc675306e111ed3db7af9822e2925d88109c31b9e309851665a975c0bd83c ./src/api/automations.rs
@@ -100,13 +98,13 @@ e8edfbb725d6de650442444b0a929ad2be0bd2c2d7d227d2b3fdd99d05c94f94 ./src/api/hous
6bfbe5135d4f93bd8d19a707877b53ed2029fd8490b4b1954a7520888fb1d664 ./src/api/middleware.rs 6bfbe5135d4f93bd8d19a707877b53ed2029fd8490b4b1954a7520888fb1d664 ./src/api/middleware.rs
45e34a447ff384d99a3c42c489ca9fa75849c74d4d246caa91c63d927de17396 ./src/api/openapi.rs 45e34a447ff384d99a3c42c489ca9fa75849c74d4d246caa91c63d927de17396 ./src/api/openapi.rs
744ce18aa9e0227c6cdfb6980063d0d738d74c5865d45c20fd20026d4742bb3e ./src/api/public_settings.rs 744ce18aa9e0227c6cdfb6980063d0d738d74c5865d45c20fd20026d4742bb3e ./src/api/public_settings.rs
4b795bcb2e6b73c0dc9687325f6ffb0e6f008c6694b2a9fb8190a45a563451b2 ./src/api.rs
5b29f2e5aa2c422c5829ef89c7b59cf753883aa7f60661c95ab0f95cf676fa3f ./src/api/schedules.rs 5b29f2e5aa2c422c5829ef89c7b59cf753883aa7f60661c95ab0f95cf676fa3f ./src/api/schedules.rs
9d157e1901081c077e32430d5d4d7f328ffb4933996579f584ce2959d5d10f47 ./src/api/settings.rs 9d157e1901081c077e32430d5d4d7f328ffb4933996579f584ce2959d5d10f47 ./src/api/settings.rs
df3297f36f0d0fa071b872967c5c124ed3887805d4f0f1031761cfba25331e97 ./src/api/system.rs df3297f36f0d0fa071b872967c5c124ed3887805d4f0f1031761cfba25331e97 ./src/api/system.rs
badd52159fa5d19c236cf9022b623d15c6fbfc7f0b7fc59e269717eb5ee3d10b ./src/api/websocket.rs badd52159fa5d19c236cf9022b623d15c6fbfc7f0b7fc59e269717eb5ee3d10b ./src/api/websocket.rs
455c7238c9788d378e909a4fbc94d5390b67edd92e127f48b4b913ddcbe82fb0 ./src/api/zones.rs 455c7238c9788d378e909a4fbc94d5390b67edd92e127f48b4b913ddcbe82fb0 ./src/api/zones.rs
f06014454d5062b1be17ac50d875a42c02fc778b59702ec455611265ab7de934 ./src/config.rs f06014454d5062b1be17ac50d875a42c02fc778b59702ec455611265ab7de934 ./src/config.rs
e0340b0e5945d5a38a1054e549c819566d5c1ef6034ab0e4d44c68a3b9a249cf ./src/db.rs
6c278fc5728124ab2f53ac7789a733942a0462f397144a231cc878c8cfcf7426 ./src/db/climate.rs 6c278fc5728124ab2f53ac7789a733942a0462f397144a231cc878c8cfcf7426 ./src/db/climate.rs
be4082b142fe16ba40c5978b287b7ef808e67c13edbd8f2d6637ccad974b8847 ./src/db/configuration.rs be4082b142fe16ba40c5978b287b7ef808e67c13edbd8f2d6637ccad974b8847 ./src/db/configuration.rs
bc10f1a66ddcaacbb08b096a02998482da547024dd0ba3144d00f993b4351cb0 ./src/db/core_devices.rs bc10f1a66ddcaacbb08b096a02998482da547024dd0ba3144d00f993b4351cb0 ./src/db/core_devices.rs
@@ -114,10 +112,10 @@ bc10f1a66ddcaacbb08b096a02998482da547024dd0ba3144d00f993b4351cb0 ./src/db/core_
eb07d94b58bcc8ea17b5b086cc88c165a35666f84c3d9a1d74f72dc30b979829 ./src/db/events_tokens.rs eb07d94b58bcc8ea17b5b086cc88c165a35666f84c3d9a1d74f72dc30b979829 ./src/db/events_tokens.rs
bb5048ee60053f39ce3c1203dc1f24c7047310538d2357f105a052c016d21ec4 ./src/db/flows.rs bb5048ee60053f39ce3c1203dc1f24c7047310538d2357f105a052c016d21ec4 ./src/db/flows.rs
5f4b567c6bc866d0674b3b0c66f4aeccf561774623f575b872ff25bf015b91c2 ./src/db/ha_history.rs 5f4b567c6bc866d0674b3b0c66f4aeccf561774623f575b872ff25bf015b91c2 ./src/db/ha_history.rs
e0340b0e5945d5a38a1054e549c819566d5c1ef6034ab0e4d44c68a3b9a249cf ./src/db.rs
c0a7fa3eac198737d7261ad00c542a614e6d7291f6581af8e7f7aef9dec1a049 ./src/db/schedules_automations.rs c0a7fa3eac198737d7261ad00c542a614e6d7291f6581af8e7f7aef9dec1a049 ./src/db/schedules_automations.rs
1a209dc6d8df864778bb03c980f309a2ec86fc62df274880fbb95eff8470174e ./src/db/tests.rs 1a209dc6d8df864778bb03c980f309a2ec86fc62df274880fbb95eff8470174e ./src/db/tests.rs
f90fbb14f29a20b799b3856bdaa22812a9f0d9dfa46693f1341c160dccda8a97 ./src/db/zone_history.rs f90fbb14f29a20b799b3856bdaa22812a9f0d9dfa46693f1341c160dccda8a97 ./src/db/zone_history.rs
4d2c6053586558afbca6b60fbbc9b1cd397f74f8284d7c01f3337eb42bf6d4f7 ./src/engine.rs
6046bdbc9c02ac74f47068229c59af69abc8bfa46cfeff6fe7ba573b493e128c ./src/engine/automations.rs 6046bdbc9c02ac74f47068229c59af69abc8bfa46cfeff6fe7ba573b493e128c ./src/engine/automations.rs
88f85acf692e12c7061e039dd7c54f101fe0b014c4a3d799150ad92eea9e2894 ./src/engine/commands.rs 88f85acf692e12c7061e039dd7c54f101fe0b014c4a3d799150ad92eea9e2894 ./src/engine/commands.rs
8ee70ad21d8ee32914dd90952b04dfa8355ee868252ef4fc682ec40503590a7a ./src/engine/control_plan.rs 8ee70ad21d8ee32914dd90952b04dfa8355ee868252ef4fc682ec40503590a7a ./src/engine/control_plan.rs
@@ -127,7 +125,6 @@ f0c8f3384b6174771aeb5640ee1eec87f3d6d9ff79a4fbd6a35554a4eec00cfa ./src/engine/h
41b7045877771b7c352328998cb45ce2433e7f9631fad3eb1a882ab4897dc31f ./src/engine/local_thermostat.rs 41b7045877771b7c352328998cb45ce2433e7f9631fad3eb1a882ab4897dc31f ./src/engine/local_thermostat.rs
6280a7f5059d9737987bf2d72b19a26b3a6709ce578af1108c4215f3f47d7763 ./src/engine/ownership.rs 6280a7f5059d9737987bf2d72b19a26b3a6709ce578af1108c4215f3f47d7763 ./src/engine/ownership.rs
3d7e74a8180e14f398363af1a45b32a5e4c89f749d631afce556a1ecd5fe4e80 ./src/engine/polling.rs 3d7e74a8180e14f398363af1a45b32a5e4c89f749d631afce556a1ecd5fe4e80 ./src/engine/polling.rs
4d2c6053586558afbca6b60fbbc9b1cd397f74f8284d7c01f3337eb42bf6d4f7 ./src/engine.rs
f0bcd3a56b600944ccc62fa24ce20838033eeb4354f937cdb534630c1a1f5a78 ./src/engine/runtime.rs f0bcd3a56b600944ccc62fa24ce20838033eeb4354f937cdb534630c1a1f5a78 ./src/engine/runtime.rs
c1e8de5392681ba1255e3e2d871a6ee860fb8ca987a0a8f973d9ded3977a68fb ./src/engine/schedules.rs c1e8de5392681ba1255e3e2d871a6ee860fb8ca987a0a8f973d9ded3977a68fb ./src/engine/schedules.rs
b0189f28d0f337dfd3ce0934da7a565e4a5535afc1c242214c26ed584b3b7840 ./src/engine/targets.rs b0189f28d0f337dfd3ce0934da7a565e4a5535afc1c242214c26ed584b3b7840 ./src/engine/targets.rs
@@ -138,25 +135,26 @@ c89ff36c6a67bf4fbf68c43e18aa0a556de2dc69263fd79db376363afc741a4f ./src/engine/z
dd38a8b8f6e910e4475c42ae41eaad2c68237fb36b78a3d7dd5d147c08487568 ./src/engine/zone_control.rs dd38a8b8f6e910e4475c42ae41eaad2c68237fb36b78a3d7dd5d147c08487568 ./src/engine/zone_control.rs
2276aca42bca712a55de9b6c5dbe64639675c84befa85a446a7d34613596ed7e ./src/error.rs 2276aca42bca712a55de9b6c5dbe64639675c84befa85a446a7d34613596ed7e ./src/error.rs
2731f629f22a9d4fdb831ea3b283f43900b190f7e6a08fdab5b8fbb2c288547b ./src/home_assistant.rs 2731f629f22a9d4fdb831ea3b283f43900b190f7e6a08fdab5b8fbb2c288547b ./src/home_assistant.rs
342dcb54caf22d2282a3f3f2297f54bd413b5242c17756276ea74994e88e28fb ./src/influxdb.rs
da4068295f37c23222bb13bebac022d88ba7729604a49ad25438c55e45458a49 ./src/influxdb/codec.rs da4068295f37c23222bb13bebac022d88ba7729604a49ad25438c55e45458a49 ./src/influxdb/codec.rs
1769e2a96e336bf39b28ae9de02a5d942350afa2bb9702df7603fabe9d7fcba7 ./src/influxdb/query.rs 1769e2a96e336bf39b28ae9de02a5d942350afa2bb9702df7603fabe9d7fcba7 ./src/influxdb/query.rs
342dcb54caf22d2282a3f3f2297f54bd413b5242c17756276ea74994e88e28fb ./src/influxdb.rs
29dc8ed02dfa1f6419bf4aedfb99c805b25c8a2e772efef20681c750570928cf ./src/influxdb/write.rs 29dc8ed02dfa1f6419bf4aedfb99c805b25c8a2e772efef20681c750570928cf ./src/influxdb/write.rs
9ec1bc25ebd06cc925e4fddc8b49e189a21ae495c6709c8cb1bba5b4dfa35388 ./src/main.rs 9ec1bc25ebd06cc925e4fddc8b49e189a21ae495c6709c8cb1bba5b4dfa35388 ./src/main.rs
23688a5cb68efded89471ce959328d27adff370d451bd9f378a283ab51437e76 ./src/models.rs
920e028d96a14cca9f74a964bb296e68a109cfead314d3164c180201e606d151 ./src/models/automation.rs 920e028d96a14cca9f74a964bb296e68a109cfead314d3164c180201e606d151 ./src/models/automation.rs
3c3f344fe42cdde980b13dbec6e92ed0e2f5946cba8ac19b1a668846b48e7c81 ./src/models/control_plan.rs 3c3f344fe42cdde980b13dbec6e92ed0e2f5946cba8ac19b1a668846b48e7c81 ./src/models/control_plan.rs
9cd1904a0f822c557f6ad4576cdb5f96d9668d04e79ea9783885c9f39519752e ./src/models/defaults.rs 9cd1904a0f822c557f6ad4576cdb5f96d9668d04e79ea9783885c9f39519752e ./src/models/defaults.rs
f935d35b4a409f12774209f3fa2ffe60f579a8bc1722badbb27d4766efd6368e ./src/models/device.rs f935d35b4a409f12774209f3fa2ffe60f579a8bc1722badbb27d4766efd6368e ./src/models/device.rs
aeab5b5acf35d38a54fd1d82e964fe56635ade69c0149ad423df317095d01555 ./src/models/flow.rs aeab5b5acf35d38a54fd1d82e964fe56635ade69c0149ad423df317095d01555 ./src/models/flow.rs
cf63af00d98410a1452f205ce00b8a6c5f0f3525b994cba3e971d631db288396 ./src/models/history.rs cf63af00d98410a1452f205ce00b8a6c5f0f3525b994cba3e971d631db288396 ./src/models/history.rs
ea216f24f0f385903324f15a1164a0fc508adbdcc3c30d16383ea2e835c53e6e ./src/models/integrations.rs e1621255217ee6128151cc898373dd404123cb6d54017beec6c7e3e5c3030486 ./src/models/integrations.rs
23688a5cb68efded89471ce959328d27adff370d451bd9f378a283ab51437e76 ./src/models.rs
8294749dd3af524925309c51ad641ffd32ff1fd9c164cfa71660aa88c2d13d6e ./src/models/runtime.rs 8294749dd3af524925309c51ad641ffd32ff1fd9c164cfa71660aa88c2d13d6e ./src/models/runtime.rs
887eb80a58998e90023e952c1fde67435eb843493387ae64536613b74c084534 ./src/models/settings_api.rs 887eb80a58998e90023e952c1fde67435eb843493387ae64536613b74c084534 ./src/models/settings_api.rs
c4de6101de85d9d7e6814b2504b87d9216561e3d9e274054f081f505fb152140 ./src/models/temporary_thermostat.rs c4de6101de85d9d7e6814b2504b87d9216561e3d9e274054f081f505fb152140 ./src/models/temporary_thermostat.rs
7d798228a8d4d4e60a112167c001535f4b8a5fa32ec7a33554c73125c42256c2 ./src/models/zone.rs 7d798228a8d4d4e60a112167c001535f4b8a5fa32ec7a33554c73125c42256c2 ./src/models/zone.rs
2ccac88080ef3ca8546facad5167cbaadc080bdee3f5d9100c8fabb0fc3ae49d ./src/notifications.rs 48e5d0e0c8b2863daf35c64ad49bf5333fb3b807568323cf0958efbc3aee7433 ./src/notifications.rs
cca742bb2b500eb9269f69385fcf88053cd08aabf6a98b7669b8a7a2fd67df13 ./src/protocol/crypto.rs cca742bb2b500eb9269f69385fcf88053cd08aabf6a98b7669b8a7a2fd67df13 ./src/protocol/crypto.rs
28969da06a454ddd1ebea5fa606e8446a83dfd21e21352767c189013c508cb90 ./src/protocol/gree.rs
7907c33e6396c7e0d61705b735b21c84d6ed784012fb61022b872c6745540f1d ./src/protocol/gree/binding.rs 7907c33e6396c7e0d61705b735b21c84d6ed784012fb61022b872c6745540f1d ./src/protocol/gree/binding.rs
d4df52f0202eb32290e68dc945c4b0b44f3be8aa90bd57fd116eb20285960616 ./src/protocol/gree/commands.rs d4df52f0202eb32290e68dc945c4b0b44f3be8aa90bd57fd116eb20285960616 ./src/protocol/gree/commands.rs
4e419ba3b86ca9d154e8c04445cf005965175c54041093b2daad3666d4d852bd ./src/protocol/gree/core.rs 4e419ba3b86ca9d154e8c04445cf005965175c54041093b2daad3666d4d852bd ./src/protocol/gree/core.rs
@@ -164,38 +162,37 @@ d4df52f0202eb32290e68dc945c4b0b44f3be8aa90bd57fd116eb20285960616 ./src/protocol
0ab094f609edb99715402d8eeaa7e38cbfd2d271036aec787dcbb3be3e005720 ./src/protocol/gree/merge.rs 0ab094f609edb99715402d8eeaa7e38cbfd2d271036aec787dcbb3be3e005720 ./src/protocol/gree/merge.rs
a96061fbbcadac6c2df2e9708a48dcf819b951eb147f32c7d0d285ac5ae2491b ./src/protocol/gree/network.rs a96061fbbcadac6c2df2e9708a48dcf819b951eb147f32c7d0d285ac5ae2491b ./src/protocol/gree/network.rs
de37931303fc92a9399e6edc17dfabd6870a38cd2ddb27257427c76768a66ec2 ./src/protocol/gree/polling.rs de37931303fc92a9399e6edc17dfabd6870a38cd2ddb27257427c76768a66ec2 ./src/protocol/gree/polling.rs
28969da06a454ddd1ebea5fa606e8446a83dfd21e21352767c189013c508cb90 ./src/protocol/gree.rs
c868422c02ba457df21ae92acbd00698c243855ddd1d4e95ac2166796eba9a44 ./src/protocol/gree/tests.rs c868422c02ba457df21ae92acbd00698c243855ddd1d4e95ac2166796eba9a44 ./src/protocol/gree/tests.rs
3c93e5b254a2a40a07854532cb5fc07e493ad65d9ba2cf28093cff4a4a4e451c ./src/protocol/gree/transport.rs 3c93e5b254a2a40a07854532cb5fc07e493ad65d9ba2cf28093cff4a4a4e451c ./src/protocol/gree/transport.rs
923bb4b2d342d6c1870474e43f33b0aba16dc88590c561d765b874412e83df1f ./src/protocol/mod.rs 923bb4b2d342d6c1870474e43f33b0aba16dc88590c561d765b874412e83df1f ./src/protocol/mod.rs
830621fa75265da7288b8135704c0ce27e0687f87d55abf3cdbe40a6e2f3d2b1 ./src/queries.rs
7fac65a9dcbcecee09816f5447c7792dc94f736b1efb66ac85629db75f6280be ./src/queries/device_history.rs 7fac65a9dcbcecee09816f5447c7792dc94f736b1efb66ac85629db75f6280be ./src/queries/device_history.rs
3fb50f57d30ac23ef122c45dae4bd96c7cb7184df02d99aef00d9890b66479e2 ./src/queries/entities.rs 3fb50f57d30ac23ef122c45dae4bd96c7cb7184df02d99aef00d9890b66479e2 ./src/queries/entities.rs
2c5fba462b72158b04dbaaa53c8536263f8d72a1338a6c4ff06cb28a36f6ae27 ./src/queries/ha_history.rs 2c5fba462b72158b04dbaaa53c8536263f8d72a1338a6c4ff06cb28a36f6ae27 ./src/queries/ha_history.rs
c91e4b8b250b30cbe76f313b70c16244e9003bce92e02c82283a1831f91974c5 ./src/queries/maintenance.rs c91e4b8b250b30cbe76f313b70c16244e9003bce92e02c82283a1831f91974c5 ./src/queries/maintenance.rs
830621fa75265da7288b8135704c0ce27e0687f87d55abf3cdbe40a6e2f3d2b1 ./src/queries.rs
3a49bad74a2f047893e726b5e00a6e833c228ad268bdf50cd60f786ba164ea54 ./src/queries/schema.rs 3a49bad74a2f047893e726b5e00a6e833c228ad268bdf50cd60f786ba164ea54 ./src/queries/schema.rs
f13f1be3d5789539eba3fc1b59c14835f8c681eca7634e118fa3763a53aeee2b ./src/queries/zone_history.rs f13f1be3d5789539eba3fc1b59c14835f8c681eca7634e118fa3763a53aeee2b ./src/queries/zone_history.rs
008be170ed418f8701c512f521828b8e6c0071ff195cd6f7aa39fade6c7c3fa9 ./src/state.rs 008be170ed418f8701c512f521828b8e6c0071ff195cd6f7aa39fade6c7c3fa9 ./src/state.rs
b92a6cb158b494fe145b43c7641e65f6fafff47201d7d76edbec2cfd8b94835c ./systemd/gree-controller.service b92a6cb158b494fe145b43c7641e65f6fafff47201d7d76edbec2cfd8b94835c ./systemd/gree-controller.service
544a31cb2e5374227026afd6abd0d910381f3fca1638154ebd74e3c3d96a35d1 ./web/404.html 544a31cb2e5374227026afd6abd0d910381f3fca1638154ebd74e3c3d96a35d1 ./web/404.html
e98bdd7204349cce1ec6f57283509697af0bbc72280622a6c3efa6fed242db4f ./web/favicon.svg e98bdd7204349cce1ec6f57283509697af0bbc72280622a6c3efa6fed242db4f ./web/favicon.svg
b8df5b68b752c717a7772c6f70a00f748d20b245eff4ca0cda937ad603104d16 ./web/index.html 62e0a01a47a2d30e5265010aef5a089b0055d824fede940b7665d76f92018522 ./web/index.html
9ba3f6fa05b72aa989139b2a909982571b2a02055052e4c40104f1e81a9aa7eb ./web/js/README.md
45fb54541a117a8ee0dc484cd263b6af4aafab75d94d269b126bb603b5f0392c ./web/js/bootstrap.js 45fb54541a117a8ee0dc484cd263b6af4aafab75d94d269b126bb603b5f0392c ./web/js/bootstrap.js
badde8a5214a0322b2c45803c02a1cb723d53b25e57c687369cd804f509d9744 ./web/js/charts.js badde8a5214a0322b2c45803c02a1cb723d53b25e57c687369cd804f509d9744 ./web/js/charts.js
dd596b3362643b96be8537b9415e8c1be90d7cf458124b61121016a6742951c7 ./web/js/core.js dd596b3362643b96be8537b9415e8c1be90d7cf458124b61121016a6742951c7 ./web/js/core.js
d880ffdac6aa07cd10d79fbacf12f87eb4c69b48a80564bbfdd0248abe8884d5 ./web/js/dashboard.js d880ffdac6aa07cd10d79fbacf12f87eb4c69b48a80564bbfdd0248abe8884d5 ./web/js/dashboard.js
6c0d310e39a1e1f618a31fbdf5560a850023bf2219d897c69d636d0179dff004 ./web/js/entities.js 6c0d310e39a1e1f618a31fbdf5560a850023bf2219d897c69d636d0179dff004 ./web/js/entities.js
e332b3f811958a938105272c1e8e28d6ca8ba69303001da165b4b0b85727695c ./web/js/events.js 0a23ac65a4a0bd113a9f78fe1d25621d6a178e10aaca53e5df8df87587998cb4 ./web/js/events.js
2e822a00b5a6941b6a251eaf2c54ca95a53399b5d1056f3d8240e11f82d6065f ./web/js/flows.js 2e822a00b5a6941b6a251eaf2c54ca95a53399b5d1056f3d8240e11f82d6065f ./web/js/flows.js
cf1ebf3b9d666f309a1add070b4da86be86d990b02c8d6474f6d121c6d332746 ./web/js/forms.js cf1ebf3b9d666f309a1add070b4da86be86d990b02c8d6474f6d121c6d332746 ./web/js/forms.js
dbf36223863ba882c03eccea4516ba8db7acf0c2e72c6c64490cb994f1e20f96 ./web/js/history.js dbf36223863ba882c03eccea4516ba8db7acf0c2e72c6c64490cb994f1e20f96 ./web/js/history.js
7eaa04992ea828dc89f5eaebf674cbbfd160f53eb8d0d6ef0d4e47bd8c28c435 ./web/js/main.js 7eaa04992ea828dc89f5eaebf674cbbfd160f53eb8d0d6ef0d4e47bd8c28c435 ./web/js/main.js
733fcc595ed9c03c9639acc6caba46f0588f29e0b95bf72891e34443e7aa9db8 ./web/js/navigation.js 733fcc595ed9c03c9639acc6caba46f0588f29e0b95bf72891e34443e7aa9db8 ./web/js/navigation.js
9ba3f6fa05b72aa989139b2a909982571b2a02055052e4c40104f1e81a9aa7eb ./web/js/README.md
e3e01511a34175b88eb01dac2c557e8b112fcad5826f02a0bc3cd1e8dfb7ff91 ./web/js/realtime.js e3e01511a34175b88eb01dac2c557e8b112fcad5826f02a0bc3cd1e8dfb7ff91 ./web/js/realtime.js
c8c82e88c3715b1bfabf155e36266a4c94f5e2fc03eb39dcdd9d08a1985a997c ./web/js/router.js c8c82e88c3715b1bfabf155e36266a4c94f5e2fc03eb39dcdd9d08a1985a997c ./web/js/router.js
9dd9fbcc5f00584562bae6a840189495f830d1086d9679763dbad6e9c18c4fdb ./web/js/settings.js 25f5c9a0aa8622f419b05f64712c9eca4896f0e79818616904b83051fd77b07b ./web/js/settings-ui.js
427376a35832cb3644206c6e89e1654bd807eec78352f80bd0dd43f74b4ec810 ./web/js/settings-ui.js 7399a951ae585d7c9ee55cc57064c64a2806ec725e2456cfe6b09bc61f8f4166 ./web/js/settings.js
6b653e4fe2d4db4ffae6ff8f39b8ce57a10a990dc0000ee4aae51d949afadd52 ./web/manifest.webmanifest 6b653e4fe2d4db4ffae6ff8f39b8ce57a10a990dc0000ee4aae51d949afadd52 ./web/manifest.webmanifest
801bb151f7b6220587e22c3114fb224a540dcfbddd1c09870007b7b893a01301 ./web/styles.css 801bb151f7b6220587e22c3114fb224a540dcfbddd1c09870007b7b893a01301 ./web/styles.css
ae1b03f30b494f474a781a5d32072f1e73eba2b7c768109fc1cc8028cb6662a4 ./web/sw.js ae1b03f30b494f474a781a5d32072f1e73eba2b7c768109fc1cc8028cb6662a4 ./web/sw.js
+2 -2
View File
@@ -2,9 +2,9 @@
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. 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.13.5** **Current release: 0.13.6**
Release 0.13.5 keeps the 0.13.x HTTP/WS contracts and makes disabled-zone semantics explicit in both thermostat controls and zone settings. Disabling a zone stops automation, while manual thermostat, temporary thermostat and direct manual control remain available. The 0.1 °C logical thermostat precision introduced in 0.13.3 is unchanged. Release 0.13.6 adds a dedicated notification toggle for GREE vs Home Assistant room-temperature discrepancies. Disabling this alert suppresses `zone.sensor_discrepancy` notifications only; sensor fallback and thermostat safety behavior are unchanged.
> [Full API reference](docs/API.md) — authentication, every endpoint, request bodies, response models, WebSocket events and examples. > [Full API reference](docs/API.md) — authentication, every endpoint, request bodies, response models, WebSocket events and examples.
+7 -4
View File
@@ -1,6 +1,6 @@
# GREE Controller API reference # GREE Controller API reference
HTTP and WebSocket API for GREE Controller **0.13.5**. HTTP and WebSocket API for GREE Controller **0.13.6**.
[← Main documentation](../README.md) [← Main documentation](../README.md)
@@ -231,7 +231,7 @@ Response:
{ {
"status": "ok", "status": "ok",
"name": "gree-controller", "name": "gree-controller",
"version": "0.13.5", "version": "0.13.6",
"uptime_seconds": 1234, "uptime_seconds": 1234,
"control_ready": true, "control_ready": true,
"time": "2026-08-30T06:54:00Z" "time": "2026-08-30T06:54:00Z"
@@ -257,7 +257,7 @@ Returns the initial Web UI snapshot:
"control_plan": {"generated_at": "2026-09-04T08:00:00Z", "zones": [], "rules": []}, "control_plan": {"generated_at": "2026-09-04T08:00:00Z", "zones": [], "rules": []},
"control_plan_revision": 42, "control_plan_revision": 42,
"system": { "system": {
"version": "0.13.5", "version": "0.13.6",
"uptime_seconds": 1234, "uptime_seconds": 1234,
"auth_required": false, "auth_required": false,
"control_ready": true, "control_ready": true,
@@ -1107,6 +1107,7 @@ Retention values are clamped to `1..3650` days. Updating this section immediatel
"communication": true, "communication": true,
"target_timeout": true, "target_timeout": true,
"automation": true, "automation": true,
"sensor_discrepancy": true,
"control_errors": true, "control_errors": true,
"important_events": true, "important_events": true,
"other": true "other": true
@@ -1114,7 +1115,7 @@ Retention values are clamped to `1..3650` days. Updating this section immediatel
} }
``` ```
`PUT` accepts the same behavioral fields plus optional `pushover_app_token`, `pushover_user_key`, `slack_webhook_url` and `discord_webhook_url`. Omitted/`null` secrets are preserved; an explicit empty string clears them. Modes: `problems`, `important`. Providers: `pushover`, `slack`, `discord`. Cooldown is clamped to `30..86400` seconds, failure threshold to `2..100`, target timeout to `5..1440` minutes. `PUT` accepts the same behavioral fields plus optional `pushover_app_token`, `pushover_user_key`, `slack_webhook_url` and `discord_webhook_url`. Omitted/`null` secrets are preserved; an explicit empty string clears them. Modes: `problems`, `important`. Providers: `pushover`, `slack`, `discord`. Cooldown is clamped to `30..86400` seconds, failure threshold to `2..100`, target timeout to `5..1440` minutes. `alert_types.sensor_discrepancy` controls only notifications about GREE vs Home Assistant room-temperature divergence; the safety fallback to the GREE sensor remains active.
### `/api/settings/night` ### `/api/settings/night`
@@ -1467,6 +1468,8 @@ In `0.13.4`, disabled-zone thermostat controls remain visually active because ex
In `0.13.5`, the same disabled-zone behavior is explained directly beside the zone enabled/disabled setting, so users see before changing it that disabling a zone stops automation but does not block manual thermostat, temporary thermostat or direct manual control. HTTP and WebSocket contracts remain unchanged. In `0.13.5`, the same disabled-zone behavior is explained directly beside the zone enabled/disabled setting, so users see before changing it that disabling a zone stops automation but does not block manual thermostat, temporary thermostat or direct manual control. HTTP and WebSocket contracts remain unchanged.
In `0.13.6`, notification settings add `alert_types.sensor_discrepancy`, allowing GREE vs Home Assistant temperature-difference notifications to be disabled independently from thermostat/group control errors. The sensor fallback behavior itself is unchanged.
Additional engine/integration events may be introduced without changing the envelope. Additional engine/integration events may be introduced without changing the envelope.
`api.request` data: `api.request` data:
+8 -3
View File
@@ -2,9 +2,9 @@
"openapi": "3.1.0", "openapi": "3.1.0",
"info": { "info": {
"title": "GREE Controller API", "title": "GREE Controller API",
"version": "0.13.5", "version": "0.13.6",
"summary": "Local HTTP/WebSocket API for GREE HVAC control", "summary": "Local HTTP/WebSocket API for GREE HVAC control",
"description": "Self-hosted API used by the GREE Controller Web UI and Home Assistant integration.\n\n### Authentication\nNormal administrator endpoints accept `Authorization: Bearer <APP_TOKEN>` or `x-api-token: <APP_TOKEN>` when `GREE_CONTROLLER_APP_TOKEN` is configured. If the app token is empty, those endpoints intentionally run in trusted-LAN mode without authentication.\n\nThe restricted `/api/integrations/home-assistant/*` control surface always requires either a generated access token or the administrator app token. Generated tokens do **not** grant normal administrator API access.\n\nIn Swagger UI use **Authorize** and enter the token in either the bearer field or `x-api-token` field.\n\n### Control ownership\nThermostat zones, groups, house rules, direct device control, schedules and visual Flows share an ownership/arbitration model. Prefer zone/group/house endpoints for thermostat intent; direct device commands are technical/manual control and can deliberately take ownership.\n\n### 0.12.0 breaking API\nRuntime settings are split into functional `/api/settings/*` resources. The former `/api/settings`, `/api/debug`, `/api/events/retention`, `/api/settings/export` and `/api/settings/import` endpoints were removed without compatibility aliases.\n\n### 0.13.0\n`control-plan` keeps its existing HTTP response shape but is materialized in memory and pushed to WebSocket clients as `control_plan.updated`; HTTP remains the fallback/resync path. A restricted Home Assistant snapshot endpoint combines devices, groups and the control plan.\n\n### 0.13.1\nRuntime WebSocket churn is reduced without changing contracts: no-op zone regulator heartbeats are deduplicated and device heartbeat polls only invalidate the materialized control plan when plan-relevant device state changes.\n\n### 0.13.2\nCompletes live WebSocket synchronization for entity creation, schedules, automations, configuration imports and runtime device/automation state while preserving the existing HTTP API contracts and control-plan fallback behavior.\n\n### 0.13.3\nLogical thermostat targets are normalized to 0.1 C consistently, including Temporary Quick Thermostat and thermostat-managed automation/Flow actions. The bundled Web UI accepts comma or dot decimal input for the temporary thermostat target; physical GREE setpoint rounding is unchanged.\n\n### 0.13.4\nDisabled-zone thermostat controls remain visually active in the bundled Web UI because explicit temporary/manual thermostat and direct manual control remain available while zone automation is disabled. HTTP and WebSocket contracts are unchanged.\n\n### 0.13.5\nThe zone settings dialog now explains directly beside the enabled/disabled option that disabling a zone stops automation but does not block manual thermostat, temporary thermostat or direct manual control. HTTP and WebSocket contracts remain unchanged.", "description": "Self-hosted API used by the GREE Controller Web UI and Home Assistant integration.\n\n### Authentication\nNormal administrator endpoints accept `Authorization: Bearer <APP_TOKEN>` or `x-api-token: <APP_TOKEN>` when `GREE_CONTROLLER_APP_TOKEN` is configured. If the app token is empty, those endpoints intentionally run in trusted-LAN mode without authentication.\n\nThe restricted `/api/integrations/home-assistant/*` control surface always requires either a generated access token or the administrator app token. Generated tokens do **not** grant normal administrator API access.\n\nIn Swagger UI use **Authorize** and enter the token in either the bearer field or `x-api-token` field.\n\n### Control ownership\nThermostat zones, groups, house rules, direct device control, schedules and visual Flows share an ownership/arbitration model. Prefer zone/group/house endpoints for thermostat intent; direct device commands are technical/manual control and can deliberately take ownership.\n\n### 0.12.0 breaking API\nRuntime settings are split into functional `/api/settings/*` resources. The former `/api/settings`, `/api/debug`, `/api/events/retention`, `/api/settings/export` and `/api/settings/import` endpoints were removed without compatibility aliases.\n\n### 0.13.0\n`control-plan` keeps its existing HTTP response shape but is materialized in memory and pushed to WebSocket clients as `control_plan.updated`; HTTP remains the fallback/resync path. A restricted Home Assistant snapshot endpoint combines devices, groups and the control plan.\n\n### 0.13.1\nRuntime WebSocket churn is reduced without changing contracts: no-op zone regulator heartbeats are deduplicated and device heartbeat polls only invalidate the materialized control plan when plan-relevant device state changes.\n\n### 0.13.2\nCompletes live WebSocket synchronization for entity creation, schedules, automations, configuration imports and runtime device/automation state while preserving the existing HTTP API contracts and control-plan fallback behavior.\n\n### 0.13.3\nLogical thermostat targets are normalized to 0.1 C consistently, including Temporary Quick Thermostat and thermostat-managed automation/Flow actions. The bundled Web UI accepts comma or dot decimal input for the temporary thermostat target; physical GREE setpoint rounding is unchanged.\n\n### 0.13.4\nDisabled-zone thermostat controls remain visually active in the bundled Web UI because explicit temporary/manual thermostat and direct manual control remain available while zone automation is disabled. HTTP and WebSocket contracts are unchanged.\n\n### 0.13.5\nThe zone settings dialog now explains directly beside the enabled/disabled option that disabling a zone stops automation but does not block manual thermostat, temporary thermostat or direct manual control. HTTP and WebSocket contracts remain unchanged.\n\n### 0.13.6\nNotification settings add a dedicated sensor_discrepancy alert type for GREE vs Home Assistant room-temperature divergence. Disabling it suppresses only that notification; the GREE safety fallback remains active.",
"license": { "license": {
"name": "MIT" "name": "MIT"
} }
@@ -4891,7 +4891,7 @@
}, },
"version": { "version": {
"type": "string", "type": "string",
"example": "0.13.5" "example": "0.13.6"
}, },
"uptime_seconds": { "uptime_seconds": {
"type": "integer", "type": "integer",
@@ -7488,6 +7488,10 @@
"automation": { "automation": {
"type": "boolean" "type": "boolean"
}, },
"sensor_discrepancy": {
"type": "boolean",
"description": "Send notifications when GREE and Home Assistant room-temperature sensors differ beyond the configured zone limit. This does not disable the GREE safety fallback."
},
"control_errors": { "control_errors": {
"type": "boolean" "type": "boolean"
}, },
@@ -7504,6 +7508,7 @@
"communication", "communication",
"target_timeout", "target_timeout",
"automation", "automation",
"sensor_discrepancy",
"control_errors", "control_errors",
"important_events", "important_events",
"other" "other"
@@ -1,7 +1,7 @@
{ {
"domain": "gree_controller", "domain": "gree_controller",
"name": "GREE Controller", "name": "GREE Controller",
"version": "0.13.5", "version": "0.13.6",
"config_flow": true, "config_flow": true,
"integration_type": "hub", "integration_type": "hub",
"iot_class": "local_polling", "iot_class": "local_polling",
+2 -1
View File
@@ -736,6 +736,7 @@
"notifications.alertCommunication": "Device communication problems", "notifications.alertCommunication": "Device communication problems",
"notifications.alertTargetTimeout": "Target temperature timeout", "notifications.alertTargetTimeout": "Target temperature timeout",
"notifications.alertAutomation": "Automation errors and conflicts", "notifications.alertAutomation": "Automation errors and conflicts",
"notifications.alertSensorDiscrepancy": "GREE vs Home Assistant temperature difference",
"notifications.alertControlErrors": "Thermostat and group control errors", "notifications.alertControlErrors": "Thermostat and group control errors",
"notifications.alertImportantEvents": "Important state changes", "notifications.alertImportantEvents": "Important state changes",
"notifications.alertOther": "Other warnings and errors", "notifications.alertOther": "Other warnings and errors",
@@ -1171,4 +1172,4 @@
"schedules.enabledState": "Enabled", "schedules.enabledState": "Enabled",
"schedules.disabledState": "Disabled" "schedules.disabledState": "Disabled"
} }
} }
+2 -1
View File
@@ -736,6 +736,7 @@
"notifications.alertCommunication": "Problemy komunikacji z urządzeniami", "notifications.alertCommunication": "Problemy komunikacji z urządzeniami",
"notifications.alertTargetTimeout": "Nieosiągnięcie temperatury w limicie czasu", "notifications.alertTargetTimeout": "Nieosiągnięcie temperatury w limicie czasu",
"notifications.alertAutomation": "Błędy i konflikty automatyzacji", "notifications.alertAutomation": "Błędy i konflikty automatyzacji",
"notifications.alertSensorDiscrepancy": "Różnica temperatury GREE względem Home Assistant",
"notifications.alertControlErrors": "Błędy sterowania termostatami i grupami", "notifications.alertControlErrors": "Błędy sterowania termostatami i grupami",
"notifications.alertImportantEvents": "Ważne zmiany stanu", "notifications.alertImportantEvents": "Ważne zmiany stanu",
"notifications.alertOther": "Pozostałe ostrzeżenia i błędy", "notifications.alertOther": "Pozostałe ostrzeżenia i błędy",
@@ -1171,4 +1172,4 @@
"schedules.enabledState": "Włączony", "schedules.enabledState": "Włączony",
"schedules.disabledState": "Wyłączony" "schedules.disabledState": "Wyłączony"
} }
} }
+4 -4
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""Developer smoke/integration tests for GREE Controller API 0.13.5. """Developer smoke/integration tests for GREE Controller API 0.13.6.
Default mode is read-only and safe to run against a real controller. Default mode is read-only and safe to run against a real controller.
Use --settings-write to additionally round-trip all split settings resources and Use --settings-write to additionally round-trip all split settings resources and
@@ -26,7 +26,7 @@ from typing import Any, Callable, Iterable, Optional
DEFAULT_BASE_URL = os.environ.get("GREE_API_URL", "http://127.0.0.1:8787") DEFAULT_BASE_URL = os.environ.get("GREE_API_URL", "http://127.0.0.1:8787")
DEFAULT_TOKEN = os.environ.get("GREE_API_TOKEN", "") DEFAULT_TOKEN = os.environ.get("GREE_API_TOKEN", "")
DEFAULT_EXPECTED_VERSION = "0.13.5" DEFAULT_EXPECTED_VERSION = "0.13.6"
SETTINGS_PATHS: dict[str, set[str]] = { SETTINGS_PATHS: dict[str, set[str]] = {
"/api/settings/application": {"simulator_enabled"}, "/api/settings/application": {"simulator_enabled"},
@@ -519,7 +519,7 @@ def run_suite(args: argparse.Namespace) -> int:
print(f"Settings write tests: {'ENABLED' if args.settings_write else 'disabled'}\n") print(f"Settings write tests: {'ENABLED' if args.settings_write else 'disabled'}\n")
runner.run("public health", lambda: test_health(client, args.expected_version)) runner.run("public health", lambda: test_health(client, args.expected_version))
runner.run("OpenAPI 0.13.5 contract", lambda: test_openapi(client, args.expected_version)) runner.run("OpenAPI 0.13.6 contract", lambda: test_openapi(client, args.expected_version))
runner.run("protected API requires auth", lambda: test_protected_auth(client)) runner.run("protected API requires auth", lambda: test_protected_auth(client))
for path in SAFE_GET_PATHS: for path in SAFE_GET_PATHS:
@@ -587,7 +587,7 @@ def run_suite(args: argparse.Namespace) -> int:
def parse_args(argv: Optional[Iterable[str]] = None) -> argparse.Namespace: def parse_args(argv: Optional[Iterable[str]] = None) -> argparse.Namespace:
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description="Developer smoke/integration tests for GREE Controller API 0.13.5.", description="Developer smoke/integration tests for GREE Controller API 0.13.6.",
formatter_class=argparse.RawDescriptionHelpFormatter, formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""Examples: epilog="""Examples:
python3 scripts/api_dev_test.py python3 scripts/api_dev_test.py
+5 -1
View File
@@ -95,7 +95,10 @@ pub struct NotificationAlertTypes {
/// Automation execution errors and conflicts. /// Automation execution errors and conflicts.
#[serde(default = "default_true")] #[serde(default = "default_true")]
pub automation: bool, pub automation: bool,
/// Thermostat/group/device control failures and sensor discrepancies. /// GREE room temperature differs from the configured Home Assistant sensor beyond the zone limit.
#[serde(default = "default_true")]
pub sensor_discrepancy: bool,
/// Thermostat/group/device control failures.
#[serde(default = "default_true")] #[serde(default = "default_true")]
pub control_errors: bool, pub control_errors: bool,
/// Informational state changes sent when notification mode is "important". /// Informational state changes sent when notification mode is "important".
@@ -114,6 +117,7 @@ impl Default for NotificationAlertTypes {
communication: true, communication: true,
target_timeout: true, target_timeout: true,
automation: true, automation: true,
sensor_discrepancy: true,
control_errors: true, control_errors: true,
important_events: true, important_events: true,
other: true, other: true,
+22 -1
View File
@@ -43,13 +43,15 @@ fn alert_type_enabled(cfg: &NotificationSettings, kind: &str) -> bool {
if kind.starts_with("automation.") { if kind.starts_with("automation.") {
return types.automation; return types.automation;
} }
if kind == "zone.sensor_discrepancy" {
return types.sensor_discrepancy;
}
if matches!( if matches!(
kind, kind,
"zone.action_error" "zone.action_error"
| "zone.mode_change_off_error" | "zone.mode_change_off_error"
| "zone.local_power_error" | "zone.local_power_error"
| "zone.device_missing" | "zone.device_missing"
| "zone.sensor_discrepancy"
| "zone.temporary_quick_thermostat_cancelled" | "zone.temporary_quick_thermostat_cancelled"
| "zone.temporary_quick_thermostat_poweroff_error" | "zone.temporary_quick_thermostat_poweroff_error"
| "group.power_error" | "group.power_error"
@@ -142,6 +144,25 @@ pub async fn dispatch(
} }
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sensor_discrepancy_has_its_own_notification_toggle() {
let mut cfg = NotificationSettings::default();
cfg.alert_types.control_errors = true;
cfg.alert_types.sensor_discrepancy = false;
assert!(!alert_type_enabled(&cfg, "zone.sensor_discrepancy"));
assert!(alert_type_enabled(&cfg, "zone.action_error"));
cfg.alert_types.control_errors = false;
cfg.alert_types.sensor_discrepancy = true;
assert!(alert_type_enabled(&cfg, "zone.sensor_discrepancy"));
assert!(!alert_type_enabled(&cfg, "zone.action_error"));
}
}
async fn send_pushover( async fn send_pushover(
state: &AppState, state: &AppState,
cfg: &NotificationSettings, cfg: &NotificationSettings,
+2
View File
@@ -585,6 +585,8 @@
data-i18n="notifications.alertTargetTimeout">Target temperature timeout</span></label> data-i18n="notifications.alertTargetTimeout">Target temperature timeout</span></label>
<label class="check"><input type="checkbox" name="notification_alert_automation"> <span <label class="check"><input type="checkbox" name="notification_alert_automation"> <span
data-i18n="notifications.alertAutomation">Automation errors and conflicts</span></label> data-i18n="notifications.alertAutomation">Automation errors and conflicts</span></label>
<label class="check"><input type="checkbox" name="notification_alert_sensor_discrepancy"> <span
data-i18n="notifications.alertSensorDiscrepancy">GREE vs Home Assistant temperature difference</span></label>
<label class="check"><input type="checkbox" name="notification_alert_control_errors"> <span <label class="check"><input type="checkbox" name="notification_alert_control_errors"> <span
data-i18n="notifications.alertControlErrors">Thermostat and group control errors</span></label> data-i18n="notifications.alertControlErrors">Thermostat and group control errors</span></label>
<label class="check"><input type="checkbox" name="notification_alert_important_events"> <span <label class="check"><input type="checkbox" name="notification_alert_important_events"> <span
+1 -1
View File
@@ -242,7 +242,7 @@ $('#simulationOpenTab')?.addEventListener('click', () => { const params = new UR
$('#simulationFullscreen')?.addEventListener('click', async () => { try { if (document.fullscreenElement) await document.exitFullscreen(); else await document.documentElement.requestFullscreen(); } catch (error) { toast(error.message, true); } }); $('#simulationFullscreen')?.addEventListener('click', async () => { try { if (document.fullscreenElement) await document.exitFullscreen(); else await document.documentElement.requestFullscreen(); } catch (error) { toast(error.message, true); } });
document.addEventListener('fullscreenchange', () => { const button = $('#simulationFullscreen'); if (button) button.textContent = tr(document.fullscreenElement ? 'simulation.exitFullscreen' : 'simulation.fullscreen'); }); document.addEventListener('fullscreenchange', () => { const button = $('#simulationFullscreen'); if (button) button.textContent = tr(document.fullscreenElement ? 'simulation.exitFullscreen' : 'simulation.fullscreen'); });
$('#testNotifications')?.addEventListener('click', async () => { const f = $('#settingsForm'); const body = { enabled: true, mode: f.notifications_mode.value, provider: f.notifications_provider.value, pushover_app_token: f.pushover_app_token.value.trim(), pushover_user_key: f.pushover_user_key.value.trim(), slack_webhook_url: f.slack_webhook_url.value.trim(), discord_webhook_url: f.discord_webhook_url.value.trim(), cooldown_seconds: Number(f.notification_cooldown_seconds.value || 300), communication_failure_threshold: Number(f.notification_failure_threshold.value || 3), target_timeout_minutes: Number(f.notification_target_timeout.value || 60), alert_types: { stale_sensor: f.notification_alert_stale_sensor.checked, sensor_errors: f.notification_alert_sensor_errors.checked, communication: f.notification_alert_communication.checked, target_timeout: f.notification_alert_target_timeout.checked, automation: f.notification_alert_automation.checked, control_errors: f.notification_alert_control_errors.checked, important_events: f.notification_alert_important_events.checked, other: f.notification_alert_other.checked } }; try { await api('/api/integrations/notifications/test', { method: 'POST', body }); toast(tr('notifications.testSent')); } catch (e) { toast(e.message, true); } }); $('#testNotifications')?.addEventListener('click', async () => { const f = $('#settingsForm'); const body = { enabled: true, mode: f.notifications_mode.value, provider: f.notifications_provider.value, pushover_app_token: f.pushover_app_token.value.trim(), pushover_user_key: f.pushover_user_key.value.trim(), slack_webhook_url: f.slack_webhook_url.value.trim(), discord_webhook_url: f.discord_webhook_url.value.trim(), cooldown_seconds: Number(f.notification_cooldown_seconds.value || 300), communication_failure_threshold: Number(f.notification_failure_threshold.value || 3), target_timeout_minutes: Number(f.notification_target_timeout.value || 60), alert_types: { stale_sensor: f.notification_alert_stale_sensor.checked, sensor_errors: f.notification_alert_sensor_errors.checked, communication: f.notification_alert_communication.checked, target_timeout: f.notification_alert_target_timeout.checked, automation: f.notification_alert_automation.checked, sensor_discrepancy: f.notification_alert_sensor_discrepancy.checked, control_errors: f.notification_alert_control_errors.checked, important_events: f.notification_alert_important_events.checked, other: f.notification_alert_other.checked } }; try { await api('/api/integrations/notifications/test', { method: 'POST', body }); toast(tr('notifications.testSent')); } catch (e) { toast(e.message, true); } });
$('#copyZoneSettings')?.addEventListener('click', () => { $('#copyZoneSettings')?.addEventListener('click', () => {
const f = $('#zoneForm'); const f = $('#zoneForm');
+1
View File
@@ -209,6 +209,7 @@ function renderSettings() {
form.notification_alert_communication.checked = alerts.communication !== false; form.notification_alert_communication.checked = alerts.communication !== false;
form.notification_alert_target_timeout.checked = alerts.target_timeout !== false; form.notification_alert_target_timeout.checked = alerts.target_timeout !== false;
form.notification_alert_automation.checked = alerts.automation !== false; form.notification_alert_automation.checked = alerts.automation !== false;
form.notification_alert_sensor_discrepancy.checked = alerts.sensor_discrepancy !== false;
form.notification_alert_control_errors.checked = alerts.control_errors !== false; form.notification_alert_control_errors.checked = alerts.control_errors !== false;
form.notification_alert_important_events.checked = alerts.important_events !== false; form.notification_alert_important_events.checked = alerts.important_events !== false;
form.notification_alert_other.checked = alerts.other !== false; form.notification_alert_other.checked = alerts.other !== false;
+1
View File
@@ -131,6 +131,7 @@ function notificationSettingsBodyFromForm(form) {
communication: form.notification_alert_communication.checked, communication: form.notification_alert_communication.checked,
target_timeout: form.notification_alert_target_timeout.checked, target_timeout: form.notification_alert_target_timeout.checked,
automation: form.notification_alert_automation.checked, automation: form.notification_alert_automation.checked,
sensor_discrepancy: form.notification_alert_sensor_discrepancy.checked,
control_errors: form.notification_alert_control_errors.checked, control_errors: form.notification_alert_control_errors.checked,
important_events: form.notification_alert_important_events.checked, important_events: form.notification_alert_important_events.checked,
other: form.notification_alert_other.checked, other: form.notification_alert_other.checked,