使用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
属性上报的格式为,这部分具体细节可以参考文档:属性上报
{
"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"
}
]
}
}
这里我只定义了一个温度属性,上报格式也可以简化为:
{
"params":{
"temperature":20
}
}
发送一次测试:
在物联网平台可以看到对应的数据:
这样就完成了数据上报。
二、进阶部分——复杂情况的示例:
1. 介绍
下面以一个稍微复杂的设备为例,记录一下一些其他可能会用到的功能和配置:
如下图,这是基于ESP32,MQ-2,BH1750,BME280,断路器和四路继电器的物联网模拟装置,用于模拟物联网设备。
可以采集温度、湿度、气压、烟感和控制四路继电器和一路断路器。
它上传数据的格式是这样的,顾名思义,这里就不详细介绍:
{
"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消息,用来控制四路继电器和断路器,其接收数据的格式为:
{
"dalay_1": 1,
"dalay_2": 0,
"dalay_3": 0,
"dalay_4": 1,
"circuit_breaker":1
}
其中,控制项可缺省,比如这样
{
"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即可,平台也会生成对应的示例代码:
如下:
'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打开:
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端也打印出了对应的控制指令: