【IoT】基于MCU实现NB-IoT设备对接移动oneNET平台

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liwei16611/article/details/82733521

本篇主要讲解基于 MCU 对接 oneNET 流程,基于模组对接方式请参考 Blog: 基于模组对接 oneNET 平台

基于 MCU 的方式实现 NB 设备接入,即通过移植 SDK 至设备 MCU 中,通过 MCU 和模组进行交互实现连接到 OneNET 平台。该情况适用于实验阶段或是终端设备对接入 OneNET 平台有较紧急意愿,但设备所用模组暂未支持接入OneNET的情况下。

SDK移植到MCU:

用户如果使用这种软硬件架构的终端设备接入OneNET平台,需要自行将SDK移植到MCU,NB通信模组只是作为透传的传输通道。

SDK移植到NB通信模组:

此终端类型,除了在NB通信模组中移植基础通信套件SDK,还需在NB通信模组中完成基础通信套件AT指令封装、抽象接口实现和底层操作系统及驱动实现,MCU中只需要完成设备应用程序的开发。用户需要调用模组提供的AT指令完成对资源的操作。

本篇文章使用的是 M5310,只需要在 MCU 测做应用层开发:

对用户而言,用M5310开发板接入OneNET平台及数据交互过程只需要关注MCU侧和平台侧的工作流程,M5310模组侧的工作流程是模组自动完成,无需用户操作。MCU侧的工作流程具体包括创建设备(dev)、向设备添加资源(Object/Instance/Resource)、登录请求、响应模组(即平台)指令。

具体的接入实例及步骤见下:

1、移植 SDK 到 MCU

首先需要完成对 SDK 的移植操作,实现把 SDK 植入所需连接到 OneNET 的 MCU 芯片中。

NETWORK 目录:

实现通信模组的驱动,这里实现了M5310模组的驱动

COAP 目录:

在该目录中实现了M5310的Demo程序,该Demo程序屏蔽了M5310的驱动细节,并向用户提供了相应的操作接口。

Platform 目录:

该目录抽象了一些系统接口,方便用户对Demo程序进行移植,如内存管理和时间管理,下面将会详细对该目录下的文件进行说明。

2、配置网络

在连接OneNET平台之前需要对设备侧进行网络配置:

包括接入机的地址和鉴权信息等参数(即IMEI、IMSI)。

创建设备:

MCU侧创建设备(dev)包括向设备添加endpoint_name(包括IMEI和IMSI)、URI(重庆接入机地址:"coap://183.230.40.40:5683")、lifetime(设备在平台生存周期,最长24小时)、回调函数(包括读写执行函数)。创建设备函数如下:

nbiot_device_create( &dev,

                                endpoint_name,

                                   uri,

                                life_time,

                                write_callback,

                                 read_callback,

                                 execute_callback );

在该函数中使用AT+MIPLCONF指令在模组中创建设备,其使用格式为:

AT+MIPLCONF=<size>,<config>,<index>,<flag>

其中,<size>指示<config>部分总数据长度,按照ASCII计数;

<config>具体的设备配置数据,满足配置结构体规范;

<index>配置数据分片参数;

<flag>配置数据流结束符。

3、配置资源

设备上所有与 onenet 进行交互的数据变量都需要表示为资源,比如温湿度传感器的温度和湿度可以分别表示为 2 个值类型为 float 的资源,不过在 main.c 函数中为了方便同时传输温湿度的值,就把这两个值转换为字符串的形式,用一个 string 类型的资源就可以表示了。

配置好资源属性后,设备在向服务器注册的过程中会携带相应的资源列表 , 服务器端会主动向设备订阅(Observe)资源列表中所有资源。

属性 描述
objid 描述了设备上的传感器类型
instid 描述了该类型传感器的编号
resid 描述传感器的某种类型的数据,如温度的当前值,最大值,最小值
flag 该资源的可操作性,支持的类型有可读/可写/可执行
type 该资源的数据类型,支持的类型有bool/int/float/string/bin
write 用户写该资源的钩子函数
execute 用户执行该资源的钩子函数

注意:objid和resid是不能够随意定义的,必须遵守《IPSO-Smart-Objects-Expansion-Pack》文档中的规定

配置示例:

向设备添加资源:

向设备添加资源为如下函数:

nbiot_resource_add( dev,

Object ID,

Instance Index,

Resource ID,

数据类型结构体 );

