#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <ArduinoOTA.h>
#include <ESP8266WebServer.h>
#include <ThingerESP8266.h>

// Настройки дисплея
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// Настройки Wi-Fi
const char* ssid = "Beeline_2G_A7F18A";  // Ваш SSID
const char* password = "iD2tAXJN3e";     // Ваш пароль

// OTA пароль
const char* otaPassword = "35539900";

// Настройки NTP
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 10800, 60000); // UTC+3

// Аппаратные пины
#define BUZZER_PIN 14  // GPIO14
#define BUTTON_PIN 12  // GPIO12
#define LED_PIN 13     // GPIO13 поддерживает ШИМ (PWM)

// Настройки Thinger.io
#define THINGER_USERNAME "PavelMy"
#define THINGER_DEVICE_ID "ESPPROGECT1"
#define THINGER_DEVICE_CREDENTIAL "Asus35539900"

ThingerESP8266 thing(THINGER_USERNAME, THINGER_DEVICE_ID, THINGER_DEVICE_CREDENTIAL);

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

// Переменные
String scrollMessage = "";         // Сообщение для дисплея
int textXPosition = SCREEN_WIDTH;  // Стартовая позиция текста для прокрутки
bool newMessageReceived = false;   // Флаг нового сообщения
unsigned long lastButtonPress = 0; // Для антидребезга кнопки

// Переменные для деликатного мигания
bool ledFadingUp = true;       // Направление изменения яркости
int ledBrightness = 0;         // Текущая яркость светодиода (0-255)
unsigned long lastLedUpdate = 0; // Время последнего обновления яркости
const int ledFadeDelay = 30;   // Задержка между изменениями яркости (мс)

void setup() {
    Serial.begin(115200);
    Serial.println("\nStarting...");

    // Настройка пинов
    pinMode(BUZZER_PIN, OUTPUT);
    digitalWrite(BUZZER_PIN, LOW);
    pinMode(BUTTON_PIN, INPUT_PULLUP);
    pinMode(LED_PIN, OUTPUT);
    analogWrite(LED_PIN, 0); // Изначально светодиод выключен

    // Инициализация дисплея
    if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
        Serial.println(F("SSD1306 allocation failed"));
        while (true);
    }
    display.clearDisplay();
    display.display();

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

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

    // Запуск Thinger.io
    thing.add_wifi(ssid, password);

    // Настройки ресурсов Thinger.io
    thing["display_message"] << [](pson& input) {
        if (input.is_string()) {
            scrollMessage = (const char*)input;  // Сохраняем новое сообщение
            textXPosition = SCREEN_WIDTH;       // Позиция текста
            newMessageReceived = true;          // Установить флаг нового сообщения
            Serial.print("New message received: ");
            Serial.println(scrollMessage);
            Beep(); // Звуковой сигнал
        }
    };

    thing["clear_message"] = []() {
        scrollMessage = "";             // Очистить сообщение
        newMessageReceived = false;     // Сбрасываем флаг нового сообщения
        Serial.println("Message cleared");
    };

    // Запуск OTA
    ArduinoOTA.setPassword(otaPassword);
    ArduinoOTA.begin();
    Serial.println("OTA ready.");

    // Запуск веб-сервера
    WebServerInit();
    Serial.println("Setup complete.");
}

void loop() {
    // Обновление сервисов
    ArduinoOTA.handle();          // OTA обновления
    timeClient.update();          // Обновление времени
    server.handleClient();        // Обработка запросов веб-сервера
    thing.handle();               // Обработка Thinger.io

    // Обработка кнопки
    HandleButton();

    // Обновление дисплея
    UpdateDisplay();

    // Работа со светодиодом
    UpdateLed();
}

// ---- Вспомогательные функции ----

// Веб-сервер
void WebServerInit() {
    server.on("/", HTTP_GET, []() {
        String html = "<!DOCTYPE html>"
                      "<html>"
                      "<head><title>ESP8266 Control</title></head>"
                      "<body>"
                      "<h1>ESP8266 Message Control</h1>"
                      "<form action='/sendMessage' method='POST'>"
                      "Message: <input name='message' type='text'><br>"
                      "<input type='submit' value='Send Message'>"
                      "</form>"
                      "</body>"
                      "</html>";
        server.send(200, "text/html", html);
    });

    server.on("/sendMessage", HTTP_POST, []() {
        if (server.hasArg("message")) {
            scrollMessage = server.arg("message");
            textXPosition = SCREEN_WIDTH;  // Сбрасываем позицию текста
            newMessageReceived = true;    // Устанавливаем флаг
            Serial.println("New message received: " + scrollMessage);
            Beep();                       // Звуковой сигнал
            server.send(200, "text/html", "<h1>Message received!</h1><a href='/'>Back</a>");
        } else {
            server.send(400, "text/plain", "Message not provided");
        }
    });

    server.begin();
    Serial.println("Web server initialized.");
}

// Обработка кнопки
void HandleButton() {
    unsigned long currentMillis = millis();
    if (digitalRead(BUTTON_PIN) == LOW && currentMillis - lastButtonPress > 300) {
        lastButtonPress = currentMillis;  // Антидребезг
        scrollMessage = "";               // Очищаем сообщение
        newMessageReceived = false;       // Сбрасываем флаг
        Serial.println("Message cleared!");
    }
}

// Управление плавным миганием светодиода
void UpdateLed() {
    if (newMessageReceived) {
        unsigned long currentMillis = millis();
        if (currentMillis - lastLedUpdate > ledFadeDelay) {
            lastLedUpdate = currentMillis;

            // Изменяем яркость светодиода
            if (ledFadingUp) {
                ledBrightness += 15; // Увеличиваем яркость
                if (ledBrightness >= 255) { // Достигли максимальной яркости
                    ledBrightness = 255;
                    ledFadingUp = false;
                }
            } else {
                ledBrightness -= 15; // Уменьшаем яркость
                if (ledBrightness <= 0) { // Достигли минимальной яркости
                    ledBrightness = 0;
                    ledFadingUp = true;
                }
            }

            analogWrite(LED_PIN, ledBrightness);
        }
    } else {
        // Если нет новых сообщений, светодиод выключается
        analogWrite(LED_PIN, 0);
    }
}

// Обновление дисплея
void UpdateDisplay() {
    display.clearDisplay();

    // Отображение времени
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.setCursor(0, 0);
    display.print("Time: ");
    display.print(timeClient.getFormattedTime());

    // Работа с прокруткой текста
    if (scrollMessage.length() > 0) {
        display.setCursor(textXPosition, 16);
        display.setTextSize(1);
        display.print(scrollMessage);

        // Прокрутка текста
        textXPosition -= 2;
        if (textXPosition < -6 * scrollMessage.length()) {
            textXPosition = SCREEN_WIDTH;
        }
    } else {
        display.setCursor(0, 16);
        display.print("No messages");
    }

    display.display();
    delay(30);  // Плавность анимации
}

// Звуковой сигнал
void Beep() {
    digitalWrite(BUZZER_PIN, HIGH);
    delay(100);
    digitalWrite(BUZZER_PIN, LOW);
} сделай мигание диода более плавным не меняя пин поключения