#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#include <Adafruit_BMP085.h>

// Настройки Wi-Fi (замените на свои данные)
const char* ssid = "Beeline_2G_A7F18A";
const char* password = "iD2tAXJN3e";

// Настройки статического IP-адреса
IPAddress local_IP(192, 168, 1, 184);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);
IPAddress secondaryDNS(8, 8, 4, 4);

// Определение пинов дисплея ST7735S
#define TFT_CS     15 // D8 на NodeMCU (GPIO15)
#define TFT_RST    2  // D4 на NodeMCU (GPIO2)
#define TFT_DC     0  // D3 на NodeMCU (GPIO0)

// Создание экземпляра дисплея
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

// Настройки NTP клиента (UTC+3 для московского времени)
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 3 * 3600, 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;

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

// Экземпляр датчика BMP180
Adafruit_BMP085 bmp;

// Прототипы функций
void handleRoot();
void handleGetTime();
void handleSetTime();
void handleSetAlarm();
void triggerAlarm();

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 setup() {
  Serial.begin(115200);

  // Инициализация датчика BMP180
  if (!bmp.begin()) {
    Serial.println("Не удалось найти датчик BMP180!");
    while (1) {
      delay(1000); // Остаёмся здесь, если инициализация датчика не удалась
    }
  }

  // Инициализация дисплея ST7735S
  tft.initR(INITR_BLACKTAB); // Используйте соответствующий тип для вашего дисплея
  tft.fillScreen(ST7735_BLACK);
  tft.setRotation(1); // Настройка ориентации дисплея (при необходимости)
  tft.setTextWrap(true);
  tft.setTextColor(ST7735_WHITE);

  // Настройка статического 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());

  // Запуск 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();
  }

  // Чтение данных с датчика BMP180
  float temperature = bmp.readTemperature();
  float pressure = bmp.readPressure() / 100.0; // Перевод в hPa

  // Формирование строк для отображения
  char timeString[9];
  snprintf(timeString, sizeof(timeString), "%02d:%02d:%02d", currentHour, currentMinute, currentSecond);

  char tempString[16];
  snprintf(tempString, sizeof(tempString), "Темп: %.2f C", temperature);

  char pressureString[16];
  snprintf(pressureString, sizeof(pressureString), "Давл: %.2f hPa", pressure);

  // Обработка индикации будильника
  if (alarmActive) {
    unsigned long currentTimeMillis = millis();

    if (currentTimeMillis - alarmStartTime >= alarmDuration) {
      // Останавливаем будильник
      alarmActive = false;
    } else {
      // Мигание экрана или отображение сообщения о будильнике
      if ((currentTimeMillis / blinkInterval) % 2 == 0) {
        tft.fillScreen(ST7735_RED); // Заполняем экран красным цветом
        tft.setCursor(10, 50);
        tft.setTextSize(2);
        tft.setTextColor(ST7735_WHITE);
        tft.print("БУДИЛЬНИК!");
      } else {
        // Отображение нормального экрана
        tft.fillScreen(ST7735_BLACK);
        tft.setTextColor(ST7735_WHITE);
        tft.setCursor(0, 0);
        tft.setTextSize(2);
        tft.print("Время:");

        tft.setCursor(0, 20);
        tft.setTextSize(3);
        tft.print(timeString);

        tft.setCursor(0, 60);
        tft.setTextSize(2);
        tft.print(tempString);

        tft.setCursor(0, 80);
        tft.print(pressureString);
      }
    }
  } else {
    // Обновление отображения на дисплее
    tft.fillScreen(ST7735_BLACK);

    tft.setCursor(0, 0);
    tft.setTextSize(2);
    tft.setTextColor(ST7735_WHITE);
    tft.print("Время:");

    tft.setCursor(0, 20);
    tft.setTextSize(3);
    tft.print(timeString);

    tft.setCursor(0, 60);
    tft.setTextSize(2);
    tft.print(tempString);

    tft.setCursor(0, 80);
    tft.print(pressureString);
  }

  delay(1000);
}

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

  // Чтение данных с датчика BMP180
  float temperature = bmp.readTemperature();
  float pressure = bmp.readPressure() / 100.0; // Перевод в hPa

  char temperatureString[16];
  char pressureString[16];

  snprintf(temperatureString, sizeof(temperatureString), "%.2f °C", temperature);
  snprintf(pressureString, sizeof(pressureString), "%.2f hPa", pressure);

  String html = "<html><head>";
  html += "<title>Онлайн-часы с BMP180</title>";
  html += "<meta charset='UTF-8'>";
  html += "<style>";
  html += "body { font-family: Arial, sans-serif; background-color: #f0f0f0; margin: 0; padding: 0; }";
  html += "header { background-color: #20B2AA; color: #fff; padding: 20px; text-align: center; }";
  html += "h1 { margin: 0; }";
  html += "main { padding: 20px; }";
  html += "footer { background-color: #20B2AA; color: #fff; padding: 10px; text-align: center; position: fixed; bottom: 0; width: 100%; }";
  html += ".card { background-color: #fff; padding: 20px; margin-bottom: 20px; border-radius: 5px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }";
  html += "form { margin-bottom: 20px; }";
  html += "input[type='number'] { width: 60px; padding: 5px; margin-right: 10px; }";
  html += "input[type='submit'] { padding: 10px 20px; background-color: #20B2AA; border: none; color: #fff; cursor: pointer; border-radius: 5px; }";
  html += "input[type='submit']:hover { background-color: #1e90ff; }";
  html += "a { text-decoration: none; color: #0066cc; }";
  html += "</style>";
  html += "</head><body>";
  html += "<header>";
  html += "<h1>Онлайн-часы с BMP180</h1>";
  html += "</header>";
  html += "<main>";
  html += "<div class='card'>";
  html += "<h2>Текущее время: <span>" + currentTime + "</span></h2>";
  html += "</div>";
  html += "<div class='card'>";
  html += "<h2>Температура: " + String(temperatureString) + "</h2>";
  html += "<h2>Давление: " + String(pressureString) + "</h2>";
  html += "</div>";
  html += "<div class='card'>";
  html += "<h2>Настройка времени</h2>";
  html += "<form action='/setTime' method='POST'>";
  html += "Часовой пояс (UTC): <input type='number' name='offset' min='-12' max='14' value='3' required><br/><br/>";
  html += "<input type='submit' value='Установить время'>";
  html += "</form>";
  html += "</div>";
  html += "<div class='card'>";
  html += "<h2>Настройка будильника</h2>";
  html += "<form action='/setAlarm' method='POST'>";
  html += "Часы: <input type='number' name='hour' min='0' max='23' required>";
  html += " Минуты: <input type='number' name='minute' min='0' max='59' required><br/><br/>";
  html += "<input type='submit' value='Установить будильник'>";
  html += "</form>";
  html += "</div>";
  html += "</main>";
  html += "<footer>";
  html += "© 2023 Мои часы";
  html += "</footer>";
  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; padding: 20px; }";
    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; padding: 20px; }";
    html += "a { text-decoration: none; color: #0066cc; }";
    html += "</style>";
    html += "</head><body>";
    html += "<h3>Будильник установлен на " + String(alarmHour) + ":";
    html += (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();

  // Сбрасываем будильник после срабатывания
  alarmSet = false;
}
на экране дисплея слова отображаются не корректно . часть информации не вмещается на экран.