From 8df8f957109e899b4d67f68933fb1fbd7458a088 Mon Sep 17 00:00:00 2001 From: Joee Date: Sat, 6 Jan 2024 10:43:21 +0800 Subject: [PATCH 1/3] fix climate device setup error and support Scdvb HAVC --- custom_components/xiaomi_gateway3/climate.py | 64 ++++++++++++++++++- .../core/converters/devices.py | 9 +++ 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/custom_components/xiaomi_gateway3/climate.py b/custom_components/xiaomi_gateway3/climate.py index b3fbe0a3..791df6b2 100644 --- a/custom_components/xiaomi_gateway3/climate.py +++ b/custom_components/xiaomi_gateway3/climate.py @@ -23,6 +23,8 @@ HVACMode.OFF: HVACAction.OFF, HVACMode.COOL: HVACAction.COOLING, HVACMode.HEAT: HVACAction.HEATING, + HVACMode.DRY: HVACAction.DRYING, + HVACMode.FAN_ONLY: HVACAction.FAN, } @@ -32,6 +34,8 @@ async def async_setup_entry( def new_entity(gateway: XGateway, device: XDevice, conv: Converter) -> XEntity: if conv.mi == "4.21.85": return AqaraE1(gateway, device, conv) + if device.model == 14050: + return ScdvbHAVC(gateway, device, conv) else: return XiaomiClimate(gateway, device, conv) @@ -46,9 +50,7 @@ class XiaomiClimate(XEntity, ClimateEntity): _attr_hvac_mode = None _attr_hvac_modes = [HVACMode.OFF, HVACMode.COOL, HVACMode.HEAT] _attr_precision = PRECISION_WHOLE - _attr_supported_features = ( - ClimateEntityFeature.TARGET_TEMPERATURE_RANGE | ClimateEntityFeature.FAN_MODE - ) + _attr_supported_features = ClimateEntityFeature.FAN_MODE _attr_temperature_unit = UnitOfTemperature.CELSIUS # support only KTWKQ03ES for now _attr_max_temp = 30 @@ -128,3 +130,59 @@ async def async_set_hvac_mode(self, hvac_mode: str) -> None: else: return await self.device_send(payload) + +class ScdvbHAVC(XEntity, ClimateEntity): + _attr_fan_mode = None + _attr_fan_modes = [FAN_LOW, FAN_MEDIUM, FAN_HIGH, FAN_AUTO] + _attr_hvac_mode = None + _attr_hvac_modes = [HVACMode.OFF, HVACMode.COOL, HVACMode.HEAT, HVACMode.AUTO, HVACMode.DRY, HVACMode.FAN_ONLY] + _attr_precision = PRECISION_WHOLE + _attr_supported_features = ClimateEntityFeature.FAN_MODE + _attr_temperature_unit = UnitOfTemperature.CELSIUS + _attr_max_temp = 32 + _attr_min_temp = 16 + _attr_target_temperature_step = 1 + + _enabled = None + _mode = None + @callback + def async_set_state(self, data: dict): + if "climate" in data: + self._enabled = data["climate"] + if "hvac_mode" in data: + self._mode = data["hvac_mode"] + if "fan_mode" in data: + self._attr_fan_mode = data["fan_mode"] + if "current_temp" in data: + self._attr_current_temperature = data["current_temp"] + if "target_temp" in data: + self._attr_target_temperature = data["target_temp"] + + if self._enabled is None or self._mode is None: + return + + self._attr_hvac_mode = self._mode if self._enabled else HVACMode.OFF + async def async_update(self): + await self.device_read(self.subscribed_attrs) + + async def async_set_temperature(self, **kwargs) -> None: + if kwargs[ATTR_TEMPERATURE] == 0: + return + await self.device_send({"target_temp": kwargs[ATTR_TEMPERATURE]}) + + async def async_set_fan_mode(self, fan_mode: str) -> None: + if not self._enabled: + await self.device_send({"climate": True}) + self._attr_hvac_mode = self._mode + await self.device_send({"fan_mode": fan_mode}) + + async def async_set_hvac_mode(self, hvac_mode: str) -> None: + if hvac_mode == HVACMode.OFF: + await self.device_send({"climate": False}) + else: + if not self._enabled: + await self.device_send({"climate": True}) + # better support HomeKit + if hvac_mode == HVACMode.AUTO: + hvac_mode = self._mode + await self.device_send({"hvac_mode": hvac_mode}) \ No newline at end of file diff --git a/custom_components/xiaomi_gateway3/core/converters/devices.py b/custom_components/xiaomi_gateway3/core/converters/devices.py index d9955d7d..efb5efae 100644 --- a/custom_components/xiaomi_gateway3/core/converters/devices.py +++ b/custom_components/xiaomi_gateway3/core/converters/devices.py @@ -3228,6 +3228,15 @@ 0: "follow_switch", 1: "opposite_to_switch", 2: "off", 3: "on" }) ] +}, { + 14050: ["Scdvb", "Air Conditioner", "scdvb.aircondition.acm"], + "spec": [ + Converter("climate", "climate", mi="2.p.1"), + MapConv("hvac_mode", mi="2.p.2", map={0: "cool", 1: "heat", 2: "fan_only", 3: "dry"}, parent="climate"), + MapConv("fan_mode", mi="3.p.1", map={0: "auto", 1: "low", 2: "medium", 3: "high"}, parent="climate"), + Converter("current_temp", mi="4.p.1", parent="climate"), + Converter("target_temp", mi="2.p.3", parent="climate"), + ], }, { "default": "mesh", # default Mesh device "spec": [ From 05bd80c79c0c330076f86ede6d29c4a85ae41783 Mon Sep 17 00:00:00 2001 From: Joee Date: Sun, 14 Jan 2024 17:26:48 +0800 Subject: [PATCH 2/3] fix support TARGET_TEMPERATURE --- custom_components/xiaomi_gateway3/climate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/xiaomi_gateway3/climate.py b/custom_components/xiaomi_gateway3/climate.py index 791df6b2..ab0ebda8 100644 --- a/custom_components/xiaomi_gateway3/climate.py +++ b/custom_components/xiaomi_gateway3/climate.py @@ -50,7 +50,7 @@ class XiaomiClimate(XEntity, ClimateEntity): _attr_hvac_mode = None _attr_hvac_modes = [HVACMode.OFF, HVACMode.COOL, HVACMode.HEAT] _attr_precision = PRECISION_WHOLE - _attr_supported_features = ClimateEntityFeature.FAN_MODE + _attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.FAN_MODE _attr_temperature_unit = UnitOfTemperature.CELSIUS # support only KTWKQ03ES for now _attr_max_temp = 30 @@ -137,7 +137,7 @@ class ScdvbHAVC(XEntity, ClimateEntity): _attr_hvac_mode = None _attr_hvac_modes = [HVACMode.OFF, HVACMode.COOL, HVACMode.HEAT, HVACMode.AUTO, HVACMode.DRY, HVACMode.FAN_ONLY] _attr_precision = PRECISION_WHOLE - _attr_supported_features = ClimateEntityFeature.FAN_MODE + _attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.FAN_MODE _attr_temperature_unit = UnitOfTemperature.CELSIUS _attr_max_temp = 32 _attr_min_temp = 16 From 1431109bf2525be129f31f1a0a8b5bd3954fdf41 Mon Sep 17 00:00:00 2001 From: Joee Date: Wed, 31 Jan 2024 20:24:22 +0800 Subject: [PATCH 3/3] fix lumi.airrtc.tcpecn02 OFF status issue --- custom_components/xiaomi_gateway3/climate.py | 5 +++++ custom_components/xiaomi_gateway3/core/converters/devices.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/custom_components/xiaomi_gateway3/climate.py b/custom_components/xiaomi_gateway3/climate.py index ab0ebda8..4025f8ae 100644 --- a/custom_components/xiaomi_gateway3/climate.py +++ b/custom_components/xiaomi_gateway3/climate.py @@ -56,18 +56,23 @@ class XiaomiClimate(XEntity, ClimateEntity): _attr_max_temp = 30 _attr_min_temp = 17 _attr_target_temperature_step = 1 + _enabled = None + _mode = None @callback def async_set_state(self, data: dict): + self._enabled = data.get("power") self._attr_current_temperature = data.get("current_temp") self._attr_fan_mode = data.get("fan_mode") self._attr_hvac_mode = data.get("hvac_mode") + self._mode = data.get("hvac_mode") # better support HomeKit # https://github.com/AlexxIT/XiaomiGateway3/issues/707#issuecomment-1099109552 self._attr_hvac_action = ACTIONS.get(self._attr_hvac_mode) # fix scenes with turned off climate # https://github.com/AlexxIT/XiaomiGateway3/issues/101#issuecomment-757781988 self._attr_target_temperature = data.get("target_temp", 0) + self._attr_hvac_mode = self._mode if self._enabled else HVACMode.OFF async def async_update(self): await self.device_read(self.subscribed_attrs) diff --git a/custom_components/xiaomi_gateway3/core/converters/devices.py b/custom_components/xiaomi_gateway3/core/converters/devices.py index efb5efae..b8aeda9b 100644 --- a/custom_components/xiaomi_gateway3/core/converters/devices.py +++ b/custom_components/xiaomi_gateway3/core/converters/devices.py @@ -463,8 +463,8 @@ # https://github.com/AlexxIT/XiaomiGateway3/issues/101 "lumi.airrtc.tcpecn02": ["Aqara", "Thermostat S2 CN", "KTWKQ03ES"], "spec": [ - # BoolConv("power", mi="3.1.85", xiaomi="power_status"), ClimateConv("climate", "climate", mi="14.2.85"), + BoolConv("power", mi="3.1.85"), Converter("current_temp", mi="3.2.85"), MapConv("hvac_mode", mi="14.8.85", map={0: "heat", 1: "cool", 15: "off"}), MapConv("fan_mode", mi="14.10.85", map={