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)
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
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)
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)
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)
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
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
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
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
def _on_message(self, client, userdata, message): content = TBUtility.decode(message) super()._on_decoded_message(content, message) self._on_decoded_message(content, message)