Skip to content

Commit

Permalink
Fix group cpr412 (#1653)
Browse files Browse the repository at this point in the history
* makes PR412 and CPR412 handling correctly the report attribute, and consequently get group working
* implement LevelControl Stop
  • Loading branch information
pipiche38 authored Oct 15, 2023
1 parent d4eae16 commit 3d23a92
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 43 deletions.
62 changes: 41 additions & 21 deletions Classes/GroupMgtv2/GrpDomoticz.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from Classes.GroupMgtv2.GrpCommands import (set_hue_saturation,
set_kelvin_color, set_rgb_color)
from Classes.GroupMgtv2.GrpDatabase import update_due_to_nwk_id_change
from Modules.tools import Hex_Format
from Modules.tools import Hex_Format, 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_with_onoff,
Expand All @@ -19,6 +19,7 @@
zcl_group_onoff_on,
zcl_group_window_covering_off,
zcl_group_window_covering_on,
zcl_group_move_to_level_stop,
zcl_group_window_covering_stop)

WIDGET_STYLE = {
Expand Down Expand Up @@ -185,6 +186,7 @@ def best_group_widget(self, GroupId):
# }

GroupWidgetType = None
GroupWidgetStyle = None

self.logging("Debug", "best_group_widget Device - %s" % str(self.ListOfGroups[GroupId]["Devices"]))
for NwkId, devEp, iterIEEE in self.ListOfGroups[GroupId]["Devices"]:
Expand All @@ -194,7 +196,7 @@ def best_group_widget(self, GroupId):
if NwkId == "0000":
continue

self.logging("debug", "bestGroupWidget - Group: %s processing %s" % (GroupId, NwkId))
self.logging("Debug", "bestGroupWidget - Group: %s processing %s" % (GroupId, NwkId))
if NwkId not in self.ListOfDevices:
# We have some inconsistency !
continue
Expand All @@ -207,9 +209,13 @@ def best_group_widget(self, GroupId):
WidgetType = self.ListOfDevices[NwkId]["Ep"][devEp]["ClusterType"][DomoDeviceUnit]
self.logging("Debug", "------------ GroupWidget: %s WidgetType: %s" % (GroupWidgetType, WidgetType))

if WidgetType == "LvlControl" and "Blind" in self.ListOfDevices[NwkId]["Type"]:
GroupWidgetStyle = "BlindPercentInverted"

if WidgetType in ("VenetianInverted", "VanneInverted", "CurtainInverted"):
# Those widgets are commanded via cluster Level Control
GroupWidgetType = "LvlControl"
GroupWidgetStyle = "VenetianInverted"
continue

if GroupWidgetType is None and WidgetType in WIDGET_STYLE:
Expand Down Expand Up @@ -245,7 +251,6 @@ def best_group_widget(self, GroupId):
GroupWidgetType = WidgetType
continue


if WidgetType in ("Venetian", "WindowCovering", "BlindPercentInverted"):
GroupWidgetType = WidgetType

Expand Down Expand Up @@ -281,13 +286,13 @@ def best_group_widget(self, GroupId):
else:
self.ListOfGroups[GroupId]["Cluster"] = ""

self.logging(
"Debug",
"best_group_widget for GroupId: %s Found WidgetType: %s Widget: %s"
% (GroupId, GroupWidgetType, WIDGET_STYLE.get(GroupWidgetType, WIDGET_STYLE["ColorControlFull"])),
)
self.logging( "Debug", "best_group_widget for GroupId: %s Found WidgetType: %s Widget: %s" % (
GroupId, GroupWidgetType, WIDGET_STYLE.get(GroupWidgetType, WIDGET_STYLE["ColorControlFull"])), )

return WIDGET_STYLE.get(GroupWidgetType, WIDGET_STYLE["ColorControlFull"])
if GroupWidgetStyle is None:
GroupWidgetStyle = GroupWidgetType

return WIDGET_STYLE.get(GroupWidgetStyle, WIDGET_STYLE["ColorControlFull"])


def update_domoticz_group_device(self, GroupId):
Expand Down Expand Up @@ -317,7 +322,7 @@ def update_domoticz_group_device(self, GroupId):
if "Cluster" in self.ListOfGroups[GroupId]:
Cluster = self.ListOfGroups[GroupId]["Cluster"]

countOn = countOff = 0
countStop = countOn = countOff = 0
nValue = 0 if self.pluginconf.pluginConf["OnIfOneOn"] else 1
sValue = level = None
for NwkId, Ep, IEEE in self.ListOfGroups[GroupId]["Devices"]:
Expand Down Expand Up @@ -347,11 +352,13 @@ def update_domoticz_group_device(self, GroupId):
and Cluster in ("0006", "0008", "0300")
and "0006" in self.ListOfDevices[NwkId]["Ep"][Ep]
and "0000" in self.ListOfDevices[NwkId]["Ep"][Ep]["0006"]
and str(self.ListOfDevices[NwkId]["Ep"][Ep]["0006"]["0000"]).isdigit()
and is_hex( str(self.ListOfDevices[NwkId]["Ep"][Ep]["0006"]["0000"]) )
):
self.logging( "Debug", "update_domoticz_group_device - Cluster ON/OFF Group: %s NwkId: %s Ep: %s Value: %s" %(
GroupId, NwkId, Ep, self.ListOfDevices[NwkId]["Ep"][Ep]["0006"]["0000"]))
if int(self.ListOfDevices[NwkId]["Ep"][Ep]["0006"]["0000"]) != 0:
if str(self.ListOfDevices[NwkId]["Ep"][Ep]["0006"]["0000"]) == "f0":
countStop += 1
elif int(self.ListOfDevices[NwkId]["Ep"][Ep]["0006"]["0000"]) != 0:
countOn += 1
else:
countOff += 1
Expand Down Expand Up @@ -381,23 +388,31 @@ def update_domoticz_group_device(self, GroupId):
level = lvl_value if level is None else (level + lvl_value) // 2
nValue, sValue = ValuesForVenetian(level)

