summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlapa <vlapa@ya.ru>2026-06-13 18:10:53 +0300
committervlapa <vlapa@ya.ru>2026-06-13 18:10:53 +0300
commitddacdedd4976aacb16db752829af9ed33fef4ec8 (patch)
tree4aaa96cc2a58d19a930431297030374325ab47dd
First
-rw-r--r--.gitignore5
-rw-r--r--.vscode/extensions.json10
-rw-r--r--platformio.ini21
-rw-r--r--src/main.cpp345
4 files changed, 381 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..89cc49c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+.pio
+.vscode/.browse.c_cpp.db*
+.vscode/c_cpp_properties.json
+.vscode/launch.json
+.vscode/ipch
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000..080e70d
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,10 @@
+{
+ // See http://go.microsoft.com/fwlink/?LinkId=827846
+ // for the documentation about the extensions.json format
+ "recommendations": [
+ "platformio.platformio-ide"
+ ],
+ "unwantedRecommendations": [
+ "ms-vscode.cpptools-extension-pack"
+ ]
+}
diff --git a/platformio.ini b/platformio.ini
new file mode 100644
index 0000000..16499d5
--- /dev/null
+++ b/platformio.ini
@@ -0,0 +1,21 @@
+; PlatformIO Project Configuration File
+;
+; Build options: build flags, source filter
+; Upload options: custom upload port, speed and extra flags
+; Library options: dependencies, extra library storages
+; Advanced options: extra scripting
+;
+; Please visit documentation for the other options and examples
+; https://docs.platformio.org/page/projectconf.html
+
+[env:d1_mini]
+platform = espressif8266
+board = d1_mini
+framework = arduino
+
+upload_speed = 460800 ;921600
+monitor_speed = 115200
+
+lib_deps =
+ arduino-libraries/NTPClient
+ knolleary/PubSubClient \ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..6dedfcc
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,345 @@
+#include <Arduino.h>
+#include <ESP8266WiFi.h>
+#include <ESP8266HTTPUpdateServer.h>
+#include <NTPClient.h>
+#include <WiFiUdp.h>
+#include <ESP8266HTTPClient.h>
+#include <PubSubClient.h>
+
+#define PIN_RELAY D1
+
+// Время работы (более понятные имена)
+const uint8_t DAY_START_HOUR = 7; // Начало дня
+const uint8_t NIGHT_START_HOUR = 23; // Начало ночи
+const uint8_t DAY_WORK_MINUTES = 10; // Дневной интервал (минут)
+const uint8_t NIGHT_WORK_MINUTES = 20; // Ночной интервал (минут)
+const uint8_t DAY_START_MINUTE = 25; // Старт дневного интервала
+
+// Ночные интервалы (для ясности)
+const uint8_t NIGHT_INTERVAL1_START = 0;
+const uint8_t NIGHT_INTERVAL2_START = 40;
+
+// Интервал синхронизации (сейчас 30 минут для тестирования?)
+const uint32_t SYNC_INTERVAL_MS = 30 * 60 * 1000; // 30 минут
+
+// const char *ssid = "link";
+const char *ssid = "MikroTik-2";
+const char *pass = "dkfgf#*12091997";
+const char *ntp_server = "ntp3.vniiftri.ru";
+const char *host = "89.110.92.137";
+const uint16_t port = 8000;
+const char *address_page = "/";
+
+const uint32_t utcOffsetInSeconds = 10800;
+const uint32_t utcPeriodMseconds = 30 * 60 * 1000; // 86400000-р/сут; 604800000-р/нед
+uint32_t lastSync = 0;
+
+WiFiUDP ntpUDP;
+NTPClient timeClient(ntpUDP, ntp_server, utcOffsetInSeconds, utcPeriodMseconds);
+
+const uint16_t TIME_SLEEP = 60000;
+const uint8_t NUMBER_OF_ATTEMPTS = 20;
+bool flagBegining = true;
+
+const char *mqtt_client = "esp8266-761924";
+const char *mqtt_client2 = "Villa_Septik";
+const char *mqtt_user = "mqtt";
+const char *mqtt_pass = "qwe1243";
+const char *mqtt_server = "89.110.92.137";
+const char *mqtt_port = "1883";
+const char *outTopicData = "/data";
+
+ESP8266WebServer server(80);
+ESP8266HTTPUpdateServer httpUpdater;
+
+WiFiClient espClient;
+PubSubClient client(espClient);
+
+//-----------------------------------
+inline bool mqtt_subscribe(PubSubClient &client, const String &topic)
+{
+ Serial.print("Subscribing to: ");
+ Serial.println(topic);
+ return client.subscribe(topic.c_str());
+}
+
+//-----------------------------------
+inline bool mqtt_publish(PubSubClient &client, const String &topic, const String &value)
+{
+ Serial.print(topic);
+ Serial.print(" = ");
+ Serial.println(value);
+ return client.publish(topic.c_str(), value.c_str());
+}
+
+//-----------------------------------
+void mqttDataOut(uint8_t a)
+{
+ String topic, topicValue;
+
+ topic = "/";
+ topic += mqtt_client2;
+ topic += outTopicData;
+ topicValue = a;
+ topicValue += ";;;;";
+
+ uint8_t count = NUMBER_OF_ATTEMPTS;
+ while (!mqtt_publish(client, topic, topicValue) && count--)
+ {
+ mqtt_publish(client, topic, topicValue);
+ delay(500);
+ }
+}
+
+//-----------------------------------
+bool setupMQTT()
+{
+ client.setServer(mqtt_server, String(mqtt_port).toInt());
+
+ Serial.print("MQTT connect : ");
+ Serial.println(mqtt_server);
+
+ uint8_t count = NUMBER_OF_ATTEMPTS;
+ while (!(client.connect(mqtt_client, mqtt_user, mqtt_pass)) && count--)
+ {
+ Serial.print(count);
+ Serial.print('>');
+ delay(500);
+ }
+
+ if (client.connected())
+ {
+ Serial.println("MQTT connected - OK !");
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+//===========================================
+// подключение к WiFi
+bool setupWiFi()
+{
+ digitalWrite(LED_BUILTIN, LOW);
+ Serial.println("\n\nSetup WiFi: ");
+
+ WiFi.begin(ssid, pass);
+ uint8_t count = NUMBER_OF_ATTEMPTS;
+ while (WiFi.status() != WL_CONNECTED)
+ {
+ Serial.print(count);
+ Serial.print('>');
+ if (!count--)
+ return false;
+ delay(500);
+ }
+ digitalWrite(LED_BUILTIN, HIGH);
+
+ //-----------------------------------
+ // индикация IP
+ Serial.print("\nWiFi connected !\nIP: ");
+ Serial.println(WiFi.localIP());
+
+ //-----------------------------------
+ // индикация силы сигнала
+ int8_t RSSI_MAX = -50;
+ int8_t RSSI_MIN = -100;
+ int8_t dBm = WiFi.RSSI();
+ Serial.print("RSSI dBm = ");
+ Serial.println(dBm);
+ String l = "";
+ (dBm <= RSSI_MIN) ? l += 0 : (dBm >= RSSI_MAX) ? l += 100
+ : l += 2 * (dBm + 100);
+ Serial.print("RSSI % = ");
+ Serial.println(l);
+
+ return true;
+}
+
+//===========================================
+// синхронизация с NTP:
+bool syncNTP()
+{
+ Serial.println("\nСинхронизируем время: ");
+ uint8_t count = NUMBER_OF_ATTEMPTS;
+ while (!timeClient.update())
+ {
+ Serial.print(count);
+ Serial.print('.');
+ if (!count--)
+ return false;
+ delay(500);
+ }
+ Serial.println(timeClient.getFormattedTime());
+
+ return true;
+}
+
+//===========================================
+// Проверка валидности времени:
+bool isTimeValid()
+{
+ // Проверяем, что время получено (не эпоха 1970 года)
+ return timeClient.getEpochTime() > 1000000;
+}
+
+bool calculateRelayState()
+{
+ uint8_t h = timeClient.getHours();
+ uint8_t m = timeClient.getMinutes();
+
+ // Дневной режим
+ if (h >= DAY_START_HOUR && h < NIGHT_START_HOUR)
+ {
+ return (m >= DAY_START_MINUTE &&
+ m < DAY_START_MINUTE + DAY_WORK_MINUTES);
+ }
+
+ // Ночной режим
+ if (m < NIGHT_WORK_MINUTES) // Первый интервал
+ return true;
+
+ if (m >= NIGHT_INTERVAL2_START &&
+ m < NIGHT_INTERVAL2_START + NIGHT_WORK_MINUTES) // Второй интервал
+ return true;
+
+ return false;
+}
+
+void controlRelay()
+{
+ static bool lastRelayState = false;
+ bool newRelayState = calculateRelayState();
+
+ if (newRelayState != lastRelayState)
+ {
+ if (setupMQTT())
+ {
+ mqttDataOut(newRelayState);
+ Serial.println("Данные успешно отправлены");
+ }
+ digitalWrite(PIN_RELAY, newRelayState ? HIGH : LOW);
+ Serial.printf("Реле %s в %02d:%02d\n",
+ newRelayState ? "ВКЛ" : "ВЫКЛ",
+ timeClient.getHours(),
+ timeClient.getMinutes());
+ lastRelayState = newRelayState;
+ }
+}
+
+// void goToDeepSleep()
+// {
+// Serial.println("Переход в глубокий сон на 1 минуту...");
+// server.close(); // Закрываем сервер перед сном
+// delay(100);
+// // Настраиваем пробуждение через TIME_SLEEP миллисекунд
+// ESP.deepSleep(TIME_SLEEP * 1000); // deepSleep принимает микросекунды!
+// }
+
+//===========================================
+void setup()
+{
+ Serial.begin(115200);
+
+ pinMode(PIN_RELAY, OUTPUT);
+ digitalWrite(PIN_RELAY, LOW);
+
+ timeClient.begin();
+
+ server.begin();
+ httpUpdater.setup(&server);
+
+ lastSync = millis();
+}
+
+//===========================================
+void loop()
+{
+ // Синхронизация времени
+ if (millis() - lastSync >= SYNC_INTERVAL_MS || flagBegining)
+ {
+ if (setupWiFi())
+ {
+ if (syncNTP())
+ {
+ Serial.println("Время успешно синхронизировано");
+ }
+ }
+
+ // Всегда отключаем Wi-Fi после синхронизации
+ // WiFi.disconnect();
+ // delay(100);
+ // WiFi.mode(WIFI_OFF);
+ // Serial.println("\nWi-Fi отключен для экономии энергии");
+
+ lastSync = millis();
+ flagBegining = false;
+ }
+
+ // Управление реле только если время валидно
+ if (isTimeValid())
+ {
+ controlRelay();
+ }
+
+ // if (!flagBegining && WiFi.getMode() == WIFI_OFF)
+ // {
+ // goToDeepSleep();
+ // }
+
+ server.handleClient();
+ delay(10);
+}
+
+// if (millis() - lastSync >= utcPeriodMseconds || flagBegining)
+// {
+// if (setupWiFi())
+// syncNTP();
+// WiFi.disconnect(); // Отключаемся от роутера
+// delay(100); // Небольшая задержка для завершения процесса
+// WiFi.mode(WIFI_OFF); // Полностью выключаем Wi-Fi
+// Serial.println("Wi-Fi отключен.");
+// lastSync = millis();
+// }
+
+// //-----------------------------
+// // Работа по дневному тарифу:
+// if (timeClient.getHours() >= TIME_DAY && timeClient.getHours() < TIME_NIGHT)
+// {
+// if (timeClient.getMinutes() >= TIME_BEGINNING_DAY && timeClient.getMinutes() < TIME_BEGINNING_DAY + TIME_WORK_DAY_MINUT)
+// digitalWrite(PIN_RELAY, HIGH);
+// }
+// else
+// {
+// digitalWrite(PIN_RELAY, LOW);
+// }
+
+// //-----------------------------
+// // Работа по ночному тарифу:
+// if (timeClient.getHours() >= TIME_NIGHT && timeClient.getHours() < TIME_DAY)
+// {
+// if (timeClient.getMinutes() >= 0 && timeClient.getMinutes() < TIME_WORK_NIGHT_MINUT)
+// {
+// digitalWrite(PIN_RELAY, HIGH);
+// }
+// else
+// {
+// digitalWrite(PIN_RELAY, LOW);
+// }
+
+// if (timeClient.getMinutes() >= 40 && timeClient.getMinutes() < 40 + TIME_WORK_NIGHT_MINUT)
+// {
+// digitalWrite(PIN_RELAY, HIGH);
+// }
+// else
+// {
+// digitalWrite(PIN_RELAY, LOW);
+// }
+// }
+
+// server.handleClient();
+// delay(10);
+
+//===========================================