Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RC Stable7 7.1.019 #1824

Draft
wants to merge 7 commits into
base: stable7
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 31 additions & 21 deletions Classes/WebServer/WebServer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1082,8 +1082,8 @@ def rest_zDevice(self, verb, data, parameters):
if attribut == "Battery" and attribut in self.ListOfDevices[item]:
if self.ListOfDevices[item]["Battery"] in ( {}, ) and "IASBattery" in self.ListOfDevices[item]:
device[attribut] = str(self.ListOfDevices[item][ "IASBattery" ])
elif isinstance( self.ListOfDevices[item]["Battery"], int):
device[attribut] = self.ListOfDevices[item]["Battery"]
elif isinstance( self.ListOfDevices[item]["Battery"], (int,float)):
device[attribut] = int(self.ListOfDevices[item]["Battery"])
device["BatteryInside"] = True

elif item == "CheckParam":
Expand Down Expand Up @@ -1530,43 +1530,53 @@ def rest_zigate_mode(self, verb, data, parameters):
_response["Data"] = json.dumps("ZiGate mode: %s requested" % mode)
return _response


def rest_battery_state(self, verb, data, parameters):
_response = prepResponseMessage(self, setupHeadersResponse())
_response["Headers"]["Content-Type"] = "application/json; charset=utf-8"
if verb == "GET":
_battEnv = {"Battery":{"<30%":{}, "<50%": {}, ">50%" : {}},"Update Time":{ "Unknown": {}, "< 1 week": {}, "> 1 week": {}}}
for x in self.ListOfDevices:
self.logging("Debug", f"rest_battery_state - {x}")
if x == "0000":
continue
continue

if self.ListOfDevices[x]["ZDeviceName"] == "":
_deviceName = x
else:
_deviceName = self.ListOfDevices[x]["ZDeviceName"]
battery = self.ListOfDevices[x].get("Battery")

if "Battery" in self.ListOfDevices[x] and isinstance(self.ListOfDevices[x]["Battery"], int):
if self.ListOfDevices[x]["Battery"] > 50:
_battEnv["Battery"][">50%"][_deviceName] = {"Battery": self.ListOfDevices[x]["Battery"]}
if battery is None:
continue
self.logging("Debug", f"rest_battery_state - {x} Battery found")

elif self.ListOfDevices[x]["Battery"] > 30:
_battEnv["Battery"]["<50%"][_deviceName] = {"Battery": self.ListOfDevices[x]["Battery"]}
_deviceName = self.ListOfDevices[x].get("ZDeviceName", x )

else:
_battEnv["Battery"]["<30%"][_deviceName] = {"Battery": self.ListOfDevices[x]["Battery"]}
if not isinstance( battery, (int, float)):
self.logging("Debug", f"rest_battery_state - {x} Battery found, but not int !! {type(battery)}")
continue
battery = int(battery)

if "BatteryUpdateTime" in self.ListOfDevices[x]:
if (int(time.time()) - self.ListOfDevices[x]["BatteryUpdateTime"]) > 604800: # one week in seconds
_battEnv["Update Time"]["> 1 week"][_deviceName] = {"BatteryUpdateTime": self.ListOfDevices[x]["BatteryUpdateTime"]}
if self.ListOfDevices[x]["Battery"] > 50:
_battEnv["Battery"][">50%"][_deviceName] = {"Battery": battery}

else:
_battEnv["Update Time"]["< 1 week"][_deviceName] = {"BatteryUpdateTime": self.ListOfDevices[x]["BatteryUpdateTime"]}
elif self.ListOfDevices[x]["Battery"] > 30:
_battEnv["Battery"]["<50%"][_deviceName] = {"Battery": battery}

else:
_battEnv["Battery"]["<30%"][_deviceName] = {"Battery": battery}

