TCPClient hangs up core

Actually it is not the end of the story. I experimented a bit more, wrote a simple HTTP server, which accepts requests and switches on/off the LED. This one worked fine over the command line but got the same hang problem when used from the browser. The browser is firing off multiple requests (for whatever reason) either in parallel or in quick succession and this seems to be still not handled nicely. Also after a while it stopped working in many cases as well.

I then started stripping down the firmware and got to the point where it is now reliable, without any delay in my code. The culprit seems to be somewhere in the Timing_Decrement interrupt handler. I got the feeling that it simple runs for too long and then there is some conflict with some other interrupt connected to the CC3000 chip. Just a theory, of course. I even do not know if it does use an interrupt for CC3000, did not find the time to check, yet. In any case, removing everything from the Timing_Decrement function excdept doing the actual timer decrement solves the problem.

Sorry about my tangent, I just wanted to say that since my post 5 days ago about my TCP issues Iā€™ve figured out what I was doing wrong, and I believe that the majority of my issues were due to my own mistakes.

  • The 60 second socket timeout was caused by my router settings.
  • My keepalive requests opening mutliple sockets was definitely my own programming mistake.

With the right router settings and some a better server setup in Node.js, Iā€™ve got stable TCP communications.

1 Like

Thanks @Stevie for the detailed follow-through! Weā€™ll take a look at our code and see if we can replicate your improvements. Or if youā€™re feeling up to it, we welcome pull requestsā€¦ :smile:

Any updates on this one? I experience the same. Currently the core responds the first 3-5 times, and after that i have to reboot it.

tomas can you provide some more detail, perhaps a code sample and an explanation for how youā€™re using it?

Hi Zach,

I started out with trying to amend and use this code: http://arduino.cc/en/Tutorial/WebServer

I have now tried this shorter code to try to eliminate any sources of error, but still the same result. I typically get a response on the first attempts, and then no response before I restart the core (power off / power on).

TCPServer server = TCPServer(80);

void setup()
{
server.begin();
}

void loop()
{
TCPClient client = server.available();
if (client) {
delay(50);
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println("Refresh: 5");
client.println();
client.println("< !DOCTYPE HTML>");
client.println("< html>");
client.println("Hello world...?");
client.println("< /html>");
delay(50);
client.stop();
}
}

Using a terminal on port 80 gives me a answer on the first attempt:

telnet 192.168.1.13 80
Trying 192.168.1.13...
Connected to 192.168.1.13.
Escape character is '^]'.

HTTP/1.1 200 OK
Content-Type: text/html
Connection: close
Refresh: 5

< html>
Hello world...
< /html>
Connection closed by foreign host.

And after that nothing happens:

Trying 192.168.1.13...
Connected to 192.168.1.13.
Escape character is '^]'.
Connection closed by foreign host.

I have no clue whether I am doing anything wrong, or what this can be. Any help would be highly appreciated.

@tomas, please try the latest master of the 3 repos. Your issue should be fixed now.

I tested the following code which is derived from http://arduino.cc/en/Tutorial/WebServer

//TCPServer application test code: Prints analog values for A0 to A7 on browser and refreshes after 5sec

#include "application.h"

TCPServer server(80);

void setup()
{
    Serial.begin(9600);

    // start listening for clients
    server.begin();
}

void loop()
{
    // listen for incoming clients
    TCPClient 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
                    for (int analogChannel = 0; analogChannel < 8; analogChannel++) 
                    {
                        int sensorReading = analogRead(analogChannel + 10);
                        client.print("analog input A");
                        client.print(analogChannel);
                        client.print(" is ");
                        client.print(sensorReading);
                        client.println("<br />");
                    }
                    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;
                }
            }
        }

        // close the connection:
        client.stop();
        Serial.println("client disconnected");
    }
}

@satishgn
Thanks a lot for your response.
I have only used the web ide so far, can you direct me to a description on how I can use the ā€œlatest master repoā€?

Hello @tomas
The entire process of putting a firmware on the Core from the latest master is described here in the readme: https://github.com/spark/core-firmware/blob/master/README.md

Hope this helps!

1 Like

I tested the code above, and let me just make one request.
I have the latest repos.
I think the problem is that the client is not released with client.stop(); somehow blocking new connections

Dear @mohit!

To fix this issue does it mean we have to manually update the firmware? Isn't that something which is coming automatically with i compile something on the webIDE?

