mirror of
https://github.com/home-assistant/core.git
synced 2025-06-25 01:21:51 +02:00
Add support for Stiebel Eltron heat pumps (#21199)
* Start with Stiebel Eltron heatpump * STE HP * Add read of operating mode * Add read-write operation mode * Further extract ModBus access * Separation of platform and API * Last changes * Use modbus hub * Update module doc with config * Clean up platform code * Cleanup and update to dev2 of pystiebeleltron * Remove slave configuration * Add translation of states * Make name parameter optional * Consolidate platform * Correct .coveragerc after conflict * Prepare component for sensor platform * Fix issues found in review * Remove custom states and map to existing HA states * Force update, when values are modified * Update CODEOWNERS and requirements_all.txt * Fix .coveragerc file * Exclude stiebel_eltron components in .coveragerc * Break out to module level constant * Rename constant * Removed REQ and DEP constant.
This commit is contained in:
committed by
Martin Hjelmare
parent
39264af310
commit
0a0975b5d9
@ -559,6 +559,7 @@ omit =
|
||||
homeassistant/components/srp_energy/sensor.py
|
||||
homeassistant/components/starlingbank/sensor.py
|
||||
homeassistant/components/steam_online/sensor.py
|
||||
homeassistant/components/stiebel_eltron/*
|
||||
homeassistant/components/stride/notify.py
|
||||
homeassistant/components/supervisord/sensor.py
|
||||
homeassistant/components/swiss_hydrological_data/sensor.py
|
||||
|
@ -195,6 +195,7 @@ homeassistant/components/spaceapi/* @fabaff
|
||||
homeassistant/components/spider/* @peternijssen
|
||||
homeassistant/components/sql/* @dgomes
|
||||
homeassistant/components/statistics/* @fabaff
|
||||
homeassistant/components/stiebel_eltron/* @fucm
|
||||
homeassistant/components/sun/* @home-assistant/core
|
||||
homeassistant/components/swiss_hydrological_data/* @fabaff
|
||||
homeassistant/components/swiss_public_transport/* @fabaff
|
||||
|
59
homeassistant/components/stiebel_eltron/__init__.py
Normal file
59
homeassistant/components/stiebel_eltron/__init__.py
Normal file
@ -0,0 +1,59 @@
|
||||
"""The component for STIEBEL ELTRON heat pumps with ISGWeb Modbus module."""
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.modbus import (
|
||||
CONF_HUB, DEFAULT_HUB, DOMAIN as MODBUS_DOMAIN)
|
||||
from homeassistant.const import CONF_NAME, DEVICE_DEFAULT_NAME
|
||||
from homeassistant.helpers import discovery
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.util import Throttle
|
||||
|
||||
DOMAIN = 'stiebel_eltron'
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
DOMAIN: vol.Schema({
|
||||
vol.Optional(CONF_NAME, default=DEVICE_DEFAULT_NAME): cv.string,
|
||||
vol.Optional(CONF_HUB, default=DEFAULT_HUB): cv.string,
|
||||
})
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30)
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
"""Set up the STIEBEL ELTRON unit.
|
||||
|
||||
Will automatically load climate platform.
|
||||
"""
|
||||
name = config[DOMAIN][CONF_NAME]
|
||||
modbus_client = hass.data[MODBUS_DOMAIN][config[DOMAIN][CONF_HUB]]
|
||||
|
||||
hass.data[DOMAIN] = {
|
||||
'name': name,
|
||||
'ste_data': StiebelEltronData(name, modbus_client)
|
||||
}
|
||||
|
||||
discovery.load_platform(hass, 'climate', DOMAIN, {}, config)
|
||||
return True
|
||||
|
||||
|
||||
class StiebelEltronData:
|
||||
"""Get the latest data and update the states."""
|
||||
|
||||
def __init__(self, name, modbus_client):
|
||||
"""Init the STIEBEL ELTRON data object."""
|
||||
from pystiebeleltron import pystiebeleltron
|
||||
self.api = pystiebeleltron.StiebelEltronAPI(modbus_client, 1)
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||
def update(self):
|
||||
"""Update unit data."""
|
||||
if not self.api.update():
|
||||
_LOGGER.warning("Modbus read failed")
|
||||
else:
|
||||
_LOGGER.debug("Data updated successfully")
|
149
homeassistant/components/stiebel_eltron/climate.py
Normal file
149
homeassistant/components/stiebel_eltron/climate.py
Normal file
@ -0,0 +1,149 @@
|
||||
"""Support for stiebel_eltron climate platform."""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.climate import ClimateDevice
|
||||
from homeassistant.components.climate.const import (
|
||||
STATE_AUTO, STATE_ECO, STATE_MANUAL, SUPPORT_OPERATION_MODE,
|
||||
SUPPORT_TARGET_TEMPERATURE)
|
||||
from homeassistant.const import (
|
||||
ATTR_TEMPERATURE, STATE_OFF, STATE_ON, TEMP_CELSIUS)
|
||||
|
||||
from . import DOMAIN as STE_DOMAIN
|
||||
|
||||
DEPENDENCIES = ['stiebel_eltron']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
SUPPORT_FLAGS = SUPPORT_TARGET_TEMPERATURE | SUPPORT_OPERATION_MODE
|
||||
OPERATION_MODES = [STATE_AUTO, STATE_MANUAL, STATE_ECO, STATE_OFF]
|
||||
|
||||
# Mapping STIEBEL ELTRON states to homeassistant states.
|
||||
STE_TO_HA_STATE = {'AUTOMATIC': STATE_AUTO,
|
||||
'MANUAL MODE': STATE_MANUAL,
|
||||
'STANDBY': STATE_ECO,
|
||||
'DAY MODE': STATE_ON,
|
||||
'SETBACK MODE': STATE_ON,
|
||||
'DHW': STATE_OFF,
|
||||
'EMERGENCY OPERATION': STATE_ON}
|
||||
|
||||
# Mapping homeassistant states to STIEBEL ELTRON states.
|
||||
HA_TO_STE_STATE = {value: key for key, value in STE_TO_HA_STATE.items()}
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||
"""Set up the StiebelEltron platform."""
|
||||
name = hass.data[STE_DOMAIN]['name']
|
||||
ste_data = hass.data[STE_DOMAIN]['ste_data']
|
||||
|
||||
add_entities([StiebelEltron(name, ste_data)], True)
|
||||
|
||||
|
||||
class StiebelEltron(ClimateDevice):
|
||||
"""Representation of a STIEBEL ELTRON heat pump."""
|
||||
|
||||
def __init__(self, name, ste_data):
|
||||
"""Initialize the unit."""
|
||||
self._name = name
|
||||
self._target_temperature = None
|
||||
self._current_temperature = None
|
||||
self._current_humidity = None
|
||||
self._operation_modes = OPERATION_MODES
|
||||
self._current_operation = None
|
||||
self._filter_alarm = None
|
||||
self._force_update = False
|
||||
self._ste_data = ste_data
|
||||
|
||||
@property
|
||||
def supported_features(self):
|
||||
"""Return the list of supported features."""
|
||||
return SUPPORT_FLAGS
|
||||
|
||||
def update(self):
|
||||
"""Update unit attributes."""
|
||||
self._ste_data.update(no_throttle=self._force_update)
|
||||
self._force_update = False
|
||||
|
||||
self._target_temperature = self._ste_data.api.get_target_temp()
|
||||
self._current_temperature = self._ste_data.api.get_current_temp()
|
||||
self._current_humidity = self._ste_data.api.get_current_humidity()
|
||||
self._filter_alarm = self._ste_data.api.get_filter_alarm_status()
|
||||
self._current_operation = self._ste_data.api.get_operation()
|
||||
|
||||
_LOGGER.debug("Update %s, current temp: %s", self._name,
|
||||
self._current_temperature)
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return device specific state attributes."""
|
||||
return {
|
||||
'filter_alarm': self._filter_alarm
|
||||
}
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the climate device."""
|
||||
return self._name
|
||||
|
||||
# Handle SUPPORT_TARGET_TEMPERATURE
|
||||
@property
|
||||
def temperature_unit(self):
|
||||
"""Return the unit of measurement."""
|
||||
return TEMP_CELSIUS
|
||||
|
||||
@property
|
||||
def current_temperature(self):
|
||||
"""Return the current temperature."""
|
||||
return self._current_temperature
|
||||
|
||||
@property
|
||||
def target_temperature(self):
|
||||
"""Return the temperature we try to reach."""
|
||||
return self._target_temperature
|
||||
|
||||
@property
|
||||
def target_temperature_step(self):
|
||||
"""Return the supported step of target temperature."""
|
||||
return 0.1
|
||||
|
||||
@property
|
||||
def min_temp(self):
|
||||
"""Return the minimum temperature."""
|
||||
return 10.0
|
||||
|
||||
@property
|
||||
def max_temp(self):
|
||||
"""Return the maximum temperature."""
|
||||
return 30.0
|
||||
|
||||
def set_temperature(self, **kwargs):
|
||||
"""Set new target temperature."""
|
||||
target_temperature = kwargs.get(ATTR_TEMPERATURE)
|
||||
if target_temperature is not None:
|
||||
_LOGGER.debug("set_temperature: %s", target_temperature)
|
||||
self._ste_data.api.set_target_temp(target_temperature)
|
||||
self._force_update = True
|
||||
|
||||
@property
|
||||
def current_humidity(self):
|
||||
"""Return the current humidity."""
|
||||
return float("{0:.1f}".format(self._current_humidity))
|
||||
|
||||
# Handle SUPPORT_OPERATION_MODE
|
||||
@property
|
||||
def operation_list(self):
|
||||
"""List of the operation modes."""
|
||||
return self._operation_modes
|
||||
|
||||
@property
|
||||
def current_operation(self):
|
||||
"""Return current operation ie. heat, cool, idle."""
|
||||
return STE_TO_HA_STATE.get(self._current_operation)
|
||||
|
||||
def set_operation_mode(self, operation_mode):
|
||||
"""Set new operation mode."""
|
||||
new_mode = HA_TO_STE_STATE.get(operation_mode)
|
||||
_LOGGER.debug("set_operation_mode: %s -> %s", self._current_operation,
|
||||
new_mode)
|
||||
self._ste_data.api.set_operation(new_mode)
|
||||
self._force_update = True
|
14
homeassistant/components/stiebel_eltron/manifest.json
Normal file
14
homeassistant/components/stiebel_eltron/manifest.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"domain": "stiebel_eltron",
|
||||
"name": "STIEBEL ELTRON",
|
||||
"documentation": "https://www.home-assistant.io/components/stiebel_eltron",
|
||||
"requirements": [
|
||||
"pystiebeleltron==0.0.1.dev2"
|
||||
],
|
||||
"dependencies": [
|
||||
"modbus"
|
||||
],
|
||||
"codeowners": [
|
||||
"@fucm"
|
||||
]
|
||||
}
|
@ -1281,6 +1281,9 @@ pysonos==0.0.10
|
||||
# homeassistant.components.spc
|
||||
pyspcwebgw==0.4.0
|
||||
|
||||
# homeassistant.components.stiebel_eltron
|
||||
pystiebeleltron==0.0.1.dev2
|
||||
|
||||
# homeassistant.components.stride
|
||||
pystride==0.1.7
|
||||
|
||||
|
Reference in New Issue
Block a user