if "BatteryUpdateTime" in self.ListOfDevices[x]:
if (int(time.time()) - self.ListOfDevices[x]["BatteryUpdateTime"]) > 604800: # one week in seconds
_battEnv["Update Time"]["> 1 week"][_deviceName] = {"BatteryUpdateTime": self.ListOfDevices[x]["BatteryUpdateTime"]}

else:
_battEnv["Update Time"]["Unknown"][_deviceName] = "Unknown"
_battEnv["Update Time"]["< 1 week"][_deviceName] = {"BatteryUpdateTime": self.ListOfDevices[x]["BatteryUpdateTime"]}

else:
_battEnv["Update Time"]["Unknown"][_deviceName] = "Unknown"

self.logging("Debug", f"rest_battery_state - {_battEnv}")
_response["Data"] = json.dumps(_battEnv, sort_keys=True)
return _response

def logging(self, logType, message):
self.log.logging("WebServer", logType, message)

Expand Down
32 changes: 24 additions & 8 deletions Modules/actuators.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def actuator_setcolor(self, nwkid, EPout, value, Color):
if ( "Param" in self.ListOfDevices[nwkid] and "moveToLevel" in self.ListOfDevices[nwkid]["Param"] ):
transitionMoveLevel = "%04x" % int(self.ListOfDevices[nwkid]["Param"]["moveToLevel"])

force_color_command = get_deviceconf_parameter_value(self, self.ListOfDevices[nwkid]["Model"], "FORCE_COLOR_COMMAND", return_default=None)
force_color_command = is_tuya_hue_saturation_needed(self, nwkid)
ColorCapabilitiesList = device_color_capabilities( self, nwkid, EPout)
self.log.logging("Command", "Debug", "actuator_setcolor force_color_command %s" % force_color_command, nwkid)

Expand All @@ -266,7 +266,7 @@ def actuator_setcolor(self, nwkid, EPout, value, Color):
handle_color_mode_2(self, nwkid, EPout, Hue_List)
actuator_setlevel(self, nwkid, EPout, value, "Light", transitionMoveLevel)

elif Hue_List["m"] == 3 and force_color_command == "TuyaMovetoHueandSaturation":
elif Hue_List["m"] == 3 and force_color_command:
handle_color_mode_tuya( self, nwkid, EPout, Hue_List, value)

elif Hue_List["m"] == 3:
Expand Down Expand Up @@ -308,7 +308,7 @@ def handle_color_mode_3(self, nwkid, EPout, Hue_List):
#strxy = Hex_Format(4, x) + Hex_Format(4, y)
self.log.logging("Command", "Debug", "handle_color_mode_3 Set Temp X: %s Y: %s" % (x, y), nwkid)
transitionMoveLevel , transitionRGB , transitionMoveLevel , transitionHue , transitionTemp = get_all_transition_mode( self, nwkid)
if get_deviceconf_parameter_value(self, self.ListOfDevices[nwkid]["Model"], "TUYAColorControlRgbMode", return_default=None):
if is_tuya_rgb_mode_needed(self, nwkid):
tuya_color_control_rgbMode( self, nwkid, "01")
zcl_move_to_colour(self, nwkid, EPout, Hex_Format(4, x), Hex_Format(4, y), transitionRGB)

Expand All @@ -326,7 +326,7 @@ def handle_color_mode_4(self, nwkid, EPout, Hue_List ):
TempMired = 1000000 // TempKelvin
self.log.logging( "Command", "Log", "handle_color_mode_4 Set Temp Kelvin: %s-%s" % (
TempMired, Hex_Format(4, TempMired)), nwkid )
if get_deviceconf_parameter_value(self, self.ListOfDevices[nwkid]["Model"], "TUYAColorControlRgbMode", return_default=None):
if is_tuya_rgb_mode_needed(self, nwkid):
tuya_color_control_rgbMode( self, nwkid, "01")
zcl_move_to_colour_temperature( self, nwkid, EPout, Hex_Format(4, TempMired), transitionTemp)

