Hi,
I'm writing a program that receives data from the UART each 16 seconds (weather data). I'm also using a struct that handles the time (Epoch and DST time). setSyncProvider is a call back routine to get the current NTP time or time from an RTC. How can I program the callback routine in my struct. "setSyncProvider(SoftTime::getNTPTime);" or "setSyncProvider(getNTPTime);" don't work properly. this line is in the constructor of the SoftTime struct (SoftTime::SoftTime). getNTPTime returns a time_t value.
can you help? Do I need to make a function for this call-back that is not part of the struct?
A second question....I am submitiing the obtained data with MQTT to home assistant and weather undergrond. Any suggestions to easily replace values in a string and submit the result to weather underground #temperature# will be replaces by eg 19.3 degrees Celsius. Is it also possible to let the NodeMCU go into deep sleep for 14 seconds since I have an active WiFi link? Or do I have to make a link with the router and disconnect each time to go in deep sleep? Just curiuous what's possible.
Any help would be appreciated.
Thanks,
Mark
In order that your questions can be seen in context please post your current sketch, using < CODE/ > tags when you do
That, or you can make getNTPTime
a static
member function.
struct SoftTime {
// ...
static time_t getNTPTime();
// ...
};
#include "Arduino.h"
#include <stdint.h>
#include <stdbool.h>
#include <Stream.h>
#include <time.h>
//#include <NTPClient.h>
#include <TimeLib.h>
#include <WiFiUDP.h>
#include <ESP8266WiFi.h>
#include "SoftTime.h"
#define CMD_SIZE 9
#define TIMEOUT_MS 17000
#define MY_NTP_SERVER "nl.pool.ntp.org"
#define MY_TZ "CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00"
const char* NTP_SERVER = "nl.pool.ntp.org";
const char* TZ_INFO = "CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00"; // enter your time zone (https://remotemonitoringsystems.ca/time-zone-abbreviations.php)
const int timeZone = 1; // Central European Time
unsigned int localPort = 8888; // local port to listen for UDP packets
#define TodaySecsLeft(_time_) (SECS_PER_DAY - ((_time_) % SECS_PER_DAY)) // the number of seconds since last midnight
#define SECS_PER_HALF_DAY ((time_t)(SECS_PER_HOUR * 12UL))
unsigned long last;
char daysOfTheWeek[7][10] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
char dagVanDeWeek[7][10] = {"Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag"};
time_t EpochTime;
WiFiUDP UDPClient;
SoftTime SoftwareTime;
//Week Days
String weekDays[7]={"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
//Month names
String months[12]={"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
time_t GetTime(void)
{
return(SoftwareTime.getNTPTime());
}
SoftTime::SoftTime(bool NTPStart)
{
bool Result = false;
DST = false;
TimeOffset = 0;
EpochTime = 0;
prevDisplay = 0; // when the digital clock was displayed
Serial.print("IP number assigned by DHCP is ");
Serial.println(WiFi.localIP());
Serial.println("Starting UDP");
UDPClient.begin(localPort);
Serial.print("Local port: ");
Serial.println(UDPClient.localPort());
Serial.println("waiting for sync");
setSyncProvider(SoftTime::getNTPTime);
setSyncInterval(30);
if (WiFi.status() == WL_CONNECTED)
{
LastCheck = getNTPTime();
}
}
bool SoftTime::DSTChangeForthcoming(time_t CurentGMTTime)
{
//Check x time before and x time after DST day starts
const time_t DSTCheckOffset = 3*SECS_PER_HOUR;
bool CheckUpcomingDST = false;
time_t TimeDifference = 0;
tmElements_t CurrentTime;
breakTime(CurentGMTTime, CurrentTime);
tmElements_t DSTBeginDate = {0, 0, 0, 0, 24, 3, CurrentTime.Year};
tmElements_t DSTEndDate = {0, 0, 0, 0, 24, 10, CurrentTime.Year};
time_t DSTBegin, DSTEnd;
//Calculate Epoch Time when clock changes
//Starts a 2AM - an hour from CET-1
DSTBegin = nextSunday(makeTime(DSTBeginDate)) + 3600UL;
//Calculate Epoch Time when clock changes
//Starts a 3AM - an hour from CET-1 - 1 hour of DST difference
DSTEnd = nextSunday(makeTime(DSTEndDate)) + 3600UL;
CheckUpcomingDST = ((CurentGMTTime>=DSTBegin-DSTCheckOffset) && (CurentGMTTime<=DSTBegin+DSTCheckOffset)) ||
((CurentGMTTime>=DSTEnd-DSTCheckOffset) && (CurentGMTTime<=DSTEnd+DSTCheckOffset));
return (CheckUpcomingDST);
}
bool SoftTime::DSTTime(time_t CurentGMTTime)
{
bool DSTTime = false;
tmElements_t CurrentTime;
breakTime(CurentGMTTime, CurrentTime);
tmElements_t DSTBeginDate = {0, 0, 0, 0, 24, 3, CurrentTime.Year};
tmElements_t DSTEndDate = {0, 0, 0, 0, 24, 10, CurrentTime.Year};
//tmElements_t TimeNow = {hour(), minute(), second(), 0, 27, 3, (year() - 1970)};
time_t DSTBegin, DSTEnd;
//Calculate Epoch Time when clock changes
//Starts a 2AM - an hour from CET-1
DSTBegin = nextSunday(makeTime(DSTBeginDate)) + 3600UL;
//Calculate Epoch Time when clock changes
//Starts a 3AM - an hour from CET-1 - 1 hour of DST difference
DSTEnd = nextSunday(makeTime(DSTEndDate)) + 3600UL;
DSTTime = ((CurentGMTTime >= DSTBegin) && (CurentGMTTime < DSTEnd));
Serial.print(CurentGMTTime);
Serial.print(" ");
Serial.print(DSTBegin);
Serial.print(" ");
Serial.print(DSTEnd);
Serial.print(" ");
Serial.println(DSTTime);
return (DSTTime);
}
time_t SoftTime::getNTPTime()
{
if (WiFi.status() != WL_CONNECTED) exit;
unsigned long TimeUntilNextUpdate;
timeClient.update();
time_t epochTime = timeClient.getEpochTime();
UseDSTTime = DSTTime(epochTime);
if (UseDSTTime)
{
TimeOffset = (timeZone+1UL) * SECS_PER_HOUR;
}
else
{
TimeOffset = timeZone * SECS_PER_HOUR;
}
ActualTime = epochTime + TimeOffset;
//Sync clock at 12h and 0h exactly
TimeUntilNextUpdate = TodaySecsLeft(ActualTime);
if (TimeUntilNextUpdate > SECS_PER_HALF_DAY)
{
TimeUntilNextUpdate -= SECS_PER_HALF_DAY;
}
setSyncInterval(TimeUntilNextUpdate);
Serial.print("Time until next update : ");
Serial.println(TimeUntilNextUpdate);
return(ActualTime);
}
It's still code that has to be finished. Sorry for the messy code. DST works perfect
Be a good citizen; reduce the server polling to a respectable time interval. No one needs weather updates 4 times a minute.
Hi,
Thanks for reading my message. I made a struct to handle my time routines. I am having problems with compiling this code:
#include "Arduino.h"
#include <stdint.h>
#include <stdbool.h>
#include <Stream.h>
#include <time.h>
#include <NTPClient.h>
#include <TimeLib.h>
#include <WiFiUDP.h>
#include <ESP8266WiFi.h>
#include "SoftTime.h"
const char* NTP_SERVER = "nl.pool.ntp.org";
const char* TZ_INFO = "CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00"; // enter your time zone (https://remotemonitoringsystems.ca/time-zone-abbreviations.php)
const unsigned int localUDPPort = 8888; // local port to listen for UDP packets
const int timeZone = 1; // Central European Time
#define TodaySecsLeft(_time_) (SECS_PER_DAY - ((_time_) % SECS_PER_DAY)) // the number of seconds since last midnight
#define SECS_PER_HALF_DAY ((time_t)(SECS_PER_HOUR * 12UL))
unsigned long last;
char daysOfTheWeek[7][10] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
char dagVanDeWeek[7][10] = {"Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag"};
//Week Days
String weekDays[7]={"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
//Month names
String months[12]={"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
SoftTime::SoftTime(bool NTPStart)
{
TimeData.Epoch = 0;
TimeData.Actual = 0;
TimeData.DST = false;
TimeData.Offset = 0;
Serial.print("IP number assigned by DHCP is ");
Serial.println(WiFi.localIP());
Serial.println("Starting UDP");
ntpUDP.begin(localUDPPort);
Serial.print("Local port: ");
Serial.println(ntpUDP.localPort());
Serial.println("waiting for sync");
setSyncProvider(getNTPTime);
setSyncInterval(30);
/*
if (WiFi.status() == WL_CONNECTED)
{
getNTPTime();
}
*/
}
bool SoftTime::DSTChangeForthcoming(time_t CurentGMTTime)
{
//Check x time before and x time after DST day starts
const time_t DSTCheckOffset = 3*SECS_PER_HOUR;
bool CheckUpcomingDST = false;
time_t TimeDifference = 0;
tmElements_t CurrentTime;
breakTime(CurentGMTTime, CurrentTime);
tmElements_t DSTBeginDate = {0, 0, 0, 0, 24, 3, CurrentTime.Year};
tmElements_t DSTEndDate = {0, 0, 0, 0, 24, 10, CurrentTime.Year};
time_t DSTBegin, DSTEnd;
//Calculate Epoch Time when clock changes
//Starts a 2AM - an hour from CET-1
DSTBegin = nextSunday(makeTime(DSTBeginDate)) + 3600UL;
//Calculate Epoch Time when clock changes
//Starts a 3AM - an hour from CET-1 - 1 hour of DST difference
DSTEnd = nextSunday(makeTime(DSTEndDate)) + 3600UL;
CheckUpcomingDST = ((CurentGMTTime>=DSTBegin-DSTCheckOffset) && (CurentGMTTime<=DSTBegin+DSTCheckOffset)) ||
((CurentGMTTime>=DSTEnd-DSTCheckOffset) && (CurentGMTTime<=DSTEnd+DSTCheckOffset));
return (CheckUpcomingDST);
}
bool SoftTime::DSTTime(time_t CurentGMTTime)
{
bool DSTTime = false;
tmElements_t CurrentTime;
breakTime(CurentGMTTime, CurrentTime);
tmElements_t DSTBeginDate = {0, 0, 0, 0, 24, 3, CurrentTime.Year};
tmElements_t DSTEndDate = {0, 0, 0, 0, 24, 10, CurrentTime.Year};
//tmElements_t TimeNow = {hour(), minute(), second(), 0, 27, 3, (year() - 1970)};
time_t DSTBegin, DSTEnd;
//Calculate Epoch Time when clock changes
//Starts a 2AM - an hour from CET-1
DSTBegin = nextSunday(makeTime(DSTBeginDate)) + 3600UL;
//Calculate Epoch Time when clock changes
//Starts a 3AM - an hour from CET-1 - 1 hour of DST difference
DSTEnd = nextSunday(makeTime(DSTEndDate)) + 3600UL;
DSTTime = ((CurentGMTTime >= DSTBegin) && (CurentGMTTime < DSTEnd));
Serial.print(CurentGMTTime);
Serial.print(" ");
Serial.print(DSTBegin);
Serial.print(" ");
Serial.print(DSTEnd);
Serial.print(" ");
Serial.println(DSTTime);
return (DSTTime);
}
struct TimeDataStruct SoftTime::proccessEpochTime(time_t EpochTime)
{
struct TimeDataStruct TempResult;
TempResult.Epoch = EpochTime;
TempResult.DST = DSTTime(EpochTime);
TempResult.Offset = 0;
if (TempResult.DST)
{
TempResult.Offset = (timeZone+1UL) * SECS_PER_HOUR;
}
else
{
TempResult.Offset = timeZone * SECS_PER_HOUR;
}
TempResult.Actual = TempResult.Epoch + TempResult.Offset;
return(TempResult);
}
time_t SoftTime::getNTPTime()
{
const time_t DSTCheckInterval = SECS_PER_HOUR;
if (WiFi.status() != WL_CONNECTED) exit;
NTPClient timeClient(ntpUDP, NTP_SERVER);
unsigned long TimeUntilNextUpdate;
static bool DSTWillChange;
timeClient.update();
TimeData = proccessEpochTime(timeClient.getEpochTime());
DSTWillChange = DSTChangeForthcoming(TimeData.Epoch);
if (DSTWillChange)
{
TimeUntilNextUpdate = TodaySecsLeft(TimeData.Actual) % DSTCheckInterval;
}
else
{
//Sync clock at 12h and 0h exactly
TimeUntilNextUpdate = TodaySecsLeft(TimeData.Actual);
if (TimeUntilNextUpdate > SECS_PER_HALF_DAY)
{
TimeUntilNextUpdate -= SECS_PER_HALF_DAY;
}
}
if (TimeUntilNextUpdate < 20)
{
if (DSTWillChange)
{
TimeUntilNextUpdate = DSTCheckInterval;
}
else
{
TimeUntilNextUpdate = SECS_PER_HALF_DAY;
}
}
setSyncInterval(TimeUntilNextUpdate);
Serial.print("Time until next update : ");
Serial.println(TimeUntilNextUpdate);
return(TimeData.Actual);
}
This is the header file:
// SoftTime.h
#ifndef SoftTime_h
#define SoftTime_h
#include <Arduino.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <ESP8266WiFi.h>
#include <TimeLib.h>
#define TodaySecsLeft(_time_) (SECS_PER_DAY - ((_time_) % SECS_PER_DAY)) // the number of seconds since last midnight
#define SECS_PER_HALF_DAY ((time_t)(SECS_PER_HOUR * 12UL))
#define HourSecsLeft(_time_) ((_time_) % SECS_PER_HOUR)
struct TimeDataStruct
{
time_t Epoch;
time_t Actual;
bool DST;
time_t Offset;
};
class SoftTime {
private:
static WiFiUDP ntpUDP;
static struct TimeDataStruct TimeData;
static struct TimeDataStruct proccessEpochTime(time_t EpochTime);
static time_t getNTPTime();
static bool DSTChangeForthcoming(time_t CurentGMTTime);
static bool DSTTime(time_t CurentTime);
public:
/**
* Constructor.
*
*/
SoftTime(bool NTPStart);
};
#endif
Can someone help me to solve this problem? Thanks in advance.
Best regards,
Mark
Your two or more topics on the same or similar subject have been merged.
Please do not duplicate your questions as doing so wastes the time and effort of the volunteers trying to help you as they are then answering the same thing in different places.
Please create one topic only for your question and choose the forum category carefully. If you have multiple questions about the same project then please ask your questions in the one topic as the answers to one question provide useful context for the others, and also you won’t have to keep explaining your project repeatedly.
Repeated duplicate posting could result in a temporary or permanent ban from the forum.
Could you take a few moments to Learn How To Use The Forum
It will help you get the best out of the forum in the future.
Thank you.
I didn't solve this problem, but I solved it by extracting the getNTPTime to the public section and make a call with a subroutine in my main program and did a call to this routine with setSyncProvider in my main program. So no, I can't put everything under the hood unfortunately. But it works. So that's ok. You can't always make it perfect.
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.