TCP client question

Does the TCP Client require a serial connection to operate? I’m slowly moving a project from a Nano/CC3000 setup to the Spark Core. My App pulls gets data from a NOAA buoy and parses the response. I would like my App to eventually run without a serial connection. Everything works great until I edit the line “while(!Serial.available()) SPARK_WLAN_Loop();” I’ve tried “while(1) SPARK_WLAN_Loop();” and just “SPARK_WLAN_Loop();” without the while statement, but I get red LED errors codes whenever I make edits to that part of the App. I’m not sure what the “SPARK_WLAN_Loop();” actually does… do I need to have a serial connection for the TCP client? Or can the TCP client work without it? Thank you!

TCPClient will work fine without the serial connection. Note that the “while(1) SPARK_WLAN_Loop()” is an infinite loop, so you’d never end up running any code after that!

Thank you for confirming the TCPClient will work without a serial connection. And for the while(1) advice!

I boiled down my App to see where I was getting my red led error. When I was pulling out the while(!Serial.available()) SPARK_WLAN_Loop(); I was also adding a couple Spark.publish(); calls to let me know where where the Core is in the code. If I uncomment the Spark.publish("status","connected"); in the code below, I get a red led error every time. Are there rules about when I can make a Spark.publish() call?

TCPClient client;
byte server[] = { 140, 90, 238, 27 };  // NOAA

void setup()
{
 
  Serial.begin(9600);
  while(!Serial.available()) SPARK_WLAN_Loop();

  //Serial.println("connecting...");

  if (client.connect(server, 80))
  {
    Serial.println("connected");
    //Spark.publish("status","connected");
    client.println("GET /data/latest_obs/46231.rss HTTP/1.0");
    client.println("Host: www.ndbc.noaa.gov");
    client.println("Content-Length: 0");
    client.println();
    
  }
  else
  {
    Serial.println("connection failed");
    //Spark.publish("status","connection failed");
  }
}

void loop()
{
  if (client.available())
  {
    char c = client.read();
    Serial.print(c);
  }
  
   if (!client.connected())
  {
    Serial.println();
    Serial.println("disconnecting.");
    //Spark.publish("status","disconnecting.");
    client.stop();
    for(;;);
  }
}

Hi @farmstand

This code a way to make sure on a PC with a terminal emulator program running that you can connect to the Spark serial port over USB. On Mac and Linux computers you don’t need this, it is just a PC thing.

The idea is that your Spark starts up and you have the terminal emulator running on your PC and the Spark waits for you to press any key before continuing. Generally this is just for debugging.

If you are not using the USB serial port, you don’t need this at all.

Thank you, @bko! That is what I was hoping… but I’m having trouble whenever I try and get ride of the while(!Serial.available()) SPARK_WLAN_Loop(); though. The code below runs great with the serial monitor statement included, but if I remove it, I always get my “else” Spark.publish("status","connection failed"); for the TCP client connection IF statement. I’ve tried using Spark.process() as I saw other users had luck with that but still no connection. Is there something I’m missing? Thanks again for the reply. I’ve read many of your posts and they have been very helpful!

TCPClient client;
byte server[] = { 140, 90, 238, 27 };  // NOAA
    
void setup()
{
  //Serial.begin(115200);
  pinMode(D7, OUTPUT);
  digitalWrite(D7, HIGH);
  //Spark.process();
  
  //Spark.publish("status","connecting to NOAA NDBC - Station 46231 - Mission Bay, CA");
  //while(!Serial.available()) SPARK_WLAN_Loop();
  
  //Serial.println("connecting to NOAA Station 46231");
   if (client.connect(server, 80))
  {
    //Serial.println("connected");
    //digitalWrite(D7, LOW);
    client.println("GET /data/latest_obs/46231.rss HTTP/1.0");
    client.println("Host: www.ndbc.noaa.gov");
    client.println("Content-Length: 0");
    client.println();
    //Spark.publish("status","connected");
    
    }
  else
  {
    //Serial.println("connection failed");
    Spark.publish("status","connection failed");
    client.stop();
    }
  
  while (client.connected()) 
   {
    while (client.available())
    {
    char c = client.read();
    //Serial.print(c);
    } 
   }
   Spark.publish("status","exit setup");
   client.stop();
  }

void loop()
{
  digitalWrite(D7, LOW);
  delay(100);
  digitalWrite(D7, HIGH);
}

It is a little strange to do all that work in setup() rather than loop(). I know you are just trying stuff out, but if it fails the first time for any reason, you don’t get a second chance with this code. I would try moving your TCP code to loop instead and see what happens. I would add a delay so you don’t hit the server too often.

This is very similar to a private project I did that parses an RSS feed for weather info. Here is how I connect using the host name. I don’t think you want a Content-Length: header for a GET request but you should have an Accept: header.

void sendGetRequest(const char * server, const char * url)
{
    if (myTCP.connect(server, 80)) {
        myTCP.print("GET ");
        myTCP.print(url);
        myTCP.println(" HTTP/1.0");
        myTCP.println("Connection: close");
        myTCP.print("Host: ");
        myTCP.println(server);
        myTCP.println("Accept: text/html, text/plain");
        myTCP.println();
        myTCP.flush();  // this is just for safety's sake, no real purpose
    } 
}

Yeah, I had everything in a function but when I started getting red led errors I tried starting over with the TCP Client example to see where things went wrong. I will try using your method and see if I have better luck. Thanks again, @bko!

1 Like

Thanks for your suggestion @bko! I pulled the GET request into a function and I still get an error on the first run BUT it works every time after that :smile:

Is there a condition I can test before the first pass? Or perhaps something I can enable? Its not the end of the world if it fails to connect on the first try… I can work on resetting a millis() variable and have it try again but it would be great if I knew why it wasn’t working the first time through.

Thanks again!

TCPClient myTCP;
byte server[] = { 140, 90, 238, 27 };  // NOAA


void setup()
{
  Serial.begin(115200);
  pinMode(D7, OUTPUT);
  digitalWrite(D7, HIGH);
}


void loop()
{
  digitalWrite(D7, LOW);
  getWaves();
  delay(20000);
}

void getWaves()
{
  if (myTCP.connect(server, 80)) {
    digitalWrite(D7, HIGH);
    myTCP.print("GET ");
    myTCP.print("/data/latest_obs/46231.rss");
    myTCP.println(" HTTP/1.0");
    myTCP.println("Connection: close");
    myTCP.print("Host: ");
    myTCP.println("www.ndbc.noaa.gov");
    myTCP.println("Accept: text/html, text/plain");
    myTCP.println();
    }
    
  else
  {
    Serial.println("connection failed");
    Spark.publish("status", "connection failed");
    myTCP.stop();
  }

  while (myTCP.connected())
  {
    while (myTCP.available())
    {
      char c = myTCP.read();
      Serial.print(c);
    }
  }

  Spark.publish("status", "exit getWaves");
  myTCP.flush();
  myTCP.stop();

}

I know I have seen this before in the past. You should make sure your core’s TI patch (deep update) is fully up to date. The easiest way is via Spark CLI over USB, putting the core into flashing yellow DFU mode and then doing:

spark flash --usb cc3000
spark flash --usb tinker
spark flash --factory tinker

Then install your code again and test.

I used Spark CLI and ran the three updates but still the same behavior. First connection always fails but then it works great after that. Thanks for the suggestion though!