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 temp
This commit is contained in:
parent
d63c44f778
commit
c1d441b0ac
5 changed files with 190 additions and 16 deletions
|
@ -1,6 +1,7 @@
|
||||||
"""Support for an Intergas boiler via an InComfort/Intouch Lan2RF gateway."""
|
"""Support for an Intergas boiler via an InComfort/Intouch Lan2RF gateway."""
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from aiohttp import ClientResponseError
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
from incomfortclient import Gateway as InComfortGateway
|
from incomfortclient import Gateway as InComfortGateway
|
||||||
|
|
||||||
|
@ -30,21 +31,20 @@ async def async_setup(hass, hass_config):
|
||||||
credentials = dict(hass_config[DOMAIN])
|
credentials = dict(hass_config[DOMAIN])
|
||||||
hostname = credentials.pop(CONF_HOST)
|
hostname = credentials.pop(CONF_HOST)
|
||||||
|
|
||||||
|
client = incomfort_data['client'] = InComfortGateway(
|
||||||
|
hostname, **credentials, session=async_get_clientsession(hass)
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
client = incomfort_data['client'] = InComfortGateway(
|
|
||||||
hostname, **credentials, session=async_get_clientsession(hass)
|
|
||||||
)
|
|
||||||
|
|
||||||
heater = incomfort_data['heater'] = list(await client.heaters)[0]
|
heater = incomfort_data['heater'] = list(await client.heaters)[0]
|
||||||
await heater.update()
|
except ClientResponseError as err:
|
||||||
|
|
||||||
except AssertionError: # assert response.status == HTTP_OK
|
|
||||||
_LOGGER.warning(
|
_LOGGER.warning(
|
||||||
"Setup failed, check your configuration.",
|
"Setup failed, check your configuration, message is: %s", err)
|
||||||
exc_info=True)
|
|
||||||
return False
|
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.async_create_task(async_load_platform(
|
||||||
hass, platform, DOMAIN, {}, hass_config))
|
hass, platform, DOMAIN, {}, hass_config))
|
||||||
|
|
||||||
|
|
52
homeassistant/components/incomfort/binary_sensor.py
Normal file
52
homeassistant/components/incomfort/binary_sensor.py
Normal file
|
@ -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
|
110
homeassistant/components/incomfort/sensor.py
Normal file
110
homeassistant/components/incomfort/sensor.py
Normal file
|
@ -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 asyncio
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from aiohttp import ClientResponseError
|
||||||
from homeassistant.components.water_heater import WaterHeaterDevice
|
from homeassistant.components.water_heater import WaterHeaterDevice
|
||||||
from homeassistant.const import TEMP_CELSIUS
|
from homeassistant.const import TEMP_CELSIUS
|
||||||
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||||
|
|
||||||
from . import DOMAIN
|
from . import DOMAIN
|
||||||
|
|
||||||
|
@ -16,8 +18,8 @@ HEATER_MIN_TEMP = 30.0
|
||||||
|
|
||||||
HEATER_NAME = 'Boiler'
|
HEATER_NAME = 'Boiler'
|
||||||
HEATER_ATTRS = [
|
HEATER_ATTRS = [
|
||||||
'display_code', 'display_text', 'fault_code', 'is_burning', 'is_failed',
|
'display_code', 'display_text', 'is_burning',
|
||||||
'is_pumping', 'is_tapping', 'heater_temp', 'tap_temp', 'pressure']
|
'rf_message_rssi', 'nodenr', 'rfstatus_cntr']
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(hass, hass_config, async_add_entities,
|
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 the name of the water_heater device."""
|
||||||
return HEATER_NAME
|
return HEATER_NAME
|
||||||
|
|
||||||
|
@property
|
||||||
|
def icon(self):
|
||||||
|
"""Return the icon of the water_heater device."""
|
||||||
|
return "mdi:oil-temperature"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_state_attributes(self):
|
def device_state_attributes(self):
|
||||||
"""Return the device state attributes."""
|
"""Return the device state attributes."""
|
||||||
|
@ -55,7 +62,9 @@ class IncomfortWaterHeater(WaterHeaterDevice):
|
||||||
"""Return the current temperature."""
|
"""Return the current temperature."""
|
||||||
if self._heater.is_tapping:
|
if self._heater.is_tapping:
|
||||||
return self._heater.tap_temp
|
return self._heater.tap_temp
|
||||||
return self._heater.heater_temp
|
if self._heater.is_pumping:
|
||||||
|
return self._heater.heater_temp
|
||||||
|
return max(self._heater.heater_temp, self._heater.tap_temp)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def min_temp(self):
|
def min_temp(self):
|
||||||
|
@ -81,7 +90,7 @@ class IncomfortWaterHeater(WaterHeaterDevice):
|
||||||
def current_operation(self):
|
def current_operation(self):
|
||||||
"""Return the current operation mode."""
|
"""Return the current operation mode."""
|
||||||
if self._heater.is_failed:
|
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
|
return self._heater.display_text
|
||||||
|
|
||||||
|
@ -90,5 +99,7 @@ class IncomfortWaterHeater(WaterHeaterDevice):
|
||||||
try:
|
try:
|
||||||
await self._heater.update()
|
await self._heater.update()
|
||||||
|
|
||||||
except (AssertionError, asyncio.TimeoutError) as err:
|
except (ClientResponseError, asyncio.TimeoutError) as err:
|
||||||
_LOGGER.warning("Update failed, message: %s", 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 units
|
||||||
PRESSURE_PA = 'Pa' # type: str
|
PRESSURE_PA = 'Pa' # type: str
|
||||||
PRESSURE_HPA = 'hPa' # type: str
|
PRESSURE_HPA = 'hPa' # type: str
|
||||||
|
PRESSURE_BAR = 'bar' # type: str
|
||||||
PRESSURE_MBAR = 'mbar' # type: str
|
PRESSURE_MBAR = 'mbar' # type: str
|
||||||
PRESSURE_INHG = 'inHg' # type: str
|
PRESSURE_INHG = 'inHg' # type: str
|
||||||
PRESSURE_PSI = 'psi' # type: str
|
PRESSURE_PSI = 'psi' # type: str
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue