rewrite
This commit is contained in:
parent
8b74a90ebb
commit
46ddc8425f
67
Docs.md
Normal file
67
Docs.md
Normal 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
302
ESP82_PANEL.ino
Normal 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() {
|
||||
}
|
17
README.md
17
README.md
@ -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
1
data/.venv/bin/python
Symbolic link
@ -0,0 +1 @@
|
||||
python3
|
1
data/.venv/bin/python3
Symbolic link
1
data/.venv/bin/python3
Symbolic link
@ -0,0 +1 @@
|
||||
/usr/bin/python3
|
1
data/.venv/bin/python3.12
Symbolic link
1
data/.venv/bin/python3.12
Symbolic link
@ -0,0 +1 @@
|
||||
python3
|
1
data/.venv/lib64
Symbolic link
1
data/.venv/lib64
Symbolic link
@ -0,0 +1 @@
|
||||
lib
|
5
data/.venv/pyvenv.cfg
Normal file
5
data/.venv/pyvenv.cfg
Normal 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
BIN
data/kit128 (copy).bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
5
data/kitleft.h
Normal file
5
data/kitleft.h
Normal file
File diff suppressed because one or more lines are too long
39
data/main.py
Normal file
39
data/main.py
Normal 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
5
data/output.h
Normal file
File diff suppressed because one or more lines are too long
2704
fonts/Font_BOLD.h
Normal file
2704
fonts/Font_BOLD.h
Normal file
File diff suppressed because it is too large
Load Diff
25
output.h
25
output.h
@ -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
|
64
output.txt
64
output.txt
@ -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
224
panel.ino
@ -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);
|
||||
}
|
||||
//-------------------------------------------------------//
|
Loading…
x
Reference in New Issue
Block a user