Example #1
0
    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)
Example #3
0
    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
Example #4
0
 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))
Example #5
0
 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
Example #6
0
 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))
Example #10
0
 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
Example #16
0
    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)
Example #17
0
 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)
Example #19
0
 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)
Example #21
0
    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)