Convert flume to use DataUpdateCoordinator (#42017)

* Convert flume to use DataUpdateCoordinator

* pylint

* Update homeassistant/components/flume/sensor.py

* Update homeassistant/components/flume/sensor.py
pull/42052/head
J. Nick Koston 2020-10-18 13:44:36 -05:00 committed by GitHub
parent 6c1078d1ca
commit 37df7bf4c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 50 additions and 50 deletions

View File

@ -16,8 +16,11 @@ from homeassistant.const import (
CONF_USERNAME, CONF_USERNAME,
) )
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity from homeassistant.helpers.update_coordinator import (
from homeassistant.util import Throttle CoordinatorEntity,
DataUpdateCoordinator,
UpdateFailed,
)
from .const import ( from .const import (
DEFAULT_NAME, DEFAULT_NAME,
@ -88,12 +91,13 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
http_session=http_session, http_session=http_session,
) )
flume_data = FlumeSensorData(flume_device) coordinator = _create_flume_device_coordinator(hass, flume_device)
for flume_query_sensor in FLUME_QUERIES_SENSOR.items(): for flume_query_sensor in FLUME_QUERIES_SENSOR.items():
flume_entity_list.append( flume_entity_list.append(
FlumeSensor( FlumeSensor(
flume_data, coordinator,
flume_device,
flume_query_sensor, flume_query_sensor,
f"{device_friendly_name} {flume_query_sensor[1]['friendly_name']}", f"{device_friendly_name} {flume_query_sensor[1]['friendly_name']}",
device_id, device_id,
@ -104,17 +108,16 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
async_add_entities(flume_entity_list) async_add_entities(flume_entity_list)
class FlumeSensor(Entity): class FlumeSensor(CoordinatorEntity):
"""Representation of the Flume sensor.""" """Representation of the Flume sensor."""
def __init__(self, flume_data, flume_query_sensor, name, device_id): def __init__(self, coordinator, flume_device, flume_query_sensor, name, device_id):
"""Initialize the Flume sensor.""" """Initialize the Flume sensor."""
self._flume_data = flume_data super().__init__(coordinator)
self._flume_device = flume_device
self._flume_query_sensor = flume_query_sensor self._flume_query_sensor = flume_query_sensor
self._name = name self._name = name
self._device_id = device_id self._device_id = device_id
self._undo_track_sensor = None
self._available = self._flume_data.available
self._state = None self._state = None
@property @property
@ -135,7 +138,21 @@ class FlumeSensor(Entity):
@property @property
def state(self): def state(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._state sensor_key = self._flume_query_sensor[0]
if sensor_key not in self._flume_device.values:
_LOGGER.debug(
"Updating sensor: '%s', key: '%s' is not yet available.",
self._name,
sensor_key,
)
return None
_LOGGER.debug(
"Updating sensor: '%s', value: '%s'",
self._name,
self._flume_device.values[sensor_key],
)
return _format_state_value(self._flume_device.values[sensor_key])
@property @property
def unit_of_measurement(self): def unit_of_measurement(self):
@ -143,64 +160,47 @@ class FlumeSensor(Entity):
# This is in gallons per SCAN_INTERVAL # This is in gallons per SCAN_INTERVAL
return self._flume_query_sensor[1]["unit_of_measurement"] return self._flume_query_sensor[1]["unit_of_measurement"]
@property
def available(self):
"""Device is available."""
return self._available
@property @property
def unique_id(self): def unique_id(self):
"""Flume query and Device unique ID.""" """Flume query and Device unique ID."""
return f"{self._flume_query_sensor[0]}_{self._device_id}" return f"{self._flume_query_sensor[0]}_{self._device_id}"
def update(self):
"""Get the latest data and updates the states."""
def format_state_value(value):
return round(value, 1) if isinstance(value, Number) else None
self._flume_data.update()
self._state = format_state_value(
self._flume_data.flume_device.values[self._flume_query_sensor[0]]
)
_LOGGER.debug(
"Updating sensor: '%s', value: '%s'",
self._name,
self._flume_data.flume_device.values[self._flume_query_sensor[0]],
)
self._available = self._flume_data.available
async def async_added_to_hass(self): async def async_added_to_hass(self):
"""Request an update when added.""" """Request an update when added."""
# We do ask for an update with async_add_entities() await super().async_added_to_hass()
# We do not ask for an update with async_add_entities()
# because it will update disabled entities # because it will update disabled entities
self.async_schedule_update_ha_state() await self.coordinator.async_request_refresh()
class FlumeSensorData: def _format_state_value(value):
"""Get the latest data and update the states.""" return round(value, 1) if isinstance(value, Number) else None
def __init__(self, flume_device):
"""Initialize the data object."""
self.flume_device = flume_device
self.available = True
@Throttle(MIN_TIME_BETWEEN_UPDATES) def _create_flume_device_coordinator(hass, flume_device):
def update(self): """Create a data coordinator for the flume device."""
async def _async_update_data():
"""Get the latest data from the Flume.""" """Get the latest data from the Flume."""
_LOGGER.debug("Updating Flume data") _LOGGER.debug("Updating Flume data")
try: try:
self.flume_device.update_force() await hass.async_add_executor_job(flume_device.update_force)
except Exception as ex: # pylint: disable=broad-except except Exception as ex: # pylint: disable=broad-except
if self.available: raise UpdateFailed(f"Error communicating with flume API: {ex}") from ex
_LOGGER.error("Update of Flume data failed: %s", ex)
self.available = False
return
self.available = True
_LOGGER.debug( _LOGGER.debug(
"Flume update details: %s", "Flume update details: %s",
{ {
"values": self.flume_device.values, "values": flume_device.values,
"query_payload": self.flume_device.query_payload, "query_payload": flume_device.query_payload,
}, },
) )
return DataUpdateCoordinator(
hass,
_LOGGER,
# Name of the data. For logging purposes.
name=flume_device.device_id,
update_method=_async_update_data,
# Polling interval. Will only be polled if there are subscribers.
update_interval=SCAN_INTERVAL,
)