Browse Source

Improved NTP support

pull/461/head
Xose Pérez 6 years ago
parent
commit
95968a97c3
11 changed files with 3533 additions and 3429 deletions
  1. +2
    -0
      code/espurna/config/general.h
  2. +1
    -1
      code/espurna/config/version.h
  3. BIN
      code/espurna/data/index.html.gz
  4. +41
    -24
      code/espurna/ntp.ino
  5. +3176
    -3172
      code/espurna/static/index.html.gz.h
  6. +58
    -69
      code/espurna/utils.ino
  7. +22
    -4
      code/espurna/ws.ino
  8. +179
    -119
      code/html/custom.css
  9. +21
    -0
      code/html/custom.js
  10. +32
    -39
      code/html/index.html
  11. +1
    -1
      code/platformio.ini

+ 2
- 0
code/espurna/config/general.h View File

@ -370,6 +370,7 @@ PROGMEM const char* const custom_reset_string[] = {
#define WS_BUFFER_SIZE 5 // Max number of secured websocket connections
#define WS_TIMEOUT 1800000 // Timeout for secured websocket
#define WS_UPDATE_INTERVAL 30000 // Update clients every 30 seconds
// -----------------------------------------------------------------------------
// API
@ -755,6 +756,7 @@ PROGMEM const char* const custom_reset_string[] = {
#define NTP_TIME_OFFSET 1 // Default timezone offset (GMT+1)
#define NTP_DAY_LIGHT true // Enable daylight time saving by default
#define NTP_UPDATE_INTERVAL 1800 // NTP check every 30 minutes
#define NTP_START_DELAY 1000 // Delay NTP start 1 second
// -----------------------------------------------------------------------------
// ALEXA


+ 1
- 1
code/espurna/config/version.h View File

@ -1,5 +1,5 @@
#define APP_NAME "ESPURNA"
#define APP_VERSION "1.12.2a"
#define APP_VERSION "1.12.2b"
#define APP_AUTHOR "xose.perez@gmail.com"
#define APP_WEBSITE "http://tinkerman.cat"
#define CFG_VERSION 3

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


+ 41
- 24
code/espurna/ntp.ino View File

@ -13,6 +13,7 @@ Copyright (C) 2016-2018 by Xose Pérez <xose dot perez at gmail dot com>
#include <WiFiClient.h>
#include <Ticker.h>
unsigned long _ntp_start = 0;
bool _ntp_update = false;
bool _ntp_configure = false;
@ -21,25 +22,21 @@ bool _ntp_configure = false;
// -----------------------------------------------------------------------------
void _ntpWebSocketOnSend(JsonObject& root) {
root["time"] = ntpDateTime();
root["ntpVisible"] = 1;
root["ntpStatus"] = ntpSynced();
root["ntpServer1"] = getSetting("ntpServer1", NTP_SERVER);
root["ntpServer2"] = getSetting("ntpServer2");
root["ntpServer3"] = getSetting("ntpServer3");
root["ntpStatus"] = (timeStatus() == timeSet);
root["ntpServer"] = getSetting("ntpServer", NTP_SERVER);
root["ntpOffset"] = getSetting("ntpOffset", NTP_TIME_OFFSET).toInt();
root["ntpDST"] = getSetting("ntpDST", NTP_DAY_LIGHT).toInt() == 1;
if (ntpSynced()) root["now"] = now();
}
void _ntpUpdate() {
_ntp_update = false;
void _ntpStart() {
#if WEB_SUPPORT
wsSend(_ntpWebSocketOnSend);
#endif
_ntp_start = 0;
DEBUG_MSG_P(PSTR("[NTP] Time: %s\n"), (char *) ntpDateTime().c_str());
NTP.begin(getSetting("ntpServer", NTP_SERVER));
NTP.setInterval(NTP_UPDATE_INTERVAL);
_ntpConfigure();
}
@ -50,24 +47,41 @@ void _ntpConfigure() {
int offset = getSetting("ntpOffset", NTP_TIME_OFFSET).toInt();
int sign = offset > 0 ? 1 : -1;
offset = abs(offset);
int tz_hours = sign * (offset / 60);
int tz_minutes = sign * (offset % 60);
if (NTP.getTimeZone() != tz_hours || NTP.getTimeZoneMinutes() != tz_minutes) {
NTP.setTimeZone(tz_hours, tz_minutes);
_ntp_update = true;
}
NTP.begin(
getSetting("ntpServer", 1, NTP_SERVER).c_str(),
sign * (offset / 60),
getSetting("ntpDST", NTP_DAY_LIGHT).toInt() == 1,
sign * (offset % 60)
);
bool daylight = getSetting("ntpDST", NTP_DAY_LIGHT).toInt() == 1;
if (NTP.getDayLight() != daylight) {
NTP.setDayLight(daylight);
_ntp_update = true;
}
if (hasSetting("ntpServer", 2)) NTP.setNtpServerName(getSetting("ntpServer", 2).c_str(), 1);
if (hasSetting("ntpServer", 3)) NTP.setNtpServerName(getSetting("ntpServer", 3).c_str(), 2);
NTP.setInterval(NTP_UPDATE_INTERVAL);
String server = getSetting("ntpServer", NTP_SERVER);
if (!NTP.getNtpServerName().equals(server)) {
NTP.setNtpServerName(server);
}
}
void _ntpUpdate() {
_ntp_update = false;
#if WEB_SUPPORT
wsSend(_ntpWebSocketOnSend);
#endif
_ntp_update = true;
DEBUG_MSG_P(PSTR("[NTP] Time: %s\n"), (char *) ntpDateTime().c_str());
}
void _ntpLoop() {
if (0 < _ntp_start && _ntp_start < millis()) _ntpStart();
if (_ntp_configure) _ntpConfigure();
if (_ntp_update) _ntpUpdate();
@ -84,6 +98,9 @@ void _ntpLoop() {
}
void _ntpBackwards() {
moveSetting("ntpServer1", "ntpServer");
delSetting("ntpServer2");
delSetting("ntpServer3");
int offset = getSetting("ntpOffset", NTP_TIME_OFFSET).toInt();
if (-30 < offset && offset < 30) {
offset *= 60;
@ -94,7 +111,7 @@ void _ntpBackwards() {
// -----------------------------------------------------------------------------
bool ntpSynced() {
return (timeStatus() == timeSet);
return (year() > 2017);
}
String ntpDateTime() {
@ -130,7 +147,7 @@ void ntpSetup() {
});
wifiRegister([](justwifi_messages_t code, char * parameter) {
if (code == MESSAGE_CONNECTED) _ntp_configure = true;
if (code == MESSAGE_CONNECTED) _ntp_start = millis() + NTP_START_DELAY;
});
#if WEB_SUPPORT


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


+ 58
- 69
code/espurna/utils.ino View File

@ -101,55 +101,7 @@ void heartbeat() {
unsigned long uptime_seconds = getUptime();
unsigned int free_heap = getFreeHeap();
// -------------------------------------------------------------------------
// MQTT
// -------------------------------------------------------------------------
#if MQTT_SUPPORT
#if (HEARTBEAT_REPORT_INTERVAL)
mqttSend(MQTT_TOPIC_INTERVAL, HEARTBEAT_INTERVAL / 1000);
#endif
#if (HEARTBEAT_REPORT_APP)
mqttSend(MQTT_TOPIC_APP, APP_NAME);
#endif
#if (HEARTBEAT_REPORT_VERSION)
mqttSend(MQTT_TOPIC_VERSION, APP_VERSION);
#endif
#if (HEARTBEAT_REPORT_HOSTNAME)
mqttSend(MQTT_TOPIC_HOSTNAME, getSetting("hostname").c_str());
#endif
#if (HEARTBEAT_REPORT_IP)
mqttSend(MQTT_TOPIC_IP, getIP().c_str());
#endif
#if (HEARTBEAT_REPORT_MAC)
mqttSend(MQTT_TOPIC_MAC, WiFi.macAddress().c_str());
#endif
#if (HEARTBEAT_REPORT_RSSI)
mqttSend(MQTT_TOPIC_RSSI, String(WiFi.RSSI()).c_str());
#endif
#if (HEARTBEAT_REPORT_UPTIME)
mqttSend(MQTT_TOPIC_UPTIME, String(uptime_seconds).c_str());
#endif
#if (HEARTBEAT_REPORT_DATETIME) & (NTP_SUPPORT)
mqttSend(MQTT_TOPIC_DATETIME, String(ntpDateTime()).c_str());
#endif
#if (HEARTBEAT_REPORT_FREEHEAP)
mqttSend(MQTT_TOPIC_FREEHEAP, String(free_heap).c_str());
#endif
#if (HEARTBEAT_REPORT_RELAY)
relayMQTT();
#endif
#if (LIGHT_PROVIDER != LIGHT_PROVIDER_NONE) & (HEARTBEAT_REPORT_LIGHT)
lightMQTT();
#endif
#if (HEARTBEAT_REPORT_VCC)
#if ADC_VCC_ENABLED
mqttSend(MQTT_TOPIC_VCC, String(ESP.getVcc()).c_str());
#endif
#endif
#if (HEARTBEAT_REPORT_STATUS)
mqttSend(MQTT_TOPIC_STATUS, MQTT_STATUS_ONLINE, true);
#endif
bool serial = !mqttConnected();
#else
bool serial = true;
@ -165,9 +117,62 @@ void heartbeat() {
#if ADC_VCC_ENABLED
DEBUG_MSG_P(PSTR("[MAIN] Power: %lu mV\n"), ESP.getVcc());
#endif
#if NTP_SUPPORT
if (ntpSynced()) DEBUG_MSG_P(PSTR("[MAIN] Time: %s\n"), (char *) ntpDateTime().c_str());
#endif
}
#if NTP_SUPPORT
DEBUG_MSG_P(PSTR("[MAIN] Time: %s\n"), (char *) ntpDateTime().c_str());
// -------------------------------------------------------------------------
// MQTT
// -------------------------------------------------------------------------
#if MQTT_SUPPORT
if (!serial) {
#if (HEARTBEAT_REPORT_INTERVAL)
mqttSend(MQTT_TOPIC_INTERVAL, HEARTBEAT_INTERVAL / 1000);
#endif
#if (HEARTBEAT_REPORT_APP)
mqttSend(MQTT_TOPIC_APP, APP_NAME);
#endif
#if (HEARTBEAT_REPORT_VERSION)
mqttSend(MQTT_TOPIC_VERSION, APP_VERSION);
#endif
#if (HEARTBEAT_REPORT_HOSTNAME)
mqttSend(MQTT_TOPIC_HOSTNAME, getSetting("hostname").c_str());
#endif
#if (HEARTBEAT_REPORT_IP)
mqttSend(MQTT_TOPIC_IP, getIP().c_str());
#endif
#if (HEARTBEAT_REPORT_MAC)
mqttSend(MQTT_TOPIC_MAC, WiFi.macAddress().c_str());
#endif
#if (HEARTBEAT_REPORT_RSSI)
mqttSend(MQTT_TOPIC_RSSI, String(WiFi.RSSI()).c_str());
#endif
#if (HEARTBEAT_REPORT_UPTIME)
mqttSend(MQTT_TOPIC_UPTIME, String(uptime_seconds).c_str());
#endif
#if (HEARTBEAT_REPORT_DATETIME) && (NTP_SUPPORT)
if (ntpSynced()) mqttSend(MQTT_TOPIC_DATETIME, ntpDateTime().c_str());
#endif
#if (HEARTBEAT_REPORT_FREEHEAP)
mqttSend(MQTT_TOPIC_FREEHEAP, String(free_heap).c_str());
#endif
#if (HEARTBEAT_REPORT_RELAY)
relayMQTT();
#endif
#if (LIGHT_PROVIDER != LIGHT_PROVIDER_NONE) & (HEARTBEAT_REPORT_LIGHT)
lightMQTT();
#endif
#if (HEARTBEAT_REPORT_VCC)
#if ADC_VCC_ENABLED
mqttSend(MQTT_TOPIC_VCC, String(ESP.getVcc()).c_str());
#endif
#endif
#if (HEARTBEAT_REPORT_STATUS)
mqttSend(MQTT_TOPIC_STATUS, MQTT_STATUS_ONLINE, true);
#endif
}
#endif
// -------------------------------------------------------------------------
@ -183,24 +188,6 @@ void heartbeat() {
#endif
#endif
// -------------------------------------------------------------------------
// WebSockets
// -------------------------------------------------------------------------
#if WEB_SUPPORT
#if NTP_SUPPORT
{
char buffer[200];
snprintf_P(
buffer,
sizeof(buffer) - 1,
PSTR("{\"time\": \"%s\", \"uptime\": %lu, \"heap\": %lu}"),
ntpDateTime().c_str(), uptime_seconds, free_heap
);
wsSend(buffer);
}
#endif
#endif
}
#endif /// HEARTBEAT_ENABLED
@ -417,7 +404,9 @@ void info() {
DEBUG_MSG_P(PSTR("[INIT] Power saving delay value: %lu ms\n"), _loopDelay);
if (!systemCheck()) DEBUG_MSG_P(PSTR("\n[INIT] Device is in SAFE MODE\n"));
#if SYSTEM_CHECK_ENABLED
if (!systemCheck()) DEBUG_MSG_P(PSTR("\n[INIT] Device is in SAFE MODE\n"));
#endif
DEBUG_MSG_P(PSTR("\n"));


+ 22
- 4
code/espurna/ws.ino View File

@ -200,6 +200,16 @@ 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["distance"] = wifiDistance(WiFi.RSSI());
#if NTP_SUPPORT
if (ntpSynced()) root["now"] = now();
#endif
}
void _wsOnStart(JsonObject& root) {
#if USE_PASSWORD && WEB_FORCE_PASS_CHANGE
@ -234,17 +244,15 @@ void _wsOnStart(JsonObject& root) {
root["mac"] = WiFi.macAddress();
root["bssid"] = String(bssid_str);
root["channel"] = WiFi.channel();
root["rssi"] = WiFi.RSSI();
root["distance"] = wifiDistance(WiFi.RSSI());
root["device"] = DEVICE;
root["hostname"] = getSetting("hostname");
root["network"] = getNetwork();
root["deviceip"] = getIP();
root["uptime"] = getUptime();
root["heap"] = getFreeHeap();
root["sketch_size"] = ESP.getSketchSize();
root["free_size"] = ESP.getFreeSketchSpace();
_wsUpdate(root);
root["btnDelay"] = getSetting("btnDelay", BUTTON_DBLCLICK_DELAY).toInt();
root["webPort"] = getSetting("webPort", WEB_PORT).toInt();
root["tmpUnits"] = getSetting("tmpUnits", SENSOR_TEMPERATURE_UNITS).toInt();
@ -292,6 +300,15 @@ void _wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTy
}
void _wsLoop() {
static unsigned long last = 0;
if (!wsConnected()) return;
if (millis() - last > WS_UPDATE_INTERVAL) {
last = millis();
wsSend(_wsUpdate);
}
}
// -----------------------------------------------------------------------------
// Piblic API
// -----------------------------------------------------------------------------
@ -371,6 +388,7 @@ void wsSetup() {
#endif
wsOnSendRegister(_wsOnStart);
wsOnAfterParseRegister(wsConfigure);
espurnaRegisterLoop(_wsLoop);
}
#endif // WEB_SUPPORT

+ 179
- 119
code/html/custom.css View File

@ -1,145 +1,99 @@
/* -----------------------------------------------------------------------------
General
-------------------------------------------------------------------------- */
#menu .pure-menu-heading {
font-size: 100%;
padding: .5em .5em;
}
.header h2 {
font-size: 1em;
}
.panel {
display: none;
}
.footer {
padding: 10px;
font-size: 80%;
color: #999;
}
#menu .footer a {
text-decoration: none;
padding: 0px;
}
.content {
margin: 0px;
}
.page {
margin-top: 10px;
}
.pure-button {
color: white;
padding: 8px 8px;
border-radius: 4px;
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
}
.main-buttons {
margin: 50px auto;
text-align: center;
}
.main-buttons button {
width: 100px;
margin: 5px auto;
}
.button-update-password,
.button-update {
background: #1f8dd6;
}
.button-reboot,
.button-reconnect,
.button-ha-del,
.button-rfb-forget {
background: rgb(202, 60, 60);
}
.button-upgrade {
background: rgb(202, 60, 60);
margin-left: 5px;
}
.button-upgrade-browse,
.button-ha-add,
.button-apikey {
background: rgb(0, 202, 0);
margin-left: 5px;
}
.button-add-network,
.button-add-schedule,
.button-rfb-learn {
background: rgb(28, 184, 65);
}
.button-del-network,
.button-del-schedule {
background: rgb(202, 60, 60);
}
.pure-button {
letter-spacing: 0;
}
.button-more-network,
.button-more-schedule,
.button-wifi-scan,
.button-rfb-send {
background: rgb(223, 117, 20);
}
.button-settings-backup,
.button-settings-restore {
background: rgb(0, 202, 0);
margin-bottom: 10px;
}
.pure-g {
margin-bottom: 0px;
}
.pure-form legend {
font-weight: bold;
letter-spacing: 0;
margin: 10px 0 1em 0;
}
.l-box {
padding-right: 1px;
.pure-form .pure-g > label {
margin: .4em 0 .2em;
}
.pure-form input {
margin-bottom: 10px;
}
.pure-form input[type=text][disabled] {
color: #777777;
}
.header h2 {
font-size: 1em;
}
.panel {
display: none;
}
.content {
margin: 0px;
}
.page {
margin-top: 10px;
}
div.hint {
font-size: 80%;
color: #ccc;
margin: -10px 0 10px 0;
}
.break {
margin-top: 5px;
}
#networks .pure-g,
#schedules .pure-g {
padding: 10px 0 10px 0;
margin-bottom: 10px;
border-bottom: 1px solid #eee;
}
#networks .more {
display: none;
}
legend.module,
.module {
display: none;
}
.template {
display: none;
}
input[name=upgrade] {
display: none;
}
#upgrade-progress {
display: none;
.panel.block {
display: block;
}
select {
width: 100%;
height: 20px;
margin-top: 10px;
margin-bottom: 10px;
}
hr {
display: block;
height: 1px;
border: 0;
border-top: 1px solid #eee;
margin: 1em 0;
padding: 0;
}
input.center {
margin-bottom: 0px;
}
div.center {
margin: .5em 0 1em;
}
.webmode {
display: none;
}
#credentials {
font-size: 200%;
text-align: center;
@ -151,6 +105,7 @@ div.center {
margin-top: -50px;
margin-left: -200px;
}
div.state {
border-top: 1px solid #eee;
margin-top: 20px;
@ -165,65 +120,170 @@ div.state {
font-size: 80%;
font-weight: bold;
}
.right {
text-align: right;
}
/* -----------------------------------------------------------------------------
Buttons
-------------------------------------------------------------------------- */
.pure-button {
color: white;
padding: 8px 8px;
border-radius: 4px;
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
letter-spacing: 0;
margin-bottom: 10px;
}
.main-buttons {
margin: 20px auto;
text-align: center;
}
.main-buttons button {
width: 100px;
}
.button-reboot,
.button-reconnect,
.button-ha-del,
.button-rfb-forget,
.button-del-network,
.button-del-schedule,
.button-upgrade {
background: rgb(192, 0, 0); /* redish */
}
.button-update,
.button-update-password,
.button-add-network,
.button-add-schedule,
.button-rfb-learn,
.button-upgrade-browse,
.button-ha-add,
.button-settings-backup,
.button-settings-restore,
.button-apikey {
background: rgb(0, 192, 0); /* green */
}
.button-more-network,
.button-more-schedule,
.button-wifi-scan,
.button-rfb-send {
background: rgb(255, 128, 0); /* orange */
}
.button-upgrade-browse,
.button-ha-add,
.button-apikey,
.button-upgrade {
margin-left: 5px;
}
/* -----------------------------------------------------------------------------
Sliders
-------------------------------------------------------------------------- */
input.slider {
margin-top: 10px;
}
span.slider {
font-size: 70%;
margin-left: 10px;
margin-top: 7px;
letter-spacing: 0;
}
/* -----------------------------------------------------------------------------
Loading
-------------------------------------------------------------------------- */
div.loading {
background-image: url('images/loading.gif');
width: 20px;
height: 20px;
margin: 8px 0 0 10px;
display: none;
}
/* -----------------------------------------------------------------------------
Menu
-------------------------------------------------------------------------- */
#menu span.small {
font-size: 60%;
padding-left: 9px;
}
#menu div.footer {
padding: 10px;
font-size: 80%;
color: #999;
}
#menu div.footer a {
text-decoration: none;
padding: 0px;
}
/* -----------------------------------------------------------------------------
RF Bridge panel
-------------------------------------------------------------------------- */
#panel-rfb fieldset {
margin: 10px 2px;
padding: 20px;
}
#panel-rfb input {
margin-right: 5px;
}
#panel-rfb label {
padding-top: 5px;
}
#panel-rfb input {
text-align: center;
}
/* -----------------------------------------------------------------------------
Admin panel
-------------------------------------------------------------------------- */
#upgrade-progress {
display: none;
width: 100%;
height: 20px;
margin-top: 10px;
}
#uploader,
#downloader {
display: none;
}
.panel.block {
display: block;
}
select {
width: 100%;
/* -----------------------------------------------------------------------------
Wifi panel
-------------------------------------------------------------------------- */
#networks .pure-g,
#schedules .pure-g {
padding: 10px 0 10px 0;
margin-bottom: 10px;
border-bottom: 1px solid #eee;
}
hr {
display: block;
height: 1px;
border: 0;
border-top: 1px solid #eee;
margin: 1em 0;
padding: 0;
#networks .more {
display: none;
}
#scanResult {
margin-top: 10px;
font-size: 60%;
color: #888;
font-family: 'Courier New', monospace;
}
div.loading {
background-image: url('images/loading.gif');
width: 20px;
height: 20px;
margin: 8px 0 0 10px;
display: none;
}
#menu span.small {
font-size: 60%;
padding-left: 9px;
}

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

