1
0
mirror of https://github.com/USA-RedDragon/badnest.git synced 2025-01-18 13:05:26 +00:00

Implemented custom service for hot water boosting and hot water sensor

This commit is contained in:
Charles Garner 2020-03-20 04:22:34 +00:00
parent 7ab48d968e
commit 40af195cb6
6 changed files with 150 additions and 2 deletions

View File

@ -1,10 +1,22 @@
"""The example integration."""
import logging
import voluptuous as vol
from homeassistant.helpers import config_validation as cv
from datetime import datetime
import time
from homeassistant.util.dt import utcnow
from homeassistant.const import (
ATTR_ENTITY_ID
)
from .api import NestAPI
from .const import DOMAIN, CONF_ISSUE_TOKEN, CONF_COOKIE, CONF_USER_ID, CONF_ACCESS_TOKEN, CONF_REGION
SERVICE_BOOST_HOT_WATER = "boost_hot_water"
ATTR_TIME_PERIOD = "time_period"
ATTR_MODE = "on_off"
CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.All(
@ -23,9 +35,36 @@ CONFIG_SCHEMA = vol.Schema(
extra=vol.ALLOW_EXTRA,
)
BOOST_HOT_WATER_SCHEMA = vol.Schema(
{
vol.Required(ATTR_ENTITY_ID): cv.entity_id,
vol.Optional(ATTR_TIME_PERIOD, default=30): cv.positive_int,
vol.Required(ATTR_MODE): cv.string,
}
)
_LOGGER = logging.getLogger(__name__)
def setup(hass, config):
"""Set up the badnest component."""
def hot_water_boost(service):
"""Handle the service call."""
node_id = hass.data.get(service.data[ATTR_ENTITY_ID])
if not node_id:
# log or raise error
_LOGGER.error("Cannot boost entity id entered")
return
minutes = service.data[ATTR_TIME_PERIOD]
timeToEnd = int(time.mktime(datetime.timetuple(utcnow()))+(minutes*60))
mode = service.data[ATTR_MODE]
if mode == "on":
api.hotwater_set_boost(node_id, timeToEnd)
elif mode == "off":
api.hotwater_set_boost(node_id, 0)
if config.get(DOMAIN) is not None:
user_id = config[DOMAIN].get(CONF_USER_ID)
access_token = config[DOMAIN].get(CONF_ACCESS_TOKEN)
@ -49,4 +88,13 @@ def setup(hass, config):
),
}
api = hass.data[DOMAIN]['api']
hass.services.register(
DOMAIN,
SERVICE_BOOST_HOT_WATER,
hot_water_boost,
schema=BOOST_HOT_WATER_SCHEMA,
)
return True

View File

@ -48,6 +48,7 @@ class NestAPI():
self.cameras = []
self.thermostats = []
self.temperature_sensors = []
self.hotwatercontrollers = []
self.protects = []
self.login()
self._get_devices()
@ -153,6 +154,7 @@ class NestAPI():
sn = bucket.replace('device.', '')
self.thermostats.append(sn)
self.temperature_sensors.append(sn)
self.hotwatercontrollers.append(sn)
self.device_data[sn] = {}
self.cameras = self._get_cameras()
@ -270,6 +272,9 @@ class NestAPI():
self.device_data[sn]['eco'] = True
else:
self.device_data[sn]['eco'] = False
# Hot water
self.device_data[sn]['hot_water_active'] = \
sensor_data["hot_water_active"]
# Protect
elif bucket["object_key"].startswith(
f"topaz.{sn}"):
@ -484,6 +489,34 @@ class NestAPI():
self.login()
self.thermostat_set_eco_mode(device_id, state)
def hotwater_set_boost(self, device_id, time):
if device_id not in self.hotwatercontrollers:
return
try:
self._session.post(
f"{self._czfe_url}/v5/put",
json={
"objects": [
{
"object_key": f'device.{device_id}',
"op": "MERGE",
"value": {"hot_water_boost_time_to_end": time},
}
]
},
headers={"Authorization": f"Basic {self._access_token}"},
)
except requests.exceptions.RequestException as e:
_LOGGER.error(e)
_LOGGER.error('Failed to boost hot water, trying again')
self.hotwater_set_boost(device_id, time)
except KeyError:
_LOGGER.debug('Failed to boost hot water, trying to log in again')
self.login()
self.hotwater_set_boost(device_id, time)
def _camera_set_properties(self, device_id, property, value):
if device_id not in self.cameras:
return

