Progetto 01 - IoT e IoE con Packet Tracer - Lezione 1 MCU sensori attuatori | Prof. Giagnotti
🧪 PROGETTI · IoT e IoE con Packet Tracer
A cura di Prof. Giagnotti · Sistemi e Reti · Laboratorio IoE

Progetto 01 - IoT e IoE con Packet Tracer - Lezione 1 MCU sensori attuatori

Realizziamo un sistema IoE completo con Cisco Packet Tracer, Real HTTP, PHP, MySQL e dashboard web: dal potenziometro e MCU simulati al database reale e ritorno con il controllo remoto del LED.

✓Acquisire un dato reale: leggere il valore del potenziometro dall'MCU simulato e visualizzarlo sul display a 7 segmenti.
✓Trasmettere in HTTP Real: creare un oggetto JSON con valore e stato LED e inviarlo con RealHTTPClient POST a PHP.
✓Memorizzare e gestire: ricevere il JSON in PHP con php://input, decodificarlo e registrarlo in MySQL tabella sensor_data.
✓Visualizzare e interagire: sviluppare dashboard PHP + Bootstrap + Chart.js con tabella, grafico storico e controllo LED.
✓Integrare sistemi eterogenei: comprendere il flusso completo simulazione → rete → API → persistenza → visualizzazione e ritorno.
✓Analizzare e estendere: applicare troubleshooting multilivello e progettare estensioni con altri sensori e attuatori.

1. L'architettura del progetto IoE completo

Prima di entrare nel codice è utile osservare il progetto come un insieme di componenti che collaborano tra loro. Il potenziometro rappresenta la sorgente del dato, mentre il LED rappresenta un attuatore che può essere comandato da remoto. In questo progetto utilizziamo Cisco Packet Tracer per realizzare un sistema IoE capace di comunicare con componenti software realmente eseguiti sul computer.

Il dispositivo simulato acquisisce il valore di un potenziometro, lo visualizza sul display e lo invia attraverso una richiesta HTTP a un server reale. Il server PHP riceve i dati, li registra in un database MySQL e li rende disponibili a una dashboard web. Dalla stessa dashboard è inoltre possibile inviare un comando all'MCU simulato per accendere o spegnere un LED.

POTENZIOMETRO
dato 0-1023
→
MCU
Packet Tracer
→
HTTP POST
JSON
→
PHP
API REST
→
MYSQL
sensor_data
→
DASHBOARD
Chart.js
PACKET TRACER MCU + Potenziometro Display + LED sensore Lezione 1: MCU base HTTP JSON / GET / POST PHP API iot_data.php control_led.php REST endpoint MYSQL IoT_database sensor_data DASHBOARD Tabella + Grafico Chart.js Controllo LED remoto simulazione → comunicazione → elaborazione → persistenza → visualizzazione
📌 Definizione - Idea da ricordare

In questo progetto Packet Tracer non rappresenta più l'intero sistema. La simulazione diventa una parte di un'architettura più ampia: l'MCU comunica realmente con software eseguito sul computer attraverso il protocollo HTTP. L'MCU è client quando invia, server quando riceve.

01 · PACKET TRACER

Simulazione del dispositivo IoT

MCU, potenziometro A0, display pin 2, LED pin 1. Base della Lezione 1 sensori e attuatori.

02 · HTTP REAL

Comunicazione tra client e server

RealHTTPClient per POST JSON e RealHTTPServer sulla porta 8765 per ricevere comandi.

03 · PHP + MYSQL

Ricezione e memorizzazione

iot_data.php salva valore e led_status, control_led.php inoltra GET all'MCU.

04 · DASHBOARD

Visualizzazione e controllo

Bootstrap, tabella ultimi 10 valori, grafico Chart.js, pulsante accendi/spegni.

05 · LEZIONE 1 FOCUS

MCU sensori attuatori

Il potenziometro è sensore analogico, LED attuatore digitale. gpio e analogRead in Python.

06 · INTEGRAZIONE

