ESP8266 WiFiUDP sending packet causes hang and then crash - arduino

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

Related

ESP8266 tcp recv returning errno 11 (EAGAIN) when handling large amounts of data

I am running ESP8266_RTOS_SDK_3.4 for an app that uses TCP to talk to a private port on a local server. In normal operation, it uploads large amounts of data to the server and receives acknowledgements that are usually less than 200 bytes: this always works fine. When I do an OTA update, where it's mainly receiving data, TCP recv fails on attempting to read the first block, and errno is set to 11 (EAGAIN). Even if I make the server send just 1024 bytes, the same thing happens.
This is the TCP connect and recv code:
bool net_tcp_connect (SENDER_DESTINATION * dest) {
struct sockaddr_in destAddr;
if (!find_host (dest->hostname)) {
return false;
}
memset(&destAddr, 0, sizeof(destAddr));
memcpy (&destAddr.sin_addr, findhost_ip (), sizeof (destAddr.sin_addr));
destAddr.sin_family = AF_INET;
destAddr.sin_port = htons (dest->port);
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
LOGEF("Create: errno %d", errno);
return false;
}
struct timeval tv;
tv.tv_sec = dest->timeout;
tv.tv_usec = 0;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));
if (connect(sock, (struct sockaddr *)&destAddr, sizeof(destAddr)) != 0) {
LOGEF("Connect: %s %d errno %d", findhost_str (), dest->port, errno);
EVENT_HERE ( );
net_tcp_close ();
return false;
}
return true;
}
// --------------------------------------------------------------------------------------------
int net_tcp_recv (void * buffer, int max_length) {
if (sock < 0)
return false;
int bytes_received = recv (sock, buffer, max_length, 0);
if (bytes_received < 0) {
LOGEF("Receive: errno= %d", errno);
net_tcp_close ();
bytes_received = 0;
}
return bytes_received;
}
EAGAIN can be a sign of a receive timeout, but the timeout is set to 30 seconds and the server usually sends out the first 32k bytes in less than a second.
The ESP8266 code does run OK on some access points and, as far as I can tell, the same code on an ESP32 runs OK on all access points.
Any suggestions for why this might happen, or things that I could try changing in the code or the ESP setup to make it work reliably on any access point?

Boost.Asio simple client server model do not return a response

