diff --git a/README.md b/README.md
index 7cfed9b..bcd4499 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# ESPUI (v2.X)
+# ESPUI
![ESPUI](https://github.com/s00500/ESPUI/blob/master/docs/ui_complete.png)
diff --git a/data/js/controls.js b/data/js/controls.js
index 6d9aeb9..3cfd42c 100644
--- a/data/js/controls.js
+++ b/data/js/controls.js
@@ -232,6 +232,11 @@ function start() {
var center = "";
switch (data.type) {
case UI_INITIAL_GUI:
+ // Clear current elements
+ $("#row").html("");
+ $("#tabsnav").html("");
+ $("#tabscontent").html("");
+
if (data.sliderContinuous) {
sliderContinuous = data.sliderContinuous;
}
@@ -242,9 +247,9 @@ function start() {
handleEvent(fauxEvent);
});
break;
- case UI_RELOAD:
- window.location.reload();
- break;
+ case UI_RELOAD:
+ window.location.reload();
+ break;
case UI_TITEL:
document.title = data.label;
diff --git a/data/js/controls.min.js b/data/js/controls.min.js
index 6c023de..ff0e134 100644
--- a/data/js/controls.min.js
+++ b/data/js/controls.min.js
@@ -1,249 +1,249 @@
-const UI_INITIAL_GUI=200;const UI_RELOAD=201;const UPDATE_OFFSET=100;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 UPTDATE_ACCEL=117;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_NONE:return"dark";default:return"";}}
-var websock;var websockConnected=false;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);return savedData[id];}
-return[];}
-function restart(){$(document).add("*").off();$("#row").html("");websock.close();start();}
-function conStatusError(){websockConnected=false;$("#conStatus").removeClass("color-green");$("#conStatus").addClass("color-red");$("#conStatus").html("Error / No Connection ↻");$("#conStatus").off();$("#conStatus").on({click:restart,});}
-function handleVisibilityChange(){if(!websockConnected&&!document.hidden){restart();}}
-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");}
-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(evt);conStatusError();};var handleEvent=function(evt){var data=JSON.parse(evt.data);var e=document.body;var center="";switch(data.type){case UI_INITIAL_GUI:if(data.sliderContinuous){sliderContinuous=data.sliderContinuous;}
-data.controls.forEach(element=>{var fauxEvent={data:JSON.stringify(element),};handleEvent(fauxEvent);});break;case UI_RELOAD:window.location.reload();break;case UI_TITEL:document.title=data.label;$("#mainHeader").html(data.label);break;case UI_LABEL:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-parent.append("
"+
-"
"+
-data.label+
-" "+
-""+
-data.value+
-" "+
-"");break;case UI_BUTTON:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-parent.append(""+
-"
"+
-data.label+
-" "+
-""+
-data.value+
-" ");$("#btn"+data.id).on({touchstart:function(e){e.preventDefault();buttonclick(data.id,true);},touchend:function(e){e.preventDefault();buttonclick(data.id,false);},});break;case UI_SWITCHER:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-parent.append(""+
-"
"+
-data.label+
-" "+
-"
"+
-"
"+
-" "+
-"
");switcher(data.id,data.value);break;case UI_CPAD:case UI_PAD:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-parent.append(""+
-"
"+
-data.label+
-" "+
-"
"+
-""+
-"▲ "+
-"▲ "+
-"▲ "+
-"▲ "+
-" "+
-(data.type==UI_CPAD?"OK ":"")+
-" "+
-"
");$("#pf"+data.id).on({touchstart:function(e){e.preventDefault();padclick(UP,data.id,true);},touchend:function(e){e.preventDefault();padclick(UP,data.id,false);},});$("#pl"+data.id).on({touchstart:function(e){e.preventDefault();padclick(LEFT,data.id,true);},touchend:function(e){e.preventDefault();padclick(LEFT,data.id,false);},});$("#pr"+data.id).on({touchstart:function(e){e.preventDefault();padclick(RIGHT,data.id,true);},touchend:function(e){e.preventDefault();padclick(RIGHT,data.id,false);},});$("#pb"+data.id).on({touchstart:function(e){e.preventDefault();padclick(DOWN,data.id,true);},touchend:function(e){e.preventDefault();padclick(DOWN,data.id,false);},});$("#pc"+data.id).on({touchstart:function(e){e.preventDefault();padclick(CENTER,data.id,true);},touchend:function(e){e.preventDefault();padclick(CENTER,data.id,false);},});break;case UI_SLIDER:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-parent.append(""+
-"
"+
-data.label+
-" "+
-"
"+
-" "+
-""+
-data.value+
-" "+
-"
"+
-"
");rangeSlider(!sliderContinuous);break;case UI_NUMBER:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-parent.append(""+
-"
"+
-data.label+
-" "+
-" "+
-"");break;case UI_TEXT_INPUT:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-parent.append(""+
-"
"+
-data.label+
-" "+
-" "+
-"");break;case UI_TAB:$("#tabsnav").append(""+data.value+" ");$("#tabscontent").append("
");tabs=$(".tabscontent").tabbedContent({loop:true}).data("api");$("a").filter(function(){return $(this).attr("href")==="#click-to-switch";}).on("click",function(e){var tab=prompt("Tab to switch to (number or id)?");if(!tabs.switchTab(tab)){alert("That tab does not exist :\\");}
-e.preventDefault();});break;case UI_SELECT:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-parent.append(""+
-"
"+
-data.label+
-" "+
-" "+
-"");break;case UI_OPTION:if(data.parentControl){var parent=$("#select"+data.parentControl);parent.append(""+
-data.label+
-" ");}
-break;case UI_MIN:if(data.parentControl){var parent=$("#id"+data.parentControl+" input");if(parent.size()){parent.attr("min",data.value);}}
-break;case UI_MAX:if(data.parentControl){var parent=$("#id"+data.parentControl+" input");if(parent.size()){parent.attr("max",data.value);}}
-break;case UI_STEP:if(data.parentControl){var parent=$("#id"+data.parentControl+" input");if(parent.size()){parent.attr("step",data.value);}}
-break;case UI_GRAPH:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-parent.append(""+
-"
"+
-data.label+
-" "+
-""+
-""+
-data.label+
-" "+
-" "+
-"");graphData[data.id]=restoreGraphData(data.id);renderGraphSvg(graphData[data.id],"graph"+data.id);break;case ADD_GRAPH_POINT:var ts=Math.round(new Date().getTime()/1000);graphData[data.id].push({x:ts,y:data.value});saveGraphData();renderGraphSvg(graphData[data.id],"graph"+data.id);break;case CLEAR_GRAPH:graphData[data.id]=[];saveGraphData();renderGraphSvg(graphData[data.id],"graph"+data.id);break;case UI_GAUGE:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-parent.append(""+
-"
"+
-data.label+
-" "+
-"WILL BE A GAUGE "+
-"");break;case UI_ACCEL:if(hasAccel)break;var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-hasAccel=true;parent.append(""+
-"
"+
-data.label+
-" "+
-"ACCEL // Not implemented fully!
");requestOrientationPermission();break;case UPDATE_LABEL:$("#l"+data.id).html(data.value);break;case UPDATE_SWITCHER:switcher(data.id,data.value=="0"?0:1);break;case UPDATE_SLIDER:slider_move($("#sl"+data.id),data.value,"100",false);break;case UPDATE_NUMBER:$("#num"+data.id).val(data.value);break;case UPDATE_TEXT_INPUT:$("#text"+data.id).val(data.value);break;case UPDATE_SELECT:$("#select"+data.id).val(data.value);break;case UPDATE_BUTTON:case UPDATE_PAD:case UPDATE_CPAD:break;case UPDATE_GAUGE:$("#gauge"+data.id).val(data.value);break;case UPDATE_ACCEL:break;default:console.error("Unknown type or event");break;}
-if(data.type>=UPDATE_OFFSET&&data.type
{var fauxEvent={data:JSON.stringify(element),};handleEvent(fauxEvent);});break;case UI_RELOAD:window.location.reload();break;case UI_TITEL:document.title=data.label;$("#mainHeader").html(data.label);break;case UI_LABEL:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+parent.append(""+
+"
"+
+data.label+
+" "+
+""+
+data.value+
+" "+
+"");break;case UI_BUTTON:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+parent.append(""+
+"
"+
+data.label+
+" "+
+""+
+data.value+
+" ");$("#btn"+data.id).on({touchstart:function(e){e.preventDefault();buttonclick(data.id,true);},touchend:function(e){e.preventDefault();buttonclick(data.id,false);},});break;case UI_SWITCHER:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+parent.append(""+
+"
"+
+data.label+
+" "+
+"
"+
+"
"+
+" "+
+"
");switcher(data.id,data.value);break;case UI_CPAD:case UI_PAD:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+parent.append(""+
+"
"+
+data.label+
+" "+
+"
"+
+""+
+"▲ "+
+"▲ "+
+"▲ "+
+"▲ "+
+" "+
+(data.type==UI_CPAD?"OK ":"")+
+" "+
+"
");$("#pf"+data.id).on({touchstart:function(e){e.preventDefault();padclick(UP,data.id,true);},touchend:function(e){e.preventDefault();padclick(UP,data.id,false);},});$("#pl"+data.id).on({touchstart:function(e){e.preventDefault();padclick(LEFT,data.id,true);},touchend:function(e){e.preventDefault();padclick(LEFT,data.id,false);},});$("#pr"+data.id).on({touchstart:function(e){e.preventDefault();padclick(RIGHT,data.id,true);},touchend:function(e){e.preventDefault();padclick(RIGHT,data.id,false);},});$("#pb"+data.id).on({touchstart:function(e){e.preventDefault();padclick(DOWN,data.id,true);},touchend:function(e){e.preventDefault();padclick(DOWN,data.id,false);},});$("#pc"+data.id).on({touchstart:function(e){e.preventDefault();padclick(CENTER,data.id,true);},touchend:function(e){e.preventDefault();padclick(CENTER,data.id,false);},});break;case UI_SLIDER:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+parent.append(""+
+"
"+
+data.label+
+" "+
+"
"+
+" "+
+""+
+data.value+
+" "+
+"
"+
+"
");rangeSlider(!sliderContinuous);break;case UI_NUMBER:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+parent.append(""+
+"
"+
+data.label+
+" "+
+" "+
+"");break;case UI_TEXT_INPUT:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+parent.append(""+
+"
"+
+data.label+
+" "+
+" "+
+"");break;case UI_TAB:$("#tabsnav").append(""+data.value+" ");$("#tabscontent").append("
");tabs=$(".tabscontent").tabbedContent({loop:true}).data("api");$("a").filter(function(){return $(this).attr("href")==="#click-to-switch";}).on("click",function(e){var tab=prompt("Tab to switch to (number or id)?");if(!tabs.switchTab(tab)){alert("That tab does not exist :\\");}
+e.preventDefault();});break;case UI_SELECT:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+parent.append(""+
+"
"+
+data.label+
+" "+
+" "+
+"");break;case UI_OPTION:if(data.parentControl){var parent=$("#select"+data.parentControl);parent.append(""+
+data.label+
+" ");}
+break;case UI_MIN:if(data.parentControl){var parent=$("#id"+data.parentControl+" input");if(parent.size()){parent.attr("min",data.value);}}
+break;case UI_MAX:if(data.parentControl){var parent=$("#id"+data.parentControl+" input");if(parent.size()){parent.attr("max",data.value);}}
+break;case UI_STEP:if(data.parentControl){var parent=$("#id"+data.parentControl+" input");if(parent.size()){parent.attr("step",data.value);}}
+break;case UI_GRAPH:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+parent.append(""+
+"
"+
+data.label+
+" "+
+""+
+""+
+data.label+
+" "+
+" "+
+"");graphData[data.id]=restoreGraphData(data.id);renderGraphSvg(graphData[data.id],"graph"+data.id);break;case ADD_GRAPH_POINT:var ts=Math.round(new Date().getTime()/1000);graphData[data.id].push({x:ts,y:data.value});saveGraphData();renderGraphSvg(graphData[data.id],"graph"+data.id);break;case CLEAR_GRAPH:graphData[data.id]=[];saveGraphData();renderGraphSvg(graphData[data.id],"graph"+data.id);break;case UI_GAUGE:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+parent.append(""+
+"
"+
+data.label+
+" "+
+"WILL BE A GAUGE "+
+"");break;case UI_ACCEL:if(hasAccel)break;var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+hasAccel=true;parent.append(""+
+"
"+
+data.label+
+" "+
+"ACCEL // Not implemented fully!
");requestOrientationPermission();break;case UPDATE_LABEL:$("#l"+data.id).html(data.value);break;case UPDATE_SWITCHER:switcher(data.id,data.value=="0"?0:1);break;case UPDATE_SLIDER:slider_move($("#sl"+data.id),data.value,"100",false);break;case UPDATE_NUMBER:$("#num"+data.id).val(data.value);break;case UPDATE_TEXT_INPUT:$("#text"+data.id).val(data.value);break;case UPDATE_SELECT:$("#select"+data.id).val(data.value);break;case UPDATE_BUTTON:case UPDATE_PAD:case UPDATE_CPAD:break;case UPDATE_GAUGE:$("#gauge"+data.id).val(data.value);break;case UPDATE_ACCEL:break;default:console.error("Unknown type or event");break;}
+if(data.type>=UPDATE_OFFSET&&data.type
verbosity) {
+ if (this->verbosity)
+ {
Serial.println("About to prepare filesystem...");
}
#if defined(ESP32)
LittleFS.format();
- if (!LittleFS.begin(true)) {
- if (this->verbosity) {
+ if (!LittleFS.begin(true))
+ {
+ if (this->verbosity)
+ {
Serial.println("SPIFFS Mount Failed");
}
return;
}
- if (this->verbosity) {
+ if (this->verbosity)
+ {
listDir("/", 1);
Serial.println("SPIFFS Mount ESP32 Done");
}
@@ -206,7 +252,8 @@ void ESPUIClass::prepareFileSystem() {
LittleFS.format();
LittleFS.begin();
- if (this->verbosity) {
+ if (this->verbosity)
+ {
Serial.println("SPIFFS Mount ESP8266 Done");
}
@@ -223,7 +270,8 @@ void ESPUIClass::prepareFileSystem() {
deleteFile("/js/graph.js");
deleteFile("/js/tabbedcontent.js");
- if (this->verbosity) {
+ if (this->verbosity)
+ {
Serial.println("Cleanup done");
}
@@ -240,13 +288,15 @@ void ESPUIClass::prepareFileSystem() {
writeFile("/js/tabbedcontent.js", JS_TABBEDCONTENT);
- if (this->verbosity) {
+ if (this->verbosity)
+ {
Serial.println("Done Initializing filesystem :-)");
}
#if defined(ESP32)
- if (this->verbosity) {
+ if (this->verbosity)
+ {
listDir("/", 1);
}
@@ -256,56 +306,71 @@ void ESPUIClass::prepareFileSystem() {
}
// Handle Websockets Communication
-void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
- switch (type) {
- case WS_EVT_DISCONNECT: {
- if (ESPUI.verbosity) {
+void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len)
+{
+ switch (type)
+ {
+ case WS_EVT_DISCONNECT:
+ {
+ if (ESPUI.verbosity)
+ {
Serial.printf("Disconnected!\n");
}
break;
}
- case WS_EVT_PONG: {
- if (ESPUI.verbosity) {
+ case WS_EVT_PONG:
+ {
+ if (ESPUI.verbosity)
+ {
Serial.printf("Received PONG!\n");
}
break;
}
- case WS_EVT_ERROR: {
- if (ESPUI.verbosity) {
+ case WS_EVT_ERROR:
+ {
+ if (ESPUI.verbosity)
+ {
Serial.printf("WebSocket Error!\n");
}
break;
}
- case WS_EVT_CONNECT: {
- if (ESPUI.verbosity) {
+ case WS_EVT_CONNECT:
+ {
+ if (ESPUI.verbosity)
+ {
Serial.print("Connected: ");
Serial.println(client->id());
}
ESPUI.jsonDom(client);
- if (ESPUI.verbosity) {
+ if (ESPUI.verbosity)
+ {
Serial.println("JSON Data Sent to Client!");
}
- } break;
+ }
+ break;
- case WS_EVT_DATA: {
+ case WS_EVT_DATA:
+ {
String msg = "";
msg.reserve(len + 1);
- for (size_t i = 0; i < len; i++) {
+ for (size_t i = 0; i < len; i++)
+ {
msg += (char)data[i];
}
uint16_t id = msg.substring(msg.lastIndexOf(':') + 1).toInt();
- if (ESPUI.verbosity >= Verbosity::VerboseJSON) {
+ if (ESPUI.verbosity >= Verbosity::VerboseJSON)
+ {
Serial.print("WS rec: ");
Serial.println(msg);
Serial.print("WS recognised ID: ");
@@ -314,8 +379,10 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
Control *c = ESPUI.getControl(id);
- if (c == nullptr) {
- if (ESPUI.verbosity) {
+ if (c == nullptr)
+ {
+ if (ESPUI.verbosity)
+ {
Serial.print("No control found for ID ");
Serial.println(id);
}
@@ -323,8 +390,10 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
return;
}
- if (c->callback == nullptr) {
- if (ESPUI.verbosity) {
+ if (c->callback == nullptr)
+ {
+ if (ESPUI.verbosity)
+ {
Serial.print("No callback found for ID ");
Serial.println(id);
}
@@ -332,60 +401,99 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
return;
}
- if (msg.startsWith("bdown:")) {
+ if (msg.startsWith("bdown:"))
+ {
c->callback(c, B_DOWN);
- } else if (msg.startsWith("bup:")) {
+ }
+ else if (msg.startsWith("bup:"))
+ {
c->callback(c, B_UP);
- } else if (msg.startsWith("pfdown:")) {
+ }
+ else if (msg.startsWith("pfdown:"))
+ {
c->callback(c, P_FOR_DOWN);
- } else if (msg.startsWith("pfup:")) {
+ }
+ else if (msg.startsWith("pfup:"))
+ {
c->callback(c, P_FOR_UP);
- } else if (msg.startsWith("pldown:")) {
+ }
+ else if (msg.startsWith("pldown:"))
+ {
c->callback(c, P_LEFT_DOWN);
- } else if (msg.startsWith("plup:")) {
+ }
+ else if (msg.startsWith("plup:"))
+ {
c->callback(c, P_LEFT_UP);
- } else if (msg.startsWith("prdown:")) {
+ }
+ else if (msg.startsWith("prdown:"))
+ {
c->callback(c, P_RIGHT_DOWN);
- } else if (msg.startsWith("prup:")) {
+ }
+ else if (msg.startsWith("prup:"))
+ {
c->callback(c, P_RIGHT_UP);
- } else if (msg.startsWith("pbdown:")) {
+ }
+ else if (msg.startsWith("pbdown:"))
+ {
c->callback(c, P_BACK_DOWN);
- } else if (msg.startsWith("pbup:")) {
+ }
+ else if (msg.startsWith("pbup:"))
+ {
c->callback(c, P_BACK_UP);
- } else if (msg.startsWith("pcdown:")) {
+ }
+ else if (msg.startsWith("pcdown:"))
+ {
c->callback(c, P_CENTER_DOWN);
- } else if (msg.startsWith("pcup:")) {
+ }
+ else if (msg.startsWith("pcup:"))
+ {
c->callback(c, P_CENTER_UP);
- } else if (msg.startsWith("sactive:")) {
+ }
+ else if (msg.startsWith("sactive:"))
+ {
c->value = "1";
ESPUI.updateControl(c, client->id());
c->callback(c, S_ACTIVE);
- } else if (msg.startsWith("sinactive:")) {
+ }
+ else if (msg.startsWith("sinactive:"))
+ {
c->value = "0";
ESPUI.updateControl(c, client->id());
c->callback(c, S_INACTIVE);
- } else if (msg.startsWith("slvalue:")) {
+ }
+ else if (msg.startsWith("slvalue:"))
+ {
c->value = msg.substring(msg.indexOf(':') + 1, msg.lastIndexOf(':'));
ESPUI.updateControl(c, client->id());
c->callback(c, SL_VALUE);
- } else if (msg.startsWith("nvalue:")) {
+ }
+ else if (msg.startsWith("nvalue:"))
+ {
c->value = msg.substring(msg.indexOf(':') + 1, msg.lastIndexOf(':'));
ESPUI.updateControl(c, client->id());
c->callback(c, N_VALUE);
- } else if (msg.startsWith("tvalue:")) {
+ }
+ else if (msg.startsWith("tvalue:"))
+ {
c->value = msg.substring(msg.indexOf(':') + 1, msg.lastIndexOf(':'));
ESPUI.updateControl(c, client->id());
c->callback(c, T_VALUE);
- } else if (msg.startsWith("svalue:")) {
+ }
+ else if (msg.startsWith("svalue:"))
+ {
c->value = msg.substring(msg.indexOf(':') + 1, msg.lastIndexOf(':'));
ESPUI.updateControl(c, client->id());
c->callback(c, S_VALUE);
- } else {
- if (ESPUI.verbosity) {
+ }
+ else
+ {
+ if (ESPUI.verbosity)
+ {
Serial.println("Malformated message from the websocket");
}
}
- } break;
+ }
+ break;
default:
break;
@@ -393,15 +501,20 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
}
uint16_t ESPUIClass::addControl(ControlType type, const char *label, String value, ControlColor color, uint16_t parentControl,
- void (*callback)(Control *, int)) {
+ void (*callback)(Control *, int))
+{
Control *control = new Control(type, label, callback, value, color, parentControl);
- if (this->controls == nullptr) {
+ if (this->controls == nullptr)
+ {
this->controls = control;
- } else {
+ }
+ else
+ {
Control *iterator = this->controls;
- while (iterator->next != nullptr) {
+ while (iterator->next != nullptr)
+ {
iterator = iterator->next;
}
@@ -411,57 +524,59 @@ uint16_t ESPUIClass::addControl(ControlType type, const char *label, String valu
return control->id;
}
-bool ESPUIClass::remControl(uint16_t id, bool reload_ui)
+bool ESPUIClass::removeControl(uint16_t id, bool force_reload_ui)
{
- if(nullptr == this->controls) return false;
+ if (nullptr == this->controls)
+ return false;
- Control * it = this->controls;
-
- if(id == it->id) {
+ Control *it = this->controls;
+
+ if (id == it->id)
+ {
this->controls = it->next;
delete it;
- if(reload_ui) {
- reload();
+ if (force_reload_ui)
+ {
+ jsonReload();
+ }
+ else
+ {
+ jsonDom();
}
return true;
}
- Control * it_next = it->next;
- while(nullptr != it_next && id != it_next->id) {
+ 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) {
+ if (nullptr != it_next)
+ {
it->next = it_next->next;
delete it_next;
- if(reload_ui) {
- reload();
- }
+ if (force_reload_ui)
+ {
+ jsonReload();
+ }
+ else
+ {
+ jsonDom();
+ }
return true;
}
-
+
return false;
}
-void ESPUIClass::reload()
-{
- int tryId = 0;
-
- for (int count = 0; count < this->ws->count();) {
- if (this->ws->hasClient(tryId)) {
- ESPUI.jsonReload(this->ws->client(tryId));
- count++;
- }
- tryId++;
- }
-}
-
uint16_t ESPUIClass::label(const char *label, ControlColor color, String value) { return addControl(ControlType::Label, label, value, color); }
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);
addControl(ControlType::Min, label, String(min), ControlColor::None, sliderId);
addControl(ControlType::Max, label, String(max), ControlColor::None, sliderId);
@@ -469,48 +584,59 @@ uint16_t ESPUIClass::slider(const char *label, void (*callback)(Control *, int),
return sliderId;
}
-uint16_t ESPUIClass::button(const char *label, void (*callback)(Control *, int), ControlColor color, String value) {
+uint16_t ESPUIClass::button(const char *label, void (*callback)(Control *, int), ControlColor color, String value)
+{
return addControl(ControlType::Button, label, value, color, Control::noParent, callback);
}
-uint16_t ESPUIClass::switcher(const char *label, void (*callback)(Control *, int), ControlColor color, bool startState) {
+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::pad(const char *label, void (*callback)(Control *, int), ControlColor color) {
+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::padWithCenter(const char *label, void (*callback)(Control *, int), ControlColor color) {
+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::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);
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 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);
addControl(ControlType::Min, label, String(min), ControlColor::None, numberId);
addControl(ControlType::Max, label, String(max), ControlColor::None, numberId);
return numberId;
}
-uint16_t ESPUIClass::accelerometer(const char *label, void (*callback)(Control *, int), ControlColor color) {
+uint16_t ESPUIClass::accelerometer(const char *label, void (*callback)(Control *, int), ControlColor color)
+{
return addControl(ControlType::Accel, label, "", color, Control::noParent, callback);
}
-uint16_t ESPUIClass::text(const char *label, void (*callback)(Control *, int), ControlColor color, String value) {
+uint16_t ESPUIClass::text(const char *label, void (*callback)(Control *, int), ControlColor color, String value)
+{
return addControl(ControlType::Text, label, value, color, Control::noParent, callback);
}
-Control *ESPUIClass::getControl(uint16_t id) {
+Control *ESPUIClass::getControl(uint16_t id)
+{
Control *control = this->controls;
- while (control != nullptr) {
- if (control->id == id) {
+ while (control != nullptr)
+ {
+ if (control->id == id)
+ {
return control;
}
@@ -520,8 +646,10 @@ Control *ESPUIClass::getControl(uint16_t id) {
return nullptr;
}
-void ESPUIClass::updateControl(Control *control, int clientId) {
- if (!control) {
+void ESPUIClass::updateControl(Control *control, int clientId)
+{
+ if (!control)
+ {
return;
}
@@ -535,11 +663,13 @@ void ESPUIClass::updateControl(Control *control, int clientId) {
root["color"] = (int)control->color;
serializeJson(document, json);
- if (this->verbosity >= Verbosity::VerboseJSON) {
+ if (this->verbosity >= Verbosity::VerboseJSON)
+ {
Serial.println(json);
}
- if (clientId < 0) {
+ if (clientId < 0)
+ {
this->ws->textAll(json);
return;
}
@@ -547,12 +677,16 @@ void ESPUIClass::updateControl(Control *control, int clientId) {
// function like this and it's clients array is private
int tryId = 0;
- for (int count = 0; count < this->ws->count();) {
- if (this->ws->hasClient(tryId)) {
- if (clientId != tryId) {
+ for (int count = 0; count < this->ws->count();)
+ {
+ if (this->ws->hasClient(tryId))
+ {
+ if (clientId != tryId)
+ {
this->ws->client(tryId)->text(json);
- if (this->verbosity >= Verbosity::VerboseJSON) {
+ if (this->verbosity >= Verbosity::VerboseJSON)
+ {
Serial.println(json);
}
}
@@ -564,11 +698,14 @@ void ESPUIClass::updateControl(Control *control, int clientId) {
}
}
-void ESPUIClass::updateControl(uint16_t id, int clientId) {
+void ESPUIClass::updateControl(uint16_t id, int clientId)
+{
Control *control = getControl(id);
- if (!control) {
- if (this->verbosity) {
+ if (!control)
+ {
+ if (this->verbosity)
+ {
Serial.println(String("Error: There is no control with ID ") + String(id));
}
return;
@@ -577,8 +714,10 @@ void ESPUIClass::updateControl(uint16_t id, int clientId) {
updateControl(control, clientId);
}
-void ESPUIClass::updateControlValue(Control *control, String value, int clientId) {
- if (!control) {
+void ESPUIClass::updateControlValue(Control *control, String value, int clientId)
+{
+ if (!control)
+ {
return;
}
@@ -586,11 +725,14 @@ void ESPUIClass::updateControlValue(Control *control, String value, int clientId
updateControl(control, clientId);
}
-void ESPUIClass::updateControlValue(uint16_t id, String value, int clientId) {
+void ESPUIClass::updateControlValue(uint16_t id, String value, int clientId)
+{
Control *control = getControl(id);
- if (!control) {
- if (this->verbosity) {
+ if (!control)
+ {
+ if (this->verbosity)
+ {
Serial.println(String("Error: There is no control with ID ") + String(id));
}
return;
@@ -617,9 +759,11 @@ void ESPUIClass::updateGauge(uint16_t id, int number, int clientId) { updateCont
void ESPUIClass::clearGraph(uint16_t id, int clientId) {}
-void ESPUIClass::addGraphPoint(uint16_t id, int nValue, int clientId) {
+void ESPUIClass::addGraphPoint(uint16_t id, int nValue, int clientId)
+{
Control *control = getControl(id);
- if (!control) {
+ if (!control)
+ {
return;
}
@@ -632,11 +776,13 @@ void ESPUIClass::addGraphPoint(uint16_t id, int nValue, int clientId) {
root["id"] = control->id;
serializeJson(document, json);
- if (this->verbosity >= Verbosity::VerboseJSON) {
+ if (this->verbosity >= Verbosity::VerboseJSON)
+ {
Serial.println(json);
}
- if (clientId < 0) {
+ if (clientId < 0)
+ {
this->ws->textAll(json);
return;
}
@@ -644,12 +790,16 @@ void ESPUIClass::addGraphPoint(uint16_t id, int nValue, int clientId) {
// function like this and it's clients array is private
int tryId = 0;
- for (int count = 0; count < this->ws->count();) {
- if (this->ws->hasClient(tryId)) {
- if (clientId != tryId) {
+ for (int count = 0; count < this->ws->count();)
+ {
+ if (this->ws->hasClient(tryId))
+ {
+ if (clientId != tryId)
+ {
this->ws->client(tryId)->text(json);
- if (this->verbosity >= Verbosity::VerboseJSON) {
+ if (this->verbosity >= Verbosity::VerboseJSON)
+ {
Serial.println(json);
}
}
@@ -666,7 +816,8 @@ Initially this function used to send the control element data individually.
Due to a change in the ESPAsyncWebserver library this had top be changed to be
sent as one blob at the beginning. Therefore a new type is used as well
*/
-void ESPUIClass::jsonDom(AsyncWebSocketClient *client) {
+void ESPUIClass::jsonDom(AsyncWebSocketClient *client)
+{
String json;
DynamicJsonDocument document(jsonInitialDocumentSize);
document["type"] = (int)UI_INITIAL_GUI;
@@ -679,7 +830,8 @@ void ESPUIClass::jsonDom(AsyncWebSocketClient *client) {
titleItem["type"] = (int)UI_TITLE;
titleItem["label"] = ui_title;
- while (control != nullptr) {
+ while (control != nullptr)
+ {
JsonObject item = items.createNestedObject();
item["id"] = String(control->id);
@@ -688,16 +840,21 @@ void ESPUIClass::jsonDom(AsyncWebSocketClient *client) {
item["value"] = String(control->value);
item["color"] = (int)control->color;
- if (control->parentControl != Control::noParent) {
+ if (control->parentControl != Control::noParent)
+ {
item["parentControl"] = String(control->parentControl);
}
// special case for selects: to preselect an option, you have to add
// "selected" to
- if (control->type == ControlType::Option) {
- if (ESPUI.getControl(control->parentControl)->value == control->value) {
+ if (control->type == ControlType::Option)
+ {
+ if (ESPUI.getControl(control->parentControl)->value == control->value)
+ {
item["selected"] = "selected";
- } else {
+ }
+ else
+ {
item["selected"] = "";
}
}
@@ -708,14 +865,22 @@ void ESPUIClass::jsonDom(AsyncWebSocketClient *client) {
// Send as one big bunch
serializeJson(document, json);
- if (this->verbosity >= Verbosity::VerboseJSON) {
+ if (this->verbosity >= Verbosity::VerboseJSON)
+ {
Serial.println(json);
}
- client->text(json);
+ if (client != nullptr)
+ {
+ client->text(json);
+ }
+ else
+ {
+ this->ws->textAll(json);
+ }
}
-void ESPUIClass::jsonReload(AsyncWebSocketClient *client)
+void ESPUIClass::jsonReload()
{
String json;
DynamicJsonDocument document(jsonUpdateDocumentSize);
@@ -724,41 +889,51 @@ void ESPUIClass::jsonReload(AsyncWebSocketClient *client)
root["type"] = (int)UI_RELOAD;
serializeJson(document, json);
- if (this->verbosity >= Verbosity::VerboseJSON) {
+ if (this->verbosity >= Verbosity::VerboseJSON)
+ {
Serial.println(json);
}
this->ws->textAll(json);
}
-void ESPUIClass::beginSPIFFS(const char *_title, const char *username, const char *password) {
+void ESPUIClass::beginSPIFFS(const char *_title, const char *username, const char *password)
+{
ui_title = _title;
this->basicAuthUsername = username;
this->basicAuthPassword = password;
- if (username == nullptr && password == nullptr) {
+ if (username == nullptr && password == nullptr)
+ {
basicAuth = false;
- } else {
+ }
+ else
+ {
basicAuth = true;
}
server = new AsyncWebServer(80);
ws = new AsyncWebSocket("/ws");
- if (!LittleFS.begin()) {
- if (ESPUI.verbosity) {
+ if (!LittleFS.begin())
+ {
+ if (ESPUI.verbosity)
+ {
Serial.println("SPIFFS Mount Failed, PLEASE CHECK THE README ON HOW TO PREPARE YOUR ESP!!!!!!!");
}
return;
}
- if (ESPUI.verbosity) {
+ if (ESPUI.verbosity)
+ {
listDir("/", 1);
}
- if (!LittleFS.exists("/index.htm")) {
- if (ESPUI.verbosity) {
+ if (!LittleFS.exists("/index.htm"))
+ {
+ if (ESPUI.verbosity)
+ {
Serial.println("Please read the README!!!!!!!, Make sure to ESPUI.prepareFileSystem() once in an empty sketch");
}
@@ -768,19 +943,23 @@ void ESPUIClass::beginSPIFFS(const char *_title, const char *username, const cha
ws->onEvent(onWsEvent);
server->addHandler(ws);
- if (basicAuth) {
- if (WS_AUTHENTICATION) {
+ if (basicAuth)
+ {
+ if (WS_AUTHENTICATION)
+ {
ws->setAuthentication(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword);
}
-
server->serveStatic("/", LittleFS, "/").setDefaultFile("index.htm").setAuthentication(username, password);
- } else {
+ }
+ else
+ {
server->serveStatic("/", LittleFS, "/").setDefaultFile("index.htm");
}
// Heap for general Servertest
server->on("/heap", HTTP_GET, [](AsyncWebServerRequest *request) {
- if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword)) {
+ if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
+ {
return request->requestAuthentication();
}
@@ -791,18 +970,23 @@ void ESPUIClass::beginSPIFFS(const char *_title, const char *username, const cha
server->begin();
- if (this->verbosity) {
+ if (this->verbosity)
+ {
Serial.println("UI Initialized");
}
}
-void ESPUIClass::begin(const char *_title, const char *username, const char *password) {
+void ESPUIClass::begin(const char *_title, const char *username, const char *password)
+{
basicAuthUsername = username;
basicAuthPassword = password;
- if (username != nullptr && password != nullptr) {
+ if (username != nullptr && password != nullptr)
+ {
basicAuth = true;
- } else {
+ }
+ else
+ {
basicAuth = false;
}
@@ -818,7 +1002,8 @@ void ESPUIClass::begin(const char *_title, const char *username, const char *pas
ws->setAuthentication(username, password);
server->on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
- if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword)) {
+ if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
+ {
return request->requestAuthentication();
}
@@ -829,7 +1014,8 @@ void ESPUIClass::begin(const char *_title, const char *username, const char *pas
// Javascript files
server->on("/js/zepto.min.js", HTTP_GET, [](AsyncWebServerRequest *request) {
- if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword)) {
+ if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
+ {
return request->requestAuthentication();
}
@@ -839,7 +1025,8 @@ void ESPUIClass::begin(const char *_title, const char *username, const char *pas
});
server->on("/js/controls.js", HTTP_GET, [](AsyncWebServerRequest *request) {
- if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword)) {
+ if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
+ {
return request->requestAuthentication();
}
@@ -849,7 +1036,8 @@ void ESPUIClass::begin(const char *_title, const char *username, const char *pas
});
server->on("/js/slider.js", HTTP_GET, [](AsyncWebServerRequest *request) {
- if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword)) {
+ if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
+ {
return request->requestAuthentication();
}
@@ -859,7 +1047,8 @@ void ESPUIClass::begin(const char *_title, const char *username, const char *pas
});
server->on("/js/graph.js", HTTP_GET, [](AsyncWebServerRequest *request) {
- if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword)) {
+ if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
+ {
return request->requestAuthentication();
}
@@ -869,7 +1058,8 @@ void ESPUIClass::begin(const char *_title, const char *username, const char *pas
});
server->on("/js/tabbedcontent.js", HTTP_GET, [](AsyncWebServerRequest *request) {
- if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword)) {
+ if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
+ {
return request->requestAuthentication();
}
@@ -881,7 +1071,8 @@ void ESPUIClass::begin(const char *_title, const char *username, const char *pas
// Stylesheets
server->on("/css/style.css", HTTP_GET, [](AsyncWebServerRequest *request) {
- if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword)) {
+ if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
+ {
return request->requestAuthentication();
}
@@ -891,7 +1082,8 @@ void ESPUIClass::begin(const char *_title, const char *username, const char *pas
});
server->on("/css/normalize.css", HTTP_GET, [](AsyncWebServerRequest *request) {
- if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword)) {
+ if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
+ {
return request->requestAuthentication();
}
@@ -902,7 +1094,8 @@ void ESPUIClass::begin(const char *_title, const char *username, const char *pas
// Heap for general Servertest
server->on("/heap", HTTP_GET, [](AsyncWebServerRequest *request) {
- if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword)) {
+ if (ESPUI.basicAuth && !request->authenticate(ESPUI.basicAuthUsername, ESPUI.basicAuthPassword))
+ {
return request->requestAuthentication();
}
@@ -913,11 +1106,12 @@ void ESPUIClass::begin(const char *_title, const char *username, const char *pas
server->begin();
- if (this->verbosity) {
+ if (this->verbosity)
+ {
Serial.println("UI Initialized");
}
}
void ESPUIClass::setVerbosity(Verbosity v) { this->verbosity = v; }
-ESPUIClass ESPUI;
\ No newline at end of file
+ESPUIClass ESPUI;
diff --git a/src/ESPUI.h b/src/ESPUI.h
index 2e76cf7..b00116c 100644
--- a/src/ESPUI.h
+++ b/src/ESPUI.h
@@ -206,9 +206,8 @@ public:
void prepareFileSystem(); // Initially preps the filesystem and loads a lot of stuff into SPIFFS
void list(); // Lists SPIFFS directory
- uint16_t addControl(ControlType type, const char *label, String value = String(""), ControlColor color = ControlColor::Turquoise,
- uint16_t parentControl = Control::noParent, void (*callback)(Control *, int) = nullptr);
- bool remControl(uint16_t id, bool reload_ui = true);
+ uint16_t addControl(ControlType type, const char *label, String value = String(""), ControlColor color = ControlColor::Turquoise, uint16_t parentControl = Control::noParent, void (*callback)(Control *, int) = nullptr);
+ bool removeControl(uint16_t id, bool force_reload_ui = false);
// create Elements
uint16_t button(const char *label, void (*callback)(Control *, int), ControlColor color, String value = ""); // Create Event Button
@@ -223,10 +222,9 @@ public:
uint16_t text(const char *label, void (*callback)(Control *, int), ControlColor color, String value = ""); // Create a Text Input Control
// Output only
- uint16_t label(const char *label, ControlColor color, String value = ""); // Create Label
- uint16_t graph(const char *label, ControlColor color); // Create Graph display
- uint16_t gauge(const char *label, ControlColor color, int value, int min = 0,
- int max = 100); // Create Gauge display
+ uint16_t label(const char *label, ControlColor color, String value = ""); // Create Label
+ uint16_t graph(const char *label, ControlColor color); // Create Graph display
+ uint16_t gauge(const char *label, ControlColor color, int value, int min = 0, int max = 100); // Create Gauge display
// Input only
uint16_t accelerometer(const char *label, void (*callback)(Control *, int), ControlColor color);
@@ -242,8 +240,6 @@ public:
void updateControl(uint16_t id, int clientId = -1);
void updateControl(Control *control, int clientId = -1);
- void reload();
-
void print(uint16_t id, String value);
void updateLabel(uint16_t id, String value);
void updateSwitcher(uint16_t id, bool nValue, int clientId = -1);
@@ -259,8 +255,8 @@ public:
// Variables
const char *ui_title = "ESPUI"; // Store UI Title and Header Name
Control *controls = nullptr;
+ void jsonReload();
void jsonDom(AsyncWebSocketClient *client);
- void jsonReload(AsyncWebSocketClient *client);
Verbosity verbosity;
diff --git a/src/dataControlsJS.h b/src/dataControlsJS.h
index d62b572..9c61a55 100644
--- a/src/dataControlsJS.h
+++ b/src/dataControlsJS.h
@@ -1,253 +1,253 @@
-const char JS_CONTROLS[] PROGMEM = R"=====(
-const UI_INITIAL_GUI=200;const UI_RELOAD=201;const UPDATE_OFFSET=100;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 UPTDATE_ACCEL=117;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_NONE:return"dark";default:return"";}}
-var websock;var websockConnected=false;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);return savedData[id];}
-return[];}
-function restart(){$(document).add("*").off();$("#row").html("");websock.close();start();}
-function conStatusError(){websockConnected=false;$("#conStatus").removeClass("color-green");$("#conStatus").addClass("color-red");$("#conStatus").html("Error / No Connection ↻");$("#conStatus").off();$("#conStatus").on({click:restart,});}
-function handleVisibilityChange(){if(!websockConnected&&!document.hidden){restart();}}
-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");}
-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(evt);conStatusError();};var handleEvent=function(evt){var data=JSON.parse(evt.data);var e=document.body;var center="";switch(data.type){case UI_INITIAL_GUI:if(data.sliderContinuous){sliderContinuous=data.sliderContinuous;}
-data.controls.forEach(element=>{var fauxEvent={data:JSON.stringify(element),};handleEvent(fauxEvent);});break;case UI_RELOAD:window.location.reload();break;case UI_TITEL:document.title=data.label;$("#mainHeader").html(data.label);break;case UI_LABEL:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-parent.append(""+
-"
"+
-data.label+
-" "+
-""+
-data.value+
-" "+
-"");break;case UI_BUTTON:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-parent.append(""+
-"
"+
-data.label+
-" "+
-""+
-data.value+
-" ");$("#btn"+data.id).on({touchstart:function(e){e.preventDefault();buttonclick(data.id,true);},touchend:function(e){e.preventDefault();buttonclick(data.id,false);},});break;case UI_SWITCHER:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-parent.append(""+
-"
"+
-data.label+
-" "+
-"
"+
-"
"+
-" "+
-"
");switcher(data.id,data.value);break;case UI_CPAD:case UI_PAD:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-parent.append(""+
-"
"+
-data.label+
-" "+
-"
"+
-""+
-"▲ "+
-"▲ "+
-"▲ "+
-"▲ "+
-" "+
-(data.type==UI_CPAD?"OK ":"")+
-" "+
-"
");$("#pf"+data.id).on({touchstart:function(e){e.preventDefault();padclick(UP,data.id,true);},touchend:function(e){e.preventDefault();padclick(UP,data.id,false);},});$("#pl"+data.id).on({touchstart:function(e){e.preventDefault();padclick(LEFT,data.id,true);},touchend:function(e){e.preventDefault();padclick(LEFT,data.id,false);},});$("#pr"+data.id).on({touchstart:function(e){e.preventDefault();padclick(RIGHT,data.id,true);},touchend:function(e){e.preventDefault();padclick(RIGHT,data.id,false);},});$("#pb"+data.id).on({touchstart:function(e){e.preventDefault();padclick(DOWN,data.id,true);},touchend:function(e){e.preventDefault();padclick(DOWN,data.id,false);},});$("#pc"+data.id).on({touchstart:function(e){e.preventDefault();padclick(CENTER,data.id,true);},touchend:function(e){e.preventDefault();padclick(CENTER,data.id,false);},});break;case UI_SLIDER:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-parent.append(""+
-"
"+
-data.label+
-" "+
-"
"+
-" "+
-""+
-data.value+
-" "+
-"
"+
-"
");rangeSlider(!sliderContinuous);break;case UI_NUMBER:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-parent.append(""+
-"
"+
-data.label+
-" "+
-" "+
-"");break;case UI_TEXT_INPUT:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-parent.append(""+
-"
"+
-data.label+
-" "+
-" "+
-"");break;case UI_TAB:$("#tabsnav").append(""+data.value+" ");$("#tabscontent").append("
");tabs=$(".tabscontent").tabbedContent({loop:true}).data("api");$("a").filter(function(){return $(this).attr("href")==="#click-to-switch";}).on("click",function(e){var tab=prompt("Tab to switch to (number or id)?");if(!tabs.switchTab(tab)){alert("That tab does not exist :\\");}
-e.preventDefault();});break;case UI_SELECT:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-parent.append(""+
-"
"+
-data.label+
-" "+
-" "+
-"");break;case UI_OPTION:if(data.parentControl){var parent=$("#select"+data.parentControl);parent.append(" "+
-data.label+
-" ");}
-break;case UI_MIN:if(data.parentControl){var parent=$("#id"+data.parentControl+" input");if(parent.size()){parent.attr("min",data.value);}}
-break;case UI_MAX:if(data.parentControl){var parent=$("#id"+data.parentControl+" input");if(parent.size()){parent.attr("max",data.value);}}
-break;case UI_STEP:if(data.parentControl){var parent=$("#id"+data.parentControl+" input");if(parent.size()){parent.attr("step",data.value);}}
-break;case UI_GRAPH:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-parent.append(""+
-"
"+
-data.label+
-" "+
-""+
-""+
-data.label+
-" "+
-" "+
-"");graphData[data.id]=restoreGraphData(data.id);renderGraphSvg(graphData[data.id],"graph"+data.id);break;case ADD_GRAPH_POINT:var ts=Math.round(new Date().getTime()/1000);graphData[data.id].push({x:ts,y:data.value});saveGraphData();renderGraphSvg(graphData[data.id],"graph"+data.id);break;case CLEAR_GRAPH:graphData[data.id]=[];saveGraphData();renderGraphSvg(graphData[data.id],"graph"+data.id);break;case UI_GAUGE:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-parent.append(""+
-"
"+
-data.label+
-" "+
-"WILL BE A GAUGE "+
-"");break;case UI_ACCEL:if(hasAccel)break;var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
-hasAccel=true;parent.append(""+
-"
"+
-data.label+
-" "+
-"ACCEL // Not implemented fully!
");requestOrientationPermission();break;case UPDATE_LABEL:$("#l"+data.id).html(data.value);break;case UPDATE_SWITCHER:switcher(data.id,data.value=="0"?0:1);break;case UPDATE_SLIDER:slider_move($("#sl"+data.id),data.value,"100",false);break;case UPDATE_NUMBER:$("#num"+data.id).val(data.value);break;case UPDATE_TEXT_INPUT:$("#text"+data.id).val(data.value);break;case UPDATE_SELECT:$("#select"+data.id).val(data.value);break;case UPDATE_BUTTON:case UPDATE_PAD:case UPDATE_CPAD:break;case UPDATE_GAUGE:$("#gauge"+data.id).val(data.value);break;case UPDATE_ACCEL:break;default:console.error("Unknown type or event");break;}
-if(data.type>=UPDATE_OFFSET&&data.type
{var fauxEvent={data:JSON.stringify(element),};handleEvent(fauxEvent);});break;case UI_RELOAD:window.location.reload();break;case UI_TITEL:document.title=data.label;$("#mainHeader").html(data.label);break;case UI_LABEL:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+parent.append(""+
+"
"+
+data.label+
+" "+
+""+
+data.value+
+" "+
+"");break;case UI_BUTTON:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+parent.append(""+
+"
"+
+data.label+
+" "+
+""+
+data.value+
+" ");$("#btn"+data.id).on({touchstart:function(e){e.preventDefault();buttonclick(data.id,true);},touchend:function(e){e.preventDefault();buttonclick(data.id,false);},});break;case UI_SWITCHER:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+parent.append(""+
+"
"+
+data.label+
+" "+
+"
"+
+"
"+
+" "+
+"
");switcher(data.id,data.value);break;case UI_CPAD:case UI_PAD:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+parent.append(""+
+"
"+
+data.label+
+" "+
+"
"+
+""+
+"▲ "+
+"▲ "+
+"▲ "+
+"▲ "+
+" "+
+(data.type==UI_CPAD?"OK ":"")+
+" "+
+"
");$("#pf"+data.id).on({touchstart:function(e){e.preventDefault();padclick(UP,data.id,true);},touchend:function(e){e.preventDefault();padclick(UP,data.id,false);},});$("#pl"+data.id).on({touchstart:function(e){e.preventDefault();padclick(LEFT,data.id,true);},touchend:function(e){e.preventDefault();padclick(LEFT,data.id,false);},});$("#pr"+data.id).on({touchstart:function(e){e.preventDefault();padclick(RIGHT,data.id,true);},touchend:function(e){e.preventDefault();padclick(RIGHT,data.id,false);},});$("#pb"+data.id).on({touchstart:function(e){e.preventDefault();padclick(DOWN,data.id,true);},touchend:function(e){e.preventDefault();padclick(DOWN,data.id,false);},});$("#pc"+data.id).on({touchstart:function(e){e.preventDefault();padclick(CENTER,data.id,true);},touchend:function(e){e.preventDefault();padclick(CENTER,data.id,false);},});break;case UI_SLIDER:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+parent.append(""+
+"
"+
+data.label+
+" "+
+"
"+
+" "+
+""+
+data.value+
+" "+
+"
"+
+"
");rangeSlider(!sliderContinuous);break;case UI_NUMBER:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+parent.append(""+
+"
"+
+data.label+
+" "+
+" "+
+"");break;case UI_TEXT_INPUT:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+parent.append(""+
+"
"+
+data.label+
+" "+
+" "+
+"");break;case UI_TAB:$("#tabsnav").append(""+data.value+" ");$("#tabscontent").append("
");tabs=$(".tabscontent").tabbedContent({loop:true}).data("api");$("a").filter(function(){return $(this).attr("href")==="#click-to-switch";}).on("click",function(e){var tab=prompt("Tab to switch to (number or id)?");if(!tabs.switchTab(tab)){alert("That tab does not exist :\\");}
+e.preventDefault();});break;case UI_SELECT:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+parent.append(""+
+"
"+
+data.label+
+" "+
+" "+
+"");break;case UI_OPTION:if(data.parentControl){var parent=$("#select"+data.parentControl);parent.append(""+
+data.label+
+" ");}
+break;case UI_MIN:if(data.parentControl){var parent=$("#id"+data.parentControl+" input");if(parent.size()){parent.attr("min",data.value);}}
+break;case UI_MAX:if(data.parentControl){var parent=$("#id"+data.parentControl+" input");if(parent.size()){parent.attr("max",data.value);}}
+break;case UI_STEP:if(data.parentControl){var parent=$("#id"+data.parentControl+" input");if(parent.size()){parent.attr("step",data.value);}}
+break;case UI_GRAPH:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+parent.append(""+
+"
"+
+data.label+
+" "+
+""+
+""+
+data.label+
+" "+
+" "+
+"");graphData[data.id]=restoreGraphData(data.id);renderGraphSvg(graphData[data.id],"graph"+data.id);break;case ADD_GRAPH_POINT:var ts=Math.round(new Date().getTime()/1000);graphData[data.id].push({x:ts,y:data.value});saveGraphData();renderGraphSvg(graphData[data.id],"graph"+data.id);break;case CLEAR_GRAPH:graphData[data.id]=[];saveGraphData();renderGraphSvg(graphData[data.id],"graph"+data.id);break;case UI_GAUGE:var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+parent.append(""+
+"
"+
+data.label+
+" "+
+"WILL BE A GAUGE "+
+"");break;case UI_ACCEL:if(hasAccel)break;var parent;if(data.parentControl){parent=$("#tab"+data.parentControl);}else{parent=$("#row");}
+hasAccel=true;parent.append(""+
+"
"+
+data.label+
+" "+
+"ACCEL // Not implemented fully!
");requestOrientationPermission();break;case UPDATE_LABEL:$("#l"+data.id).html(data.value);break;case UPDATE_SWITCHER:switcher(data.id,data.value=="0"?0:1);break;case UPDATE_SLIDER:slider_move($("#sl"+data.id),data.value,"100",false);break;case UPDATE_NUMBER:$("#num"+data.id).val(data.value);break;case UPDATE_TEXT_INPUT:$("#text"+data.id).val(data.value);break;case UPDATE_SELECT:$("#select"+data.id).val(data.value);break;case UPDATE_BUTTON:case UPDATE_PAD:case UPDATE_CPAD:break;case UPDATE_GAUGE:$("#gauge"+data.id).val(data.value);break;case UPDATE_ACCEL:break;default:console.error("Unknown type or event");break;}
+if(data.type>=UPDATE_OFFSET&&data.type