mirror of
https://github.com/USA-RedDragon/badnest.git
synced 2025-01-31 08:00:27 +00:00
Implemented custom service for hot water boosting and hot water sensor
This commit is contained in:
parent
7ab48d968e
commit
40af195cb6
@ -1,10 +1,22 @@
|
|||||||
"""The example integration."""
|
"""The example integration."""
|
||||||
|
import logging
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
from homeassistant.helpers import config_validation as cv
|
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 .api import NestAPI
|
||||||
from .const import DOMAIN, CONF_ISSUE_TOKEN, CONF_COOKIE, CONF_USER_ID, CONF_ACCESS_TOKEN, CONF_REGION
|
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(
|
CONFIG_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
DOMAIN: vol.All(
|
DOMAIN: vol.All(
|
||||||
@ -23,9 +35,36 @@ CONFIG_SCHEMA = vol.Schema(
|
|||||||
extra=vol.ALLOW_EXTRA,
|
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):
|
def setup(hass, config):
|
||||||
"""Set up the badnest component."""
|
"""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:
|
if config.get(DOMAIN) is not None:
|
||||||
user_id = config[DOMAIN].get(CONF_USER_ID)
|
user_id = config[DOMAIN].get(CONF_USER_ID)
|
||||||
access_token = config[DOMAIN].get(CONF_ACCESS_TOKEN)
|
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
|
return True
|
||||||
|
@ -48,6 +48,7 @@ class NestAPI():
|
|||||||
self.cameras = []
|
self.cameras = []
|
||||||
self.thermostats = []
|
self.thermostats = []
|
||||||
self.temperature_sensors = []
|
self.temperature_sensors = []
|
||||||
|
self.hotwatercontrollers = []
|
||||||
self.protects = []
|
self.protects = []
|
||||||
self.login()
|
self.login()
|
||||||
self._get_devices()
|
self._get_devices()
|
||||||
@ -153,6 +154,7 @@ class NestAPI():
|
|||||||
sn = bucket.replace('device.', '')
|
sn = bucket.replace('device.', '')
|
||||||
self.thermostats.append(sn)
|
self.thermostats.append(sn)
|
||||||
self.temperature_sensors.append(sn)
|
self.temperature_sensors.append(sn)
|
||||||
|
self.hotwatercontrollers.append(sn)
|
||||||
self.device_data[sn] = {}
|
self.device_data[sn] = {}
|
||||||
|
|
||||||
self.cameras = self._get_cameras()
|
self.cameras = self._get_cameras()
|
||||||
@ -270,6 +272,9 @@ class NestAPI():
|
|||||||
self.device_data[sn]['eco'] = True
|
self.device_data[sn]['eco'] = True
|
||||||
else:
|
else:
|
||||||
self.device_data[sn]['eco'] = False
|
self.device_data[sn]['eco'] = False
|
||||||
|
# Hot water
|
||||||
|
self.device_data[sn]['hot_water_active'] = \
|
||||||
|
sensor_data["hot_water_active"]
|
||||||
# Protect
|
# Protect
|
||||||
elif bucket["object_key"].startswith(
|
elif bucket["object_key"].startswith(
|
||||||
f"topaz.{sn}"):
|
f"topaz.{sn}"):
|
||||||
@ -484,6 +489,34 @@ class NestAPI():
|
|||||||
self.login()
|
self.login()
|
||||||
self.thermostat_set_eco_mode(device_id, state)
|
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):
|
def _camera_set_properties(self, device_id, property, value):
|
||||||
if device_id not in self.cameras:
|
if device_id not in self.cameras:
|
||||||
return
|
return
|
||||||
|
@ -117,6 +117,9 @@ class NestClimate(ClimateDevice):
|
|||||||
if self.device.device_data[device_id]['target_humidity_enabled']:
|
if self.device.device_data[device_id]['target_humidity_enabled']:
|
||||||
self._support_flags = self._support_flags | SUPPORT_TARGET_HUMIDITY
|
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
|
@property
|
||||||
def unique_id(self):
|
def unique_id(self):
|
||||||
|
@ -32,7 +32,14 @@ async def async_setup_platform(hass,
|
|||||||
_LOGGER.info(f"Adding nest temp sensor uuid: {sensor}")
|
_LOGGER.info(f"Adding nest temp sensor uuid: {sensor}")
|
||||||
temperature_sensors.append(NestTemperatureSensor(sensor, api))
|
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(temperature_sensors)
|
||||||
|
async_add_entities(hw_sensors)
|
||||||
|
|
||||||
protect_sensors = []
|
protect_sensors = []
|
||||||
_LOGGER.info("Adding 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):
|
class NestProtectSensor(Entity):
|
||||||
"""Implementation of the Nest Protect sensor."""
|
"""Implementation of the Nest Protect sensor."""
|
||||||
|
|
||||||
|
11
custom_components/badnest/services.yaml
Normal file
11
custom_components/badnest/services.yaml
Normal 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" }
|
9
info.md
9
info.md
@ -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 support
|
||||||
- Nest Thermostat Sensor support
|
- Nest Thermostat Sensor support
|
||||||
- Nest Camera support
|
- Nest Camera support
|
||||||
|
- Nest Hot Water support (UK)
|
||||||
|
|
||||||
## Drawbacks
|
## 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
|
If you're not in the US or EU, you should be able to add your
|
||||||
two-character country code, and it should work.
|
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
|
### Example configuration.yaml - When you're not using the Google Auth Login
|
||||||
|
|
||||||
Google recently introduced reCAPTCHA when logging to Nest. That means username
|
Google recently introduced reCAPTCHA when logging to Nest. That means username
|
||||||
|
Loading…
x
Reference in New Issue
Block a user