firmware wip - gauge meter for Grow overview :)

This commit is contained in:
Marcus 2024-05-03 00:33:23 +02:00
parent cc34bc851b
commit 67d8968d0c
8 changed files with 806 additions and 88 deletions

View file

@ -184,14 +184,12 @@ const char HTMLheaderP1[] PROGMEM = R"EOF(
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<title>
)EOF";
// here comes the page title in returnHTMLheader()
// second part of HTML header stuff
// Having the whole CSS here ensures it's all the time present
const char HTMLheaderP2[] PROGMEM = R"EOF(
</title>
<link rel='icon' href='data:;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsTAAALEwEAmpwYAAABcElEQVQ4y42TzU/bQBDFf7Nx1qGuAYVgQSuo2khBggPhyIH//9AiJAQ9tEeLqCKiUD6sxF52OMSEBCdW57aa9968fTsr3V5XWVLPO6sANNL7ZRAMNeU6Ea4T1UEI6pr55kcAwhpMrYOpk2/r/yEQmKWkIonf+TZVgex4Fw0bIEtIAALF3gbZ8U5VwKa3PJ18JT9IpiLvyflBwuhLG5veVUM0/0aoCONPa2hQjWZ8uEVeupJnXSBwO8YOH8iTeAKc2Q4Xt2C1VZL93F7MjbK/bxDnp5Zn7b+So+9pdQ+K/Q5qJlrRj5Ts6DM+rK7Ih7Mr3HaM7jYQVZqXQ6Tb6yqBYdTfomhHiFfUyMI3f+01/z7RHNzTGDyWGThP63SA2d8EEfIkrgQpzmOvH0AV+3M4zegNpUwagAYG8Yp4BS0nl4Kz5Mpf0JXJMby6w/66Aa+M+9uE53/Iexsggq4ESOYWC0jmsBfX8xdXhcJjL4cLc3kBl8uJGQ/CrpAAAAAASUVORK5CYII='>
<style>
body {
@ -321,6 +319,284 @@ function convertDateToEpoch(src, dst) {
</script>
)EOF";
// The gauge meter are based on sathomas' gaugemeter
// https://github.com/sathomas/material-gauge
const char CSSgauge[] PROGMEM = R"EOF(
.gauge {
position: relative;
margin-right: 10px;
}
.gaugeWrapper {
overflow: hidden;
display: flex;
justify-content: center;
}
.gaugeLabel {
font-weight: bold;
}
.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;
}
.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; }
@media only screen and (min-width: 720px) {
.gauge { height: calc(120px + 3em); }
.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; }
}
.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);
}
)EOF";
const char JSgauge[] PROGMEM = R"EOF(
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;
};
)EOF";
const char HTMLgauge[] PROGMEM = R"EOF(
<div class='gaugeWrapper'>
<div class='gauge gauge--liveupdate' id='gaugeTemperature' style='float:left;'>
<span class='gaugeLabel'>Temperature</span>
<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>
<span class='gauge__label--high'></span>
</div>
</div>
<div class='gauge gauge--liveupdate' id='gaugeHumidity' style='float:left;'>
<span class='gaugeLabel'>Humidity</span>
<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>
<div class='gauge gauge--liveupdate' id='gaugeSoilmoisture' style='float:left;'>
<span class='gaugeLabel'>Moisture</span>
<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>
</div>
<script src='gauge.js'></script>
<script>
var gaugeTemperature = new Gauge(document.getElementById('gaugeTemperature'));
var gaugeHumidity = new Gauge(document.getElementById('gaugeHumidity'));
var gaugeSoilmoisture = new Gauge(document.getElementById('gaugeSoilmoisture'));
</script>
)EOF";
/*
*
* Pin assignments
@ -1350,6 +1626,10 @@ void WebHandler() {
// api stuff
webserver.on("/api/sensors", HTTP_GET, APIgetSensors);
// gauge meter stuff
webserver.on("/gauge.css", HTTP_GET, WEBgaugeCss);
webserver.on("/gauge.js", HTTP_GET, WEBgaugeJs);
}
/*
@ -1362,6 +1642,8 @@ String returnHTMLheader(String MenuEntry = "") {
String activeMenu = "class='activeMenu'";
// add first part of the header
header += FPSTR(HTMLheaderP1);
// add title tag
header += "<title>";
// check if GrowName was set. if yes, its part of the page title.
if(strlen(GrowName) > 0) {
header += "CanGrow - ";
@ -1369,6 +1651,13 @@ String returnHTMLheader(String MenuEntry = "") {
} else {
header += "CanGrow";
}
// close title tag
header += "</title>\n";
// add additional header stuff, like loading guage files
if(MenuEntry == "root") {
header += "<link rel='stylesheet' type='text/css' href='gauge.css'>";
}
header += FPSTR(HTMLheaderP2);
@ -1580,6 +1869,19 @@ void Syslogout() {
*
*/
/*
* Gauge meter files
*/
void WEBgaugeCss() {
//String css = CSSgauge;
webserver.send(200, "text/css", FPSTR(CSSgauge));
}
void WEBgaugeJs() {
//String javascript = JSgauge;
webserver.send(200, "text/javascript", FPSTR(JSgauge));
}
/*
* Root page
*/
@ -1595,37 +1897,50 @@ void WEBroot() {
webserver.sendHeader("Location", String("/growSettings"), true);
webserver.send(302, "text/plain", "please configure growSettings first");
} else {
String body = returnHTMLheader();
String body = returnHTMLheader("root");
body += "<h1>&#x1F331; ";
body += "<h2>&#x1F331; ";
body += GrowName;
body += "</h1>";
body += "</h2>";
// add gauge meter
body += FPSTR(HTMLgauge);
// and give javascript the values
// todo: auto refresh by api call
body += "<script>";
body += "gaugeTemperature.value(";
body += valTemperature;
body += ", 42, ' °C' ); ";
body += "gaugeHumidity.value(";
body += valHumidity;
body += " ); ";
body += "gaugeSoilmoisture.value(";
body += valSoilmoisture;
body += " ); ";
body += "</script>";
body += "Grow started: ";
body += returnStrDateFromEpoch(GrowStart);
body += "<br>\n";
body += "Day of Grow: ";
body += DayOfGrow;
body += "<br>\n";
body += "Soil Moisture: ";
body += valSoilmoisture;
body += " %<br>\n";
body += "Humidity: ";
body += valHumidity;
body += " %<br>\n";
body += "Temperature: ";
body += valTemperature;
body += " °C<br>\n";
if(UsePump == true) {
body += "Pump water level: ";
switch(getWaterlevel()) {
case 0:
body += "OK";
body += "<span style='color: green;'>OK</span>";
break;
case 1:
body += "Warning";
body += "<span style='color: yellow;'>Warning</span>";
break;
case 2:
body += "Critical";
body += "<span style='color: red;'>Critical</span>";
break;
}
}
@ -1651,7 +1966,8 @@ void WEBroot() {
body += "<input type='submit' value='Save'>\n";
body += "</form>";
body += FPSTR(HTMLfooter);
webserver.send(200, "text/html", body);

View file

@ -1,13 +1,13 @@
<!doctype html>
<html lang="en">
<html lang='en'>
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta charset='utf-8'>
<meta http-equiv='x-ua-compatible' content='ie=edge'>
<title>Material Design Gauge</title>
<meta name="description"
content="Simple Material Design gauge control implemented in pure CSS/HTML">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="material-gauge.css">
<meta name='description'
content='Simple Material Design gauge control implemented in pure CSS/HTML'>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel='stylesheet' type='text/css' href='material-gauge.css'>
<style>
body {
@ -29,64 +29,64 @@
</style>
</head>
<body>
<div class="center">
<div style="overflow: hidden;">
<div class="gauge gauge--liveupdate" id="gauge" style="float:left;">
<span >Humidity</span>
<div class="gauge__container">
<div class='center'>
<div style='overflow: hidden; display: flex; justify-content: center;'>
<div class='gauge gauge--liveupdate' id='gauge' style='float:left;'>
<span class='gaugeLabel'>Humidity</span>
<div class='gauge__container'>
<!-- <div class="gauge__marker"></div> -->
<div class="gauge__background"></div>
<div class="gauge__center"></div>
<div class="gauge__data"></div>
<div class="gauge__needle"></div>
<!-- <div class='gauge__marker'></div> -->
<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 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>
<div class="gauge gauge--liveupdate" id="gauge2" style="float:left;">
<span >Moisture</span>
<div class="gauge__container">
<!-- <div class="gauge__marker"></div> -->
<div class="gauge__background"></div>
<div class="gauge__center"></div>
<div class="gauge__data"></div>
<div class="gauge__needle"></div>
<div class='gauge gauge--liveupdate' id='gauge2' style='float:left;'>
<span class='gaugeLabel'>Moisture</span>
<div class='gauge__container'>
<!-- <div class='gauge__marker'></div> -->
<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 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>
<div class="gauge gauge--liveupdate" id="gauge3" style="float:left;">
<span >Temperature</span>
<div class="gauge__container">
<!-- <div class="gauge__marker"></div> -->
<div class="gauge__background"></div>
<div class="gauge__center"></div>
<div class="gauge__data"></div>
<div class="gauge__needle"></div>
<div class='gauge gauge--liveupdate' id='gauge3' style='float:left;'>
<span class='gaugeLabel'>Temperature</span>
<div class='gauge__container'>
<!-- <div class='gauge__marker'></div> -->
<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>
<span class="gauge__label--high"></span>
<div class='gauge__labels mdl-typography__headline'>
<span class='gauge__label--low'></span>
<span class='gauge__label--spacer'></span></span>
<span class='gauge__label--high'></span>
</div>
</div>
</div>
</div>
<script src="material-gauge.js"></script>
<script src='material-gauge.js'></script>
<script>
var gauge = new Gauge(document.getElementById("gauge"));
var gauge2 = new Gauge(document.getElementById("gauge2"));
var gauge3 = new Gauge(document.getElementById("gauge3"));
var gauge = new Gauge(document.getElementById('gauge'));
var gauge2 = new Gauge(document.getElementById('gauge2'));
var gauge3 = new Gauge(document.getElementById('gauge3'));
//gauge.value(75);
//gauge2.value(50);

View file

@ -3,18 +3,18 @@
*
* The standard markup for the component is:
*
* <div class="gauge">
* <div class="gauge__container">
* <div class="gauge__marker"></div>
* <div class="gauge__background"></div>
* <div class="gauge__center"></div>
* <div class="gauge__data"></div>
* <div class="gauge__needle"></div>
* <div class='gauge'>
* <div class='gauge__container'>
* <div class='gauge__marker'></div>
* <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">
* <span class="gauge__label--low">No</span>
* <span class="gauge__label--spacer"></span>
* <span class="gauge__label--high">Yes</span>
* <div class='gauge__labels'>
* <span class='gauge__label--low'>No</span>
* <span class='gauge__label--spacer'></span>
* <span class='gauge__label--high'>Yes</span>
* </div>
* </div>
*/
@ -93,6 +93,10 @@
transform-origin: left center;
}
.gaugeLabel {
font-weight: bold;
}
.gauge__labels {
display: table;
margin: 0 auto;

View file

@ -21,11 +21,11 @@ function Gauge(el) {
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");
data = element.querySelector('.gauge__data');
needle = element.querySelector('.gauge__needle');
valueLabel = element.querySelector('.gauge__label--spacer');
//valueLabel = element.getElementsByTagName("span"); //valueLabel = element.querySelector("span.gauge__label--spacer");
//valueLabel = element.getElementsByTagName('span'); //valueLabel = element.querySelector('span.gauge__label--spacer');
};
@ -33,13 +33,13 @@ function Gauge(el) {
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)";
data.style[prop] = 'rotate(' + turns + 'turn)';
needle.style[prop] = 'rotate(' + turns + 'turn)';
valueLabel.textContent = x + unit;
/*
for (var i = 0; i < valueLabel.children.length; i++) {
window.alert(valueLabel.children[i].className);
if (valueLabel.children[i].className == "gauge__label--spacer") {
if (valueLabel.children[i].className == 'gauge__label--spacer') {
window.alert(valueLabel.children[i]);
valueLabel.children[i].textContent = x + unit;
break;
@ -68,10 +68,10 @@ function Gauge(el) {
// ##### Initialization
var body = document.getElementsByTagName("body")[0];
["webkitTransform", "mozTransform", "msTransform", "oTransform", "transform"].
var body = document.getElementsByTagName('body')[0];
['webkitTransform', 'mozTransform', 'msTransform', 'oTransform', 'transform'].
forEach(function(p) {
if (typeof body.style[p] !== "undefined") { prop = p; }
if (typeof body.style[p] !== 'undefined') { prop = p; }
}
);

View file

@ -0,0 +1,152 @@
.gauge {
position: relative;
margin-right: 10px;
}
.gaugeWrapper {
overflow: hidden;
display: flex;
justify-content: center;
}
.gaugeLabel {
font-weight: bold;
}
.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;
}
.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; }
@media only screen and (min-width: 720px) {
.gauge { height: calc(120px + 3em); }
.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; }
}
.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);
}

View file

@ -0,0 +1,61 @@
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;
};

View file

@ -0,0 +1,185 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<title>CanGrow - Ruderalis Indica</title>
<link rel='stylesheet' type='text/css' href='gauge.css'>
<link rel='icon' href='data:;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsTAAALEwEAmpwYAAABcElEQVQ4y42TzU/bQBDFf7Nx1qGuAYVgQSuo2khBggPhyIH//9AiJAQ9tEeLqCKiUD6sxF52OMSEBCdW57aa9968fTsr3V5XWVLPO6sANNL7ZRAMNeU6Ea4T1UEI6pr55kcAwhpMrYOpk2/r/yEQmKWkIonf+TZVgex4Fw0bIEtIAALF3gbZ8U5VwKa3PJ18JT9IpiLvyflBwuhLG5veVUM0/0aoCONPa2hQjWZ8uEVeupJnXSBwO8YOH8iTeAKc2Q4Xt2C1VZL93F7MjbK/bxDnp5Zn7b+So+9pdQ+K/Q5qJlrRj5Ts6DM+rK7Ih7Mr3HaM7jYQVZqXQ6Tb6yqBYdTfomhHiFfUyMI3f+01/z7RHNzTGDyWGThP63SA2d8EEfIkrgQpzmOvH0AV+3M4zegNpUwagAYG8Yp4BS0nl4Kz5Mpf0JXJMby6w/66Aa+M+9uE53/Iexsggq4ESOYWC0jmsBfX8xdXhcJjL4cLc3kBl8uJGQ/CrpAAAAAASUVORK5CYII='>
<style>
body {
color: #cae0d0;
background-color: #1d211e;
font-family: helvetica;
}
.center {
width: 60%; min-width: 420px;
margin: auto;
}
h1, h2, h3, h4, h5 {
text-align: center;
}
a:link, a:visited {
color: #04AA6D;
}
a:hover {
color: #64AA6D;
}
a:active {
color: #04AA6D;
}
.infomsg , .warnmsg {
color: #fff;
border-radius: 3px;
padding: 4px;
width: fit-content; min-width: 200px; max-width: 420px;
margin: auto;
margin-bottom: 5px;
font-weight: bold;
text-align: center;
text-decoration: none;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.5);
}
.infomsg {
background: #04AA6D;
}
.warnmsg {
background: #aa4204;
}
.inputShort {
width: 42px;
}
.nav {
background: #333;
width: 60%; min-width: 420px;
margin: auto;
margin-bottom: 10px;
padding: 0;
position: relative;
border-radius: 3px;
}
.nav li {
display: inline-block;
list-style: none;
}
.nav li:first-of-type {
background: #026b45;
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
}
.nav li a , .nav span {
color: #ddd;
display: block;
font-family: 'Lucida Sans Unicode', 'Lucida Grande', sans-serif;
font-size:0.8em;
padding: 10px 20px;
text-decoration: none;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.5);
}
.nav li a:hover , .activeMenu , .menuTime{
background: #04AA6D;
color: #fff;
border-radius: 3px;
}
.nav li a:active {
color: #cae0d0;
}
.activeMenu {
background: #444;
}
.MenuTime {
background: #292929;
}
</style>
</head>
<body>
<ul class='nav'><li><a href='/'>&#x1F331; Ruderalis Indica</a></li>
<li><a href='/growSettings' >Grow settings</a></li>
<li><a href='/systemSettings' >System settings</a></li>
<li><a href='/wifiSettings' >WiFi settings</a></li>
<li><a href='/help' >Help</a></li>
<li><span class='MenuTime'>23:57:31</span></li>
<li><a href='https://git.la10cy.net/DeltaLima/CanGrow' target='_blank'>CanGrow v0.1</a></li>
</ul><div class='center'><h2>&#x1F331; Ruderalis Indica</h2>
<div class='gaugeWrapper'>
<div class='gauge gauge--liveupdate' id='gaugeTemperature' style='float:left;'>
<span class='gaugeLabel'>Temperature</span>
<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>
<span class='gauge__label--high'></span>
</div>
</div>
<div class='gauge gauge--liveupdate' id='gaugeHumidity' style='float:left;'>
<span class='gaugeLabel'>Humidity</span>
<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>
<div class='gauge gauge--liveupdate' id='gaugeSoilmoisture' style='float:left;'>
<span class='gaugeLabel'>Moisture</span>
<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>
</div>
<script src='gauge.js'></script>
<script>
var gaugeTemperature = new Gauge(document.getElementById('gaugeTemperature'));
var gaugeHumidity = new Gauge(document.getElementById('gaugeHumidity'));
var gaugeSoilmoisture = new Gauge(document.getElementById('gaugeSoilmoisture'));
</script>
Grow started: 2024-04-12<br>
Day of Grow: 20<br>
<script>gaugeTemperature.value(22.00, 42, ' °C' ); gaugeHumidity.value(59.00 ); gaugeSoilmoisture.value(98 ); </script>Pump water level: <span style='color: red;'>Critical</span><br>
Growlight brightnes: 100 %<br>
<form method='post' action='/switch'>
MOSFET<select id='output' name='output' required>
<option disabled value='' selected hidden>---</option>
<option value='1'>LED</option>
<option value='2'>FAN</option>
<option value='3'>PUMP</option>
</select><br>On/Off: <select id='state' name='state' required>
<option disabled value='' selected hidden>---</option>
<option value='1'>On</option>
<option value='0'>Off</option>
</select><br>
Intensity: <input type='range' id='OutputPWM' name='OutputPWM' min='1' max='255' value='255'/><br>
<input type='submit' value='Save'>
</form>
</div>
</body>
</html>