0

I am testing the connection and publishing to a thing created in the AWS IoT console. I am using the following code:

import paho.mqtt.client as mqtt
import ssl, random
from time import sleep

mqtt_url = "XXXXXX.iot.us-east-2.amazonaws.com"
root_ca = './certs/iotRootCA.pem'
public_crt = './certs/deviceCert.crt'
private_key = './certs/deviceCert.key'

connflag = False

def on_connect(client, userdata, flags, response_code):
    global connflag
    connflag = True
    print("Connected with status: {0}".format(response_code))

def on_publish(client, userdata, mid):
    client.disconnect()

def on_message(client, userdata, msg):
    print "---ON MESSAGE"
    print(msg.topic + " " + str(msg.payload))

if __name__ == "__main__":
    print "Loaded MQTT configuration information."
    print "Endpoint URL: " + mqtt_url
    print "Root Cert: " + root_ca
    print "Device Cert: " + public_crt
    print "Private Key: " + private_key

    client = mqtt.Client("aws_connector")
    client.tls_set(root_ca,
                   certfile = public_crt,
                   keyfile = private_key,
                   cert_reqs = ssl.CERT_REQUIRED,
                   tls_version = ssl.PROTOCOL_TLSv1_2,
                   ciphers = None)

    client.on_connect = on_connect
    client.on_message = on_message

    print "Connecting to AWS IoT Broker..."
    client.connect(mqtt_url, port = 8883)
    client.loop_start()

    while 1==1:
        sleep(0.5)
        if connflag == True:
            print "Publishing..."
            ap_measurement = random.uniform(25.0, 150.0)
            client.publish("ActivePower", ap_measurement, qos=1)
        else:
            print("Waiting for connection...")

My policies are described as below:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:Connect",
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "iot:Publish",
      "Resource": "arn:aws:iot:us-east-2:338639570104:topic/sm1"
    },
    {
      "Effect": "Allow",
      "Action": "iot:Subscribe",
      "Resource": "arn:aws:iot:us-east-2:338639570104:topic/sm1"
    }
  ]
}

Apparently, the connection is working and I am getting the following output:

Loaded MQTT configuration information.
Endpoint URL: XXXXXX.iot.us-east-2.amazonaws.com
Root Cert: ./certs/iotRootCA.pem Device Cert: ./certs/deviceCert.crt > Private Key: ./certs/deviceCert.key
Connecting to AWS IoT Broker...
Connected with status: 0
Publishing...
Publishing...
Publishing...
Publishing...
Connected with status: 0
Publishing...

The problem is I am getting no messages from the publishing process. Am I doing something wrong? Is there something missing?

Dalton Cézane
  • 3,672
  • 2
  • 35
  • 60
  • Have you tried using aws mqtt client library? It is slightly different from the paho implementation. https://github.com/aws/aws-iot-device-sdk-python – Deividi Silva Mar 16 '18 at 10:47
  • No. I tried the `aws iot device sdk embedded c` which has a [problem in the subscribe operation](https://stackoverflow.com/questions/49280665/aws-iot-sdk-main-l206-error-subscribing-28-c-code). Furthermore, I saw that this python sdk also uses `paho-mqtt`. So, it works as a wrapper. – Dalton Cézane Mar 19 '18 at 15:22
  • `while 1==1:` -> `while True:`? However, it seems `1==1` is `0.003 usecs` faster on my machine. Interesting. Not worth the readability cost, however, imho. – Drise Mar 19 '18 at 15:29
  • @Drise , `while 1==1` == `while True` == `while 1` == `while 1>0` == ... This part of code I just got of another example I found out at github... the problem is not related to that, so, I left as it was (though I also prefer `True`). Good observation, btw, related to performance! – Dalton Cézane Mar 19 '18 at 15:34
  • @Dalton By habit, if I see `while True` I instantly assocciate that with some application or thread loop (or a giant red flag). `while 1==1` to me is not instantly recognizable as this, though my brain is quite lazy when reading code, so it might just be me. – Drise Mar 19 '18 at 15:39
  • Agree with you, @Drise . – Dalton Cézane Mar 19 '18 at 15:43

1 Answers1

4

Make sure that the AWS IoT policy associated with your IoT certificate allows publishing on the ActivePower topic.

Currently your policy only allows you to publish to topic sm1. Update it to

 {
    "Effect": "Allow",
    "Action": "iot:Publish",
    "Resource": "arn:aws:iot:us-east-2:338639570104:topic/ActivePower"
 }

or as a quick and dirty way of troubleshooting if this is a policy issue add

{
    "Effect": "Allow",
    "Action": "iot:*",
    "Resource": "*"
}

A policy this liberal is not recommended for production.

Also your subscribe policy has the wrong resource, and you need to add a policy statement for iot:Receive to be able to receive messages, if you were to subscribe to that topic.

AWS IoT policy resource documentation

cementblocks
  • 4,326
  • 18
  • 24
  • I updated my question with the policies I have described and activated. Is there something missing? – Dalton Cézane Mar 19 '18 at 15:26
  • I tried both approaches: same problem. Now I tried to delete my policy to create another one, but I am facing this problem: `The action failed because the resource conflicts with the precondition of the action. The policy cannot be deleted as versions other than than default version exist (name=SMPolicy)`. – Dalton Cézane Mar 19 '18 at 18:21
  • I created a new policy, leaving the problematic one there. I just attached the new policy, that is: `{ "Effect": "Allow", "Action": [ "iot:Connect", "iot:Publish", "iot:Subscribe", "iot:Receive" ], "Resource": "arn:aws:iot:us-east-2:338639570104:topic/*" }`. But, still, there is no message received from the publishing process. Apparently, the `on_message` is not working... – Dalton Cézane Mar 19 '18 at 18:47
  • You are not subscribing to any topics in the code sample provided. on_message should fire when a message comes in on a topic you have subscribed to. Also note that to subscribe you need to allow iot:Subscribe on a topicfilter resource e.g. `arn:aws:iot:us-east-2: 338639570104:topicfilter/*` – cementblocks Mar 19 '18 at 18:54
  • Thanks by explanation. I was thinking the `on_message` was used by any feedback from the `server`. So, our publish operations do not have answers from server, right? How do we know if the operations were succeeded? Yet, how can I see the values sent to specific topics? – Dalton Cézane Mar 19 '18 at 19:01
  • The simplest way I've found it to use the AWS IoT console. Select Test from the left side bar. Subscribe to `#` after it connects. You should see any published messages. You can also subscribe to a specific topic. – cementblocks Mar 19 '18 at 19:10