物联网实战--驱动篇之(九)NB-IOT(BC260)

目录

一、NB-IOT简介

二、NB-IOT要素

三、代码详解

四、平台端


一、NB-IOT简介

        实际上,就是NB-Iot彻底引爆了物联网的,大概2018年左右,NB推广如火如荼,同时广域网、低功耗的LPWAN网络也逐渐传开,现在回头来看,还是有些过火了,实际上还是得结合市场的。目前NB的主要市场还是在市政领域,水表、气表、停车场地磁等等,基本上是政企推动的;技术上,NB和LoRa有交集,但是更多的互补关系。NB在推广上主要的是电信,移动也算还好,联通就比较少看到了,因为NB基站需要重新部署,涉及到投入产出的问题,就目前来看,电信应该县级城市都有覆盖了。

        在使用上,我之前主要还是使用电信的,电信刚开始只有电信IOT平台,开账号得企业,比较麻烦,说实话也不好用,后面电信又出了个AEP平台,这个整体体验还不错,所以我们这里也以AEP为主,驱动程序也主要还是框架,像移动的onenet和阿里平台还没具体实现,有时间再慢慢完善。AEP网址在这儿,自己去注册https://sso.ctwing.cn/login?service=https%3A%2F%2Fwww.ctwing.cn%2Flogin%2Fcas#/

        

二、NB-IOT要素

        NB要素主要有以下几个:

IMEI--模块识别码,平台一般当作身份信息;

ICCID--20位的卡号,装NB卡了才有;

NB卡--这个需要联系客户经理给你开卡,跟我们平时的4G卡外形一样,但有本质区别,不能通用,其中电信NB卡一般是按次收费,一般2万次/年,算下来差不多半小时发送一次,够用了,移动一般是一年360M,具体套餐由费用决定,要跟客户经理商谈;

模块费用:我们这里的模块型号是移远的BC260Y,支持电信跟移动,模组+外设元器件估计也是要20+的,我这里购买成品模块,36块,NB卡10块,购买可以参考这里https://item.taobao.com/item.htm?_u=kpfmfmg80d4&id=675137321790&skuId=5031188443830&spm=a1z09.2.0.0.67002e8d7mF2cG

低功耗:这里暂时没有涉及低功耗,因为这个最好用具体项目讲解比较好理解,NB的低功耗比较特别,不仅跟模块配置有关,还跟NB卡有关,不同的APN对应不同的低功耗水平,简单讲就是唤醒后多久进入睡眠是卡决定的,不过这里不同厂家可能不一样,仅做参考。

三、代码详解

        整个流程跟4G类似,差别在于,NB一般对接中间平台,如电信AEP、移动onenet,在平台上编辑插件对设备消息进行解析,解析完后推送给你自己的平台,整个流程也没有很轻松,刚开始电信的NB只能对接电信IOT平台,刚开始bug又很多,使用起来确实不太畅快。

        硬件连接上,使用串口2,波特率是9600,我采购的模块电源是3.3V的,STM32的PA2接模块RX,PA3接模块TX。

        这里的流程需要根据不同的平台分开定义,我们先看AEP的,在网络注册流程中,只要卡没问题,模块会自己注册,我们只要不断查询注册状态即可,注册成功一般会返回

+CEREG: 0,1

主要是后面的1这个状态值,有时候是5,是这两个值就可以认为注册成功了。

网络没问题之后,就要根据不同平台走连接流程了,AEP相对比较简单,如下图所示,IP和端口都是固定的,这里用的是LWM2M协议,COAP的端口是5682,连接成功后就可以进行数据收发了。