Sistema completo

Simulazione + rete + API + DB + web in un unico progetto didattico verticale.

💬 Tip del docente - Architettura

Spiega alla classe partendo dal flusso fisico: il dato nasce analogico, diventa digitale con ADC a 10 bit (0-1023), poi JSON, poi HTTP. Disegna la freccia alla lavagna: SENSORE → MCU → RETE → SERVER → DB. Quando vedono il flusso, il codice diventa più chiaro.

2. Creazione del database MySQL con XAMPP

La prima componente reale del progetto è il database. Utilizziamo XAMPP per avviare Apache e MySQL e phpMyAdmin per creare il database e la tabella che conterrà i dati provenienti dal dispositivo IoT.

Avviare Apache dal pannello di controllo XAMPP.
Avviare MySQL.
Cliccare su Admin in corrispondenza di MySQL.
Aprire il tab SQL di phpMyAdmin.

Creiamo il database IoT_database e la tabella sensor_data.

SQL · CREAZIONE DATABASE E TABELLA
CREATE DATABASE IoT_database; USE IoT_database; CREATE TABLE sensor_data ( id INT AUTO_INCREMENT PRIMARY KEY, valore INT(5), led_status VARCHAR(10), timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP );

La tabella contiene tre informazioni fondamentali oltre alla chiave primaria:

CAMPO VALORE

valore INT(5)

Contiene il valore letto dal potenziometro. Nell'esempio 0-1023 da ADC 10 bit. 2^10 = 1024 livelli.

CAMPO LED_STATUS

led_status VARCHAR(10)

Memorizza lo stato corrente del LED, acceso oppure spento. Aggiornato dalla route control_led.

CAMPO TIMESTAMP

timestamp automatico

Registra data e ora dell'inserimento. Utile per asse X del grafico Chart.js.

🎯 Esempio in classe - ADC

Perché 0-1023? Il potenziometro viene letto tramite ADC a 10 bit. Con 10 bit hai 2¹⁰ = 1024 livelli numerici, rappresentati dall'intervallo 0–1023. Se ruoti il potenziometro a metà, leggerai circa 512. Questo è un ottimo collegamento con Sistemi e Reti e TPSIT sul concetto di conversione analogico-digitale.

⚠️ Errore comune - Nome database

In phpMyAdmin MySQL su Windows è case-insensitive, ma nello script PHP usiamo iot_database minuscolo. Se crei IoT_database e in PHP scrivi iot_database, funziona su Windows ma su Linux no. Mantieni ovunque lo stesso nome e ricorda: XAMPP vuole password root vuota, altrimenti la connessione fallisce.

3. Le API REST in PHP - iot_data e control_led

Il database da solo non comunica direttamente con Packet Tracer. Abbiamo bisogno di un componente intermedio che riceva le richieste HTTP, interpreti i dati e interagisca con MySQL. Questo ruolo viene svolto da due script PHP:

API 01 · POST

iot_data.php

Riceve dal dispositivo il valore del potenziometro e stato LED via POST JSON e memorizza nel DB.

API 02 · GET

control_led.php

Riceve dalla dashboard comando accendi/spegni e inoltra GET http://127.0.0.1:8765/control_led?comando=1

ENDPOINT

Che cos'è un endpoint?

URL attraverso cui app accede a funzionalità server. MCU usa endpoint http://127.0.0.1/test/IoT/iot_data.php

3.1 API per la ricezione dei dati — iot_data.php

Creiamo il file iot_data.php all'interno della directory utilizzata da XAMPP, ad esempio: C:\xampp\htdocs\test\IoT

