diff --git a/README.md b/README.md
index 9025eb1..7bc3db4 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,6 @@ We've got some interesting branches in this repo inspired by user feedback. Thes
- 6 modes (Clock, Digital Clock, SPIRAL animation, TETRIS, SNAKE, PONG)
- time update via NTP server
- automatic summer/wintertime change
-- automatic timezone selection
- easy WIFI setup with WifiManager
- configurable color
- configurable night mode (start and end time)
diff --git a/data/index.html b/data/index.html
index 4bce60d..46ae4ba 100644
--- a/data/index.html
+++ b/data/index.html
@@ -354,7 +354,7 @@
WORDCLOCK 2.0
-
+
diff --git a/ledmatrix.cpp b/ledmatrix.cpp
index 49f1faa..90e0413 100644
--- a/ledmatrix.cpp
+++ b/ledmatrix.cpp
@@ -206,7 +206,8 @@ void LEDMatrix::drawOnMatrix(float factor){
// loop over all minute indicator leds
for(int i = 0; i < 4; i++){
uint32_t filteredColor = interpolateColor24bit(currentindicators[i], targetindicators[i], factor);
- (*neomatrix).drawPixel(WIDTH - (1+i), HEIGHT, color24to16bit(filteredColor));
+ (*neomatrix).drawPixel(3-i, HEIGHT, color24to16bit(filteredColor));
+ //(*neomatrix).drawPixel(WIDTH - (1+i), HEIGHT, color24to16bit(filteredColor));
currentindicators[i] = filteredColor;
totalCurrent += calcEstimatedLEDCurrent(filteredColor);
}
diff --git a/ledmatrix.h b/ledmatrix.h
index e130512..4d3a855 100644
--- a/ledmatrix.h
+++ b/ledmatrix.h
@@ -9,7 +9,7 @@
// width of the led matrix
#define WIDTH 11
// height of the led matrix
-#define HEIGHT 11
+#define HEIGHT 10
#define DEFAULT_CURRENT_LIMIT 9999
diff --git a/multicastUDP_receiver.py b/multicastUDP_receiver.py
index a5fea57..6c0e572 100644
--- a/multicastUDP_receiver.py
+++ b/multicastUDP_receiver.py
@@ -5,16 +5,12 @@
import queue
# ip address of network interface
-MCAST_IF_IP = '192.168.178.38'
+MCAST_IF_IP = '192.168.1.55'
multicast_group = '230.120.10.2'
server_address = ('', 8123)
-
-def start(filters=None):
- if filters is None:
- filters = []
-
+def start(filter = None):
# Create the socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
@@ -23,51 +19,55 @@ def start(filters=None):
print("Start")
- # Tell the operating system to add the socket to the multicast group on the specified interface
+ # Tell the operating system to add the socket to the multicast group
+ # on all interfaces.
group = socket.inet_aton(multicast_group)
mreq = struct.pack('4s4s', group, socket.inet_aton(MCAST_IF_IP))
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
print("Ready")
+ saveCounter = 0
- # Initialize buffers and save counters for each filter
- buffers = {filter_val: queue.Queue(20) for filter_val in filters}
- save_counters = {filter_val: 0 for filter_val in filters}
+ buffer = queue.Queue(20)
# Receive/respond loop
while True:
data, address = sock.recvfrom(1024)
data_str = data.decode("utf-8").strip()
- timestamped_data = f"[{address[0]} - {datetime.now().strftime('%b-%d-%Y_%H:%M:%S')}] {data_str}"
- print(timestamped_data)
-
- # Check each filter and process data accordingly
- for filter_val in filters:
- if filter_val in data_str:
- buffers[filter_val].put(timestamped_data)
- if buffers[filter_val].full():
- buffers[filter_val].get()
-
- # Save data if specific keywords are found or if save counter is active
- if "NTP-Update not successful" in data_str or "Start program" in data_str:
- with open(f"log_{filter_val}.txt", 'a') as f:
- while not buffers[filter_val].empty():
- f.write(buffers[filter_val].get() + "\n")
- save_counters[filter_val] = 20 # Start the save counter
-
- if save_counters[filter_val] > 0:
- with open(f"log_{filter_val}.txt", 'a') as f:
- f.write(timestamped_data + "\n")
- if save_counters[filter_val] == 1:
- f.write("\n")
- save_counters[filter_val] -= 1
+ if filter is not None and filter not in data_str:
+ continue
+ data_str = "[" + str(address[0]) + " - " + datetime.now().strftime('%b-%d-%Y_%H:%M:%S') + "] " + data_str
+ print(data_str)
+ buffer.put(data_str)
+ if buffer.full():
+ buffer.get()
+
+
+ if "NTP-Update not successful" in data_str or "Start program" in data_str:
+ f = open("log.txt",'a')
+ while not buffer.empty():
+ f.write(buffer.get())
+ f.write("\n")
+ f.close()
+ saveCounter = 20
+
+ if saveCounter > 0:
+ f = open("log.txt",'a')
+ f.write(data_str)
+ f.write("\n")
+ if saveCounter == 1:
+ f.write("\n")
+ f.close()
+ saveCounter -= 1
# Main
if __name__ == '__main__':
- # Check if filters are given
- # Use filters as arguments: python3 multicastUDP_receiver.py "filter1" "filter2" ...
+
+ # Check if a filter is given
+ # use filter as argument to filter messages: python3 multicastUDP_receiver.py "filter"
+
if len(sys.argv) > 1:
- start(sys.argv[1:])
+ start(sys.argv[1])
else:
start()
diff --git a/ntp_client_plus.cpp b/ntp_client_plus.cpp
index 451bde3..79331f5 100644
--- a/ntp_client_plus.cpp
+++ b/ntp_client_plus.cpp
@@ -265,10 +265,10 @@ void NTPClientPlus::calcDate()
daysInMonth[2] = 28;
}
- unsigned int dayOfYear = (days1900 - ((this->_dateYear - 1900) * 365) - leapDays);
+ this->_dayOfYear = (days1900 - ((this->_dateYear - 1900) * 365) - leapDays);
// calc current month
- this->_dateMonth = this->getMonth(dayOfYear);
+ this->_dateMonth = this->getMonth(this->_dayOfYear);
this->_dateDay = 0;
@@ -277,7 +277,7 @@ void NTPClientPlus::calcDate()
{
this->_dateDay = this->_dateDay + daysInMonth[i];
}
- this->_dateDay = dayOfYear - this->_dateDay;
+ this->_dateDay = this->_dayOfYear - this->_dateDay;
// calc day of week:
// Monday = 1, Tuesday = 2, Wednesday = 3, Thursday = 4, Friday = 5, Saturday = 6, Sunday = 7
@@ -314,6 +314,16 @@ unsigned int NTPClientPlus::getDayOfWeek()
return this->_dayOfWeek;
}
+/**
+ * @brief Getter for day of the year
+ *
+ * @return unsigned int
+ */
+unsigned int NTPClientPlus::getDayOfYear()
+{
+ return this->_dayOfYear;
+}
+
/**
* @brief Function to calc current year
*
diff --git a/ntp_client_plus.h b/ntp_client_plus.h
index 847306c..2abe9a7 100644
--- a/ntp_client_plus.h
+++ b/ntp_client_plus.h
@@ -33,6 +33,7 @@ class NTPClientPlus{
String getFormattedDate();
void calcDate();
unsigned int getDayOfWeek();
+ unsigned int getDayOfYear();
unsigned int getYear();
bool isLeapYear(unsigned int year);
int getMonth(int dayOfYear);
@@ -60,6 +61,7 @@ class NTPClientPlus{
unsigned int _dateMonth = 0;
unsigned int _dateDay = 0;
unsigned int _dayOfWeek = 0;
+ unsigned int _dayOfYear = 0;
byte _packetBuffer[NTP_PACKET_SIZE];
diff --git a/pong.h b/pong.h
index e5c226c..bf44200 100644
--- a/pong.h
+++ b/pong.h
@@ -21,7 +21,7 @@
#define DEBOUNCE_TIME_PONG 10 // in ms
#define X_MAX 11
-#define Y_MAX 11
+#define Y_MAX 10
#define GAME_DELAY_PONG 80 // in ms
#define BALL_DELAY_MAX 350 // in ms
diff --git a/snake.h b/snake.h
index f4619cb..364bc6a 100644
--- a/snake.h
+++ b/snake.h
@@ -20,7 +20,7 @@
#define DEBOUNCE_TIME_SNAKE 300 // in ms
#define X_MAX 11
-#define Y_MAX 11
+#define Y_MAX 10
#define GAME_DELAY_SNAKE 400 // in ms
diff --git a/tetris.h b/tetris.h
index e5b372f..3a74c17 100644
--- a/tetris.h
+++ b/tetris.h
@@ -50,7 +50,7 @@
#define LEVELUP 4 // Number of rows before levelup, default 5
#define WIDTH 11
-#define HEIGHT 11
+#define HEIGHT 10
class Tetris{
diff --git a/wordclock_esp8266.ino b/wordclock_esp8266.ino
index 12d0dd9..8399b70 100644
--- a/wordclock_esp8266.ino
+++ b/wordclock_esp8266.ino
@@ -98,7 +98,7 @@ enum direction {right, left, up, down};
// width of the led matrix
#define WIDTH 11
// height of the led matrix
-#define HEIGHT 11
+#define HEIGHT 10
// own datatype for state machine states
#define NUM_STATES 6
@@ -127,6 +127,10 @@ const char WebserverURL[] = "www.wordclock.local";
int utcOffset = 60; // UTC offset in minutes
+const unsigned int num_coeff = 5; // number of coeffients + 1
+// Sunsetminutes (without summer- wintertimeshift!)
+const double sunsetMinutes[] = { 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1014, 1015, 1016, 1017, 1019, 1020, 1021, 1023, 1024, 1026, 1027, 1028, 1030, 1031, 1033, 1034, 1036, 1037, 1039, 1040, 1042, 1043, 1045, 1047, 1048, 1050, 1051, 1053, 1054, 1056, 1057, 1059, 1061, 1062, 1064, 1065, 1067, 1068, 1070, 1071, 1073, 1075, 1076, 1078, 1079, 1081, 1082, 1084, 1085, 1087, 1088, 1090, 1091, 1093, 1094, 1096, 1097, 1098, 1100, 1101, 1103, 1104, 1106, 1107, 1109, 1110, 1111, 1113, 1114, 1116, 1117, 1119, 1120, 1121, 1123, 1124, 1126, 1127, 1128, 1130, 1131, 1133, 1134, 1135, 1137, 1138, 1140, 1141, 1142, 1144, 1145, 1147, 1148, 1149, 1151, 1152, 1154, 1155, 1156, 1158, 1159, 1161, 1162, 1163, 1165, 1166, 1168, 1169, 1170, 1172, 1173, 1174, 1176, 1177, 1179, 1180, 1181, 1183, 1184, 1185, 1187, 1188, 1189, 1190, 1192, 1193, 1194, 1195, 1197, 1198, 1199, 1200, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1216, 1217, 1218, 1219, 1219, 1220, 1221, 1221, 1222, 1222, 1223, 1223, 1223, 1224, 1224, 1224, 1224, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1224, 1224, 1224, 1224, 1223, 1223, 1222, 1222, 1221, 1221, 1220, 1220, 1219, 1218, 1217, 1217, 1216, 1215, 1214, 1213, 1212, 1211, 1210, 1209, 1208, 1207, 1205, 1204, 1203, 1202, 1200, 1199, 1198, 1196, 1195, 1193, 1192, 1190, 1189, 1187, 1186, 1184, 1182, 1181, 1179, 1177, 1176, 1174, 1172, 1170, 1169, 1167, 1165, 1163, 1161, 1159, 1158, 1156, 1154, 1152, 1150, 1148, 1146, 1144, 1142, 1140, 1138, 1136, 1134, 1132, 1130, 1128, 1126, 1124, 1122, 1120, 1118, 1116, 1114, 1112, 1110, 1108, 1106, 1104, 1102, 1100, 1098, 1096, 1094, 1092, 1090, 1088, 1086, 1084, 1082, 1080, 1078, 1076, 1074, 1072, 1070, 1068, 1066, 1064, 1062, 1060, 1058, 1056, 1055, 1053, 1051, 1049, 1047, 1046, 1044, 1042, 1040, 1039, 1037, 1035, 1034, 1032, 1030, 1029, 1027, 1026, 1024, 1023, 1021, 1020, 1019, 1017, 1016, 1015, 1013, 1012, 1011, 1010, 1009, 1008, 1007, 1006, 1005, 1004, 1003, 1002, 1001, 1000, 1000, 999, 998, 998, 997, 997, 996, 996, 995, 995, 995, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 995, 995, 995, 996, 996, 997, 997, 998, 998, 999, 1000, 1000, 1001, 1002, 1003, 1004};
+
// ----------------------------------------------------------------------------------
// GLOBAL VARIABLES
// ----------------------------------------------------------------------------------
@@ -612,23 +616,39 @@ void checkNightmode(){
logger.logString("Check nightmode");
int hours = ntp.getHours24();
int minutes = ntp.getMinutes();
-
+ int dayofyear = ntp.getDayOfYear();
+ bool summertime = ntp.updateSWChange();
+
+ dayofyear = limit(dayofyear, 1, 365);
nightMode = false; // Initial assumption
// Convert all times to minutes for easier comparison
int currentTimeInMinutes = hours * 60 + minutes;
- int startInMinutes = nightModeStartHour * 60 + nightModeStartMin;
int endInMinutes = nightModeEndHour * 60 + nightModeEndMin;
+ //double poly[] = {1.0208E+3, -170.4552E-3, 30.0056E-3, -173.0480E-6, 251.6062E-9}; // a0+a1*x+a2*x^2+a3*x^3+a4*x^4
+ //int startInMinutes = poly_eval(poly, dayofyear);
+ //if (summertime == true) startInMinutes += 60;
+ //logger.logString("Sunset startInminutes (polynomial): " + String(startInMinutes));
+ int startInMinutes = sunsetMinutes[dayofyear - 1];
+ if (summertime == true) startInMinutes += 60;
+ logger.logString("Sunset startInminutes: " + String(startInMinutes));
+
+ loadBrightnessSettingsFromEEPROM();
+
if (startInMinutes < endInMinutes && nightModeActivated) { // Same day scenario
if (startInMinutes < currentTimeInMinutes && currentTimeInMinutes < endInMinutes) {
- nightMode = true;
- logger.logString("Nightmode active");
+ brightness = (uint8_t)(brightness * 0.5);
+ ledmatrix.setBrightness(brightness);
+ logger.logString("Darkmode Brightness: " + String(brightness));
+ logger.logString("Darkmode active");
}
} else if (startInMinutes > endInMinutes && nightModeActivated) { // Overnight scenario
if (currentTimeInMinutes >= startInMinutes || currentTimeInMinutes < endInMinutes) {
- nightMode = true;
- logger.logString("Nightmode active");
+ brightness = (uint8_t)(brightness * 0.5);
+ ledmatrix.setBrightness(brightness);
+ logger.logString("Darkmode Brightness: " + String(brightness));
+ logger.logString("Darkmode active");
}
}
}
@@ -1157,3 +1177,35 @@ String leadingZero2Digit(int value){
msg += String(value);
return msg;
}
+
+/**
+ * @brief Polynomial evaluation (num_coeff = grade simplified)
+ *
+ * @param coeff
+ * @param x
+ * @return double
+ */
+double poly_eval(double coeff[num_coeff], double x) {
+ double result = coeff[num_coeff-1];
+ for (size_t i = num_coeff-1; i --> 0;)
+ result = coeff[i] + x * result;
+ return result;
+}
+
+/**
+ * @brief Limit value to min/max
+ *
+ * @param value
+ * @param min
+ * @param max
+ * @return int
+ */
+int limit(int value, int min, int max) {
+ if (value < min) {
+ return min;
+ } else if (value > max) {
+ return max;
+ } else {
+ return value;
+ }
+}
diff --git a/wordclockfunctions.ino b/wordclockfunctions.ino
index ecbdc6e..94afdd2 100644
--- a/wordclockfunctions.ino
+++ b/wordclockfunctions.ino
@@ -1,5 +1,5 @@
-const String clockStringGerman = "ESPISTAFUNFVIERTELZEHNZWANZIGUVORTECHNICNACHHALBMELFUNFXCONTROLLEREINSEAWZWEIDREITUMVIERSECHSQYACHTSIEBENZWOLFZEHNEUNJUHR";
+const String clockStringGerman = "ESKISCHUFUFVIERTUNFZAAZWANZGSEVORABCHAUBIECMEISZWOISDRUVIERIFUFISTSACHSISIBNIACHTINUNIELZANIECHEUFIZWOUFIENGSI";
/**
* @brief control the four minute indicator LEDs
@@ -96,53 +96,53 @@ int showStringOnClock(String message, uint32_t color){
String timeToString(uint8_t hours,uint8_t minutes){
//ES IST
- String message = "ES IST ";
+ String message = "ES ISCH ";
//show minutes
if(minutes >= 5 && minutes < 10)
{
- message += "FUNF NACH ";
+ message += "FUF AB ";
}
else if(minutes >= 10 && minutes < 15)
{
- message += "ZEHN NACH ";
+ message += "ZAA AB ";
}
else if(minutes >= 15 && minutes < 20)
{
- message += "VIERTEL NACH ";
+ message += "VIERTU AB ";
}
else if(minutes >= 20 && minutes < 25)
{
- message += "ZEHN VOR HALB ";
+ message += "ZWANZG AB ";
}
else if(minutes >= 25 && minutes < 30)
{
- message += "FUNF VOR HALB ";
+ message += "FUF VOR HAUBI ";
}
else if(minutes >= 30 && minutes < 35)
{
- message += "HALB ";
+ message += "HAUBI ";
}
else if(minutes >= 35 && minutes < 40)
{
- message += "FUNF NACH HALB ";
+ message += "FUF AB HAUBI ";
}
else if(minutes >= 40 && minutes < 45)
{
- message += "ZEHN NACH HALB ";
+ message += "ZWANZG VOR ";
}
else if(minutes >= 45 && minutes < 50)
{
- message += "VIERTEL VOR ";
+ message += "VIERTU VOR ";
}
else if(minutes >= 50 && minutes < 55)
{
- message += "ZEHN VOR ";
+ message += "ZAA VOR ";
}
else if(minutes >= 55 && minutes < 60)
{
- message += "FUNF VOR ";
+ message += "FUF VOR ";
}
//convert hours to 12h format
@@ -150,7 +150,7 @@ String timeToString(uint8_t hours,uint8_t minutes){
{
hours -= 12;
}
- if(minutes >= 20)
+ if(minutes >= 25)
{
hours++;
}
@@ -163,54 +163,49 @@ String timeToString(uint8_t hours,uint8_t minutes){
switch(hours)
{
case 0:
- message += "ZWOLF ";
+ message += "ZWOUFI ";
break;
case 1:
- message += "EIN";
+ message += "EIS ";
//EIN(S)
- if(minutes > 4){
- message += "S";
- }
- message += " ";
break;
case 2:
- message += "ZWEI ";
+ message += "ZWOI ";
break;
case 3:
- message += "DREI ";
+ message += "DRU ";
break;
case 4:
- message += "VIER ";
+ message += "VIERI ";
break;
case 5:
- message += "FUNF ";
+ message += "FUFI ";
break;
case 6:
- message += "SECHS ";
+ message += "SACHSI ";
break;
case 7:
- message += "SIEBEN ";
+ message += "SIBNI ";
break;
case 8:
- message += "ACHT ";
+ message += "ACHTI ";
break;
case 9:
- message += "NEUN ";
+ message += "NUNI ";
break;
case 10:
- message += "ZEHN ";
+ message += "ZANI ";
break;
case 11:
- message += "ELF ";
+ message += "EUFI ";
break;
}
- if(minutes < 5)
+ if(minutes % 5 != 0)
{
- message += "UHR ";
+ message += "GSI ";
}
logger.logString("time as String: " + String(message));
return message;
}
-