MQTT发布者脚本中也使用信号库的管道错误

时间:2018-01-12 11:00:01

标签: python raspberry-pi mqtt

我从我的Raspberry Pi Zero W(拉伸操作系统)上使用的pimoroni上买了一个触摸phat。 Touch phat基本上是一个用于覆盆子设备屏蔽的电容式按钮。(https://shop.pimoroni.com/products/touch-phat)。我决定在我的touch phat python脚本中实现Paho MQTT函数,我从pimoroni示例脚本(https://github.com/pimoroni/touch-phat/blob/master/examples/buttons.py)中获取。例如,当我按下A' A'按钮,脚本将MQTT消息发布到另一个同时运行的脚本(MQTT客户端),通知按钮已被按下,MQTT客户端脚本将执行最终操作(例如播放音频文件)。当我的脚本处于非活动状态大约5分钟时出现问题。当我再次触摸该按钮时,终端会打印一个错误,指出具有MQTT发布者功能的touchphat脚本的管道损坏([Errno 32] Broken pipe)。按下touchphat按钮的后续尝试不会导致在终端上打印相同的错误(损坏的管道),但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()

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

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