diff --git a/Classes/GroupMgtv2/GrpDomoticz.py b/Classes/GroupMgtv2/GrpDomoticz.py index 0e0d7acdc..04db0fa8f 100644 --- a/Classes/GroupMgtv2/GrpDomoticz.py +++ b/Classes/GroupMgtv2/GrpDomoticz.py @@ -18,9 +18,9 @@ from Modules.domoticzAbstractLayer import ( FreeUnit, domo_create_api, domo_delete_widget, domo_read_Name, domo_read_nValue_sValue, domo_read_SwitchType_SubType_Type, - domo_update_api, domo_update_name, domo_update_SwitchType_SubType_Type, - find_first_unit_widget_from_deviceID) -from Modules.tools import Hex_Format, is_hex + domo_read_Typename, domo_update_api, domo_update_name, + domo_update_SwitchType_SubType_Type, find_first_unit_widget_from_deviceID) +from Modules.tools import Hex_Format, is_domoticz_latest_typename, is_hex from Modules.zigateConsts import ADDRESS_MODE, LEGRAND_REMOTES, ZIGATE_EP from Zigbee.zclCommands import (zcl_group_level_move_to_level, zcl_group_move_to_level_stop, @@ -46,6 +46,21 @@ "ColorControlFull": (241, 7, 7), } +WIDGET_STYLE_TO_DOMOTICZ_TYPEMAP = { + "Plug": "On/Off ", + "Switch": "On/Off ", + "LvlControl": "Dimmer", + "BlindPercentInverted": "BlindsPercentage", + "WindowCovering": "VenetianBlindsEU", + "Venetian": "VenetianBlindsEU", + "VenetianInverted": "VenetianBlindsEU", + "ColorControlWW": "CW_WW", + "ColorControlRGB": "RGB", + "ColorControlRGBWW": "RGB_CW_WW", + "ColorControlFull": "RGB_CW_WW_Z", + +} + def create_domoticz_group_device(self, GroupName, GroupId): """ Create Device for just created group in Domoticz. """ @@ -122,13 +137,27 @@ def update_domoticz_group_device_widget(self, GroupId): return Type_, Subtype_, SwitchType_ = best_group_widget(self, GroupId) + + if is_domoticz_latest_typename(self): + current_typename = domo_read_Typename(self, self.Devices, GroupId, unit) + new_typename = get_typename(Type_, Subtype_, SwitchType_) + + self.logging("Debug", f" Looking to update Unit: {unit} from {current_typename} to {new_typename}") + if current_typename != new_typename: + domo_update_SwitchType_SubType_Type(self, self.Devices, GroupId, unit, Type_, Subtype_, SwitchType_, Typename_=new_typename) + + return + + # Old fashion we rely only on Type_, Subtype_, SwitchType_ current_switchType, current_Subtype, current_Type = domo_read_SwitchType_SubType_Type(self, self.Devices, GroupId, unit) - self.logging( "Debug", " Looking to update Unit: %s from %s %s %s to %s %s %s"% ( - unit, current_Type, current_Subtype, current_switchType, Type_, Subtype_, SwitchType_, ),) + self.logging("Debug", f" Looking to update Unit: {unit} from {current_Type} {current_Subtype} {current_switchType} to {Type_} {Subtype_} {SwitchType_}") domo_update_SwitchType_SubType_Type(self, self.Devices, GroupId, unit, Type_, Subtype_, SwitchType_) +def get_typename(Type_, Subtype_, SwitchType_): + return WIDGET_STYLE_TO_DOMOTICZ_TYPEMAP.get(WIDGET_STYLE.get((Type_, Subtype_, SwitchType_))) + def best_group_widget(self, GroupId): # WIDGETS = { diff --git a/Modules/domoticzAbstractLayer.py b/Modules/domoticzAbstractLayer.py index 6afe33515..a88d38a19 100644 --- a/Modules/domoticzAbstractLayer.py +++ b/Modules/domoticzAbstractLayer.py @@ -480,17 +480,15 @@ def domo_update_name(self, Devices, DeviceID_, Unit_, Name_): Devices[Unit_].Update(**update_params) -def domo_update_SwitchType_SubType_Type(self, Devices, DeviceID_, Unit_, Type_=0, Subtype_=0, Switchtype_=0): +def domo_update_SwitchType_SubType_Type(self, Devices, DeviceID_, Unit_, Type_=0, Subtype_=0, Switchtype_=0, Typename_=None): self.log.logging("AbstractDz", "Debug", "domo_update_SwitchType_SubType_Type DeviceID: %s,Unit: %s,Type: %s,Subtype: %s,Switchtype: %s" %( DeviceID_, Unit_, Type_, Subtype_, Switchtype_)) if DOMOTICZ_EXTENDED_API: - # Due to bug https://github.com/domoticz/domoticz/issues/6027 (on extended Framework ) - # Devices[DeviceID_].Units[Unit_].Type = Type_ - # Devices[DeviceID_].Units[Unit_].Subtype = Subtype_ - # Devices[DeviceID_].Units[Unit_].Switchtype = Switchtype_ - # Devices[DeviceID_].Units[Unit_].Update(Log=True) + # With Domoticz Extended the change of Widget type, can be done only via Typename + if Typename_: + Devices[DeviceID_].Units[Unit_].Update(TypeName=Typename_) return update_params = { @@ -611,6 +609,15 @@ def domo_read_SwitchType_SubType_Type(self, Devices, DeviceID, Unit): return _unit.SwitchType, _unit.SubType, _unit.Type +def domo_read_Typename(self, Devices, DeviceID, Unit): + self.log.logging("AbstractDz", "Debug", f"domo_read_Typename: DeviceID: {DeviceID} Unit {Unit}") + if DOMOTICZ_EXTENDED_API: + _unit = Devices[DeviceID].Units[Unit] + else: + _unit = Devices[Unit] + + return _unit.TypeName + def _is_meter_widget(self, Devices, DeviceID_, Unit_): if DOMOTICZ_EXTENDED_API: diff --git a/Modules/tools.py b/Modules/tools.py index 51a54fcdc..6075b4d24 100644 --- a/Modules/tools.py +++ b/Modules/tools.py @@ -1624,7 +1624,19 @@ def is_domoticz_2023(self): def is_domoticz_above_2023(self): return self.DomoticzMajor > 2023 - + + +def is_domoticz_bellow_2024(self): + return self.DomoticzMajor < 2024 + + +def is_domoticz_2024(self): + return self.DomoticzMajor == 2024 + + +def is_domoticz_above_2024(self): + return self.DomoticzMajor > 2024 + def is_domoticz_new_API(self): 'is_domoticz_new_API() False True 1 15356' @@ -1640,10 +1652,25 @@ def is_domoticz_new_API(self): # Domoticz 2024 ! return True +def is_domoticz_latest_typename(self): + """Checks if the Domoticz binary includes the latest typename.""" + + # If Domoticz version is below 2024, it's not the latest typename. + if is_domoticz_bellow_2024(self): + return False + + # If DomoticzMinor is greater than 4 or DomoticzBuild is 15956 or higher, it's the latest typename. + if self.DomoticzMinor > 4 or self.DomoticzBuild >= 15956: + return True + + # Otherwise, it's not the latest typename. + return False + def is_domoticz_new_blind(self): return is_domoticz_above_2022_2(self) + def is_domoticz_update_SuppressTriggers( self ): if is_domoticz_above_2022: @@ -1659,28 +1686,41 @@ def is_domoticz_update_SuppressTriggers( self ): def is_domoticz_touch(self): - if self.VersionNewFashion: - return True - if self.DomoticzMajor >= 2022: + """Checks if the Domoticz version supports touch.""" + + # If VersionNewFashion flag is set or DomoticzMajor is 2022 or higher, it supports touch. + if self.VersionNewFashion or self.DomoticzMajor >= 2022: return True + + # If DomoticzMajor is 4 and DomoticzMinor is 10547 or higher, it supports touch. return self.DomoticzMajor == 4 and self.DomoticzMinor >= 10547 +def get_device_config_param(self, NwkId, config_parameter): + """Retrieve config_parameter from the Param section in Config or Device""" -def get_device_config_param( self, NwkId, config_parameter): - """ Retreive config_parameter from the Param section in Config or Device""" - - self.log.logging("Input", "Debug", "get_device_config_param: %s Config: %s" %( NwkId,config_parameter )) - - if NwkId not in self.ListOfDevices: - return None - if "Param" not in self.ListOfDevices[NwkId]: + # Log debug information + self.log.logging("Input", "Debug", f"get_device_config_param: {NwkId} Config: {config_parameter}") + + # Get the device dictionary for the given NwkId, defaulting to None if not found + device = self.ListOfDevices.get(NwkId) + + # If device dictionary does not exist, return None + if not device: return None - if config_parameter not in self.ListOfDevices[NwkId]["Param"]: + + # Get the "Param" section dictionary from the device, defaulting to None if not found + param_section = device.get("Param") + + # If "Param" section dictionary does not exist, return None + if not param_section: return None - - - self.log.logging("Input", "Debug", "get_device_config_param: %s Config: %s return %s" %( - NwkId,config_parameter, self.ListOfDevices[NwkId]["Param"][ config_parameter ])) - return self.ListOfDevices[NwkId]["Param"][ config_parameter ] + # Get the value of config_parameter from the "Param" section, defaulting to None if not found + param_value = param_section.get(config_parameter) + + # Log debug information + self.log.logging("Input", "Debug", f"get_device_config_param: {NwkId} Config: {config_parameter} return {param_value}") + + # Return the value of config_parameter + return param_value