Files
IoTManager/src/Main.cpp

392 lines
13 KiB
C++
Raw Normal View History

#include "Main.h"
#include <time.h>
#include "classes/IoTDB.h"
#include "utils/Statistic.h"
2024-03-16 19:47:18 +03:00
#include "classes/IoTBench.h"
2024-09-20 12:45:17 +03:00
#ifndef LIBRETINY
#include <Wire.h>
2024-09-20 12:45:17 +03:00
#endif
2024-09-20 11:07:08 +03:00
#include "DebugTrace.h"
2024-11-16 15:00:04 +03:00
#if defined(ESP32)
#include <esp_task_wdt.h>
#endif
2023-10-17 22:21:13 +03:00
#if defined(esp32s2_4mb) || defined(esp32s3_16mb)
#include <USB.h>
#endif
2021-12-22 14:09:50 +01:00
IoTScenario iotScen; // объект управления сценарием
String volStrForSave = "";
// unsigned long currentMillis; // это сдесь лишнее
// unsigned long prevMillis;
void elementsLoop() {
// передаем управление каждому элементу конфигурации для выполнения своих функций
for (std::list<IoTItem *>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
2024-02-26 23:29:02 +03:00
if (benchTaskItem) benchTaskItem->preTaskFunction((*it)->getID());
(*it)->loop();
2024-02-26 23:29:02 +03:00
if (benchTaskItem) benchTaskItem->postTaskFunction((*it)->getID());
// if ((*it)->iAmDead) {
if (!((*it)->iAmLocal) && (*it)->getIntFromNet() == -1) {
delete *it;
IoTItems.erase(it);
break;
}
}
handleOrder();
handleEvent();
}
#define SETUPBASE_ERRORMARKER 0
#define SETUPCONF_ERRORMARKER 1
#define SETUPSCEN_ERRORMARKER 2
#define SETUPINET_ERRORMARKER 3
#define SETUPLAST_ERRORMARKER 4
#define TICKER_ERRORMARKER 5
#define HTTP_ERRORMARKER 6
#define SOCKETS_ERRORMARKER 7
#define MQTT_ERRORMARKER 8
#define MODULES_ERRORMARKER 9
#define COUNTER_ERRORMARKER 4 // количество шагов счетчика
#define STEPPER_ERRORMARKER 100000 // размер шага счетчика интервала доверия выполнения блока кода мкс
2024-11-26 23:30:16 +03:00
#if defined(esp32_4mb) || defined(esp32_4mb3f) || defined(esp32_16mb) || defined(esp32cam_4mb)
static int IRAM_ATTR initErrorMarkerId = 0; // ИД маркера
static int IRAM_ATTR errorMarkerId = 0;
static int IRAM_ATTR errorMarkerCounter = 0;
hw_timer_t *My_timer = NULL;
void IRAM_ATTR onTimer() {
if (errorMarkerCounter >= 0) {
if (errorMarkerCounter >= COUNTER_ERRORMARKER) {
errorMarkerId = initErrorMarkerId;
errorMarkerCounter = -1;
} else
errorMarkerCounter++;
}
}
#endif
void initErrorMarker(int id) {
2024-11-26 23:30:16 +03:00
#if defined(esp32_4mb) || defined(esp32_4mb3f) || defined(esp32_16mb) || defined(esp32cam_4mb)
initErrorMarkerId = id;
errorMarkerCounter = 0;
#endif
}
void stopErrorMarker(int id) {
2024-11-26 23:30:16 +03:00
#if defined(esp32_4mb) || defined(esp32_4mb3f) || defined(esp32_16mb) || defined(esp32cam_4mb)
errorMarkerCounter = -1;
if (errorMarkerId)
SerialPrint("I", "WARNING!", "A lazy (freezing loop more than " + (String)(COUNTER_ERRORMARKER * STEPPER_ERRORMARKER / 1000) + " ms) section has been found! With ID=" + (String)errorMarkerId);
errorMarkerId = 0;
initErrorMarkerId = 0;
#endif
}
2021-12-22 14:09:50 +01:00
void setup() {
2023-10-17 22:21:13 +03:00
#if defined(esp32s2_4mb) || defined(esp32s3_16mb)
USB.begin();
2023-06-20 21:47:29 +02:00
#endif
2024-11-26 23:30:16 +03:00
#if defined(esp32_4mb) || defined(esp32_4mb3f) || defined(esp32_16mb) || defined(esp32cam_4mb)
My_timer = timerBegin(0, 80, true);
timerAttachInterrupt(My_timer, &onTimer, true);
timerAlarmWrite(My_timer, STEPPER_ERRORMARKER, true);
timerAlarmEnable(My_timer);
// timerAlarmDisable(My_timer);
initErrorMarker(SETUPBASE_ERRORMARKER);
#endif
2021-12-22 14:09:50 +01:00
Serial.begin(115200);
Serial.flush();
2024-09-20 11:07:08 +03:00
//----------- Отладка EXCEPTION (функции с заглушками для отключения) ---------
2024-11-22 22:45:10 +03:00
#if defined(RESTART_DEBUG_INFO)
2024-09-20 11:07:08 +03:00
//Привязка коллбэк функции для вызова при перезагрузке
esp_register_shutdown_handler(debugUpdate);
2024-11-16 15:00:04 +03:00
#endif // RESTART_DEBUG_INFO
2024-09-20 11:07:08 +03:00
// Печать или оправка отладочной информации
printDebugTrace();
startWatchDog();
2021-12-22 14:09:50 +01:00
Serial.println();
Serial.println(F("--------------started----------------"));
// создание экземпляров классов
// myNotAsyncActions = new NotAsync(do_LAST);
// инициализация файловой системы
2021-12-22 14:09:50 +01:00
fileSystemInit();
Serial.println(F("------------------------"));
Serial.println("FIRMWARE NAME " + String(FIRMWARE_NAME));
Serial.println("FIRMWARE VERSION " + String(FIRMWARE_VERSION));
Serial.println("WEB VERSION " + getWebVersion());
2023-06-20 21:47:29 +02:00
const String buildTime = String(BUILD_DAY) + "." + String(BUILD_MONTH) + "." + String(BUILD_YEAR) + " " + String(BUILD_HOUR) + ":" + String(BUILD_MIN) + ":" + String(BUILD_SEC);
Serial.println("BUILD TIME " + buildTime);
jsonWriteStr_(errorsHeapJson, F("bt"), buildTime);
Serial.println(F("------------------------"));
2021-12-22 14:09:50 +01:00
// получение chip id
setChipId();
2024-09-20 12:05:34 +03:00
verifyFirmware();
// синхронизация глобальных переменных с flash
globalVarsSync();
stopErrorMarker(SETUPBASE_ERRORMARKER);
initErrorMarker(SETUPCONF_ERRORMARKER);
// настраиваем i2c шину
int i2c, pinSCL, pinSDA, i2cFreq;
jsonRead(settingsFlashJson, "pinSCL", pinSCL, false);
jsonRead(settingsFlashJson, "pinSDA", pinSDA, false);
jsonRead(settingsFlashJson, "i2cFreq", i2cFreq, false);
jsonRead(settingsFlashJson, "i2c", i2c, false);
jsonWriteStr_(ssidListHeapJson, "0", "Scaning...");
if (i2c != 0) {
#ifdef ESP32
Wire.end();
Wire.begin(pinSDA, pinSCL, (uint32_t)i2cFreq);
2024-09-20 12:45:17 +03:00
#elif defined(ESP8266)
Wire.begin(pinSDA, pinSCL);
Wire.setClock(i2cFreq);
#endif
SerialPrint("i", "i2c", F("i2c pins overriding done"));
}
2024-11-22 22:45:10 +03:00
#if defined(RESTART_DEBUG_INFO)
esp_reset_reason_t esp_reason = esp_reset_reason();
if (esp_reason == ESP_RST_UNKNOWN || esp_reason == ESP_RST_POWERON)
bootloop_panic_count = 0;
/* else if (bootloop_panic_count == 3 || bootloop_panic_count == 0 ) bootloop_panic_count = 1;
else if (bootloop_panic_count == 2) bootloop_panic_count = 3;
else if (bootloop_panic_count == 1) bootloop_panic_count = 2;
else bootloop_panic_count = 0; */
Serial.println("bootloop_panic_count " + String(bootloop_panic_count));
if (bootloop_panic_count >3 )
{
//resetSettingsFlashByPanic();
bootloop_panic_count = 0;
}
2024-09-20 12:05:34 +03:00
if (bootloop_panic_count >= 3)
{
resetSettingsFlashByPanic();
bootloop_panic_count = -1;
}
if (bootloop_panic_count == -1)
2024-09-21 11:28:46 +03:00
{
2024-09-20 12:05:34 +03:00
SerialPrint("E", "CORE", F("CONFIG and SCENARIO reset !!!"));
2024-09-21 11:28:46 +03:00
bootloop_panic_count = 0;
2024-11-17 17:15:49 +03:00
ESP.restart();
}
2024-11-16 15:00:04 +03:00
#endif // RESTART_DEBUG_INFO
// настраиваем микроконтроллер
configure("/config.json");
stopErrorMarker(SETUPCONF_ERRORMARKER);
initErrorMarker(SETUPSCEN_ERRORMARKER);
// подготавливаем сценарии
iotScen.loadScenario("/scenario.txt");
// создаем событие завершения инициализации основных моментов для возможности выполнения блока кода при загрузке
createItemFromNet("onInit", "1", 1);
2024-02-26 23:29:02 +03:00
// elementsLoop(); //Для работы MQTT Брокера перенес ниже, иначе брокер падает если вызван до routerConnect();
stopErrorMarker(SETUPSCEN_ERRORMARKER);
initErrorMarker(SETUPINET_ERRORMARKER);
2024-02-26 23:29:02 +03:00
// подключаемся к роутеру
2025-02-15 00:20:44 +03:00
#ifdef ESP8266
routerConnect();
2025-02-15 00:20:44 +03:00
#else
WiFiUtilsItit();
#endif
// инициализация асинхронного веб сервера и веб сокетов
#ifdef ASYNC_WEB_SERVER
asyncWebServerInit();
#endif
#ifdef ASYNC_WEB_SOCKETS
asyncWebSocketsInit();
#endif
// инициализация стандартного веб сервера и веб сокетов
#ifdef STANDARD_WEB_SERVER
standWebServerInit();
#endif
#ifdef STANDARD_WEB_SOCKETS
standWebSocketsInit();
#endif
stopErrorMarker(SETUPINET_ERRORMARKER);
2024-09-20 11:07:08 +03:00
bool postMsgTelegram;
2024-11-30 21:11:02 +03:00
if (!jsonRead(settingsFlashJson, "debugTraceMsgTlgrm", postMsgTelegram, false)) postMsgTelegram = 1;
2024-09-20 11:07:08 +03:00
sendDebugTraceAndFreeMemory(postMsgTelegram);
initErrorMarker(SETUPLAST_ERRORMARKER);
2024-02-26 23:29:02 +03:00
elementsLoop();
// NTP
ntpInit();
// инициализация задач переодического выполнения
periodicTasksInit();
2025-02-17 20:49:33 +03:00
#if defined(ESP8266)
// Перенесли после получения IP, так как теперь работа WiFi асинхронная
// запуск работы udp
addThisDeviceToList();
2024-09-20 12:45:17 +03:00
#ifdef UDP_ENABLED
udpListningInit();
udpBroadcastInit();
2024-09-20 12:45:17 +03:00
#endif
2025-02-17 20:49:33 +03:00
#endif
// создаем событие завершения конфигурирования для возможности выполнения блока кода при загрузке
createItemFromNet("onStart", "1", 1);
stInit();
// настраиваем секундные обслуживания системы
ts.add(
2022-11-22 15:07:29 +01:00
TIMES, 1000, [&](void *) {
2024-11-16 15:00:04 +03:00
// сброс WDT
#if defined(ESP32)
2024-11-20 00:22:55 +03:00
//SerialPrint("i", "Task", "reset wdt");
#if !defined(esp32c6_4mb) && !defined(esp32c6_8mb) //TODO esp32-c6 переписать esp_task_wdt_init
2024-11-16 15:00:04 +03:00
esp_task_wdt_reset();
#endif
2024-11-16 15:00:04 +03:00
#endif
// сохраняем значения IoTItems в файл каждую секунду, если были изменения (установлены маркеры на сохранение)
if (needSaveValues) {
syncValuesFlashJson();
needSaveValues = false;
}
2022-11-22 15:07:29 +01:00
// проверяем все элементы на тухлость
for (std::list<IoTItem *>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
(*it)->checkIntFromNet();
2022-11-22 15:07:29 +01:00
// Serial.printf("[ITEM] size: %d, id: %s, int: %d, intnet: %d\n", sizeof(**it), (*it)->getID(), (*it)->getInterval(), (*it)->getIntFromNet());
}
},
2022-11-22 15:07:29 +01:00
nullptr, true);
// ловим пинги от WS (5сек) и дисконнектим если их нет (20сек)
ts.add(
PiWS, 6000, [&](void*) {
if (isNetworkActive()) {
for (size_t i = 0; i < WEBSOCKETS_CLIENT_MAX; i++)
{
if (ws_clients[i] == 0) {
disconnectWSClient(i);
ws_clients[i]=-1;
}
if (ws_clients[i] > 0) {
ws_clients[i]=0;
}
}
}
},
nullptr, true);
// test
//Serial.println("-------test start--------");
//Serial.println("--------test end---------");
stopErrorMarker(SETUPLAST_ERRORMARKER);
2024-11-22 22:45:10 +03:00
#if defined(RESTART_DEBUG_INFO)
2024-09-20 12:05:34 +03:00
bootloop_panic_count = 0;
2024-11-16 15:00:04 +03:00
#endif // RESTART_DEBUG_INFO
2021-12-22 14:09:50 +01:00
}
void loop() {
2025-02-17 20:49:33 +03:00
#if !defined(ESP8266)
static bool udpFirstFlag = true;
// Перенесли после получения IP, так как теперь работа WiFi асинхронная
if (isNetworkActive() && udpFirstFlag) {
udpFirstFlag = false;
// запуск работы udp
addThisDeviceToList();
#ifdef UDP_ENABLED
udpListningInit();
udpBroadcastInit();
#endif
}
#endif
2022-10-12 03:14:55 +02:00
#ifdef LOOP_DEBUG
unsigned long st = millis();
#endif
2024-02-26 23:29:02 +03:00
if (benchLoadItem) benchLoadItem->preLoadFunction();
if (benchTaskItem) benchTaskItem->preTaskFunction("TickerScheduler");
initErrorMarker(TICKER_ERRORMARKER);
2021-12-23 17:55:46 +01:00
ts.update();
stopErrorMarker(TICKER_ERRORMARKER);
2024-02-26 23:29:02 +03:00
if (benchTaskItem) benchTaskItem->postTaskFunction("TickerScheduler");
if (benchTaskItem) benchTaskItem->preTaskFunction("webServer");
#ifdef STANDARD_WEB_SERVER
initErrorMarker(HTTP_ERRORMARKER);
HTTP.handleClient();
stopErrorMarker(HTTP_ERRORMARKER);
#endif
2024-02-26 23:29:02 +03:00
if (benchTaskItem) benchTaskItem->postTaskFunction("webServer");
if (benchTaskItem) benchTaskItem->preTaskFunction("webSocket");
#ifdef STANDARD_WEB_SOCKETS
initErrorMarker(SOCKETS_ERRORMARKER);
standWebSocket.loop();
stopErrorMarker(SOCKETS_ERRORMARKER);
#endif
2024-02-26 23:29:02 +03:00
if (benchTaskItem) benchTaskItem->postTaskFunction("webSocket");
if (benchTaskItem) benchTaskItem->preTaskFunction("mqtt");
initErrorMarker(MQTT_ERRORMARKER);
2022-01-15 19:11:01 +01:00
mqttLoop();
stopErrorMarker(MQTT_ERRORMARKER);
2024-02-26 23:29:02 +03:00
if (benchTaskItem) benchTaskItem->postTaskFunction("mqtt");
initErrorMarker(MODULES_ERRORMARKER);
elementsLoop();
stopErrorMarker(MODULES_ERRORMARKER);
2024-02-26 23:29:02 +03:00
if (benchLoadItem) benchLoadItem->postLoadFunction();
2022-11-22 15:07:29 +01:00
// #ifdef LOOP_DEBUG
// loopPeriod = millis() - st;
// if (loopPeriod > 2) Serial.println(loopPeriod);
// #endif
2021-12-22 14:09:50 +01:00
}
// отправка json
// #ifdef QUEUE_FROM_STR
// if (sendJsonFiles) sendJsonFiles->loop();
// #endif
2022-10-12 03:14:55 +02:00
// if(millis()%2000==0){
// //watch->settimeUnix(time(&iotTimeNow));
// Serial.println(watch->gettime("d-m-Y, H:i:s, M"));
// delay(1);
// }
// File dir = FileFS.open("/", "r");
// String out;
// printDirectory(dir, out);
// Serial.println(out);
//=======проверка очереди из структур=================
// myDB = new IoTDB;
// QueueItems myItem;
// myItem.myword = "word1";
// myDB->push(myItem);
// myItem.myword = "word2";
// myDB->push(myItem);
// myItem.myword = "word3";
// myDB->push(myItem);
// Serial.println(myDB->front().myword);
// Serial.println(myDB->front().myword);
// Serial.println(myDB->front().myword);
// Serial.println(FileList("lg"));