diff options
Diffstat (limited to 'src/main.cpp')
| -rw-r--r-- | src/main.cpp | 459 |
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 |
