Passaggio tra variabili

Buongiorno,

nel listato che allego vorrei passare la variabile double temp; dentro la funzione void http_server_on_temp(), in particolare vorrei eguagliarla alla variabile javascript, così

var randomnumber = 'temp';

Come posso fare?

#include <Wire.h>
#include "ABlocks_LiquidCrystal_I2C.h"
#include "WiFi.h"
#include <WebServer.h>
#include "ABlocks_DHT.h"

double temp;
LiquidCrystal_I2C lcd_1(0x3F,16,2);
const char espwifi_ssid[]="TP-Link_A9E4";
const char espwifi_pass[]="Jz3mkRzy9sN5";
WebServer http_server;
DHT dht32(32,DHT11);

void espwifi_setup(){
	WiFi.mode(WIFI_STA);
	WiFi.begin(espwifi_ssid,espwifi_pass);
	while (WiFi.status() != WL_CONNECTED) delay(500);
}

void fnc_io_i2c_scanner(){
	byte error, address;
	int nDevices=0;
	for(address = 1; address < 127; address++){
		Wire.beginTransmission(address);
		error = Wire.endTransmission();
		if (error == 0){
			Serial.print("I2C device: ");
			Serial.print("0x");
			if(address<16)Serial.print("0");
			Serial.println(address,HEX);
			nDevices++;
		}
	}
	Serial.print("I2C devices found: ");
	Serial.println(nDevices);
}

