mirror of
https://github.com/s00500/ESPUI.git
synced 2024-11-22 04:00:55 +00:00
commit
372157b980
@ -495,7 +495,7 @@ ESPUI includes a range of advanced features that can customise your UIs.
|
|||||||
|
|
||||||
### Dynamic Visibility
|
### Dynamic Visibility
|
||||||
|
|
||||||
Cotrols can be made visible or invisible at runtime with the `updateVisibility()` function.
|
Controls can be made visible or invisible at runtime with the `updateVisibility()` function.
|
||||||
|
|
||||||
```
|
```
|
||||||
ESPUI.updateVisibility(controlId, false);
|
ESPUI.updateVisibility(controlId, false);
|
||||||
|
@ -26,8 +26,18 @@
|
|||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <ESPmDNS.h>
|
#include <ESPmDNS.h>
|
||||||
#else
|
#else
|
||||||
|
// esp8266
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <ESP8266mDNS.h>
|
#include <ESP8266mDNS.h>
|
||||||
|
#include <umm_malloc/umm_heap_select.h>
|
||||||
|
#ifndef MMU_IRAM_HEAP
|
||||||
|
#warning Try MMU option '2nd heap shared' in 'tools' IDE menu (cf. https://arduino-esp8266.readthedocs.io/en/latest/mmu.html#option-summary)
|
||||||
|
#warning use decorators: { HeapSelectIram doAllocationsInIRAM; ESPUI.addControl(...) ... } (cf. https://arduino-esp8266.readthedocs.io/en/latest/mmu.html#how-to-select-heap)
|
||||||
|
#warning then check http://<ip>/heap
|
||||||
|
#endif // MMU_IRAM_HEAP
|
||||||
|
#ifndef DEBUG_ESP_OOM
|
||||||
|
#error on ESP8266 and ESPUI, you must define OOM debug option when developping
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//Settings
|
//Settings
|
||||||
@ -62,6 +72,11 @@ volatile bool updates = false;
|
|||||||
|
|
||||||
// This is the main function which builds our GUI
|
// This is the main function which builds our GUI
|
||||||
void setUpUI() {
|
void setUpUI() {
|
||||||
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
{ HeapSelectIram doAllocationsInIRAM;
|
||||||
|
#endif
|
||||||
|
|
||||||
//Turn off verbose debugging
|
//Turn off verbose debugging
|
||||||
ESPUI.setVerbosity(Verbosity::Quiet);
|
ESPUI.setVerbosity(Verbosity::Quiet);
|
||||||
|
|
||||||
@ -274,6 +289,11 @@ void setUpUI() {
|
|||||||
//Finally, start up the UI.
|
//Finally, start up the UI.
|
||||||
//This should only be called once we are connected to WiFi.
|
//This should only be called once we are connected to WiFi.
|
||||||
ESPUI.begin(HOSTNAME);
|
ESPUI.begin(HOSTNAME);
|
||||||
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
} // HeapSelectIram
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//This callback generates and applies inline styles to a bunch of controls to change their colour.
|
//This callback generates and applies inline styles to a bunch of controls to change their colour.
|
||||||
|
1
examples/completeExample/completeExample.ino
Normal file
1
examples/completeExample/completeExample.ino
Normal file
@ -0,0 +1 @@
|
|||||||
|
// placeholder
|
@ -8,7 +8,17 @@ DNSServer dnsServer;
|
|||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#else
|
#else
|
||||||
|
// esp8266
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <umm_malloc/umm_heap_select.h>
|
||||||
|
#ifndef MMU_IRAM_HEAP
|
||||||
|
#warning Try MMU option '2nd heap shared' in 'tools' IDE menu (cf. https://arduino-esp8266.readthedocs.io/en/latest/mmu.html#option-summary)
|
||||||
|
#warning use decorators: { HeapSelectIram doAllocationsInIRAM; ESPUI.addControl(...) ... } (cf. https://arduino-esp8266.readthedocs.io/en/latest/mmu.html#how-to-select-heap)
|
||||||
|
#warning then check http://<ip>/heap
|
||||||
|
#endif // MMU_IRAM_HEAP
|
||||||
|
#ifndef DEBUG_ESP_OOM
|
||||||
|
#error on ESP8266 and ESPUI, you must define OOM debug option when developping
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char* ssid = "ESPUI";
|
const char* ssid = "ESPUI";
|
||||||
@ -235,6 +245,10 @@ void setup(void)
|
|||||||
Serial.print("IP address: ");
|
Serial.print("IP address: ");
|
||||||
Serial.println(WiFi.getMode() == WIFI_AP ? WiFi.softAPIP() : WiFi.localIP());
|
Serial.println(WiFi.getMode() == WIFI_AP ? WiFi.softAPIP() : WiFi.localIP());
|
||||||
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
{ HeapSelectIram doAllocationsInIRAM;
|
||||||
|
#endif
|
||||||
|
|
||||||
status = ESPUI.addControl(ControlType::Label, "Status:", "Stop", ControlColor::Turquoise);
|
status = ESPUI.addControl(ControlType::Label, "Status:", "Stop", ControlColor::Turquoise);
|
||||||
|
|
||||||
uint16_t select1 = ESPUI.addControl(
|
uint16_t select1 = ESPUI.addControl(
|
||||||
@ -281,6 +295,10 @@ void setup(void)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
ESPUI.begin("ESPUI Control");
|
ESPUI.begin("ESPUI Control");
|
||||||
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
} // HeapSelectIram
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop(void)
|
void loop(void)
|
||||||
|
@ -8,7 +8,17 @@ DNSServer dnsServer;
|
|||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#else
|
#else
|
||||||
|
// esp8266
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <umm_malloc/umm_heap_select.h>
|
||||||
|
#ifndef MMU_IRAM_HEAP
|
||||||
|
#warning Try MMU option '2nd heap shared' in 'tools' IDE menu (cf. https://arduino-esp8266.readthedocs.io/en/latest/mmu.html#option-summary)
|
||||||
|
#warning use decorators: { HeapSelectIram doAllocationsInIRAM; ESPUI.addControl(...) ... } (cf. https://arduino-esp8266.readthedocs.io/en/latest/mmu.html#how-to-select-heap)
|
||||||
|
#warning then check http://<ip>/heap
|
||||||
|
#endif // MMU_IRAM_HEAP
|
||||||
|
#ifndef DEBUG_ESP_OOM
|
||||||
|
#error on ESP8266 and ESPUI, you must define OOM debug option when developping
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char* ssid = "ESPUI";
|
const char* ssid = "ESPUI";
|
||||||
@ -225,6 +235,10 @@ void setup(void)
|
|||||||
Serial.print("IP address: ");
|
Serial.print("IP address: ");
|
||||||
Serial.println(WiFi.getMode() == WIFI_AP ? WiFi.softAPIP() : WiFi.localIP());
|
Serial.println(WiFi.getMode() == WIFI_AP ? WiFi.softAPIP() : WiFi.localIP());
|
||||||
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
{ HeapSelectIram doAllocationsInIRAM;
|
||||||
|
#endif
|
||||||
|
|
||||||
statusLabelId = ESPUI.label("Status:", ControlColor::Turquoise, "Stop");
|
statusLabelId = ESPUI.label("Status:", ControlColor::Turquoise, "Stop");
|
||||||
millisLabelId = ESPUI.label("Millis:", ControlColor::Emerald, "0");
|
millisLabelId = ESPUI.label("Millis:", ControlColor::Emerald, "0");
|
||||||
ESPUI.button("Push Button", &buttonCallback, ControlColor::Peterriver, "Press");
|
ESPUI.button("Push Button", &buttonCallback, ControlColor::Peterriver, "Press");
|
||||||
@ -257,6 +271,10 @@ void setup(void)
|
|||||||
* password, for example begin("ESPUI Control", "username", "password")
|
* password, for example begin("ESPUI Control", "username", "password")
|
||||||
*/
|
*/
|
||||||
ESPUI.begin("ESPUI Control");
|
ESPUI.begin("ESPUI Control");
|
||||||
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
} // HeapSelectIram
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop(void)
|
void loop(void)
|
||||||
|
@ -8,7 +8,17 @@ DNSServer dnsServer;
|
|||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#else
|
#else
|
||||||
|
// esp8266
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <umm_malloc/umm_heap_select.h>
|
||||||
|
#ifndef MMU_IRAM_HEAP
|
||||||
|
#warning Try MMU option '2nd heap shared' in 'tools' IDE menu (cf. https://arduino-esp8266.readthedocs.io/en/latest/mmu.html#option-summary)
|
||||||
|
#warning use decorators: { HeapSelectIram doAllocationsInIRAM; ESPUI.addControl(...) ... } (cf. https://arduino-esp8266.readthedocs.io/en/latest/mmu.html#how-to-select-heap)
|
||||||
|
#warning then check http://<ip>/heap
|
||||||
|
#endif // MMU_IRAM_HEAP
|
||||||
|
#ifndef DEBUG_ESP_OOM
|
||||||
|
#error on ESP8266 and ESPUI, you must define OOM debug option when developping
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char* ssid = "ESPUI";
|
const char* ssid = "ESPUI";
|
||||||
@ -233,6 +243,10 @@ void setup(void)
|
|||||||
Serial.print("IP address: ");
|
Serial.print("IP address: ");
|
||||||
Serial.println(WiFi.getMode() == WIFI_AP ? WiFi.softAPIP() : WiFi.localIP());
|
Serial.println(WiFi.getMode() == WIFI_AP ? WiFi.softAPIP() : WiFi.localIP());
|
||||||
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
{ HeapSelectIram doAllocationsInIRAM;
|
||||||
|
#endif
|
||||||
|
|
||||||
uint16_t tab1 = ESPUI.addControl(ControlType::Tab, "Settings 1", "Settings 1");
|
uint16_t tab1 = ESPUI.addControl(ControlType::Tab, "Settings 1", "Settings 1");
|
||||||
uint16_t tab2 = ESPUI.addControl(ControlType::Tab, "Settings 2", "Settings 2");
|
uint16_t tab2 = ESPUI.addControl(ControlType::Tab, "Settings 2", "Settings 2");
|
||||||
uint16_t tab3 = ESPUI.addControl(ControlType::Tab, "Settings 3", "Settings 3");
|
uint16_t tab3 = ESPUI.addControl(ControlType::Tab, "Settings 3", "Settings 3");
|
||||||
@ -279,6 +293,10 @@ void setup(void)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
ESPUI.begin("ESPUI Control");
|
ESPUI.begin("ESPUI Control");
|
||||||
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
} // HeapSelectIram
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop(void)
|
void loop(void)
|
||||||
|
@ -13,6 +13,61 @@
|
|||||||
#include "dataTabbedcontentJS.h"
|
#include "dataTabbedcontentJS.h"
|
||||||
#include "dataZeptoJS.h"
|
#include "dataZeptoJS.h"
|
||||||
|
|
||||||
|
#if ESP8266
|
||||||
|
#include <umm_malloc/umm_heap_select.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static String heapInfo (const __FlashStringHelper* mode)
|
||||||
|
{
|
||||||
|
#if ESP8266
|
||||||
|
|
||||||
|
uint32_t hfree;
|
||||||
|
uint32_t hmax;
|
||||||
|
uint8_t hfrag;
|
||||||
|
String result;
|
||||||
|
result.reserve(128);
|
||||||
|
|
||||||
|
#ifdef UMM_HEAP_IRAM
|
||||||
|
// here esp8266 is configurerd to use an extra 16KB (i)ram
|
||||||
|
{
|
||||||
|
HeapSelectIram useInstructionRamHere;
|
||||||
|
ESP.getHeapStats(&hfree, &hmax, &hfrag);
|
||||||
|
}
|
||||||
|
result += F("IRAM: free: ");
|
||||||
|
result += hfree;
|
||||||
|
result += F(" max: ");
|
||||||
|
result += hmax;
|
||||||
|
result += F(" frag: ");
|
||||||
|
result += hfrag;
|
||||||
|
result += "%\n";
|
||||||
|
#endif // !UMM_HEAP_IRAM
|
||||||
|
{
|
||||||
|
HeapSelectDram useRegularRamHere;
|
||||||
|
ESP.getHeapStats(&hfree, &hmax, &hfrag);
|
||||||
|
}
|
||||||
|
result += F("DRAM: free: ");
|
||||||
|
result += hfree;
|
||||||
|
result += F(" max: ");
|
||||||
|
result += hmax;
|
||||||
|
result += F(" frag: ");
|
||||||
|
result += hfrag;
|
||||||
|
result += "%\n";
|
||||||
|
|
||||||
|
#else // !ESP8266
|
||||||
|
|
||||||
|
result += ESP.getFreeHeap();
|
||||||
|
result += ' ';
|
||||||
|
|
||||||
|
#endif // !ESP8266
|
||||||
|
|
||||||
|
result += mode;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ################# LITTLEFS functions
|
// ################# LITTLEFS functions
|
||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
void listDir(const char* dirname, uint8_t levels)
|
void listDir(const char* dirname, uint8_t levels)
|
||||||
@ -1260,7 +1315,8 @@ void ESPUIClass::beginLITTLEFS(const char* _title, const char* username, const c
|
|||||||
return request->requestAuthentication();
|
return request->requestAuthentication();
|
||||||
}
|
}
|
||||||
|
|
||||||
request->send(200, "text/plain", String(ESP.getFreeHeap()) + " In LITTLEFS mode");
|
request->send(200, "text/plain", heapInfo(F("In LITTLEFS mode")));
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
server->onNotFound([this](AsyncWebServerRequest* request) {
|
server->onNotFound([this](AsyncWebServerRequest* request) {
|
||||||
@ -1418,7 +1474,7 @@ void ESPUIClass::begin(const char* _title, const char* username, const char* pas
|
|||||||
return request->requestAuthentication();
|
return request->requestAuthentication();
|
||||||
}
|
}
|
||||||
|
|
||||||
request->send(200, "text/plain", String(ESP.getFreeHeap()) + " In Memorymode");
|
request->send(200, "text/plain", heapInfo(F("In Memorymode")));
|
||||||
});
|
});
|
||||||
|
|
||||||
server->onNotFound([this](AsyncWebServerRequest* request) {
|
server->onNotFound([this](AsyncWebServerRequest* request) {
|
||||||
|
29
src/ESPUI.h
29
src/ESPUI.h
@ -87,20 +87,25 @@ enum Verbosity : uint8_t
|
|||||||
class ESPUIClass
|
class ESPUIClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
ESPUIClass()
|
ESPUIClass()
|
||||||
{
|
{
|
||||||
verbosity = Verbosity::Quiet;
|
|
||||||
jsonUpdateDocumentSize = 2000;
|
|
||||||
jsonInitialDocumentSize = 8000;
|
|
||||||
sliderContinuous = false;
|
|
||||||
#ifdef ESP32
|
|
||||||
ControlsSemaphore = xSemaphoreCreateMutex();
|
ControlsSemaphore = xSemaphoreCreateMutex();
|
||||||
xSemaphoreGive(ControlsSemaphore);
|
xSemaphoreGive(ControlsSemaphore);
|
||||||
#endif // def ESP32
|
|
||||||
}
|
}
|
||||||
unsigned int jsonUpdateDocumentSize;
|
SemaphoreHandle_t ControlsSemaphore = NULL;
|
||||||
unsigned int jsonInitialDocumentSize;
|
#endif // def ESP32
|
||||||
bool sliderContinuous;
|
|
||||||
|
unsigned int jsonUpdateDocumentSize = 2000;
|
||||||
|
#ifdef ESP8266
|
||||||
|
unsigned int jsonInitialDocumentSize = 2000;
|
||||||
|
unsigned int jsonChunkNumberMax = 5;
|
||||||
|
#else
|
||||||
|
unsigned int jsonInitialDocumentSize = 8000;
|
||||||
|
unsigned int jsonChunkNumberMax = 0;
|
||||||
|
#endif
|
||||||
|
bool sliderContinuous = false;
|
||||||
void onWsEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len);
|
void onWsEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len);
|
||||||
bool captivePortal = true;
|
bool captivePortal = true;
|
||||||
|
|
||||||
@ -205,17 +210,13 @@ public:
|
|||||||
void jsonReload();
|
void jsonReload();
|
||||||
void jsonDom(uint16_t startidx, AsyncWebSocketClient* client = nullptr, bool Updating = false);
|
void jsonDom(uint16_t startidx, AsyncWebSocketClient* client = nullptr, bool Updating = false);
|
||||||
|
|
||||||
Verbosity verbosity;
|
Verbosity verbosity = Verbosity::Quiet;
|
||||||
AsyncWebServer* server;
|
AsyncWebServer* server;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class ESPUIclient;
|
friend class ESPUIclient;
|
||||||
friend class ESPUIcontrol;
|
friend class ESPUIcontrol;
|
||||||
|
|
||||||
#ifdef ESP32
|
|
||||||
SemaphoreHandle_t ControlsSemaphore = NULL;
|
|
||||||
#endif // def ESP32
|
|
||||||
|
|
||||||
void RemoveToBeDeletedControls();
|
void RemoveToBeDeletedControls();
|
||||||
|
|
||||||
AsyncWebSocket* ws;
|
AsyncWebSocket* ws;
|
||||||
|
@ -2,6 +2,42 @@
|
|||||||
#include "ESPUIclient.h"
|
#include "ESPUIclient.h"
|
||||||
#include "ESPUIcontrol.h"
|
#include "ESPUIcontrol.h"
|
||||||
|
|
||||||
|
// JSONSlave:
|
||||||
|
// helper to process exact JSON serialization size
|
||||||
|
// it takes ~2ms on esp8266 and avoid large String reallocation which is really worth the cost
|
||||||
|
class JSONSlave: public Print
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
size_t write (uint8_t c) override { counter++; return 1; }
|
||||||
|
size_t write (const uint8_t* buf, size_t count) override { counter += count; return count; }
|
||||||
|
size_t get_counter () { return counter; }
|
||||||
|
|
||||||
|
static size_t serializedSize (JsonDocument& doc)
|
||||||
|
{
|
||||||
|
JSONSlave counter;
|
||||||
|
serializeJson(doc, counter);
|
||||||
|
return counter.get_counter();
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t serialize (JsonDocument& doc, String& str)
|
||||||
|
{
|
||||||
|
size_t s = serializedSize(doc) + 10; // 10 is paranoid
|
||||||
|
str.reserve(s);
|
||||||
|
serializeJson(doc, str);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String toString (JsonDocument& doc)
|
||||||
|
{
|
||||||
|
String str;
|
||||||
|
serialize(doc, str);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
size_t counter = 0;
|
||||||
|
};
|
||||||
|
|
||||||
ESPUIclient::ESPUIclient(AsyncWebSocketClient * _client):
|
ESPUIclient::ESPUIclient(AsyncWebSocketClient * _client):
|
||||||
client(_client)
|
client(_client)
|
||||||
{
|
{
|
||||||
@ -309,7 +345,7 @@ uint32_t ESPUIclient::prepareJSONChunk(uint16_t startindex,
|
|||||||
elementcount++;
|
elementcount++;
|
||||||
control->MarshalControl(item, InUpdateMode);
|
control->MarshalControl(item, InUpdateMode);
|
||||||
|
|
||||||
if (rootDoc.overflowed())
|
if (rootDoc.overflowed() || (ESPUI.jsonChunkNumberMax > 0 && (elementcount % ESPUI.jsonChunkNumberMax) == 0))
|
||||||
{
|
{
|
||||||
// String("prepareJSONChunk: too much data in the message. Remove the last entry");
|
// String("prepareJSONChunk: too much data in the message. Remove the last entry");
|
||||||
if (1 == elementcount)
|
if (1 == elementcount)
|
||||||
@ -407,9 +443,8 @@ bool ESPUIclient::SendControlsToClient(uint16_t startidx,
|
|||||||
if (ESPUI.verbosity >= Verbosity::VerboseJSON)
|
if (ESPUI.verbosity >= Verbosity::VerboseJSON)
|
||||||
{
|
{
|
||||||
Serial.println(F("ESPUIclient:SendControlsToClient: Sending elements --------->"));
|
Serial.println(F("ESPUIclient:SendControlsToClient: Sending elements --------->"));
|
||||||
String json;
|
serializeJson(document, Serial);
|
||||||
serializeJson(document, json);
|
Serial.println();
|
||||||
Serial.println(json);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -454,10 +489,7 @@ bool ESPUIclient::SendJsonDocToWebSocket(DynamicJsonDocument& document)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
String json;
|
String json = JSONSlave::toString(document);
|
||||||
json.reserve(document.size() / 2);
|
|
||||||
json.clear();
|
|
||||||
serializeJson(document, json);
|
|
||||||
|
|
||||||
#if defined(DEBUG_ESPUI)
|
#if defined(DEBUG_ESPUI)
|
||||||
if (ESPUI.verbosity >= Verbosity::VerboseJSON)
|
if (ESPUI.verbosity >= Verbosity::VerboseJSON)
|
||||||
|
Loading…
Reference in New Issue
Block a user