v0.15.4
This commit is contained in:
Generated
+395
-295
File diff suppressed because it is too large
Load Diff
+29
-29
@@ -1,44 +1,44 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "gree-controller"
|
name = "gree-controller"
|
||||||
version = "0.15.2"
|
version = "0.15.4"
|
||||||
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"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
aes = "0.8"
|
aes = "=0.9.3"
|
||||||
aes-gcm = "0.10"
|
aes-gcm = "=0.11.1"
|
||||||
anyhow = "1"
|
anyhow = "=1.0.104"
|
||||||
axum = { version = "0.7", features = ["macros", "ws"] }
|
axum = { version = "=0.8.9", features = ["macros", "ws"] }
|
||||||
base64 = "0.22"
|
base64 = "=0.23.1"
|
||||||
chrono = { version = "0.4", features = ["serde", "clock"] }
|
chrono = { version = "=0.4.45", features = ["serde", "clock"] }
|
||||||
clap = { version = "4", features = ["derive", "env"] }
|
clap = { version = "=4.6.7", features = ["derive", "env"] }
|
||||||
dotenvy = "0.15"
|
dotenvy = "=0.15.7"
|
||||||
futures-util = "0.3"
|
futures-util = "=0.3.34"
|
||||||
libc = "0.2"
|
libc = "=0.2.189"
|
||||||
rand = "0.8"
|
rand = "=0.10.2"
|
||||||
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
|
reqwest = { version = "=0.13.5", default-features = false, features = ["json", "query", "form", "rustls-no-provider"] }
|
||||||
rusqlite = { version = "0.32", features = ["bundled"] }
|
rusqlite = { version = "=0.40.2", features = ["bundled"] }
|
||||||
webpki-roots = "1"
|
webpki-roots = "=1.0.9"
|
||||||
tokio-rustls = { version = "0.26", default-features = false, features = ["ring", "tls12", "logging"] }
|
tokio-rustls = { version = "=0.26.5", default-features = false, features = ["ring", "tls12", "logging"] }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "=1.0.229", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "=1.0.151"
|
||||||
sha2 = "0.10"
|
sha2 = "=0.11.0"
|
||||||
thiserror = "2"
|
thiserror = "=2.0.20"
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "=1.53.1", features = ["full"] }
|
||||||
tower-http = { version = "0.6", features = ["compression-gzip", "cors", "trace"] }
|
tower-http = { version = "=0.7.1", features = ["compression-gzip", "cors", "trace"] }
|
||||||
tracing = "0.1"
|
tracing = "=0.1.44"
|
||||||
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
|
tracing-subscriber = { version = "=0.3.23", features = ["env-filter", "fmt"] }
|
||||||
utoipa-swagger-ui = { version = "=8.0.3", default-features = false, features = ["axum", "debug-embed", "vendored"] }
|
utoipa-swagger-ui = { version = "=9.0.2", default-features = false, features = ["axum", "debug-embed", "vendored"] }
|
||||||
url = "2"
|
url = "=2.5.8"
|
||||||
uuid = { version = "1", features = ["v4", "serde"] }
|
uuid = { version = "=1.26.1", features = ["v4", "serde"] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
serde_json = "1"
|
serde_json = "=1.0.151"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = "3"
|
tempfile = "=3.27.0"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
strip = true
|
strip = true
|
||||||
|
|||||||
+26
-27
@@ -1,19 +1,18 @@
|
|||||||
de0793949cf01d27d903653226ecc9b5f72523d8711f20bcab022cf42c4c4ed0 ./.env.example
|
de0793949cf01d27d903653226ecc9b5f72523d8711f20bcab022cf42c4c4ed0 ./.env.example
|
||||||
a4ec3874a2e3ab1bad28fb40bb620f7b01f64d01ad9b699306bf70ada31227db ./.gitignore
|
a4ec3874a2e3ab1bad28fb40bb620f7b01f64d01ad9b699306bf70ada31227db ./.gitignore
|
||||||
82bb41f94fdf5c66ebd9e6caa92e0f1794431067298e0a27c95c8e5bfd68de89 ./Cargo.lock
|
37e255dd094e4720f96b74e501a179cf81c838ff327cbc1924b8fc4b5ea555fa ./Cargo.toml
|
||||||
39bdb16196253559e3487aa912ff770c09c7b08cdfbb21e9db1d8af1304ea7e0 ./Cargo.toml
|
|
||||||
19b2943504acb8f8de280f873a8dbec4bb6ebbe3870b158f5655d4fb8c298f5f ./LICENSE
|
19b2943504acb8f8de280f873a8dbec4bb6ebbe3870b158f5655d4fb8c298f5f ./LICENSE
|
||||||
84a0803bc75dc3199e23ef56c11c6950e8bd888c686ecda7cc369829e8e3073f ./README.md
|
c1cac4ca532e73d64e5b090ad410a2161e9790b8d77fc6732adf52c248fb3472 ./README.md
|
||||||
f21732756af313565bfe0788230e45cc11c384cee1187f006d426c5463183c0c ./SOURCE_MANIFEST.sha256
|
8dc1f42dd20c98873fcd0a979475560f9ec79e098f01375de47f8fd96ef6e80d ./SOURCE_MANIFEST.sha256
|
||||||
29e9821e5ed216ea3565dd6d8bc0b174ed3cf9fa72c4ccebbfa99e98db3ad8f9 ./build.rs
|
29e9821e5ed216ea3565dd6d8bc0b174ed3cf9fa72c4ccebbfa99e98db3ad8f9 ./build.rs
|
||||||
604a795dec077dd7e4f3462a564fdda68e8084aef07da0fcf3dfb6053a46cc58 ./docs/API.md
|
0da3db314314e19a00c08700f94495075fecd1e54a5b188f6a62cb237307e96f ./docs/API.md
|
||||||
a881ba0808dd3f189d92038f6163c39d6b6208f6dbff5c32c0ea1a2628f3fbb4 ./docs/FLOW.md
|
a881ba0808dd3f189d92038f6163c39d6b6208f6dbff5c32c0ea1a2628f3fbb4 ./docs/FLOW.md
|
||||||
8babaa6830fa70b2d3d8208ef51808e79c9d68c4e007b9ba1537fe582ba03b3d ./docs/openapi.json
|
55ffdcc5b0a43d930823cea7c94235990dbbc4a35b60832b9adca1faf606d036 ./docs/openapi.json
|
||||||
c65aa543d2e99f8f7d52736307b07ebd182597d80124661d53a16bb23f6f1118 ./ha-addon/.env.example
|
77b8becf7a2c16a384ea85721d878b76e2d520549cb4455d9aa806e57e5a2ecd ./ha-addon/.env.example
|
||||||
0993076ca45b6d31859680835204cdc111b3f9bdbf460d50b4efec56cd5e685b ./ha-addon/Dockerfile
|
0ca6e58170c2b8925194431ebbdb55f0c8b377fec5cd422cd2bd257e2d9328e3 ./ha-addon/Dockerfile
|
||||||
adf7ff248d782a3b1cba82b8789c57b6849ddaaaf5fbc108af75e18b1534a885 ./ha-addon/README.md
|
0951696a2c2e66d4d969f8e7f8641184e3012f261583b31074bc38a7a1c0cc1a ./ha-addon/README.md
|
||||||
dd9291b12afade6fc20d66e80a5513251270e18e4c265260b2bbbe393a5a94c4 ./ha-addon/build.sh
|
a4596a70e50acfe698a8ae1dcb9bebd04adba95b69781218fca7add82c17703e ./ha-addon/build.sh
|
||||||
4061846cec4d829e4101b4021df7f07dc2e0293ccfd11e91589f49733ec7c5b4 ./ha-addon/home-assistant/README.md
|
7dd2534a6f8405e640e28b7cb0e94270cc5f01fad8a972193ec254befe8a96b9 ./ha-addon/home-assistant/README.md
|
||||||
f8e8559fe10fe523ac5bc9aac25c6e26e862f679d502e8f3c39f38a0a8e40911 ./ha-addon/home-assistant/custom_components/gree_controller/__init__.py
|
f8e8559fe10fe523ac5bc9aac25c6e26e862f679d502e8f3c39f38a0a8e40911 ./ha-addon/home-assistant/custom_components/gree_controller/__init__.py
|
||||||
3f6ef15ef58456376ac53fde7cace1ef359d6a6f7a64c5b575ad77ea6e55ccc4 ./ha-addon/home-assistant/custom_components/gree_controller/api.py
|
3f6ef15ef58456376ac53fde7cace1ef359d6a6f7a64c5b575ad77ea6e55ccc4 ./ha-addon/home-assistant/custom_components/gree_controller/api.py
|
||||||
da2a0a9390ab75cef150cd281bc329fa409d0d28f51382b36bd8de3a73325c16 ./ha-addon/home-assistant/custom_components/gree_controller/climate.py
|
da2a0a9390ab75cef150cd281bc329fa409d0d28f51382b36bd8de3a73325c16 ./ha-addon/home-assistant/custom_components/gree_controller/climate.py
|
||||||
@@ -22,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
|
||||||
d467809d894b8cb9e8e04a2cc279e0cec3227c1d1c689098bdc3c0380aa9043e ./ha-addon/home-assistant/custom_components/gree_controller/manifest.json
|
d1ec103c9a167382e33877183b6df221a5cced5db58cf5d6eefd2eb24ab16077 ./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,10 +29,10 @@ 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
|
||||||
e3a227ffe23368b152d0ba4a4e81a95b70d35e9870b2a8dc7b2048d6901a7f05 ./ha-addon/repository/gree-controller/CHANGELOG.md
|
1d1508e247b67487e6aac52b532adec2842494ec2e60144491c5144967a4f8f3 ./ha-addon/repository/gree-controller/CHANGELOG.md
|
||||||
1b5599195329cc3e643c23aa1caadcec80f133e8e515eec7d92b9f3cbda5b80b ./ha-addon/repository/gree-controller/DOCS.md
|
50b8ba050c6b4919e4d057f7b38c1e23d3913b5b7c87552626452e9695d37251 ./ha-addon/repository/gree-controller/DOCS.md
|
||||||
c3db302f38d26dc9f8caf37a1a8a07a1334cc07ae301d452f2940a5ec5915719 ./ha-addon/repository/gree-controller/README.md
|
e3834bf712d4cd2acc715d8c85db96dd6e2fb3fbb758dac537f6034c337b3745 ./ha-addon/repository/gree-controller/README.md
|
||||||
21b82216d0d84cc66ecbed69457caf61174fa9304528fe051c98e8ef7c634025 ./ha-addon/repository/gree-controller/config.yaml
|
d060ee39cdea4de68bd9ededaebb7b81d974821e418b69e00c39cbdebd61f801 ./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
|
||||||
@@ -85,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
|
||||||
81f2d3f512f21d167c6d18bd2bda9d9e1557c0b234aa7826148ea557d726ddc2 ./scripts/api_dev_test.py
|
b9bd0f1db6bf879ca3778c4969dd56d3c35b7bdd137df517dbd2cd2e11856080 ./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
|
||||||
@@ -98,9 +97,9 @@ e00d211e3885e30d7fed1e43b44e6fdad40a67019060156c0641816a93e3365f ./scripts/netw
|
|||||||
81345b6a0b51736bdbc98fd23199b62e4c721b4e7437e02dab7ea79b97dff29a ./scripts/service.sh
|
81345b6a0b51736bdbc98fd23199b62e4c721b4e7437e02dab7ea79b97dff29a ./scripts/service.sh
|
||||||
bd703ef841f9763f13367aaa5764381b9c59ee87210e806c24617f3cc0739a9b ./scripts/smoke.sh
|
bd703ef841f9763f13367aaa5764381b9c59ee87210e806c24617f3cc0739a9b ./scripts/smoke.sh
|
||||||
b50782b3742dfbf8a319c60571c968e93fdf8547db747c759edcffae68cb98bf ./scripts/update.sh
|
b50782b3742dfbf8a319c60571c968e93fdf8547db747c759edcffae68cb98bf ./scripts/update.sh
|
||||||
bd7e0455c6a1501f761f0d4c00ff74833eecbd75078af9168235f90a2d9485b3 ./src/api.rs
|
f4ace9a1104ab1d0016db1d34c3ac2c4010fc1a5534af5fbf02d2042d5815d8c ./src/api.rs
|
||||||
0db0d81da4b8161004ddcbed2096812c285ecec9d944771670e6c8edf0775175 ./src/api/assets.rs
|
0db0d81da4b8161004ddcbed2096812c285ecec9d944771670e6c8edf0775175 ./src/api/assets.rs
|
||||||
b24092f34a46626d64628b510eba82193f0b203fd097f6a621b91af5d91eb571 ./src/api/auth.rs
|
1139dacbd3f6ff94bf721eb5a60d469016fb935ddcf484d71bfeb249b72c833a ./src/api/auth.rs
|
||||||
9e4fc675306e111ed3db7af9822e2925d88109c31b9e309851665a975c0bd83c ./src/api/automations.rs
|
9e4fc675306e111ed3db7af9822e2925d88109c31b9e309851665a975c0bd83c ./src/api/automations.rs
|
||||||
27a788efe385ad7180cb7fc7ec66c34ebd5e6062d9cdf35b32fb461e52a42863 ./src/api/configuration.rs
|
27a788efe385ad7180cb7fc7ec66c34ebd5e6062d9cdf35b32fb461e52a42863 ./src/api/configuration.rs
|
||||||
19bc141286a336ad67e99079496eb0ae5126f986ab28be62b5f97758e5f6969c ./src/api/debug_tokens.rs
|
19bc141286a336ad67e99079496eb0ae5126f986ab28be62b5f97758e5f6969c ./src/api/debug_tokens.rs
|
||||||
@@ -110,16 +109,16 @@ ca21f6d5a407e2e3532899d53ba4e8682c2fe961a46d8cd870ddc459721513ef ./src/api/devi
|
|||||||
2ef2f64b77886e2abd6b410adf8de91a2333d3ebdb8fcee8376ba566e5bba029 ./src/api/flows.rs
|
2ef2f64b77886e2abd6b410adf8de91a2333d3ebdb8fcee8376ba566e5bba029 ./src/api/flows.rs
|
||||||
82c02fa135132ea3ebdb4d88dd1210dc536d22f987151d7f82595ee3d3d03440 ./src/api/gree_cloud.rs
|
82c02fa135132ea3ebdb4d88dd1210dc536d22f987151d7f82595ee3d3d03440 ./src/api/gree_cloud.rs
|
||||||
b61b0b4f196c5e72e47cf06ca0c14df3cf8eedbdef0242a9d2af33623663489f ./src/api/groups.rs
|
b61b0b4f196c5e72e47cf06ca0c14df3cf8eedbdef0242a9d2af33623663489f ./src/api/groups.rs
|
||||||
3cc64b9c992805f3fbf01c0785cf29ce3121750bf30bd6420ed6e5cf2f8df422 ./src/api/history.rs
|
b6d586bc42b166ac05648f3da7d9aeb88efde2e9eaab5642685eb4d9cf15f95a ./src/api/history.rs
|
||||||
e8edfbb725d6de650442444b0a929ad2be0bd2c2d7d227d2b3fdd99d05c94f94 ./src/api/house.rs
|
e8edfbb725d6de650442444b0a929ad2be0bd2c2d7d227d2b3fdd99d05c94f94 ./src/api/house.rs
|
||||||
8495967c3df72110f591c744975984c78cafc8181b2d430e7fd5b9baf57eba95 ./src/api/integrations.rs
|
8495967c3df72110f591c744975984c78cafc8181b2d430e7fd5b9baf57eba95 ./src/api/integrations.rs
|
||||||
7658111f7d125db55a6e23f88157339b110b2cd1ed13ceabd8f860b42dba5101 ./src/api/middleware.rs
|
7658111f7d125db55a6e23f88157339b110b2cd1ed13ceabd8f860b42dba5101 ./src/api/middleware.rs
|
||||||
45e34a447ff384d99a3c42c489ca9fa75849c74d4d246caa91c63d927de17396 ./src/api/openapi.rs
|
c01b8b942e64a46dac19ce08346aa844df7e9ac7147c0ad6d0f2cfd90e071ec0 ./src/api/openapi.rs
|
||||||
b777e7fbeccef699e11ffd16bb18633843c99afecacce2221280e54b09f6d2da ./src/api/public_settings.rs
|
b777e7fbeccef699e11ffd16bb18633843c99afecacce2221280e54b09f6d2da ./src/api/public_settings.rs
|
||||||
5b29f2e5aa2c422c5829ef89c7b59cf753883aa7f60661c95ab0f95cf676fa3f ./src/api/schedules.rs
|
5b29f2e5aa2c422c5829ef89c7b59cf753883aa7f60661c95ab0f95cf676fa3f ./src/api/schedules.rs
|
||||||
fd08162d0f9287700196028ad0ca2aec7c242238056b0a228ca5bdcb319ece4e ./src/api/settings.rs
|
fd08162d0f9287700196028ad0ca2aec7c242238056b0a228ca5bdcb319ece4e ./src/api/settings.rs
|
||||||
bb57f4b28df75ba350c9706719650fff3a689afee0cb6979c1fcae79396ac0cf ./src/api/system.rs
|
bb57f4b28df75ba350c9706719650fff3a689afee0cb6979c1fcae79396ac0cf ./src/api/system.rs
|
||||||
94d3845def693aafe15fa6e8b390881c46c3c236b62f247ddfdc055d9226ed22 ./src/api/websocket.rs
|
3b0124a76dbc654584bcf186d43f89d20b6e7fd980ce0ffbf5a9e8eced5ec7f6 ./src/api/websocket.rs
|
||||||
ddd1bfc8625b66f6e5f3d24b3122ac86c25f89b0af527e3dfce9102551a8f142 ./src/api/zones.rs
|
ddd1bfc8625b66f6e5f3d24b3122ac86c25f89b0af527e3dfce9102551a8f142 ./src/api/zones.rs
|
||||||
0b7d2ace2e8cb1dd0cb59aa6ca3e80cec14078e93530fd7b58081798585cd833 ./src/config.rs
|
0b7d2ace2e8cb1dd0cb59aa6ca3e80cec14078e93530fd7b58081798585cd833 ./src/config.rs
|
||||||
de0ce7807aebe4c0e325fbef01855e7fc1cfd117529f53f04a416fda3997673a ./src/db.rs
|
de0ce7807aebe4c0e325fbef01855e7fc1cfd117529f53f04a416fda3997673a ./src/db.rs
|
||||||
@@ -156,12 +155,12 @@ af4edaf12faf294f44a8992d120a99b09edd1cbdd66981390e027d13fd6b6790 ./src/engine/t
|
|||||||
c89ff36c6a67bf4fbf68c43e18aa0a556de2dc69263fd79db376363afc741a4f ./src/engine/zone_actions.rs
|
c89ff36c6a67bf4fbf68c43e18aa0a556de2dc69263fd79db376363afc741a4f ./src/engine/zone_actions.rs
|
||||||
fb169bcc20f95abe9892367df6dd3a683584bdbc721792d6ffb9311b81ca30d9 ./src/engine/zone_control.rs
|
fb169bcc20f95abe9892367df6dd3a683584bdbc721792d6ffb9311b81ca30d9 ./src/engine/zone_control.rs
|
||||||
bfac95cec87f0df6ce562153cd3cfe6731359d703e6c592d2c2f7ba01ea62d99 ./src/error.rs
|
bfac95cec87f0df6ce562153cd3cfe6731359d703e6c592d2c2f7ba01ea62d99 ./src/error.rs
|
||||||
c55d32f288fe95869fc288d47817b8e289fbe284be4219e81b1e7493ff5e3a57 ./src/home_assistant.rs
|
a9768150162a010579d40060417e276703e8756c139fcf57dddab9fffc98d840 ./src/home_assistant.rs
|
||||||
bcd14e4d1af3ca580f3b95bcd86164c40f762511e1b8e2501cb8a598a6d8adf4 ./src/influxdb.rs
|
bcd14e4d1af3ca580f3b95bcd86164c40f762511e1b8e2501cb8a598a6d8adf4 ./src/influxdb.rs
|
||||||
da4068295f37c23222bb13bebac022d88ba7729604a49ad25438c55e45458a49 ./src/influxdb/codec.rs
|
da4068295f37c23222bb13bebac022d88ba7729604a49ad25438c55e45458a49 ./src/influxdb/codec.rs
|
||||||
2d36405912646b30b1a1a37a7a4e18c2104ab22e865b593316a609dda884aec2 ./src/influxdb/query.rs
|
2d36405912646b30b1a1a37a7a4e18c2104ab22e865b593316a609dda884aec2 ./src/influxdb/query.rs
|
||||||
67e42a92295480d2f1d364958f184654cfb5d4b77e7e1df47f588bdec18868a0 ./src/influxdb/write.rs
|
67e42a92295480d2f1d364958f184654cfb5d4b77e7e1df47f588bdec18868a0 ./src/influxdb/write.rs
|
||||||
1982ce54737a8780d1404b105d53db59cd5bee3d1c426f9a881d26cef7059bf5 ./src/main.rs
|
62f9da6ef4f5fd92701d0857773f9f6236ef25356f21b9b42236abab6ba7da53 ./src/main.rs
|
||||||
23688a5cb68efded89471ce959328d27adff370d451bd9f378a283ab51437e76 ./src/models.rs
|
23688a5cb68efded89471ce959328d27adff370d451bd9f378a283ab51437e76 ./src/models.rs
|
||||||
920e028d96a14cca9f74a964bb296e68a109cfead314d3164c180201e606d151 ./src/models/automation.rs
|
920e028d96a14cca9f74a964bb296e68a109cfead314d3164c180201e606d151 ./src/models/automation.rs
|
||||||
fc5f2802a073a175a8985e56bcb87eb1ff481226d5b4eeabad73dbba1839fc45 ./src/models/control_plan.rs
|
fc5f2802a073a175a8985e56bcb87eb1ff481226d5b4eeabad73dbba1839fc45 ./src/models/control_plan.rs
|
||||||
@@ -175,7 +174,7 @@ f1359b68f1d041cd441f80429e77893eeb6f6194613b58fd3e7a212fb511db3e ./src/models/r
|
|||||||
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
|
||||||
cca742bb2b500eb9269f69385fcf88053cd08aabf6a98b7669b8a7a2fd67df13 ./src/protocol/crypto.rs
|
7746bca683809b82529ed152272ae5c0cd3971758a02e076def58f770e7adf10 ./src/protocol/crypto.rs
|
||||||
daca14e9a4dd65394add7c7753c8ae5e7e43e991323a5ca23d8788aae4428925 ./src/protocol/gree.rs
|
daca14e9a4dd65394add7c7753c8ae5e7e43e991323a5ca23d8788aae4428925 ./src/protocol/gree.rs
|
||||||
7907c33e6396c7e0d61705b735b21c84d6ed784012fb61022b872c6745540f1d ./src/protocol/gree/binding.rs
|
7907c33e6396c7e0d61705b735b21c84d6ed784012fb61022b872c6745540f1d ./src/protocol/gree/binding.rs
|
||||||
91d82c3ecae21615e4edad31b7ea95dca9b578650348666a2b61475b5a644669 ./src/protocol/gree/commands.rs
|
91d82c3ecae21615e4edad31b7ea95dca9b578650348666a2b61475b5a644669 ./src/protocol/gree/commands.rs
|
||||||
@@ -186,10 +185,10 @@ ff33db623f8f1bf30015b4a00e1f247a99de713da3d297c672e42c0795ec845c ./src/protocol
|
|||||||
1076cb80950be00ca19f9e2370c73040902d1483b0e80c0ca349c7830d38c9f7 ./src/protocol/gree/polling.rs
|
1076cb80950be00ca19f9e2370c73040902d1483b0e80c0ca349c7830d38c9f7 ./src/protocol/gree/polling.rs
|
||||||
e0555fac67d1dd0129ecfea6d1fd2fbeb1a73ac89ad95d1b74a7094e50e29ae4 ./src/protocol/gree/tests.rs
|
e0555fac67d1dd0129ecfea6d1fd2fbeb1a73ac89ad95d1b74a7094e50e29ae4 ./src/protocol/gree/tests.rs
|
||||||
3c93e5b254a2a40a07854532cb5fc07e493ad65d9ba2cf28093cff4a4a4e451c ./src/protocol/gree/transport.rs
|
3c93e5b254a2a40a07854532cb5fc07e493ad65d9ba2cf28093cff4a4a4e451c ./src/protocol/gree/transport.rs
|
||||||
297983059c915057869fbb4f6bcfe752f3d5bd1e93c3a2651a1bf883c739ed29 ./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
|
||||||
6258ee3888a5f9a4f8bb6cfbbac97f2621de07f9da6bcb2fa596d452f47f2e49 ./src/protocol/mod.rs
|
6258ee3888a5f9a4f8bb6cfbbac97f2621de07f9da6bcb2fa596d452f47f2e49 ./src/protocol/mod.rs
|
||||||
2a08099b456847f24a828d711c4a0aba3fc372936d9a53f0be931f6706226cc5 ./src/provider.rs
|
a677ce61d3d0f4cf358055ddbc343e73b452c68daed80798499147370819615e ./src/provider.rs
|
||||||
830621fa75265da7288b8135704c0ce27e0687f87d55abf3cdbe40a6e2f3d2b1 ./src/queries.rs
|
830621fa75265da7288b8135704c0ce27e0687f87d55abf3cdbe40a6e2f3d2b1 ./src/queries.rs
|
||||||
7fac65a9dcbcecee09816f5447c7792dc94f736b1efb66ac85629db75f6280be ./src/queries/device_history.rs
|
7fac65a9dcbcecee09816f5447c7792dc94f736b1efb66ac85629db75f6280be ./src/queries/device_history.rs
|
||||||
580917b91441fe9b3276cf0cfc31536ba7954b6a86f4080347b93f9367a5b1ac ./src/queries/entities.rs
|
580917b91441fe9b3276cf0cfc31536ba7954b6a86f4080347b93f9367a5b1ac ./src/queries/entities.rs
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
|
|
||||||
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.2**
|
**Version: 0.15.4**
|
||||||
|
|
||||||
Version 0.15.2 adds granular single-function unit actions to Visual Flow and exposes fan/Quiet/Turbo/Panel Light/Air/X-Fan/Health/Sleep controls in legacy automations, so automations can change one unit feature without touching unrelated settings.
|
Version 0.15.4 refreshes the Rust dependency stack, including Axum 0.8, Reqwest 0.13, Rusqlite 0.40, Rand 0.10, RustCrypto AES/AES-GCM and utoipa-swagger-ui 9, with the required compatibility migrations.
|
||||||
|
|
||||||
> [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`.
|
||||||
|
|
||||||
## What it does
|
## What it does
|
||||||
|
|
||||||
|
|||||||
+25
-26
@@ -1,18 +1,17 @@
|
|||||||
de0793949cf01d27d903653226ecc9b5f72523d8711f20bcab022cf42c4c4ed0 ./.env.example
|
de0793949cf01d27d903653226ecc9b5f72523d8711f20bcab022cf42c4c4ed0 ./.env.example
|
||||||
a4ec3874a2e3ab1bad28fb40bb620f7b01f64d01ad9b699306bf70ada31227db ./.gitignore
|
a4ec3874a2e3ab1bad28fb40bb620f7b01f64d01ad9b699306bf70ada31227db ./.gitignore
|
||||||
82bb41f94fdf5c66ebd9e6caa92e0f1794431067298e0a27c95c8e5bfd68de89 ./Cargo.lock
|
37e255dd094e4720f96b74e501a179cf81c838ff327cbc1924b8fc4b5ea555fa ./Cargo.toml
|
||||||
39bdb16196253559e3487aa912ff770c09c7b08cdfbb21e9db1d8af1304ea7e0 ./Cargo.toml
|
|
||||||
19b2943504acb8f8de280f873a8dbec4bb6ebbe3870b158f5655d4fb8c298f5f ./LICENSE
|
19b2943504acb8f8de280f873a8dbec4bb6ebbe3870b158f5655d4fb8c298f5f ./LICENSE
|
||||||
84a0803bc75dc3199e23ef56c11c6950e8bd888c686ecda7cc369829e8e3073f ./README.md
|
c1cac4ca532e73d64e5b090ad410a2161e9790b8d77fc6732adf52c248fb3472 ./README.md
|
||||||
29e9821e5ed216ea3565dd6d8bc0b174ed3cf9fa72c4ccebbfa99e98db3ad8f9 ./build.rs
|
29e9821e5ed216ea3565dd6d8bc0b174ed3cf9fa72c4ccebbfa99e98db3ad8f9 ./build.rs
|
||||||
604a795dec077dd7e4f3462a564fdda68e8084aef07da0fcf3dfb6053a46cc58 ./docs/API.md
|
0da3db314314e19a00c08700f94495075fecd1e54a5b188f6a62cb237307e96f ./docs/API.md
|
||||||
a881ba0808dd3f189d92038f6163c39d6b6208f6dbff5c32c0ea1a2628f3fbb4 ./docs/FLOW.md
|
a881ba0808dd3f189d92038f6163c39d6b6208f6dbff5c32c0ea1a2628f3fbb4 ./docs/FLOW.md
|
||||||
8babaa6830fa70b2d3d8208ef51808e79c9d68c4e007b9ba1537fe582ba03b3d ./docs/openapi.json
|
55ffdcc5b0a43d930823cea7c94235990dbbc4a35b60832b9adca1faf606d036 ./docs/openapi.json
|
||||||
c65aa543d2e99f8f7d52736307b07ebd182597d80124661d53a16bb23f6f1118 ./ha-addon/.env.example
|
77b8becf7a2c16a384ea85721d878b76e2d520549cb4455d9aa806e57e5a2ecd ./ha-addon/.env.example
|
||||||
0993076ca45b6d31859680835204cdc111b3f9bdbf460d50b4efec56cd5e685b ./ha-addon/Dockerfile
|
0ca6e58170c2b8925194431ebbdb55f0c8b377fec5cd422cd2bd257e2d9328e3 ./ha-addon/Dockerfile
|
||||||
adf7ff248d782a3b1cba82b8789c57b6849ddaaaf5fbc108af75e18b1534a885 ./ha-addon/README.md
|
0951696a2c2e66d4d969f8e7f8641184e3012f261583b31074bc38a7a1c0cc1a ./ha-addon/README.md
|
||||||
dd9291b12afade6fc20d66e80a5513251270e18e4c265260b2bbbe393a5a94c4 ./ha-addon/build.sh
|
a4596a70e50acfe698a8ae1dcb9bebd04adba95b69781218fca7add82c17703e ./ha-addon/build.sh
|
||||||
4061846cec4d829e4101b4021df7f07dc2e0293ccfd11e91589f49733ec7c5b4 ./ha-addon/home-assistant/README.md
|
7dd2534a6f8405e640e28b7cb0e94270cc5f01fad8a972193ec254befe8a96b9 ./ha-addon/home-assistant/README.md
|
||||||
f8e8559fe10fe523ac5bc9aac25c6e26e862f679d502e8f3c39f38a0a8e40911 ./ha-addon/home-assistant/custom_components/gree_controller/__init__.py
|
f8e8559fe10fe523ac5bc9aac25c6e26e862f679d502e8f3c39f38a0a8e40911 ./ha-addon/home-assistant/custom_components/gree_controller/__init__.py
|
||||||
3f6ef15ef58456376ac53fde7cace1ef359d6a6f7a64c5b575ad77ea6e55ccc4 ./ha-addon/home-assistant/custom_components/gree_controller/api.py
|
3f6ef15ef58456376ac53fde7cace1ef359d6a6f7a64c5b575ad77ea6e55ccc4 ./ha-addon/home-assistant/custom_components/gree_controller/api.py
|
||||||
da2a0a9390ab75cef150cd281bc329fa409d0d28f51382b36bd8de3a73325c16 ./ha-addon/home-assistant/custom_components/gree_controller/climate.py
|
da2a0a9390ab75cef150cd281bc329fa409d0d28f51382b36bd8de3a73325c16 ./ha-addon/home-assistant/custom_components/gree_controller/climate.py
|
||||||
@@ -21,7 +20,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
|
||||||
d467809d894b8cb9e8e04a2cc279e0cec3227c1d1c689098bdc3c0380aa9043e ./ha-addon/home-assistant/custom_components/gree_controller/manifest.json
|
d1ec103c9a167382e33877183b6df221a5cced5db58cf5d6eefd2eb24ab16077 ./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,10 +28,10 @@ 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
|
||||||
e3a227ffe23368b152d0ba4a4e81a95b70d35e9870b2a8dc7b2048d6901a7f05 ./ha-addon/repository/gree-controller/CHANGELOG.md
|
1d1508e247b67487e6aac52b532adec2842494ec2e60144491c5144967a4f8f3 ./ha-addon/repository/gree-controller/CHANGELOG.md
|
||||||
1b5599195329cc3e643c23aa1caadcec80f133e8e515eec7d92b9f3cbda5b80b ./ha-addon/repository/gree-controller/DOCS.md
|
50b8ba050c6b4919e4d057f7b38c1e23d3913b5b7c87552626452e9695d37251 ./ha-addon/repository/gree-controller/DOCS.md
|
||||||
c3db302f38d26dc9f8caf37a1a8a07a1334cc07ae301d452f2940a5ec5915719 ./ha-addon/repository/gree-controller/README.md
|
e3834bf712d4cd2acc715d8c85db96dd6e2fb3fbb758dac537f6034c337b3745 ./ha-addon/repository/gree-controller/README.md
|
||||||
21b82216d0d84cc66ecbed69457caf61174fa9304528fe051c98e8ef7c634025 ./ha-addon/repository/gree-controller/config.yaml
|
d060ee39cdea4de68bd9ededaebb7b81d974821e418b69e00c39cbdebd61f801 ./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
|
||||||
@@ -84,7 +83,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
|
||||||
81f2d3f512f21d167c6d18bd2bda9d9e1557c0b234aa7826148ea557d726ddc2 ./scripts/api_dev_test.py
|
b9bd0f1db6bf879ca3778c4969dd56d3c35b7bdd137df517dbd2cd2e11856080 ./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
|
||||||
@@ -97,9 +96,9 @@ e00d211e3885e30d7fed1e43b44e6fdad40a67019060156c0641816a93e3365f ./scripts/netw
|
|||||||
81345b6a0b51736bdbc98fd23199b62e4c721b4e7437e02dab7ea79b97dff29a ./scripts/service.sh
|
81345b6a0b51736bdbc98fd23199b62e4c721b4e7437e02dab7ea79b97dff29a ./scripts/service.sh
|
||||||
bd703ef841f9763f13367aaa5764381b9c59ee87210e806c24617f3cc0739a9b ./scripts/smoke.sh
|
bd703ef841f9763f13367aaa5764381b9c59ee87210e806c24617f3cc0739a9b ./scripts/smoke.sh
|
||||||
b50782b3742dfbf8a319c60571c968e93fdf8547db747c759edcffae68cb98bf ./scripts/update.sh
|
b50782b3742dfbf8a319c60571c968e93fdf8547db747c759edcffae68cb98bf ./scripts/update.sh
|
||||||
bd7e0455c6a1501f761f0d4c00ff74833eecbd75078af9168235f90a2d9485b3 ./src/api.rs
|
f4ace9a1104ab1d0016db1d34c3ac2c4010fc1a5534af5fbf02d2042d5815d8c ./src/api.rs
|
||||||
0db0d81da4b8161004ddcbed2096812c285ecec9d944771670e6c8edf0775175 ./src/api/assets.rs
|
0db0d81da4b8161004ddcbed2096812c285ecec9d944771670e6c8edf0775175 ./src/api/assets.rs
|
||||||
b24092f34a46626d64628b510eba82193f0b203fd097f6a621b91af5d91eb571 ./src/api/auth.rs
|
1139dacbd3f6ff94bf721eb5a60d469016fb935ddcf484d71bfeb249b72c833a ./src/api/auth.rs
|
||||||
9e4fc675306e111ed3db7af9822e2925d88109c31b9e309851665a975c0bd83c ./src/api/automations.rs
|
9e4fc675306e111ed3db7af9822e2925d88109c31b9e309851665a975c0bd83c ./src/api/automations.rs
|
||||||
27a788efe385ad7180cb7fc7ec66c34ebd5e6062d9cdf35b32fb461e52a42863 ./src/api/configuration.rs
|
27a788efe385ad7180cb7fc7ec66c34ebd5e6062d9cdf35b32fb461e52a42863 ./src/api/configuration.rs
|
||||||
19bc141286a336ad67e99079496eb0ae5126f986ab28be62b5f97758e5f6969c ./src/api/debug_tokens.rs
|
19bc141286a336ad67e99079496eb0ae5126f986ab28be62b5f97758e5f6969c ./src/api/debug_tokens.rs
|
||||||
@@ -109,16 +108,16 @@ ca21f6d5a407e2e3532899d53ba4e8682c2fe961a46d8cd870ddc459721513ef ./src/api/devi
|
|||||||
2ef2f64b77886e2abd6b410adf8de91a2333d3ebdb8fcee8376ba566e5bba029 ./src/api/flows.rs
|
2ef2f64b77886e2abd6b410adf8de91a2333d3ebdb8fcee8376ba566e5bba029 ./src/api/flows.rs
|
||||||
82c02fa135132ea3ebdb4d88dd1210dc536d22f987151d7f82595ee3d3d03440 ./src/api/gree_cloud.rs
|
82c02fa135132ea3ebdb4d88dd1210dc536d22f987151d7f82595ee3d3d03440 ./src/api/gree_cloud.rs
|
||||||
b61b0b4f196c5e72e47cf06ca0c14df3cf8eedbdef0242a9d2af33623663489f ./src/api/groups.rs
|
b61b0b4f196c5e72e47cf06ca0c14df3cf8eedbdef0242a9d2af33623663489f ./src/api/groups.rs
|
||||||
3cc64b9c992805f3fbf01c0785cf29ce3121750bf30bd6420ed6e5cf2f8df422 ./src/api/history.rs
|
b6d586bc42b166ac05648f3da7d9aeb88efde2e9eaab5642685eb4d9cf15f95a ./src/api/history.rs
|
||||||
e8edfbb725d6de650442444b0a929ad2be0bd2c2d7d227d2b3fdd99d05c94f94 ./src/api/house.rs
|
e8edfbb725d6de650442444b0a929ad2be0bd2c2d7d227d2b3fdd99d05c94f94 ./src/api/house.rs
|
||||||
8495967c3df72110f591c744975984c78cafc8181b2d430e7fd5b9baf57eba95 ./src/api/integrations.rs
|
8495967c3df72110f591c744975984c78cafc8181b2d430e7fd5b9baf57eba95 ./src/api/integrations.rs
|
||||||
7658111f7d125db55a6e23f88157339b110b2cd1ed13ceabd8f860b42dba5101 ./src/api/middleware.rs
|
7658111f7d125db55a6e23f88157339b110b2cd1ed13ceabd8f860b42dba5101 ./src/api/middleware.rs
|
||||||
45e34a447ff384d99a3c42c489ca9fa75849c74d4d246caa91c63d927de17396 ./src/api/openapi.rs
|
c01b8b942e64a46dac19ce08346aa844df7e9ac7147c0ad6d0f2cfd90e071ec0 ./src/api/openapi.rs
|
||||||
b777e7fbeccef699e11ffd16bb18633843c99afecacce2221280e54b09f6d2da ./src/api/public_settings.rs
|
b777e7fbeccef699e11ffd16bb18633843c99afecacce2221280e54b09f6d2da ./src/api/public_settings.rs
|
||||||
5b29f2e5aa2c422c5829ef89c7b59cf753883aa7f60661c95ab0f95cf676fa3f ./src/api/schedules.rs
|
5b29f2e5aa2c422c5829ef89c7b59cf753883aa7f60661c95ab0f95cf676fa3f ./src/api/schedules.rs
|
||||||
fd08162d0f9287700196028ad0ca2aec7c242238056b0a228ca5bdcb319ece4e ./src/api/settings.rs
|
fd08162d0f9287700196028ad0ca2aec7c242238056b0a228ca5bdcb319ece4e ./src/api/settings.rs
|
||||||
bb57f4b28df75ba350c9706719650fff3a689afee0cb6979c1fcae79396ac0cf ./src/api/system.rs
|
bb57f4b28df75ba350c9706719650fff3a689afee0cb6979c1fcae79396ac0cf ./src/api/system.rs
|
||||||
94d3845def693aafe15fa6e8b390881c46c3c236b62f247ddfdc055d9226ed22 ./src/api/websocket.rs
|
3b0124a76dbc654584bcf186d43f89d20b6e7fd980ce0ffbf5a9e8eced5ec7f6 ./src/api/websocket.rs
|
||||||
ddd1bfc8625b66f6e5f3d24b3122ac86c25f89b0af527e3dfce9102551a8f142 ./src/api/zones.rs
|
ddd1bfc8625b66f6e5f3d24b3122ac86c25f89b0af527e3dfce9102551a8f142 ./src/api/zones.rs
|
||||||
0b7d2ace2e8cb1dd0cb59aa6ca3e80cec14078e93530fd7b58081798585cd833 ./src/config.rs
|
0b7d2ace2e8cb1dd0cb59aa6ca3e80cec14078e93530fd7b58081798585cd833 ./src/config.rs
|
||||||
de0ce7807aebe4c0e325fbef01855e7fc1cfd117529f53f04a416fda3997673a ./src/db.rs
|
de0ce7807aebe4c0e325fbef01855e7fc1cfd117529f53f04a416fda3997673a ./src/db.rs
|
||||||
@@ -155,12 +154,12 @@ af4edaf12faf294f44a8992d120a99b09edd1cbdd66981390e027d13fd6b6790 ./src/engine/t
|
|||||||
c89ff36c6a67bf4fbf68c43e18aa0a556de2dc69263fd79db376363afc741a4f ./src/engine/zone_actions.rs
|
c89ff36c6a67bf4fbf68c43e18aa0a556de2dc69263fd79db376363afc741a4f ./src/engine/zone_actions.rs
|
||||||
fb169bcc20f95abe9892367df6dd3a683584bdbc721792d6ffb9311b81ca30d9 ./src/engine/zone_control.rs
|
fb169bcc20f95abe9892367df6dd3a683584bdbc721792d6ffb9311b81ca30d9 ./src/engine/zone_control.rs
|
||||||
bfac95cec87f0df6ce562153cd3cfe6731359d703e6c592d2c2f7ba01ea62d99 ./src/error.rs
|
bfac95cec87f0df6ce562153cd3cfe6731359d703e6c592d2c2f7ba01ea62d99 ./src/error.rs
|
||||||
c55d32f288fe95869fc288d47817b8e289fbe284be4219e81b1e7493ff5e3a57 ./src/home_assistant.rs
|
a9768150162a010579d40060417e276703e8756c139fcf57dddab9fffc98d840 ./src/home_assistant.rs
|
||||||
bcd14e4d1af3ca580f3b95bcd86164c40f762511e1b8e2501cb8a598a6d8adf4 ./src/influxdb.rs
|
bcd14e4d1af3ca580f3b95bcd86164c40f762511e1b8e2501cb8a598a6d8adf4 ./src/influxdb.rs
|
||||||
da4068295f37c23222bb13bebac022d88ba7729604a49ad25438c55e45458a49 ./src/influxdb/codec.rs
|
da4068295f37c23222bb13bebac022d88ba7729604a49ad25438c55e45458a49 ./src/influxdb/codec.rs
|
||||||
2d36405912646b30b1a1a37a7a4e18c2104ab22e865b593316a609dda884aec2 ./src/influxdb/query.rs
|
2d36405912646b30b1a1a37a7a4e18c2104ab22e865b593316a609dda884aec2 ./src/influxdb/query.rs
|
||||||
67e42a92295480d2f1d364958f184654cfb5d4b77e7e1df47f588bdec18868a0 ./src/influxdb/write.rs
|
67e42a92295480d2f1d364958f184654cfb5d4b77e7e1df47f588bdec18868a0 ./src/influxdb/write.rs
|
||||||
1982ce54737a8780d1404b105d53db59cd5bee3d1c426f9a881d26cef7059bf5 ./src/main.rs
|
62f9da6ef4f5fd92701d0857773f9f6236ef25356f21b9b42236abab6ba7da53 ./src/main.rs
|
||||||
23688a5cb68efded89471ce959328d27adff370d451bd9f378a283ab51437e76 ./src/models.rs
|
23688a5cb68efded89471ce959328d27adff370d451bd9f378a283ab51437e76 ./src/models.rs
|
||||||
920e028d96a14cca9f74a964bb296e68a109cfead314d3164c180201e606d151 ./src/models/automation.rs
|
920e028d96a14cca9f74a964bb296e68a109cfead314d3164c180201e606d151 ./src/models/automation.rs
|
||||||
fc5f2802a073a175a8985e56bcb87eb1ff481226d5b4eeabad73dbba1839fc45 ./src/models/control_plan.rs
|
fc5f2802a073a175a8985e56bcb87eb1ff481226d5b4eeabad73dbba1839fc45 ./src/models/control_plan.rs
|
||||||
@@ -174,7 +173,7 @@ f1359b68f1d041cd441f80429e77893eeb6f6194613b58fd3e7a212fb511db3e ./src/models/r
|
|||||||
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
|
||||||
cca742bb2b500eb9269f69385fcf88053cd08aabf6a98b7669b8a7a2fd67df13 ./src/protocol/crypto.rs
|
7746bca683809b82529ed152272ae5c0cd3971758a02e076def58f770e7adf10 ./src/protocol/crypto.rs
|
||||||
daca14e9a4dd65394add7c7753c8ae5e7e43e991323a5ca23d8788aae4428925 ./src/protocol/gree.rs
|
daca14e9a4dd65394add7c7753c8ae5e7e43e991323a5ca23d8788aae4428925 ./src/protocol/gree.rs
|
||||||
7907c33e6396c7e0d61705b735b21c84d6ed784012fb61022b872c6745540f1d ./src/protocol/gree/binding.rs
|
7907c33e6396c7e0d61705b735b21c84d6ed784012fb61022b872c6745540f1d ./src/protocol/gree/binding.rs
|
||||||
91d82c3ecae21615e4edad31b7ea95dca9b578650348666a2b61475b5a644669 ./src/protocol/gree/commands.rs
|
91d82c3ecae21615e4edad31b7ea95dca9b578650348666a2b61475b5a644669 ./src/protocol/gree/commands.rs
|
||||||
@@ -185,10 +184,10 @@ ff33db623f8f1bf30015b4a00e1f247a99de713da3d297c672e42c0795ec845c ./src/protocol
|
|||||||
1076cb80950be00ca19f9e2370c73040902d1483b0e80c0ca349c7830d38c9f7 ./src/protocol/gree/polling.rs
|
1076cb80950be00ca19f9e2370c73040902d1483b0e80c0ca349c7830d38c9f7 ./src/protocol/gree/polling.rs
|
||||||
e0555fac67d1dd0129ecfea6d1fd2fbeb1a73ac89ad95d1b74a7094e50e29ae4 ./src/protocol/gree/tests.rs
|
e0555fac67d1dd0129ecfea6d1fd2fbeb1a73ac89ad95d1b74a7094e50e29ae4 ./src/protocol/gree/tests.rs
|
||||||
3c93e5b254a2a40a07854532cb5fc07e493ad65d9ba2cf28093cff4a4a4e451c ./src/protocol/gree/transport.rs
|
3c93e5b254a2a40a07854532cb5fc07e493ad65d9ba2cf28093cff4a4a4e451c ./src/protocol/gree/transport.rs
|
||||||
297983059c915057869fbb4f6bcfe752f3d5bd1e93c3a2651a1bf883c739ed29 ./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
|
||||||
6258ee3888a5f9a4f8bb6cfbbac97f2621de07f9da6bcb2fa596d452f47f2e49 ./src/protocol/mod.rs
|
6258ee3888a5f9a4f8bb6cfbbac97f2621de07f9da6bcb2fa596d452f47f2e49 ./src/protocol/mod.rs
|
||||||
2a08099b456847f24a828d711c4a0aba3fc372936d9a53f0be931f6706226cc5 ./src/provider.rs
|
a677ce61d3d0f4cf358055ddbc343e73b452c68daed80798499147370819615e ./src/provider.rs
|
||||||
830621fa75265da7288b8135704c0ce27e0687f87d55abf3cdbe40a6e2f3d2b1 ./src/queries.rs
|
830621fa75265da7288b8135704c0ce27e0687f87d55abf3cdbe40a6e2f3d2b1 ./src/queries.rs
|
||||||
7fac65a9dcbcecee09816f5447c7792dc94f736b1efb66ac85629db75f6280be ./src/queries/device_history.rs
|
7fac65a9dcbcecee09816f5447c7792dc94f736b1efb66ac85629db75f6280be ./src/queries/device_history.rs
|
||||||
580917b91441fe9b3276cf0cfc31536ba7954b6a86f4080347b93f9367a5b1ac ./src/queries/entities.rs
|
580917b91441fe9b3276cf0cfc31536ba7954b6a86f4080347b93f9367a5b1ac ./src/queries/entities.rs
|
||||||
|
|||||||
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
# GREE Controller API reference
|
# GREE Controller API reference
|
||||||
|
|
||||||
HTTP and WebSocket API for GREE Controller **0.15.2**.
|
HTTP and WebSocket API for GREE Controller **0.15.4**.
|
||||||
|
|
||||||
[← Main documentation](../README.md)
|
[← Main documentation](../README.md)
|
||||||
|
|
||||||
@@ -240,7 +240,7 @@ Response:
|
|||||||
{
|
{
|
||||||
"status": "ok",
|
"status": "ok",
|
||||||
"name": "gree-controller",
|
"name": "gree-controller",
|
||||||
"version": "0.15.2",
|
"version": "0.15.4",
|
||||||
"uptime_seconds": 1234,
|
"uptime_seconds": 1234,
|
||||||
"control_ready": true,
|
"control_ready": true,
|
||||||
"time": "2026-08-30T06:54:00Z"
|
"time": "2026-08-30T06:54:00Z"
|
||||||
@@ -303,7 +303,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.2",
|
"version": "0.15.4",
|
||||||
"uptime_seconds": 1234,
|
"uptime_seconds": 1234,
|
||||||
"auth_required": false,
|
"auth_required": false,
|
||||||
"control_ready": true,
|
"control_ready": true,
|
||||||
|
|||||||
+4
-4
File diff suppressed because one or more lines are too long
@@ -2,7 +2,7 @@
|
|||||||
REGISTRY=repo.example.com
|
REGISTRY=repo.example.com
|
||||||
IMAGE_NAME=gree-controller
|
IMAGE_NAME=gree-controller
|
||||||
DISTRO=alpine
|
DISTRO=alpine
|
||||||
RUST_VERSION=1.89
|
RUST_VERSION=1.98.1
|
||||||
BUILD_PLATFORMS=linux/amd64,linux/arm64
|
BUILD_PLATFORMS=linux/amd64,linux/arm64
|
||||||
BUILDER=gree-controller-multiarch
|
BUILDER=gree-controller-multiarch
|
||||||
BUILDER_CONFIG=
|
BUILDER_CONFIG=
|
||||||
|
|||||||
+5
-3
@@ -1,5 +1,5 @@
|
|||||||
# syntax=docker/dockerfile:1.7
|
# syntax=docker/dockerfile:1.7
|
||||||
ARG RUST_VERSION=1.89
|
ARG RUST_VERSION=1.98.1
|
||||||
ARG XX_VERSION=1.9.0
|
ARG XX_VERSION=1.9.0
|
||||||
|
|
||||||
# Cross-compilation helpers. Builder stages always run on BUILDPLATFORM, so an
|
# Cross-compilation helpers. Builder stages always run on BUILDPLATFORM, so an
|
||||||
@@ -16,11 +16,12 @@ RUN apt-get update \
|
|||||||
|
|
||||||
# Fetch Rust dependencies before TARGETPLATFORM enters the cache chain, so the
|
# Fetch Rust dependencies before TARGETPLATFORM enters the cache chain, so the
|
||||||
# same registry/git cache is reused by amd64 and arm64 builds.
|
# same registry/git cache is reused by amd64 and arm64 builds.
|
||||||
COPY Cargo.toml Cargo.lock ./
|
COPY Cargo.toml ./
|
||||||
RUN --mount=type=cache,id=gree-controller-cargo-registry,target=/usr/local/cargo/registry \
|
RUN --mount=type=cache,id=gree-controller-cargo-registry,target=/usr/local/cargo/registry \
|
||||||
--mount=type=cache,id=gree-controller-cargo-git,target=/usr/local/cargo/git \
|
--mount=type=cache,id=gree-controller-cargo-git,target=/usr/local/cargo/git \
|
||||||
mkdir -p src \
|
mkdir -p src \
|
||||||
&& printf 'fn main() {}\n' > src/main.rs \
|
&& printf 'fn main() {}\n' > src/main.rs \
|
||||||
|
&& cargo generate-lockfile \
|
||||||
&& cargo fetch --locked \
|
&& cargo fetch --locked \
|
||||||
&& rm -rf src
|
&& rm -rf src
|
||||||
|
|
||||||
@@ -56,11 +57,12 @@ WORKDIR /src
|
|||||||
RUN apk add --no-cache clang lld llvm file pkgconf
|
RUN apk add --no-cache clang lld llvm file pkgconf
|
||||||
|
|
||||||
# Keep dependency fetching architecture-independent here as well.
|
# Keep dependency fetching architecture-independent here as well.
|
||||||
COPY Cargo.toml Cargo.lock ./
|
COPY Cargo.toml ./
|
||||||
RUN --mount=type=cache,id=gree-controller-cargo-registry,target=/usr/local/cargo/registry \
|
RUN --mount=type=cache,id=gree-controller-cargo-registry,target=/usr/local/cargo/registry \
|
||||||
--mount=type=cache,id=gree-controller-cargo-git,target=/usr/local/cargo/git \
|
--mount=type=cache,id=gree-controller-cargo-git,target=/usr/local/cargo/git \
|
||||||
mkdir -p src \
|
mkdir -p src \
|
||||||
&& printf 'fn main() {}\n' > src/main.rs \
|
&& printf 'fn main() {}\n' > src/main.rs \
|
||||||
|
&& cargo generate-lockfile \
|
||||||
&& cargo fetch --locked \
|
&& cargo fetch --locked \
|
||||||
&& rm -rf src
|
&& rm -rf src
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
This directory contains the OCI build, Home Assistant add-on repository source, custom integration and repository synchronization tooling.
|
This directory contains the OCI build, Home Assistant add-on repository source, custom integration and repository synchronization tooling.
|
||||||
|
|
||||||
|
The packaged controller includes its HTTP/WebSocket API and built-in Swagger documentation at `/api-docs` (`/api-docs/openapi.json` for OpenAPI 3.1).
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Create the local build/repository configuration once:
|
Create the local build/repository configuration once:
|
||||||
@@ -20,7 +22,7 @@ Important variables:
|
|||||||
REGISTRY=repo.example.com
|
REGISTRY=repo.example.com
|
||||||
IMAGE_NAME=gree-controller
|
IMAGE_NAME=gree-controller
|
||||||
DISTRO=alpine
|
DISTRO=alpine
|
||||||
RUST_VERSION=1.89
|
RUST_VERSION=1.98.1
|
||||||
BUILD_PLATFORMS=linux/amd64,linux/arm64
|
BUILD_PLATFORMS=linux/amd64,linux/arm64
|
||||||
BUILDER=gree-controller-multiarch
|
BUILDER=gree-controller-multiarch
|
||||||
BUILDER_CONFIG=
|
BUILDER_CONFIG=
|
||||||
@@ -40,7 +42,7 @@ INTEGRATION_DOMAIN=gree_controller
|
|||||||
./build.sh push
|
./build.sh push
|
||||||
```
|
```
|
||||||
|
|
||||||
The project version comes only from root `Cargo.toml`. `render` synchronizes it to `Cargo.lock`, add-on `config.yaml` and the custom integration `manifest.json`, and sets the OCI image from `.env`.
|
The project version comes only from root `Cargo.toml`. `render` synchronizes it to add-on `config.yaml` and the custom integration `manifest.json`, and sets the OCI image from `.env`. The container build generates `Cargo.lock` from the exact direct dependency versions in `Cargo.toml` before fetching and compiling dependencies.
|
||||||
|
|
||||||
For the Home Assistant package, TCP `8787` is an intentional fixed host-network/ingress port contract. `build.sh render` verifies `config.yaml`, `run.sh`, the watchdog URL and Docker image metadata stay consistent. The runtime also compares the Supervisor-reported ingress port before starting. Standalone installations remain free to use any `GREE_CONTROLLER_BIND` port.
|
For the Home Assistant package, TCP `8787` is an intentional fixed host-network/ingress port contract. `build.sh render` verifies `config.yaml`, `run.sh`, the watchdog URL and Docker image metadata stay consistent. The runtime also compares the Supervisor-reported ingress port before starting. Standalone installations remain free to use any `GREE_CONTROLLER_BIND` port.
|
||||||
|
|
||||||
|
|||||||
+6
-16
@@ -32,7 +32,6 @@ VERSION="$(awk -F '"' '/^version = "/ {print $2; exit}' "$PROJECT_ROOT/Cargo.tom
|
|||||||
IMAGE_REPO="${REGISTRY%/}/${IMAGE_NAME#/}"
|
IMAGE_REPO="${REGISTRY%/}/${IMAGE_NAME#/}"
|
||||||
IMAGE_TAG="${IMAGE_REPO}:${VERSION}"
|
IMAGE_TAG="${IMAGE_REPO}:${VERSION}"
|
||||||
CONFIG="$SCRIPT_DIR/repository/$ADDON_DIR/config.yaml"
|
CONFIG="$SCRIPT_DIR/repository/$ADDON_DIR/config.yaml"
|
||||||
LOCKFILE="$PROJECT_ROOT/Cargo.lock"
|
|
||||||
INTEGRATION_MANIFEST="$SCRIPT_DIR/home-assistant/custom_components/$INTEGRATION_DOMAIN/manifest.json"
|
INTEGRATION_MANIFEST="$SCRIPT_DIR/home-assistant/custom_components/$INTEGRATION_DOMAIN/manifest.json"
|
||||||
REPOSITORY_CONFIG="$SCRIPT_DIR/repository/repository.yaml"
|
REPOSITORY_CONFIG="$SCRIPT_DIR/repository/repository.yaml"
|
||||||
RUN_SCRIPT="$SCRIPT_DIR/run.sh"
|
RUN_SCRIPT="$SCRIPT_DIR/run.sh"
|
||||||
@@ -44,18 +43,16 @@ DOCKERFILE="$SCRIPT_DIR/Dockerfile"
|
|||||||
|
|
||||||
render_metadata() {
|
render_metadata() {
|
||||||
command -v python3 >/dev/null 2>&1 || { echo "python3 is required" >&2; exit 1; }
|
command -v python3 >/dev/null 2>&1 || { echo "python3 is required" >&2; exit 1; }
|
||||||
python3 - "$CONFIG" "$LOCKFILE" "$INTEGRATION_MANIFEST" "$REPOSITORY_CONFIG" "$VERSION" "$IMAGE_REPO" "$HA_REPO_URL" <<'PY'
|
python3 - "$CONFIG" "$INTEGRATION_MANIFEST" "$REPOSITORY_CONFIG" "$VERSION" "$IMAGE_REPO" "$HA_REPO_URL" <<'PY'
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import re
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
config = Path(sys.argv[1])
|
config = Path(sys.argv[1])
|
||||||
lockfile = Path(sys.argv[2])
|
manifest = Path(sys.argv[2])
|
||||||
manifest = Path(sys.argv[3])
|
repository = Path(sys.argv[3])
|
||||||
repository = Path(sys.argv[4])
|
version = sys.argv[4]
|
||||||
version = sys.argv[5]
|
image = sys.argv[5]
|
||||||
image = sys.argv[6]
|
repo_url = sys.argv[6]
|
||||||
repo_url = sys.argv[7]
|
|
||||||
|
|
||||||
lines = config.read_text(encoding="utf-8").splitlines()
|
lines = config.read_text(encoding="utf-8").splitlines()
|
||||||
out = []
|
out = []
|
||||||
@@ -70,13 +67,6 @@ for line in lines:
|
|||||||
out.append(line)
|
out.append(line)
|
||||||
config.write_text("\n".join(out) + "\n", encoding="utf-8")
|
config.write_text("\n".join(out) + "\n", encoding="utf-8")
|
||||||
|
|
||||||
lock = lockfile.read_text(encoding="utf-8")
|
|
||||||
pattern = r'(\[\[package\]\]\nname = "gree-controller"\nversion = ")[^"]+("\n)'
|
|
||||||
updated, count = re.subn(pattern, rf'\g<1>{version}\g<2>', lock, count=1)
|
|
||||||
if count != 1:
|
|
||||||
raise SystemExit("Could not find gree-controller package version in Cargo.lock")
|
|
||||||
lockfile.write_text(updated, encoding="utf-8")
|
|
||||||
|
|
||||||
import json
|
import json
|
||||||
data = json.loads(manifest.read_text(encoding="utf-8"))
|
data = json.loads(manifest.read_text(encoding="utf-8"))
|
||||||
data["version"] = version
|
data["version"] = version
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ ha-addon/home-assistant/custom_components/gree_controller/
|
|||||||
|
|
||||||
It creates HA entities for physical units, thermostat zones, whole-house controls and climate groups, while sending every command to the standalone Rust controller. Home Assistant therefore remains a client and UDP/AES GREE communication stays outside HA.
|
It creates HA entities for physical units, thermostat zones, whole-house controls and climate groups, while sending every command to the standalone Rust controller. Home Assistant therefore remains a client and UDP/AES GREE communication stays outside HA.
|
||||||
|
|
||||||
|
The controller exposes the API used by the integration and Web UI under `/api/*` and `/ws`; interactive Swagger documentation is available at `/api-docs`, with OpenAPI JSON at `/api-docs/openapi.json`.
|
||||||
|
|
||||||
The climate proxy supports power/turn on/off, HVAC modes, target temperature, fan mode, granular vertical louver positions and granular horizontal louver positions. `off`/`on` remain the first two swing modes for compatibility, followed by fixed positions and the supported vertical partial-swing ranges. The card UI translates those modes using the Home Assistant language while the underlying mode IDs (for example `fixed_upper`) remain unchanged for services, scripts and automations.
|
The climate proxy supports power/turn on/off, HVAC modes, target temperature, fan mode, granular vertical louver positions and granular horizontal louver positions. `off`/`on` remain the first two swing modes for compatibility, followed by fixed positions and the supported vertical partial-swing ranges. The card UI translates those modes using the Home Assistant language while the underlying mode IDs (for example `fixed_upper`) remain unchanged for services, scripts and automations.
|
||||||
|
|
||||||
Automation plan:
|
Automation plan:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"domain": "gree_controller",
|
"domain": "gree_controller",
|
||||||
"name": "GREE Controller",
|
"name": "GREE Controller",
|
||||||
"version": "0.15.2",
|
"version": "0.15.4",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"integration_type": "hub",
|
"integration_type": "hub",
|
||||||
"iot_class": "local_polling",
|
"iot_class": "local_polling",
|
||||||
|
|||||||
@@ -1,5 +1,18 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.15.4
|
||||||
|
|
||||||
|
- Updates the Rust dependency stack to current major/minor releases, including Axum 0.8, Reqwest 0.13, Rusqlite 0.40, Rand 0.10, AES 0.9, AES-GCM 0.11, Base64 0.23, SHA-2 0.11, Tower HTTP 0.7 and utoipa-swagger-ui 9.
|
||||||
|
- Migrates Axum route parameters and WebSocket text frames, Rand APIs, RustCrypto AES/AES-GCM APIs and Reqwest TLS configuration for the new dependency versions.
|
||||||
|
- Updates the Home Assistant add-on Rust builder to Rust 1.98.1.
|
||||||
|
- Pins direct Rust dependencies to exact updated releases; container builds generate a fresh lockfile before fetching and compiling with `--locked`.
|
||||||
|
- Uses `ring` as the single Rustls crypto provider across Reqwest and the direct MQTT TLS client, avoiding the Rustls provider ambiguity introduced by Reqwest 0.13.
|
||||||
|
|
||||||
|
## 0.15.3
|
||||||
|
|
||||||
|
- Simplifies the built-in Swagger API documentation: removes the embedded release-history changelog, starts with all endpoint groups collapsed and hides the global Schemas section.
|
||||||
|
- Documents the HTTP/WebSocket API, Swagger UI (`/api-docs`) and OpenAPI document (`/api-docs/openapi.json`) in the main documentation and Home Assistant add-on package.
|
||||||
|
|
||||||
## 0.15.2
|
## 0.15.2
|
||||||
|
|
||||||
- Adds a dedicated Visual Flow action for changing exactly one GREE unit function without modifying unrelated settings.
|
- Adds a dedicated Visual Flow action for changing exactly one GREE unit function without modifying unrelated settings.
|
||||||
|
|||||||
@@ -59,6 +59,10 @@ Broadcast zwykle nie przechodzi przez router. Sterowanie unicast może działać
|
|||||||
| `public_chart_base_url` | opcjonalny bazowy URL publicznych linków Custom Chart; puste = automatyczne główne IPv4 hosta HA + `:8787` |
|
| `public_chart_base_url` | opcjonalny bazowy URL publicznych linków Custom Chart; puste = automatyczne główne IPv4 hosta HA + `:8787` |
|
||||||
| `log_level` | `error`, `warn`, `info`, `debug`, `trace` |
|
| `log_level` | `error`, `warn`, `info`, `debug`, `trace` |
|
||||||
|
|
||||||
|
### API i dokumentacja API
|
||||||
|
|
||||||
|
Aplikacja udostępnia HTTP API pod `/api/*` oraz WebSocket pod `/ws`. Interaktywna dokumentacja Swagger jest dostępna pod `/api-docs`, a dokument OpenAPI 3.1 pod `/api-docs/openapi.json`. Te same ścieżki działają przez ingress Home Assistant; bezpośredni dostęp na porcie `8787` podlega regułom `app_token`.
|
||||||
|
|
||||||
### Home Assistant API
|
### Home Assistant API
|
||||||
|
|
||||||
Dodatek korzysta automatycznie z wewnętrznego proxy Home Assistant Core (`http://supervisor/core/api/`) i tokenu `SUPERVISOR_TOKEN` przekazywanego przez Supervisor. Gdy token jest wykryty, UI pokazuje automatyczną autoryzację i ukrywa ręczne pola URL/token. Dopiero nieudany `Test HA` odblokowuje awaryjny ręczny fallback. Token Supervisor jest używany tylko w pamięci procesu i nie jest zapisywany w SQLite.
|
Dodatek korzysta automatycznie z wewnętrznego proxy Home Assistant Core (`http://supervisor/core/api/`) i tokenu `SUPERVISOR_TOKEN` przekazywanego przez Supervisor. Gdy token jest wykryty, UI pokazuje automatyczną autoryzację i ukrywa ręczne pola URL/token. Dopiero nieudany `Test HA` odblokowuje awaryjny ręczny fallback. Token Supervisor jest używany tylko w pamięci procesu i nie jest zapisywany w SQLite.
|
||||||
@@ -125,6 +129,10 @@ Broadcast normally does not cross routers. Unicast control may work through rout
|
|||||||
| `public_chart_base_url` | optional base URL for public Custom Chart links; empty = primary HA host IPv4 + `:8787` automatically |
|
| `public_chart_base_url` | optional base URL for public Custom Chart links; empty = primary HA host IPv4 + `:8787` automatically |
|
||||||
| `log_level` | `error`, `warn`, `info`, `debug`, `trace` |
|
| `log_level` | `error`, `warn`, `info`, `debug`, `trace` |
|
||||||
|
|
||||||
|
### API and API documentation
|
||||||
|
|
||||||
|
The application exposes its HTTP API under `/api/*` and WebSocket under `/ws`. Interactive Swagger documentation is available at `/api-docs`, with the OpenAPI 3.1 document at `/api-docs/openapi.json`. The same paths work through Home Assistant ingress; direct access on port `8787` follows the configured `app_token` rules.
|
||||||
|
|
||||||
### Home Assistant API
|
### Home Assistant API
|
||||||
|
|
||||||
The add-on automatically uses the internal Home Assistant Core proxy (`http://supervisor/core/api/`) and the runtime `SUPERVISOR_TOKEN` provided by Supervisor. When the token is detected, the UI shows automatic authorization and hides manual URL/token fields. A failed `Test HA` unlocks the optional manual fallback. The Supervisor token is used only at runtime and is not stored in SQLite.
|
The add-on automatically uses the internal Home Assistant Core proxy (`http://supervisor/core/api/`) and the runtime `SUPERVISOR_TOKEN` provided by Supervisor. When the token is detected, the UI shows automatic authorization and hides manual URL/token fields. A failed `Test HA` unlocks the optional manual fallback. The Supervisor token is used only at runtime and is not stored in SQLite.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# GREE Controller
|
# GREE Controller
|
||||||
|
|
||||||
Local GREE HVAC controller packaged as a Home Assistant add-on, with Web UI, local API, UDP discovery/control, `amd64` and `aarch64` support, ingress, and database backup from `/data/gree-controller.db`.
|
Local GREE HVAC controller packaged as a Home Assistant add-on, with Web UI, HTTP/WebSocket API, built-in Swagger API documentation, UDP discovery/control, `amd64` and `aarch64` support, ingress, and database backup from `/data/gree-controller.db`.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -8,6 +8,8 @@ For VLAN deployments, configure VLAN interfaces on the Home Assistant OS host. T
|
|||||||
|
|
||||||
Full documentation: [DOCS.md](./DOCS.md).
|
Full documentation: [DOCS.md](./DOCS.md).
|
||||||
|
|
||||||
|
The controller exposes `/api/*` and `/ws`. Interactive API documentation is available at `/api-docs`, with the OpenAPI 3.1 document at `/api-docs/openapi.json`. The same paths work through Home Assistant ingress; direct access on port `8787` follows the configured `app_token` rules.
|
||||||
|
|
||||||
The same Git repository also contains the optional `custom_components/gree_controller` integration. It is distributed with the repository but is not installed automatically with the add-on.
|
The same Git repository also contains the optional `custom_components/gree_controller` integration. It is distributed with the repository but is not installed automatically with the add-on.
|
||||||
|
|
||||||
Repository: https://git.linuxiarz.pl/gru/gree-controller-ha-addon/
|
Repository: https://git.linuxiarz.pl/gru/gree-controller-ha-addon/
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: "GREE Controller"
|
name: "GREE Controller"
|
||||||
version: "0.15.2"
|
version: "0.15.4"
|
||||||
slug: "gree_controller"
|
slug: "gree_controller"
|
||||||
description: "Local GREE HVAC controller with Web UI and Home Assistant integration"
|
description: "Local GREE HVAC controller with Web UI, API, Swagger API docs and Home Assistant integration"
|
||||||
url: "https://git.linuxiarz.pl/gru/gree-controller-ha-addon/"
|
url: "https://git.linuxiarz.pl/gru/gree-controller-ha-addon/"
|
||||||
arch:
|
arch:
|
||||||
- amd64
|
- amd64
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Developer smoke/integration tests for GREE Controller API 0.14.18.
|
"""Developer smoke/integration tests for GREE Controller API 0.15.4.
|
||||||
|
|
||||||
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.14.18"
|
DEFAULT_EXPECTED_VERSION = "0.15.4"
|
||||||
|
|
||||||
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.14.18 contract", lambda: test_openapi(client, args.expected_version))
|
runner.run("OpenAPI 0.15.4 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))
|
||||||
|
|
||||||
|
|||||||
+28
-29
@@ -34,7 +34,6 @@ use axum::{
|
|||||||
use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _};
|
use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _};
|
||||||
use chrono::{Duration as ChronoDuration, NaiveTime, Utc};
|
use chrono::{Duration as ChronoDuration, NaiveTime, Utc};
|
||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
use rand::{rngs::OsRng, RngCore};
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
@@ -91,31 +90,31 @@ pub fn router(state: AppState) -> Router {
|
|||||||
.route("/api/discovery", post(discover))
|
.route("/api/discovery", post(discover))
|
||||||
.route("/api/devices", get(list_devices).post(add_device))
|
.route("/api/devices", get(list_devices).post(add_device))
|
||||||
.route(
|
.route(
|
||||||
"/api/devices/:id",
|
"/api/devices/{id}",
|
||||||
get(get_device).patch(patch_device).delete(delete_device),
|
get(get_device).patch(patch_device).delete(delete_device),
|
||||||
)
|
)
|
||||||
.route("/api/devices/:id/bind", post(bind_device))
|
.route("/api/devices/{id}/bind", post(bind_device))
|
||||||
.route("/api/devices/:id/poll", post(poll_device))
|
.route("/api/devices/{id}/poll", post(poll_device))
|
||||||
.route("/api/devices/:id/probe", post(probe_device))
|
.route("/api/devices/{id}/probe", post(probe_device))
|
||||||
.route("/api/devices/:id/command", post(command_device))
|
.route("/api/devices/{id}/command", post(command_device))
|
||||||
.route(
|
.route(
|
||||||
"/api/device-groups",
|
"/api/device-groups",
|
||||||
get(list_device_groups).post(create_device_group),
|
get(list_device_groups).post(create_device_group),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
"/api/device-groups/:id",
|
"/api/device-groups/{id}",
|
||||||
get(get_device_group)
|
get(get_device_group)
|
||||||
.put(update_device_group)
|
.put(update_device_group)
|
||||||
.delete(delete_device_group),
|
.delete(delete_device_group),
|
||||||
)
|
)
|
||||||
.route("/api/zones", get(list_zones).post(create_zone))
|
.route("/api/zones", get(list_zones).post(create_zone))
|
||||||
.route(
|
.route(
|
||||||
"/api/zones/:id",
|
"/api/zones/{id}",
|
||||||
get(get_zone).put(update_zone).delete(delete_zone),
|
get(get_zone).put(update_zone).delete(delete_zone),
|
||||||
)
|
)
|
||||||
.route("/api/zones/:id/control", post(update_zone_control))
|
.route("/api/zones/{id}/control", post(update_zone_control))
|
||||||
.route(
|
.route(
|
||||||
"/api/zones/:id/compressor-queue/cancel",
|
"/api/zones/{id}/compressor-queue/cancel",
|
||||||
post(cancel_zone_compressor_queue),
|
post(cancel_zone_compressor_queue),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
@@ -123,21 +122,21 @@ pub fn router(state: AppState) -> Router {
|
|||||||
post(cancel_all_compressor_queues),
|
post(cancel_all_compressor_queues),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
"/api/zones/:id/schedule-template",
|
"/api/zones/{id}/schedule-template",
|
||||||
post(apply_schedule_template),
|
post(apply_schedule_template),
|
||||||
)
|
)
|
||||||
.route("/api/groups", get(list_groups).post(create_group))
|
.route("/api/groups", get(list_groups).post(create_group))
|
||||||
.route(
|
.route(
|
||||||
"/api/groups/:id",
|
"/api/groups/{id}",
|
||||||
get(get_group).put(update_group).delete(delete_group),
|
get(get_group).put(update_group).delete(delete_group),
|
||||||
)
|
)
|
||||||
.route("/api/groups/:id/control", post(update_group_control))
|
.route("/api/groups/{id}/control", post(update_group_control))
|
||||||
.route("/api/house/control", post(update_house_control))
|
.route("/api/house/control", post(update_house_control))
|
||||||
.route("/api/house/power", post(update_house_power))
|
.route("/api/house/power", post(update_house_power))
|
||||||
.route("/api/house/preset", post(update_house_preset))
|
.route("/api/house/preset", post(update_house_preset))
|
||||||
.route("/api/schedules", get(list_schedules).post(create_schedule))
|
.route("/api/schedules", get(list_schedules).post(create_schedule))
|
||||||
.route(
|
.route(
|
||||||
"/api/schedules/:id",
|
"/api/schedules/{id}",
|
||||||
get(get_schedule)
|
get(get_schedule)
|
||||||
.put(update_schedule)
|
.put(update_schedule)
|
||||||
.delete(delete_schedule),
|
.delete(delete_schedule),
|
||||||
@@ -147,7 +146,7 @@ pub fn router(state: AppState) -> Router {
|
|||||||
get(list_automations).post(create_automation),
|
get(list_automations).post(create_automation),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
"/api/automations/:id",
|
"/api/automations/{id}",
|
||||||
get(get_automation)
|
get(get_automation)
|
||||||
.put(update_automation)
|
.put(update_automation)
|
||||||
.delete(delete_automation),
|
.delete(delete_automation),
|
||||||
@@ -155,10 +154,10 @@ pub fn router(state: AppState) -> Router {
|
|||||||
.route("/api/flows", get(list_flows).post(create_flow))
|
.route("/api/flows", get(list_flows).post(create_flow))
|
||||||
.route("/api/flows/import", post(import_flow))
|
.route("/api/flows/import", post(import_flow))
|
||||||
.route("/api/flows/simulate", post(simulate_flow))
|
.route("/api/flows/simulate", post(simulate_flow))
|
||||||
.route("/api/flows/:id/export", get(export_flow))
|
.route("/api/flows/{id}/export", get(export_flow))
|
||||||
.route("/api/flows/:id/logs", get(flow_logs))
|
.route("/api/flows/{id}/logs", get(flow_logs))
|
||||||
.route(
|
.route(
|
||||||
"/api/flows/:id",
|
"/api/flows/{id}",
|
||||||
get(get_flow).put(update_flow).delete(delete_flow),
|
get(get_flow).put(update_flow).delete(delete_flow),
|
||||||
)
|
)
|
||||||
.route("/api/readings", get(readings))
|
.route("/api/readings", get(readings))
|
||||||
@@ -215,7 +214,7 @@ pub fn router(state: AppState) -> Router {
|
|||||||
get(list_access_tokens).post(create_access_token),
|
get(list_access_tokens).post(create_access_token),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
"/api/access-tokens/:id",
|
"/api/access-tokens/{id}",
|
||||||
axum::routing::delete(delete_access_token),
|
axum::routing::delete(delete_access_token),
|
||||||
)
|
)
|
||||||
.route("/api/integrations/gree-cloud/test", post(test_gree_cloud))
|
.route("/api/integrations/gree-cloud/test", post(test_gree_cloud))
|
||||||
@@ -224,7 +223,7 @@ pub fn router(state: AppState) -> Router {
|
|||||||
get(discover_gree_cloud_devices),
|
get(discover_gree_cloud_devices),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
"/api/integrations/gree-cloud/devices/:cloud_id/add",
|
"/api/integrations/gree-cloud/devices/{cloud_id}/add",
|
||||||
post(add_gree_cloud_device),
|
post(add_gree_cloud_device),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
@@ -236,7 +235,7 @@ pub fn router(state: AppState) -> Router {
|
|||||||
post(reconnect_gree_cloud),
|
post(reconnect_gree_cloud),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
"/api/devices/:id/cloud-diagnostics",
|
"/api/devices/{id}/cloud-diagnostics",
|
||||||
get(cloud_device_diagnostics),
|
get(cloud_device_diagnostics),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
@@ -271,7 +270,7 @@ pub fn router(state: AppState) -> Router {
|
|||||||
get(list_devices),
|
get(list_devices),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
"/api/integrations/home-assistant/devices/:id/command",
|
"/api/integrations/home-assistant/devices/{id}/command",
|
||||||
post(command_home_assistant_device),
|
post(command_home_assistant_device),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
@@ -283,7 +282,7 @@ pub fn router(state: AppState) -> Router {
|
|||||||
get(list_home_assistant_groups),
|
get(list_home_assistant_groups),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
"/api/integrations/home-assistant/groups/:id/control",
|
"/api/integrations/home-assistant/groups/{id}/control",
|
||||||
post(update_home_assistant_group_control),
|
post(update_home_assistant_group_control),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
@@ -299,7 +298,7 @@ pub fn router(state: AppState) -> Router {
|
|||||||
post(update_house_power),
|
post(update_house_power),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
"/api/integrations/home-assistant/zones/:id/control",
|
"/api/integrations/home-assistant/zones/{id}/control",
|
||||||
post(update_home_assistant_zone_control),
|
post(update_home_assistant_zone_control),
|
||||||
)
|
)
|
||||||
.route_layer(middleware::from_fn_with_state(
|
.route_layer(middleware::from_fn_with_state(
|
||||||
@@ -309,8 +308,8 @@ pub fn router(state: AppState) -> Router {
|
|||||||
|
|
||||||
let mut app = Router::new()
|
let mut app = Router::new()
|
||||||
.route("/api/health", get(health))
|
.route("/api/health", get(health))
|
||||||
.route("/api/public/charts/custom/:token", get(public_custom_chart))
|
.route("/api/public/charts/custom/{token}", get(public_custom_chart))
|
||||||
.route("/charts/custom/:token", get(custom_chart_page))
|
.route("/charts/custom/{token}", get(custom_chart_page))
|
||||||
.route("/custom-chart.js", get(custom_chart_js))
|
.route("/custom-chart.js", get(custom_chart_js))
|
||||||
.route("/ws", get(websocket))
|
.route("/ws", get(websocket))
|
||||||
.route("/", get(index))
|
.route("/", get(index))
|
||||||
@@ -322,11 +321,11 @@ pub fn router(state: AppState) -> Router {
|
|||||||
.route("/manifest.webmanifest", get(manifest))
|
.route("/manifest.webmanifest", get(manifest))
|
||||||
.route("/sw.js", get(service_worker))
|
.route("/sw.js", get(service_worker))
|
||||||
.route("/favicon.svg", get(favicon))
|
.route("/favicon.svg", get(favicon))
|
||||||
.route("/flows/:id", get(index))
|
.route("/flows/{id}", get(index))
|
||||||
.route("/lang/index.json", get(language_index))
|
.route("/lang/index.json", get(language_index))
|
||||||
.route("/lang/:file", get(language_file))
|
.route("/lang/{file}", get(language_file))
|
||||||
.route("/presets/index.json", get(preset_index))
|
.route("/presets/index.json", get(preset_index))
|
||||||
.route("/presets/:file", get(preset_file))
|
.route("/presets/{file}", get(preset_file))
|
||||||
.merge(openapi::swagger_ui(&state.config.base_path))
|
.merge(openapi::swagger_ui(&state.config.base_path))
|
||||||
.merge(protected)
|
.merge(protected)
|
||||||
.merge(home_assistant_api);
|
.merge(home_assistant_api);
|
||||||
|
|||||||
+1
-2
@@ -99,7 +99,6 @@ fn hash_token(token: &str) -> String {
|
|||||||
|
|
||||||
fn generate_access_token() -> String {
|
fn generate_access_token() -> String {
|
||||||
let mut bytes = [0u8; 32];
|
let mut bytes = [0u8; 32];
|
||||||
let mut rng = OsRng;
|
rand::fill(&mut bytes);
|
||||||
rng.fill_bytes(&mut bytes);
|
|
||||||
format!("gree_controller_{}", URL_SAFE_NO_PAD.encode(bytes))
|
format!("gree_controller_{}", URL_SAFE_NO_PAD.encode(bytes))
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -550,8 +550,7 @@ fn validate_public_chart_spec(series: &[String]) -> Result<(), AppError> {
|
|||||||
|
|
||||||
fn generate_public_chart_token() -> String {
|
fn generate_public_chart_token() -> String {
|
||||||
let mut bytes = [0u8; 32];
|
let mut bytes = [0u8; 32];
|
||||||
let mut rng = OsRng;
|
rand::fill(&mut bytes);
|
||||||
rng.fill_bytes(&mut bytes);
|
|
||||||
format!("chart_{}", URL_SAFE_NO_PAD.encode(bytes))
|
format!("chart_{}", URL_SAFE_NO_PAD.encode(bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-4
@@ -12,10 +12,8 @@ pub(super) fn swagger_ui(base_path: &str) -> SwaggerUi {
|
|||||||
.external_url_unchecked("/api-docs/openapi.json", document(base_path))
|
.external_url_unchecked("/api-docs/openapi.json", document(base_path))
|
||||||
.config(
|
.config(
|
||||||
SwaggerConfig::new([docs_url])
|
SwaggerConfig::new([docs_url])
|
||||||
.filter(true)
|
.doc_expansion("none")
|
||||||
.try_it_out_enabled(true)
|
.default_models_expand_depth(-1),
|
||||||
.display_request_duration(true)
|
|
||||||
.persist_authorization(true),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ async fn send_ws_bootstrap(state: &AppState, socket: &mut WebSocket) -> Result<O
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
socket
|
socket
|
||||||
.send(Message::Text(message.to_string()))
|
.send(Message::Text(message.to_string().into()))
|
||||||
.await
|
.await
|
||||||
.map_err(|_| ())?;
|
.map_err(|_| ())?;
|
||||||
Ok(revision)
|
Ok(revision)
|
||||||
@@ -81,7 +81,7 @@ async fn websocket_loop(state: AppState, mut socket: WebSocket) {
|
|||||||
match event {
|
match event {
|
||||||
Ok(event) => {
|
Ok(event) => {
|
||||||
if let Ok(text) = serde_json::to_string(&event) {
|
if let Ok(text) = serde_json::to_string(&event) {
|
||||||
if socket.send(Message::Text(text)).await.is_err() { break; }
|
if socket.send(Message::Text(text.into())).await.is_err() { break; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(tokio::sync::broadcast::error::RecvError::Lagged(skipped)) => {
|
Err(tokio::sync::broadcast::error::RecvError::Lagged(skipped)) => {
|
||||||
@@ -105,7 +105,7 @@ async fn websocket_loop(state: AppState, mut socket: WebSocket) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let text = control_plan_ws_message(snapshot.as_ref()).to_string();
|
let text = control_plan_ws_message(snapshot.as_ref()).to_string();
|
||||||
if socket.send(Message::Text(text)).await.is_err() { break; }
|
if socket.send(Message::Text(text.into())).await.is_err() { break; }
|
||||||
last_control_plan_revision = Some(snapshot.revision);
|
last_control_plan_revision = Some(snapshot.revision);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,8 +94,8 @@ fn request_client(
|
|||||||
reqwest::Client::builder()
|
reqwest::Client::builder()
|
||||||
.timeout(Duration::from_secs(10))
|
.timeout(Duration::from_secs(10))
|
||||||
.user_agent(concat!("gree-controller/", env!("CARGO_PKG_VERSION")))
|
.user_agent(concat!("gree-controller/", env!("CARGO_PKG_VERSION")))
|
||||||
.danger_accept_invalid_certs(true)
|
.tls_danger_accept_invalid_certs(true)
|
||||||
.danger_accept_invalid_hostnames(true)
|
.tls_danger_accept_invalid_hostnames(true)
|
||||||
.build()
|
.build()
|
||||||
.context("cannot build Home Assistant HTTPS client")
|
.context("cannot build Home Assistant HTTPS client")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
|
install_rustls_crypto_provider();
|
||||||
let config = Config::load()?;
|
let config = Config::load()?;
|
||||||
init_tracing();
|
init_tracing();
|
||||||
|
|
||||||
@@ -191,6 +192,13 @@ async fn main() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn install_rustls_crypto_provider() {
|
||||||
|
// reqwest is built with `rustls-no-provider` while tokio-rustls enables only
|
||||||
|
// `ring`. Install it once at process startup so every rustls consumer uses
|
||||||
|
// the same provider and rustls never has to guess between ring and AWS-LC.
|
||||||
|
let _ = tokio_rustls::rustls::crypto::ring::default_provider().install_default();
|
||||||
|
}
|
||||||
|
|
||||||
fn init_tracing() {
|
fn init_tracing() {
|
||||||
let filter = tracing_subscriber::EnvFilter::try_from_default_env()
|
let filter = tracing_subscriber::EnvFilter::try_from_default_env()
|
||||||
.unwrap_or_else(|_| "info,tower_http=info".into());
|
.unwrap_or_else(|_| "info,tower_http=info".into());
|
||||||
|
|||||||
+16
-11
@@ -1,10 +1,10 @@
|
|||||||
use aes::{
|
use aes::{
|
||||||
cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt, KeyInit},
|
cipher::{BlockCipherDecrypt, BlockCipherEncrypt, KeyInit},
|
||||||
Aes128,
|
Aes128, Block,
|
||||||
};
|
};
|
||||||
use aes_gcm::{
|
use aes_gcm::{
|
||||||
aead::{AeadInPlace, KeyInit as AeadKeyInit},
|
aead::{consts::U12, AeadInOut, KeyInit as AeadKeyInit},
|
||||||
Aes128Gcm, Nonce,
|
Aes128Gcm, Nonce, Tag,
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, bail, Context, Result};
|
use anyhow::{anyhow, bail, Context, Result};
|
||||||
use base64::{
|
use base64::{
|
||||||
@@ -62,7 +62,8 @@ pub fn encrypt_v1(key: &str, plaintext: &[u8]) -> Result<String> {
|
|||||||
data.extend_from_slice(plaintext);
|
data.extend_from_slice(plaintext);
|
||||||
data.extend(std::iter::repeat(pad as u8).take(pad));
|
data.extend(std::iter::repeat(pad as u8).take(pad));
|
||||||
for block in data.chunks_exact_mut(16) {
|
for block in data.chunks_exact_mut(16) {
|
||||||
cipher.encrypt_block(GenericArray::from_mut_slice(block));
|
let block: &mut Block = block.try_into().expect("AES block is 16 bytes");
|
||||||
|
cipher.encrypt_block(block);
|
||||||
}
|
}
|
||||||
Ok(STANDARD.encode(data))
|
Ok(STANDARD.encode(data))
|
||||||
}
|
}
|
||||||
@@ -77,7 +78,8 @@ pub fn decrypt_v1(key: &str, ciphertext_b64: &str) -> Result<Vec<u8>> {
|
|||||||
bail!("invalid AES-ECB ciphertext length")
|
bail!("invalid AES-ECB ciphertext length")
|
||||||
}
|
}
|
||||||
for block in data.chunks_exact_mut(16) {
|
for block in data.chunks_exact_mut(16) {
|
||||||
cipher.decrypt_block(GenericArray::from_mut_slice(block));
|
let block: &mut Block = block.try_into().expect("AES block is 16 bytes");
|
||||||
|
cipher.decrypt_block(block);
|
||||||
}
|
}
|
||||||
let pad = *data.last().ok_or_else(|| anyhow!("empty plaintext"))? as usize;
|
let pad = *data.last().ok_or_else(|| anyhow!("empty plaintext"))? as usize;
|
||||||
let valid_padding = pad > 0
|
let valid_padding = pad > 0
|
||||||
@@ -106,10 +108,10 @@ pub fn encrypt_v2(key: &str, plaintext: &[u8]) -> Result<V2Encrypted> {
|
|||||||
let key = normalize_key(key)?;
|
let key = normalize_key(key)?;
|
||||||
let cipher = <Aes128Gcm as AeadKeyInit>::new_from_slice(&key)
|
let cipher = <Aes128Gcm as AeadKeyInit>::new_from_slice(&key)
|
||||||
.map_err(|_| anyhow!("invalid AES-GCM key"))?;
|
.map_err(|_| anyhow!("invalid AES-GCM key"))?;
|
||||||
let nonce = Nonce::from_slice(&GCM_NONCE);
|
let nonce: Nonce<U12> = GCM_NONCE.into();
|
||||||
let mut buffer = plaintext.to_vec();
|
let mut buffer = plaintext.to_vec();
|
||||||
let tag = cipher
|
let tag = cipher
|
||||||
.encrypt_in_place_detached(nonce, GCM_AAD, &mut buffer)
|
.encrypt_inout_detached(&nonce, GCM_AAD, (&mut buffer[..]).into())
|
||||||
.map_err(|_| anyhow!("AES-GCM encryption failed"))?;
|
.map_err(|_| anyhow!("AES-GCM encryption failed"))?;
|
||||||
Ok(V2Encrypted {
|
Ok(V2Encrypted {
|
||||||
ciphertext: STANDARD.encode(buffer),
|
ciphertext: STANDARD.encode(buffer),
|
||||||
@@ -130,10 +132,13 @@ pub fn decrypt_v2(key: &str, ciphertext_b64: &str, tag_b64: &str) -> Result<Vec<
|
|||||||
let mut data = GREE_BASE64_DECODE
|
let mut data = GREE_BASE64_DECODE
|
||||||
.decode(ciphertext_b64)
|
.decode(ciphertext_b64)
|
||||||
.context("invalid GCM ciphertext")?;
|
.context("invalid GCM ciphertext")?;
|
||||||
let nonce = Nonce::from_slice(&GCM_NONCE);
|
let nonce: Nonce<U12> = GCM_NONCE.into();
|
||||||
let tag = GenericArray::from_slice(&tag_bytes);
|
let tag: &Tag = tag_bytes
|
||||||
|
.as_slice()
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| anyhow!("invalid GCM tag length"))?;
|
||||||
cipher
|
cipher
|
||||||
.decrypt_in_place_detached(nonce, GCM_AAD, &mut data, tag)
|
.decrypt_inout_detached(&nonce, GCM_AAD, (&mut data[..]).into(), tag)
|
||||||
.map_err(|_| anyhow!("AES-GCM authentication failed"))?;
|
.map_err(|_| anyhow!("AES-GCM authentication failed"))?;
|
||||||
// A few modules append 0xff filler bytes to decrypted JSON.
|
// A few modules append 0xff filler bytes to decrypted JSON.
|
||||||
data.retain(|byte| *byte != 0xff);
|
data.retain(|byte| *byte != 0xff);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use super::crypto::decrypt_v1;
|
use super::crypto::decrypt_v1;
|
||||||
use aes::{
|
use aes::{
|
||||||
cipher::{generic_array::GenericArray, BlockEncrypt, KeyInit},
|
cipher::{BlockCipherEncrypt, KeyInit},
|
||||||
Aes128,
|
Aes128, Block,
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, bail, Context, Result};
|
use anyhow::{anyhow, bail, Context, Result};
|
||||||
use base64::{engine::general_purpose::STANDARD, Engine as _};
|
use base64::{engine::general_purpose::STANDARD, Engine as _};
|
||||||
@@ -387,7 +387,8 @@ fn encrypt_cloud_api(plaintext: &[u8]) -> Result<String> {
|
|||||||
data.extend_from_slice(plaintext);
|
data.extend_from_slice(plaintext);
|
||||||
data.extend(std::iter::repeat(pad as u8).take(pad));
|
data.extend(std::iter::repeat(pad as u8).take(pad));
|
||||||
for block in data.chunks_exact_mut(16) {
|
for block in data.chunks_exact_mut(16) {
|
||||||
cipher.encrypt_block(GenericArray::from_mut_slice(block));
|
let block: &mut Block = block.try_into().expect("AES block is 16 bytes");
|
||||||
|
cipher.encrypt_block(block);
|
||||||
}
|
}
|
||||||
Ok(STANDARD.encode(data))
|
Ok(STANDARD.encode(data))
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-9
@@ -14,7 +14,6 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use anyhow::{anyhow, bail, Context, Result};
|
use anyhow::{anyhow, bail, Context, Result};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use rand::Rng;
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
use std::{
|
use std::{
|
||||||
@@ -1072,8 +1071,7 @@ impl GreeCloudProvider {
|
|||||||
} else {
|
} else {
|
||||||
(encrypt_v1(key, &plaintext)?, None)
|
(encrypt_v1(key, &plaintext)?, None)
|
||||||
};
|
};
|
||||||
let cid = rand::thread_rng()
|
let cid = rand::random_range(1_000_000_000_u64..=9_999_999_999_u64)
|
||||||
.gen_range(1_000_000_000_u64..=9_999_999_999_u64)
|
|
||||||
.to_string();
|
.to_string();
|
||||||
let request_kind = inner_payload
|
let request_kind = inner_payload
|
||||||
.get("t")
|
.get("t")
|
||||||
@@ -2047,7 +2045,7 @@ pub async fn cloud_reconnect_loop(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let base = (1_u64 << attempt.min(6)).min(60);
|
let base = (1_u64 << attempt.min(6)).min(60);
|
||||||
let jitter = rand::thread_rng().gen_range(0..=base.min(10));
|
let jitter = rand::random_range(0..=base.min(10));
|
||||||
sleep(Duration::from_secs(base + jitter)).await;
|
sleep(Duration::from_secs(base + jitter)).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2056,6 +2054,11 @@ pub async fn cloud_reconnect_loop(
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
fn test_http_client() -> reqwest::Client {
|
||||||
|
crate::install_rustls_crypto_provider();
|
||||||
|
reqwest::Client::new()
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn status_parser_rejects_malformed_column_count() {
|
fn status_parser_rejects_malformed_column_count() {
|
||||||
assert!(properties_from_payload(&json!({"t":"dat","cols":["Pow"],"dat":[]})).is_err());
|
assert!(properties_from_payload(&json!({"t":"dat","cols":["Pow"],"dat":[]})).is_err());
|
||||||
@@ -2151,7 +2154,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn mqtt_payload_is_ignored_after_all_cloud_devices_are_removed() {
|
async fn mqtt_payload_is_ignored_after_all_cloud_devices_are_removed() {
|
||||||
let provider = GreeCloudProvider::new(reqwest::Client::new());
|
let provider = GreeCloudProvider::new(test_http_client());
|
||||||
let result = provider
|
let result = provider
|
||||||
.handle_raw_message("status/stale-parent/device", b"not-json-anymore")
|
.handle_raw_message("status/stale-parent/device", b"not-json-anymore")
|
||||||
.await;
|
.await;
|
||||||
@@ -2160,7 +2163,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn mqtt_payload_for_unknown_parent_still_errors_when_devices_are_registered() {
|
async fn mqtt_payload_for_unknown_parent_still_errors_when_devices_are_registered() {
|
||||||
let provider = GreeCloudProvider::new(reqwest::Client::new());
|
let provider = GreeCloudProvider::new(test_http_client());
|
||||||
provider.inner.registered.write().await.insert(
|
provider.inner.registered.write().await.insert(
|
||||||
"AABBCCDDEEFF".into(),
|
"AABBCCDDEEFF".into(),
|
||||||
RegisteredDevice {
|
RegisteredDevice {
|
||||||
@@ -2190,7 +2193,7 @@ mod tests {
|
|||||||
None,
|
None,
|
||||||
Arc::new(AtomicBool::new(false)),
|
Arc::new(AtomicBool::new(false)),
|
||||||
);
|
);
|
||||||
let providers = ProviderDispatcher::new(local, reqwest::Client::new());
|
let providers = ProviderDispatcher::new(local, test_http_client());
|
||||||
let mut device = Device::simulated_default();
|
let mut device = Device::simulated_default();
|
||||||
device.connection_type = ConnectionType::Local;
|
device.connection_type = ConnectionType::Local;
|
||||||
assert_eq!(providers.provider_name(&device), "local");
|
assert_eq!(providers.provider_name(&device), "local");
|
||||||
@@ -2200,7 +2203,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn cloud_provider_rejects_local_device_before_network_io() {
|
async fn cloud_provider_rejects_local_device_before_network_io() {
|
||||||
let provider = GreeCloudProvider::new(reqwest::Client::new());
|
let provider = GreeCloudProvider::new(test_http_client());
|
||||||
let device = Device::simulated_default();
|
let device = Device::simulated_default();
|
||||||
let error = provider.register_device(&device).await.unwrap_err();
|
let error = provider.register_device(&device).await.unwrap_err();
|
||||||
assert!(error.to_string().contains("Local device"));
|
assert!(error.to_string().contains("Local device"));
|
||||||
@@ -2242,7 +2245,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn cloud_command_order_matches_reference() {
|
async fn cloud_command_order_matches_reference() {
|
||||||
let provider = GreeCloudProvider::new(reqwest::Client::new());
|
let provider = GreeCloudProvider::new(test_http_client());
|
||||||
let mut device = Device::simulated_default();
|
let mut device = Device::simulated_default();
|
||||||
device.id = "cloud-test".into();
|
device.id = "cloud-test".into();
|
||||||
device.connection_type = ConnectionType::GreeCloud;
|
device.connection_type = ConnectionType::GreeCloud;
|
||||||
|
|||||||
Reference in New Issue
Block a user