From b082d14c5917d0e1f2f208f2cda54dca7e67d231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xose=20P=C3=A9rez?= Date: Fri, 19 Jan 2018 11:34:14 +0100 Subject: [PATCH] Loop hooks --- code/espurna/alexa.ino | 3 + code/espurna/button.ino | 3 + code/espurna/config/sensors.h | 3 +- code/espurna/espurna.ino | 110 +++++++++----------------------- code/espurna/hardware.ino | 47 -------------- code/espurna/i2c.ino | 8 +++ code/espurna/ir.ino | 5 ++ code/espurna/led.ino | 4 ++ code/espurna/light.ino | 3 - code/espurna/mdns.ino | 7 ++ code/espurna/mqtt.ino | 3 + code/espurna/nofuss.ino | 3 + code/espurna/ntp.ino | 3 + code/espurna/ota.ino | 3 + code/espurna/relay.ino | 2 + code/espurna/rf.ino | 3 + code/espurna/rfbridge.ino | 3 + code/espurna/scheduler.ino | 3 + code/espurna/sensor.ino | 3 + code/espurna/settings.ino | 3 + code/espurna/ssdp.ino | 3 + code/espurna/system.ino | 116 ++++++++++++++++++++++++++++++++++ code/espurna/thinkspeak.ino | 7 ++ code/espurna/utils.ino | 44 ------------- code/espurna/wifi.ino | 3 + 25 files changed, 220 insertions(+), 175 deletions(-) delete mode 100644 code/espurna/hardware.ino create mode 100644 code/espurna/system.ino diff --git a/code/espurna/alexa.ino b/code/espurna/alexa.ino index 48a26c26..ee9a375f 100644 --- a/code/espurna/alexa.ino +++ b/code/espurna/alexa.ino @@ -68,6 +68,9 @@ void alexaSetup() { return relayStatus(device_id); }); + // Register loop + espurnaRegisterLoop(alexaLoop); + } void alexaLoop() { diff --git a/code/espurna/button.ino b/code/espurna/button.ino index e12f3119..101183c1 100644 --- a/code/espurna/button.ino +++ b/code/espurna/button.ino @@ -184,6 +184,9 @@ void buttonSetup() { DEBUG_MSG_P(PSTR("[BUTTON] Number of buttons: %u\n"), _buttons.size()); + // Register loop + espurnaRegisterLoop(buttonLoop); + } void buttonLoop() { diff --git a/code/espurna/config/sensors.h b/code/espurna/config/sensors.h index 5844f2e9..beac93f0 100644 --- a/code/espurna/config/sensors.h +++ b/code/espurna/config/sensors.h @@ -474,7 +474,8 @@ #define I2C_CLOCK_STRETCH_TIME 200 // BRZO clock stretch time #define I2C_SCL_FREQUENCY 1000 // BRZO SCL frequency -#define I2C_CLEAR_BUS 0 // Clear I2C bus at boot +#define I2C_CLEAR_BUS 0 // Clear I2C bus on boot +#define I2C_PERFORM_SCAN 1 // Perform a bus scan on boot //-------------------------------------------------------------------------------- // Internal power monitor diff --git a/code/espurna/espurna.ino b/code/espurna/espurna.ino index a6d278a3..24244b4b 100644 --- a/code/espurna/espurna.ino +++ b/code/espurna/espurna.ino @@ -20,10 +20,17 @@ along with this program. If not, see . */ #include "config/all.h" +#include +std::vector _loop_callbacks; + +// ----------------------------------------------------------------------------- +// REGISTER // ----------------------------------------------------------------------------- -unsigned long _loopDelay = 0; +void espurnaRegisterLoop(void (*callback)()) { + _loop_callbacks.push_back(callback); +} // ----------------------------------------------------------------------------- // BOOTING @@ -31,13 +38,8 @@ unsigned long _loopDelay = 0; void setup() { - // Init EEPROM, Serial and SPIFFS - hardwareSetup(); - - // Question system stability - #if SYSTEM_CHECK_ENABLED - systemCheck(false); - #endif + // Init EEPROM, Serial, SPIFFS and system check + systemSetup(); // Init persistance and terminal features settingsSetup(); @@ -46,24 +48,31 @@ void setup() { } setBoardName(); - // Cache loop delay value to speed things (recommended max 250ms) - _loopDelay = atol(getSetting("loopDelay", LOOP_DELAY_TIME).c_str()); - // Show welcome message and system configuration info(); + // ------------------------------------------------------------------------- // Basic modules, will always run + // ------------------------------------------------------------------------- + wifiSetup(); otaSetup(); #if TELNET_SUPPORT telnetSetup(); #endif - // Do not run the next services if system is flagged stable + // ------------------------------------------------------------------------- + // Check if system is stable + // ------------------------------------------------------------------------- + #if SYSTEM_CHECK_ENABLED if (!systemCheck()) return; #endif + // ------------------------------------------------------------------------- + // Next modules will be only loaded if system is flagged as stable + // ------------------------------------------------------------------------- + // Init webserver required before any module that uses API #if WEB_SUPPORT webSetup(); @@ -71,19 +80,23 @@ void setup() { apiSetup(); #endif + // lightSetup must be called before relaySetup #if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE lightSetup(); #endif + relaySetup(); buttonSetup(); ledSetup(); #if MQTT_SUPPORT mqttSetup(); #endif - #if MDNS_SERVER_SUPPORT mdnsServerSetup(); #endif + #if MDNS_CLIENT_SUPPORT + mdnsClientSetup(); + #endif #if LLMNR_SUPPORT llmnrSetup(); #endif @@ -98,12 +111,7 @@ void setup() { #endif #if I2C_SUPPORT i2cSetup(); - #if I2C_CLEAR_BUS - i2cClearBus(); - #endif - i2cScan(); #endif - #ifdef ITEAD_SONOFF_RFBRIDGE rfbSetup(); #endif @@ -152,67 +160,9 @@ void setup() { void loop() { - hardwareLoop(); - settingsLoop(); - wifiLoop(); - otaLoop(); - - #if SYSTEM_CHECK_ENABLED - systemCheckLoop(); - // Do not run the next services if system is flagged stable - if (!systemCheck()) return; - #endif - - #if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE - lightLoop(); - #endif - relayLoop(); - buttonLoop(); - ledLoop(); - #if MQTT_SUPPORT - mqttLoop(); - #endif - - #ifdef ITEAD_SONOFF_RFBRIDGE - rfbLoop(); - #endif - #if SSDP_SUPPORT - ssdpLoop(); - #endif - #if NTP_SUPPORT - ntpLoop(); - #endif - #if ALEXA_SUPPORT - alexaLoop(); - #endif - #if NOFUSS_SUPPORT - nofussLoop(); - #endif - #if RF_SUPPORT - rfLoop(); - #endif - #if IR_SUPPORT - irLoop(); - #endif - #if SENSOR_SUPPORT - sensorLoop(); - #endif - #if THINGSPEAK_SUPPORT - tspkLoop(); - #endif - #if SCHEDULER_SUPPORT - schLoop(); - #endif - #if MDNS_CLIENT_SUPPORT - mdnsClientLoop(); - #endif - - // 3rd party code hook - #if USE_EXTRA - extraLoop(); - #endif - - // Power saving delay - delay(_loopDelay); + // Call registered loop callbacks + for (unsigned char i = 0; i < _loop_callbacks.size(); i++) { + (_loop_callbacks[i])(); + } } diff --git a/code/espurna/hardware.ino b/code/espurna/hardware.ino deleted file mode 100644 index b5e534e7..00000000 --- a/code/espurna/hardware.ino +++ /dev/null @@ -1,47 +0,0 @@ -/* - -HARDWARE MODULE - -Copyright (C) 2018 by Xose Pérez - -*/ - -#include - -void hardwareSetup() { - - EEPROM.begin(EEPROM_SIZE); - - #if DEBUG_SERIAL_SUPPORT - DEBUG_PORT.begin(SERIAL_BAUDRATE); - #if DEBUG_ESP_WIFI - DEBUG_PORT.setDebugOutput(true); - #endif - #elif defined(SERIAL_BAUDRATE) - Serial.begin(SERIAL_BAUDRATE); - #endif - - #if SPIFFS_SUPPORT - SPIFFS.begin(); - #endif - - #if defined(ESPLIVE) - //The ESPLive has an ADC MUX which needs to be configured. - pinMode(16, OUTPUT); - digitalWrite(16, HIGH); //Defualt CT input (pin B, solder jumper B) - #endif - -} - -void hardwareLoop() { - - // Heartbeat - #if HEARTBEAT_ENABLED - static unsigned long last = 0; - if ((last == 0) || (millis() - last > HEARTBEAT_INTERVAL)) { - last = millis(); - heartbeat(); - } - #endif // HEARTBEAT_ENABLED - -} diff --git a/code/espurna/i2c.ino b/code/espurna/i2c.ino index 9c396fe9..712fc209 100644 --- a/code/espurna/i2c.ino +++ b/code/espurna/i2c.ino @@ -196,6 +196,14 @@ void i2cSetup() { DEBUG_MSG_P(PSTR("[I2C] Using GPIO%u for SDA and GPIO%u for SCL\n"), sda, scl); + #if I2C_CLEAR_BUS + i2cClearBus(); + #endif + + #if I2C_PERFORM_SCAN + i2cScan(); + #endif + } #endif diff --git a/code/espurna/ir.ino b/code/espurna/ir.ino index 13d23f15..ae951baf 100644 --- a/code/espurna/ir.ino +++ b/code/espurna/ir.ino @@ -92,8 +92,13 @@ void _irProcessCode(unsigned long code) { // ----------------------------------------------------------------------------- void irSetup() { + _ir_recv = new IRrecv(IR_PIN); _ir_recv->enableIRIn(); + + // Register loop + espurnaRegisterLoop(irLoop); + } void irLoop() { diff --git a/code/espurna/led.ino b/code/espurna/led.ino index 86e1dbf6..412212f9 100644 --- a/code/espurna/led.ino +++ b/code/espurna/led.ino @@ -167,6 +167,10 @@ void ledSetup() { DEBUG_MSG_P(PSTR("[LED] Number of leds: %d\n"), _leds.size()); + // Register loop + espurnaRegisterLoop(ledLoop); + + } void ledLoop() { diff --git a/code/espurna/light.ino b/code/espurna/light.ino index 131c2ca7..eb05913b 100644 --- a/code/espurna/light.ino +++ b/code/espurna/light.ino @@ -1041,7 +1041,4 @@ void lightSetup() { } -void lightLoop(){ -} - #endif // LIGHT_PROVIDER != LIGHT_PROVIDER_NONE diff --git a/code/espurna/mdns.ino b/code/espurna/mdns.ino index 24f14c8f..c82f328a 100644 --- a/code/espurna/mdns.ino +++ b/code/espurna/mdns.ino @@ -118,6 +118,13 @@ String mdnsResolve(String name) { return mdnsResolve((char *) name.c_str()); } +void mdnsClientSetup() { + + // Register loop + espurnaRegisterLoop(mdnsClientLoop); + +} + void mdnsClientLoop() { _mdns_resolver.loop(); } diff --git a/code/espurna/mqtt.ino b/code/espurna/mqtt.ino index 7ffbaa0c..a69f2da0 100644 --- a/code/espurna/mqtt.ino +++ b/code/espurna/mqtt.ino @@ -729,6 +729,9 @@ void mqttSetup() { _mqttInitCommands(); #endif + // Register loop + espurnaRegisterLoop(mqttLoop); + } void mqttLoop() { diff --git a/code/espurna/nofuss.ino b/code/espurna/nofuss.ino index dd1db595..ddeba808 100644 --- a/code/espurna/nofuss.ino +++ b/code/espurna/nofuss.ino @@ -153,6 +153,9 @@ void nofussSetup() { _nofussInitCommands(); #endif + // Register loop + espurnaRegisterLoop(nofussLoop); + } void nofussLoop() { diff --git a/code/espurna/ntp.ino b/code/espurna/ntp.ino index 97d7d39c..4332b434 100644 --- a/code/espurna/ntp.ino +++ b/code/espurna/ntp.ino @@ -94,6 +94,9 @@ void ntpSetup() { wsOnAfterParseRegister(_ntpConfigure); #endif + // Register loop + espurnaRegisterLoop(ntpLoop); + } void ntpLoop() { diff --git a/code/espurna/ota.ino b/code/espurna/ota.ino index d1aad3ad..61886ebe 100644 --- a/code/espurna/ota.ino +++ b/code/espurna/ota.ino @@ -61,6 +61,9 @@ void otaSetup() { ArduinoOTA.begin(); + // Register loop + espurnaRegisterLoop(otaLoop); + } void otaLoop() { diff --git a/code/espurna/relay.ino b/code/espurna/relay.ino index 0a1c51bd..0a500b62 100644 --- a/code/espurna/relay.ino +++ b/code/espurna/relay.ino @@ -728,6 +728,8 @@ void relaySetup() { _relayBoot(); relayLoop(); + espurnaRegisterLoop(relayLoop); + #if WEB_SUPPORT relaySetupAPI(); relaySetupWS(); diff --git a/code/espurna/rf.ino b/code/espurna/rf.ino index 34597b4c..3ae60a70 100644 --- a/code/espurna/rf.ino +++ b/code/espurna/rf.ino @@ -101,6 +101,9 @@ void rfSetup() { wsOnAfterParseRegister(_rfBuildCodes); #endif + // Register loop + espurnaRegisterLoop(rfLoop); + } #endif diff --git a/code/espurna/rfbridge.ino b/code/espurna/rfbridge.ino index c96e646d..f90fb14f 100644 --- a/code/espurna/rfbridge.ino +++ b/code/espurna/rfbridge.ino @@ -505,6 +505,9 @@ void rfbSetup() { wsOnActionRegister(_rfbWebSocketOnAction); #endif + // Register oop + espurnaRegisterLoop(rfbLoop); + } void rfbLoop() { diff --git a/code/espurna/scheduler.ino b/code/espurna/scheduler.ino index 8ff8a17d..5f551ce0 100644 --- a/code/espurna/scheduler.ino +++ b/code/espurna/scheduler.ino @@ -116,6 +116,9 @@ void schSetup() { wsOnAfterParseRegister(_schConfigure); #endif + // Register loop + espurnaRegisterLoop(schLoop); + } void schLoop() { diff --git a/code/espurna/sensor.ino b/code/espurna/sensor.ino index c3b2e7ea..fd617a2c 100644 --- a/code/espurna/sensor.ino +++ b/code/espurna/sensor.ino @@ -619,6 +619,9 @@ void sensorSetup() { _sensorInitCommands(); #endif + // Register loop + espurnaRegisterLoop(sensorLoop); + } void sensorLoop() { diff --git a/code/espurna/settings.ino b/code/espurna/settings.ino index a56e7650..51e44352 100644 --- a/code/espurna/settings.ino +++ b/code/espurna/settings.ino @@ -416,6 +416,9 @@ void settingsSetup() { #endif #endif + // Register loop + espurnaRegisterLoop(settingsLoop); + } void settingsLoop() { diff --git a/code/espurna/ssdp.ino b/code/espurna/ssdp.ino index 87f7df86..80f2817e 100644 --- a/code/espurna/ssdp.ino +++ b/code/espurna/ssdp.ino @@ -31,6 +31,9 @@ void ssdpSetup() { }); #endif + // Register loop + espurnaRegisterLoop(ssdpLoop); + } void ssdpLoop() { diff --git a/code/espurna/system.ino b/code/espurna/system.ino new file mode 100644 index 00000000..8f21c75e --- /dev/null +++ b/code/espurna/system.ino @@ -0,0 +1,116 @@ +/* + +SYSTEM MODULE + +Copyright (C) 2018 by Xose Pérez + +*/ + +#include + +// ----------------------------------------------------------------------------- + +unsigned long _loopDelay = 0; + +// ----------------------------------------------------------------------------- + +#if SYSTEM_CHECK_ENABLED + +// Call this method on boot with start=true to increase the crash counter +// Call it again once the system is stable to decrease the counter +// If the counter reaches SYSTEM_CHECK_MAX then the system is flagged as unstable +// setting _systemOK = false; +// +// An unstable system will only have serial access, WiFi in AP mode and OTA + +bool _systemStable = true; + +void systemCheck(bool stable) { + unsigned char value = EEPROM.read(EEPROM_CRASH_COUNTER); + if (stable) { + value = 0; + DEBUG_MSG_P(PSTR("[MAIN] System OK\n")); + } else { + if (++value > SYSTEM_CHECK_MAX) { + _systemStable = false; + value = 0; + DEBUG_MSG_P(PSTR("[MAIN] System UNSTABLE\n")); + } + } + EEPROM.write(EEPROM_CRASH_COUNTER, value); + EEPROM.commit(); +} + +bool systemCheck() { + return _systemStable; +} + +void systemCheckLoop() { + static bool checked = false; + if (!checked && (millis() > SYSTEM_CHECK_TIME)) { + // Check system as stable + systemCheck(true); + checked = true; + } +} + +#endif + +// ----------------------------------------------------------------------------- + +void systemLoop() { + + // Check system stability + #if SYSTEM_CHECK_ENABLED + systemCheckLoop(); + #endif + + #if HEARTBEAT_ENABLED + // Heartbeat + static unsigned long last = 0; + if ((last == 0) || (millis() - last > HEARTBEAT_INTERVAL)) { + last = millis(); + heartbeat(); + } + #endif // HEARTBEAT_ENABLED + + // Power saving delay + delay(_loopDelay); + +} + +void systemSetup() { + + EEPROM.begin(EEPROM_SIZE); + + #if DEBUG_SERIAL_SUPPORT + DEBUG_PORT.begin(SERIAL_BAUDRATE); + #if DEBUG_ESP_WIFI + DEBUG_PORT.setDebugOutput(true); + #endif + #elif defined(SERIAL_BAUDRATE) + Serial.begin(SERIAL_BAUDRATE); + #endif + + #if SPIFFS_SUPPORT + SPIFFS.begin(); + #endif + + // Question system stability + #if SYSTEM_CHECK_ENABLED + systemCheck(false); + #endif + + #if defined(ESPLIVE) + //The ESPLive has an ADC MUX which needs to be configured. + pinMode(16, OUTPUT); + digitalWrite(16, HIGH); //Defualt CT input (pin B, solder jumper B) + #endif + + // Cache loop delay value to speed things (recommended max 250ms) + _loopDelay = atol(getSetting("loopDelay", LOOP_DELAY_TIME).c_str()); + + // Register Loop + espurnaRegisterLoop(systemLoop); + +} diff --git a/code/espurna/thinkspeak.ino b/code/espurna/thinkspeak.ino index 294ed76f..ca3c1aa8 100644 --- a/code/espurna/thinkspeak.ino +++ b/code/espurna/thinkspeak.ino @@ -242,15 +242,22 @@ bool tspkEnabled() { } void tspkSetup() { + _tspkConfigure(); + #if WEB_SUPPORT wsOnSendRegister(_tspkWebSocketOnSend); wsOnAfterParseRegister(_tspkConfigure); #endif + DEBUG_MSG_P(PSTR("[THINGSPEAK] Async %s, SSL %s\n"), THINGSPEAK_USE_ASYNC ? "ENABLED" : "DISABLED", THINGSPEAK_USE_SSL ? "ENABLED" : "DISABLED" ); + + // Register loop + espurnaRegisterLoop(tspkLoop); + } void tspkLoop() { diff --git a/code/espurna/utils.ino b/code/espurna/utils.ino index bcfb8137..99a1ca20 100644 --- a/code/espurna/utils.ino +++ b/code/espurna/utils.ino @@ -489,50 +489,6 @@ void deferredReset(unsigned long delay, unsigned char reason) { // ----------------------------------------------------------------------------- -#if SYSTEM_CHECK_ENABLED - -// Call this method on boot with start=true to increase the crash counter -// Call it again once the system is stable to decrease the counter -// If the counter reaches SYSTEM_CHECK_MAX then the system is flagged as unstable -// setting _systemOK = false; -// -// An unstable system will only have serial access, WiFi in AP mode and OTA - -bool _systemStable = true; - -void systemCheck(bool stable) { - unsigned char value = EEPROM.read(EEPROM_CRASH_COUNTER); - if (stable) { - value = 0; - DEBUG_MSG_P(PSTR("[MAIN] System OK\n")); - } else { - if (++value > SYSTEM_CHECK_MAX) { - _systemStable = false; - value = 0; - DEBUG_MSG_P(PSTR("[MAIN] System UNSTABLE\n")); - } - } - EEPROM.write(EEPROM_CRASH_COUNTER, value); - EEPROM.commit(); -} - -bool systemCheck() { - return _systemStable; -} - -void systemCheckLoop() { - static bool checked = false; - if (!checked && (millis() > SYSTEM_CHECK_TIME)) { - // Check system as stable - systemCheck(true); - checked = true; - } -} - -#endif - -// ----------------------------------------------------------------------------- - char * ltrim(char * s) { char *p = s; while ((unsigned char) *p == ' ') ++p; diff --git a/code/espurna/wifi.ino b/code/espurna/wifi.ino index bd5773c2..4c0c0266 100644 --- a/code/espurna/wifi.ino +++ b/code/espurna/wifi.ino @@ -447,6 +447,9 @@ void wifiSetup() { _wifiInitCommands(); #endif + // Register loop + espurnaRegisterLoop(wifiLoop); + } void wifiLoop() {