Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions homeassistant/components/opentherm_gw/__init__.py
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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}-{self._var}"

@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
Original file line number Diff line number Diff line change
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(
Comment thread
MartinHjelmare marked this conversation as 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
Original file line number Diff line number Diff line change
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}-{self._var}"

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