PHP · IOT_DATA.PHP - RICEZIONE JSON
<?php $servername = "localhost"; $username = "root"; $password = ""; $dbname = "iot_database"; // Connessione al database $conn = new mysqli($servername,$username,$password,$dbname); if ($conn->connect_error) { die("Connessione fallita: " . $conn->connect_error); } // Ricezione dal MCU in JSON if ($_SERVER["REQUEST_METHOD"] == "POST") { $json = file_get_contents("php://input"); $data = json_decode($json, true); if (isset($data["valore"]) && isset($data["led_status"])) { $statoPot = $data["valore"]; $led_status = $data["led_status"]; $sql = "INSERT INTO sensor_data (valore, led_status) VALUES ('$statoPot', '$led_status')"; if ($conn->query($sql) === TRUE) { echo "Dati salvati con successo"; } else { echo "Errore: " . $sql . "
" . $conn->error; } } else { echo "Errore: valore o stato del LED non ricevuti"; } } $conn->close(); ?>
📌 Definizione - php://input

La funzione file_get_contents() normalmente legge una risorsa. Lo stream php://input permette di accedere al corpo della richiesta HTTP quando il contenuto è JSON. Il risultato viene trasformato in array PHP con json_decode().

PYTHON · RICHIESTA POST DAL MCU
request = client.post( "http://127.0.0.1/test/IoT/iot_data.php", json_data, "application/json" )
💬 Tip del docente - Percorso del dato

Fai scrivere agli studenti alla lavagna: valore sensore → oggetto Python → json.dumps() → HTTP POST → PHP php://input → array PHP → SQL → MySQL. Ripetilo a voce: questo è il cuore dell'IoE. Se ricordano il percorso, capiscono dove mettere i debug.

3.2 API per il controllo del LED — control_led.php

La comunicazione può avvenire anche nella direzione opposta. Quando l'utente preme "Accendi" oppure "Spegni", la dashboard richiama l'API control_led.php. L'API legge il parametro comando e invia una richiesta HTTP GET all'MCU.

PHP · CONTROL_LED.PHP - COMANDO VERSO MCU
<?php $servername = "localhost"; $username = "root"; $password = ""; $dbname = "iot_database"; $conn = new mysqli($servername,$username,$password,$dbname); if ($conn->connect_error) { die("Connessione fallita: " . $conn->connect_error); } if ($_SERVER["REQUEST_METHOD"] == "GET") { if (isset($_GET['comando'])) { $comando = $_GET['comando']; $url = "http://127.0.0.1:8765/control_led?comando=$comando"; file_get_contents($url); header("Location: dashboard.php"); } } $conn->close(); ?>
DASHBOARD
→
control_led.php
→
HTTP GET
→
MCU :8765
→
LED ON/OFF
🔁 Esempio - Ruolo duale dell'MCU

Quando invia: MCU è CLIENT → POST a iot_data.php
Quando riceve: MCU è SERVER → espone route /control_led su RealHTTPServer porta 8765. Questo è fondamentale per la verifica: chiedi "Quando l'MCU è client e quando server?" e fai disegnare le due frecce opposte.

4. Realizzazione IoE in Packet Tracer - Real HTTP Client e Server

La rete e il collegamento dei dispositivi sono già stati illustrati nel progetto introduttivo IoT e IoE con Cisco Packet Tracer. Qui ci concentriamo sull'aspetto nuovo: la possibilità di utilizzare le funzionalità Real HTTP offerte da Packet Tracer. Apriamo la scheda Programming dell'MCU e osserviamo i template dedicati.

TEMPLATE 1

Real HTTP Client - Python

Permette al dispositivo di inviare richieste HTTP verso un server reale XAMPP. Usato per POST JSON.

TEMPLATE 2

Real HTTP Server - Python

Permette al dispositivo di ricevere richieste HTTP e rispondere tramite propria route. Per controllo LED.

LEZIONE 1 + HTTP REAL

Novità del progetto

Partiamo dalla base MCU + sensori + attuatori della Lezione 1 e aggiungiamo livello applicativo HTTP reale.

4.1 Creazione del progetto Python e import

PYTHON · IMPORT MODULI MCU
from realhttp import * from gpio import * from time import * import json

4.2 Configurazione dell'MCU - Setup pin e server

