khoih-prog / NTPClient_Generic

Library for NTPClient to connect to an NTP time-server. Get time from a NTP time-server and keep it in sync. For ESP8266/ESP32, nRF52, SAMD21/SAMD51, STM32F/L/H/G/WB/MP1, Teensy, etc. besides AVR, using ESP WiFi, WiFiNINA, Ethernet W5x00, ENC28J60, LAN8742A, ESP8266/ESP32 AT-command WiFi.
MIT License
30 stars 12 forks source link

timeClient.updated() not updating? #11

Closed Five-Nines closed 2 years ago

Five-Nines commented 2 years ago

Using MKR1010 FW v1.4.8, Windows Arduino IDE v1.8.19, NTPClient_Generic v3.7.5.

Pi is running NTP server and its IP address is hardcoded in the NINA_NTPClient_Advanced.ino sketch.

  1. When I stop the NTP service (or shutdown the Pi), timeClient.updated() is not updated to 0 (but the time displayed by the sketch is kept seemingly accurate.)
  2. Stopping the NTP service and booting the MKR1010, timeClient.updated() = 0. Then starting the NTP Service results in timeClient.updated() = 1 with correct time info.
  3. Therefore, timeClient.updated() operates correctly during its first pass (boot/reboot), but remains true thereafter regardless of the NTP server’s state. From my experience with the original NTPClient (https://github.com/arduino-libraries/NTPClient, see issue isTimeSet() does not reset when update fail #175), it exhibits the similar/same operation.

I’ve left NTP stopped for an hour while the MKR1010 continued run thinking that a buffer might get purged, but there was no change in the results of 1 above. It’s operating as if there is a time server being accessed. The issue could be my Arduino system configuration (libraries)…but I don’t see anything.

NTP started (1 above):

[NTP] Update from NTP Server
Using NTP Server 192.168.1.56
timeClient.updated() 1
********UPDATED********
UTC : 02:34:33
UTC :  2:34:33 Wed  9 Nov 2022
LOC : 20:34:33
LOC : 20:34:33 Tue  8 Nov 2022
UTC EPOCH : 1667961273
LOC EPOCH : 1667939673
UTC : 2:34:33 Wed 9/11/2022 or 9 Nov 2022
UTC : 02:34:33 Wed 9/11/2022 or 9 Nov 2022
LOC : 20:34:33 Tue 8/11/2022 or 8 Nov 2022
LOC : 20:34:33 Tue 8/11/2022 or 8 Nov 2022
**********************end loop********************** 

NTP stopped (1 above), no difference other than time:

[NTP] Update from NTP Server
Using NTP Server 192.168.1.56
timeClient.updated() 1
********UPDATED********
UTC : 02:35:53
UTC :  2:35:53 Wed  9 Nov 2022
LOC : 20:35:53
LOC : 20:35:53 Tue  8 Nov 2022
UTC EPOCH : 1667961353
LOC EPOCH : 1667939753
UTC : 2:35:53 Wed 9/11/2022 or 9 Nov 2022
UTC : 02:35:53 Wed 9/11/2022 or 9 Nov 2022
LOC : 20:35:53 Tue 8/11/2022 or 8 Nov 2022
LOC : 20:35:53 Tue 8/11/2022 or 8 Nov 2022
**********************end loop********************** 

NTP stopped, then MKR1010 booted (2 above):

Using NTP Server 192.168.1.56
[NTP] Update from NTP Server
[NTP] forceUpdate from NTP Server
Using NTP Server 192.168.1.56
timeClient.updated() 0
******NOT UPDATED******
UTC : 00:00:04
UTC :  0: 0: 4 Thu  1 Jan 1970
LOC : 00:28:20
LOC :  0:28:20 Sun  7 Feb 2106
UTC EPOCH : 4
LOC EPOCH : 4294945700
UTC : 0:0:4 Thu 1/1/1970 or 1 Jan 1970
UTC : 00:00:04 Thu 1/1/1970 or 1 Jan 1970
LOC : 0:28:20 Sun 7/2/2106 or 7 Feb 2106
LOC : 00:28:20 Sun 7/2/2106 or 7 Feb 2106
**********************end loop********************** 

NTP started after MKR1010 boot plus ~30 seconds (2 above):

[NTP] Update from NTP Server
[NTP] forceUpdate from NTP Server
[NTP] numBytesRead (48) = 48
[NTP] isValid: leapIndicator (!=3) = 0 , version (>=1) = 4
[NTP] stratum (1 <= stratum <= 15) = 2 , refTimeInt (!= 0) = 3876949998
[NTP] refTimeFrac (!= 0) = 4199878345
Using NTP Server 192.168.1.56
timeClient.updated() 1
********UPDATED********
UTC : 02:33:23
UTC :  2:33:23 Wed  9 Nov 2022
LOC : 20:33:23
LOC : 20:33:23 Tue  8 Nov 2022
UTC EPOCH : 1667961203
LOC EPOCH : 1667939603
UTC : 2:33:23 Wed 9/11/2022 or 9 Nov 2022
UTC : 02:33:23 Wed 9/11/2022 or 9 Nov 2022
LOC : 20:33:23 Tue 8/11/2022 or 8 Nov 2022
LOC : 20:33:23 Tue 8/11/2022 or 8 Nov 2022
**********************end loop********************** 
//https://github.com/khoih-prog/NTPClient_Generic
#include <WiFiNINA.h>
#include <RTCZero.h>
#include <TimeLib.h>

#include "C:\Users\me\Arduino\Secrets\arduino_secrets.h"
char ssid[] = SECRET_SSID;
char pass[] = SECRET_PASS;

//Used for WiFi.config(ip, dns, gateway, subnet);
IPAddress ip(192, 168, 1, 159);
IPAddress dns(192, 168, 1, 1);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);

/****************************************************************************************************************************
  NINA_NTPClient_Advanced.ino

  For AVR, ESP8266/ESP32, SAMD21/SAMD51, nRF52, STM32, SAM DUE, WT32_ETH01, RTL8720DN boards using 
  a) Ethernet W5x00, ENC28J60, LAN8742A
  b) WiFiNINA
  c) ESP8266/ESP32 WiFi
  d) ESP8266/ESP32-AT-command WiFi
  e) WT32_ETH01 (ESP32 + LAN8720)
  f) RTL8720DN

  Based on and modified from Arduino NTPClient Library (https://github.com/arduino-libraries/NTPClient)
  to support other boards such as ESP8266/ESP32, SAMD21, SAMD51, Adafruit's nRF52 boards, SAM DUE, RTL8720DN, etc.
  and Ethernet/WiFi/WiFiNINA shields

  Copyright (C) 2015 by Fabrice Weinberg and licensed under MIT License (MIT)

  Built by Khoi Hoang https://github.com/khoih-prog/NTPClient_Generic
  Licensed under MIT license
 *****************************************************************************************************************************/

#define NTP_DBG_PORT                Serial //Added

// Debug Level from 0 to 4
#define _NTP_LOGLEVEL_              4 //Added

//#include "defines.h" //Commented out

// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include <NTPClient_Generic.h>          // https://github.com/khoih-prog/NTPClient_Generic

// A UDP instance to let us send and receive packets over UDP
WiFiUDP ntpUDP;

// NTP server
//World
//char timeServer[] = "time.nist.gov";
// Canada
char timeServer[] = "192.168.1.56"; //Added
//char timeServer[] = "0.ca.pool.ntp.org";
//char timeServer[] = "1.ca.pool.ntp.org";
//char timeServer[] = "2.ca.pool.ntp.org";
//char timeServer[] = "3.ca.pool.ntp.org";
// Europe
//char timeServer[] = ""europe.pool.ntp.org";

#define TIME_ZONE_OFFSET_HRS            (-6) //Added
//#define TIME_ZONE_OFFSET_HRS            (-4)
#define NTP_UPDATE_INTERVAL_MS          60000L

// You can specify the time server pool and the offset (in seconds, can be
// changed later with setTimeOffset() ). Additionaly you can specify the
// update interval (in milliseconds, can be changed using setUpdateInterval() ).
NTPClient timeClient(ntpUDP, timeServer, (3600 * TIME_ZONE_OFFSET_HRS), NTP_UPDATE_INTERVAL_MS);

void setup() 
{
  Serial.begin(115200);
  while (!Serial && millis() < 5000);

//  Serial.print(F("\nStart NINA_NTPClient_Advanced on ")); Serial.print(BOARD_NAME);
//  Serial.print(F(" with ")); Serial.println(SHIELD_TYPE);
//  Serial.println(WIFI_WEBSERVER_VERSION);
  Serial.println(NTPCLIENT_GENERIC_VERSION);

  Serial.println("Connecting to: " + String(ssid));

  WiFi.config(ip, dns, gateway, subnet); //added
  WiFi.begin(ssid, pass);

  while ( WiFi.status() != WL_CONNECTED ) 
  {
    delay ( 500 );
    Serial.print ( "." );
  }

  Serial.print(F("\nNTPClient_Advanced started @ IP address: "));
  Serial.println(WiFi.localIP());

  timeClient.begin();

  Serial.println("Using NTP Server " + timeClient.getPoolServerName());
}

