Skip to content

使用MQTT接入阿里云物联网平台

[! danger] 注意: 阿里云在2025/2/1后不再支持开通物联网平台,后续可能会逐步取消物联网服务。

一、基础部分

1. 开通物联网平台公共实例

进入阿里云官方,找到物联网平台产品,选择开通公共实例:

公共实例可以无限期试用,限制最多500个设备,同时在线设备50个,消息上下行与消息转发均为5 TPS。超出后按量计费。

开通后可在控制台找到(注意选择正确的地区):

进入后,显示如下:

2. 创建产品和设备

接下来创建设备进行接入,找到产品->创建产品:

输入信息创建一个产品,这里以温度采集模块为例:

添加后可在产品列表看到我们新建的产品:

点击进入,如下图:

接下来为产品添加属性,单击功能定义,选择编辑草稿:

添加自定义功能:

这里添加一个温度属性:

然后发布物模型,产品就创建好了:

接下来创建设备,选择添加设备

选择刚才创建的产品,输入自定义的产品名称

点击设备可以看到设备详情:

如下:

点击设备信息里的MQTT连接参数,可以看到对应的连接所需的参数:

3. 设备通过MQTT连接

下面试与MQTT客户端软件MQTTX去模拟设备连接至阿里云物联网平台:

打开MQTTx 新建连接:

输入刚才的连接参数:

点击连接,可以看到已经连接上了:

对应的物联网平台的设备状态也变成了在线:

4. 发布数据到平台

在产品一栏可以找到物模型通信 Topic 列表,找到设备属性上报一项主题为:

/sys/${ProductKey}/${deviceName}/thing/event/property/post

这里我的产品ID为k29vtAnX0iK,设备名为test,所以上报的主题为:/sys/k29vtAnX0iK/test/thing/event/property/post

属性上报的格式为,这部分具体细节可以参考文档:属性上报

json
{
    "id":"883*****",
    "version":"1.0",
    "method":"thing.event.property.post",
    "params":{
        "SpeechList":[
            {
                "size":28.48046875,
                "format":"wav",
                "id":"ZFBDZ"
            },
            {
                "size":28.48046875,
                "format":"amr",
                "id":"welcome"
            },
            {
                "size":420.076171875,
                "format":"mp3",
                "id":"test"
            }
        ]
    }
}

这里我只定义了一个温度属性,上报格式也可以简化为:

json
{
    "params":{
		"temperature":20
    }
}

发送一次测试:

在物联网平台可以看到对应的数据:

这样就完成了数据上报。

二、进阶部分——复杂情况的示例:

1. 介绍

下面以一个稍微复杂的设备为例,记录一下一些其他可能会用到的功能和配置:

如下图,这是基于ESP32,MQ-2,BH1750,BME280,断路器和四路继电器的物联网模拟装置,用于模拟物联网设备。

可以采集温度、湿度、气压、烟感和控制四路继电器和一路断路器。

它上传数据的格式是这样的,顾名思义,这里就不详细介绍:

json
{
	"params": {
		"temperature":	18.59,
		"humidity":	47.14,
		"pressure":	1038.11,
		"lightIntensity":	66.67,
		"smokeDensity":	0.15,
		"relayStatus_1":	1,
		"relayStatus_2":	0,
		"relayStatus_3":	0,
		"relayStatus_4":	1,
		"circuitBreakerStatus":	"0"
	 }
}

数据格式是阿里云物联网平台的标准格式

[! WARNING] 这里需要注意,我们上传到云平台的数据必须按照阿里云物联网平台的要求格式来,虽然物联网平台有消息解析这个 功能,但并不能把不规则的Json转换为标准json,这里可以参考文档:什么是消息解析

并且这个设备还可以接收MQTT消息,用来控制四路继电器和断路器,其接收数据的格式为:

json
{
  "dalay_1": 1,
  "dalay_2": 0,
  "dalay_3": 0,
  "dalay_4": 1,
  "circuit_breaker":1
}

其中,控制项可缺省,比如这样

json
{
  "dalay_1": 1,
  "dalay_2": 0,
}

也是可以的。

这里我提供一个用于模拟上述装置的ESP32程序

程序模拟采集数据(虚拟随机值),和被控制的过程(通过命令行打印控制信息)不需要连接硬件,只需要任意的开发板即可: 具体的使用请参考本文的第三部分:SP32模拟物联网设备程序

2. 数据上传

我们前往阿里云物联网平台为这个设备新建一个产品品类,属性如下:

并且添加一个设备,如下:

接下来配置设备连接到云平台(这部分参考基础部分的设备通过MQTT连接),就可以拿到数据了:

3. 数据下发

数据下发有多种方式,这里展示较为自由的主题订阅:

首先在产品里找到可订阅的主题:

让我们的设备端订阅该地址,这个时候设备的主题列表就可以看到被订阅的主题:

可以点击发布消息,来控制设备:

发送后设备已经成功被控制。

4. 使用OpenAPI 获取设备数据、控制设备

[! INFO] 物联网平台提供云端管理产品、设备、分组、Topic、规则、设备影子等API接口,和从云端发布消息的API接口。使用云端SDK,向API的服务端地址发送HTTPS/HTTP GET或POST请求,并按照API接口说明,在请求中加入相应请求参数来调用API。物联网平台根据请求的处理情况,返回处理结果。调用API的方法和说明,请参见链接文档

