def _on_message(self, client, userdata, message): content = TBUtility.decode(message) super()._on_decoded_message(content, message) self._on_decoded_message(content, message)
def _on_message(self, client, userdata, message): print("tb_gateway_mqtt _on_message", message.topic) print("self.__sub_dict=", self.__sub_dict) content = TBUtility.decode(message) super()._on_decoded_message(content, message) self._on_decoded_message(content, message)
def _on_message(self, client, userdata, message): self.statistics['MessagesReceived'] += 1 content = TBUtility.decode(message) # Check if message topic exists in mappings "i.e., I'm posting telemetry/attributes" --------------------------- topic_handlers = [ regex for regex in self.__mapping_sub_topics if fullmatch(regex, message.topic) ] if topic_handlers: # Note: every topic may be associated to one or more converter. This means that a single MQTT message # may produce more than one message towards ThingsBoard. This also means that I cannot return after # the first successful conversion: I got to use all the available ones. # I will use a flag to understand whether at least one converter succeeded request_handled = False for topic in topic_handlers: available_converters = self.__mapping_sub_topics[topic] for converter in available_converters: try: if isinstance(content, list): for item in content: request_handled = self.put_data_to_convert( converter, message, item) if not request_handled: self.__log.error( 'Cannot find converter for the topic:"%s"! Client: %s, User data: %s', message.topic, str(client), str(userdata)) else: request_handled = self.put_data_to_convert( converter, message, content) except Exception as e: log.exception(e) if not request_handled: self.__log.error( 'Cannot find converter for the topic:"%s"! Client: %s, User data: %s', message.topic, str(client), str(userdata)) # Note: if I'm in this branch, this was for sure a telemetry/attribute push message # => Execution must end here both in case of failure and success return None # Check if message topic exists in connection handlers "i.e., I'm connecting a device" ------------------------- topic_handlers = [ regex for regex in self.__connect_requests_sub_topics if fullmatch(regex, message.topic) ] if topic_handlers: for topic in topic_handlers: handler = self.__connect_requests_sub_topics[topic] found_device_name = None found_device_type = 'default' # Get device name, either from topic or from content if handler.get("deviceNameTopicExpression"): device_name_match = search( handler["deviceNameTopicExpression"], message.topic) if device_name_match is not None: found_device_name = device_name_match.group(0) elif handler.get("deviceNameJsonExpression"): found_device_name = TBUtility.get_value( handler["deviceNameJsonExpression"], content) # Get device type (if any), either from topic or from content if handler.get("deviceTypeTopicExpression"): device_type_match = search( handler["deviceTypeTopicExpression"], message.topic) found_device_type = device_type_match.group( 0) if device_type_match is not None else handler[ "deviceTypeTopicExpression"] elif handler.get("deviceTypeJsonExpression"): found_device_type = TBUtility.get_value( handler["deviceTypeJsonExpression"], content) if found_device_name is None: self.__log.error( "Device name missing from connection request") continue # Note: device must be added even if it is already known locally: else ThingsBoard # will not send RPCs and attribute updates self.__log.info("Connecting device %s of type %s", found_device_name, found_device_type) self.__gateway.add_device(found_device_name, {"connector": self}, device_type=found_device_type) # Note: if I'm in this branch, this was for sure a connection message # => Execution must end here both in case of failure and success return None # Check if message topic exists in disconnection handlers "i.e., I'm disconnecting a device" ------------------- topic_handlers = [ regex for regex in self.__disconnect_requests_sub_topics if fullmatch(regex, message.topic) ] if topic_handlers: for topic in topic_handlers: handler = self.__disconnect_requests_sub_topics[topic] found_device_name = None found_device_type = 'default' # Get device name, either from topic or from content if handler.get("deviceNameTopicExpression"): device_name_match = search( handler["deviceNameTopicExpression"], message.topic) if device_name_match is not None: found_device_name = device_name_match.group(0) elif handler.get("deviceNameJsonExpression"): found_device_name = TBUtility.get_value( handler["deviceNameJsonExpression"], content) # Get device type (if any), either from topic or from content if handler.get("deviceTypeTopicExpression"): device_type_match = search( handler["deviceTypeTopicExpression"], message.topic) if device_type_match is not None: found_device_type = device_type_match.group(0) elif handler.get("deviceTypeJsonExpression"): found_device_type = TBUtility.get_value( handler["deviceTypeJsonExpression"], content) if found_device_name is None: self.__log.error( "Device name missing from disconnection request") continue if found_device_name in self.__gateway.get_devices(): self.__log.info("Disconnecting device %s of type %s", found_device_name, found_device_type) self.__gateway.del_device(found_device_name) else: self.__log.info("Device %s was not connected", found_device_name) break # Note: if I'm in this branch, this was for sure a disconnection message # => Execution must end here both in case of failure and success return None # Check if message topic exists in attribute request handlers "i.e., I'm asking for a shared attribute" -------- topic_handlers = [ regex for regex in self.__attribute_requests_sub_topics if fullmatch(regex, message.topic) ] if topic_handlers: try: for topic in topic_handlers: handler = self.__attribute_requests_sub_topics[topic] found_device_name = None found_attribute_name = None # Get device name, either from topic or from content if handler.get("deviceNameTopicExpression"): device_name_match = search( handler["deviceNameTopicExpression"], message.topic) if device_name_match is not None: found_device_name = device_name_match.group(0) elif handler.get("deviceNameJsonExpression"): found_device_name = TBUtility.get_value( handler["deviceNameJsonExpression"], content) # Get attribute name, either from topic or from content if handler.get("attributeNameTopicExpression"): attribute_name_match = search( handler["attributeNameTopicExpression"], message.topic) if attribute_name_match is not None: found_attribute_name = attribute_name_match.group( 0) elif handler.get("attributeNameJsonExpression"): found_attribute_name = TBUtility.get_value( handler["attributeNameJsonExpression"], content) if found_device_name is None: self.__log.error( "Device name missing from attribute request") continue if found_attribute_name is None: self.__log.error( "Attribute name missing from attribute request") continue self.__log.info("Will retrieve attribute %s of %s", found_attribute_name, found_device_name) self.__gateway.tb_client.client.gw_request_shared_attributes( found_device_name, [found_attribute_name], lambda data, *args: self.notify_attribute( data, found_attribute_name, handler.get("topicExpression"), handler.get("valueExpression"), handler.get('retain', False))) break except Exception as e: log.exception(e) # Note: if I'm in this branch, this was for sure an attribute request message # => Execution must end here both in case of failure and success return None # Check if message topic exists in RPC handlers ---------------------------------------------------------------- # The gateway is expecting for this message => no wildcards here, the topic must be evaluated as is if self.__gateway.is_rpc_in_progress(message.topic): log.info("RPC response arrived. Forwarding it to thingsboard.") self.__gateway.rpc_with_reply_processing(message.topic, content) return None self.__log.debug( "Received message to topic \"%s\" with unknown interpreter data: \n\n\"%s\"", message.topic, content)
def _on_message(self, client, userdata, message): self.statistics['MessagesReceived'] += 1 content = TBUtility.decode(message) regex_topic = [ regex for regex in self.__sub_topics if fullmatch(regex, message.topic) ] if regex_topic: try: for regex in regex_topic: if self.__sub_topics.get(regex): for converter_value in range( len(self.__sub_topics.get(regex))): if self.__sub_topics[regex][converter_value]: for converter in self.__sub_topics.get( regex)[converter_value]: converted_content = converter.convert( message.topic, content) if converted_content: try: self.__sub_topics[regex][ converter_value][ converter] = converted_content except Exception as e: self.__log.exception(e) self.__gateway.send_to_storage( self.name, converted_content) self.statistics['MessagesSent'] += 1 else: continue else: self.__log.error( 'Cannot find converter for topic:"%s"!', message.topic) return except Exception as e: log.exception(e) return elif self.__service_config.get("connectRequests"): connect_requests = [ connect_request for connect_request in self.__service_config.get("connectRequests") ] if connect_requests: for request in connect_requests: if request.get("topicFilter"): if message.topic in request.get("topicFilter") or\ (request.get("deviceNameTopicExpression") is not None and search(request.get("deviceNameTopicExpression"), message.topic)): founded_device_name = None if request.get("deviceNameJsonExpression"): founded_device_name = TBUtility.get_value( request["deviceNameJsonExpression"], content) if request.get("deviceNameTopicExpression"): device_name_expression = request[ "deviceNameTopicExpression"] founded_device_name = search( device_name_expression, message.topic) if founded_device_name is not None and founded_device_name not in self.__gateway.get_devices( ): self.__gateway.add_device( founded_device_name, {"connector": self}) else: self.__log.error( "Cannot find connect request for device from message from topic: %s and with data: %s", message.topic, content) else: self.__log.error( "\"topicFilter\" in connect requests config not found." ) else: self.__log.error("Connection requests in config not found.") elif self.__service_config.get("disconnectRequests") is not None: disconnect_requests = [ disconnect_request for disconnect_request in self.__service_config.get("disconnectRequests") ] if disconnect_requests: for request in disconnect_requests: if request.get("topicFilter") is not None: if message.topic in request.get("topicFilter") or\ (request.get("deviceNameTopicExpression") is not None and search(request.get("deviceNameTopicExpression"), message.topic)): founded_device_name = None if request.get("deviceNameJsonExpression"): founded_device_name = TBUtility.get_value( request["deviceNameJsonExpression"], content) if request.get("deviceNameTopicExpression"): device_name_expression = request[ "deviceNameTopicExpression"] founded_device_name = search( device_name_expression, message.topic) if founded_device_name is not None and founded_device_name in self.__gateway.get_devices( ): self.__gateway.del_device(founded_device_name) else: self.__log.error( "Cannot find connect request for device from message from topic: %s and with data: %s", message.topic, content) else: self.__log.error( "\"topicFilter\" in connect requests config not found." ) else: self.__log.error("Disconnection requests in config not found.") elif message.topic in self.__gateway.rpc_requests_in_progress: self.__gateway.rpc_with_reply_processing(message.topic, content) else: self.__log.debug( "Received message to topic \"%s\" with unknown interpreter data: \n\n\"%s\"", message.topic, content)
def _on_message(self, client, userdata, message): self.statistics['MessagesReceived'] += 1 content = TBUtility.decode(message) # Check if message topic exists in mappings "i.e., I'm posting telemetry/attributes" regex_topic = [ regex for regex in self.__sub_topics if fullmatch(regex, message.topic) ] if regex_topic: try: for regex in regex_topic: if self.__sub_topics.get(regex): for converter_value in range( len(self.__sub_topics.get(regex))): if self.__sub_topics[regex][converter_value]: for converter in self.__sub_topics.get( regex)[converter_value]: converted_content = converter.convert( message.topic, content) if converted_content: try: self.__sub_topics[regex][ converter_value][ converter] = converted_content except Exception as e: self.__log.exception(e) self.__gateway.send_to_storage( self.name, converted_content) self.statistics['MessagesSent'] += 1 else: continue else: self.__log.error( 'Cannot find converter for the topic:"%s"! Client: %s, User data: %s', message.topic, str(client), str(userdata)) return None except Exception as e: log.exception(e) return None # Check if message topic is matched by an existing connection request handler if self.__service_config.get("connectRequests"): for request in self.__service_config["connectRequests"]: # Check that the current connection request handler defines a topic filter (mandatory) if request.get("topicFilter") is None: continue found_device_name = None found_device_type = 'default' # Extract device name and type from regexps, if any. # This cannot be postponed because message topic may contain wildcards if request.get("deviceNameJsonExpression"): found_device_name = TBUtility.get_value( request["deviceNameJsonExpression"], content) if request.get("deviceNameTopicExpression"): device_name_expression = request[ "deviceNameTopicExpression"] device_name_match = search(device_name_expression, message.topic) if device_name_match is not None: found_device_name = device_name_match.group(0) if request.get("deviceTypeJsonExpression"): found_device_type = TBUtility.get_value( request["deviceTypeJsonExpression"], content) if request.get("deviceTypeTopicExpression"): device_type_expression = request[ "deviceTypeTopicExpression"] found_device_type = search(device_type_expression, message.topic) # Check if request topic matches with message topic before of after regexp substitution if message.topic not in request.get("topicFilter"): sub_topic = message.topic # Substitute device name (if defined) in topic if found_device_name is not None: sub_topic = sub(found_device_name, "+", sub_topic) # Substitute device type in topic sub_topic = sub(found_device_type, "+", sub_topic) # If topic still not matches, this is not the correct handler if sub_topic not in request.get("topicFilter"): continue # I'm now sure that this message must be handled by this connection request handler if found_device_name is None: self.__log.error( "Device name missing from connection request") return None # Note: device must be added even if it is already known locally: else ThingsBoard # will not send RPCs and attribute updates self.__gateway.add_device(found_device_name, {"connector": self}, device_type=found_device_type) return None # Check if message topic is matched by an existing disconnection request handler if self.__service_config.get("disconnectRequests"): for request in self.__service_config["disconnectRequests"]: # Check that the current disconnection request handler defines a topic filter (mandatory) if request.get("topicFilter") is None: continue found_device_name = None found_device_type = 'default' # Extract device name and type from regexps, if any. # This cannot be postponed because message topic may contain wildcards if request.get("deviceNameJsonExpression"): found_device_name = TBUtility.get_value( request["deviceNameJsonExpression"], content) if request.get("deviceNameTopicExpression"): device_name_expression = request[ "deviceNameTopicExpression"] device_name_match = search(device_name_expression, message.topic) if device_name_match is not None: found_device_name = device_name_match.group(0) if request.get("deviceTypeJsonExpression"): found_device_type = TBUtility.get_value( request["deviceTypeJsonExpression"], content) if request.get("deviceTypeTopicExpression"): device_type_expression = request[ "deviceTypeTopicExpression"] found_device_type = search(device_type_expression, message.topic) # Check if request topic matches with message topic before of after regexp substitution if message.topic not in request.get("topicFilter"): sub_topic = message.topic # Substitute device name (if defined) in topic if found_device_name is not None: sub_topic = sub(found_device_name, "+", sub_topic) # Substitute device type in topic sub_topic = sub(found_device_type, "+", sub_topic) # If topic still not matches, this is not the correct handler if sub_topic not in request.get("topicFilter"): continue # I'm now sure that this message must be handled by this connection request handler if found_device_name is None: self.__log.error( "Device name missing from disconnection request") return None if found_device_name in self.__gateway.get_devices(): self.__log.info("Device %s of type %s disconnected", found_device_name, found_device_type) self.__gateway.del_device(found_device_name) else: self.__log.info("Device %s is already disconnected", found_device_name) return None if message.topic in self.__gateway.rpc_requests_in_progress: self.__gateway.rpc_with_reply_processing(message.topic, content) else: self.__log.debug( "Received message to topic \"%s\" with unknown interpreter data: \n\n\"%s\"", message.topic, content)