Arduino/Microduino与OneNet平台及web服务器端的交互
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??一、上傳
? ? ? ? 近期在做硬件編程方面的小學期實驗課,采用的硬件是Microduino模塊,編程語言風格和C差不多。這種硬件編程的優(yōu)點是它的語言的靈活性、簡單性,因為它把底層都封裝了,但是正因為這種過度的封裝,導致引入不同的庫文件后就會有許多代碼大幅度的改動,并且代碼不夠輕巧,我因為這些缺點在小學期的硬件編程上也算是吃了不少苦頭。。。
? ? ? ?當然對硬件編程吐槽歸吐槽,還是要大贊可編程硬件,畢竟改改代碼就能實現(xiàn)復雜的功能,同時省去了很多對于底層的理解,利于快速的創(chuàng)新開發(fā)!由于我在小學期期間內(nèi)主要研究了Mcookie的WiFi模塊的編程,所以對于WiFi模塊和服務器端的交互這種較為復雜的功能實現(xiàn)也有些個人心得:
?????? 首先講解下與移動方OneNet物聯(lián)網(wǎng)平臺的交互,在Microduino中已經(jīng)有具體相關的示例,在示例代碼中WiFi模塊連上網(wǎng)絡這些都是比較簡單的,但其中上傳數(shù)據(jù)這塊較為復雜,不過比著葫蘆畫個瓢也能大致實現(xiàn)向OneNet發(fā)送自己想要發(fā)送的數(shù)據(jù)。現(xiàn)附上我的一段實現(xiàn)向OneNet上傳數(shù)據(jù)的代碼:? ?
#include "ESP8266.h"
//CoreUSB UART Port: [Serial1] [D0,D1]? 用于實現(xiàn)wifi串口通信
#if defined(__AVR_ATmega32U4__) //ATmega32U4---coreusb版本號
#define EspSerial Serial1
#define UARTSPEED? 115200
#endif
?
#define SSID???????"CCMC" //無線網(wǎng)賬號
/*Service Set Identifier的縮寫,意思是:服務集標識。SSID技術(shù)可以將一個無線局域網(wǎng)分為幾個需要不同身份驗證的子網(wǎng)絡,每一個子網(wǎng)絡都需要獨立的身份驗證,只有通過身份驗證的用戶才可以進入相應的子網(wǎng)絡,防止未被授權(quán)的用戶進入本網(wǎng)絡。*/
#define PASSWORD???"qwertyuiop" //無線網(wǎng)密碼
#define DEVICEID??? "*******"//設備ID號
#define HOST_NAME??"api.heclouds.com" //網(wǎng)址?
#define HOST_PORT?? (80)//端口號
String? apiKey = "**********";//產(chǎn)品API密鑰
String jsonToSend;
String postString;
ESP8266 wifi(&EspSerial);
?
void setup()
{
? Serial.begin(115200);//設置波特率為115200
? while (!Serial);
ERR:
? Serial.print("setupbegin\r\n");? ??
? wifi.setUart(UARTSPEED,DEFAULT_PATTERN);
?EspSerial.begin(UARTSPEED);//設值波特率
? delay(100);
?
? if (wifi.joinAP(SSID,PASSWORD))//wifi驗證賬號密碼
? {
Serial.print(F("Join APsuccess\r\n"));
? }
? else
? {
goto ERR;
? }
?Serial.print(F("setup end\r\n"));
}
?
void loop()
{
? updateData();
? while(true);
}
?
void updateData() //上傳數(shù)據(jù)函數(shù)
{
? if(wifi.createTCP(HOST_NAME, HOST_PORT)) //創(chuàng)建tcp連接
? {
???Serial.print(F("create tcp ok\r\n"));
? }
? else
? {
???Serial.print(F("create tcp err\r\n"));
? }
?
? jsonToSend="{\"a\":10000}"; // ?\"轉(zhuǎn)義符--> "
?
? postString ="POST/devices/";????? //根據(jù)數(shù)據(jù)類型修改格式
? postString +=DEVICEID;? //設備ID號
? postString +="/datapoints?type=3 HTTP/1.1";
? postString +="\r\n";
? postString +="api-key:";
? postString += apiKey; //產(chǎn)品的API key值
? postString +="\r\n";
? postString +="Host:api.heclouds.com\r\n";
? postString +="Connection:close\r\n";
? postString +="Content-Length:";
? postString +=jsonToSend.length();
? postString +="\r\n";
? postString +="\r\n";
? postString +=jsonToSend;
? postString +="\r\n";
? postString +="\r\n";
? postString +="\r\n";
? //Content-Length:23 后的換行符號一定要。{"shidu":22,"wendu":22}后的換行符可以不要,但盡量使用換行符,這是個習慣問題同時報頭結(jié)尾還要有兩個換行符
? const char *postArray =postString.c_str();??? //用指針指向數(shù)據(jù)
? /*json 要求輸入的是 char *類型。而如果你的是 string類型,那么需要通過
??? toCharArray()的函數(shù)進行轉(zhuǎn)換,而不能使用c_str(),因為 c_str()返回的是 const 類型*/
? wifi.send((constuint8_t*)postArray, strlen(postArray)); //發(fā)送數(shù)據(jù)
? Serial.println(F("Send Success!"));
? postArray = NULL;
?Serial.println(freeRam());
}
?
int freeRam() { //用于查詢剩余的內(nèi)存,使用wifi模塊一定要保證剩余內(nèi)存在600B以上
? extern int __heap_start,*__brkval;
? int v;
? return (int) &v -(__brkval == 0 ? (int) &__heap_start :(int) __brkval);
}
在這里需要注明的是由于microduino引入的庫文件可能不同,所以我的這一段代碼不一定肯定可以跑通,我把它貼出,是為了分析向OneNet端發(fā)送數(shù)據(jù)的HTTP報頭。當然,這個HTTP報頭如果是自己分析,肯定不會容易,不過這段報頭我也是借鑒microduino中關于OneNet使用的示例進行修改的。在此附上關于OneNet臺的HTTP協(xié)議的匯總博客:http://open.iot.10086.cn/bbs/forum.php?mod=viewthread&tid=536&extra=page%3D2%26filter%3Dreply%26orderby%3Dreplies。
在我貼出的代碼段中,有:
if(wifi.createTCP(HOST_NAME, HOST_PORT)) //創(chuàng)建tcp連接
? {
???Serial.print(F("createtcp ok\r\n"));
? }
可以看出WiFi模塊首先和OneNET服務器端建立tcp連接,有關tcp協(xié)議的細節(jié),可以自己找資料,或者看看《計算機網(wǎng)絡》,里面講解的很詳細。在這里,建立tcp連接是之后WiFi模塊與服務器之后交互的前提,tcp連接建立后,WIFI模塊就可以經(jīng)它的套接字向服務器端發(fā)送HTTP請求報文了。在我看來,WiFi模塊的功能就像是瀏覽器/服務器模式中的瀏覽器的作用,只不過WiFi模塊不像瀏覽器那般會對接收發(fā)送的HTTP報文進行封裝,呈現(xiàn)出的是非常易懂的形式,它按照HTTP協(xié)議收發(fā)數(shù)據(jù)時都是純粹的HTTP報文形式。在上面的代碼段中,其HTTP請求報文實際上就是如下的格式:
POST/devices/*****/datapoints?type=3HTTP/1.1
api-key:****************
Host:api.heclouds.com
Connection:close?
Content-Length:23
?
{“a”:10000}
?
注意這段報頭的格式,其實都是OneNet的官方文檔中的API封裝好的,我們只需要按照這種形式調(diào)用即可。需要說明的是,在此處Http 1.1為長連接,該連接可以在一定時間內(nèi)保持tcp連接打開,此舉在某些情況下可以減少開銷,但此處我出于測試,所以在HTTP請求報文末尾追加Connection:close,也就是表示W(wǎng)iFi模塊和服務器端就只有一次報文的交互,當WiFi模塊接收到服務器發(fā)回的HTTP響應報文后,此次tcp連接即斷開。(之前調(diào)試程序時有tcp連接釋放的代碼段,但每次串口打印出的都是釋放失敗,后來仔細想想才發(fā)現(xiàn)是這塊理解錯誤!)
?????? 到此,關于WiFi向OneNet平臺上傳數(shù)據(jù)部分已經(jīng)解釋完了,理解不深刻,有些分析不得當?shù)牡胤揭蚕M蠹野輣在下一篇會討論Microduino模塊從OneNet平臺接收數(shù)據(jù)。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??二、接收數(shù)據(jù)
? ? ? ?關于從OneNet端接收數(shù)據(jù)其中的工作機制其實和向OneNET上傳數(shù)據(jù)的原理是一樣的,所以對于工作機制的解說,我可能會很粗糙。先附上我寫的一段從OneNET平臺接收數(shù)據(jù)的代碼:
#include "ESP8266.h"
//CoreUSB UART Port: [Serial1] [D0,D1]? 用于實現(xiàn)wifi串口通信
#if defined(__AVR_ATmega32U4__)//ATmega32U4---coreusb版本號
#define EspSerial Serial1
#define UARTSPEED? 115200
#endif
?
#define SSID???????"CCMC" //無線網(wǎng)賬號
/*Service Set Identifier的縮寫,意思是:服務集標識。SSID技術(shù)可以將一個無線局域網(wǎng)分為幾個需要不同身份驗證的子網(wǎng)絡,每一個子網(wǎng)絡都需要獨立的身份驗證,只有通過身份驗證的用戶才可以進入相應的子網(wǎng)絡,防止未被授權(quán)的用戶進入本網(wǎng)絡。*/
#define PASSWORD??? "qwertyuiop" //無線網(wǎng)密碼
#define DEVICEID??? "*****"//設備ID號
#define HOST_NAME?? "api.heclouds.com" //網(wǎng)址?
#define HOST_PORT?? (80) //端口號
String? apiKey = "***********"; //產(chǎn)品API密鑰
char buf[10];?
String jsonToSend;
String postString;
ESP8266wifi(&EspSerial);
?
void setup()
{
? Serial.begin(115200);//設置波特率為115200
? while (!Serial);
ERR:
? Serial.print(F("setup begin\r\n"));
? EspSerial.begin(UARTSPEED); //初始化
? delay(100);
? if (wifi.joinAP(SSID, PASSWORD))//wifi驗證賬號密碼
? {
??? Serial.print(F("Join APsuccess\r\n"));
? }
? else
? {
??? goto ERR;
???}
? Serial.print(F("setup end\r\n"));
}
?
void loop()
{
?? uint8_t buffer[560] = {0};
?
? if (wifi.createTCP(HOST_NAME, HOST_PORT)) //創(chuàng)建tcp連接
? {
??? Serial.print(F("create tcpok\r\n"));
? }
? else
? {
??? Serial.print(F("create tcperr\r\n"));
? }
?
? postString = "GET/devices/";????? //根據(jù)數(shù)據(jù)類型修改格式
? postString += DEVICEID;? //設備ID號
? postString +="/datapoints?datastream_id=a&limit=5 "; //數(shù)據(jù)流選擇為a,且限制獲取的數(shù)據(jù)數(shù)目為 5
? postString += "HTTP/1.1";
? postString += "\r\n";
? postString += "api-key:";
? postString += apiKey; //產(chǎn)品的API key值
? postString += "\r\n";
? postString +="Host:api.heclouds.com\r\n";
? postString +="Connection:close\r\n\r\n";
? //此處connection:close在調(diào)試程序時,發(fā)現(xiàn)是斷開了長連接,所以此后如果還有發(fā)送或接受數(shù)據(jù),就需要再建立tcp長連接
? const char *postArray =postString.c_str();??? //用指針指向數(shù)據(jù)
? /*json 要求輸入的是char *類型。而如果你的是 string類型,那么需要通過toCharArray()的函數(shù)進行轉(zhuǎn)換,而不能使用 c_str(),因為 c_str()返回的是 const類型*/
? wifi.send((const uint8_t*)postArray,strlen(postArray)); //發(fā)送數(shù)據(jù)
? Serial.println(postArray);
? Serial.println(F("Send Success!"));
? postArray = NULL;
? uint32_t len = wifi.recv(buffer,sizeof(buffer), 10000);//接受從WiFi回復的信息至數(shù)組 buffer中,注:10000--timeout,為設置的響應時間!并返回信息的長度
?
? if (len > 0)
? {
??? Serial.print("Received:[");
??? for (uint32_t i = 0; i < len; i++) {
????? Serial.print((char)buffer[i]);
??? }
??? Serial.print("]\r\n");
? }
? Serial.println(freeRam());
? while(true);
}
?
int freeRam() { //用于查詢剩余的內(nèi)存,使用wifi模塊一定要保證剩余內(nèi)存在600B以上
? extern int __heap_start, *__brkval;
? int v;
? return (int) &v - (__brkval == 0 ? (int)&__heap_start :(int) __brkval);
}
關于此段代碼,可以發(fā)現(xiàn)和上一篇上傳數(shù)據(jù)的代碼段大部分一致,只不過修改了HTTP請求報文,同時WiFi模塊接收了服務器發(fā)回的響應報文,獲取了自己想要的數(shù)據(jù)。關于此段接收數(shù)據(jù)的HTTP報頭,其格式如下:
GET/devices/***/datapoints?datastream_id=a&limit=5HTTP/1.1
api-key:*************
Host:api.heclouds.com
Connection:close
?
?
在此,關于從OneNET平臺接收數(shù)據(jù)這一方面已經(jīng)講述完畢了,因為理論在上一篇已經(jīng)講解很詳細了~ 在下一篇,會講解在WiFi模塊硬件編程方面的代碼優(yōu)化小技巧。
?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?三、內(nèi)存優(yōu)化
? ? ? 在此前詳細得解說了WiFi大致的工作原理,同時也附上了與OneNET交互的上傳及下發(fā)的代碼,不過那些都是修改后的代碼,接下來我會講解我的代碼是如何一步一步優(yōu)化的:
a.??用串口打印數(shù)據(jù)時,可以使用類似于Serial.print(F("setup begin\r\n"));這樣的形式打印數(shù)據(jù),其實就是在打印內(nèi)容前加個F()形式的函數(shù),具體工作原理我不是很清楚,只知道這樣打印數(shù)據(jù)時會有效地優(yōu)化內(nèi)存。。。
?
b.??在原始案例中倘若調(diào)用WiFi模塊,setup 內(nèi)初始化過程中會調(diào)用了相當多的函數(shù),我在看了底層函數(shù)后,發(fā)現(xiàn)其實很多代碼是起著輔助調(diào)試作用,如果內(nèi)存夠的話這么玩是可以的,畢竟嚴謹,但是內(nèi)存都不夠了,也就不端著架子了。于是乎,我的WiFi模塊的初始化代碼是以下這么一段:
void setup()
{
? Serial.begin(115200);//設置波特率為115200
? while (!Serial);
ERR:
? Serial.print(F("setup begin\r\n"));
?
? EspSerial.begin(UARTSPEED); //初始化
? delay(100);
?
? if (wifi.joinAP(SSID, PASSWORD))//wifi驗證賬號密碼
? {
??? Serial.print(F("Join APsuccess\r\n"));
? }
? else
? {
????goto ERR;
??? //Serial.print(F("Join APfailure\r\n"));
? }
? Serial.print(F("setup end\r\n"));
}
可以看到,這里的代碼量有大幅度的減少,函數(shù)也砍了大半,不過缺點是初始化的過程中可能就看不到具體的調(diào)試信息了。同時我對ERR 以及 goto ERR部分有進行標紅,這可以用于如果第一次初始化WiFi因為網(wǎng)絡不好沒有成功連接,可重復嘗試連接
?
c.?在 loop中,案例里有提到這段代碼:uint8_tbuffer[1024] = {0};,這里初始化了一個很耗內(nèi)存的數(shù)組用于接收從服務器端返還的數(shù)據(jù),當然如果是大佬的話,應該會注意修改這一部分。不過我當時太蠢,沒敢改這個部分。這里這個數(shù)組的大小由返還的http響應報文數(shù)據(jù)大小決定,原則上,只要HTTP響應報文數(shù)據(jù)沒有接漏,都說明數(shù)組的大小是沒問題的。
?
d.??postString +="Connection:close\r\n\r\n”;這段代碼案例中貌似就是這么寫的,不過需要提及的是,此處connection:close 我感覺是優(yōu)化到了內(nèi)存。因為http1.1協(xié)議應該是長連接,所以默認是connection:keep-alive的,之所以把connection改為關閉,可能是這次loop中不需要再和服務器建立tcp連接,開著也沒必要了。當然如果你想在一個loop中多次和服務器接發(fā)數(shù)據(jù)進行交互,可以改為connection:keep-alive,在最后一個接發(fā)中再改為close 就ok了,這樣的話還有一個好處就是,省去了釋放tcp連接的那塊函數(shù),因為你在發(fā)送后已經(jīng)斷開了連接。
?
e.??最后附上一個用于檢測剩余內(nèi)存的函數(shù),它要比編譯運行時看到的內(nèi)存剩余要精準許多。在原則上coreUSB要求是剩余500-600B之上,才能避免WiFi模塊使用時的內(nèi)存問題
(函數(shù)如下:)
int freeRam() { //用于查詢剩余的內(nèi)存,使用wifi模塊應該保證剩余內(nèi)存在600B以上
?extern int __heap_start, *__brkval;
?int v;
?return (int) &v - (__brkval == 0 ? (int) &__heap_start :(int)__brkval);
}
在主程序中只需要Serial.println(freeRam());這段代碼,就可以在串口打印出所余內(nèi)存,其中單位為字節(jié)。
? ? ? ? ? ? ?四、Arduino/Microduino與本地web服務器的交互
? ? ? ?在此前的硬件編程分析之后,想必這個標題更吸引人,因為它可以和你寫的網(wǎng)頁端進行交互,并且可以實時刷新從網(wǎng)頁端返還的數(shù)據(jù)。這意味著,通過硬件可以實現(xiàn)物聯(lián)網(wǎng)中很多功能,當然在此處,我不打算細說應用場景,應用案例。我只打算簡單地介紹下如何和自己搭的服務器進行交互,其實還是和同OneNET交互一樣的“套路”,都是在HTTP報文方面下功夫,不過在和自己的服務器進行交互時,HTTP請求報文可不是像OneNet官方文檔那般,詳細介紹了它的Api調(diào)用方式以及HTTP報文的格式。在此處,HTTP報文出于穩(wěn)重,它的格式需要抓包看一下(雖然大多數(shù)HTTP報文格式都差不多,畢竟都是遵守HTTP協(xié)議。。),在此處,我推薦fiddle 這款抓包軟件,下面是它打開的界面。
?????? 先附上我寫的和自己的服務器進行交互的代碼:
#include "ESP8266.h"
//CoreUSB UART Port: [Serial1] [D0,D1]? wifi串口通信
#if defined(__AVR_ATmega32U4__)//ATmega32U4---coreusb版本號
#define EspSerial Serial1
#define UARTSPEED? 115200
#endif
?
#define SSID???????"CCMC" //無線網(wǎng)賬號
#define PASSWORD???"qwertyuiop" //無線網(wǎng)密碼
#define HOST_NAME??"192.168.43.215" //ip地址,自己搭建的服務器的IP地址
#define HOST_PORT?? (80)//端口號
?
ESP8266 wifi(&EspSerial);
?
void setup()
{
? Serial.begin(115200);//設置波特率為115200
? while (!Serial);
ERR:
?Serial.print(F("setup begin\r\n"));
?
?EspSerial.begin(UARTSPEED); //初始化
? delay(100);
?
? if (wifi.joinAP(SSID,PASSWORD))//wifi驗證賬號密碼
? {
???Serial.print(F("Join AP success\r\n"));
? }
? else
? {
??? goto ERR;
???//Serial.print(F("JoinAP failure\r\n"));
? }
?Serial.print(F("setup end\r\n"));
}
?
void loop(void) {
?
?if(wifi.createTCP(HOST_NAME, HOST_PORT)) //創(chuàng)建tcp連接
? {
???Serial.print(F("create tcp ok\r\n"));
? }
? else
? {
???Serial.print(F("create tcp err\r\n"));
? }
? uint8_t buffer[256+64] ={0};
???char *hello ="GEThttp://192.168.43.215/php/Try/get.php?id=1HTTP/1.1\r\nHost:192.168.43.215\r\nConnection: close\r\n\r\n";
??? //當使用Keep-Alive模式(又稱持久連接、連接重用)時,Keep-Alive功能使客戶端到服務器端的連接持續(xù)有效,當出現(xiàn)對服務器的后繼請求時,Keep-Alive功能避免了建立或者重新建立連接。
//此處此處由于只獲取一次數(shù)據(jù),所以無需關心后繼請求,故而為Connection:close???
wifi.send((constuint8_t*)hello,strlen(hello));//將信息頭發(fā)送出去:內(nèi)容,長度
//boolsend(constuint8_t *buffer, uint32_t len);
??? hello=NULL; //釋放內(nèi)存
??? uint32_t len =wifi.recv(buffer, sizeof(buffer), 10000);
?? ?uint8_t a=Print(buffer,len);//對于接受的數(shù)據(jù)進行處理
? }
?
uint8_t Print(uint8_t * buffer, uint32_t len)
{
? if (len > 0)
? {
??? uint32_t i = 0; //定義整型變量 i
while ((i < len -1) && (!((buffer[i] == 13) && (buffer[i+ 1] == 10) &&(buffer[i + 2] == 13) &&
?(buffer[i + 3] == 10)))) //用于判別信息頭同時只獲取信息頭后的值
??? {
????? i++;
??? }
??? //由于此處我只打算獲取權(quán)限,1代表可以,0代表不可以,所以只獲取一個字符即可?
??? return buffer[i + 4];
? }
}
在這里,可以發(fā)現(xiàn)我的HTTP報文是:
GEThttp://192.168.43.215/php/Try/get.php?id=1 HTTP/1.1\r\n
Host:192.168.43.215\r\n
Connection:close\r\n\r\n
?
?它的報文格式和之前與OneNet平臺的交互的格式其實相仿,下面我來詳細解說這段HTTP請求報文的獲取方式:
首先講解下這個地址的含義:http://192.168.43.215/php/Try/get.php?id=1中http://192.168.43.215/php/Try/get.php指代一個本地的我寫的網(wǎng)站,192.168.43.215為本地web服務器的ip地址,學過web的同學應該都有了解Localhost,在這里192.168.43.215其實就是該域名對應的本地Ip地址,只不過本地的服務器IP地址只能在局域網(wǎng)內(nèi)訪問,不能夠在公網(wǎng)訪問。關于IP地址的獲取,可以在dos命令下輸入ipconfig,?在下面截圖中所示的IPV4地址即位本地服務器的ip地址。
而后面的?id=1,其實為以get形式返還給服務器的數(shù)據(jù),在這里附上對應的get.php的源代碼,是一個非常簡單的腳本文件:
<?php
$id =$_GET['id']; //獲取GET形式返還的id數(shù)值
if($id=1){?echo 1; }
else{ echo 0; }
?>
該腳本的功能就是獲取get形式返還的id數(shù)據(jù)值。
其次關于在WiFi模塊硬件編程中如何寫此與服務器交互的HTTP請求報文,其實有一個簡單的方法,就是在自己瀏覽器中輸入剛剛提到的網(wǎng)址形式:http://192.168.43.215/php/Try/get.php?id=1,然后在fiddle中分析抓到的包:
可以看到,在WiFi模塊中寫的HTTP請求報文只是這個完整請求報文的一部分,至于為什么只選取其中的一部分,是源于對Onenet示例中源碼的分析后大膽的刪減。不過我之前也有測試過發(fā)送完整的HTTP請求報文是絕對可行的,目前可以認為這兩種格式的HTTP請求報文格式都是可行的。
?
至于服務器端返還的響應報文在WiFi模塊中便不似請求報文那種是可變的,它幾乎是傻瓜式的返回,沒有任何處理,就和從瀏覽器抓的響應報文是一樣的格式:
可是對于硬件來說,返回的響應報文頭部都是沒有意義的,需要刪減,于是我寫了一個函數(shù)用于剝?nèi)シ祷氐捻憫獔笪念^部:
uint8_t Print(uint8_t * buffer, uint32_t len)
{
? if (len > 0)
? {
??? uint32_t i = 0; //定義整型變量 i
while ((i < len -1) && (!((buffer[i] == 13) && (buffer[i+ 1] == 10) &&(buffer[i + 2] == 13) &&
(buffer[i + 3] == 10)))) //用于判別信息頭同時只獲取信息頭后的值
??? {
????? i++;
??? }
??? //由于此處我只打算獲取權(quán)限,1代表可以,0代表不可以,所以只獲取一個字符即可?
??? return buffer[i + 4];
? }
}
當然需要吐槽這個函數(shù)也是傻瓜式遍歷的,對于程序的優(yōu)化肯定還是有優(yōu)化的空間的,不過我懶并且能力有限所以這一塊并沒有深入去做。。。
? ? ? ??至此整個程序大致流程都已經(jīng)分析完了,關于Microduino/Arduino WiFi模塊編程的系列也大致講述完了,希望大家看完后能有些許幫助~
?
??????????????????????????????????????????????
?
?
?
總結(jié)
以上是生活随笔為你收集整理的Arduino/Microduino与OneNet平台及web服务器端的交互的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 搭建WAMP 环境时,解决Windows
- 下一篇: 调用Cython时报错: More th