Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 52 additions & 18 deletions ntp_client_plus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,12 @@ void NTPClientPlus::setPoolServerName(const char *poolServerName)
* @return unsigned long seconds since 1. Jan. 1900
*/
unsigned long NTPClientPlus::getSecsSince1900() const
{
return this->_utcx * this->secondperminute + // UTC offset
this->_summertime * this->secondperhour + // Summer time offset
this->_secsSince1900 + // seconds returned by the NTP server
((millis() - this->_lastUpdate) / 1000); // Time since last update
{
int64_t secsSince1900WithDST = static_cast<int64_t>(this->_secsSince1900) + // seconds returned by the NTP server
static_cast<int64_t>((millis() - this->_lastUpdate) / 1000) + // Time since last update
this->_summertime * this->secondperhour + // Summer time offset
(static_cast<int64_t>(this->_utcx) * this->secondperminute); // UTC offset
return static_cast<unsigned long>(secsSince1900WithDST);
}

/**
Expand Down Expand Up @@ -199,15 +200,14 @@ int NTPClientPlus::getSeconds() const
String NTPClientPlus::getFormattedTime() const {
unsigned long rawTime = this->getEpochTime();
unsigned long hours = (rawTime % 86400L) / 3600;
String hoursStr = hours < 10 ? "0" + String(hours) : String(hours);

unsigned long minutes = (rawTime % 3600) / 60;
String minuteStr = minutes < 10 ? "0" + String(minutes) : String(minutes);

unsigned long seconds = rawTime % 60;
String secondStr = seconds < 10 ? "0" + String(seconds) : String(seconds);

return hoursStr + ":" + minuteStr + ":" + secondStr;
// Fester Puffer statt mehrfacher String-Verkettung, um Heap-Fragmentierung zu vermeiden
// Format identisch zu vorher: hh:mm:ss (jeweils 2-stellig, mit fuehrender Null)
char buffer[9]; // "hh:mm:ss" + '\0'
snprintf(buffer, sizeof(buffer), "%02lu:%02lu:%02lu", hours, minutes, seconds);
return String(buffer);
}

/**
Expand Down Expand Up @@ -585,6 +585,21 @@ bool NTPClientPlus::updateSWChange()
unsigned int dateDay = this->_dateDay;
unsigned int dateMonth = this->_dateMonth;

// Calculate local STANDARD time (without DST) for exact switch-hour handling.
// EU rule: DST starts on last Sunday in March at 02:00 (standard time),
// and ends on last Sunday in October at 03:00 local summer time
// (== 02:00 standard time).
int64_t currentUtcSeconds = static_cast<int64_t>(this->_secsSince1900) +
static_cast<int64_t>((millis() - this->_lastUpdate) / 1000);
int64_t secsSince1900NoDST = currentUtcSeconds +
(static_cast<int64_t>(this->_utcx) * this->secondperminute);
int64_t secondsIntoDay = secsSince1900NoDST % this->secondperday;
if (secondsIntoDay < 0)
{
secondsIntoDay += this->secondperday;
}
unsigned int hourNoDST = static_cast<unsigned int>(secondsIntoDay / this->secondperhour);

bool summertimeActive = false;

if (this->_swChange)
Expand All @@ -607,10 +622,19 @@ bool NTPClientPlus::updateSWChange()
//Calculation: 31 - 30 = 1; 1 + 2 = 3;
//Result: Last day in March is a Wednesday. Changeover to summer time already done => set summer time

// If today is Sunday (dayOfWeek == 7) then this is already the last sunday in march -> set summer time
// If today is Sunday (dayOfWeek == 7) then this is the last Sunday in March.
// Switch to summer time at 02:00 standard time (clock jumps to 03:00).
if(dayOfWeek == 7){
this->setSummertime(1);
summertimeActive = true;
if (hourNoDST >= 2)
{
this->setSummertime(1);
summertimeActive = true;
}
else
{
this->setSummertime(0);
summertimeActive = false;
}
}

//There follows within the last week in March one more Sunday => set winter time
Expand Down Expand Up @@ -652,10 +676,20 @@ bool NTPClientPlus::updateSWChange()
//Calculation: 31 - 26 = 5; 5 + 2 = 7;
//Result: Last day in October is a Sunday. There follows another Sunday in October => set summer time

// If today is Sunday (dayOfWeek == 7) then this is already the last sunday in october -> winter time
// If today is Sunday (dayOfWeek == 7) then this is the last Sunday in October.
// Switch back to winter time at 02:00 standard time
// (which corresponds to 03:00 local summer time).
if(dayOfWeek == 7){
this->setSummertime(0);
summertimeActive = false;
if (hourNoDST >= 2)
{
this->setSummertime(0);
summertimeActive = false;
}
else
{
this->setSummertime(1);
summertimeActive = true;
}
}

// There follows within the last week in October one more Sunday => summer time
Expand Down Expand Up @@ -697,4 +731,4 @@ bool NTPClientPlus::updateSWChange()
}

return summertimeActive;
}
}
12 changes: 7 additions & 5 deletions udplogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,23 @@ UDPLogger::UDPLogger(IPAddress interfaceAddr, IPAddress multicastAddr, int port)
_interfaceAddr = interfaceAddr;
_name = "Log";
_Udp.beginMulticast(_interfaceAddr, _multicastAddr, _port);
_lastSend = 0;
}

void UDPLogger::setName(String name){
_name = name;
}

void UDPLogger::logString(String logmessage){
void UDPLogger::logString(const String& logmessage){
// wait 5 milliseconds if last send was less than 5 milliseconds before
if(millis() < (_lastSend + 5)){
delay(5);
}
logmessage = _name + ": " + logmessage;
Serial.println(logmessage);
// use fixed buffer instead of string concatenation to avoid heap fragmentation
// message will be truncated to fit into _packetBuffer (99 chars + NUL)
snprintf(_packetBuffer, sizeof(_packetBuffer), "%s: %s", _name.c_str(), logmessage.c_str());
Serial.println(_packetBuffer);
_Udp.beginPacketMulticast(_multicastAddr, _port, _interfaceAddr);
logmessage.toCharArray(_packetBuffer, 100);
_Udp.print(_packetBuffer);
_Udp.endPacket();
_lastSend=millis();
Expand All @@ -35,4 +37,4 @@ void UDPLogger::logColor24bit(uint32_t color){
uint8_t resultGreen = color >> 8 & 0xff;
uint8_t resultBlue = color & 0xff;
logString(String(resultRed) + ", " + String(resultGreen) + ", " + String(resultBlue));
}
}
2 changes: 1 addition & 1 deletion udplogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class UDPLogger{
UDPLogger();
UDPLogger(IPAddress interfaceAddr, IPAddress multicastAddr, int port);
void setName(String name);
void logString(String logmessage);
void logString(const String& logmessage);
void logColor24bit(uint32_t color);
private:
String _name;
Expand Down
23 changes: 18 additions & 5 deletions wordclock_esp8266.ino
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
#define PERIOD_SNAKE 50
#define PERIOD_PONG 10
#define TIMEOUT_LEDDIRECT 5000
#define TIMEOUT_WIFI_DISCONNECTED 30000
#define PERIOD_STATECHANGE 10000
#define PERIOD_NTPUPDATE 30000
#define PERIOD_TIMEVISUUPDATE 1000
Expand Down Expand Up @@ -189,6 +190,7 @@ long lastNTPUpdate = millis() - (PERIOD_NTPUPDATE-3000); // time of last NTP up
long lastAnimationStep = millis(); // time of last Matrix update
long lastNightmodeCheck = millis() - (PERIOD_NIGHTMODECHECK-3000); // time of last nightmode check
long buttonPressStart = 0; // time of push button press start
long wifiDisconnectedSince = 0; // time since WiFi connection was lost (0 = connected)
uint16_t behaviorUpdatePeriod = PERIOD_TIMEVISUUPDATE; // holdes the period in which the behavior should be updated

// Create necessary global objects
Expand Down Expand Up @@ -456,11 +458,22 @@ void loop() {
lastheartbeat = millis();

// Check wifi status (only if no apmode)
if(!apmode && WiFi.status() != WL_CONNECTED){
Serial.println("connection lost");
ledmatrix.gridAddPixel(0, 5, colors24bit[1]);
ledmatrix.drawOnMatrixInstant();
delay(1000);
if(!apmode){
if(WiFi.status() != WL_CONNECTED){
if(wifiDisconnectedSince == 0){
wifiDisconnectedSince = millis();
Serial.println("connection lost");
}

if(millis() - wifiDisconnectedSince >= TIMEOUT_WIFI_DISCONNECTED){
ledmatrix.gridAddPixel(0, 5, colors24bit[1]);
ledmatrix.drawOnMatrixInstant();
delay(1000);
}
}
else {
wifiDisconnectedSince = 0;
}
}
}

Expand Down
Loading