");
poststr(request, sensdataset->sensors[i].names.name_friendly);
poststr(request, " ");
@@ -197,18 +201,18 @@ void BL09XX_AppendInformationToHTTPIndexPage(http_request_t * request, int bPreS
{
poststr(request, "Energy Clear Date: ");
if (ConsumptionResetTime) {
- ltm = gmtime(&ConsumptionResetTime);
+/* ltm = gmtime(&ConsumptionResetTime);
hprintf255(request, "%04d-%02d-%02d %02d:%02d:%02d",
ltm->tm_year+1900, ltm->tm_mon+1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec);
+*/
+ hprintf255(request, "%s",TS2STR(ConsumptionResetTime,TIME_FORMAT_LONG));
} else {
poststr(request, "(not set)");
}
hprintf255(request, " ");
- if(DRV_IsRunning("NTP")==false) {
- hprintf255(request,"NTP driver is not started, daily energy stats disabled.");
- } else if (!NTP_IsTimeSynced()) {
- hprintf255(request,"Daily energy stats awaiting NTP driver to sync real time...");
+ if(TIME_IsTimeSynced()==false) {
+ hprintf255(request,"Device time not in sync, daily energy stats disabled.");
}
hprintf255(request, " ");
@@ -324,7 +328,7 @@ commandResult_t BL09XX_ResetEnergyCounterEx(int asensdatasetix, float* pvalue)
sensdataset->sensors[OBK_CONSUMPTION_TOTAL].lastReading = *pvalue;
energyCounterStamp[asensdatasetix] = xTaskGetTickCount();
}
- ConsumptionResetTime = (time_t)NTP_GetCurrentTime();
+ ConsumptionResetTime = (time_t)TIME_GetCurrentTime();
if (OTA_GetProgress()==-1)
{
BL09XX_SaveEmeteringStatistics();
@@ -630,8 +634,8 @@ void BL_ProcessUpdate(float voltage, float current, float power,
cJSON* stats;
char *msg;
portTickType interval;
- time_t ntpTime;
- struct tm *ltm;
+ time_t deviceTime;
+// struct tm *ltm;
char datetime[64];
float diff;
@@ -699,23 +703,27 @@ void BL_ProcessUpdate(float voltage, float current, float power,
#endif
sensdataset->sensors[OBK_CONSUMPTION_TODAY].lastReading += energy;
- if (NTP_IsTimeSynced()) {
- ntpTime = (time_t)NTP_GetCurrentTime();
- ltm = gmtime(&ntpTime);
+ if (TIME_IsTimeSynced()) {
+ deviceTime = (time_t)TIME_GetCurrentTime();
+// ltm = gmtime(&deviceTime);
+ uint8_t mday=TIME_GetMDay();
if (ConsumptionResetTime == 0)
- ConsumptionResetTime = (time_t)ntpTime;
+ ConsumptionResetTime = (time_t)deviceTime;
if (actual_mday[asensdatasetix] == -1)
{
- actual_mday[asensdatasetix] = ltm->tm_mday;
+// actual_mday[asensdatasetix] = ltm->tm_mday;
+ actual_mday[asensdatasetix] = mday;
}
- if (actual_mday[asensdatasetix] != ltm->tm_mday)
+// if (actual_mday[asensdatasetix] != ltm->tm_mday)
+ if (actual_mday[asensdatasetix] != mday)
{
for (i = OBK_CONSUMPTION__DAILY_LAST; i >= OBK_CONSUMPTION__DAILY_FIRST; i--) {
sensdataset->sensors[i].lastReading = sensdataset->sensors[i - 1].lastReading;
}
sensdataset->sensors[OBK_CONSUMPTION_TODAY].lastReading = 0.0;
- actual_mday[asensdatasetix] = ltm->tm_mday;
+// actual_mday[asensdatasetix] = ltm->tm_mday;
+ actual_mday[asensdatasetix] = mday;
//MQTT_PublishMain_StringFloat(sensdataset->sensors[OBK_CONSUMPTION_YESTERDAY].names.name_mqtt, BL_ChangeEnergyUnitIfNeeded(sensors[OBK_CONSUMPTION_YESTERDAY].lastReading ),
// sensdataset->sensors[OBK_CONSUMPTION_YESTERDAY].rounding_decimals, 0);
@@ -751,21 +759,34 @@ void BL_ProcessUpdate(float voltage, float current, float power,
cJSON_AddNumberToObject(root, "consumption_stat_index", energyCounterMinutesIndex);
cJSON_AddNumberToObject(root, "consumption_sample_count", energyCounterSampleCount);
cJSON_AddNumberToObject(root, "consumption_sampling_period", energyCounterSampleInterval);
- if(NTP_IsTimeSynced() == true)
+ if(TIME_IsTimeSynced() == true)
{
cJSON_AddNumberToObject(root, "consumption_today", BL_ChangeEnergyUnitIfNeeded(DRV_GetReading(OBK_CONSUMPTION_TODAY)));
cJSON_AddNumberToObject(root, "consumption_yesterday", BL_ChangeEnergyUnitIfNeeded(DRV_GetReading(OBK_CONSUMPTION_YESTERDAY)));
- ltm = gmtime(&ConsumptionResetTime);
- if (NTP_GetTimesZoneOfsSeconds()>0)
+// ltm = gmtime(&ConsumptionResetTime);
+/*
+ if (TIME_GetTimesZoneOfsSeconds()>0)
{
snprintf(datetime,sizeof(datetime), "%04i-%02i-%02iT%02i:%02i+%02i:%02i",
ltm->tm_year+1900, ltm->tm_mon+1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min,
- NTP_GetTimesZoneOfsSeconds()/3600, (NTP_GetTimesZoneOfsSeconds()/60) % 60);
+ TIME_GetTimesZoneOfsSeconds()/3600, (TIME_GetTimesZoneOfsSeconds()/60) % 60);
} else {
snprintf(datetime, sizeof(datetime), "%04i-%02i-%02iT%02i:%02i-%02i:%02i",
ltm->tm_year+1900, ltm->tm_mon+1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min,
- abs(NTP_GetTimesZoneOfsSeconds()/3600), (abs(NTP_GetTimesZoneOfsSeconds())/60) % 60);
+ abs(TIME_GetTimesZoneOfsSeconds()/3600), (abs(TIME_GetTimesZoneOfsSeconds())/60) % 60);
}
+*/
+ // optimized output: since we can be sure, a negative offset is minumum 1 hour,
+ // the sign for the hour will be "-" for "negative" timezones
+ // this wouldn't work if a negative offset less than one hour would be possible
+/*
+ snprintf(datetime, sizeof(datetime), "%04i-%02i-%02iT%02i:%02i%+03i:%02i",
+ ltm->tm_year+1900, ltm->tm_mon+1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min,
+ TIME_GetTimesZoneOfsSeconds()/3600, (abs(TIME_GetTimesZoneOfsSeconds())/60) % 60);
+*/
+ snprintf(datetime, sizeof(datetime), "%.16s%+03i:%02i",TS2STR(ConsumptionResetTime, TIME_FORMAT_ISO_8601),
+ TIME_GetTimesZoneOfsSeconds()/3600, (abs(TIME_GetTimesZoneOfsSeconds())/60) % 60);
+
cJSON_AddStringToObject(root, "consumption_clear_date", datetime);
}
@@ -881,18 +902,31 @@ void BL_ProcessUpdate(float voltage, float current, float power,
if (i == OBK_CONSUMPTION_CLEAR_DATE) {
{
sensdataset->sensors[i].lastReading = ConsumptionResetTime; //Only to make the 'nochangeframe' mechanism work here
- ltm = gmtime(&ConsumptionResetTime);
+// ltm = gmtime(&ConsumptionResetTime);
/* 2019-09-07T15:50-04:00 */
- if (NTP_GetTimesZoneOfsSeconds()>0)
+/*
+ if (TIME_GetTimesZoneOfsSeconds()>0)
{
snprintf(datetime, sizeof(datetime), "%04i-%02i-%02iT%02i:%02i+%02i:%02i",
ltm->tm_year+1900, ltm->tm_mon+1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min,
- NTP_GetTimesZoneOfsSeconds()/3600, (NTP_GetTimesZoneOfsSeconds()/60) % 60);
+ TIME_GetTimesZoneOfsSeconds()/3600, (TIME_GetTimesZoneOfsSeconds()/60) % 60);
} else {
snprintf(datetime, sizeof(datetime), "%04i-%02i-%02iT%02i:%02i-%02i:%02i",
ltm->tm_year+1900, ltm->tm_mon+1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min,
- abs(NTP_GetTimesZoneOfsSeconds()/3600), (abs(NTP_GetTimesZoneOfsSeconds())/60) % 60);
+ abs(TIME_GetTimesZoneOfsSeconds()/3600), (abs(TIME_GetTimesZoneOfsSeconds())/60) % 60);
}
+*/
+ // optimized output: since we can be sure, a negative offset is minumum 1 hour,
+ // the sign for the hour will be "-" for "negative" timezones
+ // this wouldn't work if a negative offset less than one hour would be possible
+/*
+ snprintf(datetime, sizeof(datetime), "%04i-%02i-%02iT%02i:%02i%+03i:%02i",
+ ltm->tm_year+1900, ltm->tm_mon+1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min,
+ TIME_GetTimesZoneOfsSeconds()/3600, (abs(TIME_GetTimesZoneOfsSeconds())/60) % 60);
+*/
+ snprintf(datetime, sizeof(datetime), "%.16s%+03i:%02i",TS2STR(ConsumptionResetTime, TIME_FORMAT_ISO_8601),
+ TIME_GetTimesZoneOfsSeconds()/3600, (abs(TIME_GetTimesZoneOfsSeconds())/60) % 60);
+
MQTT_PublishMain_StringString(sensdataset->sensors[i].names.name_mqtt, datetime, 0);
}
} else { //all other sensors
diff --git a/src/driver/drv_charts.c b/src/driver/drv_charts.c
index ceae8ae85..27f5dd3ac 100644
--- a/src/driver/drv_charts.c
+++ b/src/driver/drv_charts.c
@@ -8,6 +8,8 @@
#include "../hal/hal_pins.h"
#include "../httpserver/new_http.h"
#include "drv_ntp.h"
+#include "drv_deviceclock.h"
+
/*
// Sample 1
// single variable chart
@@ -638,7 +640,7 @@ static commandResult_t CMD_Chart_AddNow(const void *context, const char *cmd, co
float f = Tokenizer_GetArgFloat(i);
Chart_SetSample(g_chart, i, f);
}
- Chart_AddTime(g_chart, NTP_GetCurrentTimeWithoutOffset()); // Fix issue #1376 .....was NTP_GetCurrentTime() ... now "WithoutOffset" since NTP drivers timestamp are already offsetted
+ Chart_AddTime(g_chart, TIME_GetCurrentTimeWithoutOffset()); // Fix issue #1376 .....was NTP_GetCurrentTime() ... now "WithoutOffset" since NTP drivers timestamp are already offsetted
return CMD_RES_OK;
}
diff --git a/src/driver/drv_deviceclock.c b/src/driver/drv_deviceclock.c
new file mode 100644
index 000000000..bdab58c04
--- /dev/null
+++ b/src/driver/drv_deviceclock.c
@@ -0,0 +1,606 @@
+
+//#include
+
+#include "../new_common.h"
+#include "../new_cfg.h"
+// Commands register, execution API and cmd tokenizer
+#include "../cmnds/cmd_public.h"
+#include "../httpserver/new_http.h"
+#include "../logging/logging.h"
+
+#include "drv_deviceclock.h"
+#include "../libraries/obktime/obktime.h"
+// functions for handling device time even without NTP driver present
+// using "g_epochOnStartup" and "g_UTCoffset" if NTP not present (or not synced)
+
+#include "drv_ntp.h"
+#include
+
+
+// "eoch" on startup of device; If we add g_secondsElapsed we get the actual time
+uint32_t g_epochOnStartup = 0;
+// UTC offset
+int g_UTCoffset = 0;
+void TIME_setDeviceTime(uint32_t time){
+ ADDLOG_DEBUG(LOG_FEATURE_RAW, "TIME_setDeviceTime - time = %lu - g_secondsElapsed =%lu \r\n",time,g_secondsElapsed);
+#if (ENABLE_DRIVER_DS3231)
+ uint32_t temp = g_epochOnStartup;
+#endif
+ g_epochOnStartup = (uint32_t)time - g_secondsElapsed;
+#if ENABLE_TIME_DST
+ setDST(); // just to be sure: recalculate DST
+#endif
+#if (ENABLE_DRIVER_DS3231)
+#include "drv_public.h"
+#include "drv_ds3231.h"
+// ADDLOG_DEBUG(LOG_FEATURE_RAW, "TIME_setDeviceTime 1 - temp = %lu - g_epochOnStartup = %lu \r\n",temp,g_epochOnStartup);
+ temp -= g_epochOnStartup;
+// ADDLOG_DEBUG(LOG_FEATURE_RAW, "TIME_setDeviceTime 2 - temp = %lu \r\n",temp);
+ if (DRV_IsRunning("DS3231")) DS3231_informClockWasSet( (temp*temp > 25)); // use "force" if new time differs more than 5 seconds (temp*temp is allways positive)
+#endif
+
+// ADDLOG_INFO(LOG_FEATURE_RAW, "TIME_setDeviceTime - time = %lu - g_secondsElapsed =%lu - g_epochOnStartup=%lu \r\n",time,g_secondsElapsed,g_epochOnStartup);
+}
+
+void TIME_setDeviceTimeOffset(int offs){
+// ADDLOG_INFO(LOG_FEATURE_RAW, "TIME_setDeviceTimeOffset - offs = %i\r\n",offs);
+ g_UTCoffset = offs;
+}
+
+commandResult_t SetTimeZoneOfs(const void *context, const char *cmd, const char *args, int cmdFlags) {
+ int a, b;
+ const char *arg;
+ int oldOfs = g_UTCoffset;
+
+ Tokenizer_TokenizeString(args,0);
+ // following check must be done after 'Tokenizer_TokenizeString',
+ // so we know arguments count in Tokenizer. 'cmd' argument is
+ // only for warning display
+ if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) {
+ return CMD_RES_NOT_ENOUGH_ARGUMENTS;
+ }
+ arg = Tokenizer_GetArg(0);
+ if (strchr(arg, ':')) {
+ int useSign = 1;
+ if (*arg == '-') {
+ arg++;
+ useSign = -1;
+ }
+ sscanf(arg, "%i:%i", &a, &b);
+ g_UTCoffset = useSign * (a * 60 * 60 + b * 60);
+ }
+ else {
+ g_UTCoffset = Tokenizer_GetArgInteger(0) * 60 * 60;
+ }
+#if WINDOWS
+ NTP_SetTimesZoneOfsSeconds(g_UTCoffset);
+#endif
+#if ENABLE_TIME_DST
+ setDST(); // check if local time is DST or not and set offset
+#endif
+ addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"Time offset set to %i seconds"
+#if ENABLE_TIME_DST
+ " (DST offset %i seconds)"
+#endif
+ ,g_UTCoffset
+#if ENABLE_TIME_DST
+ ,getDST_offset()
+#endif
+ );
+ return CMD_RES_OK;
+}
+
+commandResult_t SetDeviceTime(const void *context, const char *cmd, const char *args, int cmdFlags) {
+ Tokenizer_TokenizeString(args,0);
+ // following check must be done after 'Tokenizer_TokenizeString',
+ // so we know arguments count in Tokenizer. 'cmd' argument is
+ // only for warning display
+ if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) {
+ return CMD_RES_NOT_ENOUGH_ARGUMENTS;
+ }
+// uint32_t t=Tokenizer_GetArgInteger(0);
+ uint32_t t1=atol(Tokenizer_GetArg(0));
+// TIME_setDeviceTime(Tokenizer_GetArgInteger(0));
+ TIME_setDeviceTime(t1);
+#if ENABLE_TIME_DST
+ setDST(); // check if local time is DST or not and set offset
+#endif
+ return CMD_RES_OK;
+}
+
+
+
+#if ENABLE_TIME_DST
+static uint32_t next_DST_switch_epoch=0;
+
+typedef struct {
+ // DST configuration 1 (16 bits)
+ unsigned week1 : 3; // 0-7 (3 bits)
+ unsigned month1 : 4; // 1-12 (4 bits)
+ unsigned day1 : 3; // 0-6 (3 bits) 0=sunday 1=monday ...
+ unsigned hour1 : 5; // 0-23 (5 bits)
+ unsigned isDST1 : 1; // 0: no (end of DST) 1 yes (start of DST)
+
+ // DST configuration 2 (16 bits)
+ unsigned week2 : 3; // 0-7 (3 bits)
+ unsigned month2 : 4; // 1-12 (4 bits)
+ unsigned day2 : 3; // 0-6 (3 bits) 0=sunday 1=monday ...
+ unsigned hour2 : 5; // 0-23 (5 bits)
+ unsigned isDST2 : 1; // 0: no (end of DST) 1 yes (start of DST)
+
+ // DST offset in seconds (13 bits: 0-8191 seconds (136 minutes; maximum DST is 2 hours)
+ unsigned DSToffset : 13;
+
+ // DST state (3 bits)
+ unsigned DSTactive : 1; // 0=inactive, 1=active
+ unsigned DSTinitialized : 1; // 0=uninitialized, 1=initialized
+ unsigned : 1; // Padding/reserved
+} DSTcfg;
+
+
+static DSTcfg dst_config = {0};
+
+#define useDST (dst_config.DSTinitialized)
+
+#endif
+
+extern void TIME_Init_Events(void);
+extern void TIME_RunEvents(unsigned int newTime, bool bTimeValid);
+
+#if ENABLE_TIME_SUNRISE_SUNSET
+extern void TIME_CalculateSunrise(byte *outHour, byte *outMinute);
+extern void TIME_CalculateSunset(byte *outHour, byte *outMinute);
+#endif
+
+// leave it for the moment, until a TIME logging is possible ...
+#define LOG_FEATURE LOG_FEATURE_NTP
+
+#if ENABLE_TIME_SUNRISE_SUNSET
+
+/* sunrise/sunset defaults */
+#define CFG_DEFAULT_LATITUDE 43.994131
+#define CFG_DEFAULT_LONGITUDE -123.095854
+#define SUN_DATA_COORD_MULT 1000000
+
+struct SUN_DATA sun_data =
+ {
+ .latitude = (int) (CFG_DEFAULT_LATITUDE * SUN_DATA_COORD_MULT),
+ .longitude = (int) (CFG_DEFAULT_LONGITUDE * SUN_DATA_COORD_MULT),
+ };
+
+//Set Latitude and Longitude for sunrise/sunset calc
+commandResult_t TIME_SetLatlong(const void *context, const char *cmd, const char *args, int cmdFlags) {
+ const char *newValue;
+
+ Tokenizer_TokenizeString(args,0);
+ // following check must be done after 'Tokenizer_TokenizeString',
+ // so we know arguments count in Tokenizer. 'cmd' argument is
+ // only for warning display
+ if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 2)) {
+ return CMD_RES_NOT_ENOUGH_ARGUMENTS;
+ }
+ newValue = Tokenizer_GetArg(0);
+ TIME_setLatitude(atof(newValue));
+ addLogAdv(LOG_INFO, LOG_FEATURE_NTP, "TIME latitude set to %s", newValue);
+
+ newValue = Tokenizer_GetArg(1);
+ TIME_setLongitude(atof(newValue));
+ addLogAdv(LOG_INFO, LOG_FEATURE_NTP, "TIME longitude set to %s", newValue);
+ return CMD_RES_OK;
+}
+
+void TIME_setLatitude(float lat){
+ sun_data.latitude = (int) (lat * SUN_DATA_COORD_MULT);
+};
+
+void TIME_setLongitude(float longi){
+ sun_data.longitude = (int) (longi * SUN_DATA_COORD_MULT);
+};
+
+
+float TIME_GetLatitude(){
+ return (float)sun_data.latitude/SUN_DATA_COORD_MULT;
+};
+
+float TIME_GetLongitude(){
+ return (float)sun_data.longitude/SUN_DATA_COORD_MULT ;
+};
+
+int TIME_GetSunrise()
+{
+ byte hour, minute;
+ int sunriseInSecondsFromMidnight;
+
+ TIME_CalculateSunrise(&hour, &minute);
+ addLogAdv(LOG_INFO, LOG_FEATURE_NTP, "TIME sunrise is at %02i:%02i", hour, minute);
+ sunriseInSecondsFromMidnight = ((int)hour * 3600) + ((int)minute * 60);
+ return sunriseInSecondsFromMidnight;
+}
+
+int TIME_GetSunset()
+{
+ byte hour, minute;
+ int sunsetInSecondsFromMidnight;
+
+ TIME_CalculateSunset(&hour, &minute);
+ addLogAdv(LOG_INFO, LOG_FEATURE_NTP, "TIME sunset is at %02i:%02i", hour, minute);
+ sunsetInSecondsFromMidnight = ((int)hour * 3600) + ((int)minute * 60);
+ return sunsetInSecondsFromMidnight;
+}
+#endif
+
+// Shared implementation helper
+static TimeComponents getCurrentComponents(void) {
+ return calculateComponents(TIME_GetCurrentTime());
+}
+
+// Individual getter functions
+int TIME_GetSecond(void) {
+ return getCurrentComponents().second;
+}
+
+int TIME_GetMinute(void) {
+ return getCurrentComponents().minute;
+}
+
+int TIME_GetHour(void) {
+ return getCurrentComponents().hour;
+}
+
+int TIME_GetMDay(void) {
+ return getCurrentComponents().day;
+}
+
+int TIME_GetMonth(void) {
+ return getCurrentComponents().month;
+}
+
+int TIME_GetYear(void) {
+ return getCurrentComponents().year;
+}
+
+int TIME_GetWeekDay(void) {
+ return getCurrentComponents().wday;
+}
+
+
+#if ENABLE_TIME_DST
+
+
+// new approach for "RuleToTime" to find epoch of DST transitions
+// we will use "normal" weekday count here (sun=0, so if we use Tasmota-style sun=1,
+// do fix that when calling this function !!!
+uint32_t RuleToTime(uint8_t dayOfWeek, uint8_t month, uint8_t weekNum, uint8_t hour, uint16_t year) {
+ // check for valid input
+ if (month < 1 || month > 12 || weekNum > 5 || dayOfWeek > 6) return 0;
+ // when looking for "last" occurrence, we search the first in following month and then substract 7 days
+ // else we search the first occurence in given month. If we look for second, third ... occurrenc, advance multiple of 7 days )
+ int8_t daysToAdd = (weekNum == 0) ? -7 : (weekNum - 1) * 7;
+
+
+ // not nice, but working: if rule is "last day" in December, we will ask for a date in January of next year.
+ // E.g. to get the "last sunday in December 2025 at 4", we would call e.g. "dateToEpoch(2026, 1, 0, 4, 0, 0);"
+ //
+ // BUT we can also call "dateToEpoch(2025, 13, 0, 4, 0, 0);" in this special case, knowing the implementation ao dateToEpoch:
+ // We add all days of the years before and then the "days per month" _before_ the actual month + the days in the actual month
+ // In this special case (month=13), we only add all days per month up to 12, which is a valid operation (days in a year = sum of days in january to december)
+ //
+ // So we can avoid another special case for December and only take the disadvantage not to add 365 (or 366) in one but in 12 parts...
+ //
+ uint32_t retval = dateToEpoch(year, month + (weekNum == 0), 1, hour, 0, 0);
+
+ uint8_t firstWeekday = (retval / SECS_PER_DAY + 4) % 7; // 1970-01-01 is Thursday ( = 4)
+
+ // if the weekday of the first day in a month is the one we are looking for (dayOfWeek == firstWeekday), we are done (0+7)%7=0 .
+ // else we need to advance to that day
+ daysToAdd += (dayOfWeek - firstWeekday + 7) % 7;
+
+
+ return retval + daysToAdd * SECS_PER_DAY;
+}
+
+
+
+int getDST_offset() {
+ return dst_config.DSTactive ? dst_config.DSToffset : 0;
+}
+
+int IsDST() {
+ return dst_config.DSTactive;
+}
+
+bool IsDST_initialized() {
+ return dst_config.DSTinitialized;
+}
+
+
+// make sure pointer is e.g. uint32_t DST[2];
+void getDSTtransition(uint32_t * DST){
+ // if first entry starts DST, isDST2 will be 0 else it will be 1
+ DST[dst_config.isDST2] = (RuleToTime(dst_config.day1, dst_config.month1, dst_config.week1, dst_config.hour1, TIME_GetYear()));
+ // if second entry starts DST, isDST1 will be 0 else it will be 1
+ DST[dst_config.isDST1] = (RuleToTime(dst_config.day2, dst_config.month2, dst_config.week2, dst_config.hour2, TIME_GetYear()));
+}
+
+// this will calculate the actual DST stage and the time of the next DST switch
+
+uint32_t setDST() {
+ if (!dst_config.DSTinitialized || !TIME_IsTimeSynced()) {
+ return 0;
+ }
+
+ uint16_t year = (uint16_t)TIME_GetYear();
+ time_t tempt = (time_t)TIME_GetCurrentTimeWithoutOffset();
+ int old_DST_active = dst_config.DSTactive;
+
+ next_DST_switch_epoch = (RuleToTime(dst_config.day1, dst_config.month1, dst_config.week1, dst_config.hour1, year) - g_UTCoffset - dst_config.isDST2 * dst_config.DSToffset);
+ if ( tempt < next_DST_switch_epoch){
+ dst_config.DSTactive = dst_config.isDST2;
+ }
+ else {
+ next_DST_switch_epoch = (RuleToTime(dst_config.day2, dst_config.month2, dst_config.week2, dst_config.hour2, year) - g_UTCoffset - dst_config.isDST1 * dst_config.DSToffset);
+ if (tempt < next_DST_switch_epoch){
+ dst_config.DSTactive = dst_config.isDST1;
+ }
+ else {
+ next_DST_switch_epoch = RuleToTime(dst_config.day1, dst_config.month1, dst_config.week1, dst_config.hour1, year+1) - g_UTCoffset - (dst_config.isDST2) * dst_config.DSToffset;
+ dst_config.DSTactive = dst_config.isDST2;
+ }
+ }
+
+ tempt = next_DST_switch_epoch + (uint32_t)g_UTCoffset + (dst_config.DSTactive)*dst_config.DSToffset; // DST calculation is in UTC, so add offset for local time
+#if ENABLE_TIME_SUNRISE_SUNSET
+ if (old_DST_active != dst_config.DSTactive){
+ // if we had a DST switch, we might corect sunset/sunrise events, which were calculated before (with "previous" DST settings)
+ // if we changed to DST, we need to add DST_offset (old_DST_active = 0)
+ // if we were in DST before switch, we need to sub DST_offset (old_DST_active = 1)
+ int fix_DSTMinutes = (dst_config.DSToffset / 60);
+ fix_DSTMinutes *= old_DST_active ? -1 : 1;
+ ADDLOG_INFO(LOG_FEATURE_RAW, "DST switch - calling fix_DSTforEvents(%d)\r\n", fix_DSTMinutes );
+ fix_DSTforEvents(fix_DSTMinutes);
+ }
+#endif
+ ADDLOG_INFO(LOG_FEATURE_RAW, "In %s time - next DST switch at %u (%s) \r\n", (dst_config.DSTactive)?"summer":"standard", (uint32_t)tempt, TS2STR(tempt,TIME_FORMAT_LONG));
+
+ return dst_config.DSTactive;
+}
+
+
+
+//
+// | |-- 1st rule: last_week March sunday 2_o_clock 60_minutes_DST_after_this_time
+// TIME_setDST 0 3 1 2 60 0 10 1 3 0
+// | |-- 2nd_rule: last_week October sunday 3_o_clock 0_minutes_DST_after_this_time
+commandResult_t TIME_SetDST(const int *args) {
+ // d1/d2 for day and DST values, needed more than once, so store values to avoid multiple "GetArg" calls
+ uint8_t d1,d2;
+
+ // DST1 must be before DST2
+ int add = (args[1] < args[6])? 0 : 5; // check if first entry is "before" second (compare month number)
+ dst_config.week1 = args[add];
+ dst_config.month1 = args[1+add];
+ dst_config.day1 = args[2+add]-1;
+ dst_config.hour1 = args[3+add];
+ d1 = args[4+add]; // first DST offset
+ // Second DST configuration - if we added 5 for first DST, we need to sub 5 now (no change for add=0)
+ add *= -1;
+ dst_config.week2 = args[5+add];
+ dst_config.month2 = args[6+add];
+ dst_config.day2 = args[7+add]-1;
+ dst_config.hour2 = args[8+add];
+ d2 = args[9+add]; // second DST offset
+
+ // no case needed for "DSToffset": one entry must be 0, one != 0, so if valid, the sum is the DST offset
+ dst_config.DSToffset = 60*(d1+d2)*(d1*d2 == 0);
+ if ( dst_config.DSToffset == 0 ) return CMD_RES_BAD_ARGUMENT; // neither two times 0 nor two times != 0 is valid !
+
+
+ dst_config.isDST1 = (d1 != 0);
+ dst_config.isDST2 = (d2 != 0);
+
+ if (TIME_IsTimeSynced()) setDST();
+
+ dst_config.DSTinitialized = 1;
+
+ addLogAdv(LOG_INFO, LOG_FEATURE_NTP, "DST config set: offset=%d seconds",
+ dst_config.DSToffset);
+ return CMD_RES_OK;
+}
+
+//
+// | |-- 1st rule: last_week March sunday 2_o_clock 60_minutes_DST_after_this_time
+// TIME_setDST 0 3 1 2 60 0 10 1 3 0
+// | |-- 2nd_rule: last_week October sunday 3_o_clock 0_minutes_DST_after_this_time
+commandResult_t CMD_TIME_SetDST(const void *context, const char *cmd, const char *args, int cmdFlags) {
+ Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES);
+ if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 10)) {
+ return CMD_RES_NOT_ENOUGH_ARGUMENTS;
+ }
+ int clkargs[10];
+ for (int i=0; i<10; i++){
+ clkargs[i]=Tokenizer_GetArgInteger(i);
+ }
+ return TIME_SetDST(clkargs);
+}
+
+
+
+
+// to keep compatibility to prior command
+commandResult_t CMD_TIME_CalcDST(const void *context, const char *cmd, const char *args, int cmdFlags) {
+ // arguments: nthWeekEnd, monthEnd, dayEnd, hourEnd, nthWeekStart, monthStart, dayStart, hourStart,g_DST_offset
+ // we know that new command "TIME_setDST" will take care or finding first or last DST event, so only add "0" as DST-Offset for "ending" (arg[4])
+ // and use 1 as default DST if non given (arg[9])
+ //
+ // for reference
+ //
+ //
+ // | |-- 1st rule: last_week March sunday 2_o_clock 60_minutes_DST_after_this_time
+ // TIME_setDST 0 3 1 2 60 0 10 1 3 0
+ // | |-- 2nd_rule: last_week October sunday 3_o_clock 0_minutes_DST_after_this_time
+ //
+
+ Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES);
+ // following check must be done after 'Tokenizer_TokenizeString',
+ // so we know arguments count in Tokenizer. 'cmd' argument is
+ // only for warning display
+ if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 8)) {
+ return CMD_RES_NOT_ENOUGH_ARGUMENTS;
+ }
+
+ int clkargs[10];
+ clkargs[4]=0; // starts with "DST-End", so after this DST offset is 0
+ for (int i=0; i<4; i++){
+ clkargs[i]=Tokenizer_GetArgInteger(i);
+ }
+ for (int i=4; i<8; i++){
+ clkargs[i+1]=Tokenizer_GetArgInteger(i);
+ }
+ clkargs[9]=Tokenizer_GetArgIntegerDefault(8, 1)*60; // we'll use minutes with TIME_SetDST
+ return TIME_SetDST(clkargs);
+}
+
+
+int Time_IsDST(){
+ return IsDST();
+}
+#endif
+
+
+void TIME_Init() {
+
+#if ENABLE_TIME_SUNRISE_SUNSET
+ //cmddetail:{"name":"time_setLatLong","args":"[Latlong]",
+ //cmddetail:"descr":"Sets the devices latitude and longitude",
+ //cmddetail:"fn":"TIME_SetLatlong","file":"driver/drv_deviceclock.c","requires":"",
+ //cmddetail:"examples":"TIME_SetLatlong -34.911498 138.809488"}
+ CMD_RegisterCommand("time_setLatLong", TIME_SetLatlong, NULL);
+// and register an alias for backward compatibility
+ //cmddetail:{"name":"ntp_setLatLong","args":"[Latlong]",
+ //cmddetail:"descr":"Depreciated! Only for backward compatibility! Please use 'time_setLatLong' in the future!",
+ //cmddetail:"fn":"TIME_SetLatlong","file":"driver/drv_deviceclock.c","requires":"",
+ //cmddetail:"examples":"ntp_SetLatlong -34.911498 138.809488"}
+ CMD_RegisterCommand("ntp_setLatLong", TIME_SetLatlong, NULL);
+#endif
+#if ENABLE_CALENDAR_EVENTS
+ TIME_Init_Events();
+#endif
+#if ENABLE_TIME_DST
+ //cmddetail:{"name":"TIME_setDST","args":" Rule# [1/2] nthWeek month day hour DSToffset [additional minutes _after_ this Point: for "start" of DST, 0 for "end" of DST]",
+ //cmddetail:"descr":"Checks, if actual time is during DST or not.",
+ //cmddetail:"fn":"CLOCK_CalcDST","file":"driver/drv_deviceclock.c","requires":"",
+ //cmddetail:"examples":"TIME_setDST 0 3 1 2 1 0 10 1 3 0 -- 1st rule: last_week March sunday 2_o_clock 1_hour_DST_after_this_time -- 2nd_rule: last_week October sunday 3_o_clock 0_hours_DST_after_this_time "}
+ CMD_RegisterCommand("time_setDST",CMD_TIME_SetDST, NULL);
+ //cmddetail:{"name":"CLOCK_calcDST","args":" Depreciated! Only for backward compatibility! Please use 'TIME_setDST' in the future!",
+ //cmddetail:"descr":"Sets DST settings.",
+ //cmddetail:"fn":"CLOCK_CalcDST","file":"driver/drv_deviceclock.c","requires":"",
+ //cmddetail:"examples":"CLOCK_calcDST 0 10 1 3 0 3 1 2 1 -- DST-End: last_week(0) October(10) sunday(1) 3_o_clock(3) - DST-Start: last_week(0) March(3) sunday(1) 2_o_clock(2) 1_hour_DST_offset"}
+ CMD_RegisterCommand("clock_calcDST",CMD_TIME_CalcDST, NULL);
+
+ dst_config.DSTinitialized = 0;
+
+#endif
+ //cmddetail:{"name":"time_setTZ","args":"[Value]",
+ //cmddetail:"descr":"Sets the time zone offset in hours. Also supports HH:MM syntax if you want to specify value in minutes. For negative values, use -HH:MM syntax, for example -5:30 will shift time by 5 hours and 30 minutes negative.",
+ //cmddetail:"fn":"SetTimeZoneOfs","file":"driver/drv_deviceclock.c","requires":"",
+ //cmddetail:"examples":""}
+ CMD_RegisterCommand("time_setTZ",SetTimeZoneOfs, NULL);
+ //cmddetail:{"name":"time_setTime","args":"[Value]",
+ //cmddetail:"descr":"Sets the time of device in seconds after 19700101.",
+ //cmddetail:"fn":"SetDeviceTime","file":"driver/drv_deviceclock.c","requires":"",
+ //cmddetail:"examples":""}
+ CMD_RegisterCommand("time_setTime",SetDeviceTime, NULL);
+ addLogAdv(LOG_INFO, LOG_FEATURE_NTP, "CLOCK driver initialized.");
+}
+
+void TIME_OnEverySecond()
+{
+
+#if ENABLE_CALENDAR_EVENTS
+ TIME_RunEvents(TIME_GetCurrentTime(), TIME_IsTimeSynced());
+#endif
+#if ENABLE_TIME_DST
+ if (useDST && TIME_IsTimeSynced() && (TIME_GetCurrentTimeWithoutOffset() >= next_DST_switch_epoch)){
+ int old_DST=getDST_offset();
+ setDST();
+ addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"Passed DST switch time - recalculated DST offset. Was:%i - now:%i",old_DST,getDST_offset());
+ }
+#endif
+
+
+}
+
+
+uint32_t TIME_GetCurrentTime(){ // replacement for NTP_GetCurrentTime() to return time regardless of NTP present/running
+// if we use "LOCAL_CLOCK", NTP will set this clock if enabled, so no further check needed
+uint32_t temp=0;
+ if (g_epochOnStartup > 10) {
+ temp = g_epochOnStartup + g_secondsElapsed + g_UTCoffset;
+#if ENABLE_TIME_DST
+ temp += getDST_offset();
+#endif
+ } // no "else" needed, will return 0 anyway if we don't return here
+// addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"TIME_GetCurrentTime - returning :%lu (g_epochOnStartup=%lu g_secondsElapsed=%lu g_UTCoffset=%i DST=%i)",temp,g_epochOnStartup, g_secondsElapsed, g_UTCoffset,getDST_offset());
+ return temp; // we will report 1970-01-01 if no time present - avoids "hack" e.g. in json status ...
+
+};
+
+uint32_t TIME_GetCurrentTimeWithoutOffset(){ // ... same forNTP_GetCurrentTimeWithoutOffset()...
+ if (g_epochOnStartup > 10) {
+ return g_epochOnStartup + g_secondsElapsed;
+ }
+ return 0;
+};
+
+bool TIME_IsTimeSynced(){ // ... and for NTP_IsTimeSynced()
+ if (g_epochOnStartup > 10) {
+ return true;
+ }
+#if ENABLE_NTP
+ if (NTP_IsTimeSynced() == true) {
+ return true;
+ }
+#endif
+ return false;
+}
+
+int TIME_GetTimesZoneOfsSeconds() // ... and for NTP_GetTimesZoneOfsSeconds()
+{
+ if (g_epochOnStartup > 10) {
+ return g_UTCoffset
+#if ENABLE_TIME_DST
+ + getDST_offset()
+#endif
+ ;
+ } // no "else" needed, will return 0 anyway if we don't return here
+ return 0;
+}
+void TIME_AppendInformationToHTTPIndexPage(http_request_t *request, int bPreState)
+{
+ if (bPreState)
+ return;
+ uint32_t tempt=TIME_GetCurrentTime();
+#if ENABLE_NTP
+ char ntpinfo[50]={0};
+ if (NTP_IsTimeSynced()){
+ sprintf(ntpinfo," (NTP-Server: %s)",CFG_GetNTPServer());
+ }
+#endif
+ if (TIME_IsTimeSynced()) hprintf255(request, "Local clock: %s"
+#if ENABLE_TIME_DST
+ "%s"
+#endif
+#if ENABLE_NTP
+ "%s"
+#endif
+ " ",TS2STR(tempt,TIME_FORMAT_LONG)
+#if ENABLE_TIME_DST
+ , ! dst_config.DSTinitialized ? "" : IsDST()?" (summer-time)":" (winter-time)"
+#endif
+#if ENABLE_NTP
+ , ntpinfo
+#endif
+ );
+}
+
+
diff --git a/src/driver/drv_deviceclock.h b/src/driver/drv_deviceclock.h
new file mode 100644
index 000000000..453c0918d
--- /dev/null
+++ b/src/driver/drv_deviceclock.h
@@ -0,0 +1,71 @@
+#ifndef __DRV_DEVICECLOCK_H__
+#define __DRV_DEVICECLOCK_H__
+
+#include "../httpserver/new_http.h"
+#include "../cmnds/cmd_public.h"
+#include "../new_common.h"
+#include
+
+
+int TIME_GetWeekDay();
+int TIME_GetHour();
+int TIME_GetMinute();
+int TIME_GetSecond();
+int TIME_GetMDay();
+int TIME_GetMonth();
+int TIME_GetYear();
+int TIME_GetSunrise();
+int TIME_GetSunset();
+// drv_timed_events.c
+int TIME_Print_EventList();
+void TIME_setDeviceTime(uint32_t time);
+void TIME_setDeviceTimeOffset(int offs);
+int TIME_GetEventTime(int id);
+int TIME_RemoveEvent(int id);
+int TIME_ClearEvents();
+void TIME_Init();
+void TIME_OnEverySecond();
+commandResult_t SetTimeZoneOfs(const void *context, const char *cmd, const char *args, int cmdFlags);
+commandResult_t SetDeviceTime(const void *context, const char *cmd, const char *args, int cmdFlags);
+
+#if ENABLE_TIME_SUNRISE_SUNSET
+extern struct SUN_DATA { /* sunrise / sunset globals */
+ int latitude; /* latitude * 1000000 */
+ int longitude; /* longitude * 1000000 */
+ } sun_data;
+int TIME_GetSunrise();
+int TIME_GetSunset();
+float TIME_GetLatitude();
+float TIME_GetLongitude();
+void TIME_setLatitude(float lat);
+void TIME_setLongitude(float longi);
+#if ENABLE_CALENDAR_EVENTS
+void TIME_CalculateSunrise(byte *outHour, byte *outMinute);
+void TIME_CalculateSunset(byte *outHour, byte *outMinute);
+#endif // to #if ENABLE_CALENDAR_EVENTS
+#endif
+uint32_t TIME_GetCurrentTime(); // might replace for NTP_GetCurrentTime() to return time regardless of NTP present/running
+uint32_t TIME_GetCurrentTimeWithoutOffset(); // ... same for NTP_GetCurrentTimeWithoutOffset()...
+bool TIME_IsTimeSynced(); // ... and for NTP_IsTimeSynced()
+
+int TIME_GetTimesZoneOfsSeconds(); // ... and for NTP_GetTimesZoneOfsSeconds()
+
+#if ENABLE_TIME_DST
+int Time_IsDST();
+bool IsDST_initialized();
+uint32_t setDST();
+int getDST_offset();
+#if ENABLE_TIME_SUNRISE_SUNSET
+// since we calculate time "in the future", which might be after a DST switch, we migth need to fix sunset/sunrise time (add ore sub DST_offset)
+// in case a DST switch happens, we should change future events of sunset/sunrise, since this will be different after a switch
+// since we calculated the events in advance, we need to "fix" all events, postulating the DST switch is allways before a days sunrise and sunset
+void fix_DSTforEvents(int minutes); // inside "drv_timed_events.c"
+#endif
+uint32_t RuleToTime(uint8_t dayOfWeek, uint8_t month, uint8_t weekNum, uint8_t hour, uint16_t year);
+void getDSTtransition(uint32_t * DST);
+#endif
+void TIME_AppendInformationToHTTPIndexPage(http_request_t *request, int bPreState);
+
+
+#endif /* __DRV_DEVICECLOCK_H__ */
+
diff --git a/src/driver/drv_ds3231.c b/src/driver/drv_ds3231.c
new file mode 100644
index 000000000..ab6194650
--- /dev/null
+++ b/src/driver/drv_ds3231.c
@@ -0,0 +1,260 @@
+#include "../obk_config.h"
+
+#if (ENABLE_DRIVER_DS3231)
+#include "../new_pins.h"
+#include "../logging/logging.h"
+#include "drv_local.h"
+#include "drv_ds3231.h"
+//#include
+#include "../libraries/obktime/obktime.h" // for time functions
+
+#include "drv_deviceclock.h"
+
+
+#define DS3231_I2C_ADDR (0x68 << 1)
+
+static softI2C_t g_ds3231_softI2C;
+static uint8_t sync2device = 0; // 0 do nothing 1 set devicetime to RTC on startup 2 set devicetime to RTC regulary
+static uint8_t clocksetcounter = 0; // if deviceclock is set, this driver is informed, so it can decide, if RTC should be set, too (e.g on first event and the every 60 events (1 hour for ntp)
+
+
+static uint8_t bcd_to_dec(uint8_t val) {
+ return ((val / 16 * 10) + (val % 16));
+}
+
+static uint8_t dec_to_bcd(uint8_t val) {
+ return ((val / 10 * 16) + (val % 10));
+}
+
+// Epoch helpers
+static time_t DS3231_TimeToEpoch(const ds3231_time_t* time)
+{
+/*
+ struct tm t;
+ t.tm_sec = time->seconds;
+ t.tm_min = time->minutes;
+ t.tm_hour = time->hours;
+ t.tm_mday = time->date;
+ t.tm_mon = time->month - 1; // tm_mon is 0-11
+ t.tm_year = time->year + 100; // DS3231 year is 00-99, tm_year since 1900
+ t.tm_isdst = -1;
+ return mktime(&t);
+*/
+ return (time_t)dateToEpoch((uint16_t)time->year+2000, time->month, time->date,
+ time->hours, time->minutes, time->seconds);
+}
+
+static void DS3231_EpochToTime(time_t epoch, ds3231_time_t* time)
+{
+/* struct tm* t = gmtime(&epoch);
+ time->seconds = t->tm_sec;
+ time->minutes = t->tm_min;
+ time->hours = t->tm_hour;
+ time->date = t->tm_mday;
+ time->month = t->tm_mon + 1;
+ time->year = t->tm_year - 100;
+ time->day = t->tm_wday;
+*/
+ TimeComponents tc=calculateComponents((uint32_t) epoch);
+ time->seconds = tc.second;
+ time->minutes = tc.minute;
+ time->hours = tc.hour;
+ time->date = tc.day;
+ time->month = tc.month;
+ time->year = tc.year%100; // tc.year: "full" years, but DS3231 has only 00-99; so get years in century, mod 100
+ time->day = tc.wday;
+}
+
+
+bool DS3231_ReadTime(ds3231_time_t* time)
+{
+ uint8_t data[7];
+
+ Soft_I2C_Start(&g_ds3231_softI2C, DS3231_I2C_ADDR);
+ Soft_I2C_WriteByte(&g_ds3231_softI2C, 0x00);
+ Soft_I2C_Stop(&g_ds3231_softI2C);
+
+ Soft_I2C_Start(&g_ds3231_softI2C, DS3231_I2C_ADDR | 1);
+ Soft_I2C_ReadBytes(&g_ds3231_softI2C, data, 7);
+ Soft_I2C_Stop(&g_ds3231_softI2C);
+
+ time->seconds = bcd_to_dec(data[0] & 0x7F);
+ time->minutes = bcd_to_dec(data[1]);
+ time->hours = bcd_to_dec(data[2] & 0x3F);
+ time->day = bcd_to_dec(data[3]);
+ time->date = bcd_to_dec(data[4]);
+ time->month = bcd_to_dec(data[5] & 0x1F);
+ time->year = bcd_to_dec(data[6]);
+
+// ADDLOG_INFO(LOG_FEATURE_RAW, "DS3231 Time: %02d/%02d/%02d %02d:%02d:%02d",
+// time->date, time->month, time->year, time->hours, time->minutes, time->seconds);
+
+ return true;
+}
+
+uint32_t DS3231_ReadEpoch()
+{
+ ds3231_time_t time;
+ uint32_t retval = 0;
+ if (DS3231_ReadTime(&time)) retval= (uint32_t)DS3231_TimeToEpoch(&time);
+ return retval;
+}
+
+
+bool DS3231_SetEpoch(const time_t st)
+{
+ ds3231_time_t time;
+ DS3231_EpochToTime(st, &time);
+ return (DS3231_SetTime(&time));
+}
+
+void DS3231_informClockWasSet(bool force){
+// ADDLOG_DEBUG(LOG_FEATURE_RAW, "DS3231_informClockWasSet called. force=%i - clocksetcounter=%i",force, clocksetcounter);
+ if ((clocksetcounter++ % 60 == 0) || force){
+ ADDLOG_INFO(LOG_FEATURE_RAW, "DS3231_informClockWasSet - setting RTC time. force=%i - clocksetcounter=%i",force, clocksetcounter);
+ DS3231_SetEpoch(TIME_GetCurrentTimeWithoutOffset());
+ }
+}
+
+
+bool DS3231_SetTime(const ds3231_time_t* time)
+{
+ uint8_t data[7];
+ data[0] = dec_to_bcd(time->seconds);
+ data[1] = dec_to_bcd(time->minutes);
+ data[2] = dec_to_bcd(time->hours);
+ data[3] = dec_to_bcd(time->day);
+ data[4] = dec_to_bcd(time->date);
+ data[5] = dec_to_bcd(time->month);
+ data[6] = dec_to_bcd(time->year);
+
+ Soft_I2C_Start(&g_ds3231_softI2C, DS3231_I2C_ADDR);
+ Soft_I2C_WriteByte(&g_ds3231_softI2C, 0x00);
+ for (int i = 0; i < 7; i++) {
+ Soft_I2C_WriteByte(&g_ds3231_softI2C, data[i]);
+ }
+ Soft_I2C_Stop(&g_ds3231_softI2C);
+
+ ADDLOG_INFO(LOG_FEATURE_RAW, "DS3231 Time Set: %02d/%02d/%02d %02d:%02d:%02d",
+ time->date, time->month, time->year, time->hours, time->minutes, time->seconds);
+
+ return true;
+}
+
+// Standard get/set commands
+commandResult_t DS3231_GetTimeCmd(const void* context, const char* cmd, const char* args, int cmdFlags)
+{
+ ds3231_time_t time;
+ if (DS3231_ReadTime(&time)) {
+ ADDLOG_INFO(LOG_FEATURE_RAW, "DS3231_GetTimeCmd: %02d/%02d/%02d %02d:%02d:%02d",
+ time.date, time.month, time.year, time.hours, time.minutes, time.seconds);
+ return CMD_RES_OK;
+ }
+ return CMD_RES_ERROR;
+}
+
+commandResult_t DS3231_SetTimeCmd(const void* context, const char* cmd, const char* args, int cmdFlags)
+{
+ Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_DONT_EXPAND);
+ if(Tokenizer_CheckArgsCountAndPrintWarning(cmd, 6)) return CMD_RES_NOT_ENOUGH_ARGUMENTS;
+ ds3231_time_t time;
+ time.hours = Tokenizer_GetArgInteger(0);
+ time.minutes = Tokenizer_GetArgInteger(1);
+ time.seconds = Tokenizer_GetArgInteger(2);
+ time.date = Tokenizer_GetArgInteger(3);
+ time.month = Tokenizer_GetArgInteger(4);
+ time.year = Tokenizer_GetArgInteger(5)%100;
+
+ if (DS3231_SetTime(&time)) {
+ return CMD_RES_OK;
+ }
+ return CMD_RES_ERROR;
+}
+
+// Epoch get/set commands
+commandResult_t DS3231_GetEpochCmd(const void* context, const char* cmd, const char* args, int cmdFlags)
+{
+ ds3231_time_t time;
+ if (DS3231_ReadTime(&time)) {
+ time_t epoch = DS3231_TimeToEpoch(&time);
+ ADDLOG_INFO(LOG_FEATURE_RAW, "DS3231_GetEpochCmd: Epoch: %lu", (unsigned long)epoch);
+ // Optionally return epoch to HTTP or other interface
+ return CMD_RES_OK;
+ }
+ return CMD_RES_ERROR;
+}
+
+commandResult_t DS3231_SetEpochCmd(const void* context, const char* cmd, const char* args, int cmdFlags)
+{
+ Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_DONT_EXPAND);
+ if(Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) return CMD_RES_NOT_ENOUGH_ARGUMENTS;
+ time_t epoch = (time_t)Tokenizer_GetArgInteger(0);
+ if (DS3231_SetEpoch(epoch)) {
+ ADDLOG_INFO(LOG_FEATURE_RAW, "DS3231_SetEpochCmd: Set time to epoch %lu", (unsigned long)epoch);
+ return CMD_RES_OK;
+ }
+ return CMD_RES_ERROR;
+}
+
+void DS3231_Init()
+{
+ if(Tokenizer_GetArgsCount() < 3){
+ ADDLOG_INFO(LOG_FEATURE_CMD, "\"startdriver DS3213\" needs at least two arguments and , given ony %i" , Tokenizer_GetArgsCount() -1 );
+// Tokenizer_CheckArgsCountAndPrintWarning("startdriver DS3213" , 3);
+ return;
+ }
+ g_ds3231_softI2C.pin_clk = Tokenizer_GetPin(1, 9);
+ g_ds3231_softI2C.pin_data = Tokenizer_GetPin(2, 14);
+ Soft_I2C_PreInit(&g_ds3231_softI2C);
+ rtos_delay_milliseconds(100);
+ ADDLOG_INFO(LOG_FEATURE_RAW, "DS3231 RTC Initialized.");
+
+ //cmddetail:{"name":"DS3231_GetTime","args":"-",
+ //cmddetail:"descr":"Gets time from RTC",
+ //cmddetail:"fn":"DS3231_GetTimeCmd","file":"driver/drv_ds3231.c","requires":"",
+ //cmddetail:"examples":""}
+ CMD_RegisterCommand("DS3231_GetTime", DS3231_GetTimeCmd, NULL);
+ //cmddetail:{"name":"DS3231_SetTime","args":" ",
+ //cmddetail:"descr":"Sets RTC time",
+ //cmddetail:"fn":"DS3231_SetTimeCmd","file":"driver/drv_ds3231.c","requires":"",
+ //cmddetail:"examples":"DS3231_SetTime 19 50 01 13 8 25"}
+ CMD_RegisterCommand("DS3231_SetTime", DS3231_SetTimeCmd, NULL);
+ //cmddetail:{"name":"DS3231_GetEpoch","args":"-",
+ //cmddetail:"descr":"Gets time from RTC",
+ //cmddetail:"fn":"DS3231_GetEpochCmd","file":"driver/drv_ds3231.c","requires":"",
+ //cmddetail:"examples":""}
+ CMD_RegisterCommand("DS3231_GetEpoch", DS3231_GetEpochCmd, NULL);
+ //cmddetail:{"name":"DS3231_SetEpoch","args":"",
+ //cmddetail:"descr":"Sets RTC time (to epoch)",
+ //cmddetail:"fn":"DS3231_SetEpochCmd","file":"driver/drv_ds3231.c","requires":"",
+ //cmddetail:"examples":"DS3231_SetTime 3269879540"}
+ CMD_RegisterCommand("DS3231_SetEpoch", DS3231_SetEpochCmd, NULL);
+ sync2device=Tokenizer_GetArgIntegerDefault(3, 0);
+ if (sync2device > 0 ) {
+ ADDLOG_INFO(LOG_FEATURE_RAW, "DS3231 set deviceclock to RTC time.");
+ time_t t = DS3231_ReadEpoch();
+ if ( t > g_secondsElapsed + 3600 ) TIME_setDeviceTime(t);
+ }
+}
+
+void DS3231_Stop(){
+};
+
+void DS3231_AppendInformationToHTTPIndexPage(http_request_t* request, int bPreState){
+ if (bPreState){
+ return;
+ }
+ if (! TIME_IsTimeSynced()){
+ ds3231_time_t time;
+ if (DS3231_ReadTime(&time)) {
+ hprintf255(request, "DS3231 Time: %02d/%02d/%02d %02d:%02d:%02d ",
+ time.date, time.month, time.year, time.hours, time.minutes, time.seconds);
+ }
+ }
+};
+
+void DS3231_OnEverySecond(){
+ if ( sync2device > 1 && g_secondsElapsed % 60 == 2 )
+ TIME_setDeviceTime(DS3231_ReadEpoch());
+};
+#endif // #if (ENABLE_DRIVER_DS3231)
diff --git a/src/driver/drv_ds3231.h b/src/driver/drv_ds3231.h
new file mode 100644
index 000000000..19f9b747e
--- /dev/null
+++ b/src/driver/drv_ds3231.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include
+#include
+#include
+
+typedef struct {
+ uint8_t seconds;
+ uint8_t minutes;
+ uint8_t hours;
+ uint8_t day;
+ uint8_t date;
+ uint8_t month; // 1-12
+ uint8_t year; // 00-99
+} ds3231_time_t;
+
+void DS3231_Init();
+void DS3231_Stop();
+bool DS3231_ReadTime(ds3231_time_t* time);
+bool DS3231_SetTime(const ds3231_time_t* time);
+bool DS3231_SetEpoch(const time_t st);
+void DS3231_informClockWasSet(bool force);
+void DS3231_RegisterCommands();
+void DS3231_AppendInformationToHTTPIndexPage(http_request_t* request, int bPreState);
+void DS3231_OnEverySecond();
+
diff --git a/src/driver/drv_main.c b/src/driver/drv_main.c
index d040a2b7c..be677de29 100644
--- a/src/driver/drv_main.c
+++ b/src/driver/drv_main.c
@@ -7,6 +7,7 @@
#include "drv_ir.h"
#include "drv_local.h"
#include "drv_ntp.h"
+#include "drv_deviceclock.h"
#include "drv_public.h"
#include "drv_ssdp.h"
#include "drv_test_drivers.h"
@@ -16,6 +17,7 @@
#include "drv_ds1820_simple.h"
#include "drv_ds1820_full.h"
#include "drv_ds1820_common.h"
+#include "drv_ds3231.h"
#include "drv_hlw8112.h"
@@ -333,10 +335,26 @@ static driver_t g_drivers[] = {
NTP_OnEverySecond, // onEverySecond
NTP_AppendInformationToHTTPIndexPage, // appendInformationToHTTPIndexPage
NULL, // runQuickTick
- NULL, // stopFunction
- NULL, // onChannelChanged
- NULL, // onHassDiscovery
- false, // loaded
+ NTP_Stop, // stopFunction
+ NULL, // onChannelChanged
+ NULL, // onHassDiscovery
+ false, // loaded
+ },
+#endif
+#if ENABLE_DRIVER_DS3231
+ //drvdetail:{"name":"DS3231",
+ //drvdetail:"title":"TODO",
+ //drvdetail:"descr":"Driver for DS3231 RTC. Start with \"startdriver DS3231 []\". Sync values: 0 - do nothing / 1: set device clock to RTC on driver start / 2: regulary (every minute) set device clock to RTC (so RTC is time source)",
+ //drvdetail:"requires":""}
+ { "DS3231", // Driver Name
+ DS3231_Init, // Init
+ DS3231_OnEverySecond, // onEverySecond
+ DS3231_AppendInformationToHTTPIndexPage, // appendInformationToHTTPIndexPage
+ NULL, // runQuickTick
+ DS3231_Stop, // stopFunction
+ NULL, // onChannelChanged
+ NULL, // onHassDiscovery
+ false, // loaded
},
#endif
#if ENABLE_DRIVER_HTTPBUTTONS
@@ -1384,6 +1402,10 @@ void DRV_OnEverySecond() {
}
}
}
+#ifndef OBK_DISABLE_ALL_DRIVERS
+ // unconditionally run TIME
+ TIME_OnEverySecond();
+#endif
DRV_Mutex_Free();
}
void DRV_RunQuickTick() {
@@ -1521,7 +1543,6 @@ static commandResult_t DRV_Start(const void* context, const char* cmd, const cha
if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) {
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
}
-
DRV_StartDriver(Tokenizer_GetArg(0));
return CMD_RES_OK;
}
@@ -1550,6 +1571,10 @@ void DRV_Generic_Init() {
//cmddetail:"fn":"DRV_Stop","file":"driver/drv_main.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("stopDriver", DRV_Stop, NULL);
+#ifndef OBK_DISABLE_ALL_DRIVERS
+ // init TIME unconditionally on start
+ TIME_Init();
+#endif
}
void DRV_OnHassDiscovery(const char *topic) {
@@ -1575,6 +1600,9 @@ void DRV_AppendInformationToHTTPIndexPage(http_request_t* request, int bPreState
if (DRV_Mutex_Take(100) == false) {
return;
}
+#ifndef OBK_DISABLE_ALL_DRIVERS
+ TIME_AppendInformationToHTTPIndexPage(request, bPreState);
+#endif
for (i = 0; i < g_numDrivers; i++) {
if (g_drivers[i].bLoaded) {
c_active++;
diff --git a/src/driver/drv_max72xx_clock.c b/src/driver/drv_max72xx_clock.c
index 46541b254..4cceafe90 100644
--- a/src/driver/drv_max72xx_clock.c
+++ b/src/driver/drv_max72xx_clock.c
@@ -8,8 +8,9 @@
#include "../hal/hal_pins.h"
#include "drv_public.h"
#include "drv_local.h"
-#include "drv_ntp.h"
-#include
+#include "drv_deviceclock.h"
+//#include
+#include "../libraries/obktime/obktime.h" // for time functions
char *my_strcat(char *p, const char *s) {
strcat(p, s);
@@ -29,14 +30,17 @@ enum {
CLOCK_HUMIDITY,
CLOCK_TEMPERATURE,
};
+/*
void Clock_Send(int type) {
char time[64];
struct tm *ltm;
float val;
char *p;
+ time_t ntpTime;
+ ntpTime=(time_t)TIME_GetCurrentTime();
// NOTE: on windows, you need _USE_32BIT_TIME_T
- ltm = gmtime(&g_ntpTime);
+ ltm = gmtime(&ntpTime);
if (ltm == 0) {
return;
@@ -76,6 +80,54 @@ void Clock_Send(int type) {
CMD_ExecuteCommandArgs("MAX72XX_Print", time, 0);
}
+*/
+void Clock_Send(int type) {
+ char time[64];
+ TimeComponents tc;
+ float val;
+ char *p;
+ time_t ntpTime;
+
+ ntpTime=(time_t)TIME_GetCurrentTime();
+ // NOTE: on windows, you need _USE_32BIT_TIME_T
+ tc=calculateComponents((uint32_t)ntpTime);
+
+ time[0] = 0;
+ p = time;
+ if (type == CLOCK_TIME) {
+ p = my_strcat(p, " ");
+ p = add_padded(p, tc.hour);
+ p = my_strcat(p, ":");
+ p = add_padded(p, tc.minute);
+ strcat(p, " ");
+ }
+ else if (type == CLOCK_DATE) {
+ p = my_strcat(p, " ");
+ p = add_padded(p, tc.day);
+ p = my_strcat(p, ".");
+ p = add_padded(p, tc.month);
+ p = my_strcat(p, ".");
+ //p = add_padded(p, tc.year);
+ strcat(p, " ");
+ }
+ else if (type == CLOCK_HUMIDITY) {
+ if (false==CHANNEL_GetGenericHumidity(&val)) {
+ // failed - exit early, do not change string
+ return;
+ }
+ sprintf(time, "H: %i%% ", (int)val);
+ }
+ else if (type == CLOCK_TEMPERATURE) {
+ if (false == CHANNEL_GetGenericTemperature(&val)) {
+ // failed - exit early, do not change string
+ return;
+ }
+ sprintf(time, "T: %iC ", (int)val);
+ }
+
+ CMD_ExecuteCommandArgs("MAX72XX_Print", time, 0);
+}
+
void Clock_SendTime() {
Clock_Send(CLOCK_TIME);
}
@@ -108,6 +160,7 @@ void Run_NoAnimation() {
cycle %= 40;
}
static int g_del = 0;
+/*
void Run_Animated() {
cycle++;
if (cycle < 4) {
@@ -117,9 +170,11 @@ void Run_Animated() {
char time[64];
struct tm *ltm;
char *p;
+ time_t ntpTime;
+ ntpTime=(time_t)TIME_GetCurrentTime();
// NOTE: on windows, you need _USE_32BIT_TIME_T
- ltm = gmtime(&g_ntpTime);
+ ltm = gmtime(&ntpTime);
if (ltm == 0) {
return;
@@ -156,6 +211,54 @@ void Run_Animated() {
CMD_ExecuteCommandArgs("MAX72XX_Scroll", "-1", 0);
CMD_ExecuteCommandArgs("MAX72XX_refresh", "", 0);
}
+*/
+void Run_Animated() {
+ cycle++;
+ if (cycle < 4) {
+ return;
+ }
+ cycle = 0;
+ char time[64];
+ TimeComponents tc;
+ char *p;
+ time_t ntpTime;
+
+ ntpTime=(time_t)TIME_GetCurrentTime();
+ // NOTE: on windows, you need _USE_32BIT_TIME_T
+ tc=calculateComponents((uint32_t)ntpTime);
+
+ int scroll = MAX72XXSingle_GetScrollCount();
+ //scroll_cycle = 0;
+ if (scroll == 0 && g_del == 0) {
+ time[0] = 0;
+ p = time;
+ p = my_strcat(p, " ");
+
+ p = add_padded(p, tc.hour);
+ p = my_strcat(p, ":");
+ p = add_padded(p, tc.minute);
+ strcat(p, " ");
+
+ p = my_strcat(p, " ");
+ p = add_padded(p, tc.year);
+ p = my_strcat(p, ".");
+ p = add_padded(p, tc.month);
+ p = my_strcat(p, ".");
+ p = add_padded(p, tc.month);
+ strcat(p, " ");
+
+ CMD_ExecuteCommandArgs("MAX72XX_Clear", NULL, 0);
+ CMD_ExecuteCommandArgs("MAX72XX_Print", time, 0);
+ CMD_ExecuteCommandArgs("MAX72XX_refresh", "", 0);
+ g_del = 10;
+ }
+ if (g_del > 0) {
+ g_del--;
+ return;
+ }
+ CMD_ExecuteCommandArgs("MAX72XX_Scroll", "-1", 0);
+ CMD_ExecuteCommandArgs("MAX72XX_refresh", "", 0);
+}
bool g_animated = false;
void DRV_MAX72XX_Clock_OnEverySecond() {
if (g_animated == false) {
diff --git a/src/driver/drv_max72xx_single.c b/src/driver/drv_max72xx_single.c
index 793e99b1c..8c6a27ad8 100644
--- a/src/driver/drv_max72xx_single.c
+++ b/src/driver/drv_max72xx_single.c
@@ -315,7 +315,6 @@ byte g_font[] =
4, 157, 160, 160, 125, // 255 - y diaresis
255,
};
-
byte *MAX_GetFontStart(byte code) {
byte *p;
byte current;
diff --git a/src/driver/drv_ntp.c b/src/driver/drv_ntp.c
index 7429032fe..3364c75c5 100644
--- a/src/driver/drv_ntp.c
+++ b/src/driver/drv_ntp.c
@@ -1,8 +1,9 @@
// NTP client
// Based on my previous work here:
// https://www.elektroda.pl/rtvforum/topic3712112.html
-
-#include
+#include "../obk_config.h"
+#if ENABLE_NTP
+//#include
#include "../new_common.h"
#include "../new_cfg.h"
@@ -11,33 +12,10 @@
#include "../httpserver/new_http.h"
#include "../logging/logging.h"
#include "../hal/hal_ota.h"
-
+#include "drv_deviceclock.h" // for TIME_Init()
+#include "../libraries/obktime/obktime.h" // for time functions
#include "drv_ntp.h"
-#define LTSTR "Local Time: %04d-%02d-%02d %02d:%02d:%02d"
-#define LTM2TIME(T) (T)->tm_year+1900, (T)->tm_mon+1, (T)->tm_mday, (T)->tm_hour, (T)->tm_min, (T)->tm_sec
-
-extern void NTP_Init_Events(void);
-extern void NTP_RunEvents(unsigned int newTime, bool bTimeValid);
-
-#if ENABLE_NTP_SUNRISE_SUNSET
-extern void NTP_CalculateSunrise(byte *outHour, byte *outMinute);
-extern void NTP_CalculateSunset(byte *outHour, byte *outMinute);
-#endif
-
-#if ENABLE_NTP_DST
-static uint32_t Start_DST_epoch=0 , End_DST_epoch=0, next_DST_switch_epoch=0;
-static uint8_t nthWeekEnd, monthEnd, dayEnd, hourEnd, nthWeekStart, monthStart, dayStart, hourStart;
-static int8_t g_DST_offset=0, g_DST=-128; // g_DST_offset: offset during DST; 0: unset / g_DST: actual DST_offset in hours; -128: not initialised
-#define useDST (g_DST_offset)
-const uint32_t SECS_PER_MIN = 60UL;
-const uint32_t SECS_PER_HOUR = 3600UL;
-const uint32_t SECS_PER_DAY = 3600UL * 24UL;
-const uint32_t MINS_PER_HOUR = 60UL;
-#define LEAP_YEAR(Y) ((!(Y%4) && (Y%100)) || !(Y%400))
-static const uint8_t DaysMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-#endif
-
#define LOG_FEATURE LOG_FEATURE_NTP
typedef struct
@@ -81,114 +59,31 @@ static struct sockaddr_in g_address;
static int adrLen;
// in seconds, before next retry
static int g_ntp_delay = 0;
-static bool g_synced;
+static bool g_synced = false;
// time offset (time zone?) in seconds
//#define CFG_DEFAULT_TIMEOFFSETSECONDS (-8 * 60 * 60)
static int g_timeOffsetSeconds = 0;
// current time - this may be 32 or 64 bit, depending on platform
+// don't use as global variable, use functions to access and manipulate "clock" in "drv_deviceclock.c"
time_t g_ntpTime;
+static unsigned int g_ntp_syncinterval=60;
int NTP_GetTimesZoneOfsSeconds()
{
return g_timeOffsetSeconds;
}
-commandResult_t NTP_SetTimeZoneOfs(const void *context, const char *cmd, const char *args, int cmdFlags) {
- int a, b;
- const char *arg;
- int oldOfs;
- Tokenizer_TokenizeString(args,0);
- // following check must be done after 'Tokenizer_TokenizeString',
- // so we know arguments count in Tokenizer. 'cmd' argument is
- // only for warning display
- if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) {
- return CMD_RES_NOT_ENOUGH_ARGUMENTS;
- }
- arg = Tokenizer_GetArg(0);
- oldOfs = g_timeOffsetSeconds;
- if (strchr(arg, ':')) {
- int useSign = 1;
- if (*arg == '-') {
- arg++;
- useSign = -1;
- }
- sscanf(arg, "%i:%i", &a, &b);
- g_timeOffsetSeconds = useSign * (a * 60 * 60 + b * 60);
- }
- else {
- g_timeOffsetSeconds = Tokenizer_GetArgInteger(0) * 60 * 60;
- }
- g_ntpTime -= oldOfs;
- g_ntpTime += g_timeOffsetSeconds;
-#if ENABLE_NTP_DST
-// in rare cases time can be decreased so time of next DST is wrong
-// e.g. by mistake we set offset to two hours in EU and we have just passed start of summertime - next DST switch will be end of summertime
-// if we now adjust the clock to the correct offset of one hour, we are slightliy before start of summertime
-// so just to be sure, recalculate DST in any case
- setDST(1); // setDST will take care of all details
-#endif
- addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"NTP offset set"
-#if ENABLE_NTP_DST
- " - DST offset set to %i hours",g_DST
-#endif
- );
- return CMD_RES_OK;
+// set offset seconds directly
+void NTP_SetTimesZoneOfsSeconds(int o) {
+/*
+ g_ntpTime -= g_timeOffsetSeconds; // sub old offset
+ g_timeOffsetSeconds = o; // set new offset
+ g_ntpTime += g_timeOffsetSeconds; // add offset again
+*/
+ g_timeOffsetSeconds = o; // set new offset
+ TIME_setDeviceTimeOffset(g_timeOffsetSeconds);
}
-#if ENABLE_NTP_SUNRISE_SUNSET
-
-/* sunrise/sunset defaults */
-#define CFG_DEFAULT_LATITUDE 43.994131
-#define CFG_DEFAULT_LONGITUDE -123.095854
-#define SUN_DATA_COORD_MULT 1000000
-
-struct SUN_DATA sun_data =
- {
- .latitude = (int) (CFG_DEFAULT_LATITUDE * SUN_DATA_COORD_MULT),
- .longitude = (int) (CFG_DEFAULT_LONGITUDE * SUN_DATA_COORD_MULT),
- };
-
-//Set Latitude and Longitude for sunrise/sunset calc
-commandResult_t NTP_SetLatlong(const void *context, const char *cmd, const char *args, int cmdFlags) {
- const char *newValue;
-
- Tokenizer_TokenizeString(args,0);
- // following check must be done after 'Tokenizer_TokenizeString',
- // so we know arguments count in Tokenizer. 'cmd' argument is
- // only for warning display
- if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 2)) {
- return CMD_RES_NOT_ENOUGH_ARGUMENTS;
- }
- newValue = Tokenizer_GetArg(0);
- sun_data.latitude = (int) (atof(newValue) * SUN_DATA_COORD_MULT);
- addLogAdv(LOG_INFO, LOG_FEATURE_NTP, "NTP latitude set to %s", newValue);
-
- newValue = Tokenizer_GetArg(1);
- sun_data.longitude = (int) (atof(newValue) * SUN_DATA_COORD_MULT);
- addLogAdv(LOG_INFO, LOG_FEATURE_NTP, "NTP longitude set to %s", newValue);
- return CMD_RES_OK;
-}
-
-int NTP_GetSunrise()
-{
- byte hour, minute;
- int sunriseInSecondsFromMidnight;
-
- NTP_CalculateSunrise(&hour, &minute);
- sunriseInSecondsFromMidnight = ((int)hour * 3600) + ((int)minute * 60);
- return sunriseInSecondsFromMidnight;
-}
-
-int NTP_GetSunset()
-{
- byte hour, minute;
- int sunsetInSecondsFromMidnight;
-
- NTP_CalculateSunset(&hour, &minute);
- sunsetInSecondsFromMidnight = ((int)hour * 3600) + ((int)minute * 60);
- return sunsetInSecondsFromMidnight;
-}
-#endif
//Set custom NTP server
commandResult_t NTP_SetServer(const void *context, const char *cmd, const char *args, int cmdFlags) {
@@ -209,291 +104,21 @@ commandResult_t NTP_SetServer(const void *context, const char *cmd, const char *
//Display settings used by the NTP driver
commandResult_t NTP_Info(const void *context, const char *cmd, const char *args, int cmdFlags) {
- addLogAdv(LOG_INFO, LOG_FEATURE_NTP, "Server=%s, Time offset=%d", CFG_GetNTPServer(), g_timeOffsetSeconds);
+ addLogAdv(LOG_INFO, LOG_FEATURE_NTP, "Server=%s, Time offset=%d", CFG_GetNTPServer(), TIME_GetTimesZoneOfsSeconds());
return CMD_RES_OK;
}
-#if ENABLE_NTP_DST
-
-// derived from tasmotas "RuleToTime"
-
-uint32_t RuleToTime(uint8_t dow, uint8_t mo, uint8_t week, uint8_t hr, int yr) {
- struct tm tm={0};
- uint32_t t=0;
- int i;
- uint8_t m=mo-1; // we use struct tm here, so month values are 0..11
- uint8_t w=week; // m and w are copies of mo(nth) and week
-
- if (0 == w) { // for "Last XX" (w=0), we compute first occurence in following month and go back 7 days
- if (++m > 11) { // so go to the next month ...
- m = 0; // .. and to next year, if we need last XX in December
- yr++;
- }
- w = 1; // search first week of next month, we will subtract 7 days later
- }
-
- // avoid mktime - this enlarges the image especially for BL602!
- // so calculate seconds from epoch locally
- // we start by calculating the number of days since 1970 - will also be used to get weekday
- uint16_t days;
- days = (yr - 1970) * 365; // days per full years
- // add one day every leap year - first leap after 1970 is 1972, possible leap years every 4 years
- for (i=1972; i < yr; i+=4) days += LEAP_YEAR(i);
- for (i=0; i begin before end
- if (g_ntpTime < Start_DST_epoch) {
- // we are in winter time before start of summer time
- next_DST_switch_epoch=Start_DST_epoch;
- g_DST=0;
-// tempt = (time_t)Start_DST_epoch;
-// ADDLOG_INFO(LOG_FEATURE_RAW, "Before first DST switch in %i. Info: DST starts at %lu (%.24s local time)\r\n",year,Start_DST_epoch,ctime(&tempt));
- } else if (g_ntpTime < End_DST_epoch ){
- // we in summer time
- next_DST_switch_epoch=End_DST_epoch;
- g_DST=g_DST_offset;
-// tempt = (time_t)End_DST_epoch;
-// ADDLOG_INFO(LOG_FEATURE_RAW, "In DST of %i. Info: DST ends at %lu (%.24s local time)\r\n",year,End_DST_epoch,ctime(&tempt));
- } else {
- // we are in winter time, after summer time --> next DST starts in next year
- Start_DST_epoch = RuleToTime(dayStart,monthStart,nthWeekStart,hourStart,year+1);
- next_DST_switch_epoch=Start_DST_epoch;
- g_DST=0;
-// tempt = (time_t)Start_DST_epoch;
-// ADDLOG_INFO(LOG_FEATURE_RAW, "After DST in %i. Info: Next DST start in next year at %lu (%.24s local time)\r\n",year,Start_DST_epoch,ctime(&tempt));
- }
- } else { // so end of DST before begin of DST --> southern
- if (g_ntpTime < End_DST_epoch) {
- // we in summer time at beginning of the yeay
- next_DST_switch_epoch=End_DST_epoch;
- g_DST=g_DST_offset;
-// tempt = (time_t)End_DST_epoch;
-// ADDLOG_INFO(LOG_FEATURE_RAW, "In first DST period of %i. Info: DST ends at %lu (%.24s local time)\r\n",year,End_DST_epoch,ctime(&tempt));
- } else if (g_ntpTime < Start_DST_epoch ){
- // we are in winter time
- next_DST_switch_epoch=Start_DST_epoch;
- g_DST=0;
-// tempt = (time_t)Start_DST_epoch;
-// ADDLOG_INFO(LOG_FEATURE_RAW, "Regular time of %i. Info: DST starts at %lu (%.24s local time)\r\n",year,Start_DST_epoch,ctime(&tempt));
- } else {
- // we in summer time at the end of the year --> DST will end next year
- End_DST_epoch = RuleToTime(dayEnd,monthEnd,nthWeekEnd,hourEnd,year+1);
- next_DST_switch_epoch=End_DST_epoch;
- g_DST=g_DST_offset;
-// tempt = (time_t)End_DST_epoch;
-// ADDLOG_INFO(LOG_FEATURE_RAW, "In second DST of %i. Info: DST ends next year at %lu (%.24s local time)\r\n",year,End_DST_epoch,ctime(&tempt));
- }
- }
- g_ntpTime += (g_DST-old_DST)*3600*setNTP;
- tempt = (time_t)next_DST_switch_epoch;
-
- struct tm *ltm;
- ltm = gmtime(&tempt);
-#if ENABLE_NTP_SUNRISE_SUNSET
- if (old_DST != g_DST){
- // if we had a DST switch, we might corect sunset/sunrise events, which were calculated before (with "previous" DST settings)
- // if we changed to DST, we need to add DST_offset (old_DST = 0)
- // if we were in DST before switch, we need to sub DST_offset (old_DST = g_DST_offset)
- ADDLOG_INFO(LOG_FEATURE_RAW, "DST switch - calling fix_DSTforEvents(%d)\r\n", old_DST ? - g_DST_offset : g_DST_offset );
- fix_DSTforEvents( old_DST ? - g_DST_offset : g_DST_offset );
- }
-#endif
-
- ADDLOG_INFO(LOG_FEATURE_RAW, "In %s time - next DST switch at %lu (" LTSTR ")\r\n",
- (g_DST)?"summer":"standard", next_DST_switch_epoch, LTM2TIME(ltm));
- return g_DST;
- }
- else return 0; // DST not (yet) set or can't be calculated (if ntp not synced)
-
-}
-
-int IsDST()
-{
- if (( g_DST == -128) || (g_ntpTime > next_DST_switch_epoch)) return (setDST(1)); // only in case we don't know DST status, calculate it - and while at it: set ntpTime correctly...
- return (g_DST); // otherwise we can safely return the prevously calkulated value
-}
-
-commandResult_t CLOCK_CalcDST(const void *context, const char *cmd, const char *args, int cmdFlags) {
- int year=NTP_GetYear();
- time_t te,tb; // time_t of timestamps needed for ctime() to get string of timestamp
-
- Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES);
- // following check must be done after 'Tokenizer_TokenizeString',
- // so we know arguments count in Tokenizer. 'cmd' argument is
- // only for warning display
- if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 8)) {
- return CMD_RES_NOT_ENOUGH_ARGUMENTS;
- }
-
-// ADDLOG_INFO(LOG_FEATURE_RAW, "CLOCK_SetConfigs: we have %u Args\r\n", Tokenizer_GetArgsCount());
- nthWeekEnd = Tokenizer_GetArgInteger(0);
- monthEnd = Tokenizer_GetArgInteger(1);
- dayEnd = Tokenizer_GetArgInteger(2);
- hourEnd = Tokenizer_GetArgInteger(3);
- nthWeekStart = Tokenizer_GetArgInteger(4);
- monthStart = Tokenizer_GetArgInteger(5);
- dayStart = Tokenizer_GetArgInteger(6);
- hourStart = Tokenizer_GetArgInteger(7);
- g_DST_offset=Tokenizer_GetArgIntegerDefault(8, 1);
- ADDLOG_INFO(LOG_FEATURE_RAW, "read values: %u,%u,%u,%u,%u,%u,%u,%u,(%u)\r\n", nthWeekEnd, monthEnd, dayEnd, hourEnd, nthWeekStart, monthStart, dayStart, hourStart,g_DST_offset);
-
-/* Start_DST_epoch = RuleToTime(dayStart,monthStart,nthWeekStart,hourStart,year);
- End_DST_epoch = RuleToTime(dayEnd,monthEnd,nthWeekEnd,hourEnd,year);
- te=(time_t)End_DST_epoch;
- tb=(time_t)Start_DST_epoch;
-
- ADDLOG_INFO(LOG_FEATURE_RAW, "Calculated DST switch epochs in %i. DST start at %lu (%.24s local time) - DST end at %lu (%.24s local time)\r\n",year,Start_DST_epoch,ctime(&tb),End_DST_epoch,ctime(&te));
-*/
- return CMD_RES_OK;
-};
-
-
-
-#endif
-
-
-
-int NTP_GetWeekDay() {
- struct tm *ltm;
-
- // NOTE: on windows, you need _USE_32BIT_TIME_T
- ltm = gmtime(&g_ntpTime);
-
- if (ltm == 0) {
- return 0;
- }
-
- return ltm->tm_wday;
-}
-int NTP_GetHour() {
- struct tm *ltm;
-
- // NOTE: on windows, you need _USE_32BIT_TIME_T
- ltm = gmtime(&g_ntpTime);
-
- if (ltm == 0) {
- return 0;
- }
-
- return ltm->tm_hour;
-}
-int NTP_GetMinute() {
- struct tm *ltm;
-
- // NOTE: on windows, you need _USE_32BIT_TIME_T
- ltm = gmtime(&g_ntpTime);
-
- if (ltm == 0) {
- return 0;
- }
-
- return ltm->tm_min;
-}
-int NTP_GetSecond() {
- struct tm *ltm;
-
- // NOTE: on windows, you need _USE_32BIT_TIME_T
- ltm = gmtime(&g_ntpTime);
-
- if (ltm == 0) {
- return 0;
- }
-
- return ltm->tm_sec;
-}
-int NTP_GetMDay() {
- struct tm *ltm;
-
- // NOTE: on windows, you need _USE_32BIT_TIME_T
- ltm = gmtime(&g_ntpTime);
-
- if (ltm == 0) {
- return 0;
- }
-
- return ltm->tm_mday;
-}
-int NTP_GetMonth() {
- struct tm *ltm;
-
- // NOTE: on windows, you need _USE_32BIT_TIME_T
- ltm = gmtime(&g_ntpTime);
-
- if (ltm == 0) {
- return 0;
- }
-
- return ltm->tm_mon+1;
-}
-int NTP_GetYear() {
- struct tm *ltm;
-
- // NOTE: on windows, you need _USE_32BIT_TIME_T
- ltm = gmtime(&g_ntpTime);
-
- if (ltm == 0) {
- return 0;
- }
-
- return ltm->tm_year+1900;
-}
-#if ENABLE_NTP_DST
-int Time_IsDST(){
- return IsDST();
-}
-#endif
#if WINDOWS
bool b_ntp_simulatedTime = false;
void NTP_SetSimulatedTime(unsigned int timeNow) {
+/*
g_ntpTime = timeNow;
g_ntpTime += g_timeOffsetSeconds;
-#if ENABLE_NTP_DST
- g_ntpTime += setDST(0)*3600;
+*/
+ TIME_setDeviceTime(timeNow);
+#if ENABLE_TIME_DST
+// g_ntpTime += setDST(0)*60;
+ setDST(0);
#endif
g_synced = true;
b_ntp_simulatedTime = true;
@@ -506,52 +131,38 @@ void NTP_Init() {
#endif
//cmddetail:{"name":"ntp_timeZoneOfs","args":"[Value]",
//cmddetail:"descr":"Sets the time zone offset in hours. Also supports HH:MM syntax if you want to specify value in minutes. For negative values, use -HH:MM syntax, for example -5:30 will shift time by 5 hours and 30 minutes negative.",
- //cmddetail:"fn":"NTP_SetTimeZoneOfs","file":"driver/drv_ntp.c","requires":"",
+ //cmddetail:"fn":"SetTimeZoneOfs","file":"driver/drv_ntp.c","requires":"",
//cmddetail:"examples":""}
- CMD_RegisterCommand("ntp_timeZoneOfs",NTP_SetTimeZoneOfs, NULL);
+ CMD_RegisterCommand("ntp_timeZoneOfs",SetTimeZoneOfs, NULL);
//cmddetail:{"name":"ntp_setServer","args":"[ServerIP]",
//cmddetail:"descr":"Sets the NTP server",
//cmddetail:"fn":"NTP_SetServer","file":"driver/drv_ntp.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("ntp_setServer", NTP_SetServer, NULL);
-#if ENABLE_NTP_SUNRISE_SUNSET
- //cmddetail:{"name":"ntp_setLatLong","args":"[Latlong]",
- //cmddetail:"descr":"Sets the NTP latitude and longitude",
- //cmddetail:"fn":"NTP_SetLatlong","file":"driver/drv_ntp.c","requires":"",
- //cmddetail:"examples":"NTP_SetLatlong -34.911498 138.809488"}
- CMD_RegisterCommand("ntp_setLatLong", NTP_SetLatlong, NULL);
-#endif
//cmddetail:{"name":"ntp_info","args":"",
//cmddetail:"descr":"Display NTP related settings",
//cmddetail:"fn":"NTP_Info","file":"driver/drv_ntp.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("ntp_info", NTP_Info, NULL);
+
+ g_ntp_syncinterval = Tokenizer_GetArgIntegerDefault(1, 60);
-#if ENABLE_CALENDAR_EVENTS
- NTP_Init_Events();
-#endif
-#if ENABLE_NTP_DST
- //cmddetail:{"name":"clock_calcDST","args":"[nthWeekEnd monthEnd dayEnd hourEnd nthWeekStart monthStart dayStart hourStart [g_DSToffset hours - default is 1 if unset]",
- //cmddetail:"descr":"Checks, if actual time is during DST or not.",
- //cmddetail:"fn":"CLOCK_CalcDST","file":"driver/drv_ntp.c","requires":"",
- //cmddetail:"examples":""}
- CMD_RegisterCommand("clock_calcDST",CLOCK_CalcDST, NULL);
-#endif
-
- addLogAdv(LOG_INFO, LOG_FEATURE_NTP, "NTP driver initialized with server=%s, offset=%d", CFG_GetNTPServer(), g_timeOffsetSeconds);
+ addLogAdv(LOG_INFO, LOG_FEATURE_NTP, "NTP driver initialized with server=%s, offset=%d, syncing every %i seconds", CFG_GetNTPServer(), g_timeOffsetSeconds, g_ntp_syncinterval);
g_synced = false;
}
+// if driver is stopped, we need to make sure, we don't keep NTP in state "synched"
+void NTP_Stop() {
+ addLogAdv(LOG_INFO, LOG_FEATURE_NTP, "NTP driver stopped");
+ g_synced = false;
+}
+
+// just for compatibility
unsigned int NTP_GetCurrentTime() {
- return g_ntpTime;
+ return TIME_GetCurrentTime();
}
unsigned int NTP_GetCurrentTimeWithoutOffset() {
-#if ENABLE_NTP_DST
- return g_ntpTime - g_timeOffsetSeconds - g_DST%128; // if g_DST is unset, it's -128 --> -128%128 = 0 as needed
-#else
- return g_ntpTime - g_timeOffsetSeconds;
-#endif
-
+ return TIME_GetCurrentTimeWithoutOffset();
}
@@ -566,7 +177,7 @@ void NTP_Shutdown() {
}
g_ntp_socket = 0;
// can attempt in next 10 seconds
- g_ntp_delay = 60;
+ g_ntp_delay = g_ntp_syncinterval-1;
}
void NTP_SendRequest(bool bBlocking) {
byte *ptr;
@@ -670,17 +281,21 @@ void NTP_CheckForReceive() {
secsSince1900 = highWord << 16 | lowWord;
addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"Seconds since Jan 1 1900 = %u",secsSince1900);
+/*
g_ntpTime = secsSince1900 - NTP_OFFSET;
g_ntpTime += g_timeOffsetSeconds;
-#if ENABLE_NTP_DST
- g_ntpTime += setDST(0)*3600; // just to be sure: recalculate DST before setting, in case we somehow "moved back in time" we start with freshly set g_ntpTime, so don't change it inside setDST()!
-#endif
- addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"Unix time : %u",(unsigned int)g_ntpTime);
- ltm = gmtime(&g_ntpTime);
- addLogAdv(LOG_INFO, LOG_FEATURE_NTP, LTSTR, LTM2TIME(ltm));
+*/
+ TIME_setDeviceTime((uint32_t) (secsSince1900 - NTP_OFFSET) );
+// g_ntpTime=(time_t)TIME_GetCurrentTime();
+ addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"Unix time : %u - local Time %s",(uint32_t) (secsSince1900 - NTP_OFFSET),TS2STR(TIME_GetCurrentTime(),TIME_FORMAT_LONG));
+// ltm = gmtime(&g_ntpTime);
+// addLogAdv(LOG_INFO, LOG_FEATURE_NTP, LTSTR, LTM2TIME(ltm));
if (g_synced == false) {
EventHandlers_FireEvent(CMD_EVENT_NTP_STATE, 1);
+ // so now clock is synced. If it wasn't set before, start "TIME_Init()" for timed events
+ // done in CMD_Init_Delayed() in cmd_main.c
+// if (! TIME_IsTimeSynced() ) TIME_Init();
}
g_synced = true;
#if 0
@@ -708,18 +323,7 @@ void NTP_SendRequest_BlockingMode() {
void NTP_OnEverySecond()
{
- g_ntpTime++;
-#if ENABLE_NTP_DST
- if (useDST && (g_ntpTime >= next_DST_switch_epoch)){
- int8_t old_DST=g_DST;
- setDST(1);
- addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"Passed DST switch time - recalculated DST offset. Was:%i - now:%i",old_DST,g_DST);
- }
-#endif
-#if ENABLE_CALENDAR_EVENTS
- NTP_RunEvents(g_ntpTime, g_synced);
-#endif
if(Main_IsConnectedToWiFi()==0)
{
return;
@@ -757,15 +361,20 @@ void NTP_AppendInformationToHTTPIndexPage(http_request_t* request, int bPreState
{
if (bPreState)
return;
+/*
struct tm *ltm;
+ g_ntpTime=(time_t)TIME_GetCurrentTime();
ltm = gmtime(&g_ntpTime);
-
if (g_synced == true)
- hprintf255(request, "NTP (%s): " LTSTR " ",
- CFG_GetNTPServer(),LTM2TIME(ltm));
+ hprintf255(request, "NTP (%s): local Time %s ",
+ CFG_GetNTPServer(),TS2STR(TIME_GetCurrentTime(),TIME_FORMAT_LONG));
else
hprintf255(request, "NTP: Syncing with %s.... ",CFG_GetNTPServer());
+*/
+ // if NTP is synced, we'll print time with deviceclocks HTTP information
+ if (g_synced != true)
+ hprintf255(request, "NTP: Syncing with %s.... ",CFG_GetNTPServer());
}
bool NTP_IsTimeSynced()
@@ -773,3 +382,4 @@ bool NTP_IsTimeSynced()
return g_synced;
}
+#endif // #if ENABLE_NTP
diff --git a/src/driver/drv_ntp.h b/src/driver/drv_ntp.h
index f9ed40eb1..8361f60c7 100644
--- a/src/driver/drv_ntp.h
+++ b/src/driver/drv_ntp.h
@@ -2,8 +2,12 @@
#define __DRV_NTP_H__
#include "../httpserver/new_http.h"
-
+/*
+#define LTSTR "Local Time: %04d-%02d-%02d %02d:%02d:%02d"
+#define LTM2TIME(T) (T)->tm_year+1900, (T)->tm_mon+1, (T)->tm_mday, (T)->tm_hour, (T)->tm_min, (T)->tm_sec
+*/
void NTP_Init();
+void NTP_Stop();
void NTP_OnEverySecond();
// returns number of seconds passed after 1900
unsigned int NTP_GetCurrentTime();
@@ -11,40 +15,11 @@ unsigned int NTP_GetCurrentTimeWithoutOffset();
void NTP_AppendInformationToHTTPIndexPage(http_request_t* request, int bPreState);
bool NTP_IsTimeSynced();
int NTP_GetTimesZoneOfsSeconds();
-int NTP_GetWeekDay();
-int NTP_GetHour();
-int NTP_GetMinute();
-int NTP_GetSecond();
-int NTP_GetMDay();
-int NTP_GetMonth();
-int NTP_GetYear();
-int NTP_GetSunrise();
-int NTP_GetSunset();
+void NTP_SetTimesZoneOfsSeconds(int o);
// for Simulator only, on Windows, for unit testing
void NTP_SetSimulatedTime(unsigned int timeNow);
// drv_ntp_events.c
-int NTP_PrintEventList();
-int NTP_GetEventTime(int id);
-int NTP_RemoveClockEvent(int id);
-int NTP_ClearEvents();
-#if ENABLE_NTP_DST
-int Time_IsDST();
-// usually we want to set/correct g_ntpTime inside setDST() --> call setDST(1)
-// only after setting g_ntpTime freshly from an NTP packet --> call setDST(0)
-// we must not alter g_ntpTime inside setDST in this case (the old offsets are no longer valid)
-uint32_t setDST(bool setNTP);
-#if ENABLE_NTP_SUNRISE_SUNSET
-// in case a DST switch happens, we should change future events of sunset/sunrise, since this will be different after a switch
-// since we calculated the events in advance, we need to "fix" all events, postulating the DST switch is allways before a days sunrise and sunset
-void fix_DSTforEvents(int hours);
-#endif
-#endif
-
extern time_t g_ntpTime;
-extern struct SUN_DATA { /* sunrise / sunset globals */
- int latitude; /* latitude * 1000000 */
- int longitude; /* longitude * 1000000 */
- } sun_data;
#endif /* __DRV_NTP_H__ */
diff --git a/src/driver/drv_openWeatherMap.c b/src/driver/drv_openWeatherMap.c
index 764676cac..d9a3dd12c 100644
--- a/src/driver/drv_openWeatherMap.c
+++ b/src/driver/drv_openWeatherMap.c
@@ -13,6 +13,7 @@
#include "lwip/ip_addr.h"
#include "lwip/inet.h"
#include "../cJSON/cJSON.h"
+#include "../libraries/obktime/obktime.h" // for time functions
#if ENABLE_DRIVER_OPENWEATHERMAP
@@ -273,12 +274,17 @@ void OWM_AppendInformationToHTTPIndexPage(http_request_t *request, int bPreState
hprintf255(request, "Weather: %s (%s) ", g_weather.main_weather, g_weather.description);
hprintf255(request, "Temperature: %.2f C, Pressure: %d hPa, Humidity: %d%% ", g_weather.temp, g_weather.pressure, g_weather.humidity);
+/*
struct tm *tm = gmtime(&g_weather.sunrise);
strftime(buff, sizeof(buff), "%H:%M:%S", tm);
hprintf255(request, "Timezone: %d, Sunrise: %s, ", g_weather.timezone, buff);
tm = gmtime(&g_weather.sunset);
strftime(buff, sizeof(buff), "%H:%M:%S", tm);
hprintf255(request, "Sunset: %s ", buff);
+*/
+ hprintf255(request, "Timezone: %d, Sunrise: %s, ", g_weather.timezone, TS2STR(g_weather.sunrise,TIME_FORMAT_TIMEonly));
+ hprintf255(request, "Sunset: %s ", TS2STR(g_weather.sunset,TIME_FORMAT_TIMEonly));
+
}
}
/*
diff --git a/src/driver/drv_ntp_events.c b/src/driver/drv_timed_events.c
similarity index 68%
rename from src/driver/drv_ntp_events.c
rename to src/driver/drv_timed_events.c
index 0823eb9e6..a69692184 100644
--- a/src/driver/drv_ntp_events.c
+++ b/src/driver/drv_timed_events.c
@@ -1,5 +1,7 @@
//
-#include
+//#include
+#include "../libraries/obktime/obktime.h" // for time functions
+
#include
#include "../new_common.h"
@@ -10,19 +12,19 @@
#include "../logging/logging.h"
#include "../hal/hal_ota.h"
-#include "drv_ntp.h"
+#include "drv_deviceclock.h"
#define M_PI 3.14159265358979323846264338327950288
#define LOG_FEATURE LOG_FEATURE_NTP
-time_t ntp_eventsTime = 0;
+time_t clock_eventsTime = 0;
-typedef struct ntpEvent_s {
+typedef struct clockEvent_s {
byte hour;
byte minute;
byte second;
byte weekDayFlags;
-#if ENABLE_NTP_SUNRISE_SUNSET
+#if ENABLE_TIME_SUNRISE_SUNSET
byte lastDay; /* used so we don't repeat sunrise sunset events the same day */
byte sunflags; /* flags for sunrise/sunset as follows: */
#define SUNRISE_FLAG (1 << 0)
@@ -30,12 +32,12 @@ typedef struct ntpEvent_s {
#endif
int id;
char *command;
- struct ntpEvent_s *next;
-} ntpEvent_t;
+ struct clockEvent_s *next;
+} clockEvent_t;
-ntpEvent_t *ntp_events = 0;
+clockEvent_t *clock_events = 0;
-#if ENABLE_NTP_SUNRISE_SUNSET
+#if ENABLE_TIME_SUNRISE_SUNSET
/* Sunrise/sunset algorithm, somewhat based on https://edwilliams.org/sunrise_sunset_algorithm.htm and tasmota code */
const float pi2 = (M_PI * 2);
const float pi = M_PI;
@@ -93,9 +95,9 @@ static inline uint32_t JulianDay(void)
{
/* https://en.wikipedia.org/wiki/Julian_day */
- uint32_t Year = NTP_GetYear(); /* Year ex:2020 */
- uint32_t Month = NTP_GetMonth(); /* 1..12 */
- uint32_t Day = NTP_GetMDay(); /* 1..31 */
+ uint32_t Year = TIME_GetYear(); /* Year ex:2020 */
+ uint32_t Month = TIME_GetMonth(); /* 1..12 */
+ uint32_t Day = TIME_GetMDay(); /* 1..31 */
uint32_t Julian; /* Julian day number */
if (Month <= 2) {
@@ -124,7 +126,7 @@ static void dusk2Dawn(struct SUN_DATA *Settings, byte sunflags, uint8_t *hour, u
float geoLatitude = Settings->latitude / (1000000.0f / RAD);
float geoLongitude = ((float) Settings->longitude) / 1000000;
- float timeZone = ((float) NTP_GetTimesZoneOfsSeconds()) / 3600; /* convert to hours */
+ float timeZone = ((float) TIME_GetTimesZoneOfsSeconds()) / 3600; /* convert to hours */
float timeEquation = TimeFormula(&declination, Tdays);
float timeDiff = acosf((sin_h - sinf(geoLatitude) * sinf(declination)) / (cosf(geoLatitude) * cosf(declination))) * (12.0f / pi);
@@ -158,33 +160,18 @@ static int calc_day_offset(int tm_wday, int weekDayFlags)
}
return (day_offset);
}
-void NTP_CalculateSunrise(byte *outHour, byte *outMinute) {
+void TIME_CalculateSunrise(byte *outHour, byte *outMinute) {
dusk2Dawn(&sun_data, SUNRISE_FLAG, outHour, outMinute, 0);
}
-void NTP_CalculateSunset(byte *outHour, byte *outMinute) {
+void TIME_CalculateSunset(byte *outHour, byte *outMinute) {
dusk2Dawn(&sun_data, SUNSET_FLAG, outHour, outMinute, 0);
}
#endif
-#if ENABLE_NTP_SUNRISE_SUNSET && ENABLE_NTP_DST
-// in case a DST switch happens, we should change future events of sunset/sunrise, since this will be different after a switch
-// since we calculated the events in advance, we need to "fix" all events, postulating the DST switch happens allways before a days sunrise and sunset
-void fix_DSTforEvents(int hours){
- ntpEvent_t *e;
- e = ntp_events;
- while (e) {
-// addLogAdv(LOG_INFO, LOG_FEATURE_CMD,"fix_DSTforEvents(%i) - testing %s",hours,e->command);
- if (e->command && e->sunflags) { // only for (future) sunflag events
-// addLogAdv(LOG_INFO, LOG_FEATURE_CMD,"fix_DSTforEvents(%i) - fixing %s",hours,e->command);
- e->hour += hours;
- }
- e = e->next;
- }
-}
-#endif
-
-void NTP_RunEventsForSecond(time_t runTime) {
- ntpEvent_t *e;
+void TIME_RunEventsForSecond(time_t runTime) {
+ clockEvent_t *e;
+
+/*
struct tm *ltm;
// NOTE: on windows, you need _USE_32BIT_TIME_T
@@ -193,23 +180,35 @@ void NTP_RunEventsForSecond(time_t runTime) {
if (ltm == 0) {
return;
}
-
- e = ntp_events;
+*/
+ TimeComponents tc=calculateComponents(runTime);
+ e = clock_events;
while (e) {
if (e->command) {
// base check
- if (e->hour == ltm->tm_hour && e->second == ltm->tm_sec && e->minute == ltm->tm_min) {
+// if (e->hour == ltm->tm_hour && e->second == ltm->tm_sec && e->minute == ltm->tm_min) {
+ if (e->hour == tc.hour && e->second == tc.second && e->minute == tc.minute) {
// weekday check
- if (BIT_CHECK(e->weekDayFlags, ltm->tm_wday)) {
-#if ENABLE_NTP_SUNRISE_SUNSET
- if (e->sunflags) {
+// if (BIT_CHECK(e->weekDayFlags, ltm->tm_wday)) {
+ if (BIT_CHECK(e->weekDayFlags, tc.wday)) {
+#if ENABLE_TIME_SUNRISE_SUNSET
+ if (e->sunflags) { // no need to check for sunrise/sunset here. If sunflags != 0, it's either of them!!
+/*
if (e->lastDay != ltm->tm_wday) {
- e->lastDay = ltm->tm_wday; /* stop any further sun events today */
+ e->lastDay = ltm->tm_wday; // stop any further sun events today
dusk2Dawn(&sun_data, e->sunflags, &e->hour, &e->minute,
- calc_day_offset(ltm->tm_wday + 1, e->weekDayFlags)); /* setup for tomorrow */
+ calc_day_offset(ltm->tm_wday + 1, e->weekDayFlags)); // setup for tomorrow
CMD_ExecuteCommand(e->command, 0);
}
+*/
+ if (e->lastDay != tc.wday) {
+ e->lastDay = tc.wday; /* stop any further sun events today */
+ dusk2Dawn(&sun_data, e->sunflags, &e->hour, &e->minute,
+ calc_day_offset(tc.wday + 1, e->weekDayFlags)); /* setup for tomorrow */
+ CMD_ExecuteCommand(e->command, 0);
+ }
+
else {
e->lastDay = -1; /* mark with anything but a valid day of week */
}
@@ -223,45 +222,63 @@ void NTP_RunEventsForSecond(time_t runTime) {
e = e->next;
}
}
-
-void NTP_RunEvents(unsigned int newTime, bool bTimeValid) {
+#if ENABLE_TIME_SUNRISE_SUNSET && ENABLE_TIME_DST
+// in case a DST switch happens, we should change future events of sunset/sunrise, since this will be different after a switch
+// since we calculated the events in advance, we need to "fix" all events, postulating the DST switch is allways before a days sunrise and sunset
+void fix_DSTforEvents(int minutes){
+ clockEvent_t *e;
+ e = clock_events;
+ while (e) {
+// addLogAdv(LOG_INFO, LOG_FEATURE_CMD,"fix_DSTforEvents(%i) - testing %s",minutes,e->command);
+ if (e->command && e->sunflags) { // only for (future) sunflag events
+// addLogAdv(LOG_INFO, LOG_FEATURE_CMD,"fix_DSTforEvents(%i) - fixing %s",minutes,e->command);
+ int h = minutes/60;
+ int m = minutes % 60;
+ e->hour += h;
+ e->minute += m;
+ }
+ e = e->next;
+ }
+}
+#endif
+void TIME_RunEvents(unsigned int newTime, bool bTimeValid) {
unsigned int delta;
unsigned int i;
// new time invalid?
if (bTimeValid == false) {
- ntp_eventsTime = 0;
+ clock_eventsTime = 0;
return;
}
// old time invalid, but new one ok?
- if (ntp_eventsTime == 0) {
- ntp_eventsTime = (time_t)newTime;
+ if (clock_eventsTime == 0) {
+ clock_eventsTime = (time_t)newTime;
return;
}
// time went backwards
- if (newTime < ntp_eventsTime) {
- ntp_eventsTime = (time_t)newTime;
+ if (newTime < clock_eventsTime) {
+ clock_eventsTime = (time_t)newTime;
return;
}
- if (ntp_events) {
+ if (clock_events) {
// NTP resynchronization could cause us to skip some seconds in some rare cases?
- delta = (unsigned int)((time_t)newTime - ntp_eventsTime);
+ delta = (unsigned int)((time_t)newTime - clock_eventsTime);
// a large shift in time is not expected, so limit to a constant number of seconds
if (delta > 100)
delta = 100;
for (i = 0; i < delta; i++) {
- NTP_RunEventsForSecond(ntp_eventsTime + i);
+ TIME_RunEventsForSecond(clock_eventsTime + i);
}
}
- ntp_eventsTime = (time_t)newTime;
+ clock_eventsTime = (time_t)newTime;
}
-#if ENABLE_NTP_SUNRISE_SUNSET
-void NTP_AddClockEvent(int hour, int minute, int second, int weekDayFlags, int id, int sunflags, const char* command) {
+#if ENABLE_TIME_SUNRISE_SUNSET
+void TIME_AddEvent(int hour, int minute, int second, int weekDayFlags, int id, int sunflags, const char* command) {
#else
-void NTP_AddClockEvent(int hour, int minute, int second, int weekDayFlags, int id, const char* command) {
+void TIME_AddEvent(int hour, int minute, int second, int weekDayFlags, int id, const char* command) {
#endif
- ntpEvent_t* newEvent = (ntpEvent_t*)malloc(sizeof(ntpEvent_t));
+ clockEvent_t* newEvent = (clockEvent_t*)malloc(sizeof(clockEvent_t));
if (newEvent == NULL) {
// handle error
return;
@@ -271,25 +288,25 @@ void NTP_AddClockEvent(int hour, int minute, int second, int weekDayFlags, int i
newEvent->minute = minute;
newEvent->second = second;
newEvent->weekDayFlags = weekDayFlags;
-#if ENABLE_NTP_SUNRISE_SUNSET
+#if ENABLE_TIME_SUNRISE_SUNSET
newEvent->lastDay = -1; /* mark with anything but a valid day of week */
newEvent->sunflags = sunflags;
#endif
newEvent->id = id;
newEvent->command = strdup(command);
- newEvent->next = ntp_events;
+ newEvent->next = clock_events;
- ntp_events = newEvent;
+ clock_events = newEvent;
}
-int NTP_RemoveClockEvent(int id) {
+int TIME_RemoveEvent(int id) {
int ret = 0;
- ntpEvent_t* curr = ntp_events;
- ntpEvent_t* prev = NULL;
+ clockEvent_t* curr = clock_events;
+ clockEvent_t* prev = NULL;
while (curr != NULL) {
if (curr->id == id) {
if (prev == NULL) {
- ntp_events = curr->next;
+ clock_events = curr->next;
}
else {
prev->next = curr->next;
@@ -298,7 +315,7 @@ int NTP_RemoveClockEvent(int id) {
free(curr);
ret++;
if (prev == NULL) {
- curr = ntp_events;
+ curr = clock_events;
}
else {
curr = prev->next;
@@ -321,15 +338,16 @@ int NTP_RemoveClockEvent(int id) {
// addClockEvent 15:06:00 0xff 123 POWER TOGGLE
// Example: do event every Wednesday at sunrise
// addClockEvent sunrise 0x08 12 POWER OFF
-commandResult_t CMD_NTP_AddClockEvent(const void *context, const char *cmd, const char *args, int cmdFlags) {
+commandResult_t CMD_TIME_AddEvent(const void *context, const char *cmd, const char *args, int cmdFlags) {
int hour, minute = 0, second = 0;
const char *s;
int flags;
int id;
-#if ENABLE_NTP_SUNRISE_SUNSET
+#if ENABLE_TIME_SUNRISE_SUNSET
uint8_t hour_b, minute_b;
int sunflags = 0;
- struct tm *ltm = gmtime(&ntp_eventsTime);
+// struct tm *ltm = gmtime(&clock_eventsTime);
+ TimeComponents tc=calculateComponents(clock_eventsTime);
#endif
Tokenizer_TokenizeString(args, TOKENIZER_ALTERNATE_EXPAND_AT_START);
@@ -345,11 +363,14 @@ commandResult_t CMD_NTP_AddClockEvent(const void *context, const char *cmd, cons
if (sscanf(s, "%2d:%2d:%2d", &hour, &minute, &second) >= 2) {
// hour, minute and second has correct value parsed
}
-#if ENABLE_NTP_SUNRISE_SUNSET
- else if (strcasestr(s, "sunrise")) {
+#if ENABLE_TIME_SUNRISE_SUNSET
+//#include
+// else if (strcasestr(s, "sunrise")) { // eg W800 won't have strcasestr, so use wal_stricmp from new_common
+ else if (! wal_stricmp(s, "sunrise")) {
sunflags |= SUNRISE_FLAG;
}
- else if (strcasestr(s, "sunset")) {
+// else if (strcasestr(s, "sunset")) {
+ else if (! wal_stricmp(s, "sunset")) {
sunflags |= SUNSET_FLAG;
}
#endif
@@ -364,21 +385,23 @@ commandResult_t CMD_NTP_AddClockEvent(const void *context, const char *cmd, cons
id = Tokenizer_GetArgInteger(2);
s = Tokenizer_GetArgFrom(3);
-#if ENABLE_NTP_SUNRISE_SUNSET
+#if ENABLE_TIME_SUNRISE_SUNSET
if (sunflags) {
- dusk2Dawn(&sun_data, sunflags, &hour_b, &minute_b, calc_day_offset(ltm->tm_wday, flags));
+// dusk2Dawn(&sun_data, sunflags, &hour_b, &minute_b, calc_day_offset(ltm->tm_wday, flags));
+ dusk2Dawn(&sun_data, sunflags, &hour_b, &minute_b, calc_day_offset(tc.wday, flags));
hour = hour_b;
minute = minute_b;
+ addLogAdv(LOG_DEBUG, LOG_FEATURE_CMD,"Adding sunflags %2x",sunflags);
}
- NTP_AddClockEvent(hour, minute, second, flags, id, sunflags, s);
+ TIME_AddEvent(hour, minute, second, flags, id, sunflags, s);
#else
- NTP_AddClockEvent(hour, minute, second, flags, id, s);
+ TIME_AddEvent(hour, minute, second, flags, id, s);
#endif
return CMD_RES_OK;
}
// addPeriodValue [ChannelIndex] [Start_DayOfWeek] [Start_HH:MM:SS] [End_DayOfWeek] [End_HH:MM:SS] [Value] [UniqueID] [Flags]
-//commandResult_t CMD_NTP_AddPeriodValue(const void *context, const char *cmd, const char *args, int cmdFlags) {
+//commandResult_t CMD_TIME_AddPeriodValue(const void *context, const char *cmd, const char *args, int cmdFlags) {
// int start_hour, start_minute, start_second, start_day;
// int end_hour, end_minute, end_second, end_day;
// const char *s;
@@ -413,7 +436,7 @@ commandResult_t CMD_NTP_AddClockEvent(const void *context, const char *cmd, cons
// return CMD_RES_OK;
//}
-commandResult_t CMD_NTP_RemoveClockEvent(const void* context, const char* cmd, const char* args, int cmdFlags) {
+commandResult_t CMD_TIME_RemoveEvent(const void* context, const char* cmd, const char* args, int cmdFlags) {
int id;
// tokenize the args string
@@ -428,13 +451,13 @@ commandResult_t CMD_NTP_RemoveClockEvent(const void* context, const char* cmd, c
id = Tokenizer_GetArgInteger(0);
// Remove the clock event with the given id
- NTP_RemoveClockEvent(id);
+ TIME_RemoveEvent(id);
return CMD_RES_OK;
}
-int NTP_GetEventTime(int id) {
- for (ntpEvent_t* e = ntp_events; e; e = e->next)
+int TIME_GetEventTime(int id) {
+ for (clockEvent_t* e = clock_events; e; e = e->next)
{
if (e->id == id)
{
@@ -445,16 +468,16 @@ int NTP_GetEventTime(int id) {
return -1;
}
-int NTP_PrintEventList() {
- ntpEvent_t* e;
+int TIME_Print_EventList() {
+ clockEvent_t* e;
int t;
- e = ntp_events;
+ e = clock_events;
t = 0;
while (e) {
// Print the command
-#if ENABLE_CLOCK_SUNRISE_SUNSET
+#if ENABLE_TIME_SUNRISE_SUNSET
char sun[25] = {0};
if (e->sunflags) {
if (e->sunflags & SUNRISE_FLAG){
@@ -474,21 +497,21 @@ int NTP_PrintEventList() {
addLogAdv(LOG_INFO, LOG_FEATURE_CMD, "Total %i events", t);
return t;
}
-commandResult_t CMD_NTP_ListEvents(const void* context, const char* cmd, const char* args, int cmdFlags) {
+commandResult_t CMD_TIME_ListEvents(const void* context, const char* cmd, const char* args, int cmdFlags) {
- NTP_PrintEventList();
+ TIME_Print_EventList();
return CMD_RES_OK;
}
-int NTP_ClearEvents() {
- ntpEvent_t* e;
+int TIME_ClearEvents() {
+ clockEvent_t* e;
int t;
- e = ntp_events;
+ e = clock_events;
t = 0;
while (e) {
- ntpEvent_t *p = e;
+ clockEvent_t *p = e;
t++;
e = e->next;
@@ -496,38 +519,38 @@ int NTP_ClearEvents() {
free(p->command);
free(p);
}
- ntp_events = 0;
+ clock_events = 0;
addLogAdv(LOG_INFO, LOG_FEATURE_CMD, "Removed %i events", t);
return t;
}
-commandResult_t CMD_NTP_ClearEvents(const void* context, const char* cmd, const char* args, int cmdFlags) {
+commandResult_t CMD_TIME_ClearEvents(const void* context, const char* cmd, const char* args, int cmdFlags) {
- NTP_ClearEvents();
+ TIME_ClearEvents();
return CMD_RES_OK;
}
-void NTP_Init_Events() {
+void TIME_Init_Events() {
//cmddetail:{"name":"addClockEvent","args":"[TimerSeconds or Time or sunrise or sunset] [WeekDayFlags] [UniqueIDForRemoval][Command]",
- //cmddetail:"descr":"Schedule command to run on given time in given day of week. NTP must be running. TimerSeconds is seconds from midnight, Time is a time like HH:mm or HH:mm:ss, WeekDayFlag is a bitflag on which day to run, 0xff mean all days, 0x01 means sunday, 0x02 monday, 0x03 sunday and monday, etc, id is an unique id so event can be removed later. (NOTE: Use of sunrise/sunset requires compiling with ENABLE_NTP_SUNRISE_SUNSET set which adds about 11k of code)",
- //cmddetail:"fn":"CMD_NTP_AddClockEvent","file":"driver/drv_ntp_events.c","requires":"",
- //cmddetail:"examples":""}
- CMD_RegisterCommand("addClockEvent",CMD_NTP_AddClockEvent, NULL);
+ //cmddetail:"descr":"Schedule command to run on given time in given day of week. CLOCK must be running. TimerSeconds is seconds from midnight, Time is a time like HH:mm or HH:mm:ss, WeekDayFlag is a bitflag on which day to run, 0xff mean all days, 0x01 means sunday, 0x02 monday, 0x03 sunday and monday, etc, id is an unique id so event can be removed later. (NOTE: Use of sunrise/sunset requires compiling with ENABLE_TIME_SUNRISE_SUNSET set which adds about 11k of code)",
+ //cmddetail:"fn":"CMD_TIME_AddEvent","file":"driver/drv_timed_events.c","requires":"",
+ //cmddetail:"examples":""}
+ CMD_RegisterCommand("addClockEvent",CMD_TIME_AddEvent, NULL);
//cmddetail:{"name":"removeClockEvent","args":"[ID]",
//cmddetail:"descr":"Removes clock event with given ID",
- //cmddetail:"fn":"CMD_NTP_RemoveClockEvent","file":"driver/drv_ntp_events.c","requires":"",
+ //cmddetail:"fn":"CMD_TIME_RemoveEvent","file":"driver/drv_timed_events.c","requires":"",
//cmddetail:"examples":""}
- CMD_RegisterCommand("removeClockEvent", CMD_NTP_RemoveClockEvent, NULL);
+ CMD_RegisterCommand("removeClockEvent", CMD_TIME_RemoveEvent, NULL);
//cmddetail:{"name":"listClockEvents","args":"",
//cmddetail:"descr":"Print the complete set clock events list",
- //cmddetail:"fn":"CMD_NTP_ListEvents","file":"driver/drv_ntp_events.c","requires":"",
+ //cmddetail:"fn":"CMD_TIME_ListEvents","file":"driver/drv_timed_events.c","requires":"",
//cmddetail:"examples":""}
- CMD_RegisterCommand("listClockEvents", CMD_NTP_ListEvents, NULL);
+ CMD_RegisterCommand("listClockEvents", CMD_TIME_ListEvents, NULL);
//cmddetail:{"name":"clearClockEvents","args":"",
//cmddetail:"descr":"Removes all set clock events",
- //cmddetail:"fn":"CMD_NTP_ClearEvents","file":"driver/drv_ntp_events.c","requires":"",
+ //cmddetail:"fn":"CMD_TIME_ClearEvents","file":"driver/drv_timed_events.c","requires":"",
//cmddetail:"examples":""}
- CMD_RegisterCommand("clearClockEvents", CMD_NTP_ClearEvents, NULL);
- //CMD_RegisterCommand("addPeriodValue", CMD_NTP_AddPeriodValue, NULL);
+ CMD_RegisterCommand("clearClockEvents", CMD_TIME_ClearEvents, NULL);
+ //CMD_RegisterCommand("addPeriodValue", CMD_TIME_AddPeriodValue, NULL);
}
diff --git a/src/driver/drv_tuyaMCU.c b/src/driver/drv_tuyaMCU.c
index b4efbaec9..4e6e1b9e7 100644
--- a/src/driver/drv_tuyaMCU.c
+++ b/src/driver/drv_tuyaMCU.c
@@ -25,7 +25,7 @@ https://developer.tuya.com/en/docs/iot/tuyacloudlowpoweruniversalserialaccesspro
#include "drv_uart.h"
#include "drv_public.h"
#include
-#include "drv_ntp.h"
+#include "drv_deviceclock.h"
#include "../rgb2hsv.h"
@@ -781,9 +781,11 @@ void TuyaMCU_Send_SetTime(struct tm* pTime, bool bSensorMode) {
}
struct tm* TuyaMCU_Get_NTP_Time() {
struct tm* ptm;
+ time_t ntpTime;
- addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "MCU time to set: %i\n", g_ntpTime);
- ptm = gmtime(&g_ntpTime);
+ ntpTime=(time_t)TIME_GetCurrentTime();
+ addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "MCU time to set: %i\n", ntpTime);
+ ptm = gmtime(&ntpTime);
if (ptm != 0) {
addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "ptime ->gmtime => tm_hour: %i\n", ptm->tm_hour);
addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "ptime ->gmtime => tm_min: %i\n", ptm->tm_min);
diff --git a/src/driver/drv_txw81x_camera.c b/src/driver/drv_txw81x_camera.c
index 2d1392a83..ecf93539c 100644
--- a/src/driver/drv_txw81x_camera.c
+++ b/src/driver/drv_txw81x_camera.c
@@ -17,6 +17,7 @@
#include "lib/net/eloop/eloop.h"
#include "lib/video/dvp/jpeg/jpg.h"
#include "project_config.h"
+#include "../libraries/obktime/obktime.h" // for time functions
extern struct vpp_device* vpp_test;
bool isStarted = false;
@@ -106,9 +107,15 @@ void TXW_Cam_RunEverySecond(void)
{
if(showTimestamp)
{
+/*
struct tm* ltm = gmtime(&g_ntpTime);
set_time_watermark(ltm->tm_year + 1900, ltm->tm_mon + 1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec);
+*/
+ TimeComponents tc;
+ tc=calculateComponents(TIME_GetCurrentTime());
+ set_time_watermark(tc.year, tc.month, tc.day, tc.hour, tc.minute, tc.second);
+
}
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/httpserver/http_fns.c b/src/httpserver/http_fns.c
index e7135ac94..d59a383fd 100644
--- a/src/httpserver/http_fns.c
+++ b/src/httpserver/http_fns.c
@@ -20,6 +20,7 @@
#include "../cJSON/cJSON.h"
#include
#include "../driver/drv_ntp.h"
+#include "../driver/drv_deviceclock.h" // to set clock via Javascript in pmntp
#include "../driver/drv_local.h"
#ifdef PLATFORM_BEKEN
#include "start_type_pub.h"
@@ -207,6 +208,38 @@ int http_fn_testmsg(http_request_t* request) {
}
+#if ENABLE_TIME_PMNTP
+// poor mans NTP
+int http_fn_pmntp(http_request_t* request) {
+ char tmpA[128];
+ uint32_t actepoch=0;
+ // javascripts "getTime()" should return time since 01.01.1970 (UTC)
+ if (http_getArg(request->url, "EPOCH", tmpA, sizeof(tmpA))) {
+ actepoch = (uint32_t)strtoul(tmpA,0,10);
+ TIME_setDeviceTime(actepoch);
+ addLogAdv(LOG_DEBUG, LOG_FEATURE_HTTP,"Set clock to %u! \n",actepoch);
+ }
+#if ENABLE_TIME_DST
+ if (! IsDST_initialized()) {
+#endif
+ if (http_getArg(request->url, "OFFSET", tmpA, sizeof(tmpA)) && actepoch != 0 ) {
+ // if actual time is during DST period, javascript will return
+ // an offset including the one additional hour of DST
+ // if we don't handle DST, simply accept this as "offset"
+ TIME_setDeviceTimeOffset(atoi(tmpA));
+ addLogAdv(LOG_DEBUG, LOG_FEATURE_HTTP,"Clock - set g_UTCoffset to %i! \n",
+ atoi(tmpA));
+ }
+#if ENABLE_TIME_DST
+ // ignore JS offset, if we can/will calculate DST on our own
+ } else setDST();
+#endif
+ poststr(request, "HTTP/1.1 302 OK\nLocation: /index\nConnection: close\n\n");
+ poststr(request, NULL);
+ return 0;
+}
+#endif
+
// bit mask telling which channels are hidden from HTTP
// If given bit is set, then given channel is hidden
extern int g_hiddenChannels;
@@ -1142,7 +1175,9 @@ typedef enum {
}
poststr(request, " ");
poststr(request, "");
-
+#if ENABLE_TIME_PMNTP
+ poststr(request, "");
+#endif
poststr(request, htmlFooterRefreshLink);
http_html_end(request);
}
diff --git a/src/httpserver/http_fns.h b/src/httpserver/http_fns.h
index f5ba95ac1..46170d813 100644
--- a/src/httpserver/http_fns.h
+++ b/src/httpserver/http_fns.h
@@ -33,3 +33,4 @@ int http_fn_startup_command(http_request_t* request);
int http_fn_cfg_generic(http_request_t* request);
int http_fn_cfg_startup(http_request_t* request);
int http_fn_cfg_dgr(http_request_t* request);
+int http_fn_pmntp(http_request_t* request);
diff --git a/src/httpserver/json_interface.c b/src/httpserver/json_interface.c
index 263fd914a..483394367 100644
--- a/src/httpserver/json_interface.c
+++ b/src/httpserver/json_interface.c
@@ -16,14 +16,17 @@
#include "../mqtt/new_mqtt.h"
#include "hass.h"
#include "../cJSON/cJSON.h"
-#include
+//#include
#include "../driver/drv_ntp.h"
+#include "../driver/drv_deviceclock.h"
#include "../driver/drv_local.h"
#include "../driver/drv_bl_shared.h"
#include "../driver/drv_ds1820_simple.h"
#include "../driver/drv_ds1820_full.h"
+#include "../libraries/obktime/obktime.h" // for time functions
+
#if ENABLE_TASMOTA_JSON
void JSON_PrintKeyValue_String(void* request, jsonCb_t printer, const char* key, const char* value, bool bComma) {
@@ -378,10 +381,12 @@ static int http_tasmota_json_SENSOR(void* request, jsonCb_t printer) {
/*
{"StatusSNS":{"Time":"2023-04-10T10:19:55"}}
*/
-static void format_date(char *buffer, int buflength, struct tm *ltm)
+/*static void format_date(char *buffer, int buflength, struct tm *ltm)
{
snprintf(buffer, buflength, "%04d-%02d-%02dT%02d:%02d:%02d",ltm->tm_year+1900, ltm->tm_mon+1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec);
}
+*/
+// use obktimes ISO_8601 for this, e.g. TS2STR(TIME_GetCurrentTime(),TIME_FORMAT_ISO_8601)
static int http_tasmota_json_status_SNS(void* request, jsonCb_t printer, bool bAppendHeader) {
char buff[20];
@@ -391,9 +396,11 @@ static int http_tasmota_json_status_SNS(void* request, jsonCb_t printer, bool bA
}
printer(request, "{");
- time_t localTime = (time_t)NTP_GetCurrentTime();
+/* time_t localTime = (time_t)TIME_GetCurrentTime();
format_date(buff, sizeof(buff), gmtime(&localTime));
JSON_PrintKeyValue_String(request, printer, "Time", buff, false);
+*/
+ JSON_PrintKeyValue_String(request, printer, "Time", TS2STR(TIME_GetCurrentTime(),TIME_FORMAT_ISO_8601), false);
#ifndef OBK_DISABLE_ALL_DRIVERS
#ifdef ENABLE_DRIVER_BL0937
@@ -466,14 +473,16 @@ void format_time(int total_seconds, char* output, int outLen) {
static int http_tasmota_json_status_STS(void* request, jsonCb_t printer, bool bAppendHeader) {
char buff[20];
- time_t localTime = (time_t)NTP_GetCurrentTime();
+ time_t localTime = (time_t)TIME_GetCurrentTime();
if (bAppendHeader) {
printer(request, "\"StatusSTS\":");
}
printer(request, "{");
- format_date(buff, sizeof(buff), gmtime(&localTime));
- JSON_PrintKeyValue_String(request, printer, "Time", buff, true);
+// format_date(buff, sizeof(buff), gmtime(&localTime));
+// JSON_PrintKeyValue_String(request, printer, "Time", buff, true);
+ JSON_PrintKeyValue_String(request, printer, "Time", TS2STR(TIME_GetCurrentTime(),TIME_FORMAT_ISO_8601), true);
+
format_time(g_secondsElapsed, buff, sizeof(buff));
JSON_PrintKeyValue_String(request, printer, "Uptime", buff, true);
//JSON_PrintKeyValue_String(request, printer, "Uptime", "30T02:59:30", true);
@@ -516,16 +525,29 @@ static int http_tasmota_json_status_STS(void* request, jsonCb_t printer, bool bA
static int http_tasmota_json_status_TIM(void* request, jsonCb_t printer) {
char buff[20];
- time_t localTime = (time_t)NTP_GetCurrentTime();
- time_t localUTC = (time_t)NTP_GetCurrentTimeWithoutOffset();
+// time_t localTime = (time_t)TIME_GetCurrentTime();
+// time_t localUTC = (time_t)TIME_GetCurrentTimeWithoutOffset();
printer(request, "\"StatusTIM\":{");
- format_date(buff, sizeof(buff), gmtime(&localUTC));
- JSON_PrintKeyValue_String(request, printer, "UTC", buff, true);
- format_date(buff, sizeof(buff), gmtime(&localTime));
- JSON_PrintKeyValue_String(request, printer, "Local", buff, true);
+// format_date(buff, sizeof(buff), gmtime(&localUTC));
+// JSON_PrintKeyValue_String(request, printer, "UTC", buff, true);
+ JSON_PrintKeyValue_String(request, printer, "UTC", TS2STR(TIME_GetCurrentTimeWithoutOffset(),TIME_FORMAT_ISO_8601), true);
+// format_date(buff, sizeof(buff), gmtime(&localTime));
+// JSON_PrintKeyValue_String(request, printer, "Local", buff, true);
+ JSON_PrintKeyValue_String(request, printer, "Local", TS2STR(TIME_GetCurrentTime(),TIME_FORMAT_ISO_8601), true);
+#if ENABLE_TIME_DST
+ uint32_t DST[2]={0,0};
+ // only get DST settings, if DST is set
+ if (getDST_offset() > 0) getDSTtransition(DST);
+ JSON_PrintKeyValue_String(request, printer, "StartDST", TS2STR(DST[0],TIME_FORMAT_ISO_8601) , true);
+ JSON_PrintKeyValue_String(request, printer, "EndDST", TS2STR(DST[1],TIME_FORMAT_ISO_8601), true);
+#else
JSON_PrintKeyValue_String(request, printer, "StartDST", "2022-03-27T02:00:00", true);
JSON_PrintKeyValue_String(request, printer, "EndDST", "2022-10-30T03:00:00", true);
- JSON_PrintKeyValue_String(request, printer, "Timezone", "+01:00", true);
+#endif
+ int TZ=TIME_GetCurrentTime() - TIME_GetCurrentTimeWithoutOffset();
+ char tmp[8];
+ sprintf(tmp,"%+03i:%02i",(int8_t)TZ/3600,(uint8_t)abs((TZ%3600)/60));
+ JSON_PrintKeyValue_String(request, printer, "Timezone", tmp, true);
JSON_PrintKeyValue_String(request, printer, "Sunrise", "07:50", true);
JSON_PrintKeyValue_String(request, printer, "Sunset", "17:17", false);
printer(request, "}");
@@ -735,17 +757,20 @@ static int http_tasmota_json_status_generic(void* request, jsonCb_t printer) {
JSON_PrintKeyValue_String(request, printer, "OtaUrl", "https://github.com/openshwprojects/OpenBK7231T_App/releases/latest", true);
JSON_PrintKeyValue_String(request, printer, "RestartReason", "HardwareWatchdog", true);
JSON_PrintKeyValue_Int(request, printer, "Uptime", g_secondsElapsed, true);
- struct tm* ltm;
+// struct tm* ltm;
time_t ntpTime = 0; // if no NTP_time set, we will not change this value, but just stick to 0 and hence "fake" start of epoch 1970-01-01T00:00:00
- if (NTP_GetCurrentTimeWithoutOffset() > g_secondsElapsed) { // would be negative else, leading to unwanted results when converted to (unsigned) time_t
- ntpTime = (time_t)NTP_GetCurrentTimeWithoutOffset() - (time_t)g_secondsElapsed;
+ if (TIME_GetCurrentTimeWithoutOffset() > g_secondsElapsed) { // would be negative else, leading to unwanted results when converted to (unsigned) time_t
+ ntpTime = (time_t)TIME_GetCurrentTimeWithoutOffset() - (time_t)g_secondsElapsed;
}
+/*
ltm = gmtime(&ntpTime);
if (ltm != 0) {
printer(request, "\"StartupUTC\":\"%04d-%02d-%02dT%02d:%02d:%02d\",", ltm->tm_year + 1900, ltm->tm_mon + 1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec);
}
else {
}
+*/
+ printer(request, "\"StartupUTC\":\"%s\",", TS2STR(TIME_GetCurrentTime(),TIME_FORMAT_ISO_8601));
JSON_PrintKeyValue_Int(request, printer, "Sleep", 50, true);
JSON_PrintKeyValue_Int(request, printer, "CfgHolder", 4617, true);
JSON_PrintKeyValue_Int(request, printer, "BootCount", 22, true);
diff --git a/src/httpserver/new_http.c b/src/httpserver/new_http.c
index 7cfd77b97..c80bc494d 100644
--- a/src/httpserver/new_http.c
+++ b/src/httpserver/new_http.c
@@ -340,9 +340,9 @@ void http_html_end(http_request_t* request) {
poststr(request, g_build_str);
hprintf255(request, " Online for - ", g_secondsElapsed);
-
WiFI_GetMacAddress((char*)mac);
+
snprintf(upTimeStr, sizeof(upTimeStr), " Device MAC: %02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
poststr(request, upTimeStr);
snprintf(upTimeStr, sizeof(upTimeStr), " Short name: %s, Chipset %s", CFG_GetShortDeviceName(), PLATFORM_MCU_NAME);
@@ -912,7 +912,10 @@ int HTTP_ProcessPacket(http_request_t* request) {
if (http_checkUrlBase(urlStr, "ota")) return http_fn_ota(request);
if (http_checkUrlBase(urlStr, "ota_exec")) return http_fn_ota_exec(request);
if (http_checkUrlBase(urlStr, "cm")) return http_fn_cm(request);
-
+
+#if ENABLE_TIME_PMNTP
+ if (http_checkUrlBase(urlStr, "pmntp")) return http_fn_pmntp(request); // poor mans NTP
+#endif
return http_fn_other(request);
}
diff --git a/src/libraries/obktime/obktime.c b/src/libraries/obktime/obktime.c
new file mode 100644
index 000000000..7836fef40
--- /dev/null
+++ b/src/libraries/obktime/obktime.c
@@ -0,0 +1,182 @@
+#include "obktime.h"
+#include
+#include "../../logging/logging.h"
+
+char timestring[20];
+static const uint8_t daysInMonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
+
+bool isLeapYear(uint16_t year) {
+ return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
+}
+
+bool isValidDate(uint16_t year, uint8_t month, uint8_t day) {
+ if (year < EPOCH_YEAR || month < 1 || month > 12 || day < 1 || day > 31)
+ return false;
+
+ uint8_t dim = daysInMonth[month-1];
+ if (month == 2 && isLeapYear(year)) dim++;
+ return day <= dim;
+}
+
+TimeComponents calculateComponents(uint32_t timestamp) {
+ TimeComponents tc = {0};
+ if (timestamp == 0) return tc;
+
+ // Calculate time
+ tc.second = timestamp % SECS_PER_MIN;
+
+ timestamp /= SECS_PER_MIN;
+ tc.minute = timestamp % SECS_PER_MIN;
+
+ timestamp /= SECS_PER_MIN;
+ tc.hour = timestamp % 24;
+
+ timestamp /= 24;
+ // Calculate weekday (0=Sunday)
+ tc.wday = (timestamp + 4) % 7; // 1970-01-01 was Thursday (4)
+
+ // Calculate date
+ uint16_t days = timestamp;
+ tc.year = EPOCH_YEAR;
+
+ while (days >= (isLeapYear(tc.year) ? 366 : 365)) {
+ days -= isLeapYear(tc.year) ? 366 : 365;
+ tc.year++;
+ }
+
+ uint8_t month = 0;
+ days++;
+ for (month = 0; month < 12; month++) {
+ uint8_t dim = daysInMonth[month];
+ if (month == 1 && isLeapYear(tc.year)) dim++;
+ if (days <= dim) break;
+ days -= dim;
+ }
+
+ tc.month = month + 1;
+ tc.day = days;
+
+ return tc;
+}
+
+uint32_t dateToEpoch(uint16_t year, uint8_t month, uint8_t day,
+ uint8_t hour, uint8_t minute, uint8_t second) {
+ if (!isValidDate(year, month, day)) return 0;
+
+ // Calculate days since epoch
+ uint32_t days = 0;
+ for (uint16_t y = EPOCH_YEAR; y < year; y++) {
+ days += isLeapYear(y) ? 366 : 365;
+ }
+
+ // Add days in current year
+ for (uint8_t m = 1; m < month; m++) {
+ days += daysInMonth[m-1];
+ if (m == 2 && isLeapYear(year)) days++;
+ }
+ days += day - 1;
+
+ return ((days * 24 + hour) * 60 + minute) * 60 + second;
+}
+
+/*
+uint32_t stringToEpoch(const char* datetime) {
+ uint16_t year;
+ uint8_t month, day, hour, minute, second;
+
+ if (strlen(datetime) == 19) {
+ sscanf(datetime, "%04hu-%02hhu-%02hhu %02hhu:%02hhu:%02hhu",
+ &year, &month, &day, &hour, &minute, &second);
+ } else {
+ sscanf(datetime, "%04hu%02hhu%02hhu-%02hhu%02hhu%02hhu",
+ &year, &month, &day, &hour, &minute, &second);
+ }
+
+ return dateToEpoch(year, month, day, hour, minute, second);
+}
+*/
+
+void formatTimestamp(uint32_t timestamp, char* buffer, char date_sep, char datetime_sep, char time_sep) {
+ TimeComponents tc = calculateComponents(timestamp);
+ char *p = buffer;
+
+ // Year (always 4 digits)
+ *p++ = '0' + (tc.year/1000)%10;
+ *p++ = '0' + (tc.year/100)%10;
+ *p++ = '0' + (tc.year/10)%10;
+ *p++ = '0' + tc.year%10;
+
+ // Date separator and month
+ if (date_sep) *p++ = date_sep;
+ *p++ = '0' + tc.month/10;
+ *p++ = '0' + tc.month%10;
+
+ // Date separator and day
+ if (date_sep) *p++ = date_sep;
+ *p++ = '0' + tc.day/10;
+ *p++ = '0' + tc.day%10;
+
+ // Date-time separator
+ if (datetime_sep) *p++ = datetime_sep;
+
+ // Hour
+ *p++ = '0' + tc.hour/10;
+ *p++ = '0' + tc.hour%10;
+
+ // Time separator and minute
+ if (time_sep) *p++ = time_sep;
+ *p++ = '0' + tc.minute/10;
+ *p++ = '0' + tc.minute%10;
+
+ // Time separator and second
+ if (time_sep) *p++ = time_sep;
+ *p++ = '0' + tc.second/10;
+ *p++ = '0' + tc.second%10;
+
+ *p = '\0';
+}
+
+char * TS2STR(uint32_t timestamp, char date_sep, char datetime_sep, char time_sep) {
+ TimeComponents tc = calculateComponents(timestamp);
+ char *p = timestring;
+ timestring[19]='\0';
+ if (date_sep != '\x1'){
+ // Year (always 4 digits)
+ *p++ = '0' + (tc.year/1000)%10;
+ *p++ = '0' + (tc.year/100)%10;
+ *p++ = '0' + (tc.year/10)%10;
+ *p++ = '0' + tc.year%10;
+
+ // Date separator and month
+ if (date_sep) *p++ = date_sep;
+ *p++ = '0' + tc.month/10;
+ *p++ = '0' + tc.month%10;
+
+ // Date separator and day
+ if (date_sep) *p++ = date_sep;
+ *p++ = '0' + tc.day/10;
+ *p++ = '0' + tc.day%10;
+ }
+ // Date-time separator
+ if (datetime_sep) *p++ = datetime_sep;
+
+ if (time_sep != '\x1'){
+ // Hour
+ *p++ = '0' + tc.hour/10;
+ *p++ = '0' + tc.hour%10;
+
+ // Time separator and minute
+ if (time_sep) *p++ = time_sep;
+ *p++ = '0' + tc.minute/10;
+ *p++ = '0' + tc.minute%10;
+
+ // Time separator and second
+ if (time_sep) *p++ = time_sep;
+ *p++ = '0' + tc.second/10;
+ *p++ = '0' + tc.second%10;
+ }
+ *p = '\0';
+
+ return timestring;
+
+}
diff --git a/src/libraries/obktime/obktime.h b/src/libraries/obktime/obktime.h
new file mode 100644
index 000000000..d6d8ffe58
--- /dev/null
+++ b/src/libraries/obktime/obktime.h
@@ -0,0 +1,57 @@
+#ifndef TIME_UTILS_H
+#define TIME_UTILS_H
+
+#include
+#include
+#include "../../new_common.h"
+
+// Time components structure
+typedef struct {
+ uint8_t second; // 0-59
+ uint8_t minute; // 0-59
+ uint8_t hour; // 0-23
+ uint8_t day; // 1-31
+ uint8_t month; // 1-12
+ uint16_t year; // full year, e.g. 1899 or 2025
+ uint8_t wday; // 0-6 (Sunday=0)
+} TimeComponents;
+
+// Constants
+#define SECS_PER_MIN 60
+#define SECS_PER_HOUR 3600
+#define SECS_PER_DAY 86400
+#define EPOCH_YEAR 1970
+
+// API Functions
+
+// Conversion functions
+TimeComponents calculateComponents(uint32_t timestamp); // replacement for gmtime() to get (some) components of an epoch timestamp
+
+// two simple replacements for mktime()
+uint32_t dateToEpoch(uint16_t year, uint8_t month, uint8_t day,
+ uint8_t hour, uint8_t minute, uint8_t second);
+//uint32_t stringToEpoch(const char* datetime);
+
+// Formatting functions
+#define TIME_FORMAT_SHORT 0, '-', 0 // "20231231-235959"
+#define TIME_FORMAT_LONG '-', ' ', ':' // "2023-12-31 23:59:59"
+#define TIME_FORMAT_ISO_8601 '-', 'T', ':' // "2023-12-31T23:59:59"
+#define TIME_FORMAT_DATEonly '-', 0, '\x1' // "2023-12-31"
+#define TIME_FORMAT_TIMEonly '\x1', 0, ':' // "23:59:59"
+/*
+// examples with
+formatTime(ts, buf, TIME_FORMAT_LONG) "2023-12-31 23:59:59" "YYYY-MM-DD HH:MM:SS" needs 20 chars including \0
+formatTime(ts, buf, TIME_FORMAT_SHORT) "20231231-235959"
+No separators formatTimeEx(ts, buf, 0, 0, 0) "20231231235959"
+File-safe formatTimeEx(ts, buf, '-', '_', '-') "2023-12-31_23-59-59"
+*/
+
+void formatTimestamp(uint32_t timestamp, char* buffer, char date_sep, char datetime_sep, char time_sep);
+// same, but return pointer to internal char array. This is shared!!!!
+char * TS2STR(uint32_t timestamp, char date_sep, char datetime_sep, char time_sep);
+
+// Helper functions
+bool isValidDate(uint16_t year, uint8_t month, uint8_t day);
+bool isLeapYear(uint16_t year);
+
+#endif // TIME_UTILS_H
diff --git a/src/mqtt/new_mqtt.c b/src/mqtt/new_mqtt.c
index 5c43ca813..8433196d7 100644
--- a/src/mqtt/new_mqtt.c
+++ b/src/mqtt/new_mqtt.c
@@ -13,6 +13,7 @@
#include "../hal/hal_wifi.h"
#include "../driver/drv_public.h"
#include "../driver/drv_ntp.h"
+#include "../driver/drv_deviceclock.h"
#include "../driver/drv_tuyaMCU.h"
#include "../hal/hal_ota.h"
#ifndef WINDOWS
@@ -2067,19 +2068,31 @@ OBK_Publish_Result MQTT_DoItemPublish(int idx)
case PUBLISHITEM_SELF_DATETIME:
- //Drivers are only built on BK7231 chips
+// TIME_GetCurrentTime() is allways present
+/* //Drivers are only built on BK7231 chips
#ifndef OBK_DISABLE_ALL_DRIVERS
+
if (DRV_IsRunning("NTP")) {
- sprintf(dataStr, "%d", NTP_GetCurrentTime());
- return MQTT_DoItemPublishString("datetime", dataStr);
- }
+*/
+#ifdef PLATFORM_ESP8266
+ // while all other platforms will accept uint32_t as long unsigned, ESP8266 needs %u
+ // biuild fails otherwise because of -Werror=format
+ // src/mqtt/new_mqtt.c:2036:24: error: format '%ld' expects argument of type 'long int', but argument 3 has type 'uint32_t' {aka 'unsigned int'} [-Werror=format=]
+ // al other ESP:
+ /// src/mqtt/new_mqtt.c:2036:44: error: format '%d' expects argument of type 'int', but argument 3 has type 'uint32_t' {aka 'long unsigned int'} [-Werror=format=]
+ sprintf(dataStr, "%u", TIME_GetCurrentTime());
+#else
+ sprintf(dataStr, "%lu", TIME_GetCurrentTime());
+#endif
+ return MQTT_DoItemPublishString("datetime", dataStr);
+/* }
else {
return OBK_PUBLISH_WAS_NOT_REQUIRED;
}
#else
return OBK_PUBLISH_WAS_NOT_REQUIRED;
#endif
-
+*/
case PUBLISHITEM_SELF_SOCKETS:
sprintf(dataStr, "%d", LWIP_GetActiveSockets());
return MQTT_DoItemPublishString("sockets", dataStr);
@@ -2579,7 +2592,9 @@ struct tm* mbedtls_platform_gmtime_r(const mbedtls_time_t* tt, struct tm* tm_buf
}
return ltm;
}
- return gmtime_r((time_t*)&g_ntpTime, tm_buf);
+ time_t ntpTime;
+ ntpTime=(time_t)TIME_GetCurrentTime();
+ return gmtime_r((time_t*)&ntpTime, tm_buf);
}
#endif //MBEDTLS_PLATFORM_GMTIME_R_ALT
diff --git a/src/new_common.h b/src/new_common.h
index 9c24e3433..c06c6b6bd 100644
--- a/src/new_common.h
+++ b/src/new_common.h
@@ -309,6 +309,8 @@ This platform is not supported, error!
#define bk_printf printf
// generic
+#include
+
typedef int bool;
#define true 1
#define false 0
@@ -478,6 +480,8 @@ OSStatus rtos_suspend_thread(beken_thread_t* thread);
#include
#include
#include "lwip/sys.h"
+#include
+
#define GLOBAL_INT_DECLARATION() ;
#define GLOBAL_INT_DISABLE() ;
diff --git a/src/obk_config.h b/src/obk_config.h
index c2a628802..87444eded 100644
--- a/src/obk_config.h
+++ b/src/obk_config.h
@@ -74,7 +74,7 @@
#define ENABLE_MQTT 1
#define ENABLE_TASMOTADEVICEGROUPS 1
#define ENABLE_NTP 1
-// #define ENABLE_NTP_DST 1
+//#define ENABLE_TIME_DST 1
#define ENABLE_DRIVER_BL0937 1
#define ENABLE_DRIVER_DHT 1
#define ENABLE_TASMOTA_JSON 1
@@ -134,7 +134,7 @@
#define ENABLE_TASMOTADEVICEGROUPS 1
#define ENABLE_LITTLEFS 1
#define ENABLE_NTP 1
-#define ENABLE_NTP_DST 1
+#define ENABLE_TIME_DST 1
#define ENABLE_DRIVER_LED 1
#define ENABLE_DRIVER_BL0937 1
#define ENABLE_DRIVER_BL0942 1
@@ -159,7 +159,7 @@
#define ENABLE_DRIVER_PT6523 1
#define ENABLE_DRIVER_MAX6675 1
#define ENABLE_DRIVER_TEXTSCROLLER 1
-#define ENABLE_NTP_SUNRISE_SUNSET 1
+#define ENABLE_TIME_SUNRISE_SUNSET 1
// parse things like $CH1 or $hour etc
#define ENABLE_EXPAND_CONSTANT 1
#define ENABLE_DRIVER_DHT 1
@@ -196,7 +196,7 @@
#define ENABLE_TASMOTADEVICEGROUPS 1
#define ENABLE_LITTLEFS 1
#define ENABLE_NTP 1
-// #define ENABLE_NTP_DST 1
+// #define ENABLE_TIME_DST 1
#define ENABLE_CALENDAR_EVENTS 1
#define ENABLE_DRIVER_LED 1
#define ENABLE_DRIVER_BL0937 1
@@ -246,8 +246,8 @@
#define ENABLE_TASMOTADEVICEGROUPS 1
#define ENABLE_LITTLEFS 1
#define ENABLE_NTP 1
-// #define ENABLE_NTP_DST 1
-#define ENABLE_NTP_SUNRISE_SUNSET 1
+// #define ENABLE_TIME_DST 1
+#define ENABLE_TIME_SUNRISE_SUNSET 1
#define ENABLE_DRIVER_LED 1
#define ENABLE_DRIVER_BL0937 1
#define ENABLE_DRIVER_BL0942 1
@@ -276,6 +276,7 @@
#define ENABLE_DRIVER_SM16703P 1
#define ENABLE_DRIVER_PIXELANIM 1
#define ENABLE_DRIVER_SM15155E 1
+
#endif
// parse things like $CH1 or $hour etc
#define ENABLE_EXPAND_CONSTANT 1
@@ -365,7 +366,7 @@
#define ENABLE_MQTT 1
#define ENABLE_TASMOTADEVICEGROUPS 1
#define ENABLE_NTP 1
-//#define ENABLE_NTP_DST 1
+//#define ENABLE_TIME_DST 1
#define ENABLE_DRIVER_BL0937 1
#define ENABLE_DRIVER_LED 1
#define ENABLE_DRIVER_WEMO 1
@@ -393,7 +394,7 @@
#define ENABLE_MQTT 1
#define ENABLE_I2C 1
#define ENABLE_NTP 1
-//#define ENABLE_NTP_DST 1
+//#define ENABLE_TIME_DST 1
#define ENABLE_DRIVER_LED 1
#define ENABLE_DRIVER_TUYAMCU 1
#define ENABLE_LITTLEFS 1
@@ -608,6 +609,5 @@
// #define ENABLE_BL_MOVINGAVG 1
#endif
-
// closing OBK_CONFIG_H
#endif
diff --git a/src/selftest/selftest_clockEvents.c b/src/selftest/selftest_clockEvents.c
index 237535064..96ef556c2 100644
--- a/src/selftest/selftest_clockEvents.c
+++ b/src/selftest/selftest_clockEvents.c
@@ -4,8 +4,8 @@
#include "../driver/drv_ntp.h"
static void ResetEventsAndChannels(int eventsCleared) {
- SELFTEST_ASSERT(NTP_ClearEvents() == eventsCleared);
- SELFTEST_ASSERT(NTP_PrintEventList() == 0);
+ SELFTEST_ASSERT(TIME_ClearEvents() == eventsCleared);
+ SELFTEST_ASSERT(TIME_Print_EventList() == 0);
CMD_ExecuteCommand("setChannel 1 0", 0);
CMD_ExecuteCommand("setChannel 2 0", 0);
@@ -21,64 +21,64 @@ void Test_ClockEvents() {
CMD_ExecuteCommand("startDriver NTP", 0);
- SELFTEST_ASSERT(NTP_PrintEventList() == 0);
+ SELFTEST_ASSERT(TIME_Print_EventList() == 0);
CMD_ExecuteCommand("addClockEvent 15:30:00 0xff 123 POWER0 ON", 0);
// now there is 1
- SELFTEST_ASSERT(NTP_PrintEventList() == 1);
+ SELFTEST_ASSERT(TIME_Print_EventList() == 1);
// none removed
- SELFTEST_ASSERT(NTP_RemoveClockEvent(1245) == 0);
+ SELFTEST_ASSERT(TIME_RemoveEvent(1245) == 0);
// one removed
- SELFTEST_ASSERT(NTP_RemoveClockEvent(123) == 1);
+ SELFTEST_ASSERT(TIME_RemoveEvent(123) == 1);
// now there is 0
- SELFTEST_ASSERT(NTP_PrintEventList() == 0);
+ SELFTEST_ASSERT(TIME_Print_EventList() == 0);
CMD_ExecuteCommand("addClockEvent 15:30:00 0xff 1001 POWER0 ON", 0);
// now there is 1
- SELFTEST_ASSERT(NTP_PrintEventList() == 1);
+ SELFTEST_ASSERT(TIME_Print_EventList() == 1);
CMD_ExecuteCommand("addClockEvent 15:30:00 0xff 1002 POWER0 ON", 0);
// now there is 2
- SELFTEST_ASSERT(NTP_PrintEventList() == 2);
+ SELFTEST_ASSERT(TIME_Print_EventList() == 2);
CMD_ExecuteCommand("addClockEvent 15:30:00 0xff 1003 POWER0 ON", 0);
// now there is 3
- SELFTEST_ASSERT(NTP_PrintEventList() == 3);
+ SELFTEST_ASSERT(TIME_Print_EventList() == 3);
CMD_ExecuteCommand("addClockEvent 15:30:00 0xff 1004 POWER0 ON", 0);
// now there is 4
- SELFTEST_ASSERT(NTP_PrintEventList() == 4);
+ SELFTEST_ASSERT(TIME_Print_EventList() == 4);
// one removed
- SELFTEST_ASSERT(NTP_RemoveClockEvent(1004) == 1);
+ SELFTEST_ASSERT(TIME_RemoveEvent(1004) == 1);
// now there is 3
- SELFTEST_ASSERT(NTP_PrintEventList() == 3);
+ SELFTEST_ASSERT(TIME_Print_EventList() == 3);
// one removed
- SELFTEST_ASSERT(NTP_RemoveClockEvent(1003) == 1);
+ SELFTEST_ASSERT(TIME_RemoveEvent(1003) == 1);
// now there is 2
- SELFTEST_ASSERT(NTP_PrintEventList() == 2);
+ SELFTEST_ASSERT(TIME_Print_EventList() == 2);
CMD_ExecuteCommand("addClockEvent 15:30:00 0xff 1005 POWER0 ON", 0);
// now there is 3
- SELFTEST_ASSERT(NTP_PrintEventList() == 3);
+ SELFTEST_ASSERT(TIME_Print_EventList() == 3);
CMD_ExecuteCommand("addClockEvent 15:30:00 0xff 1006 POWER0 ON", 0);
// now there is 4
- SELFTEST_ASSERT(NTP_PrintEventList() == 4);
+ SELFTEST_ASSERT(TIME_Print_EventList() == 4);
// one removed
- SELFTEST_ASSERT(NTP_RemoveClockEvent(1005) == 1);
+ SELFTEST_ASSERT(TIME_RemoveEvent(1005) == 1);
// now there is 3
- SELFTEST_ASSERT(NTP_PrintEventList() == 3);
+ SELFTEST_ASSERT(TIME_Print_EventList() == 3);
// one removed
- SELFTEST_ASSERT(NTP_RemoveClockEvent(1001) == 1);
+ SELFTEST_ASSERT(TIME_RemoveEvent(1001) == 1);
// now there is 2
- SELFTEST_ASSERT(NTP_PrintEventList() == 2);
+ SELFTEST_ASSERT(TIME_Print_EventList() == 2);
// one removed
- SELFTEST_ASSERT(NTP_RemoveClockEvent(1002) == 1);
+ SELFTEST_ASSERT(TIME_RemoveEvent(1002) == 1);
// now there is 1
- SELFTEST_ASSERT(NTP_PrintEventList() == 1);
+ SELFTEST_ASSERT(TIME_Print_EventList() == 1);
CMD_ExecuteCommand("addClockEvent 8:09:00 0xff 1007 POWER0 ON", 0);
// now there is 2
- SELFTEST_ASSERT(NTP_PrintEventList() == 2);
+ SELFTEST_ASSERT(TIME_Print_EventList() == 2);
CMD_ExecuteCommand("addClockEvent 09:08:07 0xff 1008 POWER0 ON", 0);
// now there is 3
- SELFTEST_ASSERT(NTP_PrintEventList() == 3);
+ SELFTEST_ASSERT(TIME_Print_EventList() == 3);
- SELFTEST_ASSERT(NTP_GetEventTime(1006) == 15 * 3600 + 30 * 60);
- SELFTEST_ASSERT(NTP_GetEventTime(1007) == 8 * 3600 + 9 * 60);
- SELFTEST_ASSERT(NTP_GetEventTime(1008) == 9 * 3600 + 8 * 60 + 7);
+ SELFTEST_ASSERT(TIME_GetEventTime(1006) == 15 * 3600 + 30 * 60);
+ SELFTEST_ASSERT(TIME_GetEventTime(1007) == 8 * 3600 + 9 * 60);
+ SELFTEST_ASSERT(TIME_GetEventTime(1008) == 9 * 3600 + 8 * 60 + 7);
ResetEventsAndChannels(3);
@@ -88,7 +88,7 @@ void Test_ClockEvents() {
unsigned int simTime = 1681998870;
for (int i = 0; i < 100; i++) {
- NTP_RunEvents(simTime + i, true);
+ TIME_RunEvents(simTime + i, true);
}
SELFTEST_ASSERT_CHANNEL(1, 10);
SELFTEST_ASSERT_CHANNEL(2, 20);
@@ -105,7 +105,7 @@ void Test_ClockEvents() {
// start 300 seconds earlier
simTime = 1681998570;
for (int i = 0; i < 500; i += abs(rand() % 40)) {
- NTP_RunEvents(simTime + i, true);
+ TIME_RunEvents(simTime + i, true);
}
printf("Channel 1 is %i\n", CHANNEL_Get(1));
printf("Channel 2 is %i\n", CHANNEL_Get(2));
@@ -133,7 +133,7 @@ void Test_ClockEvents() {
simTime = 1681998870;
for (int i = 0; i < 100; i++) {
- NTP_RunEvents(simTime + i, true);
+ TIME_RunEvents(simTime + i, true);
}
// Event handler command should expand constants when the handler is run.
diff --git a/src/selftest/selftest_local.h b/src/selftest/selftest_local.h
index cfc039e9d..b8664cc93 100644
--- a/src/selftest/selftest_local.h
+++ b/src/selftest/selftest_local.h
@@ -104,8 +104,8 @@ void Test_RepeatingEvents();
void Test_HTTP_Client();
void Test_DeviceGroups();
void Test_NTP();
-void Test_NTP_DST();
-void Test_NTP_SunsetSunrise();
+void Test_TIME_DST();
+void Test_TIME_SunsetSunrise();
void Test_MQTT();
void Test_Tasmota();
void Test_Backlog();
diff --git a/src/selftest/selftest_ntp_DST.c b/src/selftest/selftest_ntp_DST.c
index bdd45c145..ecfdc5573 100644
--- a/src/selftest/selftest_ntp_DST.c
+++ b/src/selftest/selftest_ntp_DST.c
@@ -2,7 +2,7 @@
#include "selftest_local.h"
-void Test_NTP_DST() {
+void Test_TIME_DST() {
// reset whole device
SIM_ClearOBK(0);
@@ -29,7 +29,8 @@ void Test_NTP_DST() {
//
// 0 10 1 3 means "End of DST on last(=0) Octobers(=10) Sunday(=1) at 3"
// 0 3 1 2 means "Start of DST on last(=0) Marchs(=3) Sunday(=1) at 2"
- CMD_ExecuteCommand("CLOCK_calcDST 0 10 1 3 0 3 1 2", 0);
+// CMD_ExecuteCommand("CLOCK_calcDST 0 10 1 3 0 3 1 2", 0);
+ CMD_ExecuteCommand("TIME_setDST 0 3 1 2 60 0 10 1 3 0", 0);
// test - we are (slightly) "before" DST
SELFTEST_ASSERT_EXPRESSION("$isDST", 0);
@@ -156,7 +157,7 @@ void Test_NTP_DST() {
SELFTEST_ASSERT_EXPRESSION("$isDST", 0);
-#if ENABLE_NTP_SUNRISE_SUNSET
+#if ENABLE_TIME_SUNRISE_SUNSET
// test DST and sunset/sunrise events:
// after such an event took place, the next event will calculated
// if a DST switch takes place, before the sunset/sunrise takes place
@@ -165,16 +166,17 @@ void Test_NTP_DST() {
CMD_ExecuteCommand("ntp_setLatlong 52.237049 21.017532", 0);
// 1761440395 = Sun, Oct 26 2025 02:59:55 CEST - 5 seconds before DST switch
NTP_SetSimulatedTime(1761440395);
- CMD_ExecuteCommand("addClockEvent sunset 0xff 31 setChannel 0 1", 0); // 16:17:00
- SELFTEST_ASSERT_INTCOMPARE(NTP_GetEventTime(31), 16*3600 + 17*60);
- CMD_ExecuteCommand("addClockEvent sunrise 0xff 32 setChannel 0 0", 0); // 06:21:00
- SELFTEST_ASSERT_INTCOMPARE(NTP_GetEventTime(32), 6*3600 + 21*60);
+ CMD_ExecuteCommand("echo sunset=$sunset sunrise=$sunrise", 0); // expected: 17:17:00 and 07:21:00
+ CMD_ExecuteCommand("addClockEvent sunset 0xff 31 setChannel 0 1", 0); // 17:17:00
+ SELFTEST_ASSERT_INTCOMPARE(TIME_GetEventTime(31), 17*3600 + 17*60);
+ CMD_ExecuteCommand("addClockEvent sunrise 0xff 32 setChannel 0 0", 0); // 07:21:00
+ SELFTEST_ASSERT_INTCOMPARE(TIME_GetEventTime(32), 7*3600 + 21*60);
// 1761440395 = Sun, Oct 26 2025 02:59:55 CEST
Sim_RunSeconds(7, false);
// Switch from summertime to winter time, so time is now one hour back
// test, if sunset/sunrise events are corrected
- SELFTEST_ASSERT_INTCOMPARE(NTP_GetEventTime(31), 15*3600 + 17*60);
- SELFTEST_ASSERT_INTCOMPARE(NTP_GetEventTime(32), 5*3600 + 21*60);
+ SELFTEST_ASSERT_INTCOMPARE(TIME_GetEventTime(31), 16*3600 + 17*60);
+ SELFTEST_ASSERT_INTCOMPARE(TIME_GetEventTime(32), 6*3600 + 21*60);
#endif
}
diff --git a/src/selftest/selftest_ntp_sunsetSunrise.c b/src/selftest/selftest_ntp_sunsetSunrise.c
index e6378f249..bfea4a7c2 100644
--- a/src/selftest/selftest_ntp_sunsetSunrise.c
+++ b/src/selftest/selftest_ntp_sunsetSunrise.c
@@ -2,8 +2,9 @@
#include "selftest_local.h"
#include "../driver/drv_ntp.h"
+#include "../driver/drv_deviceclock.h"
-void Test_NTP_SunsetSunrise() {
+void Test_TIME_SunsetSunrise() {
byte hour, minute;
int sunrise, sunset;
@@ -18,15 +19,15 @@ void Test_NTP_SunsetSunrise() {
// set Tue, 19 Dec 2023 20:14:52
NTP_SetSimulatedTime(1703016892);
- sunrise = NTP_GetSunrise();
- NTP_CalculateSunrise(&hour, &minute);
+ sunrise = TIME_GetSunrise();
+ TIME_CalculateSunrise(&hour, &minute);
// Expect sunrise at 7:11
SELFTEST_ASSERT(hour == 7);
SELFTEST_ASSERT(minute == 11);
SELFTEST_ASSERT(sunrise == 25860);
- sunset = NTP_GetSunset();
- NTP_CalculateSunset(&hour, &minute);
+ sunset = TIME_GetSunset();
+ TIME_CalculateSunset(&hour, &minute);
// Expect sunset at 16:02
SELFTEST_ASSERT(hour == 16);
SELFTEST_ASSERT(minute == 2);
@@ -39,15 +40,15 @@ void Test_NTP_SunsetSunrise() {
// set Tue, 19 Dec 2023 20:14:52
NTP_SetSimulatedTime(1703016892);
- sunrise = NTP_GetSunrise();
- NTP_CalculateSunrise(&hour, &minute);
+ sunrise = TIME_GetSunrise();
+ TIME_CalculateSunrise(&hour, &minute);
// Expect sunrise at 6:52
SELFTEST_ASSERT(hour == 6);
SELFTEST_ASSERT(minute == 52);
SELFTEST_ASSERT(sunrise == 24720);
- sunset = NTP_GetSunset();
- NTP_CalculateSunset(&hour, &minute);
+ sunset = TIME_GetSunset();
+ TIME_CalculateSunset(&hour, &minute);
// Expect sunset at 16:45
SELFTEST_ASSERT(hour == 16);
SELFTEST_ASSERT(minute == 45);
@@ -60,15 +61,15 @@ void Test_NTP_SunsetSunrise() {
// set Wed Jul 12 2023 13:47:13 GMT+0000
NTP_SetSimulatedTime(1689169633);
- sunrise = NTP_GetSunrise();
- NTP_CalculateSunrise(&hour, &minute);
+ sunrise = TIME_GetSunrise();
+ TIME_CalculateSunrise(&hour, &minute);
// Expect sunrise at 6:37
SELFTEST_ASSERT(hour == 6);
SELFTEST_ASSERT(minute == 37);
SELFTEST_ASSERT(sunrise == 23820);
- sunset = NTP_GetSunset();
- NTP_CalculateSunset(&hour, &minute);
+ sunset = TIME_GetSunset();
+ TIME_CalculateSunset(&hour, &minute);
// Expect sunset at 20:34
SELFTEST_ASSERT(hour == 20);
SELFTEST_ASSERT(minute == 34);
@@ -86,13 +87,13 @@ void Test_NTP_SunsetSunrise() {
SELFTEST_ASSERT_CHANNEL(15,123);
// expect set at 15:23
- NTP_CalculateSunset(&hour, &minute);
+ TIME_CalculateSunset(&hour, &minute);
SELFTEST_ASSERT(hour == 15);
SELFTEST_ASSERT(minute == 23);
SELFTEST_ASSERT_EXPRESSION("$sunset", 55380);
// expect rise at 7:41
- NTP_CalculateSunrise(&hour, &minute);
+ TIME_CalculateSunrise(&hour, &minute);
SELFTEST_ASSERT(hour == 7);
SELFTEST_ASSERT(minute == 41);
SELFTEST_ASSERT_EXPRESSION("$sunrise", 27660);
@@ -103,6 +104,11 @@ void Test_NTP_SunsetSunrise() {
// during next 10 minutes, the rise should occur
int runSeconds = 10 * 60;
for (int i = 0; i < runSeconds; i++) {
+ // we moved clock functionality away from NTP source
+ // so "tewak" the clock by adding a second
+ g_secondsElapsed++;
+ // we might have an action pending for this time, so call TIME_OnEverySecond();
+ TIME_OnEverySecond();
NTP_OnEverySecond();
}
SELFTEST_ASSERT_CHANNEL(15, 2020);
@@ -110,15 +116,18 @@ void Test_NTP_SunsetSunrise() {
SELFTEST_ASSERT_EXPRESSION("$hour", 15);
SELFTEST_ASSERT_EXPRESSION("$minute", 26);
- g_ntpTime += (9+6)*(60 * 60);
+// g_ntpTime += (9+6)*(60 * 60);
+ g_secondsElapsed += (9+6)*(60 * 60);
// 6:26 now
SELFTEST_ASSERT_EXPRESSION("$hour", 6);
SELFTEST_ASSERT_EXPRESSION("$minute", 26);
- g_ntpTime += (34 * 60);
+// g_ntpTime += (34 * 60);
+ g_secondsElapsed += (34 * 60);
// 7:00 now
SELFTEST_ASSERT_EXPRESSION("$hour", 7);
SELFTEST_ASSERT_EXPRESSION("$minute", 0);
- g_ntpTime += (35 * 60);
+// g_ntpTime += (35 * 60);
+ g_secondsElapsed += (35 * 60);
// 7:35 now
SELFTEST_ASSERT_EXPRESSION("$hour", 7);
SELFTEST_ASSERT_EXPRESSION("$minute", 35);
@@ -126,6 +135,11 @@ void Test_NTP_SunsetSunrise() {
// during next 10 minutes, the rise should occur
runSeconds = 10 * 60;
for (int i = 0; i < runSeconds; i++) {
+ // we moved clock functionality away from NTP source
+ // so "tewak" the clock by adding a second
+ g_secondsElapsed++;
+ // we might have an action pending for this time, so call TIME_OnEverySecond();
+ TIME_OnEverySecond();
NTP_OnEverySecond();
}
// channel value should change
diff --git a/src/user_main.c b/src/user_main.c
index bccd0c31d..1bcbcc091 100644
--- a/src/user_main.c
+++ b/src/user_main.c
@@ -14,6 +14,8 @@
#include "driver/drv_hlw8112.h"
//#include "ir/ir_local.h"
+#include "driver/drv_deviceclock.h"
+
// Commands register, execution API and cmd tokenizer
#include "cmnds/cmd_public.h"
@@ -699,6 +701,12 @@ float g_wifi_temperature = 0;
static byte g_secondsSpentInLowMemoryWarning = 0;
void Main_OnEverySecond()
{
+#if PLATFORM_W600 || PLATFORM_W800
+#define TimeOut_t xTimeOutType
+#endif
+#if ! ( WINDOWS || PLATFORM_TXW81X || PLATFORM_RDA5981)
+ TimeOut_t myTimeout; // to get uptime from xTicks - not working on WINDOWS and TXW81X and RDA5981
+#endif
int newMQTTState;
const char* safe;
int i;
@@ -870,8 +878,14 @@ void Main_OnEverySecond()
}
}
}
-
+#if (WINDOWS || PLATFORM_TXW81X || PLATFORM_RDA5981)
g_secondsElapsed++;
+#elif defined(PLATFORM_ESPIDF)
+ g_secondsElapsed = (int)(esp_timer_get_time() / 1000000);
+#else
+ vTaskSetTimeOutState( &myTimeout );
+ g_secondsElapsed = (int)((((uint64_t) myTimeout.xOverflowCount << (sizeof(portTickType)*8) | myTimeout.xTimeOnEntering)*portTICK_RATE_MS ) / 1000 );
+#endif
if (bSafeMode) {
safe = "[SAFE] ";
}
diff --git a/src/win_main.c b/src/win_main.c
index 4ed89089b..a618193e1 100644
--- a/src/win_main.c
+++ b/src/win_main.c
@@ -275,8 +275,8 @@ void Win_DoUnitTests()
#endif
Test_Tasmota();
Test_NTP();
- Test_NTP_DST();
- Test_NTP_SunsetSunrise();
+ Test_TIME_DST();
+ Test_TIME_SunsetSunrise();
Test_ExpandConstant();
Test_ChangeHandlers_MQTT();
Test_ChangeHandlers();