def convert(self, _, body): try: data = body["data"]["value"] self.dict_result["deviceName"] = TBUtility.get_value( self.__config.get("deviceNameJsonExpression"), body, expression_instead_none=True) self.dict_result["deviceType"] = TBUtility.get_value( self.__config.get("deviceTypeJsonExpression"), body, expression_instead_none=True) self.dict_result["attributes"] = [] self.dict_result["telemetry"] = [] converted_bytes = bytearray.fromhex(data) if self.__config.get("extension-config") is not None: for telemetry_key in self.__config["extension-config"]: value = None byteorder = telemetry_key.get("byteorder", "big").lower() signed = telemetry_key.get("signed", True) if telemetry_key.get("byteAddress") is None: interest_bytes = converted_bytes[ telemetry_key["fromByte"]:telemetry_key["toByte"]] if telemetry_key["type"] == "float": value = struct.unpack( ">f" if byteorder == "big" else "<f", interest_bytes) value = value[0] if isinstance(value, list) else None if telemetry_key["type"] == "int": value = int.from_bytes(interest_bytes, byteorder=byteorder, signed=signed) else: interest_byte = converted_bytes[ telemetry_key["byteAddress"]] bits = "{0:{fill}8b}".format(interest_byte, fill='0') bits = bits if byteorder == "big" else bits[::-1] value = int( bits[::-1][telemetry_key.get("fromBit"): telemetry_key.get("toBit")][::-1], 2) if value is not None: value = value * telemetry_key.get("multiplier", 1) telemetry_to_send = { telemetry_key["key"]: value } # creating telemetry data for sending into Thingsboard # current_byte_position += self.__config["extension-config"][telemetry_key] self.dict_result["telemetry"].append( telemetry_to_send ) # adding data to telemetry array else: self.dict_result["telemetry"] = { "data": int(body, 0) } # if no specific configuration in config file - just send data which received return self.dict_result except Exception as e: log.error( 'Error in converter, for config: \n%s\n and message: \n%s\n', dumps(self.__config), body) log.exception(e)
def convert(self, config, data): device_name = self.__config["deviceName"] result = { "deviceName": device_name, "deviceType": self.__config.get("deviceType", "OPC-UA Device"), "attributes": [], "telemetry": [], } current_variable = config.split('.') try: for attr in self.__config["attributes"]: path = TBUtility.get_value(attr["path"], get_tag=True) if path == '.'.join(current_variable[-len(path.split('.')):]): result["attributes"].append({ attr["key"]: attr["path"].replace("${" + path + "}", str(data)) }) for ts in self.__config["timeseries"]: path = TBUtility.get_value(ts["path"], get_tag=True) if path == '.'.join(current_variable[-len(path.split('.')):]): result["telemetry"].append({ ts["key"]: ts["path"].replace("${" + path + "}", str(data)) }) return result except Exception as e: log.exception(e)
def convert(self, config, data): if isinstance(data, (bytes, str)): data = loads(data) dict_result = {"deviceName": None, "deviceType": None, "attributes": [], "telemetry": []} try: if self.__config.get("deviceNameJsonExpression") is not None: dict_result["deviceName"] = TBUtility.get_value(self.__config.get("deviceNameJsonExpression"), data, expression_instead_none=True) else: log.error("The expression \"%s\" for looking \"deviceName\" not found in config %s", dumps(self.__config)) if self.__config.get("deviceTypeJsonExpression") is not None: dict_result["deviceType"] = TBUtility.get_value(self.__config.get("deviceTypeJsonExpression"), data, expression_instead_none=True) else: log.error("The expression for looking \"deviceType\" not found in config %s", dumps(self.__config)) except Exception as e: log.exception(e) try: for datatype in self.__datatypes: current_datatype = self.__datatypes[datatype] for datatype_object_config in self.__config["converter"].get(datatype, []): datatype_object_config_key = TBUtility.get_value(datatype_object_config["key"], data, datatype_object_config["type"], expression_instead_none=True) datatype_object_config_value = TBUtility.get_value(datatype_object_config["value"], data, datatype_object_config["type"]) if datatype_object_config_key is not None and datatype_object_config_value is not None: dict_result[current_datatype].append({datatype_object_config_key: datatype_object_config_value}) else: error_string = "Cannot find the key in the input data" if datatype_object_config_key is None else "Cannot find the value from the input data" log.error(error_string) except Exception as e: log.exception(e) return dict_result
def __search_general_info(self, device): result = {"deviceName": None, "deviceType": None, "deviceNode": None} result["deviceNode"] = self.__search_node( self.__opcua_nodes["root"], TBUtility.get_value(device["deviceNodePattern"], get_tag=True)) if result["deviceNode"] is not None: name_pattern_config = device["deviceNamePattern"] name_expression = TBUtility.get_value(name_pattern_config, get_tag=True) if "${" in name_pattern_config and "}" in name_pattern_config: device_name_node = self.__search_node( self.__opcua_nodes["root"], name_expression) if device_name_node is not None: device_name_from_node = device_name_node.get_value() full_device_name = name_pattern_config.replace( "${" + name_expression + "}", device_name_from_node).replace(name_expression, device_name_from_node) else: log.error("Device name node not found with expression: %s", name_expression) return else: full_device_name = name_expression result["deviceName"] = full_device_name log.debug("Device name: %s", full_device_name) if device.get("deviceTypePattern"): device_type_expression = TBUtility.get_value( device["deviceTypePattern"], get_tag=True) if "${" in device_type_expression and "}" in device_type_expression: device_type_node = self.__search_node( self.__opcua_nodes["root"], device_type_expression) if device_type_node is not None: device_type = device_type_node.get_value() full_device_type = device_type_expression.replace( "${" + device_type_expression + "}", device_type).replace(device_type_expression, device_type) else: log.error( "Device type node not found with expression: %s", device_type_expression) full_device_type = "default" else: full_device_type = device_type_expression result["deviceType"] = full_device_type log.debug("Device type: %s", full_device_type) else: result["deviceType"] = "default" return result else: log.error( "Device node not found with expression: %s", TBUtility.get_value(device["deviceNodePattern"], get_tag=True))
def __search_general_info(self, device): result = [] match_devices = [] self.__search_node(self.__opcua_nodes["root"], TBUtility.get_value(device["deviceNodePattern"], get_tag=True), result=match_devices) for device_node in match_devices: if device_node is not None: result_device_dict = {"deviceName": None, "deviceType": None, "deviceNode": device_node, "configuration": deepcopy(device)} name_pattern_config = device["deviceNamePattern"] name_expression = TBUtility.get_value(name_pattern_config, get_tag=True) if "${" in name_pattern_config and "}" in name_pattern_config: log.debug("Looking for device name") name_path = self._check_path(name_expression, device_node) device_name_node = [] self.__search_node(device_node, name_path, result=device_name_node) device_name_node = device_name_node[0] if device_name_node is not None: device_name_from_node = device_name_node.get_value() full_device_name = name_pattern_config.replace("${" + name_expression + "}", str(device_name_from_node)).replace( name_expression, str(device_name_from_node)) else: log.error("Device name node not found with expression: %s", name_expression) return None else: full_device_name = name_expression result_device_dict["deviceName"] = full_device_name log.debug("Device name: %s", full_device_name) if device.get("deviceTypePattern"): device_type_expression = TBUtility.get_value(device["deviceTypePattern"], get_tag=True) if "${" in device_type_expression and "}" in device_type_expression: type_path = self._check_path(device_type_expression, device_node) device_type_node = [] self.__search_node(device_node, type_path, result=device_type_node) device_type_node = device_type_node[0] if device_type_node is not None: device_type = device_type_node.get_value() full_device_type = device_type_expression.replace("${" + device_type_expression + "}", device_type).replace(device_type_expression, device_type) else: log.error("Device type node not found with expression: %s", device_type_expression) full_device_type = "default" else: full_device_type = device_type_expression result_device_dict["deviceType"] = full_device_type log.debug("Device type: %s", full_device_type) else: result_device_dict["deviceType"] = "default" result.append(result_device_dict) else: log.error("Device node not found with expression: %s", TBUtility.get_value(device["deviceNodePattern"], get_tag=True)) return result
def convert(self, config, data): device_name = self.__config["deviceName"] result = { "deviceName": device_name, "deviceType": self.__config.get("deviceType", "OPC-UA Device"), "attributes": [], "telemetry": [], } try: information_types = { "attributes": "attributes", "timeseries": "telemetry" } for information_type in information_types: for information in self.__config[information_type]: path = TBUtility.get_value(information["path"], get_tag=True) if isinstance(config, tuple): config_information = config[0].replace('\\\\', '\\') if path == config[0].replace('\\\\', '\\') or fullmatch(path, config[0].replace('\\\\', '\\')) else \ config[1].replace('\\\\', '\\') else: config_information = config.replace('\\\\', '\\') if path == config_information or fullmatch( path, config_information) or path.replace( '\\\\', '\\') == config_information: result[information_types[information_type]].append({ information["key"]: information["path"].replace( "${" + path + "}", str(data)) }) return result except Exception as e: log.exception(e)
def add_device(self, data): if self.__devices_address_name.get(data["address"]) is None: for device in self.__config_devices: if device["address"] == data["address"]: try: config_address = Address(device["address"]) device_name_tag = TBUtility.get_value(device["deviceName"], get_tag=True) device_name = device["deviceName"].replace("${" + device_name_tag + "}", data.pop("name")) device_information = { **data, **self.__get_requests_configs(device), "type": device["deviceType"], "config": device, "attributes": device.get("attributes", []), "telemetry": device.get("timeseries", []), "poll_period": device.get("pollPeriod", 5000), "deviceName": device_name, } if config_address == data["address"] or \ (config_address, GlobalBroadcast) or \ (isinstance(config_address, LocalBroadcast) and isinstance(device["address"], LocalStation)) or \ (isinstance(config_address, (LocalStation, RemoteStation)) and isinstance( data["address"], ( LocalStation, RemoteStation))): self.__devices_address_name[data["address"]] = device_information["deviceName"] self.__devices.append(device_information) log.debug(data["address"].addrType) except Exception as e: log.exception(e)
def __search_tags(self, node, recursion_level, sub=None): try: for childId in node.get_children(): ch = self.client.get_node(childId) current_var_path = '.'.join(x.split(":")[1] for x in ch.get_path(20000, True)) if self.__interest_nodes: if ch.get_node_class() == ua.NodeClass.Object: for interest_node in self.__interest_nodes: for int_node in interest_node: if re.search(int_node.split('\\.')[recursion_level-2], ch.get_display_name().Text): try: methods = ch.get_methods() for method in methods: self.__available_object_resources[interest_node[int_node]["deviceName"]]["methods"].append({method.get_display_name().Text: method, "node": ch}) except Exception as e: log.exception(e) self.__search_tags(ch, recursion_level+1, sub) elif ch.get_node_class() == ua.NodeClass.Variable: try: for interest_node in self.__interest_nodes: for int_node in interest_node: if interest_node[int_node].get("attributes_updates"): try: for attribute_update in interest_node[int_node]["attributes_updates"]: if attribute_update["attributeOnDevice"] == ch.get_display_name().Text: self.__available_object_resources[interest_node[int_node]["deviceName"]]['variables'].append({attribute_update["attributeOnThingsBoard"]: ch, }) except Exception as e: log.exception(e) if re.search(int_node.replace('$', ''), current_var_path): tags = [] if interest_node[int_node].get("attributes"): tags.extend(interest_node[int_node]["attributes"]) if interest_node[int_node].get("timeseries"): tags.extend(interest_node[int_node]["timeseries"]) for tag in tags: target = TBUtility.get_value(tag["path"], get_tag=True) if ch.get_display_name().Text == target: sub.subscribe_data_change(ch) if interest_node[int_node].get("uplink_converter") is None: if interest_node[int_node].get('converter') is None: converter = OpcUaUplinkConverter(interest_node[int_node]) else: converter = TBUtility.check_and_import(self.__connector_type, interest_node[int_node]['converter']) interest_node[int_node]["uplink_converter"] = converter else: converter = interest_node[int_node]["uplink_converter"] self.subscribed[ch] = {"converter": converter, "path": current_var_path} except BadWaitingForInitialData: pass elif not self.__interest_nodes: log.error("Nodes in mapping not found, check your settings.") except Exception as e: log.exception(e)
def __search_nodes_and_subscribe(self, device_info): sub_nodes = [] information_types = {"attributes": "attributes", "timeseries": "telemetry"} for information_type in information_types: for information in device_info["configuration"][information_type]: information_key = information["key"] config_path = TBUtility.get_value(information["path"], get_tag=True) information_path = self._check_path(config_path, device_info["deviceNode"]) information["path"] = '${%s}' % information_path information_nodes = [] self.__search_node(device_info["deviceNode"], information_path, result=information_nodes) for information_node in information_nodes: if information_node is not None: try: information_value = information_node.get_value() except: log.error("Err get_value: %s", str(information_node)) continue log.debug("Node for %s \"%s\" with path: %s - FOUND! Current values is: %s", information_type, information_key, information_path, str(information_value)) if device_info.get("uplink_converter") is None: configuration = {**device_info["configuration"], "deviceName": device_info["deviceName"], "deviceType": device_info["deviceType"]} if device_info["configuration"].get('converter') is None: converter = OpcUaUplinkConverter(configuration) else: converter = TBModuleLoader.import_module(self._connector_type, configuration) device_info["uplink_converter"] = converter else: converter = device_info["uplink_converter"] self.subscribed[information_node] = {"converter": converter, "path": information_path, "config_path": config_path} if not device_info.get(information_types[information_type]): device_info[information_types[information_type]] = [] converted_data = converter.convert((config_path, information_path), information_value) self.statistics['MessagesReceived'] = self.statistics['MessagesReceived'] + 1 self.data_to_send.append(converted_data) self.statistics['MessagesSent'] = self.statistics['MessagesSent'] + 1 log.debug("Data to ThingsBoard: %s", converted_data) if not self.__server_conf.get("disableSubscriptions", False): sub_nodes.append(information_node) else: log.error("Node for %s \"%s\" with path %s - NOT FOUND!", information_type, information_key, information_path) if not self.__server_conf.get("disableSubscriptions", False): if self.__sub is None: self.__sub = self.client.create_subscription(self.__server_conf.get("subCheckPeriodInMillis", 500), self.__sub_handler) if sub_nodes: self.__sub.subscribe_data_change(sub_nodes) log.debug("Added subscription to nodes: %s", str(sub_nodes))
def __search_nodes_and_subscribe(self, device_configuration, device_info): device_configuration.update(**device_info) information_types = { "attributes": "attributes", "timeseries": "telemetry" } for information_type in information_types: for information in device_configuration[information_type]: information_key = information["key"] config_path = TBUtility.get_value(information["path"], get_tag=True) information_path = self._check_path(config_path, device_info["deviceNode"]) information["path"] = '${%s}' % information_path information_node = self.__search_node( device_info["deviceNode"], information_path) if information_node is not None: information_value = information_node.get_value() log.debug( "Node for %s \"%s\" with path: %s - FOUND! Current values is: %s", information_type, information_key, information_path, str(information_value)) if device_configuration.get("uplink_converter") is None: if device_configuration.get('converter') is None: converter = OpcUaUplinkConverter( device_configuration) else: converter = TBUtility.check_and_import( self.__connector_type, device_configuration['converter']) device_configuration["uplink_converter"] = converter else: converter = device_configuration["uplink_converter"] self.subscribed[information_node] = { "converter": converter, "path": information_path, "config_path": config_path } if not device_info.get( information_types[information_type]): device_info[information_types[information_type]] = [] converted_data = converter.convert( (config_path, information_path), information_value) self.statistics['MessagesReceived'] += 1 self.data_to_send.append(converted_data) self.statistics['MessagesSent'] += 1 self.__sub.subscribe_data_change(information_node) log.debug("Data to ThingsBoard: %s", converted_data) else: log.error("Node for %s \"%s\" with path %s - NOT FOUND!", information_type, information_key, information_path)
def convert(self, config, data): dict_result = {"deviceName": None, "deviceType": None,"attributes": [], "telemetry": []} try: if self.__config.get("deviceNameJsonExpression") is not None: dict_result["deviceName"] = TBUtility.get_value(self.__config.get("deviceNameJsonExpression"), data) elif self.__config.get("deviceNameTopicExpression") is not None: search_result = search(self.__config["deviceNameTopicExpression"], config) if search_result is not None: dict_result["deviceName"] = search_result.group(0) else: log.debug("Regular expression result is None. deviceNameTopicExpression parameter will be interpreted as a deviceName\n Topic: %s\nRegex: %s", config, self.__config.get("deviceNameTopicExpression")) dict_result["deviceName"] = self.__config.get("deviceNameTopicExpression") else: log.error("The expression for looking \"deviceName\" not found in config %s", dumps(self.__config)) if self.__config.get("deviceTypeJsonExpression") is not None: dict_result["deviceType"] = TBUtility.get_value(self.__config.get("deviceTypeJsonExpression"), data) elif self.__config.get("deviceTypeTopicExpression") is not None: search_result = search(self.__config["deviceTypeTopicExpression"], config) if search_result is not None: dict_result["deviceType"] = search_result.group(0) else: log.debug("Regular expression result is None. deviceTypeTopicExpression will be interpreted as a deviceType\n Topic: %s\nRegex: %s", config, self.__config.get("deviceTypeTopicExpression")) dict_result["deviceType"] = self.__config.get("deviceTypeTopicExpression") else: log.error("The expression for looking \"deviceType\" not found in config %s", dumps(self.__config)) dict_result["attributes"] = [] dict_result["telemetry"] = [] except Exception as e: log.error('Error in converter, for config: \n%s\n and message: \n%s\n', dumps(self.__config), data) log.exception(e) try: if self.__config.get("attributes"): for attribute in self.__config.get("attributes"): attribute_value = TBUtility.get_value(attribute["value"], data, attribute["type"]) tag = TBUtility.get_value(attribute["value"], data, attribute["type"], get_tag=True) if attribute_value is not None and data.get(tag) is not None and attribute_value != attribute["value"]: dict_result["attributes"].append({attribute["key"]: attribute_value}) else: log.debug("%s key not found in message: %s", attribute["value"].replace("${", '"').replace("}", '"'), data) except Exception as e: log.error('Error in converter, for config: \n%s\n and message: \n%s\n', dumps(self.__config), data) log.exception(e) try: if self.__config.get("timeseries"): for ts in self.__config.get("timeseries"): ts_value = TBUtility.get_value(ts["value"], data, ts["type"]) tag = TBUtility.get_value(ts["value"], data, ts["type"], get_tag=True) if ts_value is not None and data.get(tag) is not None and ts_value != ts["value"]: if data.get('ts') is not None or data.get('timestamp') is not None: dict_result["telemetry"].append({"ts": data.get('ts', data.get('timestamp', int(time()))), 'values': {ts['key']: ts_value}}) else: dict_result["telemetry"].append({ts["key"]: ts_value}) else: log.debug("%s key not found in message: %s", ts["value"].replace("${", '"').replace("}", '"'), data) except Exception as e: log.error('Error in converter, for config: \n%s\n and message: \n%s\n', dumps(self.__config), data) log.exception(e) return dict_result
def convert(self, config, data): datatypes = {"attributes": "attributes", "timeseries": "telemetry"} dict_result = {"deviceName": None, "deviceType": None, "attributes": [], "telemetry": []} try: if self.__config.get("deviceNameJsonExpression") is not None: dict_result["deviceName"] = TBUtility.get_value(self.__config.get("deviceNameJsonExpression"), data, expression_instead_none=True) elif self.__config.get("deviceNameTopicExpression") is not None: search_result = search(self.__config["deviceNameTopicExpression"], config) if search_result is not None: dict_result["deviceName"] = search_result.group(0) else: log.debug("Regular expression result is None. deviceNameTopicExpression parameter will be interpreted as a deviceName\n Topic: %s\nRegex: %s", config, self.__config.get("deviceNameTopicExpression")) dict_result["deviceName"] = self.__config.get("deviceNameTopicExpression") else: log.error("The expression for looking \"deviceName\" not found in config %s", dumps(self.__config)) if self.__config.get("deviceTypeJsonExpression") is not None: dict_result["deviceType"] = TBUtility.get_value(self.__config.get("deviceTypeJsonExpression"), data, expression_instead_none=True) elif self.__config.get("deviceTypeTopicExpression") is not None: search_result = search(self.__config["deviceTypeTopicExpression"], config) if search_result is not None: dict_result["deviceType"] = search_result.group(0) else: log.debug("Regular expression result is None. deviceTypeTopicExpression will be interpreted as a deviceType\n Topic: %s\nRegex: %s", config, self.__config.get("deviceTypeTopicExpression")) dict_result["deviceType"] = self.__config.get("deviceTypeTopicExpression") else: log.error("The expression for looking \"deviceType\" not found in config %s", dumps(self.__config)) except Exception as e: log.error('Error in converter, for config: \n%s\n and message: \n%s\n', dumps(self.__config), data) log.exception(e) try: for datatype in datatypes: dict_result[datatypes[datatype]] = [] for datatype_config in self.__config.get(datatype, []): value = TBUtility.get_value(datatype_config["value"], data, datatype_config["type"], expression_instead_none=True) value_tag = TBUtility.get_value(datatype_config["value"], data, datatype_config["type"], get_tag=True) key = TBUtility.get_value(datatype_config["key"], data, datatype_config["type"], expression_instead_none=True) key_tag = TBUtility.get_value(datatype_config["key"], data, get_tag=True) if ("${" not in str(value) and "}" not in str(value)) \ and ("${" not in str(key) and "}" not in str(key)): is_valid_key = isinstance(key, str) and "${" in datatype_config["key"] and "}" in datatype_config["key"] is_valid_value = isinstance(value, str) and "${" in datatype_config["value"] and "}" in datatype_config["value"] full_key = datatype_config["key"].replace('${' + key_tag + '}', key) if is_valid_key else key_tag full_value = datatype_config["value"].replace('${' + value_tag + '}', value) if is_valid_value else value if datatype == 'timeseries' and (data.get("ts") is not None or data.get("timestamp") is not None): dict_result[datatypes[datatype]].append({"ts": data.get('ts', data.get('timestamp', int(time()))), 'values': {full_key: full_value}}) else: dict_result[datatypes[datatype]].append({full_key: full_value}) except Exception as e: log.error('Error in converter, for config: \n%s\n and message: \n%s\n', dumps(self.__config), str(data)) log.exception(e) return dict_result
def __search_name(self, node, recursion_level): try: for childId in node.get_children(): ch = self.client.get_node(childId) current_var_path = '.'.join(x.split(":")[1] for x in ch.get_path(20000, True)) if self.__interest_nodes: if ch.get_node_class() == ua.NodeClass.Object: for interest_node in self.__interest_nodes: for int_node in interest_node: if re.search(int_node.split('\\.')[recursion_level-2], ch.get_display_name().Text): self.__search_name(ch, recursion_level+1) elif ch.get_node_class() == ua.NodeClass.Variable: try: for interest_node in self.__interest_nodes: for int_node in interest_node: if interest_node[int_node].get("deviceName") is None: try: name_pattern = TBUtility.get_value(interest_node[int_node]["deviceNamePattern"], get_tag=True) device_name_node = re.search(name_pattern.split('.')[-1], current_var_path) if device_name_node is not None: device_name = ch.get_value() full_device_name = interest_node[int_node]["deviceNamePattern"].replace("${"+name_pattern+"}", device_name) interest_node[int_node]["deviceName"] = full_device_name if self.__available_object_resources.get(full_device_name) is None: self.__available_object_resources[full_device_name] = {'methods': [], 'variables': []} if not self.__gateway.get_devices().get(full_device_name): self.__gateway.add_device(full_device_name, {"connector": None}) self.__gateway.update_device(full_device_name, "connector", self) except Exception as e: log.exception(e) except BadWaitingForInitialData: pass elif not self.__interest_nodes: log.error("Nodes in mapping not found, check your settings.") except Exception as e: log.exception(e)
def convert(self, config, data): datatypes = {"attributes": "attributes", "timeseries": "telemetry"} dict_result = {"deviceName": None, "deviceType": None, "attributes": [], "telemetry": []} try: if self.__config.get("deviceNameExpression") is not None: dict_result["deviceName"] = TBUtility.get_value(self.__config.get("deviceNameExpression"), data, expression_instead_none=True) else: log.error("The expression for looking \"deviceName\" not found in config %s", dumps(self.__config)) if self.__config.get("deviceTypeExpression") is not None: dict_result["deviceType"] = TBUtility.get_value(self.__config.get("deviceTypeExpression"), data, expression_instead_none=True) else: log.error("The expression for looking \"deviceType\" not found in config %s", dumps(self.__config)) except Exception as e: log.error('Error in converter, for config: \n%s\n and message: \n%s\n', dumps(self.__config), data) log.exception(e) try: for datatype in datatypes: dict_result[datatypes[datatype]] = [] for datatype_config in self.__config.get(datatype, []): value = TBUtility.get_value(datatype_config["value"], data, datatype_config["type"], expression_instead_none=True) value_tag = TBUtility.get_value(datatype_config["value"], data, datatype_config["type"], get_tag=True) key = TBUtility.get_value(datatype_config["key"], data, datatype_config["type"], expression_instead_none=True) key_tag = TBUtility.get_value(datatype_config["key"], data, get_tag=True) if ("${" not in str(value) and "}" not in str(value)) \ and ("${" not in str(key) and "}" not in str(key)): is_string_key = isinstance(value, str) is_string_value = isinstance(value, str) full_key = datatype_config["key"].replace('${' + key_tag + '}', key) if is_string_key else key full_value = datatype_config["value"].replace('${' + value_tag + '}', value) if is_string_value else value if datatype == 'timeseries' and (data.get("ts") is not None or data.get("timestamp") is not None): dict_result[datatypes[datatype]].append({"ts": data.get('ts', data.get('timestamp', int(time()))), 'values': {full_key: full_value}}) else: dict_result[datatypes[datatype]].append({full_key: full_value}) except Exception as e: log.error('Error in converter, for config: \n%s\n and message: \n%s\n', dumps(self.__config), str(data)) log.exception(e) return dict_result
def convert(self, config, data): if type(data) in (bytes, str): data = loads(data) dict_result = { "deviceName": None, "deviceType": None, "attributes": [], "telemetry": [] } try: if self.__config.get("deviceNameJsonExpression") is not None: dict_result["deviceName"] = TBUtility.get_value( self.__config.get("deviceNameJsonExpression"), data, expression_instead_none=True) else: log.error( "The expression for looking \"deviceName\" not found in config %s", dumps(self.__config)) if self.__config.get("deviceTypeJsonExpression") is not None: dict_result["deviceType"] = TBUtility.get_value( self.__config.get("deviceTypeJsonExpression"), data, expression_instead_none=True) else: log.error( "The expression for looking \"deviceType\" not found in config %s", dumps(self.__config)) dict_result["attributes"] = [] dict_result["telemetry"] = [] except Exception as e: log.exception(e) try: if self.__config.get("attributes"): for attribute in self.__config.get("attributes"): attribute_value = TBUtility.get_value( attribute["value"], data, attribute["type"]) if attribute_value is not None: dict_result["attributes"].append( {attribute["key"]: attribute_value}) else: log.debug( "%s key not found in response: %s", attribute["value"].replace("${", '"').replace("}", '"'), data) except Exception as e: log.error( 'Error in converter, for config: \n%s\n and message: \n%s\n', dumps(self.__config), data) log.exception(e) try: if self.__config.get("telemetry"): for ts in self.__config.get("telemetry"): ts_value = TBUtility.get_value(ts["value"], data, ts["type"]) if ts_value is not None: dict_result["telemetry"].append({ts["key"]: ts_value}) else: log.debug( "%s key not found in response: %s", ts["value"].replace("${", '"').replace("}", '"'), data) except Exception as e: log.exception(e) return dict_result
def _on_message(self, client, userdata, message): self.statistics['MessagesReceived'] += 1 content = TBUtility.decode(message) # Check if message topic exists in mappings "i.e., I'm posting telemetry/attributes" --------------------------- topic_handlers = [ regex for regex in self.__mapping_sub_topics if fullmatch(regex, message.topic) ] if topic_handlers: # Note: every topic may be associated to one or more converter. This means that a single MQTT message # may produce more than one message towards ThingsBoard. This also means that I cannot return after # the first successful conversion: I got to use all the available ones. # I will use a flag to understand whether at least one converter succeeded request_handled = False for topic in topic_handlers: available_converters = self.__mapping_sub_topics[topic] for converter in available_converters: try: if isinstance(content, list): for item in content: request_handled = self.put_data_to_convert( converter, message, item) if not request_handled: self.__log.error( 'Cannot find converter for the topic:"%s"! Client: %s, User data: %s', message.topic, str(client), str(userdata)) else: request_handled = self.put_data_to_convert( converter, message, content) except Exception as e: log.exception(e) if not request_handled: self.__log.error( 'Cannot find converter for the topic:"%s"! Client: %s, User data: %s', message.topic, str(client), str(userdata)) # Note: if I'm in this branch, this was for sure a telemetry/attribute push message # => Execution must end here both in case of failure and success return None # Check if message topic exists in connection handlers "i.e., I'm connecting a device" ------------------------- topic_handlers = [ regex for regex in self.__connect_requests_sub_topics if fullmatch(regex, message.topic) ] if topic_handlers: for topic in topic_handlers: handler = self.__connect_requests_sub_topics[topic] found_device_name = None found_device_type = 'default' # Get device name, either from topic or from content if handler.get("deviceNameTopicExpression"): device_name_match = search( handler["deviceNameTopicExpression"], message.topic) if device_name_match is not None: found_device_name = device_name_match.group(0) elif handler.get("deviceNameJsonExpression"): found_device_name = TBUtility.get_value( handler["deviceNameJsonExpression"], content) # Get device type (if any), either from topic or from content if handler.get("deviceTypeTopicExpression"): device_type_match = search( handler["deviceTypeTopicExpression"], message.topic) found_device_type = device_type_match.group( 0) if device_type_match is not None else handler[ "deviceTypeTopicExpression"] elif handler.get("deviceTypeJsonExpression"): found_device_type = TBUtility.get_value( handler["deviceTypeJsonExpression"], content) if found_device_name is None: self.__log.error( "Device name missing from connection request") continue # Note: device must be added even if it is already known locally: else ThingsBoard # will not send RPCs and attribute updates self.__log.info("Connecting device %s of type %s", found_device_name, found_device_type) self.__gateway.add_device(found_device_name, {"connector": self}, device_type=found_device_type) # Note: if I'm in this branch, this was for sure a connection message # => Execution must end here both in case of failure and success return None # Check if message topic exists in disconnection handlers "i.e., I'm disconnecting a device" ------------------- topic_handlers = [ regex for regex in self.__disconnect_requests_sub_topics if fullmatch(regex, message.topic) ] if topic_handlers: for topic in topic_handlers: handler = self.__disconnect_requests_sub_topics[topic] found_device_name = None found_device_type = 'default' # Get device name, either from topic or from content if handler.get("deviceNameTopicExpression"): device_name_match = search( handler["deviceNameTopicExpression"], message.topic) if device_name_match is not None: found_device_name = device_name_match.group(0) elif handler.get("deviceNameJsonExpression"): found_device_name = TBUtility.get_value( handler["deviceNameJsonExpression"], content) # Get device type (if any), either from topic or from content if handler.get("deviceTypeTopicExpression"): device_type_match = search( handler["deviceTypeTopicExpression"], message.topic) if device_type_match is not None: found_device_type = device_type_match.group(0) elif handler.get("deviceTypeJsonExpression"): found_device_type = TBUtility.get_value( handler["deviceTypeJsonExpression"], content) if found_device_name is None: self.__log.error( "Device name missing from disconnection request") continue if found_device_name in self.__gateway.get_devices(): self.__log.info("Disconnecting device %s of type %s", found_device_name, found_device_type) self.__gateway.del_device(found_device_name) else: self.__log.info("Device %s was not connected", found_device_name) break # Note: if I'm in this branch, this was for sure a disconnection message # => Execution must end here both in case of failure and success return None # Check if message topic exists in attribute request handlers "i.e., I'm asking for a shared attribute" -------- topic_handlers = [ regex for regex in self.__attribute_requests_sub_topics if fullmatch(regex, message.topic) ] if topic_handlers: try: for topic in topic_handlers: handler = self.__attribute_requests_sub_topics[topic] found_device_name = None found_attribute_name = None # Get device name, either from topic or from content if handler.get("deviceNameTopicExpression"): device_name_match = search( handler["deviceNameTopicExpression"], message.topic) if device_name_match is not None: found_device_name = device_name_match.group(0) elif handler.get("deviceNameJsonExpression"): found_device_name = TBUtility.get_value( handler["deviceNameJsonExpression"], content) # Get attribute name, either from topic or from content if handler.get("attributeNameTopicExpression"): attribute_name_match = search( handler["attributeNameTopicExpression"], message.topic) if attribute_name_match is not None: found_attribute_name = attribute_name_match.group( 0) elif handler.get("attributeNameJsonExpression"): found_attribute_name = TBUtility.get_value( handler["attributeNameJsonExpression"], content) if found_device_name is None: self.__log.error( "Device name missing from attribute request") continue if found_attribute_name is None: self.__log.error( "Attribute name missing from attribute request") continue self.__log.info("Will retrieve attribute %s of %s", found_attribute_name, found_device_name) self.__gateway.tb_client.client.gw_request_shared_attributes( found_device_name, [found_attribute_name], lambda data, *args: self.notify_attribute( data, found_attribute_name, handler.get("topicExpression"), handler.get("valueExpression"), handler.get('retain', False))) break except Exception as e: log.exception(e) # Note: if I'm in this branch, this was for sure an attribute request message # => Execution must end here both in case of failure and success return None # Check if message topic exists in RPC handlers ---------------------------------------------------------------- # The gateway is expecting for this message => no wildcards here, the topic must be evaluated as is if self.__gateway.is_rpc_in_progress(message.topic): log.info("RPC response arrived. Forwarding it to thingsboard.") self.__gateway.rpc_with_reply_processing(message.topic, content) return None self.__log.debug( "Received message to topic \"%s\" with unknown interpreter data: \n\n\"%s\"", message.topic, content)
def __search_tags(self, node, recursion_level, sub=None): print( "__search_tags -----------------------------------------__search_tags node=", node, "recursion_level=", recursion_level, "node.get_children()=", node.get_children()) try: for childId in node.get_children(): ch = self.client.get_node(childId) current_var_path = '.'.join( x.split(":")[1] for x in ch.get_path(20000, True)) print("__search_tags current_var_path=", current_var_path, "ch.get_node_class()=", ch.get_node_class()) if self.__interest_nodes: if ch.get_node_class() == ua.NodeClass.Object: for interest_node in self.__interest_nodes: for int_node in interest_node: try: name_to_check = int_node.split('\\.')[ recursion_level + 1] if '\\.' in int_node else int_node # name_to_check = int_node.split('.')[recursion_level] if '.' in int_node else name_to_check except IndexError: name_to_check = int_node.split( '\\.' )[-1] if '\\.' in int_node else int_node # name_to_check = int_node.split('.')[-1] if '.' in int_node else name_to_check log.debug("%s\t%s", name_to_check, ch.get_display_name().Text) print("__search_tags ch.get_methods()", ch.get_methods(), "int_node=", int_node) if re.search( name_to_check.replace("\\", "\\\\"), ch.get_display_name().Text): try: methods = ch.get_methods() for method in methods: self.__available_object_resources[ interest_node[int_node] ["deviceName"]][ "methods"].append({ method.get_display_name( ).Text: method, "node": ch }) except Exception as e: log.exception(e) # for tag in interest_node[int_node]["timeseries"] + interest_node[int_node]["attributes"]: # subrecursion_level = recursion_level # if subrecursion_level != recursion_level + len(tag["path"].split("\\.")): # self.__search_tags(ch, subrecursion_level+1, sub) # else: # return self.__search_tags(ch, recursion_level + 1, sub) elif ch.get_node_class() == ua.NodeClass.Variable: try: for interest_node in self.__interest_nodes: for int_node in interest_node: if interest_node[int_node].get( "attributes_updates"): try: for attribute_update in interest_node[ int_node][ "attributes_updates"]: if attribute_update[ "attributeOnDevice"] == ch.get_display_name( ).Text: self.__available_object_resources[ interest_node[int_node] ["deviceName"]][ 'variables'].append({ attribute_update["attributeOnThingsBoard"]: ch, }) except Exception as e: log.exception(e) name_to_check = int_node.split( '\\.' )[-1] if '\\.' in int_node else int_node # name_to_check = int_node.split('.')[-1] if '.' in int_node else name_to_check print( "__search_tags name_to_check.replace('$', '')=", name_to_check.replace('$', ''), "current_var_path.split=", current_var_path.split(".")[-2]) if re.search( name_to_check.replace('$', ''), current_var_path.split(".")[-2]): print("__search_tags search!!!") tags = [] if interest_node[int_node].get( "attributes"): tags.extend(interest_node[int_node] ["attributes"]) if interest_node[int_node].get( "timeseries"): tags.extend(interest_node[int_node] ["timeseries"]) for tag in tags: target = TBUtility.get_value( tag["path"], get_tag=True) try: tag_name_for_check = target.split( '\\.' )[recursion_level] if '\\.' in target else target # tag_name_for_check = target.split('.')[recursion_level] if '.' in target else tag_name_for_check except IndexError: tag_name_for_check = target.split( '\\.' )[-1] if '\\.' in target else target # tag_name_for_check = target.split('.')[-1] if '.' in target else tag_name_for_check current_node_name = ch.get_display_name( ).Text print( "__search_tags current_node_name=", current_node_name, "tag_name_for_check=", tag_name_for_check) if current_node_name == tag_name_for_check: print( "__search_tags subscribe_data_change" ) sub.subscribe_data_change(ch) if interest_node[int_node].get( "uplink_converter" ) is None: if interest_node[ int_node].get( 'converter' ) is None: converter = OpcUaUplinkConverter( interest_node[ int_node]) else: converter = TBUtility.check_and_import( self. __connector_type, interest_node[ int_node] ['converter']) interest_node[int_node][ "uplink_converter"] = converter else: converter = interest_node[ int_node][ "uplink_converter"] self.subscribed[ch] = { "converter": converter, "path": current_var_path } else: return except BadWaitingForInitialData: pass elif not self.__interest_nodes: log.error( "Nodes in mapping not found, check your settings.") except Exception as e: log.exception(e)
def __search_name(self, node, recursion_level): try: for childId in node.get_children(): ch = self.client.get_node(childId) current_var_path = '.'.join( x.split(":")[1] for x in ch.get_path(20000, True)) if self.__server_conf.get("showMap"): log.info("Looking for name: %s", current_var_path) if self.__interest_nodes: if ch.get_node_class() == ua.NodeClass.Object: for interest_node in self.__interest_nodes: for int_node in interest_node: subrecursion_level = recursion_level if subrecursion_level != recursion_level + len( interest_node[int_node] ["deviceNamePattern"].split("\\.")): if ch.get_display_name().Text in TBUtility.get_value(interest_node[int_node]["deviceNamePattern"], get_tag=True).split('\\.') or \ re.search(TBUtility.get_value(interest_node[int_node]["deviceNodePattern"].split("\\.")[recursion_level+1], get_tag=True), ch.get_display_name().Text): if interest_node[int_node].get( "deviceName") is None: self.__search_name( ch, subrecursion_level + 1) else: return elif ch.get_node_class() == ua.NodeClass.Variable: try: for interest_node in self.__interest_nodes: for int_node in interest_node: if interest_node[int_node].get( "deviceName") is None: try: name_pattern = TBUtility.get_value( interest_node[int_node] ["deviceNamePattern"], get_tag=True) log.debug(current_var_path) device_name_node = re.search( name_pattern.split('\\.')[-1], current_var_path) if device_name_node is not None: device_name = ch.get_value() if "${" + name_pattern + "}" in interest_node[ int_node][ "deviceNamePattern"]: full_device_name = interest_node[ int_node][ "deviceNamePattern"].replace( "${" + name_pattern + "}", device_name) log.debug( "Full device name is: %s", full_device_name) elif device_name in interest_node[ int_node][ "deviceNamePattern"]: full_device_name = interest_node[ int_node][ "deviceNamePattern"].replace( name_pattern, device_name) log.debug( "Full device name is: %s", full_device_name) else: log.error( "Name pattern not found." ) break interest_node[int_node][ "deviceName"] = full_device_name if self.__available_object_resources.get( full_device_name ) is None: self.__available_object_resources[ full_device_name] = { 'methods': [], 'variables': [] } if not self.__gateway.get_devices( ).get(full_device_name): self.__gateway.add_device( full_device_name, {"connector": None}) self.__gateway.update_device( full_device_name, "connector", self) return else: try: if re.search( int_node.split( '\\.') [recursion_level], ch. get_display_name( ).Text): if interest_node[ int_node].get( "deviceName" ) is None: self.__search_name( ch, recursion_level + 1) except IndexError: if re.search( int_node.split( '\\.')[-1], ch. get_display_name( ).Text): if interest_node[ int_node].get( "deviceName" ) is None: self.__search_name( ch, recursion_level + 1) except Exception as e: log.exception(e) else: break except BadWaitingForInitialData: pass elif not self.__interest_nodes: log.error( "Nodes in mapping not found, check your settings.") except Exception as e: log.exception(e)
def convert(self, config, data): dict_result = { "deviceName": None, "deviceType": None, "attributes": [], "telemetry": [] } try: if self.__config.get("deviceNameJsonExpression") is not None: dict_result["deviceName"] = TBUtility.get_value( self.__config.get("deviceNameJsonExpression"), data) elif self.__config.get("deviceNameTopicExpression") is not None: dict_result["deviceName"] = search( self.__config["deviceNameTopicExpression"], config) else: log.error( "The expression for looking \"deviceName\" not found in config %s", dumps(self.__config)) if self.__config.get("deviceTypeJsonExpression") is not None: dict_result["deviceType"] = TBUtility.get_value( self.__config.get("deviceTypeJsonExpression"), data) elif self.__config.get("deviceTypeTopicExpression") is not None: dict_result["deviceType"] = search( self.__config["deviceTypeTopicExpression"], config) else: log.error( "The expression for looking \"deviceType\" not found in config %s", dumps(self.__config)) dict_result["attributes"] = [] dict_result["telemetry"] = [] except Exception as e: log.error( 'Error in converter, for config: \n%s\n and message: \n%s\n', dumps(self.__config), data) log.exception(e) try: if self.__config.get("attributes"): for attribute in self.__config.get("attributes"): dict_result["attributes"].append({ attribute["key"]: TBUtility.get_value(attribute["value"], data, attribute["type"]) }) except Exception as e: log.error( 'Error in converter, for config: \n%s\n and message: \n%s\n', dumps(self.__config), data) log.exception(e) try: if self.__config.get("timeseries"): for ts in self.__config.get("timeseries"): dict_result["telemetry"].append({ ts["key"]: TBUtility.get_value(ts["value"], data, ts["type"]) }) except Exception as e: log.error( 'Error in converter, for config: \n%s\n and message: \n%s\n', dumps(self.__config), data) log.exception(e) return dict_result
def _on_message(self, client, userdata, message): self.statistics['MessagesReceived'] += 1 content = TBUtility.decode(message) regex_topic = [ regex for regex in self.__sub_topics if fullmatch(regex, message.topic) ] if regex_topic: try: for regex in regex_topic: if self.__sub_topics.get(regex): for converter_value in range( len(self.__sub_topics.get(regex))): if self.__sub_topics[regex][converter_value]: for converter in self.__sub_topics.get( regex)[converter_value]: converted_content = converter.convert( message.topic, content) if converted_content: try: self.__sub_topics[regex][ converter_value][ converter] = converted_content except Exception as e: self.__log.exception(e) self.__gateway.send_to_storage( self.name, converted_content) self.statistics['MessagesSent'] += 1 else: continue else: self.__log.error( 'Cannot find converter for topic:"%s"!', message.topic) return except Exception as e: log.exception(e) return elif self.__service_config.get("connectRequests"): connect_requests = [ connect_request for connect_request in self.__service_config.get("connectRequests") ] if connect_requests: for request in connect_requests: if request.get("topicFilter"): if message.topic in request.get("topicFilter") or\ (request.get("deviceNameTopicExpression") is not None and search(request.get("deviceNameTopicExpression"), message.topic)): founded_device_name = None if request.get("deviceNameJsonExpression"): founded_device_name = TBUtility.get_value( request["deviceNameJsonExpression"], content) if request.get("deviceNameTopicExpression"): device_name_expression = request[ "deviceNameTopicExpression"] founded_device_name = search( device_name_expression, message.topic) if founded_device_name is not None and founded_device_name not in self.__gateway.get_devices( ): self.__gateway.add_device( founded_device_name, {"connector": self}) else: self.__log.error( "Cannot find connect request for device from message from topic: %s and with data: %s", message.topic, content) else: self.__log.error( "\"topicFilter\" in connect requests config not found." ) else: self.__log.error("Connection requests in config not found.") elif self.__service_config.get("disconnectRequests") is not None: disconnect_requests = [ disconnect_request for disconnect_request in self.__service_config.get("disconnectRequests") ] if disconnect_requests: for request in disconnect_requests: if request.get("topicFilter") is not None: if message.topic in request.get("topicFilter") or\ (request.get("deviceNameTopicExpression") is not None and search(request.get("deviceNameTopicExpression"), message.topic)): founded_device_name = None if request.get("deviceNameJsonExpression"): founded_device_name = TBUtility.get_value( request["deviceNameJsonExpression"], content) if request.get("deviceNameTopicExpression"): device_name_expression = request[ "deviceNameTopicExpression"] founded_device_name = search( device_name_expression, message.topic) if founded_device_name is not None and founded_device_name in self.__gateway.get_devices( ): self.__gateway.del_device(founded_device_name) else: self.__log.error( "Cannot find connect request for device from message from topic: %s and with data: %s", message.topic, content) else: self.__log.error( "\"topicFilter\" in connect requests config not found." ) else: self.__log.error("Disconnection requests in config not found.") elif message.topic in self.__gateway.rpc_requests_in_progress: self.__gateway.rpc_with_reply_processing(message.topic, content) else: self.__log.debug( "Received message to topic \"%s\" with unknown interpreter data: \n\n\"%s\"", message.topic, content)
def _on_message(self, client, userdata, message): self.statistics['MessagesReceived'] += 1 content = TBUtility.decode(message) # Check if message topic exists in mappings "i.e., I'm posting telemetry/attributes" regex_topic = [ regex for regex in self.__sub_topics if fullmatch(regex, message.topic) ] if regex_topic: try: for regex in regex_topic: if self.__sub_topics.get(regex): for converter_value in range( len(self.__sub_topics.get(regex))): if self.__sub_topics[regex][converter_value]: for converter in self.__sub_topics.get( regex)[converter_value]: converted_content = converter.convert( message.topic, content) if converted_content: try: self.__sub_topics[regex][ converter_value][ converter] = converted_content except Exception as e: self.__log.exception(e) self.__gateway.send_to_storage( self.name, converted_content) self.statistics['MessagesSent'] += 1 else: continue else: self.__log.error( 'Cannot find converter for the topic:"%s"! Client: %s, User data: %s', message.topic, str(client), str(userdata)) return None except Exception as e: log.exception(e) return None # Check if message topic is matched by an existing connection request handler if self.__service_config.get("connectRequests"): for request in self.__service_config["connectRequests"]: # Check that the current connection request handler defines a topic filter (mandatory) if request.get("topicFilter") is None: continue found_device_name = None found_device_type = 'default' # Extract device name and type from regexps, if any. # This cannot be postponed because message topic may contain wildcards if request.get("deviceNameJsonExpression"): found_device_name = TBUtility.get_value( request["deviceNameJsonExpression"], content) if request.get("deviceNameTopicExpression"): device_name_expression = request[ "deviceNameTopicExpression"] device_name_match = search(device_name_expression, message.topic) if device_name_match is not None: found_device_name = device_name_match.group(0) if request.get("deviceTypeJsonExpression"): found_device_type = TBUtility.get_value( request["deviceTypeJsonExpression"], content) if request.get("deviceTypeTopicExpression"): device_type_expression = request[ "deviceTypeTopicExpression"] found_device_type = search(device_type_expression, message.topic) # Check if request topic matches with message topic before of after regexp substitution if message.topic not in request.get("topicFilter"): sub_topic = message.topic # Substitute device name (if defined) in topic if found_device_name is not None: sub_topic = sub(found_device_name, "+", sub_topic) # Substitute device type in topic sub_topic = sub(found_device_type, "+", sub_topic) # If topic still not matches, this is not the correct handler if sub_topic not in request.get("topicFilter"): continue # I'm now sure that this message must be handled by this connection request handler if found_device_name is None: self.__log.error( "Device name missing from connection request") return None # Note: device must be added even if it is already known locally: else ThingsBoard # will not send RPCs and attribute updates self.__gateway.add_device(found_device_name, {"connector": self}, device_type=found_device_type) return None # Check if message topic is matched by an existing disconnection request handler if self.__service_config.get("disconnectRequests"): for request in self.__service_config["disconnectRequests"]: # Check that the current disconnection request handler defines a topic filter (mandatory) if request.get("topicFilter") is None: continue found_device_name = None found_device_type = 'default' # Extract device name and type from regexps, if any. # This cannot be postponed because message topic may contain wildcards if request.get("deviceNameJsonExpression"): found_device_name = TBUtility.get_value( request["deviceNameJsonExpression"], content) if request.get("deviceNameTopicExpression"): device_name_expression = request[ "deviceNameTopicExpression"] device_name_match = search(device_name_expression, message.topic) if device_name_match is not None: found_device_name = device_name_match.group(0) if request.get("deviceTypeJsonExpression"): found_device_type = TBUtility.get_value( request["deviceTypeJsonExpression"], content) if request.get("deviceTypeTopicExpression"): device_type_expression = request[ "deviceTypeTopicExpression"] found_device_type = search(device_type_expression, message.topic) # Check if request topic matches with message topic before of after regexp substitution if message.topic not in request.get("topicFilter"): sub_topic = message.topic # Substitute device name (if defined) in topic if found_device_name is not None: sub_topic = sub(found_device_name, "+", sub_topic) # Substitute device type in topic sub_topic = sub(found_device_type, "+", sub_topic) # If topic still not matches, this is not the correct handler if sub_topic not in request.get("topicFilter"): continue # I'm now sure that this message must be handled by this connection request handler if found_device_name is None: self.__log.error( "Device name missing from disconnection request") return None if found_device_name in self.__gateway.get_devices(): self.__log.info("Device %s of type %s disconnected", found_device_name, found_device_type) self.__gateway.del_device(found_device_name) else: self.__log.info("Device %s is already disconnected", found_device_name) return None if message.topic in self.__gateway.rpc_requests_in_progress: self.__gateway.rpc_with_reply_processing(message.topic, content) else: self.__log.debug( "Received message to topic \"%s\" with unknown interpreter data: \n\n\"%s\"", message.topic, content)