diff --git a/include/Clock.h b/include/Clock.h index 3f361122..bab9267f 100644 --- a/include/Clock.h +++ b/include/Clock.h @@ -4,6 +4,7 @@ #include "Utils/PrintMessage.h" #include "TZ.h" +#include "sntp.h" class Clock { const char* MODULE = "Clock"; @@ -11,6 +12,27 @@ class Clock { public: Clock() : _timezone{0}, _hasSynced{false}, _configured{false} {} + void loop() { + unsigned long passed = millis_since(_uptime); + if (passed < ONE_SECOND_ms) { + return; + } + _uptime += passed; + + // world time + time_t now = getSystemTime(); + time_t estimated = _epoch + (passed / ONE_SECOND_ms); + double drift = difftime(now, estimated); + if (drift > 1) { + // Обработать ситуации c дрифтом времени на значительные величины + } + // TODO сохранять время на флеше + + _epoch = now; + + breakEpochToTime(_epoch, _time); + } + bool hasSync() { if (!_hasSynced) { startSync(); @@ -19,18 +41,26 @@ class Clock { } void setNtpPool(String ntp) { - _ntp = ntp; + if (!_ntp.equals(ntp)) { + _ntp = ntp; + _configured = false; + } } void setTimezone(int timezone) { - _timezone = timezone; + if (_timezone != timezone) { + _timezone = timezone; + _configured = false; + } } void startSync() { if (!_configured) { - pm.info("sync to: " + _ntp + " time zone: " + String(_timezone)); + pm.info("sync to: " + _ntp + " timezone: " + String(_timezone)); setupSntp(); _configured = true; + // лучше не ждать, проверим в следующий раз + return; } _hasSynced = hasTimeSynced(); if (_hasSynced) { @@ -41,42 +71,70 @@ class Clock { } void setupSntp() { - int tzs = getOffsetInSeconds(_timezone); - int tzh = tzs / 3600; - tzs -= tzh * 3600; - int tzm = tzs / 60; - tzs -= tzm * 60; - - char tzstr[64]; - snprintf(tzstr, sizeof tzstr, "ESPUSER<%+d:%02d:%02d>", tzh, tzm, tzs); - pm.info(String(tzstr)); - configTime(tzstr, _ntp.c_str()); - } - // #ifdef ESP32 - // uint8_t i = 0; - // struct tm timeinfo; - // while (!getLocalTime(&timeinfo) && i <= 4) { - // Serial.print("."); - // i++; - // delay(1000); - // } - // #endifr - - bool hasTimeSynced() { - return getSystemTime() > 30000; + sntp_setservername(0, _ntp.c_str()); + sntp_setservername(1, "ru.pool.ntp.org"); + sntp_setservername(2, "pool.ntp.org"); + sntp_stop(); + sntp_set_timezone(0); // UTC time + sntp_init(); } - time_t getSystemTime() { + bool hasTimeSynced() const { + return _epoch > MIN_DATETIME; + } + + time_t getSystemTime() const { timeval tv{0, 0}; - timezone tz = timezone{getOffsetInMinutes(_timezone), 0}; + timezone tz = timezone{0, 0}; + time_t epoch = 0; if (gettimeofday(&tv, &tz) != -1) { - _epoch = tv.tv_sec; + epoch = tv.tv_sec; } - return _epoch; + return epoch; + } + + const String getTimeUnix() { + return String(_epoch); + } + + /* + * Локальное время "дд.ММ.гг" + */ + const String getDateDigitalFormated() { + char buf[16]; + sprintf(buf, "%02d.%02d.%02d", _time.day_of_month, _time.month, _time.year); + return String(buf); + } + + /* + * Локальное время "чч:мм:cc" + */ + const String getTime() { + char buf[16]; + sprintf(buf, "%02d:%02d:%02d", _time.hour, _time.minute, _time.second); + return String(buf); + } + + /* + * Локальное время "чч:мм" + */ + const String getTimeWOsec() { + char buf[16]; + sprintf(buf, "%02d:%02d", _time.hour, _time.minute); + return String(buf); + } + + /* + * Время с момента запуска "чч:мм" далее "дд чч:мм" + */ + const String getUptime() { + return prettyMillis(_uptime); } private: - time_t _epoch; + Time_t _time; + unsigned long _uptime; + unsigned long _epoch; int _timezone; String _ntp; bool _hasSynced; diff --git a/include/CommonTypes.h b/include/CommonTypes.h index 1050bcc9..a5783b30 100644 --- a/include/CommonTypes.h +++ b/include/CommonTypes.h @@ -1,5 +1,18 @@ #pragma once +struct Time_t { + uint8_t second; + uint8_t minute; + uint8_t hour; + uint8_t day_of_week; // sunday is day 1 + uint8_t day_of_month; + uint8_t month; + uint16_t day_of_year; + uint16_t year; + unsigned long days; + unsigned long valid; +}; + enum TimerTask_t { WIFI_SCAN, WIFI_MQTT_CONNECTION_CHECK, SENSORS, diff --git a/include/Global.h b/include/Global.h index 87040f0c..c646f943 100644 --- a/include/Global.h +++ b/include/Global.h @@ -14,7 +14,6 @@ #include "Bus/BusScanner.h" #include "Errors.h" #include "GyverFilters.h" -#include "UptimeInterval.h" #include "Upgrade.h" #include "Clock.h" @@ -46,7 +45,7 @@ extern AsyncWebSocket ws; //extern AsyncEventSource events; #endif -extern Clock* rtc; +extern Clock* timeNow; extern TickerScheduler ts; diff --git a/include/UptimeInterval.h b/include/UptimeInterval.h deleted file mode 100644 index 1e90ec47..00000000 --- a/include/UptimeInterval.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include - -class UptimeInterval { - public: - UptimeInterval(unsigned long interval, boolean postpone = true) : _next{0}, _interval{interval} { - reset(postpone); - } - - boolean check() { - if (_next <= get()) { - _next += _interval; - return true; - } - return false; - } - - void reset(bool postpone = true) { - _next = (postpone ? _uptime_seconds + _interval : _uptime_seconds); - } - - static unsigned long get() { - unsigned long _uptime_seconds = millis() / 1000; - return _uptime_seconds; - }; - - static unsigned long _uptime_seconds; - - private: - unsigned long _next, _interval; -}; diff --git a/include/Utils/PrintMessage.h b/include/Utils/PrintMessage.h index ec3ab5bb..04514ee5 100644 --- a/include/Utils/PrintMessage.h +++ b/include/Utils/PrintMessage.h @@ -24,7 +24,7 @@ class PrintMessage { private: void print(const ErrorLevel_t level, const String& str) { - Serial.printf("%s [%s] [%s] %s\n", prettyMillis().c_str(), getErrorLevelStr(level).c_str(), _module, str.c_str()); + Serial.printf("%s [%s] [%s] %s\n", prettyMillis(millis()).c_str(), getErrorLevelStr(level).c_str(), _module, str.c_str()); } private: diff --git a/include/Utils/TimeUtils.h b/include/Utils/TimeUtils.h index 7cf508a5..b65e97f5 100644 --- a/include/Utils/TimeUtils.h +++ b/include/Utils/TimeUtils.h @@ -1,37 +1,15 @@ #pragma once -#ifdef ESP8266 -#include -#endif + #include -/* -* Получение текущего времени -*/ -String getTime(); +#include "CommonTypes.h" -/* -* Получаем время в формате linux gmt -*/ -String getTimeUnix(); - -/* -* Параметр время -* @result результат -*/ -boolean getUnixTimeStr(String&); - -String getTimeWOsec(); - -/* -* Получение даты -*/ -String getDate(); - -String getDateDigitalFormated(); - -int timeToMin(String Time); - -const String prettyMillis(unsigned long time_ms = millis()); +#define ONE_MINUTE_s 60 +#define ONE_HOUR_m 60 +#define ONE_HOUR_s 60 * ONE_MINUTE_s +#define LEAP_YEAR(Y) (((1970 + Y) > 0) && !((1970 + Y) % 4) && (((1970 + Y) % 100) || !((1970 + Y) % 400))) +#define MIN_DATETIME 1575158400 +#define ONE_SECOND_ms 1000 /* * Время (мс) прошедщее с @since @@ -43,6 +21,31 @@ unsigned long millis_since(unsigned long sinse); */ unsigned long millis_passed(unsigned long start, unsigned long finish); +/* +* Форматиронное время интервала (мс) +* "чч:мм:cc", +* "дд чч:мм", если > 24 часов +*/ +const String prettyMillis(unsigned long time_ms = millis()); + +/* +* Форматиронное время интервала (c) +* "чч:мм:cc", +* "дд чч:мм", если > 24 часов +*/ +const String prettySeconds(unsigned long time_s); + +/* +* Тайм зона в секундах +*/ int getOffsetInSeconds(int timezone); +/* +* Тайм зона в минутах +*/ int getOffsetInMinutes(int timezone); + +/* +* Разбивает время на составляющие +*/ +void breakEpochToTime(unsigned long epoch, Time_t& tm); \ No newline at end of file diff --git a/src/Cmd.cpp b/src/Cmd.cpp index e770ba01..b9521860 100644 --- a/src/Cmd.cpp +++ b/src/Cmd.cpp @@ -100,8 +100,6 @@ void CMD_init() { sCmd.addCommand("firmwareUpdate", firmwareUpdate); sCmd.addCommand("firmwareVersion", firmwareVersion); - - handle_time_init(); } @@ -332,7 +330,7 @@ void timeSet() { void handle_time_init() { ts.add( TIME, 1000, [&](void *) { - String tmp = getTime(); + String tmp = timeNow->getTime(); jsonWriteStr(configLiveJson, "time", tmp); tmp.replace(":", "-"); jsonWriteStr(configLiveJson, "timenow", tmp); @@ -360,9 +358,9 @@ void textSet() { if (text.indexOf("-time") >= 0) { text.replace("-time", ""); text.replace("#", " "); - String time = getTime(); + String time = timeNow->getTime(); time.replace(":", "."); - text = text + " " + getDateDigitalFormated() + " " + time; + text = text + " " + timeNow->getDateDigitalFormated() + " " + time; } jsonWriteStr(configLiveJson, "text" + number, text); diff --git a/src/Global.cpp b/src/Global.cpp index ceebddb2..39599158 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -5,7 +5,7 @@ AsyncWebSocket ws; //AsyncEventSource events; #endif -Clock* rtc; +Clock* timeNow; TickerScheduler ts(TEST + 1); diff --git a/src/Init.cpp b/src/Init.cpp index e5215f0a..ee9846cd 100644 --- a/src/Init.cpp +++ b/src/Init.cpp @@ -90,7 +90,7 @@ void telemetry_init() { } void handle_uptime() { - jsonWriteStr(configSetupJson, "uptime", prettyMillis()); + jsonWriteStr(configSetupJson, "getUptime", timeNow->getUptime()); } void handle_statistics() { diff --git a/src/Logging.cpp b/src/Logging.cpp index 00035aa9..0abe9fb5 100644 --- a/src/Logging.cpp +++ b/src/Logging.cpp @@ -75,7 +75,7 @@ void logging() { /* * Удаление стрых данных и запись новых */ -void deleteOldDate(const String filename, size_t max_lines_cnt, String date_to_add) { +void deleteOldDate(const String filename, size_t max_lines_cnt, String payload) { String log_date = readFile(filename, 5120); size_t lines_cnt = itemsCount(log_date, "\r\n"); @@ -88,13 +88,13 @@ void deleteOldDate(const String filename, size_t max_lines_cnt, String date_to_a if (lines_cnt > max_lines_cnt) { log_date = deleteBeforeDelimiter(log_date, "\r\n"); - if (getTimeUnix() != "failed") { - log_date += getTimeUnix() + " " + date_to_add + "\r\n"; + if (timeNow->hasTimeSynced()) { + log_date += timeNow->getTimeUnix() + " " + payload + "\r\n"; writeFile(filename, log_date); } } else { - if (getTimeUnix() != "failed") { - addFile(filename, getTimeUnix() + " " + date_to_add); + if (timeNow->hasTimeSynced()) { + addFile(filename, timeNow->getTimeUnix() + " " + payload); } } } diff --git a/src/MqttDiscovery.cpp b/src/MqttDiscovery.cpp index 626ee798..7ccd0bc1 100644 --- a/src/MqttDiscovery.cpp +++ b/src/MqttDiscovery.cpp @@ -2,31 +2,31 @@ namespace Discovery { -static const char* json_is_defined = "is_defined"; -static const char* jsonId = "id"; -static const char* jsonBatt = "batt"; -static const char* jsonLux = "lux"; -static const char* jsonPres = "pres"; -static const char* jsonFer = "fer"; -static const char* jsonMoi = "moi"; -static const char* jsonHum = "hum"; -static const char* jsonTemp = "tem"; -static const char* jsonStep = "steps"; -static const char* jsonWeight = "weight"; -static const char* jsonPresence = "presence"; -static const char* jsonAltim = "altim"; -static const char* jsonAltif = "altift"; -static const char* jsonTempf = "tempf"; -static const char* jsonMsg = "message"; -static const char* jsonVal = "value"; -static const char* jsonVolt = "volt"; -static const char* jsonCurrent = "current"; -static const char* jsonPower = "power"; -static const char* jsonGpio = "gpio"; -static const char* jsonFtcd = "ftcd"; -static const char* jsonWm2 = "wattsm2"; -static const char* jsonAdc = "adc"; -static const char* jsonPa = "pa"; +static const char json_is_defined[] = "is_defined"; +static const char jsonId[] = "id"; +static const char jsonBatt[] = "batt"; +static const char jsonLux[] = "lux"; +static const char jsonPres[] = "pres"; +static const char jsonFer[] = "fer"; +static const char jsonMoi[] = "moi"; +static const char jsonHum[] = "hum"; +static const char jsonTemp[] = "tem"; +static const char jsonStep[] = "steps"; +static const char jsonWeight[] = "weight"; +static const char jsonPresence[] = "presence"; +static const char jsonAltim[] = "altim"; +static const char jsonAltif[] = "altift"; +static const char jsonTempf[] = "tempf"; +static const char jsonMsg[] = "message"; +static const char jsonVal[] = "value"; +static const char jsonVolt[] = "volt"; +static const char jsonCurrent[] = "current"; +static const char jsonPower[] = "power"; +static const char jsonGpio[] = "gpio"; +static const char jsonFtcd[] = "ftcd"; +static const char jsonWm2[] = "wattsm2"; +static const char jsonAdc[] = "adc"; +static const char jsonPa[] = "pa"; const String getValueJson(const char* str) { char buf[32]; @@ -35,16 +35,15 @@ const String getValueJson(const char* str) { } void createDiscovery( - char* unique_id, - const char* type, char* name, char* clazz, - char* value_template, char* payload_on, char* payload_off, - char* maasure_unit, int off_delay, char* has_payload, char* no_payload, - char* avail_topi, char* cmd_topic, char* state_topic, bool child) { + const char* type, const char* name, const char* clazz, + const char* value_template, const char* payload_on, const char* payload_off, + const char* maasure_unit, int off_delay, const char* has_payload, const char* no_payload, + const char* avail_topi, const char* cmd_topic, const char* state_topic, bool child) { + //const char* unique_id = getUniqueId(name).c_str(); } void createADC(const char* name) { createDiscovery( - (char*)getUniqueId(name).c_str(), "Type", "Name", "Clazz", "Value", "Payload", "NoPayload", "Measure", 0, "HasPayload", "NoPayload", @@ -53,7 +52,6 @@ void createADC(const char* name) { void createSwitch(const char* name) { createDiscovery( - (char*)getUniqueId(name).c_str(), "Type", "Name", "Clazz", "Value", "Payload", "NoPayload", "Measure", 0, "HasPayload", "NoPayload", @@ -65,14 +63,13 @@ void createSwitch(const char* name) { // availability topic, // device class, // value template, payload on, payload off, unit of measurement -char* BMEsensor[6][8] = { +const char* BMEsensor[6][8] = { {"sensor", "tempc", "bme", "temperature", "", "", "°C"}, //jsonTemp {"sensor", "tempf", "bme", "temperature", "", "", "°F"}, //jsonTempf {"sensor", "pa", "bme", "", "", "", "hPa"}, //jsonPa {"sensor", "hum", "bme", "humidity", "", "", "%"}, // jsonHum {"sensor", "altim", "bme", "", "", "", "m"}, //jsonAltim {"sensor", "altift", "bme", "", "", "", "ft"} // jsonAltif - }; } // namespace Discovery diff --git a/src/Utils/TimeUtils.cpp b/src/Utils/TimeUtils.cpp index 09c7185d..ab96bd65 100644 --- a/src/Utils/TimeUtils.cpp +++ b/src/Utils/TimeUtils.cpp @@ -1,114 +1,105 @@ #include "Utils\TimeUtils.h" - -#include "Global.h" #include "Utils\StringUtils.h" -#define ONE_MINUTE_s 60 -#define ONE_HOUR_m 60 -#define ONE_HOUR_s 60 * ONE_MINUTE_s +static const uint8_t days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; +static const char* week_days[7] = {"Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat"}; -time_t t; -struct tm* tm; -static const char* wd[7] = {"Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat"}; -String getTimeUnix() { - t = time(NULL); - tm = localtime(&t); - Serial.printf("%04d/%02d/%02d(%s) %02d:%02d:%02d\n", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, wd[tm->tm_wday], - tm->tm_hour, tm->tm_min, tm->tm_sec); - delay(1000); - time_t now = time(nullptr); - if (now < 30000) { - return "failed"; - } - return String(now); -} +// String getTimeUnix() { +// time_t t; +// struct tm* tm; -boolean getUnixTimeStr(String& res) { - time_t now = time(nullptr); - res = String(now); - return now > 30000; -} +// t = time(NULL); +// tm = localtime(&t); +// Serial.printf("%04d/%02d/%02d(%s) %02d:%02d:%02d\n", +// tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, week_days[tm->tm_wday], +// tm->tm_hour, tm->tm_min, tm->tm_sec); +// delay(1000); +// time_t now = time(nullptr); +// if (now < 30000) { +// return "failed"; +// } +// return String(now); +// } -String getTime() { - time_t now = time(nullptr); - int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt(); - now = now + zone; - String Time = ""; // Строка для результатов времени - Time += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 - int i = Time.indexOf(":"); //Ишем позицию первого символа : - Time = Time.substring(i - 2, i + 6); // Выделяем из строки 2 символа перед символом : и 6 символов после - return Time; // Возврашаем полученное время -} +// String getTime() { +// time_t now = time(nullptr); +// int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt(); +// now = now + zone; +// String Time = ""; // Строка для результатов времени +// Time += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 +// int i = Time.indexOf(":"); //Ишем позицию первого символа : +// Time = Time.substring(i - 2, i + 6); // Выделяем из строки 2 символа перед символом : и 6 символов после +// return Time; // Возврашаем полученное время +// } -String getTimeWOsec() { - time_t now = time(nullptr); - int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt(); - now = now + zone; - String Time = ""; // Строка для результатов времени - Time += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 - int i = Time.indexOf(":"); //Ишем позицию первого символа : - Time = Time.substring(i - 2, i + 3); // Выделяем из строки 2 символа перед символом : и 6 символов после - return Time; // Возврашаем полученное время -} +// String getTimeWOsec() { +// time_t now = time(nullptr); +// int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt(); +// now = now + zone; +// String Time = ""; // Строка для результатов времени +// Time += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 +// int i = Time.indexOf(":"); //Ишем позицию первого символа : +// Time = Time.substring(i - 2, i + 3); // Выделяем из строки 2 символа перед символом : и 6 символов после +// return Time; // Возврашаем полученное время +// } -String getDate() { - time_t now = time(nullptr); - int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt(); - now = now + zone; - String Data = ""; // Строка для результатов времени - Data += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 - Data.replace("\n", ""); - uint8_t i = Data.lastIndexOf(" "); //Ишем позицию последнего символа пробел - String Time = Data.substring(i - 8, i + 1); // Выделяем время и пробел - Data.replace(Time, ""); // Удаляем из строки 8 символов времени и пробел - return Data; // Возврашаем полученную дату -} +// String getDate() { +// time_t now = time(nullptr); +// int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt(); +// now = now + zone; +// String Data = ""; // Строка для результатов времени +// Data += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 +// Data.replace("\n", ""); +// uint8_t i = Data.lastIndexOf(" "); //Ишем позицию последнего символа пробел +// String Time = Data.substring(i - 8, i + 1); // Выделяем время и пробел +// Data.replace(Time, ""); // Удаляем из строки 8 символов времени и пробел +// return Data; // Возврашаем полученную дату +// } -String getDateDigitalFormated() { - String date = getDate(); +// String getDateDigitalFormated() { +// String date = getDate(); - date = deleteBeforeDelimiter(date, " "); +// date = deleteBeforeDelimiter(date, " "); - date.replace("Jan", "01"); - date.replace("Feb", "02"); - date.replace("Mar", "03"); - date.replace("Apr", "04"); - date.replace("May", "05"); - date.replace("Jun", "06"); - date.replace("Jul", "07"); - date.replace("Aug", "08"); - date.replace("Sep", "09"); - date.replace("Oct", "10"); - date.replace("Nov", "11"); - date.replace("Dec", "12"); +// date.replace("Jan", "01"); +// date.replace("Feb", "02"); +// date.replace("Mar", "03"); +// date.replace("Apr", "04"); +// date.replace("May", "05"); +// date.replace("Jun", "06"); +// date.replace("Jul", "07"); +// date.replace("Aug", "08"); +// date.replace("Sep", "09"); +// date.replace("Oct", "10"); +// date.replace("Nov", "11"); +// date.replace("Dec", "12"); - String month = date.substring(0, 2); - String day = date.substring(3, 5); - String year = date.substring(8, 10); +// String month = date.substring(0, 2); +// String day = date.substring(3, 5); +// String year = date.substring(8, 10); - String out = day; - out += "."; - out += month; - out += "."; - out += year; +// String out = day; +// out += "."; +// out += month; +// out += "."; +// out += year; - return out; -} +// return out; +// } -int timeToMin(String Time) { - //"00:00:00" время в секунды - long min = selectToMarker(Time, ":").toInt() * 60; //общее количество секунд в полных часах - Time = deleteBeforeDelimiter(Time, ":"); // Теперь здесь минуты секунды - min += selectToMarker(Time, ":").toInt(); // Добавим секунды из полных минут - return min; -} +// int timeToMin(String Time) { +// //"00:00:00" время в секунды +// long min = selectToMarker(Time, ":").toInt() * 60; //общее количество секунд в полных часах +// Time = deleteBeforeDelimiter(Time, ":"); // Теперь здесь минуты секунды +// min += selectToMarker(Time, ":").toInt(); // Добавим секунды из полных минут +// return min; +// } static const char* TIME_FORMAT PROGMEM = "%02d:%02d:%02d"; static const char* TIME_FORMAT_WITH_DAYS PROGMEM = "%dd %02d:%02d"; -const String prettyMillis(unsigned long time_ms) { - unsigned long tmp = time_ms / 1000; +const String prettySeconds(unsigned long time_s) { + unsigned long tmp = time_s; unsigned long seconds; unsigned long minutes; unsigned long hours; @@ -132,6 +123,10 @@ const String prettyMillis(unsigned long time_ms) { return String(buf); } +const String prettyMillis(unsigned long time_ms) { + return prettySeconds(time_ms / 1000); +} + unsigned long millis_since(unsigned long sinse) { return millis_passed(sinse, millis()); } @@ -165,3 +160,55 @@ int getOffsetInSeconds(int timezone) { int getOffsetInMinutes(int timezone) { return timezone * ONE_HOUR_m; } + +void breakEpochToTime(unsigned long epoch, Time_t& tm) { + // break the given time_input into time components + // this is a more compact version of the C library localtime function + uint8_t year; + uint8_t month; + uint8_t month_length; + uint32_t time; + unsigned long days; + + time = epoch; + tm.second = time % 60; + time /= 60; // now it is minutes + tm.minute = time % 60; + time /= 60; // now it is hours + tm.hour = time % 24; + time /= 24; // now it is days + tm.days = time; + tm.day_of_week = ((time + 4) % 7) + 1; // Sunday is day 1 + + year = 0; + days = 0; + while ((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) { + year++; + } + tm.year = year - 30; + + days -= LEAP_YEAR(year) ? 366 : 365; + time -= days; // now it is days in this year, starting at 0 + tm.day_of_year = time; + + for (month = 0; month < 12; month++) { + if (1 == month) { // february + if (LEAP_YEAR(year)) { + month_length = 29; + } else { + month_length = 28; + } + } else { + month_length = days_in_month[month]; + } + + if (time >= month_length) { + time -= month_length; + } else { + break; + } + } + tm.month = month + 1; // jan is month 1 + tm.day_of_month = time + 1; // day of month + tm.valid = (epoch > MIN_DATETIME); +} diff --git a/src/Web.cpp b/src/Web.cpp index ae123d45..8f435189 100644 --- a/src/Web.cpp +++ b/src/Web.cpp @@ -133,14 +133,14 @@ void web_init() { String timezoneStr = request->getParam("timezone")->value(); jsonWriteStr(configSetupJson, "timezone", timezoneStr); saveConfig(); - rtc->setTimezone(timezoneStr.toInt()); + timeNow->setTimezone(timezoneStr.toInt()); request->send(200, "text/text", "OK"); } if (request->hasArg("ntp")) { String ntpStr = request->getParam("ntp")->value(); jsonWriteStr(configSetupJson, "ntp", ntpStr); saveConfig(); - rtc->setNtpPool(ntpStr); + timeNow->setNtpPool(ntpStr); request->send(200, "text/text", "OK"); } //-------------------------------------------------------------------------------- diff --git a/src/main.cpp b/src/main.cpp index 00737fff..b39d48e1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,7 +8,41 @@ void not_async_actions(); static const char* MODULE = "Main"; +Timings metric; +boolean initialized = false; + void do_fscheck(String& results) { + // TODO Проверка наличие важных файлов, возможно версии ФС +} + +void clock_init() { + timeNow = new Clock(); + timeNow->setNtpPool(jsonReadStr(configSetupJson, "ntp")); + timeNow->setTimezone(jsonReadStr(configSetupJson, "timezone").toInt()); + + ts.add( + TIME_SYNC, 30000, [&](void*) { + timeNow->hasSync(); + }, + nullptr, true); +} +void do_scan_bus() { + if (busScanFlag) { + String res = ""; + BusScanner* scanner = BusScannerFactory::get(res, busToScan); + scanner->scan(); + jsonWriteStr(configLiveJson, BusScannerFactory::label(busToScan), res); + busScanFlag = false; + } +} + +void do_check_fs() { + if (fsCheckFlag) { + String buf; + do_fscheck(buf); + jsonWriteStr(configLiveJson, "fscheck", buf); + fsCheckFlag = false; + } } void setup() { @@ -58,19 +92,11 @@ void setup() { web_init(); pm.info("Clock"); - rtc = new Clock(); - rtc->setNtpPool(jsonReadStr(configSetupJson, "ntp")); - rtc->setTimezone(jsonReadStr(configSetupJson, "timezone").toInt()); - - ts.add( - TIME_SYNC, 30000, [&](void*) { - rtc->hasSync(); - }, - nullptr, true); + clock_init(); #ifdef UDP_ENABLED + pm.info("Broadcast UDP"); UDP_init(); - pm.info("Broadcast"); #endif ts.add( TEST, 10000, [&](void*) { @@ -79,25 +105,26 @@ void setup() { nullptr, true); just_load = false; -} -void saveConfig() { - writeFile(String("config.json"), configSetupJson); + initialized = true; } -Timings metric; - void loop() { + if (!initialized) { + return; + } + timeNow->loop(); + #ifdef OTA_UPDATES_ENABLED ArduinoOTA.handle(); #endif #ifdef WS_enable ws.cleanupClients(); #endif - metric.add(MT_ONE); + // metric.add(MT_ONE); not_async_actions(); - metric.add(MT_TWO); + // metric.add(MT_TWO); MqttClient::loop(); loopCmd(); @@ -126,7 +153,9 @@ void not_async_actions() { MqttClient::reconnect(); mqttParamsChanged = false; } + getLastVersion(); + flashUpgrade(); #ifdef UDP_ENABLED @@ -134,20 +163,9 @@ void not_async_actions() { do_mqtt_send_settings_to_udp(); #endif - if (busScanFlag) { - String res = ""; - BusScanner* scanner = BusScannerFactory::get(res, busToScan); - scanner->scan(); - jsonWriteStr(configLiveJson, BusScannerFactory::label(busToScan), res); - busScanFlag = false; - } + do_scan_bus(); - if (fsCheckFlag) { - String buf; - do_fscheck(buf); - jsonWriteStr(configLiveJson, "fscheck", buf); - fsCheckFlag = false; - } + do_check_fs(); } String getURL(const String& urls) { @@ -194,6 +212,10 @@ void setChipId() { Serial.println(chipId); } +void saveConfig() { + writeFile(String("config.json"), configSetupJson); +} + #ifdef ESP8266 #ifdef LED_PIN void setLedStatus(LedStatus_t status) {