2

Libraries

Board

Olimex ESP32-POE board

Behaviour

I have written a code that connects the board to a local NTP Server (which is an embedded board). I tried assigning the IP Address of the above NTP Server using IPAddress and then convert it to c_str() to pass into the NTPClient constructor as follows:

 WiFiUDP ntpUDP; // udp socket object for NTP

 IPAddress NTPServer(192.168.3.11); // Local NTP Server IP Address

 NTPClient timeClient(ntpUDP, NTPServer.toString().c_str(), 0, 60000);

The reason for this is because the NTPClient class uses const char* for the IP Address of the NTP Server.

The values that are obtained once the code is flashed on the board are wrong because the timestamps are have the year 2106.

On the contrary, when I use

 NTPClient timeClient(ntpUDP, "192.168.3.11", 0, 60000);

and run the code on the board, this provides me perfect values of UTC time.

Why is there some discrepancy here?

Code

#include <Wire.h>
#include <ETH.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <RTClib.h>

WiFiUDP ntpUDP;
/* IP CONF for NODE */
///////// >>>> MODIFY Values Here <<<< ////////
const IPAddress node_static_ip(192, 168, 3, 101);
const IPAddress default_gateway(192, 168, 3, 250);
const IPAddress subnet_mask(255, 255, 255, 0);
const IPAddress dns_add(192, 168, 3, 250);
const IPAddress NTPServer(192, 168, 3, 11);

NTPClient timeClient(ntpUDP, "192.168.3.11", 0, 60000); // This works
NTPClient timeClient(ntpUDP, NTPServer.toString().c_str(), 0, 60000); // This won't (provides timestamps of 2106)

void setup() {
  // put your setup code here, to run once:
  Wire.begin(I2C_SDA, I2C_SCL);
  Serial.begin(115200);
  ETH.begin();
  ETH.config(node_static_ip, default_gateway, subnet_mask, dns_add);
  delay(1000);
  if (!rtc.begin()) {
    Serial.println("No RTC");
  }
  timeClient.begin();

}
void loop() {
  // put your main code here, to run repeatedly:
  timeClient.update();
  Serial.println(timeClient.getEpochTime());
  DateTime now_time(timeClient.getEpochTime());
  Serial.print(now_time.year(), DEC);
    Serial.print('/');
    Serial.print(now_time.month(), DEC);
    Serial.print('/');
    Serial.print(now_time.day(), DEC);
    Serial.print(now_time.hour(), DEC);
    Serial.print(':');
    Serial.print(now_time.minute(), DEC);
    Serial.print(':');
    Serial.print(now_time.second(), DEC);
Serial.println();

  delay(2000);

}
3
  • 1
    Don't you mean toString().c_str(), not toString.c_str()?
    – Majenko
    Commented Nov 8, 2018 at 17:37
  • Sorry Typo! I meant the latter.
    – Shan-Desai
    Commented Nov 8, 2018 at 17:39
  • 1
    I thought so, since the former doesn't compile. A simple test of printing to serial works fine. I suggest adding that into your program to make sure it's actually converting it wrong and not something else. Serial.println(NTPServer.toString().c_str());
    – Majenko
    Commented Nov 8, 2018 at 17:42

1 Answer 1

5

The String object created as return from IPAddress.toString() as parameter to constructor of NtpClient is temporary. It contains the char array returned by c_str(). NTPClient doesn't copy the string, only stores a reference to it. And the referenced string (char array) doesn't exist at the time the NTPClient wants to use it.

class TestClass {
public:
  TestClass(const char* _ip) : ip(_ip) { }

  void test() {
    Serial.println("--");
    Serial.println(ip);
    Serial.println("--");
  }

private:
  const char* ip;
};


//String s("abc");
//TestClass Test(s.c_str()); <- this works

TestClass Test(String("abc").c_str()); // <- this can't work

void setup() {
  Serial.begin(9600);
  Test.test();
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.