PYTHON · SETUP MCU, LED, DISPLAY, HTTP
# ---------------- SETUP ---------------- # Configurazione dei pin pinMode(1, OUT) # LED pinMode(2, OUT) # Display # Inizializzazione del client HTTP client = RealHTTPClient() # Avvio del server HTTP server = RealHTTPServer() print("Server started: %s" % (server.start(8765))) print("Server listening: %s" % (server.isListening())) # Stato iniziale del LED stato_led = "spento"

L'MCU ascolta sulla porta 8765. Questo permette al server PHP di raggiungere l'MCU attraverso l'endpoint dedicato al controllo del LED. Il display sul pin 2 mostra il valore del potenziometro letto da A0, il LED sul pin 1 è l'attuatore comandabile.

4.3 La route per il controllo del LED - Server HTTP su MCU

Definiamo ora la funzione Python che riceve la richiesta HTTP. Il parametro comando determina se il LED deve essere acceso oppure spento.

PYTHON · FUNZIONE CONTROL_LED E ROUTE
#-------------- CONTROLLO LED -------------# def control_led(context, request, reply): global stato_led print("Ricevuto comando per LED:", request.url()) # Lettura dell'URL url = request.url() comando = None # Estrazione della query string if "?" in url: query_string = url.split("?")[1] params = dict( param.split("=") for param in query_string.split("&") if "=" in param ) comando = params.get("comando") # Controllo del comando if comando == "1": digitalWrite(1, HIGH) stato_led = "acceso" reply.setContent("LED acceso!") elif comando == "0": digitalWrite(1, LOW) stato_led = "spento" reply.setContent("LED spento!") else: reply.setContent( "Comando non valido! Usa " "'comando=1' per accendere " "o 'comando=0' per spegnere." ) reply.setStatus(200) reply.end() #------------ ROUTE CONTROLLO LED ----------# server.route( "/control_led", ["GET"], control_led )

La route viene registrata con server.route("/control_led", ["GET"], control_led). Di conseguenza:

HTTP · ESEMPI COMANDO LED
http://127.0.0.1:8765/control_led?comando=1 → LED acceso http://127.0.0.1:8765/control_led?comando=0 → LED spento
💬 Tip del docente - Query string

La parte più ostica per gli studenti è lo split della query string. Mostra con print intermedi: url → split("?")[1] → split("&") → dict. Fai aggiungere print(params) per vedere cosa contiene. Così capiscono che comando=1 diventa {"comando":"1"}. Non dare per scontato che sappiano parsare URL.

4.4 Il ciclo principale - Lettura sensore e invio

Nel ciclo principale leggiamo il potenziometro, aggiorniamo il display, prepariamo l'oggetto JSON e inviamo i dati al server reale. Dopo ogni invio attendiamo due secondi.

PYTHON · CICLO PRINCIPALE MCU SENZA THREADING
#----- Ciclo principale senza threading -----# while True: # Legge il valore del potenziometro valPot = analogRead(A0) # Scrive il valore sul display customWrite(2, valPot) # Creazione dell'oggetto JSON data = { "valore": valPot, "led_status": stato_led } json_data = json.dumps(data) # Invio HTTP POST try: request = client.post( "http://127.0.0.1/test/IoT/iot_data.php", json_data, "application/json" ) print("Dati inviati:", json_data) except Exception as e: print("Errore nell'invio dei dati:", e) # Attesa prima del prossimo invio sleep(2)
📌 Flusso del ciclo - Da ricordare

Ogni 2 secondi: lettura sensore analogRead(A0) → scrittura display customWrite → creazione JSON → client.post() → sleep(2). Se dalla dashboard arriva comando LED, la variabile globale stato_led viene aggiornata dalla funzione control_led.

5. Sviluppo della dashboard web completa

La dashboard costituisce l'interfaccia attraverso cui osserviamo i dati acquisiti e interagiamo con il dispositivo simulato. Viene realizzata utilizzando PHP per connessione DB, Bootstrap per layout e Chart.js per rappresentazione grafica.

01 · PHP