self.logging( "Debug", "update_domoticz_group_device - Processing: Group: %s %s/%s On: %s, Off: %s level: %s" % (
GroupId, NwkId, Ep, countOn, countOff, level), )
self.logging( "Debug", "update_domoticz_group_device - Processing: Group: %s %s/%s On: %s, Off: %s Stop: %s, level: %s" % (
GroupId, NwkId, Ep, countOn, countOff, countStop, level), )

if self.pluginconf.pluginConf["OnIfOneOn"]:
if countStop > 0:
nValue = 17
elif self.pluginconf.pluginConf["OnIfOneOn"]:
if countOn > 0:
nValue = 1
elif countOff > 0:
nValue = 0
self.logging( "Debug", "update_domoticz_group_device - Processing: Group: %s == > nValue: %s, level: %s" % (
GroupId, nValue, level), )


# At that stage
# nValue == 0 if Off
# nValue == 1 if Open/On
# nValue == 17 if Stop
# level is None, so we use nValue/sValue
# level is not None; so we have a LvlControl
if sValue is None and level:
if nValue == 17:
# Stop
sValue = "0"

elif sValue is None and level:
if self.Devices[unit].SwitchType not in (13, 14, 15, 16):
# Not a Shutter/Blind
analogValue = level
Expand Down Expand Up @@ -439,11 +454,8 @@ def update_domoticz_group_device(self, GroupId):
else:
sValue = "On"

self.logging(
"Debug",
"update_domoticz_group_device - Processing: Group: %s == > from %s:%s to %s:%s"
% (GroupId, self.Devices[unit].nValue, self.Devices[unit].sValue, nValue, sValue),
)
self.logging( "Debug", "update_domoticz_group_device - Processing: Group: %s == > from %s:%s to %s:%s" % (
GroupId, self.Devices[unit].nValue, self.Devices[unit].sValue, nValue, sValue), )
if nValue != self.Devices[unit].nValue or sValue != self.Devices[unit].sValue:
self.logging("Log", "UpdateGroup - (%15s) %s:%s" % (self.Devices[unit].Name, nValue, sValue))
self.Devices[unit].Update(nValue, sValue)
Expand Down Expand Up @@ -680,6 +692,14 @@ def processCommand(self, unit, GrpId, Command, Level, Color_):
sValue = "On"
self.Devices[unit].Update(nValue=int(nValue), sValue=str(sValue))

