mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 09:17:53 +00:00
Multiple devices support for opentherm_gw (#22932)
* Breaking change: Rewrite opentherm_gw to add support for more than one OpenTherm Gateway. Breaks config layout and child entity ids and adds a required parameter to all service calls (gateway_id). * Add schema and parameter description for service opentherm_gw.reset_gateway. * Add optional name attribute in config to be used for friendly names. Fix bugs in binary_sensor and climate platforms. * pylint fixes * Remove unused variables. * Update manifest.json, remove REQUIREMENTS from .py file * Update CODEOWNERS * Address issues that were brought up (requested changes): - Move imports to module level - Change certain functions from async to sync - Move constants to const.py (new file) - Call gateway setup from outside of __init__() - Move validation of monitored_variables to config schema * Address requested changes: - Make module imports relative - Move more functions from async to sync, decorate with @callback where necessary - Remove monitored_variables option, add all sensors by default
This commit is contained in:
parent
d9f2a406f6
commit
43a6be6471
@ -184,6 +184,7 @@ homeassistant/components/nsw_fuel_station/* @nickw444
|
||||
homeassistant/components/nuki/* @pschmitt
|
||||
homeassistant/components/ohmconnect/* @robbiet480
|
||||
homeassistant/components/onboarding/* @home-assistant/core
|
||||
homeassistant/components/opentherm_gw/* @mvn23
|
||||
homeassistant/components/openuv/* @bachya
|
||||
homeassistant/components/openweathermap/* @fabaff
|
||||
homeassistant/components/orangepi_gpio/* @pascallj
|
||||
|
@ -2,357 +2,256 @@
|
||||
import logging
|
||||
from datetime import datetime, date
|
||||
|
||||
import pyotgw
|
||||
import pyotgw.vars as gw_vars
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.binary_sensor import DOMAIN as COMP_BINARY_SENSOR
|
||||
from homeassistant.components.climate import DOMAIN as COMP_CLIMATE
|
||||
from homeassistant.components.sensor import DOMAIN as COMP_SENSOR
|
||||
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)
|
||||
ATTR_DATE, ATTR_ID, ATTR_TEMPERATURE, ATTR_TIME, CONF_DEVICE, 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
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
from .const import (
|
||||
ATTR_GW_ID, ATTR_MODE, ATTR_LEVEL, CONF_CLIMATE, CONF_FLOOR_TEMP,
|
||||
CONF_PRECISION, DATA_GATEWAYS, DATA_OPENTHERM_GW, SERVICE_RESET_GATEWAY,
|
||||
SERVICE_SET_CLOCK, SERVICE_SET_CONTROL_SETPOINT, SERVICE_SET_GPIO_MODE,
|
||||
SERVICE_SET_LED_MODE, SERVICE_SET_MAX_MOD, SERVICE_SET_OAT,
|
||||
SERVICE_SET_SB_TEMP)
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
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,
|
||||
PRECISION_WHOLE]),
|
||||
vol.Optional(CONF_FLOOR_TEMP, default=False): cv.boolean,
|
||||
})
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
DOMAIN: vol.Schema({
|
||||
DOMAIN: cv.schema_with_slug_keys({
|
||||
vol.Required(CONF_DEVICE): cv.string,
|
||||
vol.Optional(CONF_CLIMATE, default={}): CLIMATE_SCHEMA,
|
||||
vol.Optional(CONF_MONITORED_VARIABLES, default=[]): vol.All(
|
||||
cv.ensure_list, [cv.string]),
|
||||
vol.Optional(CONF_NAME): cv.string,
|
||||
}),
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
|
||||
async def async_setup(hass, config):
|
||||
"""Set up the OpenTherm Gateway component."""
|
||||
import pyotgw
|
||||
conf = config[DOMAIN]
|
||||
gateway = pyotgw.pyotgw()
|
||||
monitored_vars = conf.get(CONF_MONITORED_VARIABLES)
|
||||
hass.data[DATA_OPENTHERM_GW] = {
|
||||
DATA_DEVICE: gateway,
|
||||
DATA_GW_VARS: pyotgw.vars,
|
||||
DATA_LATEST_STATUS: {}
|
||||
}
|
||||
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:
|
||||
hass.async_create_task(setup_monitored_vars(
|
||||
hass, config, monitored_vars))
|
||||
# Schedule directly on the loop to avoid blocking HA startup.
|
||||
hass.loop.create_task(
|
||||
connect_and_subscribe(hass, conf[CONF_DEVICE], gateway))
|
||||
hass.data[DATA_OPENTHERM_GW] = {DATA_GATEWAYS: {}}
|
||||
for gw_id, cfg in conf.items():
|
||||
gateway = OpenThermGatewayDevice(hass, gw_id, cfg)
|
||||
hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS][gw_id] = gateway
|
||||
hass.async_create_task(async_load_platform(hass, COMP_CLIMATE, DOMAIN,
|
||||
gw_id, config))
|
||||
hass.async_create_task(async_load_platform(hass, COMP_BINARY_SENSOR,
|
||||
DOMAIN, gw_id, config))
|
||||
hass.async_create_task(async_load_platform(hass, COMP_SENSOR, DOMAIN,
|
||||
gw_id, config))
|
||||
# Schedule directly on the loop to avoid blocking HA startup.
|
||||
hass.loop.create_task(gateway.connect_and_subscribe(cfg[CONF_DEVICE]))
|
||||
register_services(hass)
|
||||
return True
|
||||
|
||||
|
||||
async def connect_and_subscribe(hass, device_path, gateway):
|
||||
"""Connect to serial device and subscribe report handler."""
|
||||
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):
|
||||
def register_services(hass):
|
||||
"""Register services for the component."""
|
||||
gw_vars = hass.data[DATA_OPENTHERM_GW][DATA_GW_VARS]
|
||||
service_reset_schema = vol.Schema({
|
||||
vol.Required(ATTR_GW_ID): vol.All(
|
||||
cv.string, vol.In(hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS])),
|
||||
})
|
||||
service_set_clock_schema = vol.Schema({
|
||||
vol.Required(ATTR_GW_ID): vol.All(
|
||||
cv.string, vol.In(hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS])),
|
||||
vol.Optional(ATTR_DATE, default=date.today()): cv.date,
|
||||
vol.Optional(ATTR_TIME, default=datetime.now().time()): cv.time,
|
||||
})
|
||||
service_set_control_setpoint_schema = vol.Schema({
|
||||
vol.Required(ATTR_GW_ID): vol.All(
|
||||
cv.string, vol.In(hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS])),
|
||||
vol.Required(ATTR_TEMPERATURE): vol.All(vol.Coerce(float),
|
||||
vol.Range(min=0, max=90)),
|
||||
})
|
||||
service_set_gpio_mode_schema = vol.Schema(vol.Any(
|
||||
vol.Schema({
|
||||
vol.Required(ATTR_GW_ID): vol.All(
|
||||
cv.string, vol.In(
|
||||
hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS])),
|
||||
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_GW_ID): vol.All(
|
||||
cv.string, vol.In(
|
||||
hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS])),
|
||||
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_schema = vol.Schema({
|
||||
vol.Required(ATTR_GW_ID): vol.All(
|
||||
cv.string, vol.In(hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS])),
|
||||
vol.Required(ATTR_ID): vol.In('ABCDEF'),
|
||||
vol.Required(ATTR_MODE): vol.In('RXTBOFHWCEMP'),
|
||||
})
|
||||
service_set_max_mod_schema = vol.Schema({
|
||||
vol.Required(ATTR_GW_ID): vol.All(
|
||||
cv.string, vol.In(hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS])),
|
||||
vol.Required(ATTR_LEVEL): vol.All(vol.Coerce(int),
|
||||
vol.Range(min=-1, max=100))
|
||||
})
|
||||
service_set_oat_schema = vol.Schema({
|
||||
vol.Required(ATTR_GW_ID): vol.All(
|
||||
cv.string, vol.In(hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS])),
|
||||
vol.Required(ATTR_TEMPERATURE): vol.All(vol.Coerce(float),
|
||||
vol.Range(min=-40, max=99)),
|
||||
})
|
||||
service_set_sb_temp_schema = vol.Schema({
|
||||
vol.Required(ATTR_GW_ID): vol.All(
|
||||
cv.string, vol.In(hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS])),
|
||||
vol.Required(ATTR_TEMPERATURE): vol.All(vol.Coerce(float),
|
||||
vol.Range(min=0, max=30)),
|
||||
})
|
||||
|
||||
async def reset_gateway(call):
|
||||
"""Reset the OpenTherm Gateway."""
|
||||
gw_dev = (
|
||||
hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS][call.data[ATTR_GW_ID]])
|
||||
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)
|
||||
status = await gw_dev.gateway.set_mode(mode_rst)
|
||||
gw_dev.status = status
|
||||
async_dispatcher_send(hass, gw_dev.update_signal, gw_dev.status)
|
||||
hass.services.async_register(DOMAIN, SERVICE_RESET_GATEWAY, reset_gateway,
|
||||
service_reset_schema)
|
||||
|
||||
async def set_control_setpoint(call):
|
||||
"""Set the control setpoint on the OpenTherm Gateway."""
|
||||
gw_dev = (
|
||||
hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS][call.data[ATTR_GW_ID]])
|
||||
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)
|
||||
value = await gw_dev.gateway.set_control_setpoint(
|
||||
call.data[ATTR_TEMPERATURE])
|
||||
gw_dev.status.update({gw_var: value})
|
||||
async_dispatcher_send(hass, gw_dev.update_signal, gw_dev.status)
|
||||
hass.services.async_register(DOMAIN, SERVICE_SET_CONTROL_SETPOINT,
|
||||
set_control_setpoint,
|
||||
SERVICE_SET_CONTROL_SETPOINT_SCHEMA)
|
||||
service_set_control_setpoint_schema)
|
||||
|
||||
async def set_device_clock(call):
|
||||
"""Set the clock on the OpenTherm Gateway."""
|
||||
gw_dev = (
|
||||
hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS][call.data[ATTR_GW_ID]])
|
||||
attr_date = call.data[ATTR_DATE]
|
||||
attr_time = call.data[ATTR_TIME]
|
||||
await gateway.set_clock(datetime.combine(attr_date, attr_time))
|
||||
await gw_dev.gateway.set_clock(datetime.combine(attr_date, attr_time))
|
||||
hass.services.async_register(DOMAIN, SERVICE_SET_CLOCK, set_device_clock,
|
||||
SERVICE_SET_CLOCK_SCHEMA)
|
||||
service_set_clock_schema)
|
||||
|
||||
async def set_gpio_mode(call):
|
||||
"""Set the OpenTherm Gateway GPIO modes."""
|
||||
gw_dev = (
|
||||
hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS][call.data[ATTR_GW_ID]])
|
||||
gpio_id = call.data[ATTR_ID]
|
||||
gpio_mode = call.data[ATTR_MODE]
|
||||
mode = await gateway.set_gpio_mode(gpio_id, gpio_mode)
|
||||
mode = await gw_dev.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)
|
||||
gw_dev.status.update({gpio_var: mode})
|
||||
async_dispatcher_send(hass, gw_dev.update_signal, gw_dev.status)
|
||||
hass.services.async_register(DOMAIN, SERVICE_SET_GPIO_MODE, set_gpio_mode,
|
||||
SERVICE_SET_GPIO_MODE_SCHEMA)
|
||||
service_set_gpio_mode_schema)
|
||||
|
||||
async def set_led_mode(call):
|
||||
"""Set the OpenTherm Gateway LED modes."""
|
||||
gw_dev = (
|
||||
hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS][call.data[ATTR_GW_ID]])
|
||||
led_id = call.data[ATTR_ID]
|
||||
led_mode = call.data[ATTR_MODE]
|
||||
mode = await gateway.set_led_mode(led_id, led_mode)
|
||||
mode = await gw_dev.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)
|
||||
gw_dev.status.update({led_var: mode})
|
||||
async_dispatcher_send(hass, gw_dev.update_signal, gw_dev.status)
|
||||
hass.services.async_register(DOMAIN, SERVICE_SET_LED_MODE, set_led_mode,
|
||||
SERVICE_SET_LED_MODE_SCHEMA)
|
||||
service_set_led_mode_schema)
|
||||
|
||||
async def set_max_mod(call):
|
||||
"""Set the max modulation level."""
|
||||
gw_dev = (
|
||||
hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS][call.data[ATTR_GW_ID]])
|
||||
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)
|
||||
value = await gw_dev.gateway.set_max_relative_mod(level)
|
||||
gw_dev.status.update({gw_var: value})
|
||||
async_dispatcher_send(hass, gw_dev.update_signal, gw_dev.status)
|
||||
hass.services.async_register(DOMAIN, SERVICE_SET_MAX_MOD, set_max_mod,
|
||||
SERVICE_SET_MAX_MOD_SCHEMA)
|
||||
service_set_max_mod_schema)
|
||||
|
||||
async def set_outside_temp(call):
|
||||
"""Provide the outside temperature to the OpenTherm Gateway."""
|
||||
gw_dev = (
|
||||
hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS][call.data[ATTR_GW_ID]])
|
||||
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)
|
||||
value = await gw_dev.gateway.set_outside_temp(
|
||||
call.data[ATTR_TEMPERATURE])
|
||||
gw_dev.status.update({gw_var: value})
|
||||
async_dispatcher_send(hass, gw_dev.update_signal, gw_dev.status)
|
||||
hass.services.async_register(DOMAIN, SERVICE_SET_OAT, set_outside_temp,
|
||||
SERVICE_SET_OAT_SCHEMA)
|
||||
service_set_oat_schema)
|
||||
|
||||
async def set_setback_temp(call):
|
||||
"""Set the OpenTherm Gateway SetBack temperature."""
|
||||
gw_dev = (
|
||||
hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS][call.data[ATTR_GW_ID]])
|
||||
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)
|
||||
value = await gw_dev.gateway.set_setback_temp(
|
||||
call.data[ATTR_TEMPERATURE])
|
||||
gw_dev.status.update({gw_var: value})
|
||||
async_dispatcher_send(hass, gw_dev.update_signal, gw_dev.status)
|
||||
hass.services.async_register(DOMAIN, SERVICE_SET_SB_TEMP, set_setback_temp,
|
||||
SERVICE_SET_SB_TEMP_SCHEMA)
|
||||
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]
|
||||
sensor_type_map = {
|
||||
COMP_BINARY_SENSOR: [
|
||||
gw_vars.DATA_MASTER_CH_ENABLED,
|
||||
gw_vars.DATA_MASTER_DHW_ENABLED,
|
||||
gw_vars.DATA_MASTER_COOLING_ENABLED,
|
||||
gw_vars.DATA_MASTER_OTC_ENABLED,
|
||||
gw_vars.DATA_MASTER_CH2_ENABLED,
|
||||
gw_vars.DATA_SLAVE_FAULT_IND,
|
||||
gw_vars.DATA_SLAVE_CH_ACTIVE,
|
||||
gw_vars.DATA_SLAVE_DHW_ACTIVE,
|
||||
gw_vars.DATA_SLAVE_FLAME_ON,
|
||||
gw_vars.DATA_SLAVE_COOLING_ACTIVE,
|
||||
gw_vars.DATA_SLAVE_CH2_ACTIVE,
|
||||
gw_vars.DATA_SLAVE_DIAG_IND,
|
||||
gw_vars.DATA_SLAVE_DHW_PRESENT,
|
||||
gw_vars.DATA_SLAVE_CONTROL_TYPE,
|
||||
gw_vars.DATA_SLAVE_COOLING_SUPPORTED,
|
||||
gw_vars.DATA_SLAVE_DHW_CONFIG,
|
||||
gw_vars.DATA_SLAVE_MASTER_LOW_OFF_PUMP,
|
||||
gw_vars.DATA_SLAVE_CH2_PRESENT,
|
||||
gw_vars.DATA_SLAVE_SERVICE_REQ,
|
||||
gw_vars.DATA_SLAVE_REMOTE_RESET,
|
||||
gw_vars.DATA_SLAVE_LOW_WATER_PRESS,
|
||||
gw_vars.DATA_SLAVE_GAS_FAULT,
|
||||
gw_vars.DATA_SLAVE_AIR_PRESS_FAULT,
|
||||
gw_vars.DATA_SLAVE_WATER_OVERTEMP,
|
||||
gw_vars.DATA_REMOTE_TRANSFER_DHW,
|
||||
gw_vars.DATA_REMOTE_TRANSFER_MAX_CH,
|
||||
gw_vars.DATA_REMOTE_RW_DHW,
|
||||
gw_vars.DATA_REMOTE_RW_MAX_CH,
|
||||
gw_vars.DATA_ROVRD_MAN_PRIO,
|
||||
gw_vars.DATA_ROVRD_AUTO_PRIO,
|
||||
gw_vars.OTGW_GPIO_A_STATE,
|
||||
gw_vars.OTGW_GPIO_B_STATE,
|
||||
gw_vars.OTGW_IGNORE_TRANSITIONS,
|
||||
gw_vars.OTGW_OVRD_HB,
|
||||
],
|
||||
COMP_SENSOR: [
|
||||
gw_vars.DATA_CONTROL_SETPOINT,
|
||||
gw_vars.DATA_MASTER_MEMBERID,
|
||||
gw_vars.DATA_SLAVE_MEMBERID,
|
||||
gw_vars.DATA_SLAVE_OEM_FAULT,
|
||||
gw_vars.DATA_COOLING_CONTROL,
|
||||
gw_vars.DATA_CONTROL_SETPOINT_2,
|
||||
gw_vars.DATA_ROOM_SETPOINT_OVRD,
|
||||
gw_vars.DATA_SLAVE_MAX_RELATIVE_MOD,
|
||||
gw_vars.DATA_SLAVE_MAX_CAPACITY,
|
||||
gw_vars.DATA_SLAVE_MIN_MOD_LEVEL,
|
||||
gw_vars.DATA_ROOM_SETPOINT,
|
||||
gw_vars.DATA_REL_MOD_LEVEL,
|
||||
gw_vars.DATA_CH_WATER_PRESS,
|
||||
gw_vars.DATA_DHW_FLOW_RATE,
|
||||
gw_vars.DATA_ROOM_SETPOINT_2,
|
||||
gw_vars.DATA_ROOM_TEMP,
|
||||
gw_vars.DATA_CH_WATER_TEMP,
|
||||
gw_vars.DATA_DHW_TEMP,
|
||||
gw_vars.DATA_OUTSIDE_TEMP,
|
||||
gw_vars.DATA_RETURN_WATER_TEMP,
|
||||
gw_vars.DATA_SOLAR_STORAGE_TEMP,
|
||||
gw_vars.DATA_SOLAR_COLL_TEMP,
|
||||
gw_vars.DATA_CH_WATER_TEMP_2,
|
||||
gw_vars.DATA_DHW_TEMP_2,
|
||||
gw_vars.DATA_EXHAUST_TEMP,
|
||||
gw_vars.DATA_SLAVE_DHW_MAX_SETP,
|
||||
gw_vars.DATA_SLAVE_DHW_MIN_SETP,
|
||||
gw_vars.DATA_SLAVE_CH_MAX_SETP,
|
||||
gw_vars.DATA_SLAVE_CH_MIN_SETP,
|
||||
gw_vars.DATA_DHW_SETPOINT,
|
||||
gw_vars.DATA_MAX_CH_SETPOINT,
|
||||
gw_vars.DATA_OEM_DIAG,
|
||||
gw_vars.DATA_TOTAL_BURNER_STARTS,
|
||||
gw_vars.DATA_CH_PUMP_STARTS,
|
||||
gw_vars.DATA_DHW_PUMP_STARTS,
|
||||
gw_vars.DATA_DHW_BURNER_STARTS,
|
||||
gw_vars.DATA_TOTAL_BURNER_HOURS,
|
||||
gw_vars.DATA_CH_PUMP_HOURS,
|
||||
gw_vars.DATA_DHW_PUMP_HOURS,
|
||||
gw_vars.DATA_DHW_BURNER_HOURS,
|
||||
gw_vars.DATA_MASTER_OT_VERSION,
|
||||
gw_vars.DATA_SLAVE_OT_VERSION,
|
||||
gw_vars.DATA_MASTER_PRODUCT_TYPE,
|
||||
gw_vars.DATA_MASTER_PRODUCT_VERSION,
|
||||
gw_vars.DATA_SLAVE_PRODUCT_TYPE,
|
||||
gw_vars.DATA_SLAVE_PRODUCT_VERSION,
|
||||
gw_vars.OTGW_MODE,
|
||||
gw_vars.OTGW_DHW_OVRD,
|
||||
gw_vars.OTGW_ABOUT,
|
||||
gw_vars.OTGW_BUILD,
|
||||
gw_vars.OTGW_CLOCKMHZ,
|
||||
gw_vars.OTGW_LED_A,
|
||||
gw_vars.OTGW_LED_B,
|
||||
gw_vars.OTGW_LED_C,
|
||||
gw_vars.OTGW_LED_D,
|
||||
gw_vars.OTGW_LED_E,
|
||||
gw_vars.OTGW_LED_F,
|
||||
gw_vars.OTGW_GPIO_A,
|
||||
gw_vars.OTGW_GPIO_B,
|
||||
gw_vars.OTGW_SB_TEMP,
|
||||
gw_vars.OTGW_SETP_OVRD_MODE,
|
||||
gw_vars.OTGW_SMART_PWR,
|
||||
gw_vars.OTGW_THRM_DETECT,
|
||||
gw_vars.OTGW_VREF,
|
||||
]
|
||||
}
|
||||
binary_sensors = []
|
||||
sensors = []
|
||||
for var in monitored_vars:
|
||||
if var in sensor_type_map[COMP_SENSOR]:
|
||||
sensors.append(var)
|
||||
elif var in sensor_type_map[COMP_BINARY_SENSOR]:
|
||||
binary_sensors.append(var)
|
||||
else:
|
||||
_LOGGER.error("Monitored variable not supported: %s", var)
|
||||
if binary_sensors:
|
||||
hass.async_create_task(async_load_platform(
|
||||
hass, COMP_BINARY_SENSOR, DOMAIN, binary_sensors, config))
|
||||
if sensors:
|
||||
hass.async_create_task(async_load_platform(
|
||||
hass, COMP_SENSOR, DOMAIN, sensors, config))
|
||||
class OpenThermGatewayDevice():
|
||||
"""OpenTherm Gateway device class."""
|
||||
|
||||
def __init__(self, hass, gw_id, config):
|
||||
"""Initialize the OpenTherm Gateway."""
|
||||
self.hass = hass
|
||||
self.gw_id = gw_id
|
||||
self.name = config.get(CONF_NAME, gw_id)
|
||||
self.climate_config = config[CONF_CLIMATE]
|
||||
self.status = {}
|
||||
self.update_signal = '{}_{}_update'.format(DATA_OPENTHERM_GW, gw_id)
|
||||
self.gateway = pyotgw.pyotgw()
|
||||
|
||||
async def connect_and_subscribe(self, device_path):
|
||||
"""Connect to serial device and subscribe report handler."""
|
||||
await self.gateway.connect(self.hass.loop, device_path)
|
||||
_LOGGER.debug("Connected to OpenTherm Gateway at %s", device_path)
|
||||
|
||||
async def cleanup(event):
|
||||
"""Reset overrides on the gateway."""
|
||||
await self.gateway.set_control_setpoint(0)
|
||||
await self.gateway.set_max_relative_mod('-')
|
||||
self.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)
|
||||
self.status = status
|
||||
async_dispatcher_send(self.hass, self.update_signal, status)
|
||||
self.gateway.subscribe(handle_report)
|
||||
|
@ -3,116 +3,54 @@ import logging
|
||||
|
||||
from homeassistant.components.binary_sensor import (
|
||||
ENTITY_ID_FORMAT, BinarySensorDevice)
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity import async_generate_entity_id
|
||||
|
||||
from . import DATA_GW_VARS, DATA_OPENTHERM_GW, SIGNAL_OPENTHERM_GW_UPDATE
|
||||
from .const import BINARY_SENSOR_INFO, DATA_GATEWAYS, DATA_OPENTHERM_GW
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DEVICE_CLASS_COLD = 'cold'
|
||||
DEVICE_CLASS_HEAT = 'heat'
|
||||
DEVICE_CLASS_PROBLEM = 'problem'
|
||||
|
||||
|
||||
async def async_setup_platform(
|
||||
hass, config, async_add_entities, discovery_info=None):
|
||||
"""Set up the OpenTherm Gateway binary sensors."""
|
||||
if discovery_info is None:
|
||||
return
|
||||
gw_vars = hass.data[DATA_OPENTHERM_GW][DATA_GW_VARS]
|
||||
sensor_info = {
|
||||
# [device_class, friendly_name]
|
||||
gw_vars.DATA_MASTER_CH_ENABLED: [
|
||||
None, "Thermostat Central Heating Enabled"],
|
||||
gw_vars.DATA_MASTER_DHW_ENABLED: [
|
||||
None, "Thermostat Hot Water Enabled"],
|
||||
gw_vars.DATA_MASTER_COOLING_ENABLED: [
|
||||
None, "Thermostat Cooling Enabled"],
|
||||
gw_vars.DATA_MASTER_OTC_ENABLED: [
|
||||
None, "Thermostat Outside Temperature Correction Enabled"],
|
||||
gw_vars.DATA_MASTER_CH2_ENABLED: [
|
||||
None, "Thermostat Central Heating 2 Enabled"],
|
||||
gw_vars.DATA_SLAVE_FAULT_IND: [
|
||||
DEVICE_CLASS_PROBLEM, "Boiler Fault Indication"],
|
||||
gw_vars.DATA_SLAVE_CH_ACTIVE: [
|
||||
DEVICE_CLASS_HEAT, "Boiler Central Heating Status"],
|
||||
gw_vars.DATA_SLAVE_DHW_ACTIVE: [
|
||||
DEVICE_CLASS_HEAT, "Boiler Hot Water Status"],
|
||||
gw_vars.DATA_SLAVE_FLAME_ON: [
|
||||
DEVICE_CLASS_HEAT, "Boiler Flame Status"],
|
||||
gw_vars.DATA_SLAVE_COOLING_ACTIVE: [
|
||||
DEVICE_CLASS_COLD, "Boiler Cooling Status"],
|
||||
gw_vars.DATA_SLAVE_CH2_ACTIVE: [
|
||||
DEVICE_CLASS_HEAT, "Boiler Central Heating 2 Status"],
|
||||
gw_vars.DATA_SLAVE_DIAG_IND: [
|
||||
DEVICE_CLASS_PROBLEM, "Boiler Diagnostics Indication"],
|
||||
gw_vars.DATA_SLAVE_DHW_PRESENT: [None, "Boiler Hot Water Present"],
|
||||
gw_vars.DATA_SLAVE_CONTROL_TYPE: [None, "Boiler Control Type"],
|
||||
gw_vars.DATA_SLAVE_COOLING_SUPPORTED: [None, "Boiler Cooling Support"],
|
||||
gw_vars.DATA_SLAVE_DHW_CONFIG: [
|
||||
None, "Boiler Hot Water Configuration"],
|
||||
gw_vars.DATA_SLAVE_MASTER_LOW_OFF_PUMP: [
|
||||
None, "Boiler Pump Commands Support"],
|
||||
gw_vars.DATA_SLAVE_CH2_PRESENT: [
|
||||
None, "Boiler Central Heating 2 Present"],
|
||||
gw_vars.DATA_SLAVE_SERVICE_REQ: [
|
||||
DEVICE_CLASS_PROBLEM, "Boiler Service Required"],
|
||||
gw_vars.DATA_SLAVE_REMOTE_RESET: [None, "Boiler Remote Reset Support"],
|
||||
gw_vars.DATA_SLAVE_LOW_WATER_PRESS: [
|
||||
DEVICE_CLASS_PROBLEM, "Boiler Low Water Pressure"],
|
||||
gw_vars.DATA_SLAVE_GAS_FAULT: [
|
||||
DEVICE_CLASS_PROBLEM, "Boiler Gas Fault"],
|
||||
gw_vars.DATA_SLAVE_AIR_PRESS_FAULT: [
|
||||
DEVICE_CLASS_PROBLEM, "Boiler Air Pressure Fault"],
|
||||
gw_vars.DATA_SLAVE_WATER_OVERTEMP: [
|
||||
DEVICE_CLASS_PROBLEM, "Boiler Water Overtemperature"],
|
||||
gw_vars.DATA_REMOTE_TRANSFER_DHW: [
|
||||
None, "Remote Hot Water Setpoint Transfer Support"],
|
||||
gw_vars.DATA_REMOTE_TRANSFER_MAX_CH: [
|
||||
None, "Remote Maximum Central Heating Setpoint Write Support"],
|
||||
gw_vars.DATA_REMOTE_RW_DHW: [
|
||||
None, "Remote Hot Water Setpoint Write Support"],
|
||||
gw_vars.DATA_REMOTE_RW_MAX_CH: [
|
||||
None, "Remote Central Heating Setpoint Write Support"],
|
||||
gw_vars.DATA_ROVRD_MAN_PRIO: [
|
||||
None, "Remote Override Manual Change Priority"],
|
||||
gw_vars.DATA_ROVRD_AUTO_PRIO: [
|
||||
None, "Remote Override Program Change Priority"],
|
||||
gw_vars.OTGW_GPIO_A_STATE: [None, "Gateway GPIO A State"],
|
||||
gw_vars.OTGW_GPIO_B_STATE: [None, "Gateway GPIO B State"],
|
||||
gw_vars.OTGW_IGNORE_TRANSITIONS: [None, "Gateway Ignore Transitions"],
|
||||
gw_vars.OTGW_OVRD_HB: [None, "Gateway Override High Byte"],
|
||||
}
|
||||
gw_dev = hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS][discovery_info]
|
||||
sensors = []
|
||||
for var in discovery_info:
|
||||
device_class = sensor_info[var][0]
|
||||
friendly_name = sensor_info[var][1]
|
||||
entity_id = async_generate_entity_id(ENTITY_ID_FORMAT, var, hass=hass)
|
||||
sensors.append(OpenThermBinarySensor(entity_id, var, device_class,
|
||||
friendly_name))
|
||||
for var, info in BINARY_SENSOR_INFO.items():
|
||||
device_class = info[0]
|
||||
friendly_name_format = info[1]
|
||||
sensors.append(OpenThermBinarySensor(gw_dev, var, device_class,
|
||||
friendly_name_format))
|
||||
async_add_entities(sensors)
|
||||
|
||||
|
||||
class OpenThermBinarySensor(BinarySensorDevice):
|
||||
"""Represent an OpenTherm Gateway binary sensor."""
|
||||
|
||||
def __init__(self, entity_id, var, device_class, friendly_name):
|
||||
def __init__(self, gw_dev, var, device_class, friendly_name_format):
|
||||
"""Initialize the binary sensor."""
|
||||
self.entity_id = entity_id
|
||||
self.entity_id = async_generate_entity_id(
|
||||
ENTITY_ID_FORMAT, '{}_{}'.format(var, gw_dev.gw_id),
|
||||
hass=gw_dev.hass)
|
||||
self._gateway = gw_dev
|
||||
self._var = var
|
||||
self._state = None
|
||||
self._device_class = device_class
|
||||
self._friendly_name = friendly_name
|
||||
self._friendly_name = friendly_name_format.format(gw_dev.name)
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Subscribe to updates from the component."""
|
||||
_LOGGER.debug(
|
||||
"Added OpenTherm Gateway binary sensor %s", self._friendly_name)
|
||||
async_dispatcher_connect(self.hass, SIGNAL_OPENTHERM_GW_UPDATE,
|
||||
async_dispatcher_connect(self.hass, self._gateway.update_signal,
|
||||
self.receive_report)
|
||||
|
||||
async def receive_report(self, status):
|
||||
@callback
|
||||
def receive_report(self, status):
|
||||
"""Handle status updates from the component."""
|
||||
self._state = bool(status.get(self._var))
|
||||
self.async_schedule_update_ha_state()
|
||||
|
@ -1,17 +1,21 @@
|
||||
"""Support for OpenTherm Gateway climate devices."""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.climate import ClimateDevice
|
||||
from pyotgw import vars as gw_vars
|
||||
|
||||
from homeassistant.components.climate import ClimateDevice, ENTITY_ID_FORMAT
|
||||
from homeassistant.components.climate.const import (
|
||||
STATE_COOL, STATE_HEAT, STATE_IDLE, SUPPORT_TARGET_TEMPERATURE)
|
||||
from homeassistant.const import (
|
||||
ATTR_TEMPERATURE, CONF_NAME, PRECISION_HALVES, PRECISION_TENTHS,
|
||||
PRECISION_WHOLE, TEMP_CELSIUS)
|
||||
ATTR_TEMPERATURE, PRECISION_HALVES, PRECISION_TENTHS, PRECISION_WHOLE,
|
||||
TEMP_CELSIUS)
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity import async_generate_entity_id
|
||||
|
||||
from .const import (
|
||||
CONF_FLOOR_TEMP, CONF_PRECISION, DATA_GATEWAYS, DATA_OPENTHERM_GW)
|
||||
|
||||
from . import (
|
||||
CONF_FLOOR_TEMP, CONF_PRECISION, DATA_DEVICE, DATA_GW_VARS,
|
||||
DATA_OPENTHERM_GW, SIGNAL_OPENTHERM_GW_UPDATE)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@ -21,20 +25,22 @@ SUPPORT_FLAGS = SUPPORT_TARGET_TEMPERATURE
|
||||
async def async_setup_platform(
|
||||
hass, config, async_add_entities, discovery_info=None):
|
||||
"""Set up the opentherm_gw device."""
|
||||
gateway = OpenThermGateway(hass, discovery_info)
|
||||
gw_dev = hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS][discovery_info]
|
||||
gateway = OpenThermClimate(gw_dev)
|
||||
async_add_entities([gateway])
|
||||
|
||||
|
||||
class OpenThermGateway(ClimateDevice):
|
||||
class OpenThermClimate(ClimateDevice):
|
||||
"""Representation of a climate device."""
|
||||
|
||||
def __init__(self, hass, config):
|
||||
def __init__(self, gw_dev):
|
||||
"""Initialize the device."""
|
||||
self._gateway = hass.data[DATA_OPENTHERM_GW][DATA_DEVICE]
|
||||
self._gw_vars = hass.data[DATA_OPENTHERM_GW][DATA_GW_VARS]
|
||||
self.friendly_name = config.get(CONF_NAME)
|
||||
self.floor_temp = config.get(CONF_FLOOR_TEMP)
|
||||
self.temp_precision = config.get(CONF_PRECISION)
|
||||
self._gateway = gw_dev
|
||||
self.entity_id = async_generate_entity_id(
|
||||
ENTITY_ID_FORMAT, gw_dev.gw_id, hass=gw_dev.hass)
|
||||
self.friendly_name = gw_dev.name
|
||||
self.floor_temp = gw_dev.climate_config[CONF_FLOOR_TEMP]
|
||||
self.temp_precision = gw_dev.climate_config.get(CONF_PRECISION)
|
||||
self._current_operation = STATE_IDLE
|
||||
self._current_temperature = None
|
||||
self._new_target_temperature = None
|
||||
@ -47,36 +53,37 @@ class OpenThermGateway(ClimateDevice):
|
||||
async def async_added_to_hass(self):
|
||||
"""Connect to the OpenTherm Gateway device."""
|
||||
_LOGGER.debug("Added device %s", self.friendly_name)
|
||||
async_dispatcher_connect(self.hass, SIGNAL_OPENTHERM_GW_UPDATE,
|
||||
async_dispatcher_connect(self.hass, self._gateway.update_signal,
|
||||
self.receive_report)
|
||||
|
||||
async def receive_report(self, status):
|
||||
@callback
|
||||
def receive_report(self, status):
|
||||
"""Receive and handle a new report from the Gateway."""
|
||||
ch_active = status.get(self._gw_vars.DATA_SLAVE_CH_ACTIVE)
|
||||
flame_on = status.get(self._gw_vars.DATA_SLAVE_FLAME_ON)
|
||||
cooling_active = status.get(self._gw_vars.DATA_SLAVE_COOLING_ACTIVE)
|
||||
ch_active = status.get(gw_vars.DATA_SLAVE_CH_ACTIVE)
|
||||
flame_on = status.get(gw_vars.DATA_SLAVE_FLAME_ON)
|
||||
cooling_active = status.get(gw_vars.DATA_SLAVE_COOLING_ACTIVE)
|
||||
if ch_active and flame_on:
|
||||
self._current_operation = STATE_HEAT
|
||||
elif cooling_active:
|
||||
self._current_operation = STATE_COOL
|
||||
else:
|
||||
self._current_operation = STATE_IDLE
|
||||
self._current_temperature = status.get(self._gw_vars.DATA_ROOM_TEMP)
|
||||
temp_upd = status.get(self._gw_vars.DATA_ROOM_SETPOINT)
|
||||
self._current_temperature = status.get(gw_vars.DATA_ROOM_TEMP)
|
||||
temp_upd = status.get(gw_vars.DATA_ROOM_SETPOINT)
|
||||
if self._target_temperature != temp_upd:
|
||||
self._new_target_temperature = None
|
||||
self._target_temperature = temp_upd
|
||||
|
||||
# GPIO mode 5: 0 == Away
|
||||
# GPIO mode 6: 1 == Away
|
||||
gpio_a_state = status.get(self._gw_vars.OTGW_GPIO_A)
|
||||
gpio_a_state = status.get(gw_vars.OTGW_GPIO_A)
|
||||
if gpio_a_state == 5:
|
||||
self._away_mode_a = 0
|
||||
elif gpio_a_state == 6:
|
||||
self._away_mode_a = 1
|
||||
else:
|
||||
self._away_mode_a = None
|
||||
gpio_b_state = status.get(self._gw_vars.OTGW_GPIO_B)
|
||||
gpio_b_state = status.get(gw_vars.OTGW_GPIO_B)
|
||||
if gpio_b_state == 5:
|
||||
self._away_mode_b = 0
|
||||
elif gpio_b_state == 6:
|
||||
@ -85,10 +92,10 @@ class OpenThermGateway(ClimateDevice):
|
||||
self._away_mode_b = None
|
||||
if self._away_mode_a is not None:
|
||||
self._away_state_a = (status.get(
|
||||
self._gw_vars.OTGW_GPIO_A_STATE) == self._away_mode_a)
|
||||
gw_vars.OTGW_GPIO_A_STATE) == self._away_mode_a)
|
||||
if self._away_mode_b is not None:
|
||||
self._away_state_b = (status.get(
|
||||
self._gw_vars.OTGW_GPIO_B_STATE) == self._away_mode_b)
|
||||
gw_vars.OTGW_GPIO_B_STATE) == self._away_mode_b)
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
@property
|
||||
@ -126,9 +133,9 @@ class OpenThermGateway(ClimateDevice):
|
||||
if self._current_temperature is None:
|
||||
return
|
||||
if self.floor_temp is True:
|
||||
if self.temp_precision == PRECISION_HALVES:
|
||||
if self.precision == PRECISION_HALVES:
|
||||
return int(2 * self._current_temperature) / 2
|
||||
if self.temp_precision == PRECISION_TENTHS:
|
||||
if self.precision == PRECISION_TENTHS:
|
||||
return int(10 * self._current_temperature) / 10
|
||||
return int(self._current_temperature)
|
||||
return self._current_temperature
|
||||
@ -141,7 +148,7 @@ class OpenThermGateway(ClimateDevice):
|
||||
@property
|
||||
def target_temperature_step(self):
|
||||
"""Return the supported step of target temperature."""
|
||||
return self.temp_precision
|
||||
return self.precision
|
||||
|
||||
@property
|
||||
def is_away_mode_on(self):
|
||||
@ -154,8 +161,8 @@ class OpenThermGateway(ClimateDevice):
|
||||
temp = float(kwargs[ATTR_TEMPERATURE])
|
||||
if temp == self.target_temperature:
|
||||
return
|
||||
self._new_target_temperature = await self._gateway.set_target_temp(
|
||||
temp)
|
||||
self._new_target_temperature = (
|
||||
await self._gateway.gateway.set_target_temp(temp))
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
@property
|
||||
|
215
homeassistant/components/opentherm_gw/const.py
Normal file
215
homeassistant/components/opentherm_gw/const.py
Normal file
@ -0,0 +1,215 @@
|
||||
"""Constants for the opentherm_gw integration."""
|
||||
import pyotgw.vars as gw_vars
|
||||
|
||||
from homeassistant.const import DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS
|
||||
|
||||
ATTR_GW_ID = 'gateway_id'
|
||||
ATTR_MODE = 'mode'
|
||||
ATTR_LEVEL = 'level'
|
||||
|
||||
CONF_CLIMATE = 'climate'
|
||||
CONF_FLOOR_TEMP = 'floor_temperature'
|
||||
CONF_PRECISION = 'precision'
|
||||
|
||||
DATA_GATEWAYS = 'gateways'
|
||||
DATA_OPENTHERM_GW = 'opentherm_gw'
|
||||
|
||||
DEVICE_CLASS_COLD = 'cold'
|
||||
DEVICE_CLASS_HEAT = 'heat'
|
||||
DEVICE_CLASS_PROBLEM = 'problem'
|
||||
|
||||
SERVICE_RESET_GATEWAY = 'reset_gateway'
|
||||
SERVICE_SET_CLOCK = 'set_clock'
|
||||
SERVICE_SET_CONTROL_SETPOINT = 'set_control_setpoint'
|
||||
SERVICE_SET_GPIO_MODE = 'set_gpio_mode'
|
||||
SERVICE_SET_LED_MODE = 'set_led_mode'
|
||||
SERVICE_SET_MAX_MOD = 'set_max_modulation'
|
||||
SERVICE_SET_OAT = 'set_outside_temperature'
|
||||
SERVICE_SET_SB_TEMP = 'set_setback_temperature'
|
||||
|
||||
UNIT_BAR = 'bar'
|
||||
UNIT_HOUR = 'h'
|
||||
UNIT_KW = 'kW'
|
||||
UNIT_L_MIN = 'L/min'
|
||||
UNIT_PERCENT = '%'
|
||||
|
||||
BINARY_SENSOR_INFO = {
|
||||
# [device_class, friendly_name format]
|
||||
gw_vars.DATA_MASTER_CH_ENABLED: [
|
||||
None, "Thermostat Central Heating Enabled {}"],
|
||||
gw_vars.DATA_MASTER_DHW_ENABLED: [None, "Thermostat Hot Water Enabled {}"],
|
||||
gw_vars.DATA_MASTER_COOLING_ENABLED: [
|
||||
None, "Thermostat Cooling Enabled {}"],
|
||||
gw_vars.DATA_MASTER_OTC_ENABLED: [
|
||||
None, "Thermostat Outside Temperature Correction Enabled {}"],
|
||||
gw_vars.DATA_MASTER_CH2_ENABLED: [
|
||||
None, "Thermostat Central Heating 2 Enabled {}"],
|
||||
gw_vars.DATA_SLAVE_FAULT_IND: [
|
||||
DEVICE_CLASS_PROBLEM, "Boiler Fault Indication {}"],
|
||||
gw_vars.DATA_SLAVE_CH_ACTIVE: [
|
||||
DEVICE_CLASS_HEAT, "Boiler Central Heating Status {}"],
|
||||
gw_vars.DATA_SLAVE_DHW_ACTIVE: [
|
||||
DEVICE_CLASS_HEAT, "Boiler Hot Water Status {}"],
|
||||
gw_vars.DATA_SLAVE_FLAME_ON: [DEVICE_CLASS_HEAT, "Boiler Flame Status {}"],
|
||||
gw_vars.DATA_SLAVE_COOLING_ACTIVE: [
|
||||
DEVICE_CLASS_COLD, "Boiler Cooling Status {}"],
|
||||
gw_vars.DATA_SLAVE_CH2_ACTIVE: [
|
||||
DEVICE_CLASS_HEAT, "Boiler Central Heating 2 Status {}"],
|
||||
gw_vars.DATA_SLAVE_DIAG_IND: [
|
||||
DEVICE_CLASS_PROBLEM, "Boiler Diagnostics Indication {}"],
|
||||
gw_vars.DATA_SLAVE_DHW_PRESENT: [None, "Boiler Hot Water Present {}"],
|
||||
gw_vars.DATA_SLAVE_CONTROL_TYPE: [None, "Boiler Control Type {}"],
|
||||
gw_vars.DATA_SLAVE_COOLING_SUPPORTED: [None, "Boiler Cooling Support {}"],
|
||||
gw_vars.DATA_SLAVE_DHW_CONFIG: [None, "Boiler Hot Water Configuration {}"],
|
||||
gw_vars.DATA_SLAVE_MASTER_LOW_OFF_PUMP: [
|
||||
None, "Boiler Pump Commands Support {}"],
|
||||
gw_vars.DATA_SLAVE_CH2_PRESENT: [
|
||||
None, "Boiler Central Heating 2 Present {}"],
|
||||
gw_vars.DATA_SLAVE_SERVICE_REQ: [
|
||||
DEVICE_CLASS_PROBLEM, "Boiler Service Required {}"],
|
||||
gw_vars.DATA_SLAVE_REMOTE_RESET: [None, "Boiler Remote Reset Support {}"],
|
||||
gw_vars.DATA_SLAVE_LOW_WATER_PRESS: [
|
||||
DEVICE_CLASS_PROBLEM, "Boiler Low Water Pressure {}"],
|
||||
gw_vars.DATA_SLAVE_GAS_FAULT: [
|
||||
DEVICE_CLASS_PROBLEM, "Boiler Gas Fault {}"],
|
||||
gw_vars.DATA_SLAVE_AIR_PRESS_FAULT: [
|
||||
DEVICE_CLASS_PROBLEM, "Boiler Air Pressure Fault {}"],
|
||||
gw_vars.DATA_SLAVE_WATER_OVERTEMP: [
|
||||
DEVICE_CLASS_PROBLEM, "Boiler Water Overtemperature {}"],
|
||||
gw_vars.DATA_REMOTE_TRANSFER_DHW: [
|
||||
None, "Remote Hot Water Setpoint Transfer Support {}"],
|
||||
gw_vars.DATA_REMOTE_TRANSFER_MAX_CH: [
|
||||
None, "Remote Maximum Central Heating Setpoint Write Support {}"],
|
||||
gw_vars.DATA_REMOTE_RW_DHW: [
|
||||
None, "Remote Hot Water Setpoint Write Support {}"],
|
||||
gw_vars.DATA_REMOTE_RW_MAX_CH: [
|
||||
None, "Remote Central Heating Setpoint Write Support {}"],
|
||||
gw_vars.DATA_ROVRD_MAN_PRIO: [
|
||||
None, "Remote Override Manual Change Priority {}"],
|
||||
gw_vars.DATA_ROVRD_AUTO_PRIO: [
|
||||
None, "Remote Override Program Change Priority {}"],
|
||||
gw_vars.OTGW_GPIO_A_STATE: [None, "Gateway GPIO A State {}"],
|
||||
gw_vars.OTGW_GPIO_B_STATE: [None, "Gateway GPIO B State {}"],
|
||||
gw_vars.OTGW_IGNORE_TRANSITIONS: [None, "Gateway Ignore Transitions {}"],
|
||||
gw_vars.OTGW_OVRD_HB: [None, "Gateway Override High Byte {}"],
|
||||
}
|
||||
|
||||
SENSOR_INFO = {
|
||||
# [device_class, unit, friendly_name]
|
||||
gw_vars.DATA_CONTROL_SETPOINT: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, "Control Setpoint {}"],
|
||||
gw_vars.DATA_MASTER_MEMBERID: [None, None, "Thermostat Member ID {}"],
|
||||
gw_vars.DATA_SLAVE_MEMBERID: [None, None, "Boiler Member ID {}"],
|
||||
gw_vars.DATA_SLAVE_OEM_FAULT: [None, None, "Boiler OEM Fault Code {}"],
|
||||
gw_vars.DATA_COOLING_CONTROL: [
|
||||
None, UNIT_PERCENT, "Cooling Control Signal {}"],
|
||||
gw_vars.DATA_CONTROL_SETPOINT_2: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, "Control Setpoint 2 {}"],
|
||||
gw_vars.DATA_ROOM_SETPOINT_OVRD: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Room Setpoint Override {}"],
|
||||
gw_vars.DATA_SLAVE_MAX_RELATIVE_MOD: [
|
||||
None, UNIT_PERCENT, "Boiler Maximum Relative Modulation {}"],
|
||||
gw_vars.DATA_SLAVE_MAX_CAPACITY: [
|
||||
None, UNIT_KW, "Boiler Maximum Capacity {}"],
|
||||
gw_vars.DATA_SLAVE_MIN_MOD_LEVEL: [
|
||||
None, UNIT_PERCENT, "Boiler Minimum Modulation Level {}"],
|
||||
gw_vars.DATA_ROOM_SETPOINT: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, "Room Setpoint {}"],
|
||||
gw_vars.DATA_REL_MOD_LEVEL: [
|
||||
None, UNIT_PERCENT, "Relative Modulation Level {}"],
|
||||
gw_vars.DATA_CH_WATER_PRESS: [
|
||||
None, UNIT_BAR, "Central Heating Water Pressure {}"],
|
||||
gw_vars.DATA_DHW_FLOW_RATE: [
|
||||
None, UNIT_L_MIN, "Hot Water Flow Rate {}"],
|
||||
gw_vars.DATA_ROOM_SETPOINT_2: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, "Room Setpoint 2 {}"],
|
||||
gw_vars.DATA_ROOM_TEMP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, "Room Temperature {}"],
|
||||
gw_vars.DATA_CH_WATER_TEMP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Central Heating Water Temperature {}"],
|
||||
gw_vars.DATA_DHW_TEMP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Hot Water Temperature {}"],
|
||||
gw_vars.DATA_OUTSIDE_TEMP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, "Outside Temperature {}"],
|
||||
gw_vars.DATA_RETURN_WATER_TEMP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Return Water Temperature {}"],
|
||||
gw_vars.DATA_SOLAR_STORAGE_TEMP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Solar Storage Temperature {}"],
|
||||
gw_vars.DATA_SOLAR_COLL_TEMP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Solar Collector Temperature {}"],
|
||||
gw_vars.DATA_CH_WATER_TEMP_2: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Central Heating 2 Water Temperature {}"],
|
||||
gw_vars.DATA_DHW_TEMP_2: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Hot Water 2 Temperature {}"],
|
||||
gw_vars.DATA_EXHAUST_TEMP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, "Exhaust Temperature {}"],
|
||||
gw_vars.DATA_SLAVE_DHW_MAX_SETP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Hot Water Maximum Setpoint {}"],
|
||||
gw_vars.DATA_SLAVE_DHW_MIN_SETP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Hot Water Minimum Setpoint {}"],
|
||||
gw_vars.DATA_SLAVE_CH_MAX_SETP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Boiler Maximum Central Heating Setpoint {}"],
|
||||
gw_vars.DATA_SLAVE_CH_MIN_SETP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Boiler Minimum Central Heating Setpoint {}"],
|
||||
gw_vars.DATA_DHW_SETPOINT: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, "Hot Water Setpoint {}"],
|
||||
gw_vars.DATA_MAX_CH_SETPOINT: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Maximum Central Heating Setpoint {}"],
|
||||
gw_vars.DATA_OEM_DIAG: [None, None, "OEM Diagnostic Code {}"],
|
||||
gw_vars.DATA_TOTAL_BURNER_STARTS: [None, None, "Total Burner Starts {}"],
|
||||
gw_vars.DATA_CH_PUMP_STARTS: [
|
||||
None, None, "Central Heating Pump Starts {}"],
|
||||
gw_vars.DATA_DHW_PUMP_STARTS: [None, None, "Hot Water Pump Starts {}"],
|
||||
gw_vars.DATA_DHW_BURNER_STARTS: [None, None, "Hot Water Burner Starts {}"],
|
||||
gw_vars.DATA_TOTAL_BURNER_HOURS: [
|
||||
None, UNIT_HOUR, "Total Burner Hours {}"],
|
||||
gw_vars.DATA_CH_PUMP_HOURS: [
|
||||
None, UNIT_HOUR, "Central Heating Pump Hours {}"],
|
||||
gw_vars.DATA_DHW_PUMP_HOURS: [None, UNIT_HOUR, "Hot Water Pump Hours {}"],
|
||||
gw_vars.DATA_DHW_BURNER_HOURS: [
|
||||
None, UNIT_HOUR, "Hot Water Burner Hours {}"],
|
||||
gw_vars.DATA_MASTER_OT_VERSION: [
|
||||
None, None, "Thermostat OpenTherm Version {}"],
|
||||
gw_vars.DATA_SLAVE_OT_VERSION: [None, None, "Boiler OpenTherm Version {}"],
|
||||
gw_vars.DATA_MASTER_PRODUCT_TYPE: [
|
||||
None, None, "Thermostat Product Type {}"],
|
||||
gw_vars.DATA_MASTER_PRODUCT_VERSION: [
|
||||
None, None, "Thermostat Product Version {}"],
|
||||
gw_vars.DATA_SLAVE_PRODUCT_TYPE: [None, None, "Boiler Product Type {}"],
|
||||
gw_vars.DATA_SLAVE_PRODUCT_VERSION: [
|
||||
None, None, "Boiler Product Version {}"],
|
||||
gw_vars.OTGW_MODE: [None, None, "Gateway/Monitor Mode {}"],
|
||||
gw_vars.OTGW_DHW_OVRD: [None, None, "Gateway Hot Water Override Mode {}"],
|
||||
gw_vars.OTGW_ABOUT: [None, None, "Gateway Firmware Version {}"],
|
||||
gw_vars.OTGW_BUILD: [None, None, "Gateway Firmware Build {}"],
|
||||
gw_vars.OTGW_CLOCKMHZ: [None, None, "Gateway Clock Speed {}"],
|
||||
gw_vars.OTGW_LED_A: [None, None, "Gateway LED A Mode {}"],
|
||||
gw_vars.OTGW_LED_B: [None, None, "Gateway LED B Mode {}"],
|
||||
gw_vars.OTGW_LED_C: [None, None, "Gateway LED C Mode {}"],
|
||||
gw_vars.OTGW_LED_D: [None, None, "Gateway LED D Mode {}"],
|
||||
gw_vars.OTGW_LED_E: [None, None, "Gateway LED E Mode {}"],
|
||||
gw_vars.OTGW_LED_F: [None, None, "Gateway LED F Mode {}"],
|
||||
gw_vars.OTGW_GPIO_A: [None, None, "Gateway GPIO A Mode {}"],
|
||||
gw_vars.OTGW_GPIO_B: [None, None, "Gateway GPIO B Mode {}"],
|
||||
gw_vars.OTGW_SB_TEMP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Gateway Setback Temperature {}"],
|
||||
gw_vars.OTGW_SETP_OVRD_MODE: [
|
||||
None, None, "Gateway Room Setpoint Override Mode {}"],
|
||||
gw_vars.OTGW_SMART_PWR: [None, None, "Gateway Smart Power Mode {}"],
|
||||
gw_vars.OTGW_THRM_DETECT: [None, None, "Gateway Thermostat Detection {}"],
|
||||
gw_vars.OTGW_VREF: [None, None, "Gateway Reference Voltage Setting {}"],
|
||||
}
|
@ -6,5 +6,7 @@
|
||||
"pyotgw==0.4b4"
|
||||
],
|
||||
"dependencies": [],
|
||||
"codeowners": []
|
||||
"codeowners": [
|
||||
"@mvn23"
|
||||
]
|
||||
}
|
||||
|
@ -2,175 +2,55 @@
|
||||
import logging
|
||||
|
||||
from homeassistant.components.sensor import ENTITY_ID_FORMAT
|
||||
from homeassistant.const import DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity import Entity, async_generate_entity_id
|
||||
|
||||
from . import DATA_GW_VARS, DATA_OPENTHERM_GW, SIGNAL_OPENTHERM_GW_UPDATE
|
||||
from .const import DATA_GATEWAYS, DATA_OPENTHERM_GW, SENSOR_INFO
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
UNIT_BAR = 'bar'
|
||||
UNIT_HOUR = 'h'
|
||||
UNIT_KW = 'kW'
|
||||
UNIT_L_MIN = 'L/min'
|
||||
UNIT_PERCENT = '%'
|
||||
|
||||
|
||||
async def async_setup_platform(
|
||||
hass, config, async_add_entities, discovery_info=None):
|
||||
"""Set up the OpenTherm Gateway sensors."""
|
||||
if discovery_info is None:
|
||||
return
|
||||
gw_vars = hass.data[DATA_OPENTHERM_GW][DATA_GW_VARS]
|
||||
sensor_info = {
|
||||
# [device_class, unit, friendly_name]
|
||||
gw_vars.DATA_CONTROL_SETPOINT: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, "Control Setpoint"],
|
||||
gw_vars.DATA_MASTER_MEMBERID: [None, None, "Thermostat Member ID"],
|
||||
gw_vars.DATA_SLAVE_MEMBERID: [None, None, "Boiler Member ID"],
|
||||
gw_vars.DATA_SLAVE_OEM_FAULT: [None, None, "Boiler OEM Fault Code"],
|
||||
gw_vars.DATA_COOLING_CONTROL: [
|
||||
None, UNIT_PERCENT, "Cooling Control Signal"],
|
||||
gw_vars.DATA_CONTROL_SETPOINT_2: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, "Control Setpoint 2"],
|
||||
gw_vars.DATA_ROOM_SETPOINT_OVRD: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, "Room Setpoint Override"],
|
||||
gw_vars.DATA_SLAVE_MAX_RELATIVE_MOD: [
|
||||
None, UNIT_PERCENT, "Boiler Maximum Relative Modulation"],
|
||||
gw_vars.DATA_SLAVE_MAX_CAPACITY: [
|
||||
None, UNIT_KW, "Boiler Maximum Capacity"],
|
||||
gw_vars.DATA_SLAVE_MIN_MOD_LEVEL: [
|
||||
None, UNIT_PERCENT, "Boiler Minimum Modulation Level"],
|
||||
gw_vars.DATA_ROOM_SETPOINT: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, "Room Setpoint"],
|
||||
gw_vars.DATA_REL_MOD_LEVEL: [
|
||||
None, UNIT_PERCENT, "Relative Modulation Level"],
|
||||
gw_vars.DATA_CH_WATER_PRESS: [
|
||||
None, UNIT_BAR, "Central Heating Water Pressure"],
|
||||
gw_vars.DATA_DHW_FLOW_RATE: [None, UNIT_L_MIN, "Hot Water Flow Rate"],
|
||||
gw_vars.DATA_ROOM_SETPOINT_2: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, "Room Setpoint 2"],
|
||||
gw_vars.DATA_ROOM_TEMP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, "Room Temperature"],
|
||||
gw_vars.DATA_CH_WATER_TEMP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Central Heating Water Temperature"],
|
||||
gw_vars.DATA_DHW_TEMP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, "Hot Water Temperature"],
|
||||
gw_vars.DATA_OUTSIDE_TEMP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, "Outside Temperature"],
|
||||
gw_vars.DATA_RETURN_WATER_TEMP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Return Water Temperature"],
|
||||
gw_vars.DATA_SOLAR_STORAGE_TEMP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Solar Storage Temperature"],
|
||||
gw_vars.DATA_SOLAR_COLL_TEMP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Solar Collector Temperature"],
|
||||
gw_vars.DATA_CH_WATER_TEMP_2: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Central Heating 2 Water Temperature"],
|
||||
gw_vars.DATA_DHW_TEMP_2: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, "Hot Water 2 Temperature"],
|
||||
gw_vars.DATA_EXHAUST_TEMP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, "Exhaust Temperature"],
|
||||
gw_vars.DATA_SLAVE_DHW_MAX_SETP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Hot Water Maximum Setpoint"],
|
||||
gw_vars.DATA_SLAVE_DHW_MIN_SETP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Hot Water Minimum Setpoint"],
|
||||
gw_vars.DATA_SLAVE_CH_MAX_SETP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Boiler Maximum Central Heating Setpoint"],
|
||||
gw_vars.DATA_SLAVE_CH_MIN_SETP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Boiler Minimum Central Heating Setpoint"],
|
||||
gw_vars.DATA_DHW_SETPOINT: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, "Hot Water Setpoint"],
|
||||
gw_vars.DATA_MAX_CH_SETPOINT: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Maximum Central Heating Setpoint"],
|
||||
gw_vars.DATA_OEM_DIAG: [None, None, "OEM Diagnostic Code"],
|
||||
gw_vars.DATA_TOTAL_BURNER_STARTS: [
|
||||
None, None, "Total Burner Starts"],
|
||||
gw_vars.DATA_CH_PUMP_STARTS: [
|
||||
None, None, "Central Heating Pump Starts"],
|
||||
gw_vars.DATA_DHW_PUMP_STARTS: [None, None, "Hot Water Pump Starts"],
|
||||
gw_vars.DATA_DHW_BURNER_STARTS: [
|
||||
None, None, "Hot Water Burner Starts"],
|
||||
gw_vars.DATA_TOTAL_BURNER_HOURS: [
|
||||
None, UNIT_HOUR, "Total Burner Hours"],
|
||||
gw_vars.DATA_CH_PUMP_HOURS: [
|
||||
None, UNIT_HOUR, "Central Heating Pump Hours"],
|
||||
gw_vars.DATA_DHW_PUMP_HOURS: [None, UNIT_HOUR, "Hot Water Pump Hours"],
|
||||
gw_vars.DATA_DHW_BURNER_HOURS: [
|
||||
None, UNIT_HOUR, "Hot Water Burner Hours"],
|
||||
gw_vars.DATA_MASTER_OT_VERSION: [
|
||||
None, None, "Thermostat OpenTherm Version"],
|
||||
gw_vars.DATA_SLAVE_OT_VERSION: [
|
||||
None, None, "Boiler OpenTherm Version"],
|
||||
gw_vars.DATA_MASTER_PRODUCT_TYPE: [
|
||||
None, None, "Thermostat Product Type"],
|
||||
gw_vars.DATA_MASTER_PRODUCT_VERSION: [
|
||||
None, None, "Thermostat Product Version"],
|
||||
gw_vars.DATA_SLAVE_PRODUCT_TYPE: [None, None, "Boiler Product Type"],
|
||||
gw_vars.DATA_SLAVE_PRODUCT_VERSION: [
|
||||
None, None, "Boiler Product Version"],
|
||||
gw_vars.OTGW_MODE: [None, None, "Gateway/Monitor Mode"],
|
||||
gw_vars.OTGW_DHW_OVRD: [None, None, "Gateway Hot Water Override Mode"],
|
||||
gw_vars.OTGW_ABOUT: [None, None, "Gateway Firmware Version"],
|
||||
gw_vars.OTGW_BUILD: [None, None, "Gateway Firmware Build"],
|
||||
gw_vars.OTGW_CLOCKMHZ: [None, None, "Gateway Clock Speed"],
|
||||
gw_vars.OTGW_LED_A: [None, None, "Gateway LED A Mode"],
|
||||
gw_vars.OTGW_LED_B: [None, None, "Gateway LED B Mode"],
|
||||
gw_vars.OTGW_LED_C: [None, None, "Gateway LED C Mode"],
|
||||
gw_vars.OTGW_LED_D: [None, None, "Gateway LED D Mode"],
|
||||
gw_vars.OTGW_LED_E: [None, None, "Gateway LED E Mode"],
|
||||
gw_vars.OTGW_LED_F: [None, None, "Gateway LED F Mode"],
|
||||
gw_vars.OTGW_GPIO_A: [None, None, "Gateway GPIO A Mode"],
|
||||
gw_vars.OTGW_GPIO_B: [None, None, "Gateway GPIO B Mode"],
|
||||
gw_vars.OTGW_SB_TEMP: [
|
||||
DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS,
|
||||
"Gateway Setback Temperature"],
|
||||
gw_vars.OTGW_SETP_OVRD_MODE: [
|
||||
None, None, "Gateway Room Setpoint Override Mode"],
|
||||
gw_vars.OTGW_SMART_PWR: [None, None, "Gateway Smart Power Mode"],
|
||||
gw_vars.OTGW_THRM_DETECT: [None, None, "Gateway Thermostat Detection"],
|
||||
gw_vars.OTGW_VREF: [None, None, "Gateway Reference Voltage Setting"],
|
||||
}
|
||||
gw_dev = hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS][discovery_info]
|
||||
sensors = []
|
||||
for var in discovery_info:
|
||||
device_class = sensor_info[var][0]
|
||||
unit = sensor_info[var][1]
|
||||
friendly_name = sensor_info[var][2]
|
||||
entity_id = async_generate_entity_id(ENTITY_ID_FORMAT, var, hass=hass)
|
||||
sensors.append(
|
||||
OpenThermSensor(entity_id, var, device_class, unit, friendly_name))
|
||||
for var, info in SENSOR_INFO.items():
|
||||
device_class = info[0]
|
||||
unit = info[1]
|
||||
friendly_name_format = info[2]
|
||||
sensors.append(OpenThermSensor(gw_dev, var, device_class, unit,
|
||||
friendly_name_format))
|
||||
async_add_entities(sensors)
|
||||
|
||||
|
||||
class OpenThermSensor(Entity):
|
||||
"""Representation of an OpenTherm Gateway sensor."""
|
||||
|
||||
def __init__(self, entity_id, var, device_class, unit, friendly_name):
|
||||
def __init__(self, gw_dev, var, device_class, unit, friendly_name_format):
|
||||
"""Initialize the OpenTherm Gateway sensor."""
|
||||
self.entity_id = entity_id
|
||||
self.entity_id = async_generate_entity_id(
|
||||
ENTITY_ID_FORMAT, '{}_{}'.format(var, gw_dev.gw_id),
|
||||
hass=gw_dev.hass)
|
||||
self._gateway = gw_dev
|
||||
self._var = var
|
||||
self._value = None
|
||||
self._device_class = device_class
|
||||
self._unit = unit
|
||||
self._friendly_name = friendly_name
|
||||
self._friendly_name = friendly_name_format.format(gw_dev.name)
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Subscribe to updates from the component."""
|
||||
_LOGGER.debug("Added OpenTherm Gateway sensor %s", self._friendly_name)
|
||||
async_dispatcher_connect(self.hass, SIGNAL_OPENTHERM_GW_UPDATE,
|
||||
async_dispatcher_connect(self.hass, self._gateway.update_signal,
|
||||
self.receive_report)
|
||||
|
||||
async def receive_report(self, status):
|
||||
@callback
|
||||
def receive_report(self, status):
|
||||
"""Handle status updates from the component."""
|
||||
value = status.get(self._var)
|
||||
if isinstance(value, float):
|
||||
|
@ -2,10 +2,17 @@
|
||||
|
||||
reset_gateway:
|
||||
description: Reset the OpenTherm Gateway.
|
||||
fields:
|
||||
gateway_id:
|
||||
description: The gateway_id of the OpenTherm Gateway.
|
||||
example: 'opentherm_gateway'
|
||||
|
||||
set_clock:
|
||||
description: Set the clock and day of the week on the connected thermostat.
|
||||
fields:
|
||||
gateway_id:
|
||||
description: The gateway_id of the OpenTherm Gateway.
|
||||
example: 'opentherm_gateway'
|
||||
date:
|
||||
description: Optional date from which the day of the week will be extracted. Defaults to today.
|
||||
example: '2018-10-23'
|
||||
@ -18,6 +25,9 @@ set_control_setpoint:
|
||||
Set the central heating control setpoint override on the gateway.
|
||||
You will only need this if you are writing your own software thermostat.
|
||||
fields:
|
||||
gateway_id:
|
||||
description: The gateway_id of the OpenTherm Gateway.
|
||||
example: 'opentherm_gateway'
|
||||
temperature:
|
||||
description: >
|
||||
The central heating setpoint to set on the gateway.
|
||||
@ -28,6 +38,9 @@ set_control_setpoint:
|
||||
set_gpio_mode:
|
||||
description: Change the function of the GPIO pins of the gateway.
|
||||
fields:
|
||||
gateway_id:
|
||||
description: The gateway_id of the OpenTherm Gateway.
|
||||
example: 'opentherm_gateway'
|
||||
id:
|
||||
description: The ID of the GPIO pin. Either "A" or "B".
|
||||
example: 'B'
|
||||
@ -40,6 +53,9 @@ set_gpio_mode:
|
||||
set_led_mode:
|
||||
description: Change the function of the LEDs of the gateway.
|
||||
fields:
|
||||
gateway_id:
|
||||
description: The gateway_id of the OpenTherm Gateway.
|
||||
example: 'opentherm_gateway'
|
||||
id:
|
||||
description: The ID of the LED. Possible values are "A" through "F".
|
||||
example: 'C'
|
||||
@ -54,6 +70,9 @@ set_max_modulation:
|
||||
Override the maximum relative modulation level.
|
||||
You will only need this if you are writing your own software thermostat.
|
||||
fields:
|
||||
gateway_id:
|
||||
description: The gateway_id of the OpenTherm Gateway.
|
||||
example: 'opentherm_gateway'
|
||||
level:
|
||||
description: >
|
||||
The modulation level to provide to the gateway.
|
||||
@ -66,6 +85,9 @@ set_outside_temperature:
|
||||
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:
|
||||
gateway_id:
|
||||
description: The gateway_id of the OpenTherm Gateway.
|
||||
example: 'opentherm_gateway'
|
||||
temperature:
|
||||
description: >
|
||||
The temperature to provide to the thermostat.
|
||||
@ -76,6 +98,9 @@ set_outside_temperature:
|
||||
set_setback_temperature:
|
||||
description: Configure the setback temperature to be used with the GPIO away mode function.
|
||||
fields:
|
||||
gateway_id:
|
||||
description: The gateway_id of the OpenTherm Gateway.
|
||||
example: 'opentherm_gateway'
|
||||
temperature:
|
||||
description: The setback temperature to configure on the gateway. Values between 0.0 and 30.0 are accepted.
|
||||
example: '16.0'
|
||||
|
Loading…
x
Reference in New Issue
Block a user