Files
IoTManager/include/Clock.h

142 lines
3.4 KiB
C
Raw Normal View History

2020-06-22 03:11:02 +03:00
#pragma once
2020-06-25 09:21:42 +03:00
#include "Utils/TimeUtils.h"
#include "Utils/PrintMessage.h"
2020-06-22 03:11:02 +03:00
2020-06-25 20:13:20 +03:00
#include "TZ.h"
2020-06-27 01:21:58 +03:00
#include "sntp.h"
2020-06-22 03:11:02 +03:00
2020-06-25 09:21:42 +03:00
class Clock {
const char* MODULE = "Clock";
public:
2020-06-26 01:38:29 +03:00
Clock() : _timezone{0}, _hasSynced{false}, _configured{false} {}
2020-06-25 09:21:42 +03:00
2020-06-27 01:21:58 +03:00
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);
}
2020-06-25 09:21:42 +03:00
bool hasSync() {
if (!_hasSynced) {
startSync();
}
return _hasSynced;
}
2020-06-25 20:13:20 +03:00
void setNtpPool(String ntp) {
2020-06-27 01:21:58 +03:00
if (!_ntp.equals(ntp)) {
_ntp = ntp;
_configured = false;
}
2020-06-25 09:21:42 +03:00
}
void setTimezone(int timezone) {
2020-06-27 01:21:58 +03:00
if (_timezone != timezone) {
_timezone = timezone;
_configured = false;
}
2020-06-25 09:21:42 +03:00
}
void startSync() {
if (!_configured) {
2020-06-27 01:21:58 +03:00
pm.info("sync to: " + _ntp + " timezone: " + String(_timezone));
2020-06-25 09:21:42 +03:00
setupSntp();
_configured = true;
2020-06-27 01:21:58 +03:00
// лучше не ждать, проверим в следующий раз
return;
2020-06-25 09:21:42 +03:00
}
_hasSynced = hasTimeSynced();
if (_hasSynced) {
pm.info("synced " + getDateDigitalFormated() + " " + getTime());
} else {
pm.error("failed to obtain");
}
}
void setupSntp() {
2020-06-27 01:21:58 +03:00
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();
2020-06-25 09:21:42 +03:00
}
2020-06-27 01:21:58 +03:00
bool hasTimeSynced() const {
return _epoch > MIN_DATETIME;
2020-06-25 20:13:20 +03:00
}
2020-06-27 01:21:58 +03:00
time_t getSystemTime() const {
2020-06-25 20:13:20 +03:00
timeval tv{0, 0};
2020-06-27 01:21:58 +03:00
timezone tz = timezone{0, 0};
time_t epoch = 0;
2020-06-25 20:13:20 +03:00
if (gettimeofday(&tv, &tz) != -1) {
2020-06-27 01:21:58 +03:00
epoch = tv.tv_sec;
2020-06-25 20:13:20 +03:00
}
2020-06-27 01:21:58 +03:00
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);
2020-06-25 09:21:42 +03:00
}
private:
2020-06-27 01:21:58 +03:00
Time_t _time;
unsigned long _uptime;
unsigned long _epoch;
2020-06-25 09:21:42 +03:00
int _timezone;
String _ntp;
bool _hasSynced;
bool _configured;
};