[init]
This commit is contained in:
commit
7dbb880056
228
esp32-electrical-switch.ino
Normal file
228
esp32-electrical-switch.ino
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
#include "esp_system.h"
|
||||||
|
#include "sntp.h"
|
||||||
|
#include "time.h"
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <WiFiUdp.h>
|
||||||
|
#include <Preferences.h>
|
||||||
|
#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 = "Wokwi-GUEST";
|
||||||
|
const char* password = "";
|
||||||
|
|
||||||
|
// 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
|
||||||
|
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;
|
||||||
|
uint16_t 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};
|
||||||
|
uint16_t 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};
|
||||||
|
uint16_t* scheduler_list[] = {
|
||||||
|
scheduler_1,
|
||||||
|
scheduler_2
|
||||||
|
};
|
||||||
|
|
||||||
|
// PINS
|
||||||
|
unsigned int PIN_1 = 2;
|
||||||
|
unsigned int PIN_2 = 4;
|
||||||
|
unsigned int pin_list[2] = {
|
||||||
|
PIN_1,
|
||||||
|
PIN_2
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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(){
|
||||||
|
|
||||||
|
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
|
||||||
|
uint16_t* scheduler = scheduler_list[i];
|
||||||
|
unsigned int pin = pin_list[i];
|
||||||
|
// Set the expected status
|
||||||
|
uint8_t minutes_by_5 = (current_minute / 5);
|
||||||
|
uint16_t 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);
|
||||||
|
bool pref_init = preferences.isKey("nvsInit");
|
||||||
|
if (pref_init == false) {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
/* Huh... This crashes wokwi
|
||||||
|
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();
|
||||||
|
|
||||||
|
// WIFI
|
||||||
|
Serial.println("Setup::WIFI");
|
||||||
|
Serial.printf("Connecting to %s ", ssid);
|
||||||
|
WiFi.begin(ssid, password);
|
||||||
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
|
delay(500);
|
||||||
|
Serial.print(".");
|
||||||
|
}
|
||||||
|
Serial.print("Connect to IP Address: ");
|
||||||
|
Serial.print("http://");
|
||||||
|
Serial.println(WiFi.localIP());
|
||||||
|
|
||||||
|
// 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 + EVENT_INC_MINUTE, 0 );
|
||||||
|
|
||||||
|
|
||||||
|
// HTTP
|
||||||
|
Serial.println("Setup::HTTP");
|
||||||
|
// Todo
|
||||||
|
}
|
||||||
|
void loop(){
|
||||||
|
|
||||||
|
Serial.println("Loop::Enter");
|
||||||
|
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
|
||||||
|
nc }
|
83
preferences.ino
Normal file
83
preferences.ino
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#include <Preferences.h>
|
||||||
|
|
||||||
|
// See https://docs.espressif.com/projects/arduino-esp32/en/latest/tutorials/preferences.html
|
||||||
|
Preferences preferences;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
String S1 = "String numéro 1";
|
||||||
|
String S2 = "String numéro 2";
|
||||||
|
String S3 = "String numéro 3";
|
||||||
|
String S4 = "String numéro 4";
|
||||||
|
|
||||||
|
const byte tailleMax = 30;
|
||||||
|
char cs1[tailleMax + 1] = "c-string numéro 1";
|
||||||
|
char cs2[tailleMax + 1] = "c-string numéro 2";
|
||||||
|
char cs3[tailleMax + 1] = "c-string numéro 3";
|
||||||
|
char cs4[tailleMax + 1] = "c-string numéro 4";
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
preferences.begin("my-app", false);
|
||||||
|
|
||||||
|
// on sauve tout
|
||||||
|
preferences.putString("S1", S1);
|
||||||
|
preferences.putString("S2", S2);
|
||||||
|
preferences.putString("S3", S3);
|
||||||
|
preferences.putString("S4", S4);
|
||||||
|
|
||||||
|
preferences.putBytes("cs1", cs1, tailleMax + 1);
|
||||||
|
preferences.putBytes("cs2", cs2, tailleMax + 1);
|
||||||
|
preferences.putBytes("cs3", cs3, tailleMax + 1);
|
||||||
|
preferences.putBytes("cs4", cs4, tailleMax + 1);
|
||||||
|
|
||||||
|
String lectureS1 = "";
|
||||||
|
String lectureS2 = "";
|
||||||
|
String lectureS3 = "";;
|
||||||
|
String lectureS4 = "";
|
||||||
|
|
||||||
|
char lectureCs1[tailleMax + 1] = {};
|
||||||
|
char lectureCs2[tailleMax + 1] = {};
|
||||||
|
char lectureCs3[tailleMax + 1] = {};
|
||||||
|
char lectureCs4[tailleMax + 1] = {};
|
||||||
|
|
||||||
|
|
||||||
|
Serial.println("AVANT LECTURE");
|
||||||
|
Serial.print("lectureS1 = "); Serial.println(lectureS1);
|
||||||
|
Serial.print("lectureS2 = "); Serial.println(lectureS2);
|
||||||
|
Serial.print("lectureS3 = "); Serial.println(lectureS3);
|
||||||
|
Serial.print("lectureS4 = "); Serial.println(lectureS4);
|
||||||
|
|
||||||
|
Serial.print("lectureCs1 = "); Serial.println(lectureCs1);
|
||||||
|
Serial.print("lectureCs2 = "); Serial.println(lectureCs2);
|
||||||
|
Serial.print("lectureCs3 = "); Serial.println(lectureCs3);
|
||||||
|
Serial.print("lectureCs4 = "); Serial.println(lectureCs4);
|
||||||
|
|
||||||
|
// on relit tout
|
||||||
|
|
||||||
|
lectureS1 = preferences.getString("S1", "");
|
||||||
|
lectureS2 = preferences.getString("S2", "");
|
||||||
|
lectureS3 = preferences.getString("S3", "");
|
||||||
|
lectureS4 = preferences.getString("S4", "");
|
||||||
|
|
||||||
|
preferences.getBytes("cs1", lectureCs1, tailleMax + 1);
|
||||||
|
preferences.getBytes("cs2", lectureCs2, tailleMax + 1);
|
||||||
|
preferences.getBytes("cs3", lectureCs3, tailleMax + 1);
|
||||||
|
preferences.getBytes("cs4", lectureCs4, tailleMax + 1);
|
||||||
|
|
||||||
|
Serial.println("\n\nAPRES LECTURE");
|
||||||
|
Serial.print("lectureS1 = "); Serial.println(lectureS1);
|
||||||
|
Serial.print("lectureS2 = "); Serial.println(lectureS2);
|
||||||
|
Serial.print("lectureS3 = "); Serial.println(lectureS3);
|
||||||
|
Serial.print("lectureS4 = "); Serial.println(lectureS4);
|
||||||
|
|
||||||
|
Serial.print("lectureCs1 = "); Serial.println(lectureCs1);
|
||||||
|
Serial.print("lectureCs2 = "); Serial.println(lectureCs2);
|
||||||
|
Serial.print("lectureCs3 = "); Serial.println(lectureCs3);
|
||||||
|
Serial.print("lectureCs4 = "); Serial.println(lectureCs4);
|
||||||
|
|
||||||
|
preferences.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {}
|
68
scheduler.h
Normal file
68
scheduler.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
|
||||||
|
#define A00 0b000000000000
|
||||||
|
#define A60 0b111111111111
|
||||||
|
#define HALF_HOUR 0b000000111111
|
||||||
|
#define EVERY_2 0b010101010101
|
||||||
|
#define EVERY_2_INV 0b101010101010
|
||||||
|
|
||||||
|
#define HOUR_DEFAULT 16
|
||||||
|
#define MINUTE_DEFAULT 41
|
||||||
|
#define EVENT_INC_MINUTE 5
|
||||||
|
|
||||||
|
// our scheduler loop every 24 hour.
|
||||||
|
// one hour is represented by 1 unsigned int
|
||||||
|
// each bit of the hour represent one BI_MINUTE.
|
||||||
|
// the output of the scheduler is ON if one bit is set, OFF otherwise.
|
||||||
|
unsigned int scheduler_1_default[24] = {
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
};
|
||||||
|
unsigned int scheduler_2_default[24] = {
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
EVERY_2,
|
||||||
|
EVERY_2_INV,
|
||||||
|
};
|
||||||
|
|
11
scheduler_prefs.h
Normal file
11
scheduler_prefs.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
const char* PREF_NAMESPACE = "rXsch";
|
||||||
|
const char* RELAY_1_SCHEDULE = "r1sch";
|
||||||
|
const char* RELAY_2_SCHEDULE = "r2sch";
|
||||||
|
const char* RELAY_3_SCHEDULE = "r3sch";
|
||||||
|
const char* RELAY_4_SCHEDULE = "r4sch";
|
||||||
|
const char* RELAY_5_SCHEDULE = "r5sch";
|
||||||
|
const char* RELAY_6_SCHEDULE = "r6sch";
|
||||||
|
const char* RELAY_7_SCHEDULE = "r7sch";
|
||||||
|
const char* RELAY_8_SCHEDULE = "r8sch";
|
||||||
|
|
238
sources/biminute-relay.ino
Normal file
238
sources/biminute-relay.ino
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
#include "esp_system.h"
|
||||||
|
#include "sntp.h"
|
||||||
|
#include "time.h"
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <WiFiUdp.h>
|
||||||
|
#include <Preferences.h>
|
||||||
|
#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 = "Wokwi-GUEST";
|
||||||
|
const char* password = "";
|
||||||
|
|
||||||
|
// NTP
|
||||||
|
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
|
||||||
|
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;
|
||||||
|
uint8_t scheduler_1[24] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
|
||||||
|
uint8_t scheduler_2[24] = {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||||
|
uint8_t* scheduler_list[] = {
|
||||||
|
scheduler_1, scheduler_2
|
||||||
|
};
|
||||||
|
|
||||||
|
// PINS
|
||||||
|
unsigned int PIN_1 = 2;
|
||||||
|
unsigned int PIN_2 = 4;
|
||||||
|
unsigned int pin_list[2] = { PIN_1, PIN_2 };
|
||||||
|
|
||||||
|
// MISC
|
||||||
|
|
||||||
|
char buffer[40];
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
// ts: 11h 44m 11s
|
||||||
|
// ev: 11h 44m 0s
|
||||||
|
// ts > ev => FALSE
|
||||||
|
|
||||||
|
// if time looped at midnight
|
||||||
|
// ts: 23h 57m 21s
|
||||||
|
// ev: 0h 1m 0s => 60
|
||||||
|
// ts > ev => TRUE
|
||||||
|
|
||||||
|
|
||||||
|
// Simple case
|
||||||
|
if ( current_ts < event_ts ){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if( (current_ts - event_ts) > 600 && event_ts < 300 ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// NTP helper
|
||||||
|
void setLocalTime()
|
||||||
|
{
|
||||||
|
struct tm timeinfo;
|
||||||
|
if (!getLocalTime(&timeinfo)){
|
||||||
|
Serial.println("No time available (yet)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
current_hour = timeinfo.tm_hour;
|
||||||
|
current_minute = timeinfo.tm_min;
|
||||||
|
current_second = timeinfo.tm_sec;
|
||||||
|
Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
|
||||||
|
}
|
||||||
|
|
||||||
|
// NTP Callback
|
||||||
|
void timeavailable(struct timeval *t)
|
||||||
|
{
|
||||||
|
Serial.println("Got time adjustment from NTP!");
|
||||||
|
|
||||||
|
setLocalTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TIMER Callback
|
||||||
|
void IRAM_ATTR onTimer(){
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
struct tm timeinfo;
|
||||||
|
// Get the current time via NTP, or downgrade
|
||||||
|
if (getLocalTime(&timeinfo)){
|
||||||
|
Serial.println("onTimer::Got local time");
|
||||||
|
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
|
||||||
|
uint8_t* scheduler = scheduler_list[i];
|
||||||
|
unsigned int pin = pin_list[i];
|
||||||
|
// Set the expected status
|
||||||
|
uint8_t min_fivers = (current_minute / 5);
|
||||||
|
uint8_t hour = scheduler[current_hour];
|
||||||
|
Serial.printf("Check %d >> %d\n", hour, min_fivers);
|
||||||
|
if (( hour >> min_fivers ) & 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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
bool pref_init = preferences.isKey("nvsInit");
|
||||||
|
if (pref_init == false) {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
/* Huh... This crashes wokwi
|
||||||
|
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();
|
||||||
|
|
||||||
|
// WIFI
|
||||||
|
Serial.println("Setup::WIFI");
|
||||||
|
Serial.printf("Connecting to %s ", ssid);
|
||||||
|
WiFi.begin(ssid, password);
|
||||||
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
|
delay(500);
|
||||||
|
Serial.print(".");
|
||||||
|
}
|
||||||
|
Serial.print("Connect to IP Address: ");
|
||||||
|
Serial.print("http://");
|
||||||
|
Serial.println(WiFi.localIP());
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// SCHEDULER
|
||||||
|
Serial.println("Setup::SCHEDULER");
|
||||||
|
next_event_ts = get_timestamp( HOUR_DEFAULT, MINUTE_DEFAULT + EVENT_INC_MINUTE, 0 );
|
||||||
|
|
||||||
|
|
||||||
|
// HTTP
|
||||||
|
Serial.println("Setup::HTTP");
|
||||||
|
// Todo
|
||||||
|
}
|
||||||
|
void loop(){
|
||||||
|
|
||||||
|
Serial.println("Loop::Enter");
|
||||||
|
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
}
|
240
sources/sam-http-server.ino
Normal file
240
sources/sam-http-server.ino
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
/*
|
||||||
|
ESP32 WiFi STA Mode
|
||||||
|
http:://www.electronicwings.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <NTPClient.h>
|
||||||
|
#include <WiFiUdp.h>
|
||||||
|
#include "esp_system.h"
|
||||||
|
|
||||||
|
// For example purpose
|
||||||
|
String formattedDate;
|
||||||
|
|
||||||
|
// Define NTP Client to get time
|
||||||
|
WiFiUDP ntpUDP;
|
||||||
|
NTPClient timeClient(ntpUDP);
|
||||||
|
|
||||||
|
// Timer conf
|
||||||
|
const int wdtTimeout = 30; //time in ms to trigger the watchdog
|
||||||
|
hw_timer_t *timer = NULL;
|
||||||
|
|
||||||
|
// Wifi conf
|
||||||
|
const char* ssid = "Wokwi-GUEST"; /*Enter Your SSID*/
|
||||||
|
const char* password = ""; /*Enter Your Password*/
|
||||||
|
WiFiServer server(80); /* Instance of WiFiServer with port number 80 */
|
||||||
|
String request;
|
||||||
|
|
||||||
|
bool L1 = false;
|
||||||
|
bool L2 = false;
|
||||||
|
bool L3 = false;
|
||||||
|
bool L4 = false;
|
||||||
|
bool L5 = false;
|
||||||
|
bool L6 = false;
|
||||||
|
bool L7 = false;
|
||||||
|
bool L8 = false;
|
||||||
|
|
||||||
|
String programme = "000000000000000000";
|
||||||
|
|
||||||
|
WiFiClient client;
|
||||||
|
|
||||||
|
void callback() {
|
||||||
|
|
||||||
|
Serial.print("Callback... ");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
Serial.print("Connecting to: ");
|
||||||
|
Serial.println(ssid);
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
WiFi.begin(ssid, password);
|
||||||
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
|
Serial.print(".");
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
Serial.print("\n");
|
||||||
|
Serial.print("Connected to Wi-Fi ");
|
||||||
|
Serial.println(WiFi.SSID());
|
||||||
|
delay(1000);
|
||||||
|
server.begin(); /* Start the HTTP web Server */
|
||||||
|
Serial.print("Connect to IP Address: ");
|
||||||
|
Serial.print("http://");
|
||||||
|
Serial.println(WiFi.localIP());
|
||||||
|
|
||||||
|
timeClient.begin();
|
||||||
|
// Set offset time in seconds to adjust for your timezone, for example:
|
||||||
|
timeClient.setTimeOffset(7200);
|
||||||
|
timeClient.update();
|
||||||
|
|
||||||
|
timer = timerBegin(0, 80, true); //timer 0, div 80
|
||||||
|
timerAttachInterrupt(timer, &callback, true); //attach callback
|
||||||
|
timerAlarmWrite(timer, wdtTimeout * 1000, false); //set time in us
|
||||||
|
timerAlarmEnable(timer); //enable interrupt
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void html() {
|
||||||
|
client.println("HTTP/1.1 200 OK");
|
||||||
|
client.println("Content-Type: text/html");
|
||||||
|
client.println("Connection: close");
|
||||||
|
client.println();
|
||||||
|
|
||||||
|
client.println("<!DOCTYPE HTML>");
|
||||||
|
client.println("<html>");
|
||||||
|
|
||||||
|
client.println("<head>");
|
||||||
|
client.println("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
|
||||||
|
client.println("<link rel=\"icon\" href=\"data:,\">");
|
||||||
|
client.println("<style>");
|
||||||
|
client.println("html { font-family: Roboto; display: inline-block; margin: 0px auto; text-align: center;}");
|
||||||
|
client.println(".button {float:left;background-color: #4CAF50; border: none; color: white; padding: 15px 32px; text-align: center; text-decoration: none; display: inline-block; font-size: 16px; margin: 4px 2px; cursor: pointer;");
|
||||||
|
client.println("text-decoration: none; font-size: 25px; margin: 2px; cursor: pointer;}");
|
||||||
|
client.println(".button_ON {background-color: white; color: black; border: 2px solid #4CAF50;}");
|
||||||
|
client.println(".button_OFF {background-color: white; color: black; border: 2px solid #f44336;}");
|
||||||
|
client.println("</style>");
|
||||||
|
client.println("</head>");
|
||||||
|
client.println("<body>");
|
||||||
|
client.println("<h2>Programmation actuelle</h2>");
|
||||||
|
client.println("<h3>"+programme+"</h3>");
|
||||||
|
client.print("<form action=\"/PROG\n\" method=\"post\">");
|
||||||
|
client.print("<label>Modifier Programmation : <input type=\"text\" name=\"progo\" id=\"toto\" value=\"" + programme + "\"/></label>");
|
||||||
|
client.print("<input type=\"submit\" /></form>");
|
||||||
|
client.println("<h2>Prises Programmées</h2>");
|
||||||
|
|
||||||
|
|
||||||
|
if (L1) {
|
||||||
|
client.print("<p><a href=\"/L1\n\"><button class=\"button button_ON\">1 ON</button></a></p>");
|
||||||
|
} else {
|
||||||
|
client.print("<p><a href=\"/L1\n\"><button class=\"button button_OFF\">1 OFF</button></a></p>");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (L2) {
|
||||||
|
client.print("<p><a href=\"/L2\n\"><button class=\"button button_ON\">2 ON</button></a></p>");
|
||||||
|
} else {
|
||||||
|
client.print("<p><a href=\"/L2\n\"><button class=\"button button_OFF\">2 OFF</button></a></p>");
|
||||||
|
}
|
||||||
|
if (L3) {
|
||||||
|
client.print("<p><a href=\"/L3\n\"><button class=\"button button_ON\">3 ON</button></a></p>");
|
||||||
|
} else {
|
||||||
|
client.print("<p><a href=\"/L3\n\"><button class=\"button button_OFF\">3 OFF</button></a></p>");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (L4) {
|
||||||
|
client.print("<p><a href=\"/L4\n\"><button class=\"button button_ON\">4 ON</button></a></p>");
|
||||||
|
} else {
|
||||||
|
client.print("<p><a href=\"/L4\n\"><button class=\"button button_OFF\">4 OFF</button></a></p>");
|
||||||
|
}
|
||||||
|
if (L5) {
|
||||||
|
client.print("<p><a href=\"/L5\n\"><button class=\"button button_ON\">5 ON</button></a></p>");
|
||||||
|
} else {
|
||||||
|
client.print("<p><a href=\"/L5\n\"><button class=\"button button_OFF\">5 OFF</button></a></p>");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (L6) {
|
||||||
|
client.print("<p><a href=\"/L6\n\"><button class=\"button button_ON\">6 ON</button></a></p>");
|
||||||
|
} else {
|
||||||
|
client.print("<p><a href=\"/L6\n\"><button class=\"button button_OFF\">6 OFF</button></a></p>");
|
||||||
|
}
|
||||||
|
if (L7) {
|
||||||
|
client.print("<p><a href=\"/L7\n\"><button class=\"button button_ON\">7 ON</button></a></p>");
|
||||||
|
} else {
|
||||||
|
client.print("<p><a href=\"/L7\n\"><button class=\"button button_OFF\">7 OFF</button></a></p>");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (L8) {
|
||||||
|
client.print("<p><a href=\"/L8\n\"><button class=\"button button_ON\">8 ON</button></a></p>");
|
||||||
|
} else {
|
||||||
|
client.print("<p><a href=\"/L8\n\"><button class=\"button button_OFF\">8 OFF</button></a></p>");
|
||||||
|
}
|
||||||
|
|
||||||
|
client.println("</body>");
|
||||||
|
client.println("</html>");
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
|
||||||
|
formattedDate = timeClient.getFormattedTime();
|
||||||
|
Serial.println(formattedDate);
|
||||||
|
|
||||||
|
timerWrite(timer, 0); //reset timer (feed watchdog)
|
||||||
|
long loopTime = millis();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Extract date
|
||||||
|
int splitT = formattedDate.indexOf("T");
|
||||||
|
dayStamp = formattedDate.substring(0, splitT);
|
||||||
|
Serial.print("DATE: ");
|
||||||
|
Serial.println(dayStamp);
|
||||||
|
// Extract time
|
||||||
|
timeStamp = formattedDate.substring(splitT+1, formattedDate.length()-1);
|
||||||
|
Serial.print("HOUR: ");
|
||||||
|
Serial.println(timeStamp);
|
||||||
|
*/
|
||||||
|
delay(1000);
|
||||||
|
/*
|
||||||
|
client = server.available();
|
||||||
|
if (!client) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (client.connected()) {
|
||||||
|
if (client.available()) {
|
||||||
|
char c = client.read();
|
||||||
|
|
||||||
|
|
||||||
|
request += c;
|
||||||
|
|
||||||
|
if (c == '\n') {
|
||||||
|
String postres = client.readString();
|
||||||
|
int indp = postres.indexOf("progo=")+6;
|
||||||
|
Serial.println(postres);
|
||||||
|
Serial.println(request);
|
||||||
|
|
||||||
|
|
||||||
|
if (request.indexOf("POST /PROG") != -1) {
|
||||||
|
Serial.println("go");
|
||||||
|
programme =postres.substring(indp);
|
||||||
|
}
|
||||||
|
if (request.indexOf("GET /L1") != -1) {
|
||||||
|
L1 = !L1;
|
||||||
|
}
|
||||||
|
if (request.indexOf("GET /L2") != -1) {
|
||||||
|
L2 = !L2;
|
||||||
|
}
|
||||||
|
if (request.indexOf("GET /L3") != -1) {
|
||||||
|
L3 = !L3;
|
||||||
|
}
|
||||||
|
if (request.indexOf("GET /L4") != -1) {
|
||||||
|
L4 = !L4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.indexOf("GET /L5") != -1) {
|
||||||
|
L5 = !L5;
|
||||||
|
}
|
||||||
|
if (request.indexOf("GET /L6") != -1) {
|
||||||
|
L6 = !L6;
|
||||||
|
}
|
||||||
|
if (request.indexOf("GET /L7") != -1) {
|
||||||
|
L7 = !L7;
|
||||||
|
}
|
||||||
|
if (request.indexOf("GET /L8") != -1) {
|
||||||
|
L8 = !L8;
|
||||||
|
}
|
||||||
|
|
||||||
|
html();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(1);
|
||||||
|
request = "";
|
||||||
|
client.stop();
|
||||||
|
*/
|
||||||
|
}
|
56
sources/sntp.ino
Normal file
56
sources/sntp.ino
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include "esp_system.h"
|
||||||
|
#include "sntp.h"
|
||||||
|
#include "time.h"
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <WiFiUdp.h>
|
||||||
|
|
||||||
|
const char* ssid = "Wokwi-GUEST";
|
||||||
|
const char* password = "";
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
void printLocalTime()
|
||||||
|
{
|
||||||
|
struct tm timeinfo;
|
||||||
|
if (!getLocalTime(&timeinfo)){
|
||||||
|
Serial.println("No time available (yet)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback function (get's called when time adjusts via NTP)
|
||||||
|
void timeavailable(struct timeval *t)
|
||||||
|
{
|
||||||
|
Serial.println("Got time adjustment from NTP!");
|
||||||
|
printLocalTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
// set notification call-back function
|
||||||
|
sntp_set_time_sync_notification_cb(timeavailable);
|
||||||
|
|
||||||
|
// This will set configured NTP servers and the new GMT and daylight offsets for IST.
|
||||||
|
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer1, ntpServer2);
|
||||||
|
|
||||||
|
// Connect to WiFi
|
||||||
|
Serial.printf("Connecting to %s ", ssid);
|
||||||
|
WiFi.begin(ssid, password);
|
||||||
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
|
delay(500);
|
||||||
|
Serial.print(".");
|
||||||
|
}
|
||||||
|
Serial.println(" CONNECTED");
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
delay(5000);
|
||||||
|
printLocalTime(); // it will take some time to sync time :)
|
||||||
|
}
|
33
sources/timer-interrupts.ino
Normal file
33
sources/timer-interrupts.ino
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#define LED1 12
|
||||||
|
#define LED2 14
|
||||||
|
hw_timer_t*My_timer1 = NULL;
|
||||||
|
hw_timer_t*My_timer2 = NULL;
|
||||||
|
int ledState1 = 0;
|
||||||
|
int ledState2 = 0;
|
||||||
|
|
||||||
|
void IRAM_ATTR onTimer1(){
|
||||||
|
ledState1 =! ledState1;
|
||||||
|
digitalWrite(LED1, ledState1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRAM_ATTR onTimer2(){
|
||||||
|
ledState2 =! ledState2;
|
||||||
|
digitalWrite(LED2, ledState2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
pinMode(LED1, OUTPUT);
|
||||||
|
My_timer1 = timerBegin(0, 80, true);
|
||||||
|
timerAttachInterrupt(My_timer1, &onTimer1, true);
|
||||||
|
timerAlarmWrite(My_timer1, 1000000, true);
|
||||||
|
timerAlarmEnable(My_timer1);
|
||||||
|
pinMode(LED2, OUTPUT);
|
||||||
|
My_timer2 = timerBegin(1, 200, true);
|
||||||
|
timerAttachInterrupt(My_timer2, &onTimer2, true);
|
||||||
|
timerAlarmWrite(My_timer2, 1000000, true);
|
||||||
|
timerAlarmEnable(My_timer2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
//do nothing
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user