mirror of
https://github.com/home-assistant/core.git
synced 2025-06-25 01:21:51 +02:00
Add Streamlabs Water Monitor (#21205)
* Add Streamlabs Water Monitor * Fail Streamlabswater component setup when given invalid parameters The Streamlabs Water component is unable to recover if it is given an invalid API key or location id so this change is to ensure we validate they are correct during setup and return a failure if they are not. * Prime Streamlabswater component sensors so data is available immediately The sensors for the component were not causing an immediate load of data from the API when being set up so there was some lag after startup before values would show up. This change does an explicit update when the sensors are setup to ensure data is viewable immediately after startup. * Switch Streamlabswater logging to use %s for string formatting * Update Streamlabswater component with correct dependencies Dependencies were incorrectly specified using DEPENDS rather than DEPENDENCIES * Streamlabswater pull request feedback Remove detailed class docstrings since they're in the documentation, reduce code duplication in sensor classes, and remove periods from the end of log messages. * Reduce line length in Streamlabswater sensor * Add docstring on Streamlabswater service callback method * Get rid of unnecessary initializers in Streamlabswater sensor * Add manifest file for Streamlabs Water Monitor * Remove unused REQUIREMENTS
This commit is contained in:
@ -574,6 +574,7 @@ omit =
|
||||
homeassistant/components/starlingbank/sensor.py
|
||||
homeassistant/components/steam_online/sensor.py
|
||||
homeassistant/components/stiebel_eltron/*
|
||||
homeassistant/components/streamlabswater/*
|
||||
homeassistant/components/stride/notify.py
|
||||
homeassistant/components/supervisord/sensor.py
|
||||
homeassistant/components/swiss_hydrological_data/sensor.py
|
||||
|
84
homeassistant/components/streamlabswater/__init__.py
Normal file
84
homeassistant/components/streamlabswater/__init__.py
Normal file
@ -0,0 +1,84 @@
|
||||
"""Support for Streamlabs Water Monitor devices."""
|
||||
import logging
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import CONF_API_KEY
|
||||
from homeassistant.helpers import discovery
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
DOMAIN = 'streamlabswater'
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ATTR_AWAY_MODE = 'away_mode'
|
||||
SERVICE_SET_AWAY_MODE = 'set_away_mode'
|
||||
AWAY_MODE_AWAY = 'away'
|
||||
AWAY_MODE_HOME = 'home'
|
||||
|
||||
STREAMLABSWATER_COMPONENTS = [
|
||||
'sensor', 'binary_sensor'
|
||||
]
|
||||
|
||||
CONF_LOCATION_ID = "location_id"
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
DOMAIN: vol.Schema({
|
||||
vol.Required(CONF_API_KEY): cv.string,
|
||||
vol.Optional(CONF_LOCATION_ID): cv.string
|
||||
})
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
SET_AWAY_MODE_SCHEMA = vol.Schema({
|
||||
vol.Required(ATTR_AWAY_MODE): vol.In([AWAY_MODE_AWAY, AWAY_MODE_HOME])
|
||||
})
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
"""Set up the streamlabs water component."""
|
||||
from streamlabswater import streamlabswater
|
||||
|
||||
conf = config[DOMAIN]
|
||||
api_key = conf.get(CONF_API_KEY)
|
||||
location_id = conf.get(CONF_LOCATION_ID)
|
||||
|
||||
client = streamlabswater.StreamlabsClient(api_key)
|
||||
locations = client.get_locations().get('locations')
|
||||
|
||||
if locations is None:
|
||||
_LOGGER.error("Unable to retrieve locations. Verify API key")
|
||||
return False
|
||||
|
||||
if location_id is None:
|
||||
location = locations[0]
|
||||
location_id = location['locationId']
|
||||
_LOGGER.info("Streamlabs Water Monitor auto-detected location_id=%s",
|
||||
location_id)
|
||||
else:
|
||||
location = next((
|
||||
l for l in locations if location_id == l['locationId']), None)
|
||||
if location is None:
|
||||
_LOGGER.error("Supplied location_id is invalid")
|
||||
return False
|
||||
|
||||
location_name = location['name']
|
||||
|
||||
hass.data[DOMAIN] = {
|
||||
'client': client,
|
||||
'location_id': location_id,
|
||||
'location_name': location_name
|
||||
}
|
||||
|
||||
for component in STREAMLABSWATER_COMPONENTS:
|
||||
discovery.load_platform(hass, component, DOMAIN, {}, config)
|
||||
|
||||
def set_away_mode(service):
|
||||
"""Set the StreamLabsWater Away Mode."""
|
||||
away_mode = service.data.get(ATTR_AWAY_MODE)
|
||||
client.update_location(location_id, away_mode)
|
||||
|
||||
hass.services.register(
|
||||
DOMAIN, SERVICE_SET_AWAY_MODE, set_away_mode,
|
||||
schema=SET_AWAY_MODE_SCHEMA)
|
||||
|
||||
return True
|
73
homeassistant/components/streamlabswater/binary_sensor.py
Normal file
73
homeassistant/components/streamlabswater/binary_sensor.py
Normal file
@ -0,0 +1,73 @@
|
||||
"""Support for Streamlabs Water Monitor Away Mode."""
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
from homeassistant.components.binary_sensor import BinarySensorDevice
|
||||
from homeassistant.components.streamlabswater import (
|
||||
DOMAIN as STREAMLABSWATER_DOMAIN)
|
||||
from homeassistant.util import Throttle
|
||||
|
||||
DEPENDS = ['streamlabswater']
|
||||
|
||||
MIN_TIME_BETWEEN_LOCATION_UPDATES = timedelta(seconds=60)
|
||||
|
||||
ATTR_LOCATION_ID = "location_id"
|
||||
NAME_AWAY_MODE = "Water Away Mode"
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Set up the StreamLabsWater mode sensor."""
|
||||
client = hass.data[STREAMLABSWATER_DOMAIN]['client']
|
||||
location_id = hass.data[STREAMLABSWATER_DOMAIN]['location_id']
|
||||
location_name = hass.data[STREAMLABSWATER_DOMAIN]['location_name']
|
||||
|
||||
streamlabs_location_data = StreamlabsLocationData(location_id, client)
|
||||
streamlabs_location_data.update()
|
||||
|
||||
add_devices([
|
||||
StreamlabsAwayMode(location_name, streamlabs_location_data)
|
||||
])
|
||||
|
||||
|
||||
class StreamlabsLocationData:
|
||||
"""Track and query location data."""
|
||||
|
||||
def __init__(self, location_id, client):
|
||||
"""Initialize the location data."""
|
||||
self._location_id = location_id
|
||||
self._client = client
|
||||
self._is_away = None
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_LOCATION_UPDATES)
|
||||
def update(self):
|
||||
"""Query and store location data."""
|
||||
location = self._client.get_location(self._location_id)
|
||||
self._is_away = location['homeAway'] == 'away'
|
||||
|
||||
def is_away(self):
|
||||
"""Return whether away more is enabled."""
|
||||
return self._is_away
|
||||
|
||||
|
||||
class StreamlabsAwayMode(BinarySensorDevice):
|
||||
"""Monitor the away mode state."""
|
||||
|
||||
def __init__(self, location_name, streamlabs_location_data):
|
||||
"""Initialize the away mode device."""
|
||||
self._location_name = location_name
|
||||
self._streamlabs_location_data = streamlabs_location_data
|
||||
self._is_away = None
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name for away mode."""
|
||||
return "{} {}".format(self._location_name, NAME_AWAY_MODE)
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return if away mode is on."""
|
||||
return self._streamlabs_location_data.is_away()
|
||||
|
||||
def update(self):
|
||||
"""Retrieve the latest location data and away mode state."""
|
||||
self._streamlabs_location_data.update()
|
10
homeassistant/components/streamlabswater/manifest.json
Normal file
10
homeassistant/components/streamlabswater/manifest.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"domain": "streamlabswater",
|
||||
"name": "Streamlabs Water",
|
||||
"documentation": "https://www.home-assistant.io/components/streamlabswater",
|
||||
"requirements": [
|
||||
"streamlabswater==1.0.1"
|
||||
],
|
||||
"dependencies": [],
|
||||
"codeowners": []
|
||||
}
|
128
homeassistant/components/streamlabswater/sensor.py
Normal file
128
homeassistant/components/streamlabswater/sensor.py
Normal file
@ -0,0 +1,128 @@
|
||||
"""Support for Streamlabs Water Monitor Usage."""
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
from homeassistant.components.streamlabswater import (
|
||||
DOMAIN as STREAMLABSWATER_DOMAIN)
|
||||
from homeassistant.const import VOLUME_GALLONS
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.util import Throttle
|
||||
|
||||
DEPENDENCIES = ['streamlabswater']
|
||||
|
||||
WATER_ICON = 'mdi:water'
|
||||
MIN_TIME_BETWEEN_USAGE_UPDATES = timedelta(seconds=60)
|
||||
|
||||
NAME_DAILY_USAGE = "Daily Water"
|
||||
NAME_MONTHLY_USAGE = "Monthly Water"
|
||||
NAME_YEARLY_USAGE = "Yearly Water"
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Set up water usage sensors."""
|
||||
client = hass.data[STREAMLABSWATER_DOMAIN]['client']
|
||||
location_id = hass.data[STREAMLABSWATER_DOMAIN]['location_id']
|
||||
location_name = hass.data[STREAMLABSWATER_DOMAIN]['location_name']
|
||||
|
||||
streamlabs_usage_data = StreamlabsUsageData(location_id, client)
|
||||
streamlabs_usage_data.update()
|
||||
|
||||
add_devices([
|
||||
StreamLabsDailyUsage(location_name, streamlabs_usage_data),
|
||||
StreamLabsMonthlyUsage(location_name, streamlabs_usage_data),
|
||||
StreamLabsYearlyUsage(location_name, streamlabs_usage_data)
|
||||
])
|
||||
|
||||
|
||||
class StreamlabsUsageData:
|
||||
"""Track and query usage data."""
|
||||
|
||||
def __init__(self, location_id, client):
|
||||
"""Initialize the usage data."""
|
||||
self._location_id = location_id
|
||||
self._client = client
|
||||
self._today = None
|
||||
self._this_month = None
|
||||
self._this_year = None
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_USAGE_UPDATES)
|
||||
def update(self):
|
||||
"""Query and store usage data."""
|
||||
water_usage = self._client.get_water_usage_summary(self._location_id)
|
||||
self._today = round(water_usage['today'], 1)
|
||||
self._this_month = round(water_usage['thisMonth'], 1)
|
||||
self._this_year = round(water_usage['thisYear'], 1)
|
||||
|
||||
def get_daily_usage(self):
|
||||
"""Return the day's usage."""
|
||||
return self._today
|
||||
|
||||
def get_monthly_usage(self):
|
||||
"""Return the month's usage."""
|
||||
return self._this_month
|
||||
|
||||
def get_yearly_usage(self):
|
||||
"""Return the year's usage."""
|
||||
return self._this_year
|
||||
|
||||
|
||||
class StreamLabsDailyUsage(Entity):
|
||||
"""Monitors the daily water usage."""
|
||||
|
||||
def __init__(self, location_name, streamlabs_usage_data):
|
||||
"""Initialize the daily water usage device."""
|
||||
self._location_name = location_name
|
||||
self._streamlabs_usage_data = streamlabs_usage_data
|
||||
self._state = None
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name for daily usage."""
|
||||
return "{} {}".format(self._location_name, NAME_DAILY_USAGE)
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Return the daily usage icon."""
|
||||
return WATER_ICON
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the current daily usage."""
|
||||
return self._streamlabs_usage_data.get_daily_usage()
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
"""Return gallons as the unit measurement for water."""
|
||||
return VOLUME_GALLONS
|
||||
|
||||
def update(self):
|
||||
"""Retrieve the latest daily usage."""
|
||||
self._streamlabs_usage_data.update()
|
||||
|
||||
|
||||
class StreamLabsMonthlyUsage(StreamLabsDailyUsage):
|
||||
"""Monitors the monthly water usage."""
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name for monthly usage."""
|
||||
return "{} {}".format(self._location_name, NAME_MONTHLY_USAGE)
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the current monthly usage."""
|
||||
return self._streamlabs_usage_data.get_monthly_usage()
|
||||
|
||||
|
||||
class StreamLabsYearlyUsage(StreamLabsDailyUsage):
|
||||
"""Monitors the yearly water usage."""
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name for yearly usage."""
|
||||
return "{} {}".format(self._location_name, NAME_YEARLY_USAGE)
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the current yearly usage."""
|
||||
return self._streamlabs_usage_data.get_yearly_usage()
|
4
homeassistant/components/streamlabswater/services.yaml
Normal file
4
homeassistant/components/streamlabswater/services.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
set_away_mode:
|
||||
description: 'Set the home/away mode for a Streamlabs Water Monitor.'
|
||||
fields:
|
||||
away_mode: {description: home or away, example: 'home'}
|
@ -1707,6 +1707,9 @@ statsd==3.2.1
|
||||
# homeassistant.components.steam_online
|
||||
steamodd==4.21
|
||||
|
||||
# homeassistant.components.streamlabswater
|
||||
streamlabswater==1.0.1
|
||||
|
||||
# homeassistant.components.solaredge
|
||||
# homeassistant.components.thermoworks_smoke
|
||||
# homeassistant.components.traccar
|
||||
|
Reference in New Issue
Block a user