Browse Source

ntp: simplify tick callback, dont use broker

dev
Maxim Prokhorov 3 years ago
parent
commit
13cbc0310a
4 changed files with 50 additions and 51 deletions
  1. +36
    -34
      code/espurna/ntp.cpp
  2. +3
    -7
      code/espurna/ntp.h
  3. +1
    -1
      code/espurna/rpnrules.cpp
  4. +10
    -9
      code/espurna/scheduler.cpp

+ 36
- 34
code/espurna/ntp.cpp View File

@ -22,6 +22,8 @@ Copyright (C) 2019 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
#include <lwip/apps/sntp.h> #include <lwip/apps/sntp.h>
#include <TZ.h> #include <TZ.h>
#include <forward_list>
static_assert( static_assert(
(SNTP_SERVER_DNS == 1), (SNTP_SERVER_DNS == 1),
"lwip must be configured with SNTP_SERVER_DNS" "lwip must be configured with SNTP_SERVER_DNS"
@ -30,11 +32,8 @@ static_assert(
#include "config/buildtime.h" #include "config/buildtime.h"
#include "ntp_timelib.h" #include "ntp_timelib.h"
#include "broker.h"
#include "ws.h" #include "ws.h"
BrokerBind(NtpBroker);
// Arduino/esp8266 lwip2 custom functions that can be redefined // Arduino/esp8266 lwip2 custom functions that can be redefined
// Must return time in milliseconds, legacy settings are in seconds. // Must return time in milliseconds, legacy settings are in seconds.
@ -54,7 +53,6 @@ uint32_t sntp_update_delay_MS_rfc_not_less_than_15000() {
// We also must shim TimeLib functions until everything else is ported. // We also must shim TimeLib functions until everything else is ported.
// We can't sometimes avoid TimeLib as dependancy though, which would be really bad // We can't sometimes avoid TimeLib as dependancy though, which would be really bad
static Ticker _ntp_broker_timer;
static bool _ntp_synced = false; static bool _ntp_synced = false;
static time_t _ntp_last = 0; static time_t _ntp_last = 0;
@ -296,20 +294,20 @@ String ntpDateTime() {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#if BROKER_SUPPORT
using NtpTickCallbacks = std::forward_list<NtpTickCallback>;
NtpTickCallbacks _ntp_tick_callbacks;
void _ntpBrokerSchedule(int offset);
static Ticker _ntp_tick;
void _ntpBrokerCallback() {
void _ntpTickSchedule(int offset);
void _ntpTickCallback() {
if (!ntpSynced()) { if (!ntpSynced()) {
_ntpBrokerSchedule(60);
_ntpTickSchedule(60);
return; return;
} }
const auto ts = now(); const auto ts = now();
// current time and formatter string is in local TZ
tm local_tm; tm local_tm;
localtime_r(&ts, &local_tm); localtime_r(&ts, &local_tm);
@ -319,48 +317,48 @@ void _ntpBrokerCallback() {
static int last_hour = -1; static int last_hour = -1;
static int last_minute = -1; static int last_minute = -1;
String datetime;
if ((last_minute != now_minute) || (last_hour != now_hour)) {
datetime = ntpDateTime(&local_tm);
}
// notify subscribers about each tick interval (note that both can happen simultaneously) // notify subscribers about each tick interval (note that both can happen simultaneously)
if (last_hour != now_hour) { if (last_hour != now_hour) {
last_hour = now_hour; last_hour = now_hour;
NtpBroker::Publish(NtpTick::EveryHour, ts, datetime);
for (auto& callback : _ntp_tick_callbacks) {
callback(NtpTick::EveryHour);
}
} }
if (last_minute != now_minute) { if (last_minute != now_minute) {
last_minute = now_minute; last_minute = now_minute;
NtpBroker::Publish(NtpTick::EveryMinute, ts, datetime);
for (auto& callback : _ntp_tick_callbacks) {
callback(NtpTick::EveryMinute);
}
} }
// try to autocorrect each invocation // try to autocorrect each invocation
_ntpBrokerSchedule(60 - local_tm.tm_sec);
_ntpTickSchedule(60 - local_tm.tm_sec);
} }
// XXX: Nonos docs for some reason mention 100 micros as minimum time. Schedule next second in case this is 0
void _ntpBrokerSchedule(int offset) {
_ntp_broker_timer.once_scheduled(offset ?: 1, _ntpBrokerCallback);
// XXX: NONOS SDK docs for some reason mention 100 micros as minimum time. Schedule next second in case this is 0
void _ntpTickSchedule(int offset) {
static bool scheduled { false };
if (!scheduled) {
scheduled = true;
_ntp_tick.once_scheduled(offset ? offset : 1, []() {
scheduled = false;
_ntpTickCallback();
});
}
} }
#endif
void _ntpSetTimeOfDayCallback() { void _ntpSetTimeOfDayCallback() {
_ntp_synced = true; _ntp_synced = true;
_ntp_last = time(nullptr); _ntp_last = time(nullptr);
#if BROKER_SUPPORT
static bool once = true; static bool once = true;
if (once) { if (once) {
schedule_function(_ntpBrokerCallback);
schedule_function(_ntpTickCallback);
once = false; once = false;
} }
#endif
#if WEB_SUPPORT
wsPost(_ntpWebSocketOnData);
#endif
#if WEB_SUPPORT
wsPost(_ntpWebSocketOnData);
#endif
schedule_function(_ntpReport); schedule_function(_ntpReport);
} }
@ -385,13 +383,13 @@ void _ntpConvertLegacyOffsets() {
if (key == F("ntpTZ")) { if (key == F("ntpTZ")) {
save = false; save = false;
} else if (key == F("ntpOffset")) { } else if (key == F("ntpOffset")) {
offset = kv.value.read().toInt();
offset = settings::internal::convert<int>(kv.value.read());
found = true; found = true;
} else if (key == F("ntpDST")) { } else if (key == F("ntpDST")) {
dst = (1 == kv.value.read().toInt());
dst = settings::internal::convert<bool>(kv.value.read());
found = true; found = true;
} else if (key == F("ntpRegion")) { } else if (key == F("ntpRegion")) {
europe = (0 == kv.value.read().toInt());
europe = (0 == settings::internal::convert<int>(kv.value.read()));
found = true; found = true;
} }
}); });
@ -423,6 +421,10 @@ void _ntpConvertLegacyOffsets() {
delSetting("ntpRegion"); delSetting("ntpRegion");
} }
void ntpOnTick(NtpTickCallback callback) {
_ntp_tick_callbacks.push_front(callback);
}
void ntpSetup() { void ntpSetup() {
// Randomized in time to avoid clogging the server with simultaneous requests from multiple devices // Randomized in time to avoid clogging the server with simultaneous requests from multiple devices


+ 3
- 7
code/espurna/ntp.h View File

@ -10,13 +10,14 @@ Copyright (C) 2019-2021 by Maxim Prokhorov <prokhorov dot max at outlook dot com
#pragma once #pragma once
#include "espurna.h" #include "espurna.h"
#include "broker.h"
enum class NtpTick { enum class NtpTick {
EveryMinute, EveryMinute,
EveryHour EveryHour
}; };
using NtpTickCallback = void(*)(NtpTick);
struct NtpCalendarWeekday { struct NtpCalendarWeekday {
int local_wday; int local_wday;
int local_hour; int local_hour;
@ -34,14 +35,9 @@ struct NtpInfo {
time_t now; time_t now;
}; };
BrokerDeclare(NtpBroker, void(NtpTick, time_t, const String&));
void ntpOnTick(NtpTickCallback);
NtpInfo ntpInfo(); NtpInfo ntpInfo();
#if NTP_LEGACY_SUPPORT
time_t ntpLocal2UTC(time_t local);
#endif
String ntpDateTime(tm* timestruct); String ntpDateTime(tm* timestruct);
String ntpDateTime(time_t ts); String ntpDateTime(time_t ts);
String ntpDateTime(); String ntpDateTime();


+ 1
- 1
code/espurna/rpnrules.cpp View File

@ -1008,7 +1008,7 @@ void rpnSetup() {
#endif #endif
#if NTP_SUPPORT #if NTP_SUPPORT
NtpBroker::Register([](NtpTick tick, time_t, const String&) {
ntpOnTick([](NtpTick tick) {
switch (tick) { switch (tick) {
case NtpTick::EveryMinute: case NtpTick::EveryMinute:
_rpn_ntp_tick_minute = true; _rpn_ntp_tick_minute = true;


+ 10
- 9
code/espurna/scheduler.cpp View File

@ -368,16 +368,17 @@ void schSetup() {
#endif #endif
static bool restore_once = true; static bool restore_once = true;
NtpBroker::Register([](NtpTick tick, time_t, const String&) {
if (NtpTick::EveryMinute != tick) {
ntpOnTick([](NtpTick tick) {
switch (tick) {
case NtpTick::EveryHour:
return; return;
}
if (restore_once) {
auto targets = schedulableCount();
for (unsigned char i = 0; i < targets; i++) {
if (getSetting({"schRestore", i}, scheduler::build::restoreLast())) {
_schCheck(i, 0);
case NtpTick::EveryMinute:
if (restore_once) {
auto targets = schedulableCount();
for (size_t i = 0; i < targets; i++) {
if (getSetting({"schRestore", i}, scheduler::build::restoreLast())) {
_schCheck(i, 0);
}
} }
} }
restore_once = false; restore_once = false;


Loading…
Cancel
Save