Author Topic: Multiple client connections  (Read 4770 times)

kranfahrer

  • Newbie
  • *
  • Posts: 3
Multiple client connections
« on: July 29, 2014, 04:51:30 am »
Hi all,

i have a problem with multiple client connections to different servers.
what i want to do is fetching a NTP Timestamp and afterwards upload some values to xively

i have combined the example SetRTCbyNTP and the DatastreamUpload but i get an HTTP_ERROR_TIMED_OUT = -3 when trying to upload to xively. The xively website does not recognize any connection attempt, so i think the first client connection to the timeserver is not closed properly... i try to do this with wifi.stop() after i have gotten a timestamp. if i erase the command wifi.stop() the result is the same and the error code is still -3.

Maybe someone can help me with my problem? Or maybe someone has an working example with multiple client connections or an client and server in the same sketch?

btw. i am using the latest DigiFi library from github and the wifi modules operation mode currently is AP+STA. Do i have to change this to STA?

Thanks in advance!


gogol

  • Sr. Member
  • ****
  • Posts: 398
Re: Multiple client connections
« Reply #1 on: July 30, 2014, 07:26:41 am »
Without code its impossible to tell you anything!
NTP is UDP, there are no connections, like in TCP.
Have you tried basic unchanged examples first? Are those running?


kranfahrer

  • Newbie
  • *
  • Posts: 3
Re: Multiple client connections
« Reply #2 on: July 30, 2014, 08:06:22 am »
Hi gogol,

thank you for your reply! i have tested all the examples and each one of them works fine.
i have made an example which combines the SetRTCbyNTP and XivelyDatastreamUpload. This shows the same errors as i have in my project.

Code: [Select]
#include <DigiFi.h>
#include <HttpClient.h>
#include <Xively.h>
#include <rtc_clock.h>


RTC_clock rtc_clock(XTAL);
char* daynames[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
int hh, mm, ss, dow, dd, mon, yyyy;
char timeServer[] = "time.nist.gov"; // time.nist.gov NTP server
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
uint8_t packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets


//Make sure to set your api key and feed number!
// Your Xively key to let you upload data
char xivelyKey[] = "M75AsUV7uO0zdlnCG5PYwwfkFSgKj3F5lh6k7LEtdSqiTKP7";

// Define the strings for our datastream IDs
char sensorId[] = "sensor_reading";
XivelyDatastream datastreams[] = {
  XivelyDatastream(sensorId, strlen(sensorId), DATASTREAM_FLOAT),
};
// Finally, wrap the datastreams into a feed
XivelyFeed feed(1681204889, datastreams, 1 /* number of datastreams */);

DigiFi client;
XivelyClient xivelyclient(client);

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  //DigiX trick - since we are on serial over USB wait for character to be entered in serial terminal
  while (!Serial.available()) {
    Serial.println("Enter any key to begin");
    delay(1000);
  }


  Serial.println("Starting single datastream upload to Xively...");
  Serial.println();

  client.begin();
  while (client.ready() != 1)
  {
    Serial.println("Connecting to network...");
    delay(1000);
  }

  rtc_clock.init();
  // start the connection:
  client.begin(9600);
  //client.setDebug(true);
  //wait for module to be ready
  while (client.ready() != 1)
  {
    Serial.println("Connecting to network...");
    delay(1000);
  }
  client.setMode(UDP); //must come before connect
  rtc_clock.set_time(__TIME__);
  Serial.println("Setting up UDP connection");
  client.connect(timeServer, 123);
  unsigned long ntpUnixTime = 0;
  while (ntpUnixTime == 0) {
    sendNTPpacket(); // send an NTP packet to a time server
    delay(1000);
    ntpUnixTime = getNTPpacket();
  }
  Serial.print("Got NTP Timestamp: ");
  Serial.println(ntpUnixTime);
  Serial.println("Setting RTC Clock");
  rtc_clock.set_timestamp(ntpUnixTime);

}

