Add tier summation delivered for Lixee Zlinky TIC (#82602)

* Add tier summation delivered for zlinky

* Improve name case

* Add other tiers and register tier

* Fix smartenergy sensor update

* Account for new reporting configuration in unit tests

* Use cluster ID attributes instead of hardcoding the values

* Use tier names instead of the numeric constants for formatter

* Revert active register tier delivered

* Fix tests

Co-authored-by: puddly <32534428+puddly@users.noreply.github.com>
This commit is contained in:
Paul Bottein 2023-01-16 16:33:18 +01:00 committed by GitHub
parent 83591704b5
commit c3e27f6812
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 186 additions and 43 deletions

View file

@ -68,6 +68,24 @@ class Metering(ZigbeeChannel):
REPORT_CONFIG = (
AttrReportConfig(attr="instantaneous_demand", config=REPORT_CONFIG_OP),
AttrReportConfig(attr="current_summ_delivered", config=REPORT_CONFIG_DEFAULT),
AttrReportConfig(
attr="current_tier1_summ_delivered", config=REPORT_CONFIG_DEFAULT
),
AttrReportConfig(
attr="current_tier2_summ_delivered", config=REPORT_CONFIG_DEFAULT
),
AttrReportConfig(
attr="current_tier3_summ_delivered", config=REPORT_CONFIG_DEFAULT
),
AttrReportConfig(
attr="current_tier4_summ_delivered", config=REPORT_CONFIG_DEFAULT
),
AttrReportConfig(
attr="current_tier5_summ_delivered", config=REPORT_CONFIG_DEFAULT
),
AttrReportConfig(
attr="current_tier6_summ_delivered", config=REPORT_CONFIG_DEFAULT
),
AttrReportConfig(attr="status", config=REPORT_CONFIG_ASAP),
)
ZCL_INIT_ATTRS = {

View file

@ -1,6 +1,7 @@
"""Sensors on Zigbee Home Automation networks."""
from __future__ import annotations
import enum
import functools
import numbers
from typing import TYPE_CHECKING, Any, TypeVar
@ -174,7 +175,7 @@ class Sensor(ZhaEntity, SensorEntity):
"""Handle state update from channel."""
self.async_write_ha_state()
def formatter(self, value: int) -> int | float | None:
def formatter(self, value: int | enum.IntEnum) -> int | float | str | None:
"""Numeric pass-through formatter."""
if self._decimals > 0:
return round(
@ -495,7 +496,7 @@ class SmartEnergySummation(SmartEnergyMetering, id_suffix="summation_delivered")
@MULTI_MATCH(
channel_names=CHANNEL_SMARTENERGY_METERING,
models={"TS011F"},
models={"TS011F", "ZLinky_TIC"},
stop_on_match_group=CHANNEL_SMARTENERGY_METERING,
)
class PolledSmartEnergySummation(SmartEnergySummation):
@ -510,6 +511,84 @@ class PolledSmartEnergySummation(SmartEnergySummation):
await self._channel.async_force_update()
@MULTI_MATCH(
channel_names=CHANNEL_SMARTENERGY_METERING,
models={"ZLinky_TIC"},
)
class Tier1SmartEnergySummation(
SmartEnergySummation, id_suffix="tier1_summation_delivered"
):
"""Tier 1 Smart Energy Metering summation sensor."""
SENSOR_ATTR: int | str = "current_tier1_summ_delivered"
_attr_name: str = "Tier 1 summation delivered"
@MULTI_MATCH(
channel_names=CHANNEL_SMARTENERGY_METERING,
models={"ZLinky_TIC"},
)
class Tier2SmartEnergySummation(
SmartEnergySummation, id_suffix="tier2_summation_delivered"
):
"""Tier 2 Smart Energy Metering summation sensor."""
SENSOR_ATTR: int | str = "current_tier2_summ_delivered"
_attr_name: str = "Tier 2 summation delivered"
@MULTI_MATCH(
channel_names=CHANNEL_SMARTENERGY_METERING,
models={"ZLinky_TIC"},
)
class Tier3SmartEnergySummation(
SmartEnergySummation, id_suffix="tier3_summation_delivered"
):
"""Tier 3 Smart Energy Metering summation sensor."""
SENSOR_ATTR: int | str = "current_tier3_summ_delivered"
_attr_name: str = "Tier 3 summation delivered"
@MULTI_MATCH(
channel_names=CHANNEL_SMARTENERGY_METERING,
models={"ZLinky_TIC"},
)
class Tier4SmartEnergySummation(
SmartEnergySummation, id_suffix="tier4_summation_delivered"
):
"""Tier 4 Smart Energy Metering summation sensor."""
SENSOR_ATTR: int | str = "current_tier4_summ_delivered"
_attr_name: str = "Tier 4 summation delivered"
@MULTI_MATCH(
channel_names=CHANNEL_SMARTENERGY_METERING,
models={"ZLinky_TIC"},
)
class Tier5SmartEnergySummation(
SmartEnergySummation, id_suffix="tier5_summation_delivered"
):
"""Tier 5 Smart Energy Metering summation sensor."""
SENSOR_ATTR: int | str = "current_tier5_summ_delivered"
_attr_name: str = "Tier 5 summation delivered"
@MULTI_MATCH(
channel_names=CHANNEL_SMARTENERGY_METERING,
models={"ZLinky_TIC"},
)
class Tier6SmartEnergySummation(
SmartEnergySummation, id_suffix="tier6_summation_delivered"
):
"""Tier 6 Smart Energy Metering summation sensor."""
SENSOR_ATTR: int | str = "current_tier6_summ_delivered"
_attr_name: str = "Tier 6 summation delivered"
@MULTI_MATCH(channel_names=CHANNEL_PRESSURE)
class Pressure(Sensor):
"""Pressure sensor."""

View file

@ -106,35 +106,43 @@ async def poll_control_device(zha_device_restored, zigpy_device_mock):
@pytest.mark.parametrize(
"cluster_id, bind_count, attrs",
[
(0x0000, 0, {}),
(0x0001, 1, {"battery_voltage", "battery_percentage_remaining"}),
(0x0002, 1, {"current_temperature"}),
(0x0003, 0, {}),
(0x0004, 0, {}),
(0x0005, 1, {}),
(0x0006, 1, {"on_off"}),
(0x0007, 1, {}),
(0x0008, 1, {"current_level"}),
(0x0009, 1, {}),
(0x000C, 1, {"present_value"}),
(0x000D, 1, {"present_value"}),
(0x000E, 1, {"present_value"}),
(0x000D, 1, {"present_value"}),
(0x0010, 1, {"present_value"}),
(0x0011, 1, {"present_value"}),
(0x0012, 1, {"present_value"}),
(0x0013, 1, {"present_value"}),
(0x0014, 1, {"present_value"}),
(0x0015, 1, {}),
(0x0016, 1, {}),
(0x0019, 0, {}),
(0x001A, 1, {}),
(0x001B, 1, {}),
(0x0020, 1, {}),
(0x0021, 0, {}),
(0x0101, 1, {"lock_state"}),
(zigpy.zcl.clusters.general.Basic.cluster_id, 0, {}),
(
0x0201,
zigpy.zcl.clusters.general.PowerConfiguration.cluster_id,
1,
{"battery_voltage", "battery_percentage_remaining"},
),
(
zigpy.zcl.clusters.general.DeviceTemperature.cluster_id,
1,
{"current_temperature"},
),
(zigpy.zcl.clusters.general.Identify.cluster_id, 0, {}),
(zigpy.zcl.clusters.general.Groups.cluster_id, 0, {}),
(zigpy.zcl.clusters.general.Scenes.cluster_id, 1, {}),
(zigpy.zcl.clusters.general.OnOff.cluster_id, 1, {"on_off"}),
(zigpy.zcl.clusters.general.OnOffConfiguration.cluster_id, 1, {}),
(zigpy.zcl.clusters.general.LevelControl.cluster_id, 1, {"current_level"}),
(zigpy.zcl.clusters.general.Alarms.cluster_id, 1, {}),
(zigpy.zcl.clusters.general.AnalogInput.cluster_id, 1, {"present_value"}),
(zigpy.zcl.clusters.general.AnalogOutput.cluster_id, 1, {"present_value"}),
(zigpy.zcl.clusters.general.AnalogValue.cluster_id, 1, {"present_value"}),
(zigpy.zcl.clusters.general.AnalogOutput.cluster_id, 1, {"present_value"}),
(zigpy.zcl.clusters.general.BinaryOutput.cluster_id, 1, {"present_value"}),
(zigpy.zcl.clusters.general.BinaryValue.cluster_id, 1, {"present_value"}),
(zigpy.zcl.clusters.general.MultistateInput.cluster_id, 1, {"present_value"}),
(zigpy.zcl.clusters.general.MultistateOutput.cluster_id, 1, {"present_value"}),
(zigpy.zcl.clusters.general.MultistateValue.cluster_id, 1, {"present_value"}),
(zigpy.zcl.clusters.general.Commissioning.cluster_id, 1, {}),
(zigpy.zcl.clusters.general.Partition.cluster_id, 1, {}),
(zigpy.zcl.clusters.general.Ota.cluster_id, 0, {}),
(zigpy.zcl.clusters.general.PowerProfile.cluster_id, 1, {}),
(zigpy.zcl.clusters.general.ApplianceControl.cluster_id, 1, {}),
(zigpy.zcl.clusters.general.PollControl.cluster_id, 1, {}),
(zigpy.zcl.clusters.general.GreenPowerProxy.cluster_id, 0, {}),
(zigpy.zcl.clusters.closures.DoorLock.cluster_id, 1, {"lock_state"}),
(
zigpy.zcl.clusters.hvac.Thermostat.cluster_id,
1,
{
"local_temperature",
@ -150,9 +158,9 @@ async def poll_control_device(zha_device_restored, zigpy_device_mock):
"pi_heating_demand",
},
),
(0x0202, 1, {"fan_mode"}),
(zigpy.zcl.clusters.hvac.Fan.cluster_id, 1, {"fan_mode"}),
(
0x0300,
zigpy.zcl.clusters.lighting.Color.cluster_id,
1,
{
"current_x",
@ -163,16 +171,54 @@ async def poll_control_device(zha_device_restored, zigpy_device_mock):
"current_saturation",
},
),
(0x0400, 1, {"measured_value"}),
(0x0401, 1, {"level_status"}),
(0x0402, 1, {"measured_value"}),
(0x0403, 1, {"measured_value"}),
(0x0404, 1, {"measured_value"}),
(0x0405, 1, {"measured_value"}),
(0x0406, 1, {"occupancy"}),
(0x0702, 1, {"instantaneous_demand"}),
(
0x0B04,
zigpy.zcl.clusters.measurement.IlluminanceMeasurement.cluster_id,
1,
{"measured_value"},
),
(
zigpy.zcl.clusters.measurement.IlluminanceLevelSensing.cluster_id,
1,
{"level_status"},
),
(
zigpy.zcl.clusters.measurement.TemperatureMeasurement.cluster_id,
1,
{"measured_value"},
),
(
zigpy.zcl.clusters.measurement.PressureMeasurement.cluster_id,
1,
{"measured_value"},
),
(
zigpy.zcl.clusters.measurement.FlowMeasurement.cluster_id,
1,
{"measured_value"},
),
(
zigpy.zcl.clusters.measurement.RelativeHumidity.cluster_id,
1,
{"measured_value"},
),
(zigpy.zcl.clusters.measurement.OccupancySensing.cluster_id, 1, {"occupancy"}),
(
zigpy.zcl.clusters.smartenergy.Metering.cluster_id,
1,
{
"instantaneous_demand",
"current_summ_delivered",
"current_tier1_summ_delivered",
"current_tier2_summ_delivered",
"current_tier3_summ_delivered",
"current_tier4_summ_delivered",
"current_tier5_summ_delivered",
"current_tier6_summ_delivered",
"status",
},
),
(
zigpy.zcl.clusters.homeautomation.ElectricalMeasurement.cluster_id,
1,
{
"active_power",

View file

@ -309,7 +309,7 @@ async def async_test_device_temperature(hass, cluster, entity_id):
smartenergy.Metering.cluster_id,
"instantaneous_demand",
async_test_metering,
1,
9,
{
"demand_formatting": 0xF9,
"divisor": 1,
@ -323,7 +323,7 @@ async def async_test_device_temperature(hass, cluster, entity_id):
smartenergy.Metering.cluster_id,
"summation_delivered",
async_test_smart_energy_summation,
1,
9,
{
"demand_formatting": 0xF9,
"divisor": 1000,