From 9cd15db1ad8bcb62f3e361d38c410c7fdf3efd5e Mon Sep 17 00:00:00 2001 From: Ian Gray Date: Thu, 20 Jan 2022 21:50:06 +0000 Subject: [PATCH] Add Time control Adds a new invisible control that can fetch the current time from a connected client. Documentation is in the README. --- README.md | 29 +++++++++++++++++++++++++++++ data/js/controls.js | 11 +++++++++++ data/js/controls.min.js | 6 +++--- src/ESPUI.cpp | 11 +++++++++++ src/ESPUI.h | 4 ++++ src/dataControlsJS.h | 8 ++++---- 6 files changed, 62 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index ee04e88..98bf7f0 100644 --- a/README.md +++ b/README.md @@ -466,6 +466,35 @@ This can be applied to every element to force a single column layout, or to indi Note that this will have no effect on small screens. +### Advanced: Getting the Time + +ESPUI can create an invisible control that can be used to fetch the current time from the client when they are connected to the UI. This could be used to intermittently provide an accurate time source to your ESP. Remember that clients cannot be relied upon to be correct or truthful. If this is not a concern, you can do the following: + +``` +//Add the invisible "Time" control +auto timeId = ESPUI.addControl(Time, "", "", None, 0, timeCallback); +``` + +After creating the UI, sending an update to the Time control will cause it to fetch the current time from the client and then fire its callback with the result. + +``` +//Request an update to the time +ESPUI.updateTime(timeId); +//Will trigger timeCallback +``` + +In `timeCallback` you can then print the control's value as normal: + +``` +void timeCallback(Control *sender, int type) { + if(type == TM_VALUE) { + Serial.println(sender->value); + } +} +``` + +The returned string will be an [ISO string](https://www.w3schools.com/jsref/jsref_toisostring.asp) as returned by the Javascript `new Date().toISOString()`. The format is `YYYY-MM-DDTHH:mm:ss.sssZ` so for example: `2022-01-20T21:44:22.913Z`. + # Notes for Development If you want to work on the HTML/CSS/JS files, do make changes in the _data_ diff --git a/data/js/controls.js b/data/js/controls.js index 2d22e28..2b5ff1c 100644 --- a/data/js/controls.js +++ b/data/js/controls.js @@ -57,6 +57,9 @@ 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; @@ -555,6 +558,11 @@ function start() { 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; @@ -724,6 +732,9 @@ var addToHTML = function(data) { html = "
" + "
" + data.label + "

"; break; + case UI_TIME: + //Invisible element + break; } parent.append(html); diff --git a/data/js/controls.min.js b/data/js/controls.min.js index a14985c..60ee074 100644 --- a/data/js/controls.min.js +++ b/data/js/controls.min.js @@ -1,4 +1,4 @@ -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 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"";}} +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;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];} @@ -39,7 +39,7 @@ break;case UPDATE_TEXT_INPUT:$("#text"+data.id).val(data.value);if(data.hasOwnPr 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;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>=UPDATE_OFFSET&&data.type
"+data.label+"

"+ elementHTML(data.type,data.id,data.value,data.label,elementStyle)+ "";break;case UI_SEPARATOR:html="
"+ -"
"+data.label+"

";break;} +"
"+data.label+"

";break;case UI_TIME:break;} parent.append(html);}else{var parent=$("#id"+data.parentControl);parent.append(elementHTML(data.type,data.id,data.value,data.label,elementStyle));}} var elementHTML=function(type,id,value,label,elementStyle){switch(type){case UI_LABEL:return""+value+"";case UI_BUTTON:return"