CAT1模块 EC800M HTTP使用总结记录_ec800g http使用(1)

    }
}
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)]( )


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


![在这里插入图片描述](https://img-blog.csdnimg.cn/89271832f0e64b95b6f5843a4e6069e1.png)


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



> 
> **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 上电初始化的流程。


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


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


![在这里插入图片描述](https://img-blog.csdnimg.cn/b7e76074e1d04ec2af71a9580f27d2d5.png)


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


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


![在这里插入图片描述](https://img-blog.csdnimg.cn/9bca2cdfcb574017afe58830e4621e7a.png)


比如本次测试,我使用了了 `"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 的说明如下:


![在这里插入图片描述](https://img-blog.csdnimg.cn/4de9e5615d4340ab83524d0870de639d.png)


这里我们 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”);
}


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


![在这里插入图片描述](https://img-blog.csdnimg.cn/bab8baa937f84b519f248d98ac631261.png)


#### 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 格式的比较多,比如测试过程中,我的程序如下:


![在这里插入图片描述](https://img-blog.csdnimg.cn/8240a3d535324fe8ab623f2af9d7d92d.png)


最后上面流程中调用的`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 响应头信息:


![在这里插入图片描述](https://img-blog.csdnimg.cn/e58b861e79804336b873a8a969b69f12.png)


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


![在这里插入图片描述](https://img-blog.csdnimg.cn/522a5cd11dea44dc8817e9e92a395091.png)



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


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


![在这里插入图片描述](https://img-blog.csdnimg.cn/927b97d514ad4016b457c7af36d0c185.png)



> 
> 此时返回不到200字节
> 
> 
> 


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


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


![在这里插入图片描述](https://img-blog.csdnimg.cn/a4d7258822bf4e169e62deb82ce7f2a8.png)


但是对于 `AT+QHTTPPOST` 和 `AT+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,华为云等等由 物联网模型支持的,服务器端只需要自己进行一些基本的产品创建,配置,然后根据平台提供的开发文档,进行上面的流程即可,比如:


![在这里插入图片描述](https://img-blog.csdnimg.cn/a482fac6c1094014aa92791abca99bb4.png)


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


## 四、 接收 HTTP 服务器下发数据


在上面的文章中,我们只讲到上报需要的数据,但是没有考虑过 HTTP 服务器下发数据的处理,也有粉丝问过我怎么数据交互,这不正好后期客户有需要下发的需求,所以特来补充一下此部分内容。


在实际应用中,我们除了上报数据,有时候还需要通过服务器下发对应的指令对终端设备进行一些远程设置,但是这里有一个问题,就是 HTTP 的通讯方式,服务器无法随时对指定的终端设备下发指令,所以,我们交互的时机只能放在我们终端设备进行 POST 后,然后读取服务器响应的时刻。


所以其实这里我们确定了数据交互的方式后,我们就可以直接进行操作了,在上文的 “3.1.4 注意事项” 小结中的 " 2、关于 HTTP 响应 " 中我们有说明(我们以禁用 HTTP 响应头信息为例说明),正常读取为:


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/13fa9edb866646769ca272f79597af34.png)


上图红色部分其实是由服务器控制的,HTTP 服务器可以设定自己回应的消息,比如本次示例博主让同事把下发的数据改成如下:


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/9556ed46a73240ff9e309eafcab14caf.png)


在上面的回应语句中, `{"expectGear":2}` 就是本次示例想要获取的指令,这就回到了我们很正常的流程中来,当我们 POST 完毕,然后使用 QHTTPREAD 读取服务器的数据,然后找到自己想要的内容。


这里上一下这部分处理的代码:



最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!

片转存中…(img-LO83ywKK-1715543016661)]

[外链图片转存中…(img-qaS45I4f-1715543016662)]

[外链图片转存中…(img-0uNqSN7N-1715543016663)]

[外链图片转存中…(img-yySLvlZI-1715543016663)]

[外链图片转存中…(img-q3jCOmLY-1715543016663)]

[外链图片转存中…(img-WWHeWPCN-1715543016664)]

[外链图片转存中…(img-wxjPzySM-1715543016664)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!

  • 16
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值