fix Timezone and SNTP sync
This commit is contained in:
parent
8a50acdff4
commit
913b4fbfaa
@ -2,20 +2,21 @@
|
||||
#include <TaskScheduler.h>
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN //ToDo check benefit
|
||||
|
||||
//#include <MacroLogger.h>
|
||||
#include <NeoPixelBrightnessBus.h>
|
||||
#include <IotWebConf.h>
|
||||
#include <IotWebConfTParameter.h>
|
||||
// UpdateServer includes
|
||||
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
# include <ESP8266HTTPUpdateServer.h>
|
||||
#include <TZ.h>
|
||||
#define MYTZ TZ_Europe_Berlin
|
||||
#include <coredecls.h> // settimeofday_cb()
|
||||
//#include <Schedule.h>
|
||||
//#include <PolledTimeout.h>
|
||||
#include <sys/time.h> // struct timeval
|
||||
#include <sntp.h> // sntp_servermode_dhcp()
|
||||
|
||||
#elif defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
// For ESP32 IotWebConf provides a drop-in replacement for UpdateServer.
|
||||
@ -60,17 +61,19 @@ void brightnessAdjustmentCallback();
|
||||
void brightnessFadingCallback();
|
||||
void iotWebConfLoopCallback();
|
||||
|
||||
|
||||
const char* ntpServer = "pool.ntp.org";
|
||||
const long gmtOffset_sec = 3600; //ToDo changable from user
|
||||
const int daylightOffset_sec = 3600;
|
||||
//https://github.com/esp8266/Arduino/blob/master/cores/esp8266/TZ.h
|
||||
#define MYTZ TZ_Europe_Berlin
|
||||
String currentNTP;
|
||||
struct tm timeinfo;
|
||||
time_t now;
|
||||
//https://github.com/arduino/esp8266/blob/master/cores/esp8266/sntp-lwip2.c
|
||||
|
||||
|
||||
//mapping for analog time representation
|
||||
volatile int currentSec = 30;
|
||||
volatile int currentMin = 50;
|
||||
volatile int currentHour = 50;
|
||||
volatile bool NTPreachable = false;
|
||||
|
||||
volatile int MAX_BRIGHTNESS = 200;
|
||||
#ifdef LDR_PIN
|
||||
// variable for storing the potentiometer value
|
||||
@ -86,7 +89,7 @@ const char wifiInitialApPassword[] = "12345678";
|
||||
// -- Maximal length the input-range attributes can have.
|
||||
//#define COLOR_ATTR_LENGTH 60
|
||||
// -- Configuration specific key. The value should be modified if config structure was changed.
|
||||
#define CONFIG_VERSION "V1.1.8"
|
||||
#define CONFIG_VERSION "V1.1.10"
|
||||
|
||||
|
||||
#ifdef RGBW
|
||||
@ -206,13 +209,20 @@ ESP8266HTTPUpdateServer httpUpdater;
|
||||
HTTPUpdateServer httpUpdater;
|
||||
#endif
|
||||
|
||||
|
||||
IotWebConf iotWebConf(thingName, &dnsServer, &server, wifiInitialApPassword, CONFIG_VERSION);
|
||||
iotwebconf::ParameterGroup timeGroup = iotwebconf::ParameterGroup("Time", "Time settings");
|
||||
iotwebconf::TextTParameter<STRING_LEN> timezoneParam =
|
||||
iotwebconf::Builder<iotwebconf::TextTParameter<STRING_LEN>>("timezone").
|
||||
label("TimeZone").
|
||||
defaultValue("TZ_Europe_Berlin").
|
||||
build();
|
||||
/*
|
||||
iotwebconf::TextTParameter<STRING_LEN> ntpServerParam =
|
||||
iotwebconf::Builder<iotwebconf::TextTParameter<STRING_LEN>>("ntpServer").
|
||||
label("NTP Server").
|
||||
defaultValue("pool.ntp.org").
|
||||
build();
|
||||
build();*/
|
||||
iotwebconf::ParameterGroup ledGroup = iotwebconf::ParameterGroup("LED", "LED settings");
|
||||
iotwebconf::IntTParameter<int16_t> maxBrightnessParam =
|
||||
iotwebconf::Builder<iotwebconf::IntTParameter<int16_t>>("Max Brightness").
|
||||
@ -316,6 +326,7 @@ CustomHtmlFormatProvider customHtmlFormatProvider;
|
||||
|
||||
Task bootAnim(200, TASK_FOREVER, &bootAnimCallback);
|
||||
Task clockTick(1000, TASK_FOREVER, &clockTickCallback);
|
||||
Task ntpReachableCheck(1800000, TASK_FOREVER, &ntpReachableCheckCallback);
|
||||
Task ledRefresh(200, TASK_FOREVER, &ledRefreshCallback);
|
||||
#ifdef LDR_PIN
|
||||
Task brightnessAdjustment(10000, TASK_FOREVER, &brightnessAdjustmentCallback);
|
||||
|
@ -19,9 +19,12 @@ void iotWebConfHandleRoot() {
|
||||
s += "<table>";
|
||||
s += "<tr><td>Current Time:</td><td>";
|
||||
s += printLocalTime();
|
||||
s += "</td></tr></table><table>";
|
||||
s += "</tr><td><tr><td>Current Timezone:</td><td>";
|
||||
s += (getenv("TZ") ? : "(none)");
|
||||
s += "</td></tr>";
|
||||
s += "</table><table>";
|
||||
s += "<tr></tr><tr><td>NTP Server:</td><td>";
|
||||
s += ntpServerParam.value();
|
||||
s += currentNTP;
|
||||
s += "</td><tr><tr><td>Current Brightness value: </td><td>";
|
||||
s += String(strip.GetBrightness());
|
||||
s += "</td><tr><tr><td>Max Brightness value: </td><td>";
|
||||
@ -64,7 +67,7 @@ void iotWebConfHandleRoot() {
|
||||
|
||||
void iotWebConfConfigSaved()
|
||||
{
|
||||
//ToDo ntpServerParamValue;
|
||||
setTimeZone();
|
||||
MAX_BRIGHTNESS = maxBrightnessParam.value();
|
||||
singleSecond = singleSecondParam.isChecked() ? true : false;
|
||||
//Serial.println(singleSecondParam.isChecked() ? "true" : "false");
|
||||
@ -89,7 +92,8 @@ void iotWebConfConfigSaved()
|
||||
|
||||
void iotWebConf_Setup() {
|
||||
|
||||
timeGroup.addItem(&ntpServerParam);
|
||||
timeGroup.addItem(&timezoneParam);
|
||||
//timeGroup.addItem(&ntpServerParam);
|
||||
|
||||
ledGroup.addItem(&maxBrightnessParam);
|
||||
ledGroup.addItem(&singleSecondParam);
|
||||
@ -109,7 +113,7 @@ void iotWebConf_Setup() {
|
||||
|
||||
iotWebConf.setConfigSavedCallback(&iotWebConfConfigSaved);
|
||||
//iotWebConf.setWifiConnectionTimeoutMs(60000);
|
||||
iotWebConf.setWifiConnectionCallback(&setNTP); //setNTP call after connection established
|
||||
iotWebConf.setWifiConnectionCallback(&ntpReachableCheckCallback);
|
||||
//iotWebConf.setFormValidator(&iotWebConfFormValidator);
|
||||
iotWebConf.getApTimeoutParameter()->visible = true;
|
||||
iotWebConf.setupUpdateServer(
|
||||
|
@ -1,4 +1,9 @@
|
||||
|
||||
/*
|
||||
* Callback to set the led
|
||||
* like the analog time
|
||||
* struct
|
||||
*
|
||||
*/
|
||||
void ledRefreshCallback() {
|
||||
temp = allDotsOn ? backlightColor : black;
|
||||
strip.ClearTo(temp);
|
||||
@ -33,6 +38,13 @@ void ledRefreshCallback() {
|
||||
strip.Show();
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback to animate
|
||||
* black running for online but not NTP
|
||||
* white running for connecting
|
||||
* green running for AP mode
|
||||
* red running for boot and unconfigured
|
||||
*/
|
||||
void bootAnimCallback() {
|
||||
strip.ClearTo(black);
|
||||
int tail = -1;
|
||||
@ -50,6 +62,7 @@ void bootAnimCallback() {
|
||||
}
|
||||
}
|
||||
|
||||
//ToDo change to no valid time
|
||||
if (iotWebConf.getState() == iotwebconf::OnLine && !NTPreachable) {
|
||||
strip.ClearTo(white);
|
||||
strip.SetPixelColor(MOD((currentSec - 0), NUM_LEDS), black);
|
||||
@ -75,6 +88,11 @@ void bootAnimCallback() {
|
||||
strip.Show();
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback fo the brigthness
|
||||
* takes 10 values, get the median
|
||||
* and set the new value
|
||||
*/
|
||||
#ifdef LDR_PIN
|
||||
void brightnessAdjustmentCallback() {
|
||||
//Serial.println(ldrValue);
|
||||
@ -89,6 +107,9 @@ void brightnessAdjustmentCallback() {
|
||||
//Serial.println("Brightness: " + String(strip.GetBrightness()) + "(" + String(ldrValue) + ")");
|
||||
}
|
||||
|
||||
/*
|
||||
* callback for fading the brigthness smootly
|
||||
*/
|
||||
void brightnessFadingCallback() {
|
||||
int currentBrightness = strip.GetBrightness();
|
||||
int diff = targetBrightness - currentBrightness;
|
||||
|
9
main.ino
9
main.ino
@ -65,6 +65,10 @@ void setup() {
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
#endif
|
||||
setTimeZone();
|
||||
//setNTP();
|
||||
settimeofday_cb(timeRefreshCallback); //internal callback for timesetting
|
||||
ntpReachableCheck.enable();
|
||||
}
|
||||
|
||||
void loop()
|
||||
@ -74,8 +78,5 @@ void loop()
|
||||
#ifdef ESP8266
|
||||
ESP.wdtFeed();
|
||||
#endif
|
||||
/*
|
||||
while (Serial.available())
|
||||
Serial.read();
|
||||
*/
|
||||
|
||||
}
|
||||
|
140
realtime.ino
140
realtime.ino
@ -1,38 +1,79 @@
|
||||
|
||||
// https://github.com/esp8266/Arduino/commit/a05a71fa9d2e6b143cb34f01b47e22c4b66b80a1
|
||||
//#ifdef ESP8266
|
||||
//bool getLocalTimeMe(struct tm * info, uint32_t ms)
|
||||
//{
|
||||
// uint32_t start = millis();
|
||||
// time_t now;
|
||||
// while ((millis() - start) <= ms) {
|
||||
// time(&now);
|
||||
// localtime_r(&now, info);
|
||||
// if (info->tm_year > (2016 - 1900)) {
|
||||
// return true;
|
||||
// }
|
||||
// delay(10);
|
||||
// }
|
||||
// return false;
|
||||
//}
|
||||
//#endif
|
||||
|
||||
void debugSNTP() {
|
||||
// lwIP v2 is able to list more details about the currently configured SNTP servers
|
||||
for (int i = 0; i < SNTP_MAX_SERVERS; i++) {
|
||||
IPAddress sntp = *sntp_getserver(i);
|
||||
const char* name = sntp_getservername(i);
|
||||
if (sntp.isSet()) {
|
||||
Serial.printf("sntp%d: ", i);
|
||||
if (name) {
|
||||
Serial.printf("%s (%s) ", name, sntp.toString().c_str());
|
||||
} else {
|
||||
Serial.printf("%s ", sntp.toString().c_str());
|
||||
}
|
||||
Serial.printf("- IPv6: %s - Reachability: %o\n", sntp.isV6() ? "Yes" : "No", sntp_getreachability(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String printLocalTime() {
|
||||
if (!getLocalTime(&timeinfo, 200)) {
|
||||
Serial.println("Failed to obtain time");
|
||||
NTPreachable = false;
|
||||
return "N/A";
|
||||
}
|
||||
//Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
|
||||
char timeStringBuff[50]; //50 chars should be enough
|
||||
strftime(timeStringBuff, sizeof(timeStringBuff), "%A, %B %d %Y %H:%M:%S", &timeinfo);
|
||||
//Serial.println(timeStringBuff);
|
||||
NTPreachable = true;
|
||||
return timeStringBuff;
|
||||
|
||||
}
|
||||
|
||||
void timeRefresh( bool from_sntp ) {
|
||||
/*
|
||||
* Check for DHCP supplied NTP
|
||||
*/
|
||||
void ntpReachableCheckCallback() {
|
||||
// lwIP v2 is able to list more details about the currently configured SNTP servers
|
||||
int usuableServer = 0;
|
||||
int serverCount = 0;
|
||||
for (int i = 0; i < SNTP_MAX_SERVERS; i++) {
|
||||
IPAddress sntp = *sntp_getserver(i);
|
||||
const char* name = sntp_getservername(i);
|
||||
if (sntp.isSet()) {
|
||||
serverCount++;
|
||||
if (sntp_getreachability(i) > 0) {
|
||||
NTPreachable = true;
|
||||
usuableServer++;
|
||||
getLocalTime(&timeinfo, 200);
|
||||
Serial.println("NTP reachable");
|
||||
currentNTP=sntp.toString();
|
||||
}
|
||||
else {
|
||||
NTPreachable = false;
|
||||
Serial.println("ntp NOT reachable");
|
||||
}
|
||||
}
|
||||
if (serverCount == 0) {
|
||||
setFallbackNTP();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
refresh the internal time struct
|
||||
*/
|
||||
void timeRefreshCallback( bool from_sntp ) {
|
||||
getLocalTime(&timeinfo, 200);
|
||||
Serial.print(asctime(&timeinfo));
|
||||
Serial.printf("timezone: %s\n", getenv("TZ") ? : "(none)");
|
||||
|
||||
//set new time only when from sntp
|
||||
//no manual way to set time
|
||||
if (!from_sntp) {
|
||||
Serial.println("Not SNTP time");
|
||||
}
|
||||
else {
|
||||
debugSNTP();
|
||||
Serial.println("SNTP time used");
|
||||
if (clockwiseRing) {
|
||||
currentSec = timeinfo.tm_sec;
|
||||
currentMin = timeinfo.tm_min;
|
||||
@ -44,38 +85,55 @@ void timeRefresh( bool from_sntp ) {
|
||||
currentMin = 60 - timeinfo.tm_min;
|
||||
currentHour = 12 - MOD(timeinfo.tm_hour, 12);
|
||||
}
|
||||
Serial.println("NTP mapped: " + String(int(currentHour * NUM_LEDS / 12)) + ":" + String(int(currentMin * NUM_LEDS / 60)) + ":" + String(int(currentSec * NUM_LEDS / 60)));
|
||||
Serial.println("timestruct mapped: " + String(int(currentHour * NUM_LEDS / 12)) + ":" + String(int(currentMin * NUM_LEDS / 60)) + ":" + String(int(currentSec * NUM_LEDS / 60)));
|
||||
bootAnim.disable();
|
||||
iotWebConfConfigSaved();
|
||||
ledRefresh.enable();
|
||||
//iotWebConfConfigSaved(); //ToDo why?
|
||||
ledRefresh.enableIfNot();
|
||||
#ifdef LDR_PIN
|
||||
brightnessFading.enable();
|
||||
brightnessFading.enableIfNot();
|
||||
#endif
|
||||
clockTick.enable(); //enable to check for ntp every 60 seconds
|
||||
brightnessAdjustment.enable();
|
||||
clockTick.enableIfNot();
|
||||
brightnessAdjustment.enableIfNot();
|
||||
}
|
||||
}
|
||||
|
||||
void setNTP() {
|
||||
void setTimeZone() {
|
||||
//init and get the time
|
||||
#ifdef ESP8266
|
||||
//sntp_servermode_dhcp(0);
|
||||
configTime(MYTZ, ntpServerParam.value());
|
||||
//sntp_servermode_dhcp(0); // 0: disable obtaining SNTP servers from DHCP (enabled by default)
|
||||
configTime(MYTZ,currentNTP);
|
||||
yield();
|
||||
settimeofday_cb(timeRefresh);
|
||||
#endif
|
||||
#ifdef ESP32
|
||||
configTime(0, 0, ntpServer);
|
||||
// TZ string information: https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
|
||||
setenv("TZ", "AEST-10", 1);
|
||||
tzset(); // save the TZ variable
|
||||
//setTimeZone(long offset, int daylight);
|
||||
//configTime(gmtOffset_sec, daylightOffset_sec, ntpServerParamValue);
|
||||
#endif
|
||||
Serial.println(printLocalTime());
|
||||
timeRefresh(false);
|
||||
yield();
|
||||
}
|
||||
/*
|
||||
function to set NTP server
|
||||
maybe not needed
|
||||
*/
|
||||
void setFallbackNTP() {
|
||||
//init and get the time
|
||||
#ifdef ESP8266
|
||||
//sntp_servermode_dhcp(0); // 0: disable obtaining SNTP servers from DHCP (enabled by default)
|
||||
//configTime(int timezone, int daylightOffset_sec, const char* server1, const char* server2, const char* server3 )
|
||||
configTime(MYTZ, "pool.ntp.org"); //ToDo skip TZ
|
||||
//setTZ(MYTZ);
|
||||
#endif
|
||||
#ifdef ESP32
|
||||
configTime(0, 0, "pool.ntp.org");
|
||||
#endif
|
||||
yield();
|
||||
}
|
||||
|
||||
// Scheduler
|
||||
/*
|
||||
Callback to handle the separate
|
||||
loose time structure for the mapping
|
||||
to the analog representation of a clock
|
||||
|
||||
*/
|
||||
void clockTickCallback() {
|
||||
#ifdef LDR_PIN
|
||||
ldrValue = (ldrValue + analogRead(LDR_PIN));
|
||||
@ -84,9 +142,6 @@ void clockTickCallback() {
|
||||
if (currentSec >= 60) {
|
||||
currentSec = 0;
|
||||
currentMin++;
|
||||
if (!NTPreachable) {
|
||||
setNTP();
|
||||
}
|
||||
if (currentMin >= 60) {
|
||||
currentMin = 0;
|
||||
currentHour++;
|
||||
@ -107,9 +162,6 @@ void clockTickCallback() {
|
||||
if (currentSec < 0) {
|
||||
currentSec = 59;
|
||||
currentMin--;
|
||||
if (!NTPreachable) {
|
||||
setNTP();
|
||||
}
|
||||
if (currentMin < 0) {
|
||||
currentMin = 59;
|
||||
currentHour--;
|
||||
|
Loading…
Reference in New Issue
Block a user