diff --git a/homeassistant/components/incomfort/__init__.py b/homeassistant/components/incomfort/__init__.py index 8aaa8e7e19d..024875e38c1 100644 --- a/homeassistant/components/incomfort/__init__.py +++ b/homeassistant/components/incomfort/__init__.py @@ -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) + client = incomfort_data['client'] = InComfortGateway( + hostname, **credentials, session=async_get_clientsession(hass) + ) + try: - client = incomfort_data['client'] = InComfortGateway( - hostname, **credentials, session=async_get_clientsession(hass) - ) - 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)) diff --git a/homeassistant/components/incomfort/binary_sensor.py b/homeassistant/components/incomfort/binary_sensor.py new file mode 100644 index 00000000000..87ca5d5385f --- /dev/null +++ b/homeassistant/components/incomfort/binary_sensor.py @@ -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 diff --git a/homeassistant/components/incomfort/sensor.py b/homeassistant/components/incomfort/sensor.py new file mode 100644 index 00000000000..1d4ddff37b9 --- /dev/null +++ b/homeassistant/components/incomfort/sensor.py @@ -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]} diff --git a/homeassistant/components/incomfort/water_heater.py b/homeassistant/components/incomfort/water_heater.py index 9223902f5a3..535d55df193 100644 --- a/homeassistant/components/incomfort/water_heater.py +++ b/homeassistant/components/incomfort/water_heater.py @@ -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 - 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 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) diff --git a/homeassistant/const.py b/homeassistant/const.py index 4b78ab9618b..972e9e25f72 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -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