Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add opentherm_gw device support #28722

Merged
merged 4 commits into from Nov 27, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 23 additions & 7 deletions homeassistant/components/opentherm_gw/__init__.py
@@ -1,4 +1,5 @@
"""Support for OpenTherm Gateway devices."""
import asyncio
import logging
from datetime import datetime, date

Expand Down Expand Up @@ -344,6 +345,18 @@ async def set_setback_temp(call):
)


async def async_unload_entry(hass, entry):
"""Cleanup and disconnect from gateway."""
await asyncio.gather(
hass.config_entries.async_forward_entry_unload(entry, COMP_BINARY_SENSOR),
hass.config_entries.async_forward_entry_unload(entry, COMP_CLIMATE),
hass.config_entries.async_forward_entry_unload(entry, COMP_SENSOR),
)
gateway = hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS][entry.data[CONF_ID]]
await gateway.cleanup()
return True


class OpenThermGatewayDevice:
"""OpenTherm Gateway device class."""

Expand All @@ -358,18 +371,21 @@ def __init__(self, hass, config_entry):
self.update_signal = f"{DATA_OPENTHERM_GW}_{self.gw_id}_update"
self.options_update_signal = f"{DATA_OPENTHERM_GW}_{self.gw_id}_options_update"
self.gateway = pyotgw.pyotgw()
self.gw_version = None

async def cleanup(self, event=None):
"""Reset overrides on the gateway."""
await self.gateway.set_control_setpoint(0)
await self.gateway.set_max_relative_mod("-")
await self.gateway.disconnect()

async def connect_and_subscribe(self):
"""Connect to serial device and subscribe report handler."""
await self.gateway.connect(self.hass.loop, self.device_path)
self.status = await self.gateway.connect(self.hass.loop, self.device_path)
_LOGGER.debug("Connected to OpenTherm Gateway at %s", self.device_path)
self.gw_version = self.status.get(gw_vars.OTGW_BUILD)

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)
self.hass.bus.async_listen(EVENT_HOMEASSISTANT_STOP, self.cleanup)

async def handle_report(status):
"""Handle reports from the OpenTherm Gateway."""
Expand Down
32 changes: 31 additions & 1 deletion homeassistant/components/opentherm_gw/binary_sensor.py
Expand Up @@ -7,6 +7,7 @@
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import async_generate_entity_id

from . import DOMAIN
from .const import BINARY_SENSOR_INFO, DATA_GATEWAYS, DATA_OPENTHERM_GW


Expand Down Expand Up @@ -44,14 +45,27 @@ def __init__(self, gw_dev, var, device_class, friendly_name_format):
self._state = None
self._device_class = device_class
self._friendly_name = friendly_name_format.format(gw_dev.name)
self._unsub_updates = None

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._unsub_updates = async_dispatcher_connect(
self.hass, self._gateway.update_signal, self.receive_report
)

async def async_will_remove_from_hass(self):
"""Unsubscribe from updates from the component."""
_LOGGER.debug(
"Removing OpenTherm Gateway binary sensor %s", self._friendly_name
)
self._unsub_updates()

@property
def entity_registry_enabled_default(self):
"""Disable binary_sensors by default."""
return False

@callback
def receive_report(self, status):
"""Handle status updates from the component."""
Expand All @@ -63,6 +77,22 @@ def name(self):
"""Return the friendly name."""
return self._friendly_name

@property
def device_info(self):
"""Return device info."""
return {
"identifiers": {(DOMAIN, self._gateway.gw_id)},
"name": self._gateway.name,
"manufacturer": "Schelte Bron",
"model": "OpenTherm Gateway",
"sw_version": self._gateway.gw_version,
}

@property
def unique_id(self):
"""Return a unique ID."""
return f"{self._gateway.gw_id}-binary-sensor-{self._var}"
MartinHjelmare marked this conversation as resolved.
Show resolved Hide resolved

@property
def is_on(self):
"""Return true if the binary sensor is on."""
Expand Down
30 changes: 27 additions & 3 deletions homeassistant/components/opentherm_gw/climate.py
Expand Up @@ -3,7 +3,7 @@

from pyotgw import vars as gw_vars

from homeassistant.components.climate import ClimateDevice
from homeassistant.components.climate import ClimateDevice, ENTITY_ID_FORMAT
from homeassistant.components.climate.const import (
CURRENT_HVAC_COOL,
CURRENT_HVAC_HEAT,
Expand All @@ -25,7 +25,9 @@
)
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import async_generate_entity_id

from . import DOMAIN
from .const import CONF_FLOOR_TEMP, CONF_PRECISION, DATA_GATEWAYS, DATA_OPENTHERM_GW


Expand Down Expand Up @@ -53,6 +55,9 @@ class OpenThermClimate(ClimateDevice):
def __init__(self, gw_dev, options):
"""Initialize the device."""
self._gateway = gw_dev
self.entity_id = async_generate_entity_id(
MartinHjelmare marked this conversation as resolved.
Show resolved Hide resolved
ENTITY_ID_FORMAT, gw_dev.gw_id, hass=gw_dev.hass
)
self.friendly_name = gw_dev.name
self.floor_temp = options[CONF_FLOOR_TEMP]
self.temp_precision = options.get(CONF_PRECISION)
Expand All @@ -65,6 +70,8 @@ def __init__(self, gw_dev, options):
self._away_mode_b = None
self._away_state_a = False
self._away_state_b = False
self._unsub_options = None
self._unsub_updates = None

@callback
def update_options(self, entry):
Expand All @@ -76,13 +83,19 @@ def update_options(self, entry):
async def async_added_to_hass(self):
"""Connect to the OpenTherm Gateway device."""
_LOGGER.debug("Added OpenTherm Gateway climate device %s", self.friendly_name)
async_dispatcher_connect(
self._unsub_updates = async_dispatcher_connect(
self.hass, self._gateway.update_signal, self.receive_report
)
async_dispatcher_connect(
self._unsub_options = async_dispatcher_connect(
self.hass, self._gateway.options_update_signal, self.update_options
)

async def async_will_remove_from_hass(self):
"""Unsubscribe from updates from the component."""
_LOGGER.debug("Removing OpenTherm Gateway climate %s", self.friendly_name)
self._unsub_options()
self._unsub_updates()

@callback
def receive_report(self, status):
"""Receive and handle a new report from the Gateway."""
Expand Down Expand Up @@ -136,6 +149,17 @@ def name(self):
"""Return the friendly name."""
return self.friendly_name

@property
def device_info(self):
"""Return device info."""
return {
"identifiers": {(DOMAIN, self._gateway.gw_id)},
"name": self._gateway.name,
"manufacturer": "Schelte Bron",
"model": "OpenTherm Gateway",
"sw_version": self._gateway.gw_version,
}

@property
def unique_id(self):
"""Return a unique ID."""
Expand Down
30 changes: 29 additions & 1 deletion homeassistant/components/opentherm_gw/sensor.py
Expand Up @@ -7,6 +7,7 @@
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import Entity, async_generate_entity_id

from . import DOMAIN
from .const import DATA_GATEWAYS, DATA_OPENTHERM_GW, SENSOR_INFO


Expand Down Expand Up @@ -47,14 +48,25 @@ def __init__(self, gw_dev, var, device_class, unit, friendly_name_format):
self._device_class = device_class
self._unit = unit
self._friendly_name = friendly_name_format.format(gw_dev.name)
self._unsub_updates = None

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._unsub_updates = async_dispatcher_connect(
self.hass, self._gateway.update_signal, self.receive_report
)

async def async_will_remove_from_hass(self):
"""Unsubscribe from updates from the component."""
_LOGGER.debug("Removing OpenTherm Gateway sensor %s", self._friendly_name)
self._unsub_updates()

@property
def entity_registry_enabled_default(self):
"""Disable sensors by default."""
return False

@callback
def receive_report(self, status):
"""Handle status updates from the component."""
Expand All @@ -69,6 +81,22 @@ def name(self):
"""Return the friendly name of the sensor."""
return self._friendly_name

@property
def device_info(self):
"""Return device info."""
return {
"identifiers": {(DOMAIN, self._gateway.gw_id)},
"name": self._gateway.name,
"manufacturer": "Schelte Bron",
"model": "OpenTherm Gateway",
"sw_version": self._gateway.gw_version,
}

@property
def unique_id(self):
"""Return a unique ID."""
return f"{self._gateway.gw_id}-sensor-{self._var}"

@property
def device_class(self):
"""Return the device class."""
Expand Down