中移4G模组ML307C以MQTT协议接入新版OneNET完整流程
本篇文章用于记录一下本人使用中移4G模组ML307C使用MQTT协议接入OneNET的流程以及这个过程中遇到的一些问题。OneNET文档中心提供了各个功能的详细说明,文章中的一些流程直接引用的文档中心的内容,大家有什么问题也可多查阅官方文档,详读几遍,其义自见。
0 流程概要
使用OneNET进行物联网开发,基本流程为:
(0)创建账号
(1)创建产品:创建账号之后,第一步就是创建产品,后续开发均以产品为基础
(2)添加产品的相关功能属性
(3)在产品下添加设备:一个产品可添加多个设备,每个设备拥有产品的相关功能属性
(4)设备接入准备:平台上添加完设备之后,需要利用产品名称、设备名称、设备秘钥等参数生成一个鉴权参数token,也就是设备接入平台的密码
(5)设备接入:完成上面的步骤之后,就可以进行实际的设备接入了
(6)数据交互:设备成功接入之后就可以进行平台和设备之间的数据交互了
本文以上述流程展开叙述,最后叙述本人在这个过程中遇到的一些问题。
1 OneNET平台配置
1.1 账号注册与登录
在使用OneNET物联网平台前,需要注册账号,后续开发均在注册的账号下进行。
基本步骤:
(1)访问OneNET官网:https://open.iot.10086.cn
(2)点击"注册"按钮,填写相关信息完成注册
(3)登录后进入开发者中心控制台
1.2 创建产品
产品是一组具有相同功能定义的设备集合,创建产品是使用平台的第一步,快速创建产品后可定义产品功能、添加对应设备、进行设备开发、软硬件设备调试和发布量产,产品开发的全流程配置都在产品的基础上完成。
基本步骤:
(1)在控制台产品开发界面点击"创建产品"
(2)填写产品基本信息
(3)确定
创建产品流程示例:https://iot.10086.cn/doc/aiot/fuse/detail/906
1.3 添加物模型(功能定义)
物模型定义了设备的能力和属性,是设备与云端通信的数据模板。
基本步骤:
(1)进入产品详情页,点击"产品开发"
(2)设置物模型-添加功能点
添加物模型流程示例:https://iot.10086.cn/doc/aiot/fuse/detail/900
1.4 创建设备
物理设备要连接到平台,需要先在平台创建设备(支持单个或批量导入创建),并获取连接到平台的鉴权信息。设备列表包含自主创建的设备和他人转移的设备,同时支持灵活的搜索和列表导出。
基本步骤:
(1)在产品详情页点击"设备列表" → "添加设备"
(2)填写设备信息:
- 所属产品:选择所属产品
- 设备名称:自定义设备名称
(3)记录关键信息:
- 产品ID
- 设备名称
- 设备密钥

图1 OneNET物联网平台设备详情
创建设备流程示例:https://iot.10086.cn/doc/aiot/fuse/detail/987
2 设备端开发准备
-
如只做基本连接、数据交互功能验证,只需一个MQTT客户端即可
mqttfx客户端百度网盘链接: https://pan.baidu.com/s/1pvytuHnMRtAukboTx8nNWA?pwd=0101 提取码: 0101
-
如只做AT指令和4G模块功能验证,只需要4G模块和串口调试助手即可
3 MQTT协议接入原理
通过上述步骤,完成了账号注册、创建产品、添加功能点、创建设备步骤,接下来就需要通过MQTT协议将设备连接至OneNET。
3.1 OneNET MQTT协议规范
官方文档说明:https://iot.10086.cn/doc/aiot/fuse/detail/912
3.2 连接参数生成
设备接入物联网平台之前,需通过身份认证,目前平台提供IMEI和设备秘钥两种鉴权方式,对于不同接入方式的设备,鉴权方式不同。
本例采用的是设备密钥方式,即通过设备密钥等参数来生成token。
接入安全验证说明:https://iot.10086.cn/doc/aiot/fuse/detail/913
OneNET提供了token生成工具:https://iot.10086.cn/doc/aiot/fuse/detail/1487
注意:使用token工具生成token时,"et"项是token过期时间,用时间戳表示,单位为秒,必须大于当前时间,否则生成的token无效。在线时间戳转换工具:https://tool.lu/timestamp/
关键参数:
- res:products/产品id/devices/设备名
- et:10位秒级时间戳,必须大于当前时间
- key:设备秘钥

