同样使用信号库的 MQTT 发布者脚本中的管道损坏错误



我从pimoroni买了一个触摸phat,我正在使用我的Raspberry Pi Zero W(拉伸操作系统)。触摸phat基本上是覆盆子设备的电容式按钮附加罩。(https://shop.pimoroni.com/products/touch-phat)。我决定在我的触摸 phat python 脚本中实现 Paho MQTT 函数,该脚本取自 pimoroni 示例脚本 (https://github.com/pimoroni/touch-phat/blob/master/examples/buttons.py)。例如,当我按下"A"按钮时,脚本会将 MQTT 消息发布到另一个同时运行的脚本(MQTT 客户端),通知该按钮已被按下,MQTT 客户端脚本将执行最后的操作(例如播放音频文件)。当我的脚本处于非活动状态大约 5 分钟时,就会出现问题。当我再次触摸按钮时,终端会打印一个错误,指出带有 MQTT 发布者函数的触摸脚本的管道 ([Errno 32] Broken pipe) 损坏。随后尝试按下触摸按钮不会导致在终端上打印相同的错误(管道损坏),但 MQTT 客户端无法接收任何进一步的消息。我怀疑 MQTT 发布者脚本的signal.pause()可能导致 MQTT 发布者和 MQTT 客户端通信在短时间不活动后永久切断。对此有什么想法吗?如何解决此问题?或者,如何在脚本中自动重新建立连接,而无需重新启动这些 python 脚本。

我的 MQTT 发布者脚本的代码是:

#!/usr/bin/env python
import paho.mqtt.client as mqtt
import paho.mqtt.publish as publish
import signal
import time
import os
import touchphat
mqttc = mqtt.Client("client1", clean_session=False)
mqttc.username_pw_set("user", "mypassword")
mqttc.connect("m14.cloudmqtt.com", 21543, 50)

@touchphat.on_touch(['A'])
def handle_touch(event):
mqttc.publish("touchphat", payload="A", qos=0)
print("Button A pressed")

@touchphat.on_touch(['B'])
def handle_touch(event):
mqttc.publish("touchphat", payload="B", qos=0)
print("Button B pressed")

@touchphat.on_touch(['Back'])
def handle_touch(event):
mqttc.publish("touchphat", payload="Back", qos=0)
print("Button back pressed")
@touchphat.on_touch(['Enter'])
def handle_touch(event):
mqttc.publish("touchphat", payload="Enter", qos=0)
print("Button Enter pressed")
signal.pause() # I think this might be causing the broken pipe problem but I am not sure.

MQTT 客户端脚本为:

#!/usr/bin/env python
import signal
import time
from subprocess import call# added for aplay
import touchphat
import paho.mqtt.client as mqtt

def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
client.subscribe("touchphat")
def on_message(client, userdata, msg):
print(msg.topic+" "+str(msg.payload))
if msg.topic == "touchphat":
if msg.payload == "A":
print("button A is pressed")
call(["aplay", "/home/pi/projectfolder/music.wav"])
if msg.topic == "touchphat":
if msg.payload == "B":
print("button B is pressed")
if msg.topic == "touchphat":
if msg.payload == "Back":
print("button Back is pressed")
if msg.topic == "touchphat":
if msg.payload == "Enter":
print("button Enter is pressed")
# Create an MQTT client and attach our routines to it.
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.username_pw_set("user", "mypassword") 
client.connect("m14.cloudmqtt.com", 21543, 50) 
client.loop_forever()

我看到您的端口是 21543,这可能表示 cloudmqtt 上的 ssl 端口。检查您的帐户,如果是,请在连接之前使用非 SSL 端口或在客户端上调用 tls_set_context()。

您需要让发布者中的 MQTT 客户端处理网络事件,为此您需要启动网络循环。最简单的方法应该是将signal.pause()替换为client.loop_forever()

最新更新