From e87da765c57319f845abc31edc0bcaea8aa8ef64 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Fri, 9 Sep 2016 19:33:12 +0200 Subject: [PATCH] cleanup Homematic code (#3291) * cleanup old code * cleanup round 2 * remove unwanted platforms --- .../components/binary_sensor/homematic.py | 44 +------- homeassistant/components/climate/homematic.py | 26 +---- homeassistant/components/cover/homematic.py | 25 +---- homeassistant/components/homematic.py | 102 ++++++++---------- homeassistant/components/light/homematic.py | 45 ++------ .../components/rollershutter/homematic.py | 102 ------------------ homeassistant/components/sensor/homematic.py | 45 +------- homeassistant/components/switch/homematic.py | 51 ++------- .../components/thermostat/homematic.py | 90 ---------------- 9 files changed, 78 insertions(+), 452 deletions(-) delete mode 100644 homeassistant/components/rollershutter/homematic.py delete mode 100644 homeassistant/components/thermostat/homematic.py diff --git a/homeassistant/components/binary_sensor/homematic.py b/homeassistant/components/binary_sensor/homematic.py index 117642c65f1..073f5d7eb6d 100644 --- a/homeassistant/components/binary_sensor/homematic.py +++ b/homeassistant/components/binary_sensor/homematic.py @@ -31,9 +31,11 @@ def setup_platform(hass, config, add_callback_devices, discovery_info=None): if discovery_info is None: return - return homematic.setup_hmdevice_discovery_helper(HMBinarySensor, - discovery_info, - add_callback_devices) + return homematic.setup_hmdevice_discovery_helper( + HMBinarySensor, + discovery_info, + add_callback_devices + ) class HMBinarySensor(homematic.HMDevice, BinarySensorDevice): @@ -57,44 +59,8 @@ class HMBinarySensor(homematic.HMDevice, BinarySensorDevice): return "motion" return SENSOR_TYPES_CLASS.get(self._hmdevice.__class__.__name__, None) - def _check_hm_to_ha_object(self): - """Check if possible to use the HM Object as this HA type.""" - from pyhomematic.devicetypes.sensors import HMBinarySensor\ - as pyHMBinarySensor - - # Check compatibility from HMDevice - if not super()._check_hm_to_ha_object(): - return False - - # check if the Homematic device correct for this HA device - if not isinstance(self._hmdevice, pyHMBinarySensor): - _LOGGER.critical("This %s can't be use as binary", self._name) - return False - - # if exists user value? - if self._state and self._state not in self._hmdevice.BINARYNODE: - _LOGGER.critical("This %s have no binary with %s", self._name, - self._state) - return False - - # only check and give a warning to the user - if self._state is None and len(self._hmdevice.BINARYNODE) > 1: - _LOGGER.critical("%s have multiple binary params. It use all " - "binary nodes as one. Possible param values: %s", - self._name, str(self._hmdevice.BINARYNODE)) - return False - - return True - def _init_data_struct(self): """Generate a data struct (self._data) from the Homematic metadata.""" - super()._init_data_struct() - - # object have 1 binary - if self._state is None and len(self._hmdevice.BINARYNODE) == 1: - for value in self._hmdevice.BINARYNODE: - self._state = value - # add state to data struct if self._state: _LOGGER.debug("%s init datastruct with main node '%s'", self._name, diff --git a/homeassistant/components/climate/homematic.py b/homeassistant/components/climate/homematic.py index a8fa47999d2..7e0b4fd6450 100644 --- a/homeassistant/components/climate/homematic.py +++ b/homeassistant/components/climate/homematic.py @@ -29,9 +29,11 @@ def setup_platform(hass, config, add_callback_devices, discovery_info=None): if discovery_info is None: return - return homematic.setup_hmdevice_discovery_helper(HMThermostat, - discovery_info, - add_callback_devices) + return homematic.setup_hmdevice_discovery_helper( + HMThermostat, + discovery_info, + add_callback_devices + ) # pylint: disable=abstract-method @@ -116,26 +118,8 @@ class HMThermostat(homematic.HMDevice, ClimateDevice): """Return the maximum temperature - 30.5 means on.""" return convert(30.5, TEMP_CELSIUS, self.unit_of_measurement) - def _check_hm_to_ha_object(self): - """Check if possible to use the Homematic object as this HA type.""" - from pyhomematic.devicetypes.thermostats import HMThermostat\ - as pyHMThermostat - - # Check compatibility from HMDevice - if not super()._check_hm_to_ha_object(): - return False - - # Check if the Homematic device correct for this HA device - if isinstance(self._hmdevice, pyHMThermostat): - return True - - _LOGGER.critical("This %s can't be use as thermostat", self._name) - return False - def _init_data_struct(self): """Generate a data dict (self._data) from the Homematic metadata.""" - super()._init_data_struct() - # Add state to data dict self._data.update({"CONTROL_MODE": STATE_UNKNOWN, "SET_TEMPERATURE": STATE_UNKNOWN, diff --git a/homeassistant/components/cover/homematic.py b/homeassistant/components/cover/homematic.py index fd68ac3d265..aea05a9160a 100644 --- a/homeassistant/components/cover/homematic.py +++ b/homeassistant/components/cover/homematic.py @@ -24,9 +24,11 @@ def setup_platform(hass, config, add_callback_devices, discovery_info=None): if discovery_info is None: return - return homematic.setup_hmdevice_discovery_helper(HMCover, - discovery_info, - add_callback_devices) + return homematic.setup_hmdevice_discovery_helper( + HMCover, + discovery_info, + add_callback_devices + ) # pylint: disable=abstract-method @@ -77,25 +79,8 @@ class HMCover(homematic.HMDevice, CoverDevice): if self.available: self._hmdevice.stop(self._channel) - def _check_hm_to_ha_object(self): - """Check if possible to use the HM Object as this HA type.""" - from pyhomematic.devicetypes.actors import Blind - - # Check compatibility from HMDevice - if not super()._check_hm_to_ha_object(): - return False - - # Check if the homematic device is correct for this HA device - if isinstance(self._hmdevice, Blind): - return True - - _LOGGER.critical("This %s can't be use as cover!", self._name) - return False - def _init_data_struct(self): """Generate a data dict (self._data) from hm metadata.""" - super()._init_data_struct() - # Add state to data dict self._state = "LEVEL" self._data.update({self._state: STATE_UNKNOWN}) diff --git a/homeassistant/components/homematic.py b/homeassistant/components/homematic.py index b0dcad55cfe..1baf52d37d7 100644 --- a/homeassistant/components/homematic.py +++ b/homeassistant/components/homematic.py @@ -331,9 +331,11 @@ def _get_devices(device_type, keys): _LOGGER.debug("Handling %s:%i", key, channel) if channel in params: for param in params[channel]: - name = _create_ha_name(name=device.NAME, - channel=channel, - param=param) + name = _create_ha_name( + name=device.NAME, + channel=channel, + param=param + ) device_dict = { CONF_PLATFORM: "homematic", ATTR_ADDRESS: key, @@ -354,8 +356,7 @@ def _get_devices(device_type, keys): _LOGGER.debug("Channel %i not in params", channel) else: _LOGGER.debug("Got no params for %s", key) - _LOGGER.debug("%s autodiscovery: %s", - device_type, str(device_arr)) + _LOGGER.debug("%s autodiscovery: %s", device_type, str(device_arr)) return device_arr @@ -365,9 +366,7 @@ def _create_params_list(hmdevice, metadata, device_type): merge = False # use merge? - if device_type == DISCOVER_SENSORS: - merge = True - elif device_type == DISCOVER_BINARY_SENSORS: + if device_type in (DISCOVER_SENSORS, DISCOVER_BINARY_SENSORS): merge = True # Search in sensor and binary metadata per elements @@ -429,11 +428,10 @@ def setup_hmdevice_discovery_helper(hmdevicetype, discovery_info, # create object and add to HA new_device = hmdevicetype(config) - add_callback_devices([new_device]) - - # link to HM new_device.link_homematic() + add_callback_devices([new_device]) + return True @@ -668,7 +666,7 @@ class HMDevice(Entity): attr[data[0]] = value # static attributes - attr["ID"] = self._hmdevice.ADDRESS + attr['ID'] = self._hmdevice.ADDRESS return attr @@ -678,6 +676,10 @@ class HMDevice(Entity): if self._connected: return True + # pyhomematic is loaded + if HOMEMATIC is None: + return False + # Does a HMDevice from pyhomematic exist? if self._address in HOMEMATIC.devices: # Init @@ -686,33 +688,25 @@ class HMDevice(Entity): # Check if Homematic class is okay for HA class _LOGGER.info("Start linking %s to %s", self._address, self._name) - if self._check_hm_to_ha_object(): - try: - # Init datapoints of this object - self._init_data_struct() - if HOMEMATIC_LINK_DELAY: - # We delay / pause loading of data to avoid overloading - # of CCU / Homegear when doing auto detection - time.sleep(HOMEMATIC_LINK_DELAY) - self._load_init_data_from_hm() - _LOGGER.debug("%s datastruct: %s", - self._name, str(self._data)) + try: + # Init datapoints of this object + self._init_data() + if HOMEMATIC_LINK_DELAY: + # We delay / pause loading of data to avoid overloading + # of CCU / Homegear when doing auto detection + time.sleep(HOMEMATIC_LINK_DELAY) + self._load_data_from_hm() + _LOGGER.debug("%s datastruct: %s", self._name, str(self._data)) - # Link events from pyhomatic - self._subscribe_homematic_events() - self._available = not self._hmdevice.UNREACH - # pylint: disable=broad-except - except Exception as err: - self._connected = False - _LOGGER.error("Exception while linking %s: %s", - self._address, str(err)) - else: - _LOGGER.critical("Delink %s object from HM", self._name) + # Link events from pyhomatic + self._subscribe_homematic_events() + self._available = not self._hmdevice.UNREACH + _LOGGER.debug("%s linking done", self._name) + # pylint: disable=broad-except + except Exception as err: self._connected = False - - # Update HA - _LOGGER.debug("%s linking done, send update_ha_state", self._name) - self.update_ha_state() + _LOGGER.error("Exception while linking %s: %s", + self._address, str(err)) else: _LOGGER.debug("%s not found in HOMEMATIC.devices", self._address) @@ -730,7 +724,7 @@ class HMDevice(Entity): have_change = True # If available it has changed - if attribute is "UNREACH": + if attribute is 'UNREACH': self._available = bool(value) have_change = True @@ -771,7 +765,7 @@ class HMDevice(Entity): bequeath=False, channel=channel) - def _load_init_data_from_hm(self): + def _load_data_from_hm(self): """Load first value from pyhomematic.""" if not self._connected: return False @@ -800,27 +794,15 @@ class HMDevice(Entity): return self._data[self._state] return None - def _check_hm_to_ha_object(self): - """Check if it is possible to use the Homematic object as this HA type. - - NEEDS overwrite by inherit! - """ - if not self._connected or self._hmdevice is None: - _LOGGER.error("HA object is not linked to homematic.") - return False - - # Check if button option is correctly set for this object - if self._channel > self._hmdevice.ELEMENT: - _LOGGER.critical("Button option is not correct for this object!") - return False - - return True - - def _init_data_struct(self): - """Generate a data dict (self._data) from the Homematic metadata. - - NEEDS overwrite by inherit! - """ + def _init_data(self): + """Generate a data dict (self._data) from the Homematic metadata.""" # Add all attributes to data dict for data_note in self._hmdevice.ATTRIBUTENODE: self._data.update({data_note: STATE_UNKNOWN}) + + # init device specified data + self._init_data_struct() + + def _init_data_struct(self): + """Generate a data dict from the Homematic device metadata.""" + raise NotImplementedError diff --git a/homeassistant/components/light/homematic.py b/homeassistant/components/light/homematic.py index 2e233e0e3ff..3f8eb1a22a5 100644 --- a/homeassistant/components/light/homematic.py +++ b/homeassistant/components/light/homematic.py @@ -22,9 +22,11 @@ def setup_platform(hass, config, add_callback_devices, discovery_info=None): if discovery_info is None: return - return homematic.setup_hmdevice_discovery_helper(HMLight, - discovery_info, - add_callback_devices) + return homematic.setup_hmdevice_discovery_helper( + HMLight, + discovery_info, + add_callback_devices + ) class HMLight(homematic.HMDevice, Light): @@ -70,41 +72,8 @@ class HMLight(homematic.HMDevice, Light): if self.available: self._hmdevice.off(self._channel) - def _check_hm_to_ha_object(self): - """Check if possible to use the Homematic object as this HA type.""" - from pyhomematic.devicetypes.actors import Dimmer, Switch - - # Check compatibility from HMDevice - if not super()._check_hm_to_ha_object(): - return False - - # Check if the Homematic device is correct for this HA device - if isinstance(self._hmdevice, Switch): - return True - if isinstance(self._hmdevice, Dimmer): - return True - - _LOGGER.critical("This %s can't be use as light", self._name) - return False - def _init_data_struct(self): """Generate a data dict (self._data) from the Homematic metadata.""" - from pyhomematic.devicetypes.actors import Dimmer, Switch - - super()._init_data_struct() - - # Use STATE - if isinstance(self._hmdevice, Switch): - self._state = "STATE" - # Use LEVEL - if isinstance(self._hmdevice, Dimmer): - self._state = "LEVEL" - - # Add state to data dict - if self._state: - _LOGGER.debug("%s init datadict with main node '%s'", self._name, - self._state) - self._data.update({self._state: STATE_UNKNOWN}) - else: - _LOGGER.critical("Can't correctly init light %s.", self._name) + self._state = "LEVEL" + self._data.update({self._state: STATE_UNKNOWN}) diff --git a/homeassistant/components/rollershutter/homematic.py b/homeassistant/components/rollershutter/homematic.py deleted file mode 100644 index 613d7884919..00000000000 --- a/homeassistant/components/rollershutter/homematic.py +++ /dev/null @@ -1,102 +0,0 @@ -""" -The homematic rollershutter platform. - -For more details about this platform, please refer to the documentation at -https://home-assistant.io/components/rollershutter.homematic/ - -Important: For this platform to work the homematic component has to be -properly configured. -""" - -import logging -from homeassistant.const import (STATE_OPEN, STATE_CLOSED, STATE_UNKNOWN) -from homeassistant.components.rollershutter import RollershutterDevice,\ - ATTR_CURRENT_POSITION -import homeassistant.components.homematic as homematic - - -_LOGGER = logging.getLogger(__name__) - -DEPENDENCIES = ['homematic'] - - -def setup_platform(hass, config, add_callback_devices, discovery_info=None): - """Setup the platform.""" - if discovery_info is None: - return - - return homematic.setup_hmdevice_discovery_helper(HMRollershutter, - discovery_info, - add_callback_devices) - - -# pylint: disable=abstract-method -class HMRollershutter(homematic.HMDevice, RollershutterDevice): - """Represents a Homematic Rollershutter in Home Assistant.""" - - @property - def current_position(self): - """ - Return current position of rollershutter. - - None is unknown, 0 is closed, 100 is fully open. - """ - if self.available: - return int((1 - self._hm_get_state()) * 100) - return None - - def move_position(self, **kwargs): - """Move the roller shutter to a specific position.""" - if self.available: - if ATTR_CURRENT_POSITION in kwargs: - position = float(kwargs[ATTR_CURRENT_POSITION]) - position = min(100, max(0, position)) - level = (100 - position) / 100.0 - self._hmdevice.set_level(level, self._channel) - - @property - def state(self): - """Return the state of the rollershutter.""" - current = self.current_position - if current is None: - return STATE_UNKNOWN - - return STATE_CLOSED if current == 100 else STATE_OPEN - - def move_up(self, **kwargs): - """Move the rollershutter up.""" - if self.available: - self._hmdevice.move_up(self._channel) - - def move_down(self, **kwargs): - """Move the rollershutter down.""" - if self.available: - self._hmdevice.move_down(self._channel) - - def stop(self, **kwargs): - """Stop the device if in motion.""" - if self.available: - self._hmdevice.stop(self._channel) - - def _check_hm_to_ha_object(self): - """Check if possible to use the HM Object as this HA type.""" - from pyhomematic.devicetypes.actors import Blind - - # Check compatibility from HMDevice - if not super()._check_hm_to_ha_object(): - return False - - # Check if the homematic device is correct for this HA device - if isinstance(self._hmdevice, Blind): - return True - - _LOGGER.critical("This %s can't be use as rollershutter!", self._name) - return False - - def _init_data_struct(self): - """Generate a data dict (self._data) from hm metadata.""" - super()._init_data_struct() - - # Add state to data dict - self._state = "LEVEL" - self._data.update({self._state: STATE_UNKNOWN}) diff --git a/homeassistant/components/sensor/homematic.py b/homeassistant/components/sensor/homematic.py index 35cc4aea42b..8857ee6d889 100644 --- a/homeassistant/components/sensor/homematic.py +++ b/homeassistant/components/sensor/homematic.py @@ -46,9 +46,11 @@ def setup_platform(hass, config, add_callback_devices, discovery_info=None): if discovery_info is None: return - return homematic.setup_hmdevice_discovery_helper(HMSensor, - discovery_info, - add_callback_devices) + return homematic.setup_hmdevice_discovery_helper( + HMSensor, + discovery_info, + add_callback_devices + ) class HMSensor(homematic.HMDevice): @@ -76,45 +78,8 @@ class HMSensor(homematic.HMDevice): return HM_UNIT_HA_CAST.get(self._state, None) - def _check_hm_to_ha_object(self): - """Check if possible to use the HM Object as this HA type.""" - from pyhomematic.devicetypes.sensors import HMSensor as pyHMSensor - - # Check compatibility from HMDevice - if not super()._check_hm_to_ha_object(): - return False - - # Check if the homematic device is correct for this HA device - if not isinstance(self._hmdevice, pyHMSensor): - _LOGGER.critical("This %s can't be use as sensor!", self._name) - return False - - # Does user defined value exist? - if self._state and self._state not in self._hmdevice.SENSORNODE: - # pylint: disable=logging-too-many-args - _LOGGER.critical("This %s have no sensor with %s! Values are", - self._name, self._state, - str(self._hmdevice.SENSORNODE.keys())) - return False - - # No param is set and more than 1 sensor nodes are present - if self._state is None and len(self._hmdevice.SENSORNODE) > 1: - _LOGGER.critical("This %s has multiple sensor nodes. " + - "Please us param. Values are: %s", self._name, - str(self._hmdevice.SENSORNODE.keys())) - return False - - _LOGGER.debug("%s is okay for linking", self._name) - return True - def _init_data_struct(self): """Generate a data dict (self._data) from hm metadata.""" - super()._init_data_struct() - - if self._state is None and len(self._hmdevice.SENSORNODE) == 1: - for value in self._hmdevice.SENSORNODE: - self._state = value - # Add state to data dict if self._state: _LOGGER.debug("%s init datadict with main node '%s'", self._name, diff --git a/homeassistant/components/switch/homematic.py b/homeassistant/components/switch/homematic.py index e9f103b95fa..e13027780c6 100644 --- a/homeassistant/components/switch/homematic.py +++ b/homeassistant/components/switch/homematic.py @@ -19,9 +19,11 @@ def setup_platform(hass, config, add_callback_devices, discovery_info=None): if discovery_info is None: return - return homematic.setup_hmdevice_discovery_helper(HMSwitch, - discovery_info, - add_callback_devices) + return homematic.setup_hmdevice_discovery_helper( + HMSwitch, + discovery_info, + add_callback_devices + ) class HMSwitch(homematic.HMDevice, SwitchDevice): @@ -56,47 +58,12 @@ class HMSwitch(homematic.HMDevice, SwitchDevice): if self.available: self._hmdevice.off(self._channel) - def _check_hm_to_ha_object(self): - """Check if possible to use the Homematic object as this HA type.""" - from pyhomematic.devicetypes.actors import Dimmer, Switch - - # Check compatibility from HMDevice - if not super()._check_hm_to_ha_object(): - return False - - # Check if the Homematic device is correct for this HA device - if isinstance(self._hmdevice, Switch): - return True - if isinstance(self._hmdevice, Dimmer): - return True - - _LOGGER.critical("This %s can't be use as switch", self._name) - return False - def _init_data_struct(self): """Generate a data dict (self._data) from the Homematic metadata.""" - from pyhomematic.devicetypes.actors import Dimmer,\ - Switch, SwitchPowermeter - - super()._init_data_struct() - # Use STATE - if isinstance(self._hmdevice, Switch): - self._state = "STATE" - - # Use LEVEL - if isinstance(self._hmdevice, Dimmer): - self._state = "LEVEL" + self._state = "STATE" + self._data.update({self._state: STATE_UNKNOWN}) # Need sensor values for SwitchPowermeter - if isinstance(self._hmdevice, SwitchPowermeter): - for node in self._hmdevice.SENSORNODE: - self._data.update({node: STATE_UNKNOWN}) - - # Add state to data dict - if self._state: - _LOGGER.debug("%s init data dict with main node '%s'", self._name, - self._state) - self._data.update({self._state: STATE_UNKNOWN}) - else: - _LOGGER.critical("Can't correctly init light %s.", self._name) + for node in self._hmdevice.SENSORNODE: + self._data.update({node: STATE_UNKNOWN}) diff --git a/homeassistant/components/thermostat/homematic.py b/homeassistant/components/thermostat/homematic.py deleted file mode 100644 index 73901ab61df..00000000000 --- a/homeassistant/components/thermostat/homematic.py +++ /dev/null @@ -1,90 +0,0 @@ -""" -Support for Homematic thermostats. - -For more details about this platform, please refer to the documentation at -https://home-assistant.io/components/thermostat.homematic/ -""" -import logging -import homeassistant.components.homematic as homematic -from homeassistant.components.thermostat import ThermostatDevice -from homeassistant.util.temperature import convert -from homeassistant.const import TEMP_CELSIUS, STATE_UNKNOWN - -DEPENDENCIES = ['homematic'] - -_LOGGER = logging.getLogger(__name__) - - -def setup_platform(hass, config, add_callback_devices, discovery_info=None): - """Setup the Homematic thermostat platform.""" - if discovery_info is None: - return - - return homematic.setup_hmdevice_discovery_helper(HMThermostat, - discovery_info, - add_callback_devices) - - -# pylint: disable=abstract-method -class HMThermostat(homematic.HMDevice, ThermostatDevice): - """Representation of a Homematic thermostat.""" - - @property - def unit_of_measurement(self): - """Return the unit of measurement that is used.""" - return TEMP_CELSIUS - - @property - def current_temperature(self): - """Return the current temperature.""" - if not self.available: - return None - return self._data["ACTUAL_TEMPERATURE"] - - @property - def target_temperature(self): - """Return the target temperature.""" - if not self.available: - return None - return self._data["SET_TEMPERATURE"] - - def set_temperature(self, temperature): - """Set new target temperature.""" - if not self.available: - return None - self._hmdevice.set_temperature(temperature) - - @property - def min_temp(self): - """Return the minimum temperature - 4.5 means off.""" - return convert(4.5, TEMP_CELSIUS, self.unit_of_measurement) - - @property - def max_temp(self): - """Return the maximum temperature - 30.5 means on.""" - return convert(30.5, TEMP_CELSIUS, self.unit_of_measurement) - - def _check_hm_to_ha_object(self): - """Check if possible to use the Homematic object as this HA type.""" - from pyhomematic.devicetypes.thermostats import HMThermostat\ - as pyHMThermostat - - # Check compatibility from HMDevice - if not super()._check_hm_to_ha_object(): - return False - - # Check if the Homematic device correct for this HA device - if isinstance(self._hmdevice, pyHMThermostat): - return True - - _LOGGER.critical("This %s can't be use as thermostat", self._name) - return False - - def _init_data_struct(self): - """Generate a data dict (self._data) from the Homematic metadata.""" - super()._init_data_struct() - - # Add state to data dict - self._data.update({"CONTROL_MODE": STATE_UNKNOWN, - "SET_TEMPERATURE": STATE_UNKNOWN, - "ACTUAL_TEMPERATURE": STATE_UNKNOWN})