View File

@ -116,7 +116,10 @@ class NestClimate(ClimateDevice):
if self.device.device_data[device_id]['target_humidity_enabled']:
self._support_flags = self._support_flags | SUPPORT_TARGET_HUMIDITY
async def async_added_to_hass(self):
"""When entity is added to Home Assistant."""
self.hass.data[self.entity_id] = self.device_id
@property
def unique_id(self):
@ -157,7 +160,7 @@ class NestClimate(ClimateDevice):
def target_humidity(self):
"""Return the target humidity."""
return self.device.device_data[self.device_id]['target_humidity']
@property
def min_humidity(self):
"""Return the min target humidity."""

View File

@ -32,7 +32,14 @@ async def async_setup_platform(hass,
_LOGGER.info(f"Adding nest temp sensor uuid: {sensor}")
temperature_sensors.append(NestTemperatureSensor(sensor, api))
hw_sensors = []
_LOGGER.info("Adding hot water sensors")
for hotwater in api['hotwatercontrollers']:
_LOGGER.info(f"Adding nest hot water sensor uuid: {hotwater}")
hw_sensors.append(NestHWSensor(hotwater, api))
async_add_entities(temperature_sensors)
async_add_entities(hw_sensors)
protect_sensors = []
_LOGGER.info("Adding protect sensors")
@ -92,6 +99,43 @@ class NestTemperatureSensor(Entity):
}
class NestHWSensor(Entity):
"""Implementation of the Nest Hot Water sensor."""
def __init__(self, device_id, api):
"""Initialize the sensor."""
self._name = "Nest Hot Water Sensor"
self.device_id = device_id
self.device = api
@property
def unique_id(self):
"""Return an unique ID."""
return self.device_id + '_hw'
@property
def name(self):
"""Return the name of the sensor."""
return "{0} Hot Water".format(self.device.device_data[self.device_id]['name'])
@property
def icon(self):
"""Return the icon to use in the frontend."""
return "mdi:water"
@property
def state(self):
"""Return the state of the sensor."""
if self.device.device_data[self.device_id]['hot_water_active']:
return 'On'
else:
return 'Off'
def update(self):
"""Get the latest data from the Protect and updates the states."""
self.device.update()
class NestProtectSensor(Entity):
"""Implementation of the Nest Protect sensor."""

View File

@ -0,0 +1,11 @@
boost_hot_water:
description:
"Set the boost mode ON or OFF defining the period of time for the boost."
fields:
entity_id:
{
description: Enter the entity_id for the device reuired to set the boost mode.,
example: "water_heater.hot_water",
}
time_period: { description: Set the time period in minutes for the boost., example: 30}
on_off: { description: Set the boost function on or off., example: "on" }

View File

@ -14,6 +14,7 @@ This isn't an advertised or public API, it's still better than web scraping, but
- Nest Thermostat support
- Nest Thermostat Sensor support
- Nest Camera support
- Nest Hot Water support (UK)
## Drawbacks
@ -28,6 +29,14 @@ The camera's region is one of `us` or `eu` depending on your region.
If you're not in the US or EU, you should be able to add your
two-character country code, and it should work.
## Hot Water Control (UK)
Hot water boosting is controlled through the `badnest.boost_hot_water` service.
The required variables are:
`entity_id`
`time_period` - integer in minutes
`on_off`
### Example configuration.yaml - When you're not using the Google Auth Login
Google recently introduced reCAPTCHA when logging to Nest. That means username