0

I'm learning how to use MQTT on AWS IoT - the goal is to simply publish and receive between AWS IoT MQTT test client and a Python script.

I can successfully publish from my Python code but I am unable to receive.

Publish works if I set QOS to "AT_MOST_ONCE" and I in this case successfully receive "Hi" in AWS. If I set QOS to AT_LEAST_ONCE it does NOT work and remains stuck on ""Waiting for publish to complete...".

It should be further noted that when I tried to loop publish with a 2.5s sleep between it crashed with a no connection error after successfully sending one "Hi" message.

from awscrt import io, mqtt, auth, http
from awsiot import mqtt_connection_builder
import time

# Define the same connection parameters as your publish script
ENDPOINT = "123.iot.eu-north-1.amazonaws.com"
CLIENT_ID = "pc-v3"
PATH_TO_CERTIFICATE = "certificates/certs-certificate.pem.crt"
PATH_TO_PRIVATE_KEY = "certificates/certs-private.pem.key"
PATH_TO_AMAZON_ROOT_CA_1 = "certificates/AmazonRootCA1.pem"
TOPIC = "mqtt_test"

def publish_message(message: str):
    print(f"Attempting to publish message: {message}")
    publish_future, packet_id = mqtt_connection.publish(
        topic=TOPIC,
        payload=message,
        qos=mqtt.QoS.AT_MOST_ONCE  
    )
    print("Waiting for publish to complete...")
    publish_future.result()
    print("Publish completed")

# Define callback for incoming messages
def on_message_received(topic, payload, **kwargs):
    print(f"Received message from topic '{topic}': {payload}")

# Spin up resources
event_loop_group = io.EventLoopGroup(1) 
host_resolver = io.DefaultHostResolver(event_loop_group)
client_bootstrap = io.ClientBootstrap(event_loop_group, host_resolver)

mqtt_connection = mqtt_connection_builder.mtls_from_path(
    endpoint=ENDPOINT,
    cert_filepath=PATH_TO_CERTIFICATE,
    pri_key_filepath=PATH_TO_PRIVATE_KEY,
    client_bootstrap=client_bootstrap,
    ca_filepath=PATH_TO_AMAZON_ROOT_CA_1,
    client_id=CLIENT_ID,
    clean_session=False,
    keep_alive_secs=60
)

print(f"Connecting to {ENDPOINT} with client ID '{CLIENT_ID}'...")
connect_future = mqtt_connection.connect()
connect_future.result()
print("Connected!")

print(f"Subscribing to topic '{TOPIC}'...")
subscribe_future, packet_id = mqtt_connection.subscribe(
    topic=TOPIC,
    qos=mqtt.QoS.AT_LEAST_ONCE  ,
    callback=on_message_received
)

publish_message("Hi")

When I try to receive the messages in my Python code, it does not work even with AT_MOST_ONCE. The latter part of the snippet is bellow and it gets stuck on the first "Subscribed and listening for messages..." as I'm publishing messages on AWS MQTT test client.

print(f"Connecting to {ENDPOINT} with client ID '{CLIENT_ID}'...")
connect_future = mqtt_connection.connect()
connect_future.result()
print("Connected!")

print(f"Subscribing to topic '{TOPIC}'...")
subscribe_future, packet_id = mqtt_connection.subscribe(
    topic=TOPIC,
    qos=mqtt.QoS.AT_MOST_ONCE  ,
    callback=on_message_received
)

#publish_message("Hi")
print("Subscribed and listening for messages...")
subscribe_future.result()
print("Subscribed and listening for messages...")
try:
    # Keep the script running to listen for messages
    while True:
        print("looping")
        subscribe_future.result()

        time.sleep(1)

except KeyboardInterrupt:
    print("Disconnecting...")
    disconnect_future = mqtt_connection.disconnect()
    disconnect_future.result()
    print("Disconnected!")

The cert attached to the Thing is:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iot:Connect",
        "iot:Publish",
        "iot:Subscribe",
        "iot:*",
        "iot:Receive"
      ],
      "Resource": [
        "arn:aws:iot:eu-north-1:123:client/pc-v3",
        "arn:aws:iot:eu-north-1:123:client/${iot:Connection.Thing.ThingName}",
        "arn:aws:iot:eu-north-1:123:topic/mqtt_test",
        "arn:aws:iot:eu-north-1:123:topicfilter/${iot:Connection.Thing.ThingName}/",
        "arn:aws:iot:eu-north-1:123:topic/${iot:Connection.Thing.ThingName}/"
      ]
    }
  ]
}

libs: awscrt 0.28.1 awsiot 0.1.3 awsiotsdk 1.26.0 boto3 1.40.70

I'm stuck and would appreciate any help or ideas where to try and debug my code.

0

1 Answer 1

0

In your policy, there is the "arn:aws:iot:eu-north-1:123:topic/mqtt_test" resource, but subscribing requires topicfilter . So, you should try to add

"arn:aws:iot:eu-north-1:123:topicfilter/mqtt_test"

to your policy and check if subscribing works with this. See AWS docs for more details.

Also, I'd recommend using mqtt5 client, this version of protocol is much better than mqtt311. You can find samples here.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.