From 0f3a808e9e47c4a8d5ea02a2dd3f24557990095f Mon Sep 17 00:00:00 2001 From: Lukas Bachschwell Date: Mon, 30 May 2022 21:35:15 +0200 Subject: [PATCH 01/11] Bump version Signed-off-by: Lukas Bachschwell --- library.json | 2 +- library.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.json b/library.json index 8125983..51d0841 100644 --- a/library.json +++ b/library.json @@ -31,7 +31,7 @@ "frameworks": "arduino" } ], - "version": "2.1.0", + "version": "2.1.1", "frameworks": "arduino", "platforms": "*" } diff --git a/library.properties b/library.properties index a4d1139..b38bbc3 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ESPUI -version=2.1.0 +version=2.1.1 author=Lukas Bachschwell maintainer=Lukas Bachschwell sentence=ESP32 and ESP8266 Web Interface Library From 7056cdf0442d971aed4bc3b47d263d29cd53c0b5 Mon Sep 17 00:00:00 2001 From: Lukas Bachschwell Date: Tue, 31 May 2022 08:27:11 +0200 Subject: [PATCH 02/11] Update keywords to max 50 chars Signed-off-by: Lukas Bachschwell --- library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.json b/library.json index 51d0841..3d89a96 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "ESPUI", - "keywords": "espressif web interface iot control simple easy ui userinterface", + "keywords": "espressif web interface iot easy ui", "description": "ESP32 and ESP8266 Web Interface Library", "repository": { "type": "git", From 9cb962122c0965b88fe81a16fe1ca4ca6a026e56 Mon Sep 17 00:00:00 2001 From: Martin Mueller Date: Fri, 10 Jun 2022 12:44:53 -0400 Subject: [PATCH 03/11] Reworked removeControl function --- src/ESPUI.cpp | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/src/ESPUI.cpp b/src/ESPUI.cpp index a32196e..0525775 100644 --- a/src/ESPUI.cpp +++ b/src/ESPUI.cpp @@ -628,38 +628,30 @@ uint16_t ESPUIClass::addControl(ControlType type, const char* label, const Strin bool ESPUIClass::removeControl(uint16_t id, bool force_reload_ui) { - if (nullptr == this->controls) - return false; + Control* PreviousControl = nullptr; + Control* CurrentControl = this->controls; - Control* it = this->controls; - - if (id == it->id) + while(nullptr != CurrentControl) { - this->controls = it->next; - delete it; - this->controlCount--; - if (force_reload_ui) + if (id == CurrentControl->id) { - jsonReload(); + break; + } + PreviousControl = CurrentControl; + CurrentControl = CurrentControl->next; + } + + if (nullptr != CurrentControl) + { + if(nullptr == PreviousControl) + { + this->controls = CurrentControl->next; } else { - jsonDom(0); + PreviousControl->next = CurrentControl->next; } - return true; - } - - Control* it_next = it->next; - while (nullptr != it_next && id != it_next->id) - { - it = it_next; - it_next = it_next->next; - } - - if (nullptr != it_next) - { - it->next = it_next->next; - delete it_next; + delete CurrentControl; this->controlCount--; if (force_reload_ui) { From 02e847a31edba9bcea956ae7d55925359a0f5d4e Mon Sep 17 00:00:00 2001 From: Martin Mueller Date: Sat, 11 Jun 2022 00:42:25 -0400 Subject: [PATCH 04/11] First part of extending callback to include a user parm. Converted addControl to no longer use C Style function definitions. Now using C++ function overload to support multiple invocation modes. --- src/ESPUI.cpp | 90 +++++++++++++++++++++++++++++++++++++-------------- src/ESPUI.h | 27 ++++++++++++---- 2 files changed, 86 insertions(+), 31 deletions(-) diff --git a/src/ESPUI.cpp b/src/ESPUI.cpp index 0525775..065da77 100644 --- a/src/ESPUI.cpp +++ b/src/ESPUI.cpp @@ -475,9 +475,9 @@ void onWsEvent( return; } - if (c->callback == nullptr) + if (false == c->HasCallback()) { - #if defined(DEBUG_ESPUI) +#if defined(DEBUG_ESPUI) if (ESPUI.verbosity) { Serial.print(F("No callback found for ID ")); @@ -490,97 +490,97 @@ void onWsEvent( if (msg.startsWith(F("bdown:"))) { - c->callback(c, B_DOWN); + c->SendCallback(B_DOWN); } else if (msg.startsWith(F("bup:"))) { - c->callback(c, B_UP); + c->SendCallback(B_UP); } else if (msg.startsWith(F("pfdown:"))) { - c->callback(c, P_FOR_DOWN); + c->SendCallback(P_FOR_DOWN); } else if (msg.startsWith(F("pfup:"))) { - c->callback(c, P_FOR_UP); + c->SendCallback(P_FOR_UP); } else if (msg.startsWith(F("pldown:"))) { - c->callback(c, P_LEFT_DOWN); + c->SendCallback(P_LEFT_DOWN); } else if (msg.startsWith(F("plup:"))) { - c->callback(c, P_LEFT_UP); + c->SendCallback(P_LEFT_UP); } else if (msg.startsWith(F("prdown:"))) { - c->callback(c, P_RIGHT_DOWN); + c->SendCallback(P_RIGHT_DOWN); } else if (msg.startsWith(F("prup:"))) { - c->callback(c, P_RIGHT_UP); + c->SendCallback(P_RIGHT_UP); } else if (msg.startsWith(F("pbdown:"))) { - c->callback(c, P_BACK_DOWN); + c->SendCallback(P_BACK_DOWN); } else if (msg.startsWith(F("pbup:"))) { - c->callback(c, P_BACK_UP); + c->SendCallback(P_BACK_UP); } else if (msg.startsWith(F("pcdown:"))) { - c->callback(c, P_CENTER_DOWN); + c->SendCallback(P_CENTER_DOWN); } else if (msg.startsWith(F("pcup:"))) { - c->callback(c, P_CENTER_UP); + c->SendCallback(P_CENTER_UP); } else if (msg.startsWith(F("sactive:"))) { c->value = "1"; ESPUI.updateControl(c, client->id()); - c->callback(c, S_ACTIVE); + c->SendCallback(S_ACTIVE); } else if (msg.startsWith(F("sinactive:"))) { c->value = "0"; ESPUI.updateControl(c, client->id()); - c->callback(c, S_INACTIVE); + c->SendCallback(S_INACTIVE); } else if (msg.startsWith(F("slvalue:"))) { c->value = msg.substring(msg.indexOf(':') + 1, msg.lastIndexOf(':')); ESPUI.updateControl(c, client->id()); - c->callback(c, SL_VALUE); + c->SendCallback(SL_VALUE); } else if (msg.startsWith(F("nvalue:"))) { c->value = msg.substring(msg.indexOf(':') + 1, msg.lastIndexOf(':')); ESPUI.updateControl(c, client->id()); - c->callback(c, N_VALUE); + c->SendCallback(N_VALUE); } else if (msg.startsWith(F("tvalue:"))) { c->value = msg.substring(msg.indexOf(':') + 1, msg.lastIndexOf(':')); ESPUI.updateControl(c, client->id()); - c->callback(c, T_VALUE); + c->SendCallback(T_VALUE); } else if (msg.startsWith("tabvalue:")) { - c->callback(c, client->id()); + c->SendCallback(client->id()); } else if (msg.startsWith(F("svalue:"))) { c->value = msg.substring(msg.indexOf(':') + 1, msg.lastIndexOf(':')); ESPUI.updateControl(c, client->id()); - c->callback(c, S_VALUE); + c->SendCallback(S_VALUE); } else if (msg.startsWith(F("time:"))) { c->value = msg.substring(msg.indexOf(':') + 1, msg.lastIndexOf(':')); ESPUI.updateControl(c, client->id()); - c->callback(c, TM_VALUE); + c->SendCallback(TM_VALUE); } else { @@ -600,10 +600,37 @@ void onWsEvent( } } -uint16_t ESPUIClass::addControl(ControlType type, const char* label, const String& value, ControlColor color, - uint16_t parentControl, void (*callback)(Control*, int)) +uint16_t ESPUIClass::addControl(ControlType type, const char* label) { - Control* control = new Control(type, label, callback, value, color, true, parentControl); + return addControl(type, label, String("")); +} + +uint16_t ESPUIClass::addControl(ControlType type, const char* label, const String& value) +{ + return addControl(type, label, value, ControlColor::Turquoise); +} + +uint16_t ESPUIClass::addControl(ControlType type, const char* label, const String& value, ControlColor color) +{ + return addControl(type, label, value, color, Control::noParent); +} + +uint16_t ESPUIClass::addControl(ControlType type, const char* label, const String& value, ControlColor color, uint16_t parentControl) +{ + return addControl(type, label, value, color, parentControl, nullptr); +} + +uint16_t ESPUIClass::addControl(ControlType type, const char* label, const String& value, ControlColor color, uint16_t parentControl, void (*callback)(Control*, int)) +{ + uint16_t id = addControl(type, label, value, color, parentControl, nullptr, nullptr); + // set the original style callback + getControl(id)->callback = callback; + return id; +} + +uint16_t ESPUIClass::addControl(ControlType type, const char* label, const String& value, ControlColor color, uint16_t parentControl, void (*callback)(Control*, int, void *), void * UserData) +{ + Control* control = new Control(type, label, callback, UserData, value, color, true, parentControl); if (this->controls == nullptr) { @@ -1443,4 +1470,17 @@ void ESPUIClass::setVerbosity(Verbosity v) this->verbosity = v; } +void Control::SendCallback(int type) +{ + if(callback) + { + callback(this, type); + } + + if (extendedCallback) + { + extendedCallback(this, type, user); + } +} + ESPUIClass ESPUI; diff --git a/src/ESPUI.h b/src/ESPUI.h index a8bbcc3..c6daba6 100644 --- a/src/ESPUI.h +++ b/src/ESPUI.h @@ -137,6 +137,8 @@ public: uint16_t id; // just mirroring the id here for practical reasons const char* label; void (*callback)(Control*, int); + void (*extendedCallback)(Control*, int, void*); + void* user; String value; ControlColor color; bool visible; @@ -151,11 +153,16 @@ public: static constexpr uint16_t noParent = 0xffff; - Control(ControlType type, const char* label, void (*callback)(Control*, int), const String& value, - ControlColor color, bool visible = true, uint16_t parentControl = Control::noParent) + Control( + ControlType type, + const char* label, + void (*callback)(Control*, int, void*), + void* UserData, const String& value, ControlColor color, bool visible, uint16_t parentControl) : type(type), label(label), - callback(callback), + callback(nullptr), + extendedCallback(callback), + user(UserData), value(value), color(color), visible(visible), @@ -173,12 +180,16 @@ public: id(control.id), label(control.label), callback(control.callback), + extendedCallback(control.extendedCallback), + user(control.user), value(control.value), color(control.color), visible(control.visible), parentControl(control.parentControl), next(control.next) { } + void SendCallback(int type); + bool HasCallback() { return ((nullptr != callback) || (nullptr != extendedCallback)); } private: static uint16_t idCounter; @@ -241,9 +252,13 @@ public: // stuff into LITTLEFS void list(); // Lists LITTLEFS directory - uint16_t addControl(ControlType type, const char* label, const String& value = String(""), - ControlColor color = ControlColor::Turquoise, uint16_t parentControl = Control::noParent, - void (*callback)(Control*, int) = nullptr); + uint16_t addControl(ControlType type, const char* label); + uint16_t addControl(ControlType type, const char* label, const String& value); + uint16_t addControl(ControlType type, const char* label, const String& value, ControlColor color); + uint16_t addControl(ControlType type, const char* label, const String& value, ControlColor color, uint16_t parentControl); + uint16_t addControl(ControlType type, const char* label, const String& value, ControlColor color, uint16_t parentControl, void (*callback)(Control*, int)); + uint16_t addControl(ControlType type, const char* label, const String& value, ControlColor color, uint16_t parentControl, void (*callback)(Control*, int, void *), void* UserData); + bool removeControl(uint16_t id, bool force_reload_ui = false); // create Elements From 1419b2dec0a25d27e808cf29423334fcdcb63259 Mon Sep 17 00:00:00 2001 From: Martin Mueller Date: Sat, 11 Jun 2022 01:20:25 -0400 Subject: [PATCH 05/11] Updated the rest of the callback functions to support the new UserData parameter --- src/ESPUI.cpp | 55 +++++++++++++++++++++++++++++++++++++++++++++------ src/ESPUI.h | 42 +++++++++++++++++++++------------------ 2 files changed, 72 insertions(+), 25 deletions(-) diff --git a/src/ESPUI.cpp b/src/ESPUI.cpp index 065da77..bacd91f 100644 --- a/src/ESPUI.cpp +++ b/src/ESPUI.cpp @@ -704,10 +704,16 @@ uint16_t ESPUIClass::graph(const char* label, ControlColor color) return addControl(ControlType::Graph, label, "", color); } -uint16_t ESPUIClass::slider( - const char* label, void (*callback)(Control*, int), ControlColor color, int value, int min, int max) +uint16_t ESPUIClass::slider(const char* label, void (*callback)(Control*, int), ControlColor color, int value, int min, int max) { - uint16_t sliderId = addControl(ControlType::Slider, label, String(value), color, Control::noParent, callback); + uint16_t id = slider(label, nullptr, color, value, min, max, nullptr); + getControl(id)->callback = callback; + return id; +} + +uint16_t ESPUIClass::slider(const char* label, void (*callback)(Control*, int, void*), ControlColor color, int value, int min, int max, void* userData) +{ + uint16_t sliderId = addControl(ControlType::Slider, label, String(value), color, Control::noParent, callback, userData); addControl(ControlType::Min, label, String(min), ControlColor::None, sliderId); addControl(ControlType::Max, label, String(max), ControlColor::None, sliderId); @@ -719,22 +725,42 @@ uint16_t ESPUIClass::button(const char* label, void (*callback)(Control*, int), return addControl(ControlType::Button, label, value, color, Control::noParent, callback); } +uint16_t ESPUIClass::button(const char* label, void (*callback)(Control*, int, void*), ControlColor color, const String& value, void* UserData) +{ + return addControl(ControlType::Button, label, value, color, Control::noParent, callback, UserData); +} + uint16_t ESPUIClass::switcher(const char* label, void (*callback)(Control*, int), ControlColor color, bool startState) { return addControl(ControlType::Switcher, label, startState ? "1" : "0", color, Control::noParent, callback); } +uint16_t ESPUIClass::switcher(const char* label, void (*callback)(Control*, int, void*), ControlColor color, bool startState, void* UserData) +{ + return addControl(ControlType::Switcher, label, startState ? "1" : "0", color, Control::noParent, callback, UserData); +} + uint16_t ESPUIClass::pad(const char* label, void (*callback)(Control*, int), ControlColor color) { return addControl(ControlType::Pad, label, "", color, Control::noParent, callback); } + +uint16_t ESPUIClass::pad(const char* label, void (*callback)(Control*, int, void*), ControlColor color, void* UserData) +{ + return addControl(ControlType::Pad, label, "", color, Control::noParent, callback, UserData); +} + uint16_t ESPUIClass::padWithCenter(const char* label, void (*callback)(Control*, int), ControlColor color) { return addControl(ControlType::PadWithCenter, label, "", color, Control::noParent, callback); } -uint16_t ESPUIClass::number( - const char* label, void (*callback)(Control*, int), ControlColor color, int number, int min, int max) +uint16_t ESPUIClass::padWithCenter(const char* label, void (*callback)(Control*, int, void*), ControlColor color, void* UserData) +{ + return addControl(ControlType::PadWithCenter, label, "", color, Control::noParent, callback, UserData); +} + +uint16_t ESPUIClass::number(const char* label, void (*callback)(Control*, int), ControlColor color, int number, int min, int max) { uint16_t numberId = addControl(ControlType::Number, label, String(number), color, Control::noParent, callback); addControl(ControlType::Min, label, String(min), ControlColor::None, numberId); @@ -742,6 +768,14 @@ uint16_t ESPUIClass::number( return numberId; } +uint16_t ESPUIClass::number(const char* label, void (*callback)(Control*, int, void*), ControlColor color, int number, int min, int max, void* UserData) +{ + uint16_t numberId = addControl(ControlType::Number, label, String(number), color, Control::noParent, callback, UserData); + addControl(ControlType::Min, label, String(min), ControlColor::None, numberId); + addControl(ControlType::Max, label, String(max), ControlColor::None, numberId); + return numberId; +} + uint16_t ESPUIClass::gauge(const char* label, ControlColor color, int number, int min, int max) { uint16_t numberId = addControl(ControlType::Gauge, label, String(number), color, Control::noParent); @@ -759,11 +793,21 @@ uint16_t ESPUIClass::accelerometer(const char* label, void (*callback)(Control*, return addControl(ControlType::Accel, label, "", color, Control::noParent, callback); } +uint16_t ESPUIClass::accelerometer(const char* label, void (*callback)(Control*, int, void*), ControlColor color, void* UserData) +{ + return addControl(ControlType::Accel, label, "", color, Control::noParent, callback, UserData); +} + uint16_t ESPUIClass::text(const char* label, void (*callback)(Control*, int), ControlColor color, const String& value) { return addControl(ControlType::Text, label, value, color, Control::noParent, callback); } +uint16_t ESPUIClass::text(const char* label, void (*callback)(Control*, int, void*), ControlColor color, const String& value, void* UserData) +{ + return addControl(ControlType::Text, label, value, color, Control::noParent, callback, UserData); +} + Control* ESPUIClass::getControl(uint16_t id) { Control* control = this->controls; @@ -897,7 +941,6 @@ void ESPUIClass::setEnabled(uint16_t id, bool enabled, int clientId) { } } - void ESPUIClass::setVertical(uint16_t id, bool vert) { Control* control = getControl(id); if (control) diff --git a/src/ESPUI.h b/src/ESPUI.h index c6daba6..5016a83 100644 --- a/src/ESPUI.h +++ b/src/ESPUI.h @@ -153,11 +153,8 @@ public: static constexpr uint16_t noParent = 0xffff; - Control( - ControlType type, - const char* label, - void (*callback)(Control*, int, void*), - void* UserData, const String& value, ControlColor color, bool visible, uint16_t parentControl) + Control(ControlType type, const char* label, void (*callback)(Control*, int, void*), void* UserData, + const String& value, ControlColor color, bool visible, uint16_t parentControl) : type(type), label(label), callback(nullptr), @@ -262,21 +259,27 @@ public: bool removeControl(uint16_t id, bool force_reload_ui = false); // create Elements - uint16_t button(const char* label, void (*callback)(Control*, int), ControlColor color, - const String& value = ""); // Create Event Button - uint16_t switcher(const char* label, void (*callback)(Control*, int), ControlColor color, - bool startState = false); // Create Toggle Button - uint16_t pad(const char* label, void (*callback)(Control*, int), - ControlColor color); // Create Pad Control - uint16_t padWithCenter(const char* label, void (*callback)(Control*, int), - ControlColor color); // Create Pad Control with Centerbutton + // Create Event Button + uint16_t button(const char* label, void (*callback)(Control*, int), ControlColor color, const String& value = ""); + uint16_t button(const char* label, void (*callback)(Control*, int, void*), ControlColor color, const String& value, void* UserData); - uint16_t slider(const char* label, void (*callback)(Control*, int), ControlColor color, int value, int min = 0, - int max = 100); // Create Slider Control - uint16_t number(const char* label, void (*callback)(Control*, int), ControlColor color, int value, int min = 0, - int max = 100); // Create a Number Input Control - uint16_t text(const char* label, void (*callback)(Control*, int), ControlColor color, - const String& value = ""); // Create a Text Input Control + uint16_t switcher(const char* label, void (*callback)(Control*, int), ControlColor color, bool startState = false); // Create Toggle Button + uint16_t switcher(const char* label, void (*callback)(Control*, int, void*), ControlColor color, bool startState, void* UserData); // Create Toggle Button + + uint16_t pad(const char* label, void (*callback)(Control*, int), ControlColor color); // Create Pad Control + uint16_t pad(const char* label, void (*callback)(Control*, int, void*), ControlColor color, void* UserData); // Create Pad Control + + uint16_t padWithCenter(const char* label, void (*callback)(Control*, int), ControlColor color); // Create Pad Control with Centerbutton + uint16_t padWithCenter(const char* label, void (*callback)(Control*, int, void*), ControlColor color, void* UserData); // Create Pad Control with Centerbutton + + uint16_t slider(const char* label, void (*callback)(Control*, int), ControlColor color, int value, int min = 0, int max = 100); // Create Slider Control + uint16_t slider(const char* label, void (*callback)(Control*, int, void*), ControlColor color, int value, int min, int max, void* UserData); // Create Slider Control + + uint16_t number(const char* label, void (*callback)(Control*, int), ControlColor color, int value, int min = 0, int max = 100); // Create a Number Input Control + uint16_t number(const char* label, void (*callback)(Control*, int, void*), ControlColor color, int value, int min, int max, void* UserData); // Create a Number Input Control + + uint16_t text(const char* label, void (*callback)(Control*, int), ControlColor color, const String& value = ""); // Create a Text Input Control + uint16_t text(const char* label, void (*callback)(Control*, int, void*), ControlColor color, const String& value, void* UserData); // Create a Text Input Control // Output only uint16_t label(const char* label, ControlColor color, @@ -288,6 +291,7 @@ public: // Input only uint16_t accelerometer(const char* label, void (*callback)(Control*, int), ControlColor color); + uint16_t accelerometer(const char* label, void (*callback)(Control*, int, void*), ControlColor color, void* UserData); // Update Elements From 511840fa97074c8b9220f04296a5d185ca25aab4 Mon Sep 17 00:00:00 2001 From: Martin Mueller Date: Sat, 11 Jun 2022 10:56:35 -0400 Subject: [PATCH 06/11] Added an example for using the new extended parameter callback --- examples/completeExample/completeExample.cpp | 21 ++++++++++++++++++-- examples/gui-generic-api/gui-generic-api.ino | 8 +++++--- examples/gui/gui.ino | 5 +++-- examples/tabbedGui/tabbedGui.ino | 5 +++-- pio_examples/gui/src/gui.ino | 5 +++-- 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/examples/completeExample/completeExample.cpp b/examples/completeExample/completeExample.cpp index f6d9aa5..ecae5c2 100644 --- a/examples/completeExample/completeExample.cpp +++ b/examples/completeExample/completeExample.cpp @@ -49,6 +49,7 @@ void getTimeCallback(Control *sender, int type); void graphAddCallback(Control *sender, int type); void graphClearCallback(Control *sender, int type); void randomString(char *buf, int len); +void extendedCallback(Control* sender, int type, void* param); //UI handles uint16_t wifi_ssid_text, wifi_pass_text; @@ -81,7 +82,7 @@ void setUpUI() { auto maintab = ESPUI.addControl(Tab, "", "Basic controls"); ESPUI.addControl(Separator, "General controls", "", None, maintab); - ESPUI.addControl(Button, "Button", "Button 1", Alizarin, maintab, generalCallback); + ESPUI.addControl(Button, "Button", "Button 1", Alizarin, maintab, extendedCallback, (void*)19); mainLabel = ESPUI.addControl(Label, "Label", "Label text", Emerald, maintab, generalCallback); mainSwitcher = ESPUI.addControl(Switcher, "Switcher", "", Sunflower, maintab, generalCallback); @@ -360,7 +361,23 @@ void generalCallback(Control *sender, int type) { Serial.println(sender->value); } - +// Most elements in this test UI are assigned this generic callback which prints some +// basic information. Event types are defined in ESPUI.h +// The extended param can be used to hold a pointer to additional information +// or for C++ it can be used to return a this pointer for quick access +// using a lambda function +void extendedCallback(Control* sender, int type, void* param) +{ + Serial.print("CB: id("); + Serial.print(sender->id); + Serial.print(") Type("); + Serial.print(type); + Serial.print(") '"); + Serial.print(sender->label); + Serial.print("' = "); + Serial.println(sender->value); + Serial.println(String("param = ") + String((int)param)); +} void setup() { randomSeed(0); diff --git a/examples/gui-generic-api/gui-generic-api.ino b/examples/gui-generic-api/gui-generic-api.ino index 6d1f6e9..44f0119 100644 --- a/examples/gui-generic-api/gui-generic-api.ino +++ b/examples/gui-generic-api/gui-generic-api.ino @@ -55,8 +55,9 @@ void buttonCallback(Control* sender, int type) } } -void buttonExample(Control* sender, int type) +void buttonExample(Control* sender, int type, void* param) { + Serial.println(String("param: ") + String(int(param))); switch (type) { case B_DOWN: @@ -210,7 +211,8 @@ void setup(void) } #else uint32_t chipid = ESP.getChipId(); -#endif char ap_ssid[25]; +#endif + char ap_ssid[25]; snprintf(ap_ssid, 26, "ESPUI-%08X", chipid); WiFi.softAP(ap_ssid); @@ -249,7 +251,7 @@ void setup(void) button1 = ESPUI.addControl( ControlType::Button, "Push Button", "Press", ControlColor::Peterriver, Control::noParent, &buttonCallback); ESPUI.addControl( - ControlType::Button, "Other Button", "Press", ControlColor::Wetasphalt, Control::noParent, &buttonExample); + ControlType::Button, "Other Button", "Press", ControlColor::Wetasphalt, Control::noParent, &buttonExample, (void*)19); ESPUI.addControl( ControlType::PadWithCenter, "Pad with center", "", ControlColor::Sunflower, Control::noParent, &padExample); ESPUI.addControl(ControlType::Pad, "Pad without center", "", ControlColor::Carrot, Control::noParent, &padExample); diff --git a/examples/gui/gui.ino b/examples/gui/gui.ino index 361150e..c7d390c 100644 --- a/examples/gui/gui.ino +++ b/examples/gui/gui.ino @@ -60,8 +60,9 @@ void buttonCallback(Control* sender, int type) } } -void buttonExample(Control* sender, int type) +void buttonExample(Control* sender, int type, void* param) { + Serial.println(String("param: ") + String(int(param))); switch (type) { case B_DOWN: @@ -227,7 +228,7 @@ void setup(void) statusLabelId = ESPUI.label("Status:", ControlColor::Turquoise, "Stop"); millisLabelId = ESPUI.label("Millis:", ControlColor::Emerald, "0"); ESPUI.button("Push Button", &buttonCallback, ControlColor::Peterriver, "Press"); - ESPUI.button("Other Button", &buttonExample, ControlColor::Wetasphalt, "Press"); + ESPUI.button("Other Button", &buttonExample, ControlColor::Wetasphalt, "Press", (void*)19); ESPUI.padWithCenter("Pad with center", &padExample, ControlColor::Sunflower); ESPUI.pad("Pad without center", &padExample, ControlColor::Carrot); testSwitchId = ESPUI.switcher("Switch one", &switchExample, ControlColor::Alizarin, false); diff --git a/examples/tabbedGui/tabbedGui.ino b/examples/tabbedGui/tabbedGui.ino index a1ecd31..b02ae4b 100644 --- a/examples/tabbedGui/tabbedGui.ino +++ b/examples/tabbedGui/tabbedGui.ino @@ -54,8 +54,9 @@ void buttonCallback(Control* sender, int type) } } -void buttonExample(Control* sender, int type) +void buttonExample(Control* sender, int type, void* param) { + Serial.println(String("param: ") + String(int(param))); switch (type) { case B_DOWN: @@ -251,7 +252,7 @@ void setup(void) ESPUI.addControl(ControlType::Label, "Millis:", "0", ControlColor::Emerald, tab1); button1 = ESPUI.addControl( ControlType::Button, "Push Button", "Press", ControlColor::Peterriver, tab1, &buttonCallback); - ESPUI.addControl(ControlType::Button, "Other Button", "Press", ControlColor::Wetasphalt, tab1, &buttonExample); + ESPUI.addControl(ControlType::Button, "Other Button", "Press", ControlColor::Wetasphalt, tab1, &buttonExample, (void*)19); ESPUI.addControl(ControlType::PadWithCenter, "Pad with center", "", ControlColor::Sunflower, tab2, &padExample); ESPUI.addControl(ControlType::Pad, "Pad without center", "", ControlColor::Carrot, tab3, &padExample); switchOne = ESPUI.addControl(ControlType::Switcher, "Switch one", "", ControlColor::Alizarin, tab3, &switchExample); diff --git a/pio_examples/gui/src/gui.ino b/pio_examples/gui/src/gui.ino index e998061..d5a9e7c 100644 --- a/pio_examples/gui/src/gui.ino +++ b/pio_examples/gui/src/gui.ino @@ -60,8 +60,9 @@ void buttonCallback(Control* sender, int type) } } -void buttonExample(Control* sender, int type) +void buttonExample(Control* sender, int type, void* param) { + Serial.println(String("param: ") + String(int(param))); switch (type) { case B_DOWN: @@ -228,7 +229,7 @@ void setup(void) statusLabelId = ESPUI.label("Status:", ControlColor::Turquoise, "Stop"); millisLabelId = ESPUI.label("Millis:", ControlColor::Emerald, "0"); ESPUI.button("Push Button", &buttonCallback, ControlColor::Peterriver, "Press"); - ESPUI.button("Other Button", &buttonExample, ControlColor::Wetasphalt, "Press"); + ESPUI.button("Other Button", &buttonExample, ControlColor::Wetasphalt, "Press", (void*)19); ESPUI.padWithCenter("Pad with center", &padExample, ControlColor::Sunflower); ESPUI.pad("Pad without center", &padExample, ControlColor::Carrot); testSwitchId = ESPUI.switcher("Switch one", &switchExample, ControlColor::Alizarin, false); From c303668a3cf7392297f1b1f922f5afe9adef477a Mon Sep 17 00:00:00 2001 From: Martin Mueller Date: Sat, 25 Jun 2022 07:16:51 -0400 Subject: [PATCH 07/11] Added description and usage for the extended callback functionality --- README.md | 50 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index e5319c9..f47eca3 100644 --- a/README.md +++ b/README.md @@ -146,24 +146,40 @@ more program memory to work with. ## Documentation -The heart of ESPUI is -[ESPAsyncWebserver](https://github.com/me-no-dev/ESPAsyncWebServer). ESPUI's -frontend is based on [Skeleton CSS](http://getskeleton.com/) and jQuery-like -lightweight [zepto.js](https://zeptojs.com/) for handling events. The -communication between the ESP and the client browser works using web -sockets. ESPUI does not need network access and can be used in standalone access -point mode, all resources are loaded directly from the ESPs memory. +The heart of ESPUI is [ESPAsyncWebserver](https://github.com/me-no-dev/ESPAsyncWebServer). ESPUI's frontend is based on [Skeleton CSS](http://getskeleton.com/) and jQuery-like lightweight [zepto.js](https://zeptojs.com/) for handling events. The communication between the ESP and the client browser works using web sockets. ESPUI does not need network access and can be used in standalone access point mode, all resources are loaded directly from the ESPs memory. -This section will explain in detail how the Library is to be used from the -Arduino code side. In the arduino `setup()` routine the interface can be customised by adding UI Elements. -This is done by calling the corresponding library methods on the Library object -`ESPUI`. Eg: `ESPUI.button("button", &myCallback);` creates a button in the -interface that calls the `myCallback(Control *sender, int value)` function when changed. All buttons and -items call their callback whenever there is a state change from them. This means -the button will call the callback when it is pressed and also again when it is -released. To separate different events an integer number with the event name is -passed to the callback function that can be handled in a `switch(){}case{}` -statement. +This section will explain in detail how the Library is to be used from the Arduino code side. In the arduino `setup()` routine the interface can be customised by adding UI Elements. This is done by calling the corresponding library methods on the Library object `ESPUI`. Eg: `ESPUI.button("button", &myCallback);` creates a button in the interface that calls the `myCallback(Control *sender, int eventname)` function when changed. All buttons and items call their callback whenever there is a state change from them. This means the button will call the callback when it is pressed and also again when it is released. To separate different events an integer number with the event name is passed to the callback function that can be handled in a `switch(){}case{}` statement. +Alternativly you may use the extended callback funtion which provides three parameters to the callback function `myCallback(Control *sender, int eventname, void * UserParameter)`. The `UserParameter` is provided as part of the `ESPUI.addControl` and allows the user to define contextual information that is to be presented to the callback function in an unmodified form. +Here is an example of using the UserParameter to hold the `this` pointer to an object instance, providing a mechanism for sending the event to a specific object without the need for a switch / map translation of the Sender Id tp object reference. Defining an extended callback is only supported via the `ESPUI.addContol` method. The below example creates a button and uses a lambda function to implicitly define `MyExtendedCallback` which then invokes a more specialized button callback handler. +``` +ButtonElementId = ESPUI.addControl( + ControlType::Button, + ButtonLabel.c_str(), + " Button Face Text ", + ControlColor::None, + ParentElementId, + [](Control *sender, int eventname, void* param) + { + if(param) + { + reinterpret_cast(param)->myButtonCallback(sender, eventname); + } + }, + this); +``` +``` +void YourClassName::myButtonCallback(Control* sender, int eventname) +{ + if (eventname == B_DOWN) + { + // Handle the button down event + } + else if (eventname == B_UP) + { + // Handle the button up event + } +} +``` #### Button From ba9f83a93b708b893ae9b32ff237f546434bc423 Mon Sep 17 00:00:00 2001 From: Martin Mueller Date: Sat, 25 Jun 2022 07:29:44 -0400 Subject: [PATCH 08/11] Formatting changes --- README.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f47eca3..0df5890 100644 --- a/README.md +++ b/README.md @@ -147,10 +147,14 @@ more program memory to work with. ## Documentation The heart of ESPUI is [ESPAsyncWebserver](https://github.com/me-no-dev/ESPAsyncWebServer). ESPUI's frontend is based on [Skeleton CSS](http://getskeleton.com/) and jQuery-like lightweight [zepto.js](https://zeptojs.com/) for handling events. The communication between the ESP and the client browser works using web sockets. ESPUI does not need network access and can be used in standalone access point mode, all resources are loaded directly from the ESPs memory. - -This section will explain in detail how the Library is to be used from the Arduino code side. In the arduino `setup()` routine the interface can be customised by adding UI Elements. This is done by calling the corresponding library methods on the Library object `ESPUI`. Eg: `ESPUI.button("button", &myCallback);` creates a button in the interface that calls the `myCallback(Control *sender, int eventname)` function when changed. All buttons and items call their callback whenever there is a state change from them. This means the button will call the callback when it is pressed and also again when it is released. To separate different events an integer number with the event name is passed to the callback function that can be handled in a `switch(){}case{}` statement. +
+This section will explain in detail how the Library is to be used from the Arduino code side. In the arduino `setup()` routine the interface can be customised by adding UI Elements. This is done by calling the corresponding library methods on the Library object `ESPUI`. Eg: `ESPUI.button("button", &myCallback);` creates a button in the interface that calls the `myCallback(Control *sender, int eventname)` function when changed. All buttons and items call their callback whenever there is a state change from them. This means the button will call the callback when it is pressed and also again when it is released. To separate different events, an integer number with the event name is passed to the callback function that can be handled in a `switch(){}case{}` statement. +
Alternativly you may use the extended callback funtion which provides three parameters to the callback function `myCallback(Control *sender, int eventname, void * UserParameter)`. The `UserParameter` is provided as part of the `ESPUI.addControl` and allows the user to define contextual information that is to be presented to the callback function in an unmodified form. -Here is an example of using the UserParameter to hold the `this` pointer to an object instance, providing a mechanism for sending the event to a specific object without the need for a switch / map translation of the Sender Id tp object reference. Defining an extended callback is only supported via the `ESPUI.addContol` method. The below example creates a button and uses a lambda function to implicitly define `MyExtendedCallback` which then invokes a more specialized button callback handler. +
+Defining an extended callback is only supported via the `ESPUI.addContol` method. +
+The below example creates a button and defines a lambda function to implicitly create an `ExtendedCallback` which then invokes a more specialized button callback handler. The example uses the `UserParameter` to hold the `this` pointer to an object instance, providing a mechanism for sending the event to a specific object without the need for a switch / map / lookup translation of the Sender Id to an object reference. ``` ButtonElementId = ESPUI.addControl( ControlType::Button, @@ -165,7 +169,7 @@ ButtonElementId = ESPUI.addControl( reinterpret_cast(param)->myButtonCallback(sender, eventname); } }, - this); + this); // <-Third parameter for the extended callback ``` ``` void YourClassName::myButtonCallback(Control* sender, int eventname) @@ -180,8 +184,8 @@ void YourClassName::myButtonCallback(Control* sender, int eventname) } } ``` - - +
+
#### Button ![Buttons](docs/ui_button.png) From 36f6932538067624bd8fe3ca0247f00bc975f35c Mon Sep 17 00:00:00 2001 From: Martin Mueller Date: Sat, 25 Jun 2022 07:31:34 -0400 Subject: [PATCH 09/11] formatting --- README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0df5890..14ee28c 100644 --- a/README.md +++ b/README.md @@ -147,13 +147,11 @@ more program memory to work with. ## Documentation The heart of ESPUI is [ESPAsyncWebserver](https://github.com/me-no-dev/ESPAsyncWebServer). ESPUI's frontend is based on [Skeleton CSS](http://getskeleton.com/) and jQuery-like lightweight [zepto.js](https://zeptojs.com/) for handling events. The communication between the ESP and the client browser works using web sockets. ESPUI does not need network access and can be used in standalone access point mode, all resources are loaded directly from the ESPs memory. -
+

This section will explain in detail how the Library is to be used from the Arduino code side. In the arduino `setup()` routine the interface can be customised by adding UI Elements. This is done by calling the corresponding library methods on the Library object `ESPUI`. Eg: `ESPUI.button("button", &myCallback);` creates a button in the interface that calls the `myCallback(Control *sender, int eventname)` function when changed. All buttons and items call their callback whenever there is a state change from them. This means the button will call the callback when it is pressed and also again when it is released. To separate different events, an integer number with the event name is passed to the callback function that can be handled in a `switch(){}case{}` statement. -
-Alternativly you may use the extended callback funtion which provides three parameters to the callback function `myCallback(Control *sender, int eventname, void * UserParameter)`. The `UserParameter` is provided as part of the `ESPUI.addControl` and allows the user to define contextual information that is to be presented to the callback function in an unmodified form. -
-Defining an extended callback is only supported via the `ESPUI.addContol` method. -
+

+Alternativly you may use the extended callback funtion which provides three parameters to the callback function `myCallback(Control *sender, int eventname, void * UserParameter)`. The `UserParameter` is provided as part of the `ESPUI.addControl` and allows the user to define contextual information that is to be presented to the callback function in an unmodified form. Defining an extended callback is only supported via the `ESPUI.addContol` method. +

The below example creates a button and defines a lambda function to implicitly create an `ExtendedCallback` which then invokes a more specialized button callback handler. The example uses the `UserParameter` to hold the `this` pointer to an object instance, providing a mechanism for sending the event to a specific object without the need for a switch / map / lookup translation of the Sender Id to an object reference. ``` ButtonElementId = ESPUI.addControl( From a553d3257002238ac07a2a7d4a3df5bc68db5bcc Mon Sep 17 00:00:00 2001 From: Martin Mueller Date: Sat, 25 Jun 2022 07:40:09 -0400 Subject: [PATCH 10/11] Corrected class example --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 14ee28c..0e438b7 100644 --- a/README.md +++ b/README.md @@ -154,7 +154,9 @@ Alternativly you may use the extended callback funtion which provides three para

The below example creates a button and defines a lambda function to implicitly create an `ExtendedCallback` which then invokes a more specialized button callback handler. The example uses the `UserParameter` to hold the `this` pointer to an object instance, providing a mechanism for sending the event to a specific object without the need for a switch / map / lookup translation of the Sender Id to an object reference. ``` -ButtonElementId = ESPUI.addControl( +void YourClassName::setup() +{ + ButtonElementId = ESPUI.addControl( ControlType::Button, ButtonLabel.c_str(), " Button Face Text ", @@ -168,6 +170,7 @@ ButtonElementId = ESPUI.addControl( } }, this); // <-Third parameter for the extended callback +} ``` ``` void YourClassName::myButtonCallback(Control* sender, int eventname) From 9d9a1656934a6a444d6f32e197844e541e46942e Mon Sep 17 00:00:00 2001 From: Martin Mueller Date: Sat, 25 Jun 2022 10:25:05 -0400 Subject: [PATCH 11/11] Added an example using the button shortcut --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0e438b7..9e5799e 100644 --- a/README.md +++ b/README.md @@ -150,7 +150,7 @@ The heart of ESPUI is [ESPAsyncWebserver](https://github.com/me-no-dev/ESPAsyncW

This section will explain in detail how the Library is to be used from the Arduino code side. In the arduino `setup()` routine the interface can be customised by adding UI Elements. This is done by calling the corresponding library methods on the Library object `ESPUI`. Eg: `ESPUI.button("button", &myCallback);` creates a button in the interface that calls the `myCallback(Control *sender, int eventname)` function when changed. All buttons and items call their callback whenever there is a state change from them. This means the button will call the callback when it is pressed and also again when it is released. To separate different events, an integer number with the event name is passed to the callback function that can be handled in a `switch(){}case{}` statement.

-Alternativly you may use the extended callback funtion which provides three parameters to the callback function `myCallback(Control *sender, int eventname, void * UserParameter)`. The `UserParameter` is provided as part of the `ESPUI.addControl` and allows the user to define contextual information that is to be presented to the callback function in an unmodified form. Defining an extended callback is only supported via the `ESPUI.addContol` method. +Alternativly you may use the extended callback funtion which provides three parameters to the callback function `myCallback(Control *sender, int eventname, void * UserParameter)`. The `UserParameter` is provided as part of the `ESPUI.addControl` method set and allows the user to define contextual information that is to be presented to the callback function in an unmodified form.

The below example creates a button and defines a lambda function to implicitly create an `ExtendedCallback` which then invokes a more specialized button callback handler. The example uses the `UserParameter` to hold the `this` pointer to an object instance, providing a mechanism for sending the event to a specific object without the need for a switch / map / lookup translation of the Sender Id to an object reference. ``` @@ -170,6 +170,18 @@ void YourClassName::setup() } }, this); // <-Third parameter for the extended callback + + // or + ButtonElementId = ESPUI.button( + " Button Face Text ", + [](Control *sender, int eventname, void* param) + { + if(param) + { + reinterpret_cast(param)->myButtonCallback(sender, eventname); + } + }, + this); // <-Third parameter for the extended callback } ``` ```