图2 token生成
生成完毕后,记录保存生成的token,后续设备连接物联网平台时使用。
3.2 主题(Topic)规范
物联网平台中,服务端和设备端通过通信主题topic实现消息通信,设备可以通过发布消息到系统 topic 调用服务接口,也可以订阅系统 topic 用于接收服务消息通知。
MQTT通信主题列表:https://iot.10086.cn/doc/aiot/fuse/detail/920
通过上述步骤,得到了接入OneNET物联网平台的必备参数,下面进行实例验证。
4 基于MQTT客户端的交互实例
OneNET文档中心给出了mqttfx客户端功能验证实例:https://iot.10086.cn/doc/aiot/fuse/detail/922
即通过软件模拟设备,这样即使手里没有无线模块也可对相关功能进行验证。
5 基于串口助手的交互实例验证
5.1 设备准备
本例子验证需要准备以下设备:
- 4G模块:中移4G模块ML307C
- 串口调试工具:SSCOM等串口助手
在下面这个例子中,我们利用串口助手进行功能验证,在串口助手中进行基本功能验证之后才方便于后续编程。
例子主要利用ML307C的相关MQTT指令验证如下功能:接入OneNET平台、订阅属性类主题、上报设备属性、OneNET获取设备属性。
5.2 ML307C相关MQTT指令
ML307C MQTT AT指令手册地址: https://pan.baidu.com/s/14lJKJr_G9SBXIU7V-JLZsA?pwd=0101 提取码: 0101
本例子中主要用到了如下几个命令:
AT+MQTTCFG="clean",<connect_id>[,<clean_session>]//配置会话类型
AT+MQTTCONN=<connect_id>,<host>[,<port>[,<clientID>,<user>,<passwd>]]//连接
AT+MQTTSUB=<connect_id>,<topic>,<qos>[,<topic1>,<qos1>..]//订阅话题
AT+MQTTPUB=<connect_id>,<topic>,<qos>,<retain>,<dup>,<msg_len>[,<message>]//发布消息
在开始接入之间,我们先查询相关参数,命令:
AT+MQTTCFG="query"
查询结果:

图3 ML307C默认参数查询结果
根据查询结果,我们主要关注这个参数:clean,其他的参数在进行功能验证的时候,保持默认即可,后续在进行实际开发时再根据需要具体设定。
这个参数的含义我们可以查看ML307C的MQTT手册:

图4 clean_session含义
下面是关于clean_session的具体含义解释:
clean_session = true(或1):
全新会话:客户端连接时,代理将创建一个全新的会话
不保存状态:断开连接后,代理会立即丢弃该客户端的:
所有订阅信息
未确认的QoS 1和QoS 2消息
会话状态
无离线消息:客户端断开期间,代理不会为其存储任何消息
clean_session = false(或0):
持久会话:代理会为客户端保存会话状态
保存状态:断开连接后,代理会保留:
客户端的订阅信息
未送达的QoS 1和QoS 2消息
会话状态(直到会话过期)
接收离线消息:客户端重连后,可以收到断开期间错过的消息
也就是,clean_session默认值为0,但是OneNET平台是不支持的,设备使用MQTT协议接入平台,该值必须设置为1,这个限制我们可以在平台:文档中心--产品开发--设备接入--设备开发--MQTT协议接入--使用限制下看到,如图所示:

图5 OneNET平台MQTT协议使用限制
好了,通过上面的步骤,我们已经准备好了,下面进行验证。
基本流程:
(1) 配置会话类型,将clean_session设置为1
命令原型:
AT+MQTTCFG="clean",<connect_id>[,<clean_session>]
命令配置:
AT+MQTTCFG="clean",0,1
配置结果:配置成功,返回OK

