def convert(self, config, data): try: if data["data"].get("id") is None: attribute_key = list(data["data"].keys())[0] attribute_value = list(data["data"].values())[0] result = { "url": self.__config["requestUrlExpression"].replace( "${attributeKey}", quote(attribute_key)).replace( "${attributeValue}", quote(attribute_value)).replace( "${deviceName}", quote(data["device"])), "data": self.__config["valueExpression"].replace( "${attributeKey}", quote(attribute_key)).replace( "${attributeValue}", quote(attribute_value)).replace( "${deviceName}", quote(data["device"])) } else: request_id = str(data["data"]["id"]) method_name = data["data"]["method"] result = { "url": self.__config["requestUrlExpression"].replace( "${requestId}", request_id).replace( "${methodName}", method_name).replace("${deviceName}", quote(data["device"])), "data": self.__config["valueExpression"].replace( "${requestId}", request_id).replace( "${methodName}", method_name).replace("${deviceName}", quote(data["device"])) } result['url'] = TBUtility.replace_params_tags( result['url'], data) data_tags = TBUtility.get_values(config.get('valueExpression'), data['data'], 'params', get_tag=True) data_values = TBUtility.get_values( config.get('valueExpression'), data['data'], 'params', expression_instead_none=True) for (tag, value) in zip(data_tags, data_values): result['data'] = result["data"].replace( '${' + tag + '}', str(value)) return result except Exception as e: log.exception(e)
def server_side_rpc_handler(self, content): self.__log.info("Incoming server-side RPC: %s", content) # Check whether one of my RPC handlers can handle this request for rpc_config in self.__server_side_rpc: if search(rpc_config["deviceNameFilter"], content["device"]) \ and search(rpc_config["methodFilter"], content["data"]["method"]) is not None: # This handler seems able to handle the request self.__log.info("Candidate RPC handler found") expects_response = rpc_config.get("responseTopicExpression") defines_timeout = rpc_config.get("responseTimeout") # 2-way RPC setup if expects_response and defines_timeout: expected_response_topic = rpc_config["responseTopicExpression"] \ .replace("${deviceName}", str(content["device"])) \ .replace("${methodName}", str(content["data"]["method"])) \ .replace("${requestId}", str(content["data"]["id"])) expected_response_topic = TBUtility.replace_params_tags( expected_response_topic, content) timeout = time() * 1000 + rpc_config.get("responseTimeout") # Start listenting on the response topic self.__log.info("Subscribing to: %s", expected_response_topic) self.__subscribe(expected_response_topic, rpc_config.get("responseTopicQoS", 1)) # Wait for subscription to be carried out sub_response_timeout = 10 while expected_response_topic in self.__subscribes_sent.values( ): sub_response_timeout -= 1 sleep(0.1) if sub_response_timeout == 0: break # Ask the gateway to enqueue this as an RPC response self.__gateway.register_rpc_request_timeout( content, timeout, expected_response_topic, self.rpc_cancel_processing) # Wait for RPC to be successfully enqueued, which never fails. while self.__gateway.is_rpc_in_progress( expected_response_topic): sleep(0.1) elif expects_response and not defines_timeout: self.__log.info( "2-way RPC without timeout: treating as 1-way") # Actually reach out for the device request_topic: str = rpc_config.get("requestTopicExpression") \ .replace("${deviceName}", str(content["device"])) \ .replace("${methodName}", str(content["data"]["method"])) \ .replace("${requestId}", str(content["data"]["id"])) request_topic = TBUtility.replace_params_tags( request_topic, content) data_to_send_tags = TBUtility.get_values( rpc_config.get('valueExpression'), content['data'], 'params', get_tag=True) data_to_send_values = TBUtility.get_values( rpc_config.get('valueExpression'), content['data'], 'params', expression_instead_none=True) data_to_send = rpc_config.get('valueExpression') for (tag, value) in zip(data_to_send_tags, data_to_send_values): data_to_send = data_to_send.replace( '${' + tag + '}', str(value)) try: self.__log.info("Publishing to: %s with data %s", request_topic, data_to_send) self._client.publish(request_topic, data_to_send, retain=rpc_config.get( 'retain', False)) if not expects_response or not defines_timeout: self.__log.info( "One-way RPC: sending ack to ThingsBoard immediately" ) self.__gateway.send_rpc_reply( device=content["device"], req_id=content["data"]["id"], success_sent=True) # Everything went out smoothly: RPC is served return except Exception as e: self.__log.exception(e) self.__log.error("RPC not handled: %s", content)
def _convert_json_file(self, data): dict_result = { "deviceName": None, "deviceType": None, "attributes": [], "telemetry": [] } try: if self.__config.get("devicePatternName") is not None: device_name_tags = TBUtility.get_values( self.__config.get("devicePatternName"), data, get_tag=True) device_name_values = TBUtility.get_values( self.__config.get("devicePatternName"), data, expression_instead_none=True) dict_result["deviceName"] = self.__config.get( "devicePatternName") for (device_name_tag, device_name_value) in zip(device_name_tags, device_name_values): is_valid_key = "${" in self.__config.get("devicePatternName") and "}" in \ self.__config.get("devicePatternName") dict_result['deviceName'] = dict_result['deviceName'].replace('${' + str(device_name_tag) + '}', str(device_name_value)) \ if is_valid_key else device_name_tag else: log.error( "The expression for looking \"deviceName\" not found in config %s", dumps(self.__config)) if self.__config.get("devicePatternType") is not None: device_type_tags = TBUtility.get_values( self.__config.get("devicePatternType"), data, get_tag=True) device_type_values = TBUtility.get_values( self.__config.get("devicePatternType"), data, expression_instead_none=True) dict_result["deviceType"] = self.__config.get( "devicePatternType") for (device_type_tag, device_type_value) in zip(device_type_tags, device_type_values): is_valid_key = "${" in self.__config.get("devicePatternType") and "}" in \ self.__config.get("devicePatternType") dict_result["deviceType"] = dict_result["deviceType"].replace('${' + str(device_type_tag) + '}', str(device_type_value)) \ if is_valid_key else device_type_tag 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 self.__data_types: dict_result[self.__data_types[datatype]] = [] for datatype_config in self.__config.get(datatype, []): values = TBUtility.get_values(datatype_config["value"], data, datatype_config["type"], expression_instead_none=True) values_tags = TBUtility.get_values( datatype_config["value"], data, datatype_config["type"], get_tag=True) keys = TBUtility.get_values(datatype_config["key"], data, datatype_config["type"], expression_instead_none=True) keys_tags = TBUtility.get_values(datatype_config["key"], data, get_tag=True) full_key = datatype_config["key"] for (key, key_tag) in zip(keys, keys_tags): is_valid_key = "${" in datatype_config["key"] and "}" in \ datatype_config["key"] full_key = full_key.replace( '${' + str(key_tag) + '}', str(key)) if is_valid_key else key_tag full_value = datatype_config["value"] for (value, value_tag) in zip(values, values_tags): is_valid_value = "${" in datatype_config["value"] and "}" in \ datatype_config["value"] full_value = full_value.replace( '${' + str(value_tag) + '}', str(value)) if is_valid_value else str(value) if datatype == 'timeseries' and (data.get("ts") is not None or data.get("timestamp") is not None): dict_result[self.__data_types[datatype]].append({ "ts": data.get('ts', data.get('timestamp', int(time()))), 'values': { full_key: full_value } }) else: dict_result[self.__data_types[datatype]].append( {full_key: full_value}) except Exception as e: log.error( 'Error in converter, for config: \n%s\n and message: \n%s\n', dumps(self.__config), str(data)) log.exception(e) return dict_result
def convert(self, config, data): datatypes = {"attributes": "attributes", "timeseries": "telemetry"} dict_result = {"deviceName": None, "deviceType": None, "attributes": [], "telemetry": []} try: if self.__config.get("deviceNameJsonExpression") is not None: device_name_tags = TBUtility.get_values(self.__config.get("deviceNameJsonExpression"), data, get_tag=True) device_name_values = TBUtility.get_values(self.__config.get("deviceNameJsonExpression"), data, expression_instead_none=True) dict_result['deviceName'] = self.__config.get("deviceNameJsonExpression") for (device_name_tag, device_name_value) in zip(device_name_tags, device_name_values): is_valid_key = "${" in self.__config.get("deviceNameJsonExpression") and "}" in \ self.__config.get("deviceNameJsonExpression") dict_result['deviceName'] = dict_result['deviceName'].replace('${' + str(device_name_tag) + '}', str(device_name_value)) \ if is_valid_key else device_name_tag 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: device_type_tags = TBUtility.get_values(self.__config.get("deviceTypeJsonExpression"), data, get_tag=True) device_type_values = TBUtility.get_values(self.__config.get("deviceTypeJsonExpression"), data, expression_instead_none=True) dict_result["deviceType"] = self.__config.get("deviceTypeJsonExpression") for (device_type_tag, device_type_value) in zip(device_type_tags, device_type_values): is_valid_key = "${" in self.__config.get("deviceTypeJsonExpression") and "}" in \ self.__config.get("deviceTypeJsonExpression") dict_result["deviceType"] = dict_result["deviceType"].replace('${' + str(device_type_tag) + '}', str(device_type_value)) \ if is_valid_key else device_type_tag 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, []): values = TBUtility.get_values(datatype_config["value"], data, datatype_config["type"], expression_instead_none=True) values_tags = TBUtility.get_values(datatype_config["value"], data, datatype_config["type"], get_tag=True) keys = TBUtility.get_values(datatype_config["key"], data, datatype_config["type"], expression_instead_none=True) keys_tags = TBUtility.get_values(datatype_config["key"], data, get_tag=True) full_key = datatype_config["key"] for (key, key_tag) in zip(keys, keys_tags): is_valid_key = "${" in datatype_config["key"] and "}" in \ datatype_config["key"] full_key = full_key.replace('${' + str(key_tag) + '}', str(key)) if is_valid_key else key_tag full_value = datatype_config["value"] for (value, value_tag) in zip(values, values_tags): is_valid_value = "${" in datatype_config["value"] and "}" in \ datatype_config["value"] full_value = full_value.replace('${' + str(value_tag) + '}', str(value)) if is_valid_value else str(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