/*		
================================================================================
描述 : 注册流程
输入 : 
输出 : 
================================================================================
*/
void drv_bc260_reg_process(void)
{static u32 last_sec_time=0, wait_time=2;u32 now_sec_time=drv_get_sec_counter();if(now_sec_time-last_sec_time>wait_time){switch(g_sBc260Work.state){case BC260_STATE_START:{drv_bc260_send_at("QRST=1");//复位模块  g_sBc260Work.state=BC260_STAT_INIT;wait_time=5;break;}case BC260_STAT_INIT:{drv_bc260_send_at("CSQ");delay_os(200);drv_bc260_send_at("QSCLK=0");//禁用休眠模式delay_os(200);drv_bc260_send_at("CSCON=1");//使能信令连接状态上报g_sBc260Work.state=BC260_STAT_CEREG;wait_time=2;break;}    case BC260_STAT_CEREG://网络注册状态{ drv_bc260_send_at("CEREG?");//查询wait_time=2;break;}       case BC260_STAT_AEP_INIT:{ drv_bc260_send_at("NNMI=1");//将数据接收模式设置为直吐模式delay_os(200);drv_bc260_send_at("NCFG=0,86400");//配置生命周期时间,秒g_sBc260Work.state=BC260_STAT_AEP_CONNECT;wait_time=2;break;}case BC260_STAT_AEP_CONNECT://连接到服务器{ drv_bc260_send_at("NCDPOPEN=\"221.229.214.202\",5683");wait_time=3;break;}     case BC260_STAT_OK:{ if(g_sBc260Work.imei_buff[0]==0){drv_bc260_send_at("CGSN=1");delay_os(200);}else if(g_sBc260Work.iccid_buff[0]==0){drv_bc260_send_at("QCCID");delay_os(200);          }else{drv_bc260_send_at("CSQ");}wait_time=5;break;}       }last_sec_time=drv_get_sec_counter();}}

        数据解析也是匹配关键字,具体如下:


/*		
================================================================================
描述 : 十六进制字符串转字节数组
输入 : 
输出 : 
================================================================================
*/
void hex_str_to_array(char *hex_str, char *out_array, u16 array_len)
{for(u16 i=0; i<array_len; i++){sscanf(hex_str+i*2, "%02hhX", &out_array[i]);}
}/*		
================================================================================
描述 : 接收处理
输入 : 
输出 : 
================================================================================
*/
void drv_bc260_recv_process(void)
{u16 recv_len;char *pData=NULL;if(g_sBc260Work.pUART->iRecv>0){recv_len=0;while(recv_len<g_sBc260Work.pUART->iRecv){recv_len=g_sBc260Work.pUART->iRecv;delay_ms(5);}char *pBuff=(char*)g_sBc260Work.pUART->pBuff;printf("bc260 recv=%s\n", g_sBc260Work.pUART->pBuff);if( (pData=strstr(pBuff, "+NNMI: "))!=NULL )//AEP接收到数据{pData+=strlen("+NNMI: ");u16 data_len=atoi(pData);if( (pData=strstr(pData, ","))!=NULL && data_len<100){pData+=1;char data_buff[100]={0};hex_str_to_array(pData, data_buff, data_len);printf_hex("data=", (u8*)data_buff, data_len);if(g_sBc260Work.fun_recv_parse!=NULL){g_sBc260Work.fun_recv_parse((u8*)data_buff, data_len);}}}else if((pData=strstr(pBuff, "+QLWEVTIND: "))!=NULL ){pData+=strlen("+QLWEVTIND: ");u8 type=atoi(pData);if(type==3)//AEP服务器订阅成功{g_sBc260Work.state=BC260_STAT_OK;}}else if((pData=strstr(pBuff, "+CEREG: "))!=NULL ){pData+=strlen("+CEREG: ");pData+=2;u8 state=atoi(pData);if(state==1 || state==5)//网络已注册{switch(g_sBc260Work.server_type){case BC260_SERVER_ONENET://移动OneNet{break;}case BC260_SERVER_CHINANET_IOT://电信IOT{break;}case BC260_SERVER_CHINANET_AEP://电信AEP{g_sBc260Work.state=BC260_STAT_AEP_INIT;//进入AEP的初始化break;}case BC260_SERVER_ALI://阿里平台{break;}          }}}    else if((pData=strstr(pBuff, "+CSQ: "))!=NULL ){pData+=strlen("+CSQ: ");g_sBc260Work.rssi=atoi(pData);printf("***rssi=%d\n", g_sBc260Work.rssi);}    else if((pData=strstr(pBuff, "+CGSN: "))!=NULL ){pData+=strlen("+CGSN: ");memcpy(g_sBc260Work.imei_buff, pData, 15);printf("***imei=%s\n", g_sBc260Work.imei_buff);}      else if((pData=strstr(pBuff, "+QCCID: "))!=NULL ){pData+=strlen("+QCCID: ");memcpy(g_sBc260Work.iccid_buff, pData, 20);printf("***iccid=%s\n", g_sBc260Work.imei_buff);}  UART_Clear(g_sBc260Work.pUART);}}

        这里比较特殊的是,跟ESP8266和AIR780相比,NB返回的数据是十六进制的字符串,需要转换,以上的hex_str_to_array()函数可以看下,对于发送也是如此,要把字节数组转成字符串,具体如下:


/*		
================================================================================
描述 :
输入 : 
输出 : 
================================================================================
*/
void drv_bc260_send_data(u8 *buff, u16 len)
{if(g_sBc260Work.state!=BC260_STAT_OK)return;static char send_buff[200]={0};if(len*2+10<sizeof(send_buff)){memset(send_buff, 0, sizeof(send_buff));sprintf(send_buff, "AT+NMGS=%d,", len);for(u16 i=0; i<len; i++){char temp_buff[5]={0};sprintf(temp_buff, "%02X", buff[i]);strcat(send_buff, temp_buff);}strcat(send_buff, "\r\n");
//    printf("send data=%s\n", send_buff);drv_bc260_uart_send(send_buff);	}  
}

        应用数据接收后依然采用回调函数的方式进行处理,自己应用层去定义和注册,跟之前的WIFI和4G都差不多。

        软件方面基本上就这些了,对于AEP平台没有很复杂,后面有时间再继续完善Onenet等其它平台的流程。应用层其实就是初始化+主程序循环了。

这里我在user_app.c里加了点测试代码,这样就可以随时发送测试了。

四、平台端

        平台端注册完后要创建产品,具体流程可以参考文档,

        注意点是协议要选LWM2M,然后添加设备的IMEI要是你测试模块的IMEI,这样才能收得到数据,整体页面如下:

        设备上线后指示灯会由灰转绿色,数据查看和指令设置如下图所示,点击后会有响应显示。

数据格式可以选择16进制,便于观察;指令下发直接输入就行了,但是下发后模块一般不会马上收到,需要在模块主动上报数据后一个区间内才收的到,这也是低功耗的代价了,以后具体项目再深入讲解。

        由上图可知,主动发送后大概过了10秒才收到刚才下发的指令。

        NB设备端的整个开发流程大概就是这样了,平台端还有个物模型,就是解析插件,用来解析数据,具体可以看教程https://www.ctwing.cn/sbgl/539#see,这里贴出以前做过的示例:

驱动程序:https://download.csdn.net/download/ypp240124016/89180826

文档资料:https://download.csdn.net/download/ypp240124016/89181042

 

本项目的交流QQ群:701889554

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/1114.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python爬虫爬取中药材价格数据

&#x1f388; 博主&#xff1a;一只程序猿子 &#x1f388; 博客主页&#xff1a;一只程序猿子 博客主页 &#x1f388; 个人介绍&#xff1a;爱好(bushi)编程&#xff01; &#x1f388; 创作不易&#xff1a;喜欢的话麻烦您点个&#x1f44d;和⭐&#xff01; &#x1f388;…

【Leetcode每日一题】 穷举vs暴搜vs深搜vs回溯vs剪枝_全排列 - 全排列(难度⭐⭐)(62)

1. 题目解析 题目链接&#xff1a;46. 全排列 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 回溯算法是一种通过探索所有可能的候选解来找出所有解的算法。当候选解被确认不是一个解&#xff08;或者至少不是最后一…

包装类的认识

前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; hellohello~&#xff0c;大家好&#x1f495;&#x1f495;&#xff0c;这里是E绵绵呀✋✋ &#xff0c;如果觉得这篇文章还不错的话还请点赞❤️❤️收藏&#x1f49e; &#x1f49e; 关注&#x1f4a5;&#x1…

网络编程 -- 简易TCP网络程序

一 字符串回响 1.1 核心功能 字符串回响程序类似于 echo 指令&#xff0c;客户端向服务器发送消息&#xff0c;服务器在收到消息后会将消息发送给客户端&#xff0c;该程序实现起来比较简单&#xff0c;同时能很好的体现 socket 套接字编程的流程。 1.2 程序结构 这个程序我们…

基于Zookeeper 简单实现分布式任务协调组件

优质博文&#xff1a;IT-BLOG-CN 一、什么是 Zookeeper ZooKeeper是一个分布式的&#xff0c;开放源码的分布式应用程序协调服务&#xff0c;是Google的Chubby一个开源的实现&#xff0c;是Hadoop和Hbase的重要组件。 它是一个为分布式应用提供一致性服务的软件&#xff0c;提…

【管理】杨三角模型

企业成功 成功 战略 X 组织能力 1&#xff09;组织能力对于企业的重要性是和战略一样的&#xff1b; 2&#xff09;组织能力必须与战略适配&#xff0c;才能共同造就企业的成功。 员工思维&#xff1a;员工愿不愿意参与战略落地的实践&#xff1f;员工每天所关心、追求和重视的…

【C++】哈希封装map与set

目录 前言&#xff1a; 一&#xff0c;底层哈希结构 1-1&#xff0c;迭代器的封装 1-2&#xff0c;哈希表的封装 二&#xff0c;unordered_map的封装 三&#xff0c;unordered_set的封装 前言&#xff1a; 上一篇文章说明了哈希结构&#xff0c;这一篇文章来说明如何使用…

安装WSL2

PS C:\Users\pc> wsl --set-default-version 2 有关与 WSL 2 关键区别的信息&#xff0c;请访问 https://aka.ms/wsl2操作成功完成。PS C:\Users\pc> wsl --update 正在检查更新。 已安装最新版本的适用于 Linux 的 Windows 子系统。PS C:\Users\pc> wsl --shutdownPS…

PyTorch深度解析:Tensor——神经网络的核心构建块

在深度学习和神经网络的研究与应用中&#xff0c;Tensor&#xff08;张量&#xff09;无疑是一个核心概念。特别是在PyTorch这一强大的深度学习框架中&#xff0c;Tensor更是扮演了举足轻重的角色。本文将深入探讨PyTorch中的Tensor&#xff0c;从其基本定义、特性、操作到实际…

回溯算法练习day.3

39.组合总和 链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返…

uniapp Android 插件开发教程

一、下载uniapp提供的SDK Android 离线SDK - 正式版 | uni小程序SDK 二、在uniapp创建一个项目 查看包名&#xff1a;发行--> 原生app 云打包 三、进入dcloud官网 开发者中心 进入 应用管理 --> 我的应用 --> 点击应用名称-->各平台信息-->新增 这里需要这…

SQLite FTS3 和 FTS4 扩展(三十二)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLite FTS5 扩展&#xff08;三十&#xff09; 下一篇&#xff1a;SQLite—系列文章目录 概述 FTS3 和 FTS4 是 SQLite 虚拟表模块&#xff0c;允许用户执行 对一组文档进行全文搜索。最常见&#xff08;和最…

paddle.net怎么付款?paddle.net怎么订阅?

有需要的小伙伴可以使用Fomepay的卡进行订阅支付&#xff0c;我这里使用的是491090卡段&#xff0c;开卡步骤很简单&#xff0c;点击获取卡片 1、注册 2、填写姓名使用拼音或者英文名都可以 3、支付宝或者微信支付

基于51单片机的数字万用表设计

基于51单片机的数字万用表设计 &#xff08;仿真&#xff0b;程序&#xff0b;原理图PCB&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 1.能够切换测量电压、电流、电阻&#xff1b; 2.数码管实时显示测量值&#xff1b; 3.短路报警&#xff1b; 4.测量…

Vue.extend()和我的两米大砍刀

Vue.extends是什么&#xff1f; 一个全局API,用于注册并挂载组件。 传统的引用组件的方式是使用import直接引入&#xff0c;但是使用Vue.extends()也可以实现。 使用规则 <div id"mount-point"></div>// 创建构造器 var Profile Vue.extend({templat…

Spring 声明式事务控制

1. 编程式事务控制相关对象 1.1 PlatformTransactionManager PlatformTransactionManager 接口是 spring 的事务管理器&#xff0c;它提供了我们常用的操作事务的方法。 PlatformTransactionManager 是接口类型&#xff0c;不同的 Dao 层技术则有不同的实现类。例如:Dao层技…

3分钟看懂Microchip 32位MCU CAN模块的配置

文章目录 CAN模块系统框图Microchip MCC Harmony下CAN模块配置选项CAN模块工作模式CAN模块中断模式CAN工作速率Bit Timing Calculation配置CAN 接收的配置CAN 发送的配置CAN 过滤器工作流程说明CAN 过滤器的配置 CAN模块系统框图 CAN的英文全称&#xff1a;Control Area Networ…

连续时间折线图的前后端实现

技术栈 vue3VChartegg.jsMySQL 需求 根据已有任务数据&#xff0c;获取连续天的任务完成的数量&#xff0c;并且通过接口返回后做成图表。预期数据如下&#xff1a; [{"x": "2024-01-01","y": 0},{"x": "2024-01-02",&q…

Python实现KDJ工具判断信号:股票技术分析的工具系列(8)

Python实现KDJ工具判断信号&#xff1a;股票技术分析的工具系列&#xff08;8&#xff09; 介绍算法公式 代码rolling函数介绍完整代码data代码KDJ.py 介绍 KDJ是一种技术指标&#xff0c;用于衡量价格动量&#xff0c;帮助交易者识别趋势的强度和转折点。 先看看官方介绍&am…