Beispiel #1
0
    def _send_to_storage(self, connector_name, data):
        if not TBUtility.validate_converted_data(data):
            log.error("Data from %s connector is invalid.", connector_name)
            return
        if data["deviceName"] not in self.get_devices():
            self.add_device(
                data["deviceName"],
                {"connector": self.available_connectors[connector_name]},
                wait_for_publish=True)
        if not self.__connector_incoming_messages.get(connector_name):
            self.__connector_incoming_messages[connector_name] = 0
        else:
            self.__connector_incoming_messages[connector_name] += 1

        telemetry = {}
        for item in data["telemetry"]:
            telemetry = {**telemetry, **item}
        data["telemetry"] = {
            "ts": int(time.time() * 1000),
            "values": telemetry
        }

        json_data = dumps(data)
        save_result = self.__event_storage.put(json_data)
        if not save_result:
            log.error(
                'Data from device "%s" cannot be saved, connector name is %s.',
                data["deviceName"], connector_name)
 def __prepare_connectors_configuration(self, input_connector_config):
     try:
         self.__gateway.connectors_configs = {}
         for connector in input_connector_config['thingsboard'][
                 'connectors']:
             for input_connector in input_connector_config[
                     connector['type']]:
                 if input_connector['name'] == connector['name']:
                     if not self.__gateway.connectors_configs.get(
                             connector['type']):
                         self.__gateway.connectors_configs[
                             connector['type']] = []
                     self.__gateway.connectors_configs[
                         connector['type']].append({
                             "name": connector["name"],
                             "config": {
                                 connector['configuration']:
                                 input_connector["config"]
                             }
                         })
                     connector_class = TBUtility.check_and_import(
                         connector["type"],
                         self.__gateway._default_connectors.get(
                             connector["type"], connector.get("class")))
                     self.__gateway._implemented_connectors[
                         connector["type"]] = connector_class
     except Exception as e:
         LOG.exception(e)
 def __fill_requests(self):
     log.debug(self.__config["mapping"])
     for endpoint in self.__config["mapping"]:
         try:
             log.debug(endpoint)
             converter = None
             if endpoint["converter"]["type"] == "custom":
                 module = TBUtility.check_and_import(
                     self.__connector_type,
                     endpoint["converter"]["extension"])
                 if module is not None:
                     log.debug('Custom converter for url %s - found!',
                               endpoint["url"])
                     converter = module(endpoint)
                 else:
                     log.error(
                         "\n\nCannot find extension module for %s url.\nPlease check your configuration.\n",
                         endpoint["url"])
             else:
                 converter = JsonRequestUplinkConverter(endpoint)
             self.__requests_in_progress.append({
                 "config": endpoint,
                 "converter": converter,
                 "next_time": time(),
                 "request": request
             })
         except Exception as e:
             log.exception(e)
    def send_to_storage(self, connector_name, data):
        if not connector_name == self.name:
            if not TBUtility.validate_converted_data(data):
                log.error("Data from %s connector is invalid.", connector_name)
                return None
            if data["deviceName"] not in self.get_devices():
                self.add_device(data["deviceName"],
                                {"connector": self.available_connectors[connector_name]}, wait_for_publish=True, device_type=data["deviceType"])
            if not self.__connector_incoming_messages.get(connector_name):
                self.__connector_incoming_messages[connector_name] = 0
            else:
                self.__connector_incoming_messages[connector_name] += 1
        else:
            data["deviceName"] = "currentThingsBoardGateway"

        telemetry = {}
        telemetry_with_ts = []
        for item in data["telemetry"]:
            if item.get("ts") is None:
                telemetry = {**telemetry, **item}
            else:
                telemetry_with_ts.append({"ts": item["ts"], "values": {**item["values"]}})
        if telemetry_with_ts:
            data["telemetry"] = telemetry_with_ts
        else:
            data["telemetry"] = {"ts": int(time() * 1000), "values": telemetry}

        json_data = dumps(data)
        save_result = self._event_storage.put(json_data)
        if not save_result:
            log.error('Data from the device "%s" cannot be saved, connector name is %s.',
                      data["deviceName"],
                      connector_name)
Beispiel #5
0
 def update(self):
     if self.__version["latest_version"] is not None:
         result = TBUtility.install_package(
             "thingsboard-gateway", self.__version["latest_version"])
     else:
         result = "Congratulations! You have the latest version."
     return result
