к каким пинам подключен дисплей в этом коде? #include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <U8g2lib.h>
#include <ArduinoOTA.h>
#include <time.h>
#include <EEPROM.h> // Добавлено для работы с EEPROM

// Определяем пины для I2C на ESP-01S
#define I2C_SCL_PIN 2 // GPIO2 (SCL)
#define I2C_SDA_PIN 0 // GPIO0 (SDA)

// Определение пинов для зуммера
#define BUZZER_PIN 0 // GPIO0

// Инициализация дисплея с использованием программного I2C
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, I2C_SCL_PIN, I2C_SDA_PIN, U8X8_PIN_NONE);

// Данные для подключения к Wi-Fi будут храниться в EEPROM
String ssid = "Mesto_Chistoty";
String password = "Mesto13092022";

// Учетные данные для веб-сервера
const char* www_username = "admin";
const char* www_password = "35539900";

// Учетные данные для OTA
const char* otaHostname = "ESP01S_AlarmClock";
const char* otaPassword = "OTApassword123";

// Инициализация веб-сервера на порту 80
ESP8266WebServer server(80);

// Настройки NTP-клиента
const long utcOffsetInSeconds = 3 * 3600; // Московское время UTC+3
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);

// Переменная для хранения времени будильника
String alarmTime = "";

// Буфер для хранения логов
String logBuffer = "";
const int maxLogSize = 2048;

// Переменная для контроля режима (STA или AP)
bool apMode = false;

// Прототипы функций
void logPrint(String message);
void logPrintln(String message);
void handleRoot();
void handleSetAlarm();
void handleTime();
void handleLog();
void checkAlarm();
void startAPMode();
void handleRootAP();
void handleSaveWiFi();
void writeStringToEEPROM(int addrOffset, const String& strToWrite);
String readStringFromEEPROM(int addrOffset);

// HTML-страница, хранимая в PROGMEM
const char htmlPage[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<head>
  <title>Будильник</title>
  <style>
    body {
      background-color: #303030; /* Темно-серый фон */
      color: #B2E0D9; /* Мятный цвет текста */
      font-family: Arial, sans-serif;
      text-align: center;
      padding-top: 20px;
    }
    h1 {
      color: #FF4081; /* Цвет заголовка */
    }
    #time {
      font-size: 48px;
      margin: 20px 0;
    }
    #date {
      font-size: 32px;
      margin: 10px 0;
    }
    input[type=time] {
      padding: 10px;
      font-size: 18px;
      margin: 20px 0;
      border: 2px solid #B2E0D9; /* Мятная рамка */
      background-color: #424242; /* Темно-серая фоновая рамка */
      color: #B2E0D9; /* Мятный цвет текста */
    }
    input[type=submit] {
      background-color: #FF4081; /* Цвет кнопки */
      color: #FFFFFF; /* Цвет текста кнопки */
      border: none;
      padding: 15px 30px;
      font-size: 18px;
      cursor: pointer;
    }
    input[type=submit]:hover {
      background-color: #E91E63; /* Цвет кнопки при наведении */
    }
    #log {
      background-color: #252526; /* Темно-серый фон для логов */
      color: #B2E0D9; /* Мятный цвет текста логов */
      text-align: left;
      padding: 10px;
      margin: 20px auto;
      width: 80%;
      height: 200px;
      overflow-y: scroll;
      font-family: monospace;
      font-size: 12px;
      border: 1px solid #333;
      white-space: pre-line;
    }
  </style>
</head>
<body>
  <h1>Будильник</h1>
  <div id="time">--:--:--</div>
  <div id="date">--.--.----</div>
  <form action="/setAlarm" method="POST">
    <label for="alarm">Время будильника:</label><br>
    <input type="time" id="alarm" name="alarm" required><br>
    <input type="submit" value="Установить будильник">
  </form>
  <div id="log">Загрузка логов...</div>
  <script>
    function updateTime() {
      fetch('/time')
        .then(response => response.text())
        .then(dateTime => {
          let [time, date] = dateTime.split(' ');
          document.getElementById('time').textContent = time;
          document.getElementById('date').textContent = date;
        })
        .catch(err => console.error(err));
    }
    setInterval(updateTime, 1000);
    updateTime();

    function updateLog() {
      fetch('/log')
        .then(response => response.text())
        .then(logData => {
          document.getElementById('log').textContent = logData;
          const logDiv = document.getElementById('log');
          logDiv.scrollTop = logDiv.scrollHeight;
        })
        .catch(err => console.error(err));
    }
    setInterval(updateLog, 1000);
    updateLog();
  </script>
</body>
</html>
)=====";

// Функция setup
void setup() {
  // Инициализация Serial Monitor
  Serial.begin(115200);

  // Инициализация дисплея
  u8g2.begin();

  // Настройка пинов
  pinMode(BUZZER_PIN, OUTPUT);
  digitalWrite(BUZZER_PIN, LOW); // Зуммер выключен

  // Инициализация EEPROM
  EEPROM.begin(512);

  // Чтение сохраненных Wi-Fi данных из EEPROM
  ssid = readStringFromEEPROM(0);
  password = readStringFromEEPROM(100);

  // Проверка наличия сохраненных SSID и пароля
  if (ssid.length() == 0 || password.length() == 0) {
    logPrintln("Нет сохраненных данных Wi-Fi. Запуск точки доступа.");
    apMode = true;
  } else {
    // Подключение к Wi-Fi
    logPrint("Подключение к Wi-Fi...");
    WiFi.begin(ssid.c_str(), password.c_str());

    unsigned long startAttemptTime = millis();
    const unsigned long wifiConnectingTimeout = 60000; // 20 секунд

    // Ожидание подключения
    while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < wifiConnectingTimeout) {
      delay(500);
      logPrint(".");
    }

    if (WiFi.status() == WL_CONNECTED) {
      logPrintln("\nПодключено к Wi-Fi сети.");
      logPrint("Внутренний IP адрес: ");
      logPrintln(WiFi.localIP().toString());

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

      // Настройка обработчиков веб-сервера
      server.on("/", handleRoot);
      server.on("/setAlarm", HTTP_POST, handleSetAlarm);
      server.on("/time", handleTime);
      server.on("/log", handleLog);

      // Настройка OTA
      ArduinoOTA.setHostname(otaHostname);
      ArduinoOTA.setPassword(otaPassword);
      ArduinoOTA.begin();
      logPrintln("OTA настроен и готов к использованию.");

      // Запуск веб-сервера
      server.begin();
      logPrintln("Веб-сервер запущен на порту 80");

      apMode = false;
    } else {
      logPrintln("\nНе удалось подключиться к Wi-Fi за 60 секунд. Запуск режима точки доступа.");
      apMode = true;
    }
  }

  if (apMode) {
    startAPMode();
  }
}

// Функция запуска режима точки доступа
void startAPMode() {
  WiFi.disconnect();
  WiFi.mode(WIFI_AP);
  WiFi.softAP("ESP_AP", www_password); // Установка пароля для точки доступа
  
  IPAddress myIP = WiFi.softAPIP();
  Serial.print("Точка доступа запущена. IP адрес: ");
  Serial.println(myIP);
  
  // Настраиваем обработчики веб-сервера
  server.on("/", handleRootAP);
  server.on("/saveWiFi", handleSaveWiFi);
  
  server.begin();
  logPrintln("HTTP сервер запущен.");
}

// Функция loop
void loop() {
  // Обработка запросов веб-сервера
  server.handleClient();

  if (!apMode) {
    // Обработка OTA
    ArduinoOTA.handle();

    // Обновление времени через NTP
    timeClient.update();

    // Проверка будильника
    checkAlarm();

    // Обработка будильника или отображение времени
    if (alarmTime != "") {
      // Вы можете здесь добавить логику для активного будильника
      // handleActiveAlarm(); // Если эта функция не реализована, можно просто ее закомментировать или удалить
    }
  } else {
    // В режиме AP отображаем информацию о точке доступа
    u8g2.firstPage();
    do {
      u8g2.setFont(u8g2_font_helvR12_tr);
      u8g2.drawStr(0, 20, "Режим точки");
      u8g2.drawStr(0, 40, "доступа");
      u8g2.drawStr(0, 60, "SSID: ESP_AP");
    } while (u8g2.nextPage());
  }
}

// Функция логирования сообщений
void logPrint(String message) {
  Serial.print(message);
  logBuffer += message + "\n";
  
  // Ограничиваем размер буфера логов
  if (logBuffer.length() > maxLogSize) {
    logBuffer.remove(0, logBuffer.length() - maxLogSize);
  }
}

void logPrintln(String message) {
  logPrint(message);
}

// Функция проверки будильника
void checkAlarm() {
  if (alarmTime != "") {
    time_t rawTime = timeClient.getEpochTime();
    struct tm* timeInfo = localtime(&rawTime);
    char currentTime[6]; // "HH:MM"
    strftime(currentTime, sizeof(currentTime), "%H:%M", timeInfo);

    if (String(currentTime) == alarmTime) {
      logPrintln("Будильник сработал!");
      alarmTime = ""; // Сбрасываем будильник после срабатывания
    }
  }
}

// Обработчики веб-сервера в режиме STA
void handleRoot() {
  if (!server.authenticate(www_username, www_password)) {
    return server.requestAuthentication();
  }
  String html((__FlashStringHelper*)htmlPage);
  server.send(200, "text/html; charset=utf-8", html);
}

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

  if (server.hasArg("alarm")) {
    alarmTime = server.arg("alarm");
    logPrintln("Будильник установлен на: " + alarmTime);
    server.sendHeader("Location", "/");
    server.send(303);
  } else {
    server.send(400, "text/plain; charset=utf-8", "Неверный запрос");
  }
}

void handleTime() {
  if (!server.authenticate(www_username, www_password)) {
    return server.requestAuthentication();
  }
  time_t rawTime = timeClient.getEpochTime();
  struct tm* timeInfo = localtime(&rawTime);

  char timeString[9];
  char dateString[11];

  strftime(timeString, sizeof(timeString), "%H:%M:%S", timeInfo);
  strftime(dateString, sizeof(dateString), "%d.%m.%Y", timeInfo);

  String dateTimeString = String(timeString) + " " + String(dateString);

  server.send(200, "text/plain; charset=utf-8", dateTimeString);
}

void handleLog() {
  if (!server.authenticate(www_username, www_password)) {
    return server.requestAuthentication();
  }
  server.send(200, "text/plain; charset=utf-8", logBuffer);
}

// Обработчики веб-сервера в режиме AP
void handleRootAP() {
  String html = "<html>\
  <head><title>Настройка Wi-Fi</title></head>\
  <body>\
  <h1>Настройка Wi-Fi</h1>\
  <form action='/saveWiFi' method='post'>\
  SSID:<br><input type='text' name='ssid'><br>\
  Пароль:<br><input type='password' name='password'><br><br>\
  <input type='submit' value='Сохранить'>\
  </form>\
  </body>\
  </html>";
      
  server.send(200, "text/html; charset=utf-8", html);
}

void handleSaveWiFi() {
  String newSSID = server.arg("ssid");
  String newPassword = server.arg("password");

  // Сохраняем новые данные в EEPROM
  writeStringToEEPROM(0, newSSID);
  writeStringToEEPROM(100, newPassword);
  EEPROM.commit();

  String html = "<html><body><h1>Настройки сохранены. Перезагрузка устройства...</h1></body></html>";
  server.send(200, "text/html; charset=utf-8", html);

  delay(2000);
  ESP.restart();
}

// Функции для работы с EEPROM
void writeStringToEEPROM(int addrOffset, const String &strToWrite) {
  byte len = strToWrite.length();
  EEPROM.write(addrOffset, len);
  for (int i = 0; i < len; i++) {
    EEPROM.write(addrOffset + 1 + i, strToWrite[i]);
  }
}

String readStringFromEEPROM(int addrOffset) {
  int len = EEPROM.read(addrOffset);
  if (len < 0 || len > 31) return ""; // Проверка на допустимую длину
  char data[len + 1];
  for (int i = 0; i < len; i++) {
    data[i] = EEPROM.read(addrOffset + 1 + i);
  }
  data[len] = '\0';
  return String(data);
}