Kind regards,
Noten

@mohit, same question from me; when will the firmware be updated so that this can be done over the air?

Hey All!

Weā€™re in the process of reviewing fixes and firmware pull requests and merging them in. Right now you can pull the latest master from all the repos and compile locally, but weā€™ll probably update the stable ā€˜compile-server2ā€™ branches of the firmware sometime next week.

Thanks!
David

@Noten @tomas
The Web IDE uses a stable version of the firmware to which the user app is added to. When we roll out changes or updates, they are first made to the master branch on the core-firmware repo. In order for anyone to test latest fixes before they show up on the web IDE, they will need to use the master branch and compile it locally.

You will also need to pull changes from the master branches for core-communication and core-common repos.

We usually push updates to the IDE once in a week or two.

1 Like

@mohit and @Dave
thanx a lot for your quick response. I found the instructions for the manual update to be abit outside my technical comfort zone, but after trying it seems like I managed to get it to work. :smile:

2 Likes

@satishgn, your code works perfectly. Thanks a lot for your help as well!

2 Likes

I seem to be running this issue with the current master of all three repos. My test application.cpp is included at the end of this post. After some amount of time the Core seems to crash. It crashes somewhere between Serial.println(" -- Connected -- "); and the Serial.print(c);, but I donā€™t know exactly where. That is also assuming there arenā€™t any cached prints that donā€™t make it out before crashing. When it crashed the /dev/ttyACM0 serial port iā€™m reading closes and the Core seems to restart based on the LED, but I never get a serial port again. In my DMESG I get

[25331.384033] usb 2-1.4: new full-speed USB device number 77 using ehci_hcd
[25331.478195] cdc_acm 2-1.4:1.0: This device cannot do calls on its own. It is not a modem.
[25331.478210] cdc_acm 2-1.4:1.0: ttyACM0: USB ACM device
[25678.241534] usb 2-1.4: USB disconnect, device number 77

If I press the RST button, I get the first three lines again and it runs for a similar amount of time.

I also seem to be having general issues with the TCPClient::connect() function. Iā€™ve been getting a high number of failures to connect, in my tests it fails about 50% of the time. Out of 137 attempts to connect, it failed 861 times before crashing. It was in a Cyan Breathing the whole time.

I have the exact same loop() code running on an Arduino with Ethernet shield and Iā€™m currently at 430 attempts and 1 failure.

When I run my much bigger app it crashes much more quickly. After about 4 to 15 attempts.

#application.cpp:

#include "application.h"

TCPClient client;
char server[] = "m2.exosite.com";

const unsigned long interval = 5*1000;  // delay between updates, in milliseconds
unsigned long failCounter = 0;
unsigned long totalFailCounter = 0;
unsigned long totalCounter = 0;

void setup() {
  Serial.begin(115200);
}

void loop() {
  Serial.println(" -- Stats -- ");
  Serial.print("    Attempts: ");
  Serial.println(totalCounter++);
  Serial.print("    Failures: ");
  Serial.println(totalFailCounter);
  if (client.connect(server, 80)) {
  	failCounter = 0;
    Serial.println(" -- Connected -- ");
    
    client.println("GET /timestamp HTTP/1.1");
    client.println("Host: m2.exosite.com");
    client.println("User-Agent: Spark/? Patrick/0");
    client.println("Connection: Close");
    client.println();
    
    while(!client.available());
    
    while(client.available()) {
      char c = client.read();
      Serial.print(c);
    }
    
    Serial.println();
    
    client.stop();
    
    delay(interval);
  } 
  else {
    Serial.println(" -- Connection Failed -- ");
    Serial.print("    Count: ");
    Serial.println(++failCounter);
    totalFailCounter++;
    client.stop();
    delay(500);
  }
}
1 Like

Can someone help a noobie out here? Iā€™m trying to make the TCPServer example work. Can I use puTTY as a client? If so, what is the host name? sorry if this is silly.

Hi @captnkrunch

If your router is setup for DHCP like most home routers, you will likely have to use the IP address of the core instead of name. You can find the IP address on the core with the Network.localIP() method, which you could print on serial or have a Spark variable to get etc. or you could find it in your routerā€™s connection table with your router management software.

I think puTTY will work ok for telnet type stuff.

Hey @captnkrunch,

Did you get things sorted with the TcpServer example?

Thanks!
David