简体   繁体   English

将 paho MQTT 与 Python 中的另一个异步进程相结合

[英]Combine paho MQTT with another asyncio process in Python

I have a basic MQTTListener class in Python which listens for messages on certain topics and should start or stop an async process imported from another script.我在 Python 中有一个基本的 MQTTLListener class ,它侦听有关某些主题的消息,并且应该启动或停止从另一个脚本导入的异步进程。 This process runs forever, unless it is manually stopped.这个过程永远运行,除非它被手动停止。 Let's assume the Listener looks like this:让我们假设 Listener 看起来像这样:

import paho.mqtt.client as mqtt
import json
from python_file.py import async_forever_function

class MqttListener:

    def __init__(self, host, port, client_id):
        self.host = host
        self.port = port
        self.client_id = client_id
        self.client = mqtt.Client(client_id=self.client_id)
        self.client.connect(host=self.host, port=self.port)

    def on_connect(self, client, userdata, flags, rc):
        self.client.subscribe(topic=[("start", 1), ])
        self.client.subscribe(topic=[("stop", 1), ])
        logging.info(msg="MQTT - connected!")

    def on_disconnect(client, userdata, rc):
        logging.info(msg="MQTT - disconnected!")

    def on_message(self, client, userdata, message, ):
        print('PROCESSING MESSAGE', message.topic, message.payload.decode('utf-8'), )

        if message.topic == 'start':
            async_forever_function(param='start')
            print('process started')
        else:
            async_forever_function(param='stop')
            print('process removed')

    def start(self):
        self.client.on_connect = lambda client, userdata, flags, rc: self.on_connect(client, userdata, flags, rc)
        self.client.on_message = lambda client, userdata, message: self.on_message(client, userdata, message)
        self.client.on_disconnect = lambda client, userdata, rc: self.on_disconnect(client, userdata, rc)

        self.client.loop_start()

    def stop(self):
        self.client.loop_stop()

Now, this works for starting a new async process.现在,这适用于启动一个新的异步进程。 That is, async_function is correctly triggered when a message is posted on the start MQTT topic.也就是说,当一条消息发布到启动 MQTT 主题时,会正确触发 async_function。 However, once this async process is started, the listener is no longer able to receive/process messages from the stop MQTT topic and the async process will continue to run forever, when in fact it should have been stopped.然而,一旦这个异步进程启动,监听器将不再能够接收/处理来自停止 MQTT 主题的消息,并且异步进程将继续永远运行,而事实上它应该已经停止。

My question : how can I adapt the code of this class such that it can also process messages when an active async process is running in the background?我的问题:如何调整此 class 的代码,以便在后台运行活动异步进程时它也可以处理消息?

You can not do blocking tasks in the on_message() callback.您不能在on_message()回调中执行阻塞任务。

This call back runs on the MQTT client thread (the one started by the loop_start() function. This thread handles all network traffic and message handling, if you block it then it can't do any of that.此回调在 MQTT 客户端线程上运行(由loop_start() function 启动的线程。此线程处理所有网络流量和消息处理,如果您阻止它,则它无法执行任何操作。

If you want to call long running tasks from the on_message() callback you need to start a new thread for the long running task so it doesn't block the MQTT client loop.如果你想从on_message()回调中调用长时间运行的任务,你需要为长时间运行的任务启动一个新线程,这样它就不会阻塞 MQTT 客户端循环。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM