Add Aqara E1 thermostat entities to ZHA (#90158)
* Add Aqara E1 thermostat entities (WIP) * Remove calibrate button for now * Add diagnostic entity category to calibrated + external sensor * Add multiplier for ZHA config number/away preset temp * Set default multiplier correctly * Add and use `CONFIG_DIAGNOSTIC_MATCH` for diagnostic entities
This commit is contained in:
parent
8660035027
commit
12f49006cf
5 changed files with 121 additions and 4 deletions
|
@ -8,7 +8,7 @@ from homeassistant.components.binary_sensor import (
|
|||
BinarySensorEntity,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.const import EntityCategory, Platform
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
@ -39,6 +39,9 @@ CLASS_MAPPING = {
|
|||
|
||||
STRICT_MATCH = functools.partial(ZHA_ENTITIES.strict_match, Platform.BINARY_SENSOR)
|
||||
MULTI_MATCH = functools.partial(ZHA_ENTITIES.multipass_match, Platform.BINARY_SENSOR)
|
||||
CONFIG_DIAGNOSTIC_MATCH = functools.partial(
|
||||
ZHA_ENTITIES.config_diagnostic_match, Platform.BINARY_SENSOR
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
|
@ -201,3 +204,39 @@ class XiaomiPlugConsumerConnected(BinarySensor, id_suffix="consumer_connected"):
|
|||
SENSOR_ATTR = "consumer_connected"
|
||||
_attr_name: str = "Consumer connected"
|
||||
_attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.PLUG
|
||||
|
||||
|
||||
@MULTI_MATCH(channel_names="opple_cluster", models={"lumi.airrtc.agl001"})
|
||||
class AqaraThermostatWindowOpen(BinarySensor, id_suffix="window_open"):
|
||||
"""ZHA Aqara thermostat window open binary sensor."""
|
||||
|
||||
SENSOR_ATTR = "window_open"
|
||||
_attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.WINDOW
|
||||
_attr_name: str = "Window open"
|
||||
|
||||
|
||||
@MULTI_MATCH(channel_names="opple_cluster", models={"lumi.airrtc.agl001"})
|
||||
class AqaraThermostatValveAlarm(BinarySensor, id_suffix="valve_alarm"):
|
||||
"""ZHA Aqara thermostat valve alarm binary sensor."""
|
||||
|
||||
SENSOR_ATTR = "valve_alarm"
|
||||
_attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.PROBLEM
|
||||
_attr_name: str = "Valve alarm"
|
||||
|
||||
|
||||
@CONFIG_DIAGNOSTIC_MATCH(channel_names="opple_cluster", models={"lumi.airrtc.agl001"})
|
||||
class AqaraThermostatCalibrated(BinarySensor, id_suffix="calibrated"):
|
||||
"""ZHA Aqara thermostat calibrated binary sensor."""
|
||||
|
||||
SENSOR_ATTR = "calibrated"
|
||||
_attr_entity_category: EntityCategory = EntityCategory.DIAGNOSTIC
|
||||
_attr_name: str = "Calibrated"
|
||||
|
||||
|
||||
@CONFIG_DIAGNOSTIC_MATCH(channel_names="opple_cluster", models={"lumi.airrtc.agl001"})
|
||||
class AqaraThermostatExternalSensor(BinarySensor, id_suffix="sensor"):
|
||||
"""ZHA Aqara thermostat external sensor binary sensor."""
|
||||
|
||||
SENSOR_ATTR = "sensor"
|
||||
_attr_entity_category: EntityCategory = EntityCategory.DIAGNOSTIC
|
||||
_attr_name: str = "External sensor"
|
||||
|
|
|
@ -138,6 +138,20 @@ class OppleRemote(ZigbeeChannel):
|
|||
"serving_size": True,
|
||||
"portion_weight": True,
|
||||
}
|
||||
elif self.cluster.endpoint.model == "lumi.airrtc.agl001":
|
||||
self.ZCL_INIT_ATTRS = {
|
||||
"system_mode": True,
|
||||
"preset": True,
|
||||
"window_detection": True,
|
||||
"valve_detection": True,
|
||||
"valve_alarm": True,
|
||||
"child_lock": True,
|
||||
"away_preset_temperature": True,
|
||||
"window_open": True,
|
||||
"calibrated": True,
|
||||
"schedule": True,
|
||||
"sensor": True,
|
||||
}
|
||||
|
||||
async def async_initialize_channel_specific(self, from_cache: bool) -> None:
|
||||
"""Initialize channel specific."""
|
||||
|
|
|
@ -11,7 +11,7 @@ from zigpy.zcl.foundation import Status
|
|||
|
||||
from homeassistant.components.number import NumberEntity, NumberMode
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import EntityCategory, Platform, UnitOfMass
|
||||
from homeassistant.const import EntityCategory, Platform, UnitOfMass, UnitOfTemperature
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
@ -375,6 +375,7 @@ class ZHANumberConfigurationEntity(ZhaEntity, NumberEntity):
|
|||
|
||||
_attr_entity_category = EntityCategory.CONFIG
|
||||
_attr_native_step: float = 1.0
|
||||
_attr_multiplier: float = 1
|
||||
_zcl_attribute: str
|
||||
|
||||
@classmethod
|
||||
|
@ -417,13 +418,13 @@ class ZHANumberConfigurationEntity(ZhaEntity, NumberEntity):
|
|||
@property
|
||||
def native_value(self) -> float:
|
||||
"""Return the current value."""
|
||||
return self._channel.cluster.get(self._zcl_attribute)
|
||||
return self._channel.cluster.get(self._zcl_attribute) * self._attr_multiplier
|
||||
|
||||
async def async_set_native_value(self, value: float) -> None:
|
||||
"""Update the current value from HA."""
|
||||
try:
|
||||
res = await self._channel.cluster.write_attributes(
|
||||
{self._zcl_attribute: int(value)}
|
||||
{self._zcl_attribute: int(value / self._attr_multiplier)}
|
||||
)
|
||||
except zigpy.exceptions.ZigbeeException as ex:
|
||||
self.error("Could not set value: %s", ex)
|
||||
|
@ -861,3 +862,20 @@ class AqaraPetFeederPortionWeight(
|
|||
_attr_mode: NumberMode = NumberMode.BOX
|
||||
_attr_native_unit_of_measurement: str = UnitOfMass.GRAMS
|
||||
_attr_icon: str = "mdi:weight-gram"
|
||||
|
||||
|
||||
@CONFIG_DIAGNOSTIC_MATCH(channel_names="opple_cluster", models={"lumi.airrtc.agl001"})
|
||||
class AqaraThermostatAwayTemp(
|
||||
ZHANumberConfigurationEntity, id_suffix="away_preset_temperature"
|
||||
):
|
||||
"""Aqara away preset temperature configuration entity."""
|
||||
|
||||
_attr_entity_category = EntityCategory.CONFIG
|
||||
_attr_native_min_value: float = 5
|
||||
_attr_native_max_value: float = 30
|
||||
_attr_multiplier: float = 0.01
|
||||
_zcl_attribute: str = "away_preset_temperature"
|
||||
_attr_name: str = "Away preset temperature"
|
||||
_attr_mode: NumberMode = NumberMode.SLIDER
|
||||
_attr_native_unit_of_measurement: str = UnitOfTemperature.CELSIUS
|
||||
_attr_icon: str = ICONS[0]
|
||||
|
|
|
@ -503,3 +503,20 @@ class AqaraPetFeederMode(ZCLEnumSelectEntity, id_suffix="feeding_mode"):
|
|||
_enum = AqaraFeedingMode
|
||||
_attr_name = "Mode"
|
||||
_attr_icon: str = "mdi:wrench-clock"
|
||||
|
||||
|
||||
class AqaraThermostatPresetMode(types.enum8):
|
||||
"""Thermostat preset mode."""
|
||||
|
||||
Manual = 0x00
|
||||
Auto = 0x01
|
||||
Away = 0x02
|
||||
|
||||
|
||||
@CONFIG_DIAGNOSTIC_MATCH(channel_names="opple_cluster", models={"lumi.airrtc.agl001"})
|
||||
class AqaraThermostatPreset(ZCLEnumSelectEntity, id_suffix="preset"):
|
||||
"""Representation of an Aqara thermostat preset configuration entity."""
|
||||
|
||||
_select_attr = "preset"
|
||||
_enum = AqaraThermostatPresetMode
|
||||
_attr_name = "Preset"
|
||||
|
|
|
@ -477,3 +477,32 @@ class TuyaChildLockSwitch(ZHASwitchConfigurationEntity, id_suffix="child_lock"):
|
|||
_zcl_attribute: str = "child_lock"
|
||||
_attr_name = "Child lock"
|
||||
_attr_icon: str = "mdi:account-lock"
|
||||
|
||||
|
||||
@CONFIG_DIAGNOSTIC_MATCH(channel_names="opple_cluster", models={"lumi.airrtc.agl001"})
|
||||
class AqaraThermostatWindowDetection(
|
||||
ZHASwitchConfigurationEntity, id_suffix="window_detection"
|
||||
):
|
||||
"""Representation of an Aqara thermostat window detection configuration entity."""
|
||||
|
||||
_zcl_attribute: str = "window_detection"
|
||||
_attr_name = "Window detection"
|
||||
|
||||
|
||||
@CONFIG_DIAGNOSTIC_MATCH(channel_names="opple_cluster", models={"lumi.airrtc.agl001"})
|
||||
class AqaraThermostatValveDetection(
|
||||
ZHASwitchConfigurationEntity, id_suffix="valve_detection"
|
||||
):
|
||||
"""Representation of an Aqara thermostat valve detection configuration entity."""
|
||||
|
||||
_zcl_attribute: str = "valve_detection"
|
||||
_attr_name = "Valve detection"
|
||||
|
||||
|
||||
@CONFIG_DIAGNOSTIC_MATCH(channel_names="opple_cluster", models={"lumi.airrtc.agl001"})
|
||||
class AqaraThermostatChildLock(ZHASwitchConfigurationEntity, id_suffix="child_lock"):
|
||||
"""Representation of an Aqara thermostat child lock configuration entity."""
|
||||
|
||||
_zcl_attribute: str = "child_lock"
|
||||
_attr_name = "Child lock"
|
||||
_attr_icon: str = "mdi:account-lock"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue