diff --git a/homeassistant/components/thermostat/homematic.py b/homeassistant/components/thermostat/homematic.py index c81e53af9d9..9f8ffe9f2df 100644 --- a/homeassistant/components/thermostat/homematic.py +++ b/homeassistant/components/thermostat/homematic.py @@ -7,12 +7,17 @@ https://home-assistant.io/components/thermostat.homematic/ import logging import socket from xmlrpc.client import ServerProxy +from xmlrpc.client import Error +from collections import namedtuple from homeassistant.components.thermostat import ThermostatDevice from homeassistant.const import TEMP_CELCIUS +from homeassistant.helpers.temperature import convert REQUIREMENTS = [] +_LOGGER = logging.getLogger(__name__) + CONF_ADDRESS = 'address' CONF_DEVICES = 'devices' CONF_ID = 'id' @@ -20,29 +25,59 @@ PROPERTY_SET_TEMPERATURE = 'SET_TEMPERATURE' PROPERTY_VALVE_STATE = 'VALVE_STATE' PROPERTY_ACTUAL_TEMPERATURE = 'ACTUAL_TEMPERATURE' PROPERTY_BATTERY_STATE = 'BATTERY_STATE' +PROPERTY_LOWBAT = 'LOWBAT' PROPERTY_CONTROL_MODE = 'CONTROL_MODE' +PROPERTY_BURST_MODE = 'BURST_RX' +TYPE_HM_THERMOSTAT = 'HOMEMATIC_THERMOSTAT' +TYPE_HM_WALLTHERMOSTAT = 'HOMEMATIC_WALLTHERMOSTAT' +TYPE_MAX_THERMOSTAT = 'MAX_THERMOSTAT' -_LOGGER = logging.getLogger(__name__) +HomematicConfig = namedtuple('HomematicConfig', + ['device_type', + 'platform_type', + 'channel', + 'maint_channel']) + +HM_TYPE_MAPPING = { + 'HM-CC-RT-DN': HomematicConfig('HM-CC-RT-DN', + TYPE_HM_THERMOSTAT, + 4, 4), + 'HM-CC-RT-DN-BoM': HomematicConfig('HM-CC-RT-DN-BoM', + TYPE_HM_THERMOSTAT, + 4, 4), + 'HM-TC-IT-WM-W-EU': HomematicConfig('HM-TC-IT-WM-W-EU', + TYPE_HM_WALLTHERMOSTAT, + 2, 2), + 'BC-RT-TRX-CyG': HomematicConfig('BC-RT-TRX-CyG', + TYPE_MAX_THERMOSTAT, + 1, 0), + 'BC-RT-TRX-CyG-2': HomematicConfig('BC-RT-TRX-CyG-2', + TYPE_MAX_THERMOSTAT, + 1, 0), + 'BC-RT-TRX-CyG-3': HomematicConfig('BC-RT-TRX-CyG-3', + TYPE_MAX_THERMOSTAT, + 1, 0) +} def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Homematic thermostat.""" devices = [] try: - homegear = ServerProxy(config[CONF_ADDRESS]) + address = config[CONF_ADDRESS] + homegear = ServerProxy(address) + for name, device_cfg in config[CONF_DEVICES].items(): # get device description to detect the type device_type = homegear.getDeviceDescription( device_cfg[CONF_ID] + ':-1')['TYPE'] - if device_type in ['HM-CC-RT-DN', 'HM-CC-RT-DN-BoM']: - devices.append(HomematicThermostat(homegear, - device_cfg[CONF_ID], - name, 4)) - elif device_type == 'HM-TC-IT-WM-W-EU': - devices.append(HomematicThermostat(homegear, - device_cfg[CONF_ID], - name, 2)) + if device_type in HM_TYPE_MAPPING.keys(): + devices.append(HomematicThermostat( + HM_TYPE_MAPPING[device_type], + address, + device_cfg[CONF_ID], + name)) else: raise ValueError( "Device Type '{}' currently not supported".format( @@ -60,14 +95,16 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class HomematicThermostat(ThermostatDevice): """Representation of a Homematic thermostat.""" - def __init__(self, device, _id, name, channel): + def __init__(self, hm_config, address, _id, name): """Initialize the thermostat.""" - self.device = device + self._hm_config = hm_config + self.address = address self._id = _id - self._channel = channel self._name = name - self._full_device_name = '{}:{}'.format(self._id, self._channel) - + self._full_device_name = '{}:{}'.format(self._id, + self._hm_config.channel) + self._maint_device_name = '{}:{}'.format(self._id, + self._hm_config.maint_channel) self._current_temperature = None self._target_temperature = None self._valve = None @@ -97,9 +134,10 @@ class HomematicThermostat(ThermostatDevice): def set_temperature(self, temperature): """Set new target temperature.""" - self.device.setValue(self._full_device_name, - PROPERTY_SET_TEMPERATURE, - temperature) + device = ServerProxy(self.address) + device.setValue(self._full_device_name, + PROPERTY_SET_TEMPERATURE, + temperature) @property def device_state_attributes(self): @@ -108,21 +146,49 @@ class HomematicThermostat(ThermostatDevice): "battery": self._battery, "mode": self._mode} + @property + def min_temp(self): + """Return the minimum temperature - 4.5 means off.""" + return convert(4.5, TEMP_CELCIUS, self.unit_of_measurement) + + @property + def max_temp(self): + """Return the maximum temperature - 30.5 means on.""" + return convert(30.5, TEMP_CELCIUS, self.unit_of_measurement) + def update(self): """Update the data from the thermostat.""" try: - self._current_temperature = self.device.getValue( + device = ServerProxy(self.address) + self._current_temperature = device.getValue( self._full_device_name, PROPERTY_ACTUAL_TEMPERATURE) - self._target_temperature = self.device.getValue( + self._target_temperature = device.getValue( self._full_device_name, PROPERTY_SET_TEMPERATURE) - self._valve = self.device.getValue(self._full_device_name, - PROPERTY_VALVE_STATE) - self._battery = self.device.getValue(self._full_device_name, - PROPERTY_BATTERY_STATE) - self._mode = self.device.getValue(self._full_device_name, - PROPERTY_CONTROL_MODE) - except socket.error: + self._valve = device.getValue( + self._full_device_name, + PROPERTY_VALVE_STATE) + self._mode = device.getValue( + self._full_device_name, + PROPERTY_CONTROL_MODE) + + if self._hm_config.platform_type in [TYPE_HM_THERMOSTAT, + TYPE_HM_WALLTHERMOSTAT]: + self._battery = device.getValue(self._maint_device_name, + PROPERTY_BATTERY_STATE) + elif self._hm_config.platform_type == TYPE_MAX_THERMOSTAT: + # emulate homematic battery voltage, + # max reports lowbat if voltage < 2.2V + # while homematic battery_state should + # be between 1.5V and 4.6V + lowbat = device.getValue(self._maint_device_name, + PROPERTY_LOWBAT) + if lowbat: + self._battery = 1.5 + else: + self._battery = 4.6 + + except Error: _LOGGER.exception("Did not receive any temperature data from the " "homematic API.")