summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.cpp453
1 files changed, 453 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..51cd991
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,453 @@
+/////////////////////////////////////////////////
+//
+// 2026-06-12 v.009
+//
+/////////////////////////////////////////////////
+#include <Arduino.h>
+#include <ESP8266WiFi.h>
+#include <ESP8266HTTPUpdateServer.h>
+#include <NTPClient.h>
+#include <WiFiUdp.h>
+#include <ESP8266HTTPClient.h>
+#include <Adafruit_NeoPixel.h>
+
+#include "tablo_ws2812.h"
+
+const uint8_t TIME_DAY = 8;
+const uint8_t TIME_NIGHT = 18;
+const uint8_t BRIGHT_DAY = 4;
+const uint8_t BRIGHT_NIGHT = 1;
+
+const char *ssid = "link";
+const char *pass = "dkfgf#*12091997";
+const char *ntp_server = "ntp3.vniiftri.ru";
+const char *host = "89.110.92.137";
+const uint16_t port = 8000;
+const char *address_page = "/";
+
+const uint32_t utcOffsetInSeconds = 10800;
+const uint32_t utcPeriodMseconds = 86400000; // 86400000-р/сут; 604800000-р/нед
+
+WiFiUDP ntpUDP;
+NTPClient timeClient(ntpUDP, ntp_server, utcOffsetInSeconds, utcPeriodMseconds);
+
+const char *tablo_client = "Tablo_Home_mini";
+const char *sensor_1 = "Home_bme280_home_in";
+const char *sensor_2 = "Villa_bme280_base";
+
+String sensorKeys;
+
+WiFiClient espClient;
+HTTPClient http;
+
+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 (синий)
+
+bool flagVis = true;
+bool flagSec = true;
+uint8_t brightVis = 0;
+uint32_t timeReadOld = 0;
+uint8_t visData[] = {5, 2, 2, 2, 2};
+uint8_t displayMode = 0;
+unsigned long lastModeSwitch = 0;
+
+unsigned long lastHTTPRequest = 0;
+const unsigned long HTTP_UPDATE_INTERVAL = 60000; // Обновляем раз в минуту
+
+struct
+{
+ float temp_in = 0.0;
+ uint16_t pres = 0;
+ uint8_t hum = 0;
+ float temp_out = 0.0;
+} dataSensors;
+
+const uint8_t NUMBER_OF_ATTEMPTS = 20;
+// uint8_t count = 0;
+
+ESP8266WebServer server(80);
+ESP8266HTTPUpdateServer httpUpdater;
+
+//===================================================
+// подключение к WiFi
+bool setupWiFi()
+{
+ z = "ABABA";
+ visibleWork(z, colorWiFi, BRIGHT_DAY);
+ strip.show();
+
+ digitalWrite(LED_BUILTIN, LOW);
+ Serial.println("\n\nSetup WiFi: ");
+
+ WiFi.begin(ssid, pass);
+ uint8_t count = NUMBER_OF_ATTEMPTS;
+ while (WiFi.status() != WL_CONNECTED)
+ {
+ Serial.print(count);
+ Serial.print('>');
+ if (!count--)
+ return false;
+ delay(500);
+ }
+ digitalWrite(LED_BUILTIN, HIGH);
+
+ //-----------------------------------
+ // индикация IP
+ z = "DDDDD";
+ visibleWork(z, colorWiFi, BRIGHT_DAY);
+ strip.show();
+ 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 !\nIP: ");
+ Serial.println(WiFi.localIP());
+ delay(2000);
+ visibleWork("DDDDD", colorWiFi, BRIGHT_DAY);
+ strip.show();
+
+ //-----------------------------------
+ // индикация силы сигнала
+ int8_t RSSI_MAX = -50;
+ int8_t RSSI_MIN = -100;
+ int8_t dBm = WiFi.RSSI();
+ Serial.print("RSSI dBm = ");
+ Serial.println(dBm);
+ l = "";
+ (dBm <= RSSI_MIN) ? l += 0 : (dBm >= RSSI_MAX) ? l += 100
+ : l += 2 * (dBm + 100);
+ Serial.print("RSSI % = ");
+ Serial.println(l);
+ Serial.println();
+ (l.toInt() < 100) ? l = "DDE" + l : l = "DE" + l;
+
+ visibleWork(l, colorWiFi, BRIGHT_DAY);
+ strip.show();
+ delay(2000);
+ visibleWork("DDDDD", colorWiFi, BRIGHT_DAY);
+ strip.show();
+
+ return true;
+}
+
+//===================================================
+// синхронизация с NTP:
+bool setupNTP()
+{
+ Serial.println("\nСинхронизируем время: ");
+ uint8_t count = NUMBER_OF_ATTEMPTS;
+ while (!timeClient.update())
+ {
+ Serial.print(count);
+ Serial.print('.');
+ if (!count--)
+ return false;
+ delay(500);
+ }
+ Serial.println();
+ Serial.println(timeClient.getFormattedTime());
+ Serial.println();
+
+ return true;
+}
+
+//===================================================
+// Запрос POST на сервер:
+String http_response()
+{
+ String payload;
+
+ String url = "http://" + String(host) + ":" + String(port) + address_page;
+ Serial.println("Sending POST to: " + url);
+ Serial.println("Data: " + sensorKeys);
+
+ http.begin(espClient, url);
+ http.addHeader("Content-Type", "text/plain");
+ // http.setTimeout(10000);
+
+ // Отправляем POST с нашими ключами
+ int httpCode = http.POST(sensorKeys);
+
+ // Анализируем ответ
+ if (httpCode > 0)
+ {
+ Serial.printf("Response code: %d\n", httpCode);
+
+ if (httpCode == HTTP_CODE_OK)
+ {
+ payload = http.getString();
+ Serial.println("Server response: \n" + payload);
+ }
+ }
+ else
+ {
+ Serial.printf("POST failed, error: %s\n", http.errorToString(httpCode).c_str());
+ }
+
+ http.end();
+
+ return payload;
+}
+//===================================================
+// Парсим ответ сервера:
+void parse_data_http(String data)
+{
+ // Serial.println(data);
+ dataSensors.temp_in = data.substring(1, data.indexOf(";")).toFloat();
+ data = data.substring(data.indexOf(";") + 1, data.length());
+ // Serial.println(data);
+ dataSensors.pres = data.substring(0, data.indexOf(";")).toInt();
+ data = data.substring(data.indexOf(";") + 1, data.length());
+ // Serial.println(data);
+ dataSensors.hum = data.substring(0, data.indexOf(";")).toInt();
+ data = data.substring(data.indexOf(";") + 7, data.length());
+ // Serial.println(data);
+ dataSensors.temp_out = data.substring(0, data.indexOf(";")).toFloat();
+
+ // Serial.print(dataSensors.temp_in);
+ // Serial.print(" - ");
+ // Serial.print(dataSensors.pres);
+ // Serial.print(" - ");
+ // Serial.print(dataSensors.hum);
+ // Serial.print(" - ");
+ // Serial.print(dataSensors.temp_out);
+ // Serial.println();
+ // Serial.println(sizeof(dataSensors));
+}
+
+//===================================================
+// Форматируем время:
+void TimeMillis()
+{
+ z = "";
+
+ if (timeClient.getHours() < 10)
+ z += "D";
+ z += timeClient.getHours();
+
+ (flagSec) ? z += "B" : 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;
+ }
+}
+
+//===================================================
+// Форматируем температуру:
+void fTemp(float t)
+{
+ if (t < 0)
+ {
+ if (abs(t) < 10)
+ {
+ z = "B";
+ z += abs((int)t);
+ z += "E";
+ z += abs((int)((t - (int)t) * 10));
+ z += "A";
+ }
+ else
+ {
+ z = "DB";
+ z += abs((int)t);
+ z += "A";
+ }
+ }
+ else
+ {
+ if (t < 10)
+ {
+ z = "D";
+ z += (int)t;
+ z += "E";
+ z += (int)((t - (int)t) * 10);
+ z += "A";
+ }
+ else
+ {
+ z = "DD";
+ z += (int)t;
+ z += "A";
+ }
+ }
+}
+
+// Форматируем давление, влажность:
+void fOther(int o)
+{
+ if (o < 10)
+ {
+ z = "DDDD";
+ }
+ else if (o < 100)
+ {
+ z = "DDD";
+ }
+ else
+ {
+ z = "DD";
+ }
+ z += o;
+}
+
+//===================================================
+// Обновляем данные отображения:
+void updateDisplay()
+{
+ if (flagVis)
+ {
+ String response;
+ switch (displayMode)
+ {
+ case 0:
+ TimeMillis();
+ visibleWork(z, colorTime, brightVis);
+ strip.show();
+ flagVis = false;
+ break;
+ case 1:
+ fTemp(dataSensors.temp_in);
+ visibleWork(z, colorTemp, brightVis);
+ strip.show();
+ flagVis = false;
+
+ // Обновляем данные с сервера не чаще чем раз в минуту
+ if (millis() - lastHTTPRequest >= HTTP_UPDATE_INTERVAL)
+ {
+ String response = http_response();
+ if (response.length() > 0)
+ {
+ parse_data_http(response);
+ lastHTTPRequest = millis();
+ }
+ else
+ {
+ Serial.println("Warning: Using cached sensor data");
+ }
+ }
+ break;
+ case 2:
+ fOther(dataSensors.pres);
+ visibleWork(z, colorPress, brightVis);
+ strip.show();
+ flagVis = false;
+ break;
+ case 3:
+ fOther(dataSensors.hum);
+ visibleWork(z, colorHum, brightVis);
+ strip.show();
+ flagVis = false;
+ break;
+ case 4:
+ fTemp(dataSensors.temp_out);
+ visibleWork(z, colorTempOut, brightVis);
+ strip.show();
+ flagVis = false;
+ break;
+ default:
+ break;
+ }
+ }
+}
+//===================================================
+void setup()
+{
+ Serial.begin(115200);
+ ESP.wdtEnable(5000); // Сторожевой таймер на 5 секунд
+ pinMode(LED_BUILTIN, OUTPUT);
+ digitalWrite(LED_BUILTIN, HIGH);
+
+ strip.begin();
+ z = "DDDDD";
+ visibleWork(z, colorWiFi, BRIGHT_DAY);
+ strip.show();
+
+ if (!setupWiFi())
+ ESP.restart();
+
+ timeClient.begin();
+ if (!setupNTP())
+ ESP.restart();
+
+ sensorKeys = sensor_1;
+ sensorKeys += ",";
+ sensorKeys += sensor_2;
+
+ parse_data_http(http_response());
+
+ server.begin();
+ httpUpdater.setup(&server);
+
+ lastModeSwitch = millis();
+}
+
+//===================================================
+void loop()
+{
+ if (WiFi.status() != WL_CONNECTED)
+ if (!setupWiFi())
+ ESP.restart();
+
+ // Синхронизация NTP каждые 6 часов
+ static unsigned long lastNTPSync = 0;
+ if (millis() - lastNTPSync > 21600000)
+ {
+ if (timeClient.update())
+ {
+ lastNTPSync = millis();
+ }
+ }
+
+ if (flagVis)
+ updateDisplay();
+
+ // Отображение секундного тире
+ if (!displayMode)
+ {
+ if (millis() - timeReadOld >= 500)
+ {
+ flagSec = !flagSec;
+ timeReadOld = millis();
+ flagVis = true;
+ }
+ }
+
+ // Логика переключения между разными показаниями
+ unsigned long current = millis();
+ if (current < lastModeSwitch)
+ { // Переполнение произошло
+ lastModeSwitch = current;
+ }
+
+ if (current - lastModeSwitch >= visData[displayMode] * 1000)
+ {
+ (displayMode < sizeof(visData) - 1) ? displayMode++ : displayMode = 0;
+ lastModeSwitch = current;
+ flagVis = true;
+ timeReadOld = current;
+ }
+
+ server.handleClient();
+ delay(10);
+} \ No newline at end of file