Skip to content

Commit

Permalink
ntp: clean-up
Browse files Browse the repository at this point in the history
resolve xoseperez#2327, xoseperez#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
  • Loading branch information
mcspr committed Sep 30, 2020
1 parent 63b6f46 commit aec13ce
Show file tree
Hide file tree
Showing 23 changed files with 22,555 additions and 22,548 deletions.
Binary file modified code/espurna/data/index.all.html.gz
Binary file not shown.
Binary file modified code/espurna/data/index.curtain.html.gz
Binary file not shown.
Binary file modified code/espurna/data/index.light.html.gz
Binary file not shown.
Binary file modified code/espurna/data/index.lightfox.html.gz
Binary file not shown.
Binary file modified code/espurna/data/index.rfbridge.html.gz
Binary file not shown.
Binary file modified code/espurna/data/index.rfm69.html.gz
Binary file not shown.
Binary file modified code/espurna/data/index.sensor.html.gz
Binary file not shown.
Binary file modified code/espurna/data/index.small.html.gz
Binary file not shown.
Binary file modified code/espurna/data/index.thermostat.html.gz
Binary file not shown.
97 changes: 81 additions & 16 deletions code/espurna/ntp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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());
}
}

Expand Down Expand Up @@ -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
Expand All @@ -358,6 +422,7 @@ void ntpSetup() {

// generic configuration, always handled
espurnaRegisterReload(_ntpConfigure);
_ntpConvertLegacyOffsets();
_ntpConfigure();

// make sure our logic does know about the actual server
Expand Down
10 changes: 10 additions & 0 deletions code/espurna/ntp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
6,190 changes: 3,092 additions & 3,098 deletions code/espurna/static/index.all.html.gz.h

Large diffs are not rendered by default.

4,910 changes: 2,453 additions & 2,457 deletions code/espurna/static/index.curtain.html.gz.h

Large diffs are not rendered by default.

4,210 changes: 2,103 additions & 2,107 deletions code/espurna/static/index.light.html.gz.h

Large diffs are not rendered by default.

4,865 changes: 2,430 additions & 2,435 deletions code/espurna/static/index.lightfox.html.gz.h

Large diffs are not rendered by default.

3,573 changes: 1,784 additions & 1,789 deletions code/espurna/static/index.rfbridge.html.gz.h

Large diffs are not rendered by default.

7,837 changes: 3,916 additions & 3,921 deletions code/espurna/static/index.rfm69.html.gz.h

Large diffs are not rendered by default.

4,921 changes: 2,458 additions & 2,463 deletions code/espurna/static/index.sensor.html.gz.h

Large diffs are not rendered by default.

4,811 changes: 2,403 additions & 2,408 deletions code/espurna/static/index.small.html.gz.h

Large diffs are not rendered by default.

3,545 changes: 1,770 additions & 1,775 deletions code/espurna/static/index.thermostat.html.gz.h

Large diffs are not rendered by default.

72 changes: 44 additions & 28 deletions code/espurna/ws.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -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&>();
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
29 changes: 0 additions & 29 deletions code/html/custom.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -2323,7 +2295,6 @@ function connectToCurrentURL() {
$(function() {

initMessages();
loadTimeZones();
createCheckboxes();
setInterval(function() { keepTime(); }, 1000);

Expand Down
33 changes: 11 additions & 22 deletions code/html/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1099,44 +1099,33 @@ <h2>Automatically upgrade the firmware (see <a href="https://bitbucket.org/xosep

<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">

<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">
<label class="pure-u-1 pure-u-lg-1-4">NTP Server</label>
<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>
Expand Down

0 comments on commit aec13ce

Please sign in to comment.