概述
M5310A--学习笔记
- 前言
- 对官方例程进行粗略解析
- 2020.05.14更新:下行命令处理。
- 2020.12.14更新:发现了神奇的研究笔记
- 对例程进行二次开发主要注意以下几点
前言
本文使用中国移动OneNET 开发板-NB版 CM1719_V2.1
模组为M5310-A 通过LwM2M协议接入OneNet
使用官方提供的例程运行流程进行梳理。
对官方例程进行粗略解析
- 声明需要传递的变量的结构体
nbiot_value_t temp; /* 温度 */
nbiot_value_t humi; /* 湿度 */
nbiot_value_t illumi; //光照
nbiot_value_t press; //压力
nbiot_value_t altitude; //海拔
nbiot_value_t acceleX; //三轴加速x
nbiot_value_t acceleY; //三轴加速y
nbiot_value_t acceleZ; //三轴加速z
nbiot_value_t LED;
- 通过跳转可以看到结构体为:
typedef struct _nbiot_value_t
{
union
{
bool as_bool; //上传值为bool类型(1/0)
int64_t as_int; //上传值为int类型
double as_float; //上传值为float类型
struct
{
char *val; //所需上传的字符串
size_t len; //字符串长度
} as_buf; //上传类型为字符串
} value; //建立一个名为value的联合体
uint8_t type; //该资源的数据类型
uint8_t flag; //该资源的可操作性(可否读写)
} nbiot_value_t; //建立结构体
- 声明相应变量
extern float result_lx; //光照
extern _bmp180 bmp180; //压力/海拔
extern ADXL345_INFO adxlInfo; //三轴加速
//设置一个宏定义变量将所需上传的数据保存到变量中,方便上传资源
- 定义相关参数
char uri[] = "coap://183.230.40.40:5683"; //连接平台地址 IP+端口
nbiot_device_t *dev = NULL; //赋值NULL
time_t last_time = 0; //上一次更新时间
time_t cur_time = 0; //当前时间
- 系统初始化
static bool _nbiot_init_state = false; //系统是否初始化
void nbiot_init_environment( int argc, char *argv[] )
{
if ( !_nbiot_init_state )
{
nbiot_time_init();
M5310_Power_Init();
USART1_Init();
USART3_Init();
Peripheral_Init(); //对硬件进行初始化(LED,蜂鸣器、按键、I2C、BH1750、ADX345)
TIM3_Int_Init(1000-1,720-1);//定时器3定时10ms
mDelay(5000);
netdev_init(); //模组初始化,联网过程
_nbiot_init_state = true; //初始化成功
}
}
- netdev_init()
void netdev_init(void)
{
//SendCmd参数:发送指令,返回指令,延时时间,重试时间,等待时间
//char SendCmd(char* cmd, uint8_t *result,uint16_t timeout,uint8_t retry,uint16_t waittime)
SendCmd("AT+NRBrn", "OK", 5000,0,10); //重启设备
SendCmd("AT+CIMIrn", "OK", 2000,3,5); //检测SIM卡初始化是否成功
SendCmd("AT+CMVERrn", "OK", 5000,0xFFFF,10); //检测M5310的固件版本是否为sp3以上
SendCmd("AT+CMEE=1rn","OK", 2000,0,10); //报告ME错误(未去了解有何作用)
SendCmd("AT+CSCON=1rn","OK", 2000,0,10); //打开状态自动上报
SendCmd("AT+CEREG=2rn","OK", 2000,0,10); //查询 NB 网络注册状态
SendCmd("AT+CEDRXS=0,5rn","OK", 3000,0,5); //貌似为关闭eDRX
SendCmd("AT+CPSMS=0rn","OK", 3000,0,5); //貌似为关闭PSM
SendCmd("AT+CEREG?rn","CEREG:2,1", 3000,1000,5); //查询NB网络附着状态
SendCmd("AT+csqrn", "OK", 2000,0,5); //检测信号
SendCmd("AT+NUESTATSrn", "OK", 2000,0,5); //检测网络质量
printf("connect NB-IoT sucessrn");
Led3_Set(LED_ON); //入网成功后LED3亮
}
- 主程序
int main(int argc, char *argv[])
{
int life_time = 1000;//定义存活时间为1000s
int ret; //资源
nbiot_init_environment(argc, argv);//系统初始化
#ifdef NOTIFY_ACK
ret = nbiot_device_create(&dev,
life_time,
write_callback,
read_callback,
execute_callback,
notify_ack_callback);
#else
ret = nbiot_device_create(&dev,
life_time,
write_callback,
read_callback,
execute_callback);
#endif
if (ret)
{
nbiot_device_destroy(dev);
printf("device add resource(/3200/0/5750) failed, code = %d.rn", ret);
}
//创建资源的流程
//首先声明一个string型资源变量at,然后初始化该资源的属性,最后调用nbiot_resource_add接口将该资源注册进SDK中
LED.type = NBIOT_BOOLEAN;//定义资源为BOOL类型,结构体定义见1
LED.flag = NBIOT_READABLE | NBIOT_WRITABLE;//资源可进行读写操作
ret = nbiot_resource_add(dev,//不变
3311,//objid 传感器类型,需查表
0, //instid 设备序号
5850,//resid 表示传感器某种类型的数据,需查表
&LED); //灯控制
if (ret)
{
nbiot_device_destroy(dev);
printf("device add resource(LED) failed, code = %d.rn", ret);
}//如果失败则报错
temp.type = NBIOT_FLOAT;
temp.flag = NBIOT_READABLE;
ret = nbiot_resource_add(dev,
3303,
0,
5700,
&temp); //温度
if (ret)
{
nbiot_device_destroy(dev);
printf("device add resource(temp) failed, code = %d.rn", ret);
}
humi.type = NBIOT_FLOAT;
humi.flag = NBIOT_READABLE;
ret = nbiot_resource_add(dev,
3304,
0,
5700,
&humi); //湿度
if (ret)
{
nbiot_device_destroy(dev);
printf("device add resource(humi) failed, code = %d.rn", ret);
}
illumi.type = NBIOT_FLOAT;
illumi.flag = NBIOT_READABLE;
ret = nbiot_resource_add(dev,
3301,
0,
5700,
&illumi); //光照
if (ret)
{
nbiot_device_destroy(dev);
printf("device add resource(illumi) failed, code = %d.rn", ret);
}
nbiot_object_add(dev);
ret = nbiot_device_connect(dev, 100);
if (ret)
{
printf("connect OneNET failed.rn");
nbiot_reset();
}
else
{
printf("connect OneNET success.rn");
}
do
{
ret = nbiot_device_step(dev, 1);//是否接收到数据
//nbiot_device_step函数为例程处理上下行数据的总入口。
if (ret)
{
printf("device step error, code = %d.rn", ret);
Led4_Set(LED_OFF);
printf("connect server failed.rn");
nbiot_reset();
}
else
{
res_update(90);//每90s发送一次数据
}
} while (1);
nbiot_clear_environment();//使初始化重新进行
printf("press enter key to exit...");
return 0;
}
- 数据上传程序
void res_update(time_t interval)
{
SHT20_INFO sht20;
if (cur_time >= last_time + interval) //判断是否到达发送时间
{
cur_time = 0;
last_time = 0;//将time清零重新计时
temp.flag |= NBIOT_UPDATED;
humi.flag |= NBIOT_UPDATED;//由于温湿度是同一个模块传出的数据因此将temp和humi的发送标志位同时志1
sht20 = SHT20_GetValue();
temp.value.as_float = sht20.tempreture;
humi.value.as_float = sht20.humidity; //设置上传数据,类型与注册时数据保存一致
illumi.flag |= NBIOT_UPDATED;
BH1750_test();
illumi.value.as_float = result_lx;
}
else if (cur_time == 0 && last_time == 0)//如果两者都为0
{
cur_time = nbiot_time();//rue_time读取rtc时钟
last_time = cur_time;
}
else
{
cur_time = nbiot_time();
}
}
上述粗略的将该程序从启动到发送的过程讲诉了一遍(日后有空再补充)
2020.05.14更新:下行命令处理。
<2020.12.14 更新部分内容>黄色字体标识
根据官方给予的例程说明中可以看到:Demo 例程从下行缓存区里面获取下行数据并正确解析后会自动调用该命令对应的资源中的write钩子函数或者execute钩子函数,用户只需要编写该2个函数即可以完成下行命令的处理。
因此可以找到函数:write_callback()//平台请求写的回调函数
void write_callback(uint16_t objid,
uint16_t instid,
uint16_t resid,
nbiot_value_t *data)
{
printf("write /%d/%d/%d:%drn",
objid,
instid,
resid, data->value.as_bool);
if(objid == 3304 && instid == 0 && resid == 5700){
SHT20_INFO sht20 ={0};
humi.flag |= NBIOT_UPDATED; //将数据更新位开启
sht20=SHT20_GetValue(); //获取数据
humi.value.as_float=(int64_t)sht20.humidity; //将数据赋过去,等待数据上传
}
}
当有数据下发的时候,比如开关的状态被改变时,程序会调用该函数并对的要的数据进行判断,判断条件根据注册的资源而设定
比如:
/*
根据上文资源创建部分可以看出该资源对应的是led灯的控制,所以这一段的作用是判断下行的数据是否是控制LED灯的
如果符合条件,则对LED灯的状态进行改变,
*/
if (objid == 3311 && instid == 0 && resid == 5850)
Led1_Set(data->value.as_bool);//读取下发值,并改变LED灯状态
/*
假设还有一个LED2灯需要控制,我们需要再进行同样的操作,再平台上注册该资源,比如我们将该资源对应的instid设置为1
则判断语句可以如下
*/
if (objid == 3311 && instid == 1 && resid == 5850)
Led2_Set(data->value.as_bool);
以此类推,如果需要对其他资源下发数据进行相应的操作,先判断该资源的objidinstidresid
然后再将data指向该资源数值的类型,如果是float类型的值 就改为data->value.as_float,再将该值传递到需要的地方
以下内容为2020.12.14更新
read_callback() //平台请求读回调函数
void read_callback(uint16_t objid,
uint16_t instid,
uint16_t resid,
nbiot_value_t *data)
execute_callback() //平台请求执行回调函数
void execute_callback(uint16_t objid,
uint16_t instid,
uint16_t resid,
nbiot_value_t *data,
const void *buff,
size_t size)
2020.12.14更新:发现了神奇的研究笔记
真的妙啊,值得研究
- OneNET NB 学习笔记一 终端创建设备、资源过程
- OneNET NB 学习笔记二 内存管理 memb fifo ringbuf
- OneNET NB 学习笔记三 接收数据处理与回复过程
对例程进行二次开发主要注意以下几点
- 如果需要检测某种状态是否发生(比如按键是否按下),需要开启定时器
- 添加新资源需要进行以下操作
- 声明相应结构体
- 声明数据变量
- 注册资源时objid 和resid 不能随意填,最好查表或官网的文档中心查询,instid随意填,一般只有一个数据时填0
- 上传数据前一定要令对应的flag = NBIOT_UPDATED,这样才能被程序识别,而后上传至OneNet平台
- 部分objid和resid
- 资源来自:https://open.iot.10086.cn/bbs/thread-19650-1-1.html
- 例程下载地址 OneNET_M5310A_COAP.zip
第一次写,有些粗略。
如有疑惑可在下方评论,我会抽时间去研究一番,个人水平不是很高,对这方面没有过多的研究,望谅解。
最后
以上就是美好宝马为你收集整理的M5310A--学习笔记前言的全部内容,希望文章能够帮你解决M5310A--学习笔记前言所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复