- 前言
- 一、基礎說明
- 1.1 CAT1 與 4G
- 1.2 EC800M 模塊
- 1.3 HTTP
- 二、開始使用
- 2.1 硬件設計部分
- 2.2 模塊上電流程
- 2.3 PDP 上下文
- 三、 HTTP 流程
- 3.1 客戶端
- 3.2 服務器端
- 結語
前言
最近用到了 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 falsern");
return;
}
}
cat1_timeout = 0;
printf("uart okrn");
while(Iot_SendCmd(CPIN,"READY", 200)){
HAL_Delay(1);
cat1_timeout ++;
if(cat1_timeout >= 2000){
return;
}
}
cat1_timeout = 0;
printf("simcard okrn");
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("網絡注冊 okrn");
cat1_timeout = 0;
while(Iot_SendCmd(CGATT,"+CGATT: 1", 200)){
HAL_Delay(1);
cat1_timeout ++;
if(cat1_timeout >= 2000){
return;
}
}
printf(" 網絡附著 okrn");
}
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)
圖片引用至上面推薦博文:
內容引用至上面推薦博文:
SGSNSGSN主要用于為在其地理范圍內的移動站傳遞數據包,相當于無線網絡中的路由節點。它可以進行分組路由和轉發,移動性管理(附著,去附著和位置管理),邏輯鏈路管理,鑒權以及計費功能。SGSN的位置寄存器保存著位置信息,比如當前的小區。 SGSN的主要功能包括: 1 完成和GGSN的通信,通過GTP協議將用戶數據傳遞給GGSN,并將GGSN返回的數據傳遞給用戶 2 當用戶地理位置發生變化,執行移動性管理。GGSNGSGN作為整個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",1rn"
就是設置為 "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",1rn","OK", 200)){
HAL_Delay(1);
cat1_timeout ++;
if(cat1_timeout >= 2000){
return;
}
}
cat1_timeout = 0;
printf("設置 QHTTPCFG okrn");
while(Iot_SendCmd("AT+QIACT?rn","OK", 3000)){
HAL_Delay(1);
cat1_timeout ++;
if(cat1_timeout >= 2000){
return;
}
}
cat1_timeout = 0;
printf("PDP_CHECK one okrn");
while(Iot_SendCmd("AT+QHTTPCFG="contenttype",1rn","OK", 3000)){
HAL_Delay(1);
cat1_timeout ++;
if(cat1_timeout >= 2000){
return;
}
}
cat1_timeout = 0;
printf("CFG okrn");
// while(Iot_SendCmd("AT+QHTTPCFG="rspout/auto",1rn","OK", 3000)){
// HAL_Delay(1);
// cat1_timeout ++;
// if(cat1_timeout >= 2000){
// return;
// }
// }
// cat1_timeout = 0;
// printf("auto header okrn");
/*
"AT+QICSGP=1,1,"CMNET","","",1rn"
APN 聯通:UNINET 移動:CMNET 電信:CTNET
*/
while(Iot_SendCmd("AT+QICSGP=1,1,"CMNET","","",1rn","OK", 3000)){
HAL_Delay(1);
cat1_timeout ++;
if(cat1_timeout >= 2000){
return;
}
}
cat1_timeout = 0;
printf("PDP_CONFIG okrn");
while(Iot_SendCmd("AT+QIACT?rn","+QIACT", 3000)){
HAL_Delay(1);
cat1_timeout ++;
if(cat1_timeout >= 2000){
return;
}
}
cat1_timeout = 0;
printf("PDP_CHECK two okrn");
// while(Iot_SendCmd("AT+QIACT=1rn","OK", 500)){
// HAL_Delay(1);
// cat1_timeout ++;
// if(cat1_timeout >= 2000){
// return;
// }
// }
// cat1_timeout = 0;
// printf("PDP_激活 okrn");
}
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,%drn", 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 urlrn");
while(Iot_SendCmd(url,"OK", 5000)){
HAL_Delay(1);
cat1_timeout ++;
if(cat1_timeout >= 2000){
return;
}
}
cat1_timeout = 0;
printf("url set OKrn");
}
到目前為止,我們程序中整體調用流程如下圖所示:
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,%drn", 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!rn %srn", message);
while(Iot_SendCmd(message,"OK", 5000)){
HAL_Delay(1);
cat1_timeout ++;
if(cat1_timeout >= 2000){
return;
}
}
cat1_timeout = 0;
printf("http post OKrn");
//"AT+QHTTPREAD=1rn"
while(Iot_SendCmd("AT+QHTTPREAD=5rn","+QHTTPREAD", 1000)){
HAL_Delay(1);
cat1_timeout ++;
if(cat1_timeout >= 2000){
return;
}
}
cat1_timeout = 0;
printf("HTTPREAD OKrn");
}
當然上面的參數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 outrn");
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 %drn",rssi);
CLEAR_EC800_Buffer(EC800_RX_Data);
return 0;
}
}
else if (strstr((char*)EC800_RX_BUF, reply)){
printf("rn%srn", EC800_RX_BUF);
CLEAR_EC800_Buffer(EC800_RX_Data);
return 0;
}
return 1;
}
3.1.4 注意事項
(此處待更新,后續一些細節問題的說明需要補充)
1、關于字體
首先要注意的就是 字體,要和服務器的字體匹配;
通過"AT+QHTTPCFG="contenttype",1rn"
設置字體,這點上面已經提到過;
2、關于 HTTP 響應
指令AT+QHTTPCFG="responseheader",1
是啟用輸出 HTTP 響應頭信息:
如果啟用了以后,使用AT+QHTTPREAD
讀取的 HTTP 響應消息如下:
此時返回比較多,響應都有 600多個字節,接近 700 字節,這里大家寫程序時候需要考慮到串口緩存大小。
不啟用這個,則讀取的 HTTP 響應消息如下:
此時返回不到200字節
3、關于 cat1 模塊返回數據的處理
本文使用的是 STM32F103 芯片,在對于 AT 指令串口處理的時候需要注意,一般來說,對于普通的 AT 指令,我們可以直接使用 IDLE 中斷進行判斷是否接收完成,程序處理如下:
但是對于 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 outrn");
return 0xFF;
}
}
}
EC800ReceiveState = false;
當然,實際上對于 AT 指令的模塊來說,因為他不會不定時的發送消息,所以實際上所有 AT 指令發送后的返回結果,都可以不用 IDLE 中斷處理,發送完 AT 命令以后,直接延時等待一定的時間讀取串口數據即可。
3.2 服務器端
服務器端大家可以選擇現在常用的一些云平臺, 阿里云,ONENET,華為云等等由 物聯網模型支持的,服務器端只需要自己進行一些基本的產品創建,配置,然后根據平臺提供的開發文檔,進行上面的流程即可,比如:
本次測試使用公司自己的服務器,有軟件部門的同事專門負責,所以省去了服務器端的配置流程。
結語
原本寫本文的目的只是想記錄一下 EC800M HTTP 的使用步驟,但是因為涉及到的一些通訊的基本知識自己也都去復習了解了一邊,所以最終內容還是比預計的要多。除了把模塊 HTTP 測試流程給大家講了一邊,還額外提了一些 網絡通訊相關的內容,自己也有不少的收獲。
文中提供的代碼是自己的測試代碼,至于后期實際項目使用,大家還需要根據自己的需求進行完善。
-
模塊
+關注
關注
7文章
2733瀏覽量
47744 -
LTE
+關注
關注
15文章
1361瀏覽量
178082 -
服務器
+關注
關注
12文章
9303瀏覽量
86059 -
HTTP
+關注
關注
0文章
511瀏覽量
31518 -
Cat1
+關注
關注
0文章
42瀏覽量
3515
發布評論請先 登錄
相關推薦
![](https://file1.elecfans.com/web2/M00/FE/39/wKgaomaZnyqAKdlRAAwQgcHZQRw742.png)
無線模塊的生產測試流程!急求!感謝!
基于嵌入式網絡模塊的HTTP 數據采集方案
如何發起 HTTP 請求流程
![如何發起 <b class='flag-5'>HTTP</b> 請求<b class='flag-5'>流程</b>](https://file.elecfans.com/web1/M00/B1/A4/o4YBAF4BqXeAGCoCAAGTJB3yaiE393.png)
一文知道模塊電源量產的基本測試流程
合宙Air780EP模塊AT開發-HTTP應用指南
![合宙Air780EP<b class='flag-5'>模塊</b>AT開發-<b class='flag-5'>HTTP</b>應用指南](https://file1.elecfans.com/web2/M00/FD/20/wKgZomaYcZGAIdfqAABembvJ4Po238.png)
評論