文档中心 物联网通信 快速入门 场景一:设备互通

场景一:设备互通

最近更新时间:2019-05-31 16:15:28

操作场景

假设一个智能家居的场景(非实际产品,仅用于阐述物联网通信功能),如需实现如下图功能,您可以参考本文档进行操作。
come_home

解决方案

基于腾讯物联网通信,我们可以通过 SDK 创建两类智能设备(Door、AirConditioner),基于设备间的消息和规则引擎实现设备之间的联动,如下图所示:
rule_engine_for_smart_home

注意:

airConditioner1 不可以通过直接订阅 door1 的 update 消息来完成消息通信,原因请参考 功能组件 - 权限管理

前提条件

已登录 腾讯云控制台

操作步骤

创建门产品和设备

  1. 进入 物联网通信控制台,单击左侧菜单栏【产品列表】。
  2. 进入产品列表页,单击【创建新产品】。
  3. 创建产品(Door)并根据需要选择加密类型,输入产品描述,单击【创建】。
  4. 创建成功后,可以查看产品的基本信息。
  5. 在【设备列表】下,创建设备(door1)。

    注意:

    在非对称加密类型下创建设备会返回设备密钥,此密钥用于设备通信,并且不会在物联网通信后台存储,请妥善保管。

  6. 单击【管理】,可查询设备详情。
    • 非对称加密类型:
      查询设备
    • 对称加密类型:
      查询设备

创建空调产品和设备

  1. 进入 物联网通信控制台,单击左侧菜单栏【产品列表】。
  2. 进入产品列表页,单击【创建新产品】
  3. 创建空调产品(AirConditioner),并根据需要选择加密类型,输入产品描述,单击【创建】。
  4. 创建成功后,可以查看产品的基本信息。
  5. 在【设备列表】下,创建设备(airConditioner1)。
  6. 单击【管理】,可查询设备详情
    查询设备

查询设备详情页面,设备证书、设备私钥用于 MQTT 的 TLS 非对称加密;对称密钥用于对称加密通信(两种通信方式差别请参考 功能组件 - 设备接入)。

注意:

以上资源的创建可通过 restAPI 由后台创建,具体请参见 API 概览

创建规则引擎

具体步骤请参考 规则引擎概述

下载 SDK

SDK 下载方式请参考 SDK 下载

配置 C-SDK 示例程序

  • samples/scenarized/door_mqtt_sample.c 是门设备基于 MQTT 协议相关逻辑代码。
  • samples/scenarized/door_coap_sample.c 是门设备基于 CoAP 协议相关逻辑代码。
  • samples/scenarized/aircond_shadow_sample.c 是空调设备基于 MQTT 协议相关逻辑代码。

door_mqtt_sample.c 和 door_coap_sample.c 都是实现消息上报的示例,分别通过 MQTT 和 CoAP 协议,两个 sample 实现的功能一样。

基于 MQTT 协议实现 C-SDK 门示例程序

对应示例程序为 samples/scenarized 下的door_mqtt_sample.c,编辑src/platform/os/linux/HAL_OS_linux.c 的设备信息,使能该文件调试宏 DEBUG_DEV_INFO_USED。量产产品需关闭该调试宏,实现设备信息在非易失存储介质的读写接口,即HAL层接口适配。使用 创建门产品和设备 中获得的设备信息,填写以下配置项(下表物理含义后的编号,与 创建门产品和设备 截图中的序号一一对应)。

配置项 物理含义
sg_product_id 产品 ID,全局唯一,可从设备详情页面获取(1)
sg_device_name 设备名字,设备详情页面获取(3)
sg_device_cert_file_name 设备证书名字,在设备详情页面下载获取,仅非对称加密方式使用(4)
sg_device_privatekey_file_name 设备私钥文件名字,在设备详情页面下载获取,仅非对称加密方式使用(2)
sg_device_secret 设备对称密钥,在设备详情页面下载获取,仅对称加密方式使用(5)
  1. 完成对 MQTT 通信协议的参数初始化,_setup_connect_init_params函数内部需要填写设备相关信息,具体宏定义请参见上表:

    MQTTInitParams initParams = DEFAULT_MQTTINIT_PARAMS;
    _setup_connect_init_params(&initParams);
  2. 完成对 MQTT connect 请求的参数初始化并执行构造:

    void *client = IOT_MQTT_Construct(&initParams);
  3. 作为样例,这里根据用户执行程序时指定的 action(come_home 或者 leave_home)和 targetDeviceName(需要中转到的设备名) 参数值,对消息的内容组装和发布。用户可自行组织消息内容和 topic,执行自己的发布消息逻辑。

    _publish_msg(action, targetDeviceName);
  4. 在代码根目录执行 make,编译后,在 output/release/bin 目录下得到 door_mqtt_sample 可执行程序。

  5. 执行 ./door_mqtt_sample come_home airConditioner1(第一个输入参数是行为:come_home 或者 leave_home; 第二个参数是消息的目标对象,我们这里假设为 airConditioner1),注意如果用 TLS 非对称加密方式,请保证设备证书和设备私钥文件在 certs 上层目录下。