void loop() {

  Serial.print("Time: ");
  rtc_clock.get_time(&hh, &mm, &ss);
  rtc_clock.get_date(&dow, &dd, &mon, &yyyy);
  digitprint(hh, 2);
  Serial.print(":");
  digitprint(mm, 2);
  Serial.print(":");
  digitprint(ss, 2);
  Serial.println("");
  Serial.print("Date: ");
  Serial.print(daynames[dow - 1]);
  Serial.print(" ");
  digitprint(dd, 2);
  Serial.print(".");
  digitprint(mon, 2);
  Serial.print(".");
  Serial.println(yyyy);
  Serial.println("");
  delay(1000);


  float sensorValue = 12.0;
  datastreams[0].setFloat(sensorValue);

  Serial.print("Read sensor value ");
  Serial.println(datastreams[0].getFloat());

  Serial.println("Uploading it to Xively");
  int ret = xivelyclient.put(feed, xivelyKey);
  Serial.print("xivelyclient.put returned ");
  Serial.println(ret);

  Serial.println();
  delay(1000);
}


// send an NTP request to the time server at the given address
unsigned long sendNTPpacket()
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:
  client.write(packetBuffer, NTP_PACKET_SIZE);

}

unsigned long getNTPpacket() {
  if ( client.available() ) {
    // We've received a packet, read the data from it
    client.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer

    //the timestamp starts at byte 40 of the received packet and is four bytes,
    // or two words, long. First, esxtract the two words:

    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
    // combine the four bytes (two words) into a long integer
    // this is NTP time (seconds since Jan 1 1900):
    unsigned long secsSince1900 = highWord << 16 | lowWord;
    //Serial.print("Seconds since Jan 1 1900 = " );
    //Serial.println(secsSince1900);

    // now convert NTP time into everyday time:
    //Serial.print("Unix time = ");
    // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
    const unsigned long seventyYears = 2208988800UL;
    // subtract seventy years:
    unsigned long epoch = secsSince1900 - seventyYears;
    // print Unix time:
    return epoch;
  }
  else {
    return 0;
  }
}

void digitprint(int value, int lenght) {
  for (int i = 0; i < (lenght - numdigits(value)); i++) {
    Serial.print("0");
  }
  Serial.print(value);
}

int numdigits(int i) {
  int digits;
  if (i < 10)
    digits = 1;
  else
    digits = (int)(log10((double)i)) + 1;
  return digits;
}

Thank you!

gogol

  • Sr. Member
  • ****
  • Posts: 398
Re: Multiple client connections
« Reply #3 on: July 31, 2014, 03:19:50 am »
You are messing up the code! Is "client" the NTP client or the xively client?  You are using one variable for two independent tasks.  You need to clean your code, separate jobs!
Just mixing two programs (which use the same variable names and ressources) can't work!

Start understanding and commenting your code, and you will see, where it fails!  E.g. in setup you are calling two times client.begin()....


kranfahrer

  • Newbie
  • *
  • Posts: 3
Re: Multiple client connections
« Reply #4 on: July 31, 2014, 07:10:50 am »
Hi gogol!

Thank you again for your reply! I really appreciate it, that you use your time to help me. You are right, i messed up the code.
Now I have modified the code and i have split it in different functions.

I will post two different examples. The first one calls the uploadXively(float value) without the code for the RTC. The second example is the exact same code, but with all the stuff for the RTC and i update the timestamp via NTP in the setup().

In this example (it is without the functions for the RTC) the uploadXively(float value) function works fine and returns 200:

Code: [Select]


#include <DigiFi.h>
#include <HttpClient.h>
#include <Xively.h>

//Make sure to set your api key and feed number!

// Your Xively key to let you upload data
char xivelyKey[] = "M75AsUV7uO0zdlnCG5PYwwfkFSgKj3F5lh6k7LEtdSqiTKP7";
int xivelyFeed = 1681204889;

//
//=============================================== setup ===============================================
//
void setup() {

  // put your setup code here, to run once:
  Serial.begin(9600);

  //DigiX trick - since we are on serial over USB wait for character to be entered in serial terminal
  while (!Serial.available()) {
    Serial.println("Enter any key to begin");
    delay(1000);
  }

}

//
//=============================================== loop ===============================================
//
void loop() {
  float sensorValue = 1.1;

//  Serial.print("Uploading it to Xively...");
  uploadXively(sensorValue);
//  Serial.println(" OK");
 
  delay(1000);
}

