Add opentherm_gw services (#17762)
* Move components/opentherm_gw.py to components/opentherm_gw/__init__.py * Update requirements-all.txt * Await set_clock coroutine rather than scheduling it. * Create task for async_load_platform
This commit is contained in:
parent
239e314dc1
commit
b12e79e5cf
4 changed files with 246 additions and 7 deletions
|
@ -247,7 +247,7 @@ omit =
|
|||
homeassistant/components/opencv.py
|
||||
homeassistant/components/*/opencv.py
|
||||
|
||||
homeassistant/components/opentherm_gw.py
|
||||
homeassistant/components/opentherm_gw/*
|
||||
homeassistant/components/*/opentherm_gw.py
|
||||
|
||||
homeassistant/components/openuv/__init__.py
|
||||
|
|
|
@ -5,14 +5,16 @@ For more details about this component, please refer to the documentation at
|
|||
http://home-assistant.io/components/opentherm_gw/
|
||||
"""
|
||||
import logging
|
||||
from datetime import datetime, date
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.binary_sensor import DOMAIN as COMP_BINARY_SENSOR
|
||||
from homeassistant.components.sensor import DOMAIN as COMP_SENSOR
|
||||
from homeassistant.const import (CONF_DEVICE, CONF_MONITORED_VARIABLES,
|
||||
CONF_NAME, PRECISION_HALVES, PRECISION_TENTHS,
|
||||
PRECISION_WHOLE)
|
||||
from homeassistant.const import (
|
||||
ATTR_DATE, ATTR_ID, ATTR_TEMPERATURE, ATTR_TIME, CONF_DEVICE,
|
||||
CONF_MONITORED_VARIABLES, CONF_NAME, EVENT_HOMEASSISTANT_STOP,
|
||||
PRECISION_HALVES, PRECISION_TENTHS, PRECISION_WHOLE)
|
||||
from homeassistant.helpers.discovery import async_load_platform
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
|
||||
|
@ -20,16 +22,72 @@ import homeassistant.helpers.config_validation as cv
|
|||
|
||||
DOMAIN = 'opentherm_gw'
|
||||
|
||||
ATTR_MODE = 'mode'
|
||||
ATTR_LEVEL = 'level'
|
||||
|
||||
CONF_CLIMATE = 'climate'
|
||||
CONF_FLOOR_TEMP = 'floor_temperature'
|
||||
CONF_PRECISION = 'precision'
|
||||
|
||||
DATA_DEVICE = 'device'
|
||||
DATA_GW_VARS = 'gw_vars'
|
||||
DATA_LATEST_STATUS = 'latest_status'
|
||||
DATA_OPENTHERM_GW = 'opentherm_gw'
|
||||
|
||||
SIGNAL_OPENTHERM_GW_UPDATE = 'opentherm_gw_update'
|
||||
|
||||
SERVICE_RESET_GATEWAY = 'reset_gateway'
|
||||
|
||||
SERVICE_SET_CLOCK = 'set_clock'
|
||||
SERVICE_SET_CLOCK_SCHEMA = vol.Schema({
|
||||
vol.Optional(ATTR_DATE, default=date.today()): cv.date,
|
||||
vol.Optional(ATTR_TIME, default=datetime.now().time()): cv.time,
|
||||
})
|
||||
|
||||
SERVICE_SET_CONTROL_SETPOINT = 'set_control_setpoint'
|
||||
SERVICE_SET_CONTROL_SETPOINT_SCHEMA = vol.Schema({
|
||||
vol.Required(ATTR_TEMPERATURE): vol.All(vol.Coerce(float),
|
||||
vol.Range(min=0, max=90)),
|
||||
})
|
||||
|
||||
SERVICE_SET_GPIO_MODE = 'set_gpio_mode'
|
||||
SERVICE_SET_GPIO_MODE_SCHEMA = vol.Schema(vol.Any(
|
||||
vol.Schema({
|
||||
vol.Required(ATTR_ID): vol.Equal('A'),
|
||||
vol.Required(ATTR_MODE): vol.All(vol.Coerce(int),
|
||||
vol.Range(min=0, max=6)),
|
||||
}),
|
||||
vol.Schema({
|
||||
vol.Required(ATTR_ID): vol.Equal('B'),
|
||||
vol.Required(ATTR_MODE): vol.All(vol.Coerce(int),
|
||||
vol.Range(min=0, max=7)),
|
||||
}),
|
||||
))
|
||||
|
||||
SERVICE_SET_LED_MODE = 'set_led_mode'
|
||||
SERVICE_SET_LED_MODE_SCHEMA = vol.Schema({
|
||||
vol.Required(ATTR_ID): vol.In('ABCDEF'),
|
||||
vol.Required(ATTR_MODE): vol.In('RXTBOFHWCEMP'),
|
||||
})
|
||||
|
||||
SERVICE_SET_MAX_MOD = 'set_max_modulation'
|
||||
SERVICE_SET_MAX_MOD_SCHEMA = vol.Schema({
|
||||
vol.Required(ATTR_LEVEL): vol.All(vol.Coerce(int),
|
||||
vol.Range(min=-1, max=100))
|
||||
})
|
||||
|
||||
SERVICE_SET_OAT = 'set_outside_temperature'
|
||||
SERVICE_SET_OAT_SCHEMA = vol.Schema({
|
||||
vol.Required(ATTR_TEMPERATURE): vol.All(vol.Coerce(float),
|
||||
vol.Range(min=-40, max=99)),
|
||||
})
|
||||
|
||||
SERVICE_SET_SB_TEMP = 'set_setback_temperature'
|
||||
SERVICE_SET_SB_TEMP_SCHEMA = vol.Schema({
|
||||
vol.Required(ATTR_TEMPERATURE): vol.All(vol.Coerce(float),
|
||||
vol.Range(min=0, max=30)),
|
||||
})
|
||||
|
||||
CLIMATE_SCHEMA = vol.Schema({
|
||||
vol.Optional(CONF_NAME, default="OpenTherm Gateway"): cv.string,
|
||||
vol.Optional(CONF_PRECISION): vol.In([PRECISION_TENTHS, PRECISION_HALVES,
|
||||
|
@ -46,7 +104,7 @@ CONFIG_SCHEMA = vol.Schema({
|
|||
}),
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
REQUIREMENTS = ['pyotgw==0.2b1']
|
||||
REQUIREMENTS = ['pyotgw==0.3b0']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -60,9 +118,11 @@ async def async_setup(hass, config):
|
|||
hass.data[DATA_OPENTHERM_GW] = {
|
||||
DATA_DEVICE: gateway,
|
||||
DATA_GW_VARS: pyotgw.vars,
|
||||
DATA_LATEST_STATUS: {}
|
||||
}
|
||||
hass.async_create_task(connect_and_subscribe(
|
||||
hass, conf[CONF_DEVICE], gateway))
|
||||
hass.async_create_task(register_services(hass, gateway))
|
||||
hass.async_create_task(async_load_platform(
|
||||
hass, 'climate', DOMAIN, conf.get(CONF_CLIMATE), config))
|
||||
if monitored_vars:
|
||||
|
@ -76,13 +136,110 @@ async def connect_and_subscribe(hass, device_path, gateway):
|
|||
await gateway.connect(hass.loop, device_path)
|
||||
_LOGGER.debug("Connected to OpenTherm Gateway at %s", device_path)
|
||||
|
||||
async def cleanup(event):
|
||||
"""Reset overrides on the gateway."""
|
||||
await gateway.set_control_setpoint(0)
|
||||
await gateway.set_max_relative_mod('-')
|
||||
hass.bus.async_listen(EVENT_HOMEASSISTANT_STOP, cleanup)
|
||||
|
||||
async def handle_report(status):
|
||||
"""Handle reports from the OpenTherm Gateway."""
|
||||
_LOGGER.debug("Received report: %s", status)
|
||||
hass.data[DATA_OPENTHERM_GW][DATA_LATEST_STATUS] = status
|
||||
async_dispatcher_send(hass, SIGNAL_OPENTHERM_GW_UPDATE, status)
|
||||
gateway.subscribe(handle_report)
|
||||
|
||||
|
||||
async def register_services(hass, gateway):
|
||||
"""Register services for the component."""
|
||||
gw_vars = hass.data[DATA_OPENTHERM_GW][DATA_GW_VARS]
|
||||
|
||||
async def reset_gateway(call):
|
||||
"""Reset the OpenTherm Gateway."""
|
||||
mode_rst = gw_vars.OTGW_MODE_RESET
|
||||
status = await gateway.set_mode(mode_rst)
|
||||
hass.data[DATA_OPENTHERM_GW][DATA_LATEST_STATUS] = status
|
||||
async_dispatcher_send(hass, SIGNAL_OPENTHERM_GW_UPDATE, status)
|
||||
hass.services.async_register(DOMAIN, SERVICE_RESET_GATEWAY, reset_gateway)
|
||||
|
||||
async def set_control_setpoint(call):
|
||||
"""Set the control setpoint on the OpenTherm Gateway."""
|
||||
gw_var = gw_vars.DATA_CONTROL_SETPOINT
|
||||
value = await gateway.set_control_setpoint(call.data[ATTR_TEMPERATURE])
|
||||
status = hass.data[DATA_OPENTHERM_GW][DATA_LATEST_STATUS]
|
||||
status.update({gw_var: value})
|
||||
async_dispatcher_send(hass, SIGNAL_OPENTHERM_GW_UPDATE, status)
|
||||
hass.services.async_register(DOMAIN, SERVICE_SET_CONTROL_SETPOINT,
|
||||
set_control_setpoint,
|
||||
SERVICE_SET_CONTROL_SETPOINT_SCHEMA)
|
||||
|
||||
async def set_device_clock(call):
|
||||
"""Set the clock on the OpenTherm Gateway."""
|
||||
attr_date = call.data[ATTR_DATE]
|
||||
attr_time = call.data[ATTR_TIME]
|
||||
await gateway.set_clock(datetime.combine(attr_date, attr_time))
|
||||
hass.services.async_register(DOMAIN, SERVICE_SET_CLOCK, set_device_clock,
|
||||
SERVICE_SET_CLOCK_SCHEMA)
|
||||
|
||||
async def set_gpio_mode(call):
|
||||
"""Set the OpenTherm Gateway GPIO modes."""
|
||||
gpio_id = call.data[ATTR_ID]
|
||||
gpio_mode = call.data[ATTR_MODE]
|
||||
mode = await gateway.set_gpio_mode(gpio_id, gpio_mode)
|
||||
gpio_var = getattr(gw_vars, 'OTGW_GPIO_{}'.format(gpio_id))
|
||||
status = hass.data[DATA_OPENTHERM_GW][DATA_LATEST_STATUS]
|
||||
status.update({gpio_var: mode})
|
||||
async_dispatcher_send(hass, SIGNAL_OPENTHERM_GW_UPDATE, status)
|
||||
hass.services.async_register(DOMAIN, SERVICE_SET_GPIO_MODE, set_gpio_mode,
|
||||
SERVICE_SET_GPIO_MODE_SCHEMA)
|
||||
|
||||
async def set_led_mode(call):
|
||||
"""Set the OpenTherm Gateway LED modes."""
|
||||
led_id = call.data[ATTR_ID]
|
||||
led_mode = call.data[ATTR_MODE]
|
||||
mode = await gateway.set_led_mode(led_id, led_mode)
|
||||
led_var = getattr(gw_vars, 'OTGW_LED_{}'.format(led_id))
|
||||
status = hass.data[DATA_OPENTHERM_GW][DATA_LATEST_STATUS]
|
||||
status.update({led_var: mode})
|
||||
async_dispatcher_send(hass, SIGNAL_OPENTHERM_GW_UPDATE, status)
|
||||
hass.services.async_register(DOMAIN, SERVICE_SET_LED_MODE, set_led_mode,
|
||||
SERVICE_SET_LED_MODE_SCHEMA)
|
||||
|
||||
async def set_max_mod(call):
|
||||
"""Set the max modulation level."""
|
||||
gw_var = gw_vars.DATA_SLAVE_MAX_RELATIVE_MOD
|
||||
level = call.data[ATTR_LEVEL]
|
||||
if level == -1:
|
||||
# Backend only clears setting on non-numeric values.
|
||||
level = '-'
|
||||
value = await gateway.set_max_relative_mod(level)
|
||||
status = hass.data[DATA_OPENTHERM_GW][DATA_LATEST_STATUS]
|
||||
status.update({gw_var: value})
|
||||
async_dispatcher_send(hass, SIGNAL_OPENTHERM_GW_UPDATE, status)
|
||||
hass.services.async_register(DOMAIN, SERVICE_SET_MAX_MOD, set_max_mod,
|
||||
SERVICE_SET_MAX_MOD_SCHEMA)
|
||||
|
||||
async def set_outside_temp(call):
|
||||
"""Provide the outside temperature to the OpenTherm Gateway."""
|
||||
gw_var = gw_vars.DATA_OUTSIDE_TEMP
|
||||
value = await gateway.set_outside_temp(call.data[ATTR_TEMPERATURE])
|
||||
status = hass.data[DATA_OPENTHERM_GW][DATA_LATEST_STATUS]
|
||||
status.update({gw_var: value})
|
||||
async_dispatcher_send(hass, SIGNAL_OPENTHERM_GW_UPDATE, status)
|
||||
hass.services.async_register(DOMAIN, SERVICE_SET_OAT, set_outside_temp,
|
||||
SERVICE_SET_OAT_SCHEMA)
|
||||
|
||||
async def set_setback_temp(call):
|
||||
"""Set the OpenTherm Gateway SetBack temperature."""
|
||||
gw_var = gw_vars.OTGW_SB_TEMP
|
||||
value = await gateway.set_setback_temp(call.data[ATTR_TEMPERATURE])
|
||||
status = hass.data[DATA_OPENTHERM_GW][DATA_LATEST_STATUS]
|
||||
status.update({gw_var: value})
|
||||
async_dispatcher_send(hass, SIGNAL_OPENTHERM_GW_UPDATE, status)
|
||||
hass.services.async_register(DOMAIN, SERVICE_SET_SB_TEMP, set_setback_temp,
|
||||
SERVICE_SET_SB_TEMP_SCHEMA)
|
||||
|
||||
|
||||
async def setup_monitored_vars(hass, config, monitored_vars):
|
||||
"""Set up requested sensors."""
|
||||
gw_vars = hass.data[DATA_OPENTHERM_GW][DATA_GW_VARS]
|
||||
|
@ -203,4 +360,5 @@ async def setup_monitored_vars(hass, config, monitored_vars):
|
|||
hass.async_create_task(async_load_platform(
|
||||
hass, COMP_BINARY_SENSOR, DOMAIN, binary_sensors, config))
|
||||
if sensors:
|
||||
await async_load_platform(hass, COMP_SENSOR, DOMAIN, sensors, config)
|
||||
hass.async_create_task(async_load_platform(
|
||||
hass, COMP_SENSOR, DOMAIN, sensors, config))
|
81
homeassistant/components/opentherm_gw/services.yaml
Normal file
81
homeassistant/components/opentherm_gw/services.yaml
Normal file
|
@ -0,0 +1,81 @@
|
|||
# Describes the format for available opentherm_gw services
|
||||
|
||||
reset_gateway:
|
||||
description: Reset the OpenTherm Gateway.
|
||||
|
||||
set_clock:
|
||||
description: Set the clock and day of the week on the connected thermostat.
|
||||
fields:
|
||||
date:
|
||||
description: Optional date from which the day of the week will be extracted. Defaults to today.
|
||||
example: '2018-10-23'
|
||||
time:
|
||||
description: Optional time in 24h format which will be provided to the thermostat. Defaults to the current time.
|
||||
example: '19:34'
|
||||
|
||||
set_control_setpoint:
|
||||
description: >
|
||||
Set the central heating control setpoint override on the gateway.
|
||||
You will only need this if you are writing your own software thermostat.
|
||||
fields:
|
||||
temperature:
|
||||
description: >
|
||||
The central heating setpoint to set on the gateway.
|
||||
Values between 0 and 90 are accepted, but not all boilers support this range.
|
||||
A value of 0 disables the central heating setpoint override.
|
||||
example: '37.5'
|
||||
|
||||
set_gpio_mode:
|
||||
description: Change the function of the GPIO pins of the gateway.
|
||||
fields:
|
||||
id:
|
||||
description: The ID of the GPIO pin. Either "A" or "B".
|
||||
example: 'B'
|
||||
mode:
|
||||
description: >
|
||||
Mode to set on the GPIO pin. Values 0 through 6 are accepted for both GPIOs, 7 is only accepted for GPIO "B".
|
||||
See https://www.home-assistant.io/components/opentherm_gw/#gpio-modes for an explanation of the values.
|
||||
example: '5'
|
||||
|
||||
set_led_mode:
|
||||
description: Change the function of the LEDs of the gateway.
|
||||
fields:
|
||||
id:
|
||||
description: The ID of the LED. Possible values are "A" through "F".
|
||||
example: 'C'
|
||||
mode:
|
||||
description: >
|
||||
The function to assign to the LED. One of "R", "X", "T", "B", "O", "F", "H", "W", "C", "E", "M" or "P".
|
||||
See https://www.home-assistant.io/components/opentherm_gw/#led-modes for an explanation of the values.
|
||||
example: 'F'
|
||||
|
||||
set_max_modulation:
|
||||
description: >
|
||||
Override the maximum relative modulation level.
|
||||
You will only need this if you are writing your own software thermostat.
|
||||
fields:
|
||||
level:
|
||||
description: >
|
||||
The modulation level to provide to the gateway.
|
||||
Values between 0 and 100 will set the modulation level.
|
||||
Provide a value of -1 to clear the override and forward the value from the thermostat again.
|
||||
example: '42'
|
||||
|
||||
set_outside_temperature:
|
||||
description: >
|
||||
Provide an outside temperature to the thermostat.
|
||||
If your thermostat is unable to display an outside temperature and does not support OTC (Outside Temperature Correction), this has no effect.
|
||||
fields:
|
||||
temperature:
|
||||
description: >
|
||||
The temperature to provide to the thermostat.
|
||||
Values between -40.0 and 64.0 will be accepted, but not all thermostats can display the full range.
|
||||
Any value above 64.0 will clear a previously configured value (suggestion: 99)
|
||||
example: '-2.3'
|
||||
|
||||
set_setback_temperature:
|
||||
description: Configure the setback temperature to be used with the GPIO away mode function.
|
||||
fields:
|
||||
temperature:
|
||||
description: The setback temperature to configure on the gateway. Values between 0.0 and 30.0 are accepted.
|
||||
example: '16.0'
|
|
@ -1038,7 +1038,7 @@ pyoppleio==1.0.5
|
|||
pyota==2.0.5
|
||||
|
||||
# homeassistant.components.opentherm_gw
|
||||
pyotgw==0.2b1
|
||||
pyotgw==0.3b0
|
||||
|
||||
# homeassistant.auth.mfa_modules.notify
|
||||
# homeassistant.auth.mfa_modules.totp
|
||||
|
|
Loading…
Add table
Reference in a new issue