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}, device_type=device.get("deviceType")) self.__devices[device["deviceName"]] = {"config": device, "converter": converter, "downlink_converter": downlink_converter, "next_attributes_check": 0, "next_timeseries_check": 0, "telemetry": {}, "attributes": {}, "last_telemetry": {}, "last_attributes": {} } except Exception as e: log.exception(e)
def addDevices(self, config, connector): token = config['accessToken'] self._tokens.add(token) if token is not None: for device in config['devices']: if config.get("converter") is not None: converter = TBUtility.check_and_import( 'tcp', self._config["converter"])(device) else: converter = BytesModbusUplinkConverter(device) if config.get("downlink_converter") is not None: downlink_converter = TBUtility.check_and_import( 'tcp', 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": connector}, device_type=device.get("deviceType")) self._devices[device["deviceName"]] = { "config": device, "token": token, "converter": converter, "downlink_converter": downlink_converter, "next_attributes_check": 0, "next_timeseries_check": 0, "telemetry": {}, "attributes": {}, "last_telemetry": {}, "last_attributes": {} } break
def _load_connectors(self, config, from_file=True): 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)) if from_file: with open(self._config_dir + connector['configuration'], 'r') as conf_file: try: 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.exception(e) except Exception as e: log.exception(e)
def __get_converter(self, config, need_uplink): if config is None: return BytesNmeaUplinkConverter() if need_uplink else BytesNmeaDownlinkConverter() else: if need_uplink: uplink = config.get("uplink") return BytesNmeaUplinkConverter() if uplink is None \ else TBUtility.check_and_import(self.__connector_type, uplink) else: downlink = config.get("downlink") return BytesNmeaDownlinkConverter() if downlink is None \ else TBUtility.check_and_import(self.__connector_type, downlink)
def __fill_converters(self): try: for device in self.__devices: device["uplink_converter"] = TBUtility.check_and_import( "snmp", device.get('converter', self._default_converters["uplink"]))(device) device["downlink_converter"] = TBUtility.check_and_import( "snmp", device.get('converter', self._default_converters["downlink"]))(device) except Exception as e: log.exception(e)
def updateDevices(self, config, connector): token = config['accessToken'] self._tokens.add(token) if token is not None: # 1. 先删除之前添加的设备,避免存在脏设备。 pre_gateway_devices = filter( lambda x: self._gateway[x]["connector"].get_name() == connector .get_name(), self._gateway.get_devices()) if pre_gateway_devices is not None: for pre_device in pre_gateway_devices: self._gateway.del_device(pre_device.get('deviceName')) devices = { k: v for k, v in self._devices.items() if v['token'] == token } for device in list(devices.keys()): del self._devices[device] # 2. 新增设备,重置所有的信息 for device in config['devices']: if config.get("converter") is not None: converter = TBUtility.check_and_import( 'tcp', self._config["converter"])(device) else: converter = BytesModbusUplinkConverter(device) if config.get("downlink_converter") is not None: downlink_converter = TBUtility.check_and_import( 'tcp', 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": connector}, device_type=device.get("deviceType")) if device.get('deviceName') not in self._devices: self._devices[device["deviceName"]] = { "config": device, "token": token, "converter": converter, "downlink_converter": downlink_converter, "next_attributes_check": 0, "next_timeseries_check": 0, "telemetry": {}, "attributes": {}, "last_telemetry": {}, "last_attributes": {} } break
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 __init__(self, gateway, config, connector_type): super().__init__() self.daemon = True self.setName(config.get("name", 'ODBC Connector ' + ''.join(choice(ascii_lowercase) for _ in range(5)))) self.statistics = {'MessagesReceived': 0, 'MessagesSent': 0} self.__gateway = gateway self.__connector_type = connector_type self.__config = config self.__stopped = False self.__config_dir = "thingsboard_gateway/config/odbc/" self.__connection = None self.__cursor = None self.__rpc_cursor = None self.__iterator = None self.__iterator_file_name = "" self.__devices = {} self.__column_names = [] self.__attribute_columns = [] self.__timeseries_columns = [] self.__converter = OdbcUplinkConverter() if not self.__config.get("converter", "") else \ TBUtility.check_and_import(self.__connector_type, self.__config["converter"]) self.__configure_pyodbc() self.__parse_rpc_config()
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 _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') 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_converters(self): # Function for search a converter and save it. devices_config = self.__config.get('devices') try: if devices_config: for device_config in devices_config: if device_config.get('converter') is not None: converter = TBUtility.check_and_import( self.__connector_type, device_config['converter']) self.devices[device_config['name']] = { 'converter': converter(device_config), 'device_config': device_config } else: converter = CustomOpcdaUplinkConverter(device_config) self.devices[device_config['name']] = { 'converter': converter, 'device_config': device_config } 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 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)
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)
def _on_connect(self, client, userdata, flags, rc, *extra_params): result_codes = { 1: "incorrect protocol version", 2: "invalid client identifier", 3: "server unavailable", 4: "bad username or password", 5: "not authorised", } if rc == 0: self._connected = True self.__log.info('%s connected to %s:%s - successfully.', self.get_name(), self.__broker["host"], self.__broker.get("port", "1883")) for mapping in self.__mapping: try: converter = None if mapping["converter"]["type"] == "custom": try: module = TBUtility.check_and_import(self.__connector_type, mapping["converter"]["extension"]) if module is not None: self.__log.debug('Custom converter for topic %s - found!', mapping["topicFilter"]) converter = module(mapping) else: self.__log.error("\n\nCannot find extension module for %s topic.\n\Please check your configuration.\n", mapping["topicFilter"]) except Exception as e: self.__log.exception(e) else: converter = JsonMqttUplinkConverter(mapping) if converter is not None: regex_topic = TBUtility.topic_to_regex(mapping.get("topicFilter")) if not self.__sub_topics.get(regex_topic): self.__sub_topics[regex_topic] = [] self.__sub_topics[regex_topic].append({converter: None}) # self._client.subscribe(TBUtility.regex_to_topic(regex_topic)) self.__subscribe(mapping["topicFilter"]) self.__log.info('Connector "%s" subscribe to %s', self.get_name(), TBUtility.regex_to_topic(regex_topic)) else: self.__log.error("Cannot find converter for %s topic", mapping["topicFilter"]) except Exception as e: self.__log.exception(e) try: for request in self.__service_config: if self.__service_config.get(request) is not None: for request_config in self.__service_config.get(request): self.__subscribe(request_config["topicFilter"]) except Exception as e: self.__log.error(e) else: if rc in result_codes: self.__log.error("%s connection FAIL with error %s %s!", self.get_name(), rc, result_codes[rc]) else: self.__log.error("%s connection FAIL with unknown error!", self.get_name())
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 _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 __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 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 __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 __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 __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 __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 _load_connectors(self): self.connectors_configs = {} if self.__config.get("connectors"): for connector in self.__config['connectors']: try: type = connector["type"] type1 = self._default_connectors.get(connector["type"]) classt = connector.get("class") classtype = self._default_connectors.get( connector["type"], connector.get("class")) connector_class = TBUtility.check_and_import( connector["type"], self._default_connectors.get(connector["type"], connector.get("class"))) self._implemented_connectors[ connector["type"]] = connector_class log.info(connector_class) #加载connector配置文件 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!") self.__init_remote_configuration(force=True) log.info("Remote configuration is enabled forcibly!")
def load_converters(self): devices_config = self.__config.get('devices') try: if devices_config is not None: print("Devices config part loaded ... ") for device_config in devices_config: if device_config.get('converter') is not None: converter = TBUtility.check_and_import( self.__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 _on_connect(self, client, userdata, flags, result_code, *extra_params): result_codes = { 1: "incorrect protocol version", 2: "invalid client identifier", 3: "server unavailable", 4: "bad username or password", 5: "not authorised", } if result_code == 0: self._connected = True self.__log.info('%s connected to %s:%s - successfully.', self.get_name(), self.__broker["host"], self.__broker.get("port", "1883")) self.__log.debug( "Client %s, userdata %s, flags %s, extra_params %s", str(client), str(userdata), str(flags), extra_params) # Setup data upload requests handling ---------------------------------------------------------------------- for mapping in self.__mapping: try: # Load converter for this mapping entry ------------------------------------------------------------ # mappings are guaranteed to have topicFilter and converter fields. See __init__ default_converter_class_name = "JsonMqttUplinkConverter" # Get converter class from "extension" parameter or default converter converter_class_name = mapping["converter"].get( "extension", default_converter_class_name) # Find and load required class module = TBUtility.check_and_import( self._connector_type, converter_class_name) if module: self.__log.debug('Converter %s for topic %s - found!', converter_class_name, mapping["topicFilter"]) converter = module(mapping) else: self.__log.error("Cannot find converter for %s topic", mapping["topicFilter"]) continue # Setup regexp topic acceptance list --------------------------------------------------------------- regex_topic = TBUtility.topic_to_regex( mapping["topicFilter"]) # There may be more than one converter per topic, so I'm using vectors if not self.__mapping_sub_topics.get(regex_topic): self.__mapping_sub_topics[regex_topic] = [] self.__mapping_sub_topics[regex_topic].append(converter) # Subscribe to appropriate topic ------------------------------------------------------------------- self.__subscribe(mapping["topicFilter"], mapping.get("subscriptionQos", 0)) self.__log.info('Connector "%s" subscribe to %s', self.get_name(), TBUtility.regex_to_topic(regex_topic)) except Exception as e: self.__log.exception(e) # Setup connection requests handling ----------------------------------------------------------------------- for request in [ entry for entry in self.__connect_requests if entry is not None ]: # requests are guaranteed to have topicFilter field. See __init__ self.__subscribe(request["topicFilter"], request.get("subscriptionQos", 0)) topic_filter = TBUtility.topic_to_regex( request.get("topicFilter")) self.__connect_requests_sub_topics[topic_filter] = request # Setup disconnection requests handling -------------------------------------------------------------------- for request in [ entry for entry in self.__disconnect_requests if entry is not None ]: # requests are guaranteed to have topicFilter field. See __init__ self.__subscribe(request["topicFilter"], request.get("subscriptionQos", 0)) topic_filter = TBUtility.topic_to_regex( request.get("topicFilter")) self.__disconnect_requests_sub_topics[topic_filter] = request # Setup attributes requests handling ----------------------------------------------------------------------- for request in [ entry for entry in self.__attribute_requests if entry is not None ]: # requests are guaranteed to have topicFilter field. See __init__ self.__subscribe(request["topicFilter"], request.get("subscriptionQos", 0)) topic_filter = TBUtility.topic_to_regex( request.get("topicFilter")) self.__attribute_requests_sub_topics[topic_filter] = request else: if result_code in result_codes: self.__log.error("%s connection FAIL with error %s %s!", self.get_name(), result_code, result_codes[result_code]) else: self.__log.error("%s connection FAIL with unknown error!", self.get_name())
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)