summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorvlapa <vlapa@ya.ru>2026-06-13 18:38:24 +0300
committervlapa <vlapa@ya.ru>2026-06-13 18:38:24 +0300
commit0258932b0c21f28385c2ab3acecbf4eaaa00b399 (patch)
treea5dd89d61ce135a75d2bd992c56551a6a48d5a1d /src
Firstmain
Diffstat (limited to 'src')
-rw-r--r--src/main.cpp588
1 files changed, 588 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..9227cb7
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,588 @@
+//********************************************************************
+//*
+//* Tablo na WS2812b + mqtt + bme280 (2)
+//* 2021.02.01 - 2025.03.01
+//*
+//* A - градус
+//* В - минус
+//* С - двоеточие
+//* D - пусто
+//* E - точка
+//* F - p
+//* G - h
+//********************************************************************
+#include <Arduino.h>
+#include <WiFi.h>
+#include <HTTPUpdateServer.h>
+#include <NTPClient.h>
+#include <WiFiUdp.h>
+#include <PubSubClient.h>
+
+#include "tablo_ws2812.h"
+// #include <string.h>
+
+#include <WiFiClient.h>
+#include <WebServer.h>
+#include <ESPmDNS.h>
+#include <Update.h>
+const char *host = "esp32";
+
+const uint8_t TIME_DAY = 8;
+const uint8_t TIME_NIGHT = 18;
+const uint8_t BRIGHT_DAY = 5;
+const uint8_t BRIGHT_NIGHT = 1;
+
+// const char *ssid = "link";
+const char *ssid = "MikroTik-2";
+const char *pass = "dkfgf#*12091997";
+const char *ntp_server = "ntp3.vniiftri.ru";
+const char *mqtt_server = "89.110.92.137";
+const uint16_t mqtt_port = 1883;
+const char *mqtt_user = "mqtt";
+const char *mqtt_pass = "qwe1243";
+
+const uint32_t utcOffsetInSeconds = 10800;
+const uint32_t utcPeriodMseconds = 86400000; // 86400000-р/сут; 604800000-р/нед
+
+WiFiUDP ntpUDP;
+NTPClient timeClient(ntpUDP, ntp_server, utcOffsetInSeconds, utcPeriodMseconds);
+
+// const char *mqtt_client = "Tablo_Home_345";
+const char *mqtt_client = "Tablo_Villa-002";
+// const char *mqtt_client2 = "Home_bme280_villa";
+const char *mqtt_client2 = "Villa_bme280_base";
+
+const char *inTopic = "/t;p;h;v;;";
+// const char *inTopic_room = "/t;p;h;";
+// const char *inTopic_balkon = "/t;";
+
+String temp, pres, hum, vcc;
+
+// String outTemp_room = "00.00A";
+// String outTemp_balkon = "00.00A";
+// String outPres_room = "000";
+// String outHum_room = "00";
+// String outHum_balkon = "00";
+// String outVolt_room = "00";
+// String outVolt_balkon = "00";
+
+WiFiClient espClient;
+PubSubClient client(espClient);
+
+uint32_t timeUpdateH = 02; // время обновления NTP
+uint32_t timeUpdateM = 05; // время обновления NTP
+String z = ""; // строка данных для отображения
+
+uint32_t colorTime = 16766720; // цвет часы (желтый)
+uint32_t colorTemp = 16711935; // цвет температура (красный)
+uint32_t colorTemp2 = 65280; // цвет внешняя температура (зеленый)
+uint32_t colorTempOut = 9127187; // цвет температура2 (коричневый)
+uint32_t colorPress = 9830400; // цвет давление (розовый)
+uint32_t colorWiFi = 16728935; // цвет WiFi (томато)
+uint32_t colorHum = 52945; // цвет влажность (бирюзовый)
+uint32_t colorHumOut = 255; // цвет влажность2 (синий// Время отображения каждого показания:
+// 0-время, 1-темп, 2-давл, 3-влажн, 4-темп2, 5-влажн2
+uint16_t visData[] = {5, 2, 2, 2, 2, 2, 2};
+uint8_t count_data = 4; // сколько еще отображать показаний
+uint16_t strOld = 0;
+uint8_t count = 0;
+
+uint32_t timeReadOld = 0;
+uint32_t color = 0;
+
+bool flagSec = true;
+bool flagTemp = false;
+bool flagTemp2 = false;
+bool flagTempOut = false;
+bool flagPress = false;
+bool flagHum = false;
+bool flagHumOut = false;
+bool flagVis = true;
+
+uint32_t timeOld = 0;
+uint8_t brightVis = BRIGHT_NIGHT;
+
+WebServer server(80);
+ESP8266HTTPUpdateServer httpUpdater;
+
+//-----------------------------------
+// Login page
+const char *loginIndex =
+ "<form name='loginForm'>"
+ "<table width='20%' bgcolor='A09F9F' align='center'>"
+ "<tr>"
+ "<td colspan=2>"
+ "<center><font size=4><b>ESP32 Login Page</b></font></center>"
+ "<br>"
+ "</td>"
+ "<br>"
+ "<br>"
+ "</tr>"
+ "<td>Username:</td>"
+ "<td><input type='text' size=25 name='userid'><br></td>"
+ "</tr>"
+ "<br>"
+ "<br>"
+ "<tr>"
+ "<td>Password:</td>"
+ "<td><input type='Password' size=25 name='pwd'><br></td>"
+ "<br>"
+ "<br>"
+ "</tr>"
+ "<tr>"
+ "<td><input type='submit' onclick='check(this.form)' value='Login'></td>"
+ "</tr>"
+ "</table>"
+ "</form>"
+ "<script>"
+ "function check(form)"
+ "{"
+ "if(form.userid.value=='admin' && form.pwd.value=='admin')"
+ "{"
+ "window.open('/serverIndex')"
+ "}"
+ "else"
+ "{"
+ " alert('Error Password or Username')/*displays error message*/"
+ "}"
+ "}"
+ "</script>";
+
+// Server Index Page
+const char *serverIndex =
+ "<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>"
+ "<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>"
+ "<input type='file' name='update'>"
+ "<input type='submit' value='Update'>"
+ "</form>"
+ "<div id='prg'>progress: 0%</div>"
+ "<script>"
+ "$('form').submit(function(e){"
+ "e.preventDefault();"
+ "var form = $('#upload_form')[0];"
+ "var data = new FormData(form);"
+ " $.ajax({"
+ "url: '/update',"
+ "type: 'POST',"
+ "data: data,"
+ "contentType: false,"
+ "processData:false,"
+ "xhr: function() {"
+ "var xhr = new window.XMLHttpRequest();"
+ "xhr.upload.addEventListener('progress', function(evt) {"
+ "if (evt.lengthComputable) {"
+ "var per = evt.loaded / evt.total;"
+ "$('#prg').html('progress: ' + Math.round(per*100) + '%');"
+ "}"
+ "}, false);"
+ "return xhr;"
+ "},"
+ "success:function(d, s) {"
+ "console.log('success!')"
+ "},"
+ "error: function (a, b, c) {"
+ "}"
+ "});"
+ "});"
+ "</script>";
+
+//-----------------------------------
+inline bool mqtt_subscribe(PubSubClient &client, const String &topic)
+{
+ Serial.print("Subscribing to: ");
+ Serial.println(topic);
+ return client.subscribe(topic.c_str());
+}
+
+//-----------------------------------
+inline bool mqtt_publish(PubSubClient &client, const String &topic, const String &value)
+{
+ Serial.print("Publishing topic ");
+ Serial.print(topic);
+ Serial.print(" = ");
+ Serial.println(value);
+ return client.publish(topic.c_str(), value.c_str());
+}
+
+//-----------------------------------
+void reconnect()
+{
+ // visibleWork("DDDDD", colorWiFi, BRIGHT_DAY);
+ // strip.show();
+ uint8_t countMqtt = 20;
+ while (!client.connect(mqtt_client, mqtt_user, mqtt_pass))
+ {
+ strip.show();
+ if (countMqtt--)
+ {
+ visibleWork("0B0B0", colorWiFi, BRIGHT_DAY);
+ delay(250);
+ visibleWork("B0B0B", colorWiFi, BRIGHT_DAY);
+ delay(250);
+ }
+ else
+ {
+ ESP.restart();
+ }
+ }
+
+ String topic('/');
+ topic += mqtt_client2;
+ topic += inTopic;
+ mqtt_subscribe(client, topic);
+
+ // topic = '/';
+ // topic += mqtt_client3;
+ // topic += inTopic_balkon;
+ // mqtt_subscribe(client, topic);
+
+ Serial.println("MQTT - Ok!\n");
+}
+
+//********************************************************************
+// подключение к WiFi
+void setupWiFi()
+{
+ digitalWrite(LED_BUILTIN, LOW);
+ Serial.println("\n\nSetup WiFi: ");
+ visibleWork("ABABA", colorWiFi, BRIGHT_DAY);
+ strip.show();
+
+ WiFi.begin(ssid, pass);
+ uint8_t countWiFi = 20;
+ while (WiFi.status() != WL_CONNECTED)
+ {
+ delay(500);
+ Serial.print('.');
+ if (!countWiFi--)
+ ESP.restart();
+ }
+ digitalWrite(LED_BUILTIN, HIGH);
+
+ //-----------------------------------
+ // индикация IP
+ String l = WiFi.localIP().toString();
+ l = l.substring(l.lastIndexOf('.') + 1, l.length());
+
+ (l.toInt() < 100) ? l = "DDE" + l : l = "DE" + l;
+ visibleWork(l, colorWiFi, BRIGHT_DAY);
+
+ strip.show();
+ Serial.print("\nWiFi connected !\n");
+ Serial.println(WiFi.localIP());
+ delay(2000);
+
+ //-----------------------------------
+ // индикация силы сигнала
+ int16_t RSSI_MAX = -50;
+ int16_t RSSI_MIN = -100;
+ int16_t dBm = WiFi.RSSI();
+ Serial.print("RSSI dBm = ");
+ Serial.println(dBm);
+ l = "DDE";
+ (dBm <= RSSI_MIN) ? l += 0 : (dBm >= RSSI_MAX) ? l += 100
+ : l += 2 * (dBm + 100);
+ Serial.print("RSSI % = ");
+ Serial.println(l);
+ Serial.println("\n");
+
+ visibleWork(l, colorWiFi, BRIGHT_DAY);
+ strip.show();
+ delay(2000);
+
+ Serial.println();
+
+ z = "BBBBB";
+ visibleWork(z, colorTemp, BRIGHT_DAY);
+ strip.show();
+
+ while (!timeClient.update())
+ {
+ delay(500);
+ Serial.print('.');
+ }
+ flagVis = true;
+ count = 0;
+}
+
+//********************************************************************
+// MQTT
+void mqtt_callback(char *topic, byte *payload, unsigned int length)
+{
+ //------------------------
+ // Просто печатаем то, что пришло:
+ // Serial.print(topic);
+ // Serial.print(" \t");
+ // for (uint8_t i = 0; i < length; ++i)
+ // {
+ // Serial.print((char)payload[i]);
+ // }
+ // Serial.println("---");
+ //------------------------
+ //
+ if (!strncmp(topic + 1, mqtt_client2, strlen(mqtt_client2)))
+ {
+ char *topicBody = topic + strlen(mqtt_client2) + 1;
+ if (!strncmp(topicBody, inTopic, strlen(inTopic)))
+ {
+ String data_room = "";
+ Serial.print(topicBody);
+ Serial.print(" - ");
+ for (uint8_t i = 0; i < length; i++)
+ data_room += (char)payload[i];
+ Serial.println(data_room);
+ temp = data_room.substring(0, data_room.indexOf(";"));
+ data_room = data_room.substring(data_room.indexOf(";") + 1, data_room.length());
+ pres = data_room.substring(0, data_room.indexOf(";"));
+ data_room = data_room.substring(data_room.indexOf(";") + 1, data_room.length());
+ hum = data_room.substring(0, data_room.indexOf(";"));
+ }
+ }
+ // else if (!strncmp(topic + 1, mqtt_client3, strlen(mqtt_client3)))
+ // {
+ // char *topicBody = topic + strlen(mqtt_client3) + 1;
+ // if (!strncmp(topicBody, inTopic_balkon, strlen(inTopic_balkon)))
+ // {
+ // String data_balkon = "";
+ // Serial.print(topicBody);
+ // Serial.print(" - ");
+ // for (uint8_t i = 0; i < length; i++)
+ // data_balkon += (char)payload[i];
+ // Serial.println(data_balkon);
+ // temp_out = data_balkon.substring(0, data_balkon.indexOf(";"));
+ // }
+ // }
+
+ //------------------------
+}
+
+//********************************************************************
+// пересчет millis()
+void TimeMillis()
+{
+ color = colorTime;
+
+ if (timeClient.getHours() < 10)
+ z += "D";
+
+ z += timeClient.getHours(); // часы
+ (flagSec) ? z += "C" : z += "D";
+
+ if (timeClient.getMinutes() < 10)
+ z += "0";
+
+ z += timeClient.getMinutes(); // минуты
+
+ if ((timeClient.getHours() >= TIME_DAY) && (timeClient.getHours() < TIME_NIGHT))
+ {
+ brightVis = BRIGHT_DAY;
+ }
+ else
+ {
+ brightVis = BRIGHT_NIGHT;
+ }
+}
+
+//********************************************************************
+// BME280
+void Temp()
+{
+ if (temp.charAt(0) == '-')
+ {
+ if (temp.indexOf('.') == 2)
+ {
+ z = "B" + temp.substring(1, temp.indexOf('.'));
+ z += 'E' + temp.substring(3, 4);
+ }
+ else
+ {
+ z = "DB" + temp.substring(1, temp.indexOf('.'));
+ }
+ }
+ else
+ {
+ if (temp.indexOf('.') == 2)
+ {
+ z = temp.substring(0, temp.indexOf('.'));
+ z += 'E' + temp.substring(3, 4);
+ }
+ else
+ {
+ z = 'D' + temp.substring(0, temp.indexOf('.'));
+ z += 'E' + temp.substring(2, 3);
+ }
+ }
+ temp.substring(0, 1);
+
+ z += 'A';
+ color = colorTemp;
+ flagTemp = true;
+}
+
+void Press()
+{
+ z += "DD" + pres.substring(0, 3);
+ color = colorPress;
+ flagPress = true;
+}
+
+void Hum()
+{
+ (hum.length() > 2) ? z = "DD" : z = "DDD";
+ z += hum.substring(0, 2);
+ color = colorHum;
+ flagHum = true;
+}
+
+//********************************************************************
+// запись значений датчиков в память
+// void dataWrite(uint8_t n, String str)
+// {
+// data[n].num = str.substring(0, 1).toInt();
+// if (str.indexOf('%') > 0)
+// data[n].hum = str.substring(str.indexOf('%') + 1, str.indexOf('%') + 3).toInt();
+// if (str.indexOf('*') > 0)
+// data[n].temp = str.substring(str.indexOf('*') + 1, str.indexOf('*' + 5)).toFloat();
+// if (str.indexOf('$') > 0)
+// data[n].press = str.substring(str.indexOf('$') + 1, str.indexOf('$') + 4).toInt();
+// if (str.indexOf('^') > 0)
+// data[n].voltage = str.substring(str.indexOf('^') + 1, str.indexOf('^') + 4).toInt();
+// }
+//********************************************************************
+// void parserBuf(String tmp)
+// {
+// if (tmp.substring(0, 2).toInt() == sensorNum_1)
+// {
+// dataWrite(0, tmp);
+// }
+// // else if (tmp.substring(0, 2).toInt() == sensorNum_2)
+// // {
+// // dataWrite(1, tmp);
+// // }
+// }
+//********************************************************************
+// визуальные эффекты
+// void show_1()
+// {
+// strip.clear();
+// for (uint8_t i = 0; i < PIXEL_COUNT / 2; ++i)
+// {
+// strip.setPixelColor(i, strip.Color(random(1, 255), random(1, 255), random(1, 255)));
+// strip.setPixelColor(PIXEL_COUNT - i - 1, strip.Color(random(1, 255), random(1, 255), random(1, 255)));
+// strip.show();
+// delay(5);
+// }
+// delay(500);
+// for (uint8_t i = 0; i < PIXEL_COUNT / 2; ++i)
+// {
+// strip.setPixelColor(i, 0, 0, 0);
+// strip.setPixelColor(PIXEL_COUNT - i - 1, 0, 0, 0);
+// strip.show();
+// delay(5);
+// }
+// delay(500);
+// z = "DDDDD";
+// }
+
+//********************************************************************
+void setup()
+{
+ Serial.begin(115200);
+ pinMode(LED_BUILTIN, OUTPUT);
+ digitalWrite(LED_BUILTIN, HIGH);
+
+ strip.begin();
+ z = "AAAAA";
+ strip.show();
+
+ client.setServer(mqtt_server, mqtt_port);
+ client.setCallback(mqtt_callback);
+
+ setupWiFi();
+
+ timeClient.begin();
+ server.begin();
+ httpUpdater.setup(&server);
+
+ // visible_effect();
+
+ timeOld = millis();
+}
+
+//********************************************************************
+void loop()
+{
+ // visible_effect();
+
+ if (WiFi.status() != WL_CONNECTED)
+ {
+ setupWiFi();
+ }
+
+ if (!client.connected())
+ {
+ reconnect();
+ }
+
+ if (flagVis)
+ {
+ z = "";
+ switch (count)
+ {
+ case 0:
+ {
+ TimeMillis();
+ flagTemp = false;
+ flagPress = false;
+ flagHum = false;
+ flagTempOut = false;
+ flagHumOut = false;
+ break;
+ }
+ case 1:
+ {
+ if (flagTemp == false)
+ Temp();
+ break;
+ }
+ case 2:
+ {
+ if (flagPress == false)
+ Press();
+ break;
+ }
+ case 3:
+ {
+ if (flagHum == false)
+ Hum();
+ break;
+ }
+ }
+ flagVis = false;
+ visibleWork(z, color, brightVis);
+ // timeReadOld = millis();
+ }
+
+ // Отображение секундного тире
+ if (millis() - timeReadOld >= 500 && (!count)) // || count == 1))
+ {
+ flagSec = !flagSec;
+ timeReadOld = millis();
+
+ flagVis = true;
+ }
+
+ // Счетчик отображаемых данных
+ if (millis() - timeOld >= (visData[count] * 1000))
+ {
+ (count >= count_data) ? count = 0 : count++;
+ flagVis = true;
+ timeOld = millis();
+ }
+
+ server.handleClient();
+ client.loop();
+ delay(1);
+}
+
+//******************************************************************** \ No newline at end of file