// Codice per il monitoraggio da remoto della temperatura e umidità
// con NodeRED su http://NODEREDCLIENT_IPADDRESS/8080/ui
// con webserver ESP_IPADDRESS
#include "Adafruit_Sensor.h"
#include <DHT.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebSrv.h>
// Wokwi Virtual WiFi
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "test.mosquitto.org";// MQTT Broker address
int mqtt_broker_port = 1883;
char* mqttTopic_DHT_temp = "esp32/iot1/dht/temp"; // MQTT topic2: sensor-temerature
char* mqttTopic_DHT_hum = "esp32/iot1/dht/hum"; // MQTT topic3: sensor-humidity
WiFiClient wifiClient;
PubSubClient pubSubClient(wifiClient);
// Se si volessero introdurre certificati di SSL/TLS bisognerebbe
// creare qui gli oggetti a partire dal client(espClient)
//Constants
#define DHTPIN 4 // pin DATI sul GPIO
#define DHTTYPE DHT11 // Sensore DHT11 (AM2302)
//#define DHTTYPE DHT22 // DHT 11 (AM2302)
DHT dht(DHTPIN, DHTTYPE); // Inizializza il sensore
float temp; // valori sensore temperatura
float humidity; // valori sensore umidità
int LEDPIN = 22; //GPIO pin usato dal LED
const int ledPin = 2; //Pin controllato dal WebServer
bool ledState = 0; //Stato pin contrallato dal WebServer
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");
//----------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<title>ESP Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
<style>
html {
font-family: Arial, Helvetica, sans-serif;
text-align: center;
}
h1 {
font-size: 1.8rem;
color: white;
}
h2{
font-size: 1.5rem;
font-weight: bold;
color: #143642;
}
.topnav {
overflow: hidden;
background-color: #143642;
}
body {
margin: 0;
}
.content {
padding: 30px;
max-width: 600px;
margin: 0 auto;
}
.card {
background-color: #F8F7F9;;
box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);
padding-top:10px;
padding-bottom:20px;
}
.button {
padding: 15px 50px;
font-size: 24px;
text-align: center;
outline: none;
color: #fff;
background-color: #0f8b8d;
border: none;
border-radius: 5px;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-tap-highlight-color: rgba(0,0,0,0);
}
/*.button:hover {background-color: #0f8b8d}*/
.button:active {
background-color: #0f8b8d;
box-shadow: 2 2px #CDCDCD;
transform: translateY(2px);
}
.state {
font-size: 1.5rem;
color:#8c8c8c;
font-weight: bold;
}
</style>
<title>ESP Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
</head>
<body>
<div class="topnav">
<h1>ESP WebSocket Server</h1>
</div>
<div class="content">
<div class="card">
<h2>Output - GPIO 2</h2>
<p class="state">state: <span id="state">%STATE%</span></p>
<p><button id="button" class="button">Toggle</button></p>
</div>
</div>
<script>
var gateway = `ws://${window.location.hostname}/ws`;
var websocket;
window.addEventListener('load', onLoad);
function initWebSocket() {
console.log('Trying to open a WebSocket connection...');
websocket = new WebSocket(gateway);
websocket.onopen = onOpen;
websocket.onclose = onClose;
websocket.onmessage = onMessage; // <-- add this line
}
function onOpen(event) {
console.log('Connection opened');
}
function onClose(event) {
console.log('Connection closed');
setTimeout(initWebSocket, 2000);
}
function onMessage(event) {
var state;
if (event.data == "1"){
state = "ON";
}
else{
state = "OFF";
}
document.getElementById('state').innerHTML = state;
}
function onLoad(event) {
initWebSocket();
initButton();
}
function initButton() {
document.getElementById('button').addEventListener('click', toggle);
}
function toggle(){
websocket.send('toggle');
}
</script>
</body>
</html>
)rawliteral";
void notifyClients() {
ws.textAll(String(ledState));
}
void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {
AwsFrameInfo *info = (AwsFrameInfo*)arg;
if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
data[len] = 0;
if (strcmp((char*)data, "toggle") == 0) {
ledState = !ledState;
notifyClients();
}
}
}
void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type,
void *arg, uint8_t *data, size_t len) {
switch (type) {
case WS_EVT_CONNECT:
Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
break;
case WS_EVT_DISCONNECT:
Serial.printf("WebSocket client #%u disconnected\n", client->id());
break;
case WS_EVT_DATA:
handleWebSocketMessage(arg, data, len);
break;
case WS_EVT_PONG:
case WS_EVT_ERROR:
break;
}
}
void initWebSocket() {
ws.onEvent(onEvent);
server.addHandler(&ws);
}
String processor(const String& var){
Serial.println(var);
if(var == "STATE"){
if (ledState){
return "ON";
}
else{
return "OFF";
}
}
return String();
}
//----------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------
void setup_wifi() { // Connessione al WiFi
WiFi.mode(WIFI_STA); // default, se non lo si dichiara non serve
//delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP()); // Indirizzo IP associato all'ESP32 una volta connesso
}
// Process incoming MQTT message and control the servo motor
//void callback(char* topic, byte* payload, unsigned int length) {
//if (topic = mqttTopic_DHT_temp){
//}
//}
void setup() {
Serial.begin(115200); // Inizializzazione del monitor seriale (solo per il debugging!)
//myservo.attach(5); // Evetuale servo sul GPIO 5
pinMode(LEDPIN, OUTPUT);
dht.begin();
setup_wifi();
pubSubClient.setServer(mqtt_server, mqtt_broker_port); // Server e porta MQTT del broker al quale puntare
//pubSubClient.setCallback(callback); // Funzione di callback per i messaggi in ingresso
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
initWebSocket();
// Route root webpage : /
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});
server.begin(); // Start Web Server
delay(2000);
}
void mqttReconnect() { // Riconnessione al broker MQTT
while (!pubSubClient.connected()) {
Serial.print("Attempting MQTT connection...");
if (pubSubClient.connect("ESPClient")) {
Serial.println("connected");
pubSubClient.subscribe(mqttTopic_DHT_temp);
pubSubClient.subscribe(mqttTopic_DHT_hum);
} else {
Serial.print("failed, rc=");
Serial.print(pubSubClient.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void loop() {
if (!pubSubClient.connected()) { // Verifica lo stato della connessione MQTT
digitalWrite(LEDPIN, LOW);
mqttReconnect();
} else {
digitalWrite(LEDPIN, HIGH);
}
pubSubClient.loop();
delay(100); // ritardo per gestire il canale loop
temp = dht.readTemperature();
humidity = dht.readHumidity();
Serial.print("Temp : ");
Serial.print(temp);
Serial.println(" C ");
Serial.print("Humidity : ");
Serial.print(humidity);
Serial.println(" % ");
String messaget = String(temp); // Formato di scambio stringhe con pubsubclient
String messageh = String(humidity); // Formato di scambio stringhe con pubsubclient
pubSubClient.publish(mqttTopic_DHT_temp, messaget.c_str());
pubSubClient.publish(mqttTopic_DHT_hum, messageh.c_str());
ws.cleanupClients();
digitalWrite(ledPin, ledState);
delay(200);
}