CAT1模块 EC800M HTTP使用总结记录

分享记录一下 CAT1 模块EC800 HTTP 协议使用流程  ...... by 矜辰所致

前言

最近用到了 CAT1 模块 EC800 ,项目需求是使用 CAT1 模块通过 HTTP 协议上报数据给服务器。

以前的项目对于 MQTT 协议使用比较多,对于 HTTP 其实并没有太过深入的了解, 写本文的目的就是 记录一下 EC800 HTTP 协议的使用流程,给大家提供一个例子,在对 HTTP 协议没有深入理解的情况下,如何能够快速的使得产品正常的设计出来。ヾ(◍°∇°◍)ノ゙ !

因为涉及到移动通信网络相关问题,对于一些专业性的基本知识,本文会中会引用前人的一些博文说明,文中的引用都会给出原文连接。

我是矜辰所致,全网同名,尽量用心写好每一系列文章,不浮夸,不将就,认真对待学知识的我们,矜辰所致,金石为开!

一、基础说明

接到项目需求,第一时间就得对一些基本的背景知识做一定的了解,比如 什么是 CAT1? 模块的基本应用资料,HTTP 的相关知识等等。

1.1 CAT1 与 4G

Cat.1 的全称是 LTE UE-Category1,在2009年,Cat.1-5 是 3GPP 专门划分出来,面向于未来物联网应用市场的类别,Cat.1 的最终目标是服务于物联网并实现低功耗和低成本 LTE 连接。

LTE 英文 “Long-Term Evolution” ,中文名称为长期演进技术。它是一种用于移动通信的无线网络标准,也是4G(第四代)移动通信技术的主要标准之一。
UE 英文 “User Equipment” 指的是用户终端,它是LTE网络下用户终端设备的无线性能的分类。3GPP用Cat.1~20来衡量用户终端设备的无线性能,也就是划分终端速率等级。

Cat.1 是属于4G系列,可以完全重用现有的4G资源。Cat.1是配置为最低版本参数的用户终端级别,可让业界以低成本设计低端4G终端。

随着现在物联网的发展,Cat.1 在物联网领域越发重要,与NB-IoT和2G模块相比,Cat.1在网络覆盖范围,速度和延迟方面具有优势。与传统的 Cat.4 模块相比,它具有成本低,功耗低的优点。

1.2 EC800M 模块

EC800M-CN 是移远通信专为 M2M 和 IoT 领域而设计的超小尺寸LTE Cat 1无线通信模块,支持最大下行速率10 Mbps和最大上行速率 5 Mbps。

对于模块来说,移远会提供你完成的一套说明资料,硬件设计,软件设计,使用流程应有尽有,如果你本身对这一领域有所了解,那使用起来基本不费什么事情,完全不需要去额外的寻找资料。

在这里插入图片描述

1.3 HTTP

如果你了解 HTTP ,以及 4G 网络的一些基础,那你直接照着上面 模块的手册资料直接 AT 指令直接用起来就行了。

如果你没有了解过,确实需要花店时间去了解,这里推荐一篇文章:

HTTP超详细教程

对于我们应用而言,有几个地方我们是一定要了解的,第一个 HTTP 协议格式,比如 HTTP 的协议格式(图片引用至上面推荐文章):

HTTP 请求格式:

在这里插入图片描述
HTTP 响应格式:
在这里插入图片描述

HTTP 协议格式:

在这里插入图片描述

GET 方法用来获取服务器上面的数据,对于我们的项目,我们其实只需要用到 HTTP 的 POST 方法,POST请求需要传递的数据一般通过 body 传递。

比如一个给服务器输入用户名密码的 POST 请求例子(图片引用至上面推荐文章):

在这里插入图片描述

对于我们使用 CAT1 模块来说,我们最终要做的就是在程序中组一个类似上面内容的数据包,发送出去就行了。

当然实际上一般在物联网场合,传感器上报数据需要组的包比上面会简单得多。

二、开始使用

基础知识了解过后,接下来就是开始测试使用了。

2.1 硬件设计部分

硬件部分基本上照着 官方文档来就行了,没有一点难度,真的没什么好说的,省略,详细请参考 《Quectel_EC800M-CN_硬件设计手册_V1.1.pdf》(不同型号的芯片有不同的对应手册,根据手册来就行了)。

象征性的上一张原理图:

在这里插入图片描述

2.2 模块上电流程

虽然模块的官方会提供文档说明 HTTP 命令的使用流程,如下图:

在这里插入图片描述