阿里云OpenAPI是一系列接口,让开发者能通过代码编程方式访问和管理阿里云服务,提供自动化、定制化解决方案。为了能够让开发者快速高效地学习和使用云产品的OpenAPI,阿里云专为开发者提供了OpenAPI门户,它集成了智能OpenAPI搜索、详尽文档查阅、即时在线调试、SDK便捷获取、代码示例引用、错误诊断工具、调用统计分析等多项强大功能。通过OpenAPI门户,您能够无缝对接并调用阿里云全方位云产品的OpenAPI接口,直观审查API请求及其响应详情,加速您的开发进程。更多信息,请参见什么是 OpenAPI

下图是用户从客户端发起一个OpenAPI调用请求到接收来自阿里云服务响应数据的完整时序图:

我们尝试使用第三方程序去获取阿里云物联网平台数据,并控制设备:

我们可以使用OpenAPI 门户,可视化输入

自动生成对应语言的SDK示例:

下面我们测试使用OpenAPI给刚才的设备下发如第三部分的控制指令,这里我们使用Pub接口,该接口通过自定义Topic向设备发布消息,支持向指定产品下订阅了指定自定义Topic的在线设备发送广播消息。 ` 只需要三个参数:产品ID 、消息主题、消息主体,点击发起调用,显示调用成功(并且我的设备端也接收到了这条消息)

[! WARNING] 这里需要注意,消息主体需要将消息原文转换成二进制数据,并进行 Base64 编码,不能直接发送字符串,可以通过Base64转换工具进行转换。

想要在我们的第三方软件获取,调用这些设备,只要在对应的环境下调用OpenAPI即可,平台也会生成对应的示例代码:

如下:

js
'use strict';
// This file is auto-generated, don't edit it
// 依赖的模块可通过下载工程中的模块依赖文件或右上角的获取 SDK 依赖信息查看
const Iot20180120 = require('@alicloud/iot20180120');
const OpenApi = require('@alicloud/openapi-client');
const Util = require('@alicloud/tea-util');
const Tea = require('@alicloud/tea-typescript');

class Client {

  /**
   * 使用AK&SK初始化账号Client
   * @return Client
   * @throws Exception
   */
  static createClient() {
    // 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。
    // 建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378664.html。
    let config = new OpenApi.Config({
      // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
      accessKeyId: process.env['ALIBABA_CLOUD_ACCESS_KEY_ID'],
      // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
      accessKeySecret: process.env['ALIBABA_CLOUD_ACCESS_KEY_SECRET'],
    });
    // Endpoint 请参考 https://api.aliyun.com/product/Iot
    config.endpoint = `iot.cn-shanghai.aliyuncs.com`;
    return new Iot20180120.default(config);
  }

  static async main(args) {
    let client = Client.createClient();
    let pubRequest = new Iot20180120.PubRequest({
      iotInstanceId: 'iot-06z00ddgcvvrihm',
      productKey: 'k29vt0C22Rb',
      qos: 1,
      topicFullName: '/k29vt0C22Rb/esp32-lab/user/get',
      messageContent: 'ewogICJkYWxheV8xIjogMSwKICAiZGFsYXlfMiI6IDAsCiAgImRhbGF5XzMiOiAwLAogICJkYWxheV80IjogMSwKICAiY2lyY3VpdF9icmVha2VyIjoxCn0=',
    });
    let runtime = new Util.RuntimeOptions({ });
    try {
      // 复制代码运行请自行打印 API 的返回值
      await client.pubWithOptions(pubRequest, runtime);
    } catch (error) {
      // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
      // 错误 message
      console.log(error.message);
      // 诊断地址
      console.log(error.data["Recommend"]);
      Util.default.assertAsString(error.message);
    }    
  }

}

exports.Client = Client;
Client.main(process.argv.slice(2));

5. 消息转发与云产品流转

物联网平台提供新版云产品流转服务,支持将设备消息转发至其他Topic或其他阿里云产品进行存储或处理。如果我们有大量的数据需要转发到我们直接的服务端,可以考虑使用此功能。

下面是数据流转流程:

具体可参考文档:云产品流转概述 ,这里不再赘述,如后续有需要再进行更新。

三、其他—ESP32模拟物联网设备程序

为什么使用ESP32模拟物联网设备?

虽然可以通过MQTTX模拟客户端设备,但是使用MQTTX只能模拟简单的消息发送和接收,不能灵活的在收发数据见添加处理逻辑,并且虽然ESP32模拟物联网设备并没有对接真实物理传感器,但是足够我们调试和学习ESP32的MQTT和云平台的通信,降低了在学习过程中因为硬件问题产生的阻碍。

1. 获取程序

克隆项目,并使用Vs Code打开:

bash
git clone https://github.com/XAUT-WisdomLab/Mock-IoT-Device-ESP32.git

可以看到代码中的连接信息为空:

2. 在阿里云创建对应设备

在阿里云物联网新建产品(具体步骤参考前面几节):

创建成功后,在功能定义中导入物模型:

如下,导入成功后发布上线即可:

接下来新建一个设备,我这里起名test:

3. 修改程序中的连接参数连接至阿里云

进入设备详情,复制连接参数:

将参数填充到ESP32的程序中去:

其中:

  • MQTT_REPORT_TOPI 的格式为:/sys/${ProductKey}/${deviceName}/thing/event/property/post
  • MQTT_CONTROL_TOPIC 的格式为:/${ProductKey}/${deviceName}/user/get

然后将ESP32代码烧录至开发板(具体如何烧录,请参考我的ESP32教程专栏),烧录成功后,开发板自动连接阿里云物联网平台,若连接失败请检查参数是不是没写对,ESP32开始模拟上传数据:

平台端也可以看到数据:

此时可以通过已订阅 Topic 列表向设备发送控制指令:

可以看到ESP32端也打印出了对应的控制指令: