【问题标题】:Link Raspberry Pi #1 to Rapsberry Pi #2 using AWS as MQTT Broker使用 AWS 作为 MQTT 代理将 Raspberry Pi #1 链接到 Raspberry Pi #2
【发布时间】:2018-01-04 15:15:07
【问题描述】:

所以我有一个 Raspberry Pi #1,它将通过主题 sensors/Button 向 AWS 发布一条 MQTT 消息。这将在按下按钮时触发,如下所示。

# Import SDK packages
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
from time import sleep
from gpiozero import Button
from signal import pause

button = Button(13, pull_up=False)

def callMQTT():
    print("button is pressed.Sending to MQTT")
    mqtt_message = "{\"message\":\"button_pressed\"}"
    print(mqtt_message)
    my_rpi.publish("sensors/Button", mqtt_message, 1)
    print("Message Published!")
    sleep(5)


host="host.amazonaws.com"
rootCAPath = "rootca.pem"
certificatePath = "certificate.pem.crt"
privateKeyPath = "private.pem.key"

try:
    my_rpi = AWSIoTMQTTClient("basicPubSub")
    my_rpi.configureEndpoint(host,8883)
    my_rpi.configureCredentials(rootCAPath, privateKeyPath, certificatePath)

    my_rpi.configureOfflinePublishQueueing(-1)  # Infinite offline Publish queueing
    my_rpi.configureDrainingFrequency(2)  # Draining: 2 Hz

    # Connect and subscribe to AWS IoT
    my_rpi.connect()
    print("Connection Succesful")
except:
    print("Unexpected error:", sys.exc_info()[0])

button.when_pressed = callMQTT
pause()

在 Raspberry Pi #2 上,它将尝试使用与 Raspbery Pi #1 相同的主机、相同的事物、相同的密钥和相同的证书从 AWS 订阅 MQTT。如果收到消息,它会发出蜂鸣声并点亮 LED,如下图所示。

# Import SDK packages
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
from time import sleep
from gpiozero import Buzzer,LED
import random
import sys
from datetime import datetime

bz = Buzzer(22)
led = LED(18)

# Custom MQTT message callback
def customCallback(client, userdata, message):
    print("Received a new message: ")
    print(message.payload)
    print("from topic: ")
    print(message.topic)
    print("--------------\n\n")
        timestring = str(datetime.now())
    print("Doorbell pressed")
    bz.on()
    led.blink()
    sleep(1)
    bz.off()
    led.off()

host="host.amazonaws.com"
rootCAPath = "rootca.pem"
certificatePath = "certificate.pem.crt"
privateKeyPath = "private.pem.key"

try:
    my_rpi = AWSIoTMQTTClient("basicPubSub")
    my_rpi.configureEndpoint(host, 8883)
    my_rpi.configureCredentials(rootCAPath, privateKeyPath, certificatePath)

    my_rpi.configureOfflinePublishQueueing(-1)  # Infinite offline Publish queueing
    my_rpi.configureDrainingFrequency(2)  # Draining: 2 Hz
    my_rpi.configureConnectDisconnectTimeout(10)  # 10 sec
    my_rpi.configureMQTTOperationTimeout(5)  # 5 sec

    # Connect and subscribe to AWS IoT
    my_rpi.connect()
except:
    print("Unexpected error:", sys.exc_info()[0])

while True:
my_rpi.subscribe("sensors/Button", 1, customCallback)
sleep(2)

但是,这是不可能的。当两个程序同时运行时,Rasberry Pi #2 将始终超时。由于某种原因,它一次只允许 1 个连接。 当我运行 Raspberry Pi #1 代码时,我尝试直接通过 AWS 订阅主题。它在 AWS 上显示消息。此外,如果我尝试直接在 AWS 上发布消息并仅运行 Raspberry Pi #2 代码,它也可以正常工作,但在同时运行代码时就不行了。我在 Raspberry Pi #2 上遇到的错误是这样的:

找不到记录器的处理程序 "AWSIoTPythonSDK.core.protocol.mqttCore" Traceback(最近调用 最后):文件“Doorbell_Indoor.py”,第 72 行,在 my_rpi.subscribe("sensors/Button", 1, customCallback) 文件 "/usr/local/lib/python2.7/dist-packages/AWSIoTPythonSDK/MQTTLib.py", 第 491 行,订阅中 return self._mqttCore.subscribe(topic, QoS, callback) 文件“/usr/local/lib/python2.7/dist-packages/AWSIoTPythonSDK/core/protocol/mqttCore.py”, 第 416 行,订阅中 raise subscribeTimeoutException() AWSIoTPythonSDK.exception.AWSIoTExceptions.subscribeTimeoutException

有人知道如何解决这个问题吗?提前致谢!

【问题讨论】:

  • 每个客户端必须有一个唯一的客户端ID,最好的猜测是传递给AWSIoTMQTTClient()的字符串就是客户端ID,让这些不同,看看会发生什么

标签: python amazon-web-services raspberry-pi mqtt aws-iot


【解决方案1】:

我没有在 Python SDK 文档中看到它,但在 Java SDK 文档中它说:

clientId - 唯一标识 MQTT 连接的客户端 ID。二 不允许连接具有相同客户端 ID 的客户端 并发到同一个端点。

尝试为每个连接使用唯一的 clientId 值,而不是 "basicPubSub"

【讨论】:

  • 在哪里可以找到clientId? AWS 似乎没有。我自己编clientId吗?
  • 你弥补。您应该为每个正在运行的脚本使用不同的 id。
【解决方案2】:

来自http://docs.aws.amazon.com/iot/latest/developerguide/protocols.html

消息代理使用客户端 ID 来识别每个客户端。客户端 ID 作为 MQTT 有效负载的一部分从客户端传递到消息代理。不允许两个具有相同客户端 ID 的客户端同时连接到消息代理。当客户端使用另一个客户端正在使用的客户端 ID 连接到消息代理时,将向两个客户端发送 CONNACK 消息 >并且当前连接的客户端将断开连接。

您必须将每个客户端的唯一字符串传递给 AWSIoTMQTTClient() 或一个空字符串。如果您为客户端 ID 传递一个空字符串,AWS IoT 网关将在连接时为您分配一个随机客户端 ID。

更改 AWSIoTMQTTClient 调用

my_rpi = AWSIoTMQTTClient("basicPubSub")

my_rpi = AWSIoTMQTTClient("")

每个 RPI 将在连接时分配一个唯一的随机客户端 ID。 AWS 不建议大规模执行此操作,但它适用于测试。您也无法在策略中使用 clientid。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-03
    • 2021-12-01
    • 2019-05-11
    相关资源
    最近更新 更多