Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ZHA metering summation received sensor #107576

Merged
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class Metering(ClusterHandler):
AttrReportConfig(
attr="current_tier6_summ_delivered", config=REPORT_CONFIG_DEFAULT
),
AttrReportConfig(attr="current_summ_received", config=REPORT_CONFIG_DEFAULT),
AttrReportConfig(attr="status", config=REPORT_CONFIG_ASAP),
)
ZCL_INIT_ATTRS = {
Expand Down
13 changes: 13 additions & 0 deletions homeassistant/components/zha/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,19 @@ class Tier6SmartEnergySummation(PolledSmartEnergySummation):
_attr_translation_key: str = "tier6_summation_delivered"


@MULTI_MATCH(
cluster_handler_names=CLUSTER_HANDLER_SMARTENERGY_METERING,
)
# pylint: disable-next=hass-invalid-inheritance # needs fixing
class SmartEnergySummationReceived(PolledSmartEnergySummation):
"""Smart Energy Metering summation received sensor."""

_use_custom_polling = False # Poll indirectly by PolledSmartEnergySummation
_attribute_name = "current_summ_received"
_unique_id_suffix = "summation_received"
_attr_translation_key: str = "summation_received"


@MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_PRESSURE)
# pylint: disable-next=hass-invalid-inheritance # needs fixing
class Pressure(Sensor):
Expand Down
3 changes: 3 additions & 0 deletions homeassistant/components/zha/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,9 @@
"tier6_summation_delivered": {
"name": "Tier 6 summation delivered"
},
"summation_received": {
"name": "Summation received"
},
"device_temperature": {
"name": "Device temperature"
},
Expand Down
1 change: 1 addition & 0 deletions tests/components/zha/test_cluster_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ async def poll_control_device(zha_device_restored, zigpy_device_mock):
"current_tier4_summ_delivered",
"current_tier5_summ_delivered",
"current_tier6_summ_delivered",
"current_summ_received",
"status",
},
),
Expand Down
93 changes: 64 additions & 29 deletions tests/components/zha/test_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@

import pytest
import zigpy.profiles.zha
import zigpy.zcl.clusters.general as general
import zigpy.zcl.clusters.homeautomation as homeautomation
import zigpy.zcl.clusters.measurement as measurement
import zigpy.zcl.clusters.smartenergy as smartenergy
from zigpy.zcl.clusters import general, homeautomation, measurement, smartenergy

from homeassistant.components.sensor import SensorDeviceClass
from homeassistant.components.zha.core.const import ZHA_CLUSTER_HANDLER_READS_PER_REQ
Expand Down Expand Up @@ -70,7 +67,7 @@ def sensor_platform_only():


@pytest.fixture
async def elec_measurement_zigpy_dev(hass, zigpy_device_mock):
async def elec_measurement_zigpy_dev(hass: HomeAssistant, zigpy_device_mock):
"""Electric Measurement zigpy device."""

