mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 04:07:08 +00:00
Improve climate support for fibaro (#39038)
* Fibaro climate improvements 1, Implemented support for multinode climate devices, such as Danfoss HC10, differentiating zones based on endPointId 2, Improved recognition of temperature sensor subdevice for climate devices 3, Changed default opmode for devices without an opmode to "auto" instead of "fan_only", for better clarity and to avoid misunderstandings * pylint inspired code restructuring to reduce depth gotta love pylint
This commit is contained in:
parent
d0af3339fc
commit
3a36a789ad
@ -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
|
||||
|
||||
|
@ -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):
|
||||
|
Loading…
x
Reference in New Issue
Block a user