def rest_binding(self, verb, data, parameters): _response = prepResponseMessage(self, setupHeadersResponse()) if verb != "PUT" or len(parameters) != 0: return _response _response["Data"] = None data = data.decode("utf8") data = json.loads(data) if "sourceIeee" not in data and "sourceEp" not in data and "destIeee" not in data and "destEp" not in data and "cluster" not in data: Domoticz.Error("-----> uncomplet json %s" % data) _response["Data"] = json.dumps("uncomplet json %s" % data) return _response self.logging( "Debug", "rest_binding - Source: %s/%s Dest: %s/%s Cluster: %s" % (data["sourceIeee"], data["sourceEp"], data["destIeee"], data["destEp"], data["cluster"]), ) webBind(self, data["sourceIeee"], data["sourceEp"], data["destIeee"], data["destEp"], data["cluster"]) _response["Data"] = json.dumps( "Binding cluster %s between %s/%s and %s/%s" % (data["cluster"], data["sourceIeee"], data["sourceEp"], data["destIeee"], data["destEp"])) return _response
def rest_bindLSTdevice(self, verb, data, parameters): _response = prepResponseMessage(self, setupHeadersResponse()) if len(parameters) != 1: Domoticz.Error("Must have 1 argument. %s" % parameters) return _response listofdevices = [] clustertobind = parameters[0] for key in self.ListOfDevices: if key == "0000": dev = { "IEEE": self.ListOfDevices[key]["IEEE"], "NwkId": key, "Ep": "01", "ZDeviceName": self.ListOfDevices[key]["ZDeviceName"], } listofdevices.append(dev) continue for ep in self.ListOfDevices[key]["Ep"]: if clustertobind in self.ListOfDevices[key]["Ep"][ep]: dev = { "IEEE": self.ListOfDevices[key]["IEEE"], "NwkId": key, "Ep": ep, "ZDeviceName": self.ListOfDevices[key]["ZDeviceName"], } if dev not in listofdevices: listofdevices.append(dev) _response["Data"] = json.dumps(listofdevices) return _response
def rest_ota_devices_for_manufcode(self, verb, data, parameters): _response = prepResponseMessage(self, setupHeadersResponse()) _response["Data"] = None if self.OTA is None or verb != "GET" or len(parameters) != 1: return _response if len(self.zigatedata) == 0: _response["Data"] = fake_rest_ota_devices_for_manufcode() return _response manuf_code = parameters[0] device_list = [] for x in self.ListOfDevices: if "Manufacturer" not in self.ListOfDevices[ x] and "Manufacturer Name" not in self.ListOfDevices[x]: continue compatible = False if (manuf_code in MATRIX_MANUFACTURER_NAME and "Manufacturer Name" in self.ListOfDevices[x] and MATRIX_MANUFACTURER_NAME[manuf_code] == self.ListOfDevices[x]["Manufacturer Name"]): compatible = True if not compatible and self.ListOfDevices[x][ "Manufacturer"] != manuf_code: continue Domoticz.Log("Found device: %s" % x) device_list.append(get_device_informations(self, x)) _response["Data"] = json.dumps(device_list, sort_keys=True) return _response
def rest_group_unbinding(self, verb, data, parameters): # curl -X PUT -d '{"sourceIeee":" 84fd27fffe17e4c5", "sourceEp": "01", "groupId": " 4ca3", "cluster": "0006"}' http://127.0.0.1:9441/rest-zigate/1/unbinding-group _response = prepResponseMessage(self, setupHeadersResponse()) if verb != "PUT" or len(parameters) != 0: return _response _response["Data"] = None data = data.decode("utf8") data = json.loads(data) if "sourceIeee" not in data and "sourceEp" not in data and "groupId" not in data and "cluster" not in data: Domoticz.Error("-----> uncomplet json %s" % data) _response["Data"] = json.dumps("uncomplet json %s" % data) return _response self.logging( "Debug", "rest_group_unbinding - Source: %s/%s Dest: %s Cluster: %s" % (data["sourceIeee"], data["sourceEp"], data["groupId"], data["cluster"]), ) unbindGroup(self, data["sourceIeee"], data["sourceEp"], data["cluster"], data["groupId"]) _response["Data"] = json.dumps( "UnBinding cluster %s between %s/%s and %s" % (data["cluster"], data["sourceIeee"], data["sourceEp"], data["groupId"])) return _response
def rest_scan_devices_for_group(self, verb, data, parameter): # wget --method=PUT --body-data='[ "0000", "0001", "0002", "0003" ]' http://127.0.0.1:9442/rest-zigate/1/ScanDeviceForGrp _response = prepResponseMessage(self, setupHeadersResponse()) _response["Data"] = None if self.groupmgt is None: # Group is not enabled! return _response if verb != "PUT": # Only Put command with a Valid JSON is allow return _response if data is None: return _response if len(parameter) != 0: return _response # We receive a JSON with a list of NwkId to be scaned data = data.decode("utf8") data = json.loads(data) self.logging( "Debug", "rest_scan_devices_for_group - Trigger GroupMemberShip scan for devices: %s " % (data)) self.groupmgt.ScanDevicesForGroupMemberShip(data) action = {"Name": "Scan of device requested.", "TimeStamp": int(time())} _response["Data"] = json.dumps(action, sort_keys=True) return _response
def rest_casa_device_ircode_update(self, verb, data, parameters): # wget --method=PUT --body-data='[ # { # "NwkId": "0a90", # "IRCode": "1234", # }, # { # .... # ] # ' http://127.0.0.1:9440/rest-zigate/1/ota-firmware-update _response = prepResponseMessage(self, setupHeadersResponse()) _response["Data"] = None if verb != "PUT": # Only Put command with a Valid JSON is allow return _response if data is None: return _response if len(parameters) != 0: return _response # We receive a JSON with a list of NwkId to be scaned data = data.decode("utf8") self.logging( "Debug", "rest_casa_device_ircode_update - Data received %s " % (data)) data = json.loads(data) self.logging( "Debug", "rest_casa_device_ircode_update - List of Device IRCode %s " % (data)) status = 0 for x in data: if "NwkId" not in x and "IRCode" not in x: status = 1 continue if x["NwkId"] in self.ListOfDevices and "CASA.IA" in self.ListOfDevices[ x["NwkId"]]: Domoticz.Log("Updating : %s with %s" % (x["NwkId"], x["IRCode"])) if self.ListOfDevices[ x["NwkId"]] and "Model" in self.ListOfDevices[x["NwkId"]]: self.ListOfDevices[ x["NwkId"]]["CASA.IA"][DEVICE_ID]["IRCode"] = x["IRCode"] action = { " Name": "IRCode update performed status: %s" % status, "TimeStamp": int(time()) } _response["Data"] = json.dumps(action, sort_keys=True) return _response
def rest_new_hrdwr(self, verb, data, parameters): """ This is call to Enable/Disable a Provisioning process. As a toggle you will enable the provisioning or disable it it will return either Enable or Disable """ _response = prepResponseMessage(self, setupHeadersResponse()) if verb != "GET": return _response data = {} if len(parameters) != 1: Domoticz.Error("rest_new_hrdwr - unexpected parameter %s " % parameters) _response["Data"] = {"unexpected parameter %s " % parameters} return _response if parameters[0] not in ("enable", "cancel", "disable"): Domoticz.Error("rest_new_hrdwr - unexpected parameter %s " % parameters[0]) _response["Data"] = {"unexpected parameter %s " % parameters[0]} return _response if parameters[0] == "enable": Domoticz.Log("Enable Assisted pairing") if len(self.DevicesInPairingMode): del self.DevicesInPairingMode self.DevicesInPairingMode = [] if not self.zigatedata: # Seems we are in None mode - Testing for ben self.fakeDevicesInPairingMode = 0 if self.permitTojoin["Duration"] != 255 and self.pluginParameters[ "Mode2"] != "None": ZigatePermitToJoin(self, (4 * 60)) _response["Data"] = {"start pairing mode at %s " % int(time())} return _response if parameters[0] in ("cancel", "disable"): Domoticz.Log("Disable Assisted pairing") if len(self.DevicesInPairingMode) != 0: del self.DevicesInPairingMode self.DevicesInPairingMode = [] if not self.zigatedata: # Seems we are in None mode - Testing for ben self.fakeDevicesInPairingMode = 0 if not (self.permitTojoin["Duration"] == 255 or self.pluginParameters["Mode2"] == "None"): ZigatePermitToJoin(self, 0) _response["Data"] = {"stop pairing mode at %s " % int(time())} return _response
def rest_ota_firmware_update(self, verb, data, parameter): # wget --method=PUT --body-data='{ # "NwkId": "0a90", # "Ep": "0b", # "Brand": "Schneider", # "FileName": "EH_ZB_SNP_R_04_01_14_VACT.zigbee" # }' http://127.0.0.1:9440/rest-zigate/1/ota-firmware-update _response = prepResponseMessage(self, setupHeadersResponse()) _response["Data"] = None if self.OTA is None: # OTA is not enabled! return _response if verb != "PUT": # Only Put command with a Valid JSON is allow return _response if data is None: return _response if len(parameter) != 0: return _response # We receive a JSON with a list of NwkId to be scaned data = data.decode("utf8") self.logging("Debug", "rest_ota_firmware_update - Data received %s " % (data)) data = json.loads(data) self.logging( "Debug", "rest_ota_firmware_update - Trigger OTA upgrade %s " % (data)) # Check for x in data: if "Brand" not in x or "FileName" not in x or "NwkId" not in x or "Ep" not in x or "ForceUpdate" not in x: self.logging( "Error", "rest_ota_firmware_update - Missing key parameters %s " % (data)) _response["Data"] = json.dumps({"Error": "Missing attributes"}, sort_keys=True) return _response self.logging("Debug", "rest_ota_firmware_update - data: %s" % (data)) if self.OTA: self.OTA.restapi_firmware_update(data) action = {"Name": "OTA requested.", "TimeStamp": int(time())} _response["Data"] = json.dumps(action, sort_keys=True) return _response
def rest_ota_firmware_list(self, verb, data, parameters): _response = prepResponseMessage(self, setupHeadersResponse()) _response["Data"] = None if self.OTA and verb == "GET" and len(parameters) == 0: if len(self.zigatedata) == 0: _response["Data"] = fake_rest_ota_firmware_list() return _response _response["Data"] = json.dumps(self.OTA.restapi_list_of_firmware(), sort_keys=True) return _response
def rest_casa_device_list(self, verb, data, parameters): # Ok 10/11/2020 _response = prepResponseMessage(self, setupHeadersResponse()) _response["Data"] = None _response["Data"] = list_casaia_ac201(self) if verb == "GET" and len(parameters) == 0: if len(self.zigatedata) == 0: _response["Data"] = json.dumps(fake_list_casaia_ac201(), sort_keys=True) return _response _response["Data"] = json.dumps(list_casaia_ac201(self), sort_keys=True) return _response
def rest_recreate_widgets(self, verb, data, parameters): # curl -X PUT -d '{"IEEE":"00158d0005bea6da"}' http://127.0.0.1:9441/rest-zigate/1/recreate-widgets _response = prepResponseMessage(self, setupHeadersResponse()) Domoticz.Log("rest_recreate_widgets -->Verb: %s Data: %s Parameters: %s" % (verb, data, parameters)) if verb != "PUT": return _response data = data.decode("utf8") data = eval(data) self.logging("Log", "rest_recreate_widgets - Data: %s" % data) if "IEEE" not in data and "NWKID" not in data: Domoticz.Error("rest_recreate_widgets - unexpected parameter %s " % parameters) _response["Data"] = {"unexpected parameter %s " % parameters} return _response if "IEEE" in data: key = data["IEEE"] if key not in self.IEEE2NWK: Domoticz.Error("rest_recreate_widgets - Unknown device %s " % key) return _response nwkid = self.IEEE2NWK[key] _response["Data"] = { "IEEE %s set to Provisioning Requested at %s" % (key, int(time())) } else: nwkid = data["NWKID"] if nwkid not in self.ListOfDevices: Domoticz.Error("rest_recreate_widgets - Unknown device %s " % nwkid) return _response _response["Data"] = { "NwkId %s set to Provisioning Requested at %s" % (nwkid, int(time())) } over_write_type_from_deviceconf(self, self.Devices, nwkid) self.ListOfDevices[nwkid]["Status"] = "CreateDB" CreateDomoDevice(self, self.Devices, nwkid) return _response
def rest_rescan_group(self, verb, data, parameters): _response = prepResponseMessage(self, setupHeadersResponse()) _response["Headers"]["Content-Type"] = "application/json; charset=utf-8" action = {} if verb != "GET": return _response if self.groupmgt: self.groupmgt.ScanAllDevicesForGroupMemberShip() else: Domoticz.Error("rest_rescan_group Group not enabled!!!") action["Name"] = "Full Scan" action["TimeStamp"] = int(time()) _response["Data"] = json.dumps(action, sort_keys=True) return _response
def rest_full_reprovisionning(self, verb, data, parameters): _response = prepResponseMessage(self, setupHeadersResponse()) Domoticz.Log( "rest_full_reprovisionning -->Verb: %s Data: %s Parameters: %s" % (verb, data, parameters)) if verb != "PUT": return _response data = data.decode("utf8") data = eval(data) self.logging("Log", "Data: %s" % data) if "IEEE" not in data and "NWKID" not in data: Domoticz.Error("rest_full_reprovisionning - unexpected parameter %s " % parameters) _response["Data"] = {"unexpected parameter %s " % parameters} return _response if "IEEE" in data: key = data["IEEE"] if key not in self.IEEE2NWK: Domoticz.Error("rest_full_reprovisionning - Unknown device %s " % key) return _response nwkid = self.IEEE2NWK[key] _response["Data"] = { "IEEE %s set to Provisioning Requested at %s" % (key, int(time())) } else: nwkid = data["NWKID"] if nwkid not in self.ListOfDevices: Domoticz.Error("rest_full_reprovisionning - Unknown device %s " % nwkid) return _response _response["Data"] = { "NwkId %s set to Provisioning Requested at %s" % (nwkid, int(time())) } self.ListOfDevices[nwkid]["Status"] = "provREQ" return _response
def rest_req_topologie(self, verb, data, parameters): _response = prepResponseMessage(self, setupHeadersResponse()) if verb == "GET": action = {"Name": "Req-Topology", "TimeStamp": int(time())} _response["Data"] = json.dumps(action, sort_keys=True) self.logging("Log", "Request a Start of Network Topology scan") if self.networkmap: if not self.networkmap.NetworkMapPhase(): self.networkmap.start_scan() else: self.logging( "Log", "Cannot start Network Topology as one is in progress...") return _response
def rest_binding_table_disp(self, verb, data, parameters): _response = prepResponseMessage(self, setupHeadersResponse()) if verb != "GET": return _response if len(parameters) != 1: return _response if parameters[0] not in self.ListOfDevices: return _response nwkid = parameters[0] if "BindingTable" not in self.ListOfDevices[nwkid]: return _response bindtable = self.ListOfDevices[nwkid]["BindingTable"] _response["Data"] = json.dumps(bindtable, sort_keys=True) return _response
def rest_binding_table_req(self, verb, data, parameters): # curl http://127.0.0.1:9440/rest-zigate/1/binding-table-req/bd92 _response = prepResponseMessage(self, setupHeadersResponse()) _response["Headers"]["Content-Type"] = "application/json; charset=utf-8" if verb != "GET": return _response if len(parameters) != 1: return _response if parameters[0] not in self.ListOfDevices: return _response nwkid = parameters[0] mgt_binding_table_req(self, nwkid, start_index="00") action = {"Name": "Requested Binding table for device: %s" % nwkid} _response["Data"] = json.dumps(action, sort_keys=True) return _response
def rest_bindLSTcluster(self, verb, data, parameters): _response = prepResponseMessage(self, setupHeadersResponse()) bindCluster = [] for key in self.ListOfDevices: if key == "0000": continue for ep in self.ListOfDevices[key]["Ep"]: for cluster in self.ListOfDevices[key]["Ep"][ep]: if cluster in ZCL_CLUSTERS_ACT: item = { "ClusterId": cluster, "ClusterDesc": ZCL_CLUSTERS_ACT[cluster] } if item not in bindCluster: bindCluster.append(item) _response["Data"] = json.dumps(bindCluster) return _response
def rest_rcv_nw_hrdwr(self, verb, data, parameters): """ Will return a status on the provisioning process. Either Enable or Disable and in case there is a new device provisionned during the period, it will return the information captured. """ _response = prepResponseMessage(self, setupHeadersResponse()) if verb != "GET": return _response data = {} data["NewDevices"] = [] if not self.zigatedata: # Seems we are in None mode - Testing for ben if self.fakeDevicesInPairingMode in (0, 1): # Do nothing just wait the next pool self.fakeDevicesInPairingMode += 1 _response["Data"] = json.dumps(data) return _response if self.fakeDevicesInPairingMode in (2, 3): self.fakeDevicesInPairingMode += 1 newdev = {} newdev["NwkId"] = list(self.ListOfDevices.keys())[0] data["NewDevices"].append(newdev) _response["Data"] = json.dumps(data) return _response if self.fakeDevicesInPairingMode in (4, 5): self.fakeDevicesInPairingMode += 1 newdev = {} newdev["NwkId"] = list(self.ListOfDevices.keys())[0] data["NewDevices"].append(newdev) newdev = {} newdev["NwkId"] = list(self.ListOfDevices.keys())[1] data["NewDevices"].append(newdev) _response["Data"] = json.dumps(data) return _response if self.fakeDevicesInPairingMode in (6, 7): self.fakeDevicesInPairingMode += 1 self.DevicesInPairingMode.append( list(self.ListOfDevices.keys())[0]) self.DevicesInPairingMode.append( list(self.ListOfDevices.keys())[1]) self.DevicesInPairingMode.append( list(self.ListOfDevices.keys())[2]) Domoticz.Log("Assisted Pairing: Polling: %s" % str(self.DevicesInPairingMode)) if len(self.DevicesInPairingMode) == 0: Domoticz.Log("--> Empty queue") _response["Data"] = json.dumps(data) return _response listOfPairedDevices = list(self.DevicesInPairingMode) _fake = 0 for nwkid in listOfPairedDevices: if not self.zigatedata: _fake += 1 if nwkid not in self.ListOfDevices: continue newdev = {} newdev["NwkId"] = nwkid Domoticz.Log("--> New device: %s" % nwkid) if "Status" not in self.ListOfDevices[nwkid]: Domoticz.Error( "Something went wrong as the device seems not be created") data["NewDevices"].append(newdev) continue if self.ListOfDevices[nwkid]["Status"] in ("004d", "0045", "0043", "8045", "8043") or (_fake == 1): # Pairing in progress, just return the Nwkid data["NewDevices"].append(newdev) continue elif self.ListOfDevices[nwkid]["Status"] == "UNKNOW" or (_fake == 2): Domoticz.Log("--> UNKNOW , removed %s from List" % nwkid) self.DevicesInPairingMode.remove(nwkid) newdev["ProvisionStatus"] = "Failed" newdev["ProvisionStatusDesc"] = "Failed" elif self.ListOfDevices[nwkid]["Status"] == "inDB": Domoticz.Log("--> inDB , removed %s from List" % nwkid) self.DevicesInPairingMode.remove(nwkid) newdev["ProvisionStatus"] = "inDB" newdev["ProvisionStatusDesc"] = "inDB" else: Domoticz.Log("--> Unexpected , removed %s from List" % nwkid) self.DevicesInPairingMode.remove(nwkid) newdev["ProvisionStatus"] = "Unexpected" newdev["ProvisionStatusDesc"] = "Unexpected" Domoticz.Error("Unexpected") continue newdev["IEEE"] = "Unknown" if "IEEE" in self.ListOfDevices[nwkid]: newdev["IEEE"] = self.ListOfDevices[nwkid]["IEEE"] newdev["ProfileId"] = "" newdev["ProfileIdDesc"] = "Unknow" if "ProfileID" in self.ListOfDevices[nwkid]: if self.ListOfDevices[nwkid]["ProfileID"] != {}: newdev["ProfileId"] = self.ListOfDevices[nwkid]["ProfileID"] if int(newdev["ProfileId"], 16) in PROFILE_ID: newdev["ProfileIdDesc"] = PROFILE_ID[int( newdev["ProfileId"], 16)] newdev["ZDeviceID"] = "" newdev["ZDeviceIDDesc"] = "Unknow" if "ZDeviceID" in self.ListOfDevices[nwkid]: if self.ListOfDevices[nwkid]["ZDeviceID"] != {}: newdev["ZDeviceID"] = self.ListOfDevices[nwkid]["ZDeviceID"] if int(newdev["ProfileId"], 16) == 0x0104: # ZHA if int(newdev["ZDeviceID"], 16) in ZHA_DEVICES: newdev["ZDeviceIDDesc"] = ZHA_DEVICES[int( newdev["ZDeviceID"], 16)] else: newdev["ZDeviceIDDesc"] = "Unknow" elif int(newdev["ProfileId"], 16) == 0xC05E: # ZLL if int(newdev["ZDeviceID"], 16) in ZLL_DEVICES: newdev["ZDeviceIDDesc"] = ZLL_DEVICES[int( newdev["ZDeviceID"], 16)] if "Model" in self.ListOfDevices[nwkid]: newdev["Model"] = self.ListOfDevices[nwkid]["Model"] newdev["PluginCertified"] = "Unknow" if "ConfigSource" in self.ListOfDevices[nwkid]: if self.ListOfDevices[nwkid]["ConfigSource"] == "DeviceConf": newdev["PluginCertified"] = "yes" else: newdev["PluginCertified"] = "no" newdev["Ep"] = [] if "Ep" in self.ListOfDevices[nwkid]: for iterEp in self.ListOfDevices[nwkid]["Ep"]: ep = {} ep["Ep"] = iterEp ep["Clusters"] = [] for clusterId in self.ListOfDevices[nwkid]["Ep"][iterEp]: if clusterId in ("ClusterType", "Type", "ColorControl"): continue cluster = {} cluster["ClusterId"] = clusterId if clusterId in ZCL_CLUSTERS_LIST: cluster["ClusterDesc"] = ZCL_CLUSTERS_LIST[clusterId] else: cluster["ClusterDesc"] = "Unknown" ep["Clusters"].append(cluster) Domoticz.Log("------> New Cluster: %s" % str(cluster)) newdev["Ep"].append(ep) Domoticz.Log("----> New Ep: %s" % str(ep)) data["NewDevices"].append(newdev) Domoticz.Log(" --> New Device: %s" % str(newdev)) # for nwkid in listOfPairedDevices: _response["Data"] = json.dumps(data) return _response
def onMessage(self, Connection, Data): self.logging("Debug", "WebServer onMessage : %s" % Data) # DumpHTTPResponseToLog(Data) headerCode = "200 OK" if "Verb" not in Data: Domoticz.Error("Invalid web request received, no Verb present") headerCode = "400 Bad Request" elif Data["Verb"] not in ("GET", "PUT", "POST", "DELETE"): Domoticz.Error( "Invalid web request received, only GET requests allowed (" + Data["Verb"] + ")") headerCode = "405 Method Not Allowed" elif "URL" not in Data: Domoticz.Error("Invalid web request received, no URL present") headerCode = "400 Bad Request" parsed_url = urlparse(Data["URL"]) self.logging("Debug", "URL: %s , Path: %s" % (Data["URL"], parsed_url.path)) if Data["URL"][0] == "/": parsed_query = Data["URL"][1:].split("/") else: parsed_query = Data["URL"].split("/") # Any Cookie ? cookie = None if "Cookie" in Data["Headers"]: cookie = Data["Headers"]["Cookie"] if "Data" not in Data: Data["Data"] = None if headerCode != "200 OK": self.sendResponse(Connection, {"Status": headerCode}) return if len(parsed_query) >= 3: self.logging( "Debug", "Receiving a REST API - Version: %s, Verb: %s, Command: %s, Param: %s" % (parsed_query[1], Data["Verb"], parsed_query[2], parsed_query[3:]), ) if parsed_query[0] == "rest-zigate" and parsed_query[1] == "1": # API Version 1 self.do_rest(Connection, Data["Verb"], Data["Data"], parsed_query[1], parsed_query[2], parsed_query[3:]) else: Domoticz.Error("Unknown API %s" % parsed_query) headerCode = "400 Bad Request" self.sendResponse(Connection, {"Status": headerCode}) return # Finaly we simply has to serve a File. webFilename = self.homedirectory + "www" + Data["URL"] self.logging("Debug", "webFilename: %s" % webFilename) if not os.path.isfile(webFilename): webFilename = self.homedirectory + "www" + "/index.html" self.logging("Debug", "Redirecting to /index.html") # We are ready to send the response _response = setupHeadersResponse(cookie) if self.pluginconf.pluginConf["enableKeepalive"]: _response["Headers"]["Connection"] = "Keep-alive" else: _response["Headers"]["Connection"] = "Close" if not self.pluginconf.pluginConf["enableCache"]: _response["Headers"][ "Cache-Control"] = "no-cache, no-store, must-revalidate" _response["Headers"]["Pragma"] = "no-cache" _response["Headers"]["Expires"] = "0" _response["Headers"]["Accept"] = "*/*" else: _response["Headers"]["Cache-Control"] = "private" self.logging("Debug", "Opening: %s" % webFilename) currentVersionOnServer = os.path.getmtime(webFilename) _lastmodified = strftime("%a, %d %m %y %H:%M:%S GMT", gmtime(currentVersionOnServer)) # Check Referrrer if "Referer" in Data["Headers"]: self.logging("Debug", "Set Referer: %s" % Data["Headers"]["Referer"]) _response["Headers"]["Referer"] = Data["Headers"]["Referer"] # Can we use Cache if exists if self.pluginconf.pluginConf["enableCache"]: if "If-Modified-Since" in Data["Headers"]: lastVersionInCache = Data["Headers"]["If-Modified-Since"] self.logging( "Debug", "InCache: %s versus Current: %s" % (lastVersionInCache, _lastmodified)) if lastVersionInCache == _lastmodified: # No need to send it back self.logging( "Debug", "User Caching - file: %s InCache: %s versus Current: %s" % (webFilename, lastVersionInCache, _lastmodified), ) _response["Status"] = "304 Not Modified" self.sendResponse(Connection, _response) return _response if "Ranges" in Data["Headers"]: self.logging("Debug", "Ranges processing") RangeProcess = Data["Headers"]["Range"] fileStartPosition = int(RangeProcess[RangeProcess.find("=") + 1:RangeProcess.find("-")]) messageFileSize = os.path.getsize(webFilename) messageFile = open(webFilename, mode="rb") messageFile.seek(fileStartPosition) fileContent = messageFile.read(MAX_KB_TO_SEND) self.logging( "Debug", Connection.Address + ":" + Connection.Port + " Sent 'GET' request file '" + Data["URL"] + "' from position " + str(fileStartPosition) + ", " + str(len(fileContent)) + " bytes will be returned", ) _response["Status"] = "200 OK" if len(fileContent) == MAX_KB_TO_SEND: _response["Status"] = "206 Partial Content" _response["Headers"]["Content-Range"] = ( "bytes " + str(fileStartPosition) + "-" + str(messageFile.tell()) + "/" + str(messageFileSize)) DumpHTTPResponseToLog(_response) Connection.Send(_response) if not self.pluginconf.pluginConf["enableKeepalive"]: Connection.Disconnect() else: _response["Headers"]["Last-Modified"] = _lastmodified with open(webFilename, mode="rb") as webFile: _response["Data"] = webFile.read() _contentType, _contentEncoding = mimetypes.guess_type(Data["URL"]) if _contentType: _response["Headers"][ "Content-Type"] = _contentType + "; charset=utf-8" if _contentEncoding: _response["Headers"]["Content-Encoding"] = _contentEncoding _response["Status"] = "200 OK" if "Accept-Encoding" in Data["Headers"]: self.sendResponse( Connection, _response, AcceptEncoding=Data["Headers"]["Accept-Encoding"]) else: self.sendResponse(Connection, _response)
def do_rest(self, Connection, verb, data, version, command, parameters): REST_COMMANDS = { "bind-lst-cluster": { "Name": "bind-lst-cluster", "Verbs": {"GET"}, "function": self.rest_bindLSTcluster }, "bind-lst-device": { "Name": "bind-lst-device", "Verbs": {"GET"}, "function": self.rest_bindLSTdevice }, "binding": { "Name": "binding", "Verbs": {"PUT"}, "function": self.rest_binding }, "binding-table-req": { "Name": "binding", "Verbs": {"GET"}, "function": self.rest_binding_table_req }, "binding-table-disp": { "Name": "binding", "Verbs": {"GET"}, "function": self.rest_binding_table_disp }, "binding-group": { "Name": "binding-group", "Verbs": {"PUT"}, "function": self.rest_group_binding }, "casaia-list-devices": { "Name": "casaia-list-devices", "Verbs": {"GET"}, "function": self.rest_casa_device_list, }, "casaia-update-ircode": { "Name": "casaia-list-devices", "Verbs": {"PUT"}, "function": self.rest_casa_device_ircode_update, }, "change-channel": { "Name": "change-channel", "Verbs": {"PUT"}, "function": self.rest_change_channel }, "clear-error-history": { "Name": "clear-error-history", "Verbs": {"GET"}, "function": self.rest_logErrorHistoryClear, }, "dev-cap": { "Name": "dev-cap", "Verbs": {"GET"}, "function": self.rest_dev_capabilities }, "dev-command": { "Name": "dev-command", "Verbs": {"PUT"}, "function": self.rest_dev_command }, "device": { "Name": "device", "Verbs": {"GET"}, "function": self.rest_Device }, "domoticz-env": { "Name": "domoticz-env", "Verbs": {"GET"}, "function": self.rest_domoticz_env }, "help": { "Name": "help", "Verbs": {"GET"}, "function": None }, "full-reprovisionning": { "Name": "full-reprovisionning", "Verbs": {"PUT"}, "function": self.rest_full_reprovisionning }, "log-error-history": { "Name": "log-error-history", "Verbs": {"GET"}, "function": self.rest_logErrorHistory }, "new-hrdwr": { "Name": "new-hrdwr", "Verbs": {"GET"}, "function": self.rest_new_hrdwr }, "nwk-stat": { "Name": "nwk_stat", "Verbs": {"GET", "DELETE"}, "function": self.rest_nwk_stat }, "ota-firmware-device-list": { "Name": "ota-firmware-list", "Verbs": {"GET"}, "function": self.rest_ota_devices_for_manufcode, }, "ota-firmware-list": { "Name": "ota-firmware-list", "Verbs": {"GET"}, "function": self.rest_ota_firmware_list }, "ota-firmware-update": { "Name": "ota-firmware-update", "Verbs": {"PUT"}, "function": self.rest_ota_firmware_update, }, "permit-to-join": { "Name": "permit-to-join", "Verbs": {"GET", "PUT"}, "function": self.rest_PermitToJoin }, "plugin-health": { "Name": "plugin-health", "Verbs": {"GET"}, "function": self.rest_plugin_health }, "plugin-restart": { "Name": "plugin-restart", "Verbs": {"GET"}, "function": self.rest_plugin_restart }, "plugin-stat": { "Name": "plugin-stat", "Verbs": {"GET"}, "function": self.rest_plugin_stat }, "plugin": { "Name": "plugin", "Verbs": {"GET"}, "function": self.rest_PluginEnv }, "raw-command": { "Name": "raw-command", "Verbs": {"PUT"}, "function": self.rest_raw_command }, "rcv-nw-hrdwr": { "Name": "rcv-nw-hrdwr", "Verbs": {"GET"}, "function": self.rest_rcv_nw_hrdwr }, "recreate-widgets": { "Name": "recreate-widgets", "Verbs": {"PUT"}, "function": self.rest_recreate_widgets }, "req-nwk-full": { "Name": "req-nwk-full", "Verbs": {"GET"}, "function": self.rest_req_nwk_full }, "req-nwk-inter": { "Name": "req-nwk-inter", "Verbs": {"GET"}, "function": self.rest_req_nwk_inter }, "req-topologie": { "Name": "req-topologie", "Verbs": {"GET"}, "function": self.rest_req_topologie }, "rescan-groups": { "Name": "rescan-groups", "Verbs": {"GET"}, "function": self.rest_rescan_group }, "restart-needed": { "Name": "restart-needed", "Verbs": {"GET"}, "function": self.rest_restart_needed }, "scan-device-for-grp": { "Name": "ScanDevscan-device-for-grpiceForGrp", "Verbs": {"PUT"}, "function": self.rest_scan_devices_for_group, }, "setting-debug": { "Name": "setting", "Verbs": {"GET", "PUT"}, "function": self.rest_Settings_with_debug }, "setting": { "Name": "setting", "Verbs": {"GET", "PUT"}, "function": self.rest_Settings_wo_debug }, "sw-reset-zigate": { "Name": "sw-reset-zigate", "Verbs": {"GET"}, "function": self.rest_reset_zigate }, "topologie": { "Name": "topologie", "Verbs": {"GET", "DELETE"}, "function": self.rest_netTopologie }, "unbinding": { "Name": "unbinding", "Verbs": {"PUT"}, "function": self.rest_unbinding }, "unbinding-group": { "Name": "unbinding-group", "Verbs": {"PUT"}, "function": self.rest_group_unbinding }, "zdevice-name": { "Name": "zdevice-name", "Verbs": {"GET", "PUT", "DELETE"}, "function": self.rest_zDevice_name }, "zdevice-raw": { "Name": "zdevice-raw", "Verbs": {"GET", "PUT"}, "function": self.rest_zDevice_raw }, "zdevice": { "Name": "zdevice", "Verbs": {"GET", "DELETE"}, "function": self.rest_zDevice }, "zgroup-list-available-device": { "Name": "zgroup-list-available-device", "Verbs": {"GET"}, "function": self.rest_zGroup_lst_avlble_dev, }, "zgroup": { "Name": "device", "Verbs": {"GET", "PUT"}, "function": self.rest_zGroup }, "zigate-erase-PDM": { "Name": "zigate-erase-PDM", "Verbs": {"GET"}, "function": self.rest_zigate_erase_PDM }, "zigate-mode": { "Name": "zigate-mode", "Verbs": {"GET"}, "function": self.rest_zigate_mode }, "zigate": { "Name": "zigate", "Verbs": {"GET"}, "function": self.rest_zigate }, } self.logging( "Debug", "do_rest - Verb: %s, Command: %s, Param: %s" % (verb, command, parameters)) HTTPresponse = {} if command in REST_COMMANDS and verb in REST_COMMANDS[command]["Verbs"]: HTTPresponse = setupHeadersResponse() if self.pluginconf.pluginConf["enableKeepalive"]: HTTPresponse["Headers"]["Connection"] = "Keep-alive" else: HTTPresponse["Headers"]["Connection"] = "Close" HTTPresponse["Headers"][ "Cache-Control"] = "no-cache, no-store, must-revalidate" HTTPresponse["Headers"]["Pragma"] = "no-cache" HTTPresponse["Headers"]["Expires"] = "0" HTTPresponse["Headers"]["Accept"] = "*/*" if command == "help": _response = prepResponseMessage(self, setupHeadersResponse()) _data = {} for x in REST_COMMANDS: _data[x] = {} _data[x]["Verbs"] = [] for y in REST_COMMANDS[x]["Verbs"]: _data[x]["Verbs"].append(y) _response["Data"] = json.dumps(_data) HTTPresponse = _response elif version == "1" and REST_COMMANDS[command]["function"]: HTTPresponse = REST_COMMANDS[command]["function"](verb, data, parameters) elif version == "2" and REST_COMMANDS[command]["functionv2"]: HTTPresponse = REST_COMMANDS[command]["functionv2"](verb, data, parameters) self.logging("Debug", "==> return HTTPresponse: %s" % (HTTPresponse)) if HTTPresponse == {} or HTTPresponse is None: # We reach here due to failure ! HTTPresponse = prepResponseMessage(self, setupHeadersResponse()) HTTPresponse["Status"] = "400 BAD REQUEST" HTTPresponse["Data"] = "Unknown REST command: %s" % command HTTPresponse["Headers"]["Content-Type"] = "text/plain; charset=utf-8" self.logging( "Debug", "==> sending HTTPresponse: %s to %s" % (HTTPresponse, Connection)) self.sendResponse(Connection, HTTPresponse)
def rest_zGroup(self, verb, data, parameters): _response = prepResponseMessage(self, setupHeadersResponse()) self.logging("Debug", "rest_zGroup - ListOfGroups = %s" % str(self.groupmgt)) if verb == "GET": if self.groupmgt is None: return _response ListOfGroups = self.groupmgt.ListOfGroups if ListOfGroups is None or len(ListOfGroups) == 0: return _response if len(parameters) == 0: zgroup_lst = [] for itergrp in ListOfGroups: self.logging("Debug", "Process Group: %s" % itergrp) zgroup = {} zgroup["_GroupId"] = itergrp zgroup["GroupName"] = ListOfGroups[itergrp]["Name"] zgroup["Devices"] = [] for itemDevice in ListOfGroups[itergrp]["Devices"]: if len(itemDevice) == 2: dev, ep = itemDevice ieee = self.ListOfDevices[dev]["IEEE"] elif len(itemDevice) == 3: dev, ep, ieee = itemDevice self.logging("Debug", "--> add %s %s %s" % (dev, ep, ieee)) _dev = {} _dev["_NwkId"] = dev _dev["Ep"] = ep _dev["IEEE"] = ieee zgroup["Devices"].append(_dev) if "WidgetStyle" in ListOfGroups[itergrp]: zgroup["WidgetStyle"] = ListOfGroups[itergrp][ "WidgetStyle"] if "Cluster" in ListOfGroups[itergrp]: zgroup["Cluster"] = ListOfGroups[itergrp]["Cluster"] # Let's check if we don't have an Ikea Remote in the group if "Tradfri Remote" in ListOfGroups[itergrp]: self.logging("Debug", "--> add Ikea Tradfri Remote") _dev = {} _dev["_NwkId"] = ListOfGroups[itergrp]["Tradfri Remote"][ "Device Addr"] _dev["Unit"] = ListOfGroups[itergrp]["Tradfri Remote"][ "Device Id"] _dev["Ep"] = ListOfGroups[itergrp]["Tradfri Remote"]["Ep"] _dev["Color Mode"] = ListOfGroups[itergrp][ "Tradfri Remote"]["Color Mode"] zgroup["Devices"].append(_dev) zgroup_lst.append(zgroup) self.logging("Debug", "zGroup: %s" % zgroup_lst) _response["Data"] = json.dumps(zgroup_lst, sort_keys=True) elif len(parameters) == 1: if parameters[0] in ListOfGroups: itemGroup = parameters[0] zgroup = {} zgroup["_GroupId"] = itemGroup zgroup["GroupName"] = ListOfGroups[itemGroup]["Name"] zgroup["Devices"] = {} for itemDevice in ListOfGroups[itemGroup]["Devices"]: if len(itemDevice) == 2: dev, ep = itemDevice _ieee = self.ListOfDevices[dev]["IEEE"] elif len(itemDevice) == 3: dev, ep, _ieee = itemDevice self.logging("Debug", "--> add %s %s" % (dev, ep)) zgroup["Devices"][dev] = ep # Let's check if we don't have an Ikea Remote in the group if "Tradfri Remote" in ListOfGroups[itemGroup]: self.logging("Log", "--> add Ikea Tradfri Remote") _dev = {} _dev["_NwkId"] = ListOfGroups[itemGroup]["Tradfri Remote"][ "Device Addr"] _dev["Ep"] = "01" # zgroup["Devices"].append(_dev) This looks very bad. Don't know where it is coming from zgroup["Devices"][ListOfGroups[itemGroup]["Tradfri Remote"] ["Device Addr"]] = "01" _response["Data"] = json.dumps(zgroup, sort_keys=True) return _response if verb == "PUT": _response["Data"] = None if not self.groupmgt: Domoticz.Error("Looks like Group Management is not enabled") _response["Data"] = {} return _response ListOfGroups = self.groupmgt.ListOfGroups grp_lst = [] if len(parameters) == 0: data = data.decode("utf8") _response["Data"] = {} self.groupmgt.process_web_request(json.loads(data)) # end if len() # end if Verb= return _response
def rest_netTopologie(self, verb, data, parameters): _response = prepResponseMessage(self, setupHeadersResponse()) _filename = self.pluginconf.pluginConf[ "pluginReports"] + "NetworkTopology-v3-" + "%02d" % self.hardwareID + ".json" self.logging("Debug", "Filename: %s" % _filename) if not os.path.isfile(_filename): _response["Data"] = json.dumps({}, sort_keys=True) return _response # Read the file, as we have anyway to do it _topo = {} # All Topo reports _timestamps_lst = [] # Just the list of Timestamps with open(_filename, "rt") as handle: for line in handle: if line[0] != "{" and line[-1] != "}": continue entry = json.loads(line) for _ts in entry: _timestamps_lst.append(int(_ts)) _topo[_ts] = [ ] # List of Father -> Child relation for one TimeStamp reportLQI = entry[_ts] _topo[_ts] = extract_report(self, reportLQI) if verb == "DELETE": if len(parameters) == 0: os.remove(_filename) action = {} action["Name"] = "File-Removed" action["FileName"] = _filename _response["Data"] = json.dumps(action, sort_keys=True) elif len(parameters) == 1: timestamp = parameters[0] if timestamp in _topo: self.logging( "Debug", "Removing Report: %s from %s records" % (timestamp, len(_topo))) with open(_filename, "r+") as handle: d = handle.readlines() handle.seek(0) for line in d: if line[0] != "{" and line[-1] != "}": handle.write(line) continue entry = json.loads(line) entry_ts = entry.keys() if len(entry_ts) == 1: if timestamp in entry_ts: self.logging( "Debug", "--------> Skiping %s" % timestamp) continue else: continue handle.write(line) handle.truncate() action = {} action["Name"] = "Report %s removed" % timestamp _response["Data"] = json.dumps(action, sort_keys=True) else: Domoticz.Error("Removing Topo Report %s not found" % timestamp) _response["Data"] = json.dumps([], sort_keys=True) return _response if verb == "GET": if len(parameters) == 0: # Send list of Time Stamps _response["Data"] = json.dumps(_timestamps_lst, sort_keys=True) elif len(parameters) == 1: timestamp = parameters[0] if timestamp in _topo: self.logging("Debug", "Topologie sent: %s" % _topo[timestamp]) _response["Data"] = json.dumps(_topo[timestamp], sort_keys=True) else: _response["Data"] = json.dumps([], sort_keys=True) return _response
def rest_zGroup_lst_avlble_dev(self, verb, data, parameters): _response = prepResponseMessage(self, setupHeadersResponse()) if verb != "GET": return _response device_lst = [] _device = {} _widget = {} _device["_NwkId"] = "0000" _device["WidgetList"] = [] _widget["_ID"] = "" _widget["Name"] = "" _widget["IEEE"] = "0000000000000000" _widget["Ep"] = "01" _widget["ZDeviceName"] = "Zigate (Coordinator)" if self.zigatedata and "IEEE" in self.zigatedata: _widget["IEEE"] = self.zigatedata["IEEE"] _device["_NwkId"] = self.zigatedata["Short Address"] _device["WidgetList"].append(_widget) device_lst.append(_device) for x in self.ListOfDevices: if x == "0000": continue if "MacCapa" not in self.ListOfDevices[x]: self.logging( "Debug", "rest_zGroup_lst_avlble_dev - no 'MacCapa' info found for %s!!!!" % x) continue IkeaRemote = False if self.pluginconf.pluginConf["GroupOnBattery"] or ( "Type" in self.ListOfDevices[x] and self.ListOfDevices[x]["Type"] == "Ikea_Round_5b"): IkeaRemote = True if not (self.ListOfDevices[x]["MacCapa"] == "8e" or IkeaRemote): self.logging( "Debug", "rest_zGroup_lst_avlble_dev - %s not a Main Powered device. " % x) continue if "Ep" in self.ListOfDevices[ x] and "ZDeviceName" in self.ListOfDevices[ x] and "IEEE" in self.ListOfDevices[x]: _device = {"_NwkId": x, "WidgetList": []} for ep in self.ListOfDevices[x]["Ep"]: if "Type" in self.ListOfDevices[x] and self.ListOfDevices[x][ "Type"] == "Ikea_Round_5b" and ep == "01" and "ClusterType" in self.ListOfDevices[ x]["Ep"]["01"]: widgetID = "" for iterDev in self.ListOfDevices[x]["Ep"]["01"][ "ClusterType"]: if self.ListOfDevices[x]["Ep"]["01"]["ClusterType"][ iterDev] == "Ikea_Round_5b": widgetID = iterDev for widget in self.Devices: if self.Devices[widget].ID == int(widgetID): _widget = { "_ID": self.Devices[widget].ID, "Name": self.Devices[widget].Name, "IEEE": self.ListOfDevices[x]["IEEE"], "Ep": ep, "ZDeviceName": self.ListOfDevices[x]["ZDeviceName"], } if _widget not in _device["WidgetList"]: _device["WidgetList"].append(_widget) break if _device not in device_lst: device_lst.append(_device) continue # Next Ep if not ("0004" in self.ListOfDevices[x]["Ep"][ep] or "ClusterType" in self.ListOfDevices[x]["Ep"][ep] and "ClusterType" in self.ListOfDevices[x] or "0006" in self.ListOfDevices[x]["Ep"][ep] or "0008" in self.ListOfDevices[x]["Ep"][ep] or "0102" in self.ListOfDevices[x]["Ep"][ep]): continue if "ClusterType" in self.ListOfDevices[x]["Ep"][ep]: clusterType = self.ListOfDevices[x]["Ep"][ep][ "ClusterType"] for widgetID in clusterType: if clusterType[widgetID] not in ( "LvlControl", "Switch", "Plug", "SwitchAQ2", "DSwitch", "Button", "DButton", "LivoloSWL", "LivoloSWR", "ColorControlRGB", "ColorControlWW", "ColorControlRGBWW", "ColorControlFull", "ColorControl", "VenetianInverted", "Venetian", "WindowCovering", ): continue for widget in self.Devices: if self.Devices[widget].ID == int(widgetID): _widget = {} _widget["_ID"] = self.Devices[widget].ID _widget["Name"] = self.Devices[widget].Name _widget["IEEE"] = self.ListOfDevices[x]["IEEE"] _widget["Ep"] = ep _widget["ZDeviceName"] = self.ListOfDevices[x][ "ZDeviceName"] if _widget not in _device["WidgetList"]: _device["WidgetList"].append(_widget) elif "ClusterType" in self.ListOfDevices[x]: clusterType = self.ListOfDevices[x]["ClusterType"] for widgetID in clusterType: if clusterType[widgetID] not in ( "LvlControl", "Switch", "Plug", "SwitchAQ2", "DSwitch", "Button", "DButton", "LivoloSWL", "LivoloSWR", "ColorControlRGB", "ColorControlWW", "ColorControlRGBWW", "ColorControlFull", "ColorControl", "VenetianInverted", "Venetian", "WindowCovering", ): continue for widget in self.Devices: if self.Devices[widget].ID == int(widgetID): _widget = {} _widget["_ID"] = self.Devices[widget].ID _widget["Name"] = self.Devices[widget].Name _widget["IEEE"] = self.ListOfDevices[x]["IEEE"] _widget["Ep"] = ep _widget["ZDeviceName"] = self.ListOfDevices[x][ "ZDeviceName"] if _widget not in _device["WidgetList"]: _device["WidgetList"].append(_widget) if _device not in device_lst: device_lst.append(_device) self.logging("Debug", "Response: %s" % device_lst) _response["Data"] = json.dumps(device_lst, sort_keys=True) return _response