Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion zhaquirks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,29 @@ class LocalDataCluster(CustomCluster):
"""Cluster meant to prevent remote calls.

Set _CONSTANT_ATTRIBUTES to provide constant values for attribute ids.
Set _DEFAULT_VALUES to provide default values for attribute ids. These are
returned when no value is cached yet, but are overridden by any cached value.
Set _VALID_ATTRIBUTES to provide a list of valid attribute ids that will never be shown as unsupported.
These are attributes that should be populated later.
"""

_CONSTANT_ATTRIBUTES: dict[int, typing.Any] = {}
_DEFAULT_VALUES: dict[int, typing.Any] = {}
_VALID_ATTRIBUTES: set[int] = set()

def get(self, key: int | str, default: typing.Any | None = None) -> typing.Any:
"""Get cached attribute, falling back to _DEFAULT_VALUES then default."""
result = super().get(key)
if result is not None:
return result
try:
attr_def = self.find_attribute(key)
except KeyError:
return default
if attr_def.id in self._DEFAULT_VALUES:
return self._DEFAULT_VALUES[attr_def.id]
return default

async def bind(self):
"""Prevent bind."""
self.debug("binding LocalDataCluster")
Expand Down Expand Up @@ -101,7 +117,9 @@ async def read_attributes_raw(self, attributes, manufacturer=None, **kwargs):
if record.attrid in self._CONSTANT_ATTRIBUTES:
record.value.value = self._CONSTANT_ATTRIBUTES[record.attrid]
else:
record.value.value = self._attr_cache.get(record.attrid)
record.value.value = self._attr_cache.get(
record.attrid, self._DEFAULT_VALUES.get(record.attrid)
)
if (
record.value.value is not None
or record.attrid in self._VALID_ATTRIBUTES
Expand Down
31 changes: 11 additions & 20 deletions zhaquirks/xiaomi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -691,17 +691,14 @@ class ElectricalMeasurementCluster(LocalDataCluster, ElectricalMeasurement):
ElectricalMeasurement.AttributeDefs.ac_power_divisor.id: 10,
}

_DEFAULT_VALUES = {
ElectricalMeasurement.AttributeDefs.active_power.id: 0,
ElectricalMeasurement.AttributeDefs.rms_voltage.id: 0,
}

def __init__(self, *args, **kwargs):
"""Init."""
super().__init__(*args, **kwargs)
# put a default value so the sensors are created
if self.POWER_ID not in self._attr_cache:
self._update_attribute(self.POWER_ID, 0)
if self.VOLTAGE_ID not in self._attr_cache:
self._update_attribute(self.VOLTAGE_ID, 0)
if self.CONSUMPTION_ID not in self._attr_cache:
self._update_attribute(self.CONSUMPTION_ID, 0)

# Previously, this cluster was wrongly setting the total_active_power attribute,
# which was not added to HA.
# Since it is now added to HA and the incorrect value could be set, we need to
Expand All @@ -723,12 +720,9 @@ class MeteringCluster(LocalDataCluster, Metering):
Metering.AttributeDefs.metering_device_type.id: 0, # electric
}

def __init__(self, *args, **kwargs):
"""Init."""
super().__init__(*args, **kwargs)
# put a default value so the sensor is created
if self.CURRENT_SUMM_DELIVERED_ID not in self._attr_cache:
self._update_attribute(self.CURRENT_SUMM_DELIVERED_ID, 0)
_DEFAULT_VALUES = {
Metering.AttributeDefs.current_summ_delivered.id: 0,
}


class IlluminanceMeasurementCluster(CustomCluster, IlluminanceMeasurement):
Expand All @@ -745,12 +739,9 @@ class LocalIlluminanceMeasurementCluster(
):
"""Illuminance measurement cluster based on LocalDataCluster."""

def __init__(self, *args, **kwargs):
"""Init."""
super().__init__(*args, **kwargs)
if self.AttributeDefs.measured_value.id not in self._attr_cache:
# put a default value so the sensor is created
self._update_attribute(self.AttributeDefs.measured_value.id, 0)
_DEFAULT_VALUES = {
IlluminanceMeasurement.AttributeDefs.measured_value.id: 0,
}


class OnOffCluster(OnOff, CustomCluster):
Expand Down
Loading