@ -13,6 +13,9 @@ var numReload = 0;
var useWhite = false;
var manifest;
var now = 0;
var ago = 0;
// -----------------------------------------------------------------------------
// Messages
// -----------------------------------------------------------------------------
@ -71,6 +74,17 @@ function magnitudeError(error) {
// Utils
// -----------------------------------------------------------------------------
function keepTime() {
if (now === 0) return;
var date = new Date(now * 1000);
var text = date.toISOString().substring(0, 19).replace("T", " ");
$("input[name='now']").val(text);
$("span[name='now']").html(text);
$("span[name='ago']").html(ago);
now++;
ago++;
}
// http://www.the-art-of-web.com/javascript/validate-password/
function checkPassword(str) {
// at least one lowercase and one uppercase letter or number
@ -1065,6 +1079,12 @@ function processData(data) {
return;
}
if (key === "now") {
now = data[key];
ago = 0;
return;
}
// Pre-process
if (key === "network") {
data.network = data.network.toUpperCase();
@ -1198,6 +1218,7 @@ $(function() {
initMessages();
loadTimeZones();
setInterval(function() { keepTime(); }, 1000);
$("#menuLink").on("click", toggleMenu);
$(".pure-menu-link").on("click", showPanel);


+ 32
- 39
code/html/index.html View File

@ -51,7 +51,8 @@
<input name="adminPass" class="pure-u-1 pure-u-lg-3-4" type="password" tabindex="2" autocomplete="false" />
</div>
<button class="pure-button button-update-password">Update</button>
<div class="pure-u-0 pure-u-lg-1-4 more"></div>
<button class="pure-button button-update-password" type="button">Update</button>
</fieldset>
</div>
@ -213,7 +214,7 @@
<div class="pure-u-11-24 pure-u-lg-17-24"><span class="right" name="app_build"></span></div>
<div class="pure-u-1-2 pure-u-lg-1-4">Current time</div>
<div class="pure-u-11-24 pure-u-lg-17-24"><span class="right" name="time"></span></div>
<div class="pure-u-11-24 pure-u-lg-17-24"><span class="right" name="now"></span></div>
<div class="pure-u-1-2 pure-u-lg-1-4">Uptime</div>
<div class="pure-u-11-24 pure-u-lg-17-24"><span class="right" name="uptime"></span></div>
@ -233,6 +234,8 @@
<div class="pure-u-1-2 pure-u-lg-1-4">NTP Status</div>
<div class="pure-u-11-24 pure-u-lg-17-24"><span class="right" name="ntpStatus">NOT AVAILABLE</span></div>
<div class="pure-u-1-2 pure-u-lg-1-4">Last update</div>
<div class="pure-u-11-24 pure-u-lg-17-24"><span class="right" name="ago">?</span><span> seconds ago</span></div>
</div>
@ -302,12 +305,12 @@
</div>
<div class="pure-g module module-alexa">
<div class="pure-u-1 pure-u-lg-1-4"><label>Alexa integration</label></div>
<label class="pure-u-1 pure-u-lg-1-4">Alexa integration</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="alexaEnabled" tabindex="13" /></div>
</div>
<div class="pure-g module module-ha">
<div class="pure-u-1 pure-u-lg-1-4"><label>Home Assistant</label></div>
<label class="pure-u-1 pure-u-lg-1-4">Home Assistant</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="haEnabled" tabindex="14" /></div>
<div class="pure-u-0 pure-u-lg-1-2"></div>
<div class="pure-u-0 pure-u-lg-1-4"></div>
@ -370,7 +373,7 @@
<fieldset>
<div class="pure-g">
<div class="pure-u-1 pure-u-lg-1-4"><label>Use colorpicker</label></div>
<label class="pure-u-1 pure-u-lg-1-4">Use colorpicker</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="useColor" action="reload" tabindex="8" /></div>
<div class="pure-u-0 pure-u-lg-1-2"></div>
<div class="pure-u-0 pure-u-lg-1-4"></div>
@ -378,7 +381,7 @@
</div>
<div class="pure-g">
<div class="pure-u-1 pure-u-lg-1-4"><label>Use RGB picker</label></div>
<label class="pure-u-1 pure-u-lg-1-4">Use RGB picker</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="useRGB" action="reload" tabindex="11" /></div>
<div class="pure-u-0 pure-u-lg-1-2"></div>
<div class="pure-u-0 pure-u-lg-1-4"></div>
@ -386,7 +389,7 @@
</div>
<div class="pure-g">
<div class="pure-u-1 pure-u-lg-1-4"><label>Use white channel</label></div>
<label class="pure-u-1 pure-u-lg-1-4">Use white channel</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="useWhite" action="reload" tabindex="9" /></div>
<div class="pure-u-0 pure-u-lg-1-2"></div>
<div class="pure-u-0 pure-u-lg-1-4"></div>
@ -394,7 +397,7 @@
</div>
<div class="pure-g">
<div class="pure-u-1 pure-u-lg-1-4"><label>Use gamma correction</label></div>
<label class="pure-u-1 pure-u-lg-1-4">Use gamma correction</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="useGamma" tabindex="10" /></div>
<div class="pure-u-0 pure-u-lg-1-2"></div>
<div class="pure-u-0 pure-u-lg-1-4"></div>
@ -402,7 +405,7 @@
</div>
<div class="pure-g">
<div class="pure-u-1 pure-u-lg-1-4"><label>Use CSS style</label></div>
<label class="pure-u-1 pure-u-lg-1-4">Use CSS style</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="useCSS" tabindex="11" /></div>
<div class="pure-u-0 pure-u-lg-1-2"></div>
<div class="pure-u-0 pure-u-lg-1-4"></div>
@ -410,7 +413,7 @@
</div>
<div class="pure-g">
<div class="pure-u-1 pure-u-lg-1-4"><label>Color transitions</label></div>
<label class="pure-u-1 pure-u-lg-1-4">Color transitions</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="useTransitions" tabindex="12" /></div>
<div class="pure-u-0 pure-u-lg-1-2"></div>
<div class="pure-u-0 pure-u-lg-1-4"></div>
@ -465,12 +468,12 @@
</div>
<div class="pure-g">
<div class="pure-u-1 pure-u-lg-1-4"><label>Enable HTTP API</label></div>
<label class="pure-u-1 pure-u-lg-1-4">Enable HTTP API</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="apiEnabled" /></div>
</div>
<div class="pure-g">
<div class="pure-u-1 pure-u-lg-1-4"><label>Real time API</label></div>
<label class="pure-u-1 pure-u-lg-1-4">Real time API</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="apiRealTime" /></div>
<div class="pure-u-0 pure-u-lg-1-2"></div>
<div class="pure-u-0 pure-u-lg-1-4"></div>
@ -493,7 +496,7 @@
</div>
<div class="pure-g module module-telnet">
<div class="pure-u-1 pure-u-lg-1-4"><label>Enable TELNET</label></div>
<label class="pure-u-1 pure-u-lg-1-4">Enable TELNET</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="telnetSTA" /></div>
<div class="pure-u-0 pure-u-lg-1-2"></div>
<div class="pure-u-0 pure-u-lg-1-4"></div>
@ -502,7 +505,7 @@
<div class="pure-g module module-nofuss">
<div class="pure-u-1 pure-u-lg-1-4"><label>Automatic remote updates (NoFUSS)</label></div>
<label class="pure-u-1 pure-u-lg-1-4">Automatic remote updates (NoFUSS)</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="nofussEnabled" /></div>
</div>
@ -516,7 +519,7 @@
<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Settings</label>
<div class="pure-u-1-2 pure-u-lg-1-8"><button class="pure-button button-settings-backup pure-u-23-24">Backup</button></div>
<div class="pure-u-1-2 pure-u-lg-1-8"><button class="pure-button button-settings-restore pure-u-23-24">Restore</button></div>
<div class="pure-u-1-2 pure-u-lg-1-8"><button class="pure-button button-settings-restore pure-u-1">Restore</button></div>
</div>
<div class="pure-g">
@ -547,7 +550,7 @@
<legend>General</legend>
<div class="pure-g">
<div class="pure-u-1 pure-u-lg-1-4"><label>Scan networks</label></div>
<label class="pure-u-1 pure-u-lg-1-4">Scan networks</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="wifiScan" tabindex="1" /></div>
<div class="pure-u-0 pure-u-lg-1-2"></div>
<div class="pure-u-0 pure-u-lg-1-4"></div>
@ -610,7 +613,7 @@
<fieldset>
<div class="pure-g">
<div class="pure-u-1 pure-u-lg-1-4"><label>Enable MQTT</label></div>
<label class="pure-u-1 pure-u-lg-1-4">Enable MQTT</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="mqttEnabled" tabindex="30" /></div>
</div>
@ -697,7 +700,7 @@
</div>
<div class="pure-g">
<div class="pure-u-1 pure-u-lg-1-4"><label>Use JSON payload</label></div>
<label class="pure-u-1 pure-u-lg-1-4">Use JSON payload</label>
<div class="pure-u-1 pure-u-lg-3-4"><input type="checkbox" name="mqttUseJson" tabindex="32" /></div>
<div class="pure-u-1 pure-u-lg-1-4"></div>
<div class="pure-u-1 pure-u-lg-3-4 hint">
@ -725,32 +728,22 @@
<fieldset>
<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Current Time</label>
<input class="pure-u-1 pure-u-lg-3-4" name="time" type="text" readonly />
<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 />
</div>
<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">NTP Server #0</label>
<input class="pure-u-1 pure-u-lg-3-4" name="ntpServer1" type="text" tabindex="41" />
</div>
<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">NTP Server #1</label>
<input class="pure-u-1 pure-u-lg-3-4" name="ntpServer2" type="text" tabindex="42" />
</div>
<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">NTP Server #2</label>
<input class="pure-u-1 pure-u-lg-3-4" name="ntpServer3" type="text" tabindex="43" />
<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">
<label class="pure-u-1 pure-u-lg-1-4">Time offset</label>
<select class="pure-u-1 pure-u-lg-1-4" name="ntpOffset" tabindex="44"></select>
<select class="pure-u-1 pure-u-lg-1-4" name="ntpOffset" tabindex="42"></select>
</div>
<div class="pure-g">
<div class="pure-u-1 pure-u-lg-1-4"><label>Enable DST</label></div>
<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>
@ -775,7 +768,7 @@
<legend>General</legend>
<div class="pure-g">
<div class="pure-u-1 pure-u-lg-1-4"><label>Enable Domoticz</label></div>
<label class="pure-u-1 pure-u-lg-1-4">Enable Domoticz</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="dczEnabled" tabindex="30" /></div>
</div>
@ -820,7 +813,7 @@
<legend>General</legend>
<div class="pure-g">
<div class="pure-u-1 pure-u-lg-1-4"><label>Enable Thingspeak</label></div>
<label class="pure-u-1 pure-u-lg-1-4">Enable Thingspeak</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="tspkEnabled" tabindex="30" /></div>
</div>
@ -858,7 +851,7 @@
<fieldset>
<div class="pure-g">
<div class="pure-u-1 pure-u-lg-1-4"><label>Enable InfluxDB</label></div>
<label class="pure-u-1 pure-u-lg-1-4">Enable InfluxDB</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="idbEnabled" tabindex="40" /></div>
</div>
@ -983,7 +976,7 @@
</div>
<div class="pure-g module module-hlw module-emon">
<div class="pure-u-1 pure-u-lg-1-4"><label>Reset calibration</label></div>
<label class="pure-u-1 pure-u-lg-1-4">Reset calibration</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="pwrResetCalibration" tabindex="55" /></div>
<div class="pure-u-0 pure-u-lg-1-2"></div>
<div class="pure-u-0 pure-u-lg-1-4"></div>
@ -1124,7 +1117,7 @@
<div id="relayTemplate" class="template">
<div class="pure-g">
<div class="pure-u-1 pure-u-lg-1-4"><label>Switch #<span class="id"></span></label></div>
<label class="pure-u-1 pure-u-lg-1-4">Switch #<span class="id"></span></label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" class="relayStatus pure-u-1 pure-u-lg-1-4" data="0" /></div>
</div>
</div>


+ 1
- 1
code/platformio.ini View File

@ -17,7 +17,7 @@ lib_deps =
https://github.com/marvinroger/async-mqtt-client#v0.8.1
PubSubClient
Embedis
https://github.com/gmag11/NtpClient.git#2.5.0
https://github.com/xoseperez/NtpClient.git#f37fbba
OneWire
Brzo I2C
https://github.com/krosk93/espsoftwareserial#a770677


Loading…
Cancel
Save