diff --git a/homeassistant/components/sense/__init__.py b/homeassistant/components/sense/__init__.py index 271888d7018..b9eb5b68758 100644 --- a/homeassistant/components/sense/__init__.py +++ b/homeassistant/components/sense/__init__.py @@ -1,10 +1,8 @@ """Support for monitoring a Sense energy sensor.""" from dataclasses import dataclass -from datetime import timedelta from functools import partial import logging -from typing import Any from sense_energy import ( ASyncSenseable, @@ -13,26 +11,18 @@ from sense_energy import ( ) from homeassistant.config_entries import ConfigEntry -from homeassistant.const import ( - CONF_EMAIL, - CONF_TIMEOUT, - EVENT_HOMEASSISTANT_STOP, - Platform, -) -from homeassistant.core import HomeAssistant, callback +from homeassistant.const import CONF_TIMEOUT, Platform +from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from homeassistant.helpers.aiohttp_client import async_get_clientsession -from homeassistant.helpers.dispatcher import async_dispatcher_send -from homeassistant.helpers.event import async_track_time_interval -from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from .const import ( ACTIVE_UPDATE_RATE, SENSE_CONNECT_EXCEPTIONS, - SENSE_DEVICE_UPDATE, SENSE_TIMEOUT_EXCEPTIONS, SENSE_WEBSOCKET_EXCEPTIONS, ) +from .coordinator import SenseRealtimeCoordinator, SenseTrendCoordinator _LOGGER = logging.getLogger(__name__) @@ -45,14 +35,14 @@ class SenseData: """Sense data type.""" data: ASyncSenseable - trends: DataUpdateCoordinator[Any] + trends: SenseTrendCoordinator + rt: SenseRealtimeCoordinator async def async_setup_entry(hass: HomeAssistant, entry: SenseConfigEntry) -> bool: """Set up Sense from a config entry.""" entry_data = entry.data - email = entry_data[CONF_EMAIL] timeout = entry_data[CONF_TIMEOUT] access_token = entry_data.get("access_token", "") @@ -99,26 +89,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: SenseConfigEntry) -> boo except SENSE_WEBSOCKET_EXCEPTIONS as err: raise ConfigEntryNotReady(str(err) or "Error during realtime update") from err - async def _async_update_trend() -> None: - """Update the trend data.""" - try: - await gateway.update_trend_data() - except (SenseAuthenticationException, SenseMFARequiredException) as err: - _LOGGER.warning("Sense authentication expired") - raise ConfigEntryAuthFailed(err) from err - except SENSE_CONNECT_EXCEPTIONS as err: - raise UpdateFailed(err) from err - - trends_coordinator: DataUpdateCoordinator[None] = DataUpdateCoordinator( - hass, - _LOGGER, - name=f"Sense Trends {email}", - update_method=_async_update_trend, - update_interval=timedelta(seconds=300), - ) - # Start out as unavailable so we do not report 0 data - # until the update happens - trends_coordinator.last_update_success = False + trends_coordinator = SenseTrendCoordinator(hass, gateway) + realtime_coordinator = SenseRealtimeCoordinator(hass, gateway) # This can take longer than 60s and we already know # sense is online since get_discovered_device_data was @@ -128,40 +100,20 @@ async def async_setup_entry(hass: HomeAssistant, entry: SenseConfigEntry) -> boo trends_coordinator.async_request_refresh(), "sense.trends-coordinator-refresh", ) + entry.async_create_background_task( + hass, + realtime_coordinator.async_request_refresh(), + "sense.realtime-coordinator-refresh", + ) entry.runtime_data = SenseData( data=gateway, trends=trends_coordinator, + rt=realtime_coordinator, ) await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) - async def async_sense_update(_) -> None: - """Retrieve latest state.""" - try: - await gateway.update_realtime() - except SENSE_TIMEOUT_EXCEPTIONS as ex: - _LOGGER.error("Timeout retrieving data: %s", ex) - except SENSE_WEBSOCKET_EXCEPTIONS as ex: - _LOGGER.error("Failed to update data: %s", ex) - - async_dispatcher_send(hass, f"{SENSE_DEVICE_UPDATE}-{gateway.sense_monitor_id}") - - remove_update_callback = async_track_time_interval( - hass, async_sense_update, timedelta(seconds=ACTIVE_UPDATE_RATE) - ) - - @callback - def _remove_update_callback_at_stop(event) -> None: - remove_update_callback() - - entry.async_on_unload(remove_update_callback) - entry.async_on_unload( - hass.bus.async_listen_once( - EVENT_HOMEASSISTANT_STOP, _remove_update_callback_at_stop - ) - ) - return True diff --git a/homeassistant/components/sense/binary_sensor.py b/homeassistant/components/sense/binary_sensor.py index 3c2907a2acb..ea154751d4e 100644 --- a/homeassistant/components/sense/binary_sensor.py +++ b/homeassistant/components/sense/binary_sensor.py @@ -8,13 +8,14 @@ from homeassistant.components.binary_sensor import ( BinarySensorDeviceClass, BinarySensorEntity, ) -from homeassistant.core import HomeAssistant, callback +from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er -from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.update_coordinator import CoordinatorEntity from . import SenseConfigEntry -from .const import ATTRIBUTION, DOMAIN, MDI_ICONS, SENSE_DEVICE_UPDATE +from .const import ATTRIBUTION, DOMAIN, MDI_ICONS +from .coordinator import SenseRealtimeCoordinator _LOGGER = logging.getLogger(__name__) @@ -26,8 +27,10 @@ async def async_setup_entry( ) -> None: """Set up the Sense binary sensor.""" sense_monitor_id = config_entry.runtime_data.data.sense_monitor_id + realtime_coordinator = config_entry.runtime_data.rt + devices = [ - SenseBinarySensor(device, sense_monitor_id) + SenseBinarySensor(device, sense_monitor_id, realtime_coordinator) for device in config_entry.runtime_data.data.devices ] @@ -41,19 +44,25 @@ def sense_to_mdi(sense_icon: str) -> str: return f"mdi:{MDI_ICONS.get(sense_icon, "power-plug")}" -class SenseBinarySensor(BinarySensorEntity): +class SenseBinarySensor( + CoordinatorEntity[SenseRealtimeCoordinator], BinarySensorEntity +): """Implementation of a Sense energy device binary sensor.""" _attr_attribution = ATTRIBUTION _attr_should_poll = False - _attr_available = False _attr_device_class = BinarySensorDeviceClass.POWER - def __init__(self, device: SenseDevice, sense_monitor_id: str) -> None: + def __init__( + self, + device: SenseDevice, + sense_monitor_id: str, + coordinator: SenseRealtimeCoordinator, + ) -> None: """Initialize the Sense binary sensor.""" + super().__init__(coordinator) self._attr_name = device.name self._id = device.id - self._sense_monitor_id = sense_monitor_id self._attr_unique_id = f"{sense_monitor_id}-{self._id}" self._attr_icon = sense_to_mdi(device.icon) self._device = device @@ -63,25 +72,10 @@ class SenseBinarySensor(BinarySensorEntity): """Return the old not so unique id of the binary sensor.""" return self._id - async def async_added_to_hass(self) -> None: - """Register callbacks.""" - self.async_on_remove( - async_dispatcher_connect( - self.hass, - f"{SENSE_DEVICE_UPDATE}-{self._sense_monitor_id}", - self._async_update_from_data, - ) - ) - - @callback - def _async_update_from_data(self) -> None: - """Get the latest data, update state. Must not do I/O.""" - new_state = self._device.is_on - if self._attr_available and self._attr_is_on == new_state: - return - self._attr_available = True - self._attr_is_on = new_state - self.async_write_ha_state() + @property + def is_on(self) -> bool: + """Return the state of the sensor.""" + return self._device.is_on async def _migrate_old_unique_ids( diff --git a/homeassistant/components/sense/const.py b/homeassistant/components/sense/const.py index 5e944c18d8d..27225d769f9 100644 --- a/homeassistant/components/sense/const.py +++ b/homeassistant/components/sense/const.py @@ -11,6 +11,7 @@ from sense_energy import ( DOMAIN = "sense" DEFAULT_TIMEOUT = 30 ACTIVE_UPDATE_RATE = 60 +TREND_UPDATE_RATE = 300 DEFAULT_NAME = "Sense" SENSE_DEVICE_UPDATE = "sense_devices_update" diff --git a/homeassistant/components/sense/coordinator.py b/homeassistant/components/sense/coordinator.py new file mode 100644 index 00000000000..c0029cd79ea --- /dev/null +++ b/homeassistant/components/sense/coordinator.py @@ -0,0 +1,76 @@ +"""Sense Coordinators.""" + +from datetime import timedelta +import logging + +from sense_energy import ( + ASyncSenseable, + SenseAuthenticationException, + SenseMFARequiredException, +) + +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import ConfigEntryAuthFailed +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed + +from .const import ( + ACTIVE_UPDATE_RATE, + SENSE_CONNECT_EXCEPTIONS, + SENSE_TIMEOUT_EXCEPTIONS, + SENSE_WEBSOCKET_EXCEPTIONS, + TREND_UPDATE_RATE, +) + +_LOGGER = logging.getLogger(__name__) + + +class SenseCoordinator(DataUpdateCoordinator[None]): + """Sense Trend Coordinator.""" + + def __init__( + self, hass: HomeAssistant, gateway: ASyncSenseable, name: str, update: int + ) -> None: + """Initialize.""" + super().__init__( + hass, + logger=_LOGGER, + name=f"Sense {name} {gateway.sense_monitor_id}", + update_interval=timedelta(seconds=update), + ) + self._gateway = gateway + self.last_update_success = False + + +class SenseTrendCoordinator(SenseCoordinator): + """Sense Trend Coordinator.""" + + def __init__(self, hass: HomeAssistant, gateway: ASyncSenseable) -> None: + """Initialize.""" + super().__init__(hass, gateway, "Trends", TREND_UPDATE_RATE) + + async def _async_update_data(self) -> None: + """Update the trend data.""" + try: + await self._gateway.update_trend_data() + except (SenseAuthenticationException, SenseMFARequiredException) as err: + _LOGGER.warning("Sense authentication expired") + raise ConfigEntryAuthFailed(err) from err + except SENSE_CONNECT_EXCEPTIONS as err: + raise UpdateFailed(err) from err + + +class SenseRealtimeCoordinator(SenseCoordinator): + """Sense Realtime Coordinator.""" + + def __init__(self, hass: HomeAssistant, gateway: ASyncSenseable) -> None: + """Initialize.""" + super().__init__(hass, gateway, "Realtime", ACTIVE_UPDATE_RATE) + + async def _async_update_data(self) -> None: + """Retrieve latest state.""" + try: + await self._gateway.update_realtime() + except SENSE_TIMEOUT_EXCEPTIONS as ex: + _LOGGER.error("Timeout retrieving data: %s", ex) + except SENSE_WEBSOCKET_EXCEPTIONS as ex: + _LOGGER.error("Failed to update data: %s", ex) diff --git a/homeassistant/components/sense/sensor.py b/homeassistant/components/sense/sensor.py index bd6f8a4da1d..bb5db4771d6 100644 --- a/homeassistant/components/sense/sensor.py +++ b/homeassistant/components/sense/sensor.py @@ -1,7 +1,6 @@ """Support for monitoring a Sense energy sensor.""" from datetime import datetime -from typing import Any from sense_energy import ASyncSenseable, Scale from sense_energy.sense_api import SenseDevice @@ -17,14 +16,10 @@ from homeassistant.const import ( UnitOfEnergy, UnitOfPower, ) -from homeassistant.core import HomeAssistant, callback +from homeassistant.core import HomeAssistant from homeassistant.helpers.device_registry import DeviceInfo -from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.update_coordinator import ( - CoordinatorEntity, - DataUpdateCoordinator, -) +from homeassistant.helpers.update_coordinator import CoordinatorEntity from . import SenseConfigEntry from .const import ( @@ -43,12 +38,16 @@ from .const import ( PRODUCTION_NAME, PRODUCTION_PCT_ID, PRODUCTION_PCT_NAME, - SENSE_DEVICE_UPDATE, SOLAR_POWERED_ID, SOLAR_POWERED_NAME, TO_GRID_ID, TO_GRID_NAME, ) +from .coordinator import ( + SenseCoordinator, + SenseRealtimeCoordinator, + SenseTrendCoordinator, +) # Sensor types/ranges TRENDS_SENSOR_TYPES = { @@ -86,6 +85,7 @@ async def async_setup_entry( """Set up the Sense sensor.""" data = config_entry.runtime_data.data trends_coordinator = config_entry.runtime_data.trends + realtime_coordinator = config_entry.runtime_data.rt # Request only in case it takes longer # than 60s @@ -94,22 +94,19 @@ async def async_setup_entry( sense_monitor_id = data.sense_monitor_id entities: list[SensorEntity] = [ - SenseDevicePowerSensor(device, sense_monitor_id) + SenseDevicePowerSensor(device, sense_monitor_id, realtime_coordinator) for device in config_entry.runtime_data.data.devices ] for variant_id, variant_name in SENSOR_VARIANTS: entities.append( SensePowerSensor( - data, - sense_monitor_id, - variant_id, - variant_name, + data, sense_monitor_id, variant_id, variant_name, realtime_coordinator ) ) entities.extend( - SenseVoltageSensor(data, i, sense_monitor_id) + SenseVoltageSensor(data, i, sense_monitor_id, realtime_coordinator) for i in range(len(data.active_voltage)) ) @@ -129,14 +126,28 @@ async def async_setup_entry( async_add_entities(entities) -class SensePowerSensor(SensorEntity): +class SenseBaseSensor(CoordinatorEntity[SenseCoordinator], SensorEntity): + """Base implementation of a Sense sensor.""" + + _attr_attribution = ATTRIBUTION + _attr_should_poll = False + + def __init__( + self, + coordinator: SenseCoordinator, + sense_monitor_id: str, + unique_id: str, + ) -> None: + """Initialize the Sense sensor.""" + super().__init__(coordinator) + self._attr_unique_id = f"{sense_monitor_id}-{unique_id}" + + +class SensePowerSensor(SenseBaseSensor): """Implementation of a Sense energy sensor.""" _attr_device_class = SensorDeviceClass.POWER _attr_native_unit_of_measurement = UnitOfPower.WATT - _attr_attribution = ATTRIBUTION - _attr_should_poll = False - _attr_available = False _attr_state_class = SensorStateClass.MEASUREMENT def __init__( @@ -145,106 +156,71 @@ class SensePowerSensor(SensorEntity): sense_monitor_id: str, variant_id: str, variant_name: str, + realtime_coordinator: SenseRealtimeCoordinator, ) -> None: """Initialize the Sense sensor.""" - self._attr_name = f"{ACTIVE_NAME} {variant_name}" - self._attr_unique_id = f"{sense_monitor_id}-{ACTIVE_TYPE}-{variant_id}" - self._data = data - self._sense_monitor_id = sense_monitor_id - self._variant_id = variant_id - self._variant_name = variant_name - - async def async_added_to_hass(self) -> None: - """Register callbacks.""" - self.async_on_remove( - async_dispatcher_connect( - self.hass, - f"{SENSE_DEVICE_UPDATE}-{self._sense_monitor_id}", - self._async_update_from_data, - ) + super().__init__( + realtime_coordinator, sense_monitor_id, f"{ACTIVE_TYPE}-{variant_id}" ) + self._attr_name = f"{ACTIVE_NAME} {variant_name}" + self._data = data + self._variant_id = variant_id - @callback - def _async_update_from_data(self) -> None: - """Update the sensor from the data. Must not do I/O.""" - new_state = round( + @property + def native_value(self) -> float: + """Return the state of the sensor.""" + return round( self._data.active_solar_power if self._variant_id == PRODUCTION_ID else self._data.active_power ) - if self._attr_available and self._attr_native_value == new_state: - return - self._attr_native_value = new_state - self._attr_available = True - self.async_write_ha_state() -class SenseVoltageSensor(SensorEntity): +class SenseVoltageSensor(SenseBaseSensor): """Implementation of a Sense energy voltage sensor.""" _attr_device_class = SensorDeviceClass.VOLTAGE _attr_state_class = SensorStateClass.MEASUREMENT _attr_native_unit_of_measurement = UnitOfElectricPotential.VOLT - _attr_attribution = ATTRIBUTION - _attr_should_poll = False - _attr_available = False def __init__( self, data: ASyncSenseable, index: int, sense_monitor_id: str, + realtime_coordinator: SenseRealtimeCoordinator, ) -> None: """Initialize the Sense sensor.""" - line_num = index + 1 - self._attr_name = f"L{line_num} Voltage" - self._attr_unique_id = f"{sense_monitor_id}-L{line_num}" + super().__init__(realtime_coordinator, sense_monitor_id, f"L{index + 1}") + self._attr_name = f"L{index + 1} Voltage" self._data = data - self._sense_monitor_id = sense_monitor_id self._voltage_index = index - async def async_added_to_hass(self) -> None: - """Register callbacks.""" - self.async_on_remove( - async_dispatcher_connect( - self.hass, - f"{SENSE_DEVICE_UPDATE}-{self._sense_monitor_id}", - self._async_update_from_data, - ) - ) - - @callback - def _async_update_from_data(self) -> None: - """Update the sensor from the data. Must not do I/O.""" - new_state = round(self._data.active_voltage[self._voltage_index], 1) - if self._attr_available and self._attr_native_value == new_state: - return - self._attr_available = True - self._attr_native_value = new_state - self.async_write_ha_state() + @property + def native_value(self) -> float: + """Return the state of the sensor.""" + return round(self._data.active_voltage[self._voltage_index], 1) -class SenseTrendsSensor(CoordinatorEntity, SensorEntity): +class SenseTrendsSensor(SenseBaseSensor): """Implementation of a Sense energy sensor.""" - _attr_attribution = ATTRIBUTION - _attr_should_poll = False - def __init__( self, data: ASyncSenseable, scale: Scale, variant_id: str, variant_name: str, - trends_coordinator: DataUpdateCoordinator[Any], + trends_coordinator: SenseTrendCoordinator, sense_monitor_id: str, ) -> None: """Initialize the Sense sensor.""" - super().__init__(trends_coordinator) - self._attr_name = f"{TRENDS_SENSOR_TYPES[scale]} {variant_name}" - self._attr_unique_id = ( - f"{sense_monitor_id}-{TRENDS_SENSOR_TYPES[scale].lower()}-{variant_id}" + super().__init__( + trends_coordinator, + sense_monitor_id, + f"{TRENDS_SENSOR_TYPES[scale].lower()}-{variant_id}", ) + self._attr_name = f"{TRENDS_SENSOR_TYPES[scale]} {variant_name}" self._data = data self._scale = scale self._variant_id = variant_id @@ -279,41 +255,29 @@ class SenseTrendsSensor(CoordinatorEntity, SensorEntity): return None -class SenseDevicePowerSensor(SensorEntity): +class SenseDevicePowerSensor(SenseBaseSensor): """Implementation of a Sense energy device.""" - _attr_available = False _attr_state_class = SensorStateClass.MEASUREMENT _attr_native_unit_of_measurement = UnitOfPower.WATT - _attr_attribution = ATTRIBUTION _attr_device_class = SensorDeviceClass.POWER - _attr_should_poll = False - def __init__(self, device: SenseDevice, sense_monitor_id: str) -> None: + def __init__( + self, + device: SenseDevice, + sense_monitor_id: str, + realtime_coordinator: SenseRealtimeCoordinator, + ) -> None: """Initialize the Sense binary sensor.""" + super().__init__( + realtime_coordinator, sense_monitor_id, f"{device.id}-{CONSUMPTION_ID}" + ) self._attr_name = f"{device.name} {CONSUMPTION_NAME}" self._id = device.id - self._sense_monitor_id = sense_monitor_id - self._attr_unique_id = f"{sense_monitor_id}-{self._id}-{CONSUMPTION_ID}" self._attr_icon = sense_to_mdi(device.icon) self._device = device - async def async_added_to_hass(self) -> None: - """Register callbacks.""" - self.async_on_remove( - async_dispatcher_connect( - self.hass, - f"{SENSE_DEVICE_UPDATE}-{self._sense_monitor_id}", - self._async_update_from_data, - ) - ) - - @callback - def _async_update_from_data(self) -> None: - """Get the latest data, update state. Must not do I/O.""" - new_state = self._device.power_w - if self._attr_available and self._attr_native_value == new_state: - return - self._attr_native_value = new_state - self._attr_available = True - self.async_write_ha_state() + @property + def native_value(self) -> float: + """Return the state of the sensor.""" + return self._device.power_w diff --git a/tests/components/sense/snapshots/test_binary_sensor.ambr b/tests/components/sense/snapshots/test_binary_sensor.ambr index cc78d4a7e83..f39c1e2450b 100644 --- a/tests/components/sense/snapshots/test_binary_sensor.ambr +++ b/tests/components/sense/snapshots/test_binary_sensor.ambr @@ -45,7 +45,7 @@ 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'unavailable', + 'state': 'off', }) # --- # name: test_binary_sensors[binary_sensor.oven-entry] @@ -94,6 +94,6 @@ 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'unavailable', + 'state': 'off', }) # --- diff --git a/tests/components/sense/snapshots/test_sensor.ambr b/tests/components/sense/snapshots/test_sensor.ambr index 48eda8150ca..1ba8a755f22 100644 --- a/tests/components/sense/snapshots/test_sensor.ambr +++ b/tests/components/sense/snapshots/test_sensor.ambr @@ -410,7 +410,7 @@ 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'unavailable', + 'state': '100.0', }) # --- # name: test_sensors[sensor.daily_from_grid-entry] @@ -823,7 +823,7 @@ 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'unavailable', + 'state': '500', }) # --- # name: test_sensors[sensor.energy_usage-entry] @@ -875,7 +875,7 @@ 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'unavailable', + 'state': '100', }) # --- # name: test_sensors[sensor.l1_voltage-entry] @@ -927,7 +927,7 @@ 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'unavailable', + 'state': '120', }) # --- # name: test_sensors[sensor.l2_voltage-entry] @@ -979,7 +979,7 @@ 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'unavailable', + 'state': '240', }) # --- # name: test_sensors[sensor.monthly_from_grid-entry] @@ -1393,7 +1393,7 @@ 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'unavailable', + 'state': '50.0', }) # --- # name: test_sensors[sensor.weekly_from_grid-entry] diff --git a/tests/components/sense/test_binary_sensor.py b/tests/components/sense/test_binary_sensor.py index 907d9364ce1..f38c7ffff28 100644 --- a/tests/components/sense/test_binary_sensor.py +++ b/tests/components/sense/test_binary_sensor.py @@ -7,7 +7,7 @@ from syrupy.assertion import SnapshotAssertion from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN from homeassistant.components.sense.const import ACTIVE_UPDATE_RATE -from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNAVAILABLE, Platform +from homeassistant.const import STATE_OFF, STATE_ON, Platform from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from homeassistant.util.dt import utcnow @@ -40,15 +40,6 @@ async def test_on_off_sensors( await setup_platform(hass, config_entry, BINARY_SENSOR_DOMAIN) device_1, device_2 = mock_sense.devices - state = hass.states.get(f"binary_sensor.{DEVICE_1_NAME.lower()}") - assert state.state == STATE_UNAVAILABLE - - state = hass.states.get(f"binary_sensor.{DEVICE_2_NAME.lower()}") - assert state.state == STATE_UNAVAILABLE - - async_fire_time_changed(hass, utcnow() + timedelta(seconds=ACTIVE_UPDATE_RATE)) - await hass.async_block_till_done() - state = hass.states.get(f"binary_sensor.{DEVICE_1_NAME.lower()}") assert state.state == STATE_OFF diff --git a/tests/components/sense/test_sensor.py b/tests/components/sense/test_sensor.py index d3a32e87677..27eb5ba4e8b 100644 --- a/tests/components/sense/test_sensor.py +++ b/tests/components/sense/test_sensor.py @@ -9,7 +9,7 @@ from syrupy.assertion import SnapshotAssertion from homeassistant.components.sense.const import ACTIVE_UPDATE_RATE, CONSUMPTION_ID from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN -from homeassistant.const import STATE_UNAVAILABLE, Platform +from homeassistant.const import Platform from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from homeassistant.util.dt import utcnow @@ -40,19 +40,11 @@ async def test_device_power_sensors( config_entry: MockConfigEntry, ) -> None: """Test the Sense device power sensors.""" - await setup_platform(hass, config_entry, SENSOR_DOMAIN) device_1, device_2 = mock_sense.devices - - state = hass.states.get(f"sensor.{DEVICE_1_NAME.lower()}_{CONSUMPTION_ID}") - assert state.state == STATE_UNAVAILABLE - - state = hass.states.get(f"sensor.{DEVICE_2_NAME.lower()}_{CONSUMPTION_ID}") - assert state.state == STATE_UNAVAILABLE - device_1.power_w = 0 device_2.power_w = 0 - async_fire_time_changed(hass, utcnow() + timedelta(seconds=ACTIVE_UPDATE_RATE)) - await hass.async_block_till_done() + await setup_platform(hass, config_entry, SENSOR_DOMAIN) + device_1, device_2 = mock_sense.devices state = hass.states.get(f"sensor.{DEVICE_1_NAME.lower()}_{CONSUMPTION_ID}") assert state.state == "0" @@ -90,20 +82,10 @@ async def test_voltage_sensors( ) -> None: """Test the Sense voltage sensors.""" - type(mock_sense).active_voltage = PropertyMock(return_value=[0, 0]) + type(mock_sense).active_voltage = PropertyMock(return_value=[120, 121]) await setup_platform(hass, config_entry, SENSOR_DOMAIN) - state = hass.states.get("sensor.l1_voltage") - assert state.state == STATE_UNAVAILABLE - - state = hass.states.get("sensor.l2_voltage") - assert state.state == STATE_UNAVAILABLE - - type(mock_sense).active_voltage = PropertyMock(return_value=[120, 121]) - async_fire_time_changed(hass, utcnow() + timedelta(seconds=ACTIVE_UPDATE_RATE)) - await hass.async_block_till_done() - state = hass.states.get("sensor.l1_voltage") assert state.state == "120" @@ -129,18 +111,10 @@ async def test_active_power_sensors( ) -> None: """Test the Sense power sensors.""" - await setup_platform(hass, config_entry, SENSOR_DOMAIN) - - state = hass.states.get("sensor.energy_usage") - assert state.state == STATE_UNAVAILABLE - - state = hass.states.get("sensor.energy_production") - assert state.state == STATE_UNAVAILABLE - type(mock_sense).active_power = PropertyMock(return_value=400) type(mock_sense).active_solar_power = PropertyMock(return_value=500) - async_fire_time_changed(hass, utcnow() + timedelta(seconds=ACTIVE_UPDATE_RATE)) - await hass.async_block_till_done() + + await setup_platform(hass, config_entry, SENSOR_DOMAIN) state = hass.states.get("sensor.energy_usage") assert state.state == "400"