This commit is contained in:
gein@sfedu.ru 2025-03-14 22:46:50 +03:00
parent 8b74a90ebb
commit 46ddc8425f
17 changed files with 3131 additions and 330 deletions

67
Docs.md Normal file
View File

@ -0,0 +1,67 @@
# Веб-сервер ESP8266 & P10 PAnel
## Описание
Этот проект реализует подключение и взаимодействие через веб-сервер ESP8266 и LED панели P10 4*3
## Возможности
- Обработка веб-запросов
- Изменение текста на матрице
- Реализовано 4 режима работы матрицы
- Вывод инвормации в JSON-формате
## Используемые библиотеки
- ESP8266WiFi
- Ticker
- DMD2
- ESPAsyncWebServer
- ESPAsyncTCP
- ArduinoJSON
## Установка
Клонируйте репозиторий:
```sh
git clone https://github.com/
```
Установите недостающие библиотеки и загрузите код на ESP8266
## Путь и тело запроса
**GET /api/led**
Возвращает текущее состояние панели
**POST /api/text**
Принимает текст отображающийся на панели
Пример запроса:
```json
{
"text":"Hello \nfrom \nGitTea"
}
```
**POST /api/led**
Изменяет состояние панели (Включение/выключение) и изменяет режим работы панели
Пример запроса:
Запрос на включение/выключение:
```json
{
"panel": "on"
}
```
```json
{
"panel": "off"
}
```
Запрос на изменение режима: (state : 1-4)
```json
{
"state": "1"
}
```
Запросы на включение и изменение режима могут приниматься вместе:
```json
{
"panel": "on",
"state": "3"
}
```

302
ESP82_PANEL.ino Normal file
View File

@ -0,0 +1,302 @@
#include <ESP8266WiFi.h>
#include <Ticker.h>
#include <DMD2.h>
#include <ESPAsyncWebServer.h>
#include <ESPAsyncTCP.h>
#include <ArduinoJson.h>
#include <fonts/Font_BOLD.h>
#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<String>();
drawText();
request->send(200, "application/json", "{\"status\": \"OK\"}");
}
void handleTurn(AsyncWebServerRequest* request, const JsonVariant& json) {
String panelTurn = json["panel"].as<String>();
String panelState = json["state"].as<String>();
if (json.containsKey("panel")) {
panelTurn = json["panel"].as<String>();
}
if (json.containsKey("state")) {
panelState = json["state"].as<String>();
}
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<JsonVariant>()); // Передаём как 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<JsonVariant>());
});
server.begin();
}
void loop() {
}

View File

@ -1,17 +0,0 @@
# The code for the panel P10 + ESP32
*********
* List of features
+ Edit text in real time via HomeAssistiant
+ Split sentences into lines (features)
+ Add a drawing as a binary image
+ Panel operation modes(-> Text scroll -> Image ->) || (static image + static text)
+ OTA (Over The Air Updates) (features)
+ State of panel
+ Remote panel on/off
# Docs for API
* Endpoints
+ 10.131.170.4 - the local static IP
+ /api/text - endpoint for editing text (POST)
+ /api/led - endpint for on/off panel (POST)
+ /api/led - endpoint for check on/off panel (GET), return "{"led":"true"}" if panel ON and "{"led":"false"}" if panel OFF
+ /api/state - endpoint for swith operation modes (POST), body: ({"State" : "1"} -> static image and static text) || body: ({"State" : "2"} -> Text scroll -> Image ->)

1
data/.venv/bin/python Symbolic link
View File

@ -0,0 +1 @@
python3

1
data/.venv/bin/python3 Symbolic link
View File

@ -0,0 +1 @@
/usr/bin/python3

1
data/.venv/bin/python3.12 Symbolic link
View File

@ -0,0 +1 @@
python3

1
data/.venv/lib64 Symbolic link
View File

@ -0,0 +1 @@
lib

5
data/.venv/pyvenv.cfg Normal file
View File

@ -0,0 +1,5 @@
home = /usr/bin
include-system-site-packages = false
version = 3.12.3
executable = /usr/bin/python3.12
command = /usr/bin/python3 -m venv /home/maks_gejn/Arduino/ESP82_PANEL/data/.venv

BIN
data/kit128 (copy).bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

5
data/kitleft.h Normal file

File diff suppressed because one or more lines are too long

39
data/main.py Normal file
View File

@ -0,0 +1,39 @@
import argparse
import cv2
import numpy as np
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument("--input", required=True, help="input image path")
parser.add_argument("--output", required=False, default='output.h', help="path to output file")
return parser.parse_args()
def main():
args = parse_args()
image = cv2.imread(args.input, cv2.IMREAD_GRAYSCALE)
if image is None:
print(
f"Could not read image {args.input}. "
f"Please, check that you passed the correct path"
)
exit()
image = cv2.resize(image, (128, 48))
image[image > 0] = 1
image = 1 - image
image = list(np.ravel(image))
image_text = ''
for i, pixel_data in enumerate(image):
image_text += str(pixel_data)
if i != len(image) - 1:
image_text += ', '
text = f"#ifndef _OUTPUT_\n#define _OUTPUT_\nbyte output[128*64] = {{ {image_text} }};\n\n#endif"
with open(args.output, 'w') as f:
f.write(text)
if __name__ == "__main__":
main()

5
data/output.h Normal file

File diff suppressed because one or more lines are too long

2704
fonts/Font_BOLD.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +0,0 @@
#ifndef _OUTPUT_
#define _OUTPUT_
byte output[16 * 32] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
const int dataSize = sizeof(output) / sizeof(output[0]);
#endif

View File

@ -1,64 +0,0 @@
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000
11100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000000000000
11100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001101100000000
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001101101111111
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001101111111
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001101111111
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100111110
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110011100
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111011000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001011000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001110000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000111111111111111000000000000000000000000000000000000111000000
00000000000000000000000000000000000000000000000000000000000000001111111111111111111111111100000000000000000000000000110011000000
00000000000000000000000000000000000000000000000000000000000000000001111111111111111111111111111110000000000000000001111001000000
00000000000000000000000000000000000000000000000000000000000000001110111111111111111111111111111111111101111111111111111100000000
00000000000000000000000000000000000000000000000000000000000000001111011111111111111111111111111111111101111111111111111110000000
00000000000000000000000000000000000000000000000000000000000000001111100000000000000000011111111111111110111111111111111100000000
00000000000000000000000000000000000000000000000000000000000000000111111111111111111111001111111111111111011111111110011000000000
00000000000000000000000000000000000000000000000000000000000000000111111111111111111111100111111111111111100000000000111000000000
00000000000000000000000000000000000000000000000000000000000000000111111111111111111111110011111111111111111111111111110000000000
00000000000000000000000000000000000000000000000000000000000000000011111111111110111111111001111111111111111111111111100000000000
00000000000000000000000000000000000000000000000000000000000000000001111111111100011111111100111111111111111111111111000000000000
00000000000000000000000000000000000000000000000000000000000000000000111111111100011111111110000000011111111111111110000000000000
00000000000000000000000000000000000000000000000000000000000000000000011111111110111111111111111111000000011111111100000000000000
00000000000000000000000000000000000000000000000000000000000000000000001111111111111111111111111111111111101111110000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111110111000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111110000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000001111111111111111111111110000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111110000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000111111100000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000011111110000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000001111110000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000111111000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000011111000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000111100000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000011110000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
11111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

224
panel.ino
View File