但是我们一般不会一上电就直接这么使用,简单来说就是首先你得确保模块通讯正常并且正常附着网络,那么我们正常的使用中都会有一个 模块初始化流程(虽然模块一切正常的情况下,会自动联网)。

我们需要经过一些上电后的 AT 指令交互,确保模块联网正常,然后才能开始按照上面手册的流程走下去。

步骤 指令 说明
1 AT 串口通讯基本测试
OK 返回“OK”表示与模块通讯正常
2 AT+CPIN? 检查 SIM 卡是否插入
+CPIN: READY OK 返回“READY”表明读卡成功
3 AT+CSQ 查询信号质量
+CSQ: 23,99 OK 参数1:信号质量(0~ 31),一般打鱼8 小于31就行 参数2:忽略
4 AT+CEREG? 查询网络注册状态
+CEREG: 0,1 OK 参数2:1表示注册成功
5 AT+CGATT? 查询网络附着状态
+CGATT: 1 OK 1表示成功,0表示失败

上面的这些可作为模块上电的检查手段,完成上面的步骤,才可以开始进行后面的操作。 在程序中,我们可以把这些操作当做 模块的初始化。

上面的指令结尾都需要回车换行,在程序中定义字符串的时候末尾记得要加上

在这里插入图片描述

测试代码如下:

void ec800_init()
{
    
    
    u16 cat1_timeout = 0;

    while(Iot_SendCmd(AT,"OK", 200)){
    
    
        HAL_Delay(1);
        cat1_timeout ++;
        if(cat1_timeout >= 2000){
    
    
            printf(" uart false\r\n");
            return;   
        }
    }
    cat1_timeout = 0;
    printf("uart ok\r\n");
    while(Iot_SendCmd(CPIN,"READY", 200)){
    
    
        HAL_Delay(1);
        cat1_timeout ++;
        if(cat1_timeout >= 2000){
    
    
            return;   
        }
    }
    cat1_timeout = 0;
    printf("simcard ok\r\n");
    while(Iot_SendCmd(RSSI,"+CSQ", 200)){
    
    
        HAL_Delay(1);
        cat1_timeout ++;
        if(cat1_timeout >= 2000){
    
    
            return;   
        }
    }
    cat1_timeout = 0;
    while(Iot_SendCmd(CEREG,"0,1", 200)){
    
    
        HAL_Delay(1);
        cat1_timeout ++;
        if(cat1_timeout >= 2000){
    
    
            return;   
        }
    }
    printf("网络注册 ok\r\n");
    cat1_timeout = 0;
    while(Iot_SendCmd(CGATT,"+CGATT: 1", 200)){
    
    
        HAL_Delay(1);
        cat1_timeout ++;
        if(cat1_timeout >= 2000){
    
    
            return;   
        }
    }
    printf(" 网络附着 ok\r\n");
}

2.3 PDP 上下文

我们在看文档的时候,会有一个 PDP 上下文的概念,这里我们需要对这个概念说明一下。

PDP,Packet Data Protocol,分组数据规程,移动通信用户在发送和接收分组数据时应用的协议,应用于 GPRS以及 WCDMA 等分组网络。
.
PDP context 即 PDP 上下文,保存用户面进行隧道转发的所有信息,包括 RNC / GGSN 的用户面 IP 地址、隧道标识和 QoS 等。

实际上如果对网络不了解的看完了上面的基本概念,应该还是不理解,所以我这里用白话文简单解释一下:

就是说我们需要用 PDP(Packet Data Protocol )传输数据,那么就必须给他建立一个背景,就是所谓的上下文,你得告诉 SGSN 和 GGSN (什么是 SGSN 和 GGSN ,往下面看,就类似于中转站,网关类) 一些基本信息 :本地标识(cid),你想要的 pdp_type(这里就是IP),你的接入点信息。

接入点不同的运行商是不同的:
联通:UNINET 移动:CMNET 电信:CTNET

我们不把 PDP 上下文用专业的术语去理解,简单的说,PDP 上下文就是在你准备连接 Internet 传输数据之前,必须要做的一些基本配置,给你发个通讯卡,后面你就可以传输数据了,激活一个 PDP 上下文意味着发起一个分组数据业务呼叫。

2.3.1 什么是 SGSN 和 GGSN ?

在上面介绍 PDP 的时候提到过 SGSN 和 GGSN ,关于这一块,我也是参考前人的博文:

移动数据通信网络工作原理(SGSN&GGSN)