//
//=============================================== uploadXively ===============================================
//
void uploadXively(float value) {

  DigiFi clientXively;
  XivelyClient xivelyclient(clientXively);

  // Define the strings for our datastream IDs
  char sensorId[] = "Temperature";          // Name of the Xively Channel
  XivelyDatastream datastreams[] = {
    XivelyDatastream(sensorId, strlen(sensorId), DATASTREAM_FLOAT),
  };
 
  // Finally, wrap the datastreams into a feed
  XivelyFeed feed(xivelyFeed, datastreams, 1 /* number of datastreams */);


  // Start network client for xively
  clientXively.begin(9600);
  Serial.print("Connecting to network..");
  while (clientXively.ready() != 1) {
    Serial.print(".");
    delay(500);
  }
  Serial.println(". OK");

  // Set datastream value to given value
  datastreams[0].setFloat(value);

  // Upload to Xively 
  Serial.print("Uploading to Xively...");
  int ret = xivelyclient.put(feed, xivelyKey);
  if (ret == 200) {
    Serial.println(" OK");
  } else {
    Serial.println("ERROR!");
    Serial.print("xivelyclient.put returned ");
    Serial.println(ret);
  }
 
  // Stop network client for xively
  clientXively.stop();
  Serial.println();
}


But in this example (it is with the stuff for the RTC) the uploadXively(float value) function returns -3.

Code: [Select]

#include <DigiFi.h>
#include <HttpClient.h>
#include <Xively.h>
#include <rtc_clock.h>

//Make sure to set your api key and feed number!

// Your Xively key to let you upload data
char xivelyKey[] = "M75AsUV7uO0zdlnCG5PYwwfkFSgKj3F5lh6k7LEtdSqiTKP7";
int xivelyFeed = 1681204889;

