From 8ac1f5d28a05c781f22c20dbc4a841a147e891f2 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 1 Aug 2021 20:35:03 -0700 Subject: [PATCH] Add energy consumption sensors to smartthings devices (#53759) --- .../components/smartthings/sensor.py | 62 +++++++++++++++++++ tests/components/smartthings/test_sensor.py | 49 +++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/homeassistant/components/smartthings/sensor.py b/homeassistant/components/smartthings/sensor.py index 7a7f9a51855..5059bcc4403 100644 --- a/homeassistant/components/smartthings/sensor.py +++ b/homeassistant/components/smartthings/sensor.py @@ -220,6 +220,7 @@ CAPABILITY_TO_SENSORS = { Capability.oven_setpoint: [ Map(Attribute.oven_setpoint, "Oven Set Point", None, None, None) ], + Capability.power_consumption_report: [], Capability.power_meter: [ Map( Attribute.power, @@ -388,6 +389,13 @@ CAPABILITY_TO_SENSORS = { UNITS = {"C": TEMP_CELSIUS, "F": TEMP_FAHRENHEIT} THREE_AXIS_NAMES = ["X Coordinate", "Y Coordinate", "Z Coordinate"] +POWER_CONSUMPTION_REPORT_NAMES = [ + "energy", + "power", + "deltaEnergy", + "powerEnergy", + "energySaved", +] async def async_setup_entry(hass, config_entry, async_add_entities): @@ -403,6 +411,13 @@ async def async_setup_entry(hass, config_entry, async_add_entities): for index in range(len(THREE_AXIS_NAMES)) ] ) + elif capability == Capability.power_consumption_report: + sensors.extend( + [ + SmartThingsPowerConsumptionSensor(device, report_name) + for report_name in POWER_CONSUMPTION_REPORT_NAMES + ] + ) else: maps = CAPABILITY_TO_SENSORS[capability] sensors.extend( @@ -526,3 +541,50 @@ class SmartThingsThreeAxisSensor(SmartThingsEntity, SensorEntity): return three_axis[self._index] except (TypeError, IndexError): return None + + +class SmartThingsPowerConsumptionSensor(SmartThingsEntity, SensorEntity): + """Define a SmartThings Sensor.""" + + def __init__( + self, + device: DeviceEntity, + report_name: str, + ) -> None: + """Init the class.""" + super().__init__(device) + self.report_name = report_name + + @property + def name(self) -> str: + """Return the name of the binary sensor.""" + return f"{self._device.label} {self.report_name}" + + @property + def unique_id(self) -> str: + """Return a unique ID.""" + return f"{self._device.device_id}.{self.report_name}" + + @property + def state(self): + """Return the state of the sensor.""" + value = self._device.status.attributes[Attribute.power_consumption].value + if value.get(self.report_name) is None: + return None + if self.report_name == "power": + return value[self.report_name] + return value[self.report_name] / 1000 + + @property + def device_class(self): + """Return the device class of the sensor.""" + if self.report_name == "power": + return DEVICE_CLASS_POWER + return DEVICE_CLASS_ENERGY + + @property + def unit_of_measurement(self): + """Return the unit this state is expressed in.""" + if self.report_name == "power": + return POWER_WATT + return ENERGY_KILO_WATT_HOUR diff --git a/tests/components/smartthings/test_sensor.py b/tests/components/smartthings/test_sensor.py index ffb577c903a..fa849a3cc67 100644 --- a/tests/components/smartthings/test_sensor.py +++ b/tests/components/smartthings/test_sensor.py @@ -139,6 +139,55 @@ async def test_energy_sensors_for_switch_device(hass, device_factory): assert entry.manufacturer == "Unavailable" +async def test_power_consumption_sensor(hass, device_factory): + """Test the attributes of the entity are correct.""" + # Arrange + device = device_factory( + "refrigerator", + [Capability.power_consumption_report], + { + Attribute.power_consumption: { + "energy": 1412002, + "deltaEnergy": 25, + "power": 109, + "powerEnergy": 24.304498331745464, + "persistedEnergy": 0, + "energySaved": 0, + "start": "2021-07-30T16:45:25Z", + "end": "2021-07-30T16:58:33Z", + } + }, + ) + entity_registry = er.async_get(hass) + device_registry = dr.async_get(hass) + # Act + await setup_platform(hass, SENSOR_DOMAIN, devices=[device]) + # Assert + state = hass.states.get("sensor.refrigerator_energy") + assert state + assert state.state == "1412.002" + entry = entity_registry.async_get("sensor.refrigerator_energy") + assert entry + assert entry.unique_id == f"{device.device_id}.energy" + entry = device_registry.async_get_device({(DOMAIN, device.device_id)}) + assert entry + assert entry.name == device.label + assert entry.model == device.device_type_name + assert entry.manufacturer == "Unavailable" + + state = hass.states.get("sensor.refrigerator_power") + assert state + assert state.state == "109" + entry = entity_registry.async_get("sensor.refrigerator_power") + assert entry + assert entry.unique_id == f"{device.device_id}.power" + entry = device_registry.async_get_device({(DOMAIN, device.device_id)}) + assert entry + assert entry.name == device.label + assert entry.model == device.device_type_name + assert entry.manufacturer == "Unavailable" + + async def test_update_from_signal(hass, device_factory): """Test the binary_sensor updates when receiving a signal.""" # Arrange