Connessione e logica

mysqli, query ultimi 10 valori ORDER BY id DESC LIMIT 10, stato LED più recente.

02 · BOOTSTRAP

Layout responsive

Card per controllo LED, tabella sensor_data, canvas per chart. Interfaccia chiara.

03 · CHART.JS

Grafico storico

Line chart con labels timestamp e values valore potenziometro. Visualizza andamento tempo reale.

5.1 Connessione al database e recupero dati

PHP · CONNESSIONE MYSQL DASHBOARD
<?php $servername = "localhost"; $username = "root"; $password = ""; $dbname = "iot_database"; $conn = new mysqli($servername,$username,$password,$dbname); if ($conn->connect_error) { die("Connessione fallita: " . $conn->connect_error); }
PHP · RECUPERO ULTIMI DATI E STATO LED
$sql = " SELECT * FROM sensor_data ORDER BY id DESC LIMIT 10 "; $result = $conn->query($sql); $data = []; if ($result->num_rows > 0) { while ($row = $result->fetch_assoc()) { $data[] = $row; } } // Ottieni lo stato più recente del LED $sql_led_status = " SELECT led_status FROM sensor_data ORDER BY id DESC LIMIT 1 "; $result_led_status = $conn->query($sql_led_status); $led_status = ($result_led_status->num_rows > 0) ? $result_led_status->fetch_assoc()['led_status'] : 'spento'; $conn->close();

5.2 Refresh automatico e controllo LED

La dashboard viene aggiornata automaticamente ogni due secondi, in modo da mostrare i dati più recenti ricevuti dal dispositivo.

JAVASCRIPT · REFRESH AUTOMATICO 2 SECONDI
<script> function refreshPage() { location.reload(); } setInterval(refreshPage, 2000); </script>
HTML / PHP · PULSANTI CONTROLLO LED
<!-- Accensione --> <form method="get" action="control_led.php"> <input type="hidden" name="comando" value="1"> <button type="submit">Accendi</button> </form> <!-- Spegnimento --> <form method="get" action="control_led.php"> <input type="hidden" name="comando" value="0"> <button type="submit">Spegni</button> </form>
PHP · STATO VISUALE LED GIALLO/GRIGIO
background-color: <?= $led_status == 'acceso' ? 'yellow' : '#ccc'; ?>;

5.3 Tabella e grafico

PHP / HTML · TABELLA SENSOR_DATA
<table> <thead> <tr> <th>Timestamp</th> <th>Potenziometro</th> <th>LED</th> </tr> </thead> <tbody> <?php foreach ($data as $row): ?> <tr> <td><?= $row['timestamp'] ?></td> <td><?= $row['valore'] ?></td> <td><?= $row['led_status'] ?></td> </tr> <?php endforeach; ?> </tbody> </table>
JAVASCRIPT · CHART.JS GRAFICO LINEARE
let labels = <?= json_encode(array_column($data, 'timestamp')) ?>.reverse(); let values = <?= json_encode(array_column($data, 'valore')) ?>.reverse(); const ctx = document.getElementById('iotChart').getContext('2d'); const chart = new Chart(ctx, { type: 'line', data: { labels: labels, datasets: [{ label: 'Valore Potenziometro', data: values, borderColor: 'rgb(75, 192, 192)', tension: 0.1 }] }, options: { responsive: true, scales: { x: { title: { display: true, text: 'Tempo' } }, y: { title: { display: true, text: 'Valore' } } } } });

Il risultato è un grafico lineare che permette di osservare come varia il valore del potenziometro nel tempo. È il collegamento diretto tra Lezione 1 MCU sensori e la parte web.

⚠️ Errore comune - Chart vuoto

Se il grafico è vuoto controlla prima se la tabella sensor_data contiene dati: SELECT COUNT(*). Poi verifica array_column: se $data è vuoto, json_encode restituisce [] e Chart.js non disegna. Aggiungi console.log(labels, values) per debug. Altro errore frequente: dimenticare .reverse() così timestamp è invertito.