Beispiel #6
0
 def __load_converters(
         self,
         connector_type):  # Function for search a converter and save it.
     devices_config = self.__config.get('devices')
     try:
         if devices_config is not None:
             for device_config in devices_config:
                 if device_config.get('converter') is not None:
                     converter = TBUtility.check_and_import(
                         connector_type, device_config['converter'])
                     self.__devices[device_config['name']] = {
                         'converter': converter(device_config),
                         'device_config': device_config
                     }
                 else:
                     log.error(
                         'Converter configuration for the custom connector %s -- not found, please check your configuration file.',
                         self.get_name())
         else:
             log.error(
                 'Section "devices" in the configuration not found. A custom connector %s has being stopped.',
                 self.get_name())
             self.close()
     except Exception as e:
         log.exception(e)
 def _load_connectors(self, main_config):
     self.connectors_configs = {}
     if main_config.get("connectors"):
         for connector in main_config['connectors']:
             try:
                 connector_class = TBUtility.check_and_import(
                     connector["type"],
                     self._default_connectors.get(connector["type"],
                                                  connector.get("class")))
                 self._implemented_connectors[
                     connector["type"]] = connector_class
                 with open(self._config_dir + connector['configuration'],
                           'r',
                           encoding="UTF-8") as conf_file:
                     connector_conf = load(conf_file)
                     if not self.connectors_configs.get(connector['type']):
                         self.connectors_configs[connector['type']] = []
                     connector_conf["name"] = connector["name"]
                     self.connectors_configs[connector['type']].append({
                         "name":
                         connector["name"],
                         "config": {
                             connector['configuration']: connector_conf
                         }
                     })
             except Exception as e:
                 log.error("Error on loading connector:")
                 log.exception(e)
     else:
         log.error("Connectors - not found! Check your configuration!")
         main_config["remoteConfiguration"] = True
         log.info("Remote configuration is enabled forcibly!")
 def _load_connectors(self, main_config):
     self.connectors_configs = {}
     if not main_config.get("connectors"):
         raise Exception(
             "Configuration for connectors not found, check your config file."
         )
     for connector in main_config['connectors']:
         try:
             connector_class = TBUtility.check_and_import(
                 connector["type"],
                 self._default_connectors.get(connector["type"],
                                              connector.get("class")))
             self._implemented_connectors[
                 connector["type"]] = connector_class
             with open(self._config_dir + connector['configuration'],
                       'r') as conf_file:
                 connector_conf = load(conf_file)
                 if not self.connectors_configs.get(connector['type']):
                     self.connectors_configs[connector['type']] = []
                 self.connectors_configs[connector['type']].append({
                     "name":
                     connector["name"],
                     "config": {
                         connector['configuration']: connector_conf
                     }
                 })
         except Exception as e:
             log.error("Error on loading connector:")
             log.exception(e)
Beispiel #9
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 fullmatch(path, config.replace('\\\\', '\\')):
                     result[information_types[information_type]].append({
                         information["key"]:
                         information["path"].replace(
                             "${" + path + "}", str(data))
                     })
         return result
     except Exception as e:
         log.exception(e)
Beispiel #10
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)
         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)
             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)
                 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)
                     result["deviceType"] = full_device_type
                     log.debug("Device type: %s", full_device_type)
                 else:
                     log.error(
                         "Device type node not found with expression: %s",
                         device_type_expression)
             else:
                 result["deviceType"] = "default"
             return result
         else:
             log.error("Device name node not found with expression: %s",
                       name_expression)
             return
     else:
         log.error(
             "Device node not found with expression: %s",
             TBUtility.get_value(device["deviceNodePattern"], get_tag=True))
 def __fill_attribute_updates(self):
     for attribute_request in self.__config.get("attributeUpdates", []):
         if attribute_request.get("converter") is not None:
             converter = TBUtility.check_and_import("request", attribute_request["converter"])(attribute_request)
         else:
             converter = JsonRequestDownlinkConverter(attribute_request)
         attribute_request_dict = {**attribute_request, "converter": converter}
         self.__attribute_updates.append(attribute_request_dict)
 def __fill_rpc_requests(self):
     for rpc_request in self.__config.get("serverSideRpc", []):
         if rpc_request.get("converter") is not None:
             converter = TBUtility.check_and_import("request", rpc_request["converter"])(rpc_request)
         else:
             converter = JsonRequestDownlinkConverter(rpc_request)
         rpc_request_dict = {**rpc_request, "converter": converter}
         self.__rpc_requests.append(rpc_request_dict)
