Mini proiect (48) - Trimiterea unui mesaj de la un ESP32 către WhatsApp

Trimiterea unui mesaj de la un ESP32 către WhatsApp 

Astăzi m-am jucat cu un senzor DHT11 refolosit, a cărui date am vrut să le trimis către WhatsApp prin intermediul Callmebot. Mai jos am documentat pas cu pas cum am procedat. 

De la senzorul DHT11 am citit temperatura și umiditatea, iar de la un server NTP citesc data și ora. Aceste date le împachetez și le trimit la interval de 10 min. În același timp am implementat în software astfel încât placa ESP32 să consume cât mai puțină energie pentru a asigura o viață lungă bateriei.

Pentru a trimite un mesaj de la un ESP32 către WhatsApp cu aceste date, folosind API-ul Callmebot, puteți urma următorii pași:

  •  Asigurați-vă că aveți acces la internet prin intermediul plăcii ESP32. Acest lucru poate fi realizat prin conectarea plăcii la o rețea Wi-Fi sau prin utilizarea unui modul de conectare GSM / GPRS.
  •  Conectați senzorul DHT11 la placa ESP32. Asigurați-vă că ați configurat corect pinii de date și de alimentare a senzorului în codul dvs, iar între pin-ul 1 și 2 se va conecta o rezistență de 1KOhm (vezi schema)
  •  Creați un cont Callmebot și obțineți o cheie API. Puteți găsi instrucțiunile pentru crearea unui cont și obținerea unei chei API pe site-ul Callmebot.
  •  Instalați biblioteca "UrlEncode" pentru ESP32. Aceasta va fi necesară pentru a codifica mesajele pentru a putea fi trimise
  •  Scrieți codul pentru a citi datele temperatură și umiditate de la senzorul DHT11 și pentru a le include într-un mesaj care va fi trimis prin intermediul API-ului Callmebot către un număr de WhatsApp specificat. Asigurați-vă că includeți cheia API Callmebot și numărul de telefon destinatar în codul dvs. (vezi codul de test de mai jos)
  • Încărcați codul pe placa ESP32 și verificați dacă mesajul a fost trimis cu succes către numărul de telefon specificat.

Reducerea și optimizarea consumului

 De asemenea, aș vrea să menționez că pentru a trimite mesaje periodic la intervale de timp specifice, am folosit chiar funcția loop din Arduino, pentru a controla intervalul de timp între trimiterile mesajelor, dar am vrut și un consum cât mai mic de curent având în vedere că folosesc o baterie drept sursă de alimentare, iar pentru asta am implementat să trimit procesorul ESP32 în "deep sleep", și îl trezesc period la 10 min.

Practic pentru reducerea și optimizarea consumului de energie al plăcii ESP32, am oprit complet dispozitivului atunci când placa nu este utilizată, și trezesc dispozitivul doar câteva secunde pentru a citi datele și pentru a le trimite datele pe WhatsApp.

În modul de "deep sleep", placa ESP32 își oprește toate componentele, cu excepția unui timer intern și a unui modul de trezire, și consumă foarte puțină energie. Pentru a trece placa ESP32 în modul de "deep sleep", puteți folosi funcția "esp_deep_sleep_start()" din biblioteca "esp32-hal-sleep.h".  

Pentru a trezi placa din modul de "deep sleep", puteți utiliza unul dintre următoarele moduri:

  • Un semnal de trezire extern, precum un semnal de întrerupere sau un semnal de rețea Wi-Fi.
  • Un timer intern, prin intermediul funcției "esp_deep_sleep_set_wakeup_time()".
  • Un pin de întrerupere, prin intermediul funcției "esp_deep_sleep_enable_ext0_wakeup()" sau "esp_deep_sleep_enable_ext1_wakeup()".

În acest proiect am folosit trezirea prin intermediul timer-ului intern. Practic mai pe scurt, ESP32-ul se trezește la 10 min citește temperatura și umiditatea, plus citește data și ora, și trimite toate aceste date prin intermediul Callmebot pe WhatsApp catre numărul meu de telefon.

Componente

Schema electronica/sistem

Trimiterea unui mesaj de la un ESP32 către Whatsup cu data, ora, și de la senzorul DTH11 temperatura și umiditatea