void loop()
{
  timeClient.update();

    Serial.println("Using NTP Server " + timeClient.getPoolServerName()); //added
    Serial.print("timeClient.updated() "); //added
    Serial.println(timeClient.updated()); //added

  if (timeClient.updated())
    Serial.println("********UPDATED********");
  else
    Serial.println("******NOT UPDATED******");

  Serial.println("UTC : " + timeClient.getFormattedUTCTime());
  Serial.println("UTC : " + timeClient.getFormattedUTCDateTime());
  Serial.println("LOC : " + timeClient.getFormattedTime());
  Serial.println("LOC : " + timeClient.getFormattedDateTime());
  Serial.println("UTC EPOCH : " + String(timeClient.getUTCEpochTime()));
  Serial.println("LOC EPOCH : " + String(timeClient.getEpochTime()));

  // Function test
  // Without leading 0
  Serial.println(String("UTC : ") + timeClient.getUTCHours() + ":" + timeClient.getUTCMinutes() + ":" + timeClient.getUTCSeconds() + " " +
        timeClient.getUTCDoW() + " " + timeClient.getUTCDay() + "/" + timeClient.getUTCMonth() + "/" + timeClient.getUTCYear() + " or " +
        timeClient.getUTCDay() + " " + timeClient.getUTCMonthStr() + " " + timeClient.getUTCYear());
  // With leading 0      
  Serial.println(String("UTC : ") + timeClient.getUTCStrHours() + ":" + timeClient.getUTCStrMinutes() + ":" + timeClient.getUTCStrSeconds() + " " +
        timeClient.getUTCDoW() + " " + timeClient.getUTCDay() + "/" + timeClient.getUTCMonth() + "/" + timeClient.getUTCYear() + " or " +
        timeClient.getUTCDay() + " " + timeClient.getUTCMonthStr() + " " + timeClient.getUTCYear());      
  // Without leading 0
  Serial.println(String("LOC : ") + timeClient.getHours() + ":" + timeClient.getMinutes() + ":" + timeClient.getSeconds() + " " +
        timeClient.getDoW() + " " + timeClient.getDay() + "/" + timeClient.getMonth() + "/" + timeClient.getYear() + " or " +
        timeClient.getDay() + " " + timeClient.getMonthStr() + " " + timeClient.getYear());
  // With leading 0
  Serial.println(String("LOC : ") + timeClient.getStrHours() + ":" + timeClient.getStrMinutes() + ":" + timeClient.getStrSeconds() + " " +
        timeClient.getDoW() + " " + timeClient.getDay() + "/" + timeClient.getMonth() + "/" + timeClient.getYear() + " or " +
        timeClient.getDay() + " " + timeClient.getMonthStr() + " " + timeClient.getYear());       

 Serial.println("**********************end loop**********************"); //Added

  delay(10000);
}
khoih-prog commented 2 years ago

Hi @Five-Nines

Did you try using the public NTP servers, such as in the examples ? If OK, your code / board could be OK, and the issue could be your NTP server (hardware / software, etc).

It's your problem to solve, and I have no interest in dealing with your special use-case, unless you prove this is the bug of this library.

Good Luck,

Five-Nines commented 2 years ago

Referencing NINA_NTPClient_Advanced.ino: The …Time() variables will have values regardless of whether an NTP transaction was properly processed. The delay(1000) “conflicts” with _retryInterval and _updateInterval in that there is an impression that update()/updated() actually performs a new NTP transaction with every loop() – it may or may not occur based on the intervals and flags.

I’ve tried three NTP servers: Pi, SAN NTP, and time.nist.gov. All operate the same: Upon initial sketch operation at boot, if the NTP server is online and returns a valid a NTP response, the sketch sets its variables (updated(), …Time(), etc.) accordingly. Else, updated() =0 and the …Time() variables have their initialization values. If the NTP server goes online, then updated() =1 and the …Time() variables are set accordingly. If, while the sketch is running, the NTP server goes offline, updated() is not flipped to 0, but the …Time() variables continue to update from their previous values.

updated() is dependent on _currentEpoc (and isTimeSet()), which is dependent on _lastUpdate. Update() and forceUpdate() are dependent on the intervals, a timeout, and other flags. The point is updated() will likely be = 0 only at sketch boot. This assumes the purpose of updated() is to reflect an actual successful NTP transaction and all program limitation (intervals, flags) have been met.

Having stated the above, here’s working code for NINA_NTPClient_Advanced.ino.

  1. Set the delay at the end of loop() so all intervals will be less. Thus 70000 > the default of 60000 (_updateInterval = 60000). 10 seconds is not enough delay in loop().
  2. In setup: timeClient.begin();
  3. Beginning of loop(): if (timeClient.update()) //Performs the actual NTP transaction, and library checks (intervals, flags) Serial.println("****UPDATED****"); else Serial.println("**NOT UPDATED**");
  4. Optionally, place in NTPClient_Generic_Impl.h bool NTPClient::forceUpdate() a println as a check the update passed all checks. if (this->checkResponse()){ Serial.println("NTPClient::forceUpdate()"); return true; }

The above also works in the original library, but # 4 is: this->_currentEpoc = secsSince1900 - SEVENZYYEARS; Serial.println("NTPClient::forceUpdate()"); return true; // return true after successful update

isTimeSet() is only a flag that there is one valid NTP transaction.

Referenced: https://forum.arduino.cc/t/ntpclient-library-how-does-timeclient-update-work/553833 https://github.com/arduino-libraries/NTPClient/issues/57 https://github.com/arduino-libraries/NTPClient/issues/41