以下完成门这个设备的连接和发布功能。若执行成功,则显示如下结果:

INF|2018-01-11 20:13:22|door_mqtt_sample.c|main(207): Cloud Device Construct Success
DBG|2018-01-11 20:13:22|mqtt_client_publish.c|qcloud_iot_mqtt_publish(317): publish topic seq=33254|topicName=K02I1V7PGO/door1/event|payload={"action": "come_home", "targetDevice": "airConditioner1"}
INF|2018-01-11 20:13:22|door_mqtt_sample.c|main(227): Wait for publish ack
INF|2018-01-11 20:13:22|door_mqtt_sample.c|event_handler(89): publish success, packet-id=33254

基于 CoAP 协议实现 C-SDK 门示例程序

  1. 对应示例为 samples/scenarized 下的 door_coap_sample.c,编辑src/platform/os/linux/HAL_OS_linux.c 的设备信息,使能该文件调试宏 DEBUG_DEV_INFO_USED。量产产品需关闭该调试宏,实现设备信息在非易失存储介质的读写接口,即HAL层接口适配。使用 创建门产品和设备 中获得的设备信息,填写以下配置项(下表物理含义后的编号,与 创建门产品和设备 截图中的序号一一对应)。
配置项 物理含义
sg_product_id 设备 ID,全局唯一,可从设备详情页面获取(1)
sg_device_name 设备名字,设备详情页面获取(3)
sg_device_cert_file_name 设备证书名字,在设备详情页面下载获取,仅非对称加密方式使用(4)
sg_device_privatekey_file_name 设备私钥文件名字,在设备详情页面下载获取,仅非对称加密方式使用(2)
sg_device_secret 设备对称密钥,在设备详情页面下载获取,仅对称加密方式使用(5)
  1. 完成对 CoAP 连接和客户端的创建,初始化的参数是步骤一的配置。
    void *coap_client = IOT_COAP_Construct(&init_params);
  2. 作为样例,这里根据用户执行程序时指定的 action(come_home 或者 leave_home)和 targetDeviceName(需要中转到的设备名)参数值,对消息的内容组装和发布。用户可自行组织消息内容和 Topic,执行自己的发布消息逻辑。door_coap_sample.c 示例中的 Topic为 /$(productId)/$(deviceName)/event,执行消息发布。
     char topicName[128] = "";
     sprintf(topicName, "/%s/%s/event", QCLOUD_IOT_MY_PRODUCT_ID, QCLOUD_IOT_MY_DEVICE_NAME);
     Log_i("topic name is %s", topicName);
     rc = IOT_COAP_SendMessage(coap_client, topicName, &send_params);
  3. 在根目录下执行 make ,在 output/release/bin 目录生成可执行程序 door_coap_sample。
  4. 执行 ./door_coap_sample come_home airConditioner1 (第一个输入参数是行为:come_home 或者 leave_home; 第二个参数是消息的目标对象,我们这里假设为 airConditioner1),注意如果用 DTLS 非对称加密方式,请保证设备证书和设备私钥文件在 door_coap_sample可执行程序同级的 certs 目录下。

以下完成门这个设备的连接和发布功能。若执行成功,则显示如下结果:

INF|2018-01-12 18:07:17|coap_client.c|IOT_COAP_Construct(84): device auth successfully, connid: h4TFD
ERR|2018-01-12 18:07:17|door_coap_sample.c|main(119): 0x110c010
INF|2018-01-12 18:07:17|door_coap_sample.c|main(143): topic name is /D6WQAXE63D/skyTest1/event
INF|2018-01-12 18:07:17|coap_client_message.c|coap_message_send(390): add coap message id: 52124 into wait list ret: 0
DBG|2018-01-12 18:07:17|door_coap_sample.c|main(150): client topic has been sent, msg_id: 52124
DBG|2018-01-12 18:07:17|HAL_DTLS_mbedtls.c|HAL_DTLS_Read(356): mbedtls_ssl_read len 50 bytes
DBG|2018-01-12 18:07:17|coap_client_message.c|_coap_message_handle(292): receive coap piggy ACK message, id 52124
INF|2018-01-12 18:07:17|door_coap_sample.c|event_handler(54): message received ACK, msgid: 52124
DBG|2018-01-12 18:07:17|coap_client_message.c|_coap_message_list_proc(144): remove the message id 52124 from list
INF|2018-01-12 18:07:17|coap_client_message.c|_coap_message_list_proc(85): remove node
INF|2018-01-12 18:07:17|coap_client.c|IOT_COAP_Destroy(118): coap release!

