作者:cwb_tfx | 更新時間:2018-12-13 | 瀏覽量:1773
最近在使用ESP8266連接BIGIOT服務器做開發時遇到了一個很奇怪的問題
由于本人也是第一次玩arduino和esp8266,不知道arduino 里面的io讀寫會有這么大的坑
在使用client類調用readstring等系列(只要是讀一大串字符串的api)接口都會發生延遲的現象,手機發送的數據經過服務器傳
到板子,延遲有四五秒左右。起初我以為跟網絡延遲有關系,但是經過測試發現,與此無關。
后面我想是否跟io讀取string 數據的實現有關系,也就是說,底層讀取函數并不知道從服務器發來的數據已經讀取完成了,因此
會一直等待完整的數據到來(這種情況下,我們發送多次數據后,在停止發送后會一次性把所有的數據讀取出來),于是我想是否
可以人為的區分服務器發來的每一條信息,在查閱arduino函數后,發現有readBytes()方法,但是我在使用這個函數一次性讀取多個
字符串時也存在延遲現象,因此我改成一個字符一個字符去讀(只有每次讀一個字符才能解決,其他方式都不行,讀者可以自行測試),
讀到\n就算拿到一幀完整的數據。使用int recvData(char* buff, int len) 這個函數解決了延遲的問題。
下面貼出源碼,在此之前,先簡單介紹一下:
該源碼實現了WIFI斷開自動重啟,連接超時自動重連,離線自動重連等功能,意思就是說,無論在哪個環節掉線了,都會重新去連接。
代碼只是一段測試,有需要的朋友可以自行修改測試。
另外值得注意的地方是,這里使用的是8282端口,被動在線(客戶端不主動給服務器發心跳包,而是等服務器先發心跳包過來,然后再發心跳包給服務器)
源碼如下:
============================================================================================
#include
WiFiClient client;
#define RCV_BUFF_LEN 512
#define SND_HEART_JUMP_PKG "{\"M\":\"b\"}\n"
#define SND_CONNECT_PKG "{\"M\":\"checkin\",\"ID\":\"1234\",\"K\":\"1212121\"}\n"
#define MSG_CONNECT_TO_BIGIOT "{\"M\":\"WELCOME TO BIGIOT\"}\n"
#define LED1 16 //LED連接在8266的GPIO16上
#define LED2 2 //LED連接在8266的GPIO2上
const char *ssid = "cwbtest";//"360WiFi-3C7943";
const char *password = "1234567891";//"112233445566";
const char *host = www.eqytg.org;
const int httpPort = 8282;
static char recvBuff[RCV_BUFF_LEN] = {0};
int len = 0;
int recvData(char* buff, int len)
{
if(len <= 0)
{
Serial.print("Len value error ");
return -1;
}
char str;
int count = 0;
while(client.readBytes(&str,1) > 0)
{
recvBuff[count++] = str;
if(str == '\n')
{
recvBuff[count++] = '\0';
break;
}
if(count >= len)
{
return -1;
}
}
return count;
}
bool ConnectToWIFI(const char* ssid, const char* passwd)
{
if(WiFi.status() == WL_CONNECTED)
{
return true;
}
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, passwd);
int timeCount = 0;
while(WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
timeCount++;
if(timeCount >= 20)
{
Serial.print("Connect to ");
Serial.print(WiFi.SSID());
Serial.println("failer, time out!");
return false;
}
}
Serial.println("");
return true;
}
bool ConnectToServer(const char* host, const int port)
{
int timeCount = 0;
client.flush();
while(!client.connect(host, port))
{
Serial.println("connection to Server failed,retry...");
delay(4000);
timeCount++;
if(timeCount >= 5)
{
Serial.print("Connect to ");
Serial.print(host);
Serial.println(" failer, time out!");
return false;
}
}
timeCount = 0;
while(true)
{
if(( len = client.readBytesUntil('\0',recvBuff,RCV_BUFF_LEN)) > 0)
{
recvBuff[len] = '\0';
Serial.print(recvBuff);
String line = String(recvBuff);
if(line.compareTo(MSG_CONNECT_TO_BIGIOT) == 0)
{
Serial.print("connected to ");
Serial.println(host);
}
break;
}
delay(10);
timeCount++;
if(timeCount >= 1000)
{
Serial.println("GET Connect Message time out!");
return false;
}
}
return true;
}
bool LogInToServer()
{
int timeCount = 0;
while(true)
{
int count = 0;
bool isConnect = false;
client.write(SND_CONNECT_PKG);//登陸設備,修改成自己的ID和key
while(true)
{
if(( len = client.readBytesUntil('\0',recvBuff,RCV_BUFF_LEN)) > 0)
{
Serial.println(recvBuff);
String line = String(recvBuff);
if(line.compareTo("checkinok") > 0)
{
//Serial.println("connect ok");
return true;
}
}
delay(3000);
count++;
if(count >= 5)
{
Serial.println ("time out>>> retry");
timeCount++;
break;
}
}
if(timeCount >= 3)
{
return false;
}
}
return true;
}
bool IsWifiConnect()
{
if(WiFi.status() != WL_CONNECTED)
{
return false;
}
return true;
}
void setup()
{
Serial.begin(115200);
Serial.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
delay(10);
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
}
void loop()
{
unsigned int timeStart = 0;
unsigned int timeEnd = 0;
static int ledctrl = LOW;
while(1)
{
Serial.println("Welcom to use this ESP8266 device");
Serial.print("Step1: Connecting to ");
Serial.println(ssid);
if(!ConnectToWIFI(ssid, password))
{
continue ;
}
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
Serial.println("");
Serial.println("Step2: ConnectTo Server>>");
if(!ConnectToServer(host, httpPort))
{
delay(3000);
continue;
}
Serial.println("Connect to server successful!");
Serial.println("");
Serial.println("Step3: Login to Server>>");
if(!LogInToServer())
{
client.stop();
delay(3000);
continue;
}
Serial.println("Login to Server successful!");
Serial.println("Now you can control your device by ethernet!");
timeStart = millis();
while(1)
{
if(( len = recvData(recvBuff,RCV_BUFF_LEN)) > 0)
{
digitalWrite(LED1,ledctrl);
digitalWrite(LED2,ledctrl);
if(ledctrl == LOW)
{
ledctrl = HIGH;
}
else
{
ledctrl = LOW;
}
timeStart = millis();
String line = String(recvBuff);
if(line.compareTo(SND_HEART_JUMP_PKG) == 0)
{
Serial.println("this is heart jump package");
client.write(SND_HEART_JUMP_PKG);
}
Serial.print(line);
}
timeEnd = millis();
if((IsWifiConnect() == false) || ((timeEnd - timeStart) > 180000))
{
Serial.println(timeEnd - timeStart);
Serial.println("Error Message: Wifi Disconnect!\n");
Serial.println("Retry to connect to WIFI");
break;
}
}
}
}