NTP Timezone & Enable/Disable Setting (#80)

* quick and dirty WIP to investigate timezones, currently only building under esp8266 platform
much of the status stuff has been stripped for now, to test the concepts

* support set of common features across ESP32/ESP8266 WRT timezone and sntp
return dates as ISO format strings

* remove time library, and timelib fix which is no longer required

* fix the icons

* remove temporary changes to demo project
This commit is contained in:
rjwats
2020-01-20 11:14:46 +00:00
committed by GitHub
parent 59326c6426
commit ced5b74ba1
16 changed files with 620 additions and 184 deletions

View File

@ -14,10 +14,6 @@ NTPSettingsService::NTPSettingsService(AsyncWebServer* server, FS* fs, SecurityM
_onStationModeGotIPHandler =
WiFi.onStationModeGotIP(std::bind(&NTPSettingsService::onStationModeGotIP, this, std::placeholders::_1));
#endif
NTP.onNTPSyncEvent([this](NTPSyncEvent_t ntpEvent) {
_ntpEvent = ntpEvent;
_syncEventTriggered = true;
});
}
NTPSettingsService::~NTPSettingsService() {
@ -29,38 +25,20 @@ void NTPSettingsService::loop() {
_reconfigureNTP = false;
configureNTP();
}
// output sync event to serial
if (_syncEventTriggered) {
processSyncEvent(_ntpEvent);
_syncEventTriggered = false;
}
// keep time synchronized in background
now();
}
void NTPSettingsService::readFromJsonObject(JsonObject& root) {
_enabled = root["enabled"] | NTP_SETTINGS_SERVICE_DEFAULT_ENABLED;
_server = root["server"] | NTP_SETTINGS_SERVICE_DEFAULT_SERVER;
_interval = root["interval"];
// validate server is specified, resorting to default
_server.trim();
if (!_server) {
_server = NTP_SETTINGS_SERVICE_DEFAULT_SERVER;
}
// make sure interval is in bounds
if (_interval < NTP_SETTINGS_MIN_INTERVAL) {
_interval = NTP_SETTINGS_MIN_INTERVAL;
} else if (_interval > NTP_SETTINGS_MAX_INTERVAL) {
_interval = NTP_SETTINGS_MAX_INTERVAL;
}
_tzLabel = root["tz_label"] | NTP_SETTINGS_SERVICE_DEFAULT_TIME_ZONE_LABEL;
_tzFormat = root["tz_format"] | NTP_SETTINGS_SERVICE_DEFAULT_TIME_ZONE_FORMAT;
}
void NTPSettingsService::writeToJsonObject(JsonObject& root) {
root["enabled"] = _enabled;
root["server"] = _server;
root["interval"] = _interval;
root["tz_label"] = _tzLabel;
root["tz_format"] = _tzFormat;
}
void NTPSettingsService::onConfigUpdated() {
@ -76,7 +54,7 @@ void NTPSettingsService::onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t i
void NTPSettingsService::onStationModeDisconnected(WiFiEvent_t event, WiFiEventInfo_t info) {
Serial.printf("WiFi connection dropped, stopping NTP.\n");
_reconfigureNTP = false;
NTP.stop();
sntp_stop();
}
#elif defined(ESP8266)
void NTPSettingsService::onStationModeGotIP(const WiFiEventStationModeGotIP& event) {
@ -87,30 +65,19 @@ void NTPSettingsService::onStationModeGotIP(const WiFiEventStationModeGotIP& eve
void NTPSettingsService::onStationModeDisconnected(const WiFiEventStationModeDisconnected& event) {
Serial.printf("WiFi connection dropped, stopping NTP.\n");
_reconfigureNTP = false;
NTP.stop();
sntp_stop();
}
#endif
void NTPSettingsService::configureNTP() {
Serial.println("Configuring NTP...");
// disable sync
NTP.stop();
// enable sync
NTP.begin(_server);
NTP.setInterval(_interval);
}
void NTPSettingsService::processSyncEvent(NTPSyncEvent_t ntpEvent) {
if (ntpEvent) {
Serial.print("Time Sync error: ");
if (ntpEvent == noResponse)
Serial.println("NTP server not reachable");
else if (ntpEvent == invalidAddress)
Serial.println("Invalid NTP server address");
if (_enabled) {
#ifdef ESP32
configTzTime(_tzFormat.c_str(), _server.c_str());
#elif defined(ESP8266)
configTime(_tzFormat.c_str(), _server.c_str());
#endif
} else {
Serial.print("Got NTP time: ");
Serial.println(NTP.getTimeDateString(NTP.getLastNTPSync()));
sntp_stop();
}
}

View File

@ -3,12 +3,18 @@
#include <AdminSettingsService.h>
#include <NtpClientLib.h>
#include <TimeLib.h>
#include <time.h>
#ifdef ESP32
#include <lwip/apps/sntp.h>
#elif defined(ESP8266)
#include <sntp.h>
#endif
// default time server
#define NTP_SETTINGS_SERVICE_DEFAULT_SERVER "pool.ntp.org"
#define NTP_SETTINGS_SERVICE_DEFAULT_INTERVAL 3600
// default time zone
#define NTP_SETTINGS_SERVICE_DEFAULT_ENABLED true
#define NTP_SETTINGS_SERVICE_DEFAULT_TIME_ZONE_LABEL "Europe/London"
#define NTP_SETTINGS_SERVICE_DEFAULT_TIME_ZONE_FORMAT "GMT0BST,M3.5.0/1,M10.5.0"
#define NTP_SETTINGS_SERVICE_DEFAULT_SERVER "time.google.com"
// min poll delay of 60 secs, max 1 day
#define NTP_SETTINGS_MIN_INTERVAL 60
@ -28,14 +34,15 @@ class NTPSettingsService : public AdminSettingsService {
void readFromJsonObject(JsonObject& root);
void writeToJsonObject(JsonObject& root);
void onConfigUpdated();
void receivedNTPtime();
private:
bool _enabled;
String _tzLabel;
String _tzFormat;
String _server;
int _interval;
bool _reconfigureNTP = false;
bool _syncEventTriggered = false;
NTPSyncEvent_t _ntpEvent;
#ifdef ESP32
void onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info);
@ -49,7 +56,6 @@ class NTPSettingsService : public AdminSettingsService {
#endif
void configureNTP();
void processSyncEvent(NTPSyncEvent_t ntpEvent);
};
#endif // end NTPSettingsService_h

View File

@ -7,24 +7,33 @@ NTPStatus::NTPStatus(AsyncWebServer* server, SecurityManager* securityManager) {
AuthenticationPredicates::IS_AUTHENTICATED));
}
String toISOString(tm* time, bool incOffset) {
char time_string[25];
strftime(time_string, 25, incOffset ? "%FT%T%z" : "%FT%TZ", time);
return String(time_string);
}
void NTPStatus::ntpStatus(AsyncWebServerRequest* request) {
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_NTP_STATUS_SIZE);
JsonObject root = response->getRoot();
// request time now first, this can sometimes force a sync
time_t timeNow = now();
timeStatus_t status = timeStatus();
time_t lastSync = NTP.getLastNTPSync();
root["status"] = (int)status;
root["last_sync"] = lastSync;
root["server"] = NTP.getNtpServerName();
root["interval"] = NTP.getInterval();
root["uptime"] = NTP.getUptime();
// grab the current instant in unix seconds
time_t now = time(nullptr);
// only add now to response if we have successfully synced
if (status != timeNotSet) {
root["now"] = timeNow;
}
// only provide enabled/disabled status for now
root["status"] = sntp_enabled() ? 1 : 0;
// the current time in UTC
root["time_utc"] = toISOString(gmtime(&now), false);
// local time as ISO String with TZ
root["time_local"] = toISOString(localtime(&now), true);
// the sntp server name
root["server"] = sntp_getservername(0);
// device uptime in seconds
root["uptime"] = millis() / 1000;
response->setLength();
request->send(response);

View File

@ -1,20 +1,21 @@
#ifndef NTPStatus_h
#define NTPStatus_h
#include <time.h>
#ifdef ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
#include <lwip/apps/sntp.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <sntp.h>
#endif
#include <ArduinoJson.h>
#include <AsyncJson.h>
#include <ESPAsyncWebServer.h>
#include <NtpClientLib.h>
#include <SecurityManager.h>
#include <TimeLib.h>
#define MAX_NTP_STATUS_SIZE 1024
#define NTP_STATUS_SERVICE_PATH "/rest/ntpStatus"

View File

@ -13,7 +13,6 @@
#include <AsyncJson.h>
#include <ESPAsyncWebServer.h>
#include <SecurityManager.h>
#include <TimeLib.h>
#define SCAN_NETWORKS_SERVICE_PATH "/rest/scanNetworks"
#define LIST_NETWORKS_SERVICE_PATH "/rest/listNetworks"