Paho Mqtt客户端无法在on_message中发布

时间:2020-07-29 12:43:06

标签: python mqtt paho

main方法中的publish调用不会向代理发送消息,而是返回(0,2)。 on_publish将不会被调用。 我不确定应该如何看待错误所在。我尝试了qos = 2并运行main方法async,但是它没有解决它。基本连接有效,因为调用了on_message。 mqtt-server也可以与其他项目一起正常工作。 有任何想法吗?

import paho.mqtt.client as mqtt
import subprocess
import shutil
import os
import glob
import logging
from datetime import datetime
import RPi.GPIO as GPIO
import time
from multiprocessing import Pool
GPIO.setmode(GPIO.BCM)

direction = 19
pwm = 26
GPIO.setup(direction, GPIO.OUT)
GPIO.setup(pwm, GPIO.OUT)

pwm = GPIO.PWM(pwm,19000)
speed = 0
pwm.start(speed)
running = False

client = mqtt.Client()
#First: pip3 install paho-mqtt
print("Starte Listener")

def start():
    GPIO.output(direction, GPIO.LOW)
    for dc in range(10, 40, 1):
        speed = dc 
        pwm.ChangeDutyCycle(speed)
        time.sleep(0.25)

def end():
    GPIO.output(direction, GPIO.LOW)
    for dc in list(reversed(range(0,40,1))):
        speed = dc 
        pwm.ChangeDutyCycle(speed)
        time.sleep(0.5)


def main(mqttClient):
    print("Started Spinning")
    running = True
    start()
    print(mqttClient.publish("scanner","shoot"))
    print("Waiting 124 seconds")
    time.sleep(124)
    print("ending spinning")
    end()
    print("finished spinning")
    running = False 

def on_connect2(client, userdata, flags, rc):
    client.subscribe("scanner",2)
    print("Connected "+str(rc))
    

# The callback for when a PUBLISH message is received from the server.
def on_message(mqttClient, userdata, msg):
    print("Recived message: "+str(msg.payload,'UTF-8'))
    if(str(msg.payload,'UTF-8') == "spin" and running == False):
        main(mqttClient)

def disconnected():
    print("Disconneted")

def on_publish(self, client, userdata, mid):
    print("onPublish")
    print(client,userdata,mid)

logger = logging.getLogger(__name__)
client.enable_logger(logger)

client.on_connect = on_connect2
client.on_message = on_message
client.on_publish = on_publish
client.on_disconnect = disconnected
client.username_pw_set("....","....")
client.connect("gx1", 1883,60)
client.loop_forever()

2 个答案:

答案 0 :(得分:0)

作为一个快速修复程序,我创建了一个新客户端:

def main(mqttClient):
    print("Started Spinning")
    running = True
    start()
    mq = mqtt.Client("shot_idicator")
    mq.username_pw_set("...","...")
    mq.connect("gx1", 1883,60)
    mq.publish("scanner","shoot")
    mq.disconnect()
    mq = None
    print("Waiting 124 seconds")
    time.sleep(124)
    print("ending spinning")
    end()
    print("finished spinning")
    running = False 

现在它可以工作了,但我认为这不是应该做的事。

答案 1 :(得分:0)

这是因为您正在阻止MQTT客户端线程。

调用client.loop_forever()时,它将接管进程主线程,并使用它来处理所有MQTT通信。收到新消息后,MQTT客户端线程将其从网络堆栈中拾取,并转换为消息对象,然后将其传递给on_message()回调。此功能在客户端线程上运行。

当您致电client.publish()时,这将做2件事之一

  1. 如果消息是QOS 0且小于网络MTU,它将发布消息。
  2. 如果消息的质量QOS 1或2或大于网络MTU,则它将把消息排队,由客户端线程处理。

代码中的问题*是您将main()的返回阻止了124秒,这反过来又阻止了on_message()函数的返回,因此客户端线程无法发布您的消息。

如果您想花点时间或在on_message()(或任何回调函数)中执行操作,则应该启动一个单独的线程来运行它们。

*从理论上讲,您的消息看起来应该属于上述情况1,但可能还有其他因素导致它排队)