6. Il flusso completo e test finale

A questo punto possiamo ricostruire l'intero percorso dell'informazione come sistema IoE didattico che parte dalla Lezione 1 MCU e arriva al controllo remoto.

1
SENSORE
Potenziometro
→
2
MCU
Lezione 1
→
3
JSON
valore+led
→
4
HTTP POST
RealHTTP
→
5
PHP
iot_data.php
→
6
MYSQL
sensor_data
DATABASE
→
DASHBOARD
PHP+Chart
→
control_led.php
→
HTTP GET
:8765
→
MCU
→
LED
attuator
🎯 Concetto chiave - Percorso bidirezionale

Flusso dati: acquisizione → elaborazione → trasmissione → memorizzazione → visualizzazione.
Flusso comando: interfaccia → API → HTTP → dispositivo → attuatore. Il progetto non è solo mandare un valore a DB, è un esempio completo di comunicazione tra dispositivi, servizi web e database.

Test passo-passo

Avviare Apache e MySQL tramite XAMPP - verifica verde in pannello.
Verificare che database IoT_database sia disponibile in phpMyAdmin.
Avviare il programma Python dell'MCU in Packet Tracer - Run.
Muovere potenziometro e verificare valore sul display - customWrite(2,valPot).
Controllare che dati vengano inseriti in sensor_data - console print "Dati inviati".
Aprire dashboard.php e verificare presenza dati in tabella e grafico.
Premere Accendi e verificare LED nell'MCU si accende HIGH.
Premere Spegni e verificare LED si spegne LOW e stato aggiorna DB.

7. Troubleshooting e debug multilivello

Un progetto che coinvolge simulazione, rete, server, PHP e database può fallire in punti differenti. Un metodo utile consiste nel controllare il percorso del dato un livello alla volta.

PROBLEMA 1

Valore non arriva al DB

Controllare MCU print, URL endpoint http://127.0.0.1/test/IoT/iot_data.php, Apache attivo, connessione mysqli. Usa try/except Python.

PROBLEMA 2

Grafico vuoto

Controlla se tabella contiene dati, query SQL restituisce risultati, json_encode non vuoto, reverse labels.

PROBLEMA 3

LED non cambia stato

Verifica parametro comando 0/1, route /control_led registrata, porta 8765 in ascolto server.isListening(), firewall Windows.

⚠️ Metodo utile - Debug a livelli

Non modificare contemporaneamente tutti i componenti. Se qualcosa non funziona verifica prima singolo collegamento: MCU → HTTP, HTTP → PHP, PHP → MySQL, oppure Dashboard → PHP → MCU. In laboratorio questo metodo salva tempo: isolamento del guasto è competenza sistemistica fondamentale.

💬 Tip del docente - Firewall e porte

Il caso più frequente in aula: file_get_contents verso 127.0.0.1:8765 fallisce perché Windows Firewall blocca XAMPP o Packet Tracer. Mostra agli studenti come aggiungere eccezione porta 8765 e 80. Fallo provare: senza eccezione, led_status non cambia; con eccezione, funziona subito. Ottima lezione su porte e sicurezza.

8. Verifica / Esercizio pratico

🔬 Attività di laboratorio - Progetto 01 Lezione 1 + HTTP Real

