Abbiamo visto come creare un sito completo in sicurezza, formato da front-end e back-end a microservizi.
In questo articolo descrivo brevemente la parte web e aggiungo il link ai widget animati di temperatura e umidità utilizzati nel sito.
Puoi trovare il codice descritto per l’esp8266 e l’esp32 negli articoli precedenti sul repository GitHub.
Sito front-end
Riutilizziamo la pagina di accesso, ma cambiamo il sito per mostrare la temperatura e l’umidità di una stanza.
In questa funzione recupererò la temperatura e l’umidità dal DHT12 e le aggiungerò in una struttura Json gestita dal front-end.
var requestTempHum = function(){
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// Typical action to be performed when the document is ready:
var res = JSON.parse(xhttp.responseText);
humidityFunction(res.humidity);
termometerTemperature(res.temp);
}
};
xhttp.onerror = function () {
alert("Status code is " + this.status + " click F12 and check what is the problem on console");
};
xhttp.open("GET", "/temperatureHumidity", true);
xhttp.send();
}
L’end point /temperatureHumidity
è in GET
che restituisce un tipo MIME JSON e lato front-end puoi ottenere questi dati con una semplice XMLHttpRequest
, con una JSON.parse (xhttp.responseText) elabori la stringa json e la trasformi in un oggetto così da usarlo con più semplicità.
Il front-end have a simple structure:
favicon.ico
floatButton.css
index.html
iot-widget.min.js
login.html
logo256.jpg
sldierElement.css
sliderManager.js
Ci sono alcuni css nella pagina di login dell’esempio precedente e uno nuovo index.html
.
Il risultato è in questi screens:
Questa è solo una semplice demo, se vuoi puoi aggiungere un semplice timer per gestire una request in polling
function polling() {
setTimeout(function () {
debouncedRequestTempHum();
polling();
}, 2500);
}
polling();
ora ogni 2,5 secondi, i dati vengono aggiornati automaticamente.
Il polling non è la soluzione migliore, ma da anni è una soluzione ampiamente utilizzata.
JavaScript: widget di umidità e temperatura
Ho creato anche due semplici widget animati, che potete trovare su questo repository , oppure potete scaricare direttamente la semplice libreria js.
I widgets sono scritti in React e funzionano sia in vanilla JS e anche in React.
Ecco la dichiarazione del widget di umidità
<HumidityWidget humidity={this.state.humidity} diameter={150} animationRates={80} />
e temperatura
<TermometerWidget temperature={this.state.temperature} />
L’utilizzo è molto semplice, ad esempio il codice in vanilla JS è
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Temperature humidity demo</title>
<script type="text/javascript" src="iot-widget.min.js"></script>
</head>
<body style="">
<div id="container2"></div>
<br/><br/><br/>
<div id="container"></div>
<script type="application/javascript">
var container = document.getElementById('container');
var hw = new Widget.Humidity(container, 40, 200, 50);
hw.draw();
var container2 = document.getElementById('container2');
var tw = new Widget.Termometer(container2, 15, 250);
tw.draw();
</script>
<button onclick="hw.setHumidity(80);">Set humidity to 80</button>
<button onclick="hw.setHumidity(40);">Set humidity to 40</button>
<button onclick="tw.setTemperature(30);">Set temperature to 30</button>
<button onclick="tw.setTemperature(-5);">Set temperature to -5</button>
</body>
</html>
Puoi vedere l’effetto nel video sopra.
Qui la semplice pagina HTML del sito
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="./sldierElement.css">
<link rel="stylesheet" type="text/css" href="./floatButton.css">
<script src="iot-widget.min.js"></script>
<script src="sliderManager.js"></script>
<meta charset="UTF-8">
<title>Temperature humidity www.mischianti.org</title>
<style>
html {
height: 100%;
}
body {
height: 100%;
background: #76b852; /* fallback for old browsers */
background: -webkit-linear-gradient(right, #76b852, #8DC26F);
background: -moz-linear-gradient(right, #76b852, #8DC26F);
background: -o-linear-gradient(right, #76b852, #8DC26F);
background: linear-gradient(to left, #76b852, #8DC26F);
}
.titleContainer {
font-size: 6vw;;
text-align: center;
width: 100%;
height: 16%;
/*padding: 10px;*/
}
.sliderContainer {
height: 84%;
position: relative;
}
.humidity-container,
.termometer-container{
width: 768px;
height: 100%;
}
.humidity-container{
height: 70%;
}
</style>
</head>
<body>
<div class="titleContainer">Temperature humidity</div>
<div class="sliderContainer">
<div class="slider-wrap">
<div class="slider" id="slider">
<div class="holder">
<div class="slide-wrapper">
<div class="humidity-container" id="humidity-container"></div>
</div>
<div class="slide-wrapper">
<div class="termometer-container" id="termomter-container" ></div>
</div>
</div>
</div>
</div>
</div>
<script>
var sliderElement = document.getElementById('slider');
var sliderImageElements = document.querySelectorAll(".slide-wrapper");
var holderElement = document.querySelector(".holder");
var animateElements = document.querySelectorAll('.animate');
sliderInitialization( sliderElement,
sliderImageElements,
holderElement,
animateElements,
2);
var container = document.getElementById('humidity-container');
var hw = new Widget.Humidity(container, 0);
hw.draw();
var container2 = document.getElementById('termomter-container');
var tw = new Widget.Termometer(container2, 0);
tw.draw();
</script>
<script>
function getCookie(name) {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) return parts.pop().split(';').shift();
}
var token = getCookie('ESPSESSIONID');
function debounce(fn, threshold) {
threshold = threshold || 300;
var timer;
return function() {
if (!timer) {
fn.apply(this, arguments);
}
clearTimeout(timer);
timer = setTimeout(function() {
timer = null;
}, threshold);
};
};
var requestTempHum = function(){
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// Typical action to be performed when the document is ready:
var res = JSON.parse(xhttp.responseText);
hw.setHumidity(res.humidity);
tw.setTemperature(res.temp);
}
};
xhttp.onerror = function () {
alert("Status code is " + this.status + " click F12 and check what is the problem on console");
};
xhttp.open("GET", "/temperatureHumidity", true);
xhttp.send();
}
var debouncedRequestTempHum = debounce(requestTempHum, 400);
var refresh = function(){
debouncedRequestTempHum();
}
debouncedRequestTempHum();
function polling() {
setTimeout(function () {
debouncedRequestTempHum();
polling();
}, 2500);
}
polling();
</script>
<div style="position: absolute">
<a href="#" onclick="refresh();" class="floatRefresh">
<div style="font-size: xx-large">R</div>
</a>
</div>
<div style="position: absolute">
<a href="/logout" class="floatLogout">
<div style="font-size: xx-large">L</div>
</a>
</div>
</body>
</html>
Tutta la gestione del login è nel back-end che reindirizza alla pagina login.html, ogni volta che non c’è il cookie di autenticazione.
Grazie
- Web Server su esp8266 e esp32: servire pagine e gestire LEDs
- Web Server su esp8266 e esp32: servire pagine compresse come byte array e SPIFFS
- Web Server su esp8266 e esp32: web server generico multiuso
- Web Server su esp8266 e esp32: gestione sicurezza ed autenticazione
- Web Server su esp8266 e esp32: aggiunta di un back-end REST protetto
- Web Server su esp8266 e esp32: Interfaccia Web sicura per temperatura ed umidità di un DHT
Codice ed esempio su repository GitHub