Time based on AceTime

Moved over to AceTime completly.

And:
- turn OFF the flash on configure wifi option
- fixed some minor compiler warnings
This commit is contained in:
Robert van den Breemen 2023-01-03 14:33:00 +01:00
parent 55d7dc79bc
commit a68d542b40
9 changed files with 115 additions and 67 deletions

16
Debug.h
View File

@ -59,14 +59,26 @@ void _debugBOL(const char *fn, int line)
//Alternative based on localtime function
timeval now;
struct tm *tod;
//struct tm *tod;
gettimeofday(&now, nullptr);
tod = localtime(&now.tv_sec);
//tod = localtime(&now.tv_sec);
/*
snprintf(_bol, sizeof(_bol), "%02d:%02d:%02d.%06d (%7u|%6u) %-12.12s(%4d): ", \
tod->tm_hour, tod->tm_min, tod->tm_sec, (int)now.tv_usec, \
ESP.getFreeHeap(), ESP.getMaxFreeBlockSize(),\
fn, line);
*/
TimeZone myTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone));
ZonedDateTime myTime = ZonedDateTime::forUnixSeconds64(time(nullptr), myTz);
//DebugTf("%02d:%02d:%02d %02d-%02d-%04d\r\n", myTime.hour(), myTime.minute(), myTime.second(), myTime.day(), myTime.month(), myTime.year());
snprintf(_bol, sizeof(_bol), "%02d:%02d:%02d.%06d (%7u|%6u) %-12.12s(%4d): ", \
myTime.hour(), myTime.minute(), myTime.second(), (int)now.tv_usec, \
ESP.getFreeHeap(), ESP.getMaxFreeBlockSize(),\
fn, line);
TelnetStream.print (_bol);
}

View File

