dashboard gauge wip

This commit is contained in:
DeltaLima 2025-04-07 20:16:45 +02:00
parent 30b06c351a
commit 0103a0bfe5
5 changed files with 343 additions and 4 deletions

View file

@ -247,7 +247,165 @@ a.disabled {
/*@media only screen and (min-width: 640px) {
}*/)";
}*/
/* Gauge CSS
* based on https://github.com/sathomas/material-gauge */
.gauge {
position: relative;
}
.gaugeWrapper {
overflow: hidden;
display: flex;
justify-content: center;
}
.gauge__container {
margin: 0;
padding: 0;
position: absolute;
left: 50%;
overflow: hidden;
text-align: center;
-webkit-transform: translateX(-50%);
-moz-transform: translateX(-50%);
-ms-transform: translateX(-50%);
-o-transform: translateX(-50%);
transform: translateX(-50%);
}
.gauge__background {
z-index: 0;
position: absolute;
background-color: #cae0d0;
top: 0;
border-radius: 300px 300px 0 0;
}
.gauge__data {
z-index: 1;
position: absolute;
background-color: #04AA6D;
margin-left: auto;
margin-right: auto;
border-radius: 300px 300px 0 0;
-webkit-transform-origin: center bottom;
-moz-transform-origin: center bottom;
-ms-transform-origin: center bottom;
-o-transform-origin: center bottom;
transform-origin: center bottom;
}
.gauge__center {
z-index: 2;
position: absolute;
background-color: #1d211e;
margin-right: auto;
border-radius: 300px 300px 0 0;
}
.gauge__marker {
z-index: 3;
background-color: #fff;
position: absolute;
width: 1px;
}
.gauge__needle {
z-index: 4;
background-color: #E91E63;
height: 3px;
position: absolute;
-webkit-transform-origin: left center;
-moz-transform-origin: left center;
-ms-transform-origin: left center;
-o-transform-origin: left center;
transform-origin: left center;
}
.gauge__labels {
display: table;
margin: 0 auto;
position: relative;
font-weight: bold;
}
.gauge__label--low {
display: table-cell;
text-align: center;
}
.gauge__label--spacer {
display: table-cell;
}
.gauge__label--high {
display: table-cell;
text-align: center;
}
.gauge { height: calc(60px + 3em); }
.gauge__container { width: 120px; height: 60px; }
.gauge__marker { height: 60px; left: 59.5px; }
.gauge__background { width: 120px; height: 60px; }
.gauge__center { width: 72px; height: 36px; top: 24px; margin-left: 24px; }
.gauge__data { width: 120px; height: 60px; }
.gauge__needle { left: 60px; top: 58px; width: 60px; }
.gauge__labels { top: 60px; width: 120px; }
.gauge__label--low { width: 24px; }
.gauge__label--spacer { width: 72px; text-align: center;}
.gauge__label--high { width: 24px; }
.gaugeLabel { text-align: center; }
@media only screen and (min-width: 720px) {
.gauge { height: calc(120px + 4.2em); }
.gauge__container { width: 240px; height: 120px; }
.gauge__marker { height: 120px; left: 119.5px; }
.gauge__background { width: 240px; height: 120px; }
.gauge__center { width: 144px; height: 72px; top: 48px; margin-left: 48px; }
.gauge__data { width: 240px; height: 120px; }
.gauge__needle { left: 120px; top: 117px; width: 120px; }
.gauge__labels { top: 120px; width: 240px; }
.gauge__label--low { width: 48px; }
.gauge__label--spacer { width: 144px; text-align: center;}
.gauge__label--high { width: 48px; }
.gaugeLabel { font-size: 1.3em; }
.gauge__labels { font-size: 2em; }
}
.gauge--liveupdate .gauge__data,
.gauge--liveupdate .gauge__needle {
-webkit-transition: all 1s ease-in-out;
-moz-transition: all 1s ease-in-out;
-ms-transition: all 1s ease-in-out;
-o-transition: all 1s ease-in-out;
transition: all 1s ease-in-out;
}
.gauge__data {
-webkit-transform: rotate(-.50turn);
-moz-transform: rotate(-.50turn);
-ms-transform: rotate(-.50turn);
-o-transform: rotate(-.50turn);
transform: rotate(-.50turn);
}
.gauge__needle {
-webkit-transform: rotate(-.50turn);
-moz-transform: rotate(-.50turn);
-ms-transform: rotate(-.50turn);
-o-transform: rotate(-.50turn);
transform: rotate(-.50turn);
}
)";
void WebFile_cangrow_CSS(AsyncWebServerRequest *request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/css"), File_cangrow_CSS);

View file

@ -231,6 +231,70 @@ function sensorRefresh(sensor, reading, id) {
//console.log('sensor:' + sensor + ';reading:' + reading + ';id:' + id + ';element:' + element);
}
/* Gauge JS
* based on https://github.com/sathomas/material-gauge */
function Gauge(el) {
var element, // Containing element for the info component
data, // `.gauge__data` element
needle, // `.gauge__needle` element
value = 0.0, // Current gauge value from 0 to 1
prop, // Style for transform
valueLabel; // `.gauge__label--spacer` element
var setElement = function(el) {
// Keep a reference to the various elements and sub-elements
element = el;
data = element.querySelector('.gauge__data');
needle = element.querySelector('.gauge__needle');
valueLabel = element.querySelector('.gauge__label--spacer');
};
var setValue = function(x, max, unit) {
percentage = x * 100 / max;
value = percentage / 100;
var turns = -0.5 + (value * 0.5);
data.style[prop] = 'rotate(' + turns + 'turn)';
needle.style[prop] = 'rotate(' + turns + 'turn)';
valueLabel.textContent = x + unit;
};
function exports() { };
exports.element = function(el) {
if (!arguments.length) { return element; }
setElement(el);
return this;
};
exports.value = function(x, max=100, unit='%') {
if (!arguments.length) { return value; }
setValue(x, max, unit);
return this;
};
var body = document.getElementsByTagName('body')[0];
['webkitTransform', 'mozTransform', 'msTransform', 'oTransform', 'transform'].
forEach(function(p) {
if (typeof body.style[p] !== 'undefined') { prop = p; }
}
);
if (arguments.length) {
setElement(el);
}
return exports;
};
)";
void WebFile_cangrow_JS(AsyncWebServerRequest *request) {

View file

@ -8,14 +8,113 @@
#include "Page_root_HTML.h"
const byte Max_Dashboard_Gauge_PerLine = 3;
// https://techtutorialsx.com/2018/07/23/esp32-arduino-http-server-template-processing-with-multiple-placeholders/
String Proc_WebPage_root(const String& var) {
if(TestHeaderFooter(var)) {
return AddHeaderFooter(var);
} else if(var == "LOL") {
return String("Nice");
} else if(var == "GAUGE") {
String html;
/* first count, if any gauges are configured */
byte gaugeCount = 0;
for(byte i = 0; i < Max_Dashboard_Gauge; i++) {
if(config.grow.dashboard.gaugeConfigured[i] == true)
gaugeCount++;
}
/* if any gauges are configured, create anything needed for drawing gauges */
if(gaugeCount > 0) {
/* which gauge we are drawing, we count it here. begin with 1 */
byte gaugeNr = 0;
/* count how many gauges this line are drawn */
byte gaugeNrLine = 0;
for(byte i = 0; i < Max_Dashboard_Gauge; i++) {
if(config.grow.dashboard.gaugeConfigured[i] == true) {
/* increment gaugeNr and gauteNrLine */
gaugeNr++;
gaugeNrLine++;
/* when its the first gauge this line */
if(gaugeNrLine == 1)
/* open gauge wrapper div*/
html += F("<div class='gaugeWrapper'>");
/* open gauge div */
html += F("<div class='gauge gauge--liveupdate spacer' id='gauge-");
html += config.grow.dashboard.gaugeSensor[i];
html += F("-");
html += config.grow.dashboard.gaugeRead[i];
html += F("' style='float:left; ");
/* if it is the last gauge, dont add a margin */
if(gaugeNrLine < Max_Dashboard_Gauge_PerLine) {
html += F("margin-right: 10px;'>");
} else {
html += F("'>");
}
/* gauge label */
html += F("<div class='gaugeLabel'>");
html += FPSTR(Sensor_Read_descr[SensorIndex[config.system.sensor.type[config.grow.dashboard.gaugeSensor[i]]].read[config.grow.dashboard.gaugeRead[i]]]);
html += F("</div>\n");
/* rest of the gauge body, its always the same */
html += FPSTR(Common_HTML_Gauge_Body);
if(gaugeNrLine >= Max_Dashboard_Gauge_PerLine) {
/* close gauge wrapper div*/
html += F("</div>\n");
/* reset to 0 , max gauges per line reached */
gaugeNrLine = 0;
}
}
}
/* build javascript calls for gauges */
html += F("<script>");
/* iterate again through all configured gauges */
for(byte i = 0; i < Max_Dashboard_Gauge; i++) {
if(config.grow.dashboard.gaugeConfigured[i] == true) {
/* build name of the gauge object */
String gaugeName;
gaugeName += config.grow.dashboard.gaugeSensor[i];
gaugeName += F("-");
gaugeName += config.grow.dashboard.gaugeRead[i];
html += F("var gaugeJS-");
html += gaugeName;
html += F(" = new Gauge(document.getElementById('gauge-");
html += gaugeName;
html += F("'));\n");
/* "execute" gauge with actual sensor reading */
html += F("gauge-");
html += gaugeName;
html += F(".value('");
/* sensor reading */
html += Sensor_getCalibratedValue(config.grow.dashboard.gaugeSensor[i], config.grow.dashboard.gaugeRead[i]);
html += F("', ");
/* gaugeMax */
html += config.grow.dashboard.gaugeMax[i];
html += F(", ' ");
/* reading unit */
String unit;
unit = FPSTR(Sensor_Read_unit[SensorIndex[config.system.sensor.type[config.grow.dashboard.gaugeSensor[i]]].read[config.grow.dashboard.gaugeRead[i]]]);
unit.replace(F("%"), F("&#37;"));
html += unit;
html += F("');\n");
}
}
/* close script section */
html += F("</script>");
}
return html;
//return String("Nice");
} else if(var == "LOL") {
return String("Jojoojo :)");
} else {

View file

@ -10,4 +10,7 @@
const char Page_root_HTML[] PROGMEM = R"EOF(%HEADER%
<h2>&#x1F331; Hello world!</h2>
<a href='/api/sensor/'>Sensor data -> /api/sensor/</a>
%GAUGE%
%FOOTER% )EOF";

View file

@ -27,3 +27,18 @@ const char Common_HTML_NEED_RESTART[] PROGMEM = R"EOF(
const char Common_HTML_ACTION_ADD[] PROGMEM = {"&#10133; Add"};
const char Common_HTML_ACTION_EDIT[] PROGMEM = {"&#x270F;&#xFE0F; Edit"};
const char Common_HTML_Gauge_Body[] PROGMEM = R"EOF(
<div class='gauge__container'>
<div class='gauge__background'></div>
<div class='gauge__center'></div>
<div class='gauge__data'></div>
<div class='gauge__needle'></div>
</div>
<div class='gauge__labels mdl-typography__headline'>
<span class='gauge__label--low'></span>
<span class='gauge__label--spacer'></span>
<span class='gauge__label--high'></span>
</div>
</div>
)EOF";