zigpy_device = zigpy_device_mock(
Expand Down Expand Up @@ -110,19 +107,19 @@ async def elec_measurement_zha_dev(elec_measurement_zigpy_dev, zha_device_joined
return zha_dev


async def async_test_humidity(hass, cluster, entity_id):
async def async_test_humidity(hass: HomeAssistant, cluster, entity_id):
"""Test humidity sensor."""
await send_attributes_report(hass, cluster, {1: 1, 0: 1000, 2: 100})
assert_state(hass, entity_id, "10.0", PERCENTAGE)


async def async_test_temperature(hass, cluster, entity_id):
async def async_test_temperature(hass: HomeAssistant, cluster, entity_id):
"""Test temperature sensor."""
await send_attributes_report(hass, cluster, {1: 1, 0: 2900, 2: 100})
assert_state(hass, entity_id, "29.0", UnitOfTemperature.CELSIUS)


async def async_test_pressure(hass, cluster, entity_id):
async def async_test_pressure(hass: HomeAssistant, cluster, entity_id):
"""Test pressure sensor."""
await send_attributes_report(hass, cluster, {1: 1, 0: 1000, 2: 10000})
assert_state(hass, entity_id, "1000", UnitOfPressure.HPA)
Expand All @@ -131,7 +128,7 @@ async def async_test_pressure(hass, cluster, entity_id):
assert_state(hass, entity_id, "1000", UnitOfPressure.HPA)


async def async_test_illuminance(hass, cluster, entity_id):
async def async_test_illuminance(hass: HomeAssistant, cluster, entity_id):
"""Test illuminance sensor."""
await send_attributes_report(hass, cluster, {1: 1, 0: 10, 2: 20})
assert_state(hass, entity_id, "1", LIGHT_LUX)
Expand All @@ -143,7 +140,7 @@ async def async_test_illuminance(hass, cluster, entity_id):
assert_state(hass, entity_id, "unknown", LIGHT_LUX)


async def async_test_metering(hass, cluster, entity_id):
async def async_test_metering(hass: HomeAssistant, cluster, entity_id):
"""Test Smart Energy metering sensor."""
await send_attributes_report(hass, cluster, {1025: 1, 1024: 12345, 1026: 100})
assert_state(hass, entity_id, "12345.0", None)
Expand All @@ -164,8 +161,10 @@ async def async_test_metering(hass, cluster, entity_id):
assert hass.states.get(entity_id).attributes["status"] in ("<bitmap8.32: 32>", "32")


async def async_test_smart_energy_summation(hass, cluster, entity_id):
"""Test SmartEnergy Summation delivered sensro."""
async def async_test_smart_energy_summation_delivered(
hass: HomeAssistant, cluster, entity_id
):
"""Test SmartEnergy Summation delivered sensor."""

await send_attributes_report(
hass, cluster, {1025: 1, "current_summ_delivered": 12321, 1026: 100}
Expand All @@ -179,7 +178,24 @@ async def async_test_smart_energy_summation(hass, cluster, entity_id):
)


async def async_test_electrical_measurement(hass, cluster, entity_id):
async def async_test_smart_energy_summation_received(
hass: HomeAssistant, cluster, entity_id
):
"""Test SmartEnergy Summation received sensor."""

await send_attributes_report(
hass, cluster, {1025: 1, "current_summ_received": 12321, 1026: 100}
)
assert_state(hass, entity_id, "12.321", UnitOfEnergy.KILO_WATT_HOUR)
assert hass.states.get(entity_id).attributes["status"] == "NO_ALARMS"
assert hass.states.get(entity_id).attributes["device_type"] == "Electric Metering"
assert (
hass.states.get(entity_id).attributes[ATTR_DEVICE_CLASS]
== SensorDeviceClass.ENERGY
)


async def async_test_electrical_measurement(hass: HomeAssistant, cluster, entity_id):
"""Test electrical measurement sensor."""
# update divisor cached value
await send_attributes_report(hass, cluster, {"ac_power_divisor": 1})
Expand All @@ -201,7 +217,7 @@ async def async_test_electrical_measurement(hass, cluster, entity_id):
assert hass.states.get(entity_id).attributes["active_power_max"] == "8.8"


async def async_test_em_apparent_power(hass, cluster, entity_id):
async def async_test_em_apparent_power(hass: HomeAssistant, cluster, entity_id):
"""Test electrical measurement Apparent Power sensor."""
# update divisor cached value
await send_attributes_report(hass, cluster, {"ac_power_divisor": 1})
Expand All @@ -219,7 +235,7 @@ async def async_test_em_apparent_power(hass, cluster, entity_id):
assert_state(hass, entity_id, "9.9", UnitOfApparentPower.VOLT_AMPERE)


async def async_test_em_rms_current(hass, cluster, entity_id):
async def async_test_em_rms_current(hass: HomeAssistant, cluster, entity_id):
"""Test electrical measurement RMS Current sensor."""

await send_attributes_report(hass, cluster, {0: 1, 0x0508: 1234, 10: 1000})
Expand All @@ -237,7 +253,7 @@ async def async_test_em_rms_current(hass, cluster, entity_id):
assert hass.states.get(entity_id).attributes["rms_current_max"] == "8.8"


async def async_test_em_rms_voltage(hass, cluster, entity_id):
async def async_test_em_rms_voltage(hass: HomeAssistant, cluster, entity_id):
"""Test electrical measurement RMS Voltage sensor."""

await send_attributes_report(hass, cluster, {0: 1, 0x0505: 1234, 10: 1000})
Expand All @@ -255,7 +271,7 @@ async def async_test_em_rms_voltage(hass, cluster, entity_id):
assert hass.states.get(entity_id).attributes["rms_voltage_max"] == "8.9"


async def async_test_powerconfiguration(hass, cluster, entity_id):
async def async_test_powerconfiguration(hass: HomeAssistant, cluster, entity_id):
"""Test powerconfiguration/battery sensor."""
await send_attributes_report(hass, cluster, {33: 98})
assert_state(hass, entity_id, "49", "%")
Expand All @@ -266,7 +282,7 @@ async def async_test_powerconfiguration(hass, cluster, entity_id):
assert hass.states.get(entity_id).attributes["battery_voltage"] == 2.0


async def async_test_powerconfiguration2(hass, cluster, entity_id):
async def async_test_powerconfiguration2(hass: HomeAssistant, cluster, entity_id):
"""Test powerconfiguration/battery sensor."""
await send_attributes_report(hass, cluster, {33: -1})
assert_state(hass, entity_id, STATE_UNKNOWN, "%")
Expand All @@ -278,7 +294,7 @@ async def async_test_powerconfiguration2(hass, cluster, entity_id):
assert_state(hass, entity_id, "49", "%")


async def async_test_device_temperature(hass, cluster, entity_id):
async def async_test_device_temperature(hass: HomeAssistant, cluster, entity_id):
"""Test temperature sensor."""
await send_attributes_report(hass, cluster, {0: 2900})
assert_state(hass, entity_id, "29.0", UnitOfTemperature.CELSIUS)
Expand Down Expand Up @@ -330,21 +346,37 @@ async def async_test_device_temperature(hass, cluster, entity_id):
smartenergy.Metering.cluster_id,
"instantaneous_demand",
async_test_metering,
9,
10,
{
"demand_formatting": 0xF9,
"divisor": 1,
"metering_device_type": 0x00,
"multiplier": 1,
"status": 0x00,
},
{"current_summ_delivered"},
{"current_summ_delivered", "current_summ_received"},
),
(
smartenergy.Metering.cluster_id,
"summation_delivered",
async_test_smart_energy_summation,
9,
async_test_smart_energy_summation_delivered,
10,
{
"demand_formatting": 0xF9,
"divisor": 1000,
"metering_device_type": 0x00,
"multiplier": 1,
"status": 0x00,
"summation_formatting": 0b1_0111_010,
"unit_of_measure": 0x00,
},
{"instaneneous_demand", "current_summ_received"},
),
(
smartenergy.Metering.cluster_id,
"summation_received",
async_test_smart_energy_summation_received,
10,
{
"demand_formatting": 0xF9,
"divisor": 1000,
Expand All @@ -354,7 +386,7 @@ async def async_test_device_temperature(hass, cluster, entity_id):
"summation_formatting": 0b1_0111_010,
"unit_of_measure": 0x00,
},
{"instaneneous_demand"},
{"instaneneous_demand", "current_summ_delivered"},
),
(
homeautomation.ElectricalMeasurement.cluster_id,
Expand Down Expand Up @@ -476,7 +508,7 @@ async def test_sensor(
await async_test_rejoin(hass, zigpy_device, [cluster], (report_count,))


def assert_state(hass, entity_id, state, unit_of_measurement):
def assert_state(hass: HomeAssistant, entity_id, state, unit_of_measurement):
"""Check that the state is what is expected.

This is used to ensure that the logic in each sensor class handled the
Expand All @@ -488,7 +520,7 @@ def assert_state(hass, entity_id, state, unit_of_measurement):


@pytest.fixture
def hass_ms(hass):
def hass_ms(hass: HomeAssistant):
"""Hass instance with measurement system."""

async def _hass_ms(meas_sys):
Expand Down Expand Up @@ -710,26 +742,29 @@ async def test_electrical_measurement_init(
},
{
"summation_delivered",
"summation_received",
},
{
"instantaneous_demand",
},
),
(
smartenergy.Metering.cluster_id,
{"instantaneous_demand", "current_summ_delivered"},
{"instantaneous_demand", "current_summ_delivered", "current_summ_received"},
{},
{
"summation_delivered",
"instantaneous_demand",
"summation_delivered",
"summation_received",
},
),
(
smartenergy.Metering.cluster_id,
{},
{
"summation_delivered",
"instantaneous_demand",
"summation_delivered",
"summation_received",
},
{},
),
Expand Down
Loading
Loading