Compare commits

...

2 Commits

Author SHA1 Message Date
kkira
b0b832055e Доработка приложения 2026-06-16 22:26:33 +03:00
kkira
405a93bcae Оформление внешнего интерфейса 2026-05-28 20:20:58 +03:00
3 changed files with 568 additions and 225 deletions

View File

@@ -9,7 +9,7 @@
#include <Adafruit_NeoPixel.h> #include <Adafruit_NeoPixel.h>
// WIFI // WIFI
const char* ssid = "Cathouse"; const char* ssid = "SinceCats";
const char* password = "88888888"; const char* password = "88888888";
// CAMERA PINS // CAMERA PINS

View File

@@ -6,6 +6,8 @@
#include <Wire.h> #include <Wire.h>
#include <BH1750.h> #include <BH1750.h>
#include <ESP32Servo.h> #include <ESP32Servo.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
BH1750 lightMeter; BH1750 lightMeter;
@@ -13,21 +15,22 @@ BH1750 lightMeter;
float temperature = 0; float temperature = 0;
float humidity = 0; float humidity = 0;
float lux = 0;
String mqttStatus = "WAIT";
bool autoMode = false; // false = MANUAL
bool isNight = false;
String currentMode = "MANUAL";
WiFiClient espClient; WiFiClient espClient;
PubSubClient client(espClient); PubSubClient client(espClient);
const char* mqtt_server = "192.168.31.78"; const char* mqtt_server = "172.20.10.11";
// WIFI // WIFI
const char* ssid = "Cathouse"; const char* ssid = "SinceCats";
const char* password = "88888888"; const char* password = "88888888";
IPAddress local_IP(192,168,31,235);
IPAddress gateway(192,168,31,1);
IPAddress subnet(255,255,255,0);
IPAddress dns(192,168,31,1);
// CAMERA PINS // CAMERA PINS
#define PWDN_GPIO_NUM -1 #define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1 #define RESET_GPIO_NUM -1
@@ -49,6 +52,17 @@ IPAddress dns(192,168,31,1);
#define HREF_GPIO_NUM 7 #define HREF_GPIO_NUM 7
#define PCLK_GPIO_NUM 13 #define PCLK_GPIO_NUM 13
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(
SCREEN_WIDTH,
SCREEN_HEIGHT,
&Wire,
-1
);
// HTTP SERVER // HTTP SERVER
httpd_handle_t server = NULL; httpd_handle_t server = NULL;
@@ -249,37 +263,57 @@ void setup()
{ {
Serial.begin(115200); Serial.begin(115200);
delay(1500); delay(1500);
Serial.println("\n\n=== ESP32-S3-CAM START ===");
Serial.println("Init Camera...");
if (!initCamera()) if (!initCamera())
{ {
Serial.println("Camera init FAIL!");
delay(3000); delay(3000);
ESP.restart(); ESP.restart();
} }
Serial.println("Camera init DONE");
WiFi.config(local_IP, gateway, subnet, dns); Serial.println("Connecting WiFi...");
WiFi.begin(ssid, password); WiFi.begin(ssid, password);
WiFi.setSleep(false); WiFi.setSleep(false);
while (WiFi.status() != WL_CONNECTED) int attempts = 0;
{ while (WiFi.status() != WL_CONNECTED && attempts < 40) {
delay(300); delay(500);
Serial.print("."); Serial.print(".");
attempts++;
} }
Serial.println("\nWIFI OK"); if (WiFi.status() == WL_CONNECTED) {
Serial.println(WiFi.localIP()); Serial.println("\nWIFI OK");
Serial.println(WiFi.localIP());
} else {
Serial.println("\nWIFI FAIL");
}
Wire.begin(1, 2); Wire.begin(1, 2);
Wire.setClock(100000); Wire.setClock(100000);
lightMeter.begin(); lightMeter.begin();
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C))
{
Serial.println("OLED FAIL");
}
else
{
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
}
client.setServer(mqtt_server, 1883); client.setServer(mqtt_server, 1883);
startServer(); startServer();
Serial.println("STREAM READY:"); Serial.println("STREAM READY:");
Serial.println("http://192.168.31.235/stream"); Serial.println("http://172.20.10.2/stream");
strip.begin(); strip.begin();
strip.show(); strip.show();
@@ -297,10 +331,13 @@ void connectMQTT() {
String id = "ESP32CAM-" + String(WiFi.macAddress()); String id = "ESP32CAM-" + String(WiFi.macAddress());
if (client.connect(id.c_str())) { if (client.connect(id.c_str())) {
mqttStatus = "OK";
Serial.println("MQTT OK"); Serial.println("MQTT OK");
client.subscribe("esp32/led"); client.subscribe("esp32/led");
client.subscribe("esp32/servo"); client.subscribe("esp32/servo");
client.subscribe("esp32/mode");
} else { } else {
mqttStatus = "FAIL";
Serial.println("MQTT FAIL"); Serial.println("MQTT FAIL");
delay(2000); delay(2000);
} }
@@ -355,7 +392,26 @@ void callback(char* topic, byte* payload, unsigned int length)
Serial.print("MQTT: "); Serial.print("MQTT: ");
Serial.println(msg); Serial.println(msg);
if (String(topic) == "esp32/led"){ if (String(topic) == "esp32/mode")
{
if (msg == "AUTO")
{
autoMode = true;
currentMode = "AUTO";
Serial.println("AUTO MODE");
}
if (msg == "MANUAL")
{
autoMode = false;
currentMode = "MANUAL";
setColor(0, 0, 0);
Serial.println("MANUAL MODE");
}
}
if (String(topic) == "esp32/led" && !autoMode){
if (msg == "OFF"){ if (msg == "OFF"){
setColor(0,0,0); setColor(0,0,0);
return; return;
@@ -365,7 +421,7 @@ void callback(char* topic, byte* payload, unsigned int length)
setColor(r,g,b); setColor(r,g,b);
} }
if (String(topic) == "esp32/servo") if (String(topic) == "esp32/servo" && !autoMode)
{ {
// ДЕНЬ // ДЕНЬ
if (msg == "DAY"){ if (msg == "DAY"){
@@ -384,6 +440,35 @@ void callback(char* topic, byte* payload, unsigned int length)
} }
} }
void updateOLED(float lux)
{
display.clearDisplay();
display.setCursor(0,0);
display.print("Light: ");
display.print((int)lux);
display.println(" lx");
display.print("Temp: ");
display.print(temperature,1);
display.println(" C");
display.print("Hum : ");
display.print(humidity,1);
display.println(" %");
display.println();
display.print("MQTT: ");
display.println(mqttStatus);
display.print("MODE: ");
display.println(currentMode);
display.display();
}
void loop() void loop()
{ {
if (!client.connected()) if (!client.connected())
@@ -392,15 +477,44 @@ void loop()
client.loop(); client.loop();
static unsigned long lastMQTT = 0; static unsigned long lastMQTT = 0;
static unsigned long lastOLED = 0;
// Датчики + MQTT каждые 5 секунд
if (millis() - lastMQTT > 5000) if (millis() - lastMQTT > 5000)
{ {
lastMQTT = millis(); lastMQTT = millis();
float lux = lightMeter.readLightLevel(); lux = lightMeter.readLightLevel();
readAHT20(temperature, humidity); readAHT20(temperature, humidity);
if (autoMode)
{
// НОЧЬ
if (lux < 200 && !isNight)
{
isNight = true;
servoLeft(5000);
setColor(0,0,40);
Serial.println("AUTO NIGHT");
}
// ДЕНЬ
if (lux >= 200 && isNight)
{
isNight = false;
servoRight(5000);
setColor(40,25,10);
Serial.println("AUTO DAY");
}
}
char buf[32]; char buf[32];
snprintf(buf, sizeof(buf), "%.2f", lux); snprintf(buf, sizeof(buf), "%.2f", lux);
@@ -424,5 +538,12 @@ void loop()
Serial.println(humidity); Serial.println(humidity);
} }
// OLED раз в секунду
if (millis() - lastOLED > 1000)
{
lastOLED = millis();
updateOLED(lux);
}
vTaskDelay(2); vTaskDelay(2);
} }

View File

@@ -1,16 +1,16 @@
[ [
{ {
"id": "b6a554cb58b20b89", "id": "b54441ff0e1e1d78",
"type": "tab", "type": "tab",
"label": "Поток 1", "label": "Умная клетка для птиц",
"disabled": false, "disabled": false,
"info": "", "info": "",
"env": [] "env": []
}, },
{ {
"id": "e2dbb550ecc754bb", "id": "3329b02ba68d5122",
"type": "mqtt in", "type": "mqtt in",
"z": "b6a554cb58b20b89", "z": "b54441ff0e1e1d78",
"name": "", "name": "",
"topic": "Bird", "topic": "Bird",
"qos": "2", "qos": "2",
@@ -20,104 +20,85 @@
"rap": true, "rap": true,
"rh": 0, "rh": 0,
"inputs": 0, "inputs": 0,
"x": 230, "x": 250,
"y": 300, "y": 260,
"wires": [ "wires": [
[ [
"2362125992f2f15a", "69ab35d16ddcd908"
"853c51250983534e"
] ]
] ]
}, },
{ {
"id": "2362125992f2f15a", "id": "69ab35d16ddcd908",
"type": "debug",
"z": "b6a554cb58b20b89",
"name": "debug 1",
"active": true,
"tosidebar": false,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 440,
"y": 240,
"wires": []
},
{
"id": "853c51250983534e",
"type": "ui_template", "type": "ui_template",
"z": "b6a554cb58b20b89", "z": "b54441ff0e1e1d78",
"group": "de858d4f14ceb677", "group": "546b157844234b18",
"name": "", "name": "Video",
"order": 0, "order": 1,
"width": 0, "width": 6,
"height": 0, "height": 5,
"format": "<div id=\"camera-container\">\n <img id=\"camera-stream\" src=\"http://192.168.31.235/stream\"\n onerror=\"this.onerror=null; this.src='data:image/svg+xml,%3Csvg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"100%25\\\" height=\\\"400\\\"%3E%3Crect width=\\\"100%25\\\" height=\\\"100%25\\\" fill=\\\"%23333\\\"%3E%3C/rect%3E%3Ctext x=\\\"50%25\\\" y=\\\"50%25\\\" text-anchor=\\\"middle\\\" fill=\\\"%23fff\\\"%3ECamera offline - check connection%3C/text%3E%3C/svg%3E';\"\n style=\"width:100%; max-width:320px; height:240px;\">\n</div>\n\n<script>\n setInterval(function() {\n var img = document.getElementById('camera-stream');\n if (img) {\n var timestamp = new Date().getTime();\n img.src = 'http://192.168.31.235/stream?' + timestamp;\n }\n}, 5000);\n</script>", "format": "<div id=\"camera-container\">\n <img id=\"camera-stream\" src=\"http://192.168.31.235/stream\"\n onerror=\"this.onerror=null; this.src='data:image/svg+xml,%3Csvg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"100%25\\\" height=\\\"400\\\"%3E%3Crect width=\\\"100%25\\\" height=\\\"100%25\\\" fill=\\\"%23333\\\"%3E%3C/rect%3E%3Ctext x=\\\"50%25\\\" y=\\\"50%25\\\" text-anchor=\\\"middle\\\" fill=\\\"%23fff\\\"%3ECamera offline - check connection%3C/text%3E%3C/svg%3E';\"\n style=\"width:100%; max-width:320px; height:240px;\">\n</div>\n\n<script>\n setInterval(function() {\n var img = document.getElementById('camera-stream');\n if (img) {\n var timestamp = new Date().getTime();\n img.src = 'http://192.168.31.235/stream?' + timestamp;\n }\n}, 5000);\n</script>",
"storeOutMessages": true, "storeOutMessages": true,
"fwdInMessages": true, "fwdInMessages": true,
"resendOnRefresh": true, "resendOnRefresh": true,
"templateScope": "local", "templateScope": "local",
"className": "", "className": "",
"x": 440, "x": 430,
"y": 300, "y": 260,
"wires": [ "wires": [
[] []
] ]
}, },
{ {
"id": "f43e5b2d6e86f54d", "id": "7d8023c9457af7b3",
"type": "mqtt in", "type": "mqtt in",
"z": "b6a554cb58b20b89", "z": "b54441ff0e1e1d78",
"name": "light", "name": "light",
"topic": "esp32/sensors/light", "topic": "esp32/sensors/light",
"qos": "2", "qos": "0",
"datatype": "auto-detect", "datatype": "auto-detect",
"broker": "77647757300a0f3b", "broker": "77647757300a0f3b",
"nl": false, "nl": false,
"rap": true, "rap": true,
"rh": 0, "rh": 0,
"inputs": 0, "inputs": 0,
"x": 230, "x": 250,
"y": 400, "y": 340,
"wires": [ "wires": [
[ [
"5f6b7a790ede5d26", "d343a20cb8cc4c3f",
"744d0ca72a8e8df6" "953e9b0817d7888a"
] ]
] ]
}, },
{ {
"id": "347db67a62c25780", "id": "98a116d0b230fd5e",
"type": "mqtt in", "type": "mqtt in",
"z": "b6a554cb58b20b89", "z": "b54441ff0e1e1d78",
"name": "temp", "name": "temp",
"topic": "esp32/sensors/temp", "topic": "esp32/sensors/temp",
"qos": "2", "qos": "0",
"datatype": "auto-detect", "datatype": "auto-detect",
"broker": "77647757300a0f3b", "broker": "77647757300a0f3b",
"nl": false, "nl": false,
"rap": true, "rap": true,
"rh": 0, "rh": 0,
"inputs": 0, "inputs": 0,
"x": 230, "x": 250,
"y": 520, "y": 420,
"wires": [ "wires": [
[ [
"1abf7819982867cb", "967917ac6800fba7"
"bade5e5c2073894d"
] ]
] ]
}, },
{ {
"id": "edacc7ae819555c1", "id": "9f71a077937ffa10",
"type": "mqtt in", "type": "mqtt in",
"z": "b6a554cb58b20b89", "z": "b54441ff0e1e1d78",
"name": "humidity", "name": "humidity",
"topic": "esp32/sensors/humidity", "topic": "esp32/sensors/humidity",
"qos": "2", "qos": "0",
"datatype": "auto-detect", "datatype": "auto-detect",
"broker": "77647757300a0f3b", "broker": "77647757300a0f3b",
"nl": false, "nl": false,
@@ -125,130 +106,80 @@
"rh": 0, "rh": 0,
"inputs": 0, "inputs": 0,
"x": 240, "x": 240,
"y": 660, "y": 500,
"wires": [ "wires": [
[ [
"56ccdbc50d6e0d65", "a62bb5aa0c518728"
"dc38d7ae67c9b0fa"
] ]
] ]
}, },
{ {
"id": "5f6b7a790ede5d26", "id": "d343a20cb8cc4c3f",
"type": "debug",
"z": "b6a554cb58b20b89",
"name": "debug 2",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 440,
"y": 400,
"wires": []
},
{
"id": "1abf7819982867cb",
"type": "debug",
"z": "b6a554cb58b20b89",
"name": "debug 3",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 440,
"y": 520,
"wires": []
},
{
"id": "56ccdbc50d6e0d65",
"type": "debug",
"z": "b6a554cb58b20b89",
"name": "debug 4",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 440,
"y": 660,
"wires": []
},
{
"id": "744d0ca72a8e8df6",
"type": "ui_text", "type": "ui_text",
"z": "b6a554cb58b20b89", "z": "b54441ff0e1e1d78",
"group": "de858d4f14ceb677", "group": "546b157844234b18",
"order": 1, "order": 20,
"width": 0, "width": 4,
"height": 0, "height": 1,
"name": "", "name": "Light",
"label": "Освещённость", "label": "Освещённость",
"format": "{{msg.payload}}", "format": "{{msg.payload}} lux",
"layout": "row-left", "layout": "row-spread",
"className": "", "className": "",
"style": false, "style": false,
"font": "", "font": "",
"fontSize": 16, "fontSize": 16,
"color": "#000000", "color": "#000000",
"x": 460, "x": 430,
"y": 360, "y": 340,
"wires": [] "wires": []
}, },
{ {
"id": "bade5e5c2073894d", "id": "967917ac6800fba7",
"type": "ui_text", "type": "ui_text",
"z": "b6a554cb58b20b89", "z": "b54441ff0e1e1d78",
"group": "de858d4f14ceb677", "group": "546b157844234b18",
"order": 2, "order": 23,
"width": 0, "width": 4,
"height": 0, "height": 1,
"name": "", "name": "Temperature",
"label": "Температура", "label": "Температура",
"format": "{{msg.payload}}", "format": "{{msg.payload}} °C",
"layout": "row-left", "layout": "row-spread",
"className": "",
"style": false,
"font": "",
"fontSize": 16,
"color": "#000000",
"x": 460,
"y": 480,
"wires": []
},
{
"id": "dc38d7ae67c9b0fa",
"type": "ui_text",
"z": "b6a554cb58b20b89",
"group": "de858d4f14ceb677",
"order": 3,
"width": 0,
"height": 0,
"name": "",
"label": "Влажность",
"format": "{{msg.payload}}",
"layout": "row-left",
"className": "", "className": "",
"style": false, "style": false,
"font": "", "font": "",
"fontSize": 16, "fontSize": 16,
"color": "#000000", "color": "#000000",
"x": 450, "x": 450,
"y": 620, "y": 420,
"wires": [] "wires": []
}, },
{ {
"id": "0eacb49f1c0dd21a", "id": "a62bb5aa0c518728",
"type": "ui_text",
"z": "b54441ff0e1e1d78",
"group": "546b157844234b18",
"order": 26,
"width": 4,
"height": 1,
"name": "Humidity",
"label": "Влажность",
"format": "{{msg.payload}} %",
"layout": "row-spread",
"className": "",
"style": false,
"font": "",
"fontSize": 16,
"color": "#000000",
"x": 440,
"y": 500,
"wires": []
},
{
"id": "326e3d7cd0711c1a",
"type": "mqtt out", "type": "mqtt out",
"z": "b6a554cb58b20b89", "z": "b54441ff0e1e1d78",
"name": "", "name": "",
"topic": "esp32/led", "topic": "esp32/led",
"qos": "", "qos": "",
@@ -259,17 +190,17 @@
"correl": "", "correl": "",
"expiry": "", "expiry": "",
"broker": "77647757300a0f3b", "broker": "77647757300a0f3b",
"x": 620, "x": 660,
"y": 780, "y": 860,
"wires": [] "wires": []
}, },
{ {
"id": "dff600700ba8712a", "id": "688951172c116781",
"type": "ui_colour_picker", "type": "ui_colour_picker",
"z": "b6a554cb58b20b89", "z": "b54441ff0e1e1d78",
"name": "color_led", "name": "color_led",
"label": "Настроить освещение", "label": "Цвет свечения",
"group": "de858d4f14ceb677", "group": "546b157844234b18",
"format": "hex", "format": "hex",
"outformat": "string", "outformat": "string",
"showSwatch": true, "showSwatch": true,
@@ -280,25 +211,25 @@
"showLightness": true, "showLightness": true,
"square": "false", "square": "false",
"dynOutput": "false", "dynOutput": "false",
"order": 5, "order": 10,
"width": 0, "width": 3,
"height": 0, "height": 1,
"passthru": true, "passthru": true,
"topic": "topic", "topic": "topic",
"topicType": "msg", "topicType": "msg",
"className": "", "className": "",
"x": 200, "x": 240,
"y": 840, "y": 860,
"wires": [ "wires": [
[ [
"2095de04955e307f" "debe9d9adfca0645"
] ]
] ]
}, },
{ {
"id": "2095de04955e307f", "id": "debe9d9adfca0645",
"type": "function", "type": "function",
"z": "b6a554cb58b20b89", "z": "b54441ff0e1e1d78",
"name": "function 1", "name": "function 1",
"func": "let hex = msg.payload;\n\nhex = hex.replace(\"#\", \"\");\n\nlet r = parseInt(hex.substring(0, 2), 16);\nlet g = parseInt(hex.substring(2, 4), 16);\nlet b = parseInt(hex.substring(4, 6), 16);\n\nmsg.payload = `${r},${g},${b}`;\n\nreturn msg;", "func": "let hex = msg.payload;\n\nhex = hex.replace(\"#\", \"\");\n\nlet r = parseInt(hex.substring(0, 2), 16);\nlet g = parseInt(hex.substring(2, 4), 16);\nlet b = parseInt(hex.substring(4, 6), 16);\n\nmsg.payload = `${r},${g},${b}`;\n\nreturn msg;",
"outputs": 1, "outputs": 1,
@@ -307,25 +238,25 @@
"initialize": "", "initialize": "",
"finalize": "", "finalize": "",
"libs": [], "libs": [],
"x": 400, "x": 440,
"y": 840, "y": 860,
"wires": [ "wires": [
[ [
"0eacb49f1c0dd21a" "326e3d7cd0711c1a"
] ]
] ]
}, },
{ {
"id": "38796c6012673ea3", "id": "95c5b2f761fe6d30",
"type": "ui_switch", "type": "ui_switch",
"z": "b6a554cb58b20b89", "z": "b54441ff0e1e1d78",
"name": "led", "name": "led",
"label": "Выкл./Вкл. освещение", "label": "Выкл./Вкл. освещение",
"tooltip": "", "tooltip": "",
"group": "de858d4f14ceb677", "group": "546b157844234b18",
"order": 5, "order": 5,
"width": 0, "width": 3,
"height": 0, "height": 1,
"passthru": true, "passthru": true,
"decouple": "false", "decouple": "false",
"topic": "esp32/led", "topic": "esp32/led",
@@ -341,23 +272,24 @@
"offcolor": "", "offcolor": "",
"animate": false, "animate": false,
"className": "", "className": "",
"x": 390, "x": 430,
"y": 780, "y": 800,
"wires": [ "wires": [
[ [
"0eacb49f1c0dd21a" "326e3d7cd0711c1a",
"a7a8bbbba6048822"
] ]
] ]
}, },
{ {
"id": "56c329c92a8daa3a", "id": "9dd1c7f2d5e42901",
"type": "ui_button", "type": "ui_button",
"z": "b6a554cb58b20b89", "z": "b54441ff0e1e1d78",
"name": "day", "name": "day",
"group": "de858d4f14ceb677", "group": "546b157844234b18",
"order": 6, "order": 7,
"width": 0, "width": 2,
"height": 0, "height": 1,
"passthru": false, "passthru": false,
"label": "День", "label": "День",
"tooltip": "", "tooltip": "",
@@ -369,23 +301,24 @@
"payloadType": "str", "payloadType": "str",
"topic": "esp32/servo", "topic": "esp32/servo",
"topicType": "msg", "topicType": "msg",
"x": 390, "x": 430,
"y": 920, "y": 640,
"wires": [ "wires": [
[ [
"cb039d5711277422" "aa0c521baa5be283",
"018bce1ef78ece19"
] ]
] ]
}, },
{ {
"id": "136ce072862c41f7", "id": "3f8af190256a6358",
"type": "ui_button", "type": "ui_button",
"z": "b6a554cb58b20b89", "z": "b54441ff0e1e1d78",
"name": "night", "name": "night",
"group": "de858d4f14ceb677", "group": "546b157844234b18",
"order": 8, "order": 15,
"width": 0, "width": 2,
"height": 0, "height": 1,
"passthru": false, "passthru": false,
"label": "Ночь", "label": "Ночь",
"tooltip": "", "tooltip": "",
@@ -397,23 +330,24 @@
"payloadType": "str", "payloadType": "str",
"topic": "esp32/servo", "topic": "esp32/servo",
"topicType": "msg", "topicType": "msg",
"x": 390, "x": 430,
"y": 1000, "y": 720,
"wires": [ "wires": [
[ [
"cb039d5711277422" "aa0c521baa5be283",
"018bce1ef78ece19"
] ]
] ]
}, },
{ {
"id": "39d131b72bf61cc5", "id": "e1b2f26f37b43975",
"type": "ui_button", "type": "ui_button",
"z": "b6a554cb58b20b89", "z": "b54441ff0e1e1d78",
"name": "mid", "name": "mid",
"group": "de858d4f14ceb677", "group": "546b157844234b18",
"order": 7, "order": 12,
"width": 0, "width": 2,
"height": 0, "height": 1,
"passthru": false, "passthru": false,
"label": "Полдень", "label": "Полдень",
"tooltip": "", "tooltip": "",
@@ -425,18 +359,19 @@
"payloadType": "str", "payloadType": "str",
"topic": "esp32/servo", "topic": "esp32/servo",
"topicType": "msg", "topicType": "msg",
"x": 390, "x": 430,
"y": 960, "y": 680,
"wires": [ "wires": [
[ [
"cb039d5711277422" "aa0c521baa5be283",
"018bce1ef78ece19"
] ]
] ]
}, },
{ {
"id": "cb039d5711277422", "id": "018bce1ef78ece19",
"type": "mqtt out", "type": "mqtt out",
"z": "b6a554cb58b20b89", "z": "b54441ff0e1e1d78",
"name": "", "name": "",
"topic": "esp32/servo", "topic": "esp32/servo",
"qos": "", "qos": "",
@@ -447,10 +382,296 @@
"correl": "", "correl": "",
"expiry": "", "expiry": "",
"broker": "77647757300a0f3b", "broker": "77647757300a0f3b",
"x": 610, "x": 670,
"y": 980, "y": 640,
"wires": [] "wires": []
}, },
{
"id": "c238963e4e433c07",
"type": "ui_text",
"z": "b54441ff0e1e1d78",
"group": "546b157844234b18",
"order": 3,
"width": 4,
"height": 2,
"name": "",
"label": "Состояние жалюзи",
"format": "{{msg.payload}}",
"layout": "col-center",
"className": "",
"style": false,
"font": "",
"fontSize": 16,
"color": "#000000",
"x": 860,
"y": 720,
"wires": []
},
{
"id": "aa0c521baa5be283",
"type": "function",
"z": "b54441ff0e1e1d78",
"name": "function 2",
"func": "let command = msg.payload;\n\nlet status_text = \"\";\nlet status_color = \"\";\n\nswitch(command) {\n case \"DAY\":\n status_text = \"День\";\n status_color = \"green\";\n break;\n case \"MID\":\n status_text = \"Полдень\";\n status_color = \"orange\";\n break;\n case \"NIGHT\":\n status_text = \"Ночь\";\n status_color = \"blue\";\n break;\n default:\n status_text = \"Неизвестное состояние\";\n status_color = \"gray\";\n}\n\nmsg.payload = command;\n\nlet status_msg = {\n payload: status_text,\n topic: \"esp32/servo\"\n};\n\nnode.send([\n [status_msg],\n [msg]\n]);",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 660,
"y": 720,
"wires": [
[
"c238963e4e433c07"
]
]
},
{
"id": "a7a8bbbba6048822",
"type": "function",
"z": "b54441ff0e1e1d78",
"name": "function 3",
"func": "let led_value = msg.payload;\n\nlet status_text = \"Освещение выключено\";\nlet status_color = \"\";\n\nif (led_value === \"255,255,255\" || led_value === \"ON\") {\n status_text = \"Освещение включено\";\n status_color = \"green\";\n} else if (led_value === \"OFF\") {\n status_text = \"Освещение выключено\";\n status_color = \"red\";\n} \n\nlet status_msg = {\n payload: status_text,\n color: status_color\n};\n\nnode.send([status_msg]);\n\nlet mqtt_msg = {\n payload: led_value,\n topic: \"esp32/led\"\n};\nnode.send([null, mqtt_msg]);",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 660,
"y": 800,
"wires": [
[
"935423913e479104"
]
]
},
{
"id": "935423913e479104",
"type": "ui_text",
"z": "b54441ff0e1e1d78",
"group": "546b157844234b18",
"order": 2,
"width": 5,
"height": 2,
"name": "",
"label": "Состояние освещения",
"format": "{{msg.payload}}",
"layout": "col-center",
"className": "",
"style": false,
"font": "",
"fontSize": 16,
"color": "#000000",
"x": 870,
"y": 800,
"wires": []
},
{
"id": "953e9b0817d7888a",
"type": "ui_chart",
"z": "b54441ff0e1e1d78",
"name": "",
"group": "546b157844234b18",
"order": 17,
"width": 9,
"height": 5,
"label": "Изменение освещённости",
"chartType": "line",
"legend": "false",
"xformat": "HH:mm:ss",
"interpolate": "linear",
"nodata": "",
"dot": false,
"ymin": "0",
"ymax": "500",
"removeOlder": "24",
"removeOlderPoints": "",
"removeOlderUnit": "3600",
"cutout": 0,
"useOneColor": false,
"useUTC": false,
"colors": [
"#1f77b4",
"#aec7e8",
"#ff7f0e",
"#2ca02c",
"#98df8a",
"#d62728",
"#ff9896",
"#9467bd",
"#c5b0d5"
],
"outputs": 1,
"useDifferentColor": false,
"className": "",
"x": 640,
"y": 340,
"wires": [
[]
]
},
{
"id": "f7c54e9ed468ad03",
"type": "ui_spacer",
"z": "b54441ff0e1e1d78",
"name": "spacer",
"group": "546b157844234b18",
"order": 4,
"width": 1,
"height": 1
},
{
"id": "06f9e525bae03d4f",
"type": "ui_spacer",
"z": "b54441ff0e1e1d78",
"name": "spacer",
"group": "546b157844234b18",
"order": 6,
"width": 2,
"height": 1
},
{
"id": "7e39ac586ef75670",
"type": "ui_spacer",
"z": "b54441ff0e1e1d78",
"name": "spacer",
"group": "546b157844234b18",
"order": 8,
"width": 1,
"height": 1
},
{
"id": "eebc2ead2bdc4713",
"type": "ui_spacer",
"z": "b54441ff0e1e1d78",
"name": "spacer",
"group": "546b157844234b18",
"order": 9,
"width": 1,
"height": 1
},
{
"id": "60c5659493f5b1e3",
"type": "ui_spacer",
"z": "b54441ff0e1e1d78",
"name": "spacer",
"group": "546b157844234b18",
"order": 11,
"width": 2,
"height": 1
},
{
"id": "8e200c90a6fe2612",
"type": "ui_spacer",
"z": "b54441ff0e1e1d78",
"name": "spacer",
"group": "546b157844234b18",
"order": 13,
"width": 1,
"height": 1
},
{
"id": "13a88f7bf1f6b955",
"type": "ui_spacer",
"z": "b54441ff0e1e1d78",
"name": "spacer",
"group": "546b157844234b18",
"order": 14,
"width": 6,
"height": 1
},
{
"id": "d8806707892c2923",
"type": "ui_spacer",
"z": "b54441ff0e1e1d78",
"name": "spacer",
"group": "546b157844234b18",
"order": 16,
"width": 1,
"height": 1
},
{
"id": "9a9ebc45643a2504",
"type": "ui_spacer",
"z": "b54441ff0e1e1d78",
"name": "spacer",
"group": "546b157844234b18",
"order": 18,
"width": 6,
"height": 1
},
{
"id": "5e37295a74a08a72",
"type": "ui_spacer",
"z": "b54441ff0e1e1d78",
"name": "spacer",
"group": "546b157844234b18",
"order": 19,
"width": 1,
"height": 1
},
{
"id": "8d65bde5f5fe894d",
"type": "ui_spacer",
"z": "b54441ff0e1e1d78",
"name": "spacer",
"group": "546b157844234b18",
"order": 21,
"width": 1,
"height": 1
},
{
"id": "089a1385b0933a72",
"type": "ui_spacer",
"z": "b54441ff0e1e1d78",
"name": "spacer",
"group": "546b157844234b18",
"order": 22,
"width": 1,
"height": 1
},
{
"id": "8dad06acd8afbd47",
"type": "ui_spacer",
"z": "b54441ff0e1e1d78",
"name": "spacer",
"group": "546b157844234b18",
"order": 24,
"width": 1,
"height": 1
},
{
"id": "f1d14ae70273a27f",
"type": "ui_spacer",
"z": "b54441ff0e1e1d78",
"name": "spacer",
"group": "546b157844234b18",
"order": 25,
"width": 1,
"height": 1
},
{
"id": "2da5e779df30a880",
"type": "ui_spacer",
"z": "b54441ff0e1e1d78",
"name": "spacer",
"group": "546b157844234b18",
"order": 27,
"width": 1,
"height": 1
},
{
"id": "98a43a6570fb548d",
"type": "ui_spacer",
"z": "b54441ff0e1e1d78",
"name": "spacer",
"group": "546b157844234b18",
"order": 28,
"width": 6,
"height": 1
},
{ {
"id": "77647757300a0f3b", "id": "77647757300a0f3b",
"type": "mqtt-broker", "type": "mqtt-broker",
@@ -483,13 +704,14 @@
"sessionExpiry": "" "sessionExpiry": ""
}, },
{ {
"id": "de858d4f14ceb677", "id": "546b157844234b18",
"type": "ui_group", "type": "ui_group",
"name": "Default", "z": "b54441ff0e1e1d78",
"name": "Мониторинг и управление",
"tab": "8e35d7697e7af77c", "tab": "8e35d7697e7af77c",
"order": 1, "order": 1,
"disp": true, "disp": true,
"width": "24", "width": 15,
"collapse": false, "collapse": false,
"className": "" "className": ""
}, },
@@ -502,7 +724,7 @@
"hidden": false "hidden": false
}, },
{ {
"id": "cfd15ff24e6ffc58", "id": "d21957267aecd6fc",
"type": "global-config", "type": "global-config",
"env": [], "env": [],
"modules": { "modules": {