Browse Source

ntp: clean-up

resolve #2327, #2220

- remove legacy support in the webui
- format datetime strings on the device, use NTP panel to display them both
- migrate from the old ntpOffset + ntpDST + ntpRegion to ntpTZ
mcspr-patch-1
Maxim Prokhorov 3 years ago
parent
commit
aec13cef63
23 changed files with 22555 additions and 22548 deletions
  1. BIN
      code/espurna/data/index.all.html.gz
  2. BIN
      code/espurna/data/index.curtain.html.gz
  3. BIN
      code/espurna/data/index.light.html.gz
  4. BIN
      code/espurna/data/index.lightfox.html.gz
  5. BIN
      code/espurna/data/index.rfbridge.html.gz
  6. BIN
      code/espurna/data/index.rfm69.html.gz
  7. BIN
      code/espurna/data/index.sensor.html.gz
  8. BIN
      code/espurna/data/index.small.html.gz
  9. BIN
      code/espurna/data/index.thermostat.html.gz
  10. +81
    -16
      code/espurna/ntp.cpp
  11. +10
    -0
      code/espurna/ntp.h
  12. +3092
    -3098
      code/espurna/static/index.all.html.gz.h
  13. +2453
    -2457
      code/espurna/static/index.curtain.html.gz.h
  14. +2103
    -2107
      code/espurna/static/index.light.html.gz.h
  15. +2430
    -2435
      code/espurna/static/index.lightfox.html.gz.h
  16. +1784
    -1789
      code/espurna/static/index.rfbridge.html.gz.h
  17. +3916
    -3921
      code/espurna/static/index.rfm69.html.gz.h
  18. +2458
    -2463
      code/espurna/static/index.sensor.html.gz.h
  19. +2403
    -2408
      code/espurna/static/index.small.html.gz.h
  20. +1770
    -1775
      code/espurna/static/index.thermostat.html.gz.h
  21. +44
    -28
      code/espurna/ws.cpp
  22. +0
    -29
      code/html/custom.js
  23. +11
    -22
      code/html/index.html

BIN
code/espurna/data/index.all.html.gz View File


BIN
code/espurna/data/index.curtain.html.gz View File


BIN
code/espurna/data/index.light.html.gz View File


BIN
code/espurna/data/index.lightfox.html.gz View File


BIN
code/espurna/data/index.rfbridge.html.gz View File


BIN
code/espurna/data/index.rfm69.html.gz View File


BIN
code/espurna/data/index.sensor.html.gz View File


BIN
code/espurna/data/index.small.html.gz View File


BIN
code/espurna/data/index.thermostat.html.gz View File


+ 81
- 16
code/espurna/ntp.cpp View File

