Hi all.
I am using the following code to send data on my Heroku app. Everything is connected and works fine most of the times, however, there are times that the connection freezes right after the message "connected". Does anyone have an idea why it freezes and doesn't proceed to send the data to the app or why the connection stays open?
Is there a way to overcome this issue?
if (client.connect(serverName, 80)) { //starts client connection, checks for connection
Serial.println("connected");
client.println(postData);
<<<
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
char serverName[] = "application.herokuapp.com";
EthernetClient client;
long soundSensor;
String data = "GET /api/device/deviceName/sensor/sensorName/report?value=";
void setup(){
Serial.begin(9600);
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// no point in carrying on, so do nothing forevermore:
while(true);
}
}
void loop(){
sendGET();
delay(12000);
}
//////////////////////////
void sendGET() //client function to send/receive GET request data.
{
soundSensor = random(0,50);
String postData = data + soundSensor + " "+"HTTP/1.1";
if (client.connect(serverName, 80)) { //starts client connection, checks for connection
Serial.println("connected");
client.println(postData);
client.println("Host: application.herokuapp.com");
client.println("Connection: close"); //close 1.1 persistent connection
client.println(); //end of get request
}
else {
Serial.println("connection failed"); //error message if no client connect
Serial.println();
}
while(client.connected() && !client.available()) delay(1); //waits for data
while (client.connected() || client.available()) { //connected or data available
char c = client.read(); //gets byte from ethernet buffer
Serial.print(c); //prints byte to serial monitor
}
Serial.println();
Serial.println("disconnecting.");
Serial.println("==================");
Serial.println();
client.stop(); //stop client
}
If you use a domain name for the serverName in the connect function call, the success return value is 1. There are other non-zero values returned that are a fail indication that have to do with the resolution of the domain name. Try changing to this:
if (client.connect(serverName, 80) == 1) { //starts client connection, checks for connection
I'm not saying that is the only problem you are having, but it could be one of them.
Is the last message on the serial monitor "connected"? If it is, then you may have a stalled server or failed connection. The fix is a timeout to close the connection from the client end if these fails happen. Here is my example sketch in the playground that has the timeout feature: http://playground.arduino.cc/Code/WebClient
Here is the response read with the timeout code from that example:
// connectLoop controls the hardware fail timeout
int connectLoop = 0;
while(client.connected())
{
while(client.available())
{
char inChar = client.read();
Serial.write(inChar);
// set connectLoop to zero if a packet arrives
connectLoop = 0;
}
connectLoop++;
// if more than 10000 milliseconds since the last packet
if(connectLoop > 10000)
{
// then close the connection from this end.
Serial.println();
Serial.println(F("Timeout"));
client.stop();
}
// this is a delay for the connectLoop timing
delay(1);
}
Serial.println();
Serial.println(F("disconnecting."));
// close client end
client.stop();
I tried your suggestion, and it looks a bit better now, thanks for the tip
I don't know if this is the best way though, I was also thinking to use another protocol, perhaps MQQT. Looks a bit better...
If you are looking for speed, think about using UDP. That is what I use. It requires a bit of programming to insure the receiver is getting the packet (receiver sends a response to the sender), but I found it simpler than trying to maintain a connection.
On the topic of using UDP for speed, I am building a novel data acquisition system for a school project. I want to develop a server on the Arduino that will send data to another server on the PC every 10 seconds. My sensors update global variables continually on the Arduino and then every 10seconds I want to quickly open a server connection send the latest values of my variables in a struct (+- 20 bytes), close the connection and continue polling from the sensors. I was hoping the process could take less than 100ms. I have not found latency examples for such connections, but I was thinking using UDP might increase my chances of achieving such requirements.
Would anyone agree?
Is 100ms unrealistic? (It is basically to ensure readings from sensors are not lost)
If UDP is the way to go, can anyone maybe provide an example of checking for successful data transfers?
I have not attempted to start building because it will take me a very long time since I am quite inexperienced, and I would like to get the architecture right.
any advice would be appreciated.
*edit
Why I want the sensor polling and client listening functions separate is to ensure if the server goes down I am still logging data and can save on the SD card what I need to.
ps. I wonder when the first asynchronous processing capable Arduino will be released.
I am definitely hosting on a localnet with light traffic. And I also know I can send the data at once as a packet. I will post results when I have achieved something.
I would use MQTT instead of UDP, because with UDP you have to implement all the handshaking (= ensuring successful transmission) and other protocol/non-data stuff yourself. With MQTT you can simply use higher QOS-Flags and concentragte on the data aquisition. An Example - with low QOS-Flags - you'll find on the blog of my company: Noser Blog Lightweight Network Communication - Noser Blog
(if you have questions concerning the Blog post - write them in here, as I am the author of that blog post.)