Add incomfort sensor and binary_sensor (#23812)
* Initial commit - add sensors to incomfort * improve temp heuristics * remove self._hass * device_state_attributes shoudln't be None * bump client * refactor to reduce duplication of attributes * refactor binary_sensor to simplify * refactor binary_sensor to simplify 2 * delint * fix rebase regression * small refactor * delint * remove DEVICE_CLASS for CV pressure * tidy up exception handling * delint * fix exception handling * use differnt icon for boiler temppull/24624/head
parent
d63c44f778
commit
c1d441b0ac
|
@ -1,6 +1,7 @@
|
|||
"""Support for an Intergas boiler via an InComfort/Intouch Lan2RF gateway."""
|
||||
import logging
|
||||
|
||||
from aiohttp import ClientResponseError
|
||||
import voluptuous as vol
|
||||
from incomfortclient import Gateway as InComfortGateway
|
||||
|
||||
|
@ -30,21 +31,20 @@ async def async_setup(hass, hass_config):
|
|||
credentials = dict(hass_config[DOMAIN])
|
||||
hostname = credentials.pop(CONF_HOST)
|
||||
|
||||
try:
|
||||
client = incomfort_data['client'] = InComfortGateway(
|
||||
hostname, **credentials, session=async_get_clientsession(hass)
|
||||
)
|
||||
|
||||
try:
|
||||
heater = incomfort_data['heater'] = list(await client.heaters)[0]
|
||||
await heater.update()
|
||||
|
||||
except AssertionError: # assert response.status == HTTP_OK
|
||||
except ClientResponseError as err:
|
||||
_LOGGER.warning(
|
||||
"Setup failed, check your configuration.",
|
||||
exc_info=True)
|
||||
"Setup failed, check your configuration, message is: %s", err)
|
||||
return False
|
||||
|
||||
for platform in ['water_heater', 'climate']:
|
||||
await heater.update()
|
||||
|
||||
for platform in ['water_heater', 'binary_sensor', 'sensor', 'climate']:
|
||||
hass.async_create_task(async_load_platform(
|
||||
hass, platform, DOMAIN, {}, hass_config))
|
||||
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
"""Support for an Intergas boiler via an InComfort/InTouch Lan2RF gateway."""
|
||||
from homeassistant.components.binary_sensor import BinarySensorDevice
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
|
||||
from . import DOMAIN
|
||||
|
||||
|
||||
async def async_setup_platform(hass, config, async_add_entities,
|
||||
discovery_info=None):
|
||||
"""Set up an InComfort/InTouch binary_sensor device."""
|
||||
async_add_entities([
|
||||
IncomfortFailed(hass.data[DOMAIN]['client'],
|
||||
hass.data[DOMAIN]['heater'])
|
||||
])
|
||||
|
||||
|
||||
class IncomfortFailed(BinarySensorDevice):
|
||||
"""Representation of an InComfort Failed sensor."""
|
||||
|
||||
def __init__(self, client, boiler):
|
||||
"""Initialize the binary sensor."""
|
||||
self._client = client
|
||||
self._boiler = boiler
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Set up a listener when this entity is added to HA."""
|
||||
async_dispatcher_connect(self.hass, DOMAIN, self._refresh)
|
||||
|
||||
@callback
|
||||
def _refresh(self):
|
||||
self.async_schedule_update_ha_state(force_refresh=True)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the sensor."""
|
||||
return 'Fault state'
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return the status of the sensor."""
|
||||
return self._boiler.status['is_failed']
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the device state attributes."""
|
||||
return {'fault_code': self._boiler.status['fault_code']}
|
||||
|
||||
@property
|
||||
def should_poll(self) -> bool:
|
||||
"""Return False as this device should never be polled."""
|
||||
return False
|
|
@ -0,0 +1,110 @@
|
|||
"""Support for an Intergas boiler via an InComfort/InTouch Lan2RF gateway."""
|
||||
from homeassistant.const import (
|
||||
PRESSURE_BAR, TEMP_CELSIUS, DEVICE_CLASS_TEMPERATURE)
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
from . import DOMAIN
|
||||
|
||||
INTOUCH_HEATER_TEMP = 'CV Temp'
|
||||
INTOUCH_PRESSURE = 'CV Pressure'
|
||||
INTOUCH_TAP_TEMP = 'Tap Temp'
|
||||
|
||||
INTOUCH_MAP_ATTRS = {
|
||||
INTOUCH_HEATER_TEMP: ['heater_temp', 'is_pumping'],
|
||||
INTOUCH_TAP_TEMP: ['tap_temp', 'is_tapping'],
|
||||
}
|
||||
|
||||
|
||||
async def async_setup_platform(hass, config, async_add_entities,
|
||||
discovery_info=None):
|
||||
"""Set up an InComfort/InTouch sensor device."""
|
||||
client = hass.data[DOMAIN]['client']
|
||||
heater = hass.data[DOMAIN]['heater']
|
||||
|
||||
async_add_entities([
|
||||
IncomfortPressure(client, heater, INTOUCH_PRESSURE),
|
||||
IncomfortTemperature(client, heater, INTOUCH_HEATER_TEMP),
|
||||
IncomfortTemperature(client, heater, INTOUCH_TAP_TEMP)
|
||||
])
|
||||
|
||||
|
||||
class IncomfortSensor(Entity):
|
||||
"""Representation of an InComfort/InTouch sensor device."""
|
||||
|
||||
def __init__(self, client, boiler):
|
||||
"""Initialize the sensor."""
|
||||
self._client = client
|
||||
self._boiler = boiler
|
||||
|
||||
self._name = None
|
||||
self._device_class = None
|
||||
self._unit_of_measurement = None
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Set up a listener when this entity is added to HA."""
|
||||
async_dispatcher_connect(self.hass, DOMAIN, self._refresh)
|
||||
|
||||
@callback
|
||||
def _refresh(self):
|
||||
self.async_schedule_update_ha_state(force_refresh=True)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the sensor."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
"""Return the device class of the sensor."""
|
||||
return self._device_class
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
"""Return the unit of measurement of the sensor."""
|
||||
return self._unit_of_measurement
|
||||
|
||||
@property
|
||||
def should_poll(self) -> bool:
|
||||
"""Return False as this device should never be polled."""
|
||||
return False
|
||||
|
||||
|
||||
class IncomfortPressure(IncomfortSensor):
|
||||
"""Representation of an InTouch CV Pressure sensor."""
|
||||
|
||||
def __init__(self, client, boiler, name):
|
||||
"""Initialize the sensor."""
|
||||
super().__init__(client, boiler)
|
||||
|
||||
self._name = name
|
||||
self._unit_of_measurement = PRESSURE_BAR
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the state/value of the sensor."""
|
||||
return self._boiler.status['pressure']
|
||||
|
||||
|
||||
class IncomfortTemperature(IncomfortSensor):
|
||||
"""Representation of an InTouch Temperature sensor."""
|
||||
|
||||
def __init__(self, client, boiler, name):
|
||||
"""Initialize the signal strength sensor."""
|
||||
super().__init__(client, boiler)
|
||||
|
||||
self._name = name
|
||||
self._device_class = DEVICE_CLASS_TEMPERATURE
|
||||
self._unit_of_measurement = TEMP_CELSIUS
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the state of the sensor."""
|
||||
return self._boiler.status[INTOUCH_MAP_ATTRS[self._name][0]]
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the device state attributes."""
|
||||
key = INTOUCH_MAP_ATTRS[self._name][1]
|
||||
return {key: self._boiler.status[key]}
|
|
@ -2,8 +2,10 @@
|
|||
import asyncio
|
||||
import logging
|
||||
|
||||
from aiohttp import ClientResponseError
|
||||
from homeassistant.components.water_heater import WaterHeaterDevice
|
||||
from homeassistant.const import TEMP_CELSIUS
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
|
||||
from . import DOMAIN
|
||||
|
||||
|
@ -16,8 +18,8 @@ HEATER_MIN_TEMP = 30.0
|
|||
|
||||
HEATER_NAME = 'Boiler'
|
||||
HEATER_ATTRS = [
|
||||
'display_code', 'display_text', 'fault_code', 'is_burning', 'is_failed',
|
||||
'is_pumping', 'is_tapping', 'heater_temp', 'tap_temp', 'pressure']
|
||||
'display_code', 'display_text', 'is_burning',
|
||||
'rf_message_rssi', 'nodenr', 'rfstatus_cntr']
|
||||
|
||||
|
||||
async def async_setup_platform(hass, hass_config, async_add_entities,
|
||||
|
@ -43,6 +45,11 @@ class IncomfortWaterHeater(WaterHeaterDevice):
|
|||
"""Return the name of the water_heater device."""
|
||||
return HEATER_NAME
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Return the icon of the water_heater device."""
|
||||
return "mdi:oil-temperature"
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the device state attributes."""
|
||||
|
@ -55,7 +62,9 @@ class IncomfortWaterHeater(WaterHeaterDevice):
|
|||
"""Return the current temperature."""
|
||||
if self._heater.is_tapping:
|
||||
return self._heater.tap_temp
|
||||
if self._heater.is_pumping:
|
||||
return self._heater.heater_temp
|
||||
return max(self._heater.heater_temp, self._heater.tap_temp)
|
||||
|
||||
@property
|
||||
def min_temp(self):
|
||||
|
@ -81,7 +90,7 @@ class IncomfortWaterHeater(WaterHeaterDevice):
|
|||
def current_operation(self):
|
||||
"""Return the current operation mode."""
|
||||
if self._heater.is_failed:
|
||||
return "Failed ({})".format(self._heater.fault_code)
|
||||
return "Fault code: {}".format(self._heater.fault_code)
|
||||
|
||||
return self._heater.display_text
|
||||
|
||||
|
@ -90,5 +99,7 @@ class IncomfortWaterHeater(WaterHeaterDevice):
|
|||
try:
|
||||
await self._heater.update()
|
||||
|
||||
except (AssertionError, asyncio.TimeoutError) as err:
|
||||
_LOGGER.warning("Update failed, message: %s", err)
|
||||
except (ClientResponseError, asyncio.TimeoutError) as err:
|
||||
_LOGGER.warning("Update failed, message is: %s", err)
|
||||
|
||||
async_dispatcher_send(self.hass, DOMAIN)
|
||||
|
|
|
@ -346,6 +346,7 @@ LENGTH_MILES = 'mi' # type: str
|
|||
# Pressure units
|
||||
PRESSURE_PA = 'Pa' # type: str
|
||||
PRESSURE_HPA = 'hPa' # type: str
|
||||
PRESSURE_BAR = 'bar' # type: str
|
||||
PRESSURE_MBAR = 'mbar' # type: str
|
||||
PRESSURE_INHG = 'inHg' # type: str
|
||||
PRESSURE_PSI = 'psi' # type: str
|
||||
|
|
Loading…
Reference in New Issue