Trying for first time to build my client server on boost.asio, the server response to client is empty.
i am not sure what is the problem - will be happy to any help.
Server code:
const std::string message = "Hi";
boost::system::error_code ignored_error;
try
{
boost::asio::io_service io_service;
tcp::endpoint endpoint = tcp::endpoint(tcp::v4(), 12345);
tcp::acceptor acceptor(io_service,endpoint);
for (;;){
tcp::socket socket(io_service);
acceptor.accept(socket);
boost::asio::write(socket,boost::asio::buffer(message), ignored_error);
}
}
catch (std::exception& e){
std::cerr << e.what() << std::endl;
}
Client code:
try{
boost::asio::io_service io_service;
tcp::resolver resolver(io_service);
tcp::resolver::query query(IP, "12345");
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::socket socket(io_service);
boost::asio::connect(socket, endpoint_iterator);
for (;;)
{
std::string buf;
boost::system::error_code error;
size_t len = socket.read_some(boost::asio::buffer(buf), error);
if (error == boost::asio::error::eof)
break; // Connection closed cleanly by peer.
else if (error)
throw boost::system::system_error(error); // Some other error.
std::cout.write(buf.data());
}
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
socket.read_some reads data into a buffer which is defined by boost::asio::buffer(buf).
The size of this buffer is determined by buf.size().
In your case std::string is empty,
so the buffer for reading bytes is empty.
read_some reads 0 bytes and returns.
Because the server always send a message consisted of 2 bytes, you can resize buf to hold 2 bytes:
std::string buf;
buf.resize(2);
boost::system::error_code error;
size_t len = socket.read_some(boost::asio::buffer(buf), error);
// now read_some reads at most 2 bytes into buf
Because at the server side a socket is created, it sends message and it is destroyed,
you can use dynamic_buffer + transfer_all + boost::asio::read to read non-fixed length message:
std::string buf;
size_t len = boost::asio::read (socket,boost::asio::dynamic_buffer(buf),
boost::asio::transfer_all(),error);
if (len && error == boost::asio::error::eof)
{
// data was read from server and eof is reached
// do sth with buf
}
boost::asio::read reads data until buffer is read fully or some errors occur (for example eof - socket at server side was closed).
The server sends data, client reads data, socket at server is destroyed and client gets eof from asio::read.

Function doesn't return the right value

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?

Unstable or slow communication between ESP8266 server and web browser client

I am using an ESP8266 Thing Dev board configured as an access point and server to store data from temperature sensors.
The goal is to access this data with an Android application, but for now, the client used is my computer running Chrome.
The sensors provide new temperatures every 250 ms, which are added to a string (JSON formatted).
When the client requests the data, the string is ended (closing JSON structure), and printed on the server.
The client should be able to access up to 2*50 values at a time. However, each time a request is send, either only 2 or 4 values are printed, either the page is not working.
My Arduino code, using ESP8266 and TMP102 libraries for arduino :
#include <ESP8266WiFi.h>
#include <Wire.h>
#include <Ticker.h>
#include "tmp102.h"
#define NB_MAX_TEMP 50
#define MAX_INPUT 20
const byte sensorAddress1 = 0x90; // ADD0 -> GND
const byte sensorAddress2 = 0x92; // ADD0 -> V+
tmp102 *thermometer1 = new tmp102(&Wire);
tmp102 *thermometer2 = new tmp102(&Wire);
// Timer
Ticker ticker;
bool flag = false;
// Wifi
const char WiFiAPPSK[] = "sparkfun"; // Wifi password
WiFiServer server(80);
int count = 0;
String s;
void setupWiFi()
{
WiFi.mode(WIFI_AP);
// Do a little work to get a unique-ish name. Append the
// last two bytes of the MAC (HEX'd) to "ThingDev-":
uint8_t mac[WL_MAC_ADDR_LENGTH];
WiFi.softAPmacAddress(mac);
String macID = String(mac[WL_MAC_ADDR_LENGTH - 2], HEX) +
String(mac[WL_MAC_ADDR_LENGTH - 1], HEX);
macID.toUpperCase();
String AP_NameString = "ThingDev-" + macID;
char AP_NameChar[AP_NameString.length() + 1];
memset(AP_NameChar, 0, AP_NameString.length() + 1);
for (int i = 0; i < AP_NameString.length(); i++)
AP_NameChar[i] = AP_NameString.charAt(i);
WiFi.softAP(AP_NameChar, WiFiAPPSK);
}
void timer_done()
{
flag = true;
}
void acquire()
{
int temp1 = 0, temp2 = 0;
if (thermometer1->readTemp(temp1))
{
// If we're reading pins, print out those values:
// first temp
s += String(temp1 * 0.0625);
}
s += ",";
if (thermometer2->readTemp(temp2))
{
// If we're reading pins, print out those values:
// second temp
s += String(temp2 * 0.0625);
}
return;
}
void setup()
{
Wire.begin(); // start the I2C library
Serial.begin(115200);
thermometer1->init(sensorAddress1);
thermometer2->init(sensorAddress2);
//Set default config.
thermometer1->writeConf(TMP102_DEFAULT_CONF);
thermometer2->writeConf(TMP102_DEFAULT_CONF);
setupWiFi();
server.begin();
// timer every 0.25s
ticker.attach(0.25, timer_done);
}
void loop()
{
// Check if a client has connected
WiFiClient client = server.available();
if (!client) {
return;
}
if (flag) {
flag = false;
int temp1 = 0, temp2 = 0;
if (count == 0) {
// prepare string
s = "HTTP/1.1 200 OK\r\n";
s += "Content-Type: text/html\r\n\r\n";
s += "{temp:[";
}
delay(1);
// add a measurement
s += "[";
acquire();
s += "],";
count += 1;
if (count == NB_MAX_TEMP) {
// Prevent the string to become infinite
count = 0;
s = s.substring(0, s.length() - 1);
s += "]};";
}
}
if (client.available() > 0) {
// Read the first line of the request
String req = client.readStringUntil('\r');
client.flush();
Serial.println(req);
if (req.indexOf("/read") != -1) {
// End the string
s.setCharAt(s.length() - 1, '\0');
s += "]};";
client.print(s);
Serial.println(s);
count = 0;
}
}
delay(1);
Serial.println("Client disconnected");
// The client will actually be disconnected
// when the function returns and 'client' object is detroyed
}
And a sample of what I get on the Serial console (the JSON string is the same I read on the server page) :
GET /read HTTP/1.1
HTTP/1.1 200 OK
Content-Type: text/html
{temp:[[24.00,24.56],[24.00,24.56];
Client disconnected
GET /favicon.ico HTTP/1.1
Client disconnected
GET /read HTTP/1.1
HTTP/1.1 200 OK
Content-Type: text/html
{temp:[[24.00,24.56];
Client disconnected
What am I doing wrong ? Am I using a blocking function ? Are the /favicon.ico requests causing trouble ?
For information, the access point part, and the sensor part of my code have been tested separately and work as expected.
Thanks in advance.

arduino how to return from function

I am relatively new to arduino and its programming though I have been plodding along and getting results. I have added a shortened version of my sketch which connects to my webserver and obtains the current temp for a particular city. I will then use that temp to set my heater also controlled by my arduino. The problem I am facing is I cant get my head around how to return to the main loop after I've read the data on webserver from the connectandread function. The sketch stops/halts after receiving the data(temp). Eventually I will be calling the function every 2 hours. So all in all I need to call the function then after it runs return to the main loop. I hope I've explained clearly enough.
byte server[] = { 192,168,0,2 }; //ip Address of the server you will connect to
//The location to go to on the server
//make sure to keep HTTP/1.0 at the end, this is telling it what type of file it is
String location = "/index1.php HTTP/1.0";
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
EthernetClient client;
int convertedtemp;
char inString[32]; // string for incoming serial data
int stringPos = 0; // string index counter
boolean startRead = false; // is reading?
String responseString;
void setup() {
Ethernet.begin(mac);
delay( 1000 );
// Start the I2C interface
Wire.begin();
}
void ReadDS3231() {
int second,minute,hour,date,month,year,temperature;
second=Clock.getSecond();
minute=Clock.getMinute();
hour=Clock.getHour(h12, PM);
date=Clock.getDate();
month=Clock.getMonth(Century);
year=Clock.getYear();
lcd.setCursor(0, 1);
}
void loop() {
connectAndRead();
// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
int h0 = dht0.readHumidity();
int h1 = dht1.readHumidity();
int t0 = dht0.readTemperature();
int t1 = dht1.readTemperature();
ReadDS3231(); delay(3000);
}
String connectAndRead() {
//connect to the server
Serial.println("connecting...");
if (client.connect(server, 80)) {
Serial.println("connected");
client.print("GET ");
client.println(location);
client.println();
//Connected - Read the page
return readPage(); //go and read the output
} else {
return "connection failed";
}
}
String readPage() {
//read the page, and capture & return everything between '<' and '>'
stringPos = 0;
memset( &inString, 0, 32 ); //clear inString memory
while (true) {
if (client.available()) {
char c = client.read();
if (c == '<' ) { //'<' is our begining character
startRead = true; //Ready to start reading the part
} else if (startRead) {
if (c != '>') { //'>' is our ending character
inString[stringPos] = c;
stringPos ++;
} else {
//got what we need here! We can disconnect now
startRead = false;
//Serial.print(inString);
//convertedtemp = atoi(inString).c_str());
int val = atoi(inString);
//int convertedhumid = atoi(getValuesFromKey(responseString, "relative_humidity").c_str());
Serial.println(val);
client.stop();
client.flush();
Serial.println("disconnecting.");
//return inString;
//return ;
}
}
}
}
}
Well, at least the version of the sketch you have posted have an infinite loop in it... (while(true)).
Try un-commenting the line with return inString;.
Also unrelated, since you read data from external source, you need to stop reading after you have received 31 characters even if you have not received an ">". Otherwise, a bug or malicious code on the server can corrupt your memory.

Resources