09_NB-IoT模块数据发送流程与实现

09_NB-IoT模块数据发送流程与实现

大家好呀!我是你们的老师,今天咱们继续聊 NB-IoT 模块(骑士100,也就是 Quectel BC95)的事儿。上节课初始化完了,今天咱们重点讲咋用它把 GPS 数据发出去,从头到尾过一遍流程,搞清楚每一步咋干。别慌,咱们一步一步来,保证你能弄懂!走起!

1. 目标分析:NB-IoT 模块要干啥?

咱们先理理思路,初始化完 NB-IoT 模块后,接下来干啥?其实很简单,核心目标就是把数据发出去。

  • 目标明确:GPS 数据已经收到了(比如经纬度啥的),咱们得用 NB-IoT 模块把这些数据发到云端服务器。

  • 对比经验:之前用过的 LoRa 模块(比如 SX1276),发数据得建连接,NB-IoT 也差不多,先得建个 Socket,再发数据。

  • 核心问题:咋建连接?咋发数据?发完咋确认成功?得一步步搞清楚。

流程图:目标分析

 

NB-IoT模块初始化完成

获取GPS数据

通过NB-IoT发送到云端

创建Socket连接

发送数据

确认发送成功

补充例子

假设 GPS 数据是 latitude=30.4688,longitude=114.4689,咱们得用 NB-IoT 发到云端的一个服务器,比如 IP 是 112.125.89.8,端口 44939

2. 第一步:判断是否联网

发数据前,先得确认 NB-IoT 模块联网没。插上 SIM 卡和天线,按理说一上电就该联网,但得确认下。

  • 联网状态:就像手机插上 SIM 卡,能连上中国移动啥的,但不一定有数据交互。咱们得确认模块是不是处于“附着”状态。

  • AT 指令:用 AT+CGATT? 查询附着状态。返回 +CGATT:1 表示已附着(联网),+CGATT:0 表示未附着(没联网)。

  • 处理逻辑:发 AT+CGATT?,看响应。如果是 0,说明没联网,报错给用户,检查 SIM 卡、天线、芯片啥的。如果是 1,继续下一步。

流程图:判断是否联网

 

发送AT+CGATT?

等待响应

+CGATT:1

+CGATT:0

已联网,继续

未联网,报错

检查SIM卡/天线/芯片

补充例子

发送指令代码:

int_qs100_send_cmd((uint8_t *)"AT+CGATT?\r\n");
int_qs100_handle_response();
if (strstr((char *)qs100_response_buffer, "+CGATT:1") != NULL) {
    // 已联网,继续
} else {
    printf("Error: Not attached to network\r\n");
    return;
}

3. 第二步:创建 Socket

联网了,接下来得创建个 Socket,才能发数据。啥是 Socket?就是个通信通道。

  • AT 指令:用 AT+NSOCR 创建 Socket。格式:AT+NSOCR=<type>,<protocol>,<listen_port>,<socket_id>,<receive_control>

    • type:流式传输,填“DGRAM”。

    • protocol:咱们用 TCP(有连接),填“6”。

    • listen_port:本地端口,填“0”让系统随机分配(反正咱们是发数据,不咋用本地端口)。

    • socket_id:Socket ID,芯片支持 0 或 1,咱们填“0”。

    • receive_control:0 表示忽略下行消息(咱只发,不收)。

  • 响应结果:成功返回 +NSOCR:<socket_id>,比如 +NSOCR:0,表示创建成功,Socket ID 是 0。

  • 循环尝试:如果创建失败,每秒试一次,最多试 20 次,20 秒还不成,报错。

流程图:创建 Socket

 

计数<20

计数>=20

发送AT+NSOCR

等待响应

+NSOCR:0

失败

创建成功,继续

每秒重试,计数+1

报错:创建失败

补充例子

创建 Socket 代码:

int retry = 0;
while (retry < 20) {
    int_qs100_send_cmd((uint8_t *)"AT+NSOCR=DGRAM,6,0,0,0\r\n");
    int_qs100_handle_response();
    if (strstr((char *)qs100_response_buffer, "+NSOCR:0") != NULL) {
        break; // 创建成功
    }
    HAL_Delay(1000); // 每秒重试
    retry++;
}
if (retry >= 20) {
    printf("Error: Failed to create socket\r\n");
    return;
}

4. 第三步:创建连接

Socket 有了,得连上服务器。咋连?用服务器的 IP 和端口。

  • AT 指令:用 AT+NSOCO 创建连接。格式:AT+NSOCO=<socket_id>,<remote_addr>,<remote_port>

    • socket_id:刚才创建的 Socket ID,填“0”。

    • remote_addr:服务器 IP,比如 112.125.89.8

    • remote_port:服务器端口,比如 44939

  • 响应结果:成功返回“OK”,表示连接建立。

  • 循环尝试:如果失败,每秒试一次,最多 20 次,20 秒失败就报错。

流程图:创建连接

 

计数<20

计数>=20

发送AT+NSOCO

等待响应

OK

失败

连接成功,继续

每秒重试,计数+1

报错:连接失败

补充例子

假设服务器地址是 112.125.89.8:44939