Realizza il progetto completo partendo dalla base MCU sensori attuatori della Lezione 1 e aggiungendo comunicazione HTTP reale.

  1. Parte base (Lezione 1): Collega in Packet Tracer MCU, potenziometro su A0, display su pin 2, LED su pin 1. Scrivi codice Python che legge analogRead(A0) e visualizza con customWrite(2). Verifica funzionamento senza rete.
  2. Database: Crea IoT_database e tabella sensor_data con campi id, valore, led_status, timestamp. Inserisci manualmente una riga di test con INSERT e verifica in phpMyAdmin.
  3. API iot_data.php: Implementa ricezione JSON con php://input e json_decode. Testa con Postman inviando {"valore": 600, "led_status":"acceso"} a http://127.0.0.1/test/IoT/iot_data.php e controlla DB.
  4. Real HTTP Client su MCU: Importa realhttp, crea RealHTTPClient, implementa ciclo while True con sleep(2) e client.post JSON. Controlla console Packet Tracer e verifica nuovi dati in DB.
  5. Real HTTP Server e controllo LED: Implementa server = RealHTTPServer(), server.start(8765), funzione control_led con parsing query string comando=1/0 e digitalWrite(1,HIGH/LOW). Registra route e testa da browser http://127.0.0.1:8765/control_led?comando=1
  6. Dashboard e integrazione finale: Crea dashboard.php con query ultimi 10 record, tabella, Chart.js, pulsanti accendi/spegni verso control_led.php, refresh automatico ogni 2s. Testa flusso completo: muovi potenziometro → vedi grafico aggiornarsi → premi Accendi → LED si accende → DB registra nuovo led_status.
✅ Soluzione ragionata e criteri valutazione

Soluzione: Il funzionamento corretto prevede: MCU legge 0-1023, JSON {"valore":X,"led_status":"spento/acceso"}, POST a iot_data.php che fa INSERT, dashboard SELECT * ORDER BY id DESC LIMIT 10, Chart.js con reverse timestamp. Comando LED: form GET comando=1 → control_led.php → file_get_contents(http://127.0.0.1:8765/control_led?comando=1) → MCU digitalWrite HIGH e aggiorna stato_led globale.
Valutazione: 30% base Lezione 1 funzionante, 20% DB + API, 20% Real HTTP Client/Server, 20% dashboard completa, 10% troubleshooting documentato. Richiedi screenshot tabella sensor_data con almeno 5 valori diversi e video LED che si accende da dashboard.

📚 Possibili estensioni didattiche

Una volta completato: aggiungere altri sensori (temperatura, luce), memorizzare più grandezze nella stessa tabella, realizzare più grafici nella dashboard, aggiungere soglie e notifiche (se valore > 800 alert), introdurre ulteriori attuatori (buzzer, motore), separare maggiormente API, database e interfaccia con pattern MVC, utilizzare progetto come base per architettura IoT completa con ESP32 reale.

✓Lezione 1 MCU sensori attuatori: potenziometro è sensore analogico A0 letto con analogRead, LED è attuatore digitale pin 1 controllato con digitalWrite. Display pin 2 visualizza valore.
✓HTTP Real: RealHTTPClient per POST JSON verso server reale XAMPP, RealHTTPServer su porta 8765 per ricevere GET /control_led?comando=1 e gestire LED.
✓API PHP e JSON: php://input legge body HTTP, json_decode trasforma JSON in array PHP, file_get_contents invia comando GET all'MCU. Endpoint = URL funzionalità.
✓MySQL e Dashboard: tabella sensor_data con valore 0-1023, led_status, timestamp. Dashboard recupera ultimi 10 record, grafico Chart.js, controllo remoto LED, refresh 2s.
✓Flusso bidirezionale e ruolo MCU: MCU client quando invia dati, server quando riceve comando. Dati: SENSORE→MCU→JSON→POST→PHP→MYSQL→DASHBOARD. Comando: DASHBOARD→PHP→GET→MCU→LED.
✓Debug multilivello: verifica livelli singoli MCU→HTTP, HTTP→PHP, PHP→MySQL, Dashboard→PHP→MCU. Firewall porta 8765, nome database, URL endpoint sono errori comuni.

📚 Prossimo passo - Progetto 02 IoE con Cisco Packet Tracer e HTTP Real avanzato

Partendo da questa base Lezione 1 + HTTP Real, nel Progetto 02 approfondiremo pattern REST completi, gestione di più sensori contemporanei, autenticazione API e dashboard con soglie e notifiche. Mantieni funzionante questo progetto: sarà la fondamenta per architetture IoT distribuite più complesse e per il passaggio a dispositivi reali come ESP32.