v0.15.7
This commit is contained in:
Generated
+1
-1
@@ -719,7 +719,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gree-controller"
|
name = "gree-controller"
|
||||||
version = "0.15.6"
|
version = "0.15.7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "gree-controller"
|
name = "gree-controller"
|
||||||
version = "0.15.6"
|
version = "0.15.7"
|
||||||
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"
|
||||||
|
|||||||
+20
-20
@@ -1,14 +1,14 @@
|
|||||||
de0793949cf01d27d903653226ecc9b5f72523d8711f20bcab022cf42c4c4ed0 ./.env.example
|
de0793949cf01d27d903653226ecc9b5f72523d8711f20bcab022cf42c4c4ed0 ./.env.example
|
||||||
a4ec3874a2e3ab1bad28fb40bb620f7b01f64d01ad9b699306bf70ada31227db ./.gitignore
|
a4ec3874a2e3ab1bad28fb40bb620f7b01f64d01ad9b699306bf70ada31227db ./.gitignore
|
||||||
03fd19b33f6b87a3cf55957c44c619dc65b6c1ef6ab35a275f7142e063fa130d ./Cargo.lock
|
bc531fc3bd260aa91bc4b3f000768d740222f6f80cd780cf2bbd4522d82d8841 ./Cargo.lock
|
||||||
0f1ebc69bb39b480c603772736bbc968cdeada29efecca6a056e4ebd0b071cb7 ./Cargo.toml
|
8555c5b50711059f76fdbaae495a6a56cae16813af2efd7c69a7fde34762949d ./Cargo.toml
|
||||||
19b2943504acb8f8de280f873a8dbec4bb6ebbe3870b158f5655d4fb8c298f5f ./LICENSE
|
19b2943504acb8f8de280f873a8dbec4bb6ebbe3870b158f5655d4fb8c298f5f ./LICENSE
|
||||||
252802f9b072e316a1898b5b39922788c0ed7ab769aba6e1cb33e5ac5595d7fb ./README.md
|
4d648f23faf4e57d2900f898ce5416dd0b2be9b842f18e67e8f6b31312c511dc ./README.md
|
||||||
fb12007189dad1c860aeed1eacc561c54afb01204396982b42bfa68706dc583e ./SOURCE_MANIFEST.sha256
|
54c111977ab409876fd32101fedac6757f3026106d71b187b34c4c36b53424e9 ./SOURCE_MANIFEST.sha256
|
||||||
29e9821e5ed216ea3565dd6d8bc0b174ed3cf9fa72c4ccebbfa99e98db3ad8f9 ./build.rs
|
29e9821e5ed216ea3565dd6d8bc0b174ed3cf9fa72c4ccebbfa99e98db3ad8f9 ./build.rs
|
||||||
c52fb51807e46086e6bb44dd532dde346a742d12d52ce703055f1d4f433fd253 ./docs/API.md
|
fe1bd7a84b16782f9ba2c3c301592b52b194698d7e71f0ba806a88ed3c5a9688 ./docs/API.md
|
||||||
a881ba0808dd3f189d92038f6163c39d6b6208f6dbff5c32c0ea1a2628f3fbb4 ./docs/FLOW.md
|
a881ba0808dd3f189d92038f6163c39d6b6208f6dbff5c32c0ea1a2628f3fbb4 ./docs/FLOW.md
|
||||||
524977fb867f2b56b56df827df0b8f646e366c00fa31d62c577a5a118f76406f ./docs/openapi.json
|
f70388d4fd9a5b35c1e32c43a9a4b4599adc6bd458e388ac571684a9cb1dc20d ./docs/openapi.json
|
||||||
77b8becf7a2c16a384ea85721d878b76e2d520549cb4455d9aa806e57e5a2ecd ./ha-addon/.env.example
|
77b8becf7a2c16a384ea85721d878b76e2d520549cb4455d9aa806e57e5a2ecd ./ha-addon/.env.example
|
||||||
0ca6e58170c2b8925194431ebbdb55f0c8b377fec5cd422cd2bd257e2d9328e3 ./ha-addon/Dockerfile
|
0ca6e58170c2b8925194431ebbdb55f0c8b377fec5cd422cd2bd257e2d9328e3 ./ha-addon/Dockerfile
|
||||||
0951696a2c2e66d4d969f8e7f8641184e3012f261583b31074bc38a7a1c0cc1a ./ha-addon/README.md
|
0951696a2c2e66d4d969f8e7f8641184e3012f261583b31074bc38a7a1c0cc1a ./ha-addon/README.md
|
||||||
@@ -22,7 +22,7 @@ b7f0873109c52be9d7f09bea3dffc416103c50085e1f0680d11661a969479898 ./ha-addon/hom
|
|||||||
6509286c7b7de638dcc5d40ce53181e65d1eddc5dc36a13306dc6d87220fedbb ./ha-addon/home-assistant/custom_components/gree_controller/coordinator.py
|
6509286c7b7de638dcc5d40ce53181e65d1eddc5dc36a13306dc6d87220fedbb ./ha-addon/home-assistant/custom_components/gree_controller/coordinator.py
|
||||||
5a96fe8f5c035c34f1339370270cd078056202d09e236dec75735be11de92a7d ./ha-addon/home-assistant/custom_components/gree_controller/entity_map.py
|
5a96fe8f5c035c34f1339370270cd078056202d09e236dec75735be11de92a7d ./ha-addon/home-assistant/custom_components/gree_controller/entity_map.py
|
||||||
c4fb75c246db651087900ebfc2291ff41ac87652cd6194fc0b776b0005c1cbcf ./ha-addon/home-assistant/custom_components/gree_controller/icon.png
|
c4fb75c246db651087900ebfc2291ff41ac87652cd6194fc0b776b0005c1cbcf ./ha-addon/home-assistant/custom_components/gree_controller/icon.png
|
||||||
45af41dd19b03ddc1d786730603ff2067bf3b3a794b7663acea8e45b5c1b7200 ./ha-addon/home-assistant/custom_components/gree_controller/manifest.json
|
396c1e2aa1dce367bd1b773ff2e9b80e09729ca58900dd5141085bf30a47f8f0 ./ha-addon/home-assistant/custom_components/gree_controller/manifest.json
|
||||||
c52a484b671ce738ecc00228a1db19a5d703f69ab27530c2896a5c2ae3b4a96f ./ha-addon/home-assistant/custom_components/gree_controller/number.py
|
c52a484b671ce738ecc00228a1db19a5d703f69ab27530c2896a5c2ae3b4a96f ./ha-addon/home-assistant/custom_components/gree_controller/number.py
|
||||||
39c4309001b75abb56234f05662bc06e077054986876f1927937edbce528ec95 ./ha-addon/home-assistant/custom_components/gree_controller/select.py
|
39c4309001b75abb56234f05662bc06e077054986876f1927937edbce528ec95 ./ha-addon/home-assistant/custom_components/gree_controller/select.py
|
||||||
cca65482e36d48035aca178121a378fe7d578d600acff267ae81a6399c0da653 ./ha-addon/home-assistant/custom_components/gree_controller/sensor.py
|
cca65482e36d48035aca178121a378fe7d578d600acff267ae81a6399c0da653 ./ha-addon/home-assistant/custom_components/gree_controller/sensor.py
|
||||||
@@ -30,21 +30,21 @@ cca65482e36d48035aca178121a378fe7d578d600acff267ae81a6399c0da653 ./ha-addon/hom
|
|||||||
a745cc458c235158d5d70b6a33d8000fd8b40ff93bfe2f2796af0f4b3a9eef9b ./ha-addon/home-assistant/custom_components/gree_controller/translations/en.json
|
a745cc458c235158d5d70b6a33d8000fd8b40ff93bfe2f2796af0f4b3a9eef9b ./ha-addon/home-assistant/custom_components/gree_controller/translations/en.json
|
||||||
50b7d6fe6329ad4ea6bee9612ab141c2f73f8382fcc2af0bb076a8e8d4dd4465 ./ha-addon/home-assistant/custom_components/gree_controller/translations/pl.json
|
50b7d6fe6329ad4ea6bee9612ab141c2f73f8382fcc2af0bb076a8e8d4dd4465 ./ha-addon/home-assistant/custom_components/gree_controller/translations/pl.json
|
||||||
c5fc5c87273d82d2834a0a5a365c821a416413ed509613441e24e4dc3507c4d2 ./ha-addon/home-assistant/generated/gree_controller_entities.example.json
|
c5fc5c87273d82d2834a0a5a365c821a416413ed509613441e24e4dc3507c4d2 ./ha-addon/home-assistant/generated/gree_controller_entities.example.json
|
||||||
732265515c1d45eb11b966919cfa29ed9f600b6dd02a05e1abee8afda4151213 ./ha-addon/repository/gree-controller/CHANGELOG.md
|
861a1df8677b0539720978aa0e84e7ffc7dea96d37e6d99c6adca2ced0851a44 ./ha-addon/repository/gree-controller/CHANGELOG.md
|
||||||
50b8ba050c6b4919e4d057f7b38c1e23d3913b5b7c87552626452e9695d37251 ./ha-addon/repository/gree-controller/DOCS.md
|
50b8ba050c6b4919e4d057f7b38c1e23d3913b5b7c87552626452e9695d37251 ./ha-addon/repository/gree-controller/DOCS.md
|
||||||
e3834bf712d4cd2acc715d8c85db96dd6e2fb3fbb758dac537f6034c337b3745 ./ha-addon/repository/gree-controller/README.md
|
e3834bf712d4cd2acc715d8c85db96dd6e2fb3fbb758dac537f6034c337b3745 ./ha-addon/repository/gree-controller/README.md
|
||||||
d742c16e5f5f24be48f8055c2131ff335fb5072469d7d515328fd41e9c3aca34 ./ha-addon/repository/gree-controller/config.yaml
|
40d18f2415fb84fe83d79ec19a9c9ca20232d751e02e5713786bac4d38f715a1 ./ha-addon/repository/gree-controller/config.yaml
|
||||||
3aae6cdae4c3aaab7786a9575e7093b7e2c5b69288167075f4b7475611691a6b ./ha-addon/repository/gree-controller/topologia-ha-vlan-gree-pl.png
|
3aae6cdae4c3aaab7786a9575e7093b7e2c5b69288167075f4b7475611691a6b ./ha-addon/repository/gree-controller/topologia-ha-vlan-gree-pl.png
|
||||||
0d0b42a7639b128946eec379175436fa1f150294f39d2dfd169077bfa87fd14d ./ha-addon/repository/gree-controller/topology-ha-vlan-gree-en.png
|
0d0b42a7639b128946eec379175436fa1f150294f39d2dfd169077bfa87fd14d ./ha-addon/repository/gree-controller/topology-ha-vlan-gree-en.png
|
||||||
2272740b185e9520e948f74b8f45cf98b8b5fd28c93bdee760da626f91fe5c2a ./ha-addon/repository/gree-controller/translations/en.yaml
|
2272740b185e9520e948f74b8f45cf98b8b5fd28c93bdee760da626f91fe5c2a ./ha-addon/repository/gree-controller/translations/en.yaml
|
||||||
e6b93d3701d83a31506617a0e6f44ff32d8c24a52be038c8540c862b13546b50 ./ha-addon/repository/gree-controller/translations/pl.yaml
|
e6b93d3701d83a31506617a0e6f44ff32d8c24a52be038c8540c862b13546b50 ./ha-addon/repository/gree-controller/translations/pl.yaml
|
||||||
b54c60ceeac06d32af7797da9e83b90cb037600318e00512da523d37b94d3081 ./ha-addon/repository/repository.yaml
|
2153b230357aab4766398577e23a7a9ff83bb135ddc86d1b3f2cbfc852efe0a1 ./ha-addon/repository/repository.yaml
|
||||||
cea12bc74c066a588a5ef0ef7bad9d4906bdbcea99f2d275429b0eefc94b4b5f ./ha-addon/run.sh
|
cea12bc74c066a588a5ef0ef7bad9d4906bdbcea99f2d275429b0eefc94b4b5f ./ha-addon/run.sh
|
||||||
081e27b6e43070d44f865335c30a42a5a29668eaa6a5ea5ab6967ac4447b8e06 ./ha-addon/sync-repository.sh
|
081e27b6e43070d44f865335c30a42a5a29668eaa6a5ea5ab6967ac4447b8e06 ./ha-addon/sync-repository.sh
|
||||||
f9e31de3d109ead32bf531c074d46a087df398d62488caee0b46b5e0a1c027f7 ./ha_addon.md
|
f9e31de3d109ead32bf531c074d46a087df398d62488caee0b46b5e0a1c027f7 ./ha_addon.md
|
||||||
253a0bc912786e67ea7fc92a64e4a510ad973bec343a88ccfb1f28fca3e8cf01 ./lang/README.md
|
253a0bc912786e67ea7fc92a64e4a510ad973bec343a88ccfb1f28fca3e8cf01 ./lang/README.md
|
||||||
2175f4ce8b5d994e1e4f912244b03721a93a41e2970f39826d6ea15fdaa7078e ./lang/en.json
|
37d24f8de343b4796a0a8cfff3a839e55bdb779add0c8119799787d87ad8b953 ./lang/en.json
|
||||||
1055d5835329c03eb6f5b8fab4ee438c76b23d6eebdadf70effa42998c03a279 ./lang/pl.json
|
1610da0b2bbb9424006647adfb95e1318b7670aaed5a2798db1251db82635317 ./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
|
||||||
@@ -85,7 +85,7 @@ fdcd9a5055d08037278b842e7ab69265345c5811f0a06867136c511d140bb191 ./presets/wind
|
|||||||
804f22123cd3e8db0fac791826c8dd9f758fb866c8e3b5655fb6d25d259dccf1 ./presets/workday_comfort.json
|
804f22123cd3e8db0fac791826c8dd9f758fb866c8e3b5655fb6d25d259dccf1 ./presets/workday_comfort.json
|
||||||
fd7390d64a2378352c09382accf6efff43903d952d111b22a982f06c5b2a3b4b ./regenerate-sha.sh
|
fd7390d64a2378352c09382accf6efff43903d952d111b22a982f06c5b2a3b4b ./regenerate-sha.sh
|
||||||
c64b1c6deeb24f20af662bfce7fa3683703914987241107ce664fa2f6d1a9dcb ./scripts/README.md
|
c64b1c6deeb24f20af662bfce7fa3683703914987241107ce664fa2f6d1a9dcb ./scripts/README.md
|
||||||
03d5ee12306c95d5ae5df4a2a3a422fe5044e0961bb2be4b7ee49641a9ee7fc1 ./scripts/api_dev_test.py
|
9083c4a8c602698a53d926864f2fe7e8c9658379f3d82fcb4171f44ec946a7ad ./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
|
||||||
@@ -105,7 +105,7 @@ b53e1afab342634fedc218ea4517446f19a5ba7985dee599e191b37d9cc8058a ./src/api.rs
|
|||||||
27a788efe385ad7180cb7fc7ec66c34ebd5e6062d9cdf35b32fb461e52a42863 ./src/api/configuration.rs
|
27a788efe385ad7180cb7fc7ec66c34ebd5e6062d9cdf35b32fb461e52a42863 ./src/api/configuration.rs
|
||||||
19bc141286a336ad67e99079496eb0ae5126f986ab28be62b5f97758e5f6969c ./src/api/debug_tokens.rs
|
19bc141286a336ad67e99079496eb0ae5126f986ab28be62b5f97758e5f6969c ./src/api/debug_tokens.rs
|
||||||
ca21f6d5a407e2e3532899d53ba4e8682c2fe961a46d8cd870ddc459721513ef ./src/api/device_groups.rs
|
ca21f6d5a407e2e3532899d53ba4e8682c2fe961a46d8cd870ddc459721513ef ./src/api/device_groups.rs
|
||||||
f775aa2f3c5c554e4197d47cf381f3d2133ea4c1430a5510f045188dd41e5e51 ./src/api/devices.rs
|
8f92909dc575ea6238f4a003f8bd4056c2752fa3247b9ab226e47f875c80b916 ./src/api/devices.rs
|
||||||
4b5b784670ae761a6848b9a33fe3fb391bebd39d65e87936907428711e96ca44 ./src/api/events.rs
|
4b5b784670ae761a6848b9a33fe3fb391bebd39d65e87936907428711e96ca44 ./src/api/events.rs
|
||||||
2ef2f64b77886e2abd6b410adf8de91a2333d3ebdb8fcee8376ba566e5bba029 ./src/api/flows.rs
|
2ef2f64b77886e2abd6b410adf8de91a2333d3ebdb8fcee8376ba566e5bba029 ./src/api/flows.rs
|
||||||
82c02fa135132ea3ebdb4d88dd1210dc536d22f987151d7f82595ee3d3d03440 ./src/api/gree_cloud.rs
|
82c02fa135132ea3ebdb4d88dd1210dc536d22f987151d7f82595ee3d3d03440 ./src/api/gree_cloud.rs
|
||||||
@@ -170,20 +170,20 @@ fc5f2802a073a175a8985e56bcb87eb1ff481226d5b4eeabad73dbba1839fc45 ./src/models/c
|
|||||||
aeab5b5acf35d38a54fd1d82e964fe56635ade69c0149ad423df317095d01555 ./src/models/flow.rs
|
aeab5b5acf35d38a54fd1d82e964fe56635ade69c0149ad423df317095d01555 ./src/models/flow.rs
|
||||||
6e44df6bde2f73c282095c80ac17287e5bef77d9fc1d344e440d863dae5f5031 ./src/models/history.rs
|
6e44df6bde2f73c282095c80ac17287e5bef77d9fc1d344e440d863dae5f5031 ./src/models/history.rs
|
||||||
1fee89f939018bf1f3686c15f25434f01ab96b3239164108db7f348a1f1f8d82 ./src/models/integrations.rs
|
1fee89f939018bf1f3686c15f25434f01ab96b3239164108db7f348a1f1f8d82 ./src/models/integrations.rs
|
||||||
53caf9ba4667a2ae33d5c3ce69f85005d9f8540f2ee3c16c2cb3795a53e9d21f ./src/models/runtime.rs
|
e557ee4a443de586a7ea7dd04318694fb30d6ec053076429503e18f1bcd65c9e ./src/models/runtime.rs
|
||||||
41b85cff6fd234c8d6ea007b2c3c22df5fee5107dcd57c64dcc94a356ff70c12 ./src/models/settings_api.rs
|
41b85cff6fd234c8d6ea007b2c3c22df5fee5107dcd57c64dcc94a356ff70c12 ./src/models/settings_api.rs
|
||||||
c4de6101de85d9d7e6814b2504b87d9216561e3d9e274054f081f505fb152140 ./src/models/temporary_thermostat.rs
|
c4de6101de85d9d7e6814b2504b87d9216561e3d9e274054f081f505fb152140 ./src/models/temporary_thermostat.rs
|
||||||
bc2818ce8d0dae1edfb1b98e5d1c00b193f03eeaa28e343d3532f6023288738c ./src/models/zone.rs
|
bc2818ce8d0dae1edfb1b98e5d1c00b193f03eeaa28e343d3532f6023288738c ./src/models/zone.rs
|
||||||
4c1f676eaf0b6da45b4d4b090ae3ac862fb97c1f9e53284a1640767ae9591d8f ./src/notifications.rs
|
4c1f676eaf0b6da45b4d4b090ae3ac862fb97c1f9e53284a1640767ae9591d8f ./src/notifications.rs
|
||||||
7746bca683809b82529ed152272ae5c0cd3971758a02e076def58f770e7adf10 ./src/protocol/crypto.rs
|
7746bca683809b82529ed152272ae5c0cd3971758a02e076def58f770e7adf10 ./src/protocol/crypto.rs
|
||||||
578b9f39110abbeb98323044b6ae1a941733c82021afeb4d7ff78ad4256b5aa5 ./src/protocol/gree.rs
|
578b9f39110abbeb98323044b6ae1a941733c82021afeb4d7ff78ad4256b5aa5 ./src/protocol/gree.rs
|
||||||
5f9f46d3ee6d410b8848ad46f2c482159eebfd692e739b0f09941a43c8d97211 ./src/protocol/gree/binding.rs
|
2029bad472fdf9f73637be6b7168e9ac79f6bdb55d2bf440d4aa254f3db9659b ./src/protocol/gree/binding.rs
|
||||||
91d82c3ecae21615e4edad31b7ea95dca9b578650348666a2b61475b5a644669 ./src/protocol/gree/commands.rs
|
91d82c3ecae21615e4edad31b7ea95dca9b578650348666a2b61475b5a644669 ./src/protocol/gree/commands.rs
|
||||||
4e419ba3b86ca9d154e8c04445cf005965175c54041093b2daad3666d4d852bd ./src/protocol/gree/core.rs
|
4e419ba3b86ca9d154e8c04445cf005965175c54041093b2daad3666d4d852bd ./src/protocol/gree/core.rs
|
||||||
034344ab9b86a271854358cfc733d45386c90e8ea66e1f232afd927428422e3a ./src/protocol/gree/discovery.rs
|
f4e07ca05e037e29d08abb1635f2e6d475522ce517647c422e05b749cd648ad9 ./src/protocol/gree/discovery.rs
|
||||||
ff33db623f8f1bf30015b4a00e1f247a99de713da3d297c672e42c0795ec845c ./src/protocol/gree/network.rs
|
ff33db623f8f1bf30015b4a00e1f247a99de713da3d297c672e42c0795ec845c ./src/protocol/gree/network.rs
|
||||||
1076cb80950be00ca19f9e2370c73040902d1483b0e80c0ca349c7830d38c9f7 ./src/protocol/gree/polling.rs
|
1076cb80950be00ca19f9e2370c73040902d1483b0e80c0ca349c7830d38c9f7 ./src/protocol/gree/polling.rs
|
||||||
c438719392dfda8ddf1bccf4ad451038aa4f6aa8dc5477533b0aca96f3661bed ./src/protocol/gree/tests.rs
|
61d588dc055ac82f0f06fceac5236d5b4b7a0c0d2939144957a174bcbf2fa83c ./src/protocol/gree/tests.rs
|
||||||
3c93e5b254a2a40a07854532cb5fc07e493ad65d9ba2cf28093cff4a4a4e451c ./src/protocol/gree/transport.rs
|
3c93e5b254a2a40a07854532cb5fc07e493ad65d9ba2cf28093cff4a4a4e451c ./src/protocol/gree/transport.rs
|
||||||
b4e285f499dd787b75259777a14e3a51a1a071c7d176bcf30c1de0933920e0dc ./src/protocol/gree_cloud.rs
|
b4e285f499dd787b75259777a14e3a51a1a071c7d176bcf30c1de0933920e0dc ./src/protocol/gree_cloud.rs
|
||||||
b4b1bad9cad889dd69681b2afc3e6a09ef19e19b2a1f2900fd417c4b1f55ec2c ./src/protocol/gree_cloud_mqtt.rs
|
b4b1bad9cad889dd69681b2afc3e6a09ef19e19b2a1f2900fd417c4b1f55ec2c ./src/protocol/gree_cloud_mqtt.rs
|
||||||
@@ -202,7 +202,7 @@ b92a6cb158b494fe145b43c7641e65f6fafff47201d7d76edbec2cfd8b94835c ./systemd/gree
|
|||||||
0b783d6cea599e53fed4ed82fa95e2048c493057c6d57b0dfa423e7cfa10a7ad ./web/css/styles.css
|
0b783d6cea599e53fed4ed82fa95e2048c493057c6d57b0dfa423e7cfa10a7ad ./web/css/styles.css
|
||||||
183d122ba366303d9952ac0e68aff4bced4e0d9a468fbe51316c13f15227402b ./web/custom-chart.html
|
183d122ba366303d9952ac0e68aff4bced4e0d9a468fbe51316c13f15227402b ./web/custom-chart.html
|
||||||
e98bdd7204349cce1ec6f57283509697af0bbc72280622a6c3efa6fed242db4f ./web/favicon.svg
|
e98bdd7204349cce1ec6f57283509697af0bbc72280622a6c3efa6fed242db4f ./web/favicon.svg
|
||||||
baff48bb71ba348fe39d52fe8d2bef0614bb0c53c1ff5ee748ce09458b3983b2 ./web/index.html
|
cc1509fd76f0b0bd4c069db63e1e104210c2bed05f32a3eebac7642f94ef8a99 ./web/index.html
|
||||||
9ba3f6fa05b72aa989139b2a909982571b2a02055052e4c40104f1e81a9aa7eb ./web/js-dynamic/README.md
|
9ba3f6fa05b72aa989139b2a909982571b2a02055052e4c40104f1e81a9aa7eb ./web/js-dynamic/README.md
|
||||||
e74bb06dba646f298a4d118b5c2dca6ba24f1179ce8ea8d53c1acd6000ca332c ./web/js-dynamic/bootstrap.js
|
e74bb06dba646f298a4d118b5c2dca6ba24f1179ce8ea8d53c1acd6000ca332c ./web/js-dynamic/bootstrap.js
|
||||||
5d57253a013fd1cb79e4b8701d4be6e394e3f2acbce73dfcd726a86e5878f1a1 ./web/js-dynamic/charts.js
|
5d57253a013fd1cb79e4b8701d4be6e394e3f2acbce73dfcd726a86e5878f1a1 ./web/js-dynamic/charts.js
|
||||||
@@ -214,7 +214,7 @@ b4204241eecf387256364f4230b23ed50d947a362f4ceb1e528d69494e93d7cf ./web/js-dynam
|
|||||||
3ae714de6b71c068ba665c81a7689f994b1716284e8d937db669ad500f12cf63 ./web/js-dynamic/forms.js
|
3ae714de6b71c068ba665c81a7689f994b1716284e8d937db669ad500f12cf63 ./web/js-dynamic/forms.js
|
||||||
92d013bb5d64f64aa8c55380704540a5f72732bde7ccd16554965e401daf50ea ./web/js-dynamic/history.js
|
92d013bb5d64f64aa8c55380704540a5f72732bde7ccd16554965e401daf50ea ./web/js-dynamic/history.js
|
||||||
511c4e7cc4c48fbbdab64558a9d1c27e6759c9b6dca255d11f301b9708e955c7 ./web/js-dynamic/main.js
|
511c4e7cc4c48fbbdab64558a9d1c27e6759c9b6dca255d11f301b9708e955c7 ./web/js-dynamic/main.js
|
||||||
57d85a638359d720798068ef34c88237ab92ee08dcd7478055b806ff0c858aac ./web/js-dynamic/navigation.js
|
30cbaebb817d5d416e1a372595b647aae42c14b9cc406c4751d0ced563243b69 ./web/js-dynamic/navigation.js
|
||||||
0e398bad2cde85d4a62d8733c06e73f2b6a5b07db791d4570feba38c7ff8741f ./web/js-dynamic/realtime.js
|
0e398bad2cde85d4a62d8733c06e73f2b6a5b07db791d4570feba38c7ff8741f ./web/js-dynamic/realtime.js
|
||||||
1b667f0a8bce824b27f56a8d2f44ff8feef9a011289591dc629ee288db70d137 ./web/js-dynamic/router.js
|
1b667f0a8bce824b27f56a8d2f44ff8feef9a011289591dc629ee288db70d137 ./web/js-dynamic/router.js
|
||||||
c2710fd9c1f2b31878c1e25ceb02d74ae30456c1bbb400e69fcf7619ecc72bc2 ./web/js-dynamic/select-ui.js
|
c2710fd9c1f2b31878c1e25ceb02d74ae30456c1bbb400e69fcf7619ecc72bc2 ./web/js-dynamic/select-ui.js
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
**Version: 0.15.6**
|
**Version: 0.15.7**
|
||||||
|
|
||||||
Version 0.15.6 simplifies Local discovery to one API flow: scan candidates, select units, then add them. The obsolete add-all discovery endpoint and its compatibility code are removed.
|
Version 0.15.7 fixes mixed V1/V2 Local discovery: scan-envelope encryption is no longer mistaken for the device protocol, Auto binding verifies the real protocol, and V2-capable modules advertised through legacy discovery are classified correctly from their discovery metadata.
|
||||||
|
|
||||||
> [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.
|
||||||
> Built-in API: `/api/*` and `/ws`; interactive Swagger docs: `/api-docs`; OpenAPI JSON: `/api-docs/openapi.json`.
|
> Built-in API: `/api/*` and `/ws`; interactive Swagger docs: `/api-docs`; OpenAPI JSON: `/api-docs/openapi.json`.
|
||||||
@@ -185,7 +185,7 @@ Cloud REST and MQTT use TLS with certificate/hostname validation enabled. Passwo
|
|||||||
|
|
||||||
1. Place the controller host on a network that can reach the air-conditioner Wi-Fi modules by UDP.
|
1. Place the controller host on a network that can reach the air-conditioner Wi-Fi modules by UDP.
|
||||||
2. Open **Devices** and start discovery.
|
2. Open **Devices** and start discovery.
|
||||||
3. Auto protocol mode accepts both supported GREE encryption generations. Selecting V1 or V2 strictly filters discovery and bind to that generation.
|
3. Auto protocol mode accepts both supported GREE encryption generations. Discovery treats the reply envelope only as transport, uses the inner `ver` field as a V1/V2 hint, and verifies the real generation during bind with fallback. Selecting V1 or V2 keeps discovery and bind locked to that generation.
|
||||||
4. Review the discovery results (model, MAC and IP), select the units you want, then choose **Add selected**. Only selected units are persisted and bound.
|
4. Review the discovery results (model, MAC and IP), select the units you want, then choose **Add selected**. Only selected units are persisted and bound.
|
||||||
5. Create a thermostat zone for each unit you want the thermostat engine to own.
|
5. Create a thermostat zone for each unit you want the thermostat engine to own.
|
||||||
|
|
||||||
@@ -193,7 +193,7 @@ Discovery uses UDP broadcast, so routed/VLAN networks must explicitly permit or
|
|||||||
|
|
||||||
### Compatibility with newer GREE firmware
|
### Compatibility with newer GREE firmware
|
||||||
|
|
||||||
GREE Controller supports the two commonly reverse-engineered local LAN protocol generations used by compatible units: the older AES-ECB variant and the newer AES-GCM variant. Protocol auto-detection and binding already cover both generations.
|
GREE Controller supports the two commonly reverse-engineered local LAN protocol generations used by compatible units: the older AES-ECB variant and the newer AES-GCM variant. Some AES-GCM-capable modules still answer the common discovery scan through a legacy/plain envelope, so the envelope itself is not used as proof of V1. Auto mode uses discovery metadata as a hint and records the protocol that actually succeeds during bind.
|
||||||
|
|
||||||
Some newer GREE Wi-Fi modules and firmware releases have been reported to behave differently: the unit is reachable on the network and continues to work in the official GREE+ application, but does not answer the usual local UDP traffic on port `7000`. Reports include firmware branches such as `2.12` and `3.x`, although firmware numbering differs between Wi-Fi module families and should not be treated as a universal compatibility boundary.
|
Some newer GREE Wi-Fi modules and firmware releases have been reported to behave differently: the unit is reachable on the network and continues to work in the official GREE+ application, but does not answer the usual local UDP traffic on port `7000`. Reports include firmware branches such as `2.12` and `3.x`, although firmware numbering differs between Wi-Fi module families and should not be treated as a universal compatibility boundary.
|
||||||
|
|
||||||
|
|||||||
+19
-19
@@ -1,13 +1,13 @@
|
|||||||
de0793949cf01d27d903653226ecc9b5f72523d8711f20bcab022cf42c4c4ed0 ./.env.example
|
de0793949cf01d27d903653226ecc9b5f72523d8711f20bcab022cf42c4c4ed0 ./.env.example
|
||||||
a4ec3874a2e3ab1bad28fb40bb620f7b01f64d01ad9b699306bf70ada31227db ./.gitignore
|
a4ec3874a2e3ab1bad28fb40bb620f7b01f64d01ad9b699306bf70ada31227db ./.gitignore
|
||||||
03fd19b33f6b87a3cf55957c44c619dc65b6c1ef6ab35a275f7142e063fa130d ./Cargo.lock
|
bc531fc3bd260aa91bc4b3f000768d740222f6f80cd780cf2bbd4522d82d8841 ./Cargo.lock
|
||||||
0f1ebc69bb39b480c603772736bbc968cdeada29efecca6a056e4ebd0b071cb7 ./Cargo.toml
|
8555c5b50711059f76fdbaae495a6a56cae16813af2efd7c69a7fde34762949d ./Cargo.toml
|
||||||
19b2943504acb8f8de280f873a8dbec4bb6ebbe3870b158f5655d4fb8c298f5f ./LICENSE
|
19b2943504acb8f8de280f873a8dbec4bb6ebbe3870b158f5655d4fb8c298f5f ./LICENSE
|
||||||
252802f9b072e316a1898b5b39922788c0ed7ab769aba6e1cb33e5ac5595d7fb ./README.md
|
4d648f23faf4e57d2900f898ce5416dd0b2be9b842f18e67e8f6b31312c511dc ./README.md
|
||||||
29e9821e5ed216ea3565dd6d8bc0b174ed3cf9fa72c4ccebbfa99e98db3ad8f9 ./build.rs
|
29e9821e5ed216ea3565dd6d8bc0b174ed3cf9fa72c4ccebbfa99e98db3ad8f9 ./build.rs
|
||||||
c52fb51807e46086e6bb44dd532dde346a742d12d52ce703055f1d4f433fd253 ./docs/API.md
|
fe1bd7a84b16782f9ba2c3c301592b52b194698d7e71f0ba806a88ed3c5a9688 ./docs/API.md
|
||||||
a881ba0808dd3f189d92038f6163c39d6b6208f6dbff5c32c0ea1a2628f3fbb4 ./docs/FLOW.md
|
a881ba0808dd3f189d92038f6163c39d6b6208f6dbff5c32c0ea1a2628f3fbb4 ./docs/FLOW.md
|
||||||
524977fb867f2b56b56df827df0b8f646e366c00fa31d62c577a5a118f76406f ./docs/openapi.json
|
f70388d4fd9a5b35c1e32c43a9a4b4599adc6bd458e388ac571684a9cb1dc20d ./docs/openapi.json
|
||||||
77b8becf7a2c16a384ea85721d878b76e2d520549cb4455d9aa806e57e5a2ecd ./ha-addon/.env.example
|
77b8becf7a2c16a384ea85721d878b76e2d520549cb4455d9aa806e57e5a2ecd ./ha-addon/.env.example
|
||||||
0ca6e58170c2b8925194431ebbdb55f0c8b377fec5cd422cd2bd257e2d9328e3 ./ha-addon/Dockerfile
|
0ca6e58170c2b8925194431ebbdb55f0c8b377fec5cd422cd2bd257e2d9328e3 ./ha-addon/Dockerfile
|
||||||
0951696a2c2e66d4d969f8e7f8641184e3012f261583b31074bc38a7a1c0cc1a ./ha-addon/README.md
|
0951696a2c2e66d4d969f8e7f8641184e3012f261583b31074bc38a7a1c0cc1a ./ha-addon/README.md
|
||||||
@@ -21,7 +21,7 @@ b7f0873109c52be9d7f09bea3dffc416103c50085e1f0680d11661a969479898 ./ha-addon/hom
|
|||||||
6509286c7b7de638dcc5d40ce53181e65d1eddc5dc36a13306dc6d87220fedbb ./ha-addon/home-assistant/custom_components/gree_controller/coordinator.py
|
6509286c7b7de638dcc5d40ce53181e65d1eddc5dc36a13306dc6d87220fedbb ./ha-addon/home-assistant/custom_components/gree_controller/coordinator.py
|
||||||
5a96fe8f5c035c34f1339370270cd078056202d09e236dec75735be11de92a7d ./ha-addon/home-assistant/custom_components/gree_controller/entity_map.py
|
5a96fe8f5c035c34f1339370270cd078056202d09e236dec75735be11de92a7d ./ha-addon/home-assistant/custom_components/gree_controller/entity_map.py
|
||||||
c4fb75c246db651087900ebfc2291ff41ac87652cd6194fc0b776b0005c1cbcf ./ha-addon/home-assistant/custom_components/gree_controller/icon.png
|
c4fb75c246db651087900ebfc2291ff41ac87652cd6194fc0b776b0005c1cbcf ./ha-addon/home-assistant/custom_components/gree_controller/icon.png
|
||||||
45af41dd19b03ddc1d786730603ff2067bf3b3a794b7663acea8e45b5c1b7200 ./ha-addon/home-assistant/custom_components/gree_controller/manifest.json
|
396c1e2aa1dce367bd1b773ff2e9b80e09729ca58900dd5141085bf30a47f8f0 ./ha-addon/home-assistant/custom_components/gree_controller/manifest.json
|
||||||
c52a484b671ce738ecc00228a1db19a5d703f69ab27530c2896a5c2ae3b4a96f ./ha-addon/home-assistant/custom_components/gree_controller/number.py
|
c52a484b671ce738ecc00228a1db19a5d703f69ab27530c2896a5c2ae3b4a96f ./ha-addon/home-assistant/custom_components/gree_controller/number.py
|
||||||
39c4309001b75abb56234f05662bc06e077054986876f1927937edbce528ec95 ./ha-addon/home-assistant/custom_components/gree_controller/select.py
|
39c4309001b75abb56234f05662bc06e077054986876f1927937edbce528ec95 ./ha-addon/home-assistant/custom_components/gree_controller/select.py
|
||||||
cca65482e36d48035aca178121a378fe7d578d600acff267ae81a6399c0da653 ./ha-addon/home-assistant/custom_components/gree_controller/sensor.py
|
cca65482e36d48035aca178121a378fe7d578d600acff267ae81a6399c0da653 ./ha-addon/home-assistant/custom_components/gree_controller/sensor.py
|
||||||
@@ -29,21 +29,21 @@ cca65482e36d48035aca178121a378fe7d578d600acff267ae81a6399c0da653 ./ha-addon/hom
|
|||||||
a745cc458c235158d5d70b6a33d8000fd8b40ff93bfe2f2796af0f4b3a9eef9b ./ha-addon/home-assistant/custom_components/gree_controller/translations/en.json
|
a745cc458c235158d5d70b6a33d8000fd8b40ff93bfe2f2796af0f4b3a9eef9b ./ha-addon/home-assistant/custom_components/gree_controller/translations/en.json
|
||||||
50b7d6fe6329ad4ea6bee9612ab141c2f73f8382fcc2af0bb076a8e8d4dd4465 ./ha-addon/home-assistant/custom_components/gree_controller/translations/pl.json
|
50b7d6fe6329ad4ea6bee9612ab141c2f73f8382fcc2af0bb076a8e8d4dd4465 ./ha-addon/home-assistant/custom_components/gree_controller/translations/pl.json
|
||||||
c5fc5c87273d82d2834a0a5a365c821a416413ed509613441e24e4dc3507c4d2 ./ha-addon/home-assistant/generated/gree_controller_entities.example.json
|
c5fc5c87273d82d2834a0a5a365c821a416413ed509613441e24e4dc3507c4d2 ./ha-addon/home-assistant/generated/gree_controller_entities.example.json
|
||||||
732265515c1d45eb11b966919cfa29ed9f600b6dd02a05e1abee8afda4151213 ./ha-addon/repository/gree-controller/CHANGELOG.md
|
861a1df8677b0539720978aa0e84e7ffc7dea96d37e6d99c6adca2ced0851a44 ./ha-addon/repository/gree-controller/CHANGELOG.md
|
||||||
50b8ba050c6b4919e4d057f7b38c1e23d3913b5b7c87552626452e9695d37251 ./ha-addon/repository/gree-controller/DOCS.md
|
50b8ba050c6b4919e4d057f7b38c1e23d3913b5b7c87552626452e9695d37251 ./ha-addon/repository/gree-controller/DOCS.md
|
||||||
e3834bf712d4cd2acc715d8c85db96dd6e2fb3fbb758dac537f6034c337b3745 ./ha-addon/repository/gree-controller/README.md
|
e3834bf712d4cd2acc715d8c85db96dd6e2fb3fbb758dac537f6034c337b3745 ./ha-addon/repository/gree-controller/README.md
|
||||||
d742c16e5f5f24be48f8055c2131ff335fb5072469d7d515328fd41e9c3aca34 ./ha-addon/repository/gree-controller/config.yaml
|
40d18f2415fb84fe83d79ec19a9c9ca20232d751e02e5713786bac4d38f715a1 ./ha-addon/repository/gree-controller/config.yaml
|
||||||
3aae6cdae4c3aaab7786a9575e7093b7e2c5b69288167075f4b7475611691a6b ./ha-addon/repository/gree-controller/topologia-ha-vlan-gree-pl.png
|
3aae6cdae4c3aaab7786a9575e7093b7e2c5b69288167075f4b7475611691a6b ./ha-addon/repository/gree-controller/topologia-ha-vlan-gree-pl.png
|
||||||
0d0b42a7639b128946eec379175436fa1f150294f39d2dfd169077bfa87fd14d ./ha-addon/repository/gree-controller/topology-ha-vlan-gree-en.png
|
0d0b42a7639b128946eec379175436fa1f150294f39d2dfd169077bfa87fd14d ./ha-addon/repository/gree-controller/topology-ha-vlan-gree-en.png
|
||||||
2272740b185e9520e948f74b8f45cf98b8b5fd28c93bdee760da626f91fe5c2a ./ha-addon/repository/gree-controller/translations/en.yaml
|
2272740b185e9520e948f74b8f45cf98b8b5fd28c93bdee760da626f91fe5c2a ./ha-addon/repository/gree-controller/translations/en.yaml
|
||||||
e6b93d3701d83a31506617a0e6f44ff32d8c24a52be038c8540c862b13546b50 ./ha-addon/repository/gree-controller/translations/pl.yaml
|
e6b93d3701d83a31506617a0e6f44ff32d8c24a52be038c8540c862b13546b50 ./ha-addon/repository/gree-controller/translations/pl.yaml
|
||||||
b54c60ceeac06d32af7797da9e83b90cb037600318e00512da523d37b94d3081 ./ha-addon/repository/repository.yaml
|
2153b230357aab4766398577e23a7a9ff83bb135ddc86d1b3f2cbfc852efe0a1 ./ha-addon/repository/repository.yaml
|
||||||
cea12bc74c066a588a5ef0ef7bad9d4906bdbcea99f2d275429b0eefc94b4b5f ./ha-addon/run.sh
|
cea12bc74c066a588a5ef0ef7bad9d4906bdbcea99f2d275429b0eefc94b4b5f ./ha-addon/run.sh
|
||||||
081e27b6e43070d44f865335c30a42a5a29668eaa6a5ea5ab6967ac4447b8e06 ./ha-addon/sync-repository.sh
|
081e27b6e43070d44f865335c30a42a5a29668eaa6a5ea5ab6967ac4447b8e06 ./ha-addon/sync-repository.sh
|
||||||
f9e31de3d109ead32bf531c074d46a087df398d62488caee0b46b5e0a1c027f7 ./ha_addon.md
|
f9e31de3d109ead32bf531c074d46a087df398d62488caee0b46b5e0a1c027f7 ./ha_addon.md
|
||||||
253a0bc912786e67ea7fc92a64e4a510ad973bec343a88ccfb1f28fca3e8cf01 ./lang/README.md
|
253a0bc912786e67ea7fc92a64e4a510ad973bec343a88ccfb1f28fca3e8cf01 ./lang/README.md
|
||||||
2175f4ce8b5d994e1e4f912244b03721a93a41e2970f39826d6ea15fdaa7078e ./lang/en.json
|
37d24f8de343b4796a0a8cfff3a839e55bdb779add0c8119799787d87ad8b953 ./lang/en.json
|
||||||
1055d5835329c03eb6f5b8fab4ee438c76b23d6eebdadf70effa42998c03a279 ./lang/pl.json
|
1610da0b2bbb9424006647adfb95e1318b7670aaed5a2798db1251db82635317 ./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
|
||||||
@@ -84,7 +84,7 @@ fdcd9a5055d08037278b842e7ab69265345c5811f0a06867136c511d140bb191 ./presets/wind
|
|||||||
804f22123cd3e8db0fac791826c8dd9f758fb866c8e3b5655fb6d25d259dccf1 ./presets/workday_comfort.json
|
804f22123cd3e8db0fac791826c8dd9f758fb866c8e3b5655fb6d25d259dccf1 ./presets/workday_comfort.json
|
||||||
fd7390d64a2378352c09382accf6efff43903d952d111b22a982f06c5b2a3b4b ./regenerate-sha.sh
|
fd7390d64a2378352c09382accf6efff43903d952d111b22a982f06c5b2a3b4b ./regenerate-sha.sh
|
||||||
c64b1c6deeb24f20af662bfce7fa3683703914987241107ce664fa2f6d1a9dcb ./scripts/README.md
|
c64b1c6deeb24f20af662bfce7fa3683703914987241107ce664fa2f6d1a9dcb ./scripts/README.md
|
||||||
03d5ee12306c95d5ae5df4a2a3a422fe5044e0961bb2be4b7ee49641a9ee7fc1 ./scripts/api_dev_test.py
|
9083c4a8c602698a53d926864f2fe7e8c9658379f3d82fcb4171f44ec946a7ad ./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
|
||||||
@@ -104,7 +104,7 @@ b53e1afab342634fedc218ea4517446f19a5ba7985dee599e191b37d9cc8058a ./src/api.rs
|
|||||||
27a788efe385ad7180cb7fc7ec66c34ebd5e6062d9cdf35b32fb461e52a42863 ./src/api/configuration.rs
|
27a788efe385ad7180cb7fc7ec66c34ebd5e6062d9cdf35b32fb461e52a42863 ./src/api/configuration.rs
|
||||||
19bc141286a336ad67e99079496eb0ae5126f986ab28be62b5f97758e5f6969c ./src/api/debug_tokens.rs
|
19bc141286a336ad67e99079496eb0ae5126f986ab28be62b5f97758e5f6969c ./src/api/debug_tokens.rs
|
||||||
ca21f6d5a407e2e3532899d53ba4e8682c2fe961a46d8cd870ddc459721513ef ./src/api/device_groups.rs
|
ca21f6d5a407e2e3532899d53ba4e8682c2fe961a46d8cd870ddc459721513ef ./src/api/device_groups.rs
|
||||||
f775aa2f3c5c554e4197d47cf381f3d2133ea4c1430a5510f045188dd41e5e51 ./src/api/devices.rs
|
8f92909dc575ea6238f4a003f8bd4056c2752fa3247b9ab226e47f875c80b916 ./src/api/devices.rs
|
||||||
4b5b784670ae761a6848b9a33fe3fb391bebd39d65e87936907428711e96ca44 ./src/api/events.rs
|
4b5b784670ae761a6848b9a33fe3fb391bebd39d65e87936907428711e96ca44 ./src/api/events.rs
|
||||||
2ef2f64b77886e2abd6b410adf8de91a2333d3ebdb8fcee8376ba566e5bba029 ./src/api/flows.rs
|
2ef2f64b77886e2abd6b410adf8de91a2333d3ebdb8fcee8376ba566e5bba029 ./src/api/flows.rs
|
||||||
82c02fa135132ea3ebdb4d88dd1210dc536d22f987151d7f82595ee3d3d03440 ./src/api/gree_cloud.rs
|
82c02fa135132ea3ebdb4d88dd1210dc536d22f987151d7f82595ee3d3d03440 ./src/api/gree_cloud.rs
|
||||||
@@ -169,20 +169,20 @@ fc5f2802a073a175a8985e56bcb87eb1ff481226d5b4eeabad73dbba1839fc45 ./src/models/c
|
|||||||
aeab5b5acf35d38a54fd1d82e964fe56635ade69c0149ad423df317095d01555 ./src/models/flow.rs
|
aeab5b5acf35d38a54fd1d82e964fe56635ade69c0149ad423df317095d01555 ./src/models/flow.rs
|
||||||
6e44df6bde2f73c282095c80ac17287e5bef77d9fc1d344e440d863dae5f5031 ./src/models/history.rs
|
6e44df6bde2f73c282095c80ac17287e5bef77d9fc1d344e440d863dae5f5031 ./src/models/history.rs
|
||||||
1fee89f939018bf1f3686c15f25434f01ab96b3239164108db7f348a1f1f8d82 ./src/models/integrations.rs
|
1fee89f939018bf1f3686c15f25434f01ab96b3239164108db7f348a1f1f8d82 ./src/models/integrations.rs
|
||||||
53caf9ba4667a2ae33d5c3ce69f85005d9f8540f2ee3c16c2cb3795a53e9d21f ./src/models/runtime.rs
|
e557ee4a443de586a7ea7dd04318694fb30d6ec053076429503e18f1bcd65c9e ./src/models/runtime.rs
|
||||||
41b85cff6fd234c8d6ea007b2c3c22df5fee5107dcd57c64dcc94a356ff70c12 ./src/models/settings_api.rs
|
41b85cff6fd234c8d6ea007b2c3c22df5fee5107dcd57c64dcc94a356ff70c12 ./src/models/settings_api.rs
|
||||||
c4de6101de85d9d7e6814b2504b87d9216561e3d9e274054f081f505fb152140 ./src/models/temporary_thermostat.rs
|
c4de6101de85d9d7e6814b2504b87d9216561e3d9e274054f081f505fb152140 ./src/models/temporary_thermostat.rs
|
||||||
bc2818ce8d0dae1edfb1b98e5d1c00b193f03eeaa28e343d3532f6023288738c ./src/models/zone.rs
|
bc2818ce8d0dae1edfb1b98e5d1c00b193f03eeaa28e343d3532f6023288738c ./src/models/zone.rs
|
||||||
4c1f676eaf0b6da45b4d4b090ae3ac862fb97c1f9e53284a1640767ae9591d8f ./src/notifications.rs
|
4c1f676eaf0b6da45b4d4b090ae3ac862fb97c1f9e53284a1640767ae9591d8f ./src/notifications.rs
|
||||||
7746bca683809b82529ed152272ae5c0cd3971758a02e076def58f770e7adf10 ./src/protocol/crypto.rs
|
7746bca683809b82529ed152272ae5c0cd3971758a02e076def58f770e7adf10 ./src/protocol/crypto.rs
|
||||||
578b9f39110abbeb98323044b6ae1a941733c82021afeb4d7ff78ad4256b5aa5 ./src/protocol/gree.rs
|
578b9f39110abbeb98323044b6ae1a941733c82021afeb4d7ff78ad4256b5aa5 ./src/protocol/gree.rs
|
||||||
5f9f46d3ee6d410b8848ad46f2c482159eebfd692e739b0f09941a43c8d97211 ./src/protocol/gree/binding.rs
|
2029bad472fdf9f73637be6b7168e9ac79f6bdb55d2bf440d4aa254f3db9659b ./src/protocol/gree/binding.rs
|
||||||
91d82c3ecae21615e4edad31b7ea95dca9b578650348666a2b61475b5a644669 ./src/protocol/gree/commands.rs
|
91d82c3ecae21615e4edad31b7ea95dca9b578650348666a2b61475b5a644669 ./src/protocol/gree/commands.rs
|
||||||
4e419ba3b86ca9d154e8c04445cf005965175c54041093b2daad3666d4d852bd ./src/protocol/gree/core.rs
|
4e419ba3b86ca9d154e8c04445cf005965175c54041093b2daad3666d4d852bd ./src/protocol/gree/core.rs
|
||||||
034344ab9b86a271854358cfc733d45386c90e8ea66e1f232afd927428422e3a ./src/protocol/gree/discovery.rs
|
f4e07ca05e037e29d08abb1635f2e6d475522ce517647c422e05b749cd648ad9 ./src/protocol/gree/discovery.rs
|
||||||
ff33db623f8f1bf30015b4a00e1f247a99de713da3d297c672e42c0795ec845c ./src/protocol/gree/network.rs
|
ff33db623f8f1bf30015b4a00e1f247a99de713da3d297c672e42c0795ec845c ./src/protocol/gree/network.rs
|
||||||
1076cb80950be00ca19f9e2370c73040902d1483b0e80c0ca349c7830d38c9f7 ./src/protocol/gree/polling.rs
|
1076cb80950be00ca19f9e2370c73040902d1483b0e80c0ca349c7830d38c9f7 ./src/protocol/gree/polling.rs
|
||||||
c438719392dfda8ddf1bccf4ad451038aa4f6aa8dc5477533b0aca96f3661bed ./src/protocol/gree/tests.rs
|
61d588dc055ac82f0f06fceac5236d5b4b7a0c0d2939144957a174bcbf2fa83c ./src/protocol/gree/tests.rs
|
||||||
3c93e5b254a2a40a07854532cb5fc07e493ad65d9ba2cf28093cff4a4a4e451c ./src/protocol/gree/transport.rs
|
3c93e5b254a2a40a07854532cb5fc07e493ad65d9ba2cf28093cff4a4a4e451c ./src/protocol/gree/transport.rs
|
||||||
b4e285f499dd787b75259777a14e3a51a1a071c7d176bcf30c1de0933920e0dc ./src/protocol/gree_cloud.rs
|
b4e285f499dd787b75259777a14e3a51a1a071c7d176bcf30c1de0933920e0dc ./src/protocol/gree_cloud.rs
|
||||||
b4b1bad9cad889dd69681b2afc3e6a09ef19e19b2a1f2900fd417c4b1f55ec2c ./src/protocol/gree_cloud_mqtt.rs
|
b4b1bad9cad889dd69681b2afc3e6a09ef19e19b2a1f2900fd417c4b1f55ec2c ./src/protocol/gree_cloud_mqtt.rs
|
||||||
@@ -201,7 +201,7 @@ b92a6cb158b494fe145b43c7641e65f6fafff47201d7d76edbec2cfd8b94835c ./systemd/gree
|
|||||||
0b783d6cea599e53fed4ed82fa95e2048c493057c6d57b0dfa423e7cfa10a7ad ./web/css/styles.css
|
0b783d6cea599e53fed4ed82fa95e2048c493057c6d57b0dfa423e7cfa10a7ad ./web/css/styles.css
|
||||||
183d122ba366303d9952ac0e68aff4bced4e0d9a468fbe51316c13f15227402b ./web/custom-chart.html
|
183d122ba366303d9952ac0e68aff4bced4e0d9a468fbe51316c13f15227402b ./web/custom-chart.html
|
||||||
e98bdd7204349cce1ec6f57283509697af0bbc72280622a6c3efa6fed242db4f ./web/favicon.svg
|
e98bdd7204349cce1ec6f57283509697af0bbc72280622a6c3efa6fed242db4f ./web/favicon.svg
|
||||||
baff48bb71ba348fe39d52fe8d2bef0614bb0c53c1ff5ee748ce09458b3983b2 ./web/index.html
|
cc1509fd76f0b0bd4c069db63e1e104210c2bed05f32a3eebac7642f94ef8a99 ./web/index.html
|
||||||
9ba3f6fa05b72aa989139b2a909982571b2a02055052e4c40104f1e81a9aa7eb ./web/js-dynamic/README.md
|
9ba3f6fa05b72aa989139b2a909982571b2a02055052e4c40104f1e81a9aa7eb ./web/js-dynamic/README.md
|
||||||
e74bb06dba646f298a4d118b5c2dca6ba24f1179ce8ea8d53c1acd6000ca332c ./web/js-dynamic/bootstrap.js
|
e74bb06dba646f298a4d118b5c2dca6ba24f1179ce8ea8d53c1acd6000ca332c ./web/js-dynamic/bootstrap.js
|
||||||
5d57253a013fd1cb79e4b8701d4be6e394e3f2acbce73dfcd726a86e5878f1a1 ./web/js-dynamic/charts.js
|
5d57253a013fd1cb79e4b8701d4be6e394e3f2acbce73dfcd726a86e5878f1a1 ./web/js-dynamic/charts.js
|
||||||
@@ -213,7 +213,7 @@ b4204241eecf387256364f4230b23ed50d947a362f4ceb1e528d69494e93d7cf ./web/js-dynam
|
|||||||
3ae714de6b71c068ba665c81a7689f994b1716284e8d937db669ad500f12cf63 ./web/js-dynamic/forms.js
|
3ae714de6b71c068ba665c81a7689f994b1716284e8d937db669ad500f12cf63 ./web/js-dynamic/forms.js
|
||||||
92d013bb5d64f64aa8c55380704540a5f72732bde7ccd16554965e401daf50ea ./web/js-dynamic/history.js
|
92d013bb5d64f64aa8c55380704540a5f72732bde7ccd16554965e401daf50ea ./web/js-dynamic/history.js
|
||||||
511c4e7cc4c48fbbdab64558a9d1c27e6759c9b6dca255d11f301b9708e955c7 ./web/js-dynamic/main.js
|
511c4e7cc4c48fbbdab64558a9d1c27e6759c9b6dca255d11f301b9708e955c7 ./web/js-dynamic/main.js
|
||||||
57d85a638359d720798068ef34c88237ab92ee08dcd7478055b806ff0c858aac ./web/js-dynamic/navigation.js
|
30cbaebb817d5d416e1a372595b647aae42c14b9cc406c4751d0ced563243b69 ./web/js-dynamic/navigation.js
|
||||||
0e398bad2cde85d4a62d8733c06e73f2b6a5b07db791d4570feba38c7ff8741f ./web/js-dynamic/realtime.js
|
0e398bad2cde85d4a62d8733c06e73f2b6a5b07db791d4570feba38c7ff8741f ./web/js-dynamic/realtime.js
|
||||||
1b667f0a8bce824b27f56a8d2f44ff8feef9a011289591dc629ee288db70d137 ./web/js-dynamic/router.js
|
1b667f0a8bce824b27f56a8d2f44ff8feef9a011289591dc629ee288db70d137 ./web/js-dynamic/router.js
|
||||||
c2710fd9c1f2b31878c1e25ceb02d74ae30456c1bbb400e69fcf7619ecc72bc2 ./web/js-dynamic/select-ui.js
|
c2710fd9c1f2b31878c1e25ceb02d74ae30456c1bbb400e69fcf7619ecc72bc2 ./web/js-dynamic/select-ui.js
|
||||||
|
|||||||
+8
-6
@@ -1,6 +1,6 @@
|
|||||||
# GREE Controller API reference
|
# GREE Controller API reference
|
||||||
|
|
||||||
HTTP and WebSocket API for GREE Controller **0.15.6**.
|
HTTP and WebSocket API for GREE Controller **0.15.7**.
|
||||||
|
|
||||||
[← Main documentation](../README.md)
|
[← Main documentation](../README.md)
|
||||||
|
|
||||||
@@ -241,7 +241,7 @@ Response:
|
|||||||
{
|
{
|
||||||
"status": "ok",
|
"status": "ok",
|
||||||
"name": "gree-controller",
|
"name": "gree-controller",
|
||||||
"version": "0.15.6",
|
"version": "0.15.7",
|
||||||
"uptime_seconds": 1234,
|
"uptime_seconds": 1234,
|
||||||
"control_ready": true,
|
"control_ready": true,
|
||||||
"time": "2026-08-30T06:54:00Z"
|
"time": "2026-08-30T06:54:00Z"
|
||||||
@@ -304,7 +304,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.15.6",
|
"version": "0.15.7",
|
||||||
"uptime_seconds": 1234,
|
"uptime_seconds": 1234,
|
||||||
"auth_required": false,
|
"auth_required": false,
|
||||||
"control_ready": true,
|
"control_ready": true,
|
||||||
@@ -388,9 +388,9 @@ Scans without adding or binding anything. Request body fields are optional:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`protocol_version` accepts `0` (auto/both), `1` (AES-ECB only) or `2` (AES-GCM only). Explicit V1/V2 selection rejects replies from the other protocol generation before decryption. The UDP scan packet itself is common to both generations.
|
`protocol_version` accepts `0` (auto/both), `1` (AES-ECB only) or `2` (AES-GCM only). The UDP scan packet is common to both generations, and newer V2-capable modules may advertise through a legacy/plain discovery envelope. Discovery therefore decodes the reply first and uses the inner `ver` metadata as the protocol hint (`V1.*` -> V1, `V2.*` and newer -> V2). Auto keeps unresolved replies as protocol `0`; explicit V1/V2 scans return only candidates whose hint matches the selected generation.
|
||||||
|
|
||||||
The response contains candidates with MAC, IP, detected protocol and an `already_added` flag:
|
The response contains candidates with MAC, IP, protocol hint, a `protocol_locked` flag and an `already_added` flag:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -402,6 +402,7 @@ The response contains candidates with MAC, IP, detected protocol and an `already
|
|||||||
"ip": "192.168.50.30",
|
"ip": "192.168.50.30",
|
||||||
"port": 7000,
|
"port": 7000,
|
||||||
"protocol_version": 1,
|
"protocol_version": 1,
|
||||||
|
"protocol_locked": false,
|
||||||
"model": "GREE",
|
"model": "GREE",
|
||||||
"firmware": "",
|
"firmware": "",
|
||||||
"already_added": false
|
"already_added": false
|
||||||
@@ -423,6 +424,7 @@ Add only selected candidates returned by `/api/discovery/scan`:
|
|||||||
"ip": "192.168.50.30",
|
"ip": "192.168.50.30",
|
||||||
"port": 7000,
|
"port": 7000,
|
||||||
"protocol_version": 1,
|
"protocol_version": 1,
|
||||||
|
"protocol_locked": false,
|
||||||
"model": "GREE",
|
"model": "GREE",
|
||||||
"firmware": "",
|
"firmware": "",
|
||||||
"already_added": false
|
"already_added": false
|
||||||
@@ -431,7 +433,7 @@ Add only selected candidates returned by `/api/discovery/scan`:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Each selected candidate is bound strictly with its detected `protocol_version`. Existing MAC addresses are skipped.
|
For Auto discovery (`protocol_locked=false`), `protocol_version` is only the preferred bind order. The controller falls back to the other generation if needed and stores the protocol that actually binds successfully. Explicit V1/V2 discovery returns `protocol_locked=true` and binds strictly with the selected protocol. Existing MAC addresses are skipped.
|
||||||
|
|
||||||
### `GET /api/devices`
|
### `GET /api/devices`
|
||||||
|
|
||||||
|
|||||||
+14
-7
@@ -2,7 +2,7 @@
|
|||||||
"openapi": "3.1.0",
|
"openapi": "3.1.0",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "GREE Controller API",
|
"title": "GREE Controller API",
|
||||||
"version": "0.15.6",
|
"version": "0.15.7",
|
||||||
"summary": "Local HTTP/WebSocket API for GREE Controller",
|
"summary": "Local HTTP/WebSocket API for GREE Controller",
|
||||||
"description": "Local API used by the GREE Controller Web UI and Home Assistant integration.",
|
"description": "Local API used by the GREE Controller Web UI and Home Assistant integration.",
|
||||||
"license": {
|
"license": {
|
||||||
@@ -204,7 +204,7 @@
|
|||||||
"Devices"
|
"Devices"
|
||||||
],
|
],
|
||||||
"summary": "Scan for local GREE devices",
|
"summary": "Scan for local GREE devices",
|
||||||
"description": "Broadcasts GREE discovery and returns local device candidates without persisting or binding them. protocol_version=1 or 2 strictly accepts only that protocol; protocol_version=0 accepts both.",
|
"description": "Broadcasts GREE discovery and returns local device candidates without persisting or binding them. The scan envelope is not treated as the device protocol: Auto decodes replies, uses inner ver metadata as a V1/V2 hint and keeps unresolved candidates as protocol 0. Explicit protocol_version=1 or 2 returns only candidates whose resolved hint matches the selected generation.",
|
||||||
"operationId": "scanDiscoveredDevices",
|
"operationId": "scanDiscoveredDevices",
|
||||||
"requestBody": {
|
"requestBody": {
|
||||||
"required": true,
|
"required": true,
|
||||||
@@ -262,7 +262,7 @@
|
|||||||
"Devices"
|
"Devices"
|
||||||
],
|
],
|
||||||
"summary": "Add selected discovered devices",
|
"summary": "Add selected discovered devices",
|
||||||
"description": "Persists and binds only the local discovery candidates selected by the caller. Each selected unit is bound strictly with the protocol version detected during the scan.",
|
"description": "Persists and binds only the local discovery candidates selected by the caller. Auto-discovered candidates use their protocol hint as the preferred bind order, fall back to the other generation, and persist the protocol that actually succeeds. Candidates from explicit V1/V2 discovery are bound strictly.",
|
||||||
"operationId": "addDiscoveredDevices",
|
"operationId": "addDiscoveredDevices",
|
||||||
"requestBody": {
|
"requestBody": {
|
||||||
"required": true,
|
"required": true,
|
||||||
@@ -281,7 +281,8 @@
|
|||||||
"protocol_version": 1,
|
"protocol_version": 1,
|
||||||
"model": "GREE",
|
"model": "GREE",
|
||||||
"firmware": "",
|
"firmware": "",
|
||||||
"already_added": false
|
"already_added": false,
|
||||||
|
"protocol_locked": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -5966,7 +5967,7 @@
|
|||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"example": "0.15.6"
|
"example": "0.15.7"
|
||||||
},
|
},
|
||||||
"uptime_seconds": {
|
"uptime_seconds": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
@@ -6685,7 +6686,7 @@
|
|||||||
},
|
},
|
||||||
"protocol_version": {
|
"protocol_version": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "0=auto/both, 1=AES-ECB, 2=AES-GCM",
|
"description": "0=auto/both with protocol hint + bind verification, 1=AES-ECB only, 2=AES-GCM only",
|
||||||
"minimum": 0,
|
"minimum": 0,
|
||||||
"maximum": 2,
|
"maximum": 2,
|
||||||
"example": 0
|
"example": 0
|
||||||
@@ -9663,10 +9664,16 @@
|
|||||||
"protocol_version": {
|
"protocol_version": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"enum": [
|
"enum": [
|
||||||
|
0,
|
||||||
1,
|
1,
|
||||||
2
|
2
|
||||||
],
|
],
|
||||||
"description": "Detected protocol generation"
|
"description": "Discovery protocol hint: 0=unknown/auto, 1=legacy AES-ECB, 2=AES-GCM"
|
||||||
|
},
|
||||||
|
"protocol_locked": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"description": "True when discovery explicitly selected V1 or V2; false for Auto so binding may verify/fallback"
|
||||||
},
|
},
|
||||||
"model": {
|
"model": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"domain": "gree_controller",
|
"domain": "gree_controller",
|
||||||
"name": "GREE Controller",
|
"name": "GREE Controller",
|
||||||
"version": "0.15.6",
|
"version": "0.15.7",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"integration_type": "hub",
|
"integration_type": "hub",
|
||||||
"iot_class": "local_polling",
|
"iot_class": "local_polling",
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.15.7
|
||||||
|
|
||||||
|
- Fixes mixed V1/V2 Local discovery: legacy/plain discovery envelopes are no longer treated as proof that a unit is V1.
|
||||||
|
- Uses the inner GREE `ver` metadata as a discovery protocol hint (`V1.*` -> V1, `V2.*`/newer -> V2), while keeping unknown results in Auto mode.
|
||||||
|
- Auto discovery now verifies the protocol during bind with V1/V2 fallback and persists the generation that actually succeeds; explicit V1/V2 discovery remains locked to the selected protocol.
|
||||||
|
- The discovery review UI shows Auto for unresolved candidates instead of incorrectly labeling them V1.
|
||||||
|
|
||||||
## 0.15.6
|
## 0.15.6
|
||||||
|
|
||||||
- Removes the obsolete add-all `POST /api/discovery` endpoint and its compatibility-only merge path.
|
- Removes the obsolete add-all `POST /api/discovery` endpoint and its compatibility-only merge path.
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
name: "GREE Controller"
|
name: "GREE Controller"
|
||||||
version: "0.15.6"
|
version: "0.15.7"
|
||||||
slug: "gree_controller"
|
slug: "gree_controller"
|
||||||
description: "Local GREE HVAC controller with Web UI, API, Swagger API docs and Home Assistant integration"
|
description: "Local GREE HVAC controller with Web UI, API, and Home Assistant integration"
|
||||||
url: "https://repo.example.com/gree-controller-ha-addon/"
|
url: "https://git.linuxiarz.pl/gru/gree-controller-ha-addon/"
|
||||||
arch:
|
arch:
|
||||||
- amd64
|
- amd64
|
||||||
- aarch64
|
- aarch64
|
||||||
image: "repo.example.com/gree-controller"
|
image: "zot.linuxiarz.pl/gree-controller"
|
||||||
startup: application
|
startup: application
|
||||||
boot: auto
|
boot: auto
|
||||||
init: false
|
init: false
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
name: GREE Controller
|
name: GREE Controller
|
||||||
url: https://repo.example.com/gree-controller-ha-addon/
|
url: https://git.linuxiarz.pl/gru/gree-controller-ha-addon/
|
||||||
maintainer: linuxiarz.pl
|
maintainer: linuxiarz.pl
|
||||||
|
|||||||
+2
-2
@@ -296,14 +296,14 @@
|
|||||||
"devices.savedAndChecked": "Saved and connection confirmed",
|
"devices.savedAndChecked": "Saved and connection confirmed",
|
||||||
"devices.savedCheckFailed": "Configuration saved, but the connection test failed",
|
"devices.savedCheckFailed": "Configuration saved, but the connection test failed",
|
||||||
"discovery.title": "Discover GREE devices",
|
"discovery.title": "Discover GREE devices",
|
||||||
"discovery.help": "Auto accepts both AES-ECB and AES-GCM devices. Selecting V1 or V2 accepts and binds only that protocol. Multiple passes improve discovery when several Wi-Fi modules answer the same broadcast.",
|
"discovery.help": "Auto accepts both AES-ECB and AES-GCM devices, uses discovery metadata only as a protocol hint and verifies the actual protocol during binding. Selecting V1 or V2 keeps discovery and binding locked to that protocol. Multiple passes improve discovery when several Wi-Fi modules answer the same broadcast.",
|
||||||
"discovery.protocol": "Discovery protocol",
|
"discovery.protocol": "Discovery protocol",
|
||||||
"discovery.passes": "Scan passes",
|
"discovery.passes": "Scan passes",
|
||||||
"discovery.timeout": "Total scan time (ms)",
|
"discovery.timeout": "Total scan time (ms)",
|
||||||
"zones.quickHint": "Quick target and mode control",
|
"zones.quickHint": "Quick target and mode control",
|
||||||
"actions.later": "Later",
|
"actions.later": "Later",
|
||||||
"discovery.nameDevices": "Discovered local devices",
|
"discovery.nameDevices": "Discovered local devices",
|
||||||
"discovery.nameDevicesHelp": "Select the units you want to add. MAC address, IP address and detected protocol are shown for every result.",
|
"discovery.nameDevicesHelp": "Select the units you want to add. MAC address, IP address and the discovery protocol hint are shown for every result; Auto is resolved during binding.",
|
||||||
"dashboard.thermostats": "Thermostats",
|
"dashboard.thermostats": "Thermostats",
|
||||||
"common.unavailable": "Unavailable",
|
"common.unavailable": "Unavailable",
|
||||||
"mode.off": "Off",
|
"mode.off": "Off",
|
||||||
|
|||||||
+2
-2
@@ -296,14 +296,14 @@
|
|||||||
"devices.savedAndChecked": "Zapisano i potwierdzono połączenie",
|
"devices.savedAndChecked": "Zapisano i potwierdzono połączenie",
|
||||||
"devices.savedCheckFailed": "Zapisano konfigurację, ale test połączenia nie powiódł się",
|
"devices.savedCheckFailed": "Zapisano konfigurację, ale test połączenia nie powiódł się",
|
||||||
"discovery.title": "Wykrywanie urządzeń GREE",
|
"discovery.title": "Wykrywanie urządzeń GREE",
|
||||||
"discovery.help": "Auto akceptuje urządzenia AES-ECB i AES-GCM. Wybranie V1 lub V2 powoduje wyszukiwanie i bindowanie wyłącznie tym protokołem. Kilka przebiegów pomaga, gdy wiele modułów Wi-Fi odpowiada na ten sam broadcast.",
|
"discovery.help": "Auto akceptuje urządzenia AES-ECB i AES-GCM, traktuje dane discovery tylko jako wskazówkę protokołu i potwierdza właściwy protokół podczas bindowania. Wybranie V1 lub V2 blokuje wyszukiwanie i bindowanie do tego protokołu. Kilka przebiegów pomaga, gdy wiele modułów Wi-Fi odpowiada na ten sam broadcast.",
|
||||||
"discovery.protocol": "Protokół wykrywania",
|
"discovery.protocol": "Protokół wykrywania",
|
||||||
"discovery.passes": "Liczba przebiegów",
|
"discovery.passes": "Liczba przebiegów",
|
||||||
"discovery.timeout": "Łączny czas wyszukiwania (ms)",
|
"discovery.timeout": "Łączny czas wyszukiwania (ms)",
|
||||||
"zones.quickHint": "Szybka zmiana celu i trybu",
|
"zones.quickHint": "Szybka zmiana celu i trybu",
|
||||||
"actions.later": "Później",
|
"actions.later": "Później",
|
||||||
"discovery.nameDevices": "Wyszukane urządzenia lokalne",
|
"discovery.nameDevices": "Wyszukane urządzenia lokalne",
|
||||||
"discovery.nameDevicesHelp": "Wybierz jednostki, które chcesz dodać. Dla każdego wyniku widoczny jest adres MAC, adres IP i wykryty protokół.",
|
"discovery.nameDevicesHelp": "Wybierz jednostki, które chcesz dodać. Dla każdego wyniku widoczny jest adres MAC, adres IP i wskazówka protokołu z discovery; Auto zostanie rozstrzygnięte podczas bindowania.",
|
||||||
"dashboard.quickThermostats": "Termostaty",
|
"dashboard.quickThermostats": "Termostaty",
|
||||||
"common.unavailable": "Niedostępne",
|
"common.unavailable": "Niedostępne",
|
||||||
"mode.off": "Wyłączone",
|
"mode.off": "Wyłączone",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Developer smoke/integration tests for GREE Controller API 0.15.6.
|
"""Developer smoke/integration tests for GREE Controller API 0.15.7.
|
||||||
|
|
||||||
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.15.6"
|
DEFAULT_EXPECTED_VERSION = "0.15.7"
|
||||||
|
|
||||||
SETTINGS_PATHS: dict[str, set[str]] = {
|
SETTINGS_PATHS: dict[str, set[str]] = {
|
||||||
"/api/settings/application": {"simulator_enabled"},
|
"/api/settings/application": {"simulator_enabled"},
|
||||||
@@ -593,7 +593,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.15.6 contract", lambda: test_openapi(client, args.expected_version))
|
runner.run("OpenAPI 0.15.7 contract", lambda: test_openapi(client, args.expected_version))
|
||||||
runner.run("bootstrap snapshot contract", lambda: test_bootstrap_contract(client))
|
runner.run("bootstrap snapshot contract", lambda: test_bootstrap_contract(client))
|
||||||
runner.run("protected API requires auth", lambda: test_protected_auth(client))
|
runner.run("protected API requires auth", lambda: test_protected_auth(client))
|
||||||
|
|
||||||
|
|||||||
+30
-10
@@ -2,13 +2,18 @@ fn normalize_local_discovery_mac(value: &str) -> String {
|
|||||||
value.replace([':', '-'], "").trim().to_ascii_uppercase()
|
value.replace([':', '-'], "").trim().to_ascii_uppercase()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn local_discovery_candidate(device: &Device, already_added: bool) -> LocalDiscoveryCandidate {
|
fn local_discovery_candidate(
|
||||||
|
device: &Device,
|
||||||
|
already_added: bool,
|
||||||
|
protocol_locked: bool,
|
||||||
|
) -> LocalDiscoveryCandidate {
|
||||||
LocalDiscoveryCandidate {
|
LocalDiscoveryCandidate {
|
||||||
name: device.name.clone(),
|
name: device.name.clone(),
|
||||||
mac: device.mac.clone(),
|
mac: device.mac.clone(),
|
||||||
ip: device.ip.clone(),
|
ip: device.ip.clone(),
|
||||||
port: device.port,
|
port: device.port,
|
||||||
protocol_version: device.protocol_version,
|
protocol_version: device.protocol_version,
|
||||||
|
protocol_locked,
|
||||||
model: device.model.clone(),
|
model: device.model.clone(),
|
||||||
firmware: device.firmware.clone(),
|
firmware: device.firmware.clone(),
|
||||||
already_added,
|
already_added,
|
||||||
@@ -24,11 +29,16 @@ fn device_from_local_discovery(candidate: LocalDiscoveryCandidate) -> Result<Dev
|
|||||||
.ip
|
.ip
|
||||||
.parse::<IpAddr>()
|
.parse::<IpAddr>()
|
||||||
.map_err(|_| AppError::BadRequest(format!("invalid IP address for {mac}")))?;
|
.map_err(|_| AppError::BadRequest(format!("invalid IP address for {mac}")))?;
|
||||||
if !matches!(candidate.protocol_version, 1 | 2) {
|
if candidate.protocol_version > 2 {
|
||||||
return Err(AppError::BadRequest(format!(
|
return Err(AppError::BadRequest(format!(
|
||||||
"invalid protocol version for {mac}"
|
"invalid protocol version for {mac}"
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
if candidate.protocol_locked && candidate.protocol_version == 0 {
|
||||||
|
return Err(AppError::BadRequest(format!(
|
||||||
|
"locked discovery protocol is missing for {mac}"
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
let model = candidate.model.trim().to_string();
|
let model = candidate.model.trim().to_string();
|
||||||
let fallback_model = if model.is_empty() { "GREE" } else { &model };
|
let fallback_model = if model.is_empty() { "GREE" } else { &model };
|
||||||
@@ -151,7 +161,11 @@ async fn scan_discovery(
|
|||||||
for device in discovered {
|
for device in discovered {
|
||||||
let mac = normalize_local_discovery_mac(&device.mac);
|
let mac = normalize_local_discovery_mac(&device.mac);
|
||||||
let already_added = state.db.get_device_by_mac(&mac)?.is_some();
|
let already_added = state.db.get_device_by_mac(&mac)?.is_some();
|
||||||
candidates.push(local_discovery_candidate(&device, already_added));
|
candidates.push(local_discovery_candidate(
|
||||||
|
&device,
|
||||||
|
already_added,
|
||||||
|
protocol_version != 0,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
state.log(
|
state.log(
|
||||||
@@ -188,6 +202,7 @@ async fn add_discovered_devices(
|
|||||||
let mut skipped = Vec::new();
|
let mut skipped = Vec::new();
|
||||||
|
|
||||||
for candidate in request.devices {
|
for candidate in request.devices {
|
||||||
|
let protocol_locked = candidate.protocol_locked;
|
||||||
let mut device = device_from_local_discovery(candidate)?;
|
let mut device = device_from_local_discovery(candidate)?;
|
||||||
let _device_guard = state.lock_device_operation(&device.id).await;
|
let _device_guard = state.lock_device_operation(&device.id).await;
|
||||||
if state.db.get_device_by_mac(&device.mac)?.is_some() {
|
if state.db.get_device_by_mac(&device.mac)?.is_some() {
|
||||||
@@ -195,13 +210,17 @@ async fn add_discovered_devices(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
match state
|
let client = state.providers.local().client();
|
||||||
.providers
|
let bind_result = if protocol_locked {
|
||||||
.local()
|
client.bind_exact(&device, device.protocol_version).await
|
||||||
.client()
|
} else {
|
||||||
.bind_exact(&device, device.protocol_version)
|
// Auto discovery only provides a protocol hint. Try that generation
|
||||||
.await
|
// first, fall back to the other one, and persist the protocol that
|
||||||
{
|
// actually completes binding.
|
||||||
|
client.bind(&device).await
|
||||||
|
};
|
||||||
|
|
||||||
|
match bind_result {
|
||||||
Ok(bound) => {
|
Ok(bound) => {
|
||||||
device.key = Some(bound.key);
|
device.key = Some(bound.key);
|
||||||
device.protocol_version = bound.protocol_version;
|
device.protocol_version = bound.protocol_version;
|
||||||
@@ -217,6 +236,7 @@ async fn add_discovered_devices(
|
|||||||
json!({
|
json!({
|
||||||
"device_id": device.id,
|
"device_id": device.id,
|
||||||
"protocol_version": device.protocol_version,
|
"protocol_version": device.protocol_version,
|
||||||
|
"protocol_locked": protocol_locked,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,8 +124,13 @@ pub struct LocalDiscoveryCandidate {
|
|||||||
pub ip: String,
|
pub ip: String,
|
||||||
#[serde(default = "default_port")]
|
#[serde(default = "default_port")]
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
/// Detected protocol: 1 = AES-ECB, 2 = AES-GCM.
|
/// Discovery protocol hint: 0 = unknown/auto, 1 = AES-ECB, 2 = AES-GCM.
|
||||||
pub protocol_version: u8,
|
pub protocol_version: u8,
|
||||||
|
/// True only when the discovery request explicitly selected V1 or V2.
|
||||||
|
/// Auto discovery keeps this false so binding can verify/fallback and store
|
||||||
|
/// the protocol that actually succeeds.
|
||||||
|
#[serde(default)]
|
||||||
|
pub protocol_locked: bool,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub model: String,
|
pub model: String,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ impl GreeClient {
|
|||||||
self.bind_with_versions(device, versions).await
|
self.bind_with_versions(device, versions).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bind using exactly the protocol detected during discovery.
|
/// Bind using exactly the requested protocol. Used by explicit V1/V2 discovery.
|
||||||
pub async fn bind_exact(&self, device: &Device, protocol_version: u8) -> Result<BindResult> {
|
pub async fn bind_exact(&self, device: &Device, protocol_version: u8) -> Result<BindResult> {
|
||||||
let versions = Self::exact_bind_versions(protocol_version)?;
|
let versions = Self::exact_bind_versions(protocol_version)?;
|
||||||
self.bind_with_versions(device, versions).await
|
self.bind_with_versions(device, versions).await
|
||||||
|
|||||||
@@ -74,40 +74,65 @@ impl GreeClient {
|
|||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn discovery_protocol_hint(value: &Value, envelope_protocol: u8) -> u8 {
|
||||||
|
// A GCM envelope proves V2 support. A V1/plain discovery envelope does
|
||||||
|
// not prove V1 because newer modules also advertise themselves that way.
|
||||||
|
if envelope_protocol == 2 {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ver = value
|
||||||
|
.get("ver")
|
||||||
|
.and_then(Value::as_str)
|
||||||
|
.unwrap_or_default()
|
||||||
|
.trim();
|
||||||
|
let ver = ver
|
||||||
|
.strip_prefix('V')
|
||||||
|
.or_else(|| ver.strip_prefix('v'))
|
||||||
|
.unwrap_or(ver);
|
||||||
|
let major = ver
|
||||||
|
.split('.')
|
||||||
|
.next()
|
||||||
|
.and_then(|part| part.parse::<u16>().ok());
|
||||||
|
|
||||||
|
match major {
|
||||||
|
Some(1) => 1,
|
||||||
|
Some(value) if value >= 2 => 2,
|
||||||
|
_ => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_discovery(
|
fn parse_discovery(
|
||||||
&self,
|
&self,
|
||||||
mut value: Value,
|
mut value: Value,
|
||||||
source: SocketAddr,
|
source: SocketAddr,
|
||||||
protocol_filter: u8,
|
protocol_filter: u8,
|
||||||
) -> Result<Option<Device>> {
|
) -> Result<Option<Device>> {
|
||||||
let mut detected_protocol = 1_u8;
|
// Discovery transport is not the same thing as the protocol used for
|
||||||
|
// bind/status/commands. In particular, AES-GCM capable modules can
|
||||||
|
// answer the common scan packet using a legacy/plain V1-style envelope.
|
||||||
|
// Keep the envelope only as a hint and resolve the device generation
|
||||||
|
// from the inner discovery payload after it has been decoded.
|
||||||
|
let mut envelope_protocol = 0_u8;
|
||||||
if value.get("t").and_then(Value::as_str) == Some("pack") {
|
if value.get("t").and_then(Value::as_str) == Some("pack") {
|
||||||
if let Some(pack_value) = value.get("pack") {
|
if let Some(pack_value) = value.get("pack") {
|
||||||
if let Some(pack) = pack_value.as_str() {
|
if let Some(pack) = pack_value.as_str() {
|
||||||
let packet_protocol = if value.get("tag").and_then(Value::as_str).is_some() {
|
|
||||||
2
|
|
||||||
} else {
|
|
||||||
1
|
|
||||||
};
|
|
||||||
if protocol_filter != 0 && packet_protocol != protocol_filter {
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
let clear = if let Some(tag) = value.get("tag").and_then(Value::as_str) {
|
let clear = if let Some(tag) = value.get("tag").and_then(Value::as_str) {
|
||||||
detected_protocol = 2;
|
envelope_protocol = 2;
|
||||||
decrypt_v2(GENERIC_GREE_V2_KEY, pack, tag)?
|
decrypt_v2(GENERIC_GREE_V2_KEY, pack, tag)?
|
||||||
} else {
|
} else {
|
||||||
|
envelope_protocol = 1;
|
||||||
decrypt_v1(GENERIC_GREE_V1_KEY, pack)?
|
decrypt_v1(GENERIC_GREE_V1_KEY, pack)?
|
||||||
};
|
};
|
||||||
value = serde_json::from_slice::<Value>(&clear)
|
value = serde_json::from_slice::<Value>(&clear)
|
||||||
.context("invalid decrypted discovery JSON")?;
|
.context("invalid decrypted discovery JSON")?;
|
||||||
} else if pack_value.is_object() {
|
} else if pack_value.is_object() {
|
||||||
if protocol_filter == 2 {
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
value = pack_value.clone();
|
value = pack_value.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let detected_protocol = Self::discovery_protocol_hint(&value, envelope_protocol);
|
||||||
if protocol_filter != 0 && detected_protocol != protocol_filter {
|
if protocol_filter != 0 && detected_protocol != protocol_filter {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn discovery_bind_uses_detected_protocol_exactly() {
|
fn bind_version_selection_supports_exact_and_auto_fallback() {
|
||||||
assert_eq!(GreeClient::exact_bind_versions(1).unwrap(), &[1]);
|
assert_eq!(GreeClient::exact_bind_versions(1).unwrap(), &[1]);
|
||||||
assert_eq!(GreeClient::exact_bind_versions(2).unwrap(), &[2]);
|
assert_eq!(GreeClient::exact_bind_versions(2).unwrap(), &[2]);
|
||||||
assert!(GreeClient::exact_bind_versions(0).is_err());
|
assert!(GreeClient::exact_bind_versions(0).is_err());
|
||||||
@@ -130,7 +130,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn discovery_protocol_filter_rejects_other_envelope_before_decode() {
|
fn discovery_uses_inner_version_as_protocol_hint() {
|
||||||
let client = GreeClient::new(
|
let client = GreeClient::new(
|
||||||
"test-controller".into(),
|
"test-controller".into(),
|
||||||
None,
|
None,
|
||||||
@@ -138,20 +138,78 @@ mod tests {
|
|||||||
Arc::new(AtomicBool::new(false)),
|
Arc::new(AtomicBool::new(false)),
|
||||||
);
|
);
|
||||||
let source: SocketAddr = "192.0.2.20:7000".parse().unwrap();
|
let source: SocketAddr = "192.0.2.20:7000".parse().unwrap();
|
||||||
|
|
||||||
let v1 = json!({
|
let v1 = json!({
|
||||||
|
"t": "pack",
|
||||||
|
"pack": {
|
||||||
|
"t": "dev",
|
||||||
|
"mac": "502CC699C117",
|
||||||
|
"name": "Legacy",
|
||||||
|
"ver": "V1.2.1"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let v2_inner = json!({
|
||||||
|
"t": "dev",
|
||||||
|
"mac": "9424B80C5AB9",
|
||||||
|
"name": "Modern",
|
||||||
|
"ver": "V3.4"
|
||||||
|
});
|
||||||
|
let v2 = json!({
|
||||||
|
"t": "pack",
|
||||||
|
// Reproduce the mixed-generation case: the device is V2-capable,
|
||||||
|
// but its discovery payload is carried in the legacy V1 envelope.
|
||||||
|
"pack": encrypt_v1(
|
||||||
|
GENERIC_GREE_V1_KEY,
|
||||||
|
&serde_json::to_vec(&v2_inner).unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
|
let legacy = client
|
||||||
|
.parse_discovery(v1.clone(), source, 0)
|
||||||
|
.unwrap()
|
||||||
|
.expect("V1 discovery");
|
||||||
|
let modern = client
|
||||||
|
.parse_discovery(v2.clone(), source, 0)
|
||||||
|
.unwrap()
|
||||||
|
.expect("V2 discovery");
|
||||||
|
|
||||||
|
assert_eq!(legacy.protocol_version, 1);
|
||||||
|
assert_eq!(modern.protocol_version, 2);
|
||||||
|
assert!(client.parse_discovery(v1.clone(), source, 1).unwrap().is_some());
|
||||||
|
assert!(client.parse_discovery(v1, source, 2).unwrap().is_none());
|
||||||
|
assert!(client.parse_discovery(v2.clone(), source, 2).unwrap().is_some());
|
||||||
|
assert!(client.parse_discovery(v2, source, 1).unwrap().is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn discovery_does_not_treat_plain_or_v1_envelope_as_definitive_v1() {
|
||||||
|
let client = GreeClient::new(
|
||||||
|
"test-controller".into(),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Arc::new(AtomicBool::new(false)),
|
||||||
|
);
|
||||||
|
let source: SocketAddr = "192.0.2.21:7000".parse().unwrap();
|
||||||
|
let unknown = json!({
|
||||||
"t": "pack",
|
"t": "pack",
|
||||||
"pack": {
|
"pack": {
|
||||||
"t": "dev",
|
"t": "dev",
|
||||||
"mac": "AABBCCDDEEFF",
|
"mac": "AABBCCDDEEFF",
|
||||||
"name": "Test"
|
"name": "Unknown"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
assert!(client
|
let candidate = client
|
||||||
.parse_discovery(v1.clone(), source, 1)
|
.parse_discovery(unknown.clone(), source, 0)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.is_some());
|
.expect("auto discovery must retain unknown protocol");
|
||||||
assert!(client.parse_discovery(v1, source, 2).unwrap().is_none());
|
assert_eq!(candidate.protocol_version, 0);
|
||||||
|
assert!(client
|
||||||
|
.parse_discovery(unknown.clone(), source, 1)
|
||||||
|
.unwrap()
|
||||||
|
.is_none());
|
||||||
|
assert!(client.parse_discovery(unknown, source, 2).unwrap().is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1263,7 +1263,7 @@
|
|||||||
<h2 data-i18n="discovery.title">Discover GREE devices</h2><button type="button" data-close
|
<h2 data-i18n="discovery.title">Discover GREE devices</h2><button type="button" data-close
|
||||||
data-ui-icon="close"></button>
|
data-ui-icon="close"></button>
|
||||||
</div>
|
</div>
|
||||||
<p class="field-note" data-i18n="discovery.help">Auto accepts both AES-ECB and AES-GCM devices. Selecting V1 or V2 accepts and binds only that protocol. Multiple passes improve discovery when several Wi-Fi modules answer the same broadcast.</p>
|
<p class="field-note" data-i18n="discovery.help">Auto accepts both AES-ECB and AES-GCM devices, uses discovery metadata only as a protocol hint and verifies the actual protocol during binding. Selecting V1 or V2 keeps discovery and binding locked to that protocol. Multiple passes improve discovery when several Wi-Fi modules answer the same broadcast.</p>
|
||||||
<label><span data-i18n="discovery.protocol">Discovery protocol</span><select name="protocol_version">
|
<label><span data-i18n="discovery.protocol">Discovery protocol</span><select name="protocol_version">
|
||||||
<option value="0" data-i18n="devices.protocolAuto">Auto (V1 + V2)</option>
|
<option value="0" data-i18n="devices.protocolAuto">Auto (V1 + V2)</option>
|
||||||
<option value="1">V1 AES-ECB</option>
|
<option value="1">V1 AES-ECB</option>
|
||||||
@@ -1284,7 +1284,7 @@
|
|||||||
<h2 data-i18n="discovery.nameDevices">Discovered local devices</h2><button type="button" data-close
|
<h2 data-i18n="discovery.nameDevices">Discovered local devices</h2><button type="button" data-close
|
||||||
data-ui-icon="close"></button>
|
data-ui-icon="close"></button>
|
||||||
</div>
|
</div>
|
||||||
<p class="field-note" data-i18n="discovery.nameDevicesHelp">Select the units you want to add. MAC address, IP address and detected protocol are shown for every result.</p>
|
<p class="field-note" data-i18n="discovery.nameDevicesHelp">Select the units you want to add. MAC address, IP address and the discovery protocol hint are shown for every result; Auto is resolved during binding.</p>
|
||||||
<div id="discoveryNamesList" class="discovery-name-list"></div>
|
<div id="discoveryNamesList" class="discovery-name-list"></div>
|
||||||
<div class="form-actions"><button type="button" class="secondary" data-close
|
<div class="form-actions"><button type="button" class="secondary" data-close
|
||||||
data-i18n="actions.cancel">Cancel</button><button class="primary" type="submit"
|
data-i18n="actions.cancel">Cancel</button><button class="primary" type="submit"
|
||||||
|
|||||||
@@ -476,7 +476,8 @@ function showDiscoveryNames(devices) {
|
|||||||
if (!list) return;
|
if (!list) return;
|
||||||
list.innerHTML = items.length ? items.map((device, index) => {
|
list.innerHTML = items.length ? items.map((device, index) => {
|
||||||
const alreadyAdded = device.already_added === true;
|
const alreadyAdded = device.already_added === true;
|
||||||
const protocol = Number(device.protocol_version) === 2 ? 'V2 AES-GCM' : 'V1 AES-ECB';
|
const protocolVersion = Number(device.protocol_version);
|
||||||
|
const protocol = protocolVersion === 2 ? 'V2 AES-GCM' : protocolVersion === 1 ? 'V1 AES-ECB' : tr('devices.protocolAuto');
|
||||||
const selectorId = `local-discovery-${index}`;
|
const selectorId = `local-discovery-${index}`;
|
||||||
return `<div class="discovery-name-row local-discovery-row">
|
return `<div class="discovery-name-row local-discovery-row">
|
||||||
<div class="local-discovery-head">
|
<div class="local-discovery-head">
|
||||||
|
|||||||
Reference in New Issue
Block a user