diff --git a/README.md b/README.md
index 49c4a0d..0b31a83 100644
--- a/README.md
+++ b/README.md
@@ -122,6 +122,7 @@ Web page disconnects may occur randomly. Simply refresh the browser if this occu
```
1.0 : Apr-05-2022, PixelRadio V1.0, official release to the public.
1.1.1 : Jun-30-2022, PixelRadio V1.1,1, See release for changelog.
+1.1.2 : Oct-18-2022, PixelRadio V1.1,2, See release for changelog.
```
diff --git a/bin/pixelradio_bin_v1_1_1.zip b/bin/pixelradio_bin_v1_1_1.zip
deleted file mode 100644
index 775e685..0000000
Binary files a/bin/pixelradio_bin_v1_1_1.zip and /dev/null differ
diff --git a/bin/pixelradio_bin_v1_1_2.zip b/bin/pixelradio_bin_v1_1_2.zip
new file mode 100644
index 0000000..a45ea2f
Binary files /dev/null and b/bin/pixelradio_bin_v1_1_2.zip differ
diff --git a/docs/Hardware/README.md b/docs/Hardware/README.md
index 1b15e0c..672ed5e 100644
--- a/docs/Hardware/README.md
+++ b/docs/Hardware/README.md
@@ -99,12 +99,15 @@ The QN8027 RF Module must be installed directly on the PCB using the SIP Header
The header strips will provide a 2-3mm gap between the main PCB and the RF module.
Do **NOT** use a plug-in socket to mount the RF module.
-### FRONT PANEL LED
+### FRONT PANEL LED (MUSIC-ON STATUS)
-The green LED (Music-On indicator) requires long leads to reach the front panel.
+The green "*Music On*" LED requires long leads to reach the front panel.
Before soldering, temporarily position the enclosure's front panel and bend the LED's leads as needed.
Then solder in place.
+>Note: The *Music On* LED will be illuminated when the external audio (music source) is enabled.
+It will turn off whenever the [Test Tone](../User_Manual/AdjustTab.md) function is active.
+
### ESP32 INSTALLATION
The LilyGo TTGO-T8 ESP32 MCU includes a 2-pin wire pigtail cable.
Solder the cable to the P1 (VBAT) pads on the PCB;
diff --git a/lib/ESPUI/README.md b/lib/ESPUI/README.md
index 8fb2e27..f4d5978 100644
--- a/lib/ESPUI/README.md
+++ b/lib/ESPUI/README.md
@@ -4,7 +4,8 @@
ESPUI is a simple library to make a web-based user interface for your projects using
the **ESP8266** or the **ESP32** It uses web sockets and lets you create,
-control, and update elements on your GUI through multiple devices like phones
+
+ol, and update elements on your GUI through multiple devices like phones
and tablets.
ESPUI uses simple Arduino-style syntax for creating a solid, functioning user
@@ -27,6 +28,7 @@ The Library runs on any kind of **ESP8266** and **ESP32** (NodeMCU, AI Thinker,
* [Slider](#slider)
* [Number Input](#number-input)
* [Text Input](#text-input)
+ * [Date, Time, Colour and Password Input](#date-time-colour-and-password-input)
* [Select control](#select-control)
* [Getting the Time](#getting-the-time)
* [Separators](#separators)
@@ -41,6 +43,7 @@ The Library runs on any kind of **ESP8266** and **ESP32** (NodeMCU, AI Thinker,
* [Grouped controls](#grouped-controls)
* [Wide controls](#wide-controls)
* [Graph (Experimental)](#graph--experimental-)
+ * [Captive Portal](#captive-portal)
- [Notes for Development](#notes-for-development)
- [Contribute](#contribute)
@@ -58,6 +61,7 @@ The Library runs on any kind of **ESP8266** and **ESP32** (NodeMCU, AI Thinker,
- Transport layer rework by @iangray001
- Time control by @iangray001
- Vertical controls by @iangray001
+- Time/date/password/color input types by @pcbbc
## Roadmap
@@ -133,6 +137,7 @@ more program memory to work with.
- Control pad
- Slider
- Text Input
+- Date, Time, Colour and Password Input
- Numberinput
- Option select
- Separator
@@ -142,26 +147,59 @@ more program memory to work with.
## Documentation
-The heart of ESPUI is
-[ESPAsyncWebserver](https://github.com/me-no-dev/ESPAsyncWebServer). ESPUI's
-frontend is based on [Skeleton CSS](http://getskeleton.com/) and jQuery-like
-lightweight [zepto.js](https://zeptojs.com/) for handling events. The
-communication between the ESP and the client browser works using web
-sockets. ESPUI does not need network access and can be used in standalone access
-point mode, all resources are loaded directly from the ESPs memory.
-
-This section will explain in detail how the Library is to be used from the
-Arduino code side. In the arduino `setup()` routine the interface can be customised by adding UI Elements.
-This is done by calling the corresponding library methods on the Library object
-`ESPUI`. Eg: `ESPUI.button("button", &myCallback);` creates a button in the
-interface that calls the `myCallback(Control *sender, int value)` function when changed. All buttons and
-items call their callback whenever there is a state change from them. This means
-the button will call the callback when it is pressed and also again when it is
-released. To separate different events an integer number with the event name is
-passed to the callback function that can be handled in a `switch(){}case{}`
-statement.
-
-
+The heart of ESPUI is [ESPAsyncWebserver](https://github.com/me-no-dev/ESPAsyncWebServer). ESPUI's frontend is based on [Skeleton CSS](http://getskeleton.com/) and jQuery-like lightweight [zepto.js](https://zeptojs.com/) for handling events. The communication between the ESP and the client browser works using web sockets. ESPUI does not need network access and can be used in standalone access point mode, all resources are loaded directly from the ESPs memory.
+
+This section will explain in detail how the Library is to be used from the Arduino code side. In the arduino `setup()` routine the interface can be customised by adding UI Elements. This is done by calling the corresponding library methods on the Library object `ESPUI`. Eg: `ESPUI.button("button", &myCallback);` creates a button in the interface that calls the `myCallback(Control *sender, int eventname)` function when changed. All buttons and items call their callback whenever there is a state change from them. This means the button will call the callback when it is pressed and also again when it is released. To separate different events, an integer number with the event name is passed to the callback function that can be handled in a `switch(){}case{}` statement.
+
+Alternativly you may use the extended callback funtion which provides three parameters to the callback function `myCallback(Control *sender, int eventname, void * UserParameter)`. The `UserParameter` is provided as part of the `ESPUI.addControl` method set and allows the user to define contextual information that is to be presented to the callback function in an unmodified form.
+
"
+ );
+ $("#tabscontent").append("");
+
+ tabs = $(".tabscontent").tabbedContent({ loop: true }).data("api");
+ // switch to tab...
+ $("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_OPTION:
+ if (data.parentControl) {
+ var parent = $("#select" + data.parentControl);
+ parent.append(
+ ""
+ );
+ }
+ break;
+
+ case UI_MIN:
+ if (data.parentControl) {
+ //Is it applied to a slider?
+ if ($('#sl' + data.parentControl).length) {
+ $('#sl' + data.parentControl).attr("min", data.value);
+ } else if ($('#num' + data.parentControl).length) {
+ //Or a number
+ $('#num' + data.parentControl).attr("min", data.value);
+ }
+ }
+ break;
+
+ case UI_MAX:
+ if (data.parentControl) {
+ //Is it applied to a slider?
+ if ($('#sl' + data.parentControl).length) {
+ $('#sl' + data.parentControl).attr("max", data.value);
+ } else if ($('#text' + data.parentControl).length) {
+ //Is it a text element
+ $('#text' + data.parentControl).attr("maxlength", data.value);
+ } else if ($('#num' + data.parentControl).length) {
+ //Or a number
+ $('#num' + data.parentControl).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:
+ if (data.visible) {
+ addToHTML(data);
+ 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_ACCEL:
+ if (hasAccel) break;
+ hasAccel = true;
+ if (data.visible) {
+ addToHTML(data);
+ requestOrientationPermission();
+ }
+ break;
+
+ /*
+ * Update messages change the value/style of a component without adding new HTML
+ */
+ case UPDATE_LABEL:
+ $("#l" + data.id).html(data.value);
+ if (data.hasOwnProperty('elementStyle')) {
+ $("#l" + data.id).attr("style", data.elementStyle);
+ }
+ break;
+
+ case UPDATE_SWITCHER:
+ switcher(data.id, data.value == "0" ? 0 : 1);
+ if (data.hasOwnProperty('elementStyle')) {
+ $("#sl" + data.id).attr("style", data.elementStyle);
+ }
+ break;
+
+ case UPDATE_SLIDER:
+ $("#sl" + data.id).attr("value", data.value)
+ slider_move($("#sl" + data.id).parent().parent(), data.value, "100", false);
+ if (data.hasOwnProperty('elementStyle')) {
+ $("#sl" + data.id).attr("style", data.elementStyle);
+ }
+ break;
+
+ case UPDATE_NUMBER:
+ $("#num" + data.id).val(data.value);
+ if (data.hasOwnProperty('elementStyle')) {
+ $("#num" + data.id).attr("style", data.elementStyle);
+ }
+ break;
+
+ case UPDATE_TEXT_INPUT:
+ $("#text" + data.id).val(data.value);
+ if (data.hasOwnProperty('elementStyle')) {
+ $("#text" + data.id).attr("style", data.elementStyle);
+ }
+ if (data.hasOwnProperty('inputType')) {
+ $("#text" + data.id).attr("type", data.inputType);
+ }
+ 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;
+
+ default:
+ console.error("Unknown type or event");
+ break;
}
- break;
- case UPDATE_SELECT:
- $("#select" + data.id).val(data.value);
- if(data.hasOwnProperty('elementStyle')) {
- $("#select" + data.id).attr("style", data.elementStyle);
+ if (data.type >= UI_TITEL && data.type < UPDATE_OFFSET) {
+ //A UI element was just added to the DOM
+ processEnabled(data);
}
- 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);
+ if (data.type >= UPDATE_OFFSET && data.type < UI_INITIAL_GUI) {
+ //An "update" message was just recieved and processed
+ var element = $("#id" + data.id);
+
+ if (data.hasOwnProperty('panelStyle')) {
+ $("#id" + data.id).attr("style", data.panelStyle);
+ }
+
+ if (data.hasOwnProperty('visible')) {
+ if (data['visible'])
+ $("#id" + data.id).show();
+ else
+ $("#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);
}
- 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) {
- //A UI element was just added to the DOM
- processEnabled(data);
- }
-
- if (data.type >= UPDATE_OFFSET && data.type < UI_INITIAL_GUI) {
- //An "update" message was just recieved and processed
- var element = $("#id" + data.id);
-
- if(data.hasOwnProperty('panelStyle')) {
- $("#id" + data.id).attr("style", data.panelStyle);
- }
- if(data.hasOwnProperty('visible')) {
- if(data['visible'])
- $("#id" + data.id).show();
- else
- $("#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"));
- });
- };
+ $(".range-slider__range").each(function () {
+ $(this)[0].value = $(this).attr("value");
+ $(this).next().html($(this).attr("value"));
+ });
+ };
- websock.onmessage = handleEvent;
+ websock.onmessage = handleEvent;
}
function sliderchange(number) {
- var val = $("#sl" + number).val();
- websock.send("slvalue:" + val + ":" + number);
+ var val = $("#sl" + number).val();
+ websock.send("slvalue:" + val + ":" + number);
- $(".range-slider__range").each(function(){
- $(this).attr("value", $(this)[0].value);
- });
+ $(".range-slider__range").each(function () {
+ $(this).attr("value", $(this)[0].value);
+ });
}
function numberchange(number) {
- var val = $("#num" + number).val();
- websock.send("nvalue:" + val + ":" + number);
+ var val = $("#num" + number).val();
+ websock.send("nvalue:" + val + ":" + number);
}
function textchange(number) {
- var val = $("#text" + number).val();
- websock.send("tvalue:" + val + ":" + number);
+ var val = $("#text" + number).val();
+ websock.send("tvalue:" + val + ":" + number);
}
function tabclick(number) {
- var val = $("#tab" + number).val();
- websock.send("tabvalue:" + val + ":" + number);
+ var val = $("#tab" + number).val();
+ websock.send("tabvalue:" + val + ":" + number);
}
function selectchange(number) {
- var val = $("#select" + number).val();
- websock.send("svalue:" + val + ":" + number);
+ var val = $("#select" + number).val();
+ websock.send("svalue:" + val + ":" + number);
}
function buttonclick(number, isdown) {
- if (isdown) websock.send("bdown:" + number);
- else websock.send("bup:" + number);
+ if (isdown) websock.send("bdown:" + number);
+ else websock.send("bup:" + number);
}
function padclick(type, number, isdown) {
-if($("#id" + number + " nav").hasClass("disabled")) {
- return;
- }
- switch (type) {
- case CENTER:
- if (isdown) websock.send("pcdown:" + number);
- else websock.send("pcup:" + number);
- break;
- case UP:
- if (isdown) websock.send("pfdown:" + number);
- else websock.send("pfup:" + number);
- break;
- case DOWN:
- if (isdown) websock.send("pbdown:" + number);
- else websock.send("pbup:" + number);
- break;
- case LEFT:
- if (isdown) websock.send("pldown:" + number);
- else websock.send("plup:" + number);
- break;
- case RIGHT:
- if (isdown) websock.send("prdown:" + number);
- else websock.send("prup:" + number);
- break;
- }
+ if ($("#id" + number + " nav").hasClass("disabled")) {
+ return;
+ }
+ switch (type) {
+ case CENTER:
+ if (isdown) websock.send("pcdown:" + number);
+ else websock.send("pcup:" + number);
+ break;
+ case UP:
+ if (isdown) websock.send("pfdown:" + number);
+ else websock.send("pfup:" + number);
+ break;
+ case DOWN:
+ if (isdown) websock.send("pbdown:" + number);
+ else websock.send("pbup:" + number);
+ break;
+ case LEFT:
+ if (isdown) websock.send("pldown:" + number);
+ else websock.send("plup:" + number);
+ break;
+ case RIGHT:
+ if (isdown) websock.send("prdown:" + number);
+ else websock.send("prup:" + number);
+ break;
+ }
}
function switcher(number, state) {
- if (state == null) {
- if (!$("#sl" + number).hasClass("checked")) {
- websock.send("sactive:" + number);
- $("#sl" + number).addClass("checked");
- } else {
- websock.send("sinactive:" + number);
- $("#sl" + number).removeClass("checked");
+ if (state == null) {
+ if (!$("#sl" + number).hasClass("checked")) {
+ websock.send("sactive:" + number);
+ $("#sl" + number).addClass("checked");
+ } else {
+ websock.send("sinactive:" + number);
+ $("#sl" + number).removeClass("checked");
+ }
+ } else if (state == 1) {
+ $("#sl" + number).addClass("checked");
+ $("#sl" + number).prop("checked", true);
+ } else if (state == 0) {
+ $("#sl" + number).removeClass("checked");
+ $("#sl" + number).prop("checked", false);
}
- } else if (state == 1) {
- $("#sl" + number).addClass("checked");
- $("#sl" + number).prop("checked", true);
- } else if (state == 0) {
- $("#sl" + number).removeClass("checked");
- $("#sl" + number).prop("checked", false);
- }
}
var rangeSlider = function (isDiscrete) {
- var range = $(".range-slider__range");
- var slidercb = function() {
- sliderchange($(this).attr("id").replace(/^\D+/g, ""));
- };
-
- range.on({input: function() {
- $(this).next().html(this.value)}
- });
-
- range.each(function() {
- $(this).next().html(this.value);
- if($(this).attr("callbackSet") != "true") {
- if (!isDiscrete) {
- $(this).on({input: slidercb}); //input fires when dragging
- } else {
- $(this).on({change: slidercb}); //change fires only once released
- }
- $(this).attr("callbackSet", "true");
- }
- });
+ var range = $(".range-slider__range");
+ var slidercb = function () {
+ sliderchange($(this).attr("id").replace(/^\D+/g, ""));
+ };
+
+ range.on({
+ input: function () {
+ $(this).next().html(this.value)
+ }
+ });
+
+ range.each(function () {
+ $(this).next().html(this.value);
+ if ($(this).attr("callbackSet") != "true") {
+ if (!isDiscrete) {
+ $(this).on({ input: slidercb }); //input fires when dragging
+ } else {
+ $(this).on({ change: slidercb }); //change fires only once released
+ }
+ $(this).attr("callbackSet", "true");
+ }
+ });
};
-var addToHTML = function(data) {
- panelStyle = data.hasOwnProperty('panelStyle') ? " style='" + data.panelStyle + "' " : "";
- panelwide = data.hasOwnProperty('wide') ? "wide" : "";
-
- if(!data.hasOwnProperty('parentControl') || $("#tab" + data.parentControl).length > 0) {
- //We add the control with its own panel
- var parent = data.hasOwnProperty('parentControl') ?
- $("#tab" + data.parentControl) :
- $("#row");
-
- var html = "";
- switch(data.type) {
- case UI_LABEL:
- case UI_BUTTON:
- case UI_SWITCHER:
- case UI_CPAD:
- case UI_PAD:
- case UI_SLIDER:
- case UI_NUMBER:
- case UI_TEXT_INPUT:
- case UI_SELECT:
- case UI_GRAPH:
- case UI_GAUGE:
- case UI_ACCEL:
- html = "
" + data.label + "
" +
- elementHTML(data) +
- "
";
- break;
- case UI_SEPARATOR:
- html = "
" +
- "
" + data.label + "
";
- break;
- case UI_TIME:
- //Invisible element
- break;
- }
+var addToHTML = function (data) {
+ panelStyle = data.hasOwnProperty('panelStyle') ? " style='" + data.panelStyle + "' " : "";
+ panelwide = data.hasOwnProperty('wide') ? "wide" : "";
+
+ if (!data.hasOwnProperty('parentControl') || $("#tab" + data.parentControl).length > 0) {
+ //We add the control with its own panel
+ var parent = data.hasOwnProperty('parentControl') ?
+ $("#tab" + data.parentControl) :
+ $("#row");
+
+ var html = "";
+ switch (data.type) {
+ case UI_LABEL:
+ case UI_BUTTON:
+ case UI_SWITCHER:
+ case UI_CPAD:
+ case UI_PAD:
+ case UI_SLIDER:
+ case UI_NUMBER:
+ case UI_TEXT_INPUT:
+ case UI_SELECT:
+ case UI_GRAPH:
+ case UI_GAUGE:
+ case UI_ACCEL:
+ html = "
" + data.label + "
" +
+ elementHTML(data) +
+ "
";
+ break;
+ case UI_SEPARATOR:
+ html = "
" +
+ "
" + data.label + "
";
+ break;
+ case UI_TIME:
+ //Invisible element
+ break;
+ }
- parent.append(html);
+ parent.append(html);
- } else {
- //We are adding to an existing panel so we only need the HTML for the element
- var parent = $("#id" + data.parentControl);
- parent.append(elementHTML(data));
- }
+ } else {
+ //We are adding to an existing panel so we only need the HTML for the element
+ var parent = $("#id" + data.parentControl);
+ parent.append(elementHTML(data));
+ }
}
-var elementHTML = function(data) {
- var id = data.id
- var elementStyle = data.hasOwnProperty('elementStyle') ? " style='" + data.elementStyle + "' " : "";
- switch(data.type) {
- case UI_LABEL:
- return "" + data.value + "";
- case UI_BUTTON:
- return "";
- case UI_SWITCHER:
- return "";
- case UI_CPAD:
- case UI_PAD:
- return "";
- case UI_SLIDER:
- return "
" +
- "" +
- data.value + "
";
- case UI_NUMBER:
- return "";
- case UI_TEXT_INPUT:
- return "";
- case UI_SELECT:
- return "";
- case UI_GRAPH:
- return "";
- case UI_GAUGE:
- return "WILL BE A GAUGE ";
- case UI_ACCEL:
- return "ACCEL // Not implemented fully!
";
- default:
- return "";
- }
+var elementHTML = function (data) {
+ var id = data.id
+ var elementStyle = data.hasOwnProperty('elementStyle') ? " style='" + data.elementStyle + "' " : "";
+ var inputType = data.hasOwnProperty('inputType') ? " type='" + data.inputType + "' " : "";
+ switch (data.type) {
+ case UI_LABEL:
+ return "" + data.value + "";
+ case UI_BUTTON:
+ return "";
+ case UI_SWITCHER:
+ return "";
+ case UI_CPAD:
+ case UI_PAD:
+ return "";
+ case UI_SLIDER:
+ return "
" +
+ "" +
+ data.value + "
";
+ case UI_NUMBER:
+ return "";
+ case UI_TEXT_INPUT:
+ return "";
+ case UI_SELECT:
+ return "";
+ case UI_GRAPH:
+ return "";
+ case UI_GAUGE:
+ return "WILL BE A GAUGE ";
+ case UI_ACCEL:
+ return "ACCEL // Not implemented fully!
";
+ default:
+ return "";
+ }
}
-var processEnabled = function(data) {
- //Handle the enabling and disabling of controls
- //Most controls can be disabled through the use of $("#").prop("disabled", true) and CSS will style it accordingly
- //The switcher and pads also require the addition of the "disabled" class
- switch(data.type) {
- case UI_SWITCHER:
- case UPDATE_SWITCHER:
- if(data.enabled) {
- $("#sl" + data.id).removeClass('disabled');
- $("#s" + data.id).prop("disabled", false);
- } else {
- $("#sl" + data.id).addClass('disabled');
- $("#s" + data.id).prop("disabled", true);
- }
- break;
-
- case UI_SLIDER:
- case UPDATE_SLIDER:
- $("#sl" + data.id).prop("disabled", !data.enabled);
- break;
-
- case UI_NUMBER:
- case UPDATE_NUMBER:
- $("#num" + data.id).prop("disabled", !data.enabled);
- break;
-
- case UI_TEXT_INPUT:
- case UPDATE_TEXT_INPUT:
- $("#text" + data.id).prop("disabled", !data.enabled);
- break;
-
- case UI_SELECT:
- case UPDATE_SELECT:
- $("#select" + data.id).prop("disabled", !data.enabled);
- break;
-
- case UI_BUTTON:
- case UPDATE_BUTTON:
- $("#btn" + data.id).prop("disabled", !data.enabled);
- break;
-
- case UI_PAD:
- case UI_CPAD:
- case UPDATE_PAD:
- case UPDATE_CPAD:
- if(data.enabled) {
- $("#id" + data.id + " nav").removeClass('disabled');
- } else {
- $("#id" + data.id + " nav").addClass('disabled');
- }
- break;
- }
+var processEnabled = function (data) {
+ //Handle the enabling and disabling of controls
+ //Most controls can be disabled through the use of $("#").prop("disabled", true) and CSS will style it accordingly
+ //The switcher and pads also require the addition of the "disabled" class
+ switch (data.type) {
+ case UI_SWITCHER:
+ case UPDATE_SWITCHER:
+ if (data.enabled) {
+ $("#sl" + data.id).removeClass('disabled');
+ $("#s" + data.id).prop("disabled", false);
+ } else {
+ $("#sl" + data.id).addClass('disabled');
+ $("#s" + data.id).prop("disabled", true);
+ }
+ break;
+
+ case UI_SLIDER:
+ case UPDATE_SLIDER:
+ $("#sl" + data.id).prop("disabled", !data.enabled);
+ break;
+
+ case UI_NUMBER:
+ case UPDATE_NUMBER:
+ $("#num" + data.id).prop("disabled", !data.enabled);
+ break;
+
+ case UI_TEXT_INPUT:
+ case UPDATE_TEXT_INPUT:
+ $("#text" + data.id).prop("disabled", !data.enabled);
+ break;
+
+ case UI_SELECT:
+ case UPDATE_SELECT:
+ $("#select" + data.id).prop("disabled", !data.enabled);
+ break;
+
+ case UI_BUTTON:
+ case UPDATE_BUTTON:
+ $("#btn" + data.id).prop("disabled", !data.enabled);
+ break;
+
+ case UI_PAD:
+ case UI_CPAD:
+ case UPDATE_PAD:
+ case UPDATE_CPAD:
+ if (data.enabled) {
+ $("#id" + data.id + " nav").removeClass('disabled');
+ } else {
+ $("#id" + data.id + " nav").addClass('disabled');
+ }
+ break;
+ }
}
diff --git a/lib/ESPUI/data/js/controls.min.js b/lib/ESPUI/data/js/controls.min.js
index e3b5774..3098429 100644
--- a/lib/ESPUI/data/js/controls.min.js
+++ b/lib/ESPUI/data/js/controls.min.js
@@ -1,13 +1,16 @@
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(){}
+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);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 restart(){$(document).add("*").off();$("#row").html("");conStatusError();start();}
+function conStatusError(){if(true===websockConnected){websockConnected=false;websock.close();$("#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){console.log(evt);var data=JSON.parse(evt.data);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;}
+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;};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));}
break;case UI_EXTEND_GUI:data.controls.forEach(element=>{var fauxEvent={data:JSON.stringify(element),};handleEvent(fauxEvent);});if(data.totalcontrols>data.startindex+(data.controls.length-1)){websock.send("uiok:"+(data.startindex+(data.controls.length-1)));}
break;case UI_RELOAD:window.location.reload();break;case UI_TITEL:document.title=data.label;$("#mainHeader").html(data.label);break;case UI_LABEL:case UI_NUMBER:case UI_TEXT_INPUT:case UI_SELECT:case UI_GAUGE:case UI_SEPARATOR:if(data.visible)addToHTML(data);break;case UI_BUTTON:if(data.visible){addToHTML(data);$("#btn"+data.id).on({touchstart:function(e){e.preventDefault();buttonclick(data.id,true);},touchend:function(e){e.preventDefault();buttonclick(data.id,false);},});}
@@ -33,9 +36,10 @@ break;case ADD_GRAPH_POINT:var ts=Math.round(new Date().getTime()/1000);graphDat
break;case UPDATE_LABEL:$("#l"+data.id).html(data.value);if(data.hasOwnProperty('elementStyle')){$("#l"+data.id).attr("style",data.elementStyle);}
break;case UPDATE_SWITCHER:switcher(data.id,data.value=="0"?0:1);if(data.hasOwnProperty('elementStyle')){$("#sl"+data.id).attr("style",data.elementStyle);}
break;case UPDATE_SLIDER:$("#sl"+data.id).attr("value",data.value)
-slider_move($("#id"+data.id),data.value,"100",false);if(data.hasOwnProperty('elementStyle')){$("#sl"+data.id).attr("style",data.elementStyle);}
+slider_move($("#sl"+data.id).parent().parent(),data.value,"100",false);if(data.hasOwnProperty('elementStyle')){$("#sl"+data.id).attr("style",data.elementStyle);}
break;case UPDATE_NUMBER:$("#num"+data.id).val(data.value);if(data.hasOwnProperty('elementStyle')){$("#num"+data.id).attr("style",data.elementStyle);}
break;case UPDATE_TEXT_INPUT:$("#text"+data.id).val(data.value);if(data.hasOwnProperty('elementStyle')){$("#text"+data.id).attr("style",data.elementStyle);}
+if(data.hasOwnProperty('inputType')){$("#text"+data.id).attr("type",data.inputType);}
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);}
@@ -65,7 +69,7 @@ elementHTML(data)+
"