#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <TM1637Display.h>

// Настройки Wi-Fi
const char* ssid = "Beeline_2G_A7F18A";
const char* password = "iD2tAXJN3e";

// Настройки статического IP-адреса
IPAddress local_IP(192, 168, 1, 184); // Задайте желаемый IP-адрес
IPAddress gateway(192, 168, 1, 1);    // IP-адрес вашего маршрутизатора
IPAddress subnet(255, 255, 255, 0);   // Маска подсети
IPAddress primaryDNS(8, 8, 8, 8);     // Предпочитаемый DNS-сервер (опционально)
IPAddress secondaryDNS(8, 8, 4, 4);   // Альтернативный DNS-сервер (опционально)

// Настройки дисплея TM1637
#define CLK 14 // GPIO14 (D5 на NodeMCU)
#define DIO 12 // GPIO12 (D6 на NodeMCU)

TM1637Display display(CLK, DIO);

// Настройки NTP клиента
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 0, 60000);

// Настройки веб-сервера
ESP8266WebServer server(80);

// Переменные для будильника
int alarmHour = -1;
int alarmMinute = -1;
bool alarmSet = false;

// Переменные для мигания дисплея при будильнике
bool alarmActive = false;
unsigned long alarmStartTime = 0;
unsigned long alarmDuration = 30000;
unsigned long blinkInterval = 500;
unsigned long lastBlinkTime = 0;
bool displayOn = true;

// Учетные данные для аутентификации
const char* www_username = "admin";
const char* www_password = "35539900";

// Добавьте прототипы функций здесь
void handleRoot();            // Прототип функции handleRoot()
void handleGetTime();         // Прототип функции handleGetTime()
void handleSetTime();         // Прототип функции handleSetTime()
void handleSetAlarm();        // Прототип функции handleSetAlarm()
void triggerAlarm();          // Прототип функции triggerAlarm()

void setup() {
  Serial.begin(115200);

  // Настройка статического IP
  if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
    Serial.println("Ошибка установки статического IP");
  }

  // Подключение к Wi-Fi
  WiFi.begin(ssid, password);
  Serial.print("Подключение к Wi-Fi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" Подключено!");
  Serial.print("IP адрес: ");
  Serial.println(WiFi.localIP());

  // Инициализация дисплея
  display.setBrightness(0x0f);

  // Запуск NTP клиента
  timeClient.begin();

  // Настройка веб-сервера с аутентификацией
  server.on("/", HTTP_GET, handleRootWithAuth);
  server.on("/getTime", HTTP_GET, handleGetTimeWithAuth);
  server.on("/setTime", HTTP_POST, handleSetTimeWithAuth);
  server.on("/setAlarm", HTTP_POST, handleSetAlarmWithAuth);

  server.begin();
  Serial.println("Веб-сервер запущен");
}

void loop() {
  timeClient.update();
  server.handleClient();

  // Получение текущего времени
  int currentHour = timeClient.getHours();
  int currentMinute = timeClient.getMinutes();
  int currentSecond = timeClient.getSeconds();

  // Проверка будильника
  if (alarmSet && currentHour == alarmHour && currentMinute == alarmMinute) {
    triggerAlarm();
  }

  // Определение состояния двоеточия (мигает каждую секунду)
  uint8_t dots = (currentSecond % 2) ? 0x00 : 0x80;

  // Обработка мигания дисплея при активном будильнике
  if (alarmActive) {
    unsigned long currentTimeMillis = millis();

    if (currentTimeMillis - alarmStartTime >= alarmDuration) {
      // Останавливаем будильник
      alarmActive = false;
      displayOn = true;
    } else {
      // Управляем миганием дисплея
      if (currentTimeMillis - lastBlinkTime >= blinkInterval) {
        lastBlinkTime = currentTimeMillis;
        displayOn = !displayOn;
      }
    }

    if (displayOn) {
      int displayTime = currentHour * 100 + currentMinute;
      display.showNumberDecEx(displayTime, dots, true);
    } else {
      display.clear();
    }

  } else {
    // Если будильник не активен
    int displayTime = currentHour * 100 + currentMinute;
    display.showNumberDecEx(displayTime, dots, true);
  }

  delay(50);
}

// Функции-обёртки для аутентификации
void handleRootWithAuth() {
  if (!server.authenticate(www_username, www_password)) {
    return server.requestAuthentication();
  }
  handleRoot();
}

void handleGetTimeWithAuth() {
  if (!server.authenticate(www_username, www_password)) {
    return server.requestAuthentication();
  }
  handleGetTime();
}

void handleSetTimeWithAuth() {
  if (!server.authenticate(www_username, www_password)) {
    return server.requestAuthentication();
  }
  handleSetTime();
}