图6 clean参数配置
(2) 连接
命令原型:
AT+MQTTCONN=<connect_id>,<host>[,<port>[,<clientID>,<user>,<passwd>]]
命令配置:
AT+MQTTCONN=0,"mqtts.heclouds.com",1883,"设备名称","产品名称","生成的token"
第一个参数是connect_id,范围是0~5,使用其中一个即可,这里使用0。
连接结果:连接成功返回
+MQTTURC: "conn",0,0

图7 连接结果
(3) 订阅话题
命令原型:
AT+MQTTSUB=<connect_id>,<topic>,<qos>[,<topic1>,<qos1>..]
命令配置(下面这个命令可一键订阅属性类话题,OneNET平台有限制,每个设备最大只能订阅10个话题,属性类正好10个话题,这些限制OneNET平台文档中心均有说明):
AT+MQTTSUB=0,"$sys/产品名称/设备名称/thing/property/#",0
订阅结果:

图8 订阅结果
(4)订阅好话题之后,我们就可以向相应的话题发布消息了,上面我们一键订阅了属性类所有话题,下面我们就进行设备属性上传和平台获取设备属性的功能验证。
首先是设备属性上传,即向平台上传设备属性消息。设备向平台发送消息的时候,消息的格式要按照平台规定的来,平台已经对每种消息格式进行了规定,均为JSON格式。
下面这个是设备属性上传的格式:

即:
{ "id": "123", "version": "1.0", "params": { "Power": { "value": "on", "time": 1524448722123 }, "WF": { "value": 23.6, "time": 1524448722123 } } }
好了,知道了向平台发送消息的格式,下面我们进行发送消息验证。
命令:
AT+MQTTPUB=<connect_id>,<topic>,<qos>,<retain>,<dup>,<msg_len>[,<message>]
在这之前,我们先看一下我们平台上的参数:

图9 平台功能定义
在平台上我已经定义好了三个参数,这里使用Iref来进行验证,这是一个只读的参数,也就是平台只能读不能写。我们设备可以上传其参数值,这里我们上传350。
JSON数据格式如下:
{"id":"123","version":"1.0","params":{"Iref":{"value":350}}}
计算出消息长度:60
在线字节计算工具:https://tool.hiofd.com/byte-counter/
实际的命令如下(大家在进行验证时根据自己的相关参数进行替换即可)
AT+MQTTPUB=0,"$sys/hN5MfoIff8/ML307_DL_CN_02/thing/property/post",0,0,0,60,"{"id":"123","version":"1.0","params":{"Iref":{"value":350}}}"
属性上报结果:我们订阅了属性类的设备上报回复的话题,上报后平台会进行回复。

图10 属性上报结果
同时,我们可以在平台看到我们上传的值:

图11 平台接收结果
好了,属性上报的功能我们验证完了,下面我们验证平台获取设备属性的功能。在这里,我们需要用到平台的设备调试--应用模拟器功能:

图12 平台应用模拟器
同理,我们先查看平台获取设备属性时,我们如何回复,即回复的消息格式。

图13
设备在接收到平台获取属性的消息之后,需要以这个消息格式回复平台,未及时回复,平台上会显示超时。
{
"id":"123",
"code":200,
"msg":"xxx",
"data":{
"temperature":39.5,
"humidity":20
}
}
这里特别注意一点,回复时,id号需要和平台下发的id号保持一致。
这里我们获取Iref的值:
属性获取结果:

图14

图15 平台获取设备属性结果
回复时用到的完整命令:
AT+MQTTPUB=0,"$sys/hN5MfoIff8/ML307_DL_CN_02/thing/property/get_reply",0,0,0,60,"{"id":"13","code":"200","msg":"success","data":{"Iref":270}}"
获取成功后,平台上设备的属性值改变为我们上传的值。
好了,简单的功能验证就到这里了。有什么问题欢迎讨论。
遇到的问题
在这个过程中遇到的一个比较玄幻的问题就是:连成成功、订阅成功后设备只要向云端发消息就会断开连接,云端日志显示是协议错误,但是检查了很多遍没有问题,最后玄学了一波,把原来的设备删了,重新建立了一个设备,一模一样的指令,莫名其妙就好了。
浙公网安备 33010602011771号