mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Add opentherm_gw device support (#28722)
* Add opentherm_gw device support * Add support for enabling/disabling of opentherm_gw entities * Disable sensors by default, base climate entity_id on gw_id instead of friendly_name to guarantee uniqueness * Remove platform name from unique_id
This commit is contained in:
parent
12ae8b025f
commit
fdf0793fdd
@ -1,4 +1,5 @@
|
||||
"""Support for OpenTherm Gateway devices."""
|
||||
import asyncio
|
||||
import logging
|
||||
from datetime import datetime, date
|
||||
|
||||
@ -344,6 +345,18 @@ def register_services(hass):
|
||||
)
|
||||
|
||||
|
||||
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."""
|
||||
|
||||
@ -358,18 +371,21 @@ class OpenThermGatewayDevice:
|
||||
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."""
|
||||
|
@ -7,6 +7,7 @@ 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 BINARY_SENSOR_INFO, DATA_GATEWAYS, DATA_OPENTHERM_GW
|
||||
|
||||
|
||||
@ -44,14 +45,27 @@ class OpenThermBinarySensor(BinarySensorDevice):
|
||||
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."""
|
||||
@ -63,6 +77,22 @@ class OpenThermBinarySensor(BinarySensorDevice):
|
||||
"""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."""
|
||||
|
@ -3,7 +3,7 @@ import logging
|
||||
|
||||
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,
|
||||
@ -25,7 +25,9 @@ from homeassistant.const import (
|
||||
)
|
||||
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
|
||||
|
||||
|
||||
@ -56,6 +58,9 @@ class OpenThermClimate(ClimateDevice):
|
||||
def __init__(self, gw_dev, options):
|
||||
"""Initialize the device."""
|
||||
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 = options.get(CONF_FLOOR_TEMP, DEFAULT_FLOOR_TEMP)
|
||||
self.temp_precision = options.get(CONF_PRECISION, DEFAULT_PRECISION)
|
||||
@ -68,6 +73,8 @@ class OpenThermClimate(ClimateDevice):
|
||||
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):
|
||||
@ -79,13 +86,19 @@ class OpenThermClimate(ClimateDevice):
|
||||
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."""
|
||||
@ -139,6 +152,17 @@ class OpenThermClimate(ClimateDevice):
|
||||
"""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."""
|
||||
|
@ -7,6 +7,7 @@ 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 DOMAIN
|
||||
from .const import DATA_GATEWAYS, DATA_OPENTHERM_GW, SENSOR_INFO
|
||||
|
||||
|
||||
@ -47,14 +48,25 @@ class OpenThermSensor(Entity):
|
||||
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."""
|
||||
@ -69,6 +81,22 @@ class OpenThermSensor(Entity):
|
||||
"""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."""
|
||||
|
Loading…
x
Reference in New Issue
Block a user