1
0
mirror of https://github.com/s00500/ESPUI.git synced 2024-11-25 14:10:54 +00:00
This commit is contained in:
Nikola Kirov 2023-12-13 09:27:21 +02:00
parent ab46429b3c
commit fe75655ecc
11 changed files with 295 additions and 447 deletions

View File

@ -62,9 +62,6 @@ The Library runs on any kind of **ESP8266** and **ESP32** (NodeMCU, AI Thinker,
- Time control by @iangray001
- Vertical controls by @iangray001
- Time/date/password/color input types by @pcbbc
- Delayed response support @MartinMueller2003
- Fragmented control transfer @ MartinMueller2003
- Extended Callback @MartinMueller2003
## Roadmap
@ -156,9 +153,7 @@ This section will explain in detail how the Library is to be used from the Ardui
<br><br>
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.
<br><br>
It also possible to use a lambda function in the callback parameter. It also allows the user to define, in a more C++ way, contextual information in any form. This is shown by the [completeLambda](examples/completeLambda/completeLambda.ino) example.
<br><br>
The below example creates a button and defines a lambda function to invoke a more specialized button callback handler:
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.
```
void YourClassName::setup()
{
@ -168,18 +163,26 @@ void YourClassName::setup()
" Button Face Text ",
ControlColor::None,
ParentElementId,
[&](Control *sender, int eventname)
[](Control *sender, int eventname, void* param)
{
myButtonCallback(sender, eventname); // class method
});
if(param)
{
reinterpret_cast<YourClassName*>(param)->myButtonCallback(sender, eventname);
}
},
this); // <-Third parameter for the extended callback
// or
ButtonElementId = ESPUI.button(
" Button Face Text ",
[&](Control *sender, int eventname)
[](Control *sender, int eventname, void* param)
{
myButtonCallback(sender, eventname); // class method
});
if(param)
{
reinterpret_cast<YourClassName*>(param)->myButtonCallback(sender, eventname);
}
},
this); // <-Third parameter for the extended callback
}
```
```

170
data/js/controls.js vendored
View File

@ -60,8 +60,6 @@ const UPDATE_SEPARATOR = 119;
const UI_TIME = 20;
const UPDATE_TIME = 120;
const UI_FRAGMENT = 21;
const UP = 0;
const DOWN = 1;
const LEFT = 2;
@ -79,8 +77,6 @@ const C_ALIZARIN = 6;
const C_DARK = 7;
const C_NONE = 255;
var controlAssemblyArray = new Object();
var FragmentAssemblyTimer = new Object();
var graphData = new Array();
var hasAccel = false;
var sliderContinuous = false;
@ -194,12 +190,6 @@ function restart() {
}
function conStatusError() {
FragmentAssemblyTimer.forEach(element => {
clearInterval(element);
});
FragmentAssemblyTimer = new Object();
controlAssemblyArray = new Object();
if (true === websockConnected) {
websockConnected = false;
websock.close();
@ -220,20 +210,17 @@ function handleVisibilityChange() {
}
function start() {
let location = window.location.hostname;
let port = window.location.port;
// let location = "192.168.10.229";
// let port = "";
document.addEventListener("visibilitychange", handleVisibilityChange, false);
if (
port != "" ||
port != 80 ||
port != 443
window.location.port != "" ||
window.location.port != 80 ||
window.location.port != 443
) {
websock = new WebSocket( "ws://" + location + "/ws" );
websock = new WebSocket(
"ws://" + window.location.hostname + ":" + window.location.port + "/ws"
);
} else {
websock = new WebSocket("ws://" + location + "/ws");
websock = new WebSocket("ws://" + window.location.hostname + "/ws");
}
// is the timer running?
@ -254,54 +241,33 @@ function start() {
$("#conStatus").addClass("color-green");
$("#conStatus").text("Connected");
websockConnected = true;
FragmentAssemblyTimer.forEach(element => {
clearInterval(element);
});
FragmentAssemblyTimer = new Object();
controlAssemblyArray = new Object();
};
websock.onclose = function (evt) {
// console.log("Close evt: '" + evt + "'");
// console.log("Close reason: '" + evt.reason + "'");
// console.log("Close code: '" + evt.code + "'");
console.log("websock close");
conStatusError();
FragmentAssemblyTimer.forEach(element => {
clearInterval(element);
});
FragmentAssemblyTimer = new Object();
controlAssemblyArray = new Object();
};
websock.onerror = function (evt) {
console.log("websock Error");
// console.log("Error evt: '" + evt + "'");
// console.log("Error data: '" + evt.data + "'");
console.log(evt);
restart();
FragmentAssemblyTimer.forEach(element => {
clearInterval(element);
});
FragmentAssemblyTimer = new Object();
controlAssemblyArray = new Object();
};
var handleEvent = function (evt) {
// console.log("handleEvent:Data evt: '" + evt + "'");
// console.log("handleEvent:Data data: '" + evt.data + "'");
console.log(evt);
try {
var data = JSON.parse(evt.data);
}
catch (Event) {
console.error(Event);
// console.info("start the update over again");
// start the update over again
websock.send("uiok:" + 0);
return;
}
var e = document.body;
var center = "";
// console.info("data.type: '" + data.type + "'");
switch (data.type) {
case UI_INITIAL_GUI:
@ -313,9 +279,7 @@ function start() {
if (data.sliderContinuous) {
sliderContinuous = data.sliderContinuous;
}
// console.info("UI_INITIAL_GUI:data record: '" + data + "'");
data.controls.forEach(element => {
// console.info("element: '" + JSON.stringify(element) + "'");
var fauxEvent = {
data: JSON.stringify(element),
};
@ -331,9 +295,7 @@ function start() {
break;
case UI_EXTEND_GUI:
// console.info("UI_EXTEND_GUI data record: '" + data + "'");
data.controls.forEach(element => {
// console.info("UI_EXTEND_GUI:element: '" + JSON.stringify(element) + "'");
var fauxEvent = {
data: JSON.stringify(element),
};
@ -639,88 +601,6 @@ function start() {
websock.send("time:" + rv + ":" + data.id);
break;
case UI_FRAGMENT:
let FragmentLen = data.length;
let FragementOffset = data.offset;
let NextFragmentOffset = FragementOffset + FragmentLen;
let Total = data.total;
let Arrived = (FragmentLen + FragementOffset);
let FragmentFinal = Total === Arrived;
// console.info("UI_FRAGMENT:FragmentLen '" + FragmentLen + "'");
// console.info("UI_FRAGMENT:FragementOffset '" + FragementOffset + "'");
// console.info("UI_FRAGMENT:NextFragmentOffset '" + NextFragmentOffset + "'");
// console.info("UI_FRAGMENT:Total '" + Total + "'");
// console.info("UI_FRAGMENT:Arrived '" + Arrived + "'");
// console.info("UI_FRAGMENT:FragmentFinal '" + FragmentFinal + "'");
if (!data.hasOwnProperty('control'))
{
console.error("UI_FRAGMENT:Missing control record, skipping control");
break;
}
let control = data.control;
StopFragmentAssemblyTimer(data.control.id);
// is this the first fragment?
if(0 === FragementOffset)
{
// console.info("Found first fragment");
controlAssemblyArray[control.id] = data;
// console.info("Value: " + controlAssemblyArray[control.id].control.value);
controlAssemblyArray[control.id].offset = NextFragmentOffset;
StartFragmentAssemblyTimer(control.id);
let TotalRequest = JSON.stringify({ 'id' : control.id, 'offset' : NextFragmentOffset });
websock.send("uifragmentok:" + 0 + ": " + TotalRequest + ":");
// console.info("asked for fragment 2");
break;
}
// not first fragment. are we assembling this control?
if("undefined" === typeof controlAssemblyArray[control.id])
{
// it looks like we missed the first fragment. Start the control over
console.error("Missing first fragment for control: " + control.id);
StartFragmentAssemblyTimer(control.id);
let TotalRequest = JSON.stringify({ 'id' : control.id, 'offset' : 0 });
websock.send("uifragmentok:" + 0 + ": " + TotalRequest + ":");
// console.info("asked for fragment 1");
break;
}
// is this the expected next fragment
if(FragementOffset !== controlAssemblyArray[control.id].offset)
{
console.error("Wrong next fragment. Expected: " + controlAssemblyArray[control.id].offset + " Got: " + FragementOffset);
StartFragmentAssemblyTimer(control.id);
let TotalRequest = JSON.stringify({ 'id' : control.id, 'offset' : controlAssemblyArray[control.id].length + controlAssemblyArray[control.id].offset });
websock.send("uifragmentok:" + 0 + ": " + TotalRequest + ":");
// console.info("asked for the expected fragment");
break;
}
// console.info("Add to existing fragment");
controlAssemblyArray[control.id].control.value += control.value;
controlAssemblyArray[control.id].offset = NextFragmentOffset;
// console.info("Value: " + controlAssemblyArray[control.id].control.value);
if(true === FragmentFinal)
{
var fauxEvent = {
data: JSON.stringify(controlAssemblyArray[control.id].control),
};
handleEvent(fauxEvent);
controlAssemblyArray[control.id] = null;
// console.info("Found last fragment");
}
else
{
// console.info("Ask for next fragment.");
StartFragmentAssemblyTimer(control.id);
let TotalRequest = JSON.stringify({ 'id' : control.id, 'offset' : NextFragmentOffset});
websock.send("uifragmentok:" + 0 + ": " + TotalRequest + ":");
}
break;
default:
console.error("Unknown type or event");
break;
@ -770,36 +650,6 @@ function start() {
websock.onmessage = handleEvent;
}
function StartFragmentAssemblyTimer(Id)
{
StopFragmentAssemblyTimer(Id);
FragmentAssemblyTimer[Id] = setInterval(function(_Id)
{
// does the fragment assembly still exist?
if("undefined" !== typeof controlAssemblyArray[_Id])
{
if(null !== controlAssemblyArray[_Id])
{
// we have a valid control that is being assembled
// ask for the next part
let TotalRequest = JSON.stringify({ 'id' : controlAssemblyArray[_Id].control.id, 'offset' : controlAssemblyArray[_Id].offset});
websock.send("uifragmentok:" + 0 + ": " + TotalRequest + ":");
}
}
}, 1000, Id);
}
function StopFragmentAssemblyTimer(Id)
{
if("undefined" !== typeof FragmentAssemblyTimer[Id])
{
if(FragmentAssemblyTimer[Id])
{
clearInterval(FragmentAssemblyTimer[Id]);
}
}
}
function sliderchange(number) {
var val = $("#sl" + number).val();
websock.send("slvalue:" + val + ":" + number);

View File

@ -1,14 +1,14 @@
const UI_INITIAL_GUI=200;const UI_RELOAD=201;const UPDATE_OFFSET=100;const UI_EXTEND_GUI=210;const UI_TITEL=0;const UI_PAD=1;const UPDATE_PAD=101;const UI_CPAD=2;const UPDATE_CPAD=102;const UI_BUTTON=3;const UPDATE_BUTTON=103;const UI_LABEL=4;const UPDATE_LABEL=104;const UI_SWITCHER=5;const UPDATE_SWITCHER=105;const UI_SLIDER=6;const UPDATE_SLIDER=106;const UI_NUMBER=7;const UPDATE_NUMBER=107;const UI_TEXT_INPUT=8;const UPDATE_TEXT_INPUT=108;const UI_GRAPH=9;const ADD_GRAPH_POINT=10;const CLEAR_GRAPH=109;const UI_TAB=11;const UPDATE_TAB=111;const UI_SELECT=12;const UPDATE_SELECT=112;const UI_OPTION=13;const UPDATE_OPTION=113;const UI_MIN=14;const UPDATE_MIN=114;const UI_MAX=15;const UPDATE_MAX=115;const UI_STEP=16;const UPDATE_STEP=116;const UI_GAUGE=17;const UPDATE_GAUGE=117;const UI_ACCEL=18;const UPDATE_ACCEL=118;const UI_SEPARATOR=19;const UPDATE_SEPARATOR=119;const UI_TIME=20;const UPDATE_TIME=120;const UI_FRAGMENT=21;const UP=0;const DOWN=1;const LEFT=2;const RIGHT=3;const CENTER=4;const C_TURQUOISE=0;const C_EMERALD=1;const C_PETERRIVER=2;const C_WETASPHALT=3;const C_SUNFLOWER=4;const C_CARROT=5;const C_ALIZARIN=6;const C_DARK=7;const C_NONE=255;var controlAssemblyArray=new Object();var FragmentAssemblyTimer=new Object();var graphData=new Array();var hasAccel=false;var sliderContinuous=false;function colorClass(colorId){colorId=Number(colorId);switch(colorId){case C_TURQUOISE:return"turquoise";case C_EMERALD:return"emerald";case C_PETERRIVER:return"peterriver";case C_WETASPHALT:return"wetasphalt";case C_SUNFLOWER:return"sunflower";case C_CARROT:return"carrot";case C_ALIZARIN:return"alizarin";case C_DARK:case C_NONE:return"dark";default:return"";}}
const UI_INITIAL_GUI=200;const UI_RELOAD=201;const UPDATE_OFFSET=100;const UI_EXTEND_GUI=210;const UI_TITEL=0;const UI_PAD=1;const UPDATE_PAD=101;const UI_CPAD=2;const UPDATE_CPAD=102;const UI_BUTTON=3;const UPDATE_BUTTON=103;const UI_LABEL=4;const UPDATE_LABEL=104;const UI_SWITCHER=5;const UPDATE_SWITCHER=105;const UI_SLIDER=6;const UPDATE_SLIDER=106;const UI_NUMBER=7;const UPDATE_NUMBER=107;const UI_TEXT_INPUT=8;const UPDATE_TEXT_INPUT=108;const UI_GRAPH=9;const ADD_GRAPH_POINT=10;const CLEAR_GRAPH=109;const UI_TAB=11;const UPDATE_TAB=111;const UI_SELECT=12;const UPDATE_SELECT=112;const UI_OPTION=13;const UPDATE_OPTION=113;const UI_MIN=14;const UPDATE_MIN=114;const UI_MAX=15;const UPDATE_MAX=115;const UI_STEP=16;const UPDATE_STEP=116;const UI_GAUGE=17;const UPDATE_GAUGE=117;const UI_ACCEL=18;const UPDATE_ACCEL=118;const UI_SEPARATOR=19;const UPDATE_SEPARATOR=119;const UI_TIME=20;const UPDATE_TIME=120;const UP=0;const DOWN=1;const LEFT=2;const RIGHT=3;const CENTER=4;const C_TURQUOISE=0;const C_EMERALD=1;const C_PETERRIVER=2;const C_WETASPHALT=3;const C_SUNFLOWER=4;const C_CARROT=5;const C_ALIZARIN=6;const C_DARK=7;const C_NONE=255;var graphData=new Array();var hasAccel=false;var sliderContinuous=false;function colorClass(colorId){colorId=Number(colorId);switch(colorId){case C_TURQUOISE:return"turquoise";case C_EMERALD:return"emerald";case C_PETERRIVER:return"peterriver";case C_WETASPHALT:return"wetasphalt";case C_SUNFLOWER:return"sunflower";case C_CARROT:return"carrot";case C_ALIZARIN:return"alizarin";case C_DARK:case C_NONE:return"dark";default:return"";}}
var websock;var websockConnected=false;var WebSocketTimer=null;function requestOrientationPermission(){}
function saveGraphData(){localStorage.setItem("espuigraphs",JSON.stringify(graphData));}
function restoreGraphData(id){var savedData=localStorage.getItem("espuigraphs",graphData);if(savedData!=null){savedData=JSON.parse(savedData);let idData=savedData[id];return Array.isArray(idData)?idData:[];}
return[];}
function restart(){$(document).add("*").off();$("#row").html("");conStatusError();start();}
function conStatusError(){FragmentAssemblyTimer.forEach(element=>{clearInterval(element);});FragmentAssemblyTimer=new Object();controlAssemblyArray=new Object();if(true===websockConnected){websockConnected=false;websock.close();$("#conStatus").removeClass("color-green");$("#conStatus").addClass("color-red");$("#conStatus").html("Error / No Connection &#8635;");$("#conStatus").off();$("#conStatus").on({click:restart,});}}
function conStatusError(){if(true===websockConnected){websockConnected=false;websock.close();$("#conStatus").removeClass("color-green");$("#conStatus").addClass("color-red");$("#conStatus").html("Error / No Connection &#8635;");$("#conStatus").off();$("#conStatus").on({click:restart,});}}
function handleVisibilityChange(){if(!websockConnected&&!document.hidden){restart();}}
function start(){let location=window.location.hostname;let port=window.location.port;document.addEventListener("visibilitychange",handleVisibilityChange,false);if(port!=""||port!=80||port!=443){websock=new WebSocket("ws://"+location+"/ws");}else{websock=new WebSocket("ws://"+location+"/ws");}
function start(){document.addEventListener("visibilitychange",handleVisibilityChange,false);if(window.location.port!=""||window.location.port!=80||window.location.port!=443){websock=new WebSocket("ws://"+window.location.hostname+":"+window.location.port+"/ws");}else{websock=new WebSocket("ws://"+window.location.hostname+"/ws");}
if(null===WebSocketTimer){WebSocketTimer=setInterval(function(){if(websock.readyState===3){restart();}},5000);}
websock.onopen=function(evt){console.log("websock open");$("#conStatus").addClass("color-green");$("#conStatus").text("Connected");websockConnected=true;FragmentAssemblyTimer.forEach(element=>{clearInterval(element);});FragmentAssemblyTimer=new Object();controlAssemblyArray=new Object();};websock.onclose=function(evt){console.log("websock close");conStatusError();FragmentAssemblyTimer.forEach(element=>{clearInterval(element);});FragmentAssemblyTimer=new Object();controlAssemblyArray=new Object();};websock.onerror=function(evt){console.log("websock Error");restart();FragmentAssemblyTimer.forEach(element=>{clearInterval(element);});FragmentAssemblyTimer=new Object();controlAssemblyArray=new Object();};var handleEvent=function(evt){try{var data=JSON.parse(evt.data);}
websock.onopen=function(evt){console.log("websock open");$("#conStatus").addClass("color-green");$("#conStatus").text("Connected");websockConnected=true;};websock.onclose=function(evt){console.log("websock close");conStatusError();};websock.onerror=function(evt){console.log("websock Error");console.log(evt);restart();};var handleEvent=function(evt){console.log(evt);try{var data=JSON.parse(evt.data);}
catch(Event){console.error(Event);websock.send("uiok:"+0);return;}
var e=document.body;var center="";switch(data.type){case UI_INITIAL_GUI:$("#row").html("");$("#tabsnav").html("");$("#tabscontent").html("");if(data.sliderContinuous){sliderContinuous=data.sliderContinuous;}
data.controls.forEach(element=>{var fauxEvent={data:JSON.stringify(element),};handleEvent(fauxEvent);});if(data.totalcontrols>(data.controls.length-1)){websock.send("uiok:"+(data.controls.length-1));}
@ -43,19 +43,7 @@ if(data.hasOwnProperty('inputType')){$("#text"+data.id).attr("type",data.inputTy
break;case UPDATE_SELECT:$("#select"+data.id).val(data.value);if(data.hasOwnProperty('elementStyle')){$("#select"+data.id).attr("style",data.elementStyle);}
break;case UPDATE_BUTTON:$("#btn"+data.id).val(data.value);$("#btn"+data.id).text(data.value);if(data.hasOwnProperty('elementStyle')){$("#btn"+data.id).attr("style",data.elementStyle);}
break;case UPDATE_PAD:case UPDATE_CPAD:break;case UPDATE_GAUGE:$("#gauge"+data.id).val(data.value);if(data.hasOwnProperty('elementStyle')){$("#gauge"+data.id).attr("style",data.elementStyle);}
break;case UPDATE_ACCEL:break;case UPDATE_TIME:var rv=new Date().toISOString();websock.send("time:"+rv+":"+data.id);break;case UI_FRAGMENT:let FragmentLen=data.length;let FragementOffset=data.offset;let NextFragmentOffset=FragementOffset+FragmentLen;let Total=data.total;let Arrived=(FragmentLen+FragementOffset);let FragmentFinal=Total===Arrived;if(!data.hasOwnProperty('control'))
{console.error("UI_FRAGMENT:Missing control record, skipping control");break;}
let control=data.control;StopFragmentAssemblyTimer(data.control.id);if(0===FragementOffset)
{controlAssemblyArray[control.id]=data;controlAssemblyArray[control.id].offset=NextFragmentOffset;StartFragmentAssemblyTimer(control.id);let TotalRequest=JSON.stringify({'id':control.id,'offset':NextFragmentOffset});websock.send("uifragmentok:"+0+": "+TotalRequest+":");break;}
if("undefined"===typeof controlAssemblyArray[control.id])
{console.error("Missing first fragment for control: "+control.id);StartFragmentAssemblyTimer(control.id);let TotalRequest=JSON.stringify({'id':control.id,'offset':0});websock.send("uifragmentok:"+0+": "+TotalRequest+":");break;}
if(FragementOffset!==controlAssemblyArray[control.id].offset)
{console.error("Wrong next fragment. Expected: "+controlAssemblyArray[control.id].offset+" Got: "+FragementOffset);StartFragmentAssemblyTimer(control.id);let TotalRequest=JSON.stringify({'id':control.id,'offset':controlAssemblyArray[control.id].length+controlAssemblyArray[control.id].offset});websock.send("uifragmentok:"+0+": "+TotalRequest+":");break;}
controlAssemblyArray[control.id].control.value+=control.value;controlAssemblyArray[control.id].offset=NextFragmentOffset;if(true===FragmentFinal)
{var fauxEvent={data:JSON.stringify(controlAssemblyArray[control.id].control),};handleEvent(fauxEvent);controlAssemblyArray[control.id]=null;}
else
{StartFragmentAssemblyTimer(control.id);let TotalRequest=JSON.stringify({'id':control.id,'offset':NextFragmentOffset});websock.send("uifragmentok:"+0+": "+TotalRequest+":");}
break;default:console.error("Unknown type or event");break;}
break;case UPDATE_ACCEL:break;case UPDATE_TIME:var rv=new Date().toISOString();websock.send("time:"+rv+":"+data.id);break;default:console.error("Unknown type or event");break;}
if(data.type>=UI_TITEL&&data.type<UPDATE_OFFSET){processEnabled(data);}
if(data.type>=UPDATE_OFFSET&&data.type<UI_INITIAL_GUI){var element=$("#id"+data.id);if(data.hasOwnProperty('panelStyle')){$("#id"+data.id).attr("style",data.panelStyle);}
if(data.hasOwnProperty('visible')){if(data['visible'])
@ -64,15 +52,6 @@ $("#id"+data.id).hide();}
if(data.type==UPDATE_SLIDER){element.removeClass("slider-turquoise slider-emerald slider-peterriver slider-wetasphalt slider-sunflower slider-carrot slider-alizarin");element.addClass("slider-"+colorClass(data.color));}else{element.removeClass("turquoise emerald peterriver wetasphalt sunflower carrot alizarin");element.addClass(colorClass(data.color));}
processEnabled(data);}
$(".range-slider__range").each(function(){$(this)[0].value=$(this).attr("value");$(this).next().html($(this).attr("value"));});};websock.onmessage=handleEvent;}
function StartFragmentAssemblyTimer(Id)
{StopFragmentAssemblyTimer(Id);FragmentAssemblyTimer[Id]=setInterval(function(_Id)
{if("undefined"!==typeof controlAssemblyArray[_Id])
{if(null!==controlAssemblyArray[_Id])
{let TotalRequest=JSON.stringify({'id':controlAssemblyArray[_Id].control.id,'offset':controlAssemblyArray[_Id].offset});websock.send("uifragmentok:"+0+": "+TotalRequest+":");}}},1000,Id);}
function StopFragmentAssemblyTimer(Id)
{if("undefined"!==typeof FragmentAssemblyTimer[Id])
{if(FragmentAssemblyTimer[Id])
{clearInterval(FragmentAssemblyTimer[Id]);}}}
function sliderchange(number){var val=$("#sl"+number).val();websock.send("slvalue:"+val+":"+number);$(".range-slider__range").each(function(){$(this).attr("value",$(this)[0].value);});}
function numberchange(number){var val=$("#num"+number).val();websock.send("nvalue:"+val+":"+number);}
function textchange(number){var val=$("#text"+number).val();websock.send("tvalue:"+val+":"+number);}

View File

@ -30,7 +30,6 @@
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <umm_malloc/umm_heap_select.h>
#ifndef CORE_MOCK
#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)
@ -40,7 +39,6 @@
#error on ESP8266 and ESPUI, you must define OOM debug option when developping
#endif
#endif
#endif
//Settings
#define SLOW_BOOT 0
@ -398,8 +396,7 @@ void extendedCallback(Control* sender, int type, void* param)
Serial.print(sender->label);
Serial.print("' = ");
Serial.println(sender->value);
Serial.print("param = ");
Serial.println((long)param);
Serial.println(String("param = ") + String((int)param));
}
void setup() {
@ -446,7 +443,6 @@ void loop() {
#if !defined(ESP32)
((void (*)())0xf00fdead)();
#endif
break;
default:
Serial.print('#');
break;

View File

@ -1,4 +1 @@
// placeholder
#if CORE_MOCK
#include "completeExample.cpp"
#endif

View File

@ -11,17 +11,15 @@ DNSServer dnsServer;
// esp8266
#include <ESP8266WiFi.h>
#include <umm_malloc/umm_heap_select.h>
#ifndef CORE_MOCK
#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
#if !defined(DEBUG_ESP_OOM)
#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* password = "espui";
@ -69,8 +67,7 @@ void buttonCallback(Control* sender, int type)
void buttonExample(Control* sender, int type, void* param)
{
Serial.print("param: ");
Serial.println((long)param);
Serial.println(String("param: ") + String(long(param)));
switch (type)
{
case B_DOWN:

View File

@ -11,7 +11,6 @@ DNSServer dnsServer;
// esp8266
#include <ESP8266WiFi.h>
#include <umm_malloc/umm_heap_select.h>
#ifndef CORE_MOCK
#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)
@ -21,7 +20,6 @@ DNSServer dnsServer;
#error on ESP8266 and ESPUI, you must define OOM debug option when developping
#endif
#endif
#endif
const char* ssid = "ESPUI";
const char* password = "espui";
@ -74,8 +72,7 @@ void buttonCallback(Control* sender, int type)
void buttonExample(Control* sender, int type, void* param)
{
Serial.print("param: ");
Serial.println((long)param);
Serial.println(String("param: ") + String(long(param)));
switch (type)
{
case B_DOWN:

View File

@ -11,7 +11,6 @@ DNSServer dnsServer;
// esp8266
#include <ESP8266WiFi.h>
#include <umm_malloc/umm_heap_select.h>
#ifndef CORE_MOCK
#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)
@ -21,7 +20,6 @@ DNSServer dnsServer;
#error on ESP8266 and ESPUI, you must define OOM debug option when developping
#endif
#endif
#endif
const char* ssid = "ESPUI";
const char* password = "espui";
@ -68,8 +66,7 @@ void buttonCallback(Control* sender, int type)
void buttonExample(Control* sender, int type, void* param)
{
Serial.print("param: ");
Serial.println((long)param);
Serial.println(String("param: ") + String(long(param)));
switch (type)
{
case B_DOWN:

View File

@ -24,6 +24,11 @@
"name": "ArduinoJson",
"authors": "Benoit Blanchon",
"frameworks": "arduino"
},
{
"name": "LittleFS_esp32",
"authors": "lorol",
"frameworks": "arduino"
}
],
"version": "2.2.3",

View File

@ -5,7 +5,11 @@
#include <ESPAsyncWebServer.h>
#include "dataControlsJS.h"
#ifndef ESPU_DISABLE_GRAPH
#include "dataGraphJS.h"
#endif
#include "dataIndexHTML.h"
#include "dataNormalizeCSS.h"
#include "dataSliderJS.h"
@ -17,6 +21,14 @@
#include <umm_malloc/umm_heap_select.h>
#endif
#if defined(DEBUG) && defined(ESPU_DEBUG)
#define ESPU_DBG(arg) Serial.print(arg)
#define ESPU_DBGL(arg) Serial.println(arg)
#else
#define ESPU_DBG(arg)
#define ESPU_DBGL(arg)
#endif
static String heapInfo(const __FlashStringHelper* mode)
{
String result;
@ -72,7 +84,7 @@ void listDir(const char* dirname, uint8_t levels)
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.printf_P(PSTR("Listing directory: %s\n"), dirname);
ESPU_DBGf_P(PSTR("Listing directory: %s\n"), dirname);
}
#endif
@ -91,7 +103,7 @@ void listDir(const char* dirname, uint8_t levels)
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.println(F("Failed to open directory"));
ESPU_DBGL(F("Failed to open directory"));
}
#endif
@ -103,7 +115,7 @@ void listDir(const char* dirname, uint8_t levels)
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.println(F("Not a directory"));
ESPU_DBGL(F("Not a directory"));
}
#endif
@ -119,8 +131,8 @@ void listDir(const char* dirname, uint8_t levels)
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.print(F(" DIR : "));
Serial.println(file.name());
ESPU_DBG(F(" DIR : "));
ESPU_DBGL(file.name());
}
#endif
@ -138,10 +150,10 @@ void listDir(const char* dirname, uint8_t levels)
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.print(F(" FILE: "));
Serial.print(file.name());
Serial.print(F(" SIZE: "));
Serial.println(file.size());
ESPU_DBG(F(" FILE: "));
ESPU_DBG(file.name());
ESPU_DBG(F(" SIZE: "));
ESPU_DBGL(file.size());
}
#endif
}
@ -156,7 +168,7 @@ void listDir(const char* dirname, uint8_t levels)
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.printf_P(PSTR("Listing directory: %s\n"), dirname);
ESPU_DBGf_P(PSTR("Listing directory: %s\n"), dirname);
}
#endif
@ -169,8 +181,8 @@ void listDir(const char* dirname, uint8_t levels)
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.print(F(" DIR : "));
Serial.println(dir.fileName());
ESPU_DBG(F(" DIR : "));
ESPU_DBGL(dir.fileName());
}
#endif
if (levels)
@ -185,10 +197,10 @@ void listDir(const char* dirname, uint8_t levels)
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.print(F(" FILE: "));
Serial.print(dir.fileName());
Serial.print(F(" SIZE: "));
Serial.println(dir.fileSize());
ESPU_DBG(F(" FILE: "));
ESPU_DBG(dir.fileName());
ESPU_DBG(F(" SIZE: "));
ESPU_DBGL(dir.fileSize());
}
#endif
}
@ -206,13 +218,13 @@ void ESPUIClass::list()
if (!LITTLEFS.begin())
#endif
{
Serial.println(F("LITTLEFS Mount Failed"));
ESPU_DBGL(F("LITTLEFS Mount Failed"));
return;
}
#else
if (!LittleFS.begin())
{
Serial.println(F("LittleFS Mount Failed"));
ESPU_DBG(F("LittleFS Mount Failed"));
return;
}
#endif
@ -220,27 +232,27 @@ void ESPUIClass::list()
listDir("/", 1);
#if defined(ESP32)
Serial.print(F("Total KB: "));
ESPU_DBG(F("Total KB: "));
#if (ESP_IDF_VERSION_MAJOR == 4 && ESP_IDF_VERSION_MINOR >= 4) || ESP_IDF_VERSION_MAJOR > 4
Serial.println(LittleFS.totalBytes() / 1024);
ESPU_DBGL(LittleFS.totalBytes() / 1024);
#else
Serial.println(LITTLEFS.totalBytes() / 1024);
ESPU_DBGL(LITTLEFS.totalBytes() / 1024);
#endif
Serial.print(F("Used KB: "));
ESPU_DBG(F("Used KB: "));
#if (ESP_IDF_VERSION_MAJOR == 4 && ESP_IDF_VERSION_MINOR >= 4) || ESP_IDF_VERSION_MAJOR > 4
Serial.println(LittleFS.usedBytes() / 1024);
ESPU_DBGL(LittleFS.usedBytes() / 1024);
#else
Serial.println(LITTLEFS.usedBytes() / 1024);
ESPU_DBGL(LITTLEFS.usedBytes() / 1024);
#endif
#else
FSInfo fs_info;
LittleFS.info(fs_info);
Serial.print(F("Total KB: "));
Serial.println(fs_info.totalBytes / 1024);
Serial.print(F("Used KB: "));
Serial.println(fs_info.usedBytes / 1024);
ESPU_DBG(F("Total KB: "));
ESPU_DBGL(fs_info.totalBytes / 1024);
ESPU_DBG(F("Used KB: "));
ESPU_DBGL(fs_info.usedBytes / 1024);
#endif
}
@ -261,7 +273,7 @@ void deleteFile(const char* path)
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.printf_P(PSTR("File: %s does not exist, not deleting\n"), path);
ESPU_DBGf_P(PSTR("File: %s does not exist, not deleting\n"), path);
}
#endif
@ -271,7 +283,7 @@ void deleteFile(const char* path)
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.printf_P(PSTR("Deleting file: %s\n"), path);
ESPU_DBGf_P(PSTR("Deleting file: %s\n"), path);
}
#endif
@ -289,7 +301,7 @@ void deleteFile(const char* path)
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.println(F("File deleted"));
ESPU_DBGL(F("File deleted"));
}
#endif
}
@ -298,7 +310,7 @@ void deleteFile(const char* path)
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.println(F("Delete failed"));
ESPU_DBGL(F("Delete failed"));
}
#endif
}
@ -309,7 +321,7 @@ void writeFile(const char* path, const char* data)
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.printf_P(PSTR("Writing file: %s\n"), path);
ESPU_DBGf_P(PSTR("Writing file: %s\n"), path);
}
#endif
@ -327,7 +339,7 @@ void writeFile(const char* path, const char* data)
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.println(F("Failed to open file for writing"));
ESPU_DBGL(F("Failed to open file for writing"));
}
#endif
@ -341,7 +353,7 @@ void writeFile(const char* path, const char* data)
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.println(F("File written"));
ESPU_DBGL(F("File written"));
}
#endif
}
@ -350,7 +362,7 @@ void writeFile(const char* path, const char* data)
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.println(F("Write failed"));
ESPU_DBGL(F("Write failed"));
}
#endif
}
@ -362,7 +374,7 @@ void writeFile(const char* path, const char* data)
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.println(F("File written"));
ESPU_DBGL(F("File written"));
}
#endif
}
@ -371,7 +383,7 @@ void writeFile(const char* path, const char* data)
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.println(F("Write failed"));
ESPU_DBGL(F("Write failed"));
}
#endif
}
@ -389,7 +401,7 @@ void ESPUIClass::prepareFileSystem(bool format)
#if defined(DEBUG_ESPUI)
if (verbosity)
{
Serial.println(F("About to prepare filesystem..."));
ESPU_DBGL(F("About to prepare filesystem..."));
}
#endif
@ -409,7 +421,7 @@ void ESPUIClass::prepareFileSystem(bool format)
#if defined(DEBUG_ESPUI)
if (verbosity)
{
Serial.println(F("LittleFS Format Failed"));
ESPU_DBGL(F("LittleFS Format Failed"));
}
#endif
return;
@ -425,7 +437,7 @@ void ESPUIClass::prepareFileSystem(bool format)
#if defined(DEBUG_ESPUI)
if (verbosity)
{
Serial.println(F("LittleFS Formatted"));
ESPU_DBGL(F("LittleFS Formatted"));
}
#endif
}
@ -434,7 +446,7 @@ void ESPUIClass::prepareFileSystem(bool format)
if (verbosity)
{
listDir("/", 1);
Serial.println(F("LittleFS Mount ESP32 Done"));
ESPU_DBGL(F("LittleFS Mount ESP32 Done"));
}
#endif
@ -447,7 +459,7 @@ void ESPUIClass::prepareFileSystem(bool format)
#if defined(DEBUG_ESPUI)
if (verbosity)
{
Serial.println(F("LittleFS Formatted"));
ESPU_DBGL(F("LittleFS Formatted"));
}
#endif
}
@ -456,7 +468,7 @@ void ESPUIClass::prepareFileSystem(bool format)
#if defined(DEBUG_ESPUI)
if (verbosity)
{
Serial.println(F("LittleFS Mount Failed"));
ESPU_DBGL(F("LittleFS Mount Failed"));
}
#endif
return;
@ -468,7 +480,7 @@ void ESPUIClass::prepareFileSystem(bool format)
#if defined(DEBUG_ESPUI)
if (verbosity)
{
Serial.println(F("LittleFS Formatted"));
ESPU_DBGL(F("LittleFS Formatted"));
}
#endif
}
@ -477,7 +489,7 @@ void ESPUIClass::prepareFileSystem(bool format)
if (verbosity)
{
listDir("/", 1);
Serial.println(F("LittleFS Mount ESP8266 Done"));
ESPU_DBGL(F("LittleFS Mount ESP8266 Done"));
}
#endif
@ -491,13 +503,15 @@ void ESPUIClass::prepareFileSystem(bool format)
deleteFile("/js/zepto.min.js");
deleteFile("/js/controls.js");
deleteFile("/js/slider.js");
#ifndef ESPU_DISABLE_GRAPH
deleteFile("/js/graph.js");
#endif
deleteFile("/js/tabbedcontent.js");
#if defined(DEBUG_ESPUI)
if (verbosity)
{
Serial.println(F("Cleanup done"));
ESPU_DBGL(F("Cleanup done"));
}
#endif
@ -512,8 +526,9 @@ void ESPUIClass::prepareFileSystem(bool format)
writeFile("/js/zepto.min.js", JS_ZEPTO);
writeFile("/js/controls.js", JS_CONTROLS);
writeFile("/js/slider.js", JS_SLIDER);
#ifndef ESPU_DISABLE_GRAPH
writeFile("/js/graph.js", JS_GRAPH);
#endif
writeFile("/js/tabbedcontent.js", JS_TABBEDCONTENT);
#else
writeFile("/index.htm", HTML_INDEX);
@ -524,8 +539,9 @@ void ESPUIClass::prepareFileSystem(bool format)
writeFile("/js/zepto.min.js", JS_ZEPTO);
writeFile("/js/controls.js", JS_CONTROLS);
writeFile("/js/slider.js", JS_SLIDER);
#ifndef ESPU_DISABLE_GRAPH
writeFile("/js/graph.js", JS_GRAPH);
#endif
writeFile("/js/tabbedcontent.js", JS_TABBEDCONTENT);
#endif
#else
@ -537,15 +553,16 @@ void ESPUIClass::prepareFileSystem(bool format)
writeFile("/js/zepto.min.js", JS_ZEPTO);
writeFile("/js/controls.js", JS_CONTROLS);
writeFile("/js/slider.js", JS_SLIDER);
#ifndef ESPU_DISABLE_GRAPH
writeFile("/js/graph.js", JS_GRAPH);
#endif
writeFile("/js/tabbedcontent.js", JS_TABBEDCONTENT);
#endif
#if defined(DEBUG_ESPUI)
if (verbosity)
{
Serial.println(F("Done Initializing filesystem :-)"));
ESPU_DBGL(F("Done Initializing filesystem :-)"));
}
#endif
@ -575,7 +592,7 @@ void ESPUIClass::prepareFileSystem(bool format)
void ESPUIClass::onWsEvent(
AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len)
{
// Serial.println(String("ESPUIClass::OnWsEvent: type: ") + String(type));
// ESPU_DBGL(String("ESPUIClass::OnWsEvent: type: ") + String(type));
RemoveToBeDeletedControls();
if (WS_EVT_DISCONNECT == type)
@ -583,13 +600,13 @@ void ESPUIClass::onWsEvent(
#if defined(DEBUG_ESPUI)
if (verbosity)
{
Serial.println(F("WS_EVT_DISCONNECT"));
ESPU_DBGL(F("WS_EVT_DISCONNECT"));
}
#endif
if (MapOfClients.end() != MapOfClients.find(client->id()))
{
// Serial.println("Delete client.");
// ESPU_DBGL("Delete client.");
delete MapOfClients[client->id()];
MapOfClients.erase(client->id());
}
@ -598,13 +615,13 @@ void ESPUIClass::onWsEvent(
{
if (MapOfClients.end() == MapOfClients.find(client->id()))
{
// Serial.println("ESPUIClass::OnWsEvent:Create new client.");
// ESPU_DBGL("ESPUIClass::OnWsEvent:Create new client.");
MapOfClients[client->id()] = new ESPUIclient(client);
}
if(MapOfClients[client->id()]->onWsEvent(type, arg, data, len))
{
// Serial.println("ESPUIClass::OnWsEvent:notify the clients that they need to be updated.");
// ESPU_DBGL("ESPUIClass::OnWsEvent:notify the clients that they need to be updated.");
NotifyClients(ESPUIclient::UpdateNeeded);
}
}
@ -702,7 +719,7 @@ bool ESPUIClass::removeControl(uint16_t id, bool force_rebuild_ui)
#ifdef DEBUG_ESPUI
else
{
// Serial.println(String("Could not Remove Control ") + String(id));
// ESPU_DBGL(String("Could not Remove Control ") + String(id));
}
#endif // def DEBUG_ESPUI
@ -919,7 +936,7 @@ void ESPUIClass::setEnabled(uint16_t id, bool enabled, int clientId)
Control* control = getControl(id);
if (control)
{
// Serial.println(String("CreateAllowed: id: ") + String(clientId) + " State: " + String(enabled));
// ESPU_DBGL(String("CreateAllowed: id: ") + String(clientId) + " State: " + String(enabled));
control->enabled = enabled;
updateControl(control, clientId);
}
@ -943,7 +960,7 @@ void ESPUIClass::updateControl(uint16_t id, int clientId)
#if defined(DEBUG_ESPUI)
if (verbosity)
{
Serial.printf_P(PSTR("Error: Update Control: There is no control with ID %d\n"), id);
ESPU_DBGf_P(PSTR("Error: Update Control: There is no control with ID %d\n"), id);
}
#endif
return;
@ -972,7 +989,7 @@ void ESPUIClass::updateControlValue(uint16_t id, const String& value, int client
#if defined(DEBUG_ESPUI)
if (verbosity)
{
Serial.printf_P(PSTR("Error: updateControlValue Control: There is no control with ID %d\n"), id);
ESPU_DBGf_P(PSTR("Error: updateControlValue Control: There is no control with ID %d\n"), id);
}
#endif
return;
@ -993,7 +1010,7 @@ void ESPUIClass::updateControlLabel(Control* control, const char* value, int cli
#if defined(DEBUG_ESPUI)
if (verbosity)
{
Serial.printf_P(PSTR("Error: updateControlLabel Control: There is no control with the requested ID \n"));
ESPU_DBGf_P(PSTR("Error: updateControlLabel Control: There is no control with the requested ID \n"));
}
#endif
return;
@ -1146,7 +1163,7 @@ void ESPUIClass::jsonReload()
{
for (auto& CurrentClient : MapOfClients)
{
// Serial.println("Requesting Reload");
// ESPU_DBGL("Requesting Reload");
CurrentClient.second->NotifyClient(ClientUpdateType_t::ReloadNeeded);
}
}
@ -1189,7 +1206,7 @@ void ESPUIClass::beginLITTLEFS(const char* _title, const char* username, const c
#if defined(DEBUG_ESPUI)
if (verbosity)
{
Serial.println(F("LITTLEFS Mount Failed, PLEASE CHECK THE README ON HOW TO "
ESPU_DBGL(F("LITTLEFS Mount Failed, PLEASE CHECK THE README ON HOW TO "
"PREPARE YOUR ESP!!!!!!!"));
}
#endif
@ -1218,7 +1235,7 @@ void ESPUIClass::beginLITTLEFS(const char* _title, const char* username, const c
#if defined(DEBUG_ESPUI)
if (verbosity)
{
Serial.println(F("Please read the README!!!!!!!, Make sure to "
ESPU_DBGL(F("Please read the README!!!!!!!, Make sure to "
"prepareFileSystem() once in an empty sketch"));
}
#endif
@ -1285,7 +1302,7 @@ void ESPUIClass::beginLITTLEFS(const char* _title, const char* username, const c
#if defined(DEBUG_ESPUI)
if (verbosity)
{
Serial.println(F("UI Initialized"));
ESPU_DBGL(F("UI Initialized"));
}
#endif
}
@ -1365,17 +1382,18 @@ void ESPUIClass::begin(const char* _title, const char* username, const char* pas
request->send(response);
});
#ifndef ESPU_DISABLE_GRAPH
server->on("/js/graph.js", HTTP_GET, [](AsyncWebServerRequest* request) {
if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
{
return request->requestAuthentication();
}
AsyncWebServerResponse* response
= request->beginResponse_P(200, "application/javascript", JS_GRAPH_GZIP, sizeof(JS_GRAPH_GZIP));
response->addHeader("Content-Encoding", "gzip");
request->send(response);
});
#endif
server->on("/js/tabbedcontent.js", HTTP_GET, [](AsyncWebServerRequest* request) {
if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
@ -1445,7 +1463,7 @@ void ESPUIClass::begin(const char* _title, const char* username, const char* pas
#if defined(DEBUG_ESPUI)
if (verbosity)
{
Serial.println(F("UI Initialized"));
ESPU_DBGL(F("UI Initialized"));
}
#endif
}

View File

@ -2,6 +2,15 @@
#include "ESPUIclient.h"
#include "ESPUIcontrol.h"
#if defined(DEBUG) && defined(ESPU_DEBUG)
#define ESPU_DBG(arg) Serial.print(arg)
#define ESPU_DBGL(arg) Serial.println(arg)
#else
#define ESPU_DBG(arg)
#define ESPU_DBGL(arg)
#endif
// JSONSlave:
// helper to process exact JSON serialization size
// it takes ~2ms on esp8266 and avoid large String reallocation which is really worth the cost
@ -100,7 +109,7 @@ bool ESPUIclient::SendClientNotification(ClientUpdateType_t value)
{
if(!CanSend())
{
// Serial.println(F("ESPUIclient::SendClientNotification:CannotSend"));
// ESPU_DBGL(F("ESPUIclient::SendClientNotification:CannotSend"));
break;
}
@ -108,13 +117,13 @@ bool ESPUIclient::SendClientNotification(ClientUpdateType_t value)
FillInHeader(document);
if(ClientUpdateType_t::ReloadNeeded == value)
{
// Serial.println(F("ESPUIclient::SendClientNotification:set type to reload"));
// ESPU_DBGL(F("ESPUIclient::SendClientNotification:set type to reload"));
document["type"] = int(UI_RELOAD);
}
// dont send any controls
Response = SendJsonDocToWebSocket(document);
// Serial.println(String("ESPUIclient::SendClientNotification:NotificationSent:Response: ") + String(Response));
// ESPU_DBGL(String("ESPUIclient::SendClientNotification:NotificationSent:Response: ") + String(Response));
} while (false);
return Response;
@ -130,7 +139,7 @@ void ESPUIclient::NotifyClient(ClientUpdateType_t newState)
bool ESPUIclient::onWsEvent(AwsEventType type, void* arg, uint8_t* data, size_t len)
{
bool Response = false;
// Serial.println(String("ESPUIclient::OnWsEvent: type: ") + String(type));
// ESPU_DBGL(String("ESPUIclient::OnWsEvent: type: ") + String(type));
switch (type)
{
@ -139,7 +148,7 @@ bool ESPUIclient::onWsEvent(AwsEventType type, void* arg, uint8_t* data, size_t
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.println(F("ESPUIclient::OnWsEvent:WS_EVT_PONG"));
ESPU_DBGL(F("ESPUIclient::OnWsEvent:WS_EVT_PONG"));
}
#endif
break;
@ -150,7 +159,7 @@ bool ESPUIclient::onWsEvent(AwsEventType type, void* arg, uint8_t* data, size_t
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.println(F("ESPUIclient::OnWsEvent:WS_EVT_ERROR"));
ESPU_DBGL(F("ESPUIclient::OnWsEvent:WS_EVT_ERROR"));
}
#endif
break;
@ -161,19 +170,19 @@ bool ESPUIclient::onWsEvent(AwsEventType type, void* arg, uint8_t* data, size_t
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.println(F("ESPUIclient::OnWsEvent:WS_EVT_CONNECT"));
Serial.println(client->id());
ESPU_DBGL(F("ESPUIclient::OnWsEvent:WS_EVT_CONNECT"));
ESPU_DBGL(client->id());
}
#endif
// Serial.println("ESPUIclient:onWsEvent:WS_EVT_CONNECT: Call NotifyClient: RebuildNeeded");
// ESPU_DBGL("ESPUIclient:onWsEvent:WS_EVT_CONNECT: Call NotifyClient: RebuildNeeded");
NotifyClient(ClientUpdateType_t::RebuildNeeded);
break;
}
case WS_EVT_DATA:
{
// Serial.println(F("ESPUIclient::OnWsEvent:WS_EVT_DATA"));
// ESPU_DBGL(F("ESPUIclient::OnWsEvent:WS_EVT_DATA"));
String msg = "";
msg.reserve(len + 1);
@ -189,50 +198,50 @@ bool ESPUIclient::onWsEvent(AwsEventType type, void* arg, uint8_t* data, size_t
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity >= Verbosity::VerboseJSON)
{
Serial.println(String(F(" WS msg: ")) + msg);
Serial.println(String(F(" WS cmd: ")) + cmd);
Serial.println(String(F(" WS id: ")) + String(id));
Serial.println(String(F("WS value: ")) + String(value));
ESPU_DBGL(String(F(" WS msg: ")) + msg);
ESPU_DBGL(String(F(" WS cmd: ")) + cmd);
ESPU_DBGL(String(F(" WS id: ")) + String(id));
ESPU_DBGL(String(F("WS value: ")) + String(value));
}
#endif
if (cmd.equals(F("uiok")))
{
// Serial.println(String(F("ESPUIclient::OnWsEvent:WS_EVT_DATA:uiok:ProcessAck:")) + pCurrentFsmState->GetStateName());
// ESPU_DBGL(String(F("ESPUIclient::OnWsEvent:WS_EVT_DATA:uiok:ProcessAck:")) + pCurrentFsmState->GetStateName());
pCurrentFsmState->ProcessAck(id, emptyString);
break;
}
if (cmd.equals(F("uifragmentok")))
{
// Serial.println(String(F("ESPUIclient::OnWsEvent:WS_EVT_DATA:uiok:uifragmentok:")) + pCurrentFsmState->GetStateName() + ":ProcessAck");
// ESPU_DBGL(String(F("ESPUIclient::OnWsEvent:WS_EVT_DATA:uiok:uifragmentok:")) + pCurrentFsmState->GetStateName() + ":ProcessAck");
if(!emptyString.equals(value))
{
// Serial.println(String(F("ESPUIclient::OnWsEvent:WS_EVT_DATA:uiok:uifragmentok:")) + pCurrentFsmState->GetStateName() + ":ProcessAck:value:'" + value + "'");
// ESPU_DBGL(String(F("ESPUIclient::OnWsEvent:WS_EVT_DATA:uiok:uifragmentok:")) + pCurrentFsmState->GetStateName() + ":ProcessAck:value:'" + value + "'");
pCurrentFsmState->ProcessAck(uint16_t(-1), value);
}
else
{
Serial.println(F("ERROR:ESPUIclient::OnWsEvent:WS_EVT_DATA:uifragmentok:ProcessAck:Fragment Header is missing"));
ESPU_DBGL(F("ERROR:ESPUIclient::OnWsEvent:WS_EVT_DATA:uifragmentok:ProcessAck:Fragment Header is missing"));
}
break;
}
if (cmd.equals(F("uiuok")))
{
// Serial.println(F("WS_EVT_DATA: uiuok. Unlock new async notifications"));
// ESPU_DBGL(F("WS_EVT_DATA: uiuok. Unlock new async notifications"));
break;
}
// Serial.println(F("WS_EVT_DATA:Process Control"));
// ESPU_DBGL(F("WS_EVT_DATA:Process Control"));
Control* control = ESPUI.getControl(id);
if (nullptr == control)
{
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.println(String(F("No control found for ID ")) + String(id));
ESPU_DBGL(String(F("No control found for ID ")) + String(id));
}
#endif
break;
@ -245,7 +254,7 @@ bool ESPUIclient::onWsEvent(AwsEventType type, void* arg, uint8_t* data, size_t
default:
{
// Serial.println(F("ESPUIclient::OnWsEvent:default"));
// ESPU_DBGL(F("ESPUIclient::OnWsEvent:default"));
break;
}
} // end switch
@ -267,7 +276,7 @@ uint32_t ESPUIclient::prepareJSONChunk(uint16_t startindex,
xSemaphoreTake(ESPUI.ControlsSemaphore, portMAX_DELAY);
#endif // def ESP32
// Serial.println(String("prepareJSONChunk: Start. InUpdateMode: ") + String(InUpdateMode));
// ESPU_DBGL(String("prepareJSONChunk: Start. InUpdateMode: ") + String(InUpdateMode));
int elementcount = 0;
do // once
@ -281,10 +290,10 @@ uint32_t ESPUIclient::prepareJSONChunk(uint16_t startindex,
if(!emptyString.equals(FragmentRequestString))
{
// Serial.println(F("prepareJSONChunk:Fragmentation:Got Header (1)"));
// Serial.println(String("prepareJSONChunk:startindex: ") + String(startindex));
// Serial.println(String("prepareJSONChunk:currentIndex: ") + String(currentIndex));
// Serial.println(String("prepareJSONChunk:FragmentRequestString: '") + FragmentRequestString + "'");
// ESPU_DBGL(F("prepareJSONChunk:Fragmentation:Got Header (1)"));
// ESPU_DBGL(String("prepareJSONChunk:startindex: ") + String(startindex));
// ESPU_DBGL(String("prepareJSONChunk:currentIndex: ") + String(currentIndex));
// ESPU_DBGL(String("prepareJSONChunk:FragmentRequestString: '") + FragmentRequestString + "'");
// this is actually a fragment or directed update request
// parse the string we got from the UI and try to update that specific
@ -292,38 +301,38 @@ uint32_t ESPUIclient::prepareJSONChunk(uint16_t startindex,
DynamicJsonDocument FragmentRequest(FragmentRequestString.length() * 3);
if(0 >= FragmentRequest.capacity())
{
Serial.println(F("ERROR:prepareJSONChunk:Fragmentation:Could not allocate memory for a fragmentation request. Skipping Response"));
ESPU_DBGL(F("ERROR:prepareJSONChunk:Fragmentation:Could not allocate memory for a fragmentation request. Skipping Response"));
break;
}
size_t FragmentRequestStartOffset = FragmentRequestString.indexOf("{");
DeserializationError error = deserializeJson(FragmentRequest, FragmentRequestString.substring(FragmentRequestStartOffset));
if(DeserializationError::Ok != error)
{
Serial.println(F("ERROR:prepareJSONChunk:Fragmentation:Could not extract json from the fragment request"));
ESPU_DBGL(F("ERROR:prepareJSONChunk:Fragmentation:Could not extract json from the fragment request"));
break;
}
if(!FragmentRequest.containsKey(F("id")))
{
Serial.println(F("ERROR:prepareJSONChunk:Fragmentation:Request does not contain a control ID"));
ESPU_DBGL(F("ERROR:prepareJSONChunk:Fragmentation:Request does not contain a control ID"));
break;
}
uint16_t ControlId = uint16_t(FragmentRequest[F("id")]);
if(!FragmentRequest.containsKey(F("offset")))
{
Serial.println(F("ERROR:prepareJSONChunk:Fragmentation:Request does not contain a starting offset"));
ESPU_DBGL(F("ERROR:prepareJSONChunk:Fragmentation:Request does not contain a starting offset"));
break;
}
DataOffset = uint16_t(FragmentRequest[F("offset")]);
control = ESPUI.getControlNoLock(ControlId);
if(nullptr == control)
{
Serial.println(String(F("ERROR:prepareJSONChunk:Fragmentation:Requested control: ")) + String(ControlId) + F(" does not exist"));
ESPU_DBGL(String(F("ERROR:prepareJSONChunk:Fragmentation:Requested control: ")) + String(ControlId) + F(" does not exist"));
break;
}
// Serial.println(F("prepareJSONChunk:Fragmentation:disable the control search operation"));
// ESPU_DBGL(F("prepareJSONChunk:Fragmentation:disable the control search operation"));
currentIndex = 1;
startindex = 0;
SingleControl = true;
@ -355,7 +364,7 @@ uint32_t ESPUIclient::prepareJSONChunk(uint16_t startindex,
// any controls left to be processed?
if(nullptr == control)
{
// Serial.println("prepareJSONChunk: No controls to process");
// ESPU_DBGL("prepareJSONChunk: No controls to process");
break;
}
@ -367,7 +376,7 @@ uint32_t ESPUIclient::prepareJSONChunk(uint16_t startindex,
// skip deleted controls or controls that have not been updated
if (control->ToBeDeleted() && !SingleControl)
{
// Serial.println(String("prepareJSONChunk: Ignoring Deleted control: ") + String(control->id));
// ESPU_DBGL(String("prepareJSONChunk: Ignoring Deleted control: ") + String(control->id));
control = control->next;
continue;
}
@ -395,8 +404,8 @@ uint32_t ESPUIclient::prepareJSONChunk(uint16_t startindex,
// String("prepareJSONChunk: too much data in the message. Remove the last entry");
if (1 == elementcount)
{
Serial.println(String(F("ERROR: prepareJSONChunk: Control ")) + String(control->id) + F(" is too large to be sent to the browser."));
// Serial.println(String(F("ERROR: prepareJSONChunk: value: ")) + control->value);
ESPU_DBGL(String(F("ERROR: prepareJSONChunk: Control ")) + String(control->id) + F(" is too large to be sent to the browser."));
// ESPU_DBGL(String(F("ERROR: prepareJSONChunk: value: ")) + control->value);
rootDoc.clear();
item = items.createNestedObject();
control->MarshalErrorMessage(item);
@ -404,8 +413,8 @@ uint32_t ESPUIclient::prepareJSONChunk(uint16_t startindex,
}
else
{
// Serial.println(String("prepareJSONChunk: Defering control: ") + String(control->id));
// Serial.println(String("prepareJSONChunk: elementcount: ") + String(elementcount));
// ESPU_DBGL(String("prepareJSONChunk: Defering control: ") + String(control->id));
// ESPU_DBGL(String("prepareJSONChunk: elementcount: ") + String(elementcount));
items.remove(elementcount);
--elementcount;
@ -415,7 +424,7 @@ uint32_t ESPUIclient::prepareJSONChunk(uint16_t startindex,
}
else if (SingleControl)
{
// Serial.println("prepareJSONChunk: exit loop");
// ESPU_DBGL("prepareJSONChunk: exit loop");
control = nullptr;
}
else
@ -430,7 +439,7 @@ uint32_t ESPUIclient::prepareJSONChunk(uint16_t startindex,
xSemaphoreGive(ESPUI.ControlsSemaphore);
#endif // def ESP32
// Serial.println(String("prepareJSONChunk: elementcount: ") + String(elementcount));
// ESPU_DBGL(String("prepareJSONChunk: elementcount: ") + String(elementcount));
return elementcount;
}
@ -457,18 +466,18 @@ etc.
bool ESPUIclient::SendControlsToClient(uint16_t startidx, ClientUpdateType_t TransferMode, String FragmentRequest)
{
bool Response = false;
// Serial.println(String("ESPUIclient:SendControlsToClient:startidx: ") + String(startidx));
// ESPU_DBGL(String("ESPUIclient:SendControlsToClient:startidx: ") + String(startidx));
do // once
{
if(!CanSend())
{
// Serial.println("ESPUIclient:SendControlsToClient: Cannot Send to clients.");
// ESPU_DBGL("ESPUIclient:SendControlsToClient: Cannot Send to clients.");
break;
}
else if ((startidx >= ESPUI.controlCount) && (emptyString.equals(FragmentRequest)))
{
// Serial.println(F("ERROR:ESPUIclient:SendControlsToClient: No more controls to send."));
// ESPU_DBGL(F("ERROR:ESPUIclient:SendControlsToClient: No more controls to send."));
Response = true;
break;
}
@ -480,44 +489,44 @@ bool ESPUIclient::SendControlsToClient(uint16_t startidx, ClientUpdateType_t Tra
if(0 == startidx)
{
// Serial.println("ESPUIclient:SendControlsToClient: Tell client we are starting a transfer of controls.");
// ESPU_DBGL("ESPUIclient:SendControlsToClient: Tell client we are starting a transfer of controls.");
document["type"] = (ClientUpdateType_t::RebuildNeeded == TransferMode) ? UI_INITIAL_GUI : UI_EXTEND_GUI;
CurrentSyncID = NextSyncID;
NextSyncID = ESPUI.GetNextControlChangeId();
}
// Serial.println(String("ESPUIclient:SendControlsToClient:type: ") + String((uint32_t)document["type"]));
// ESPU_DBGL(String("ESPUIclient:SendControlsToClient:type: ") + String((uint32_t)document["type"]));
// Serial.println("ESPUIclient:SendControlsToClient: Build Controls.");
// ESPU_DBGL("ESPUIclient:SendControlsToClient: Build Controls.");
if(prepareJSONChunk(startidx, document, ClientUpdateType_t::UpdateNeeded == TransferMode, FragmentRequest))
{
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity >= Verbosity::VerboseJSON)
{
Serial.println(F("ESPUIclient:SendControlsToClient: Sending elements --------->"));
ESPU_DBGL(F("ESPUIclient:SendControlsToClient: Sending elements --------->"));
serializeJson(document, Serial);
Serial.println();
ESPU_DBGL();
}
#endif
// Serial.println("ESPUIclient:SendControlsToClient: Send message.");
// ESPU_DBGL("ESPUIclient:SendControlsToClient: Send message.");
if(true == SendJsonDocToWebSocket(document))
{
// Serial.println("ESPUIclient:SendControlsToClient: Sent.");
// ESPU_DBGL("ESPUIclient:SendControlsToClient: Sent.");
}
else
{
// Serial.println("ESPUIclient:SendControlsToClient: Send failed.");
// ESPU_DBGL("ESPUIclient:SendControlsToClient: Send failed.");
}
}
else
{
// Serial.println("ESPUIclient:SendControlsToClient: No elements to send.");
// ESPU_DBGL("ESPUIclient:SendControlsToClient: No elements to send.");
Response = true;
}
} while(false);
// Serial.println(String("ESPUIclient:SendControlsToClient:Response: ") + String(Response));
// ESPU_DBGL(String("ESPUIclient:SendControlsToClient:Response: ") + String(Response));
return Response;
}
@ -532,10 +541,10 @@ bool ESPUIclient::SendJsonDocToWebSocket(DynamicJsonDocument& document)
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity >= Verbosity::VerboseJSON)
{
Serial.println(F("ESPUIclient::SendJsonDocToWebSocket: Cannot Send to client. Not sending websocket message"));
ESPU_DBGL(F("ESPUIclient::SendJsonDocToWebSocket: Cannot Send to client. Not sending websocket message"));
}
#endif
// Serial.println("ESPUIclient::SendJsonDocToWebSocket: Cannot Send to client. Not sending websocket message");
// ESPU_DBGL("ESPUIclient::SendJsonDocToWebSocket: Cannot Send to client. Not sending websocket message");
Response = false;
break;
}
@ -545,17 +554,17 @@ bool ESPUIclient::SendJsonDocToWebSocket(DynamicJsonDocument& document)
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity >= Verbosity::VerboseJSON)
{
Serial.println(String(F("ESPUIclient::SendJsonDocToWebSocket: json: '")) + json + "'");
ESPU_DBGL(String(F("ESPUIclient::SendJsonDocToWebSocket: json: '")) + json + "'");
}
#endif
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity >= Verbosity::VerboseJSON)
{
Serial.println(F("ESPUIclient::SendJsonDocToWebSocket: client.text"));
ESPU_DBGL(F("ESPUIclient::SendJsonDocToWebSocket: client.text"));
}
#endif
// Serial.println(F("ESPUIclient::SendJsonDocToWebSocket: client.text"));
// ESPU_DBGL(F("ESPUIclient::SendJsonDocToWebSocket: client.text"));
client->text(json);
} while (false);