Expand All @@ -339,7 +339,7 @@ def handle_color_mode_4(self, nwkid, EPout, Hue_List ):

self.log.logging("Command", "Log", "handle_color_mode_4 Set Hue X: %s Saturation: %s" % (
hue, saturation), nwkid)
if get_deviceconf_parameter_value(self, self.ListOfDevices[nwkid]["Model"], "TUYAColorControlRgbMode", return_default=None):
if is_tuya_rgb_mode_needed(self, nwkid):
tuya_color_control_rgbMode( self, nwkid, "01")
zcl_move_hue_and_saturation(self, nwkid, EPout, Hex_Format(2, hue), Hex_Format(2, saturation), transitionRGB)

Expand All @@ -353,10 +353,10 @@ def handle_color_mode_9998( self, nwkid, EPout, Hue_List, value):
hue = int(hue * 254 // 360)

self.log.logging("Command", "Debug", "handle_color_mode_9998 Set Hue X: %s Saturation: %s" % (hue, saturation), nwkid)
if get_deviceconf_parameter_value(self, self.ListOfDevices[nwkid]["Model"], "TUYAColorControlRgbMode", return_default=None):
if is_tuya_rgb_mode_needed(self, nwkid):
tuya_color_control_rgbMode( self, nwkid, "01")

if get_deviceconf_parameter_value(self, self.ListOfDevices[nwkid]["Model"], "FORCE_COLOR_COMMAND", return_default=None) == "TuyaMovetoHueandSaturation":
if is_tuya_hue_saturation_needed(self, nwkid):
tuya_Move_To_Hue_Saturation( self, nwkid, hue, saturation, value)
else:
zcl_move_hue_and_saturation(self, nwkid, EPout, Hex_Format(2, hue), Hex_Format(2, saturation), transitionRGB)
Expand All @@ -365,6 +365,22 @@ def handle_color_mode_9998( self, nwkid, EPout, Hue_List, value):
actuator_setlevel(self, nwkid, EPout, value, "Light", transitionMoveLevel)


def is_tuya_hue_saturation_needed(self, nwkid):
model = self.ListOfDevices[nwkid].get("Model","")
tuya_move_to_hue_and_saturation = get_deviceconf_parameter_value(self, model, "FORCE_COLOR_COMMAND", return_default=None) or get_device_config_param(self, nwkid, "FORCE_COLOR_COMMAND")
return tuya_move_to_hue_and_saturation == "TuyaMovetoHueandSaturation"


def is_tuya_rgb_mode_needed(self, nwkid):
model = self.ListOfDevices[nwkid].get("Model","")
return get_deviceconf_parameter_value(
self,
model,
"TUYAColorControlRgbMode",
return_default=None,
) or get_device_config_param(self, nwkid, "TUYAColorControlRgbMode")


def handle_color_mode_tuya( self, nwkid, EPout, Hue_List, value):

self.log.logging("Command", "Debug", "handle_color_mode_tuya Hue_list: %s Value: %s" % (
Expand All @@ -379,7 +395,7 @@ def handle_color_mode_tuya( self, nwkid, EPout, Hue_List, value):

self.log.logging("Command", "Log", "handle_color_mode_tuya Set Hue X: %s Saturation: %s Value: %s" % (
hue, saturation, value), nwkid)
if get_deviceconf_parameter_value(self, self.ListOfDevices[nwkid]["Model"], "TUYAColorControlRgbMode", return_default=None):
if is_tuya_rgb_mode_needed(self, nwkid):
tuya_color_control_rgbMode( self, nwkid, "01")
tuya_Move_To_Hue_Saturation( self, nwkid, EPout, hue, saturation, transitionHue, value )

Expand Down
2 changes: 1 addition & 1 deletion Modules/checkingUpdate.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def is_zigate_firmware_available(self, currentMajorVersion, currentFirmwareVersi

def is_internet_available():
try:
response = requests.get("http://www.google.com", timeout=3)
response = requests.get("https://www.google.com", timeout=3)
# Check if the status code is a success code (2xx)
return response.status_code == 200
except requests.ConnectionError:
Expand Down
5 changes: 4 additions & 1 deletion Modules/heartbeat.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
ReadAttributeRequest_0402,
ReadAttributeRequest_0405,
ReadAttributeRequest_0702_0000,
ReadAttributeRequest_0702_0017,
ReadAttributeRequest_0702_PC321,
ReadAttributeRequest_0702_ZLinky_TIC,
ReadAttributeRequest_ff66,
Expand Down Expand Up @@ -344,7 +345,9 @@ def pollingManufSpecificDevices(self, NwkId, HB):
"HumiPollingFreq": ReadAttributeRequest_0405,
"BattPollingFreq": ReadAttributeRequest_0001,
"ZLinkyIndexes": ReadAttributeReq_Scheduled_ZLinky, # Based on a specific time
"ZLinkyPollingPTEC": ReadAttributeReq_Scheduled_ZLinky # Every 15' by default
"ZLinkyPollingPTEC": ReadAttributeReq_Scheduled_ZLinky, # Every 15' by default
"InletTempPolling": ReadAttributeRequest_0702_0017, # Retreive Inlet Temperature

}

if "Param" not in self.ListOfDevices[NwkId]:
Expand Down
28 changes: 28 additions & 0 deletions Modules/readAttributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1333,6 +1333,34 @@ def ReadAttributeRequest_0702_0000(self, key):
self.log.logging("ReadAttributes", "Debug", "Request Summation on 0x0702 cluster: " + key + " EPout = " + EPout, nwkid=key)
ReadAttributeReq(self, key, ZIGATE_EP, EPout, "0702", listAttributes, ackIsDisabled=is_ack_tobe_disabled(self, key))


def ReadAttributeRequest_0702_0017(self, key):
"""
Reads the InletTemperature (Attribute 0x0017) from the Metering cluster (0x0702).

Parameters:
self: The instance of the class.
key: The network identifier for the device.
"""

# Define the cluster and attribute
cluster_id = "0702"
attributes_list = [0x0017,]

# Get the list of endpoints for the cluster
endpoints = getListOfEpForCluster(self, key, cluster_id)
for endpoint in endpoints:
self.log.logging(
"ReadAttributes",
"Debug",
f"Requesting InletTemperature (Attribute {attributes_list}) on cluster {cluster_id} for key {key}, EP = {endpoint}.",
nwkid=key
)

# Send the read attribute request
ReadAttributeReq(self, key, ZIGATE_EP, endpoint, cluster_id, attributes_list, ackIsDisabled=is_ack_tobe_disabled(self, key))


def ReadAttributeRequest_0702_multiplier_divisor(self, key):
ListOfEp = getListOfEpForCluster(self, key, "0702")
for EPout in ListOfEp:
Expand Down
4 changes: 4 additions & 0 deletions Modules/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ def getListOfEpForCluster(self, NwkId, SearchCluster):

oldFashion = ( "ClusterType" in self.ListOfDevices[NwkId] and self.ListOfDevices[NwkId]["ClusterType"] not in ({}, "") )
for Ep in list(self.ListOfDevices[NwkId]["Ep"].keys()):
# check that is not a Fake Ep
if is_fake_ep(self, NwkId, Ep):
continue

if SearchCluster not in self.ListOfDevices[NwkId]["Ep"][Ep]:
continue

Expand Down
1 change: 0 additions & 1 deletion Zigbee/zclDecoders.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@


import struct
from distutils.command.build import build
from os import stat

from Modules.tools import (is_direction_to_client, is_direction_to_server,
Expand Down
3 changes: 3 additions & 0 deletions sonar-project.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
sonar.issue.ignore.multicriteria=e1
sonar.issue.ignore.multicriteria.e1.ruleKey=python:S5332
sonar.issue.ignore.multicriteria.e1.resourceKey=**
Loading