Beispiel #13
0
 def __search_nodes_and_subscribe(self, device_info):
     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:
                     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_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 = TBUtility.check_and_import(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
                     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)
                         self.__sub.subscribe_data_change(information_node)
                     log.debug("Added subscription to node: %s", str(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):
        if isinstance(data, (bytes, str)):
            data = loads(data)
        dict_result = {"deviceName": None, "deviceType": None, "attributes": [], "telemetry": []}
        try:
            if self.__config['converter'].get("deviceNameJsonExpression") is not None:
                dict_result["deviceName"] = TBUtility.get_value(
                    self.__config['converter'].get("deviceNameJsonExpression"), data, expression_instead_none=True)
            else:
                log.error("The expression for looking \"deviceName\" not found in config %s",
                          dumps(self.__config['converter']))
            if self.__config['converter'].get("deviceTypeJsonExpression") is not None:
                dict_result["deviceType"] = TBUtility.get_value(
                    self.__config['converter'].get("deviceTypeJsonExpression"), data, expression_instead_none=True)
            else:
                log.error("The expression for looking \"deviceType\" not found in config %s",
                          dumps(self.__config['converter']))
        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:
                        if data.get("ts") is not None or data.get("timestamp") is not None:
                            dict_result[self.__datatypes[datatype]].append(
                                {"ts": data.get('ts', data.get('timestamp', int(time()))),
                                 'values': {datatype_object_config_key: datatype_object_config_value}})
                        else:
                            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
Beispiel #15
0
    def _load_connectors(self, config):
        self._connectors_configs = {}
        if not config.get("connectors"):
            raise Exception(
                "Configuration for connectors not found, check your config file."
            )
        for connector in config['connectors']:
            try:
                if connector.get('class') is not None:
                    try:
                        connector_class = TBUtility.check_and_import(
                            connector['type'], connector['class'])
                        self._implemented_connectors[
                            connector['type']] = connector_class
                    except Exception as e:
                        log.error(
                            "Exception when loading the custom connector:")
                        log.exception(e)
                elif connector.get("type") is not None and connector[
                        "type"] in self._default_connectors:
                    try:
                        connector_class = TBUtility.check_and_import(
                            connector["type"],
                            self._default_connectors[connector["type"]],
                            default=True)
                        self._implemented_connectors[
                            connector["type"]] = connector_class
                    except Exception as e:
                        log.error("Error on loading default connector:")
                        log.exception(e)
                else:
                    log.error("Connector with config %s - not found",
                              safe_dump(connector))

                with open(self._config_dir + connector['configuration'],
                          'r') as conf_file:
                    connector_conf = load(conf_file)
                    if not self._connectors_configs.get(connector['type']):
                        self._connectors_configs[connector['type']] = []
                    self._connectors_configs[connector['type']].append(
                        {connector['configuration']: connector_conf})
            except Exception as e:
                log.error(e)
 def _create_connector(self, config_filename, connector_type=None):
     if connector_type is None:
         class_name = self.__class__.__name__.lower()
         connector_type = class_name[0:class_name.find("connector")]
     self._connector_type = connector_type
     self.config = self._load_data_file(config_filename, connector_type)
     self.assertTrue(self.config is not None)
     connector = TBUtility.check_and_import(
         connector_type, DEFAULT_CONNECTORS[connector_type])
     self.assertTrue(connector is not None)
     self.connector = connector(self.gateway, self.config, connector_type)
     sleep(1)
    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 load_endpoints(self):
     endpoints = {}
     for mapping in self.__config.get("mapping"):
         converter = TBUtility.check_and_import(
             self._connector_type,
             mapping.get("extension", self._default_converters["uplink"]))
         endpoints.update({
             mapping['endpoint']: {
                 "config": mapping,
                 "converter": converter
             }
         })
     return endpoints
 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
Beispiel #20
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 __fill_interest_devices(self):
     if self.__config.get('devices') is None:
         log.error('Devices not found in configuration file. BLE Connector stopped.')
         self._connected = False
         return None
     for interest_device in self.__config.get('devices'):
         keys_in_config = ['attributes', 'telemetry']
         if interest_device.get('MACAddress') is not None:
             default_converter = BytesBLEUplinkConverter(interest_device)
             interest_uuid = {}
             for key_type in keys_in_config:
                 for type_section in interest_device.get(key_type):
                     if type_section.get("characteristicUUID") is not None:
                         converter = None
                         if type_section.get('converter') is not None:
                             try:
                                 module = TBUtility.check_and_import(self.__connector_type,
                                                                     type_section['converter'])
                                 if module is not None:
                                     log.debug('Custom converter for device %s - found!',
                                               interest_device['MACAddress'])
                                     converter = module(interest_device)
                                 else:
                                     log.error(
                                         "\n\nCannot find extension module for device %s .\nPlease check your configuration.\n",
                                         interest_device['MACAddress'])
                             except Exception as e:
                                 log.exception(e)
                         else:
                             converter = default_converter
                         if converter is not None:
                             if interest_uuid.get(type_section["characteristicUUID"].upper()) is None:
                                 interest_uuid[type_section["characteristicUUID"].upper()] = [
                                     {'section_config': type_section,
                                      'type': key_type,
                                      'converter': converter}]
                             else:
                                 interest_uuid[type_section["characteristicUUID"].upper()].append(
                                     {'section_config': type_section,
                                      'type': key_type,
                                      'converter': converter})
                     else:
                         log.error("No characteristicUUID found in configuration section for %s:\n%s\n", key_type,
                                   pformat(type_section))
             if self.__devices_around.get(interest_device['MACAddress'].upper()) is None:
                 self.__devices_around[interest_device['MACAddress'].upper()] = {}
             self.__devices_around[interest_device['MACAddress'].upper()]['device_config'] = interest_device
             self.__devices_around[interest_device['MACAddress'].upper()]['interest_uuid'] = interest_uuid
         else:
             log.error("Device address not found, please check your settings.")
 def __load_converters(self):
     try:
         for device in self.__config["devices"]:
             if self.__config.get("converter") is not None:
                 converter = TBUtility.check_and_import(self.__connector_type, self.__config["converter"])(device)
             else:
                 converter = BytesModbusUplinkConverter(device)
             if self.__config.get("downlink_converter") is not None:
                 downlink_converter = TBUtility.check_and_import(self.__connector_type, self.__config["downlink_converter"])(device)
             else:
                 downlink_converter = BytesModbusDownlinkConverter(device)
             if device.get('deviceName') not in self.__gateway.get_devices():
                 self.__gateway.add_device(device.get('deviceName'), {"connector": self})
                 self.__devices[device["deviceName"]] = {"config": device,
                                                         "converter": converter,
                                                         "downlink_converter": downlink_converter,
                                                         "next_attributes_check": 0,
                                                         "next_timeseries_check": 0,
                                                         "telemetry": {},
                                                         "attributes": {},
                                                         }
     except Exception as e:
         log.exception(e)
 def __init__(self, gateway, config, connector_type):
     self.__connector_type = connector_type
     self.statistics = {'MessagesReceived': 0, 'MessagesSent': 0}
     super().__init__()
     self.__config = config
     self.setName(
         config.get(
             'name',
             'BACnet ' + ''.join(choice(ascii_lowercase)
                                 for _ in range(5))))
     self.__devices = []
     self.__device_indexes = {}
     self.__devices_address_name = {}
     self.__gateway = gateway
     self._application = TBBACnetApplication(self, self.__config)
     self.__bacnet_core_thread = Thread(target=run,
                                        name="BACnet core thread")
     self.__bacnet_core_thread.start()
     self.__stopped = False
     self.__config_devices = self.__config["devices"]
     self.default_converters = {
         "uplink_converter":
         TBUtility.check_and_import(self.__connector_type,
                                    "BACnetUplinkConverter"),
         "downlink_converter":
         TBUtility.check_and_import(self.__connector_type,
                                    "BACnetDownlinkConverter")
     }
     self.__request_functions = {
         "writeProperty": self._application.do_write_property,
         "readProperty": self._application.do_read_property
     }
     self.__available_object_resources = {}
     self.rpc_requests_in_progress = {}
     self.__connected = False
     self.daemon = True
 def __fill_requests_from_TB(self):
     requests_from_tb = {
         "attributeUpdates": self.__attribute_updates,
         "serverSideRpc": self.__rpc_requests,
     }
     for request_section in requests_from_tb:
         for request_config_object in self.__config.get(
                 request_section, []):
             uplink_converter = TBUtility.check_and_import(
                 self._connector_type,
                 request_config_object.get(
                     "extension", self._default_converters["uplink"]))(
                         request_config_object)
             downlink_converter = TBUtility.check_and_import(
                 self._connector_type,
                 request_config_object.get(
                     "extension", self._default_converters["downlink"]))(
                         request_config_object)
             request_dict = {
                 **request_config_object,
                 "uplink_converter": uplink_converter,
                 "downlink_converter": downlink_converter,
             }
             requests_from_tb[request_section].append(request_dict)
 def __load_converters(self, device):
     datatypes = [
         "attributes", "telemetry", "attribute_updates", "server_side_rpc"
     ]
     for datatype in datatypes:
         for datatype_config in device.get(datatype, []):
             try:
                 for converter_type in self.default_converters:
                     converter_object = self.default_converters[
                         converter_type] if datatype_config.get(
                             "class"
                         ) is None else TBUtility.check_and_import(
                             self.__connector_type, device.get("class"))
                     datatype_config[converter_type] = converter_object(
                         device)
             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("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
Beispiel #27
0
    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_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
Beispiel #30
0
 def _on_message(self, client, userdata, message):
     content = TBUtility.decode(message)
     super()._on_decoded_message(content, message)
     self._on_decoded_message(content, message)