This commit is contained in:
Yuri Trikoz
2020-06-27 01:21:58 +03:00
parent b51ec4d0e2
commit 00fd9f9bb9
14 changed files with 371 additions and 266 deletions

View File

@@ -4,6 +4,7 @@
#include "Utils/PrintMessage.h" #include "Utils/PrintMessage.h"
#include "TZ.h" #include "TZ.h"
#include "sntp.h"
class Clock { class Clock {
const char* MODULE = "Clock"; const char* MODULE = "Clock";
@@ -11,6 +12,27 @@ class Clock {
public: public:
Clock() : _timezone{0}, _hasSynced{false}, _configured{false} {} 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() { bool hasSync() {
if (!_hasSynced) { if (!_hasSynced) {
startSync(); startSync();
@@ -19,18 +41,26 @@ class Clock {
} }
void setNtpPool(String ntp) { void setNtpPool(String ntp) {
_ntp = ntp; if (!_ntp.equals(ntp)) {
_ntp = ntp;
_configured = false;
}
} }
void setTimezone(int timezone) { void setTimezone(int timezone) {
_timezone = timezone; if (_timezone != timezone) {
_timezone = timezone;
_configured = false;
}
} }
void startSync() { void startSync() {
if (!_configured) { if (!_configured) {
pm.info("sync to: " + _ntp + " time zone: " + String(_timezone)); pm.info("sync to: " + _ntp + " timezone: " + String(_timezone));
setupSntp(); setupSntp();
_configured = true; _configured = true;
// лучше не ждать, проверим в следующий раз
return;
} }
_hasSynced = hasTimeSynced(); _hasSynced = hasTimeSynced();
if (_hasSynced) { if (_hasSynced) {
@@ -41,42 +71,70 @@ class Clock {
} }
void setupSntp() { void setupSntp() {
int tzs = getOffsetInSeconds(_timezone); sntp_setservername(0, _ntp.c_str());
int tzh = tzs / 3600; sntp_setservername(1, "ru.pool.ntp.org");
tzs -= tzh * 3600; sntp_setservername(2, "pool.ntp.org");
int tzm = tzs / 60; sntp_stop();
tzs -= tzm * 60; sntp_set_timezone(0); // UTC time
sntp_init();
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;
} }
time_t getSystemTime() { bool hasTimeSynced() const {
return _epoch > MIN_DATETIME;
}
time_t getSystemTime() const {
timeval tv{0, 0}; timeval tv{0, 0};
timezone tz = timezone{getOffsetInMinutes(_timezone), 0}; timezone tz = timezone{0, 0};
time_t epoch = 0;
if (gettimeofday(&tv, &tz) != -1) { 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: private:
time_t _epoch; Time_t _time;
unsigned long _uptime;
unsigned long _epoch;
int _timezone; int _timezone;
String _ntp; String _ntp;
bool _hasSynced; bool _hasSynced;

View File

@@ -1,5 +1,18 @@
#pragma once #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, enum TimerTask_t { WIFI_SCAN,
WIFI_MQTT_CONNECTION_CHECK, WIFI_MQTT_CONNECTION_CHECK,
SENSORS, SENSORS,

View File

@@ -14,7 +14,6 @@
#include "Bus/BusScanner.h" #include "Bus/BusScanner.h"
#include "Errors.h" #include "Errors.h"
#include "GyverFilters.h" #include "GyverFilters.h"
#include "UptimeInterval.h"
#include "Upgrade.h" #include "Upgrade.h"
#include "Clock.h" #include "Clock.h"
@@ -46,7 +45,7 @@ extern AsyncWebSocket ws;
//extern AsyncEventSource events; //extern AsyncEventSource events;
#endif #endif
extern Clock* rtc; extern Clock* timeNow;
extern TickerScheduler ts; extern TickerScheduler ts;

View File

@@ -1,32 +0,0 @@
#pragma once
#include <Arduino.h>
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;
};

View File

@@ -24,7 +24,7 @@ class PrintMessage {
private: private:
void print(const ErrorLevel_t level, const String& str) { 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: private:

View File

@@ -1,37 +1,15 @@
#pragma once #pragma once
#ifdef ESP8266
#include <time.h>
#endif
#include <Arduino.h> #include <Arduino.h>
/* #include "CommonTypes.h"
* Получение текущего времени
*/
String getTime();
/* #define ONE_MINUTE_s 60
* Получаем время в формате linux gmt #define ONE_HOUR_m 60
*/ #define ONE_HOUR_s 60 * ONE_MINUTE_s
String getTimeUnix(); #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
* Параметр время
* @result результат
*/
boolean getUnixTimeStr(String&);
String getTimeWOsec();
/*
* Получение даты
*/
String getDate();
String getDateDigitalFormated();
int timeToMin(String Time);
const String prettyMillis(unsigned long time_ms = millis());
/* /*
* Время (мс) прошедщее с @since * Время (мс) прошедщее с @since
@@ -43,6 +21,31 @@ unsigned long millis_since(unsigned long sinse);
*/ */
unsigned long millis_passed(unsigned long start, unsigned long finish); 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 getOffsetInSeconds(int timezone);
/*
* Тайм зона в минутах
*/
int getOffsetInMinutes(int timezone); int getOffsetInMinutes(int timezone);
/*
* Разбивает время на составляющие
*/
void breakEpochToTime(unsigned long epoch, Time_t& tm);

View File

@@ -100,8 +100,6 @@ void CMD_init() {
sCmd.addCommand("firmwareUpdate", firmwareUpdate); sCmd.addCommand("firmwareUpdate", firmwareUpdate);
sCmd.addCommand("firmwareVersion", firmwareVersion); sCmd.addCommand("firmwareVersion", firmwareVersion);
handle_time_init(); handle_time_init();
} }
@@ -332,7 +330,7 @@ void timeSet() {
void handle_time_init() { void handle_time_init() {
ts.add( ts.add(
TIME, 1000, [&](void *) { TIME, 1000, [&](void *) {
String tmp = getTime(); String tmp = timeNow->getTime();
jsonWriteStr(configLiveJson, "time", tmp); jsonWriteStr(configLiveJson, "time", tmp);
tmp.replace(":", "-"); tmp.replace(":", "-");
jsonWriteStr(configLiveJson, "timenow", tmp); jsonWriteStr(configLiveJson, "timenow", tmp);
@@ -360,9 +358,9 @@ void textSet() {
if (text.indexOf("-time") >= 0) { if (text.indexOf("-time") >= 0) {
text.replace("-time", ""); text.replace("-time", "");
text.replace("#", " "); text.replace("#", " ");
String time = getTime(); String time = timeNow->getTime();
time.replace(":", "."); time.replace(":", ".");
text = text + " " + getDateDigitalFormated() + " " + time; text = text + " " + timeNow->getDateDigitalFormated() + " " + time;
} }
jsonWriteStr(configLiveJson, "text" + number, text); jsonWriteStr(configLiveJson, "text" + number, text);

View File

@@ -5,7 +5,7 @@ AsyncWebSocket ws;
//AsyncEventSource events; //AsyncEventSource events;
#endif #endif
Clock* rtc; Clock* timeNow;
TickerScheduler ts(TEST + 1); TickerScheduler ts(TEST + 1);

View File

@@ -90,7 +90,7 @@ void telemetry_init() {
} }
void handle_uptime() { void handle_uptime() {
jsonWriteStr(configSetupJson, "uptime", prettyMillis()); jsonWriteStr(configSetupJson, "getUptime", timeNow->getUptime());
} }
void handle_statistics() { void handle_statistics() {

View File

@@ -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); String log_date = readFile(filename, 5120);
size_t lines_cnt = itemsCount(log_date, "\r\n"); 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) { if (lines_cnt > max_lines_cnt) {
log_date = deleteBeforeDelimiter(log_date, "\r\n"); log_date = deleteBeforeDelimiter(log_date, "\r\n");
if (getTimeUnix() != "failed") { if (timeNow->hasTimeSynced()) {
log_date += getTimeUnix() + " " + date_to_add + "\r\n"; log_date += timeNow->getTimeUnix() + " " + payload + "\r\n";
writeFile(filename, log_date); writeFile(filename, log_date);
} }
} else { } else {
if (getTimeUnix() != "failed") { if (timeNow->hasTimeSynced()) {
addFile(filename, getTimeUnix() + " " + date_to_add); addFile(filename, timeNow->getTimeUnix() + " " + payload);
} }
} }
} }

View File

@@ -2,31 +2,31 @@
namespace Discovery { namespace Discovery {
static const char* json_is_defined = "is_defined"; static const char json_is_defined[] = "is_defined";
static const char* jsonId = "id"; static const char jsonId[] = "id";
static const char* jsonBatt = "batt"; static const char jsonBatt[] = "batt";
static const char* jsonLux = "lux"; static const char jsonLux[] = "lux";
static const char* jsonPres = "pres"; static const char jsonPres[] = "pres";
static const char* jsonFer = "fer"; static const char jsonFer[] = "fer";
static const char* jsonMoi = "moi"; static const char jsonMoi[] = "moi";
static const char* jsonHum = "hum"; static const char jsonHum[] = "hum";
static const char* jsonTemp = "tem"; static const char jsonTemp[] = "tem";
static const char* jsonStep = "steps"; static const char jsonStep[] = "steps";
static const char* jsonWeight = "weight"; static const char jsonWeight[] = "weight";
static const char* jsonPresence = "presence"; static const char jsonPresence[] = "presence";
static const char* jsonAltim = "altim"; static const char jsonAltim[] = "altim";
static const char* jsonAltif = "altift"; static const char jsonAltif[] = "altift";
static const char* jsonTempf = "tempf"; static const char jsonTempf[] = "tempf";
static const char* jsonMsg = "message"; static const char jsonMsg[] = "message";
static const char* jsonVal = "value"; static const char jsonVal[] = "value";
static const char* jsonVolt = "volt"; static const char jsonVolt[] = "volt";
static const char* jsonCurrent = "current"; static const char jsonCurrent[] = "current";
static const char* jsonPower = "power"; static const char jsonPower[] = "power";
static const char* jsonGpio = "gpio"; static const char jsonGpio[] = "gpio";
static const char* jsonFtcd = "ftcd"; static const char jsonFtcd[] = "ftcd";
static const char* jsonWm2 = "wattsm2"; static const char jsonWm2[] = "wattsm2";
static const char* jsonAdc = "adc"; static const char jsonAdc[] = "adc";
static const char* jsonPa = "pa"; static const char jsonPa[] = "pa";
const String getValueJson(const char* str) { const String getValueJson(const char* str) {
char buf[32]; char buf[32];
@@ -35,16 +35,15 @@ const String getValueJson(const char* str) {
} }
void createDiscovery( void createDiscovery(
char* unique_id, const char* type, const char* name, const char* clazz,
const char* type, char* name, char* clazz, const char* value_template, const char* payload_on, const char* payload_off,
char* value_template, char* payload_on, char* payload_off, const char* maasure_unit, int off_delay, const char* has_payload, const char* no_payload,
char* maasure_unit, int off_delay, char* has_payload, char* no_payload, const char* avail_topi, const char* cmd_topic, const char* state_topic, bool child) {
char* avail_topi, char* cmd_topic, char* state_topic, bool child) { //const char* unique_id = getUniqueId(name).c_str();
} }
void createADC(const char* name) { void createADC(const char* name) {
createDiscovery( createDiscovery(
(char*)getUniqueId(name).c_str(),
"Type", "Name", "Clazz", "Type", "Name", "Clazz",
"Value", "Payload", "NoPayload", "Value", "Payload", "NoPayload",
"Measure", 0, "HasPayload", "NoPayload", "Measure", 0, "HasPayload", "NoPayload",
@@ -53,7 +52,6 @@ void createADC(const char* name) {
void createSwitch(const char* name) { void createSwitch(const char* name) {
createDiscovery( createDiscovery(
(char*)getUniqueId(name).c_str(),
"Type", "Name", "Clazz", "Type", "Name", "Clazz",
"Value", "Payload", "NoPayload", "Value", "Payload", "NoPayload",
"Measure", 0, "HasPayload", "NoPayload", "Measure", 0, "HasPayload", "NoPayload",
@@ -65,14 +63,13 @@ void createSwitch(const char* name) {
// availability topic, // availability topic,
// device class, // device class,
// value template, payload on, payload off, unit of measurement // 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", "tempc", "bme", "temperature", "", "", "°C"}, //jsonTemp
{"sensor", "tempf", "bme", "temperature", "", "", "°F"}, //jsonTempf {"sensor", "tempf", "bme", "temperature", "", "", "°F"}, //jsonTempf
{"sensor", "pa", "bme", "", "", "", "hPa"}, //jsonPa {"sensor", "pa", "bme", "", "", "", "hPa"}, //jsonPa
{"sensor", "hum", "bme", "humidity", "", "", "%"}, // jsonHum {"sensor", "hum", "bme", "humidity", "", "", "%"}, // jsonHum
{"sensor", "altim", "bme", "", "", "", "m"}, //jsonAltim {"sensor", "altim", "bme", "", "", "", "m"}, //jsonAltim
{"sensor", "altift", "bme", "", "", "", "ft"} // jsonAltif {"sensor", "altift", "bme", "", "", "", "ft"} // jsonAltif
}; };
} // namespace Discovery } // namespace Discovery

View File

@@ -1,114 +1,105 @@
#include "Utils\TimeUtils.h" #include "Utils\TimeUtils.h"
#include "Global.h"
#include "Utils\StringUtils.h" #include "Utils\StringUtils.h"
#define ONE_MINUTE_s 60 static const uint8_t days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
#define ONE_HOUR_m 60 static const char* week_days[7] = {"Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat"};
#define ONE_HOUR_s 60 * ONE_MINUTE_s
time_t t; // String getTimeUnix() {
struct tm* tm; // time_t t;
static const char* wd[7] = {"Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat"}; // struct tm* tm;
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);
}
boolean getUnixTimeStr(String& res) { // t = time(NULL);
time_t now = time(nullptr); // tm = localtime(&t);
res = String(now); // Serial.printf("%04d/%02d/%02d(%s) %02d:%02d:%02d\n",
return now > 30000; // 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() { // String getTime() {
time_t now = time(nullptr); // time_t now = time(nullptr);
int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt(); // int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt();
now = now + zone; // now = now + zone;
String Time = ""; // Строка для результатов времени // String Time = ""; // Строка для результатов времени
Time += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 // Time += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017
int i = Time.indexOf(":"); //Ишем позицию первого символа : // int i = Time.indexOf(":"); //Ишем позицию первого символа :
Time = Time.substring(i - 2, i + 6); // Выделяем из строки 2 символа перед символом : и 6 символов после // Time = Time.substring(i - 2, i + 6); // Выделяем из строки 2 символа перед символом : и 6 символов после
return Time; // Возврашаем полученное время // return Time; // Возврашаем полученное время
} // }
String getTimeWOsec() { // String getTimeWOsec() {
time_t now = time(nullptr); // time_t now = time(nullptr);
int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt(); // int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt();
now = now + zone; // now = now + zone;
String Time = ""; // Строка для результатов времени // String Time = ""; // Строка для результатов времени
Time += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 // Time += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017
int i = Time.indexOf(":"); //Ишем позицию первого символа : // int i = Time.indexOf(":"); //Ишем позицию первого символа :
Time = Time.substring(i - 2, i + 3); // Выделяем из строки 2 символа перед символом : и 6 символов после // Time = Time.substring(i - 2, i + 3); // Выделяем из строки 2 символа перед символом : и 6 символов после
return Time; // Возврашаем полученное время // return Time; // Возврашаем полученное время
} // }
String getDate() { // String getDate() {
time_t now = time(nullptr); // time_t now = time(nullptr);
int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt(); // int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt();
now = now + zone; // now = now + zone;
String Data = ""; // Строка для результатов времени // String Data = ""; // Строка для результатов времени
Data += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 // Data += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017
Data.replace("\n", ""); // Data.replace("\n", "");
uint8_t i = Data.lastIndexOf(" "); //Ишем позицию последнего символа пробел // uint8_t i = Data.lastIndexOf(" "); //Ишем позицию последнего символа пробел
String Time = Data.substring(i - 8, i + 1); // Выделяем время и пробел // String Time = Data.substring(i - 8, i + 1); // Выделяем время и пробел
Data.replace(Time, ""); // Удаляем из строки 8 символов времени и пробел // Data.replace(Time, ""); // Удаляем из строки 8 символов времени и пробел
return Data; // Возврашаем полученную дату // return Data; // Возврашаем полученную дату
} // }
String getDateDigitalFormated() { // String getDateDigitalFormated() {
String date = getDate(); // String date = getDate();
date = deleteBeforeDelimiter(date, " "); // date = deleteBeforeDelimiter(date, " ");
date.replace("Jan", "01"); // date.replace("Jan", "01");
date.replace("Feb", "02"); // date.replace("Feb", "02");
date.replace("Mar", "03"); // date.replace("Mar", "03");
date.replace("Apr", "04"); // date.replace("Apr", "04");
date.replace("May", "05"); // date.replace("May", "05");
date.replace("Jun", "06"); // date.replace("Jun", "06");
date.replace("Jul", "07"); // date.replace("Jul", "07");
date.replace("Aug", "08"); // date.replace("Aug", "08");
date.replace("Sep", "09"); // date.replace("Sep", "09");
date.replace("Oct", "10"); // date.replace("Oct", "10");
date.replace("Nov", "11"); // date.replace("Nov", "11");
date.replace("Dec", "12"); // date.replace("Dec", "12");
String month = date.substring(0, 2); // String month = date.substring(0, 2);
String day = date.substring(3, 5); // String day = date.substring(3, 5);
String year = date.substring(8, 10); // String year = date.substring(8, 10);
String out = day; // String out = day;
out += "."; // out += ".";
out += month; // out += month;
out += "."; // out += ".";
out += year; // out += year;
return out; // return out;
} // }
int timeToMin(String Time) { // int timeToMin(String Time) {
//"00:00:00" время в секунды // //"00:00:00" время в секунды
long min = selectToMarker(Time, ":").toInt() * 60; //общее количество секунд в полных часах // long min = selectToMarker(Time, ":").toInt() * 60; //общее количество секунд в полных часах
Time = deleteBeforeDelimiter(Time, ":"); // Теперь здесь минуты секунды // Time = deleteBeforeDelimiter(Time, ":"); // Теперь здесь минуты секунды
min += selectToMarker(Time, ":").toInt(); // Добавим секунды из полных минут // min += selectToMarker(Time, ":").toInt(); // Добавим секунды из полных минут
return min; // return min;
} // }
static const char* TIME_FORMAT PROGMEM = "%02d:%02d:%02d"; static const char* TIME_FORMAT PROGMEM = "%02d:%02d:%02d";
static const char* TIME_FORMAT_WITH_DAYS PROGMEM = "%dd %02d:%02d"; static const char* TIME_FORMAT_WITH_DAYS PROGMEM = "%dd %02d:%02d";
const String prettyMillis(unsigned long time_ms) { const String prettySeconds(unsigned long time_s) {
unsigned long tmp = time_ms / 1000; unsigned long tmp = time_s;
unsigned long seconds; unsigned long seconds;
unsigned long minutes; unsigned long minutes;
unsigned long hours; unsigned long hours;
@@ -132,6 +123,10 @@ const String prettyMillis(unsigned long time_ms) {
return String(buf); return String(buf);
} }
const String prettyMillis(unsigned long time_ms) {
return prettySeconds(time_ms / 1000);
}
unsigned long millis_since(unsigned long sinse) { unsigned long millis_since(unsigned long sinse) {
return millis_passed(sinse, millis()); return millis_passed(sinse, millis());
} }
@@ -165,3 +160,55 @@ int getOffsetInSeconds(int timezone) {
int getOffsetInMinutes(int timezone) { int getOffsetInMinutes(int timezone) {
return timezone * ONE_HOUR_m; 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);
}

View File

@@ -133,14 +133,14 @@ void web_init() {
String timezoneStr = request->getParam("timezone")->value(); String timezoneStr = request->getParam("timezone")->value();
jsonWriteStr(configSetupJson, "timezone", timezoneStr); jsonWriteStr(configSetupJson, "timezone", timezoneStr);
saveConfig(); saveConfig();
rtc->setTimezone(timezoneStr.toInt()); timeNow->setTimezone(timezoneStr.toInt());
request->send(200, "text/text", "OK"); request->send(200, "text/text", "OK");
} }
if (request->hasArg("ntp")) { if (request->hasArg("ntp")) {
String ntpStr = request->getParam("ntp")->value(); String ntpStr = request->getParam("ntp")->value();
jsonWriteStr(configSetupJson, "ntp", ntpStr); jsonWriteStr(configSetupJson, "ntp", ntpStr);
saveConfig(); saveConfig();
rtc->setNtpPool(ntpStr); timeNow->setNtpPool(ntpStr);
request->send(200, "text/text", "OK"); request->send(200, "text/text", "OK");
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------

View File

@@ -8,7 +8,41 @@ void not_async_actions();
static const char* MODULE = "Main"; static const char* MODULE = "Main";
Timings metric;
boolean initialized = false;
void do_fscheck(String& results) { 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() { void setup() {
@@ -58,19 +92,11 @@ void setup() {
web_init(); web_init();
pm.info("Clock"); pm.info("Clock");
rtc = new Clock(); clock_init();
rtc->setNtpPool(jsonReadStr(configSetupJson, "ntp"));
rtc->setTimezone(jsonReadStr(configSetupJson, "timezone").toInt());
ts.add(
TIME_SYNC, 30000, [&](void*) {
rtc->hasSync();
},
nullptr, true);
#ifdef UDP_ENABLED #ifdef UDP_ENABLED
pm.info("Broadcast UDP");
UDP_init(); UDP_init();
pm.info("Broadcast");
#endif #endif
ts.add( ts.add(
TEST, 10000, [&](void*) { TEST, 10000, [&](void*) {
@@ -79,25 +105,26 @@ void setup() {
nullptr, true); nullptr, true);
just_load = false; just_load = false;
}
void saveConfig() { initialized = true;
writeFile(String("config.json"), configSetupJson);
} }
Timings metric;
void loop() { void loop() {
if (!initialized) {
return;
}
timeNow->loop();
#ifdef OTA_UPDATES_ENABLED #ifdef OTA_UPDATES_ENABLED
ArduinoOTA.handle(); ArduinoOTA.handle();
#endif #endif
#ifdef WS_enable #ifdef WS_enable
ws.cleanupClients(); ws.cleanupClients();
#endif #endif
metric.add(MT_ONE); // metric.add(MT_ONE);
not_async_actions(); not_async_actions();
metric.add(MT_TWO); // metric.add(MT_TWO);
MqttClient::loop(); MqttClient::loop();
loopCmd(); loopCmd();
@@ -126,7 +153,9 @@ void not_async_actions() {
MqttClient::reconnect(); MqttClient::reconnect();
mqttParamsChanged = false; mqttParamsChanged = false;
} }
getLastVersion(); getLastVersion();
flashUpgrade(); flashUpgrade();
#ifdef UDP_ENABLED #ifdef UDP_ENABLED
@@ -134,20 +163,9 @@ void not_async_actions() {
do_mqtt_send_settings_to_udp(); do_mqtt_send_settings_to_udp();
#endif #endif
if (busScanFlag) { do_scan_bus();
String res = "";
BusScanner* scanner = BusScannerFactory::get(res, busToScan);
scanner->scan();
jsonWriteStr(configLiveJson, BusScannerFactory::label(busToScan), res);
busScanFlag = false;
}
if (fsCheckFlag) { do_check_fs();
String buf;
do_fscheck(buf);
jsonWriteStr(configLiveJson, "fscheck", buf);
fsCheckFlag = false;
}
} }
String getURL(const String& urls) { String getURL(const String& urls) {
@@ -194,6 +212,10 @@ void setChipId() {
Serial.println(chipId); Serial.println(chipId);
} }
void saveConfig() {
writeFile(String("config.json"), configSetupJson);
}
#ifdef ESP8266 #ifdef ESP8266
#ifdef LED_PIN #ifdef LED_PIN
void setLedStatus(LedStatus_t status) { void setLedStatus(LedStatus_t status) {