void handleSetAlarmWithAuth() {
  if (!server.authenticate(www_username, www_password)) {
    return server.requestAuthentication();
  }
  handleSetAlarm();
}

// Определения функций обработчиков
void handleRoot() {
  String currentTime = timeClient.getFormattedTime();

  String html = "<html><head>";
  html += "<title>Онлайн-часы</title>";
  html += "<meta charset='UTF-8'>";
  html += "<style>";
  html += "body { font-family: Arial, sans-serif; background-color: #f0f0f0; }";
  html += "h2 { color: #333; }";
  html += "h3 { color: #333; }";
  html += "form { background-color: #fff; padding: 20px; border-radius: 5px; }";
  html += "input[type='number'] { width: 50px; }";
  html += "input[type='submit'] { padding: 5px 10px; }";
  html += "a { text-decoration: none; color: #0066cc; }";
  html += "</style>";
  html += "<script>";
  html += "function updateTime(){";
  html += "var xhr = new XMLHttpRequest();";
  html += "xhr.open('GET', '/getTime', true);";
  html += "xhr.onreadystatechange = function(){";
  html += "if(xhr.readyState == 4 && xhr.status == 200){";
  html += "document.getElementById('time').innerHTML = xhr.responseText;";
  html += "}};";
  html += "xhr.send();";
  html += "}";
  html += "setInterval(updateTime, 1000);";
  html += "</script>";
  html += "</head><body onload='updateTime()'>";
  html += "<h2>Текущее время: <span id='time'>" + currentTime + "</span></h2>";
  html += "<h2>Настройка времени</h2>";
  html += "<form action='/setTime' method='POST'>";
  html += "Часовой пояс (UTC): <input type='number' name='offset' min='-12' max='14' required><br><br/>";
  html += "<input type='submit' value='Установить время'>";
  html += "</form><br/>";
  html += "<h2>Настройка будильника</h2>";
  html += "<form action='/setAlarm' method='POST'>";
  html += "Часы: <input type='number' name='hour' min='0' max='23' required><br><br/>";
  html += "Минуты: <input type='number' name='minute' min='0' max='59' required><br><br/>";
  html += "<input type='submit' value='Установить будильник'>";
  html += "</form>";
  html += "</body></html>";

  server.send(200, "text/html", html);
}

void handleGetTime() {
  String currentTime = timeClient.getFormattedTime();
  server.send(200, "text/plain; charset=UTF-8", currentTime);
}

void handleSetTime() {
  if (server.hasArg("offset")) {
    int offset = server.arg("offset").toInt() * 3600;
    timeClient.setTimeOffset(offset);

    String html = "<html><head>";
    html += "<meta charset='UTF-8'>";
    html += "<title>Часовой пояс установлен</title>";
    html += "<style>";
    html += "body { font-family: Arial, sans-serif; background-color: #f0f0f0; }";
    html += "h3 { color: #333; }";
    html += "a { text-decoration: none; color: #0066cc; }";
    html += "</style>";
    html += "</head><body>";
    html += "<h3>Часовой пояс установлен!</h3>";
    html += "<a href='/'>Назад</a>";
    html += "</body></html>";

    server.send(200, "text/html", html);
  } else {
    server.send(400, "text/plain; charset=UTF-8", "Параметр 'offset' не найден");
  }
}

void handleSetAlarm() {
  if (server.hasArg("hour") && server.hasArg("minute")) {
    alarmHour = server.arg("hour").toInt();
    alarmMinute = server.arg("minute").toInt();
    alarmSet = true;

    String html = "<html><head>";
    html += "<meta charset='UTF-8'>";
    html += "<title>Будильник установлен</title>";
    html += "<style>";
    html += "body { font-family: Arial, sans-serif; background-color: #f0f0f0; }";
    html += "h3 { color: #333; }";
    html += "a { text-decoration: none; color: #0066cc; }";
    html += "</style>";
    html += "</head><body>";
    html += "<h3>Будильник установлен на " + String(alarmHour) + ":" + (alarmMinute < 10 ? "0" : "") + String(alarmMinute) + "!</h3>";
    html += "<a href='/'>Назад</a>";
    html += "</body></html>";

    server.send(200, "text/html", html);
  } else {
    server.send(400, "text/plain; charset=UTF-8", "Параметры 'hour' и 'minute' не найдены");
  }
}

void triggerAlarm() {
  Serial.println("Будильник сработал!");

  // Активируем мигание дисплея
  alarmActive = true;
  alarmStartTime = millis();
  lastBlinkTime = millis();
  displayOn = true;

  // Сбрасываем будильник после срабатывания
  alarmSet = false;
}    Добавь в код мигание двоеточием