基于 MQTT 协议实现 C-SDK 空调示例程序

  1. MQTT 协议初始化。
  2. MQTT connect 连接逻辑实现。
  3. 请参考上文 实现 C-SDK 门示例程序 文档。
  4. 作为样例,_register_subscribe_topics 实现对 AirConditioner/airConditioner1/control 订阅,并且注册对应的回调处理函数。收到该 topic 消息后回调处理,判断消息内容是 “come_home” 或者 “leave_home” 而分别让 airConditioner 开启或者关闭。用户可在函数内实现对自定义 Topic 消息的订阅,并且注册自定义的回调处理。
    rc = _register_subscribe_topics();
  5. 在下面循环处理里面,IOT_Shadow_Yield 这个函数实现了对订阅 topic 的监听,当收到对应 topic 消息时候则执行其相应的回调函数。一般而言,不用更改处理逻辑。_simulate_room_temperature 简单模拟了下室内温度的变化和 airConditioner 的能耗。用户也可以实现其他自定义逻辑。
rc = IOT_Shadow_Yield(client, 200);

if (rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT) {
    sleep(1);
    continue;
}
else if (rc != QCLOUD_ERR_SUCCESS) {
    Log_e("Exit loop caused of errCode: %d", rc);
}

if (sg_subscribe_event_result != MQTT_EVENT_SUBCRIBE_SUCCESS &&
    sg_subscribe_event_result != MQTT_EVENT_SUBCRIBE_TIMEOUT &&
    sg_subscribe_event_result != MQTT_EVENT_SUBCRIBE_NACK)
{
    sleep(1);
    continue;
}

_simulate_room_temperature(&sg_report_temperature);
Log_i("airConditioner state: %s", sg_airconditioner_openned ? "open" : "close");
Log_i("currentTemperature: %f, energyConsumption: %f", sg_report_temperature, sg_energy_consumption);

sleep(1);
  1. 在代码根目录执行 make,编译后再 output/release/bin 目录下得到 aircond_shadow_sample 可执行程序。
  2. 执行 ./aircond_shadow_sample。

    注意:

    如果用 TLS 非对称加密方式,请保证设备证书和设备私钥文件在 certs 上层目录下。

    INF|2018-01-11 20:15:07|shadow_client.c|IOT_Shadow_Construct(169): Sync device data successfully
    INF|2018-01-11 20:15:07|aircond_shadow_sample.c|main(253): Cloud Device Construct Success
    DBG|2018-01-11 20:15:07|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(123): topicName=R1JMYJIOYJ/airConditioner1/control|packet_id=16076|pUserdata=(null)
    DBG|2018-01-11 20:15:07|shadow_client.c|_shadow_event_handler(63): shadow subscribe success, packet-id=16076
    INF|2018-01-11 20:15:07|aircond_shadow_sample.c|event_handler(109): subscribe success, packet-id=16076
    INF|2018-01-11 20:15:07|aircond_shadow_sample.c|main(288): airConditioner state: close
    INF|2018-01-11 20:15:07|aircond_shadow_sample.c|main(289): currentTemperature: 32.000000, energyConsumption: 0.000000

以上完成 airConditioner1 这个设备的连接和订阅功能。程序内循环监听订阅的 topic 并且输出室温和能耗相关系数。

实现设备互通

  1. 以上步骤已建立 door1 与 airConditioner1 之间的通信渠道,重新执行 ./aircond_shadow_sample;然后执行 ./door_mqtt_sample come_home airConditioner1,查看输出日志。
  2. 从日志可见,airConditioner1 已经获取到来自 door1 的消息,并且将状态state转为"open",室温currentTemperature(往缺省配置温度调整)与能耗energyConsumption也有相关动态变化。
     INF|2018-01-11 20:15:13|aircond_shadow_sample.c|main(288): airConditioner state: close
     INF|2018-01-11 20:15:13|aircond_shadow_sample.c|main(289): currentTemperature: 32.000000, energyConsumption: 0.000000
     INF|2018-01-11 20:15:14|aircond_shadow_sample.c|on_message_callback(162): Receive Message With topicName: R1JMYJIOYJ/airConditioner1/control, payload:{"action":"come_home","targetDevice":"airConditioner1"}
     INF|2018-01-11 20:15:14|aircond_shadow_sample.c|main(288): airConditioner state: open
     INF|2018-01-11 20:15:14|aircond_shadow_sample.c|main(289): currentTemperature: 31.000000, energyConsumption: 1.000000