elif Command in ( "Stop",) and self.ListOfGroups[GrpId]["Cluster"] == "0102":
# Windowscovering Stop
zcl_group_window_covering_stop(self, GrpId, "01", EPout)

elif Command in ( "Stop",) and self.ListOfGroups[GrpId]["Cluster"] == "0008":
# SetLevel Off
zcl_group_move_to_level_stop(self, GrpId, EPout)

elif Command == "Set Level":
# Level: % value of move
# Converted to value , raw value from 0 to 255
Expand Down
41 changes: 21 additions & 20 deletions Modules/domoMaj.py
Original file line number Diff line number Diff line change
Expand Up @@ -1184,14 +1184,27 @@ def MajDomoDevice(self, Devices, NWKID, Ep, clusterID, value, Attribute_="", Col
# We do update only if this is a On/off
UpdateDevice_v2(self, Devices, DeviceUnit, 1, "On", BatteryLevel, SignalLevel)

elif WidgetType == "VenetianInverted" and model_name in ( "PR412", "CPR412", "CPR412-E") and clusterID == "0006":
self.log.logging( "Widget", "Debug", "--++-> %s/%s ClusterType: %s Updating %s Value: %s" % (NWKID, Ep, ClusterType, WidgetType, value), NWKID, )
# nValue will depends if we are on % or not
if value == '01':
nValue = 0
sValue = "0"

elif value == '00':
nValue = 1
sValue = "100"

elif value == 'f0':
nValue = 17
sValue = "0"

self.log.logging("Widget", "Debug", "------> %s %s/%s Value: %s:%s" % (WidgetType, NWKID, Ep, nValue, sValue), NWKID)
UpdateDevice_v2(self, Devices, DeviceUnit, nValue, sValue, BatteryLevel, SignalLevel)

elif WidgetType in ("VenetianInverted", "Venetian", "WindowCovering", "VanneInverted", "Vanne", "Curtain", "CurtainInverted"):
_value = int(value, 16)
self.log.logging(
"Widget",
"Debug",
"------> %s/%s ClusterType: %s Updating %s Value: %s" % (NWKID, Ep, ClusterType, WidgetType, _value),
NWKID,
)
self.log.logging( "Widget", "Debug", "------> %s/%s ClusterType: %s Updating %s Value: %s" % (NWKID, Ep, ClusterType, WidgetType, _value), NWKID, )
if WidgetType in ("VenetianInverted", "VanneInverted"):
_value = 100 - _value
self.log.logging("Widget", "Debug", "------> Patching %s/%s Value: %s" % (NWKID, Ep, _value), NWKID)
Expand Down Expand Up @@ -1258,13 +1271,7 @@ def MajDomoDevice(self, Devices, NWKID, Ep, clusterID, value, Attribute_="", Col
UpdateDevice_v2(self, Devices, DeviceUnit, nValue, str(_value), BatteryLevel, SignalLevel)

if "LvlControl" in ClusterType: # LvlControl ( 0x0008)
if WidgetType == "LvlControl" or (
WidgetType
in (
"BSO-Volet",
"Blind",
)
):
if WidgetType == "LvlControl" or ( WidgetType in ( "BSO-Volet", "Blind", ) ):
# We need to handle the case, where we get an update from a Read Attribute or a Reporting message
# We might get a Level, but the device is still Off and we shouldn't make it On .
nValue = None
Expand Down Expand Up @@ -1320,13 +1327,7 @@ def MajDomoDevice(self, Devices, NWKID, Ep, clusterID, value, Attribute_="", Col
nValue, normalized_value, Devices[DeviceUnit].SwitchType), NWKID, )
UpdateDevice_v2( self, Devices, DeviceUnit, Devices[DeviceUnit].nValue, str(normalized_value), BatteryLevel, SignalLevel, )

elif WidgetType in (
"ColorControlRGB",
"ColorControlWW",
"ColorControlRGBWW",
"ColorControlFull",
"ColorControl",
):
elif WidgetType in ( "ColorControlRGB", "ColorControlWW", "ColorControlRGBWW", "ColorControlFull", "ColorControl", ):
if Devices[DeviceUnit].nValue != 0 or Devices[DeviceUnit].sValue != "Off":
nValue, sValue = getDimmerLevelOfColor(self, value)
UpdateDevice_v2(self, Devices, DeviceUnit, nValue, str(sValue), BatteryLevel, SignalLevel, Color_)
Expand Down
3 changes: 2 additions & 1 deletion Modules/readZclClusters.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,8 @@ def majdomodevice_possiblevalues( self, MsgSrcEp, MsgClusterId, MsgAttrID, model
return True
eval_result = eval( _majdomodeviceValidValues )

self.log.logging("ZclClusters", "Debug", " . majdomodevice_possiblevalues: %s -> %s" %( eval_result, _majdomodeviceValidValues))
self.log.logging("ZclClusters", "Debug", " . majdomodevice_possiblevalues: >%s<(%s) %s -> %s" %(
value, type(value), eval_result, _majdomodeviceValidValues))
return eval_result


Expand Down
11 changes: 10 additions & 1 deletion Zigbee/zclCommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,11 @@ def zcl_move_to_level_with_onoff(self, nwkid, EPout, OnOff, level, transition="0
return send_zigatecmd_zcl_noack(self, nwkid, "0081", data)
return send_zigatecmd_zcl_ack(self, nwkid, "0081", data)

def zcl_move_to_level_stop(self, nwkid, EPout, ackIsDisabled=DEFAULT_ACK_MODE):
self.log.logging("zclCommand", "Debug", "zcl_move_to_level_stop %s %s" % (nwkid, EPout, ))
zcl_command_formated_logging( self, "zcl_move_to_level_stop", nwkid, EPout, "0008", "Stop", ackIsDisabled)
if "ControllerInRawMode" in self.pluginconf.pluginConf and self.pluginconf.pluginConf["ControllerInRawMode"]:
return zcl_raw_level_move_to_level(self, nwkid, ZIGATE_EP, EPout, "Stop")

def zcl_group_move_to_level_with_onoff(self, nwkid, EPout, OnOff, level, transition="0000", ackIsDisabled=DEFAULT_ACK_MODE):
self.log.logging("zclCommand", "Debug", "zcl_move_to_level_with_onoff %s %s %s %s %s" % (nwkid, EPout, OnOff, level, transition))
Expand All @@ -457,7 +462,11 @@ def zcl_group_move_to_level_with_onoff(self, nwkid, EPout, OnOff, level, transit
data = "%02d" % ADDRESS_MODE["group"] + nwkid + ZIGATE_EP + EPout + OnOff + level + transition
return send_zigatecmd_raw(self, "0081", data)


def zcl_group_move_to_level_stop(self, nwkid, EPout, ackIsDisabled=DEFAULT_ACK_MODE):
self.log.logging("zclCommand", "Debug", "zcl_move_to_level_stop %s %s" % (nwkid, EPout, ))
zcl_command_formated_logging( self, "zcl_move_to_level_stop", nwkid, EPout, "0008", "Stop", ackIsDisabled)
if "ControllerInRawMode" in self.pluginconf.pluginConf and self.pluginconf.pluginConf["ControllerInRawMode"]:
return zcl_raw_level_move_to_level(self, nwkid, ZIGATE_EP, EPout, "Stop", groupaddrmode=True)

# Cluster 0102 ( Window Covering )
##################################
Expand Down

0 comments on commit 3d23a92

Please sign in to comment.