【问题标题】:Trying to send one message via MQTT and sleep for 5 seconds尝试通过 MQTT 发送一条消息并休眠 5 秒
【发布时间】:2020-05-01 15:27:30
【问题描述】:

我目前正在尝试通过有效的 MQTT 协议发送消息。我使用树莓派和振动传感器作为触发消息发送的手段。一开始我会触摸传感器,它会立即发送大量消息,这是我不希望发生的。所以我试着让它在检测到振动后休眠 5 秒钟。但是现在它检测到一种振动,然后不会检测到另一种振动,但不会停止文件的运行。我能让它再次检测到振动的唯一方法是再次运行文件。这是我尝试的两种方法:

import time
from grove.gpio import GPIO

import paho.mqtt.client as mqttClient


class GrovePiezoVibrationSensor(GPIO):
    def __init__(self, pin):
        super(GrovePiezoVibrationSensor, self).__init__(pin, GPIO.IN)
        self._on_detect = None

    @property
    def on_detect(self):
        return self._on_detect

    @on_detect.setter
    def on_detect(self, callback):
        if not callable(callback):
            return

        if self.on_event is None:
            self.on_event = self._handle_event

        self._on_detect = callback

    def _handle_event(self, pin, value):
        if value:
            if callable(self._on_detect):
                self._on_detect()
                time.sleep(5000)


Grove = GrovePiezoVibrationSensor
def on_connect(client, userdata, flags, rc):

    if rc == 0:

        print("Connected to broker")

        global Connected                #Use global variable
        Connected = True                #Signal connection

    else:

        print("Connection failed")

Connected = False   #global variable for the state of the connection

broker_address= "hairdresser.cloudmqtt.com"
port = 15767
user = "kprpjfue"
password = "1fIq2_CIwHZj"
client = mqttClient.Client("Python")               #create new instance
client.username_pw_set(user, password=password)    #set username and password
client.on_connect= on_connect
client.loop_start()

client.connect(broker_address, port=port)



def main():
    from grove.helper import SlotHelper
    sh = SlotHelper(SlotHelper.GPIO)
    pin = sh.argv2pin()

    pir = GrovePiezoVibrationSensor(pin)

    def callback():
        print('Detected.')
        value = 'detected'
        client.publish("sensor/Temp", value)

    pir.on_detect = callback
    while True:
        time.sleep(5000)

if __name__ == '__main__':
    main()


while Connected != True:    #Wait for connection
    time.sleep(0.1)

import time
from grove.gpio import GPIO

import paho.mqtt.client as mqttClient


class GrovePiezoVibrationSensor(GPIO):
    def __init__(self, pin):
        super(GrovePiezoVibrationSensor, self).__init__(pin, GPIO.IN)
        self._on_detect = None

    @property
    def on_detect(self):
        return self._on_detect

    @on_detect.setter
    def on_detect(self, callback):
        if not callable(callback):
            return

        if self.on_event is None:
            self.on_event = self._handle_event

        self._on_detect = callback

    def _handle_event(self, pin, value):
        if value:
            if callable(self._on_detect):
                self._on_detect()
                time.sleep(5000)


Grove = GrovePiezoVibrationSensor
def on_connect(client, userdata, flags, rc):

    if rc == 0:

        print("Connected to broker")

        global Connected                #Use global variable
        Connected = True                #Signal connection

    else:

        print("Connection failed")

Connected = False   #global variable for the state of the connection

broker_address= "hairdresser.cloudmqtt.com"
port = 15767
user = "kprpjfue"
password = "1fIq2_CIwHZj"
client = mqttClient.Client("Python")               #create new instance
client.username_pw_set(user, password=password)    #set username and password
client.on_connect= on_connect

client.connect(broker_address, port=port)



def main():
    from grove.helper import SlotHelper
    sh = SlotHelper(SlotHelper.GPIO)
    pin = sh.argv2pin()

    pir = GrovePiezoVibrationSensor(pin)

    def callback():
        print('Detected.')
        value = 'detected'
        client.publish("sensor/Temp", value)

    pir.on_detect = callback
    while True:
        time.sleep(5000)
        client.loop()

if __name__ == '__main__':
    main()


while Connected != True:    #Wait for connection
    time.sleep(0.1)

正如您在句柄事件方法中的 if callable 下看到的,我告诉过我说的是 time.sleep(5000)。我是不是放错地方了?

【问题讨论】:

  • 不,你应该有一个或另一个。 client.loop_start()client.loop(),不能同时使用。
  • 它们似乎都不起作用。我更新了我的问题,以确保我做的都是正确的。
  • 无论系统的其他部分是否按照您的意愿行事,您都需要其中之一才能让您的 MQTT 客户端正常工作。

标签: python raspberry-pi mqtt sensors


【解决方案1】:

您尚未启动 MQTT 客户端网络循环,因此它将无法接收消息或发送大于 MTU 的消息。

在保活期过后,您也会断开连接。

在调用client.connect()之前添加client.loop_start()

或在 main 循环中的 time.sleep(5000) 之后插入 client.loop(),最好将其设置为 1000 以使客户端循环至少每秒运行一次。

在回调中添加睡眠通常是一个坏主意,因为它不会阻止事件被触发,只会延迟它们,因为它们只会排队直到睡眠超时。

您应该在发送 MQTT 消息之后在第一个事件上设置一个标志,然后您可以使用 main 中的 While True 循环使该标志过期。如果在标志仍然设置的情况下出现新事件,那么您只需不发送另一条 MQTT 消息。

【讨论】:

  • 第一种放置client.start_loop()的方法会抛出这个错误client object has no attribute start_loop,而另一种只是做同样的事情,它只检测到一次振动并继续运行
  • 对不起,错字应该是loop_start()
  • 就在那里完成,它说连接到代理打印语句的原因,然后它就完成了运行
  • client.loop() 需要与主函数中 While True: 循环中的 time.sleep(5000) 后面的 time.sleep(5000) 一起使用
  • 在它继续运行的地方仍然相同,但只检测到一次振动。自从我在句柄事件中添加了time.sleep(5000) 以来,我需要它,因为它会一次发送太多消息。另外,我用所有更新编辑了我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-25
  • 1970-01-01
  • 2019-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-23
相关资源
最近更新 更多