简体   繁体   English

mqtt客户端在线程和rest-api的情况下不接收消息

[英]mqtt client does not receive message in case of thread and rest-api

I have a python script, which based on flask and mqtt.我有一个基于flask和mqtt的python脚本。 The use case is to receive a request via rest-api then to create a new thread which publishes some messages on mosquitto mqtt and expects a response (see subscribe).用例是通过 rest-api 接收请求,然后创建一个新线程,该线程在 mosquitto mqtt 上发布一些消息并期待响应(请参阅订阅)。 My problem is that I don't receive any messages.我的问题是我没有收到任何消息。 I think it has something to do with the thread, because without the thread it's working very fine.. Do you know what can be the problem?我认为这与线程有关,因为没有线程它工作得很好..你知道可能是什么问题吗?

Thank you in anticipation!谢谢期待!

here the code:这里的代码:

from flask import Flask, Response
import paho.mqtt.client as mqtt
from threading import Thread
import threading

app = Flask(__name__)
lock = threading.Lock()

def on_connect(client, userdata, flags, rc):  # The callback for when the client connects to the broker
    print("Connected with result code {0}".format(str(rc)))  # Print result of connection attempt
    client.subscribe("/mytopic")


def on_message(client, userdata, msg):  # The callback for when a PUBLISH message is received from the server.
    print(msg.topic)


client = mqtt.Client(client_id=client_name, clean_session=True)
client.on_connect = on_connect  # Define callback function for successful connection
client.on_message = on_message  # Define callback function for receipt of a message
client.username_pw_set(mqtt_user, mqtt_password)
client.loop_start()
client.connect(mqtt_host)    


def test(param1, param2):
   lock.acquire()
   try:

      ret = client.publish("/mytopic", "")
      while True:
            check the response from mqtt => but i don't get the response anymore
            ....
            break
    finally:
        lock.release()
    return result


@app.route('/test/check', methods=['POST'])
def check():
    global sessionId
    sessionId = sessionId + 1
    t = Thread(target=test, args=(sessionId,None))
    t.start()
    return {'id': sessionId, 'eta': 0}


if __name__ == '__main__':
    app.run(debug=True)

There are a couple of problems with this.这有几个问题。

  1. Both the client.connect() and the client.subscribe() calls need iterations of the client network loop to run in order to complete properly. client.connect()client.subscribe()调用都需要客户端网络循环的迭代才能运行才能正确完成。
  2. The network loop needs to run at least once every keep alive period the time after the connection has been made in order to stop the broker disconnecting the client as dead.网络循环需要在连接建立后的每个保持活动期间至少运行一次,以阻止代理将客户端断开连接为死机。 This means if there is a delay between starting the code and the first REST request then the client will be disconnected.这意味着如果启动代码和第一个 REST 请求之间存在延迟,则客户端将断开连接。

Better to use the client.start_loop() function to run MQTT client network loop continuously in the background on it's own.最好使用client.start_loop()函数自行在后台连续运行 MQTT 客户端网络循环。

You should also remove the call to client.subscribe() that is outside the on_connect() callback.你也应该删除调用client.subscribe()是外on_connect()回调。

EDIT: As hashed out in the comments/chat the following works.编辑:正如评论/聊天中所讨论的,以下作品。 It looks like running the flask app in debug mode does some strange things and creates multiple MQTT clients over and over again with the same client id.看起来在调试模式下运行 Flask 应用程序会做一些奇怪的事情,并使用相同的客户端 ID 一遍又一遍地创建多个 MQTT 客户端。 This leads to the broker constantly kicking the old ones off so messages never get delivered.这导致经纪人不断地踢掉旧的,因此消息永远不会被传递。

from flask import Flask, Response
import paho.mqtt.client as mqtt
import time
from threading import Thread
import threading

app = Flask(__name__)
lock = threading.Lock()
sessionId=0
cont=True

def on_connect(client, userdata, flags, rc): # The callback for when the client connects to the broker
print("Connected with result code {0}".format(str(rc))) # Print result of connection attempt
client.subscribe("mytopic")


def on_message(client, userdata, msg): # The callback for when a PUBLISH message is received from the server.
global cont
print(msg.topic)
cont=False


client = mqtt.Client(client_id="foo", clean_session=True)
client.on_connect = on_connect # Define callback function for successful connection
client.on_message = on_message # Define callback function for receipt of a message
#client.username_pw_set(mqtt_user, mqtt_password)
client.connect("localhost", port=1884)
client.loop_start()

def test(param1, param2):
lock.acquire()
try:
ret = client.publish("mytopic", "foo")
while cont:
time.sleep(5)
print("loop")
finally:
lock.release()

result = "foo"

return result


@app.route('/test/check', methods=['POST'])
def check():
global sessionId
sessionId = sessionId + 1
t = Thread(target=test, args=(sessionId,None))
t.start()
return {'id': sessionId, 'eta': 0}


if __name__ == '__main__':
print("started")
app.run()

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

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