Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

configTime() not working #4749

Closed
martin072 opened this issue May 20, 2018 · 9 comments
Closed

configTime() not working #4749

martin072 opened this issue May 20, 2018 · 9 comments

Comments

@martin072
Copy link

martin072 commented May 20, 2018

Hi,

I have some weird issues with configTime. I have two different sketches, both using the same function to initialise the network and do a sync with NTP. Only on one sketch it works fine, time is updated, other sketch the time defaults to 01-01-1970 09:00:00.
Even a recurrent configTime() (every few minutes) doesn't update.
Network connectivity is normal, i can access the ESP, no issues there.

Is there anyway to debug the configTime function?

  • Hardware: [WeMos D1R2]
  • Core Version: [2.4.1]

Here's the abbreviated code parts;

#define NTP_SERVERS "0.nl.pool.ntp.org", "1.nl.pool.ntp.org", "2.nl.pool.ntp.org"
#define UTC_OFFSET +1
struct dstRule StartRule = {"CEST", Last, Sun, Mar, 2, 3600}; // Central European Summer Time = UTC/GMT +2 hours
struct dstRule EndRule = {"CET", Last, Sun, Oct, 2, 0}; // Central European Time = UTC/GMT +1 hour
simpleDSTadjust dstAdjusted(StartRule, EndRule);

if (WiFi.status() == WL_CONNECTED) {
digitalWrite(LED_BUILTIN, HIGH);
DEBUG_PRINTLN(F(""));
DEBUG_PRINTLN(F("Connected successfully"));
DEBUG_PRINTLN(F(""));
DEBUG_PRINTLN(F("WiFi connected."));
if (!MDNS.begin(V_UNIT_NAME)) {
DEBUG_PRINTLN(F("Error setting up MDNS responder!"));
} else {
DEBUG_PRINT(F("MDNS Service started for http://"));
DEBUG_PRINT(V_UNIT_NAME);
DEBUG_PRINTLN(F(".local"));
}
SetupWebserver();
WebServer.begin();
DEBUG_PRINT(F("IP address: "));
DEBUG_PRINTLN(WiFi.localIP());
DEBUG_PRINT(F("Gateway: "));
DEBUG_PRINTLN(WiFi.gatewayIP());
DEBUG_PRINT(F("Server started on port:"));
DEBUG_PRINTLN(WEB_SERVER_PORT);
configTime(UTC_OFFSET * 3600, 0, NTP_SERVERS);
delay(500);
}

@RudyFiero
Copy link

I have two different sketches, both using the same function to initialise the network and do a sync with NTP. Only on one sketch it works fine,

So what makes you think this is a ESP8266/Arduino problem? (a problem with this repository) Nothing you have posted here indicates anything other than that you have a problem.

Here's the abbreviated code parts;

And how is someone supposed to do anything with that? If you are going to post your code then provide a complete simplified sketch. But keep in mind that this is not an I need help forum. See #3 in https://github.com/esp8266/Arduino/blob/master/POLICY.md And that seems to be what your issue is.

The following is a minimal example of a working sketch using configTime()

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <time.h>

const char* ssid = "xxxxx";
const char* password = "";

void setup(void) {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("");

  configTime(0, 0, "pool.ntp.org");  
  setenv("TZ", "CET-1CEST,M3.5.0,M10.5.0/3", 0);  

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println("Setup done");
}

void loop(void) {
  time_t tnow = time(nullptr);
  Serial.print(String(ctime(&tnow)));
  delay(1000);
}

And its output

....
Connected to mySSID
IP address: 192.168.100.107
Setup done
Mon May 21 18:52:35 2018
Mon May 21 18:52:36 2018
Mon May 21 18:52:37 2018
Mon May 21 18:52:38 2018
Mon May 21 18:52:39 2018
Mon May 21 18:52:40 2018

@lrmoreno007
Copy link
Contributor

Most of the time it is a DNS problem. Try directly with the IP of your DNS server. And as RudyFiero says ... it's not a problem with this repository.

@martin072
Copy link
Author

Youre absolutely right guys. My (newbie) mistake. Issue closed.

@marcelstoer
Copy link
Contributor

I've experienced such "01-01-1970 09:00:00" situations before as well. The workaround was to query time a couple of times

  Serial.println("Syncing time...");
  configTime(0, 0, "pool.ntp.org");  
  setenv("TZ", "CET-1CEST,M3.5.0,M10.5.0/3", 0);
  while(time(nullptr) <= 100000) {
    Serial.print(".");
    delay(100);
  }

@d-a-v
Copy link
Collaborator

d-a-v commented Jul 1, 2018

Time is coming from ntp servers some time after the request.
FYI when using lwip2, there is a callback set by settimeofday_cb() called when time is set by NTP.
You can see its use in the NTP-TZ-DST.ino example.

(this example needs rework though, cbtime is quite useless, and .println not wise in a callback)

@gojimmypi
Copy link
Contributor

