NTP Server library

I would like to implement time management by connecting to an NTP server but the libraries for ESP do not work with the Wio Terminal. Is there a library for Wio Terminal that manages an NTP Server?

What library does ESP use? We’ll port it for you.

I have successfully modified the arduino WiFiUdpNtpClient example to get ntp time and and setup a D3221 rtc. Not a lot needs to be done to the example. I use Adafruit’s RTCLib to manage the RTC. The nice thing about this library is its collection of time manipulation functions. Time is syncd on boot and every 12 hours.

This is great. Can you share your demo?

Hi @jimh57 I would be very happy to receive your help Can you share your modified library?
I will be very grateful to you.

Hi @Baozhu, below I send you the sketch with the library I use. I hope you can help me with porting.
Thanks in advance

/*
  NTP-TZ-DST
  NetWork Time Protocol - Time Zone - Daylight Saving Time

  This example shows how to read and set time,
  and how to use NTP (set NTP0_OR_LOCAL1 to 0 below)
  or an external RTC (set NTP0_OR_LOCAL1 to 1 below)

  TZ and DST below have to be manually set
  according to your local settings.

  This example code is in the public domain.
*/

#include <ESP8266WiFi.h>
#include <time.h>                       // time() ctime()
#include <sys/time.h>                   // struct timeval
#include <coredecls.h>                  // settimeofday_cb()

////////////////////////////////////////////////////////

#define SSID            "*********"
#define SSIDPWD         "*********"
#define TZ              1       // (utc+) TZ in hours
#define DST_MN          60      // use 60mn for summer time in some countries

#define NTP0_OR_LOCAL1  0       // 0:use NTP  1:fake external RTC
#define RTC_TEST     1510592825 // 1510592825 = Monday 13 November 2017 17:07:05 UTC

////////////////////////////////////////////////////////

#define TZ_MN           ((TZ)*60)
#define TZ_SEC          ((TZ)*3600)
#define DST_SEC         ((DST_MN)*60)

timeval cbtime;			// time set in callback
bool cbtime_set = false;

void time_is_set(void) {
  gettimeofday(&cbtime, NULL);
  cbtime_set = true;
  Serial.println("------------------ settimeofday() was called ------------------");
}

void setup() {
  Serial.begin(115200);
  settimeofday_cb(time_is_set);

  #if NTP0_OR_LOCAL1
  // local

  ESP.eraseConfig();
  time_t rtc = RTC_TEST;
  timeval tv = { rtc, 0 };
  timezone tz = { TZ_MN + DST_MN, 0 };
  settimeofday(&tv, &tz);

  #else // ntp

  configTime(TZ_SEC, DST_SEC, "pool.ntp.org");
  WiFi.mode(WIFI_STA);
  WiFi.begin(SSID, SSIDPWD);
  // don't wait, observe time changing when ntp timestamp is received

  #endif // ntp
}

// for testing purpose:
extern "C" int clock_gettime(clockid_t unused, struct timespec *tp);

#define PTM(w) \
  Serial.print(":" #w "="); \
  Serial.print(tm->tm_##w);

void printTm(const char* what, const tm* tm) {
  Serial.print(what);
  PTM(isdst); PTM(yday); PTM(wday);
  PTM(year);  PTM(mon);  PTM(mday);
  PTM(hour);  PTM(min);  PTM(sec);
}

timeval tv;
timespec tp;
time_t now;
uint32_t now_ms, now_us;

void loop() {

  gettimeofday(&tv, nullptr);
  clock_gettime(0, &tp);
  now = time(nullptr);
  now_ms = millis();
  now_us = micros();

  // localtime / gmtime every second change
  static time_t lastv = 0;
  if (lastv != tv.tv_sec) {
    lastv = tv.tv_sec;
    Serial.println();
    printTm("localtime", localtime(&now));
    Serial.println();
    printTm("gmtime   ", gmtime(&now));
    Serial.println();
    Serial.println();
  }

  // time from boot
  Serial.print("clock:");
  Serial.print((uint32_t)tp.tv_sec);
  Serial.print("/");
  Serial.print((uint32_t)tp.tv_nsec);
  Serial.print("ns");

  // time from boot
  Serial.print(" millis:");
  Serial.print(now_ms);
  Serial.print(" micros:");
  Serial.print(now_us);

  // EPOCH+tz+dst
  Serial.print(" gtod:");
  Serial.print((uint32_t)tv.tv_sec);
  Serial.print("/");
  Serial.print((uint32_t)tv.tv_usec);
  Serial.print("us");

  // EPOCH+tz+dst
  Serial.print(" time:");
  Serial.print((uint32_t)now);

  // human readable
  Serial.print(" ctime:(UTC+");
  Serial.print((uint32_t)(TZ * 60 + DST_MN));
  Serial.print("mn)");
  Serial.print(ctime(&now));

  // simple drifting loop
  delay(100);
}

Hi,

I will post the code, probably next week as I am busy this week. The ntp code is part of a larger sensor project so I will pull the ntp code into a smaller example. Hopefully this will help you progress.

thanks a lot @jimh57 I look forward to it.

Hi, @Gianfry60 @Baozhu

I have posted the code to my GitHub account found here: https://github.com/sannoxdev/wioTerm_ntp. You should have no issues getting to it.

It does work on a Wio Terminal. You may like to adjust the timer I use for syncing the RTC after 12 hours to something shorter to suit your requirements. The code is reasonably well commented.

Attached is a screen shot of the code running against my internal timeserver (WireShark capture).

Any questions let me know.

Thanks a lot @jimh57 , I will try the code and send you my results. I am very grateful to you.

Hi @jimh57, the NTP part works fine. However, I didn’t want to use an RTC but wanted to set the internal timer by aligning it with the NTP. I tried to insert the time.h library and set the Wio timer but I didn’t succeed.
Could you help me for this? I would be very grateful to you.
Thank you

I am attaching the listing that I used on ESP

#include "time.h"
#include <ESP8266WiFi.h>
//#include <WiFi.h>
const char* ssid     = "**************";                    // your network SSID (name)
const char* password = "**************";                    // your network password
const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = 3600;
const int   daylightOffset_sec = 3600;

/*

  %a Abbreviated weekday name

  %A Full weekday name

  %b Abbreviated month name

  %B Full month name

  %c Date and time representation for your locale

  %d Day of month as a decimal number (01-31)

  %H Hour in 24-hour format (00-23)

  %I Hour in 12-hour format (01-12)

  %j Day of year as decimal number (001-366)

  %m Month as decimal number (01-12)

  %M Minute as decimal number (00-59)

  %p Current locale's A.M./P.M. indicator for 12-hour clock

  %S Second as decimal number (00-59)

  %U Week of year as decimal number,  Sunday as first day of week (00-51)

  %w Weekday as decimal number (0-6; Sunday is 0)

  %W Week of year as decimal number, Monday as first day of week (00-51)

  %x Date representation for current locale

  %X Time representation for current locale

  %y Year without century, as decimal number (00-99)

  %Y Year with century, as decimal number

  %z %Z Time-zone name or abbreviation, (no characters if time zone is unknown)

  %% Percent sign

  You can include text literals (such as spaces and colons) to make a neater display or for padding between adjoining columns.

  You can suppress the display of leading zeroes  by using the "#" character  (%#d, %#H, %#I, %#j, %#m, %#M, %#S, %#U, %#w, %#W, %#y, %#Y)

*/

char buffer[80];

void printLocalTime()

{

  time_t rawtime;

  struct tm * timeinfo;

  time (&rawtime);

  timeinfo = localtime (&rawtime);

  strftime (buffer,80," %Y-%m-%d %H:%M:%S ",timeinfo);

  //struct tm timeinfo;

  //time_t now = time(nullptr);

  Serial.println(buffer);

  //Serial.print(ctime(&now));

  //Serial.print(&timeinfo, " %d %B %Y %H:%M:%S ");

}

void setup()

{

  Serial.begin(115200);

  delay(10);

 

  // We start by connecting to a WiFi network

  Serial.print("\n\nConnecting to ");

  Serial.println(ssid);

 

  /* Explicitly set the ESP8266 to be a WiFi-client, otherwise, it by default,

    would try to act as both a client and an access-point and could cause

  network-issues with your other WiFi-devices on your WiFi-network. */

  WiFi.mode(WIFI_STA);

  WiFi.begin(ssid, password);

 

  while (WiFi.status() != WL_CONNECTED)

  {

    delay(500);

    Serial.print(".");

  }

 

  Serial.println();

  Serial.println("WiFi connected");

  Serial.print("IP address: ");

  Serial.println(WiFi.localIP());

 

  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);

 

  Serial.println("\nWaiting for time");

  unsigned timeout = 5000;

  unsigned start = millis();

  while (!time(nullptr))

  {

    Serial.print(".");

    delay(1000);

  }

  delay(1000);

 

  Serial.println("Time...");

}

void loop()

{

  //time_t now = time(nullptr);

  //Serial.print(ctime(&now));

  printLocalTime();

  delay(1000);

}

Hi @Gianfry60 @Baozhu,

Porting the ESP code may work but a lot of work. There is a library called rtczero on the Arduino website that enables the use of the internal rtc on ATMEL M0 based boards i.e. Arduino Zero. This library will not compile on the Wio Terminal which based on the ATMEL M4 chips. When I looked at the code the rtczero library should be able to be ported for use on the Wio Terminal as it looks like the major issue is the registers naming used in the M4 chips.

@Baozhu Would the Seeed team be interested in porting the rtczero library for use on the Wio Terminal? It would be a useful additional base library for use on Wio Terminal.

Regards,
Jim

We are very interested, I have arranged this task internally, we will port it and PR to upstream as soon as possible. @jimh57

@Baozhu once the library is ready I am happy to test for you.

Thanks @baozhu and @jimh57 for the speed of the answers and for the commitment to resolve the matter. I will be happy to test it, if you find it useful, as soon as it is available.