From cafbf6e5faf3807deb43ebea967adaa6995e3be2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Gruszczy=C5=84ski?= Date: Thu, 17 Sep 2026 13:01:41 +0200 Subject: [PATCH] v0.15.1 --- Cargo.lock | 2 +- Cargo.toml | 2 +- FILE_MANIFEST.sha256 | 28 ++++++------- README.md | 4 +- SOURCE_MANIFEST.sha256 | 26 ++++++------ docs/API.md | 6 +-- docs/openapi.json | 6 +-- .../gree_controller/manifest.json | 2 +- .../repository/gree-controller/CHANGELOG.md | 4 ++ .../repository/gree-controller/config.yaml | 2 +- lang/en.json | 1 + lang/pl.json | 1 + web/css/styles.css | 3 +- web/js-dynamic/core.js | 2 +- web/js-dynamic/realtime.js | 41 +++++++++++++++++-- 15 files changed, 85 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 61b6c3b..1aa2d6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -700,7 +700,7 @@ dependencies = [ [[package]] name = "gree-controller" -version = "0.15.0" +version = "0.15.1" dependencies = [ "aes", "aes-gcm", diff --git a/Cargo.toml b/Cargo.toml index 6af8cb6..b19be73 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gree-controller" -version = "0.15.0" +version = "0.15.1" edition = "2021" authors = ["GREE Controller contributors"] description = "Standalone local GREE HVAC controller with Web UI, SQLite and Home Assistant sensor support" diff --git a/FILE_MANIFEST.sha256 b/FILE_MANIFEST.sha256 index 205ce66..0778768 100644 --- a/FILE_MANIFEST.sha256 +++ b/FILE_MANIFEST.sha256 @@ -1,14 +1,14 @@ de0793949cf01d27d903653226ecc9b5f72523d8711f20bcab022cf42c4c4ed0 ./.env.example a4ec3874a2e3ab1bad28fb40bb620f7b01f64d01ad9b699306bf70ada31227db ./.gitignore -c3c16d0c76fbb80ce5752b28a1736177940670b10f44235eac5997c4e195c634 ./Cargo.lock -ad513e247ab5dbed3c91a6463cf410cf1a4ac73c0b30422bad40afb93cee0159 ./Cargo.toml +852768ed3da99ac2e9bbe6c9b67e9a4a667e7115ad9482b6ce4a29ff72d8f914 ./Cargo.lock +8e58dd01d95c93ea4f5d0cc5e379cb192221705c9dda41b7b2b7182c49dbff0f ./Cargo.toml 19b2943504acb8f8de280f873a8dbec4bb6ebbe3870b158f5655d4fb8c298f5f ./LICENSE -db052d6c978b067a31d752f293fc8c02702d50137ba7b84bce87371089972f11 ./README.md -84bae184c72909d968eeece0a092dbb4fe7a8a071927b29cc188ac6fb6a450f0 ./SOURCE_MANIFEST.sha256 +4a6570c14ba56fc9a4921de6726816264e961a5b82a7fe3fcf475ef96417dad9 ./README.md +283ffafdffd463f5d670acaba251fb92fab7c88e51a6fc1e06732f6cade88b5e ./SOURCE_MANIFEST.sha256 29e9821e5ed216ea3565dd6d8bc0b174ed3cf9fa72c4ccebbfa99e98db3ad8f9 ./build.rs -8a96630c36cfac5c392837c8872b20d39d72fe3ec99c7c9e09ec78f2228fd262 ./docs/API.md +9873e774746783d65e447b439d069f84c13d2f4e556661e4eb509af59293c2f7 ./docs/API.md 58b79297607303151c1de2da74344cd4f6277bc53d80ebe04ed4567d906c963b ./docs/FLOW.md -525b03af649d0215e3b81e52ce63ebf8651f47b49503c30d0177b3e0b2714ac4 ./docs/openapi.json +9483ad7cb1e0c8e38f08c722600b6ba059d4273cfb9dcd1af57c11de522d187b ./docs/openapi.json c65aa543d2e99f8f7d52736307b07ebd182597d80124661d53a16bb23f6f1118 ./ha-addon/.env.example 0993076ca45b6d31859680835204cdc111b3f9bdbf460d50b4efec56cd5e685b ./ha-addon/Dockerfile adf7ff248d782a3b1cba82b8789c57b6849ddaaaf5fbc108af75e18b1534a885 ./ha-addon/README.md @@ -22,7 +22,7 @@ b7f0873109c52be9d7f09bea3dffc416103c50085e1f0680d11661a969479898 ./ha-addon/hom 6509286c7b7de638dcc5d40ce53181e65d1eddc5dc36a13306dc6d87220fedbb ./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 -d2a18bc3de3207b9f9025507981ad3742ddc3f3728fa223baf84c7ecbb05973e ./ha-addon/home-assistant/custom_components/gree_controller/manifest.json +a6d69fad7ea1f22436e9f643ceb36c206f1450d8337aede0c5d7a1f0613baeeb ./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,10 +30,10 @@ cca65482e36d48035aca178121a378fe7d578d600acff267ae81a6399c0da653 ./ha-addon/hom a745cc458c235158d5d70b6a33d8000fd8b40ff93bfe2f2796af0f4b3a9eef9b ./ha-addon/home-assistant/custom_components/gree_controller/translations/en.json 50b7d6fe6329ad4ea6bee9612ab141c2f73f8382fcc2af0bb076a8e8d4dd4465 ./ha-addon/home-assistant/custom_components/gree_controller/translations/pl.json c5fc5c87273d82d2834a0a5a365c821a416413ed509613441e24e4dc3507c4d2 ./ha-addon/home-assistant/generated/gree_controller_entities.example.json -b3ee553cc7dbc68c3bb7cdd6dbb9b5ca8646df113cb499ca5bd9d3d0e380db73 ./ha-addon/repository/gree-controller/CHANGELOG.md +ea5c4eb4ca2656f8d9a2be37a35ba04bb4c53d735c9c04b416b112e456699cff ./ha-addon/repository/gree-controller/CHANGELOG.md 1b5599195329cc3e643c23aa1caadcec80f133e8e515eec7d92b9f3cbda5b80b ./ha-addon/repository/gree-controller/DOCS.md c3db302f38d26dc9f8caf37a1a8a07a1334cc07ae301d452f2940a5ec5915719 ./ha-addon/repository/gree-controller/README.md -f7e5325e34b2785d0d0bea657c882202d7557d313cbdc464dcdb91f702d36391 ./ha-addon/repository/gree-controller/config.yaml +c16d31ae815dc4e324ce56b0b46529bcc78c5223688c33aa30d7463abe4f1184 ./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 2272740b185e9520e948f74b8f45cf98b8b5fd28c93bdee760da626f91fe5c2a ./ha-addon/repository/gree-controller/translations/en.yaml @@ -43,8 +43,8 @@ cea12bc74c066a588a5ef0ef7bad9d4906bdbcea99f2d275429b0eefc94b4b5f ./ha-addon/run 081e27b6e43070d44f865335c30a42a5a29668eaa6a5ea5ab6967ac4447b8e06 ./ha-addon/sync-repository.sh f9e31de3d109ead32bf531c074d46a087df398d62488caee0b46b5e0a1c027f7 ./ha_addon.md 253a0bc912786e67ea7fc92a64e4a510ad973bec343a88ccfb1f28fca3e8cf01 ./lang/README.md -1bb256c32c07b8366751bbc79e8ceb284a267f3b389115263b2c67cfd73223e3 ./lang/en.json -826362354203c7f66af8acdfc367d2b10868add09b59dc5d3c756f6102692e77 ./lang/pl.json +f7fc1aee1129cee46a30d5876e3e53f11d2661925eae19cb1e14b47deae83e9e ./lang/en.json +c05d100e9efa1a82747ffc709157a9bdd6d109b7a80c6e140d582a28d8c3de13 ./lang/pl.json d8459024f04ca514bd8e9d6bd3af872fb942fd85a7cdd5583f4a9d28aab6faba ./make_zip.py b14233a8987e53bbbdd6770386ba10fa166ec25c1e098275c173c544b37846fc ./presets/bedroom_window_night.json 1960841119c0b673fb2f03621b32237552fd828045304cd221401214b997c910 ./presets/device_resilience.json @@ -200,14 +200,14 @@ f13f1be3d5789539eba3fc1b59c14835f8c681eca7634e118fa3763a53aeee2b ./src/queries/ 8c34b70fb5f80e3249c2e0c63686e60ce1697cf44a7e6f11b3ad6f689ce17792 ./src/state.rs b92a6cb158b494fe145b43c7641e65f6fafff47201d7d76edbec2cfd8b94835c ./systemd/gree-controller.service 544a31cb2e5374227026afd6abd0d910381f3fca1638154ebd74e3c3d96a35d1 ./web/404.html -c184023f9f8a766529e047fb2798296472456a5859828e527cc3a5f180ed2b1e ./web/css/styles.css +2822a98a4d7f72f2b89b70878aa0f9bd3f391fde4ea04ba1b94e89a527dcd1fb ./web/css/styles.css 183d122ba366303d9952ac0e68aff4bced4e0d9a468fbe51316c13f15227402b ./web/custom-chart.html e98bdd7204349cce1ec6f57283509697af0bbc72280622a6c3efa6fed242db4f ./web/favicon.svg 263d5554e62d2dd26b251f2c43a7e4ec14c8d8d790fa67e55c9bebf16f9d55c0 ./web/index.html 9ba3f6fa05b72aa989139b2a909982571b2a02055052e4c40104f1e81a9aa7eb ./web/js-dynamic/README.md e74bb06dba646f298a4d118b5c2dca6ba24f1179ce8ea8d53c1acd6000ca332c ./web/js-dynamic/bootstrap.js 5d57253a013fd1cb79e4b8701d4be6e394e3f2acbce73dfcd726a86e5878f1a1 ./web/js-dynamic/charts.js -aa97e4c67a6f8fe8f473e95e678d7cb79b5756fd915270ceaae59827e6bf7ae1 ./web/js-dynamic/core.js +bb2b49361103145bd8c502f2867962d48ced409c1a1474af1214c4d8d0b378b2 ./web/js-dynamic/core.js 752b3c3b59558b42d867d4a15329238f0213f354b76f7011c10e31b4e6dbb311 ./web/js-dynamic/dashboard.js 0e1992a7b93767f1fe4634121ae5aa43900d99f8c2614c2a4cbd5770a49b87c1 ./web/js-dynamic/entities.js eeeef31f767f0aa3efb78bc44a2fea2b9eb86f4d4c50cf1ccae69b5ca30cdfda ./web/js-dynamic/events.js @@ -216,7 +216,7 @@ eeeef31f767f0aa3efb78bc44a2fea2b9eb86f4d4c50cf1ccae69b5ca30cdfda ./web/js-dynam 92d013bb5d64f64aa8c55380704540a5f72732bde7ccd16554965e401daf50ea ./web/js-dynamic/history.js 511c4e7cc4c48fbbdab64558a9d1c27e6759c9b6dca255d11f301b9708e955c7 ./web/js-dynamic/main.js 86031d4f7f7d1b46412c8fbb09ff1ad1b2b4cd84eb949bc749b27663f1dc27fa ./web/js-dynamic/navigation.js -799613c6d465cb2f92ecb57cb082d0c33729a03d88ab4ca7fa12a3cbd7e38e75 ./web/js-dynamic/realtime.js +0e398bad2cde85d4a62d8733c06e73f2b6a5b07db791d4570feba38c7ff8741f ./web/js-dynamic/realtime.js 1b667f0a8bce824b27f56a8d2f44ff8feef9a011289591dc629ee288db70d137 ./web/js-dynamic/router.js c2710fd9c1f2b31878c1e25ceb02d74ae30456c1bbb400e69fcf7619ecc72bc2 ./web/js-dynamic/select-ui.js bc42b4a0dd0d20239ce22ea1dff09b3f94e8c0e1395e01251a4585a051968a8f ./web/js-dynamic/settings-ui.js diff --git a/README.md b/README.md index 692a200..a665508 100644 --- a/README.md +++ b/README.md @@ -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.15.0** +**Version: 0.15.1** -Version 0.15.0 adds full vertical/horizontal louver positioning across direct control, thermostat views, automations, Visual Flow and Home Assistant, while keeping legacy boolean swing payloads compatible. Direct add-on access also shows an invalid-token error only after an explicit token submission. The bundled Home Assistant climate cards also localize louver/fan/profile labels without changing their stable technical service values. +Version 0.15.1 improves WebSocket connection-state handling in the Web UI: transient disconnects show a reconnecting state, persistent failures escalate after a short grace period, and successful reconnects restore the connected state without affecting the existing HTTP fallback. > [Full API reference](docs/API.md) — authentication, every endpoint, request bodies, response models, WebSocket events and examples. diff --git a/SOURCE_MANIFEST.sha256 b/SOURCE_MANIFEST.sha256 index 9628d02..2b9ae16 100644 --- a/SOURCE_MANIFEST.sha256 +++ b/SOURCE_MANIFEST.sha256 @@ -1,13 +1,13 @@ de0793949cf01d27d903653226ecc9b5f72523d8711f20bcab022cf42c4c4ed0 ./.env.example a4ec3874a2e3ab1bad28fb40bb620f7b01f64d01ad9b699306bf70ada31227db ./.gitignore -c3c16d0c76fbb80ce5752b28a1736177940670b10f44235eac5997c4e195c634 ./Cargo.lock -ad513e247ab5dbed3c91a6463cf410cf1a4ac73c0b30422bad40afb93cee0159 ./Cargo.toml +852768ed3da99ac2e9bbe6c9b67e9a4a667e7115ad9482b6ce4a29ff72d8f914 ./Cargo.lock +8e58dd01d95c93ea4f5d0cc5e379cb192221705c9dda41b7b2b7182c49dbff0f ./Cargo.toml 19b2943504acb8f8de280f873a8dbec4bb6ebbe3870b158f5655d4fb8c298f5f ./LICENSE -db052d6c978b067a31d752f293fc8c02702d50137ba7b84bce87371089972f11 ./README.md +4a6570c14ba56fc9a4921de6726816264e961a5b82a7fe3fcf475ef96417dad9 ./README.md 29e9821e5ed216ea3565dd6d8bc0b174ed3cf9fa72c4ccebbfa99e98db3ad8f9 ./build.rs -8a96630c36cfac5c392837c8872b20d39d72fe3ec99c7c9e09ec78f2228fd262 ./docs/API.md +9873e774746783d65e447b439d069f84c13d2f4e556661e4eb509af59293c2f7 ./docs/API.md 58b79297607303151c1de2da74344cd4f6277bc53d80ebe04ed4567d906c963b ./docs/FLOW.md -525b03af649d0215e3b81e52ce63ebf8651f47b49503c30d0177b3e0b2714ac4 ./docs/openapi.json +9483ad7cb1e0c8e38f08c722600b6ba059d4273cfb9dcd1af57c11de522d187b ./docs/openapi.json c65aa543d2e99f8f7d52736307b07ebd182597d80124661d53a16bb23f6f1118 ./ha-addon/.env.example 0993076ca45b6d31859680835204cdc111b3f9bdbf460d50b4efec56cd5e685b ./ha-addon/Dockerfile adf7ff248d782a3b1cba82b8789c57b6849ddaaaf5fbc108af75e18b1534a885 ./ha-addon/README.md @@ -21,7 +21,7 @@ b7f0873109c52be9d7f09bea3dffc416103c50085e1f0680d11661a969479898 ./ha-addon/hom 6509286c7b7de638dcc5d40ce53181e65d1eddc5dc36a13306dc6d87220fedbb ./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 -d2a18bc3de3207b9f9025507981ad3742ddc3f3728fa223baf84c7ecbb05973e ./ha-addon/home-assistant/custom_components/gree_controller/manifest.json +a6d69fad7ea1f22436e9f643ceb36c206f1450d8337aede0c5d7a1f0613baeeb ./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,10 +29,10 @@ cca65482e36d48035aca178121a378fe7d578d600acff267ae81a6399c0da653 ./ha-addon/hom a745cc458c235158d5d70b6a33d8000fd8b40ff93bfe2f2796af0f4b3a9eef9b ./ha-addon/home-assistant/custom_components/gree_controller/translations/en.json 50b7d6fe6329ad4ea6bee9612ab141c2f73f8382fcc2af0bb076a8e8d4dd4465 ./ha-addon/home-assistant/custom_components/gree_controller/translations/pl.json c5fc5c87273d82d2834a0a5a365c821a416413ed509613441e24e4dc3507c4d2 ./ha-addon/home-assistant/generated/gree_controller_entities.example.json -b3ee553cc7dbc68c3bb7cdd6dbb9b5ca8646df113cb499ca5bd9d3d0e380db73 ./ha-addon/repository/gree-controller/CHANGELOG.md +ea5c4eb4ca2656f8d9a2be37a35ba04bb4c53d735c9c04b416b112e456699cff ./ha-addon/repository/gree-controller/CHANGELOG.md 1b5599195329cc3e643c23aa1caadcec80f133e8e515eec7d92b9f3cbda5b80b ./ha-addon/repository/gree-controller/DOCS.md c3db302f38d26dc9f8caf37a1a8a07a1334cc07ae301d452f2940a5ec5915719 ./ha-addon/repository/gree-controller/README.md -f7e5325e34b2785d0d0bea657c882202d7557d313cbdc464dcdb91f702d36391 ./ha-addon/repository/gree-controller/config.yaml +c16d31ae815dc4e324ce56b0b46529bcc78c5223688c33aa30d7463abe4f1184 ./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 2272740b185e9520e948f74b8f45cf98b8b5fd28c93bdee760da626f91fe5c2a ./ha-addon/repository/gree-controller/translations/en.yaml @@ -42,8 +42,8 @@ cea12bc74c066a588a5ef0ef7bad9d4906bdbcea99f2d275429b0eefc94b4b5f ./ha-addon/run 081e27b6e43070d44f865335c30a42a5a29668eaa6a5ea5ab6967ac4447b8e06 ./ha-addon/sync-repository.sh f9e31de3d109ead32bf531c074d46a087df398d62488caee0b46b5e0a1c027f7 ./ha_addon.md 253a0bc912786e67ea7fc92a64e4a510ad973bec343a88ccfb1f28fca3e8cf01 ./lang/README.md -1bb256c32c07b8366751bbc79e8ceb284a267f3b389115263b2c67cfd73223e3 ./lang/en.json -826362354203c7f66af8acdfc367d2b10868add09b59dc5d3c756f6102692e77 ./lang/pl.json +f7fc1aee1129cee46a30d5876e3e53f11d2661925eae19cb1e14b47deae83e9e ./lang/en.json +c05d100e9efa1a82747ffc709157a9bdd6d109b7a80c6e140d582a28d8c3de13 ./lang/pl.json d8459024f04ca514bd8e9d6bd3af872fb942fd85a7cdd5583f4a9d28aab6faba ./make_zip.py b14233a8987e53bbbdd6770386ba10fa166ec25c1e098275c173c544b37846fc ./presets/bedroom_window_night.json 1960841119c0b673fb2f03621b32237552fd828045304cd221401214b997c910 ./presets/device_resilience.json @@ -199,14 +199,14 @@ f13f1be3d5789539eba3fc1b59c14835f8c681eca7634e118fa3763a53aeee2b ./src/queries/ 8c34b70fb5f80e3249c2e0c63686e60ce1697cf44a7e6f11b3ad6f689ce17792 ./src/state.rs b92a6cb158b494fe145b43c7641e65f6fafff47201d7d76edbec2cfd8b94835c ./systemd/gree-controller.service 544a31cb2e5374227026afd6abd0d910381f3fca1638154ebd74e3c3d96a35d1 ./web/404.html -c184023f9f8a766529e047fb2798296472456a5859828e527cc3a5f180ed2b1e ./web/css/styles.css +2822a98a4d7f72f2b89b70878aa0f9bd3f391fde4ea04ba1b94e89a527dcd1fb ./web/css/styles.css 183d122ba366303d9952ac0e68aff4bced4e0d9a468fbe51316c13f15227402b ./web/custom-chart.html e98bdd7204349cce1ec6f57283509697af0bbc72280622a6c3efa6fed242db4f ./web/favicon.svg 263d5554e62d2dd26b251f2c43a7e4ec14c8d8d790fa67e55c9bebf16f9d55c0 ./web/index.html 9ba3f6fa05b72aa989139b2a909982571b2a02055052e4c40104f1e81a9aa7eb ./web/js-dynamic/README.md e74bb06dba646f298a4d118b5c2dca6ba24f1179ce8ea8d53c1acd6000ca332c ./web/js-dynamic/bootstrap.js 5d57253a013fd1cb79e4b8701d4be6e394e3f2acbce73dfcd726a86e5878f1a1 ./web/js-dynamic/charts.js -aa97e4c67a6f8fe8f473e95e678d7cb79b5756fd915270ceaae59827e6bf7ae1 ./web/js-dynamic/core.js +bb2b49361103145bd8c502f2867962d48ced409c1a1474af1214c4d8d0b378b2 ./web/js-dynamic/core.js 752b3c3b59558b42d867d4a15329238f0213f354b76f7011c10e31b4e6dbb311 ./web/js-dynamic/dashboard.js 0e1992a7b93767f1fe4634121ae5aa43900d99f8c2614c2a4cbd5770a49b87c1 ./web/js-dynamic/entities.js eeeef31f767f0aa3efb78bc44a2fea2b9eb86f4d4c50cf1ccae69b5ca30cdfda ./web/js-dynamic/events.js @@ -215,7 +215,7 @@ eeeef31f767f0aa3efb78bc44a2fea2b9eb86f4d4c50cf1ccae69b5ca30cdfda ./web/js-dynam 92d013bb5d64f64aa8c55380704540a5f72732bde7ccd16554965e401daf50ea ./web/js-dynamic/history.js 511c4e7cc4c48fbbdab64558a9d1c27e6759c9b6dca255d11f301b9708e955c7 ./web/js-dynamic/main.js 86031d4f7f7d1b46412c8fbb09ff1ad1b2b4cd84eb949bc749b27663f1dc27fa ./web/js-dynamic/navigation.js -799613c6d465cb2f92ecb57cb082d0c33729a03d88ab4ca7fa12a3cbd7e38e75 ./web/js-dynamic/realtime.js +0e398bad2cde85d4a62d8733c06e73f2b6a5b07db791d4570feba38c7ff8741f ./web/js-dynamic/realtime.js 1b667f0a8bce824b27f56a8d2f44ff8feef9a011289591dc629ee288db70d137 ./web/js-dynamic/router.js c2710fd9c1f2b31878c1e25ceb02d74ae30456c1bbb400e69fcf7619ecc72bc2 ./web/js-dynamic/select-ui.js bc42b4a0dd0d20239ce22ea1dff09b3f94e8c0e1395e01251a4585a051968a8f ./web/js-dynamic/settings-ui.js diff --git a/docs/API.md b/docs/API.md index 668da3c..d107769 100644 --- a/docs/API.md +++ b/docs/API.md @@ -1,6 +1,6 @@ # GREE Controller API reference -HTTP and WebSocket API for GREE Controller **0.15.0**. +HTTP and WebSocket API for GREE Controller **0.15.1**. [← Main documentation](../README.md) @@ -240,7 +240,7 @@ Response: { "status": "ok", "name": "gree-controller", - "version": "0.15.0", + "version": "0.15.1", "uptime_seconds": 1234, "control_ready": true, "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_revision": 42, "system": { - "version": "0.15.0", + "version": "0.15.1", "uptime_seconds": 1234, "auth_required": false, "control_ready": true, diff --git a/docs/openapi.json b/docs/openapi.json index 7df15e9..def16aa 100644 --- a/docs/openapi.json +++ b/docs/openapi.json @@ -2,9 +2,9 @@ "openapi": "3.1.0", "info": { "title": "GREE Controller API", - "version": "0.15.0", + "version": "0.15.1", "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 ` or `x-api-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.15.0\nAdds granular vertical/horizontal louver positions across direct control, thermostat views, legacy automations, Visual Flow and the bundled Home Assistant integration. Legacy boolean swing command payloads remain accepted. Direct add-on access now shows an invalid-token error only after an explicit token submission.\n\n### 0.14.24\nPublic Custom Charts now fetch chart metadata before language assets, use English for missing-chart errors, support pinch-to-zoom/panning and clickable metric legends, and include the related missing-ID, favicon and Access Token UX fixes.\n\n### 0.14.23\nCode cleanup and small UX changes.\n\n### 0.14.22\nCode cleanup and small UX changes.\n\n### 0.14.21\nCode cleanup and small UX changes.\n\n### 0.14.20\nFixes the ARM cross-build bootstrap by removing the invalid xx-cargo version probe, prepares the target Rust standard library in a cacheable pre-source layer, shares dependency fetching across target architectures, and isolates compiled target caches per architecture while preserving DISTRO-selected Alpine/musl and Debian Trixie/glibc runtimes.\n\n### 0.14.19\nHome Assistant OCI builds now compile Rust for amd64/arm64 on the native build platform through xx cross-compilation, keep Cargo registry/target caches between builds, and send a smaller Docker context while preserving the selected Alpine (musl) or Debian Trixie (glibc) runtime. The Web UI also deduplicates the initial GREE Cloud runtime-status GET across the HTTP and WebSocket bootstrap renders.\n\n### 0.14.18\nShared Web UI CSS now uses generic reusable class names for segmented tabs, configuration layouts, chart cards, enable toggles, diagram primitives and Flow block categories; behavior and visual styling are unchanged.\n\n### 0.14.17\nHistory navigation now reuses the same segmented tab component as Flow / Schedules / Automations, with redundant History-specific tab CSS removed.\n\n### 0.14.16\nCustom Charts now expose saved-chart editing in the Web UI, public chart pages can switch history range through an optional hours override, and the standalone chart layout fits the viewport without vertical page scrolling.\n\n### 0.14.15\nHome Assistant add-on Custom Chart links now resolve the primary HA host IPv4 through Supervisor, support an explicit public_chart_base_url override, and enforce the fixed 8787 ingress/application port contract at startup and build time. Standalone bind/port behavior remains configurable.\n\n### 0.14.14\nShared Flow input Home Assistant sources now expose a dedicated entity search box separate from the selected entity_id, making large live entity catalogs easy to filter by name, ID and state.\n\n### 0.14.13\nHome Assistant add-on authentication is now hidden behind an automatic Supervisor status, manual URL/token fallback is unlocked only after a failed HA test, connection tests return a live sample entity reading, and Shared Flow input HA sources include searchable live entity suggestions.\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.", + "description": "Self-hosted API used by the GREE Controller Web UI and Home Assistant integration.\n\n### Authentication\nAdministrator endpoints accept `Authorization: Bearer ` or `x-api-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.15.1\nImproves Web UI WebSocket state handling: temporary disconnects show a reconnecting state, persistent failures escalate after 15 seconds, and successful reconnects restore the connected state while the existing HTTP fallback remains active.\n\n### 0.15.0\nAdds granular vertical/horizontal louver positions across direct control, thermostat views, legacy automations, Visual Flow and the bundled Home Assistant integration. Legacy boolean swing command payloads remain accepted. Direct add-on access now shows an invalid-token error only after an explicit token submission.\n\n### 0.14.24\nPublic Custom Charts now fetch chart metadata before language assets, use English for missing-chart errors, support pinch-to-zoom/panning and clickable metric legends, and include the related missing-ID, favicon and Access Token UX fixes.\n\n### 0.14.23\nCode cleanup and small UX changes.\n\n### 0.14.22\nCode cleanup and small UX changes.\n\n### 0.14.21\nCode cleanup and small UX changes.\n\n### 0.14.20\nFixes the ARM cross-build bootstrap by removing the invalid xx-cargo version probe, prepares the target Rust standard library in a cacheable pre-source layer, shares dependency fetching across target architectures, and isolates compiled target caches per architecture while preserving DISTRO-selected Alpine/musl and Debian Trixie/glibc runtimes.\n\n### 0.14.19\nHome Assistant OCI builds now compile Rust for amd64/arm64 on the native build platform through xx cross-compilation, keep Cargo registry/target caches between builds, and send a smaller Docker context while preserving the selected Alpine (musl) or Debian Trixie (glibc) runtime. The Web UI also deduplicates the initial GREE Cloud runtime-status GET across the HTTP and WebSocket bootstrap renders.\n\n### 0.14.18\nShared Web UI CSS now uses generic reusable class names for segmented tabs, configuration layouts, chart cards, enable toggles, diagram primitives and Flow block categories; behavior and visual styling are unchanged.\n\n### 0.14.17\nHistory navigation now reuses the same segmented tab component as Flow / Schedules / Automations, with redundant History-specific tab CSS removed.\n\n### 0.14.16\nCustom Charts now expose saved-chart editing in the Web UI, public chart pages can switch history range through an optional hours override, and the standalone chart layout fits the viewport without vertical page scrolling.\n\n### 0.14.15\nHome Assistant add-on Custom Chart links now resolve the primary HA host IPv4 through Supervisor, support an explicit public_chart_base_url override, and enforce the fixed 8787 ingress/application port contract at startup and build time. Standalone bind/port behavior remains configurable.\n\n### 0.14.14\nShared Flow input Home Assistant sources now expose a dedicated entity search box separate from the selected entity_id, making large live entity catalogs easy to filter by name, ID and state.\n\n### 0.14.13\nHome Assistant add-on authentication is now hidden behind an automatic Supervisor status, manual URL/token fallback is unlocked only after a failed HA test, connection tests return a live sample entity reading, and Shared Flow input HA sources include searchable live entity suggestions.\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" } @@ -5900,7 +5900,7 @@ }, "version": { "type": "string", - "example": "0.15.0" + "example": "0.15.1" }, "uptime_seconds": { "type": "integer", diff --git a/ha-addon/home-assistant/custom_components/gree_controller/manifest.json b/ha-addon/home-assistant/custom_components/gree_controller/manifest.json index ee5b094..3b8d6aa 100644 --- a/ha-addon/home-assistant/custom_components/gree_controller/manifest.json +++ b/ha-addon/home-assistant/custom_components/gree_controller/manifest.json @@ -1,7 +1,7 @@ { "domain": "gree_controller", "name": "GREE Controller", - "version": "0.15.0", + "version": "0.15.1", "config_flow": true, "integration_type": "hub", "iot_class": "local_polling", diff --git a/ha-addon/repository/gree-controller/CHANGELOG.md b/ha-addon/repository/gree-controller/CHANGELOG.md index dc331d1..79b4d9b 100644 --- a/ha-addon/repository/gree-controller/CHANGELOG.md +++ b/ha-addon/repository/gree-controller/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.15.1 + +- Web UI now treats temporary WebSocket loss as a reconnecting state, escalates to a connection error only after 15 seconds, and returns cleanly to connected after recovery while preserving the existing HTTP fallback. + ## 0.15.0 - Adds full vertical and horizontal louver positions to manual unit control and thermostat cards, with compact dropdowns that preserve the existing view layout. diff --git a/ha-addon/repository/gree-controller/config.yaml b/ha-addon/repository/gree-controller/config.yaml index 9b0608a..918db40 100644 --- a/ha-addon/repository/gree-controller/config.yaml +++ b/ha-addon/repository/gree-controller/config.yaml @@ -1,5 +1,5 @@ name: "GREE Controller" -version: "0.15.0" +version: "0.15.1" 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/" diff --git a/lang/en.json b/lang/en.json index bfc82a8..30641a1 100644 --- a/lang/en.json +++ b/lang/en.json @@ -8,6 +8,7 @@ "translations": { "meta.description": "Local GREE air conditioner controller", "status.connecting": "Connecting…", + "status.reconnecting": "Reconnecting…", "status.connected": "Connected", "status.disconnected": "Disconnected", "status.connectionError": "Connection error", diff --git a/lang/pl.json b/lang/pl.json index ebd2717..8929626 100644 --- a/lang/pl.json +++ b/lang/pl.json @@ -8,6 +8,7 @@ "translations": { "meta.description": "Lokalny sterownik klimatyzatorów GREE", "status.connecting": "Łączenie…", + "status.reconnecting": "Ponowne łączenie…", "status.connected": "Połączono", "status.disconnected": "Rozłączono", "status.connectionError": "Błąd połączenia", diff --git a/web/css/styles.css b/web/css/styles.css index faa3f1e..a17ad6a 100644 --- a/web/css/styles.css +++ b/web/css/styles.css @@ -2918,7 +2918,8 @@ button.outside-pill:focus-visible { box-shadow: 0 0 0 3px rgba(239, 91, 91, .14), 0 0 10px rgba(239, 91, 91, .24); } -.connection-dot.connecting { +.connection-dot.connecting, +.connection-dot.reconnecting { background: #e2a93b; box-shadow: 0 0 0 3px rgba(226, 169, 59, .14); animation: connection-pulse 1.25s ease-in-out infinite; diff --git a/web/js-dynamic/core.js b/web/js-dynamic/core.js index 40c419a..81f6f68 100644 --- a/web/js-dynamic/core.js +++ b/web/js-dynamic/core.js @@ -26,7 +26,7 @@ const preferredTheme = ['system', 'light', 'dark'].includes(getCookie('gree_cont const app = { devices: [], zones: [], groups: [], deviceGroups: [], deviceGroupEnergy: {}, schedules: [], automations: [], flows: [], accessTokens: [], settings: null, system: {}, outdoorTemperature: null, - token: localStorage.getItem('gree_controller_token') || '', authTokenSubmitted: false, ws: null, wsTimer: null, + token: localStorage.getItem('gree_controller_token') || '', authTokenSubmitted: false, ws: null, wsTimer: null, wsErrorTimer: null, currentView: 'dashboard', loading: false, bootstrapReloadPending: false, language: preferredLanguage, theme: preferredTheme, connectionStatus: 'connecting', languages: [], translations: {}, locales: {}, defaultLanguage: DEFAULT_LANGUAGE, historyTab: 'overview', historyData: { zones: [], devices: [], sensors: [] }, historyCounts: {}, diff --git a/web/js-dynamic/realtime.js b/web/js-dynamic/realtime.js index 511d407..c627d76 100644 --- a/web/js-dynamic/realtime.js +++ b/web/js-dynamic/realtime.js @@ -131,17 +131,50 @@ async function handleWebSocketMessage(event) { } catch (_) { } } +const WS_RECONNECT_DELAY_MS = 3000; +const WS_CONNECTION_ERROR_DELAY_MS = 15000; + +function clearWebSocketErrorTimer() { + clearTimeout(app.wsErrorTimer); + app.wsErrorTimer = null; +} + +function startWebSocketErrorTimer() { + if (app.wsErrorTimer) return; + app.wsErrorTimer = setTimeout(() => { + app.wsErrorTimer = null; + if (!app.ws || app.ws.readyState !== WebSocket.OPEN) updateConnectionIndicator('connectionError'); + }, WS_CONNECTION_ERROR_DELAY_MS); +} + function connectWebSocket() { if (app.ws && [WebSocket.OPEN, WebSocket.CONNECTING].includes(app.ws.readyState)) return; clearTimeout(app.wsTimer); + app.wsTimer = null; const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:'; const query = app.token ? `?token=${encodeURIComponent(app.token)}` : ''; - const ws = new WebSocket(`${protocol}//${location.host}${withBase('/ws')}${query}`); app.ws = ws; - ws.onopen = () => updateConnectionIndicator('connected'); - ws.onclose = () => { app.controlPlanPushReady = false; updateConnectionIndicator('disconnected'); scheduleControlPlanLoad(0); app.wsTimer = setTimeout(connectWebSocket, 3000); }; - ws.onerror = () => updateConnectionIndicator('connectionError'); + const ws = new WebSocket(`${protocol}//${location.host}${withBase('/ws')}${query}`); + app.ws = ws; + ws.onopen = () => { + if (app.ws !== ws) return; + clearWebSocketErrorTimer(); + updateConnectionIndicator('connected'); + }; + ws.onclose = () => { + if (app.ws !== ws) return; + app.ws = null; + app.controlPlanPushReady = false; + if (app.connectionStatus !== 'connectionError') updateConnectionIndicator('reconnecting'); + startWebSocketErrorTimer(); + scheduleControlPlanLoad(0); + app.wsTimer = setTimeout(connectWebSocket, WS_RECONNECT_DELAY_MS); + }; + // onclose owns the visible connection state. A transient onerror must not + // present an application failure while HTTP fallback and reconnect still work. + ws.onerror = () => { }; let messageQueue = Promise.resolve(); ws.onmessage = event => { + if (app.ws !== ws) return; messageQueue = messageQueue.then(() => handleWebSocketMessage(event)).catch(() => { }); }; }