图片引用至上面推荐博文:

在这里插入图片描述

内容引用至上面推荐博文:

SGSN
SGSN主要用于为在其地理范围内的移动站传递数据包,相当于无线网络中的路由节点。它可以进行分组路由和转发,移动性管理(附着,去附着和位置管理),逻辑链路管理,鉴权以及计费功能。SGSN的位置寄存器保存着位置信息,比如当前的小区。
SGSN的主要功能包括:
1 完成和GGSN的通信,通过GTP协议将用户数据传递给GGSN,并将GGSN返回的数据传递给用户
2 当用户地理位置发生变化,执行移动性管理。
GGSN
GSGN作为整个GPRS/UMTS网络的网关,位于GPRS网络和外部分组交换网络(Internet)之间。网关的作用能将一种协议格式的数据转换为另一种格式的数据。
GGSN把来自的SGSN的GPRS数据包转化为适当的分组数据协议格式,比如IP,然后再把它们发送到相应的分组数据网络,比如广域有线网。反之亦然。
SGSN和GGSN的区别
所以,GGSN和SGSN的主要区别就在于,GGSN作为网关,是在不同的通信网中转换协议,而SGSN作为路由,只是在使用相同协议的网络中发送、接受以及延迟它的数据包。
另外,GGSN能够实现地址的转换,比如把无线网络内部地址(PDP地址)转换为一个分组数据网络协议地址(IP地址),而SGSN只能实现PDP地址映射,即根据一个地址,映射到相同种类的另一个地址。可见,我们常说的3、4G网络的IP地址,其实就是对应GGSN的出口IP地址。

到这里,一些开始使用需要了解的基础问题都已经说明了,那么下面其实就可以直接开启 HTTP 的使用了。

三、 HTTP 流程

上面准备工作做完了,我们接下来往下面进行。

3.1 客户端

客户端实际上就是我们的板子,在上面我们已经给出了 EC800M 上电初始化的流程。

在完成上述的初始化以后,我们就可以按照官方手册进行下去了,本部分我们主要使用图示和实际测试代码给出说明。

我们来回顾一下上面的流程(这里我们用官方文档中的示例图说明):

在这里插入图片描述

上面的流程是官方给出的一个简单的样例,大体上,按照顺序来就行了。

其中需要注意的就是 ,有一个参数设置样例中并没有,就是数据类型,数据类型其实是大家需要 POST 的服务器有关的,这个需要自己了解服务器端需要怎样的数据类型:

在这里插入图片描述

比如本次测试,我使用了了 "AT+QHTTPCFG=\"contenttype\",1\r\n" 就是设置为 "text/plain" 类型。

上面还是用了 AT+QIACT=1 激活 PDP上下文,但是图中也提到了是默认激活的,我发现如果是激活状态,使用这个指令会返回 ERROR (有待确定)。

其他的倒是没有什么问题,这里直接上一下代码。

3.1.1 PDP 上下文配置

void ec800_pdp_prepare(){
    
    
    u16 cat1_timeout = 0;
    while(Iot_SendCmd("AT+QHTTPCFG=\"contextid\",1\r\n","OK", 200)){
    
    
        HAL_Delay(1);
        cat1_timeout ++;
        if(cat1_timeout >= 2000){
    
    
            return;   
        }
    }
    cat1_timeout = 0;
    printf("设置 QHTTPCFG ok\r\n");

    while(Iot_SendCmd("AT+QIACT?\r\n","OK", 3000)){
    
    
        HAL_Delay(1);
        cat1_timeout ++;
        if(cat1_timeout >= 2000){
    
    
            return;   
        }
    }
    cat1_timeout = 0;
    printf("PDP_CHECK one ok\r\n");

    
    while(Iot_SendCmd("AT+QHTTPCFG=\"contenttype\",1\r\n","OK", 3000)){
    
    
        HAL_Delay(1);
        cat1_timeout ++;
        if(cat1_timeout >= 2000){
    
    
            return;   
        }
    }
    cat1_timeout = 0;
    printf("CFG ok\r\n");

    // while(Iot_SendCmd("AT+QHTTPCFG=\"rspout/auto\",1\r\n","OK", 3000)){
    
    
    //     HAL_Delay(1);
    //     cat1_timeout ++;
    //     if(cat1_timeout >= 2000){
    
    
    //         return;   
    //     }
    // }
    // cat1_timeout = 0;
    // printf("auto header ok\r\n");

    /*
    "AT+QICSGP=1,1,\"CMNET\",\"\",\"\",1\r\n"
    APN 联通:UNINET   移动:CMNET   电信:CTNET
    */
    while(Iot_SendCmd("AT+QICSGP=1,1,\"CMNET\",\"\",\"\",1\r\n","OK", 3000)){
    
    
        HAL_Delay(1);
        cat1_timeout ++;
        if(cat1_timeout >= 2000){
    
    
            return;   
        }
    }
    cat1_timeout = 0;
    printf("PDP_CONFIG ok\r\n");
    while(Iot_SendCmd("AT+QIACT?\r\n","+QIACT", 3000)){
    
    
        HAL_Delay(1);
        cat1_timeout ++;
        if(cat1_timeout >= 2000){
    
    
            return;   
        }
    }
    cat1_timeout = 0;
    printf("PDP_CHECK two ok\r\n");

    // while(Iot_SendCmd("AT+QIACT=1\r\n","OK", 500)){
    
    
    //     HAL_Delay(1);
    //     cat1_timeout ++;
    //     if(cat1_timeout >= 2000){
    
    
    //         return;   
    //     }
    // }
    // cat1_timeout = 0;
    // printf("PDP_激活 ok\r\n");
}

