summaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
authorvlapa <vlapa@ya.ru>2026-07-12 19:44:52 +0300
committervlapa <vlapa@ya.ru>2026-07-12 19:44:52 +0300
commitbe16e5977cbf78bddfb8fb65e110afdeac4b2072 (patch)
tree7a842b3e83b68a66f1aa7e8c1ce650cd643518e6 /src/main.cpp
Логгер напряжения для авто
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp459
1 files changed, 459 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..897d5b9
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,459 @@
+#include <Arduino.h>
+#include <WiFi.h>
+#include <HTTPClient.h>
+#include <SPIFFS.h>
+#include <NTPClient.h>
+#include <WiFiUdp.h>
+
+// Список сетей, к которым разрешено подключаться:
+const char *allowedNetworks[] = {"link", "M2000", "MikroTik-2"};
+// Соответствующие пароли:
+const char *networkPasswords[] = {"dkfgf#*12091997", "99887766", "dkfgf#*12091997"};
+const uint8_t networkCount = 3; // Количество сетей в списке
+
+const char *server_url = "http://89.110.92.137:8000/upload";
+
+const uint32_t utcOffsetInSeconds = 10800; // +3часа
+const uint32_t utcPeriodMseconds = 259200000; // 3сутки-259200000 // 1сутки-86400000;
+
+WiFiUDP ntpUDP;
+const char *timeSite = "ntp3.vniiftri.ru"; // "pool.ntp.org"
+NTPClient timeClient(ntpUDP, timeSite, utcOffsetInSeconds, utcPeriodMseconds);
+
+const uint16_t LOG_INTERVAL = 1000; // логируем раз в минуту (60000 мс)
+
+const uint8_t PIN_LED = 1;
+const uint8_t PIN_LED_MINUS = 3;
+const uint8_t PIN_VCC = 4;
+const uint8_t PIN_BUTTON = 9;
+const uint16_t BLINK_IN = 500;
+const uint16_t NUMBER_OF_ENTRIES = 1000; // кол-во записей в файле
+String chipId = "VCC_log";
+
+uint32_t lastLogTime = 0;
+
+const uint8_t countConnect = 20;
+const uint16_t countPause = 500;
+
+float voltage = 0;
+float voltageOld = 0;
+float difference = 0.1;
+uint32_t now = 0;
+
+bool flagButton = false;
+bool flagSendData = true;
+
+//===========================================
+// Форматирование SPIFS:
+void formatSPIFFS()
+{
+ Serial.println("Начинаю форматирование SPIFFS...");
+ if (SPIFFS.format())
+ {
+ Serial.println("Форматирование успешно завершено.");
+ }
+ else
+ {
+ Serial.println("Ошибка форматирования!");
+ }
+}
+
+// ======== ОТПРАВКА ФАЙЛОВ НА СЕРВЕР =======
+bool sendFileToServer(String fileName)
+{
+ HTTPClient http;
+ WiFiClient client;
+
+ // Открываем файл для чтения
+ File file = SPIFFS.open("/" + fileName, FILE_READ);
+ if (!file)
+ {
+ Serial.println("Не могу открыть файл");
+ return false;
+ }
+
+ // Читаем файл в строку (для небольших файлов)
+ String fileContent = file.readString();
+ file.close();
+
+ // Настраиваем HTTP запрос
+ http.begin(client, server_url);
+ http.addHeader("Content-Type", "text/csv");
+ http.addHeader("X-Device-ID", chipId);
+ http.addHeader("X-File-Name", fileName);
+
+ // Отправляем POST запрос
+ int httpCode = http.POST(fileContent);
+
+ bool success = (httpCode == 200 || httpCode == 201);
+ http.end();
+
+ return success;
+}
+
+void createCSVIfNeeded(String name)
+{
+ // String fileName = name;
+ if (!SPIFFS.exists("/" + name + ".csv"))
+ {
+ File file = SPIFFS.open("/" + name + ".csv", FILE_WRITE);
+ if (file)
+ {
+ // String timeTemp = "";
+ // if (timeClient.getHours() < 10)
+ // timeTemp += "0";
+ // timeTemp += timeClient.getHours();
+ // if (timeClient.getMinutes() < 10)
+ // timeTemp += "0";
+ // timeTemp += timeClient.getMinutes();
+ // if (timeClient.getSeconds() < 10)
+ // timeTemp += "0";
+ // timeTemp += timeClient.getSeconds();
+
+ // Serial.print(timeTemp);
+ // Serial.print(" - ");
+ // Serial.println(voltage);
+
+ // file.print(timeTemp);
+ // file.print(",");
+ file.println("ЛОГГЕР :"); //, temperature); // ,%.1f,%d current, temperature, state);
+ // voltageOld = voltage;
+ file.close();
+ Serial.println("Создан новый CSV файл с заголовком");
+ }
+ else
+ {
+ Serial.println("Ошибка создания CSV файла");
+ }
+ }
+}
+
+//===========================================
+void sendAllLogsToServer()
+{
+ File root = SPIFFS.open("/");
+ if (!root)
+ {
+ Serial.println("Не удалось открыть корневую директорию");
+ return;
+ }
+
+ File file = root.openNextFile();
+
+ while (file)
+ {
+ String fileName = file.name();
+
+ // Пропускаем директории
+ if (file.isDirectory())
+ {
+ file = root.openNextFile();
+ continue;
+ }
+
+ // Отправляем только CSV файлы
+ if (fileName.endsWith(".csv")) // && !fileName.startsWith("sent_"))
+ {
+ Serial.printf("Отправка %s... ", fileName.c_str());
+ if (sendFileToServer(fileName))
+ {
+ Serial.println("Успешно !");
+ SPIFFS.remove("/" + fileName);
+ voltageOld = 0;
+ }
+ else
+ {
+ Serial.println("Ошибка !");
+ createCSVIfNeeded(chipId);
+ }
+ }
+
+ file = root.openNextFile();
+ }
+ root.close();
+}
+
+// ======== ПРОВЕРКА И ОТПРАВКА ДАННЫХ ======
+bool connectToWiFi()
+{
+ digitalWrite(PIN_LED, HIGH);
+ WiFi.mode(WIFI_STA); // Явно устанавливаем режим станции
+ delay(100);
+ Serial.println("Начинаем сканирование WiFi:");
+ int n = WiFi.scanNetworks();
+ Serial.println("Сканирование завершено.");
+ if (n == 0)
+ {
+ Serial.println("Сетей не найдено.");
+ }
+ else
+ {
+ Serial.print("Найдено сетей: ");
+ Serial.println(n);
+ }
+
+ for (uint8_t i = 0; i < networkCount; ++i)
+ {
+ for (uint8_t k = 0; k < n; ++k)
+ {
+ String foundSSID = WiFi.SSID(k);
+ if (foundSSID.equals(allowedNetworks[i]))
+ {
+ WiFi.begin(allowedNetworks[i], networkPasswords[i]);
+ Serial.print("Подключение к WiFi:\n");
+
+ int attempts = 0;
+ while (WiFi.status() != WL_CONNECTED && attempts < 20)
+ {
+ Serial.print(n);
+ Serial.print(">");
+ attempts++;
+ delay(500);
+ }
+
+ if (WiFi.status() == WL_CONNECTED)
+ {
+ Serial.println("\nWi-Fi подключен!");
+ Serial.print("IP адрес: ");
+ Serial.println(WiFi.localIP());
+ Serial.print("RSSI: ");
+ Serial.print(WiFi.RSSI());
+ Serial.println(" dBm");
+ digitalWrite(PIN_LED, LOW);
+ return true;
+ }
+ else
+ {
+ Serial.println("\nОшибка подключения к Wi-Fi");
+ }
+ }
+ }
+ }
+ for (uint8_t i = 0; i < 30; ++i)
+ {
+ digitalWrite(PIN_LED, !digitalRead(PIN_LED));
+ delay(100);
+ }
+ digitalWrite(PIN_LED, LOW);
+
+ return false;
+}
+
+//===========================================
+// Проверить доступность интернета через ping:
+#include <ESP32Ping.h>
+
+bool checkInternetConnection()
+{
+ // Проверяем доступность Google DNS:
+ bool success = Ping.ping("8.8.8.8", 3);
+ // Или проверка по доменному имени:
+ // bool success = Ping.ping("google.com", 3);
+
+ if (success)
+ {
+ Serial.println("Интернет доступен!");
+ return true;
+ }
+ else
+ {
+ Serial.println("Нет доступа в интернет!");
+ return false;
+ }
+
+ return success;
+}
+
+//===========================================
+void checkAndSendData()
+{
+ Serial.println("Проверка наличия Wi-Fi сети...");
+
+ // Пробуем подключиться к Wi-Fi
+ if (connectToWiFi())
+ {
+ if (checkInternetConnection())
+ {
+ // Отправляем все накопленные файлы
+ sendAllLogsToServer();
+ }
+
+ // Отключаем Wi-Fi для экономии энергии
+ WiFi.disconnect(true);
+ WiFi.mode(WIFI_OFF);
+ Serial.println("Wi-Fi отключен для экономии энергии");
+ }
+ else
+ {
+ Serial.println("Пропускаем отправку данных - нет подключения к Wi-Fi");
+ WiFi.disconnect(true);
+ }
+}
+
+// ======== ЛОГГИРОВАНИЕ ДАННЫХ =============
+void logBatteryData()
+{
+ static uint32_t countData = 0;
+ static uint8_t number_of_measurements = 100;
+ uint32_t raw = 0;
+ for (uint8_t i = 0; i < number_of_measurements; ++i)
+ {
+ raw += analogRead(PIN_VCC);
+ }
+ voltage = (raw / number_of_measurements) * 4884 / 1000000.0;
+
+ // // Получаем время в секундах / 10 от старта
+ // unsigned long uptime = millis() / 1000;
+
+ // Открываем файл для добавления
+ File file = SPIFFS.open("/" + chipId + ".csv", FILE_APPEND);
+ if (!file)
+ {
+ Serial.println("Ошибка открытия файла для записи");
+ return;
+ }
+
+ // Записываем строку в CSV если разница больше или равна difference:
+ if (abs(voltage - voltageOld) >= difference)
+ {
+ String timeTemp = "";
+ if (timeClient.getHours() < 10)
+ timeTemp += "0";
+ timeTemp += timeClient.getHours();
+ if (timeClient.getMinutes() < 10)
+ timeTemp += "0";
+ timeTemp += timeClient.getMinutes();
+ if (timeClient.getSeconds() < 10)
+ timeTemp += "0";
+ timeTemp += timeClient.getSeconds();
+
+ Serial.print(timeTemp);
+ Serial.print(" - ");
+ Serial.println(voltage);
+
+ file.print(timeTemp);
+ file.print(",");
+ file.println(voltage); //, temperature); // ,%.1f,%d current, temperature, state);
+ file.close();
+ voltageOld = voltage;
+
+ if (countData >= NUMBER_OF_ENTRIES - 1)
+ {
+ countData = 0;
+ checkAndSendData();
+ }
+ else
+ {
+ countData++;
+ }
+ }
+}
+
+//===========================================
+void timeSinhro()
+{
+ connectToWiFi();
+ timeClient.begin();
+ if (!timeClient.update())
+ Serial.println("Время обновить не удалось !");
+ Serial.println(timeClient.getFormattedTime());
+ flagButton = true;
+}
+
+// ================== SETUP =================
+void setup()
+{
+ Serial.begin(115200);
+ Serial.println("\n\n=== Запуск устройства ===");
+
+ pinMode(PIN_LED, OUTPUT);
+ pinMode(PIN_LED_MINUS, OUTPUT);
+ digitalWrite(PIN_LED, HIGH);
+ digitalWrite(PIN_LED_MINUS, LOW);
+
+ // Получаем уникальный ID чипа для имени файла
+ // uint64_t mac = ESP.getEfuseMac();
+ // chipId = String((uint16_t)(mac >> 32), HEX) + String((uint32_t)mac, HEX);
+ // Serial.println("ChipID: " + chipId);
+
+ // Монтируем SPIFFS
+ if (!SPIFFS.begin(true))
+ {
+ Serial.println("SPIFFS Mount Failed - пробуем форматировать");
+ formatSPIFFS();
+ if (!SPIFFS.begin(true))
+ {
+ Serial.println("Критическая ошибка SPIFFS!");
+ return;
+ }
+ }
+
+ // Создаем заголовок CSV, если файл новый
+ createCSVIfNeeded(chipId);
+
+ Serial.println("Логгер запущен");
+ Serial.println("=================\n");
+
+ while (1)
+ {
+ if (millis() - lastLogTime >= BLINK_IN)
+ {
+ digitalWrite(PIN_LED, !digitalRead(PIN_LED));
+ lastLogTime = millis();
+ }
+
+ if (!digitalRead(PIN_BUTTON))
+ {
+ delay(50);
+ if (!digitalRead(PIN_BUTTON))
+ {
+ digitalWrite(PIN_LED, HIGH);
+ timeSinhro();
+ break;
+ }
+ }
+ }
+
+ digitalWrite(PIN_LED, LOW);
+ lastLogTime = millis();
+}
+
+// ================== LOOP ==================
+void loop()
+{
+ unsigned long now = millis();
+
+ // 1. Логируем данные по расписанию
+ if (now - lastLogTime >= LOG_INTERVAL)
+ {
+ lastLogTime = now;
+ logBatteryData();
+ }
+
+ // 2. Проверяем нажатие кнопки, подключаемся к Wi-Fi, отправляем данные
+ if (!digitalRead(PIN_BUTTON))
+ {
+ delay(50);
+ if (!digitalRead(PIN_BUTTON))
+ {
+ (!flagButton) ? timeSinhro() : checkAndSendData();
+
+ WiFi.disconnect(true);
+ WiFi.mode(WIFI_OFF);
+ }
+ }
+
+ static uint8_t hourOld = 0;
+ uint8_t hour = timeClient.getHours();
+
+ if (hour != hourOld)
+ flagSendData = true;
+
+ if (hour >= 10 && hour <= 20 && flagSendData)
+ {
+ checkAndSendData();
+ flagSendData = false;
+ }
+
+ delay(10);
+} \ No newline at end of file