Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
41ad880
feat: add eeprom version code to be able to set default settings, Fix…
techniccontroller Aug 3, 2025
737f249
Merge pull request #67 from techniccontroller/dev_eeprom_versioncode
techniccontroller Aug 3, 2025
2c95a5f
Update README
techniccontroller Sep 21, 2025
d407c1d
feat: add night mode brightness setting
techniccontroller Jan 3, 2026
6008cd2
Merge pull request #71 from techniccontroller/dev_nm_brightness
techniccontroller Jan 3, 2026
ee60e8d
feat: add getters for day of the month and month number
techniccontroller Jan 3, 2026
dcd0953
Merge pull request #73 from techniccontroller/dev_daymonth
techniccontroller Jan 3, 2026
1de68ec
fix: change ZEHN VOR to ZWANZIG NACH in german version
techniccontroller Jan 3, 2026
722d02d
Merge pull request #75 from techniccontroller/dev_zwanzig
techniccontroller Jan 3, 2026
57b5d33
fix: improve daylight saving time handling in updateSWChange method, …
techniccontroller Apr 4, 2026
7afb73c
fix signed time calculations
techniccontroller Apr 4, 2026
491c35f
fix: improve calculation of seconds since 1 Jan 1900 to consider sign…
techniccontroller Apr 4, 2026
3c71cbd
Merge pull request #80 from techniccontroller/fix_dst
techniccontroller Apr 4, 2026
6d3ebc3
fix: add timeout for WiFi disconnection handling
techniccontroller Apr 26, 2026
953741f
Merge pull request #81 from techniccontroller/patch_connection_check
techniccontroller Apr 26, 2026
26c47ad
Optimize getFormattedTime method with snprintf
deepstahl77 Jul 8, 2026
f1f6db3
Refactor logString method for efficiency
deepstahl77 Jul 8, 2026
c40ed9a
Merge pull request #87 from deepstahl77/patch-1
techniccontroller Jul 11, 2026
d49386d
fix signature of logString()
techniccontroller Jul 11, 2026
18393ac
fix: initialize _lastSend in UDPLogger constructor and update logStri…
techniccontroller Jul 11, 2026
7b62e9d
Merge pull request #91 from techniccontroller/integrate-pr-88
techniccontroller Jul 11, 2026
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ We've got some interesting branches in this repo inspired by user feedback. Thes
![compile esp8266 workflow](https://github.com/techniccontroller/wordclock_esp8266/actions/workflows/compile_esp8266.yml/badge.svg?branch=rgbw_leds)
- [**static_background_pattern**](https://github.com/techniccontroller/wordclock_esp8266/tree/static_background_pattern): This branch allows to light up specific letters always during clock mode. E.G., to display some special words in another color.
![compile esp8266 workflow](https://github.com/techniccontroller/wordclock_esp8266/actions/workflows/compile_esp8266.yml/badge.svg?branch=static_background_pattern)
- [**frame_light**](https://github.com/techniccontroller/wordclock_esp8266/tree/frame_light): This branch allows to add an additional LEDs around the clock, as background/frame light it has the same color as the clock. Thanks to Sandro for the idea.
![compile esp8266 workflow](https://github.com/techniccontroller/wordclock_esp8266/actions/workflows/compile_esp8266.yml/badge.svg?branch=frame_light)

## Install needed Libraries

Expand Down
10 changes: 9 additions & 1 deletion data/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@
}

.show{
height: 280px;
height: 320px;
transition: height 1s;
}

Expand Down Expand Up @@ -280,6 +280,10 @@ <h1 id="headline">WORDCLOCK 2.0</h1>
<label for="colorshiftspeed">Color shift speed:</label>
<input type="range" id="colorshiftspeed" name="volume" min="0" max="50">
</div>
<div class="number-container">
<label for="nm_brightness">Nightmode brightness:</label>
<input type="range" id="nm_brightness" name="volume" min="0" max="100">
</div>
<div class="number-container">
<label for="nm_start" style="align-self: flex-start">Nightmode start time: </label>
<input type="time" id="nm_start" name="nm_start" min="00:00" max="23:59">
Expand Down Expand Up @@ -536,6 +540,7 @@ <h1 id="headline">WORDCLOCK 2.0</h1>
document.getElementById("nm_start").value = myVar.nightModeStart.replace("-", ":");
document.getElementById("nm_end").value = myVar.nightModeEnd.replace("-", ":");
document.getElementById("brightness").value = parseInt(myVar.brightness);
document.getElementById("nm_brightness").value = parseInt(myVar.nightModeBrightness);
document.getElementById("colorshiftspeed").value = parseInt(myVar.colorshiftspeed);

updateDisplay(parseInt(myVar.modeid));
Expand Down Expand Up @@ -606,6 +611,7 @@ <h1 id="headline">WORDCLOCK 2.0</h1>
var nmStart = document.getElementById("nm_start");
var nmEnd = document.getElementById("nm_end");
var sld_brightness = document.getElementById("brightness");
var sld_nm_brightness = document.getElementById("nm_brightness");
var sld_colorshiftspeed = document.getElementById("colorshiftspeed");
var ckb_resetWifi = document.querySelector('input[id="ResetWifi"]');
var cmdstr = "./cmd?setting=";
Expand All @@ -616,6 +622,8 @@ <h1 id="headline">WORDCLOCK 2.0</h1>
cmdstr += sld_brightness.value;
cmdstr += "-";
cmdstr += sld_colorshiftspeed.value;
cmdstr += "-";
cmdstr += sld_nm_brightness.value;
console.log(cmdstr);
sendCommand(cmdstr);
if(ckb_resetWifi.checked) {
Expand Down
90 changes: 72 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 @@ -314,6 +314,26 @@ unsigned int NTPClientPlus::getDayOfWeek()
return this->_dayOfWeek;
}

/**
* @brief Getter for day of the month
*
* @return unsigned int
*/
unsigned int NTPClientPlus::getDayOfMonth()
{
return this->_dateDay;
}

/**
* @brief Getter for the month number
*
* @return unsigned int
*/
unsigned int NTPClientPlus::getMonthNumber()
{
return this->_dateMonth;
}

/**
* @brief Function to calc current year
*
Expand Down Expand Up @@ -565,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 @@ -587,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 @@ -632,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 @@ -677,4 +731,4 @@ bool NTPClientPlus::updateSWChange()
}

return summertimeActive;
}
}
2 changes: 2 additions & 0 deletions ntp_client_plus.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ class NTPClientPlus{
String getFormattedDate();
void calcDate();
unsigned int getDayOfWeek();
unsigned int getDayOfMonth();
unsigned int getMonthNumber();
unsigned int getYear();
bool isLeapYear(unsigned int year);
int getMonth(int dayOfYear);
Expand Down
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
Loading
Loading