#include #include #include #include #include "config.h" //***********************************// // 6 byte #define TIMER_DATA_HH 0 #define TIMER_DATA_MM 1 #define TIMER_DATA_CH1 2 // the brightness of the channel #define TIMER_DATA_CH2 3 // the brightness of the channel #define TIMER_DATA_CH3 4 // the brightness of the channel #define TIMER_DATA_CH4 5 // the brightness of the channel #define LENGTH_OF_TIMER_DATA_BLOCK (TIMER_DATA_CH4 + 1) #define NUMBER_OF_TIMER_DATA_BLOCKS 10 //***********************************// /* Globals */ bool tc_testOngoing = false; uint32_t tc_last_check = 60000; WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, MY_NTP_SERVER); struct tc_data_st { uint8_t hh; uint8_t mm; uint8_t ch1; uint8_t ch2; uint8_t ch3; uint8_t ch4; }; struct tc_data_st tc_data[10]; uint8_t example_timer_data_block[] = { // hour min ch1 ch2 ch3 ch3 8, 0, 0, 0, 0, 0, // 0: off 8, 30, 25, 0, 0, 0, // 1: 10% ch1 blues 11, 0, 25, 0, 25, 0, // 2: 10% all blues 13, 0, 205, 205, 205, 205, // 3: 80% all 18, 0, 205, 205, 205, 205, // 4: 80% all for 5 hours 19, 0, 50, 50, 50, 50, // 5: 20% all 19, 30, 50, 0, 50, 0, // 6: 20% all blues 20, 0, 25, 0, 25, 0, // 9: disabled 20, 30, 25, 0, 0, 0, // 7: 10% ch1 blues 21, 0, 0, 0, 0, 0, // 8: 0% all }; uint8_t test_timer_data_block[] = { // hour min ch1 ch2 ch3 ch3 9, 20, 0, 0, 0, 0, // 0: off 9, 30, 25, 0, 0, 0, // 1: 10% ch1 blues 9, 40, 25, 0, 25, 0, // 2: 10% all blues 9, 50, 205, 205, 205, 205, // 3: 80% all 10, 0, 100, 100, 100, 100, // 4: 80% all for 5 hours 10, 10, 50, 50, 50, 50, // 5: 20% all 10, 20, 50, 0, 50, 0, // 6: 20% all blues 10, 30, 25, 0, 0, 0, // 7: 10% ch1 blues 10, 40, 0, 0, 0, 0, // 8: all off 11, 0, 0, 0, 0, 0, // 9: all off }; //***********************************// void tc_init() { if (tc_check_no_data_block() == true) { //Serial.println("TC: No data block found, writing example block to EEPROM."); tc_write_default(); } while ( WiFi.status() != WL_CONNECTED ) { delay (500); Serial.print ( "." ); } tc_last_check = millis(); // Set the timezone to Europe/Berlin setenv("TZ", LOCAL_TIMEZONE_STRING, 1); tzset(); timeClient.begin(); Serial.println("TC: Read data block from eeprom"); tc_readConfig(); if (tc_testOngoing == true) { Serial.println("TC: Test ongoing, reading test data"); for (uint8_t i = 0; i < NUMBER_OF_TIMER_DATA_BLOCKS * LENGTH_OF_TIMER_DATA_BLOCK; i += LENGTH_OF_TIMER_DATA_BLOCK) { tc_data[i / LENGTH_OF_TIMER_DATA_BLOCK].hh = test_timer_data_block[i]; tc_data[i / LENGTH_OF_TIMER_DATA_BLOCK].mm = test_timer_data_block[i+1]; tc_data[i / LENGTH_OF_TIMER_DATA_BLOCK].ch1 = test_timer_data_block[i+2]; tc_data[i / LENGTH_OF_TIMER_DATA_BLOCK].ch2 = test_timer_data_block[i+3]; tc_data[i / LENGTH_OF_TIMER_DATA_BLOCK].ch3 = test_timer_data_block[i+4]; tc_data[i / LENGTH_OF_TIMER_DATA_BLOCK].ch4 = test_timer_data_block[i+5]; Serial.print("data block: "); Serial.println(i / LENGTH_OF_TIMER_DATA_BLOCK); Serial.print(" hh: "); Serial.println(tc_data[i / LENGTH_OF_TIMER_DATA_BLOCK].hh); Serial.print(" mm: "); Serial.println(tc_data[i / LENGTH_OF_TIMER_DATA_BLOCK].mm); Serial.print(" ch1: "); Serial.println(tc_data[i / LENGTH_OF_TIMER_DATA_BLOCK].ch1); Serial.print(" ch2: "); Serial.println(tc_data[i / LENGTH_OF_TIMER_DATA_BLOCK].ch2); Serial.print(" ch3: "); Serial.println(tc_data[i / LENGTH_OF_TIMER_DATA_BLOCK].ch3); Serial.print(" ch4: "); Serial.println(tc_data[i / LENGTH_OF_TIMER_DATA_BLOCK].ch4); } } if (tc_enabled == TIMING_CONTROL_ENABLED) { Serial.println("tc_enabled = " + (String)tc_enabled); tc_update_main(); } } //********************************// void tc_update_loop() { static uint8_t last_min_check = 255; if ((timeClient.getMinutes() % 10) != 0 || last_min_check == timeClient.getMinutes()) // && tc_testOngoing == false { last_min_check = timeClient.getMinutes(); return; // only run every 10 minutes } tc_update_main(); } void tc_update_main() { static uint8_t current_target_data_block = 255; uint8_t target_data_block = 255; tc_updateTime(); // search for the current active time slot for (int i = NUMBER_OF_TIMER_DATA_BLOCKS-1; i >= 0 && target_data_block == 255; --i) { //Serial.println((String)tc_data[i].hh + ":" + (String)tc_data[i].mm); /*if (tc_data[i].hh <= timeClient.getHours() && tc_data[i].mm <= timeClient.getMinutes())*/ if (tc_data[i].hh <= hour() && tc_data[i].mm <= minute()) { target_data_block = i+1; // found the next block to load } //Serial.println((String)i + " => " + target_data_block); } if (target_data_block == 255) { // no new predecessor or successor found, start over current_target_data_block = 255; return; } if (current_target_data_block != target_data_block) { // new target block should be reached current_target_data_block = target_data_block; } else { // drop the found target block, we are already going on to reach it return; } if (target_data_block >= NUMBER_OF_TIMER_DATA_BLOCKS) { target_data_block = 255; current_target_data_block = 255; return; } // print out the current light state Serial.println("-----\nCurrent values"); for (uint8_t i = 0; i < LIGHTS_COUNT; i++) { Serial.println("current_bri[" + (String)i + "] = " + (String)current_bri[i]); } for (uint8_t i = 0; i < LIGHTS_COUNT; i++) { Serial.println("bri[" + (String)i + "] = " + (String)bri[i]); } for (uint8_t i = 0; i < LIGHTS_COUNT; i++) { Serial.println("step_level[" + (String)i + "] = " + (String)step_level[i]); } Serial.println("-----\ntdb = " + (String)target_data_block); Serial.print("target time: "); Serial.print(tc_data[target_data_block].hh); Serial.print(":"); Serial.print(tc_data[target_data_block].mm); Serial.println(); // set the channels current and target brightness bri[0] = tc_data[target_data_block].ch1; bri[1] = tc_data[target_data_block].ch2; bri[2] = tc_data[target_data_block].ch3; bri[3] = tc_data[target_data_block].ch4; if (tc_data[target_data_block-1].ch1 != current_bri[0]) { current_bri[0] = tc_data[target_data_block-1].ch1 + ((tc_data[target_data_block].ch1 == 0) ? 1 : -1); } if (tc_data[target_data_block-1].ch2 != current_bri[1]) { current_bri[1] = tc_data[target_data_block-1].ch2 + ((tc_data[target_data_block].ch2 == 0) ? 1 : -1); } if (tc_data[target_data_block-1].ch3 != current_bri[2]) { current_bri[2] = tc_data[target_data_block-1].ch3 + ((tc_data[target_data_block].ch3 == 0) ? 1 : -1); } if (tc_data[target_data_block-1].ch4 != current_bri[3]) { current_bri[3] = tc_data[target_data_block-1].ch4 + ((tc_data[target_data_block].ch4 == 0) ? 1 : -1); } for (uint8_t i = 0; i < LIGHTS_COUNT; i++) { Serial.println("current_bri[" + (String)i + "] = " + (String)current_bri[i]); } for (uint8_t i = 0; i < LIGHTS_COUNT; i++) { Serial.println("bri[" + (String)i + "] = " + (String)bri[i]); } // enable the lights light_state[0] = true; light_state[1] = true; light_state[2] = true; light_state[3] = true; for (uint8_t i = 0; i < LIGHTS_COUNT; i++) { Serial.println("light_state[" + (String)i + "] = " + (String)light_state[i]); } // set the transition time int t_time = 0; if (target_data_block > 0) { // hours as seconds from now on to the next enabled block t_time = ((uint16_t)tc_data[target_data_block].hh * 60 * 60) - ((uint16_t)hour() * 60 * 60); // add the left over seconds to the next enabled block t_time += ((uint16_t)tc_data[target_data_block].mm * 60) - ((uint16_t)minute() * 60); } transitiontime[0] = t_time; transitiontime[1] = t_time; transitiontime[2] = t_time; transitiontime[3] = t_time; // calculate the step level for (uint8_t i = 0; i < LIGHTS_COUNT; i++) { process_lightdata(i, transitiontime[i]); Serial.println("transitiontime[" + (String)i + "] = " + (String)transitiontime[i]); } for (uint8_t i = 0; i < LIGHTS_COUNT; i++) { Serial.println("step_level[" + (String)i + "] = " + (String)step_level[i]); } } //********************************// void tc_updateTime() { /**/ if (timeClient.update() || millis() > (tc_last_check + TIME_CHECK_INTERVAL_MS)) { tc_last_check = millis(); adjustTimeForDST(); Serial.print("=====\nLocal time: "); Serial.print(hour()); Serial.print(":"); Serial.println(minute()); } /**/ } //********************************// void adjustTimeForDST() { // Get the time and date information time_t now = timeClient.getEpochTime(); struct tm timeinfo; localtime_r(&now, &timeinfo); // set the local time setTime(timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, timeinfo.tm_mday, timeinfo.tm_mon + 1, timeinfo.tm_year + 1900); } //********************************// void tc_readConfig() { for (uint8_t i = 0; i < NUMBER_OF_TIMER_DATA_BLOCKS; i++) { /*Serial.print("Reading from address: "); Serial.print(EEPROM_TIMING_DATA_ADDRESS); Serial.print(" + ("); Serial.print(i); Serial.print(" * "); Serial.print(LENGTH_OF_TIMER_DATA_BLOCK); Serial.print(") + "); Serial.println(TIMER_DATA_ENSTATE);*/ tc_data[i].hh = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i * LENGTH_OF_TIMER_DATA_BLOCK + TIMER_DATA_HH); tc_data[i].mm = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i * LENGTH_OF_TIMER_DATA_BLOCK + TIMER_DATA_MM); tc_data[i].ch1 = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i * LENGTH_OF_TIMER_DATA_BLOCK + TIMER_DATA_CH1); tc_data[i].ch2 = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i * LENGTH_OF_TIMER_DATA_BLOCK + TIMER_DATA_CH2); tc_data[i].ch3 = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i * LENGTH_OF_TIMER_DATA_BLOCK + TIMER_DATA_CH3); tc_data[i].ch4 = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i * LENGTH_OF_TIMER_DATA_BLOCK + TIMER_DATA_CH4); /*Serial.print("data block: "); Serial.print(i); Serial.print(" @ "); Serial.println((EEPROM_TIMING_DATA_ADDRESS + (i * LENGTH_OF_TIMER_DATA_BLOCK) + TIMER_DATA_ENSTATE)); Serial.print(" es: "); Serial.println(tc_data[i].enstate); Serial.print(" hh: "); Serial.println(tc_data[i].hh); Serial.print(" mm: "); Serial.println(tc_data[i].mm); Serial.print(" ch1: "); Serial.println(tc_data[i].ch1); Serial.print(" ch2: "); Serial.println(tc_data[i].ch2); Serial.print(" ch3: "); Serial.println(tc_data[i].ch3); Serial.print(" ch4: "); Serial.println(tc_data[i].ch4);*/ } } //********************************// void tc_write_default() { //Serial.print("-----\nWrite data block starting from address EEPROM_TIMING_DATA_ADDRESS = "); Serial.println(EEPROM_TIMING_DATA_ADDRESS); for (int i = 0; i < NUMBER_OF_TIMER_DATA_BLOCKS * LENGTH_OF_TIMER_DATA_BLOCK; i++) { //Serial.print(EEPROM_TIMING_DATA_ADDRESS + i); Serial.print(" <= "); Serial.print(example_timer_data_block[i]); Serial.print(" <= "); EEPROM.write(EEPROM_TIMING_DATA_ADDRESS + i, example_timer_data_block[i]); EEPROM.commit(); //Serial.println(EEPROM.read(EEPROM_TIMING_DATA_ADDRESS + i)); } //Serial.println("-----"); } //********************************// bool tc_check_no_data_block() { //Serial.print("Check data block address EEPROM_TIMING_DATA_ADDRESS = "); Serial.println(EEPROM_TIMING_DATA_ADDRESS); uint8_t e = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS); //Serial.println(e); if (e > 23) // the maximum value for tis memory section is 23 { return true; } return false; } //********************************// String tc_getJsonData() { String output = "{\"tcdata\":["; for (uint8_t i = 0; i < NUMBER_OF_TIMER_DATA_BLOCKS; i++) { output += "{\"hour\":" + (String)(int)tc_data[i].hh + ","; output += "\"min\":" + (String)(int)tc_data[i].mm + ","; output += "\"ch1\":" + (String)(int)tc_data[i].ch1 + ","; output += "\"ch2\":" + (String)(int)tc_data[i].ch2 + ","; output += "\"ch3\":" + (String)(int)tc_data[i].ch3 + ","; output += "\"ch4\":" + (String)(int)tc_data[i].ch4 + "}"; if (i < NUMBER_OF_TIMER_DATA_BLOCKS-1) { output += ","; } } if (tc_testOngoing == false) { output += "], \"currenttime\":{\"hour\":" + (String)hour() + ",\"min\":" + (String)minute() + "}}"; } else { output += "], \"currenttime\":{\"hour\":16,\"min\":0}}"; } return output; } //********************************// void tc_jsonDataBlocksToEEPROM(String json_data_string) { StaticJsonDocument<512> doc; deserializeJson(doc, json_data_string); // Loop through each data block in the JSON data and store it in the tc_data array for (uint8_t i = 0; i < NUMBER_OF_TIMER_DATA_BLOCKS; i++) { JsonObject obj = doc[i]; // Check and set the limits of the hour value int hour = obj["hour"]; if (hour < 0) { hour = 0; } else if (hour > 23) { hour = 23; } tc_data[i].hh = hour; // Check and set the limits of the minute value int minute = obj["min"]; if (minute < 0) { minute = 0; } else if (minute > 59) { minute = 59; } tc_data[i].mm = minute; // Check and set the limits of the ch1 value int ch1 = obj["ch1"]; if (ch1 < 0) { ch1 = 0; } else if (ch1 > 255) { ch1 = 255; } tc_data[i].ch1 = ch1; // Check and set the limits of the ch2 value int ch2 = obj["ch2"]; if (ch2 < 0) { ch2 = 0; } else if (ch2 > 255) { ch2 = 255; } tc_data[i].ch2 = ch2; // Check and set the limits of the ch3 value int ch3 = obj["ch3"]; if (ch3 < 0) { ch3 = 0; } else if (ch3 > 255) { ch3 = 255; } tc_data[i].ch3 = ch3; // Check and set the limits of the ch4 value int ch4 = obj["ch4"]; if (ch4 < 0) { ch4 = 0; } else if (ch4 > 255) { ch4 = 255; } tc_data[i].ch4 = ch4; } // Write the tc_data array to the EEPROM for (uint16_t i = 0; i < (NUMBER_OF_TIMER_DATA_BLOCKS * LENGTH_OF_TIMER_DATA_BLOCK); i++) { EEPROM.write(EEPROM_TIMING_DATA_ADDRESS + i, *((uint8_t*)&tc_data + i)); } EEPROM.commit(); } //********************************//