@ -153,7 +153,6 @@ bool _ntpWebSocketOnKeyCheck(const char * key, JsonVariant& value) {
void _ntpWebSocketOnVisible(JsonObject& root) {
root["ntpVisible"] = 1;
root["ntplwipVisible"] = 1;
}
void _ntpWebSocketOnData(JsonObject& root) {
@ -179,30 +178,44 @@ String _ntpGetServer() {
return server;
}
void _ntpReport() {
if (!ntpSynced()) {
DEBUG_MSG_P(PSTR("[NTP] Not synced\n"));
return;
}
tm utc_tm;
tm sync_tm;
NtpInfo ntpInfo() {
NtpInfo result;
auto ts = now();
gmtime_r(&ts, &utc_tm);
result.now = ts;
tm sync_tm;
gmtime_r(&_ntp_last, &sync_tm);
result.sync = ntpDateTime(&sync_tm);
DEBUG_MSG_P(PSTR("[NTP] Server : %s\n"), _ntp_server.c_str());
DEBUG_MSG_P(PSTR("[NTP] Sync Time : %s (UTC)\n"), ntpDateTime(&sync_tm).c_str());
DEBUG_MSG_P(PSTR("[NTP] UTC Time : %s\n"), ntpDateTime(&utc_tm).c_str());
tm utc_tm;
gmtime_r(&ts, &utc_tm);
result.utc = ntpDateTime(&utc_tm);
const char* cfg_tz = getenv("TZ");
if ((cfg_tz != nullptr) && (strcmp(cfg_tz, "UTC0") != 0)) {
tm local_tm;
localtime_r(&ts, &local_tm);
DEBUG_MSG_P(PSTR("[NTP] Local Time : %s (%s)\n"),
ntpDateTime(&local_tm).c_str(), cfg_tz
);
result.local = ntpDateTime(&local_tm);
result.tz = cfg_tz;
}
return result;
}
void _ntpReport() {
if (!ntpSynced()) {
DEBUG_MSG_P(PSTR("[NTP] Not synced\n"));
return;
}
auto info = ntpInfo();
DEBUG_MSG_P(PSTR("[NTP] Server : %s\n"), _ntp_server.c_str());
DEBUG_MSG_P(PSTR("[NTP] Sync Time : %s (UTC)\n"), info.sync.c_str());
DEBUG_MSG_P(PSTR("[NTP] UTC Time : %s\n"), info.utc.c_str());
if (info.tz.length()) {
DEBUG_MSG_P(PSTR("[NTP] Local Time : %s (%s)\n"), info.local.c_str(), info.tz.c_str());
}
}
@ -334,6 +347,57 @@ void _ntpSetTimestamp(time_t ts) {
// -----------------------------------------------------------------------------
void _ntpConvertLegacyOffsets() {
bool found { false };
bool europe { true };
bool dst { false };
int offset { 0 };
settings::kv_store.foreach([&](settings::kvs_type::KeyValueResult&& kv) {
const auto key = kv.key.read();
if (key == F("ntpOffset")) {
offset = kv.value.read().toInt();
found = true;
} else if (key == F("ntpDST")) {
dst = (1 == kv.value.read().toInt());
found = true;
} else if (key == F("ntpRegion")) {
europe = (0 == kv.value.read().toInt());
found = true;
}
});
if (!found) {
return;
}
// XXX: only expect offsets in hours
String custom { europe ? F("CET") : F("CST") };
custom.reserve(16);
if (offset > 0) {
custom += '-';
}
custom += offset / 60;
if (dst) {
custom += europe ? F("CEST") : F("EDT");
if (europe) {
custom += F(",M3.5.0,M10.5.0/3");
} else {
custom += F(",M3.2.0,M11.1.0");
}
}
delSetting("ntpOffset");
delSetting("ntpDST");
delSetting("ntpRegion");
setSetting("ntpTZ", custom);
}
void ntpSetup() {
// Randomized in time to avoid clogging the server with simultaneous requests from multiple devices
@ -358,6 +422,7 @@ void ntpSetup() {
// generic configuration, always handled
espurnaRegisterReload(_ntpConfigure);
_ntpConvertLegacyOffsets();
_ntpConfigure();
// make sure our logic does know about the actual server


+ 10
- 0
code/espurna/ntp.h View File

@ -44,8 +44,18 @@ struct NtpCalendarWeekday {
int utc_minute;
};
struct NtpInfo {
String local;
String utc;
String sync;
String tz;
time_t now;
};
BrokerDeclare(NtpBroker, void(const NtpTick, time_t, const String&));
NtpInfo ntpInfo();
String ntpDateTime(tm* timestruct);
String ntpDateTime(time_t ts);
String ntpDateTime();


+ 3092
- 3098
code/espurna/static/index.all.html.gz.h
File diff suppressed because it is too large
View File


+ 2453
- 2457
code/espurna/static/index.curtain.html.gz.h
File diff suppressed because it is too large
View File


+ 2103
- 2107
code/espurna/static/index.light.html.gz.h
File diff suppressed because it is too large
View File


+ 2430
- 2435
code/espurna/static/index.lightfox.html.gz.h
File diff suppressed because it is too large
View File


+ 1784
- 1789
code/espurna/static/index.rfbridge.html.gz.h
File diff suppressed because it is too large
View File


+ 3916
- 3921
code/espurna/static/index.rfm69.html.gz.h
File diff suppressed because it is too large
View File


+ 2458
- 2463
code/espurna/static/index.sensor.html.gz.h
File diff suppressed because it is too large
View File


+ 2403
- 2408
code/espurna/static/index.small.html.gz.h
File diff suppressed because it is too large
View File


+ 1770
- 1775
code/espurna/static/index.thermostat.html.gz.h
File diff suppressed because it is too large
View File


+ 44
- 28
code/espurna/ws.cpp View File

@ -22,8 +22,47 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
AsyncWebSocket _ws("/ws");
Ticker _ws_defer;
// -----------------------------------------------------------------------------
// Periodic updates
// -----------------------------------------------------------------------------
uint32_t _ws_last_update = 0;
void _wsResetUpdateTimer() {
_ws_last_update = millis() + WS_UPDATE_INTERVAL;
}
void _wsUpdate(JsonObject& root) {
root["heap"] = getFreeHeap();
root["uptime"] = getUptime();
root["rssi"] = WiFi.RSSI();
root["loadaverage"] = systemLoadAverage();
if (ADC_MODE_VALUE == ADC_VCC) {
root["vcc"] = ESP.getVcc();
} else {
root["vcc"] = "N/A (TOUT) ";
}
#if NTP_SUPPORT
if (ntpSynced()) {
auto info { ntpInfo() };
root["now"] = info.now;
root["nowString"] = info.utc;
root["nowLocalString"] = info.local.length()
? info.local
: info.utc;
}
#endif
}
void _wsDoUpdate(const bool connected) {
if (!connected) return;
if (millis() - _ws_last_update > WS_UPDATE_INTERVAL) {
_ws_last_update = millis();
wsSend(_wsUpdate);
}
}
// -----------------------------------------------------------------------------
// WS callbacks
// -----------------------------------------------------------------------------
@ -354,7 +393,6 @@ void _wsParse(AsyncWebSocketClient *client, uint8_t * payload, size_t length) {
String key = kv.key;
JsonVariant& value = kv.value;
// Check password
if (key == "adminPass") {
if (!value.is<JsonArray&>()) continue;
JsonArray& values = value.as<JsonArray&>();
@ -371,6 +409,11 @@ void _wsParse(AsyncWebSocketClient *client, uint8_t * payload, size_t length) {
}
continue;
}
#if NTP_SUPPORT
else if (key == "ntpTZ") {
_wsResetUpdateTimer();
}
#endif
if (!_wsCheckKey(key, value)) {
delSetting(key);
@ -412,33 +455,6 @@ void _wsParse(AsyncWebSocketClient *client, uint8_t * payload, size_t length) {
}
void _wsUpdate(JsonObject& root) {
root["heap"] = getFreeHeap();
root["uptime"] = getUptime();
root["rssi"] = WiFi.RSSI();
root["loadaverage"] = systemLoadAverage();
if (ADC_MODE_VALUE == ADC_VCC) {
root["vcc"] = ESP.getVcc();
} else {
root["vcc"] = "N/A (TOUT) ";
}
#if NTP_SUPPORT
if (ntpSynced()) root["now"] = now();
#endif
}
void _wsResetUpdateTimer() {
_ws_last_update = millis() + WS_UPDATE_INTERVAL;
}
void _wsDoUpdate(const bool connected) {
if (!connected) return;
if (millis() - _ws_last_update > WS_UPDATE_INTERVAL) {
_ws_last_update = millis();
wsSend(_wsUpdate);
}
}
bool _wsOnKeyCheck(const char * key, JsonVariant& value) {
if (strncmp(key, "ws", 2) == 0) return true;
if (strncmp(key, "admin", 5) == 0) return true;


+ 0
- 29
code/html/custom.js View File

@ -82,34 +82,6 @@ function zeroPad(number, positions) {
return number.toString().padStart(positions, "0");
}
function loadTimeZones() {
var time_zones = [
-720, -660, -600, -570, -540,
-480, -420, -360, -300, -240,
-210, -180, -120, -60, 0,
60, 120, 180, 210, 240,
270, 300, 330, 345, 360,
390, 420, 480, 510, 525,
540, 570, 600, 630, 660,
720, 765, 780, 840
];
for (var i in time_zones) {
var tz = time_zones[i];
var offset = tz >= 0 ? tz : -tz;
var text = "GMT" + (tz >= 0 ? "+" : "-") +
zeroPad(parseInt(offset / 60, 10), 2) + ":" +
zeroPad(offset % 60, 2);
$("select[name='ntpOffset']").append(
$("<option></option>")
.attr("value", tz)
.text(text)
);
}
}
function validatePassword(password) {
// http://www.the-art-of-web.com/javascript/validate-password/
// at least one lowercase and one uppercase letter or number
@ -2323,7 +2295,6 @@ function connectToCurrentURL() {
$(function() {
initMessages();
loadTimeZones();
createCheckboxes();
setInterval(function() { keepTime(); }, 1000);


+ 11
- 22
code/html/index.html View File

@ -1099,7 +1099,7 @@
<div class="header">
<h1>NTP</h1>
<h2>Configure your NTP (Network Time Protocol) servers and local configuration to keep your device time up to the second for your location.</h2>
<h2>Synchronize the device time with the remote server</h2>
</div>
<div class="page">
@ -1107,8 +1107,13 @@
<fieldset>
<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Device Current Time</label>
<input class="pure-u-1 pure-u-lg-3-4" name="now" type="text" readonly />
<label class="pure-u-1 pure-u-lg-1-4">Device Time</label>
<input class="pure-u-1 pure-u-lg-3-4" name="nowString" type="text" readonly />
</div>
<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Device Local Time</label>
<input class="pure-u-1 pure-u-lg-3-4" name="nowLocalString" type="text" readonly />
</div>
<div class="pure-g">
@ -1116,27 +1121,11 @@
<input class="pure-u-1 pure-u-lg-3-4" name="ntpServer" type="text" tabindex="41" />
</div>
<div class="pure-g module module-ntplwip">
<div class="pure-g module module-ntp">
<label class="pure-u-1 pure-u-lg-1-4">Time Zone</label>
<input class="pure-u-1 pure-u-lg-3-4" name="ntpTZ" type="text" tabindex="42" />
</div>
<div class="pure-g module module-ntplegacy">
<label class="pure-u-1 pure-u-lg-1-4">Time Zone</label>
<select class="pure-u-1 pure-u-lg-1-4" name="ntpOffset" tabindex="42"></select>
</div>
<div class="pure-g module module-ntplegacy">
<label class="pure-u-1 pure-u-lg-1-4">Enable DST</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="ntpDST" /></div>
</div>
<div class="pure-g module module-ntplegacy">
<label class="pure-u-1 pure-u-lg-1-4">DST Region</label>
<select class="pure-u-1 pure-u-lg-1-4" name="ntpRegion">
<option value="0">Europe</option>
<option value="1">USA</option>
</select>
<div class="pure-u-0 pure-u-lg-1-4"></div>
<div class="pure-u-1 pure-u-lg-3-4 hint">POSIX TZ variable, defaults to <code>UTC0</code><br/>For the list of possible options, <a rel="noopener" href="https://github.com/esp8266/Arduino/blob/master/cores/esp8266/TZ.h">see esp8266/Arduino's TZ.h (use the value inside of F("..."))</a>. For the complete documentation, <a rel="noopener" href="https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html">see libc tzset(3) manual page</a></div>
</div>
</fieldset>


Loading…
Cancel
Save