@ -1,224 +0,0 @@
//------------------Include Libraries------------------//
#include <WiFi.h>
#include <WebServer.h>
#include <DMD32.h>
#include <fonts/Font_BOLD.h>
#include <SPIFFS.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include "data/output.h"
//------------------------------------------------------//
#define DEBUG 1
//------------------Settings for panel------------------//
#define FONT Font_BOLD
#define DISPLAYS_ACROSS 1
#define DISPLAYS_DOWN 1
DMD dmd(DISPLAYS_ACROSS, DISPLAYS_DOWN);
//-------------------------------------------------------//
//------------------Wi-Fi Settings----------------------//
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);
//-------------------------------------------------------//
//------------------Web Server Settings-----------------//
AsyncWebServer server(80);
//-------------------------------------------------------//
//------------------Other Variables---------------------//
String displayText = "Привет из СКБ \"КИТ\"";
bool isScrolling = true;
bool showImage = false;
unsigned long lastScrollTime = 0;
unsigned long scrollDuration = 5000;
unsigned long imageStartTime = 0;
hw_timer_t *timer = NULL;
//-------------------------------------------------------//
//------------------Wi-Fi Connection Setup-------------//
void setupWiFi() {
WiFi.begin(ssid, password);
if (!WiFi.config(staticIP, gateway, subnet)) {
Serial.println("Failed to configure Static IP");
} else {
Serial.println("Static IP configured!");
}
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected to WiFi");
Serial.println(WiFi.localIP());
}
//-------------------------------------------------------//
//------------------Web Server Handlers-----------------//
void handleText(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) {
JsonDocument jsonReq;
String dataRequest = String((char *)data, len);
DeserializationError error = deserializeJson(jsonReq, dataRequest);
if (error) {
Serial.println(F("deserializeJson() failed"));
request->send(400, "text/html", "");
return;
}
if (jsonReq["text"].is<String>()) {
displayText = jsonReq["text"].as<String>();
}
request->send(200, "text/html; charset=UTF-8", "");
}
void handleStateChange(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) {
JsonDocument jsonReq;
String dataRequest = String((char *)data, len);
DeserializationError error = deserializeJson(jsonReq, dataRequest);
if (error) {
request->send(400, "text/html", "");
return;
}
String state = jsonReq["state"];
if (state == "1") {
dmd.clearScreen(true); // Reset the screen
displayText = "Привет из СКБ \"КИТ\"";
} else if (state == "2") {
isScrolling = true;
lastScrollTime = millis();
showImage = false;
} else if (state == "3") {
showImage = true;
imageStartTime = millis();
}
request->send(200, "text/html", "");
}
//-------------------------------------------------------//
//------------------Panel Management--------------------//
void handlePanelState(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) {
JsonDocument jsonReq;
String dataRequest = String((char *)data, len);
DeserializationError error = deserializeJson(jsonReq, dataRequest);
if (error) {
request->send(400, "text/html", "");
return;
}
String state = jsonReq["panel"];
if (state == "on") {
displayText = "Привет из СКБ \"КИТ\"";
} else if (state == "off") {
displayText = "";
}
request->send(200, "text/html", "");
}
//-------------------------------------------------------//
//------------------Display Binary Array Function------//
void displayBinaryArray() {
for (int y = 0; y < 32; y++) {
for (int x = 0; x < 16; x++) {
int idx = x * 32 + y;
if (output[idx] == 1) {
dmd.writePixel(x, y, GRAPHICS_NORMAL, true);
} else {
dmd.writePixel(x, y, GRAPHICS_NORMAL, false);
}
}
}
}
//-------------------------------------------------------//
//------------------Marquee Scroll Function-------------//
void scrollText() {
dmd.drawMarquee(displayText.c_str(), displayText.length(), (32 * DISPLAYS_ACROSS) - 1, 0);
long start = millis();
long timer = start;
bool ret = false;
while (!ret) {
if ((timer + 30) < millis()) {
ret = dmd.stepMarquee(-1, 0);
timer = millis();
}
}
if (millis() - lastScrollTime >= scrollDuration) {
isScrolling = false;
showImage = true;
imageStartTime = millis();
}
}
//-------------------------------------------------------//
//------------------Timer Interrupt Function------------//
void IRAM_ATTR triggerScan() {
dmd.scanDisplayBySPI();
}
//-------------------------------------------------------//
//------------------Setup Function-----------------------//
void setup() {
Serial.begin(115200);
dmd.selectFont(FONT);
SPIFFS.begin(true);
pinMode(22, OUTPUT);
setupWiFi();
server.on("/api/led", HTTP_GET, [](AsyncWebServerRequest *request) {
String state = isScrolling ? "true" : "false";
request->send(200, "application/json", "{\"state\": \"" + state + "\"}");
});
server.on("/api/led", HTTP_POST, [](AsyncWebServerRequest *request) {}, NULL, handlePanelState);
server.on("/api/text", HTTP_POST, [](AsyncWebServerRequest *request) {}, NULL, handleText);
server.on("/api/state", HTTP_POST, [](AsyncWebServerRequest *request) {}, NULL, handleStateChange);
server.begin();
uint8_t cpuClock = ESP.getCpuFreqMHz();
timer = timerBegin(0, cpuClock, true);
timerAttachInterrupt(timer, &triggerScan, true);
timerAlarmWrite(timer, 300, true);
timerAlarmEnable(timer);
dmd.clearScreen(true);
}
//-------------------------------------------------------//
//------------------Loop Function------------------------//
void loop() {
dmd.clearScreen(true);
if (isScrolling) {
scrollText();
}
if (showImage) {
displayBinaryArray();
if (millis() - imageStartTime >= 5000) {
showImage = false;
isScrolling = true;
lastScrollTime = millis();
}
}
delay(500);
}
//-------------------------------------------------------//