int retry = 0;
char cmd[64];
sprintf(cmd, "AT+NSOCO=0,%s,%u\r\n", "112.125.89.8", 44939);
while (retry < 20) {
    int_qs100_send_cmd((uint8_t *)cmd);
    int_qs100_handle_response();
    if (strstr((char *)qs100_response_buffer, "OK") != NULL) {
        break; // 连接成功
    }
    HAL_Delay(1000);
    retry++;
}
if (retry >= 20) {
    printf("Error: Failed to connect\r\n");
    return;
}

5. 第四步:发送数据

连接好了,准备发数据。数据得按十六进制字符串格式发,比如“ABC”得转成“616263”。

  • AT 指令:用 AT+NSOSD 发送数据。格式:AT+NSOSD=<socket_id>,<length>,<data>,<flag>,<cycles>

    • socket_id:填“0”。

    • length:数据长度(十六进制字符串长度)。

    • data:十六进制字符串,比如“616263”。

    • flag:默认“0x200”,表示发完发下一条。

    • cycles:消息编号,1 到 255,递增用。

  • 响应结果:返回 OK 表示模块收到指令,但不代表发到云端成功。

  • 数据转换:比如发“ABC”,ASCII 是 97、98、99,十六进制是“616263”。

流程图:发送数据

 

准备数据

转十六进制字符串

构造AT+NSOSD

发送指令

等待响应

OK

失败

模块收到,继续

重试几次

补充例子

发送“ABC”代码:

uint8_t data[] = "ABC";
char hex_data[128];
for (int i = 0; i < strlen((char *)data); i++) {
    sprintf(hex_data + i*2, "%02X", data[i]);
}
char cmd[256];
sprintf(cmd, "AT+NSOSD=0,%u,%s,0x200,1\r\n", strlen(hex_data)/2, hex_data);
int_qs100_send_cmd((uint8_t *)cmd);
int_qs100_handle_response();

6. 第五步:查询发送状态

模块收到指令不代表发到云端成功,得查状态。

  • AT 指令:用 AT+NSOSTS 查询发送状态。格式:AT+NSOSTS=<socket_id>,<cycles>

    • socket_id:填“0”。

    • cycles:刚才发数据的编号,比如“1”。

  • 响应结果:返回 +NSOSTS:<socket_id>,<cycles>,<status>。状态:0=失败,1=成功,2=发送中,-1=无此消息。

  • 循环查询:每秒查一次,直到状态是 1(成功)或 0(失败),最多查 60 秒。

流程图:查询发送状态

 

60秒

发送AT+NSOSTS

等待响应

+NSOSTS:0,1,1

+NSOSTS:0,1,2

成功,结束

每秒重试

失败,报错

补充例子

查询代码:

int retry = 0;
char cmd[64];
sprintf(cmd, "AT+NSOSTS=0,1\r\n");
while (retry < 60) {
    int_qs100_send_cmd((uint8_t *)cmd);
    int_qs100_handle_response();
    if (strstr((char *)qs100_response_buffer, "+NSOSTS:0,1,1") != NULL) {
        printf("Data sent successfully\r\n");
        break;
    }
    if (strstr((char *)qs100_response_buffer, "+NSOSTS:0,1,0") != NULL) {
        printf("Error: Data send failed\r\n");
        break;
    }
    HAL_Delay(1000);
    retry++;
}

7. 封装函数:整合发送逻辑

最后把这几步封装成一个函数,方便调用。

  • 函数定义void int_qs100_send_data(const uint8_t *server_ip, uint16_t server_port, const uint8_t *data, uint16_t data_len, uint8_t cycles)

  • 步骤整合

    1. 判断是否联网(60 秒超时)。

    2. 创建 Socket(20 次重试)。

    3. 创建连接(20 次重试)。

    4. 发送数据。

    5. 查询发送状态(60 秒查询)。

  • 返回值:成功返回 0,失败返回 -1。

流程图:封装函数逻辑

 

成功

失败

成功

失败

成功

失败

成功

失败

int_qs100_send_data

判断联网

创建Socket

报错

创建连接

发送数据

查询发送状态

返回0

返回-1

补充例子

伪代码:

int int_qs100_send_data(const uint8_t *server_ip, uint16_t server_port, const uint8_t *data, uint16_t data_len, uint8_t cycles) {
    // 1. 判断联网
    // 2. 创建Socket
    // 3. 创建连接
    // 4. 发送数据
    // 5. 查询状态
    // 返回结果
}

总结

好了,今天咱们把 NB-IoT 模块发数据的流程过了一遍!从判断联网到创建 Socket、连接、发数据、再到确认成功,核心就是这几步。流程清楚了,代码就好写了。

关键点是:

  1. 先用 AT+CGATT? 确认联网,60 秒超时。

  2. AT+NSOCR 创建 Socket,AT+NSOCO 创建连接,20 次重试。

  3. AT+NSOSD 发数据,数据转十六进制,AT+NSOSTS 查状态。

课后可以试试把这几步写成代码,跑跑看,感受下完整流程。下节课咱们再细聊封装细节,有问题随时来问我哈,休息下,继续搞~


希望这篇博客对你有帮助!如果有啥需要调整的地方,随时告诉我~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值