#include "esp_system.h" #include "sntp.h" #include "time.h" #include #include #include #include "scheduler.h" #include "scheduler_prefs.h" // Init const and global objects // PREFRENCES Preferences preferences; #define RW_MODE false #define RO_MODE true // WIFI const char* ssid = "/tmp/lab"; const char* password = "bitte2cucung"; const uint8_t wifi_loop_max = 10; // NTP bool sntp_initialized = false; const char* ntpServer1 = "pool.ntp.org"; const char* ntpServer2 = "time.nist.gov"; const long gmtOffset_sec = 2 * 3600; // GMT + 2 const int daylightOffset_sec = 0; // TIMER hw_timer_t*timer_main = NULL; uint32_t timer_interval = 3000000; uint16_t timer_interval_in_secs = timer_interval / 1000000; ; // SCHEDULER bool brun_scheduler = true; uint8_t current_hour = HOUR_DEFAULT; uint8_t current_minute = MINUTE_DEFAULT; uint8_t current_second = 0; uint32_t current_ts = 0; uint32_t next_event_ts = 0; int scheduler_1[24] ; // = {A60,A60,A60,A60,A60,A60,A60,A60,A60,A60,A60,A60,A60,A60,A60,A60,A60,A60,A60,A60,A60,A60,A60,A60}; int scheduler_2[24] ; // = {A00,A00,A00,A00,A00,A00,A00,A00,A00,A00,A00,A00,A00,A00,A00,A00,A00,A00,A00,A00,A00,A00,A00,A00}; int* scheduler_list[] = { scheduler_1, scheduler_2 }; // PINS unsigned int PIN_1 = 12; unsigned int PIN_2 = 14; unsigned int PIN_3 = 27; unsigned int PIN_4 = 26; unsigned int PIN_5 = 20; unsigned int PIN_6 = 33; unsigned int PIN_7 = 32; unsigned int PIN_8 = 35; unsigned int pin_list[2] = { PIN_1, PIN_2 }; // HTTP WiFiClient http_client; WiFiServer http_server(80); String request; // Local functions // Time helper uint32_t get_timestamp( uint8_t hour, uint8_t minute, uint8_t second){ return ( 3600 * hour + 60 * minute + second) % 86400; } bool event_keep_waiting( uint32_t current_ts, uint32_t event_ts ){ // basic case // ts: 11h 41m 11s // ev: 11h 44m 0s // ts < ev => TRUE if ( current_ts < event_ts ){ return true; } // if time looped at midnight // ts: 23h 57m 21s // ev: 0h 1m 0s // ts > ev => TRUE (for high to very low values ) if( (current_ts - event_ts) > 600 && event_ts < 300 ) { return true; } // ts: 11h 44m 11s // ev: 11h 44m 0s // ts > ev => FALSE return false; } // NTP Callback void timeavailable(struct timeval *t) { Serial.println("NTP::Got time adjustment from NTP!"); sntp_initialized = true; return; } // TIMER Callback void IRAM_ATTR onTimer(){ brun_scheduler = true; } void run_scheduler(){ // Serial.println("onTimer::run"); // Get the current time via NTP, or downgrade if ( sntp_initialized ){ struct tm timeinfo; time_t now; time(&now); localtime_r(&now, &timeinfo); current_hour = timeinfo.tm_hour; current_minute = timeinfo.tm_min; current_second = timeinfo.tm_sec; // If no NTP clock }else{ // Serial.println("onTimer::NO NTP"); current_second += timer_interval_in_secs; if(current_second >= 60) { current_second = 0; current_minute += 1; if(current_minute >= 60) { current_minute = 0; current_hour += 1; if(current_hour >= 24) { current_hour = 0; } } } } // If not expected to run exit current_ts = get_timestamp( current_hour, current_minute, current_second ); Serial.printf("onTimer::check event %d %d\n", current_ts, next_event_ts); if( event_keep_waiting( current_ts, next_event_ts ) ){ return; } // Set the next target next_event_ts = get_timestamp( current_hour, current_minute + EVENT_INC_MINUTE, current_second ); Serial.println("Reconfigure the Relays!"); // Run the relays reconfiguration for ( int i = 0; i < 2; i++ ) { // Get a pointer to the current array int* scheduler = scheduler_list[i]; unsigned int pin = pin_list[i]; // Set the expected status uint8_t minutes_by_5 = (current_minute / 5); int hourly_12_values = scheduler[current_hour]; // Serial.printf("Check hour(%d) >> minutes(%d x 5)\n", hourly_12_values, minutes_by_5); char buffer[40]; if (( hourly_12_values >> minutes_by_5 ) & 1) { digitalWrite(pin, HIGH); sprintf (buffer, "Pin %d is up ", pin); } else { digitalWrite(pin, LOW); sprintf (buffer, "Pin %d is down ", pin); } Serial.println(buffer); // Get the expected status } Serial.println("Reconfiguration over"); return; } void setup(){ // HARDWARE Serial.begin(115200); delay(1000); Serial.println("Starting."); pinMode(PIN_1, OUTPUT); pinMode(PIN_2, OUTPUT); // PREFERENCES Serial.println("Setup::PREFERENCES"); preferences.begin(PREF_NAMESPACE, RW_MODE); preferences.clear(); bool pref_init = preferences.isKey("test"); if (pref_init == false) { Serial.println("preferences not exist"); preferences.putBool("test", true); preferences.putBytes(RELAY_1_SCHEDULE, scheduler_1_default, sizeof(scheduler_1_default)); preferences.putBytes(RELAY_2_SCHEDULE, scheduler_2_default, sizeof(scheduler_2_default)); /// ... more to come } bool test = preferences.getBool("test"); preferences.getBytes(RELAY_1_SCHEDULE, scheduler_1, preferences.getBytesLength(RELAY_1_SCHEDULE)); preferences.getBytes(RELAY_2_SCHEDULE, scheduler_2, preferences.getBytesLength(RELAY_2_SCHEDULE)); preferences.end(); Serial.println("Setup::PREFERENCES::end"); // WIFI Serial.println("Setup::WIFI"); Serial.printf("Connecting to %s ", ssid); WiFi.begin(ssid, password); uint8_t wifi_loop_count = 0; while (WiFi.status() != WL_CONNECTED or wifi_loop_count < wifi_loop_max ) { delay(1000); wifi_loop_count++; Serial.print("."); } // TIMER Serial.println("Setup::Timer"); timer_main = timerBegin(0, 80, true); timerAttachInterrupt(timer_main, &onTimer, true); timerAlarmWrite(timer_main, timer_interval, true); timerAlarmEnable(timer_main); // NTP Serial.println("Setup::NTP"); sntp_set_time_sync_notification_cb(timeavailable); configTime(gmtOffset_sec, daylightOffset_sec, ntpServer1, ntpServer2); delay(5000); // SCHEDULER Serial.println("Setup::SCHEDULER"); next_event_ts = get_timestamp( HOUR_DEFAULT, MINUTE_DEFAULT, 10 ); // HTTP Serial.println("Setup::HTTP"); http_server.begin(); Serial.print("Connect to IP Address: "); Serial.print("http://"); Serial.println(WiFi.localIP()); // Todo } void html() { http_client.println("HTTP/1.1 200 OK"); http_client.println("Content-Type: text/html"); http_client.println("Connection: close"); http_client.println(); http_client.println(""); http_client.println(""); http_client.println(""); http_client.println(""); } void loop(){ if( brun_scheduler == true ){ brun_scheduler = false; run_scheduler(); } http_client = http_server.available(); if (!http_client) { return; } while (http_client.connected()) { if (http_client.available()) { char c = http_client.read(); request += c; if (c == '\n') { String postres = http_client.readString(); int indp = postres.indexOf("progo=")+6; Serial.println(postres); Serial.println(request); html(); break; } } } delay(1); request = ""; http_client.stop(); }