#include #include #include #include #include #include #include #include "data/output.h" #include "data/kitleft.h" const uint8_t* FONT = Font_BOLD; const int WIDTH = 4; // Количество матриц в ширину const int HEIGHT = 3; // Количество матриц в высоту AsyncWebServer server(80); String displayText = "Привет из СКБ \"КИТ\""; bool isON = true; bool showText = true; bool scroll = true; const char* skb = "СКБ"; const char* kit = "\"КИТ\""; const char* ictib = "ИКТИБ"; const char* ssid = "SKBKIT"; const char* password = "skbkit2024"; IPAddress staticIP(10, 131, 170, 4); IPAddress gateway(10, 131, 170, 1); IPAddress subnet(255, 255, 255, 0); SPIDMD dmd(WIDTH, HEIGHT); DMD_TextBox* box = nullptr; // Указатель на текстовый бокс Ticker ticker; void setupWiFi() { WiFi.begin(ssid, password); if (!WiFi.config(staticIP, gateway, subnet)) { Serial.println("Failed WiFi connect!"); } else { Serial.println("Static WiFi configured!"); } while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\nConnected to WiFi"); Serial.println(WiFi.localIP()); } void drawBinaryArrayKit() { dmd.clearScreen(); for (int x = 0; x < WIDTH * 32; x++) { for (int y = 0; y < HEIGHT * 16; y++) { int idx = y * (WIDTH * 32) + x; // Индекс с учетом полной ширины if (output[idx] == 1) { dmd.setPixel(x, y, GRAPHICS_ON); } else { dmd.setPixel(x, y, GRAPHICS_OFF); } } } } void drawBinaryArrayKitLeft() { dmd.clearScreen(); for (int x = 0; x < WIDTH * 32; x++) { for (int y = 0; y < HEIGHT * 16; y++) { int idx = y * (WIDTH * 32) + x; // Индекс с учетом полной ширины if (kitleft[idx] == 1) { dmd.setPixel(x, y, GRAPHICS_ON); } else { dmd.setPixel(x, y, GRAPHICS_OFF); } } } } void switchDisplayMode() { if (isON) { if (showText) { drawScrollingText(); // Запускаем скролл текста на второй строке } else { drawBinaryArrayKit(); } showText = !showText; } } void switchDisplayModeScroll() { if (isON && scroll) { //box->scrollX(1); // Двигаем текст влево //box->drawScrollingText(); dmd.marqueeScrollX(1); } } void drawScrollingText() { if (!box) { box = new DMD_TextBox(dmd, 0, 17, WIDTH * 32, HEIGHT * 16); // Устанавливаем текстовый бокс на вторую строку } else { box->clear(); } box->print(displayText.c_str()); } void drawText() { dmd.clearScreen(); if (!box) { // Создаём текстовый бокс только один раз box = new DMD_TextBox(dmd, 0, 0, WIDTH * 32, HEIGHT * 16); } else { box->clear(); // Очищаем текущий бокс перед обновлением текста } box->print(displayText.c_str()); } void handleText(AsyncWebServerRequest* request, const JsonVariant& json) { if (!json.containsKey("text")) { request->send(400, "application/json", "{\"error\": \"Missing text field\"}"); return; } displayText = json["text"].as(); drawText(); request->send(200, "application/json", "{\"status\": \"OK\"}"); } void handleTurn(AsyncWebServerRequest* request, const JsonVariant& json) { String panelTurn = json["panel"].as(); String panelState = json["state"].as(); if (json.containsKey("panel")) { panelTurn = json["panel"].as(); } if (json.containsKey("state")) { panelState = json["state"].as(); } ticker.detach(); if (!panelTurn.isEmpty()) { if (panelTurn == "on") { isON = true; } else if (panelTurn == "off") { isON = false; dmd.clearScreen(); dmd.drawFilledBox(0, 0, WIDTH * 32 - 1, HEIGHT * 16 - 1, GRAPHICS_OFF); } } if (!panelState.isEmpty()) { if (panelState == "1") { // Скролинг текста dmd.clearScreen(); dmd.selectFont(FONT); dmd.drawLine(0, 14, 16, 14, GRAPHICS_ON); // x y x y dmd.drawLine(0, 13, 16, 13, GRAPHICS_ON); dmd.drawLine(16, 14, 20, 5, GRAPHICS_ON); dmd.drawLine(16, 13, 20, 4, GRAPHICS_ON); dmd.drawLine(20, 5, 30, 5, GRAPHICS_ON); dmd.drawLine(20, 4, 30, 4, GRAPHICS_ON); dmd.drawCircle(33, 4, 3, GRAPHICS_ON); dmd.drawCircle(33, 4, 2, GRAPHICS_ON); //1 line dmd.drawLine(20, 14, 40, 14, GRAPHICS_ON); dmd.drawLine(20, 13, 40, 13, GRAPHICS_ON); dmd.drawLine(40, 14, 45, 5, GRAPHICS_ON); dmd.drawLine(40, 13, 45, 4, GRAPHICS_ON); dmd.drawLine(45, 5, 60, 5, GRAPHICS_ON); dmd.drawLine(45, 4, 60, 4, GRAPHICS_ON); dmd.drawLine(60, 5, 65, 14, GRAPHICS_ON); dmd.drawLine(60, 4, 65, 13, GRAPHICS_ON); dmd.drawLine(65, 14, 75, 14, GRAPHICS_ON); dmd.drawLine(65, 13, 75, 13, GRAPHICS_ON); dmd.drawCircle(78, 13, 3, GRAPHICS_ON); dmd.drawCircle(78, 13, 2, GRAPHICS_ON); //2 line dmd.drawCircle(68, 4, 3, GRAPHICS_ON); dmd.drawCircle(68, 4, 2, GRAPHICS_ON); dmd.drawLine(71, 5, 85, 5, GRAPHICS_ON); dmd.drawLine(71, 4, 85, 4, GRAPHICS_ON); dmd.drawLine(85, 5, 90, 14, GRAPHICS_ON); dmd.drawLine(85, 4, 90, 13, GRAPHICS_ON); dmd.drawLine(90, 14, 100, 14, GRAPHICS_ON); dmd.drawLine(90, 13, 100, 13, GRAPHICS_ON); dmd.drawLine(100, 14, 105, 5, GRAPHICS_ON); dmd.drawLine(100, 13, 105, 4, GRAPHICS_ON); dmd.drawLine(105, 5, 128, 5, GRAPHICS_ON); dmd.drawLine(105, 4, 128, 4, GRAPHICS_ON); // 3 line // ====================================== dmd.drawLine(0, 35, 16, 35, GRAPHICS_ON); dmd.drawLine(0, 36, 16, 36, GRAPHICS_ON); dmd.drawLine(16, 35, 21, 43, GRAPHICS_ON); dmd.drawLine(16, 36, 21, 44, GRAPHICS_ON); dmd.drawLine(21, 43, 31, 43, GRAPHICS_ON); dmd.drawLine(21, 44, 31, 44, GRAPHICS_ON); dmd.drawCircle(34, 44, 3, GRAPHICS_ON); dmd.drawCircle(34, 44, 2, GRAPHICS_ON); // 1 line dmd.drawLine(20, 35, 40, 35, GRAPHICS_ON); dmd.drawLine(20, 36, 40, 36, GRAPHICS_ON); dmd.drawLine(40, 35, 45, 43, GRAPHICS_ON); dmd.drawLine(40, 36, 45, 44, GRAPHICS_ON); // 2 line dmd.drawLine(45, 43, 60, 43, GRAPHICS_ON); dmd.drawLine(45, 44, 60, 44, GRAPHICS_ON); dmd.drawLine(60, 43, 65, 35, GRAPHICS_ON); dmd.drawLine(60, 44, 65, 36, GRAPHICS_ON); dmd.drawLine(65, 35, 75, 35, GRAPHICS_ON); dmd.drawLine(65, 36, 75, 36, GRAPHICS_ON); dmd.drawCircle(78, 36, 3, GRAPHICS_ON); dmd.drawCircle(78, 36, 2, GRAPHICS_ON); } else if (panelState == "2") { // Текст и картинка динамика dmd.clearScreen(); drawText(); ticker.attach(5, switchDisplayMode); dmd.clearScreen(); drawBinaryArrayKit(); } else if (panelState == "3") { // Текст и картинка статика dmd.clearScreen(); drawBinaryArrayKitLeft(); dmd.drawString_P(79, 2, skb); dmd.drawString_P(71, 17, kit); dmd.drawString_P(68, 32, ictib); } } String response = "{\"panel\" : " + String(isON ? "\"on\"" : "\"off\"") + ", \"state\" : " + (panelState.isEmpty() ? "null" : panelState) + "}"; request->send(200, "application/json", response); } void setup() { Serial.begin(9600); setupWiFi(); dmd.setBrightness(255); dmd.selectFont(FONT); dmd.begin(); dmd.clearScreen(); box = new DMD_TextBox(dmd, 0, 0, WIDTH * 32, HEIGHT * 16); // Создаём текстовый бокс один раз box->print("Hello"); server.on( "/api/text", HTTP_POST, [](AsyncWebServerRequest* request) {}, NULL, [](AsyncWebServerRequest* request, uint8_t* data, size_t len, size_t, size_t) { StaticJsonDocument<256> jsonReq; DeserializationError error = deserializeJson(jsonReq, data, len); if (error) { request->send(400, "application/json", "{\"error\": \"Invalid JSON\"}"); return; } handleText(request, jsonReq.as()); // Передаём как const JsonVariant& }); server.on("/api/led", HTTP_GET, [](AsyncWebServerRequest* request) { if (isON) { request->send(200, "application/json", "{\"panel\" : \"on\"}"); } else if (!isON) { request->send(200, "application/json", "{\"panel\" : \"off\"}"); } }); server.on( "/api/led", HTTP_POST, [](AsyncWebServerRequest* request) {}, NULL, [](AsyncWebServerRequest* request, uint8_t* data, size_t len, size_t, size_t) { StaticJsonDocument<256> jsonReq; DeserializationError error = deserializeJson(jsonReq, data, len); if (error) { request->send(400, "application/json", "{\"error\": \"Invalid JSON\"}"); return; } handleTurn(request, jsonReq.as()); }); server.begin(); } void loop() { }