diff --git a/homeassistant/components/fibaro/__init__.py b/homeassistant/components/fibaro/__init__.py index 54dd5b6234f..4b51c82469e 100644 --- a/homeassistant/components/fibaro/__init__.py +++ b/homeassistant/components/fibaro/__init__.py @@ -200,9 +200,26 @@ class FibaroController: if device.parentId == device_id ] - def get_siblings(self, device_id): + def get_children2(self, device_id, endpoint_id): + """Get a list of child devices for the same endpoint.""" + return [ + device + for device in self._device_map.values() + if device.parentId == device_id + and ( + "endPointId" not in device.properties + or device.properties.endPointId == endpoint_id + ) + ] + + def get_siblings(self, device): """Get the siblings of a device.""" - return self.get_children(self._device_map[device_id].parentId) + if "endPointId" in device.properties: + return self.get_children2( + self._device_map[device.id].parentId, + self._device_map[device.id].properties.endPointId, + ) + return self.get_children(self._device_map[device.id].parentId) @staticmethod def _map_device_to_type(device): @@ -262,6 +279,7 @@ class FibaroController: self._device_map = {} self.fibaro_devices = defaultdict(list) last_climate_parent = None + last_endpoint = None for device in devices: try: if "name" not in device or "id" not in device: @@ -289,23 +307,10 @@ class FibaroController: else: device.mapped_type = None dtype = device.mapped_type - if dtype: - device.unique_id_str = f"{self.hub_serial}.{device.id}" - self._device_map[device.id] = device - if dtype != "climate": - self.fibaro_devices[dtype].append(device) - else: - # if a sibling of this has been added, skip this one - # otherwise add the first visible device in the group - # which is a hack, but solves a problem with FGT having - # hidden compatibility devices before the real device - if ( - last_climate_parent != device.parentId - and "visible" in device - and device.visible - ): - self.fibaro_devices[dtype].append(device) - last_climate_parent = device.parentId + if dtype is None: + continue + device.unique_id_str = f"{self.hub_serial}.{device.id}" + self._device_map[device.id] = device _LOGGER.debug( "%s (%s, %s) -> %s %s", device.ha_id, @@ -314,6 +319,36 @@ class FibaroController: dtype, str(device), ) + if dtype != "climate": + self.fibaro_devices[dtype].append(device) + continue + # We group climate devices into groups with the same + # endPointID belonging to the same parent device. + if "endPointId" in device.properties: + _LOGGER.debug( + "climate device: %s, endPointId: %s", + device.ha_id, + device.properties.endPointId, + ) + else: + _LOGGER.debug("climate device: %s, no endPointId", device.ha_id) + # If a sibling of this device has been added, skip this one + # otherwise add the first visible device in the group + # which is a hack, but solves a problem with FGT having + # hidden compatibility devices before the real device + if last_climate_parent != device.parentId or ( + "endPointId" in device.properties + and last_endpoint != device.properties.endPointId + ): + _LOGGER.debug("Handle separately") + self.fibaro_devices[dtype].append(device) + last_climate_parent = device.parentId + if "endPointId" in device.properties: + last_endpoint = device.properties.endPointId + else: + last_endpoint = 0 + else: + _LOGGER.debug("not handling separately") except (KeyError, ValueError): pass diff --git a/homeassistant/components/fibaro/climate.py b/homeassistant/components/fibaro/climate.py index 5776a293756..eee1c08bd36 100644 --- a/homeassistant/components/fibaro/climate.py +++ b/homeassistant/components/fibaro/climate.py @@ -120,12 +120,24 @@ class FibaroThermostat(FibaroDevice, ClimateEntity): self._preset_support = [] self._fan_support = [] - siblings = fibaro_device.fibaro_controller.get_siblings(fibaro_device.id) + siblings = fibaro_device.fibaro_controller.get_siblings(fibaro_device) + _LOGGER.debug("%s siblings: %s", fibaro_device.ha_id, siblings) tempunit = "C" for device in siblings: + # Detecting temperature device, one strong and one weak way of + # doing so, so we prefer the hard evidence, if there is such. if device.type == "com.fibaro.temperatureSensor": self._temp_sensor_device = FibaroDevice(device) tempunit = device.properties.unit + elif ( + self._temp_sensor_device is None + and "unit" in device.properties + and "value" in device.properties + and (device.properties.unit == "C" or device.properties.unit == "F") + ): + self._temp_sensor_device = FibaroDevice(device) + tempunit = device.properties.unit + if ( "setTargetLevel" in device.actions or "setThermostatSetpoint" in device.actions @@ -133,9 +145,11 @@ class FibaroThermostat(FibaroDevice, ClimateEntity): self._target_temp_device = FibaroDevice(device) self._support_flags |= SUPPORT_TARGET_TEMPERATURE tempunit = device.properties.unit + if "setMode" in device.actions or "setOperatingMode" in device.actions: self._op_mode_device = FibaroDevice(device) self._support_flags |= SUPPORT_PRESET_MODE + if "setFanMode" in device.actions: self._fan_mode_device = FibaroDevice(device) self._support_flags |= SUPPORT_FAN_MODE @@ -188,9 +202,7 @@ class FibaroThermostat(FibaroDevice, ClimateEntity): await super().async_added_to_hass() # Register update callback for child devices - siblings = self.fibaro_device.fibaro_controller.get_siblings( - self.fibaro_device.id - ) + siblings = self.fibaro_device.fibaro_controller.get_siblings(self.fibaro_device) for device in siblings: if device != self.fibaro_device: self.controller.register(device.id, self._update_callback) @@ -225,7 +237,7 @@ class FibaroThermostat(FibaroDevice, ClimateEntity): def fibaro_op_mode(self): """Return the operating mode of the device.""" if not self._op_mode_device: - return 6 # Fan only + return 3 # Default to AUTO if "operatingMode" in self._op_mode_device.fibaro_device.properties: return int(self._op_mode_device.fibaro_device.properties.operatingMode) @@ -241,7 +253,7 @@ class FibaroThermostat(FibaroDevice, ClimateEntity): def hvac_modes(self): """Return the list of available operation modes.""" if not self._op_mode_device: - return [HVAC_MODE_FAN_ONLY] + return [HVAC_MODE_AUTO] # Default to this return self._hvac_support def set_hvac_mode(self, hvac_mode):