AWS IoT core MQTT publish message to a topic

0

Hello all I'm very new to using AWS IoT core. I am using a raspberry pi to send and receive messages with sensor data to and from the console. I can successfully send messages, but I am unable to receive messages I publish to the same topic (I don't see them on the raspberry pi when I post to the topic) I am using a template I found for room occupancy here: https://aws.amazon.com/blogs/iot/monitor-and-visualise-building-occupancy-with-aws-iot-core-amazon-quicksight-and-raspberry-pi/

I also would like to know how to save the message I send down into a variable to use in my program.

from datetime import datetime

global message
import requests
import time
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient

myMQTTClient = AWSIoTMQTTClient("outsidecam")
myMQTTClient.configureEndpoint("myendpoint", 8883)

myMQTTClient.configureCredentials("/home/pi/certs/Amazon-root-CA-1.pem", "/home/pi/certs/private.pem.key", "/home/pi/certs//home/pi/certs/certificate.pem.crt")

print ('Initiating Realtime Data Transfer From Raspberry Pi...')

Myvar= myMQTTClient.connect()

date = datetime.now().strftime("%Y_%m_%d-%I:%M:%S_%p")
print (f"Timestamp:{date}")


while True:
    print("Sending message")
    message= "This is a Test"
    myMQTTClient.publish("topic/pi", "{\"MotionMessage\":\""+ message + "\", \"Timestamp\" :\""+ str(date)+ "\"}", 0)
    time.sleep(60)

asked 2 years ago1.3K views
1 Answer
2
Accepted Answer

Hi AWS-currydem,

from what I can see your code only publishes messages. To receive messages you need to subscribe to a topic. You are also using the old version of the AWS IoT Device SDK.

You can try the current AWS IoT Device SDK v2 for Python. It includes also a pubsub example.

In the sample mentioned above the message is stored in a variable before it is published. This would address your use-case to store the message in a variable.

Cheers,
Philipp

AWS
EXPERT
answered 2 years ago
profile picture
EXPERT
reviewed 7 months ago
profile picture
EXPERT
reviewed 8 months ago
  • I took your advice and it worked like a charm. for the second part of the question I'm still confused.

    When I publish a message I can see it in my python program, but I still am not sure on how to save my specific message into a string variable

    for example If I publish

    { "message": "Blue" }

    I receive in my program

    b'{\n "message": "Blue"\n}'

    How do I save the "Blue" to a variable like "color"

    color = Str(payload) color = "Blue"

  • Assuming the message is stored in the variable message:

    import json  
    color = json.loads(message.decode())['message']
    
  • I tried using what you suggested and got this error message: "AttributeError: 'str' object has no attribute 'decode'"

    Upon further investigation of the pubsub.py file I theorized that the message is stored in the function "def on_message_received" and the message is stored in the "payload" variable

    Callback when the subscribed topic receives a message

    def on_message_received(topic, payload, dup, qos, retain, **kwargs): print("Received message from topic '{}': {}".format(topic, payload)) global received_count received_count += 1 if received_count == cmdUtils.get_command("count"): received_all_event.set()

    I then tried to change the line to "color = json.loads(payload.decode())['message']" and got this error message at first: NameError: name 'payload' is not defined

    I assumed this was caused because "payload" is a parameter of the function "def on_message_received" instead of a declared variable, so I then tried these ways of declaring "payload";

    payload = "" #I then got this error message:"AttributeError: 'str' object has no attribute 'decode'"


    payload = 0 #I then got this error message:"AttributeError: 'int' object has no attribute 'decode'"

    I'm pretty sure that "payload" is where the messages received are stored but I'm still not sure on how to save it to a variable I appreciate your help and I apologize if I'm not catching on as fast, I did try to find tutorials on how to do what I need.

  • You are using a variable (payload) that is not defined in your code. Replace payload with the variable name that contains your message in bytes sequence format.

  • Thank you so much for your help, it's almost working perfectly besides one error. I changed the "def on_message_received" function

    Callback when the subscribed topic receives a message

    def on_message_received(topic, payload, dup, qos, retain, **kwargs): print("Received message from topic '{}': {}".format(topic, payload)) global received_count received_count += 1 if received_count == cmdUtils.get_command("count"): received_all_event.set() color = json.loads(payload.decode())['message'] print(color)

    This is the format of the message I am sending from the topic

    { "message": "blue" }

    This allows me to save the received message to color and just prints blue. However, I also get this error message TypeError: string indices must be integers. And I know this is because there is supposed to be an integer in the brackets instead of the word 'message' but when I place either a 0 or a 1 the output, I get is either: A or 1

    I also tried changing the function and just having color = json.loads(payload) But when I do this the output is {'message': 'blue'}

    Is there a way to still get the output of print(color) as blue without getting the error message: TypeError: string indices must be integers?

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions