Идея создания проекта - Контроль влажности подвала Arduino pro mini | Аппаратная платформа Arduino
Переделано на ESP8266 - полностью.
Исходники и скриншоты прилагаются.
Server ESP_Gar_server.ino
// 15.04.2023
// https://randomnerdtutorials.com/esp8266-esp-now-wi-fi-web-server/
#include <espnow.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncWebServer.h>
#include <Arduino_JSON.h> // version=0.2.0
#include <SparkFunHTU21D.h> // version=1.1.3
#include <LiquidCrystal_I2C.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h> // version=1.0
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <UrlEncode.h> // version=1.0.1
#include <RemoteDebug.h> // version=2.1.2
#include "html.h" // веб-страница
#include "settings.h" // Настройки - ввести свои данные!!!
#define ENABLE_OTA_UPDATE true //Обновление ESP8266 по воздуху
//Глобальные переменные - не изменять!!!!!
//-----------------------------------
// данные WiFi AP точки доступа, должны совпадать с клиентом в подвале
const char ssidAP[] = "esp_8266";
const char passAP[] = "00000000";
//-----------------------------------
// пины вентилятора и отопителя ////////////////////////////
const int FANpin = 14; // GPIO14(D5).
bool FANstatus = false; // реле ВЫКЛ.
const int HEATERpin = 12; // GPIO12(D6).
bool HEATERstatus = false; // реле ВЫКЛ.
String fan_= "OFF"; // ON, OFF статус
String hea_= "OFF";
//-----------------------------------
bool DataRecv_ERROR = true; // ошибка получения данных от передатчика в погребе
bool WiFi_status = false; // статус WiFi - отключен
bool RemoteSerial = true; //true = Remote and local serial, false = local serial only
const char* host = "R_Debug"; // ArduinoOTA
// Вводим переменные для показаний гараж
float temp_gar;
float hum_gar;
float outAbsH; // абс влажность гараж
// Вводим переменные для хранения входящих показаний
float incomingTemp = Temp_Heater_ON + 1; // подвал, предварительно устанавливаем температуру для не вкл. отопителя при старте модуля
// float incomingTemp; // подвал
float incomingHum;
float cellarAbsH; // абс влажность подвал
unsigned int Read_id;
int32_t rssi_dB;
int32_t rssi_dB_WiFi;
//-----------------------------------
// принимаемая структура
typedef struct struct_message {
int id;
float temp;
float hum;
unsigned int readingId;
int32_t rssi;
} struct_message;
struct_message incomingReadings; //создание структуры incomingReadings
//-----------------------------------
// инициализация
RemoteDebug RSerial; // удалённый мониторинг - telnet
HTU21D myHumidity; // датчик температуры и влажности
LiquidCrystal_I2C lcd(0x27, 16, 2); // дисплей
JSONVar board; // Переменная JSON с именем board
AsyncWebServer server(80); // Асинхронный веб-сервер, порт:80.
AsyncEventSource events("/events"); // Источник событий /events
// Обработчик событий Wi-Fi
//WiFiEventHandler wifiConnectHandler; //Connect
WiFiEventHandler wifiDisconnectHandler; //Disconnect
void setup() {
Serial.begin(115200); // Запуск Serial Monitor
RSerial.begin(host); // удалённый мониторинг - telnet
RSerial.setSerialEnabled(true);
//Зарегистрировать обработчики событий Wi-Fi
// wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect);
wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect);
// GPIO как выходы
pinMode(FANpin, OUTPUT);
pinMode(HEATERpin, OUTPUT);
digitalWrite(FANpin, HIGH); // выключаем вентилятор
digitalWrite(HEATERpin, HIGH); // выключаем отопитель
myHumidity.begin();
delay (500);
initWiFi();
if ( ENABLE_OTA_UPDATE )
{
initOTA();
}
lcd.begin();
lcd.backlight();
lcd.clear();
delay(500);
lcd.setCursor(0, 0);lcd.print(WiFi.localIP());
lcd.setCursor(0, 1);lcd.print(WiFi.softAPIP());
// Init ESP-NOW получаем информацию
initEspNow();
getReadings();
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html);
});
events.onConnect([](AsyncEventSourceClient *client){
if(client->lastId()){
RSerial.printf("Client reconnected! Last message ID that it got is: %u\n", client->lastId());
}
// отправить событие с сообщением "hello!" и устанавливаем задержку переподключения
client->send("hello!", NULL, millis(), 10000);
});
server.addHandler(&events);
server.begin();
} // end setup
void loop() {
if ( ENABLE_OTA_UPDATE )
{
ArduinoOTA.handle();
}
static unsigned long lastEventTime = millis();
if ((millis() - lastEventTime) > EVENT_INTERVAL_MS * 1000) {
events.send("ping",NULL,millis());
// lastEventTime = millis();
incomingTemp = incomingReadings.temp; // температура
incomingHum = incomingReadings.hum; // влажность
Read_id = incomingReadings.readingId;
rssi_dB = incomingReadings.rssi;
getReadings();
// проверка от ложных показаний датчиков
if (CalcAbsH(incomingTemp,incomingHum) <100){
cellarAbsH = CalcAbsH(incomingTemp,incomingHum); // абсолют. влажность в подвале
}
if (CalcAbsH(temp_gar,hum_gar) <100){
outAbsH = CalcAbsH(temp_gar,hum_gar); // абсолют. влажность в подвале
}
printIncomingReadings(); // Отображаем показания в мониторе порта
// полученный уровень сигнала WiFi dB:
rssi_dB_WiFi = getWiFidBm(ssid);
// переподключение к нашей сети WiFi после пропадания и потом в момент появления
if ((getWiFiSSID(ssid) == String (ssid)) and (WiFi_status == false))
{
RSerial.print("Connect to: ");
RSerial.println(WiFi.SSID());
RSerial.println("initWiFi() .. ");
initWiFi();
// RSerial.println("restart .. ");
// restart();
}
else {
RSerial.println("Connect-successfully");
}
//обработка датчиков подвала и гаража
if ( DataRecv_ERROR == false) // если данные получены управляем вентилятором и отопителем
{
RSerial.println("DATA RECV.- YES");
if (incomingTemp < Temp_Heater_ON) //при температуре в подвале менее +1.5 градуса включить отопитель и выкл вентилятор.
{ digitalWrite(FANpin, HIGH); // выключаем вентилятор
FANstatus = false; // реле ВЫКЛ. - мониторинг
fan_= "OFF";
digitalWrite(HEATERpin, LOW); // включаем отопитель
HEATERstatus = true; // реле ВКЛ. - мониторинг
hea_= "ON"; }//end if (incomingTemp < Temp_Heater_ON)
if (incomingTemp >= Temp_Heater_ON + Temp_Heater_Hysteresis) //выключаем отопитель +1 для гистерезиса вкл/откл отопителя
{ digitalWrite(HEATERpin, HIGH);
HEATERstatus = false; // реле ВЫКЛ. - мониторинг
hea_= "OFF"; }//if (incomingTemp >=
if (temp_gar > Temp_FAN_ON) // включить вентилятор при температуре в гараже более +3 градуса
{
// if ((outAbsH + Temp_FAN_Hysteresis < cellarAbsH) && (incomingTemp > temp_gar)){ // сверяем значение и управляем вентилятором
if ((outAbsH + Temp_FAN_Hysteresis < cellarAbsH) and (incomingTemp > temp_gar)){ // сверяем значение и управляем вентилятором
digitalWrite(FANpin, LOW); //Вентилятор вкл, когда абсолютная влажность в погребе выше, + гистерезис вкл/откл вентилятора
FANstatus = true; // реле ВКЛ. - мониторинг - мониторинг //и температура в гараже должна быть ниже чем в погребе
fan_= "ON";
}
else
{
digitalWrite(FANpin, HIGH); // выключаем вентилятор
FANstatus = false; // реле ВЫКЛ. - мониторинг
fan_= "OFF"; }
}//if (temp_gar > Temp_FAN_ON)
// if ((outAbsH > cellarAbsH) || (temp_gar > incomingTemp)) { // абсолютная влажность в гараже выше чем в погребе
if ((outAbsH > cellarAbsH) or (temp_gar > incomingTemp)) { // абсолютная влажность в гараже выше чем в погребе
digitalWrite(FANpin, HIGH); // или температура в гаражее выше чем в погребе;
FANstatus = false; // реле ВЫКЛ. - мониторинг // выключаем вентилятор
fan_= "OFF";
}//end if ((outAbsH > cellarAbsH)
sendLCD(); // выводим показания на дисплей
id_WhatsAPP = 0; // обнуляем кол-во неудачных циклов обновления данных после возобновления приёма данных
// Формируем GET запрос
String httpGet = String(omApiId) + omApiKey;
// Добавляем значения с сенсоров...здесь нужное количество данных для отправки...
httpGet = httpGet + omApiField + String(1) + "=" + String(temp_gar,2);
httpGet = httpGet + omApiField + String(2) + "=" + String(incomingTemp,2);
httpGet = httpGet + omApiField + String(3) + "=" + String(hum_gar,2);
httpGet = httpGet + omApiField + String(4) + "=" + String(incomingHum,2);
httpGet = httpGet + omApiField + String(5) + "=" + String(outAbsH,2);
httpGet = httpGet + omApiField + String(6) + "=" + String(cellarAbsH,2);
httpGet = httpGet + omApiField + String(7) + "=" + String(fan_);
httpGet = httpGet + omApiField + String(8) + "=" + String(FANstatus);
httpGet = httpGet + omApiField + String(9) + "=" + String(hea_);
httpGet = httpGet + omApiField + String(10) + "=" + String(HEATERstatus);
httpGet = httpGet + omApiField + String(11) + "=" + String(Read_id);
httpGet = httpGet + omApiField + String(12) + "=" + String(rssi_dB);
httpGet = httpGet + omApiField + String(13) + "=" + String(rssi_dB_WiFi);
// Отправляем запрос на сервер
omPublish(httpGet);
}//end if ( DataRecv_ERROR == false)
else // если ошибка получения данных DataRecv_ERROR=TRUE
{
// Отправляем сообщение WhatsAPP
if ( id_WhatsAPP == 1 ) { // задержка отправки на один цикл
WhatsAPP_ERROR();
sendMessage("DATA RECEIVER ERROR. FAN/HEATER-OFF");
}//end if
id_WhatsAPP = id_WhatsAPP + 1;
// пропускаем 30 циклов перезагрузка - esp
if ( id_WhatsAPP == 30 ){
RSerial.println("ESP restart");
sendMessage("ESP RESTART");
delay (5000);
restart();
// id_WhatsAPP = 0;
} //end if
} //end else
DataRecv_ERROR = true;
lastEventTime = millis();
}//end if ((millis()
if (RemoteSerial) RSerial.handle();
yield();
} //end loop
// вычисление абсалютной влажности из относительной и температуры.
// https://carnotcycle.wordpress.com/2012/08/04/how-to-convert-relative-humidity-to-absolute-humidity/
float CalcAbsH(float t, float h) {
double tmp = pow(2.718281828,(17.67*t)/(t+243.5));
return (6.112*tmp*h*2.1674)/(273.15+t); // Это граммы воды в одном кубометре воздуха.
// Serial.println(F("Abs Humidity is " absHumid " g/m3"));
}
// мониторинг данных на LCD и Serial подвал - гараж
void sendLCD(){
lcd.clear();
lcd.setCursor(0, 0);lcd.print(temp_gar, 1); lcd.print("/"); lcd.print(hum_gar, 0); lcd.print("="); lcd.print(outAbsH, 0);
lcd.print(" F:"); lcd.print(fan_);
lcd.setCursor(0, 1);lcd.print(incomingTemp, 1); lcd.print("/"); lcd.print(incomingHum, 0); lcd.print("="); lcd.print(cellarAbsH, 0);
lcd.print(" H:"); lcd.print(hea_);
RSerial.print(temp_gar, 1); RSerial.print("/"); RSerial.print(hum_gar, 0); RSerial.print("="); RSerial.print(outAbsH, 0);
RSerial.print(" F:"); RSerial.println(fan_);
RSerial.print(incomingTemp, 1); RSerial.print("/"); RSerial.print(incomingHum, 0); RSerial.print("="); RSerial.print(cellarAbsH, 0);
RSerial.print(" H:"); RSerial.println(hea_);
}
// функция будет выполняться при получении данных от клиента в подвале
void OnDataRecv(uint8_t * mac_addr,uint8_t *incomingData, uint8_t len) //ESP8266
{
// Копирует mac-адрес отправителя в строку
char macStr[18];
RSerial.print("Packet received from: ");
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
RSerial.println(macStr);
memcpy(&incomingReadings, incomingData, sizeof(incomingReadings));
DataRecv_ERROR = false; //данных приняты успешно
board["id"] = incomingReadings.id;
board["temperature"] = incomingReadings.temp;
board["humidity"] = incomingReadings.hum;
board["readingId"] = String(incomingReadings.readingId);
board["tempGAR"] = String(temp_gar);
board["humGAR"] = String(hum_gar);
board["outAbsH"] = String(outAbsH);
board["cellarAbsH"] = String(cellarAbsH);
board["fan1"] = String(fan_);
board["hea1"] = String(hea_);
board["rssi1"] = String(incomingReadings.rssi);
board["rssi2"] = String(rssi_dB_WiFi);
String jsonString = JSON.stringify(board);
events.send(jsonString.c_str(), "new_readings", millis());
}
// https://kotyara12.ru/iot/open-monitoring/
// Функция отправки данных на сервер https://open-monitoring.online
bool omPublish(const String request)
{
WiFiClient client;
bool result = false;
if (client.connect(omApiServer, 80)) { // Отправляем HTTP-запрос
client.printf(omApiPost, request.c_str());
client.printf(omApiHost, omApiServer);
client.println(F("User-Agent: ESP8266 (nothans)/1.0"));
client.println(F("Connection: close"));
client.println();
// Читаем результат (первую строку отправленного заголовка)
RSerial.printf("OpenMon :: send data \"%s\": %s\n", request.c_str(), client.readStringUntil('\n'));
result = true;
}
else {
RSerial.print(F("OpenMon :: Failed connection to "));
RSerial.println(omApiServer);
};
return result;
}
//Отправить сообщение WhatsApp // https://randomnerdtutorials.com/esp8266-nodemcu-send-messages-whatsapp/
void sendMessage(String message){
// URL для запроса с номером телефона, ключом API и сообщением
String url = "http://api.callmebot.com/whatsapp.php?phone=" + phoneNumber + "&apikey=" + apiKey + "&text=" + urlEncode(message);
WiFiClient clientWhatsApp;
HTTPClient http;
http.begin(clientWhatsApp, url);
http.addHeader("Content-Type", "application/x-www-form-urlencoded"); // тип контента
int httpResponseCode = http.POST(url); // код ответа 200, запрос прошел успешно
if (httpResponseCode == 200){
RSerial.println("Message sent successfully");
}
else{
RSerial.println("Error sending the message");
RSerial.print("HTTP response code: ");
RSerial.println(httpResponseCode);
}
http.end(); // освободить ресурсы
}
// Отображаем показания в мониторе порта
void printIncomingReadings(){
RSerial.print("POD Reading ID: "); RSerial.println(Read_id);
RSerial.print("GAR temperature: "); RSerial.print(temp_gar); RSerial.println(" C°");
RSerial.print("GAR humidity: "); RSerial.print(hum_gar); RSerial.println(" C°");
RSerial.print("GAR outAbsH: "); RSerial.print(outAbsH); RSerial.println(" %");
RSerial.print("POD temperature: "); RSerial.print(incomingTemp); RSerial.println(" %");
RSerial.print("POD humidity: "); RSerial.print(incomingHum); RSerial.println(" %");
RSerial.print("POD cellarAbsH: "); RSerial.print(cellarAbsH); RSerial.println(" %");
RSerial.print("WiFi_AP: "); RSerial.print(rssi_dB); RSerial.println(" dB"); RSerial.println(" .............................");
}
// Снимаем значение температуры и влажности
void getReadings(){
delay(1000);
temp_gar = myHumidity.readTemperature();
hum_gar = myHumidity.readHumidity();
}
// инициализация EspNow
void initEspNow() { // Initialize EspNow
if (esp_now_init() != 0) {
RSerial.println("ESP NOW failed to initialize");
return;
}
esp_now_register_recv_cb(OnDataRecv);
}
// определяем уровень WiFi
int32_t getWiFidBm(const char *ssid) {
if (int32_t n = WiFi.scanNetworks()) {
for (uint8_t i=0; i<n; i++) {
RSerial.print(WiFi.SSID(i));
RSerial.printf(" STA_RSSI: %d dBm\n", WiFi.RSSI(i));
// RSerial.println(WiFi.localIP());
return WiFi.RSSI(i);
}
}
return 0;
}
// определяем наличие определённой сети WiFi
String getWiFiSSID(const char *ssid) {
if (int32_t n = WiFi.scanNetworks()) {
for (uint8_t i=0; i<n; i++) {
RSerial.print(WiFi.SSID(i)); RSerial.print(" IP: ");
RSerial.println(WiFi.localIP());
if (WiFi.SSID(i) == ssid){
return WiFi.SSID(i);
}
}
}
return String(".");
}
// устанавливаем соеденение WiFi
void initWiFi() {
//ESP - станция и точка доступа одновременно
WiFi.mode(WIFI_AP_STA);
WiFi.softAP(ssidAP, passAP);
if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
RSerial.println("STA Failed to configure");} // static IP address
// Установить ESP в качестве станции Wi-Fi
WiFi.begin(ssid, password);
/* Если persistent - false,то SSID и пароль будут записаны на flash-память только в том случае,
если новые значения не будут соответствовать тем, что хранятся во flash-памяти. */
WiFi.persistent(false);
// WiFi.setAutoConnect(true);
WiFi.setAutoReconnect(true);//Если параметр autoReconnect выставлен на true, модуль сделает попытку повторного подключения к точке доступа, а если false, то нет.
RSerial.println("._.");
// проверка WiFi
byte a = 10; // выполнится 10 раз
while (a--) {
delay(6000); // нет WiFi через минуту работаем без него
// RSerial.print("_.");
if (WiFi.status() != WL_CONNECTED) {
RSerial.println("Connection failed..");
}
else
{
RSerial.println("Connected to Wi-Fi sucessfully.");
RSerial.println("Setting as a Wi-Fi Station..");
RSerial.print("Station IP Address: "); // Данные Wi-Fi
RSerial.println(WiFi.localIP());
RSerial.print("AP IP Address: ");
RSerial.println(WiFi.softAPIP());
RSerial.print("Wi-Fi Channel: ");
RSerial.println(WiFi.channel());
RSerial.print("ESP Board MAC Address: ");
RSerial.println(WiFi.macAddress());
RSerial.print("ESP Board gatewayIP: ");
RSerial.println(WiFi.gatewayIP());
RSerial.print("ESP Board subnetMask: ");
RSerial.println(WiFi.subnetMask());
RSerial.print("ESP Board dnsIP: ");
RSerial.println(WiFi.dnsIP());
WiFi_status = true;
break;
}
}
}
/* ESP8266 получает IP-адрес
void onWifiConnect(const WiFiEventStationModeGotIP& event) {
RSerial.println("Connected to Wi-Fi sucessfully.");
RSerial.print("IP address: ");
RSerial.println(WiFi.localIP());
}
*/
// ESP8266 не подключен к точке доступа.
void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) {
RSerial.println("Disconnected from Wi-Fi, trying to connect...");
WiFi_status = false;
WiFi.disconnect();
}
// нет получения данных от клиента в подвале
void WhatsAPP_ERROR() {
digitalWrite(FANpin, HIGH); // выключаем вентилятор
FANstatus = false; // реле ВЫКЛ. - мониторинг
fan_= "OFF";
digitalWrite(HEATERpin, HIGH); //выключаем отопитель
HEATERstatus = false; // реле ВЫКЛ. - мониторинг
hea_= "OFF";
lcd.clear();
lcd.setCursor(0, 0);lcd.print("FAN/HEATER-OFF"); // выводим показания на дисплей
lcd.setCursor(0, 1);lcd.print("DATA RECV. ERROR");
RSerial.println("FAN/HEATER-OFF");
RSerial.println("DATA RECV. ERROR");
}
// перезапуск ESP8266
void restart()
{
RSerial.println("Restart ESP...");
ESP.restart();
}
void initOTA()
{
ArduinoOTA.setHostname("Esp8266_Gar");
RSerial.println("Begin OTA handler Esp8266_Gar");
// ArduinoOTA.setPassword("admin");
ArduinoOTA.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH)
type = "sketch";
else // U_SPIFFS
type = "filesystem";
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
RSerial.println("Start updating " + type);
});
ArduinoOTA.onEnd([]() {
RSerial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
RSerial.printf("Progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
RSerial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) RSerial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) RSerial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) RSerial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) RSerial.println("Receive Failed");
else if (error == OTA_END_ERROR) RSerial.println("End Failed");
});
ArduinoOTA.begin();
}
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp8266-esp-now-wi-fi-web-server/
// https://randomnerdtutorials.com/esp8266-nodemcu-send-messages-whatsapp/
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.
*/
html.h
// https://randomnerdtutorials.com/esp8266-esp-now-wi-fi-web-server/
//Веб - страница
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<title>ESP Метеостанция</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset='UTF-8'>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<link rel="icon" href="data:,">
<style>
html {font-family: Arial; display: inline-block; text-align: center;}
p { font-size: 1rem;}
body { margin: 0;}
.topnav { overflow: hidden; background-color: #2f4468; color: white; font-size: 0.6rem; }
.content { padding: 20px; }
.card { background-color: white; box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5); }
.cards { max-width: 800px; margin: 0 auto; display: grid; grid-gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.reading { font-size: 1.4rem; }
.packet { color: #bebebe; }
.card.temperature { color: #fd7e14; }
.card.humidity { color: #1b78e2; }
.card.abc_humidity { color: #059e8a; }
</style>
</head>
<body>
<div class="topnav">
<h1>Метео данные</h1>
</div>
<div class="content">
<div class="cards">
<div class="card temperature">
<h4><i class="fas fa-thermometer-half"></i> Температура гараж</h4><p><span class="reading"><span id="t2"></span> °C</span></p>
</div>
<div class="card humidity">
<h4><i class="fas fa-tint"></i> Влажность гараж</h4><p><span class="reading"><span id="h2"></span> %</span></p>
</div>
<div class="card abc_humidity">
<h4><i class="fas fa-tint"></i> Абс. влажность гараж</h4><p><span class="reading"><span id="ha2"></span> %</span></p>
</div>
<div class="card temperature">
<h4><i class="fas fa-thermometer-half"></i> Температура подвал</h4><p><span class="reading"><span id="t1"></span> °C</span></p>
</div>
<div class="card humidity">
<h4><i class="fas fa-tint"></i> Влажность подвал</h4><p><span class="reading"><span id="h1"></span> %</span></p>
</div>
<div class="card abc_humidity">
<h4><i class="fas fa-tint"></i> Абс. влажность подвал</h4><p><span class="reading"><span id="ha1"></span> %</span></p>
</div>
<div class="card readingId">
<h4><p class="packet">Вентилятор: <span id="fan"></span></p><p class="packet">Отопитель: <span id="hea"></span></p>
</div>
<div class="card readingId">
<h4><p class="packet">Дата: <span id="rt2"></span></p><p class="packet">DataID: <span id="rh2"></span></p>
</div>
<div class="card readingId">
<h4><p class="packet">WiFi-STA: <span id="rssi_"></span> дБм</span></p><p class="packet">WiFi-AP: <span id="rssi"></span> дБм</span></p>
</div>
</div>
</div>
<script>
function getDateTime() {
var currentdate = new Date();
var datetime = currentdate.getDate() + "."
+ (currentdate.getMonth()+1) + "."
+ currentdate.getFullYear() + " - "
+ currentdate.getHours() + ":"
+ currentdate.getMinutes() + ":"
+ currentdate.getSeconds();
return datetime;
}
if (!!window.EventSource) {
var source = new EventSource('/events');
source.addEventListener('open', function(e) { // прослушиватели событий по умолчанию
console.log("Events Connected");
}, false);
source.addEventListener('error', function(e) {
if (e.target.readyState != EventSource.OPEN) {
console.log("Events Disconnected");
}
}, false);
source.addEventListener('message', function(e) {
console.log("message", e.data);
}, false);
source.addEventListener('new_readings', function(e) { //прослушиватель событий
console.log("new_readings", e.data);
var obj = JSON.parse(e.data);
document.getElementById("t1").innerHTML = obj.temperature.toFixed(2);
document.getElementById("h1").innerHTML = obj.humidity.toFixed(2);
document.getElementById("t2").innerHTML = obj.tempGAR;
document.getElementById("h2").innerHTML = obj.humGAR;
document.getElementById("ha1").innerHTML = obj.cellarAbsH;
document.getElementById("ha2").innerHTML = obj.outAbsH;
document.getElementById("rh2").innerHTML = obj.readingId;
document.getElementById("rt2").innerHTML = getDateTime();
document.getElementById("fan").innerHTML = obj.fan1;
document.getElementById("hea").innerHTML = obj.hea1;
document.getElementById("rssi").innerHTML = obj.rssi1;
document.getElementById("rssi_").innerHTML = obj.rssi2;
}, false);
}
</script>
</body>
</html>)rawliteral";
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp8266-esp-now-wi-fi-web-server/
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.
*/
settings.h
Нет возможности дальше опубликовать код из-за ограничения сайта для новичков, попытаюсь прикрепить весь проект архивом.
Подскажите как прирепить сюда архив?
Пока только так, больше вариантов как добавить на сайт не нашёл.