3.1.2 URL 设置

接下来就是设置 URL ,URL 从哪里来,就是服务器会提供,比如 ONENET 平台对于 HTTP 的说明如下:

在这里插入图片描述

这里我们 POST 设置的 URL ,就是上面的 Address+URL,对应在下面的程序中,就是char *url 这个参数:

void http_set_url(char *url)
{
    
    
    u16 cat1_timeout = 0;
    char message[32];
    snprintf(message, sizeof(message), "AT+QHTTPURL=%d,%d\r\n", strlen(url), 5);
    while(Iot_SendCmd(message,"CONNECT", 1000)){
    
    
        HAL_Delay(1);
        cat1_timeout ++;
        if(cat1_timeout >= 2000){
    
    
            return;   
        }
    }
    cat1_timeout = 0;
    printf("ready to send url\r\n");
    while(Iot_SendCmd(url,"OK", 5000)){
    
    
        HAL_Delay(1);
        cat1_timeout ++;
        if(cat1_timeout >= 2000){
    
    
            return;   
        }
    }
    cat1_timeout = 0;
    printf("url set OK\r\n");
}

到目前为止,我们程序中整体调用流程如下图所示:

在这里插入图片描述

3.1.3 POST 请求

上面的 URL 设置完成,我们就可以随时发送 POST 请求了,比如我们是一个传感器设备,周期性的采集传感器数据,到了自己设定的时间,就直接 POST 就行了,下面是 POST 请求的实现函数:


void http_post_message(const char *message) {
    
    
    int length = strlen(message);
    char at_post[32];
    u16 cat1_timeout = 0;
    snprintf(at_post, sizeof(at_post), "AT+QHTTPPOST=%d,%d,%d\r\n", length, 5, 10);
    while(Iot_SendCmd(at_post,"CONNECT", 500)){
    
    
        HAL_Delay(1);
        cat1_timeout ++;
        if(cat1_timeout >= 2000){
    
    
            return;   
        }
    }
    cat1_timeout = 0;
    printf("ready to send post message!\r\n %s\r\n", message);
    while(Iot_SendCmd(message,"OK", 5000)){
    
    
        HAL_Delay(1);
        cat1_timeout ++;
        if(cat1_timeout >= 2000){
    
    
            return;   
        }
    }
    cat1_timeout = 0;
    printf("http post OK\r\n");
    //"AT+QHTTPREAD=1\r\n"
    while(Iot_SendCmd("AT+QHTTPREAD=5\r\n","+QHTTPREAD", 1000)){
    
    
        HAL_Delay(1);
        cat1_timeout ++;
        if(cat1_timeout >= 2000){
    
    
            return;   
        }
    }
    cat1_timeout = 0;
    printf("HTTPREAD OK\r\n");
}

当然上面的参数const char *message 是需要我们自己组包的,一般来说使用 JSON 格式的比较多,比如测试过程中,我的程序如下:

在这里插入图片描述

最后上面流程中调用的Iot_SendCmd函数也上一下:

