v0.14.12
This commit is contained in:
Generated
+1
-1
@@ -700,7 +700,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "gree-controller"
|
||||
version = "0.14.11"
|
||||
version = "0.14.12"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"aes-gcm",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "gree-controller"
|
||||
version = "0.14.11"
|
||||
version = "0.14.12"
|
||||
edition = "2021"
|
||||
authors = ["GREE Controller contributors"]
|
||||
description = "Standalone local GREE HVAC controller with Web UI, SQLite and Home Assistant sensor support"
|
||||
|
||||
+21
-21
@@ -1,14 +1,14 @@
|
||||
d67af429e4da9ce08e9d2f2a8472849ffbd70d135b1c5da535a076026794d04c ./.env.example
|
||||
a4ec3874a2e3ab1bad28fb40bb620f7b01f64d01ad9b699306bf70ada31227db ./.gitignore
|
||||
c9a8dafdb9328539fd9372533794010ed8870d0ccf0207e722a0dc02cc01cdfe ./Cargo.lock
|
||||
b4f4da4922f2c08642dfd41f6f0d99889ebe7b2c6437e48985cb2d7bb573feca ./Cargo.toml
|
||||
9f50e09694de525ba281e9a2632794331cb5002265a47da3644e2efdd335b591 ./Cargo.lock
|
||||
b10ec633e8c0845e5b31cd193366f700b067081887594910e02617db49cb1d6e ./Cargo.toml
|
||||
19b2943504acb8f8de280f873a8dbec4bb6ebbe3870b158f5655d4fb8c298f5f ./LICENSE
|
||||
d4779b55a4e485344cbea50f413de7fd4624d85b2487d6a88ac448ea51ea2439 ./README.md
|
||||
721e840e5ef62b61e4be0a1c4a97ac1af97e0220305c8763b84b18b46443d8ab ./SOURCE_MANIFEST.sha256
|
||||
70ca0a29454ccb569a7b15f9792d98d9b8d860d223052cf28d9ef4b3475a494e ./README.md
|
||||
53e0a751210bfd29d1cb8570dad2ed914ff11877fe0270adda064d8b3434f5e8 ./SOURCE_MANIFEST.sha256
|
||||
5302570299af2c2650bada12e123f598c5db8009949c75761385f73ed57343c5 ./build.rs
|
||||
0aeab38e1f3fc7fc126c625ac8ece370048da132411c3aed1bf4427a747befc6 ./docs/API.md
|
||||
25d1afb075e70422aea5ad4c8921fdf19389f6322b88fcd8f6e6a679fe4c4946 ./docs/API.md
|
||||
f21d732eb1147f8f3167d2172cdf0b57e61edabdfecbaf97811d46c5bff7e47a ./docs/FLOW.md
|
||||
91491953a94cdb4a573eab300b1c49b710df11467cb6e725427abbed22e61b64 ./docs/openapi.json
|
||||
a86b1622971abb0a713cc1311b4f74f8711a754bedddff81fe5111f477688ad0 ./docs/openapi.json
|
||||
c65aa543d2e99f8f7d52736307b07ebd182597d80124661d53a16bb23f6f1118 ./ha-addon/.env.example
|
||||
a18d2460340264d34c267fa704ee51a42e59bcc1783ee4c0dbb2a8ef42fa0f16 ./ha-addon/Dockerfile
|
||||
0417c88a990c72aecf071fba64d5d9da65dcda4d396cd7565477f7a4532c8c5e ./ha-addon/README.md
|
||||
@@ -22,7 +22,7 @@ b7f0873109c52be9d7f09bea3dffc416103c50085e1f0680d11661a969479898 ./ha-addon/hom
|
||||
41a8958a6fe6d10e5679c95ac34832583a2a15ecfd67d09b4e094a83d06f5c47 ./ha-addon/home-assistant/custom_components/gree_controller/coordinator.py
|
||||
5a96fe8f5c035c34f1339370270cd078056202d09e236dec75735be11de92a7d ./ha-addon/home-assistant/custom_components/gree_controller/entity_map.py
|
||||
c4fb75c246db651087900ebfc2291ff41ac87652cd6194fc0b776b0005c1cbcf ./ha-addon/home-assistant/custom_components/gree_controller/icon.png
|
||||
67147cb87c2a641385e02d7fa99237a3d590c4f305511eb04e422bfd539ef3dc ./ha-addon/home-assistant/custom_components/gree_controller/manifest.json
|
||||
9e90c948024ccafced975a147da079d1f65433e1b04d5ee0a0427f243e14ead8 ./ha-addon/home-assistant/custom_components/gree_controller/manifest.json
|
||||
c52a484b671ce738ecc00228a1db19a5d703f69ab27530c2896a5c2ae3b4a96f ./ha-addon/home-assistant/custom_components/gree_controller/number.py
|
||||
39c4309001b75abb56234f05662bc06e077054986876f1927937edbce528ec95 ./ha-addon/home-assistant/custom_components/gree_controller/select.py
|
||||
cca65482e36d48035aca178121a378fe7d578d600acff267ae81a6399c0da653 ./ha-addon/home-assistant/custom_components/gree_controller/sensor.py
|
||||
@@ -30,21 +30,21 @@ cca65482e36d48035aca178121a378fe7d578d600acff267ae81a6399c0da653 ./ha-addon/hom
|
||||
6bddb7b4620021ecd2099a86a77ef5c7f2c2dcd3d07d5db4e7b4c4ce6d3e8c03 ./ha-addon/home-assistant/custom_components/gree_controller/translations/en.json
|
||||
13f30e2dcdcedbd1b6c3f99c2335e0487108fd72c8e86922368b84f2fa2038ae ./ha-addon/home-assistant/custom_components/gree_controller/translations/pl.json
|
||||
c5fc5c87273d82d2834a0a5a365c821a416413ed509613441e24e4dc3507c4d2 ./ha-addon/home-assistant/generated/gree_controller_entities.example.json
|
||||
9ca650cd8994d2de0ac0a8827c1f5db50f5b2c144e1f030d9078a7fa392cf470 ./ha-addon/repository/gree-controller/CHANGELOG.md
|
||||
3c06bd11671452ea6472afd5543fb91a39aba73a1d2d95c7762c04f94ab64030 ./ha-addon/repository/gree-controller/DOCS.md
|
||||
ac8d7b7d0171dd9527654ffd29e659046f862c65bb52a4d0d2f5ff78b47500cd ./ha-addon/repository/gree-controller/CHANGELOG.md
|
||||
93f82db18021aad642d7e37c30983460a7f654b72f6c5984a82b7d3fd58e0a7d ./ha-addon/repository/gree-controller/DOCS.md
|
||||
c3db302f38d26dc9f8caf37a1a8a07a1334cc07ae301d452f2940a5ec5915719 ./ha-addon/repository/gree-controller/README.md
|
||||
a07b8c3d2afac7d80ccbd8c0c1673eb575c3658fe6bf0509200a3c2a1619293e ./ha-addon/repository/gree-controller/config.yaml
|
||||
37515b63be1acd3d8ce68011e11cbed0e89f4d03f879640edb75d4c41f48fe3c ./ha-addon/repository/gree-controller/config.yaml
|
||||
3aae6cdae4c3aaab7786a9575e7093b7e2c5b69288167075f4b7475611691a6b ./ha-addon/repository/gree-controller/topologia-ha-vlan-gree-pl.png
|
||||
0d0b42a7639b128946eec379175436fa1f150294f39d2dfd169077bfa87fd14d ./ha-addon/repository/gree-controller/topology-ha-vlan-gree-en.png
|
||||
d13e4c2b993d209078342c0c86d852b300692089b377aa044f811308dd188a1e ./ha-addon/repository/gree-controller/translations/en.yaml
|
||||
9cf50879d7ea32cd3ff7ee95a6d50c4f1eab727420bc6610282931a9117e7dde ./ha-addon/repository/gree-controller/translations/pl.yaml
|
||||
2153b230357aab4766398577e23a7a9ff83bb135ddc86d1b3f2cbfc852efe0a1 ./ha-addon/repository/repository.yaml
|
||||
c123b190219556382f0e7f3058056fb233f6261f257a01eceb96a2c0bbfa12f3 ./ha-addon/run.sh
|
||||
e8a77dbdb98c6ebcfbe6a08b0b5546178d965f25496c19f7aebaff287630838e ./ha-addon/run.sh
|
||||
081e27b6e43070d44f865335c30a42a5a29668eaa6a5ea5ab6967ac4447b8e06 ./ha-addon/sync-repository.sh
|
||||
f9e31de3d109ead32bf531c074d46a087df398d62488caee0b46b5e0a1c027f7 ./ha_addon.md
|
||||
253a0bc912786e67ea7fc92a64e4a510ad973bec343a88ccfb1f28fca3e8cf01 ./lang/README.md
|
||||
6d4f8efd56c36cac8c4f127a12d514e364cec86038bbe0fb2135961b7223d22c ./lang/en.json
|
||||
e70c1f6ef69f4f183626fa872248652e1eae6a9d677cdd2b294bd6c19ef52190 ./lang/pl.json
|
||||
e808dc4a0ea74744fc55cdcae160a536b5f0f466540c00c477bdc9388d7ef847 ./lang/en.json
|
||||
f13b3706e56f785e539359009febef3441546f62bb94dde8e6c5dfb717d0f741 ./lang/pl.json
|
||||
d8459024f04ca514bd8e9d6bd3af872fb942fd85a7cdd5583f4a9d28aab6faba ./make_zip.py
|
||||
b14233a8987e53bbbdd6770386ba10fa166ec25c1e098275c173c544b37846fc ./presets/bedroom_window_night.json
|
||||
1960841119c0b673fb2f03621b32237552fd828045304cd221401214b997c910 ./presets/device_resilience.json
|
||||
@@ -85,7 +85,7 @@ fdcd9a5055d08037278b842e7ab69265345c5811f0a06867136c511d140bb191 ./presets/wind
|
||||
804f22123cd3e8db0fac791826c8dd9f758fb866c8e3b5655fb6d25d259dccf1 ./presets/workday_comfort.json
|
||||
01952aa92b217f8eae2493b88870e2dec595100cd15c4d561ff11ae2b936c46f ./regenerate-sha.sh
|
||||
c64b1c6deeb24f20af662bfce7fa3683703914987241107ce664fa2f6d1a9dcb ./scripts/README.md
|
||||
d4bbad174adb471745c5b09d234d02db65405444c20ed15be94524b44a2c5b76 ./scripts/api_dev_test.py
|
||||
ca47f462f0df056191a8d71eff74179762584a864f3d43d68140714598a88885 ./scripts/api_dev_test.py
|
||||
5bc736c7bc76ca80aaa406bb171d2aa91baf4c3aa8695dce0e09b888b6ab3146 ./scripts/common.sh
|
||||
6403786610ee6d2f628193c25aee0dd058d62e904aa1a31d5f62fdaae0e94b4f ./scripts/configure-gree-network.sh
|
||||
1d6e14e26e49aa9d3527f30a23668bf8d9c48b67e6628ef686c3155c012155de ./scripts/dev.sh
|
||||
@@ -102,7 +102,7 @@ b50782b3742dfbf8a319c60571c968e93fdf8547db747c759edcffae68cb98bf ./scripts/upda
|
||||
3dfd1e053cbfa0d684dd88cf99b244a96a36e2ff23d2a0715b8327ab62258254 ./src/api/assets.rs
|
||||
05c255919f7b3d81188fc5f1410be6a0037471dfc44e93bffb009f29a1e6a3fc ./src/api/auth.rs
|
||||
9e4fc675306e111ed3db7af9822e2925d88109c31b9e309851665a975c0bd83c ./src/api/automations.rs
|
||||
11f4cbe485047dd3b723149d6cdae3f03232ae3d4c8a0c62fccaedb1eadfcf2c ./src/api/configuration.rs
|
||||
c031fa7e9c6fc29ed9cdbd8150621111c1fd26e652d0c8e072811dfaeaaa2a19 ./src/api/configuration.rs
|
||||
19bc141286a336ad67e99079496eb0ae5126f986ab28be62b5f97758e5f6969c ./src/api/debug_tokens.rs
|
||||
32ade46ec45d6faf7852242b9f5ba1be6eacbacbeb33d2deabfab59bf1610ce0 ./src/api/device_groups.rs
|
||||
fcbb3da0538aab451f71810f829cc248d6bb67e586dc418d71a572980583823d ./src/api/devices.rs
|
||||
@@ -115,9 +115,9 @@ e8edfbb725d6de650442444b0a929ad2be0bd2c2d7d227d2b3fdd99d05c94f94 ./src/api/hous
|
||||
371b719cb8883c94ebe7de3b222daad503957bbff6589b19ba27595963972f1c ./src/api/integrations.rs
|
||||
6bfbe5135d4f93bd8d19a707877b53ed2029fd8490b4b1954a7520888fb1d664 ./src/api/middleware.rs
|
||||
45e34a447ff384d99a3c42c489ca9fa75849c74d4d246caa91c63d927de17396 ./src/api/openapi.rs
|
||||
4feca416de6ce8acc34082f432721016b109c7e6e70116e5e0b710ea403c7006 ./src/api/public_settings.rs
|
||||
736a5396644b65f44cbb25dbc873b8a41673a479795c4988519cf84ef175aca8 ./src/api/public_settings.rs
|
||||
5b29f2e5aa2c422c5829ef89c7b59cf753883aa7f60661c95ab0f95cf676fa3f ./src/api/schedules.rs
|
||||
513743ac7752d92f16213099d1fca6431759f2cd05a8a12f4ee1226cfd1637b3 ./src/api/settings.rs
|
||||
10164f2357a23d63f22adf66e94f52dbb3df5edcb60d7bd5195e6d396e3eb1d8 ./src/api/settings.rs
|
||||
1c1fe39aec55d10608ca3db83827855b07249cd1a81ae054eb1ee6464514092b ./src/api/system.rs
|
||||
9118a5a3a381b010e22d646498ff56d2e05f51656789682cc4371b09c384aa98 ./src/api/websocket.rs
|
||||
ddd1bfc8625b66f6e5f3d24b3122ac86c25f89b0af527e3dfce9102551a8f142 ./src/api/zones.rs
|
||||
@@ -156,7 +156,7 @@ b0189f28d0f337dfd3ce0934da7a565e4a5535afc1c242214c26ed584b3b7840 ./src/engine/t
|
||||
c89ff36c6a67bf4fbf68c43e18aa0a556de2dc69263fd79db376363afc741a4f ./src/engine/zone_actions.rs
|
||||
3a7fada1f6dd9ebab4026b353f41b21d8ca19342b02538c711dbb2dfb599cbe7 ./src/engine/zone_control.rs
|
||||
bfac95cec87f0df6ce562153cd3cfe6731359d703e6c592d2c2f7ba01ea62d99 ./src/error.rs
|
||||
10271a141ec441964c66d5732155abda8993d9fcba8dc0cc77e7c35d5a40e466 ./src/home_assistant.rs
|
||||
26c7617b99a5a46e9afb15d317af4c804d16806dd6fcd3c8a9301c193884b1f2 ./src/home_assistant.rs
|
||||
e78ca9aff23362971eb6450534ea21bdc15150456c378ef9b226cb93a8dbc612 ./src/influxdb.rs
|
||||
da4068295f37c23222bb13bebac022d88ba7729604a49ad25438c55e45458a49 ./src/influxdb/codec.rs
|
||||
b96624fa34b218a6d5f028ba09579633f6f8a04c109f0e94801e8d89ceeeb4b5 ./src/influxdb/query.rs
|
||||
@@ -171,7 +171,7 @@ aeab5b5acf35d38a54fd1d82e964fe56635ade69c0149ad423df317095d01555 ./src/models/f
|
||||
ba5d359e4d6c12d9f62c1b28bdfb40d312737930df5421814f5310f7183e96c1 ./src/models/history.rs
|
||||
110b73c179ea1f85b7afa14f4cdcfd9b8232dd005a6417cf357b8efc73e702c0 ./src/models/integrations.rs
|
||||
f1359b68f1d041cd441f80429e77893eeb6f6194613b58fd3e7a212fb511db3e ./src/models/runtime.rs
|
||||
f8bd9b4106145ebcf20d003471bb54a329e7373cf14a3a712ecabf87ac59d6d3 ./src/models/settings_api.rs
|
||||
527bea024c76d8025fa8f7c4dbf2c6067cbdff8103ebe9763033eeea4accf788 ./src/models/settings_api.rs
|
||||
c4de6101de85d9d7e6814b2504b87d9216561e3d9e274054f081f505fb152140 ./src/models/temporary_thermostat.rs
|
||||
bc2818ce8d0dae1edfb1b98e5d1c00b193f03eeaa28e343d3532f6023288738c ./src/models/zone.rs
|
||||
62e696df8b86835df7ad127f03c257a78580769dc82bc66daa5041f71e8440a5 ./src/notifications.rs
|
||||
@@ -216,8 +216,8 @@ b08b0fe301642d1daa084b322a02e351d284d2465231505d45079a52ccb4028f ./web/js/flows
|
||||
6bb9386707dcf601111fea15a1a366d8798313b973ca1624878618f4c3095add ./web/js/navigation.js
|
||||
799613c6d465cb2f92ecb57cb082d0c33729a03d88ab4ca7fa12a3cbd7e38e75 ./web/js/realtime.js
|
||||
9546ca5c5566994aff3c33d92295be46b65d51d874681764abe77470dc9c9c73 ./web/js/router.js
|
||||
195e8a2ec5faa3da28e0c38e1eff429744139cb6fb859748cd931fb34378d4b4 ./web/js/select-ui.js
|
||||
c48b6101b203b40832976532d2f9c9633c0eaaf3b06cca43a0cfce1531a2b006 ./web/js/settings-ui.js
|
||||
c2710fd9c1f2b31878c1e25ceb02d74ae30456c1bbb400e69fcf7619ecc72bc2 ./web/js/select-ui.js
|
||||
7d3be06768e30884839aec682f55c5cb8085e464aa2fc389ac6ac9ed7a7639d3 ./web/js/settings-ui.js
|
||||
f00c3f603eb314f755a0c46424681b579e0b890453e2550007c719273815147c ./web/js/settings.js
|
||||
3815fea7ae1694568c2f249bc8460e0563ced6bde89214f74f21b41fe8cad9a6 ./web/lang-init.js
|
||||
6b653e4fe2d4db4ffae6ff8f39b8ce57a10a990dc0000ee4aae51d949afadd52 ./web/manifest.webmanifest
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
Self-hosted controller for GREE-compatible air conditioners with a local Web UI, thermostat zones, schedules, Home Assistant integration, history, notifications and a documented HTTP/WebSocket API.
|
||||
|
||||
**Version: 0.14.11**
|
||||
**Version: 0.14.12**
|
||||
|
||||
Version 0.14.11 replaces font-dependent Unicode UI icons with a shared inline SVG set across navigation, dialogs, Flow, charts, controls and event categories for consistent rendering across Android, iOS and desktop browsers. It also includes the 0.14.10 full-width settings layout fix.
|
||||
Version 0.14.12 adds Home Assistant Supervisor authentication for the packaged HA add-on and fixes mouse hover/click selection in custom dropdowns opened inside modal dialogs. The add-on uses the Supervisor Core API proxy and runtime `SUPERVISOR_TOKEN` automatically, while standalone installations keep the existing manual Home Assistant URL and Long-Lived Access Token configuration.
|
||||
|
||||
> [Full API reference](docs/API.md) — authentication, every endpoint, request bodies, response models, WebSocket events and examples.
|
||||
|
||||
@@ -281,7 +281,9 @@ There are two independent Home Assistant directions.
|
||||
|
||||
### 1. Home Assistant as a temperature source
|
||||
|
||||
Configure **Home Assistant / Sensors** in the Web UI or use:
|
||||
In the Home Assistant add-on, the connection to Home Assistant Core is automatic through the Supervisor API proxy; no Home Assistant URL or Long-Lived Access Token is required.
|
||||
|
||||
For standalone installations, configure **Home Assistant / Sensors** in the Web UI or use:
|
||||
|
||||
```text
|
||||
HA_URL=
|
||||
@@ -291,7 +293,7 @@ HA_SENSOR_STALE_AFTER_SECONDS=300
|
||||
HA_ALLOW_INVALID_TLS=false
|
||||
```
|
||||
|
||||
The Home Assistant connection test checks only `HA_URL` and `HA_TOKEN`; no entity is required. `HA_OUTDOOR_ENTITY_ID` is the optional global outdoor-temperature sensor. Per zone, `sensor_source` can be:
|
||||
In standalone mode, the Home Assistant connection test checks only `HA_URL` and `HA_TOKEN`; no entity is required. `HA_OUTDOOR_ENTITY_ID` is the optional global outdoor-temperature sensor. Per zone, `sensor_source` can be:
|
||||
|
||||
- `device` — GREE indoor sensor,
|
||||
- `home_assistant` — Home Assistant room sensor,
|
||||
|
||||
+20
-20
@@ -1,13 +1,13 @@
|
||||
d67af429e4da9ce08e9d2f2a8472849ffbd70d135b1c5da535a076026794d04c ./.env.example
|
||||
a4ec3874a2e3ab1bad28fb40bb620f7b01f64d01ad9b699306bf70ada31227db ./.gitignore
|
||||
c9a8dafdb9328539fd9372533794010ed8870d0ccf0207e722a0dc02cc01cdfe ./Cargo.lock
|
||||
b4f4da4922f2c08642dfd41f6f0d99889ebe7b2c6437e48985cb2d7bb573feca ./Cargo.toml
|
||||
9f50e09694de525ba281e9a2632794331cb5002265a47da3644e2efdd335b591 ./Cargo.lock
|
||||
b10ec633e8c0845e5b31cd193366f700b067081887594910e02617db49cb1d6e ./Cargo.toml
|
||||
19b2943504acb8f8de280f873a8dbec4bb6ebbe3870b158f5655d4fb8c298f5f ./LICENSE
|
||||
d4779b55a4e485344cbea50f413de7fd4624d85b2487d6a88ac448ea51ea2439 ./README.md
|
||||
70ca0a29454ccb569a7b15f9792d98d9b8d860d223052cf28d9ef4b3475a494e ./README.md
|
||||
5302570299af2c2650bada12e123f598c5db8009949c75761385f73ed57343c5 ./build.rs
|
||||
0aeab38e1f3fc7fc126c625ac8ece370048da132411c3aed1bf4427a747befc6 ./docs/API.md
|
||||
25d1afb075e70422aea5ad4c8921fdf19389f6322b88fcd8f6e6a679fe4c4946 ./docs/API.md
|
||||
f21d732eb1147f8f3167d2172cdf0b57e61edabdfecbaf97811d46c5bff7e47a ./docs/FLOW.md
|
||||
91491953a94cdb4a573eab300b1c49b710df11467cb6e725427abbed22e61b64 ./docs/openapi.json
|
||||
a86b1622971abb0a713cc1311b4f74f8711a754bedddff81fe5111f477688ad0 ./docs/openapi.json
|
||||
c65aa543d2e99f8f7d52736307b07ebd182597d80124661d53a16bb23f6f1118 ./ha-addon/.env.example
|
||||
a18d2460340264d34c267fa704ee51a42e59bcc1783ee4c0dbb2a8ef42fa0f16 ./ha-addon/Dockerfile
|
||||
0417c88a990c72aecf071fba64d5d9da65dcda4d396cd7565477f7a4532c8c5e ./ha-addon/README.md
|
||||
@@ -21,7 +21,7 @@ b7f0873109c52be9d7f09bea3dffc416103c50085e1f0680d11661a969479898 ./ha-addon/hom
|
||||
41a8958a6fe6d10e5679c95ac34832583a2a15ecfd67d09b4e094a83d06f5c47 ./ha-addon/home-assistant/custom_components/gree_controller/coordinator.py
|
||||
5a96fe8f5c035c34f1339370270cd078056202d09e236dec75735be11de92a7d ./ha-addon/home-assistant/custom_components/gree_controller/entity_map.py
|
||||
c4fb75c246db651087900ebfc2291ff41ac87652cd6194fc0b776b0005c1cbcf ./ha-addon/home-assistant/custom_components/gree_controller/icon.png
|
||||
67147cb87c2a641385e02d7fa99237a3d590c4f305511eb04e422bfd539ef3dc ./ha-addon/home-assistant/custom_components/gree_controller/manifest.json
|
||||
9e90c948024ccafced975a147da079d1f65433e1b04d5ee0a0427f243e14ead8 ./ha-addon/home-assistant/custom_components/gree_controller/manifest.json
|
||||
c52a484b671ce738ecc00228a1db19a5d703f69ab27530c2896a5c2ae3b4a96f ./ha-addon/home-assistant/custom_components/gree_controller/number.py
|
||||
39c4309001b75abb56234f05662bc06e077054986876f1927937edbce528ec95 ./ha-addon/home-assistant/custom_components/gree_controller/select.py
|
||||
cca65482e36d48035aca178121a378fe7d578d600acff267ae81a6399c0da653 ./ha-addon/home-assistant/custom_components/gree_controller/sensor.py
|
||||
@@ -29,21 +29,21 @@ cca65482e36d48035aca178121a378fe7d578d600acff267ae81a6399c0da653 ./ha-addon/hom
|
||||
6bddb7b4620021ecd2099a86a77ef5c7f2c2dcd3d07d5db4e7b4c4ce6d3e8c03 ./ha-addon/home-assistant/custom_components/gree_controller/translations/en.json
|
||||
13f30e2dcdcedbd1b6c3f99c2335e0487108fd72c8e86922368b84f2fa2038ae ./ha-addon/home-assistant/custom_components/gree_controller/translations/pl.json
|
||||
c5fc5c87273d82d2834a0a5a365c821a416413ed509613441e24e4dc3507c4d2 ./ha-addon/home-assistant/generated/gree_controller_entities.example.json
|
||||
9ca650cd8994d2de0ac0a8827c1f5db50f5b2c144e1f030d9078a7fa392cf470 ./ha-addon/repository/gree-controller/CHANGELOG.md
|
||||
3c06bd11671452ea6472afd5543fb91a39aba73a1d2d95c7762c04f94ab64030 ./ha-addon/repository/gree-controller/DOCS.md
|
||||
ac8d7b7d0171dd9527654ffd29e659046f862c65bb52a4d0d2f5ff78b47500cd ./ha-addon/repository/gree-controller/CHANGELOG.md
|
||||
93f82db18021aad642d7e37c30983460a7f654b72f6c5984a82b7d3fd58e0a7d ./ha-addon/repository/gree-controller/DOCS.md
|
||||
c3db302f38d26dc9f8caf37a1a8a07a1334cc07ae301d452f2940a5ec5915719 ./ha-addon/repository/gree-controller/README.md
|
||||
a07b8c3d2afac7d80ccbd8c0c1673eb575c3658fe6bf0509200a3c2a1619293e ./ha-addon/repository/gree-controller/config.yaml
|
||||
37515b63be1acd3d8ce68011e11cbed0e89f4d03f879640edb75d4c41f48fe3c ./ha-addon/repository/gree-controller/config.yaml
|
||||
3aae6cdae4c3aaab7786a9575e7093b7e2c5b69288167075f4b7475611691a6b ./ha-addon/repository/gree-controller/topologia-ha-vlan-gree-pl.png
|
||||
0d0b42a7639b128946eec379175436fa1f150294f39d2dfd169077bfa87fd14d ./ha-addon/repository/gree-controller/topology-ha-vlan-gree-en.png
|
||||
d13e4c2b993d209078342c0c86d852b300692089b377aa044f811308dd188a1e ./ha-addon/repository/gree-controller/translations/en.yaml
|
||||
9cf50879d7ea32cd3ff7ee95a6d50c4f1eab727420bc6610282931a9117e7dde ./ha-addon/repository/gree-controller/translations/pl.yaml
|
||||
2153b230357aab4766398577e23a7a9ff83bb135ddc86d1b3f2cbfc852efe0a1 ./ha-addon/repository/repository.yaml
|
||||
c123b190219556382f0e7f3058056fb233f6261f257a01eceb96a2c0bbfa12f3 ./ha-addon/run.sh
|
||||
e8a77dbdb98c6ebcfbe6a08b0b5546178d965f25496c19f7aebaff287630838e ./ha-addon/run.sh
|
||||
081e27b6e43070d44f865335c30a42a5a29668eaa6a5ea5ab6967ac4447b8e06 ./ha-addon/sync-repository.sh
|
||||
f9e31de3d109ead32bf531c074d46a087df398d62488caee0b46b5e0a1c027f7 ./ha_addon.md
|
||||
253a0bc912786e67ea7fc92a64e4a510ad973bec343a88ccfb1f28fca3e8cf01 ./lang/README.md
|
||||
6d4f8efd56c36cac8c4f127a12d514e364cec86038bbe0fb2135961b7223d22c ./lang/en.json
|
||||
e70c1f6ef69f4f183626fa872248652e1eae6a9d677cdd2b294bd6c19ef52190 ./lang/pl.json
|
||||
e808dc4a0ea74744fc55cdcae160a536b5f0f466540c00c477bdc9388d7ef847 ./lang/en.json
|
||||
f13b3706e56f785e539359009febef3441546f62bb94dde8e6c5dfb717d0f741 ./lang/pl.json
|
||||
d8459024f04ca514bd8e9d6bd3af872fb942fd85a7cdd5583f4a9d28aab6faba ./make_zip.py
|
||||
b14233a8987e53bbbdd6770386ba10fa166ec25c1e098275c173c544b37846fc ./presets/bedroom_window_night.json
|
||||
1960841119c0b673fb2f03621b32237552fd828045304cd221401214b997c910 ./presets/device_resilience.json
|
||||
@@ -84,7 +84,7 @@ fdcd9a5055d08037278b842e7ab69265345c5811f0a06867136c511d140bb191 ./presets/wind
|
||||
804f22123cd3e8db0fac791826c8dd9f758fb866c8e3b5655fb6d25d259dccf1 ./presets/workday_comfort.json
|
||||
01952aa92b217f8eae2493b88870e2dec595100cd15c4d561ff11ae2b936c46f ./regenerate-sha.sh
|
||||
c64b1c6deeb24f20af662bfce7fa3683703914987241107ce664fa2f6d1a9dcb ./scripts/README.md
|
||||
d4bbad174adb471745c5b09d234d02db65405444c20ed15be94524b44a2c5b76 ./scripts/api_dev_test.py
|
||||
ca47f462f0df056191a8d71eff74179762584a864f3d43d68140714598a88885 ./scripts/api_dev_test.py
|
||||
5bc736c7bc76ca80aaa406bb171d2aa91baf4c3aa8695dce0e09b888b6ab3146 ./scripts/common.sh
|
||||
6403786610ee6d2f628193c25aee0dd058d62e904aa1a31d5f62fdaae0e94b4f ./scripts/configure-gree-network.sh
|
||||
1d6e14e26e49aa9d3527f30a23668bf8d9c48b67e6628ef686c3155c012155de ./scripts/dev.sh
|
||||
@@ -101,7 +101,7 @@ b50782b3742dfbf8a319c60571c968e93fdf8547db747c759edcffae68cb98bf ./scripts/upda
|
||||
3dfd1e053cbfa0d684dd88cf99b244a96a36e2ff23d2a0715b8327ab62258254 ./src/api/assets.rs
|
||||
05c255919f7b3d81188fc5f1410be6a0037471dfc44e93bffb009f29a1e6a3fc ./src/api/auth.rs
|
||||
9e4fc675306e111ed3db7af9822e2925d88109c31b9e309851665a975c0bd83c ./src/api/automations.rs
|
||||
11f4cbe485047dd3b723149d6cdae3f03232ae3d4c8a0c62fccaedb1eadfcf2c ./src/api/configuration.rs
|
||||
c031fa7e9c6fc29ed9cdbd8150621111c1fd26e652d0c8e072811dfaeaaa2a19 ./src/api/configuration.rs
|
||||
19bc141286a336ad67e99079496eb0ae5126f986ab28be62b5f97758e5f6969c ./src/api/debug_tokens.rs
|
||||
32ade46ec45d6faf7852242b9f5ba1be6eacbacbeb33d2deabfab59bf1610ce0 ./src/api/device_groups.rs
|
||||
fcbb3da0538aab451f71810f829cc248d6bb67e586dc418d71a572980583823d ./src/api/devices.rs
|
||||
@@ -114,9 +114,9 @@ e8edfbb725d6de650442444b0a929ad2be0bd2c2d7d227d2b3fdd99d05c94f94 ./src/api/hous
|
||||
371b719cb8883c94ebe7de3b222daad503957bbff6589b19ba27595963972f1c ./src/api/integrations.rs
|
||||
6bfbe5135d4f93bd8d19a707877b53ed2029fd8490b4b1954a7520888fb1d664 ./src/api/middleware.rs
|
||||
45e34a447ff384d99a3c42c489ca9fa75849c74d4d246caa91c63d927de17396 ./src/api/openapi.rs
|
||||
4feca416de6ce8acc34082f432721016b109c7e6e70116e5e0b710ea403c7006 ./src/api/public_settings.rs
|
||||
736a5396644b65f44cbb25dbc873b8a41673a479795c4988519cf84ef175aca8 ./src/api/public_settings.rs
|
||||
5b29f2e5aa2c422c5829ef89c7b59cf753883aa7f60661c95ab0f95cf676fa3f ./src/api/schedules.rs
|
||||
513743ac7752d92f16213099d1fca6431759f2cd05a8a12f4ee1226cfd1637b3 ./src/api/settings.rs
|
||||
10164f2357a23d63f22adf66e94f52dbb3df5edcb60d7bd5195e6d396e3eb1d8 ./src/api/settings.rs
|
||||
1c1fe39aec55d10608ca3db83827855b07249cd1a81ae054eb1ee6464514092b ./src/api/system.rs
|
||||
9118a5a3a381b010e22d646498ff56d2e05f51656789682cc4371b09c384aa98 ./src/api/websocket.rs
|
||||
ddd1bfc8625b66f6e5f3d24b3122ac86c25f89b0af527e3dfce9102551a8f142 ./src/api/zones.rs
|
||||
@@ -155,7 +155,7 @@ b0189f28d0f337dfd3ce0934da7a565e4a5535afc1c242214c26ed584b3b7840 ./src/engine/t
|
||||
c89ff36c6a67bf4fbf68c43e18aa0a556de2dc69263fd79db376363afc741a4f ./src/engine/zone_actions.rs
|
||||
3a7fada1f6dd9ebab4026b353f41b21d8ca19342b02538c711dbb2dfb599cbe7 ./src/engine/zone_control.rs
|
||||
bfac95cec87f0df6ce562153cd3cfe6731359d703e6c592d2c2f7ba01ea62d99 ./src/error.rs
|
||||
10271a141ec441964c66d5732155abda8993d9fcba8dc0cc77e7c35d5a40e466 ./src/home_assistant.rs
|
||||
26c7617b99a5a46e9afb15d317af4c804d16806dd6fcd3c8a9301c193884b1f2 ./src/home_assistant.rs
|
||||
e78ca9aff23362971eb6450534ea21bdc15150456c378ef9b226cb93a8dbc612 ./src/influxdb.rs
|
||||
da4068295f37c23222bb13bebac022d88ba7729604a49ad25438c55e45458a49 ./src/influxdb/codec.rs
|
||||
b96624fa34b218a6d5f028ba09579633f6f8a04c109f0e94801e8d89ceeeb4b5 ./src/influxdb/query.rs
|
||||
@@ -170,7 +170,7 @@ aeab5b5acf35d38a54fd1d82e964fe56635ade69c0149ad423df317095d01555 ./src/models/f
|
||||
ba5d359e4d6c12d9f62c1b28bdfb40d312737930df5421814f5310f7183e96c1 ./src/models/history.rs
|
||||
110b73c179ea1f85b7afa14f4cdcfd9b8232dd005a6417cf357b8efc73e702c0 ./src/models/integrations.rs
|
||||
f1359b68f1d041cd441f80429e77893eeb6f6194613b58fd3e7a212fb511db3e ./src/models/runtime.rs
|
||||
f8bd9b4106145ebcf20d003471bb54a329e7373cf14a3a712ecabf87ac59d6d3 ./src/models/settings_api.rs
|
||||
527bea024c76d8025fa8f7c4dbf2c6067cbdff8103ebe9763033eeea4accf788 ./src/models/settings_api.rs
|
||||
c4de6101de85d9d7e6814b2504b87d9216561e3d9e274054f081f505fb152140 ./src/models/temporary_thermostat.rs
|
||||
bc2818ce8d0dae1edfb1b98e5d1c00b193f03eeaa28e343d3532f6023288738c ./src/models/zone.rs
|
||||
62e696df8b86835df7ad127f03c257a78580769dc82bc66daa5041f71e8440a5 ./src/notifications.rs
|
||||
@@ -215,8 +215,8 @@ b08b0fe301642d1daa084b322a02e351d284d2465231505d45079a52ccb4028f ./web/js/flows
|
||||
6bb9386707dcf601111fea15a1a366d8798313b973ca1624878618f4c3095add ./web/js/navigation.js
|
||||
799613c6d465cb2f92ecb57cb082d0c33729a03d88ab4ca7fa12a3cbd7e38e75 ./web/js/realtime.js
|
||||
9546ca5c5566994aff3c33d92295be46b65d51d874681764abe77470dc9c9c73 ./web/js/router.js
|
||||
195e8a2ec5faa3da28e0c38e1eff429744139cb6fb859748cd931fb34378d4b4 ./web/js/select-ui.js
|
||||
c48b6101b203b40832976532d2f9c9633c0eaaf3b06cca43a0cfce1531a2b006 ./web/js/settings-ui.js
|
||||
c2710fd9c1f2b31878c1e25ceb02d74ae30456c1bbb400e69fcf7619ecc72bc2 ./web/js/select-ui.js
|
||||
7d3be06768e30884839aec682f55c5cb8085e464aa2fc389ac6ac9ed7a7639d3 ./web/js/settings-ui.js
|
||||
f00c3f603eb314f755a0c46424681b579e0b890453e2550007c719273815147c ./web/js/settings.js
|
||||
3815fea7ae1694568c2f249bc8460e0563ced6bde89214f74f21b41fe8cad9a6 ./web/lang-init.js
|
||||
6b653e4fe2d4db4ffae6ff8f39b8ce57a10a990dc0000ee4aae51d949afadd52 ./web/manifest.webmanifest
|
||||
|
||||
+6
-5
@@ -1,6 +1,6 @@
|
||||
# GREE Controller API reference
|
||||
|
||||
HTTP and WebSocket API for GREE Controller **0.14.11**.
|
||||
HTTP and WebSocket API for GREE Controller **0.14.12**.
|
||||
|
||||
[← Main documentation](../README.md)
|
||||
|
||||
@@ -233,7 +233,7 @@ Response:
|
||||
{
|
||||
"status": "ok",
|
||||
"name": "gree-controller",
|
||||
"version": "0.14.11",
|
||||
"version": "0.14.12",
|
||||
"uptime_seconds": 1234,
|
||||
"control_ready": true,
|
||||
"time": "2026-08-30T06:54:00Z"
|
||||
@@ -284,7 +284,7 @@ Returns the initial Web UI snapshot:
|
||||
"max_fan_speed": 1, "force_quiet": true, "use_native_sleep": true
|
||||
},
|
||||
"home_assistant": {
|
||||
"url": "", "token_configured": false,
|
||||
"url": "", "auth_mode": "manual", "token_configured": false,
|
||||
"outdoor_entity_id": "", "sensor_stale_after_seconds": 300,
|
||||
"allow_invalid_tls": false, "sensor_aliases": {}, "flow_inputs": [],
|
||||
"outdoor_assist_enabled": true
|
||||
@@ -296,7 +296,7 @@ Returns the initial Web UI snapshot:
|
||||
"control_plan": {"generated_at": "2026-09-04T08:00:00Z", "zones": [], "rules": []},
|
||||
"control_plan_revision": 42,
|
||||
"system": {
|
||||
"version": "0.14.11",
|
||||
"version": "0.14.12",
|
||||
"uptime_seconds": 1234,
|
||||
"auth_required": false,
|
||||
"control_ready": true,
|
||||
@@ -1185,6 +1185,7 @@ Times must use `HH:MM`; maximum fan speed is clamped to `1..5`.
|
||||
```json
|
||||
{
|
||||
"url": "http://homeassistant.local:8123",
|
||||
"auth_mode": "manual",
|
||||
"token_configured": true,
|
||||
"outdoor_entity_id": "sensor.outdoor_temperature",
|
||||
"sensor_stale_after_seconds": 300,
|
||||
@@ -1197,7 +1198,7 @@ Times must use `HH:MM`; maximum fan speed is clamped to `1..5`.
|
||||
}
|
||||
```
|
||||
|
||||
`PUT` replaces `token_configured` with optional `token`. Omitted/`null` token preserves the saved token; an explicit empty string clears it. `outdoor_entity_id` is the optional global Home Assistant outdoor-temperature sensor. Each zone can set `ha_outdoor_entity_id` to override that source only for the zone; a blank override uses the global sensor. Home Assistant room-temperature sensors remain configured per zone with `ha_entity_id` when `sensor_source` is `home_assistant` or `combined`. Sensor age is clamped to `30..86400` seconds. URLs, aliases, entity IDs and shared Flow inputs are normalized/validated before persistence. Global/per-zone outdoor sensors and per-zone room sensors are exposed through the normal alias and sensor-history/metric surfaces, and the Web UI offers them as suggestions in Flow Home Assistant entity fields. Shared inputs are value sources only; comparison operators and thresholds belong to Flow nodes. The Home Assistant connection test validates only the server/API token and requires no entity.
|
||||
`auth_mode` is runtime-only: `manual` for standalone installations and `supervisor` for the Home Assistant add-on. In Supervisor mode the returned URL is `http://supervisor/core/`, authentication uses runtime `SUPERVISOR_TOKEN`, and `PUT` does not replace the stored standalone URL/token fields. In manual mode, `PUT` replaces `token_configured` with optional `token`. Omitted/`null` token preserves the saved token; an explicit empty string clears it. `outdoor_entity_id` is the optional global Home Assistant outdoor-temperature sensor. Each zone can set `ha_outdoor_entity_id` to override that source only for the zone; a blank override uses the global sensor. Home Assistant room-temperature sensors remain configured per zone with `ha_entity_id` when `sensor_source` is `home_assistant` or `combined`. Sensor age is clamped to `30..86400` seconds. URLs, aliases, entity IDs and shared Flow inputs are normalized/validated before persistence. Global/per-zone outdoor sensors and per-zone room sensors are exposed through the normal alias and sensor-history/metric surfaces, and the Web UI offers them as suggestions in Flow Home Assistant entity fields. Shared inputs are value sources only; comparison operators and thresholds belong to Flow nodes. The Home Assistant connection test validates only the server/API token and requires no entity.
|
||||
|
||||
### `/api/settings/debug`
|
||||
|
||||
|
||||
+12
-3
@@ -2,9 +2,9 @@
|
||||
"openapi": "3.1.0",
|
||||
"info": {
|
||||
"title": "GREE Controller API",
|
||||
"version": "0.14.11",
|
||||
"version": "0.14.12",
|
||||
"summary": "Local HTTP/WebSocket API for GREE HVAC control",
|
||||
"description": "Self-hosted API used by the GREE Controller Web UI and Home Assistant integration.\n\n### Authentication\nAdministrator endpoints accept `Authorization: Bearer <APP_TOKEN>` or `x-api-token: <APP_TOKEN>` when configured. Restricted Home Assistant control endpoints also accept generated integration tokens.\n\n### Local and GREE Cloud\nDevices use one API model and one command surface. `connection_type=local` is dispatched only to the existing LAN/UDP provider; `connection_type=gree_cloud` is dispatched only to the GREE Cloud provider. No automatic transport fallback is performed.\n\n### GREE Cloud security\nCloud passwords, REST/MQTT tokens, Authorization values and device cipher keys are never returned in normal API responses or Cloud diagnostics. MQTT uses TLS with certificate and hostname validation.\n\n### Energy\nGREE Cloud `ElcAll` and selected Home Assistant cumulative energy sensors are normalized to kWh and converted to consumption deltas before aggregation. Raw cumulative values are retained only as meter samples/baselines.\n\n### 0.14.11\nWeb UI icons now use a shared inline SVG set instead of font-dependent Unicode glyphs across navigation, dialogs, Flow, charts, controls and event categories for consistent cross-platform rendering.\n\n\n### 0.14.10\nNight mode and Home Assistant / Sensors standalone settings now use the full available page width, matching the other Web UI sections.\n\n### 0.14.9\nPower controls use an embedded SVG icon instead of a font-dependent Unicode glyph. Home Assistant room-sensor stale/error events identify the affected entity and zone, and historical event rows can recover that context from metadata.\n\n### 0.14.8\nRemaining Home Assistant and notification diagnostic errors no longer use device-transport 502 responses. Missing/invalid integration configuration returns 400, configured external dependency failures return 424, and 502 is reserved for Local/LAN GREE device communication.\n\n### 0.14.7\nHome Assistant energy-sensor discovery now returns an empty optional result when HA is not configured, uses 424 for configured external-dependency failures, and custom select popovers use their rendered height when positioning above a field.\n\n\n### 0.14.6\nFixes dynamic custom-select duplication in History → Energy and hides Energy history controls when no energy source is configured.\n\n### 0.14.5\nWeb UI single-choice controls now use one consistent custom dropdown, language packs are loaded on demand, and the dashboard outdoor temperature opens a 24-hour history modal.\n\n### 0.14.4\nHome Assistant connection tests validate only the configured server/API token and require no entity. `outdoor_entity_id` is the global Home Assistant outdoor-temperature sensor; zones can override it with `ha_outdoor_entity_id`. Room-temperature Home Assistant sensors remain configured per zone with `ha_entity_id`. Global/per-zone outdoor sensors are integrated with aliases, metrics/history and Visual Flow entity suggestions.\n\n### 0.14.2\nAdds independent vertical/horizontal swing controls across manual device control, thermostat zones, legacy automations, Visual Flow and Home Assistant zone climates. Swing is treated as an auxiliary one-shot unit setting and does not replace thermostat ownership.\n\n### 0.14.1\nAdds split/multisplit installation groups with shared energy and outdoor-temperature sources, multi-target energy charts with period comparison, cleaner Cloud status/alerts and safe MQTT cleanup after the last Cloud device is removed.\n\n### 0.14.0\nAdds first-class GREE Cloud MQTT status/control, reconnect/resubscribe lifecycle, Cloud diagnostics, per-device capabilities, Cloud/HA energy sources and energy-history aggregation while preserving the LAN transport contract.",
|
||||
"description": "Self-hosted API used by the GREE Controller Web UI and Home Assistant integration.\n\n### Authentication\nAdministrator endpoints accept `Authorization: Bearer <APP_TOKEN>` or `x-api-token: <APP_TOKEN>` when configured. Restricted Home Assistant control endpoints also accept generated integration tokens.\n\n### Local and GREE Cloud\nDevices use one API model and one command surface. `connection_type=local` is dispatched only to the existing LAN/UDP provider; `connection_type=gree_cloud` is dispatched only to the GREE Cloud provider. No automatic transport fallback is performed.\n\n### GREE Cloud security\nCloud passwords, REST/MQTT tokens, Authorization values and device cipher keys are never returned in normal API responses or Cloud diagnostics. MQTT uses TLS with certificate and hostname validation.\n\n### Energy\nGREE Cloud `ElcAll` and selected Home Assistant cumulative energy sensors are normalized to kWh and converted to consumption deltas before aggregation. Raw cumulative values are retained only as meter samples/baselines.\n\n### 0.14.12\nThe Home Assistant add-on now uses the Supervisor Core API proxy and runtime SUPERVISOR_TOKEN automatically; standalone Home Assistant URL/token configuration is unchanged.\n\n### 0.14.11\nWeb UI icons now use a shared inline SVG set instead of font-dependent Unicode glyphs across navigation, dialogs, Flow, charts, controls and event categories for consistent cross-platform rendering.\n\n\n### 0.14.10\nNight mode and Home Assistant / Sensors standalone settings now use the full available page width, matching the other Web UI sections.\n\n### 0.14.9\nPower controls use an embedded SVG icon instead of a font-dependent Unicode glyph. Home Assistant room-sensor stale/error events identify the affected entity and zone, and historical event rows can recover that context from metadata.\n\n### 0.14.8\nRemaining Home Assistant and notification diagnostic errors no longer use device-transport 502 responses. Missing/invalid integration configuration returns 400, configured external dependency failures return 424, and 502 is reserved for Local/LAN GREE device communication.\n\n### 0.14.7\nHome Assistant energy-sensor discovery now returns an empty optional result when HA is not configured, uses 424 for configured external-dependency failures, and custom select popovers use their rendered height when positioning above a field.\n\n\n### 0.14.6\nFixes dynamic custom-select duplication in History → Energy and hides Energy history controls when no energy source is configured.\n\n### 0.14.5\nWeb UI single-choice controls now use one consistent custom dropdown, language packs are loaded on demand, and the dashboard outdoor temperature opens a 24-hour history modal.\n\n### 0.14.4\nHome Assistant connection tests validate only the configured server/API token and require no entity. `outdoor_entity_id` is the global Home Assistant outdoor-temperature sensor; zones can override it with `ha_outdoor_entity_id`. Room-temperature Home Assistant sensors remain configured per zone with `ha_entity_id`. Global/per-zone outdoor sensors are integrated with aliases, metrics/history and Visual Flow entity suggestions.\n\n### 0.14.2\nAdds independent vertical/horizontal swing controls across manual device control, thermostat zones, legacy automations, Visual Flow and Home Assistant zone climates. Swing is treated as an auxiliary one-shot unit setting and does not replace thermostat ownership.\n\n### 0.14.1\nAdds split/multisplit installation groups with shared energy and outdoor-temperature sources, multi-target energy charts with period comparison, cleaner Cloud status/alerts and safe MQTT cleanup after the last Cloud device is removed.\n\n### 0.14.0\nAdds first-class GREE Cloud MQTT status/control, reconnect/resubscribe lifecycle, Cloud diagnostics, per-device capabilities, Cloud/HA energy sources and energy-history aggregation while preserving the LAN transport contract.",
|
||||
"license": {
|
||||
"name": "MIT"
|
||||
}
|
||||
@@ -5520,7 +5520,7 @@
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"example": "0.14.11"
|
||||
"example": "0.14.12"
|
||||
},
|
||||
"uptime_seconds": {
|
||||
"type": "integer",
|
||||
@@ -8520,6 +8520,14 @@
|
||||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"auth_mode": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"manual",
|
||||
"supervisor"
|
||||
],
|
||||
"description": "Runtime Home Assistant authentication source. Supervisor mode is managed by the Home Assistant add-on environment."
|
||||
},
|
||||
"outdoor_entity_id": {
|
||||
"type": "string",
|
||||
"description": "Optional global Home Assistant outdoor-temperature entity. Zones use it by default and may override it with ha_outdoor_entity_id."
|
||||
@@ -8552,6 +8560,7 @@
|
||||
},
|
||||
"required": [
|
||||
"url",
|
||||
"auth_mode",
|
||||
"outdoor_entity_id",
|
||||
"sensor_stale_after_seconds",
|
||||
"allow_invalid_tls",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"domain": "gree_controller",
|
||||
"name": "GREE Controller",
|
||||
"version": "0.14.11",
|
||||
"version": "0.14.12",
|
||||
"config_flow": true,
|
||||
"integration_type": "hub",
|
||||
"iot_class": "local_polling",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## 0.14.12
|
||||
|
||||
- Home Assistant add-on now uses the Supervisor-managed Home Assistant Core API connection automatically.
|
||||
- Enables `homeassistant_api` for the add-on and authenticates Core API requests with runtime `SUPERVISOR_TOKEN`.
|
||||
- Keeps the Supervisor token out of SQLite and prevents add-on UI edits from replacing stored standalone Home Assistant URL/token settings.
|
||||
- Standalone installations keep the existing manual Home Assistant URL and Long-Lived Access Token behavior unchanged.
|
||||
- Fixes custom select mouse hover/click inside modal dialogs by keeping each dropdown popover inside the same modal top-layer subtree; keyboard behavior is unchanged.
|
||||
|
||||
## 0.14.11
|
||||
|
||||
- Replaces font-dependent Unicode glyphs used as Web UI icons with a shared inline SVG icon set.
|
||||
|
||||
@@ -58,6 +58,10 @@ Broadcast zwykle nie przechodzi przez router. Sterowanie unicast może działać
|
||||
| `app_token` | opcjonalna ochrona bezpośredniego Web UI/API |
|
||||
| `log_level` | `error`, `warn`, `info`, `debug`, `trace` |
|
||||
|
||||
### Home Assistant API
|
||||
|
||||
Dodatek korzysta automatycznie z wewnętrznego proxy Home Assistant Core (`http://supervisor/core/api/`) i tokenu `SUPERVISOR_TOKEN` przekazywanego przez Supervisor. Nie konfiguruj ręcznie URL ani Long-Lived Access Token dla połączenia kontrolera z Home Assistant. Token Supervisor jest używany tylko w pamięci procesu i nie jest zapisywany w SQLite.
|
||||
|
||||
### Dostęp, dane i bezpieczeństwo
|
||||
|
||||
Usługa słucha na TCP `8787`; ingress Home Assistant przekazuje Web UI na ten port. Jeżeli `8787` jest osiągalny z niezaufanej sieci, ustaw `app_token` albo zablokuj port firewallem. Baza jest zapisywana w `/data/gree-controller.db`; konfiguracja używa `backup: cold`, więc dane są objęte backupem dodatku.
|
||||
@@ -119,6 +123,10 @@ Broadcast normally does not cross routers. Unicast control may work through rout
|
||||
| `app_token` | optional protection for direct Web UI/API access |
|
||||
| `log_level` | `error`, `warn`, `info`, `debug`, `trace` |
|
||||
|
||||
### 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. Do not configure a Home Assistant URL or Long-Lived Access Token for the controller-to-Home-Assistant connection. The Supervisor token is used only at runtime and is not stored in SQLite.
|
||||
|
||||
### Access, data and security
|
||||
|
||||
The service listens on TCP `8787`; Home Assistant ingress proxies the Web UI to that port. If `8787` is reachable from an untrusted network, configure `app_token` or block the port at the firewall. The database is stored in `/data/gree-controller.db`; `backup: cold` keeps it in the add-on backup.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: "GREE Controller"
|
||||
version: "0.14.11"
|
||||
version: "0.14.12"
|
||||
slug: "gree_controller"
|
||||
description: "Local GREE HVAC controller with Web UI and Home Assistant integration"
|
||||
url: "https://git.linuxiarz.pl/gru/gree-controller-ha-addon/"
|
||||
@@ -11,6 +11,7 @@ startup: application
|
||||
boot: auto
|
||||
init: false
|
||||
host_network: true
|
||||
homeassistant_api: true
|
||||
ingress: true
|
||||
ingress_port: 8787
|
||||
ingress_stream: true
|
||||
|
||||
@@ -33,6 +33,7 @@ export GREE_CONTROLLER_POLL_INTERVAL_SECONDS="$POLL_INTERVAL"
|
||||
export GREE_CONTROLLER_ZONE_INTERVAL_SECONDS="$ZONE_INTERVAL"
|
||||
export GREE_CONTROLLER_DISCOVERY_TIMEOUT_MS="$DISCOVERY_TIMEOUT"
|
||||
export GREE_CONTROLLER_APP_TOKEN="$APP_TOKEN"
|
||||
export GREE_CONTROLLER_HA_AUTH="supervisor"
|
||||
export RUST_LOG="gree_controller=${LOG_LEVEL},tower_http=${LOG_LEVEL}"
|
||||
|
||||
printf 'GREE Controller: interface=%s discovery=%s database=%s\n' \
|
||||
|
||||
@@ -183,6 +183,7 @@
|
||||
"settings.haTokenKeep": "Leave empty to keep the saved token",
|
||||
"settings.haTokenSaved": "Token saved — leave empty to keep it",
|
||||
"settings.haLongLivedToken": "Long-Lived Access Token",
|
||||
"settings.haSupervisorToken": "Token provided automatically by Home Assistant Supervisor",
|
||||
"settings.testHa": "Test HA",
|
||||
"settings.systemState": "System status",
|
||||
"settings.version": "Version",
|
||||
|
||||
@@ -183,6 +183,7 @@
|
||||
"settings.haTokenKeep": "Pozostaw puste, aby zachować zapisany token",
|
||||
"settings.haTokenSaved": "Token zapisany — pozostaw puste",
|
||||
"settings.haLongLivedToken": "Długotrwały token dostępu",
|
||||
"settings.haSupervisorToken": "Token dostarczany automatycznie przez Home Assistant Supervisor",
|
||||
"settings.testHa": "Testuj HA",
|
||||
"settings.systemState": "Stan systemu",
|
||||
"settings.version": "Wersja",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Developer smoke/integration tests for GREE Controller API 0.14.11.
|
||||
"""Developer smoke/integration tests for GREE Controller API 0.14.12.
|
||||
|
||||
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
|
||||
@@ -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_TOKEN = os.environ.get("GREE_API_TOKEN", "")
|
||||
DEFAULT_EXPECTED_VERSION = "0.14.11"
|
||||
DEFAULT_EXPECTED_VERSION = "0.14.12"
|
||||
|
||||
SETTINGS_PATHS: dict[str, set[str]] = {
|
||||
"/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")
|
||||
|
||||
runner.run("public health", lambda: test_health(client, args.expected_version))
|
||||
runner.run("OpenAPI 0.14.11 contract", lambda: test_openapi(client, args.expected_version))
|
||||
runner.run("OpenAPI 0.14.12 contract", lambda: test_openapi(client, args.expected_version))
|
||||
runner.run("bootstrap snapshot contract", lambda: test_bootstrap_contract(client))
|
||||
runner.run("protected API requires auth", lambda: test_protected_auth(client))
|
||||
|
||||
@@ -662,7 +662,7 @@ def run_suite(args: argparse.Namespace) -> int:
|
||||
|
||||
def parse_args(argv: Optional[Iterable[str]] = None) -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Developer smoke/integration tests for GREE Controller API 0.14.11.",
|
||||
description="Developer smoke/integration tests for GREE Controller API 0.14.12.",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""Examples:
|
||||
python3 scripts/api_dev_test.py
|
||||
|
||||
@@ -27,7 +27,7 @@ async fn export_configuration(
|
||||
|
||||
fn validate_configuration_header(export: &ConfigurationExport) -> Result<(), AppError> {
|
||||
if export.format_version != 3 {
|
||||
return Err(AppError::BadRequest("unsupported configuration export version; version 3 is required by GREE Controller 0.14.11".into()));
|
||||
return Err(AppError::BadRequest("unsupported configuration export version; version 3 is required by GREE Controller 0.14.12".into()));
|
||||
}
|
||||
if export.settings.control_strategy != "setpoint" {
|
||||
return Err(AppError::BadRequest(
|
||||
|
||||
@@ -49,9 +49,10 @@ fn public_settings(settings: &RuntimeSettings) -> Value {
|
||||
"history_threshold_days": settings.influxdb.history_threshold_days,
|
||||
},
|
||||
"home_assistant": {
|
||||
"url": settings.home_assistant.url,
|
||||
"url": home_assistant::effective_url(&settings.home_assistant),
|
||||
"auth_mode": home_assistant::auth_mode(),
|
||||
"token": "",
|
||||
"token_configured": !settings.home_assistant.token.trim().is_empty(),
|
||||
"token_configured": home_assistant::token_configured(&settings.home_assistant),
|
||||
"outdoor_entity_id": settings.home_assistant.outdoor_entity_id,
|
||||
"sensor_stale_after_seconds": settings.home_assistant.sensor_stale_after_seconds,
|
||||
"allow_invalid_tls": settings.home_assistant.allow_invalid_tls,
|
||||
|
||||
+16
-6
@@ -78,8 +78,9 @@ fn notification_settings(settings: &RuntimeSettings) -> NotificationSettingsView
|
||||
|
||||
fn home_assistant_settings(settings: &RuntimeSettings) -> HomeAssistantSettingsView {
|
||||
HomeAssistantSettingsView {
|
||||
url: settings.home_assistant.url.clone(),
|
||||
token_configured: !settings.home_assistant.token.trim().is_empty(),
|
||||
url: home_assistant::effective_url(&settings.home_assistant),
|
||||
auth_mode: home_assistant::auth_mode().to_string(),
|
||||
token_configured: home_assistant::token_configured(&settings.home_assistant),
|
||||
outdoor_entity_id: settings.home_assistant.outdoor_entity_id.clone(),
|
||||
sensor_stale_after_seconds: settings.home_assistant.sensor_stale_after_seconds,
|
||||
allow_invalid_tls: settings.home_assistant.allow_invalid_tls,
|
||||
@@ -693,8 +694,13 @@ fn apply_home_assistant_update(
|
||||
current: &HomeAssistantSettings,
|
||||
input: HomeAssistantSettingsUpdate,
|
||||
) -> HomeAssistantSettings {
|
||||
let supervisor_managed = home_assistant::uses_supervisor_auth();
|
||||
let mut next = HomeAssistantSettings {
|
||||
url: input.url,
|
||||
url: if supervisor_managed {
|
||||
current.url.clone()
|
||||
} else {
|
||||
input.url
|
||||
},
|
||||
token: current.token.clone(),
|
||||
outdoor_entity_id: input.outdoor_entity_id,
|
||||
sensor_stale_after_seconds: input.sensor_stale_after_seconds.clamp(30, 86_400),
|
||||
@@ -702,8 +708,10 @@ fn apply_home_assistant_update(
|
||||
sensor_aliases: input.sensor_aliases,
|
||||
flow_inputs: input.flow_inputs,
|
||||
};
|
||||
if let Some(token) = input.token {
|
||||
next.token = token;
|
||||
if !supervisor_managed {
|
||||
if let Some(token) = input.token {
|
||||
next.token = token;
|
||||
}
|
||||
}
|
||||
next
|
||||
}
|
||||
@@ -720,7 +728,9 @@ async fn update_home_assistant_settings(
|
||||
normalize_sensor_aliases(&mut next);
|
||||
validate_flow_shared_inputs(&mut next, &state)?;
|
||||
canonicalize_home_assistant_entities(&mut next);
|
||||
validate_home_assistant_url(&next)?;
|
||||
if !home_assistant::uses_supervisor_auth() {
|
||||
validate_home_assistant_url(&next)?;
|
||||
}
|
||||
settings.home_assistant = next.clone();
|
||||
settings.outdoor_assist_enabled = input.outdoor_assist_enabled;
|
||||
state.db.save_runtime_settings(&settings)?;
|
||||
|
||||
+74
-56
@@ -1,9 +1,72 @@
|
||||
use crate::models::HomeAssistantSettings;
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use serde_json::Value;
|
||||
use std::time::Duration;
|
||||
use std::{env, time::Duration};
|
||||
use url::Url;
|
||||
|
||||
const SUPERVISOR_AUTH_ENV: &str = "GREE_CONTROLLER_HA_AUTH";
|
||||
const SUPERVISOR_AUTH_MODE: &str = "supervisor";
|
||||
const SUPERVISOR_TOKEN_ENV: &str = "SUPERVISOR_TOKEN";
|
||||
const SUPERVISOR_BASE_URL: &str = "http://supervisor/core/";
|
||||
|
||||
pub fn uses_supervisor_auth() -> bool {
|
||||
env::var(SUPERVISOR_AUTH_ENV)
|
||||
.map(|value| value.trim().eq_ignore_ascii_case(SUPERVISOR_AUTH_MODE))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn auth_mode() -> &'static str {
|
||||
if uses_supervisor_auth() {
|
||||
SUPERVISOR_AUTH_MODE
|
||||
} else {
|
||||
"manual"
|
||||
}
|
||||
}
|
||||
|
||||
pub fn effective_url(settings: &HomeAssistantSettings) -> String {
|
||||
if uses_supervisor_auth() {
|
||||
SUPERVISOR_BASE_URL.to_string()
|
||||
} else {
|
||||
settings.url.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn token_configured(settings: &HomeAssistantSettings) -> bool {
|
||||
if uses_supervisor_auth() {
|
||||
env::var(SUPERVISOR_TOKEN_ENV)
|
||||
.map(|token| !token.trim().is_empty())
|
||||
.unwrap_or(false)
|
||||
} else {
|
||||
!settings.token.trim().is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
fn connection(settings: &HomeAssistantSettings) -> Result<(Url, String)> {
|
||||
let (raw_url, token) = if uses_supervisor_auth() {
|
||||
let token = env::var(SUPERVISOR_TOKEN_ENV)
|
||||
.context("Home Assistant Supervisor token is not available")?;
|
||||
(SUPERVISOR_BASE_URL.to_string(), token)
|
||||
} else {
|
||||
(settings.url.clone(), settings.token.clone())
|
||||
};
|
||||
|
||||
if raw_url.trim().is_empty() {
|
||||
bail!("Home Assistant URL is not configured")
|
||||
}
|
||||
if token.trim().is_empty() {
|
||||
if uses_supervisor_auth() {
|
||||
bail!("Home Assistant Supervisor token is not available")
|
||||
}
|
||||
bail!("Home Assistant token is not configured")
|
||||
}
|
||||
|
||||
let base = Url::parse(raw_url.trim()).context("invalid Home Assistant URL")?;
|
||||
if !matches!(base.scheme(), "http" | "https") {
|
||||
bail!("Home Assistant URL must use http or https")
|
||||
}
|
||||
Ok((base, token))
|
||||
}
|
||||
|
||||
fn request_client(
|
||||
default_client: &reqwest::Client,
|
||||
settings: &HomeAssistantSettings,
|
||||
@@ -48,20 +111,11 @@ pub async fn test_connection(
|
||||
default_client: &reqwest::Client,
|
||||
settings: &HomeAssistantSettings,
|
||||
) -> Result<()> {
|
||||
if settings.url.trim().is_empty() {
|
||||
bail!("Home Assistant URL is not configured")
|
||||
}
|
||||
if settings.token.trim().is_empty() {
|
||||
bail!("Home Assistant token is not configured")
|
||||
}
|
||||
let mut base = Url::parse(settings.url.trim()).context("invalid Home Assistant URL")?;
|
||||
if !matches!(base.scheme(), "http" | "https") {
|
||||
bail!("Home Assistant URL must use http or https")
|
||||
}
|
||||
let (mut base, token) = connection(settings)?;
|
||||
base = base.join("api/").context("cannot build Home Assistant API URL")?;
|
||||
let response = request_client(default_client, settings)?
|
||||
.get(base)
|
||||
.bearer_auth(settings.token.trim())
|
||||
.bearer_auth(token.trim())
|
||||
.header("Accept", "application/json")
|
||||
.send()
|
||||
.await
|
||||
@@ -83,19 +137,10 @@ pub async fn read_temperature(
|
||||
entity_override: Option<&str>,
|
||||
stale_after_seconds: Option<u64>,
|
||||
) -> Result<f64> {
|
||||
if settings.url.trim().is_empty() {
|
||||
bail!("Home Assistant URL is not configured")
|
||||
}
|
||||
if settings.token.trim().is_empty() {
|
||||
bail!("Home Assistant token is not configured")
|
||||
}
|
||||
let (mut base, token) = connection(settings)?;
|
||||
let entity = resolve_entity_id(settings, entity_override)
|
||||
.ok_or_else(|| anyhow!("Home Assistant entity_id is not configured"))?;
|
||||
|
||||
let mut base = Url::parse(settings.url.trim()).context("invalid Home Assistant URL")?;
|
||||
if !matches!(base.scheme(), "http" | "https") {
|
||||
bail!("Home Assistant URL must use http or https")
|
||||
}
|
||||
let path = format!("api/states/{}", entity.trim_start_matches('/'));
|
||||
base = base
|
||||
.join(&path)
|
||||
@@ -104,7 +149,7 @@ pub async fn read_temperature(
|
||||
let client = request_client(default_client, settings)?;
|
||||
let response = client
|
||||
.get(base)
|
||||
.bearer_auth(settings.token.trim())
|
||||
.bearer_auth(token.trim())
|
||||
.header("Accept", "application/json")
|
||||
.send()
|
||||
.await
|
||||
@@ -195,25 +240,16 @@ pub async fn read_entity(
|
||||
settings: &HomeAssistantSettings,
|
||||
entity_override: Option<&str>,
|
||||
) -> Result<Value> {
|
||||
if settings.url.trim().is_empty() {
|
||||
bail!("Home Assistant URL is not configured")
|
||||
}
|
||||
if settings.token.trim().is_empty() {
|
||||
bail!("Home Assistant token is not configured")
|
||||
}
|
||||
let (mut base, token) = connection(settings)?;
|
||||
let entity = resolve_entity_id(settings, entity_override)
|
||||
.ok_or_else(|| anyhow!("Home Assistant entity_id is not configured"))?;
|
||||
let mut base = Url::parse(settings.url.trim()).context("invalid Home Assistant URL")?;
|
||||
if !matches!(base.scheme(), "http" | "https") {
|
||||
bail!("Home Assistant URL must use http or https")
|
||||
}
|
||||
base = base
|
||||
.join(&format!("api/states/{}", entity.trim_start_matches('/')))
|
||||
.context("cannot build Home Assistant API URL")?;
|
||||
let client = request_client(default_client, settings)?;
|
||||
let response = client
|
||||
.get(base)
|
||||
.bearer_auth(settings.token.trim())
|
||||
.bearer_auth(token.trim())
|
||||
.header("Accept", "application/json")
|
||||
.send()
|
||||
.await
|
||||
@@ -234,20 +270,11 @@ pub async fn list_entities(
|
||||
default_client: &reqwest::Client,
|
||||
settings: &HomeAssistantSettings,
|
||||
) -> Result<Vec<Value>> {
|
||||
if settings.url.trim().is_empty() {
|
||||
bail!("Home Assistant URL is not configured")
|
||||
}
|
||||
if settings.token.trim().is_empty() {
|
||||
bail!("Home Assistant token is not configured")
|
||||
}
|
||||
let mut base = Url::parse(settings.url.trim()).context("invalid Home Assistant URL")?;
|
||||
if !matches!(base.scheme(), "http" | "https") {
|
||||
bail!("Home Assistant URL must use http or https")
|
||||
}
|
||||
let (mut base, token) = connection(settings)?;
|
||||
base = base.join("api/states").context("cannot build Home Assistant API URL")?;
|
||||
let response = request_client(default_client, settings)?
|
||||
.get(base)
|
||||
.bearer_auth(settings.token.trim())
|
||||
.bearer_auth(token.trim())
|
||||
.header("Accept", "application/json")
|
||||
.send()
|
||||
.await
|
||||
@@ -292,19 +319,10 @@ pub async fn call_service(
|
||||
entity_id: Option<&str>,
|
||||
data: &Value,
|
||||
) -> Result<Value> {
|
||||
if settings.url.trim().is_empty() {
|
||||
bail!("Home Assistant URL is not configured")
|
||||
}
|
||||
if settings.token.trim().is_empty() {
|
||||
bail!("Home Assistant token is not configured")
|
||||
}
|
||||
let (mut base, token) = connection(settings)?;
|
||||
if domain.trim().is_empty() || service.trim().is_empty() {
|
||||
bail!("Home Assistant domain/service is required")
|
||||
}
|
||||
let mut base = Url::parse(settings.url.trim()).context("invalid Home Assistant URL")?;
|
||||
if !matches!(base.scheme(), "http" | "https") {
|
||||
bail!("Home Assistant URL must use http or https")
|
||||
}
|
||||
base = base
|
||||
.join(&format!(
|
||||
"api/services/{}/{}",
|
||||
@@ -319,7 +337,7 @@ pub async fn call_service(
|
||||
let client = request_client(default_client, settings)?;
|
||||
let response = client
|
||||
.post(base)
|
||||
.bearer_auth(settings.token.trim())
|
||||
.bearer_auth(token.trim())
|
||||
.header("Accept", "application/json")
|
||||
.json(&Value::Object(payload))
|
||||
.send()
|
||||
|
||||
@@ -139,6 +139,7 @@ pub struct HomeAssistantSettingsUpdate {
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct HomeAssistantSettingsView {
|
||||
pub url: String,
|
||||
pub auth_mode: String,
|
||||
pub token_configured: bool,
|
||||
pub outdoor_entity_id: String,
|
||||
pub sensor_stale_after_seconds: u64,
|
||||
|
||||
+14
-1
@@ -43,6 +43,18 @@ function customSelectLabel(select) {
|
||||
return labelSpan?.textContent?.trim() || select.name || select.id || '';
|
||||
}
|
||||
|
||||
function customSelectMenuHost(select) {
|
||||
// A modal <dialog> makes everything outside its DOM subtree inert. Keep
|
||||
// the popover menu inside the same dialog so pointer hover/click continues
|
||||
// to work while the dialog is shown with showModal().
|
||||
return select.closest('dialog') || document.body;
|
||||
}
|
||||
|
||||
function ensureCustomSelectMenuHost(select, state) {
|
||||
const host = customSelectMenuHost(select);
|
||||
if (state.menu.parentElement !== host) host.appendChild(state.menu);
|
||||
}
|
||||
|
||||
function customSelectOptionRows(select) {
|
||||
const rows = [];
|
||||
[...select.children].forEach(child => {
|
||||
@@ -198,6 +210,7 @@ function closeCustomSelect(state = customSelectOpenState) {
|
||||
function openCustomSelect(select) {
|
||||
const state = customSelectRegistry.get(select);
|
||||
if (!state || select.disabled) return;
|
||||
ensureCustomSelectMenuHost(select, state);
|
||||
if (customSelectOpenState === state && state.open) {
|
||||
closeCustomSelect(state);
|
||||
return;
|
||||
@@ -280,7 +293,7 @@ function enhanceCustomSelect(select) {
|
||||
menu.setAttribute('role', 'listbox');
|
||||
menu.setAttribute('popover', 'manual');
|
||||
menu.hidden = true;
|
||||
document.body.appendChild(menu);
|
||||
customSelectMenuHost(select).appendChild(menu);
|
||||
|
||||
let wrapper = null;
|
||||
let trigger = toolbarHost;
|
||||
|
||||
@@ -341,9 +341,14 @@ function renderHomeAssistantSettings() {
|
||||
if (!app.settings) return;
|
||||
const form = $('#homeAssistantForm');
|
||||
if (!form) return;
|
||||
const supervisorManaged = app.settings.home_assistant?.auth_mode === 'supervisor';
|
||||
form.ha_url.value = app.settings.home_assistant?.url || '';
|
||||
form.ha_url.readOnly = supervisorManaged;
|
||||
form.ha_token.value = '';
|
||||
form.ha_token.placeholder = app.settings.home_assistant?.token_configured ? tr('settings.haTokenSaved') : tr('settings.haLongLivedToken');
|
||||
form.ha_token.readOnly = supervisorManaged;
|
||||
form.ha_token.placeholder = supervisorManaged
|
||||
? tr('settings.haSupervisorToken')
|
||||
: (app.settings.home_assistant?.token_configured ? tr('settings.haTokenSaved') : tr('settings.haLongLivedToken'));
|
||||
form.ha_outdoor_entity_id.value = app.settings.home_assistant?.outdoor_entity_id || '';
|
||||
form.ha_sensor_stale_after_minutes.value = String(Math.max(1, Math.round(Number(app.settings.home_assistant?.sensor_stale_after_seconds || 300) / 60)));
|
||||
form.ha_allow_invalid_tls.checked = !!app.settings.home_assistant?.allow_invalid_tls;
|
||||
|
||||
Reference in New Issue
Block a user