diff --git a/docs/source/Hardware/Hardware.rst b/docs/source/Hardware/Hardware.rst index 1b290f245a..7b979cca05 100644 --- a/docs/source/Hardware/Hardware.rst +++ b/docs/source/Hardware/Hardware.rst @@ -101,3 +101,52 @@ If the board supports PSRAM, it hides GPIO-26 (GPIO-26 is missing from the range, as it can not be used if PSRAM is present) Overview of the GPIO pin mapping of ESP32-S2 (link to Espressif documentation): `ESP32-S2 Saola1 `_ + +-------------------- +GPIO wake from sleep +-------------------- + +.. note:: + This feature is only available on ESP32 devices. + +Supported GPIO pins can be selected to wake the unit from deep sleep. +For ESP32 devices with EXT1 wake-up support, the internal RTC-Resistors can be disabled globally and it applies to **all** selected pins. +The signal level (HIGH or LOW) is configured globally and applies to **all** selected pins. +GPIO wake-up on newer devices supports per-pin trigger level configuration, but this comes at the cost of higher power consumption. +**TODO:** Integrate per-pin trigger level selection for GPIO wake-up. + +When the unit wakes up from deep sleep, an event is generated with the GPIO number that caused the wakeup. +``"EVENT: System#GPIOWake=X"``, where ``X`` is the GPIO number. + +Make sure to add a pull-up or pull-down resistor to the selected GPIO pin(s) when needed, to avoid false wakeups. +(some GPIO pins have internal pull-up or pull-down resistors, but not all of them, and the internal pull-up/down may not be sufficient for stable operation in all cases) +For **GPIO Wake-up** all internal pull-up/down resistors should work. No need to add them anywhere as this is done automatically. + +.. note:: + + Depending on the ESP32 variant, two different wake-up mechanisms are used. + + **EXT1 Wake-up (RTC)** + + If ``SOC_PM_SUPPORT_EXT1_WAKEUP`` is available, EXT1 wake-up is used (e.g. ESP32 classic, ESP32-S2, ESP32-S3, ESP32-C6, ESP32-H2): + + - Only works on RTC-capable pins + - Very low power (RTC domain) + + **GPIO Wake-up** + + On platforms without EXT1 support (e.g. ESP32-C3), GPIO wake-up is used: + + - Works on more pins (not RTC-limited) + - Slightly higher power usage (HP domain) + + **Summary** + + - EXT1: preferred, low power + - GPIO wake-up: fallback for newer chips, more flexible but less efficient + + The firmware automatically selects the correct method at compile time. + +.. warning:: + When using this feature, be aware that if you are also using a GPIO in rules (e.g., Monitor,GPIO,8) or in a Plugin Task (P001), you might get an event at wakeup if the button is pressed slightly too long, which can cause unexpected behavior. + If this is unwanted, take precautions such as monitoring the GPIO a bit later after boot (e.g., with a timer), or disabling the corresponding task and enabling it later after boot (e.g., with a timer) to avoid this. \ No newline at end of file diff --git a/docs/source/Plugin/P000_events.repl b/docs/source/Plugin/P000_events.repl index b23bac7025..eeb19706a8 100644 --- a/docs/source/Plugin/P000_events.repl +++ b/docs/source/Plugin/P000_events.repl @@ -70,6 +70,30 @@ GPIO,15,1 endon + " + " + ``System#BootCause`` + Added: 2026-03-29 + Triggered at boot time. + "," + + .. code-block:: none + + on System#BootCause do + LogEntry,'Bootcause: %eventvalue1%' + endon + + Possible bootcauses can be: + + * 0: Manual Reboot + * 1: Cold Boot + * 2: Deep Sleep + * 3: Soft Reboot + * 10: External Watchdog + * 11: SW Watchdog + * 12: Exception + * 20: PWR Unstable + " " ``System#BootMode`` @@ -104,6 +128,19 @@ See 'Boot Strapping Pins' documentation for the boot strapping pins for all ESP32-series chips. + " + " + ``System#GPIOWake`` + Added: 2026-03-29 + Triggered at boot time. + "," + + .. code-block:: none + + on System#GPIOWake do + LogEntry,'GPIO that caused the wakeup: %eventvalue1%' + endon + " " ``System#Boot`` diff --git a/src/_Plugin_Helper.cpp b/src/_Plugin_Helper.cpp index 5c720cc649..a6582230a8 100644 --- a/src/_Plugin_Helper.cpp +++ b/src/_Plugin_Helper.cpp @@ -12,9 +12,12 @@ #include "src/Helpers/Misc.h" #include "src/Helpers/StringParser.h" +#if FEATURE_PIN_WAKEUP +# include "driver/rtc_io.h" +#endif -PluginTaskData_base *Plugin_task_data[TASKS_MAX] = {}; +PluginTaskData_base *Plugin_task_data[TASKS_MAX] = {}; String PCONFIG_LABEL(int n) { if (n < PLUGIN_CONFIGVAR_MAX) { @@ -47,9 +50,9 @@ bool initPluginTaskData(taskIndex_t taskIndex, PluginTaskData_base *data) { } // 2nd heap may have been active to allocate the PluginTaskData, but here we need to keep the default heap active - # ifdef USE_SECOND_HEAP + #ifdef USE_SECOND_HEAP HeapSelectDram ephemeral; - # endif // ifdef USE_SECOND_HEAP + #endif // ifdef USE_SECOND_HEAP clearPluginTaskData(taskIndex); @@ -61,16 +64,18 @@ bool initPluginTaskData(taskIndex_t taskIndex, PluginTaskData_base *data) { #if FEATURE_PLUGIN_STATS const uint8_t valueCount = getValueCountForTask(taskIndex); + for (size_t i = 0; i < valueCount; ++i) { if (Cache.enabledPluginStats(taskIndex, i)) { Plugin_task_data[taskIndex]->initPluginStats(i); } } - #endif + #endif // if FEATURE_PLUGIN_STATS #if FEATURE_PLUGIN_FILTER - // TODO TD-er: Implement init - #endif + // TODO TD-er: Implement init + + #endif // if FEATURE_PLUGIN_FILTER } else { delete data; @@ -81,7 +86,7 @@ bool initPluginTaskData(taskIndex_t taskIndex, PluginTaskData_base *data) { PluginTaskData_base* getPluginTaskData(taskIndex_t taskIndex) { if (pluginTaskData_initialized(taskIndex)) { - + if (!Plugin_task_data[taskIndex]->baseClassOnly()) { return Plugin_task_data[taskIndex]; } @@ -96,7 +101,6 @@ PluginTaskData_base* getPluginTaskDataBaseClassOnly(taskIndex_t taskIndex) { return nullptr; } - bool pluginTaskData_initialized(taskIndex_t taskIndex) { if (!validTaskIndex(taskIndex)) { return false; @@ -105,29 +109,24 @@ bool pluginTaskData_initialized(taskIndex_t taskIndex) { (Plugin_task_data[taskIndex]->_taskdata_pluginID == Settings.getPluginID_for_task(taskIndex)); } -String getPluginCustomArgName(int varNr) { - return getPluginCustomArgName(F("pc_arg"), varNr); -} +String getPluginCustomArgName(int varNr) { return getPluginCustomArgName(F("pc_arg"), varNr); } -String getPluginCustomArgName(const __FlashStringHelper * label, int varNr) { - return concat(label, varNr + 1); -} +String getPluginCustomArgName(const __FlashStringHelper *label, int varNr) { return concat(label, varNr + 1); } -int getFormItemIntCustomArgName(int varNr) { - return getFormItemInt(getPluginCustomArgName(varNr)); -} +int getFormItemIntCustomArgName(int varNr) { return getFormItemInt(getPluginCustomArgName(varNr)); } // Helper function to create formatted custom values for display in the devices overview page. // When called from PLUGIN_WEBFORM_SHOW_VALUES, the last item should add a traling div_br class // if the regular values should also be displayed. // The call to PLUGIN_WEBFORM_SHOW_VALUES should only return success = true when no regular values should be displayed // Note that the varNr of the custom values should not conflict with the existing variable numbers (e.g. start at VARS_PER_TASK) -void pluginWebformShowValue(taskIndex_t taskIndex, uint8_t varNr, const __FlashStringHelper * label, const String& value, bool addTrailingBreak) { +void pluginWebformShowValue(taskIndex_t taskIndex, uint8_t varNr, const __FlashStringHelper *label, const String& value, + bool addTrailingBreak) { pluginWebformShowValue(taskIndex, varNr, String(label), value, addTrailingBreak); } void pluginWebformShowValue(taskIndex_t taskIndex, - uint8_t varNr, + uint8_t varNr, const String& label, const String& value, bool addTrailingBreak) { @@ -175,11 +174,12 @@ bool pluginOptionalTaskIndexArgumentMatch(taskIndex_t taskIndex, const String& s return found_taskIndex == taskIndex; } -bool pluginWebformShowGPIOdescription(taskIndex_t taskIndex, - const __FlashStringHelper * newline, - String& description) +bool pluginWebformShowGPIOdescription(taskIndex_t taskIndex, + const __FlashStringHelper *newline, + String & description) { struct EventStruct TempEvent(taskIndex); + TempEvent.String1 = newline; return PluginCall(PLUGIN_WEBFORM_SHOW_GPIO_DESCR, &TempEvent, description); } @@ -199,6 +199,7 @@ int checkDeviceVTypeForTask(struct EventStruct *event) { String dummy; event->idx = -1; + if (PluginCall(PLUGIN_GET_DEVICEVTYPE, event, dummy)) { return event->idx; // pconfig_index } @@ -206,3 +207,90 @@ int checkDeviceVTypeForTask(struct EventStruct *event) { } return -1; } + +#if FEATURE_PIN_WAKEUP + +void setupGpioWakeup(uint64_t ext1_mask) { + + // disable wakeup completely if nothin is selected + if (ext1_mask == 0) { + #if FEATURE_PIN_WAKEUP == 1 + esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_EXT1); + #elif FEATURE_PIN_WAKEUP == 2 + esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_GPIO); + #endif + return; + } + +#if FEATURE_PIN_WAKEUP == 1 + // --- EXT1 Wakeup (supported on classic ESP32/S2/S3) --- + esp_sleep_ext1_wakeup_mode_t new_mode; + + if (Settings.wakeOnHigh()) { + new_mode = ESP_EXT1_WAKEUP_ANY_HIGH; + } else { + #if CONFIG_IDF_TARGET_ESP32 + new_mode = ESP_EXT1_WAKEUP_ALL_LOW; + #else + new_mode = ESP_EXT1_WAKEUP_ANY_LOW; + #endif + } + + // Configure pull-ups/pull-downs for all pins in the mask + for (int gpio = 0; gpio < 64; ++gpio) { + if (bitRead(ext1_mask, gpio)) { + gpio_num_t rtc_gpio = static_cast(gpio); + + if (!Settings.getWakePulls()) { + if (!Settings.wakeOnHigh()) { + rtc_gpio_pullup_en(rtc_gpio); + rtc_gpio_pulldown_dis(rtc_gpio); + } else { + rtc_gpio_pullup_dis(rtc_gpio); + rtc_gpio_pulldown_en(rtc_gpio); + } + } + else { + rtc_gpio_pullup_dis(rtc_gpio); + rtc_gpio_pulldown_dis(rtc_gpio); + } + } + } + + + esp_sleep_enable_ext1_wakeup_io(ext1_mask, new_mode); + +#elif FEATURE_PIN_WAKEUP == 2 + // --- GPIO-based wakeup for chips without EXT1 (e.g. ESP32-C3) --- + esp_deepsleep_gpio_wake_up_mode_t gpio_mode = + Settings.wakeOnHigh() ? ESP_GPIO_WAKEUP_GPIO_HIGH : ESP_GPIO_WAKEUP_GPIO_LOW; + + esp_deep_sleep_enable_gpio_wakeup(ext1_mask, gpio_mode); + +#endif +} + +int8_t getWakeupGPIO() { + esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); + +#if FEATURE_PIN_WAKEUP == 1 + if (cause != ESP_SLEEP_WAKEUP_EXT1) { + return -1; + } + uint64_t wakeMask = esp_sleep_get_ext1_wakeup_status(); +#else + if (cause != ESP_SLEEP_WAKEUP_GPIO) { + return -1; + } + uint64_t wakeMask = esp_sleep_get_gpio_wakeup_status(); +#endif + + if (wakeMask == 0) { + return -1; + } + + // Return first active GPIO + return __builtin_ctzll(wakeMask); +} + +#endif // if FEATURE_PIN_WAKEUP diff --git a/src/_Plugin_Helper.h b/src/_Plugin_Helper.h index 9848ab0ed0..6024512dcd 100644 --- a/src/_Plugin_Helper.h +++ b/src/_Plugin_Helper.h @@ -168,4 +168,9 @@ int getValueCountForTask(taskIndex_t taskIndex); // Return pconfig_index int checkDeviceVTypeForTask(struct EventStruct *event); +#if FEATURE_PIN_WAKEUP +void setupGpioWakeup(uint64_t ext1_mask); +int8_t getWakeupGPIO(); +#endif // if FEATURE_PIN_WAKEUP + #endif // PLUGIN_HELPER_H diff --git a/src/src/CustomBuild/define_plugin_sets.h b/src/src/CustomBuild/define_plugin_sets.h index 04748d003d..b89ee3478a 100644 --- a/src/src/CustomBuild/define_plugin_sets.h +++ b/src/src/CustomBuild/define_plugin_sets.h @@ -4557,3 +4557,12 @@ To create/register a plugin, you have to : #endif // if !FEATURE_SPI && !FEATURE_I2C && !FEATURE_MODBUS && !FEATURE_CAN && !FEATURE_WRMBUS && !FEATURE_WIMBUS #endif // CUSTOMBUILD_DEFINE_PLUGIN_SETS_H + +#if defined(ESP32) +#if SOC_PM_SUPPORT_EXT1_WAKEUP +#define FEATURE_PIN_WAKEUP 1 +#else // if no EXT1_WAKEUP support, we can use GPIO wakeup + // (TODO: -add per-pin trigger level control for GPIO wakeup) +#define FEATURE_PIN_WAKEUP 2 +#endif +#endif diff --git a/src/src/DataStructs/SettingsStruct.h b/src/src/DataStructs/SettingsStruct.h index 6be8e31fc4..f60c8c8f63 100644 --- a/src/src/DataStructs/SettingsStruct.h +++ b/src/src/DataStructs/SettingsStruct.h @@ -371,12 +371,23 @@ class SettingsStruct_tmpl , int8_t& index_high #endif ) const; - + public: PinBootState getPinBootState(int8_t gpio_pin) const; void setPinBootState(int8_t gpio_pin, PinBootState state); +#if FEATURE_PIN_WAKEUP + // --- Wake GPIO mask handling --- + uint64_t getWakeGpioMask() const; + void setWakeGpioMask(uint64_t mask); + + inline bool wakeOnHigh() { return VariousBits_3.wakeOnHigh_ckd; } + inline void setWakeOnHigh(bool value) { VariousBits_3.wakeOnHigh_ckd = value; } + inline bool getWakePulls() { return VariousBits_3.disableWakePulls; } + inline void setWakePulls(bool value) { VariousBits_3.disableWakePulls = value; } +#endif // if FEATURE_PIN_WAKEUP + #if FEATURE_SPI bool getSPI_pinsForTask(taskIndex_t TaskIndex, int8_t spi_gpios[3], @@ -607,7 +618,10 @@ class SettingsStruct_tmpl int8_t SPI1_SCLK_pin = -1; int8_t SPI1_MISO_pin = -1; int8_t SPI1_MOSI_pin = -1; - unsigned int OLD_TaskDeviceID[N_TASKS - 8] = {0}; // UNUSED: this can be reused + uint32_t wakePin_bitmask_lLo = 0; + uint32_t wakePin_bitmask_lHi = 0; + + unsigned int OLD_TaskDeviceID[N_TASKS - 10] = {0}; // UNUSED: this can be reused // FIXME TD-er: When used on ESP8266, this conversion union may not work // It might work as it is 32-bit in size. diff --git a/src/src/DataStructs_templ/SettingsStruct.cpp b/src/src/DataStructs_templ/SettingsStruct.cpp index a071f76d4f..38e1e742a5 100644 --- a/src/src/DataStructs_templ/SettingsStruct.cpp +++ b/src/src/DataStructs_templ/SettingsStruct.cpp @@ -987,6 +987,22 @@ void SettingsStruct_tmpl::setPinBootState(int8_t gpio_pin, PinBootState # endif // ifdef ESP32 } +# if FEATURE_PIN_WAKEUP + +template +uint64_t SettingsStruct_tmpl::getWakeGpioMask() const { + return (static_cast(wakePin_bitmask_lHi) << 32) | + wakePin_bitmask_lLo; +} + +template +void SettingsStruct_tmpl::setWakeGpioMask(uint64_t mask) { + wakePin_bitmask_lLo = static_cast(mask & 0xFFFFFFFFULL); + wakePin_bitmask_lHi = static_cast(mask >> 32); +} + +#endif + #if FEATURE_SPI template bool SettingsStruct_tmpl::isSPI_enabled(uint8_t spi_bus) const { diff --git a/src/src/ESPEasyCore/ESPEasy_setup.cpp b/src/src/ESPEasyCore/ESPEasy_setup.cpp index 5fdbec68f7..317753a0d6 100644 --- a/src/src/ESPEasyCore/ESPEasy_setup.cpp +++ b/src/src/ESPEasyCore/ESPEasy_setup.cpp @@ -561,6 +561,13 @@ void ESPEasy_setup() String event = F("System#Wake"); rulesProcessing(event); // TD-er: Process events in the setup() now. } + + if (Settings.UseRules) + { + String event = F("System#BootCause="); + event += lastBootCause; + rulesProcessing(event); // TD-er: Process events in the setup() now. + } #ifdef ESP32 if (Settings.UseRules) @@ -588,6 +595,21 @@ void ESPEasy_setup() event += bitRead(gpio_strap, 5); rulesProcessing(event); } + + # if FEATURE_PIN_WAKEUP + if (Settings.UseRules) + { + int8_t wakePin = getWakeupGPIO(); + + if (wakePin >= 0) { + String event = F("System#GPIOWake="); + event += wakePin; + rulesProcessing(event); + } + setupGpioWakeup(Settings.getWakeGpioMask()); + } + # endif // if FEATURE_PIN_WAKEUP + #endif // ifdef ESP32 #if FEATURE_REPORTING diff --git a/src/src/Helpers/ESPEasy_checks.cpp b/src/src/Helpers/ESPEasy_checks.cpp index 07a7e6fe5d..b9b9e709b8 100644 --- a/src/src/Helpers/ESPEasy_checks.cpp +++ b/src/src/Helpers/ESPEasy_checks.cpp @@ -178,7 +178,7 @@ void run_compiletime_checks() { static_assert(198u == offsetof(SettingsStruct, TaskDeviceNumber), "NOTIFICATION_MAX has changed?"); // All settings related to N_TASKS - static_assert((232 + TASKS_MAX) == offsetof(SettingsStruct, OLD_TaskDeviceID), ""); // 32-bit alignment, so offset of 2 bytes. + static_assert((240 + TASKS_MAX) == offsetof(SettingsStruct, OLD_TaskDeviceID), ""); // 32-bit alignment, so offset of 2 bytes. static_assert((200 + (67 * TASKS_MAX)) == offsetof(SettingsStruct, ControllerEnabled), ""); // Used to compute true offset. diff --git a/src/src/WebServer/HardwarePage.cpp b/src/src/WebServer/HardwarePage.cpp index cc7ce1f0a9..4f6c7cfac7 100644 --- a/src/src/WebServer/HardwarePage.cpp +++ b/src/src/WebServer/HardwarePage.cpp @@ -21,6 +21,10 @@ //#include "../Helpers/StringConverter.h" #include "../Helpers/StringGenerator_GPIO.h" +# ifdef FEATURE_PIN_WAKEUP +#include "../../_Plugin_Helper.h" +#include "driver/rtc_io.h" +# endif // ******************************************************************************** // Web Interface hardware page @@ -63,6 +67,25 @@ void handle_hardware() { } ++gpio; } + + # if FEATURE_PIN_WAKEUP + gpio = 0; + uint64_t wakeGpioMask = 0; + Settings.setWakeOnHigh(isFormItemChecked(F("WoHi"))); // Wake on HIGH or LOW + #if FEATURE_PIN_WAKEUP == 1 + Settings.setWakePulls(isFormItemChecked(F("WakePulls"))); // disable internal pulls for wakeup pins + #endif + while (gpio <= MAX_GPIO) { + if (esp_sleep_is_valid_wakeup_gpio((gpio_num_t)gpio)) { + String checkboxId = strformat(F("WoL%d"), gpio); + bitWrite(wakeGpioMask, gpio, isFormItemChecked(checkboxId)); + } + ++gpio; + } + Settings.setWakeGpioMask(wakeGpioMask); // save the bitmask + setupGpioWakeup(wakeGpioMask); //attach gpios for wakeup + # endif // if FEATURE_PIN_WAKEUP + error += SaveSettings(); addHtmlError(error); } @@ -112,10 +135,41 @@ void handle_hardware() { #endif // if FEATURE_SD addFormSubHeader(F("GPIO boot states")); - + bool expandBootStates{}; + int gpio = 0; + while (!expandBootStates && gpio <= MAX_GPIO) { + expandBootStates = Settings.getPinBootState(gpio) != PinBootState::Default_state; + ++gpio; + } + addFormDetailsStart(expandBootStates); + for (int gpio = 0; gpio <= MAX_GPIO; ++gpio) { addFormPinStateSelect(gpio, static_cast(Settings.getPinBootState(gpio))); } + addFormDetailsEnd(); + + # if FEATURE_PIN_WAKEUP + #if FEATURE_PIN_WAKEUP == 1 + addFormSubHeader(F("EXT1 Wake-up Pins")); + #else + addFormSubHeader(F("GPIO Wake-up")); + #endif + addFormDetailsStart(Settings.getWakeGpioMask() != 0); + #if FEATURE_PIN_WAKEUP == 1 + addFormCheckBox(F("Disable internal pulls"), F("WakePulls"), Settings.getWakePulls()); + #endif + addFormCheckBox(F("Wake on HIGH"), F("WoHi"), Settings.wakeOnHigh()); + #if FEATURE_PIN_WAKEUP == 1 + addFormNote(F("(default: Wake on LOW) Add an external Pull-Resistor if needed!")); + #else + addFormNote(F("(default: Wake on LOW) No external pull-up/down resistors are needed")); + #endif + for (int gpio = 0; gpio <= MAX_GPIO; ++gpio) { + addFormPinWakeSelect(gpio, Settings.getWakeGpioMask()); + } + addFormDetailsEnd(); + # endif // if FEATURE_PIN_WAKEUP + addFormSeparator(2); html_TR_TD(); diff --git a/src/src/WebServer/Markup_Forms.cpp b/src/src/WebServer/Markup_Forms.cpp index 524085b3dc..bc2b17de05 100644 --- a/src/src/WebServer/Markup_Forms.cpp +++ b/src/src/WebServer/Markup_Forms.cpp @@ -638,6 +638,22 @@ void addFormPinStateSelect(int gpio, int choice) } } +// ******************************************************************************** +// Add a GPIO wake select list +// ******************************************************************************** +# if FEATURE_PIN_WAKEUP +void addFormPinWakeSelect(int gpio, uint64_t wakeGpioMask){ + if (esp_sleep_is_valid_wakeup_gpio((gpio_num_t)gpio)) { + // Check if this GPIO is part of the wake mask + bool checked = bitRead(wakeGpioMask, gpio); + String checkboxId = strformat(F("WoL%d"), gpio); + String label = strformat(F("Wake from GPIO-%d"), gpio); + + addFormCheckBox(label, checkboxId, checked); + } + } +# endif + // ******************************************************************************** // Retrieve return values from form/checkbox. // ******************************************************************************** diff --git a/src/src/WebServer/Markup_Forms.h b/src/src/WebServer/Markup_Forms.h index 72e84f22de..83f47a03ac 100644 --- a/src/src/WebServer/Markup_Forms.h +++ b/src/src/WebServer/Markup_Forms.h @@ -307,6 +307,13 @@ void addFormSelector_YesNo(const __FlashStringHelper * label, void addFormPinStateSelect(int gpio, int choice); +// ******************************************************************************** +// Add a GPIO wake select list +// ******************************************************************************** +# if FEATURE_PIN_WAKEUP +void addFormPinWakeSelect(int gpio, uint64_t wakeGpioMask); +# endif // if FEATURE_PIN_WAKEUP + // ******************************************************************************** // Retrieve return values from form/checkbox. // ******************************************************************************** diff --git a/static/espeasy.js b/static/espeasy.js index d7a9b6822c..ff6c2092f6 100644 --- a/static/espeasy.js +++ b/static/espeasy.js @@ -12,10 +12,10 @@ var commonCommands = ["AccessInfo", "Background", "Build", "ClearAccessBlock", " "UdpPort", "UdpTest", "Unit", "UseNTP", "WdConfig", "WdRead", "WiFi", "WiFiAllowAP", "WiFiAPMode", "WiFiConnect", "WiFiDisconnect", "WiFiKey", "WiFiKey2", "WiFiMode", "WiFiScan", "WiFiSSID", "WiFiSSID2", "WiFiSTAMode", "Event", "AsyncEvent", - "GPIO", "GPIOToggle", "LongPulse", "LongPulse_mS", "Monitor", "Pulse", "PWM", "Servo", "Status", "Tone", "RTTTL", "UnMonitor", + "GPIO", "GPIOToggle", "LongPulse", "LongPulse_mS", "Monitor", "Monitor,GPIO", "Pulse", "PWM", "Servo", "Status", "Tone", "RTTTL", "UnMonitor", "UnMonitor,GPIO", "Provision", "Provision,Config", "Provision,Security", "Provision,Notification", "Provision,Provision", "Provision,Rules", "Provision,CustomCdnUrl", "Provision,Firmware"]; var commonEvents = ["Clock#Time", "Login#Failed", "MQTT#Connected", "MQTT#Disconnected", "MQTTimport#Connected", "MQTTimport#Disconnected", "Rules#Timer", "System#Boot", - "System#BootMode", "System#Sleep", "System#Wake", "TaskExit#", "TaskInit#", "ThingspeakReply", "Time#Initialized", "Time#Set", "WiFi#APmodeDisabled", "WiFi#APmodeEnabled", + "System#BootMode", "System#BootCause", "System#GPIOWake", "System#Sleep", "System#Wake", "TaskExit#", "TaskInit#", "ThingspeakReply", "Time#Initialized", "Time#Set", "WiFi#APmodeDisabled", "WiFi#APmodeEnabled", "WiFi#ChangedAccesspoint", "WiFi#ChangedWiFichannel", "WiFi#Connected", "WiFi#Disconnected"]; var commonPlugins = [ //P003