RTC_clock rtc_clock(XTAL);
char* daynames[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
int hh, mm, ss, dow, dd, mon, yyyy;
int old_unixtime;
char timeServer[] = "0.de.pool.ntp.org"; // time.nist.gov NTP server
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
uint8_t packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets


//
//=============================================== setup ===============================================
//
void setup() {

  // put your setup code here, to run once:
  Serial.begin(9600);

  //DigiX trick - since we are on serial over USB wait for character to be entered in serial terminal
  while (!Serial.available()) {
    Serial.println("Enter any key to begin");
    delay(1000);
  }

  // Get timestamp from ntp server
  setupRTC();

}

//
//=============================================== loop ===============================================
//
void loop() {
  float sensorValue = 1.1;

//  Serial.print("Uploading it to Xively...");
  uploadXively(sensorValue);
//  Serial.println(" OK");
 
  delay(1000);
}

//
//=============================================== uploadXively ===============================================
//
void uploadXively(float value) {

  DigiFi clientXively;
  XivelyClient xivelyclient(clientXively);

  // Define the strings for our datastream IDs
  char sensorId[] = "Temperature";          // Name of the Xively Channel
  XivelyDatastream datastreams[] = {
    XivelyDatastream(sensorId, strlen(sensorId), DATASTREAM_FLOAT),
  };
 
  // Finally, wrap the datastreams into a feed
  XivelyFeed feed(xivelyFeed, datastreams, 1 /* number of datastreams */);


  // Start network client for xively
  clientXively.begin(9600);
  Serial.print("Connecting to network..");
  while (clientXively.ready() != 1) {
    Serial.print(".");
    delay(500);
  }
  Serial.println(". OK");

  // Set datastream value to given value
  datastreams[0].setFloat(value);

  // Upload to Xively 
  Serial.print("Uploading to Xively...");
  int ret = xivelyclient.put(feed, xivelyKey);
  if (ret == 200) {
    Serial.println(" OK");
  } else {
    Serial.println("ERROR!");
    Serial.print("xivelyclient.put returned ");
    Serial.println(ret);
  }
 
  // Stop network client for xively
  clientXively.stop();
  Serial.println();
}

//
//=============================================== setupRTC ===============================================
//
void setupRTC() {
  DigiFi clientRTC;

  rtc_clock.init();
  // start the connection:
  clientRTC.begin(9600);
  //client.setDebug(true);
  //wait for module to be ready
  Serial.print("Connecting to network..");
  while (clientRTC.ready() != 1) {
    Serial.print(".");
    delay(500);
  }
  Serial.println(". OK");
  clientRTC.setMode(UDP); //must come before connect
  rtc_clock.set_time(__TIME__);

  Serial.print("Setting up UDP connection..");
  clientRTC.connect(timeServer, 123);
  unsigned long ntpUnixTime = 0;
  while (ntpUnixTime == 0) {
    Serial.print(".");
    sendNTPpacket(clientRTC); // send an NTP packet to a time server
    delay(500);
    ntpUnixTime = getNTPpacket(clientRTC);
  }
  Serial.println(". OK");

  Serial.print("Got NTP Timestamp: ");
  Serial.println(ntpUnixTime);
  Serial.print("Setting RTC Clock...");
  rtc_clock.set_timestamp(ntpUnixTime);

  rtc_clock.set_hours(rtc_clock.get_hours() + adjustDstEurope()) ;
  Serial.println(". OK");

  clientRTC.stop();
}



//============================================================================================================
//================================== Below are the functions for the RTC =====================================
//============================================================================================================

//
//=============================================== sendNTPpacket ===============================================
//
// send an NTP request to the time server at the given address
unsigned long sendNTPpacket(DigiFi client) {
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:
  client.write(packetBuffer, NTP_PACKET_SIZE);

}


//
//=============================================== getNTPpacket ===============================================
//
unsigned long getNTPpacket(DigiFi client) {
  if ( client.available() ) {
    // We've received a packet, read the data from it
    client.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer

    //the timestamp starts at byte 40 of the received packet and is four bytes,
    // or two words, long. First, esxtract the two words:

    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
    // combine the four bytes (two words) into a long integer
    // this is NTP time (seconds since Jan 1 1900):
    unsigned long secsSince1900 = highWord << 16 | lowWord;
    //DEBUG_PRINT("Seconds since Jan 1 1900 = " );
    //DEBUG_PRINTLN(secsSince1900);

    // now convert NTP time into everyday time:
    //DEBUG_PRINT("Unix time = ");
    // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
    const unsigned long seventyYears = 2208988800UL;
    // subtract seventy years:
    unsigned long epoch = secsSince1900 - seventyYears;
    // print Unix time:
    return epoch;
  }
  else {
    return 0;
  }
}


//
//=============================================== digitprint ===============================================
// prints digits with given lenght
//
void digitprint(int value, int lenght) {
  for (int i = 0; i < (lenght - numdigits(value)); i++) {
    Serial.print("0");
  }
  Serial.print(value);
}

//
//=============================================== numdigits ===============================================
//
int numdigits(int i) {
  int digits;
  if (i < 10)
    digits = 1;
  else
    digits = (int)(log10((double)i)) + 1;
  return digits;
}

//
//=============================================== getDigit ===============================================
//
// returns the digits in given lenght
String getDigit(int value, int lenght) {
  String result;
  for (int i = 0; i < (lenght - numdigits(value)); i++) {
    //Serial.print("0");
    result += "0";
  }
  //Serial.print(value);
  result += value;

  return result;
}

//
//=============================================== adjustDstEurope ===============================================
//
// Get correct european time with summertime
int adjustDstEurope() {
  // last sunday of march
  int beginDSTDate =  (31 - (5 * yyyy / 4 + 4) % 7);
  //  Serial.println(beginDSTDate);
  int beginDSTMonth = 3;
  //last sunday of october
  int endDSTDate = (31 - (5 * yyyy / 4 + 1) % 7);
  //  Serial.println(endDSTDate);
  int endDSTMonth = 10;
  // DST is valid as:
  if (((mon > beginDSTMonth) && (mon < endDSTMonth))
      || ((mon == beginDSTMonth) && (dd >= beginDSTDate))
      || ((mon == endDSTMonth) && (dd <= endDSTDate)))
    return 2;  // DST europe = utc +2 hour
  else return 1; // nonDST europe = utc +1 hour
}


If I use the uploadXively(float value) function without calling the setupRTC() function it works fine and returns 200. If i call setupRTC() in the setup() then the uploadXively(float value) in the loop() returns -3.

Sorry for my bad english... it is not my native language.

I really don't know, where my mistake is.