Search code examples
pythongoogle-cloud-platformpublish-subscribeiotgoogle-cloud-iot

Google IoT - Right mode to receive notifications (subscribe working)


I am following this tutorial and I already have my code publishing messages to /devices/sm1/events topic, in which sm1 is my device id.

I would like to know how to subscribe to this topic since the tutorial says to use /devices/sm1/config but I am getting empty messages. I already tried use the same "path" used in publishing (/devices/sm1/events), but it also did not work.

It is strange that the name I gave to the topic was sm1 and the topic associated to my device is on GoogleIoT console is exhibited as projects/myprojectname/topics/sm1. So, besides to discover how to subscribe to mentioned topic, I appreciate also any explanation related to the correct way of using pub/sub topics in GoogleIoT (the documentation is not so clear).

This is my subscribe.py:

mqtt_url = "mqtt.googleapis.com"
mqtt_port = 8883
topic = "/devices/sm1/config"

def on_connect(client, userdata, flags, response_code):
    print("Connected with status: {0}".format(response_code))
    client.subscribe(topic, 1)

def on_message(client, userdata, msg):
    print("Topic: {0}  --  Payload: {1}".format(msg.topic, msg.payload))

if __name__ == "__main__":    
    client = mqtt.Client("projects/{}/locations/{}/registries/{}/devices/{}".format(
                         project_id,
                         cloud_region,
                         registry_id,
                         device_id))

    client.username_pw_set(username='unused',
                           password=jwt_maker.create_jwt(project_id,
                                               private_key,
                                               algorithm="RS256"))

    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 Google IoT Broker..."
    client.connect(mqtt_url, mqtt_port, keepalive=60)
    client.loop_forever()

My output:

Connected with status: 0
Topic: /devices/sm1/config -- Payload:
Topic: /devices/sm1/config -- Payload:


Solution

  • I had to surrender to Google Pub/Sub library in order to receive notifications related to my specified topic.

    My publish code (only the important parts):

    mqtt_url = "mqtt.googleapis.com"
    mqtt_port = 8883
    mqtt_topic = "/devices/sm1/events"
    
    client = mqtt.Client("projects/{}/locations/{}/registries/{}/devices/{}".format(
                         project_id,
                         cloud_region,
                         registry_id,
                         device_id), protocol=mqtt.MQTTv311)
    
    client.username_pw_set(username='unused',
                           password=jwt_maker.create_jwt(project_id,
                                               private_key,
                                               algorithm="RS256"))
    
    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.connect(mqtt_url, mqtt_port, keepalive=60)
    res = client.publish(mqtt_topic, some_data, qos=1)
    

    In the Google Cloud Platform portal, I had to create a subscription, in the Pub/Sub section, assigning it to my created topic, which was already my default topic (probably linked to /events topic). The created subscription has the following format:

    projects/project_name/subscriptions/subscription_name
    

    My subscribe code, using the Google Pub/Sub library, since it is not possible to use the MQTT protocol:

    from google.cloud import pubsub
    
    def callback(message):
        print(message.data)
        message.ack()
    
    project_id = "project_name"
    subscription_name = "sm1"
    
    subscriber = pubsub.SubscriberClient()
    subscription_name = 'projects/{}/subscriptions/{}'.format(project_id, subscription_name)
    
    subscription = subscriber.subscribe(subscription_name)
    future = subscription.open(callback)
    
    try:
        future.result()
    except Exception as ex:
        subscription.close()
        raise
    

    I hope this can help anyone. More details can be found here(github).