Update PyFlume version, support for multiple state attributes (#38138)

* Update PyFlume version, support for multiple state attributes

* Update PyFlume to resolve issue https://github.com/ChrisMandich/PyFlume/issues/7

* Update PyFlume package to 0.5.2, flatten values in sensor

* Delete setup

* Remove 'current_interval' from attributes and round values to 1 decimal place.

* Add missing brackets to remove 'current_interval' from attributes

* Set attribute keys explicitly, check attribute format.

* Breakout intervals into separate sensors.

* Update 'unit_of_measurement' for each sensor, update sensor 'available', remove unusued variables

* Update "Device unique ID."

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* Update PyFlume, resolve API query update for request.

* Cleanup debug logging

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
Chris Mandich 2020-07-28 00:30:38 -07:00 committed by GitHub
parent 77b6f8c9f2
commit ae8a38757a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 26 deletions

View File

@ -6,6 +6,15 @@ PLATFORMS = ["sensor"]
DEFAULT_NAME = "Flume Sensor" DEFAULT_NAME = "Flume Sensor"
FLUME_TYPE_SENSOR = 2 FLUME_TYPE_SENSOR = 2
FLUME_QUERIES_SENSOR = {
"current_interval": {"friendly_name": "Current", "unit_of_measurement": "gal/m"},
"month_to_date": {"friendly_name": "Current Month", "unit_of_measurement": "gal"},
"week_to_date": {"friendly_name": "Current Week", "unit_of_measurement": "gal"},
"today": {"friendly_name": "Current Day", "unit_of_measurement": "gal"},
"last_60_min": {"friendly_name": "60 Minutes", "unit_of_measurement": "gal/h"},
"last_24_hrs": {"friendly_name": "24 Hours", "unit_of_measurement": "gal/d"},
"last_30_days": {"friendly_name": "30 Days", "unit_of_measurement": "gal/mo"},
}
FLUME_AUTH = "flume_auth" FLUME_AUTH = "flume_auth"
FLUME_HTTP_SESSION = "http_session" FLUME_HTTP_SESSION = "http_session"
@ -20,3 +29,4 @@ KEY_DEVICE_TYPE = "type"
KEY_DEVICE_ID = "id" KEY_DEVICE_ID = "id"
KEY_DEVICE_LOCATION = "location" KEY_DEVICE_LOCATION = "location"
KEY_DEVICE_LOCATION_NAME = "name" KEY_DEVICE_LOCATION_NAME = "name"
KEY_DEVICE_LOCATION_TIMEZONE = "tz"

View File

@ -2,7 +2,7 @@
"domain": "flume", "domain": "flume",
"name": "Flume", "name": "Flume",
"documentation": "https://www.home-assistant.io/integrations/flume/", "documentation": "https://www.home-assistant.io/integrations/flume/",
"requirements": ["pyflume==0.4.0"], "requirements": ["pyflume==0.5.5"],
"dependencies": [], "dependencies": [],
"codeowners": ["@ChrisMandich", "@bdraco"], "codeowners": ["@ChrisMandich", "@bdraco"],
"config_flow": true "config_flow": true

View File

@ -1,6 +1,7 @@
"""Sensor for displaying the number of result from Flume.""" """Sensor for displaying the number of result from Flume."""
from datetime import timedelta from datetime import timedelta
import logging import logging
from numbers import Number
from pyflume import FlumeData from pyflume import FlumeData
import voluptuous as vol import voluptuous as vol
@ -24,10 +25,12 @@ from .const import (
FLUME_AUTH, FLUME_AUTH,
FLUME_DEVICES, FLUME_DEVICES,
FLUME_HTTP_SESSION, FLUME_HTTP_SESSION,
FLUME_QUERIES_SENSOR,
FLUME_TYPE_SENSOR, FLUME_TYPE_SENSOR,
KEY_DEVICE_ID, KEY_DEVICE_ID,
KEY_DEVICE_LOCATION, KEY_DEVICE_LOCATION,
KEY_DEVICE_LOCATION_NAME, KEY_DEVICE_LOCATION_NAME,
KEY_DEVICE_LOCATION_TIMEZONE,
KEY_DEVICE_TYPE, KEY_DEVICE_TYPE,
) )
@ -49,7 +52,6 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Import the platform into a config entry.""" """Import the platform into a config entry."""
hass.async_create_task( hass.async_create_task(
hass.config_entries.flow.async_init( hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_IMPORT}, data=config DOMAIN, context={"source": SOURCE_IMPORT}, data=config
@ -59,7 +61,6 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
async def async_setup_entry(hass, config_entry, async_add_entities): async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up the Flume sensor.""" """Set up the Flume sensor."""
flume_domain_data = hass.data[DOMAIN][config_entry.entry_id] flume_domain_data = hass.data[DOMAIN][config_entry.entry_id]
flume_auth = flume_domain_data[FLUME_AUTH] flume_auth = flume_domain_data[FLUME_AUTH]
@ -76,16 +77,27 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
device_id = device[KEY_DEVICE_ID] device_id = device[KEY_DEVICE_ID]
device_name = device[KEY_DEVICE_LOCATION][KEY_DEVICE_LOCATION_NAME] device_name = device[KEY_DEVICE_LOCATION][KEY_DEVICE_LOCATION_NAME]
device_timezone = device[KEY_DEVICE_LOCATION][KEY_DEVICE_LOCATION_TIMEZONE]
device_friendly_name = f"{name} {device_name}" device_friendly_name = f"{name} {device_name}"
flume_device = FlumeData( flume_device = FlumeData(
flume_auth, flume_auth,
device_id, device_id,
device_timezone,
SCAN_INTERVAL, SCAN_INTERVAL,
update_on_init=False, update_on_init=False,
http_session=http_session, http_session=http_session,
) )
flume_data = FlumeSensorData(flume_device)
for flume_query_sensor in FLUME_QUERIES_SENSOR.items():
flume_entity_list.append( flume_entity_list.append(
FlumeSensor(flume_device, device_friendly_name, device_id) FlumeSensor(
flume_data,
flume_query_sensor,
f"{device_friendly_name} {flume_query_sensor[1]['friendly_name']}",
device_id,
)
) )
if flume_entity_list: if flume_entity_list:
@ -95,13 +107,14 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
class FlumeSensor(Entity): class FlumeSensor(Entity):
"""Representation of the Flume sensor.""" """Representation of the Flume sensor."""
def __init__(self, flume_device, name, device_id): def __init__(self, flume_data, flume_query_sensor, name, device_id):
"""Initialize the Flume sensor.""" """Initialize the Flume sensor."""
self._flume_device = flume_device self._flume_data = flume_data
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._undo_track_sensor = None
self._available = False self._available = self._flume_data.available
self._state = None self._state = None
@property @property
@ -128,7 +141,7 @@ class FlumeSensor(Entity):
def unit_of_measurement(self): def unit_of_measurement(self):
"""Return the unit the value is expressed in.""" """Return the unit the value is expressed in."""
# This is in gallons per SCAN_INTERVAL # This is in gallons per SCAN_INTERVAL
return "gal/m" return self._flume_query_sensor[1]["unit_of_measurement"]
@property @property
def available(self): def available(self):
@ -137,26 +150,57 @@ class FlumeSensor(Entity):
@property @property
def unique_id(self): def unique_id(self):
"""Device unique ID.""" """Flume query and Device unique ID."""
return self._device_id return f"{self._flume_query_sensor[0]}_{self._device_id}"
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self): def update(self):
"""Get the latest data and updates the states.""" """Get the latest data and updates the states."""
_LOGGER.debug("Updating flume sensor: %s", self._name)
try: def format_state_value(value):
self._flume_device.update_force() return round(value, 1) if isinstance(value, Number) else None
except Exception as ex: # pylint: disable=broad-except
if self._available: self._flume_data.update()
_LOGGER.error("Update of flume sensor %s failed: %s", self._name, ex) self._state = format_state_value(
self._available = False self._flume_data.flume_device.values[self._flume_query_sensor[0]]
return )
_LOGGER.debug("Successful update of flume sensor: %s", self._name) _LOGGER.debug(
self._state = self._flume_device.value "Updating sensor: '%s', value: '%s'",
self._available = True 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() # We do 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() self.async_schedule_update_ha_state()
class FlumeSensorData:
"""Get the latest data and update the states."""
def __init__(self, flume_device):
"""Initialize the data object."""
self.flume_device = flume_device
self.available = True
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
"""Get the latest data from the Flume."""
_LOGGER.debug("Updating Flume data")
try:
self.flume_device.update_force()
except Exception as ex: # pylint: disable=broad-except
if self.available:
_LOGGER.error("Update of Flume data failed: %s", ex)
self.available = False
return
self.available = True
_LOGGER.debug(
"Flume update details: %s",
{
"values": self.flume_device.values,
"query_payload": self.flume_device.query_payload,
},
)

View File

@ -1334,7 +1334,7 @@ pyflexit==0.3
pyflic-homeassistant==0.4.dev0 pyflic-homeassistant==0.4.dev0
# homeassistant.components.flume # homeassistant.components.flume
pyflume==0.4.0 pyflume==0.5.5
# homeassistant.components.flunearyou # homeassistant.components.flunearyou
pyflunearyou==1.0.7 pyflunearyou==1.0.7

View File

@ -616,7 +616,7 @@ pyeverlights==0.1.0
pyfido==2.1.1 pyfido==2.1.1
# homeassistant.components.flume # homeassistant.components.flume
pyflume==0.4.0 pyflume==0.5.5
# homeassistant.components.flunearyou # homeassistant.components.flunearyou
pyflunearyou==1.0.7 pyflunearyou==1.0.7