@ -139,7 +139,7 @@ void handleMQTTcallback(char* topic, byte* payload, unsigned int length) {
// parse the incoming topic and execute commands
char* token;
char otgwcmd[20]={0};
char otgwcmd[51]={0};
//first check toptopic part, it can include the seperator, e.g. "myHome/OTGW" or "OTGW""
if (strncmp(topic, settingMQTTtopTopic.c_str(), settingMQTTtopTopic.length()) != 0) {

View File

@ -821,7 +821,7 @@ void print_statusVH(uint16_t& value)
if (is_value_valid(OTdata, OTlookupitem)){
//OTGWDebugTf("Status u16 [%04x] _value [%04x] hb [%02x] lb [%02x]", OTdata.u16(), _value, OTdata.valueHB, OTdata.valueLB);
value = (OTcurrentSystemState.MasterStatusVH<<8) && OTcurrentSystemState.SlaveStatusVH;
value = (OTcurrentSystemState.MasterStatusVH<<8) & OTcurrentSystemState.SlaveStatusVH;
}
}
@ -1426,6 +1426,7 @@ void processOT(const char *buf, int len){
static bool bOTGWthermostatpreviousstate = false;
static bool bOTGWgatewaypreviousstate = false;
static bool bOTGWpreviousstate = false;
time_t now = time(nullptr);
if (isvalidotmsg(buf, len)) {
//OT protocol messages are 9 chars long
@ -1439,30 +1440,30 @@ void processOT(const char *buf, int len){
// source of otmsg
if (buf[0]=='B'){
epochBoilerlastseen = now();
epochBoilerlastseen = now;
OTdata.rsptype = OTGW_BOILER;
} else if (buf[0]=='T'){
epochThermostatlastseen = now();
epochThermostatlastseen = now;
OTdata.rsptype = OTGW_THERMOSTAT;
} else if (buf[0]=='R') {
epochGatewaylastseen = now();
epochGatewaylastseen = now;
OTdata.rsptype = OTGW_REQUEST_BOILER;
} else if (buf[0]=='A') {
epochGatewaylastseen = now();
epochGatewaylastseen = now;
OTdata.rsptype = OTGW_ANSWER_THERMOSTAT;
} else if (buf[0]=='E') {
OTdata.rsptype = OTGW_PARITY_ERROR;
}
//If the Boiler messages have not been seen for 30 seconds, then set the state to false.
bOTGWboilerstate = (now() < (epochBoilerlastseen+30));
bOTGWboilerstate = (now < (epochBoilerlastseen+30));
if ((bOTGWboilerstate != bOTGWboilerpreviousstate) || (cntOTmessagesprocessed==1)) {
sendMQTTData(F("otgw-pic/boiler_connected"), CCONOFF(bOTGWboilerstate));
bOTGWboilerpreviousstate = bOTGWboilerstate;
}
//If the Thermostat messages have not been seen for 30 seconds, then set the state to false.
bOTGWthermostatstate = (now() < (epochThermostatlastseen+30));
bOTGWthermostatstate = (now < (epochThermostatlastseen+30));
if ((bOTGWthermostatstate != bOTGWthermostatpreviousstate) || (cntOTmessagesprocessed==1)){
sendMQTTData(F("otgw-pic/thermostat_connected"), CCONOFF(bOTGWthermostatstate));
bOTGWthermostatpreviousstate = bOTGWthermostatstate;
@ -1470,7 +1471,7 @@ void processOT(const char *buf, int len){
//If the Gateway (A or R) messages have not been seen for 30 seconds, then set the state to false.
//If the Thermostat is NOT connected (so false), then the Gateway will be continuously sending R messages to the boiler, in face the Gateway the acts as the Thermostat
bOTGWgatewaystate = (now() < (epochGatewaylastseen+30));
bOTGWgatewaystate = (now < (epochGatewaylastseen+30));
if ((bOTGWgatewaystate != bOTGWgatewaypreviousstate) || (cntOTmessagesprocessed==1)){
sendMQTTData(F("otgw-pic/gateway_mode"), CCONOFF(bOTGWgatewaystate));
bOTGWgatewaypreviousstate = bOTGWgatewaystate;
@ -1522,7 +1523,7 @@ void processOT(const char *buf, int len){
OTdata.skipthis = skipthis; //skip if needed
//keep track of last update time of each message id
msglastupdated[OTdata.id] = now();
msglastupdated[OTdata.id] = now;
//Read information from this OT message ready for use...
PROGMEM_readAnything (&OTmap[OTdata.id], OTlookupitem);

View File

@ -10,15 +10,12 @@
*/
#include <Arduino.h>
//#include <ezTime.h> // https://github.com/ropg/ezTime
#include <AceTime.h>
#include <TimeLib.h>
// #include <TimeLib.h>
#include <TelnetStream.h> // https://github.com/jandrassy/TelnetStream/commit/1294a9ee5cc9b1f7e51005091e351d60c8cddecf
#include <ArduinoJson.h> // https://arduinojson.org/
#include "Wire.h"
#include "Debug.h"
#include "safeTimers.h"
#include "OTGWSerial.h" // Bron Schelte's Serial class - it upgrades and more
#include "OTGW-Core.h" // Core code for this firmware
@ -76,11 +73,18 @@ uint32_t MQTTautoConfigMap[8] = { 0 };
//Use acetime
using namespace ace_time;
static BasicZoneProcessor timeProcessor;
static const int CACHE_SIZE = 3;
//static BasicZoneProcessor timeProcessor;
//static const int CACHE_SIZE = 3;
// static BasicZoneManager<CACHE_SIZE> manager(zonedb::kZoneRegistrySize, zonedb::kZoneRegistry);
static BasicZoneProcessorCache<CACHE_SIZE> zoneProcessorCache;
static BasicZoneManager timezoneManager(zonedb::kZoneRegistrySize, zonedb::kZoneRegistry, zoneProcessorCache);
//static BasicZoneProcessorCache<CACHE_SIZE> zoneProcessorCache;
//static BasicZoneManager timezoneManager(zonedb::kZoneAndLinkRegistrySize, zonedb::kZoneAndLinkRegistry, zoneProcessorCache);
static ExtendedZoneProcessor tzProcessor;
static const int CACHE_SIZE = 3;
static ExtendedZoneProcessorCache<CACHE_SIZE> zoneProcessorCache;
static ExtendedZoneManager timezoneManager(
zonedbx::kZoneAndLinkRegistrySize,
zonedbx::kZoneAndLinkRegistry,
zoneProcessorCache);
const char *weekDayName[] { "Unknown", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Unknown" };
const char *flashMode[] { "QIO", "QOUT", "DIO", "DOUT", "Unknown" };
@ -137,9 +141,11 @@ bool settingGPIOOUTPUTSenabled = false;
int8_t settingGPIOOUTPUTSpin = 16;
int8_t settingGPIOOUTPUTStriggerBit = 0;
//Now load network suff
//Now load Debug & network library
#include "Debug.h"
#include "networkStuff.h"
// That's all folks...
/***************************************************************************

View File

@ -164,22 +164,28 @@ void sendtimecommand(){
if (NtpStatus != TIME_SYNC) return; // only send time command when time is synced
//send time command to OTGW
//send time / weekday
time_t now = time(nullptr);
TimeZone myTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone));
ZonedDateTime myTime = ZonedDateTime::forUnixSeconds64(now, myTz);
//DebugTf("%02d:%02d:%02d %02d-%02d-%04d\r\n", myTime.hour(), myTime.minute(), myTime.second(), myTime.day(), myTime.month(), myTime.year());
char msg[15]={0};
#define calc_ot_dow(dow) ((dow+5)%7+1)
sprintf(msg,"SC=%d:%02d/%ld", hour(), minute(), calc_ot_dow(dayOfWeek(now())));
int day_of_week = (myTime.dayOfWeek()+5)%7+1;
sprintf(msg,"SC=%d:%02d/%d", myTime.hour(), myTime.minute(), day_of_week);
addOTWGcmdtoqueue(msg, strlen(msg), true);
static int lastDay = 0;
if (day(now())!=lastDay){
if (myTime.day()!=lastDay){
//Send msg id 21: month, day
lastDay = day(now());
sprintf(msg,"SR=21:%d,%d", month(now()), day(now()));
lastDay = myTime.day();
sprintf(msg,"SR=21:%d,%d", myTime.month(), myTime.day());
addOTWGcmdtoqueue(msg, strlen(msg), true);
}
static int lastYear = 0;
if (year(now())!=lastYear){
lastYear = year(now());
if (myTime.year()!=lastYear){
lastYear = myTime.year();
//Send msg id 22: HB of Year, LB of Year
sprintf(msg,"SR=22:%d,%d", (lastYear >> 8) & 0xFF, lastYear & 0xFF);
addOTWGcmdtoqueue(msg, strlen(msg), true);

View File

@ -262,7 +262,9 @@ bool updateRebootLog(String text)
}
}
snprintf(log_line, LOG_LINE_LENGTH, "%d-%02d-%02d %02d:%02d:%02d - reboot cause: %s (%x) %s\r\n", year(), month(), day(), hour(), minute(), second(), CSTR(text), errorCode, log_line_excpt);
TimeZone myTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone));
ZonedDateTime myTime = ZonedDateTime::forUnixSeconds64(time(nullptr), myTz);
snprintf(log_line, LOG_LINE_LENGTH, "%d-%02d-%02d %02d:%02d:%02d - reboot cause: %s (%x) %s\r\n", myTime.year(), myTime.month(), myTime.day(), myTime.hour(), myTime.minute(), myTime.second(), CSTR(text), errorCode, log_line_excpt);
if (LittleFS.begin()) {
//start with opening the file
@ -334,14 +336,18 @@ bool prefix(const char *pre, const char *str)
bool dayChanged(){
static int8_t lastday = 0;
if (lastday==0) lastday = day();
return (lastday != day());
TimeZone myTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone));
ZonedDateTime myTime = ZonedDateTime::forUnixSeconds64(time(nullptr), myTz);
if (lastday==0) lastday = myTime.day();
return (lastday != myTime.day());
}
bool hourChanged(){
static int8_t lasthour = 0;
if (lasthour==0) lasthour = hour();
return (lasthour != hour());
TimeZone myTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone));
ZonedDateTime myTime = ZonedDateTime::forUnixSeconds64(time(nullptr), myTz);
if (lasthour==0) lasthour = myTime.hour();
return (lasthour != myTime.hour());
}
/*

View File

@ -64,6 +64,7 @@ enum NtpStatus_t {
};
NtpStatus_t NtpStatus = TIME_NOTSET;
static const time_t EPOCH_2000_01_01 = 946684800;
time_t NtpLastSync = 0; //last sync moment in EPOCH seconds
ESP8266WebServer httpServer (80);
@ -116,6 +117,12 @@ void startWiFi(const char* hostname, int timeOut)
//--- useful to make it all retry or go to sleep in seconds
//manageWiFi.setTimeout(240); // 4 minuten
manageWiFi.setTimeout(timeOut); // in seconden ...
//--- remove Info and Update buttons from Configuration Portal (security improvement 20230102)
std::vector<const char *> wm_menu = {"wifi", "exit"};
manageWiFi.setShowInfoUpdate(false);
manageWiFi.setShowInfoErase(false);
manageWiFi.setMenu(wm_menu);
//--- fetches ssid and pass and tries to connect
//--- if it does not connect it starts an access point with the specified name
@ -214,36 +221,39 @@ void getNTPtime(){
dt_sec = tp.tv_sec;
dt_ms = tp.tv_nsec / 1000000UL;
dt_nsec = tp.tv_nsec;
DebugTf("tNow=%20.10f tNow_sec=%16.10ld tNow_nsec=%16.10ld dt_sec=%16li(s) dt_msec=%16li(sm) dt_nsec=%16li(ns)\r\n", tNow, tp.tv_sec,tp.tv_nsec, dt_sec, dt_ms, dt_nsec);
DebugTf("tNow=%20.10f tNow_sec=%16.10ld tNow_nsec=%16.10ld dt_sec=%16li(s) dt_msec=%16li(sm) dt_nsec=%16li(ns)\r\n", (double)tNow, tp.tv_sec,tp.tv_nsec, dt_sec, dt_ms, dt_nsec);
DebugFlush();
}
void loopNTP(){
time_t now;
now = time(nullptr); //this is now...
if (!settingNTPenable) return;
switch (NtpStatus){
case TIME_NOTSET:
case TIME_NEEDSYNC:
NtpLastSync = time(nullptr); //remember last sync
NtpLastSync = now; //remember last sync
DebugTln(F("Start time syncing"));
startNTP();
DebugTf("Starting timezone lookup for [%s]\r\n", CSTR(settingNTPtimezone));
NtpStatus = TIME_WAITFORSYNC;
break;
case TIME_WAITFORSYNC:
if ((time(nullptr)>0) || (time(nullptr) >= NtpLastSync)) {
NtpLastSync = time(nullptr); //remember last sync
auto myTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone));
if ((now > EPOCH_2000_01_01) && (now >= NtpLastSync)) {
//DebugTf("Waited for sync: epoch: %lld\r\n", time(nullptr));
NtpLastSync = now; //remember last sync
TimeZone myTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone));
if (myTz.isError()){
//DebugTf("Error: Timezone Invalid/Not Found: [%s]\r\n", CSTR(settingNTPtimezone));
DebugTf("Error: Timezone Invalid/Not Found: [%s]\r\n", CSTR(settingNTPtimezone));
settingNTPtimezone = NTP_DEFAULT_TIMEZONE;
myTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone)); //try with default Timezone instead
} else {
//found the timezone, now set the time
auto myTime = ZonedDateTime::forUnixSeconds64(NtpLastSync, myTz);
DebugTf("%02d:%02d:%02d %02d-%02d-%04d", myTime.hour(), myTime.minute(), myTime.second(), myTime.day(), myTime.month(), myTime.year());
ZonedDateTime myTime = ZonedDateTime::forUnixSeconds64(now, myTz);
DebugTf("%02d:%02d:%02d %02d-%02d-%04d\n\r", myTime.hour(), myTime.minute(), myTime.second(), myTime.day(), myTime.month(), myTime.year());
if (!myTime.isError()) {
//finally time is synced!
setTime(myTime.hour(), myTime.minute(), myTime.second(), myTime.day(), myTime.month(), myTime.year());
//setTime(myTime.hour(), myTime.minute(), myTime.second(), myTime.day(), myTime.month(), myTime.year());
NtpStatus = TIME_SYNC;
DebugTln(F("Time synced!"));
}
@ -251,7 +261,7 @@ if (!settingNTPenable) return;
}
break;
case TIME_SYNC:
if ((time(nullptr)-NtpLastSync) > NTP_RESYNC_TIME){
if ((now - NtpLastSync) > NTP_RESYNC_TIME){
//when xx seconds have passed, resync using NTP
DebugTln(F("Time resync needed"));
NtpStatus = TIME_NEEDSYNC;
@ -259,16 +269,21 @@ if (!settingNTPenable) return;
break;
}
DECLARE_TIMER_SEC(timerNTPtime, 10, CATCH_UP_MISSED_TICKS);
if DUE(timerNTPtime)
{
DebugTf("Epoch Seconds: %d\r\n", time(nullptr)); //timeout, then break out of this loop
auto myTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone));
auto myTime = ZonedDateTime::forUnixSeconds64(time(nullptr), myTz);
DebugTf("Epoch Seconds MyTime: %d\r\n", myTime); //timeout, then break out of this loop
DebugTf("%02d:%02d:%02d %02d-%02d-%04d", myTime.hour(), myTime.minute(), myTime.second(), myTime.day(), myTime.month(), myTime.year());
}
if DUE(timerNTPtime) getNTPtime();
// DECLARE_TIMER_SEC(timerNTPtime, 10, CATCH_UP_MISSED_TICKS);
// if DUE(timerNTPtime)
// {
// //DebugTf("Epoch Seconds: %lld\r\n", now); //timeout, then break out of this loop
// DebugT("Now: ");
// Debug(now);
// Debugln();
// DebugT("Timezone : ");
// Debugln(CSTR(settingNTPtimezone));
// TimeZone myTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone));
// ZonedDateTime myTime = ZonedDateTime::forUnixSeconds64(now, myTz);
// DebugTf("%02d:%02d:%02d %02d-%02d-%04d\r\n", myTime.hour(), myTime.minute(), myTime.second(), myTime.day(), myTime.month(), myTime.year());
// }
// if DUE(timerNTPtime) getNTPtime();
}
bool isNTPtimeSet(){

View File

@ -377,13 +377,15 @@ void sendDeviceInfo()
//=======================================================================
void sendDeviceTime()
{
char actTime[50];
char buf[50];
sendStartJsonObj("devtime");
snprintf(actTime, 49, "%04d-%02d-%02d %02d:%02d:%02d", year(), month(), day()
, hour(), minute(), second());
sendNestedJsonObj("dateTime", actTime);
int32_t now = time(nullptr);
time_t now = time(nullptr);
//Timezone based devtime
TimeZone myTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone));
ZonedDateTime myTime = ZonedDateTime::forUnixSeconds64(now, myTz);
snprintf(buf, 49, "%04d-%02d-%02d %02d:%02d:%02d", myTime.year(), myTime.month(), myTime.day(), myTime.hour(), myTime.minute(), myTime.second());
sendNestedJsonObj("dateTime", buf);
sendNestedJsonObj("epoch", (int)now);
sendNestedJsonObj("message", sMessage);

View File

@ -2,15 +2,15 @@
#define _VERSION_MAJOR 0
#define _VERSION_MINOR 9
#define _VERSION_PATCH 6
#define _VERSION_BUILD 1792
#define _VERSION_GITHASH "f0a6fba"
#define _VERSION_BUILD 1834
#define _VERSION_GITHASH "55d7dc7"
#define _VERSION_PRERELEASE beta
#define _VERSION_DATE "01-01-2023"
#define _VERSION_TIME "17:46:33"
#define _VERSION_DATE "03-01-2023"
#define _VERSION_TIME "14:11:05"
#define _SEMVER_CORE "0.9.6"
#define _SEMVER_BUILD "0.9.6+1792"
#define _SEMVER_GITHASH "0.9.6+f0a6fba"
#define _SEMVER_FULL "0.9.6-beta+f0a6fba"
#define _SEMVER_NOBUILD "0.9.6-beta (01-01-2023)"
#define _VERSION "0.9.6-beta+f0a6fba (01-01-2023)"
#define _SEMVER_BUILD "0.9.6+1834"
#define _SEMVER_GITHASH "0.9.6+55d7dc7"
#define _SEMVER_FULL "0.9.6-beta+55d7dc7"
#define _SEMVER_NOBUILD "0.9.6-beta (03-01-2023)"
#define _VERSION "0.9.6-beta+55d7dc7 (03-01-2023)"
//The version information is created automatically, more information here: https://github.com/rvdbreemen/autoinc-semver