Google IoT - 接收通知的正确模式(订阅工作)

时间:2018-04-03 19:44:38

标签: python google-cloud-platform publish-subscribe iot google-cloud-iot

我正在关注this tutorial,我已将代码发布到/devices/sm1/events主题,其中sm1是我的设备ID。

我想知道如何订阅这个主题,因为教程说要使用/devices/sm1/config,但我收到空消息。我已经尝试过使用发布中使用的相同“路径”(/devices/sm1/events),但它也没有用。

奇怪的是,我给该主题的名称是sm1,与我的设备相关联的主题在GoogleIoT控制台上显示为projects/myprojectname/topics/sm1。因此,除了发现如何订阅所提到的主题外,我还要了解与在GoogleIoT中使用pub / sub主题的正确方法相关的任何解释(文档不太清楚)。

这是我的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()

我的输出:

  

连接状态:0
  主题:/ devices / sm1 / config - 有效负载:
  主题:/ devices / sm1 / config - 有效负载:

3 个答案:

答案 0 :(得分:2)

在阅读了@GabeWeiss的回答中的评论部分的讨论之后,我认为你想要实现的内容以及你尝试使用Pub / Sub的方式(或者是什么)会有一些混淆。

鉴于我认为这里的问题更具概念性,让我首先向您推荐一个关于Cloud IoT Core key concepts的通用文档页面,您将在其中找到有关Cloud IoT Core和Pub / Sub之间关系的一些信息。总之,设备遥测数据发布到Cloud IoT Core主题,稍后通过Data Broker发布到Cloud Pub / Sub主题,您可以将其用于外部用于其他目的:触发云功能,分析流数据流等数据

现在,如果您按照Quickstart guide of Cloud IoT Core进行操作,您将会看到在某个特定点,您create a device registry which is bound to a Pub/Sub topic如何发布设备遥测事件。如果您不想写入您希望写入多个主题的默认发布/订阅主题,则可以按照this other section on the documentation下的说明进行操作。

最后,遇到订阅主题的问题(Cloud IoT Core主题,而不是Pub / Sub主题,因为只有前者与设备相关),您可以使用the following command订阅MQTT主题,其中(作为示例),设备订阅配置主题,其中发布配置更新:

# This is the topic that the device will receive configuration updates on.
mqtt_config_topic = '/devices/{}/config'.format(device_id)

# Subscribe to the config topic.
client.subscribe(mqtt_config_topic, qos=1)

然后,使用the on_message() function,您可以处理在您实际订阅的主题上发布的消息。请注意,有效负载必须解析为字符串(str(message.payload))。

def on_message(unused_client, unused_userdata, message):
    payload = str(message.payload)
    print('Received message \'{}\' on topic \'{}\' with Qos {}'.format(
            payload, message.topic, str(message.qos)))

然后,在您的问题中,您说您首先订阅了/devices/{device-id}/config,但这可能不是您想要的,因为这是主题是发布配置更新(即不发布遥测事件的地方)。然后,我知道您应该订阅/devices/{device-id}/events,这是发布遥测指标的实际MQTT主题。如果这不起作用,可能存在另一个相关问题,因此请确保正确解析message变量,并尝试使用注册表创建use Pub/Sub with the default topic以检查遥测指标是否为正确发布与否。

答案 1 :(得分:1)

修改:根据以下评论进行澄清......

这里有两个GCP组件。有MQTT主题(这是/ events主题),设备使用它来与IoT Core对话。然后是projects/myprojectname/topics/sm1,它不在IoT Core中,它在Pub / Sub中。当您向/ events MQTT主题发送消息时,IoT Core会将发送到/ events MQTT主题的设备的有效负载经历到已创建并附加到设备已注册的IoT Core注册表的Pub / Sub主题。

要查看这些消息,您必须在主题projects/myprojectname/topics/sm1上的Pub / Sub中创建订阅。如果你去控制台,和Pub / Sub->主题。单击主题旁边的三个点,然后选择“新订阅”。订阅完成后,您可以从设备发送一些数据,然后在命令行上运行(假设您安装了gcloud工具):

gcloud beta pubsub subscriptions pull --max-messages=3 <subscription_id>

要对消息执行任何操作,您可以编写订阅Pub / Sub主题的脚本(请查看Pub / Sub API)以触发添加到主题中的消息。

原始消息

您是否向设备发送配置消息?混淆可能是MQTT主题是单向的。

所以:1)/ events主题是针对device-&gt; IoT Core。 2)/ config主题适用于IoT Core Admin SDK-&gt;设备

在某个地方的另一个脚本中,或者从IoT Core UI界面,您需要发送配置消息以正确查看on_message。

在IoT核心UI(在console.cloud.google.com上),您可以深入查看已注册的单个设备,并在屏幕顶​​部单击“更新配置”。将出现一个弹出窗口,允许您向该设备发送文本或base64编码的消息,它将出现在/ config主题上。

答案 2 :(得分:0)

我不得不向Google Pub / Sub库投降,以便接收与我指定主题相关的通知。

我的发布代码(仅限重要部分):

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)

在Google Cloud Platform门户中,我必须在Pub / Sub部分创建订阅,将其分配给我创建的主题,这已经是我的默认主题(可能与/ events主题相关联)。创建的订阅具有以下格式:

projects/project_name/subscriptions/subscription_name

我的订阅代码,使用Google Pub / Sub库,因为无法使用MQTT协议:

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

我希望这可以帮助任何人。更多详情can be found here(github)