mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-08 08:49:52 +03:00
180 lines
5.2 KiB
C++
180 lines
5.2 KiB
C++
/*
|
|
* customized version of Time library, originally Copyright (c) Michael Margolis 2009-2014
|
|
* modified by Paul S https://github.com/PaulStoffregen/Time
|
|
*/
|
|
|
|
#include "TimeLib.h"
|
|
|
|
static tmElements_t tm; // a cache of time elements
|
|
static time_t cacheTime; // the time the cache was updated
|
|
static uint32_t syncInterval = 300; // time sync will be attempted after this many seconds
|
|
static uint32_t sysTime = 0;
|
|
static uint32_t prevMillis = 0;
|
|
static uint32_t nextSyncTime = 0;
|
|
static timeStatus_t Status = timeNotSet;
|
|
getExternalTime getTimePtr; // pointer to external sync function
|
|
|
|
#define LEAP_YEAR(Y) (((1970 + (Y)) > 0) && !((1970 + (Y)) % 4) && (((1970 + (Y)) % 100) || !((1970 + (Y)) % 400)))
|
|
static const uint8_t monthDays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // API starts months from 1, this array starts from 0
|
|
|
|
time_t now() {
|
|
// calculate number of seconds passed since last call to now()
|
|
while (millis() - prevMillis >= 1000) {
|
|
// millis() and prevMillis are both unsigned ints thus the subtraction will always be the absolute value of the difference
|
|
sysTime++;
|
|
prevMillis += 1000;
|
|
}
|
|
if (nextSyncTime <= sysTime) {
|
|
if (getTimePtr != 0) {
|
|
time_t t = getTimePtr();
|
|
if (t != 0) {
|
|
setTime(t);
|
|
} else {
|
|
nextSyncTime = sysTime + syncInterval;
|
|
Status = (Status == timeNotSet) ? timeNotSet : timeNeedsSync;
|
|
}
|
|
}
|
|
}
|
|
return (time_t)sysTime;
|
|
}
|
|
|
|
void setSyncProvider(getExternalTime getTimeFunction) {
|
|
getTimePtr = getTimeFunction;
|
|
nextSyncTime = sysTime;
|
|
now(); // this will sync the clock
|
|
}
|
|
|
|
void setSyncInterval(time_t interval) { // set the number of seconds between re-sync
|
|
syncInterval = (uint32_t)interval;
|
|
nextSyncTime = sysTime + syncInterval;
|
|
}
|
|
|
|
void breakTime(time_t timeInput, tmElements_t & tm) {
|
|
// break the given time_t into time components
|
|
// this is a more compact version of the C library localtime function
|
|
// note that year is offset from 1970 !!!
|
|
|
|
uint8_t year;
|
|
uint8_t month, monthLength;
|
|
uint32_t time;
|
|
unsigned long days;
|
|
|
|
time = (uint32_t)timeInput;
|
|
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.Wday = ((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; // year is offset from 1970
|
|
|
|
days -= LEAP_YEAR(year) ? 366 : 365;
|
|
time -= days; // now it is days in this year, starting at 0
|
|
|
|
month = 0;
|
|
monthLength = 0;
|
|
for (month = 0; month < 12; month++) {
|
|
if (month == 1) { // february
|
|
if (LEAP_YEAR(year)) {
|
|
monthLength = 29;
|
|
} else {
|
|
monthLength = 28;
|
|
}
|
|
} else {
|
|
monthLength = monthDays[month];
|
|
}
|
|
|
|
if (time >= monthLength) {
|
|
time -= monthLength;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
tm.Month = month + 1; // jan is month 1
|
|
tm.Day = time + 1; // day of month
|
|
}
|
|
|
|
// assemble time elements into time_t
|
|
time_t makeTime(const tmElements_t & tm) {
|
|
int i;
|
|
uint32_t seconds;
|
|
|
|
// seconds from 1970 till 1 jan 00:00:00 of the given year
|
|
seconds = tm.Year * (SECS_PER_DAY * 365);
|
|
for (i = 0; i < tm.Year; i++) {
|
|
if (LEAP_YEAR(i)) {
|
|
seconds += SECS_PER_DAY; // add extra days for leap years
|
|
}
|
|
}
|
|
|
|
// add days for this year, months start from 1
|
|
for (i = 1; i < tm.Month; i++) {
|
|
if ((i == 2) && LEAP_YEAR(tm.Year)) {
|
|
seconds += SECS_PER_DAY * 29;
|
|
} else {
|
|
seconds += SECS_PER_DAY * monthDays[i - 1]; // monthDay array starts from 0
|
|
}
|
|
}
|
|
seconds += (tm.Day - 1) * SECS_PER_DAY;
|
|
seconds += tm.Hour * SECS_PER_HOUR;
|
|
seconds += tm.Minute * SECS_PER_MIN;
|
|
seconds += tm.Second;
|
|
return (time_t)seconds;
|
|
}
|
|
|
|
void refreshCache(time_t t) {
|
|
if (t != cacheTime) {
|
|
breakTime(t, tm);
|
|
cacheTime = t;
|
|
}
|
|
}
|
|
|
|
uint8_t to_second(time_t t) { // the second for the given time
|
|
refreshCache(t);
|
|
return tm.Second;
|
|
}
|
|
|
|
uint8_t to_minute(time_t t) { // the minute for the given time
|
|
refreshCache(t);
|
|
return tm.Minute;
|
|
}
|
|
|
|
uint8_t to_hour(time_t t) { // the hour for the given time
|
|
refreshCache(t);
|
|
return tm.Hour;
|
|
}
|
|
|
|
uint8_t to_day(time_t t) { // the day for the given time (0-6)
|
|
refreshCache(t);
|
|
return tm.Day;
|
|
}
|
|
|
|
uint8_t to_month(time_t t) { // the month for the given time
|
|
refreshCache(t);
|
|
return tm.Month;
|
|
}
|
|
|
|
uint8_t to_weekday(time_t t) {
|
|
refreshCache(t);
|
|
return tm.Wday;
|
|
}
|
|
|
|
uint16_t to_year(time_t t) { // the year for the given time
|
|
refreshCache(t);
|
|
return tm.Year + 1970;
|
|
}
|
|
|
|
void setTime(time_t t) {
|
|
sysTime = (uint32_t)t;
|
|
nextSyncTime = (uint32_t)t + syncInterval;
|
|
Status = timeSet;
|
|
prevMillis = millis(); // restart counting from now (thanks to Korman for this fix)
|
|
}
|