Convert sense to use DataUpdateCoordinator for trends data (#34160)
* Convert sense to use DataUpdateCoordinator for trends * remove unused * request update right away * clarify * call async refresh later * Update homeassistant/components/sense/__init__.py Co-Authored-By: Paulus Schoutsen <paulus@home-assistant.io> * Update homeassistant/components/sense/__init__.py Co-Authored-By: Paulus Schoutsen <paulus@home-assistant.io> Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
This commit is contained in:
parent
e1d66f6fdd
commit
5ddcc22583
4 changed files with 68 additions and 58 deletions
|
@ -17,6 +17,7 @@ from homeassistant.exceptions import ConfigEntryNotReady
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||||
from homeassistant.helpers.event import async_track_time_interval
|
from homeassistant.helpers.event import async_track_time_interval
|
||||||
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
ACTIVE_UPDATE_RATE,
|
ACTIVE_UPDATE_RATE,
|
||||||
|
@ -27,6 +28,7 @@ from .const import (
|
||||||
SENSE_DEVICES_DATA,
|
SENSE_DEVICES_DATA,
|
||||||
SENSE_DISCOVERED_DEVICES_DATA,
|
SENSE_DISCOVERED_DEVICES_DATA,
|
||||||
SENSE_TIMEOUT_EXCEPTIONS,
|
SENSE_TIMEOUT_EXCEPTIONS,
|
||||||
|
SENSE_TRENDS_COORDINATOR,
|
||||||
)
|
)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
@ -111,9 +113,23 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||||
except SENSE_TIMEOUT_EXCEPTIONS:
|
except SENSE_TIMEOUT_EXCEPTIONS:
|
||||||
raise ConfigEntryNotReady
|
raise ConfigEntryNotReady
|
||||||
|
|
||||||
|
trends_coordinator = DataUpdateCoordinator(
|
||||||
|
hass,
|
||||||
|
_LOGGER,
|
||||||
|
name=f"Sense Trends {email}",
|
||||||
|
update_method=gateway.update_trend_data,
|
||||||
|
update_interval=timedelta(seconds=300),
|
||||||
|
)
|
||||||
|
|
||||||
|
# This can take longer than 60s and we already know
|
||||||
|
# sense is online since get_discovered_device_data was
|
||||||
|
# successful so we do it later.
|
||||||
|
hass.loop.create_task(trends_coordinator.async_request_refresh())
|
||||||
|
|
||||||
hass.data[DOMAIN][entry.entry_id] = {
|
hass.data[DOMAIN][entry.entry_id] = {
|
||||||
SENSE_DATA: gateway,
|
SENSE_DATA: gateway,
|
||||||
SENSE_DEVICES_DATA: sense_devices_data,
|
SENSE_DEVICES_DATA: sense_devices_data,
|
||||||
|
SENSE_TRENDS_COORDINATOR: trends_coordinator,
|
||||||
SENSE_DISCOVERED_DEVICES_DATA: sense_discovered_devices,
|
SENSE_DISCOVERED_DEVICES_DATA: sense_discovered_devices,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +138,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||||
hass.config_entries.async_forward_entry_setup(entry, component)
|
hass.config_entries.async_forward_entry_setup(entry, component)
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_sense_update(now):
|
async def async_sense_update(_):
|
||||||
"""Retrieve latest state."""
|
"""Retrieve latest state."""
|
||||||
try:
|
try:
|
||||||
await gateway.update_realtime()
|
await gateway.update_realtime()
|
||||||
|
|
|
@ -72,7 +72,6 @@ class SenseDevice(BinarySensorDevice):
|
||||||
self._unique_id = f"{sense_monitor_id}-{self._id}"
|
self._unique_id = f"{sense_monitor_id}-{self._id}"
|
||||||
self._icon = sense_to_mdi(device["icon"])
|
self._icon = sense_to_mdi(device["icon"])
|
||||||
self._sense_devices_data = sense_devices_data
|
self._sense_devices_data = sense_devices_data
|
||||||
self._undo_dispatch_subscription = None
|
|
||||||
self._state = None
|
self._state = None
|
||||||
self._available = False
|
self._available = False
|
||||||
|
|
||||||
|
@ -123,16 +122,13 @@ class SenseDevice(BinarySensorDevice):
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
"""Register callbacks."""
|
"""Register callbacks."""
|
||||||
self._undo_dispatch_subscription = async_dispatcher_connect(
|
self.async_on_remove(
|
||||||
|
async_dispatcher_connect(
|
||||||
self.hass,
|
self.hass,
|
||||||
f"{SENSE_DEVICE_UPDATE}-{self._sense_monitor_id}",
|
f"{SENSE_DEVICE_UPDATE}-{self._sense_monitor_id}",
|
||||||
self._async_update_from_data,
|
self._async_update_from_data,
|
||||||
)
|
)
|
||||||
|
)
|
||||||
async def async_will_remove_from_hass(self):
|
|
||||||
"""Undo subscription."""
|
|
||||||
if self._undo_dispatch_subscription:
|
|
||||||
self._undo_dispatch_subscription()
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_from_data(self):
|
def _async_update_from_data(self):
|
||||||
|
|
|
@ -12,6 +12,7 @@ SENSE_DATA = "sense_data"
|
||||||
SENSE_DEVICE_UPDATE = "sense_devices_update"
|
SENSE_DEVICE_UPDATE = "sense_devices_update"
|
||||||
SENSE_DEVICES_DATA = "sense_devices_data"
|
SENSE_DEVICES_DATA = "sense_devices_data"
|
||||||
SENSE_DISCOVERED_DEVICES_DATA = "sense_discovered_devices"
|
SENSE_DISCOVERED_DEVICES_DATA = "sense_discovered_devices"
|
||||||
|
SENSE_TRENDS_COORDINATOR = "sense_trends_coorindator"
|
||||||
|
|
||||||
ACTIVE_NAME = "Energy"
|
ACTIVE_NAME = "Energy"
|
||||||
ACTIVE_TYPE = "active"
|
ACTIVE_TYPE = "active"
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
"""Support for monitoring a Sense energy sensor."""
|
"""Support for monitoring a Sense energy sensor."""
|
||||||
from datetime import timedelta
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
|
@ -11,7 +10,6 @@ from homeassistant.const import (
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.util import Throttle
|
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
ACTIVE_NAME,
|
ACTIVE_NAME,
|
||||||
|
@ -28,12 +26,9 @@ from .const import (
|
||||||
SENSE_DEVICE_UPDATE,
|
SENSE_DEVICE_UPDATE,
|
||||||
SENSE_DEVICES_DATA,
|
SENSE_DEVICES_DATA,
|
||||||
SENSE_DISCOVERED_DEVICES_DATA,
|
SENSE_DISCOVERED_DEVICES_DATA,
|
||||||
SENSE_TIMEOUT_EXCEPTIONS,
|
SENSE_TRENDS_COORDINATOR,
|
||||||
)
|
)
|
||||||
|
|
||||||
MIN_TIME_BETWEEN_DAILY_UPDATES = timedelta(seconds=300)
|
|
||||||
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,17 +65,18 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
"""Set up the Sense sensor."""
|
"""Set up the Sense sensor."""
|
||||||
data = hass.data[DOMAIN][config_entry.entry_id][SENSE_DATA]
|
data = hass.data[DOMAIN][config_entry.entry_id][SENSE_DATA]
|
||||||
sense_devices_data = hass.data[DOMAIN][config_entry.entry_id][SENSE_DEVICES_DATA]
|
sense_devices_data = hass.data[DOMAIN][config_entry.entry_id][SENSE_DEVICES_DATA]
|
||||||
|
trends_coordinator = hass.data[DOMAIN][config_entry.entry_id][
|
||||||
|
SENSE_TRENDS_COORDINATOR
|
||||||
|
]
|
||||||
|
|
||||||
@Throttle(MIN_TIME_BETWEEN_DAILY_UPDATES)
|
# Request only in case it takes longer
|
||||||
async def update_trends():
|
# than 60s
|
||||||
"""Update the daily power usage."""
|
await trends_coordinator.async_request_refresh()
|
||||||
await data.update_trend_data()
|
|
||||||
|
|
||||||
sense_monitor_id = data.sense_monitor_id
|
sense_monitor_id = data.sense_monitor_id
|
||||||
sense_devices = hass.data[DOMAIN][config_entry.entry_id][
|
sense_devices = hass.data[DOMAIN][config_entry.entry_id][
|
||||||
SENSE_DISCOVERED_DEVICES_DATA
|
SENSE_DISCOVERED_DEVICES_DATA
|
||||||
]
|
]
|
||||||
await data.update_trend_data()
|
|
||||||
|
|
||||||
devices = [
|
devices = [
|
||||||
SenseEnergyDevice(sense_devices_data, device, sense_monitor_id)
|
SenseEnergyDevice(sense_devices_data, device, sense_monitor_id)
|
||||||
|
@ -114,8 +110,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
name,
|
name,
|
||||||
sensor_type,
|
sensor_type,
|
||||||
is_production,
|
is_production,
|
||||||
update_trends,
|
trends_coordinator,
|
||||||
var,
|
|
||||||
unique_id,
|
unique_id,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -146,7 +141,6 @@ class SenseActiveSensor(Entity):
|
||||||
self._sensor_type = sensor_type
|
self._sensor_type = sensor_type
|
||||||
self._is_production = is_production
|
self._is_production = is_production
|
||||||
self._state = None
|
self._state = None
|
||||||
self._undo_dispatch_subscription = None
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
|
@ -190,16 +184,13 @@ class SenseActiveSensor(Entity):
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
"""Register callbacks."""
|
"""Register callbacks."""
|
||||||
self._undo_dispatch_subscription = async_dispatcher_connect(
|
self.async_on_remove(
|
||||||
|
async_dispatcher_connect(
|
||||||
self.hass,
|
self.hass,
|
||||||
f"{SENSE_DEVICE_UPDATE}-{self._sense_monitor_id}",
|
f"{SENSE_DEVICE_UPDATE}-{self._sense_monitor_id}",
|
||||||
self._async_update_from_data,
|
self._async_update_from_data,
|
||||||
)
|
)
|
||||||
|
)
|
||||||
async def async_will_remove_from_hass(self):
|
|
||||||
"""Undo subscription."""
|
|
||||||
if self._undo_dispatch_subscription:
|
|
||||||
self._undo_dispatch_subscription()
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_from_data(self):
|
def _async_update_from_data(self):
|
||||||
|
@ -217,7 +208,7 @@ class SenseTrendsSensor(Entity):
|
||||||
"""Implementation of a Sense energy sensor."""
|
"""Implementation of a Sense energy sensor."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, data, name, sensor_type, is_production, update_call, sensor_id, unique_id
|
self, data, name, sensor_type, is_production, trends_coordinator, unique_id,
|
||||||
):
|
):
|
||||||
"""Initialize the Sense sensor."""
|
"""Initialize the Sense sensor."""
|
||||||
name_type = PRODUCTION_NAME if is_production else CONSUMPTION_NAME
|
name_type = PRODUCTION_NAME if is_production else CONSUMPTION_NAME
|
||||||
|
@ -226,10 +217,11 @@ class SenseTrendsSensor(Entity):
|
||||||
self._available = False
|
self._available = False
|
||||||
self._data = data
|
self._data = data
|
||||||
self._sensor_type = sensor_type
|
self._sensor_type = sensor_type
|
||||||
self.update_sensor = update_call
|
self._coordinator = trends_coordinator
|
||||||
self._is_production = is_production
|
self._is_production = is_production
|
||||||
self._state = None
|
self._state = None
|
||||||
self._unit_of_measurement = ENERGY_KILO_WATT_HOUR
|
self._unit_of_measurement = ENERGY_KILO_WATT_HOUR
|
||||||
|
self._had_any_update = False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
|
@ -239,12 +231,12 @@ class SenseTrendsSensor(Entity):
|
||||||
@property
|
@property
|
||||||
def state(self):
|
def state(self):
|
||||||
"""Return the state of the sensor."""
|
"""Return the state of the sensor."""
|
||||||
return self._state
|
return round(self._data.get_trend(self._sensor_type, self._is_production), 1)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def available(self):
|
def available(self):
|
||||||
"""Return the availability of the sensor."""
|
"""Return if entity is available."""
|
||||||
return self._available
|
return self._had_any_update and self._coordinator.last_update_success
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unit_of_measurement(self):
|
def unit_of_measurement(self):
|
||||||
|
@ -266,18 +258,27 @@ class SenseTrendsSensor(Entity):
|
||||||
"""Return the unique id."""
|
"""Return the unique id."""
|
||||||
return self._unique_id
|
return self._unique_id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def should_poll(self):
|
||||||
|
"""No need to poll. Coordinator notifies entity of updates."""
|
||||||
|
return False
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _async_update(self):
|
||||||
|
"""Track if we had an update so we do not report zero data."""
|
||||||
|
self._had_any_update = True
|
||||||
|
self.async_write_ha_state()
|
||||||
|
|
||||||
async def async_update(self):
|
async def async_update(self):
|
||||||
"""Get the latest data, update state."""
|
"""Update the entity.
|
||||||
|
|
||||||
try:
|
Only used by the generic entity update service.
|
||||||
await self.update_sensor()
|
"""
|
||||||
except SENSE_TIMEOUT_EXCEPTIONS:
|
await self._coordinator.async_request_refresh()
|
||||||
_LOGGER.error("Timeout retrieving data")
|
|
||||||
return
|
|
||||||
|
|
||||||
state = self._data.get_trend(self._sensor_type, self._is_production)
|
async def async_added_to_hass(self):
|
||||||
self._state = round(state, 1)
|
"""When entity is added to hass."""
|
||||||
self._available = True
|
self.async_on_remove(self._coordinator.async_add_listener(self._async_update))
|
||||||
|
|
||||||
|
|
||||||
class SenseEnergyDevice(Entity):
|
class SenseEnergyDevice(Entity):
|
||||||
|
@ -292,7 +293,6 @@ class SenseEnergyDevice(Entity):
|
||||||
self._unique_id = f"{sense_monitor_id}-{self._id}-{CONSUMPTION_ID}"
|
self._unique_id = f"{sense_monitor_id}-{self._id}-{CONSUMPTION_ID}"
|
||||||
self._icon = sense_to_mdi(device["icon"])
|
self._icon = sense_to_mdi(device["icon"])
|
||||||
self._sense_devices_data = sense_devices_data
|
self._sense_devices_data = sense_devices_data
|
||||||
self._undo_dispatch_subscription = None
|
|
||||||
self._state = None
|
self._state = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -342,16 +342,13 @@ class SenseEnergyDevice(Entity):
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
"""Register callbacks."""
|
"""Register callbacks."""
|
||||||
self._undo_dispatch_subscription = async_dispatcher_connect(
|
self.async_on_remove(
|
||||||
|
async_dispatcher_connect(
|
||||||
self.hass,
|
self.hass,
|
||||||
f"{SENSE_DEVICE_UPDATE}-{self._sense_monitor_id}",
|
f"{SENSE_DEVICE_UPDATE}-{self._sense_monitor_id}",
|
||||||
self._async_update_from_data,
|
self._async_update_from_data,
|
||||||
)
|
)
|
||||||
|
)
|
||||||
async def async_will_remove_from_hass(self):
|
|
||||||
"""Undo subscription."""
|
|
||||||
if self._undo_dispatch_subscription:
|
|
||||||
self._undo_dispatch_subscription()
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_from_data(self):
|
def _async_update_from_data(self):
|
||||||
|
|
Loading…
Add table
Reference in a new issue