Cod de test

/*
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp32doit-devkit-v1]
platform = espressif32
board = esp32doit-devkit-v1
framework = arduino
upload_port = COM7
monitor_port = COM7
monitor_speed = 115200
lib_deps =
plageoj/UrlEncode@^1.0.1
adafruit/DHT sensor library@^1.4.4
beegee-tokyo/DHT sensor library for ESPx@^1.18
*/
/*
Florin Simedru
Complete project details at https://automatic-house.blogspot.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
#include <WiFi.h>
#include <HTTPClient.h>
#include <UrlEncode.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#define uS_TO_S_FACTOR 1000000ULL // Conversion factor for micro seconds to seconds
#define TIME_TO_SLEEP 120 // Time ESP32 will go to sleep (in seconds)
#define DHTPIN 16 // Digital pin connected to the DHT sensor
#define SERIAL_DEBUG_OFF // define for activating or deactivating of the Serial output - rename it to SERIAL_DEBUG_ON to activate serial output
#define DHTTYPE DHT11 // DHT 11
/* Put your SSID & Password */
const char *ssid = "SSID"; // Enter SSID here
const char *password = "PASS"; // Enter Password here
// +international_country_code + phone number
// Portugal +351, example: +351912345678
String phoneNumber = "PHONE NUMBER HERE";
String apiKey = "API KEY HERE";
const char *ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 7200;
const int daylightOffset_sec = 3600;
DHT_Unified dht(DHTPIN, DHTTYPE);
uint32_t delayMS;
String DHT11_read()
{
String DHT11_read_str;
// Delay between measurements.
delay(2000);
// Get temperature event and print its value.
sensors_event_t event;
dht.temperature().getEvent(&event);
if (isnan(event.temperature))
{
#ifdef SERIAL_DEBUG_ON
Serial.println(F("Error reading temperature!"));
#endif
DHT11_read_str = "Error reading temperature!";
}
else
{
#ifdef SERIAL_DEBUG_ON
Serial.print(F("Temperature: "));
Serial.print(event.temperature);
Serial.println(F("°C"));
#endif
DHT11_read_str = " Temperature: " + String(event.temperature) + "°C ";
}
// Get humidity event and print its value.
dht.humidity().getEvent(&event);
if (isnan(event.relative_humidity))
{
#ifdef SERIAL_DEBUG_ON
Serial.println(F("Error reading humidity!"));
#endif
DHT11_read_str = "Error reading humidity!";
}
else
{
#ifdef SERIAL_DEBUG_ON
Serial.print(F("Humidity: "));
Serial.print(event.relative_humidity);
Serial.println(F("%"));
#endif
DHT11_read_str += " Humidity: " + String(event.relative_humidity) + "% ";
}
// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
dht.humidity().getEvent(&event);
float h = event.relative_humidity;
// Read temperature as Celsius (the default)
dht.temperature().getEvent(&event);
float t = event.temperature;
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t) )
{
#ifdef SERIAL_DEBUG_ON
Serial.println(F("Failed to read from DHT sensor!"));
#endif
return String("Failed to read from DHT sensor!");
}
else
{
DHT11_read_str = " Temperature: " + String(t) + "°C ";
DHT11_read_str += " Humidity: " + String(h) + "% ";
return DHT11_read_str;
}
}
void DHT11_setup()
{
// Initialize device.
dht.begin();
#ifdef SERIAL_DEBUG_ON
Serial.println(F("DHTxx Unified Sensor Example"));
#endif
// Print temperature sensor details.
sensor_t sensor;
dht.temperature().getSensor(&sensor);
#ifdef SERIAL_DEBUG_ON
Serial.println(F("------------------------------------"));
Serial.println(F("Temperature Sensor"));
Serial.print(F("Sensor Type: "));
Serial.println(sensor.name);
Serial.print(F("Driver Ver: "));
Serial.println(sensor.version);
Serial.print(F("Unique ID: "));
Serial.println(sensor.sensor_id);
Serial.print(F("Max Value: "));
Serial.print(sensor.max_value);
Serial.println(F("°C"));
Serial.print(F("Min Value: "));
Serial.print(sensor.min_value);
Serial.println(F("°C"));
Serial.print(F("Resolution: "));
Serial.print(sensor.resolution);
Serial.println(F("°C"));
Serial.println(F("------------------------------------"));
#endif
// Print humidity sensor details.
dht.humidity().getSensor(&sensor);
#ifdef SERIAL_DEBUG_ON
Serial.println(F("Humidity Sensor"));
Serial.print(F("Sensor Type: "));
Serial.println(sensor.name);
Serial.print(F("Driver Ver: "));
Serial.println(sensor.version);
Serial.print(F("Unique ID: "));
Serial.println(sensor.sensor_id);
Serial.print(F("Max Value: "));
Serial.print(sensor.max_value);
Serial.println(F("%"));
Serial.print(F("Min Value: "));
Serial.print(sensor.min_value);
Serial.println(F("%"));
Serial.print(F("Resolution: "));
Serial.print(sensor.resolution);
Serial.println(F("%"));
Serial.println(F("------------------------------------"));
#endif
// Set delay between sensor readings based on sensor details.
delayMS = sensor.min_delay / 1000;
}
void print_wakeup_reason()
{
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
#ifdef SERIAL_DEBUG_ON
switch (wakeup_reason)
{
case ESP_SLEEP_WAKEUP_EXT0:
Serial.println("Wakeup caused by external signal using RTC_IO");
break;
case ESP_SLEEP_WAKEUP_EXT1:
Serial.println("Wakeup caused by external signal using RTC_CNTL");
break;
case ESP_SLEEP_WAKEUP_TIMER:
Serial.println("Wakeup caused by timer");
break;
case ESP_SLEEP_WAKEUP_TOUCHPAD:
Serial.println("Wakeup caused by touchpad");
break;
case ESP_SLEEP_WAKEUP_ULP:
Serial.println("Wakeup caused by ULP program");
break;
default:
Serial.printf("Wakeup was not caused by deep sleep: %d\n", wakeup_reason);
break;
}
#endif
}
String printLocalTime()
{
struct tm timeinfo;
if (!getLocalTime(&timeinfo))
{
#ifdef SERIAL_DEBUG_ON
Serial.println("Failed to obtain time");
#endif
return String("Failed to obtain time");
}
#ifdef SERIAL_DEBUG_ON
Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
Serial.print("Day of week: ");
Serial.println(&timeinfo, "%A");
Serial.print("Month: ");
Serial.println(&timeinfo, "%B");
Serial.print("Day of Month: ");
Serial.println(&timeinfo, "%d");
Serial.print("Year: ");
Serial.println(&timeinfo, "%Y");
Serial.print("Hour: ");
Serial.println(&timeinfo, "%H");
Serial.print("Hour (12 hour format): ");
Serial.println(&timeinfo, "%I");
Serial.print("Minute: ");
Serial.println(&timeinfo, "%M");
Serial.print("Second: ");
Serial.println(&timeinfo, "%S");
Serial.println("Time variables");
char timeHour[3];
char timeHMS[12];
strftime(timeHour, 3, "%H", &timeinfo);
strftime(timeHMS, 11, "%H:%M:%S", &timeinfo);
Serial.println(timeHour);
char timeWeekDay[10];
strftime(timeWeekDay, 10, "%A", &timeinfo);
Serial.println(timeWeekDay);
Serial.println();
#endif
char timeDate[36];
strftime(timeDate, 36, "%A, %B %d %Y %H:%M:%S", &timeinfo);
return String(timeDate);
}
void SendWhatsUpMessage(String message)
{
// Data to send with HTTP POST
String url = "https://api.callmebot.com/whatsapp.php?phone=" + phoneNumber + "&apikey=" + apiKey + "&text=" + urlEncode(message);
HTTPClient http;
digitalWrite(BUILTIN_LED, HIGH); // turn buzzer on
delay(100);
http.begin(url);
// Specify content-type header
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
// Send HTTP POST request
int httpResponseCode = http.POST(url);
#ifdef SERIAL_DEBUG_ON
if (httpResponseCode == 200)
{
Serial.println("Message sent successfully\n");
}
else
{
Serial.println("Error sending the message");
Serial.print("HTTP response code: ");
Serial.println(httpResponseCode);
}
#endif
// Free resources
http.end();
digitalWrite(BUILTIN_LED, LOW); // turn buzzer off
delay(100);
}
void reconnect()
{
#ifdef SERIAL_DEBUG_ON
Serial.begin(115200);
#endif
while (WiFi.status() != WL_CONNECTED)
{
WiFi.disconnect();
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
#ifdef SERIAL_DEBUG_ON
Serial.println("Reconnecting");
#endif
delay(1000);
#ifdef SERIAL_DEBUG_ON
Serial.print(".");
#endif
}
#ifdef SERIAL_DEBUG_ON
Serial.println("");
Serial.print("Connected to WiFi network with IP Address: ");
#endif
Serial.println(WiFi.localIP());
WiFi.setAutoReconnect(true);
WiFi.persistent(true);
DHT11_setup();
// Init and get the time
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
Serial.println(printLocalTime());
// Send Message to WhatsAPP
SendWhatsUpMessage("Hello from ESP32! " + printLocalTime() + " " + DHT11_read());
}
void setup()
{
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
#ifdef SERIAL_DEBUG_ON
Serial.println("Connecting");
#endif
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
#ifdef SERIAL_DEBUG_ON
Serial.print(".");
#endif
}
#ifdef SERIAL_DEBUG_ON
Serial.println("");
Serial.print("Connected to WiFi network with IP Address: ");
Serial.println(WiFi.localIP());
#endif
WiFi.setAutoReconnect(true);
WiFi.persistent(true);
// Init and get the time
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
#ifdef SERIAL_DEBUG_ON
Serial.println(printLocalTime());
#endif
// Configure DHT11 sensor
DHT11_setup();
// configure BuildIn LED for output
pinMode(BUILTIN_LED, OUTPUT);
}
void loop()
{
print_wakeup_reason(); // Print the wakeup reason for ESP32
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); // ESP32 wakes up every 60 seconds
reconnect();
#ifdef SERIAL_DEBUG_ON
Serial.println("Going to deep-sleep now");
Serial.flush();
#endif
esp_deep_sleep_start();
}

 

