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

// Параметры дисплея
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// Пины
#define BUZZER_PIN 14

// Данные для подключения к Wi-Fi по умолчанию
String ssid = "Mesto_Chistoty";
String password = "Mesto13092022";

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

// Веб-сервер
ESP8266WebServer server(80);

// Время будильника
String alarmTime = "--:--";
bool alarmActivated = false;

// Управление отображением IP
unsigned long displayStart;
bool showDate = false;

// Для анимации
unsigned long previousMillis = 0;
const long interval = 1000;  // Интервал для обновления экрана
int animationStage = 0;
bool isTulipActive = true;

void setupAccessPoint() {
    Serial.println("Switching to AP mode...");
    WiFi.softAP("ESP_CLOCK", "12345678");

    display.clearDisplay();
    display.setCursor(0, 0);
    display.println("AP Mode Active!");
    display.setCursor(0, 10);
    display.print("SSID: ESP_CLOCK");
    display.display();

    server.on("/", []() {
        String html = "<html><head><title>WiFi Setup</title></head><body>";
        html += "<h1>Setup WiFi</h1>";
        html += "<form action=\"/save\" method=\"GET\">";
        html += "SSID: <input type=\"text\" name=\"ssid\"><br>";
        html += "Password: <input type=\"password\" name=\"password\"><br>";
        html += "<input type=\"submit\" value=\"Save\">";
        html += "</form>";
        html += "</body></html>";
        server.send(200, "text/html", html);
    });

    server.on("/save", []() {
        if (server.hasArg("ssid") && server.hasArg("password")) {
            ssid = server.arg("ssid");
            password = server.arg("password");
            server.send(200, "text/html", "<html><body><h1>Settings Saved. Restarting...</h1></body></html>");
            delay(1000);
            ESP.restart();
        } else {
            server.send(200, "text/html", "<html><body><h1>Error. Enter SSID and password.</h1></body></html>");
        }
    });

    server.begin();
    Serial.println("AP Server Started");
}

void connectToWifi() {
    display.clearDisplay();
    display.setCursor(0, 0);
    display.println("Connecting to WiFi...");
    display.display();

    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid.c_str(), password.c_str());

    int attempts = 0;
    while (WiFi.status() != WL_CONNECTED && attempts < 20) {
        delay(500);
        Serial.print(".");
        ++attempts;
    }

    if (WiFi.status() == WL_CONNECTED) {
        Serial.println("\nWiFi Connected");
        display.clearDisplay();
        display.setCursor(0, 0);
        display.println("WiFi Connected!");
        display.print("IP: ");
        display.println(WiFi.localIP());
        display.display();
        delay(2000);
        timeClient.begin();
        timeClient.update();
        displayStart = millis();
    }
}

void drawTulip(int stage) {
    display.clearDisplay();
    display.setCursor(0, 0);
    display.println("Tulip Blooming:");
    switch (stage) {
        case 0: // Бутон
            display.drawCircle(64, 48, 2, SSD1306_WHITE);
            break;
        case 1: // Открывающиеся лепестки
            display.drawCircle(64, 46, 3, SSD1306_WHITE);
            display.drawLine(64, 48, 64, 63, SSD1306_WHITE); // стебель
            break;
        case 2: // Распустившийся тюльпан
            display.drawCircle(64, 44, 5, SSD1306_WHITE);
            display.drawLine(64, 48, 64, 63, SSD1306_WHITE); // стебель
            break;
    }
    display.display();
}

void drawSwayingTree(int frame) {
    display.clearDisplay();
    display.setCursor(0, 0);
    display.println("Tree in Wind:");
    int trunkX = 64;
    int offset = (frame % 2 == 0) ? -2 : 2;
    display.drawLine(trunkX + offset, 32, trunkX + offset, 63, SSD1306_WHITE);
    display.drawPixel(trunkX + offset + 3, 30, SSD1306_WHITE);
    display.drawPixel(trunkX + offset - 3, 30, SSD1306_WHITE);
    if (frame % 3 == 0) {
        display.drawPixel(trunkX + random(-10, 10), 35 + random(0, 10), SSD1306_WHITE);
    }
    display.display();
}

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

    if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
        Serial.println("SSD1306 allocation failed");
        while (true) {}
    }

    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);

    pinMode(BUZZER_PIN, OUTPUT);
    digitalWrite(BUZZER_PIN, LOW);

    connectToWifi();
    if (WiFi.status() != WL_CONNECTED) {
        setupAccessPoint();
    }
}

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

    unsigned long currentMillis = millis();

    if (currentMillis - previousMillis >= interval) {
        previousMillis = currentMillis;
        
        if (isTulipActive) {
            drawTulip(animationStage % 3);
        } else {
            drawSwayingTree(animationStage);
        }
        
        animationStage++;
        if (animationStage > 10) {
            isTulipActive = !isTulipActive;
            animationStage = 0;
        }
    }

    // Проверка срабатывания будильника
    if (timeClient.getFormattedTime().substring(0, 5) == alarmTime && alarmActivated) {
        digitalWrite(BUZZER_PIN, HIGH);
        delay(1000);
        digitalWrite(BUZZER_PIN, LOW);
        alarmActivated = false;
    }
} в этом коде замени анимацию осени . пусть в качестве эффекта будет ветвистое дерево с которого ветер срывает листья