1
0
mirror of https://github.com/home-assistant/core.git synced 2026-02-14 23:28:42 +00:00

Expose power and energy sensors for vera metered switches (#161028)

This commit is contained in:
Jon
2026-02-12 23:56:35 +01:00
committed by GitHub
parent 4921f05189
commit d10f5cc9ea
2 changed files with 152 additions and 7 deletions

View File

@@ -11,12 +11,14 @@ from homeassistant.components.sensor import (
ENTITY_ID_FORMAT,
SensorDeviceClass,
SensorEntity,
SensorStateClass,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
LIGHT_LUX,
PERCENTAGE,
Platform,
UnitOfEnergy,
UnitOfPower,
UnitOfTemperature,
)
@@ -36,13 +38,19 @@ async def async_setup_entry(
) -> None:
"""Set up the sensor config entry."""
controller_data = get_controller_data(hass, entry)
async_add_entities(
[
entities: list[SensorEntity] = [
VeraSensor(device, controller_data)
for device in controller_data.devices[Platform.SENSOR]
],
True,
)
]
for device in controller_data.devices[Platform.SWITCH]:
if device.power is not None:
entities.append(VeraPowerSensor(device, controller_data))
if device.energy is not None:
entities.append(VeraEnergySensor(device, controller_data))
async_add_entities(entities, True)
class VeraSensor(VeraEntity[veraApi.VeraSensor], SensorEntity):
@@ -109,3 +117,45 @@ class VeraSensor(VeraEntity[veraApi.VeraSensor], SensorEntity):
self._attr_native_value = "Tripped" if tripped else "Not Tripped"
else:
self._attr_native_value = "Unknown"
class VeraPowerSensor(VeraEntity[veraApi.VeraSwitch], SensorEntity):
"""Power sensor derived from a Vera switch with metering."""
_attr_device_class = SensorDeviceClass.POWER
_attr_has_entity_name = True
_attr_state_class = SensorStateClass.MEASUREMENT
_attr_native_unit_of_measurement = UnitOfPower.WATT
def __init__(
self, vera_device: veraApi.VeraSwitch, controller_data: ControllerData
) -> None:
"""Initialize the power sensor."""
VeraEntity.__init__(self, vera_device, controller_data)
self._unique_id = f"{self._unique_id}_power"
def update(self) -> None:
"""Update the sensor state."""
super().update()
self._attr_native_value = self.vera_device.power
class VeraEnergySensor(VeraEntity[veraApi.VeraSwitch], SensorEntity):
"""Energy sensor derived from a Vera switch with metering."""
_attr_device_class = SensorDeviceClass.ENERGY
_attr_has_entity_name = True
_attr_state_class = SensorStateClass.TOTAL_INCREASING
_attr_native_unit_of_measurement = UnitOfEnergy.KILO_WATT_HOUR
def __init__(
self, vera_device: veraApi.VeraSwitch, controller_data: ControllerData
) -> None:
"""Initialize the energy sensor."""
VeraEntity.__init__(self, vera_device, controller_data)
self._unique_id = f"{self._unique_id}_energy"
def update(self) -> None:
"""Update the sensor state."""
super().update()
self._attr_native_value = self.vera_device.energy

View File

@@ -11,6 +11,7 @@ import pyvera as pv
from homeassistant.components.sensor import async_rounded_state
from homeassistant.const import ATTR_UNIT_OF_MEASUREMENT, LIGHT_LUX, PERCENTAGE
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from .common import ComponentFactory, new_simple_controller_config
@@ -201,3 +202,97 @@ async def test_scene_controller_sensor(
update_callback(vera_device)
await hass.async_block_till_done()
assert hass.states.get(entity_id).state == "id0"
async def test_switch_power_and_energy_sensors_created(
hass: HomeAssistant,
vera_component_factory: ComponentFactory,
entity_registry: er.EntityRegistry,
) -> None:
"""Test that switches with metering expose power and energy sensors."""
vera_switch: pv.VeraSwitch = MagicMock(spec=pv.VeraSwitch)
vera_switch.device_id = 1
vera_switch.vera_device_id = vera_switch.device_id
vera_switch.comm_failure = False
vera_switch.name = "metered_switch"
vera_switch.category = 0
vera_switch.power = 12
vera_switch.energy = 3
vera_sensor: pv.VeraSensor = MagicMock(spec=pv.VeraSensor)
vera_sensor.device_id = 2
vera_sensor.vera_device_id = vera_sensor.device_id
vera_sensor.comm_failure = False
vera_sensor.name = "dummy_sensor"
vera_sensor.category = pv.CATEGORY_TEMPERATURE_SENSOR
vera_sensor.temperature = "20"
await vera_component_factory.configure_component(
hass=hass,
controller_config=new_simple_controller_config(
devices=(vera_switch, vera_sensor)
),
)
await hass.async_block_till_done()
power_entity_id = entity_registry.async_get_entity_id(
"sensor", "vera", "vera_1111_1_power"
)
energy_entity_id = entity_registry.async_get_entity_id(
"sensor", "vera", "vera_1111_1_energy"
)
assert power_entity_id is not None
assert energy_entity_id is not None
power_state = hass.states.get(power_entity_id)
assert power_state is not None
assert power_state.state == "12"
assert power_state.attributes[ATTR_UNIT_OF_MEASUREMENT] == "W"
energy_state = hass.states.get(energy_entity_id)
assert energy_state is not None
assert energy_state.state == "3"
assert energy_state.attributes[ATTR_UNIT_OF_MEASUREMENT] == "kWh"
async def test_switch_without_metering_does_not_create_power_energy_sensors(
hass: HomeAssistant,
vera_component_factory: ComponentFactory,
entity_registry: er.EntityRegistry,
) -> None:
"""Test that non-metered switches do not create power/energy sensors."""
vera_switch: pv.VeraSwitch = MagicMock(spec=pv.VeraSwitch)
vera_switch.device_id = 1
vera_switch.vera_device_id = vera_switch.device_id
vera_switch.comm_failure = False
vera_switch.name = "plain_switch"
vera_switch.category = 0
vera_switch.power = None
vera_switch.energy = None
vera_sensor: pv.VeraSensor = MagicMock(spec=pv.VeraSensor)
vera_sensor.device_id = 2
vera_sensor.vera_device_id = vera_sensor.device_id
vera_sensor.comm_failure = False
vera_sensor.name = "dummy_sensor"
vera_sensor.category = pv.CATEGORY_TEMPERATURE_SENSOR
vera_sensor.temperature = "20"
await vera_component_factory.configure_component(
hass=hass,
controller_config=new_simple_controller_config(
devices=(vera_switch, vera_sensor)
),
)
await hass.async_block_till_done()
power_entity_id = entity_registry.async_get_entity_id(
"sensor", "vera", "vera_1111_1_power"
)
energy_entity_id = entity_registry.async_get_entity_id(
"sensor", "vera", "vera_1111_1_energy"
)
assert power_entity_id is None
assert energy_entity_id is None