From c6cee1ccd3b8557b1ad3dcc5956393029dac35cb Mon Sep 17 00:00:00 2001 From: Jonas Pedersen Date: Wed, 23 Jan 2019 17:58:45 +0100 Subject: [PATCH] Add Danfoss Air HRV support (#20138) * Add support for Danfoss Air HRV systems. * Correct lint errors after initial commit of Danfoss Air HRV support. * A couple of lint fixes for danfoss_air. * Refactor to comply with HA standards. * Style fix. * Use wildcard for danfoss_air in .coveragerc. * Remove config example from header documentation. Correct import name for platforms. --- .coveragerc | 2 + .../components/danfoss_air/__init__.py | 83 +++++++++++++++++++ .../components/danfoss_air/binary_sensor.py | 56 +++++++++++++ .../components/danfoss_air/sensor.py | 76 +++++++++++++++++ requirements_all.txt | 3 + 5 files changed, 220 insertions(+) create mode 100644 homeassistant/components/danfoss_air/__init__.py create mode 100644 homeassistant/components/danfoss_air/binary_sensor.py create mode 100644 homeassistant/components/danfoss_air/sensor.py diff --git a/.coveragerc b/.coveragerc index e9627277905..04d8f0203be 100644 --- a/.coveragerc +++ b/.coveragerc @@ -80,6 +80,8 @@ omit = homeassistant/components/digital_ocean.py homeassistant/components/*/digital_ocean.py + homeassistant/components/danfoss_air/* + homeassistant/components/dominos.py homeassistant/components/doorbird.py diff --git a/homeassistant/components/danfoss_air/__init__.py b/homeassistant/components/danfoss_air/__init__.py new file mode 100644 index 00000000000..17a3952adec --- /dev/null +++ b/homeassistant/components/danfoss_air/__init__.py @@ -0,0 +1,83 @@ +""" +Support for Danfoss Air HRV. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/danfoss_air/ +""" +from datetime import timedelta +import logging + +import voluptuous as vol + +from homeassistant.const import CONF_HOST +from homeassistant.helpers import discovery +import homeassistant.helpers.config_validation as cv +from homeassistant.util import Throttle + +REQUIREMENTS = ['pydanfossair==0.0.6'] + +_LOGGER = logging.getLogger(__name__) + +DANFOSS_AIR_PLATFORMS = ['sensor', 'binary_sensor'] +DOMAIN = 'danfoss_air' + +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60) + +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Required(CONF_HOST): cv.string, + }), +}, extra=vol.ALLOW_EXTRA) + + +def setup(hass, config): + """Set up the Danfoss Air component.""" + conf = config[DOMAIN] + + hass.data[DOMAIN] = DanfossAir(conf[CONF_HOST]) + + for platform in DANFOSS_AIR_PLATFORMS: + discovery.load_platform(hass, platform, DOMAIN, {}, config) + + return True + + +class DanfossAir: + """Handle all communication with Danfoss Air CCM unit.""" + + def __init__(self, host): + """Initialize the Danfoss Air CCM connection.""" + self._data = {} + + from pydanfossair.danfossclient import DanfossClient + + self._client = DanfossClient(host) + + def get_value(self, item): + """Get value for sensor.""" + if item in self._data: + return self._data[item] + + return None + + @Throttle(MIN_TIME_BETWEEN_UPDATES) + def update(self): + """Use the data from Danfoss Air API.""" + _LOGGER.debug("Fetching data from Danfoss Air CCM module") + from pydanfossair.commands import ReadCommand + self._data[ReadCommand.exhaustTemperature] \ + = self._client.command(ReadCommand.exhaustTemperature) + self._data[ReadCommand.outdoorTemperature] \ + = self._client.command(ReadCommand.outdoorTemperature) + self._data[ReadCommand.supplyTemperature] \ + = self._client.command(ReadCommand.supplyTemperature) + self._data[ReadCommand.extractTemperature] \ + = self._client.command(ReadCommand.extractTemperature) + self._data[ReadCommand.humidity] \ + = round(self._client.command(ReadCommand.humidity), 2) + self._data[ReadCommand.filterPercent] \ + = round(self._client.command(ReadCommand.filterPercent), 2) + self._data[ReadCommand.bypass] \ + = self._client.command(ReadCommand.bypass) + + _LOGGER.debug("Done fetching data from Danfoss Air CCM module") diff --git a/homeassistant/components/danfoss_air/binary_sensor.py b/homeassistant/components/danfoss_air/binary_sensor.py new file mode 100644 index 00000000000..905ead24a0f --- /dev/null +++ b/homeassistant/components/danfoss_air/binary_sensor.py @@ -0,0 +1,56 @@ +""" +Support for the for Danfoss Air HRV binary sensor platform. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/binary_sensor.danfoss_air/ +""" +from homeassistant.components.binary_sensor import BinarySensorDevice +from homeassistant.components.danfoss_air import DOMAIN \ + as DANFOSS_AIR_DOMAIN + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Set up the available Danfoss Air sensors etc.""" + from pydanfossair.commands import ReadCommand + data = hass.data[DANFOSS_AIR_DOMAIN] + + sensors = [["Danfoss Air Bypass Active", ReadCommand.bypass]] + + dev = [] + + for sensor in sensors: + dev.append(DanfossAirBinarySensor(data, sensor[0], sensor[1])) + + add_devices(dev, True) + + +class DanfossAirBinarySensor(BinarySensorDevice): + """Representation of a Danfoss Air binary sensor.""" + + def __init__(self, data, name, sensor_type): + """Initialize the Danfoss Air binary sensor.""" + self._data = data + self._name = name + self._state = None + self._type = sensor_type + + @property + def name(self): + """Return the name of the sensor.""" + return self._name + + @property + def is_on(self): + """Return the state of the sensor.""" + return self._state + + @property + def device_class(self): + """Type of device class.""" + return "opening" + + def update(self): + """Fetch new state data for the sensor.""" + self._data.update() + + self._state = self._data.get_value(self._type) diff --git a/homeassistant/components/danfoss_air/sensor.py b/homeassistant/components/danfoss_air/sensor.py new file mode 100644 index 00000000000..dfb9686edea --- /dev/null +++ b/homeassistant/components/danfoss_air/sensor.py @@ -0,0 +1,76 @@ +""" +Support for the for Danfoss Air HRV sensor platform. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/sensor.danfoss_air/ +""" +from homeassistant.components.danfoss_air import DOMAIN \ + as DANFOSS_AIR_DOMAIN +from homeassistant.const import TEMP_CELSIUS +from homeassistant.helpers.entity import Entity + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Set up the available Danfoss Air sensors etc.""" + from pydanfossair.commands import ReadCommand + + data = hass.data[DANFOSS_AIR_DOMAIN] + + sensors = [ + ["Danfoss Air Exhaust Temperature", TEMP_CELSIUS, + ReadCommand.exhaustTemperature], + ["Danfoss Air Outdoor Temperature", TEMP_CELSIUS, + ReadCommand.outdoorTemperature], + ["Danfoss Air Supply Temperature", TEMP_CELSIUS, + ReadCommand.supplyTemperature], + ["Danfoss Air Extract Temperature", TEMP_CELSIUS, + ReadCommand.extractTemperature], + ["Danfoss Air Remaining Filter", '%', + ReadCommand.filterPercent], + ["Danfoss Air Humidity", '%', + ReadCommand.humidity] + ] + + dev = [] + + for sensor in sensors: + dev.append(DanfossAir(data, sensor[0], sensor[1], sensor[2])) + + add_devices(dev, True) + + +class DanfossAir(Entity): + """Representation of a Sensor.""" + + def __init__(self, data, name, sensorUnit, sensorType): + """Initialize the sensor.""" + self._data = data + self._name = name + self._state = None + self._type = sensorType + self._unit = sensorUnit + + @property + def name(self): + """Return the name of the sensor.""" + return self._name + + @property + def state(self): + """Return the state of the sensor.""" + return self._state + + @property + def unit_of_measurement(self): + """Return the unit of measurement.""" + return self._unit + + def update(self): + """Update the new state of the sensor. + + This is done through the DanfossAir object tthat does the actually + communication with the Air CCM. + """ + self._data.update() + + self._state = self._data.get_value(self._type) diff --git a/requirements_all.txt b/requirements_all.txt index 1cbea00ad96..84c0cac4f7d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -954,6 +954,9 @@ pycsspeechtts==1.0.2 # homeassistant.components.daikin pydaikin==0.9 +# homeassistant.components.danfoss_air +pydanfossair==0.0.6 + # homeassistant.components.deconz pydeconz==47