其中,dev是创建设备函数中所创建的设备;Object ID是参考IPSO定义的对象ID;Instance Index是对象实例的编号(从0开始编号);Resource ID是参考IPSO定义的资源ID;数据类型结构体是所定义资源的所有可能的数据类型。

在该函数中使用两个AT指令:

使用AT+MIPLADDOBJ指令在模组中添加对象(object),其使用格式为:

AT+MIPLADDOBJ=<ref>,<objectid>,<instanceid>;

其中,<ref>表示OneNET通信实例的引用ID;

<objectid>为具体Object的ID;

<instanceid>为实例的序号,从0开始编号。

例如,创建一个Object为3200,instance为0的对象,AT指令如下:

AT+MIPLADDOBJ=0,3200,0;

使用AT+MIPLNOTIFY指令将资源添加到对象下面,其使用格式为:

AT+MIPLNOTIFY=<ref>,<objectid>,<instanceid>,<resourceid>,<valuetype>,<value>,<flag>,[<ackid>];

其中,<ref>:OneNET通信实例的引用ID;

<objectid>:具体Object的ID;

<instanceid>:实例的序号,从0开始编号;

<resourceid>:资源ID;

<valuetype>:OneNET支持的数据类型包括,string,opaque,integer,float,bool和hex_str;

<value>:具体数值,其大小不超过1024Bytes;

<flag>:‘1’表示所有已订阅的对象实例资源已添加完成,模组将会更新到服务器;‘0’表示还有对象实例资源没添加;

<ackid>:选填,如果设置大于0,则OneNET会返回ACK。

4、心跳设置,也即终端保活机制

设备端的 SDK 在初始化的时候会设置 lifetime 的值,并在向服务器注册的时候上传该值, SDK 在到期后会主动向服务器发送Update消息,如服务器端未收到 Update 消息,服务器端将抛弃所有上报的 Notify 消息并向该设备发送 RST 消息。

用户需要在设备驱动 Main 函数中设置 lifetime 的值,例程在登陆云平台的时候会将该值告知云平台,如果超时了模组将会向上提示 MIPLCLOSE 的信息,例程收到该信息后会重新登陆,整个过程不需要用户参与。

需要注意得是 lifetime 值要根据具体的应用场景设置,太短不利于模组休眠,太长则不利于平台监控设备掉线的情况,默认为300s。

5、数据发送

如果有资源的值被更新了,需要调用 nbiot_device_notify 通知 SDK 该资源的值发生了变化,由 SDK 择机上传至 onenet。

在某个时刻如果用户需要上传某个资源的值,只需要设置该资源的 flag 属性为 NBIOT_UPDATED,用来通知设备驱动该资源的值发生了变化,例程会自动将该资源的新值上传至 onenet 中。

例如,在设备驱动 main.c 应用程序中设置每 30 秒上传一次温湿度传感器的值,进入 res_update 函数中,首先将 at 资源的状态设置为 NBIOT_UPDATED,然后读取温湿度传感器的值,接着将值转化为字符串形式并存储在 tmp 数组内,最后把利用nbiot_strdup 函数把 tmp 的内容复制到 at 资源的 buf 中。

(5)下行处理。 命令由第三方应用发送至onenet,并由云平台转发至终端设备,读写命令和执行命令均直接发送至终端,SDK会自动调用该命令对应的资源中的 write 钩子函数或者 execute 钩子函数,用户只需要编写该两个函数即可以完成下行命令的处理。

6、下行命令处理

命令由第三方应用发送至 onenet,并由云平台转发至终端设备,终端只需要将下行命令缓存起来等待设备端处理即可。设备端驱动从下行缓存区里面获取下行数据并正确解析后会自动调用该命令对应的资源中的 write 钩子函数或者 execute 钩子函数,用户只需要编写该2个函数即可以完成下行命令的处理。

7、下行 ACK 处理

用户上传数据后,往往会希望获知上传的结果,即平台是否已经正确收到了上传的数据并返回了相应的 ACK,这里有一个宏定义开关 NOTIFY_ACK,如果不打开这个开关,则例程不会进行重传;如果打开这个开关,例程会自动处理下行 ACK, 超时则会触发重传,在处理完下行 ACK 后会触 发notify_ack_callback 回调,这样用户可以在该回调函数中完成收到 ACK 后的后续处理。

 

猜你喜欢

转载自blog.csdn.net/liwei16611/article/details/82733521