This commit is contained in:
Mateusz Gruszczyński
2026-08-24 23:58:44 +02:00
parent 9191fba212
commit 25e1a854e3
9 changed files with 71 additions and 17 deletions
+10 -2
View File
@@ -1,8 +1,8 @@
# GREE Controller v0.6.3 - build and validation report
# GREE Controller v0.6.4 - build and validation report
## Scope
Version 0.6.3 includes the notification, reverse-proxy, mobile decimal-input, log filtering and thermostat-copy changes described below, the Rust type-safety hotfix for communication-failure notifications, and a clearer persistent visual state for the selected house climate mode.
Version 0.6.4 includes the notification, reverse-proxy, mobile decimal-input, log filtering and thermostat-copy changes described below, the Rust type-safety hotfix for communication-failure notifications, and a clearer persistent visual state for the selected house climate mode.
## Implemented changes
@@ -114,3 +114,11 @@ Validation performed in the build environment:
- The selected whole-house climate mode (Cool / Heat / Off) now has a persistent illuminated border, accent fill and glowing status dot.
- The active mode is still derived from persisted `settings.house_mode`, so the highlight survives refreshes and reconnects.
- Mode buttons now expose `aria-pressed` for an explicit accessible selected state.
## 0.6.4 Home Assistant zone thermostat naming
- Zone climate entities now use a descriptive entity name, `Thermostat`.
- New zone entities are therefore created as `climate.<zone_name>_thermostat` instead of falling back to ambiguous numeric suffixes such as `_2`.
- Existing zone climate registry entries are migrated on integration reload to the same scheme based on the zone's current name, fixing stale IDs left after zone renames (for example `climate.jan_2` for a zone currently named Igor).
- Migration is collision-safe: if the desired `climate.<zone_name>_thermostat` ID is already occupied, the existing entity ID is retained and a warning is logged instead of overwriting another entity.
Generated
+1 -1
View File
@@ -633,7 +633,7 @@ dependencies = [
[[package]]
name = "gree-controller"
version = "0.6.3"
version = "0.6.4"
dependencies = [
"aes",
"aes-gcm",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "gree-controller"
version = "0.6.3"
version = "0.6.4"
edition = "2021"
authors = ["GREE Controller contributors"]
description = "Standalone local GREE HVAC controller with Web UI, SQLite and Home Assistant sensor support"
+8 -8
View File
@@ -1,10 +1,10 @@
623bd769512ef75f51e9bf7fb685d4d59ec84d7ccc75c826fe72c5538be737c5 ./.env.example
a4ec3874a2e3ab1bad28fb40bb620f7b01f64d01ad9b699306bf70ada31227db ./.gitignore
afa44c1b588eddb83ad1300e62ef320bf0264ff05f19c53d42a761a8046c97b4 ./BUILD_REPORT.md
98bf4f4c86d8c6384ca55fac266f9ccae812680ebc6536063194e369669de627 ./Cargo.lock
0971917d970910ff09b0164a36e0c8f32b270ad3115a01a5bf4a53798c1e1854 ./Cargo.toml
58037959419a8de25bcf9095b020bc3ab4c1559b975764f8d24b6359ad063ad6 ./BUILD_REPORT.md
436fd46220ef759d8204f24bdd94157c965cc39976b0f9baa79cebb367ee5c85 ./Cargo.lock
53f3f794080df48e11f5726678f7817c225ab64001dd1081d48c5aa780b2a7d0 ./Cargo.toml
19b2943504acb8f8de280f873a8dbec4bb6ebbe3870b158f5655d4fb8c298f5f ./LICENSE
58471cab1a26e1212864a497e9e7b2730d849b7dd175dec7458a5a69dec1eadb ./README.md
be12639245e0929b12d11946b58c1d74f261733724bc4096a9ac68b12df30f24 ./README.md
f2c8eb28fedb26bb8f5636e1805e7a782cc472b87d882f6752d520f16216a248 ./build.rs
674f8cf1ab9f1a49188e20b8e3977f1e2b7e9b8ef975315266730c44a55bbb48 ./docs/API.md
234dd200e380a13ecd3e61b4ea455f6f08d64ce89382077dee80684acadb9703 ./docs/HOME_ASSISTANT_MIGRATION.md
@@ -13,17 +13,17 @@ f2c8eb28fedb26bb8f5636e1805e7a782cc472b87d882f6752d520f16216a248 ./build.rs
47e18e6b1723f1f6eb2516be6d83bbebd31b8155d9d3cdfccc0973177f3d8441 ./docs/PROJECT_SPEC.md
7748b1230029439a405139750b2e0607b8e463bfd56ad86982394105069697c5 ./docs/REVERSE_PROXY.md
28f1403d84b01b37bebb72548aa39a75bb14bdbb611a43bfa761319957cd6f39 ./docs/SECURITY.md
925ffa324b1b2cfad7ca40354e8255548f70627f95c4bb345b957d3f7e53694c ./home-assistant/README.md
38ac4aec7b971ae7df8db77faf5f9cb9702710ddf9a97def448fbe9e9ff138b1 ./home-assistant/README.md
f8e8559fe10fe523ac5bc9aac25c6e26e862f679d502e8f3c39f38a0a8e40911 ./home-assistant/custom_components/gree_controller/__init__.py
b8e7c0dd722bfac1d1d8d5c2a4b5ff6b2d6fa89525b9ff5c121ee1d09623a7fd ./home-assistant/custom_components/gree_controller/api.py
b0314469ddb7c69ee4a96c677815af30cb97713e93911a05597f2fdc3d10f489 ./home-assistant/custom_components/gree_controller/climate.py
abcca32b090e5a5d02574a3a340e97321f9879ae6c94ef12eb1f42d967eae2d5 ./home-assistant/custom_components/gree_controller/climate.py
5e4aef2143e81bedb5a15dd4be5c71b64a3ab448ec6d33a20851edd098e5f529 ./home-assistant/custom_components/gree_controller/config_flow.py
071f721b75af2ed68812c9be3a62b7ae63771e56e567a569f59ca976f8ff42f1 ./home-assistant/custom_components/gree_controller/const.py
8dd51322798cad28d4d19938fe459aa2a4d3b64b075532149f3c8b62049a6c8b ./home-assistant/custom_components/gree_controller/coordinator.py
5a96fe8f5c035c34f1339370270cd078056202d09e236dec75735be11de92a7d ./home-assistant/custom_components/gree_controller/entity_map.py
c4fb75c246db651087900ebfc2291ff41ac87652cd6194fc0b776b0005c1cbcf ./home-assistant/custom_components/gree_controller/icon.png
c4fb75c246db651087900ebfc2291ff41ac87652cd6194fc0b776b0005c1cbcf ./home-assistant/custom_components/gree_controller/logo.png
a789da0f9f7178916227aa1a52575687090c8e82b463a53f1e16edb13f44599c ./home-assistant/custom_components/gree_controller/manifest.json
0247514d881e563e45d272dbd10f2363ded1f3fb11b307a6ad9a0566dcff3648 ./home-assistant/custom_components/gree_controller/manifest.json
d0206766d76f70ea1c75a618e41bf1e8e8c0429f42ee97f40daac1ea12f16658 ./home-assistant/custom_components/gree_controller/number.py
5c914c2faa18a9cb9eb442dc111c9416f89a630578f820beb021d5381aa1b2d0 ./home-assistant/custom_components/gree_controller/sensor.py
7c23374d1c82e4b361089386ff89265322b80def0f4db9d3fd2c039867033105 ./home-assistant/custom_components/gree_controller/switch.py
@@ -66,5 +66,5 @@ e98bdd7204349cce1ec6f57283509697af0bbc72280622a6c3efa6fed242db4f ./web/favicon.
002c172392a00006a5128fc4cb881b0361a2d3e76298dbd80c0a013f4e1f9dde ./web/index.html
fd26156e9f1d6713d3def564ad000553d9a16a24376059701db2ee762c99ee6c ./web/manifest.webmanifest
80ea1c50c3729adb4dd392b12d73b4247659a8b6b948ee76bd2f5df213eae918 ./web/styles.css
b82ee4b915076be30211bc260a9bc33117e5b1890bde7f37ac45aa28d7a7cafe ./web/sw.js
03fdeecaa4c68308668c09077e5390286c27d2a8e296367bec6b002fb9b8b3e8 ./web/sw.js
d505d793ce7cc9485b45b78bba1c0d51887adc7451ab59a42702946e5b991382 ./web/theme-init.js
+2 -2
View File
@@ -4,7 +4,7 @@
Standalone local GREE air-conditioner controller written in Rust. It runs on a regular Linux host or an LXC container and provides a mobile-first web interface without depending on the vendor cloud.
Current version: **0.6.3**.
Current version: **0.6.4**.
## Highlights
@@ -46,7 +46,7 @@ See [`BUILD_REPORT.md`](BUILD_REPORT.md) for package validation details and [`do
On Debian, Ubuntu or an LXC container:
```bash
unzip gree-controller-v0.6.3.zip
unzip gree-controller-v0.6.4.zip
cd gree-controller
chmod +x scripts/*.sh
./scripts/dev.sh
+2
View File
@@ -122,5 +122,7 @@ The recommended `combined` strategy keeps the GREE sensor as the primary input a
Each controller zone is exposed as a full Home Assistant `climate` entity with current/target temperature and HVAC modes: Off, Auto (follow the controller house mode), Cool and Heat. The existing zone target `number` and enabled `switch` remain available for compatibility.
From version 0.6.4, zone climate entities use `climate.<zone_name>_thermostat`, for example `climate.igor_thermostat`. On integration reload, existing zone climate registry entries are migrated to this scheme using the zone's current name. If the target entity ID is already occupied, the old ID is retained and Home Assistant logs a warning.
When the controller detects optional GREE properties, the integration also creates switches for supported features such as panel light, Quiet, Turbo, X-FAN, Air, Health and native Sleep. Reload the integration (or restart Home Assistant) after upgrading so newly added entity types are created.
@@ -20,6 +20,7 @@ from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from homeassistant.util import slugify
from . import GreeControllerRuntimeData
from .const import DOMAIN
@@ -73,11 +74,54 @@ async def async_setup_entry(
for zone in runtime.coordinator.plan.get("zones", []):
zone_id = str(zone.get("zone_id") or "").strip()
if zone_id:
_ensure_zone_thermostat_entity_id(registry, zone)
entities.append(GreeControllerZoneClimate(runtime.coordinator, zone_id))
async_add_entities(entities)
def _ensure_zone_thermostat_entity_id(
registry: er.EntityRegistry, zone: dict[str, Any]
) -> None:
"""Keep zone climate entity IDs stable and descriptive.
Zone climate entities use ``climate.<zone_name>_thermostat``. Existing
registry entries are migrated to the same scheme, which also fixes stale
IDs left behind after a zone was renamed (for example ``climate.jan_2``
for a zone currently named Igor).
"""
zone_id = str(zone.get("zone_id") or "").strip()
if not zone_id:
return
unique_id = f"{zone_id}-zone-climate"
current_entity_id = registry.async_get_entity_id("climate", DOMAIN, unique_id)
if current_entity_id is None:
return
zone_name = str(zone.get("zone_name") or zone_id).strip() or zone_id
object_id = slugify(zone_name) or slugify(zone_id) or "zone"
desired_entity_id = f"climate.{object_id}_thermostat"
if current_entity_id == desired_entity_id:
return
occupied = registry.async_get(desired_entity_id)
if occupied is not None and occupied.entity_id != current_entity_id:
_LOGGER.warning(
"Cannot rename zone thermostat %s to %s because that entity ID is already in use",
current_entity_id,
desired_entity_id,
)
return
registry.async_update_entity(current_entity_id, new_entity_id=desired_entity_id)
_LOGGER.info(
"Renamed zone thermostat entity %s to %s",
current_entity_id,
desired_entity_id,
)
class GreeControllerClimate(CoordinatorEntity[GreeControllerCoordinator], ClimateEntity):
"""Home Assistant climate entity controlled through the Rust service."""
@@ -216,7 +260,7 @@ class GreeControllerZoneClimate(CoordinatorEntity[GreeControllerCoordinator], Cl
"""Full climate entity for a controller thermostat zone."""
_attr_has_entity_name = True
_attr_name = None
_attr_name = "Thermostat"
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_attr_min_temp = 8.0
_attr_max_temp = 30.0
@@ -1,7 +1,7 @@
{
"domain": "gree_controller",
"name": "GREE Controller",
"version": "0.6.3",
"version": "0.6.4",
"config_flow": true,
"integration_type": "hub",
"iot_class": "local_polling",
+1 -1
View File
@@ -1,4 +1,4 @@
const CACHE = 'gree-controller-v063';
const CACHE = 'gree-controller-v064';
const SCOPE = new URL(self.registration.scope).pathname.replace(/\/$/, '');
const path = value => `${SCOPE}${value.startsWith('/') ? value : `/${value}`}` || '/';
const ASSETS = [path('/'), path('/styles.css'), path('/app.js'), path('/theme-init.js'), path('/favicon.svg'), path('/manifest.webmanifest'), path('/lang/index.json'), path('/lang/en.json')];