作者:cwb_tfx | 更新时间:2018-12-13 | 浏览量:2436
最近在使用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.bigiot.net;
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;
}
}
}
}