To begin with, I'm doing a mini project on the verification of RFID card using NodeMCU. I set up a database and a server to handle all the requests from the client. The problem is, whenever I try to verify a valid card, the function that handles it keeps returning the wrong value.
To be clear, here is my main loop:
void loop() {
connectToHost();
key = kpd.getKey();
card = readCard();
delay(200);
//check for card status
if(verifyCard(card)){
Serial.println("Card is valid");
} else {
Serial.println("Invalid Card");
}
//check connection status
if(WiFi.status() == WL_CONNECTION_LOST){
connectToWiFi();
}
}
The main loop calls this function:
boolean verifyCard(String uid){
String url = "/ECafe/terminal_verify.php?uid=";
url += uid;
// This will send the request to the server
Serial.print("Requesting URL: ");
Serial.println(url);
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Client Timeout !");
client.stop();
}
yield();
}
// Read all the lines of the reply from server and print them to Serial
while (client.available()) {
String line = client.readStringUntil('\r');
//if string contains echo from php file
if(line.indexOf("Valid")>0){
return true;
} else {
return false;
}
yield();
}
Serial.println();
Serial.println("Closing connection");
}
I intentionally put a valid card UID in the database just to test this function. Yet, it keeps returning false. I'm sure that the response from the server is "Valid". I suspect that the function doesn't even wait for the response from the server and returns a false value because the interval between the GET request is sent and the response is returned is too short. Is that because of the if condition in the main loop? See the attachment for the serial monitor output.
The logic of your function is flawed.
// Read all the lines of the reply from server and print them to Serial
while (client.available()) {
String line = client.readStringUntil('\r');
//if string contains echo from php file
if(line.indexOf("Valid")>0){
return true;
} else {
return false;
When the code reads the first line, and it doesn't contain Valid, it will fail and return false. So your code will ALWAYS return false, as I doubt that the first line returned is Valid...
}
yield();
}
Serial.println();
Serial.println("Closing connection");
The rest of this code is never executed. "Closing connection" is never printed right?
Related
I am creating a library to manage our wifi network connection on many ESP32 devices.
Inside my library, i have a task that is looping with a 1 second pause started with an xTaskCreate inside my .begin() function. The problem is that i can't start the task if i haven't make it static in my .h file. So once the task is declared as static, i don't have access to the this-> pointer inside this task. Is there anyway i can send the this-> pointer inside my task like in parameters or something like that ?
Here is some code:
class EraWiFi{
public:
EraWiFi();
/*!
* #brief Initialize WiFi
* #return Returns true if successful
*/
bool begin(fs::FS &fs);
/*!
* #brief Start EraWiFi service
* #return Returns true if successful
*/
void downloadWiFi();
private:
static void wifiTask(void * parameter);
};
bool EraWiFi::begin(fs::FS &fs){
File file = fs.open("/WiFi.json", FILE_READ);
if(file){
DynamicJsonDocument wifi(2048);
DeserializationError error = deserializeJson(wifi, file);
file.close();
if (!error){
Serial.println("We have a VALID WiFi.json configurations file!");
Serial.println("Adding wifi networks:");
for (JsonArray arr : wifi.as<JsonArray>()){
Serial.print("SSID: ");
Serial.print(arr[0].as<char*>());
Serial.print(", KEY: ");
Serial.println(arr[1].as<char*>());
wifiMulti.addAP(arr[0].as<char*>(), arr[1].as<char*>());
}
}else{
Serial.println("We don't have a VALID WiFi.json configurations file!");
}
}else{
Serial.println("There is no WiFi.json configurations file!");
}
wifiMulti.addAP("Testing", "1234");
xTaskCreate(
this->wifiTask, // Function that should be called
"WiFiTask", // Name of the task (for debugging)
10000, // Stack size (bytes)
(void*)&this, // Parameter to pass
1, // Task priority
NULL // Task handle
);
return true;
}
void EraWiFi::downloadWiFi(){
Serial.println("Downloading WiFi.json from ErabliTEK Server.");
HTTPClient http;
// Send request
http.useHTTP10(true);
String url = "https://testing.testing.com/wifis/getWiFi/";
http.begin(url);
int httpResponseCode = http.GET();
if(httpResponseCode == HTTP_CODE_OK){
// Parse response
DynamicJsonDocument doc(2048);
DeserializationError error = deserializeJson(doc, http.getStream());
// Disconnect
http.end();
if (!error){
File file = fs.open("/WiFi.json", FILE_WRITE);
if(file){
// Serialize JSON to file
if (serializeJson(doc, file) == 0) {
Serial.println("Error saving WiFi.json!");
Serial.println(http.getString());
}else{
Serial.println("Succesfully saved WiFi.json!");
}
}
// Close the file
file.close();
}else{
Serial.println("Error downloading WiFi.json");
}
}else{
Serial.println("Problem connecting to " + url + " with http code: " + String(httpResponseCode));
}
}
void EraWiFi::wifiTask(void * parameters){
bool wifiConnected = false;
for(;;){
uint8_t wifiStatus = wifiMulti.run();
if((wifiStatus != WL_CONNECTED) and wifiConnected) {
wifiConnected = false;
Serial.println("WiFi not connected!");
}else if((wifiStatus == WL_CONNECTED) and !wifiConnected){
wifiConnected = true;
Serial.println("WiFi Connected.");
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
Serial.print("KEY: ");
Serial.println(WiFi.psk());
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
EraWiFi::downloadWiFi();
}
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
You're already doing that, you just don't realize it. Have a look at the FreeRTOS documentation on xTaskCreate() which explains how the fourth parameter pvParameters is a void pointer that gets passed on to the new task as its (one and only) input parameter.
The commented line here means you're taking the address of your EraWiFi object and passing it to the task:
xTaskCreate(
this->wifiTask,
"WiFiTask",
10000,
(void*)&this, //< Pointer gets forwarded to the task
1,
NULL
);
To use the pointer inside your task, you only need to cast it back from void*:
void EraWiFi::wifiTask(void * parameters){
EraWifi* p = static_cast<EraWifi*>(parameters); //< That's the same pointer
p->someMethod();
...
PS. Also note (before you poke at the same object from different threads, possibly causing hard-to-find bugs) that FreeRTOS provides excellent inter-thread communication facilities - the queues and task notifications often being the most useful ones. Check out their tutorial/book for an explanation.
I am building a C# windows form program that will communicate with an ESP8266. I am hoping to not have to post too much code as the both the programs are fairly large. I will try to explain my issue as best as I can;
The C# program is sending a packet over UDP broadcast while connected to the ESP8266 soft access point. The ESP8266 can receive and parse the packet just fine from the C# form. The problem is I am trying to send a response packet immediately back to the C# form. This is where the problem is occurring. The ESP8266 will get hung/freeze for a bit either when calling the "write()" or when calling "endPacket()" and then it will crash. Sometimes "endPacket()" will actually not get hung/freeze and send the response packet back, but it will still crash immediately after.
The error output most of the time seems to be: "ets Jan 8 2013,rst cause:4, boot mode:(3,6)". However sometimes it is different.
I have tried using the "yield()" function throughout my code as well but no luck.
Any guidance or solutions are appreciated!?
ESP8266 Program: Main code in question:
bool BatteryOptimizer::ProcessData()
{
size_t enc_data_len = 0;
size_t dec_data_len = 0;
//int ass_data_size_temp = 0;
char encrypted_data[BO_UDP_PACKET_SIZE];
char decrypted_data[BO_UDP_PACKET_SIZE];
char associated_data_temp[BO_AES_ASSOCIATED_DATA_SIZE];
uint8_t iv[GCM_AES_256_IV_TAG_SIZE];
uint8_t tag[GCM_AES_256_IV_TAG_SIZE];
bool status = false;
uint8_t msg_type = 0;
char response_packet[BO_PACKET_SIZE];
size_t response_packet_size = BO_PACKET_SIZE;
msg_type = (uint8_t)BatteryOptimizer::collector_manager->fields[1].ui64_field; //Get Msg Type
//See if Message type is correct first before continuing
if (msg_type < BO_AES_ASSOCIATED_DATA_SIZE)
{
enc_data_len = (size_t)(collector_manager->fields[3].ui64_field - GCM_AES_256_IV_TAG_SIZE); //Get encrypted data length
memcpy(iv, BatteryOptimizer::collector_manager->fields[2].c_array, GCM_AES_256_IV_TAG_SIZE); //Get IV
memcpy(encrypted_data, BatteryOptimizer::collector_manager->fields[3].c_array, enc_data_len); //Get encrypted data
memcpy(tag, BatteryOptimizer::collector_manager->fields[3].c_array + enc_data_len, GCM_AES_256_IV_TAG_SIZE); //Get tag
//ass_data_size_temp = BatteryOptimizer::associated_data[msg_type].length(); //Get associated data legnth
BatteryOptimizer::associated_data[msg_type].toCharArray(associated_data_temp, BO_AES_ASSOCIATED_DATA_SIZE); //Get associated data
//Decrypt data
Serial.println("ProcessData: Attempting to decrypt data!");
status = Decrypt_GCM_AES256((uint8_t *)encrypted_data,
enc_data_len,
iv,
tag,
associated_data_temp,
(uint8_t *)decrypted_data,
&dec_data_len);
if (true == status)
{
//Execute command:
BatteryOptimizer::ExecuteCommand(msg_type, decrypted_data, dec_data_len);
//Build Reponse packet:
Serial.println("ProcessData: Attempting to build Reponse packet!");
memset(response_packet, 0, BO_PACKET_SIZE);
BatteryOptimizer::BuildResponsePacket(associated_data_temp, response_packet, &response_packet_size);
//Send Response packet:
Serial.println("ProcessData: Attempting to begin packet!");
Serial.println("ProcessData: Remote IP: ");
Serial.println(BatteryOptimizer::udp_server.remoteIP());
Serial.println("ProcessData: Remote Port: ");
Serial.println(BatteryOptimizer::udp_server.remotePort());
status = BatteryOptimizer::udp_server.beginPacket(BatteryOptimizer::udp_server.remoteIP(), BatteryOptimizer::udp_server.remotePort());
if (true == status)
{
Serial.println("ProcessData: Attempting to write packet!");
Serial.println(BatteryOptimizer::udp_server.write(response_packet, response_packet_size));
Serial.println("ProcessData: Attempting to send packet!");
status = BatteryOptimizer::udp_server.endPacket();
if (true == status)
{
Serial.println("ProcessData: UDP server sent reponse packet!");
}
else
{
Serial.println("ProcessData: UDP server was unable to send repsonse packet!");
Serial.println("ProcessData: Tried to send response packet: " + BatteryOptimizer::associated_data[msg_type]);
}
}
else
{
Serial.println("ProcessData: UDP server was unable to begin packet!");
Serial.println("ProcessData: Tried to send response packet: " + BatteryOptimizer::associated_data[msg_type]);
}
}
else
{
Serial.println("ProcessData: Failed to process data!");
//Testing
Serial.println("Encrypted length: ");
Serial.println(enc_data_len);
Serial.println("Decrypted Data: ");
Serial.println(decrypted_data);
Serial.println(decrypted_data + 50);
Serial.println("Associated Data: ");
Serial.println(associated_data_temp);
}
}
return status;
} //END ProcessData
void BatteryOptimizer::UDP_ServerLoop()
{
char packet[BO_UDP_PACKET_SIZE];
int packetSize;
Serial.println("UDP server about to start parsing packets!");
//while (BatteryOptimizer::run_udp == true)
if (BatteryOptimizer::run_udp == true)
{
packetSize = BatteryOptimizer::udp_server.parsePacket();
if (packetSize > 0)
{
Serial.println("Received packet! Size: ");
Serial.println(packetSize);
size_t len = (size_t)BatteryOptimizer::udp_server.read(packet, BO_UDP_PACKET_SIZE);
if (len > 0)
{
BatteryOptimizer::collector_manager->Collect(packet, &len);
if (COLLECT_FOUND == BatteryOptimizer::collector_manager->status)
{
Serial.println("Found msg!");
Serial.println("Collected Packet Size:");
Serial.println(BatteryOptimizer::collector_manager->packet_size);
BatteryOptimizer::collector_manager->Check_Checksum();
if (COLLECT_VALID_CS == BatteryOptimizer::collector_manager->status)
{
Serial.println("Valid Checksum!");
BatteryOptimizer::collector_manager->Parse();
//Process data
if (true == BatteryOptimizer::ProcessData())
{
Serial.println("Process success!");
}
}
else
{
Serial.println("Invalid Checksum!");
}
BatteryOptimizer::collector_manager->ResetCache();
}
else
{
Serial.println("Did not find a message!");
}
}
else
{
Serial.println("Did not receive a complete packet!");
}
}
else
{
Serial.println("Packet size is 0!");
}
Serial.println("Packet received: ");
Serial.println(packet);
delay(BO_UDP_DELAY);
} //END run_udp loop
Serial.println("UDP server no longer parsing packets! ");
} //END UDP_ServerLoop
void BatteryOptimizer::UDP_StartServer()
{
if (BatteryOptimizer::is_udp_running == false)
{
Serial.println("Starting UDP server. ");
BatteryOptimizer::udp_server.begin(BO_UDP_PORT);
Serial.println("Listening on UDP port ");
Serial.println(BO_UDP_PORT);
BatteryOptimizer::run_udp = true;
BatteryOptimizer::is_udp_running = true;
}
} //END UDP_StartServer
C# Windows Form: Main code in question:
private void UDP_Initialize_Client()
{
//Start UDP server to listen in for the Battery Opetimizer device:
udp_client = new UdpClient( listenPort );
end_point = new IPEndPoint( IPAddress.Broadcast, listenPort );
udp_client.EnableBroadcast = true;
udp_client.MulticastLoopback = false;
}
private void UDP_ReceiveContinuously( IAsyncResult res )
{
byte[] received = udp_client.EndReceive( res, ref end_point );
//Process Data:
UDP_ProcessData( ref received );
UDP_SetupReceive();
} //END UDP_ReceiveContinuously
private void UDP_SetupReceive()
{
try
{
udp_client.BeginReceive( new AsyncCallback( UDP_ReceiveContinuously ), null );
}
catch (Exception e)
{
MessageBox.Show( e.ToString() );
}
} //END UDP_SetupReceive
As an update, I figured out how to use the exception decoder. Here are is the output;
0x40206afe: raise_exception at core_esp8266_postmortem.cpp line ?
0x40206b10: __assert_func at C:\Users\SpencerBell\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266/core_esp8266_postmortem.cpp line 275
0x40100ba2: get_unpoisoned_check_neighbors at C:\Users\SpencerBell\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266\umm_malloc/umm_local.c line 125
0x402074bd: uart_write at C:\Users\SpencerBell\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266/uart.cpp line 509
0x40100c91: umm_poison_free_fl at C:\Users\SpencerBell\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266\umm_malloc/umm_local.c line 148
0x40205690: HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\SpencerBell\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266/HardwareSerial.h line 164
0x4010038c: free at C:\Users\SpencerBell\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266/heap.cpp line 259
0x40205690: HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\SpencerBell\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266/HardwareSerial.h line 164
0x4020ebe5: operator delete(void*) at /workdir/repo/gcc/libstdc++-v3/libsupc++/del_op.cc line 48
0x4020ebd0: operator delete[](void*) at /workdir/repo/gcc/libstdc++-v3/libsupc++/del_opv.cc line 33
0x40204b40: Collector::FreeUnnecessaryResources() at D:\Projects\Arduino\libraries\DataHandler/DataHandler.cpp line 331 (discriminator 3)
0x40201912: BatteryOptimizer::UDP_OnPacket(AsyncUDPPacket) at C:\Users\SPENCE~1\AppData\Local\Temp\arduino_build_863316\sketch/battery_optimizer.cpp line 312 (discriminator 1)
0x4020105f: BP_OnPacket(AsyncUDPPacket&) at D:\Projects\Arduino\ESP8266\BatteryPerserver/BatteryPerserver.ino line 55
0x40208910: precache at ?? line ?
0x40102b12: wDev_ProcessFiq at ?? line ?
0x402082c0: std::_Function_handler ::_M_invoke(std::_Any_data const&, AsyncUDPPacket&) at c:\users\spencerbell\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\2.5.0-4-b40a506\xtensa-lx106-elf\include\c++\4.8.2/functional line 2073
0x40202da2: AsyncUDP::_recv(udp_pcb*, pbuf*, ip4_addr*, unsigned short) at D:\Projects\Arduino\libraries\ESPAsyncUDP\src/AsyncUDP.cpp line 197
0x40208910: precache at ?? line ?
0x40221f4b: cnx_start_handoff_cb at ?? line ?
0x401009a5: check_poison_neighbors$part$3 at C:\Users\SpencerBell\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266\umm_malloc/umm_local.c line 71
0x40100a61: umm_malloc_core at C:\Users\SpencerBell\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266\umm_malloc/umm_malloc.cpp line 458
0x40101a17: ppCalFrameTimes at ?? line ?
0x40202dd8: AsyncUDP::_s_recv(void*, udp_pcb*, pbuf*, ip4_addr const*, unsigned short) at D:\Projects\Arduino\libraries\ESPAsyncUDP\src/AsyncUDP.cpp line 210
0x4021314c: udp_input at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/lwip2-src/src/core/udp.c line 404
0x4022eb18: pbuf_alloc at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/glue-esp/lwip-esp.c line 669
0x40217cf0: ip4_input at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/lwip2-src/src/core/ipv4/ip4.c line 1461
0x40100c77: umm_free at C:\Users\SpencerBell\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266\umm_malloc/umm_malloc.cpp line 398
0x4020f349: ethernet_input_LWIP2 at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/lwip2-src/src/netif/ethernet.c line 188
0x4020f168: esp2glue_ethernet_input at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/glue-lwip/lwip-git.c line 469
0x4022ebfe: ethernet_input at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/glue-esp/lwip-esp.c line 365
Well after weeks of searching and modifying code. I figured out I was simply just using too much memory. I found several places in my code where I cut down array sizes and now its working perfect!
As a note, I also switched to using the ESPAsyncUDP library: https://github.com/me-no-dev/ESPAsyncUDP
I tried to upload an image (JPG) from an Arduino to Google drive using the API.
Sometimes it works (I do the POST request as described in the guide and send all the bits) and I receive 200 OK, but sometimes, after sending all the bytes, google drive does not give me any response.
any suggestions?
Here there is the part of the code which dose the Upload (note I pasted only the "problematic" part).
- Sometimes the while cycle finishes because I receive the 200 response.
- Sometimes I receive no response and so I start again to send the image.
In
while (millis() - startTime < 15000 && !received)
I tried to wait up to ten minutes, but no response
Serial.println("Token request has been succesful. Starting upload");
bool succesful = false;
// I have obtained the uploadID, now I start uploading
String location = "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&upload_id=" + uploadID;
received = true;
while(!succesful){ // I upload until it is successful
// I stop the previous client session, because now I start a new one, to do the PUT request and upload the file
client.stop();
// Upload request
if (client.connect("www.googleapis.com", 443)) {
client.println("PUT " + location + " HTTP/1.1");
client.println("User-Agent: Arduino Camera");
client.println("Content-Length: " + String(image.size()));
client.println("Connection: close");
client.println();
while (image.available()) {
client.write(image.read()); // Here I send the bytes of the image
}
Serial.println(".");
image.close();
received = false;
} else {
Serial.println("Connection failed");
received = true;
}
// Listening to the response
startTime = millis();
String code = "";
while (millis() - startTime < 15000 && !received) { //try to listen for 5 seconds
int i = 0;
while (client.available() && i < 12) {
received = true;
char c = client.read();
Serial.write(c);
code = code + c;
i++;
}
// HTTP 200 OK
if (code == "HTTP/1.1 200" || code == "HTTP/1.1 201")
{
while(client.available()) {
char c = client.read();
Serial.write(c);
}
Serial.println("\nUpload succesful");
succesful = true;
// client.stop();
return succesful;
}
if (!received) {
client.stop();
Serial.println("\nUpload interrupted. Starting a new session");
// I have to open image again
image = SD.open(filepath, FILE_READ);
}
}
I am writing a code with arduino and ethernet shield. It consist in an accelerometer which reads values and shows them in a web page. It is in local. If I had to write CSS style with client.print(); I would spend a lot of time and useless lines of code. I would like to add an external CSS sheet linked with the internal page made-up into the arduino sketch. I tried to put the CSSsheet into a directory of the sketch and set <link href> but it didn't work. The page is made like this:
#mike
this is the whole function, thanks.
void RichiesteAlServer() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
//client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println("Refresh: 5"); // refresh the page automatically every 5 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
// output the value of each analog input pin
client.println("<head><title>Sismografo</title><link href=\"css/style.css\" rel=\"stylesheet\" type=\"text/css\"/></head>");
client.println("<body>");
client.println("<h1>Sismografo</h1>");
client.println("<p>");
client.print("Indice Array : ");
client.print(indiceArray);
client.println("</p>");
client.println("<p>");
stampaCanvas(client);
client.println("</p>");
client.println("<p>");
client.print("valore: ");
client.print(arrayValoriAccel[indiceArray]);
client.println("</p>");
client.println("<p>");
client.print("inizio scossa : ");
client.print(inizio_scossa);
client.println("</p>");
client.println("<p>");
client.print("fine scossa : ");
client.print(fine_scossa);
client.println("</p>");
client.println("<p>");
client.print("Durata scossa : ");
client.print(durata_totale_scossa);
client.println("</p>");
client.println("<p>");
client.print("cont : ");
client.print(cont);
client.println("</p>");
client.println("</body>");
client.println("</html>");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
} else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disconnected");
}
}
I have a code that was available on this website https://hackaday.io/project/3072/instructions . I made the code work by modifying it a little but the main problem is that it serves the GET request only once. What i want is continuous page fetch and there should be no TCP connection closing.
I have tried different methods but the connection always breaks after 1 GET request.
Moreover, if i do not send any GET request then it serves the domain's index page continuously without breaking TCP connection.
This is the original code http://dunarbin.com/esp8266/retroBrowser.ino.
And this is mine.
#define SSID "vivek"
#define PASS "bustedparamour21"
#define DEST_HOST "www.electronics2work.com"
#define DEST_IP "31.170.161.234"
#define TIMEOUT 10000 // mS
#define CONTINUE false
#define HALT true
#define ECHO_COMMANDS // Un-comment to echo AT+ commands to serial monitor
// Print error message and loop stop.
void errorHalt(String msg)
{
Serial.println(msg);
Serial.println("HALT");
while(true){};
}
// Read characters from WiFi module and echo to serial until keyword occurs or timeout.
boolean echoFind(String keyword)
{
byte current_char = 0;
byte keyword_length = keyword.length();
// Fail if the target string has not been sent by deadline.
long deadline = millis() + TIMEOUT;
while(millis() < deadline)
{
if (Serial1.available())
{
char ch = Serial1.read();
Serial.write(ch);
if (ch == keyword[current_char])
if (++current_char == keyword_length)
{
Serial.println();
return true;
}
}
}
return false; // Timed out
}
// Read and echo all available module output.
// (Used when we're indifferent to "OK" vs. "no change" responses or to get around firmware bugs.)
void echoFlush()
{while(Serial1.available()) Serial.write(Serial1.read());}
// Echo module output until 3 newlines encountered.
// (Used when we're indifferent to "OK" vs. "no change" responses.)
void echoSkip()
{
echoFind("\n"); // Search for nl at end of command echo
echoFind("\n"); // Search for 2nd nl at end of response.
echoFind("\n"); // Search for 3rd nl at end of blank line.
}
// Send a command to the module and wait for acknowledgement string
// (or flush module output if no ack specified).
// Echoes all data received to the serial monitor.
boolean echoCommand(String cmd, String ack, boolean halt_on_fail)
{
Serial1.println(cmd);
#ifdef ECHO_COMMANDS
Serial.print("--"); Serial.println(cmd);
#endif
// If no ack response specified, skip all available module output.
if (ack == "")
echoSkip();
else
// Otherwise wait for ack.
if (!echoFind(ack)) // timed out waiting for ack string
if (halt_on_fail)
errorHalt(cmd+" failed");// Critical failure halt.
else
return false; // Let the caller handle it.
return true; // ack blank or ack found
}
// Connect to the specified wireless network.
boolean connectWiFi()
{
String cmd = "AT+CWJAP=\""; cmd += SSID; cmd += "\",\""; cmd += PASS; cmd += "\"";
if (echoCommand(cmd, "OK", CONTINUE)) // Join Access Point
{
Serial.println("Connected to WiFi.");
return true;
}
else
{
Serial.println("Connection to WiFi failed.");
return false;
}
}
// ******** SETUP ********
void setup()
{
Serial.begin(9600); // Communication with PC monitor via USB
Serial1.begin(9600); // Communication with ESP8266 via 5V/3.3V level shifter
Serial1.setTimeout(TIMEOUT);
Serial.println("ESP8266 Demo");
delay(2000);
Serial.println("Module is ready.");
echoCommand("AT+GMR", "OK", CONTINUE); // Retrieves the firmware ID (version number) of the module.
echoCommand("AT+CWMODE?","OK", CONTINUE);// Get module access mode.
// echoCommand("AT+CWLAP", "OK", CONTINUE); // List available access points - DOESN't WORK FOR ME
echoCommand("AT+CWMODE=1", "", HALT); // Station mode
echoCommand("AT+CIPMUX=1", "", HALT); // Allow multiple connections (we'll only use the first).
//connect to the wifi
boolean connection_established = false;
for(int i=0;i<5;i++)
{
if(connectWiFi())
{
connection_established = true;
break;
}
}
if (!connection_established) errorHalt("Connection failed");
delay(5000);
//echoCommand("AT+CWSAP=?", "OK", CONTINUE); // Test connection
echoCommand("AT+CIFSR", "", HALT); // Echo IP address. (Firmware bug - should return "OK".)
//echoCommand("AT+CIPMUX=0", "", HALT); // Set single connection mode
}
// ******** LOOP ********
void loop()
{
// Establish TCP connection
String cmd = "AT+CIPSTART=0,\"TCP\",\""; cmd += DEST_IP; cmd += "\",80";
if (!echoCommand(cmd, "OK", CONTINUE)) return;
delay(2000);
// Get connection status
if (!echoCommand("AT+CIPSTATUS", "OK", CONTINUE))
return;
// Build HTTP request.
cmd = "GET /";
cmd +="iot/graphing.php?a=1&b=ldr&c=41 ";
cmd += "HTTP/1.1\r\nHost: ";
cmd += DEST_HOST;
cmd += ":80\r\n\r\n";
// Ready the module to receive raw data
if (!echoCommand("AT+CIPSEND=0,"+String(cmd.length()), ">", CONTINUE))
{
echoCommand("AT+CIPCLOSE", "", CONTINUE);
Serial.println("Connection timeout.");
return;
}
// Send the raw HTTP request
echoCommand(cmd, "OK",CONTINUE ); // GET
// Loop forever echoing data received from destination server.
while(true)
while (Serial1.available())
Serial.write(Serial1.read());
errorHalt("ONCE ONLY");
}
This code makes get request only once. How can i make it serve GET request Continously without closing TCP connection?
THANKS in Advance!!
You need to close your connection using AT+CIPCLOSE and then start a new connection again.
For example, if you need to make two connections everytime(like making connection with 2 websites) , you can make 1 connection, then close this connection. Now make another connection and close it.
I made 2 connections in my loop() function using above logic and it is working fine.