配置 Android-SDK 示例程序

实现 Android-SDK 门示例程序

com/qcloud/iot/samples/scenarized/Door.java 是门设备类,请先填入之前创建产品和设备步骤中得到的 PRODUCT_ID, DEVICE_NAMEDEVICE_CERT_NAMEDEVICE_KEY_NAME,并将设备证书、设备私钥文件放置在 assets 目录中:

  1. 在 enterRoom() 对 MQTT 连接实例进行判空检查,若为空,则进行初始化操作并发起连接 connect();若不为空,则判断连接是否有效,有效则发布 event 主题。
  2. 作为样例,这里根据用户执行程序时指定的的 action(come_home 或者 leave_home)和 targetDeviceName(需要中转到的设备名) 参数值,对消息的内容组装和发布。用户可自行组织消息内容和 topic,执行自己的发布消息逻辑。

实现 Android-SDK 空调示例程序

com/qcloud/iot/samples/scenarized/Airconditioner.java 是空调设备类,与 实现 Android-SDK 门示例程序 一样,需先填入产品和设备相关信息。

  1. 在 Airconditioner 的构造方法中对 MQTT 连接实例进行初始化并发起连接 connect()。
  2. MQTT 连接成功过后,订阅 control 主题。

运行示例程序

  1. 单击 Android Studio Run 的【App】按钮,并安装 Demo。
  2. 切换底部 Tab ,进入设备互通 Fragment,观察 Demo 及 logcat 中日志信息,以下为 logcat 中日志信息:
    airConditioner1 连接 IoT 并订阅主题
    com.qcloud.iot I/com.qcloud.iot.mqtt.TXMqttConnection: Start connecting to ssl://connect.iot.qcloud.com:8883
    com.qcloud.iot I/com.qcloud.iot.mqtt.TXMqttConnection: onSuccess!
    com.qcloud.iot I/IoTEntryActivity: connected to ssl://connect.iot.qcloud.com:8883
    com.qcloud.iot I/com.qcloud.iot.mqtt.TXMqttConnection: Starting subscribe topic: ******/airConditioner1/control
    com.qcloud.iot I/IoTEntryActivity: onSubscribeCompleted, subscribe success
  3. 单击【进门】,连接 IoT 并发布 control 主题,对应 message 为:
    "{\"action\": \"come_home\", \"targetDevice\": \"airConditioner1\"}"
  4. 观察 Demo 及 logcat 中日志信息,以下为 logcat 日志信息:
    • door1 连接 IoT
      com.qcloud.iot I/com.qcloud.iot.mqtt.TXMqttConnection: Start connecting to ssl://connect.iot.qcloud.com:8883
      com.qcloud.iot I/com.qcloud.iot.mqtt.TXMqttConnection: onSuccess!
      com.qcloud.iot I/IoTEntryActivity: connected to ssl://connect.iot.qcloud.com:8883
    • door1 发布主题(come_home)
      com.qcloud.iot I/com.qcloud.iot.mqtt.TXMqttConnection: Starting publish topic: ******/door1/event Message: {"action": "come_home", "targetDevice": "airConditioner1"}
    • airConditioner1 接收到经规则引擎转发过来的主题
      com.qcloud.iot I/com.qcloud.iot.mqtt.TXMqttConnection: Received topic: ******/airConditioner1/control, message: {"action":"come_home","targetDevice":"airConditioner1"}
      com.qcloud.iot D/IoTEntryActivity: receive command: open airconditioner, count: 1
  5. 单击【出门】,发布 control 主题,对应 message 为:
    "{\"action\": \"leave_home\", \"targetDevice\": \"airConditioner1\"}"
  6. 观察 Demo 及 logcat 中日志信息,以下为 logcat 日志信息:
    • door1 发布主题(leave_home)
      com.qcloud.iot I/com.qcloud.iot.mqtt.TXMqttConnection: Starting publish topic: ******/door1/event Message: {"action": "leave_home", "targetDevice": "airConditioner1"}
    • airConditioner1 接收到经规则引擎转发过来的主题
      com.qcloud.iot I/com.qcloud.iot.mqtt.TXMqttConnection: Received topic: ******/airConditioner1/control, message: {"action":"leave_home","targetDevice":"airConditioner1"}
      com.qcloud.iot D/IoTEntryActivity: receive command: close airconditioner, count: 2