int Iot_SendCmd(const char* cmd, char* reply, int wait)
{
    
    
	u8 i=0;
    char* rss_str;
    int rssi,res;
    CLEAR_EC800_Buffer(EC800_RX_Data);

    Uart3_sendBuffer((u8*)cmd,strlen(cmd));
    
    while(EC800ReceiveState != true)
    {
    
    
        HAL_Delay(1);
        i++;
        if(i >= wait){
    
    
            printf("cat1 check out\r\n");
            return 0xFF;   
        }
    }
    EC800ReceiveState = false;

    if (!strcmp(reply,"+CSQ"))
    {
    
    
       rss_str = strstr((char*)EC800_RX_BUF, "+CSQ:");
        if (!rss_str) {
    
    
            return 1;
        }

        sscanf(rss_str, "+CSQ:%d,%d", &rssi, &res);
        if (rssi != 99) {
    
    
            printf("RSSI is %d\r\n",rssi);
            CLEAR_EC800_Buffer(EC800_RX_Data);
            return 0;
        }
    }
    
    else if (strstr((char*)EC800_RX_BUF, reply)){
    
      
        printf("\r\n%s\r\n", EC800_RX_BUF);
        CLEAR_EC800_Buffer(EC800_RX_Data);
        return 0;
    }

    return 1;  
}

3.1.4 注意事项

(此处待更新,后续一些细节问题的说明需要补充)

1、关于字体

首先要注意的就是 字体,要和服务器的字体匹配;

通过"AT+QHTTPCFG=\"contenttype\",1\r\n"设置字体,这点上面已经提到过;

2、关于 HTTP 响应

指令AT+QHTTPCFG="responseheader",1 是启用输出 HTTP 响应头信息:

在这里插入图片描述

如果启用了以后,使用AT+QHTTPREAD读取的 HTTP 响应消息如下:

在这里插入图片描述

此时返回比较多,响应都有 600多个字节,接近 700 字节,这里大家写程序时候需要考虑到串口缓存大小。

不启用这个,则读取的 HTTP 响应消息如下:

在这里插入图片描述

此时返回不到200字节

3、关于 cat1 模块返回数据的处理

本文使用的是 STM32F103 芯片,在对于 AT 指令串口处理的时候需要注意,一般来说,对于普通的 AT 指令,我们可以直接使用 IDLE 中断进行判断是否接收完成,程序处理如下:

在这里插入图片描述

但是对于 AT+QHTTPPOSTAT+QHTTPREAD 来说,他们返回的不是一帧数据,而是分段的数据,如果使用 上面的处理就会出问题,所以我们需要对于这两个指令进行单独的处理:

	/*省略*/
 	Uart3_sendBuffer((u8*)cmd,strlen(cmd));
    
    /*
    此处串口回的不止是一帧数据,所以使用 IDLE 中断不合适
    */
    if ((!strcmp(reply,"+QHTTPREAD:"))||(!strcmp(reply,"+QHTTPPOST:"))){
    
    
        //读取和发送的处理,直接等一段时间
        HAL_Delay(1000);// 500 600 800 1000 一直加大   
    }
    /*
        另外的设置指令大多都是等待一个 OK 返回,属于一帧数据
        所以可以用 IDLE 中断
    */
    else{
    
    
        while(EC800ReceiveState != true)
        {
    
    
            HAL_Delay(1);
            i++;
            if(i >= wait){
    
    
                printf("cat1 check out\r\n");
                return 0xFF;   
            }
        }
    }
    EC800ReceiveState = false;

当然,实际上对于 AT 指令的模块来说,因为他不会不定时的发送消息,所以实际上所有 AT 指令发送后的返回结果,都可以不用 IDLE 中断处理,发送完 AT 命令以后,直接延时等待一定的时间读取串口数据即可。

3.2 服务器端

服务器端大家可以选择现在常用的一些云平台, 阿里云,ONENET,华为云等等由 物联网模型支持的,服务器端只需要自己进行一些基本的产品创建,配置,然后根据平台提供的开发文档,进行上面的流程即可,比如:

在这里插入图片描述

本次测试使用公司自己的服务器,有软件部门的同事专门负责,所以省去了服务器端的配置流程。

结语

原本写本文的目的只是想记录一下 EC800M HTTP 的使用步骤,但是因为涉及到的一些通讯的基本知识自己也都去复习了解了一边,所以最终内容还是比预计的要多。除了把模块 HTTP 测试流程给大家讲了一边,还额外提了一些 网络通讯相关的内容,自己也有不少的收获。

文中提供的代码是自己的测试代码,至于后期实际项目使用,大家还需要根据自己的需求进行完善。

好了,本文就到这里,谢谢大家!

猜你喜欢

转载自blog.csdn.net/weixin_42328389/article/details/131262687