Rezultat


 

 După cum se observă în imaginea de mai jos am conectat o rezistență de 1KOhm între pinul 1 și 2, adică între Data și Vcc.

Trimiterea unui mesaj de la un ESP32 către Whatsup cu data, ora, și de la senzorul DTH11 temperatura și umiditatea

Iar alimentarea plăcii ESP32 am asigurat-o folosind o baterie de 9V și un regulator de 5V (plăcuța roșie). Din păcate nu am găsit acest regulator în fritzing, și în schema de mai sus am folosit o placă echivalentă (placa albastră din schemă). Ieșirea + si - de la regulator le-am conectat la VIN si GND de pe ESP32 (vezi și în schema de mai sus).

Trimiterea unui mesaj de la un ESP32 către Whatsup cu data, ora, și de la senzorul DTH11 temperatura și umiditatea
În momentul în care se trimite un mesaj se activează ledul albastru de pe placa ESP32.
Trimiterea unui mesaj de la un ESP32 către Whatsup cu data, ora, și de la senzorul DTH11 temperatura și umiditatea
 

Documentație proiect

Todo

  • Să printez o cutiuță faină pentru ESP32 
  • Să trimit aceeași informație către Home Assistant folosind protocolul MQTT

Afiliere eMag:

 Linkurile de la secțiunea "Componente" conțin adresa mea de afiliere la eMag.ro, iar dacă cumperi folosind aceste linkuri vei susține blogul meu. Mulțumesc! 

eMag Genius:
Hai și tu în Genius! Abonează-te la Genius 12 luni și primești beneficii premium și 20 lei card cadou eMAG. Profită acum! eMag Genius

Mulțumesc pentru atenție!

Pentru întrebari și/sau consultanță tehnică vă stau la dispozitie pe blog mai jos în secțiunea de comentarii sau pe email simedruflorin@automatic-house.ro. O zi și seară plăcută tuturor !  

 

Back to top of page


Etichete

Afișați mai multe

Arhiva

Afișați mai multe