In case someone else comes here looking for help on time, here's something I created based on a variety of tips and samples elsewhere.... (in this case, Pacific time) - that first checks if the time is already set, then tries to set network time, then resorts to a hard-coded epoch time (could possibly have a web service providing epoch time, too)

// *******************************************************************************************
void setupLocalTime()
// *******************************************************************************************
{
	// see https://github.com/esp8266/Arduino/issues/4637
	time_t now; 
	now = time(nullptr); // if there's no time, this will have a value of 28800; Thu Jan  1 08:00:00 1970 
	Serial.print("Initial time:"); Serial.println(now);
	Serial.println(ctime(&now));

	int myTimezone = -7;
	int dst = 0;
	int SecondsPerHour = 3600;
	int MAX_TIME_RETRY = 60;
	int i = 0;

	// it is unlikely that the time is already set since we have no battery; 
	// if no time is avalable, then try to set time from the network
	if (now <= 1500000000) {
		// try to set network time via ntp packets
		configTime(0, 0, "pool.ntp.org", "time.nist.gov"); // see https://github.com/esp8266/Arduino/issues/4749#issuecomment-390822737

                // Starting in 2007, most of the United States and Canada observe DST from
		// the second Sunday in March to the first Sunday in November.
		// example setting Pacific Time:
		setenv("TZ", "PST8PDT,M3.2.0/02:00:00,M11.1.0/02:00:00", 1); // see https://users.pja.edu.pl/~jms/qnx/help/watcom/clibref/global_data.html
		//                     | month 3, second sunday at 2:00AM
		//                                    | Month 11 - firsst Sunday, at 2:00am  
		// Mm.n.d
		//   The dth day(0 <= d <= 6) of week n of month m of the year(1 <= n <= 5, 1 <= m <= 12, where 
		//     week 5 means "the last d day in month m", which may occur in the fourth or fifth week).
		//     Week 1 is the first week in which the dth day occurs.Day zero is Sunday.

		tzset();
		Serial.print("Waiting for time(nullptr).");
		i = 0;
		while (!time(nullptr)) {
			Serial.print(".");
			delay(1000);
			i++;
			if (i > MAX_TIME_RETRY) {
				Serial.println("Gave up waiting for time(nullptr) to have a valid value.");
				break;
			}
		}
	}
	Serial.println("");

	// wait and determine if we have a valid time from the network. 
	now = time(nullptr);
	i = 0;
	Serial.print("Waiting for network time.");
	while (now <= 1500000000) {
		Serial.print(".");
		delay(1000); // allow a few seconds to connect to network time.
		i++;
		now = time(nullptr);
		if (i > MAX_TIME_RETRY) {
			Serial.println("Gave up waiting for network time(nullptr) to have a valid value.");
			break;
		}
	}
	Serial.println("");

	// get the time from the system
	char *tzvalue;
	tzvalue = getenv("TZ");
	Serial.print("Network time:");  Serial.println(now);
	Serial.println(ctime(&now));
	Serial.print("tzvalue for timezone = "); Serial.println(tzvalue);

	// TODO - implement a web service that returns current epoch time to use when NTP unavailable (insecure SSL due to cert date validation)

	// some networks may not allow ntp protocol (e.g. guest networks) so we may need to fudge the time
	if (now <= 1500000000) {
		Serial.println("Unable to get network time. Setting to fixed value. \n");
		// set to RTC text value
		// see https://www.systutorials.com/docs/linux/man/2-settimeofday/
		//
		//struct timeval {
		//	time_t      tv_sec;     /* seconds */
		//	suseconds_t tv_usec;    /* microseconds */
		//};
		timeval tv = { RTC_TEST, 0 };
		//
		//struct timezone {
		//	int tz_minuteswest;     /* minutes west of Greenwich */
		//	int tz_dsttime;         /* type of DST correction */
		//};
		timezone tz = { myTimezone * 60 , 0 };  

		// int settimeofday(const struct timeval *tv, const struct timezone *tz);
		settimeofday(&tv, &tz);
	}

	now = time(nullptr);
	Serial.println("Final time:");  Serial.println(now);
	Serial.println(ctime(&now));
}

@engbryan
Copy link

For those who may need it: just call configtime in setup(), it can even be called before the wifi begin. Throw and forget.

@marcelstoer
Copy link
Contributor

A further reference point is the full-monty bells'n whistles example at https://github.com/esp8266/Arduino/blob/master/libraries/esp8266/examples/NTP-TZ-DST/NTP-TZ-DST.ino. For most developers the only relevant lines are 254-264. In my experience configTime("my-time-zone", "pool.ntp.org") works much more reliably and faster than the previous (but still supported) configTime(0, 0, "pool.ntp.org").

@d-a-v
Copy link
Collaborator

d-a-v commented Jan 18, 2021

Should an example with this single configuration line be setup in the example repository ?
That would make a simple example for most developers, and another one with the full API described.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants