///////////////////////////////////////////////// // // 2026-06-12 v.009 // ///////////////////////////////////////////////// #include #include #include #include #include #include #include #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); }