From 6f0a7d29216d37b7b1b5c3f84ce83f8379a40834 Mon Sep 17 00:00:00 2001 From: Felipe Martins Diel <41558831+felipediel@users.noreply.github.com> Date: Mon, 18 Oct 2021 18:38:51 -0300 Subject: [PATCH] Add to the Broadlink integration support for voltage, current, overload and total consumption sensors (#53628) --- homeassistant/components/broadlink/sensor.py | 42 ++++++- tests/components/broadlink/__init__.py | 10 ++ tests/components/broadlink/test_sensors.py | 110 ++++++++++++++++++- 3 files changed, 160 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/broadlink/sensor.py b/homeassistant/components/broadlink/sensor.py index 676edb53b9a..8f739deeaa8 100644 --- a/homeassistant/components/broadlink/sensor.py +++ b/homeassistant/components/broadlink/sensor.py @@ -6,16 +6,28 @@ import logging import voluptuous as vol from homeassistant.components.sensor import ( + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_ENERGY, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_ILLUMINANCE, DEVICE_CLASS_POWER, DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_VOLTAGE, PLATFORM_SCHEMA, STATE_CLASS_MEASUREMENT, + STATE_CLASS_TOTAL_INCREASING, SensorEntity, SensorEntityDescription, ) -from homeassistant.const import CONF_HOST, PERCENTAGE, POWER_WATT, TEMP_CELSIUS +from homeassistant.const import ( + CONF_HOST, + ELECTRIC_CURRENT_AMPERE, + ELECTRIC_POTENTIAL_VOLT, + ENERGY_KILO_WATT_HOUR, + PERCENTAGE, + POWER_WATT, + TEMP_CELSIUS, +) from homeassistant.helpers import config_validation as cv from .const import DOMAIN @@ -59,6 +71,34 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = ( device_class=DEVICE_CLASS_POWER, state_class=STATE_CLASS_MEASUREMENT, ), + SensorEntityDescription( + key="volt", + name="Voltage", + native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + ), + SensorEntityDescription( + key="current", + name="Current", + native_unit_of_measurement=ELECTRIC_CURRENT_AMPERE, + device_class=DEVICE_CLASS_CURRENT, + state_class=STATE_CLASS_MEASUREMENT, + ), + SensorEntityDescription( + key="overload", + name="Overload", + native_unit_of_measurement=ELECTRIC_CURRENT_AMPERE, + device_class=DEVICE_CLASS_CURRENT, + state_class=STATE_CLASS_MEASUREMENT, + ), + SensorEntityDescription( + key="totalconsum", + name="Total consumption", + native_unit_of_measurement=ENERGY_KILO_WATT_HOUR, + device_class=DEVICE_CLASS_ENERGY, + state_class=STATE_CLASS_TOTAL_INCREASING, + ), ) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( diff --git a/tests/components/broadlink/__init__.py b/tests/components/broadlink/__init__.py index c65870add96..a323fd5e276 100644 --- a/tests/components/broadlink/__init__.py +++ b/tests/components/broadlink/__init__.py @@ -58,6 +58,16 @@ BROADLINK_DEVICES = { 20025, 5, ), + "Dining room": ( + "192.168.0.16", + "34ea34b4fd1c", + "SCB1E", + "Broadlink", + "SP4B", + 0x5115, + 57, + 5, + ), "Kitchen": ( # Not supported. "192.168.0.64", "34ea34b61d2c", diff --git a/tests/components/broadlink/test_sensors.py b/tests/components/broadlink/test_sensors.py index 1f8f913cfe4..b7fccd2e2ff 100644 --- a/tests/components/broadlink/test_sensors.py +++ b/tests/components/broadlink/test_sensors.py @@ -1,10 +1,14 @@ """Tests for Broadlink sensors.""" +from datetime import timedelta + from homeassistant.components.broadlink.const import DOMAIN, SENSOR_DOMAIN +from homeassistant.components.broadlink.updater import BroadlinkSP4UpdateManager from homeassistant.helpers.entity_registry import async_entries_for_device +from homeassistant.util import dt from . import get_device -from tests.common import mock_device_registry, mock_registry +from tests.common import async_fire_time_changed, mock_device_registry, mock_registry async def test_a1_sensor_setup(hass): @@ -286,3 +290,107 @@ async def test_rm4_pro_no_sensor(hass): entries = async_entries_for_device(entity_registry, device_entry.id) sensors = {entry for entry in entries if entry.domain == SENSOR_DOMAIN} assert len(sensors) == 0 + + +async def test_scb1e_sensor_setup(hass): + """Test a successful SCB1E sensor setup.""" + device = get_device("Dining room") + mock_api = device.get_mock_api() + mock_api.get_state.return_value = { + "pwr": 1, + "indicator": 1, + "maxworktime": 0, + "power": 255.57, + "volt": 121.7, + "current": 2.1, + "overload": 0, + "totalconsum": 1.7, + "childlock": 0, + } + + device_registry = mock_device_registry(hass) + entity_registry = mock_registry(hass) + + mock_setup = await device.setup_entry(hass, mock_api=mock_api) + + assert mock_api.get_state.call_count == 1 + device_entry = device_registry.async_get_device( + {(DOMAIN, mock_setup.entry.unique_id)} + ) + entries = async_entries_for_device(entity_registry, device_entry.id) + sensors = [entry for entry in entries if entry.domain == SENSOR_DOMAIN] + assert len(sensors) == 5 + + sensors_and_states = { + (sensor.original_name, hass.states.get(sensor.entity_id).state) + for sensor in sensors + } + assert sensors_and_states == { + (f"{device.name} Current power", "255.57"), + (f"{device.name} Voltage", "121.7"), + (f"{device.name} Current", "2.1"), + (f"{device.name} Overload", "0"), + (f"{device.name} Total consumption", "1.7"), + } + + +async def test_scb1e_sensor_update(hass): + """Test a successful SCB1E sensor update.""" + device = get_device("Dining room") + mock_api = device.get_mock_api() + mock_api.get_state.return_value = { + "pwr": 1, + "indicator": 1, + "maxworktime": 0, + "power": 255.6, + "volt": 121.7, + "current": 2.1, + "overload": 0, + "totalconsum": 1.7, + "childlock": 0, + } + + device_registry = mock_device_registry(hass) + entity_registry = mock_registry(hass) + + target_time = ( + dt.utcnow() + BroadlinkSP4UpdateManager.SCAN_INTERVAL * 3 + timedelta(seconds=1) + ) + + mock_setup = await device.setup_entry(hass, mock_api=mock_api) + + device_entry = device_registry.async_get_device( + {(DOMAIN, mock_setup.entry.unique_id)} + ) + entries = async_entries_for_device(entity_registry, device_entry.id) + sensors = [entry for entry in entries if entry.domain == SENSOR_DOMAIN] + assert len(sensors) == 5 + + mock_setup.api.get_state.return_value = { + "pwr": 1, + "indicator": 1, + "maxworktime": 0, + "power": 291.8, + "volt": 121.6, + "current": 2.4, + "overload": 0, + "totalconsum": 0.5, + "childlock": 0, + } + + async_fire_time_changed(hass, target_time) + await hass.async_block_till_done() + + assert mock_setup.api.get_state.call_count == 2 + + sensors_and_states = { + (sensor.original_name, hass.states.get(sensor.entity_id).state) + for sensor in sensors + } + assert sensors_and_states == { + (f"{device.name} Current power", "291.8"), + (f"{device.name} Voltage", "121.6"), + (f"{device.name} Current", "2.4"), + (f"{device.name} Overload", "0"), + (f"{device.name} Total consumption", "0.5"), + }