void http_server_on_(){
	http_server.send(200,String("text/html"),String("<!DOCTYPE html><HTML><HEAD>")+String("<META ")+String("charset=\"ISO-8859-1\" name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"")+String(" >")+String("<STYLE>")+String("body {background-color: #ffffff;}")+String("</STYLE>")+String("<TITLE>")+String("ESP32 ARDUINO BLOCKS")+String("</TITLE>")+String("</HEAD><BODY>")+String("<HR>")+String("<center>BENVENUTO</center>")+String("<BR>")+String("<center> <form action=\"\\\\192.168.1.104/temp\">   <button type=\"submit\"; font-size:48px>  ON  </button>    </form> </center>")+String("<HR>")+String("</BODY></HTML>"));

}

void http_server_on_temp(){
	http_server.send(200,String("text/html"),String("<center>Temperatura: </center> ")+String("<div align=\"center\">")+temp+String("</div>")+String("<HR>")+String("<!DOCTYPE html><HTML><HEAD>")+String("<META ")+String("charset=\"ISO-8859-1\" name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"")+String(" >")+String("<STYLE>")+String("body {background-color: #ffffff;}")+String("</STYLE>")+String("<TITLE>")+String("ArduinoBlocks")+String("</TITLE>")+String("</HEAD><BODY>")+String("<!DOCTYPE html> <HTML lang=\"en\"> <HEAD>    <meta charset=\"UTF-8\">    <TITLE>Crunchify - jQuery Knob Example</TITLE>    <meta name=\"description\" content=\"Crunchify - jQuery Knob Example.\">    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"> <style type=\"text/css\">   .knob{color:#66CC66 !important;} </style> <script type=\"text/javascript\"    src=\"https://code.jquery.com/jquery-1.10.1.min.js\"></script> <script src=\"https://cdnjs.cloudflare.com/ajax/libs/jQuery-Knob/1.2.13/jquery.knob.min.js\"></script> <script> function knobfunction(value1){    $(\'.dial\')    .val(value1)    .trigger(\'change\'); }      $(document).ready(            function() {                setInterval(function() {            var randomnumber = 30;             knobfunction(randomnumber);                                 }, 3000);            }); </script> </HEAD> <BODY>    <br>        <br><br>    <div align=\"center\">    <h1>Temperatura</h1>    </div>    <br><br>    <div id=\"show\" align=\"center\"></div>    <div align=\"center\">        <input type=\"text\" class=\"dial\"> &nbsp;&nbsp;&nbsp;&nbsp;        <br><br><br>        <script type=\"text/javascript\">                         </script>        <script>    $(\".dial\").knob({                 \'change\' : function (v) { console.log(v); }    });    </script> </BODY> </HTML>")+String("</BODY></HTML>"));

}

void setup()
{
  	pinMode(32, INPUT);

	Serial.begin(115200);
	Serial.flush();
	while(Serial.available()>0)Serial.read();

	Wire.begin();

	dht32.begin();

	lcd_1.begin();
	lcd_1.noCursor();
	lcd_1.backlight();
	lcd_1.setCursor(0, 0);
	lcd_1.print(String("BENVENUTO MATTEO"));
	espwifi_setup();
	Serial.println(WiFi.localIP().toString());
	http_server.begin(80);
	delay(1000);
	fnc_io_i2c_scanner();

	http_server.on("/",HTTP_GET,http_server_on_);
	http_server.on("/temp",HTTP_GET,http_server_on_temp);
}


void loop()
{
	yield();

	http_server.handleClient();
  	temp = dht32.readTemperature();
  	Serial.println(temp);
  	lcd_1.setCursor(3, 0);
  	lcd_1.print(String("Temperatura:"));
  	lcd_1.setCursor(5, 1);
  	lcd_1.print(temp);

}

Vai a rivedere il regolamento del forum italiano [REGOLAMENTO] Come usare questa sezione del forum

In particolare il punto 7.

Il suggerimento è che non accederemo a Google per vedere il tuo codice, mostralo qui.

Buongiorno, jack74 :slight_smile:

Per cortesia, anziché mettere un link a un sito esterno che richiede anche l'approvazione per l'accesso, copia il programma nel messaggio usando il tasto CODE, così sarà facilmente e immediatamente visibile.

Grazie
Gianluca

1 Like

Dovresti mettere anche il contenuto della pagina web dove c'è il JavaScript a cui fai riferimento.

Ad ogni modo, devi fare una chiamata http passando come argomento la variabile JavaScript che vuoi confrontare.

Nella funzione http_server_on_temp() recuperi questo argomento e lo confronti con la variabile dello sketch che vuoi.
Fai riferimento agli esempi inclusi nella libreria WebServer.h per vedere come

Non capisco quello che vuoi dire @cotestatnt

il mio problema è che ho due variabili in due linguaggi differenti e voglio passare quella in C dentro allo script.

Mi manca proprio la sintassi su cosa fare: qual'è la sintassi per passare dentro ad uno script una variabile C? $temp? .temp? !temp? sparo alcune ipotesi

In sostanza vorrei visualizzare il valore di temp nel knob che mi sono costruito (vedi figura)

Knob? Cioè è una manopola di regolazione?...

Non è questione di sintassi! Non puoi scambiare direttamente delle variabili da un ambiente runtime (Javascript) ad un altro ambiente runtime (il microcontrollore che esegue il suo firmware). Hai bisogno di un sistema che "sta nel mezzo" con un suo protocollo di comunicazione a usare per scambiare informazioni.

Nel tuo caso stai usando un browser e quindi il protocollo usato può essere l'HTTP.

Se vuoi "recuperare" una variabile dal microcontrollore e visualizzarla nella tua pagina web, dovrai fare una chiamata HTTP al webserver che gira sul micro il quale risponderà in modo opportuno.

Ad esempio il seguente snippet HTML+ javascript, svolge due funzioni:

  • la prima è richiamare una volta al secondo la funzione Javascript getTemperature() per inviare una richiesta GET al webserver (che gira sul microcontrollore) cosi da ottenere indietro come risposta il valore della temperatura aggiornato e visualizzarlo sulla pagina.
  • la seconda invece associa una funzione al pulsante che quando premuto invierà una seconda richiesta GET al microcontrollore dove però questa volta saranno passati anche due argomenti numerici che andranno poi elaborati dal micro.
<html>
	<head>
		<title>A simple webpage</title>
	</head>
	<body>
		<div>
			<p><span id="temperature">25.5<span> &deg;C</p>
		</div>
		<div>
			<input id="arg1" type="number" value="11" />
			<input id="arg2" type="number" value="22" />
			<button id="set-data">INVIA DATI</button>
		</div>
		<script>
			function getTemperature() {
				// Esegue una chiamata GET, la risposta aggiorna il testo dell'elemento HTML con id="temperature"
				var url = new URL("http://" + `${window.location.hostname}` + "/getTemperature");
				fetch(url)
				.then(response => response.text())
				.then(data => {
					console.log(data);
					document.getElementById("temperature").innerHTML = data;
				});
			}
			
			function setData() {
				var url = new URL("http://" + `${window.location.hostname}` + "/setData");
				var params = new URLSearchParams({
					arg1: document.getElementById("arg1").value,
					arg2: document.getElementById("arg2").value
				});
				// Esegue una chiamata GET passando i due parametri
				fetch(url + "?" + params)
				.then(response => response.text())
				.then(data => {
					console.log(data);
				});
			}
			// Chiama getTemperature() ogni secondo
			setInterval(getTemperature, 1000);
			// Associa il listener al pulsante con id="set-data" per l'evento "click" 
			document.getElementById("set-data").addEventListener("click", setData);
		</script>
	</body>
</html>

Lato microcontrollore dovrai gestire opportunamente queste due richieste HTTP, ad esempio:
(le funzioni per brevità le ho definite direttamente nel metodo come funzioni "anonime", ma puoi continuare anche come hai già fatto, non cambia nulla)

int arg1, arg2;
float myTemp = 25.6;
......
http_server.on("/getTemperature", HTTP_GET, []() {
   http_server.send(200, "text/plain", String(myTemp));
});

http_server.on("/setData", HTTP_GET, []() {
  if (http_server.hasArg("arg1")) {
    arg1 = http_server.arg("arg1").toInt();
  }
  if (http_server.hasArg("arg2")) {
    arg2 = http_server.arg("arg2").toInt();
  }
  http_server.send(200, "text/plain", "OK");
});

@cotestatnt

prima di provare il tuo prezioso esempio vorrei farti vedere dove nasce la mia domanda.

Lo script dellla visualizzazione delle temperautra del dial/knobè il seguente:

<script>
function knobfunction(value1){
   $('.dial')
   .val(value1)
   .trigger('change');
}
   $(document).ready(
           function() {
               setInterval(function() {
           var randomnumber = **???**;
            knobfunction(randomnumber);
                                }, 3000);
           });
</script>

A quanto ho visto dove ho messo i punti interrogativi dovrei mettere la mia variabile 'temp'

Ora mi sembra che l'interfaccia per tirarsi dentro in HTML 'temp' sia la funzione

<script>
			function getTemperature() {
				// Esegue una chiamata GET, la risposta aggiorna il testo dell'elemento HTML con id="temperature"
				var url = new URL("http://" + `${window.location.hostname}` + "/getTemperature");
				fetch(url)
				.then(response => response.text())
				.then(data => {
					console.log(data);
					document.getElementById("temperature").innerHTML = data;
				});
</script>

Giusto il mio ragionamento?

Devo incrociare l'Id "temperature" con "double temp"?

Nella tua pagina web stai usando la libreria JQuery e quindi la sintassi è leggermente diversa, ma il succo non cambia.
Non devi inserire righe a caso sperando che vadano bene, ma analizzare quanto già fa la tua pagina, capirlo in ogni suo passaggio e poi modificare di conseguenza, per tutto il resto c'è Google.

Nel dettaglio, questo snippet fa due cose fondamentalmente:

Per fare quello che vuoi tu a questo punto, ti basta richiamare la funzione knobfunction() quando ottieni in risposta dal micro il nuovo valore:

function getTemperature() {
  // Esegue una chiamata GET, la risposta aggiorna il testo dell'elemento HTML con id="temperature"
  var url = new URL("http://" + `${window.location.hostname}` + "/getTemperature");
  fetch(url)   // Invia una richiesta al webserver
  .then(response => response.text())  // Quando si avrà la risposta, questa dovrà essere interpretata come testo semplice 
  .then(data => {  // Qui arrivano i dati, cosa dobbiamo farne?
     // console.log(data);  // Stampa sulla console il valore ricevuto
     
     // Chiama la funzione knobfunction()
     knobfunction(parseFloat(data));   
   });
}
// Ora sarà questa funzione ad essere richiamata ogni 3 secondi e non più la funzione anonima di prima
$(document).ready( function(){   // Evento 'ready' di document (ovvero la pagina è pronta)
   setInterval(getTemperature, 3000);  // Ogni 3 secondi chiama getTemperature()
});

Per rendere il tutto più "affidabile" ci sarebbe da aggiungere la gestione degli errori:
ad esempio cosa succede se il webserver non risponde perché offline?
oppure se la risposta non è di tipo float come ci si aspetta?

qua devo mettere l'indirizzo del WebServer? tipo

'''var url = new URL("http://" + ${192.168.1.111} + "/getTemperature");'''

Inoltre al posto dei punti interrogativi cosa metto?

No, non è necessario.

La variabile window.location.hostname è l'indirizzo del webserver.
Se ci fai attenzione la stringa viene costruita usando la sequenza di caratteri `${nome variabile}` (da notare che ` è diverso da ').
Questo modo di concatenare le stringhe è detto template literal

In realtà non è necessario passare l'indirizzo nella richiesta in questo caso. Ho messo l'istruzione perché ho fatto copia/incolla da un mio progetto dove era necessario per altre ragioni.
Puoi scrivere più semplicemente in questo modo e funzionerà senza problemi


function getTemperature() {
  fetch( "/getTemperature")   // Invia una richiesta al webserver
  .then(response => response.text())  //
  .then(data => {  
     knobfunction(parseFloat(data));   
  });
}

quindi questo codice lo tolgo?

la knobfunction la nomino nella getTemperature

Si.

oggi provo, e ti dico
intanto grazie :smiley:

prima di provare avrei / mi è sorto un dubbio...

la

function getTemperature

dove va a prendersi il valore di della

double temp ??

dentro a 'data' che trovo? e a parseFloat(data)?

dove va a prendersi il valore di della double temp ??

Dalla risposta HTTP del microcontrollore

dentro a 'data' che trovo?
Il testo inviato dal microcontrollore con quest'istruzione:

    http_server.send(200, "text/plain", String(myTemp));

e a parseFloat(data)?

data è una stringa di testo che rappresenta una valore float, quindi per assegnare il nuovo valore all'elemento knob (che di base è una progress bar) devi convertire da testo a float, cosa che fa per l'appunto l'istruzione parseFloat()

Comunque, mi ripeto.
Possiamo andare avanti a mozzichi e bocconi all'infinito con il JavaScript, ma se hai intenzione di proseguire in questo tipo di sviluppo (interfacce web) prima o poi dovrai deciderti ad affrontare di petto la materia e studiarla con metodo.
Ci sono migliaia di libri sull'argomento e tantissimi anche in lingua Italiana.

Ben detto... ma devo precisare un paio di cose:
in passato ho fatto dei progetti con EmonCms e Arduino e ho visto dei Dial molto più performanti di questa cosa ;
ho lavorato anche con Labview per visualizzare questi tipi di dati e sensori vari.
Ho una minima infarinatura di HTML e PHP, e quasi nulla di JavaScript (come hai bene visto).

Dal punto di vista didattico mi sembra molto accattivante e introduttivo pensare ad una visualizzazione in questi termini (vedi la funzione knobfuntion che voglio utilizzare).

Inoltre non sto utilizzando l'IDE , ma ArduinoBlocks, che a parer mio è un figata, e che devo continuamente adattare alle esigenze del caso.

Detto questo non sono tanto distante dal risolvere questa mia 'piva mentale', anche se devo continuamente passare dal testuale ai blocchi.

Questa istruzione qua:

http_server.send(200, "text/plain", String(myTemp));

per esempio non riesco ad incastrarla nel mio 'concept' :thinking:

La Knobfunction messa nella getTemperatura smette di funzionare anche con numeri forzati a mano.

Provo a ripubblicare il testuale che ho fatto:

<!DOCTYPE html>
<HTML lang="en">
<HEAD>
   <meta charset="UTF-8">
   <TITLE>Sensor Blocks</TITLE>
   <meta name="description" content="Crunchify - jQuery Knob Example.">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
<style type="text/css">
.knob{color:#66CC66 !important;}
</style>
<script type="text/javascript"
   src="https://code.jquery.com/jquery-1.10.1.min.js">
</script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jQuery-Knob/1.2.13/jquery.knob.min.js"></script>

<script> function knobfunction(value1){ 
$('.dial')    
.val(value1)    
.trigger('change'); }      
</script> 

<script>  function getTemperature() { 					var url = new URL("/temp"); 
fetch(url)
.then(response => response.text())
.then(data => {  
console.log(data);  
knobfunction(parseFloat(data));  
              }); 
            }  
$(document).ready( function(){  
setInterval(getTemperature, 3000); 
});    
</script>

</HEAD>
<BODY>
   <br>
       <br><br>
   <div align="center">
   <h1>Temperatura</h1>
   </div>
   <br><br>
   <div id="show" align="center"></div>
   <div align="center">
       <input type="text" class="dial"> &nbsp;&nbsp;&nbsp;&nbsp;
       <br><br><br>
      
<script>
   $(".dial").knob({
                'change' : function (v) { console.log(v); }
   });
   </script>
</BODY>
</HTML>

Per completezza pubblico il blocco utilizzato da Arduino Blocks per la richiesta di Get, e nel quale viene processato il codice sopra.

Sento che mi sto perdendo in un bicchiere.... :smiley: :roll_eyes:

A parer mio invece è un giocattolino buono dal punto di vista didattico (non a caso nei corsi di coding per ragazzi si usa molto spesso), ma troppo limitante per sviluppare davvero, ma è solo la mia personale opinione.
Quel che conta quando si sviluppa software, non è il linguaggio, ma l'algoritmo che si implementa con il linguaggio scelto.

Si. Io non ti ho suggerito che puoi fare cosi

var url = new URL("/temp");`  

perché il costruttore URL vuole una stringa tipo http://etctect
Ho scritto invece che puoi fare cosi, cosa diversa.

 fetch("/temp")
 etc etc

Se abiliti gli strumenti di sviluppo del browser (tasto F12) vedi tutti gli eventuali errori nella console e fai presto a debuggare.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.