2017-07-28 3 views
1

So habe ich einen Raspberry Pi # 1, der eine MQTT-Nachricht an AWS über ein Thema sensors/Button veröffentlichen wird. Dies wird ausgelöst, wenn eine Taste gedrückt wird, wie unten gezeigt.Link Raspberry Pi # 1 zu Rapsberry Pi # 2 mit AWS als MQTT Broker

# 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() 

Auf Raspberry Pi # 2, wird es versuchen, die MQTT von AWS mit dem gleichen Host, gleiche, gleichen Schlüssel und gleiches Zertifikat wie Raspbery Pi # 1 zu abonnieren. Wenn eine Nachricht empfangen wird, ertönt der Summer und die LED leuchtet wie unten gezeigt.

# 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) 

Dies ist jedoch nicht möglich. Wenn beide Programme gleichzeitig laufen, wird Rasberry Pi # 2 immer Timeout. Aus irgendeinem Grund erlaubt es nur 1 Verbindung gleichzeitig. Ich versuche, das Thema direkt über AWS zu abonnieren, wenn ich Raspberry Pi # 1-Code ausführen. Es zeigt die Nachricht in AWS an. Wenn ich versuche, eine Nachricht direkt auf AWS zu veröffentlichen und nur Raspberry Pi # 2-Code auszuführen, funktioniert das auch, aber nicht, wenn beide den Code ausführen. Der Fehler, den ich auf Raspberry Pi # 2 bekam, ist dies:

No-Handler für Logger gefunden werden konnte "AWSIoTPythonSDK.core.protocol.mqttCore" Traceback (jüngste Aufforderung zuletzt): File "Doorbell_Indoor.py" , Zeile 72, in my_rpi.subscribe ("sensors/Button", 1, customCallback) Datei "/usr/local/lib/python2.7/dist-packages/AWSIoTPythonSDK/MQTTLib.py", Zeile 491, in subscribe return self._mqttCore.subscribe (Thema, QoS, Rückruf) Datei "/usr/local/lib/python2.7/dist-packages/AWSIoTPythonSDK/core/protocol/mqttCore.py", Zeile 416, in abonnieren erhöhen subscribeTimeoutException() AWSIoTPythonSDK.exception.AWSIoTExceptions.sub scribeTimeoutException

Weiß jemand, wie man das repariert? Danke im Voraus!

+0

Jeder Client muss eine eindeutige Client-ID haben, am besten raten wir, dass die an 'AFSIoTMQTTClient() 'übergebene Zeichenfolge die Client-ID ist, diese anders aussehen und sehen, was passiert – hardillb

Antwort

1

Ich sehe es nicht in der Python-SDK-Dokumentation dokumentiert, aber in der Java SDK-Dokumentation heißt es:

clientId - die Client-ID eindeutig eine MQTT Verbindung identifizieren. Zwei Clients mit der gleichen Client-ID dürfen nicht gleichzeitig mit demselben Endpunkt verbunden sein .

Verwenden Sie einen eindeutigen clientId Wert für jede Verbindung anstelle von "basicPubSub".

+0

Wo finde ich die clientId? AWS scheint es nicht zu haben. Mache ich meine eigene clientId? –

+0

Sie machen es aus. Sie sollten für jedes ausgeführte Skript eine andere ID verwenden. –

0

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

Der Nachrichten-Broker verwendet die Client-ID jeden Client zu identifizieren. Die Client-ID wird als Teil der MQTT-Nutzdaten vom Client an den Nachrichtenbroker übergeben. Zwei Clients mit derselben Client-ID dürfen nicht gleichzeitig mit dem Nachrichtenbroker verbunden sein. Wenn ein Client eine Verbindung mit dem Nachrichtenbroker unter Verwendung einer Client-ID herstellt, die ein anderer Client verwendet, wird eine CONNACK-Nachricht an beide Clients gesendet, und der derzeit verbundene Client wird getrennt.

Sie müssen entweder eine eindeutige Zeichenfolge pro Client an AWSIoTMQTTClient() oder eine leere Zeichenfolge übergeben. Wenn Sie eine leere Zeichenfolge für die Client-ID übergeben, weist das AWS IoT-Gateway bei der Verbindung eine zufällige Client-ID für Sie zu.

Ändern Sie den AWSIoTMQTTClient Anruf von

my_rpi = AWSIoTMQTTClient("basicPubSub") 

zu

my_rpi = AWSIoTMQTTClient("") 

und jeder der RPIs einen eindeutigen Zufalls Client-ID auf der Verbindung zugewiesen werden. AWS empfiehlt dies nicht im Maßstab, aber für Tests ist es in Ordnung. Sie verlieren auch die Möglichkeit, die Client-ID in Richtlinien zu verwenden.