mirror of
https://github.com/IoTManagerProject/IoTManager.git
synced 2026-03-26 14:12:16 +03:00
392 lines
14 KiB
C++
392 lines
14 KiB
C++
#include "Main.h"
|
||
#include <time.h>
|
||
#include "classes/IoTDB.h"
|
||
#include "utils/Statistic.h"
|
||
#include "classes/IoTBench.h"
|
||
#ifndef LIBRETINY
|
||
#include <Wire.h>
|
||
#endif
|
||
#include "DebugTrace.h"
|
||
#if defined(ESP32)
|
||
#include <esp_task_wdt.h>
|
||
#endif
|
||
#if defined(esp32s2_4mb) || defined(esp32s3_16mb)
|
||
#include <USB.h>
|
||
#endif
|
||
|
||
IoTScenario iotScen; // объект управления сценарием
|
||
|
||
String volStrForSave = "";
|
||
// unsigned long currentMillis; // это сдесь лишнее
|
||
// unsigned long prevMillis;
|
||
|
||
void elementsLoop() {
|
||
// передаем управление каждому элементу конфигурации для выполнения своих функций
|
||
for (std::list<IoTItem *>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
|
||
if (benchTaskItem) benchTaskItem->preTaskFunction((*it)->getID());
|
||
(*it)->loop();
|
||
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 // размер шага счетчика интервала доверия выполнения блока кода мкс
|
||
|
||
#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) {
|
||
#if defined(esp32_4mb) || defined(esp32_4mb3f) || defined(esp32_16mb) || defined(esp32cam_4mb)
|
||
initErrorMarkerId = id;
|
||
errorMarkerCounter = 0;
|
||
#endif
|
||
}
|
||
|
||
void stopErrorMarker(int id) {
|
||
#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
|
||
}
|
||
|
||
void setup() {
|
||
#if defined(esp32s2_4mb) || defined(esp32s3_16mb)
|
||
USB.begin();
|
||
#endif
|
||
#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
|
||
|
||
Serial.begin(115200);
|
||
Serial.flush();
|
||
//----------- Отладка EXCEPTION (функции с заглушками для отключения) ---------
|
||
#if defined(RESTART_DEBUG_INFO)
|
||
//Привязка коллбэк функции для вызова при перезагрузке
|
||
esp_register_shutdown_handler(debugUpdate);
|
||
#endif // RESTART_DEBUG_INFO
|
||
// Печать или оправка отладочной информации
|
||
printDebugTrace();
|
||
startWatchDog();
|
||
Serial.println();
|
||
Serial.println(F("--------------started----------------"));
|
||
|
||
// создание экземпляров классов
|
||
// myNotAsyncActions = new NotAsync(do_LAST);
|
||
|
||
// инициализация файловой системы
|
||
fileSystemInit();
|
||
Serial.println(F("------------------------"));
|
||
Serial.println("FIRMWARE NAME " + String(FIRMWARE_NAME));
|
||
Serial.println("FIRMWARE VERSION " + String(FIRMWARE_VERSION));
|
||
Serial.println("WEB VERSION " + getWebVersion());
|
||
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("------------------------"));
|
||
|
||
// получение chip id
|
||
setChipId();
|
||
|
||
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);
|
||
#elif defined(ESP8266)
|
||
Wire.begin(pinSDA, pinSCL);
|
||
Wire.setClock(i2cFreq);
|
||
#endif
|
||
SerialPrint("i", "i2c", F("i2c pins overriding done"));
|
||
}
|
||
#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;
|
||
}
|
||
if (bootloop_panic_count >= 3)
|
||
{
|
||
resetSettingsFlashByPanic();
|
||
bootloop_panic_count = -1;
|
||
}
|
||
if (bootloop_panic_count == -1)
|
||
{
|
||
SerialPrint("E", "CORE", F("CONFIG and SCENARIO reset !!!"));
|
||
bootloop_panic_count = 0;
|
||
ESP.restart();
|
||
}
|
||
#endif // RESTART_DEBUG_INFO
|
||
// настраиваем микроконтроллер
|
||
configure("/config.json");
|
||
|
||
stopErrorMarker(SETUPCONF_ERRORMARKER);
|
||
|
||
initErrorMarker(SETUPSCEN_ERRORMARKER);
|
||
|
||
// подготавливаем сценарии
|
||
iotScen.loadScenario("/scenario.txt");
|
||
// создаем событие завершения инициализации основных моментов для возможности выполнения блока кода при загрузке
|
||
createItemFromNet("onInit", "1", 1);
|
||
// elementsLoop(); //Для работы MQTT Брокера перенес ниже, иначе брокер падает если вызван до routerConnect();
|
||
|
||
stopErrorMarker(SETUPSCEN_ERRORMARKER);
|
||
|
||
initErrorMarker(SETUPINET_ERRORMARKER);
|
||
|
||
// подключаемся к роутеру
|
||
#ifdef ESP8266
|
||
routerConnect();
|
||
#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);
|
||
|
||
bool postMsgTelegram;
|
||
if (!jsonRead(settingsFlashJson, "debugTraceMsgTlgrm", postMsgTelegram, false)) postMsgTelegram = 1;
|
||
sendDebugTraceAndFreeMemory(postMsgTelegram);
|
||
|
||
initErrorMarker(SETUPLAST_ERRORMARKER);
|
||
|
||
elementsLoop();
|
||
// NTP
|
||
ntpInit();
|
||
|
||
// инициализация задач переодического выполнения
|
||
periodicTasksInit();
|
||
|
||
#if defined(ESP8266)
|
||
// Перенесли после получения IP, так как теперь работа WiFi асинхронная
|
||
// запуск работы udp
|
||
addThisDeviceToList();
|
||
#ifdef UDP_ENABLED
|
||
udpListningInit();
|
||
udpBroadcastInit();
|
||
#endif
|
||
#endif
|
||
// создаем событие завершения конфигурирования для возможности выполнения блока кода при загрузке
|
||
createItemFromNet("onStart", "1", 1);
|
||
|
||
stInit();
|
||
|
||
// настраиваем секундные обслуживания системы
|
||
ts.add(
|
||
TIMES, 1000, [&](void *) {
|
||
// сброс WDT
|
||
#if defined(ESP32)
|
||
//SerialPrint("i", "Task", "reset wdt");
|
||
#if !defined(esp32c6_4mb) && !defined(esp32c6_8mb) //TODO esp32-c6 переписать esp_task_wdt_init
|
||
esp_task_wdt_reset();
|
||
#endif
|
||
#endif
|
||
// сохраняем значения IoTItems в файл каждую секунду, если были изменения (установлены маркеры на сохранение)
|
||
if (needSaveValues) {
|
||
syncValuesFlashJson();
|
||
needSaveValues = false;
|
||
}
|
||
|
||
// проверяем все элементы на тухлость
|
||
for (std::list<IoTItem *>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
|
||
(*it)->checkIntFromNet();
|
||
|
||
// Serial.printf("[ITEM] size: %d, id: %s, int: %d, intnet: %d\n", sizeof(**it), (*it)->getID(), (*it)->getInterval(), (*it)->getIntFromNet());
|
||
}
|
||
},
|
||
nullptr, true);
|
||
|
||
// ловим пинги от WS (2сек) и дисконнектим если их нет 3 раза 3сек*2прохода = 6сек
|
||
ts.add(
|
||
PiWS, 3000, [&](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);
|
||
#if defined(RESTART_DEBUG_INFO)
|
||
bootloop_panic_count = 0;
|
||
#endif // RESTART_DEBUG_INFO
|
||
}
|
||
|
||
void loop() {
|
||
#if !defined(ESP8266)
|
||
static bool udpFirstFlag = true;
|
||
// Перенесли после получения IP, так как теперь работа WiFi асинхронная
|
||
if (isNetworkActive() && udpFirstFlag) {
|
||
udpFirstFlag = false;
|
||
// запуск работы udp
|
||
addThisDeviceToList();
|
||
#ifdef UDP_ENABLED
|
||
udpListningInit();
|
||
udpBroadcastInit();
|
||
#endif
|
||
}
|
||
#endif
|
||
|
||
#ifdef LOOP_DEBUG
|
||
unsigned long st = millis();
|
||
#endif
|
||
if (benchLoadItem) benchLoadItem->preLoadFunction();
|
||
if (benchTaskItem) benchTaskItem->preTaskFunction("TickerScheduler");
|
||
initErrorMarker(TICKER_ERRORMARKER);
|
||
ts.update();
|
||
stopErrorMarker(TICKER_ERRORMARKER);
|
||
if (benchTaskItem) benchTaskItem->postTaskFunction("TickerScheduler");
|
||
if (benchTaskItem) benchTaskItem->preTaskFunction("webServer");
|
||
#ifdef STANDARD_WEB_SERVER
|
||
initErrorMarker(HTTP_ERRORMARKER);
|
||
HTTP.handleClient();
|
||
stopErrorMarker(HTTP_ERRORMARKER);
|
||
#endif
|
||
if (benchTaskItem) benchTaskItem->postTaskFunction("webServer");
|
||
if (benchTaskItem) benchTaskItem->preTaskFunction("webSocket");
|
||
#ifdef STANDARD_WEB_SOCKETS
|
||
initErrorMarker(SOCKETS_ERRORMARKER);
|
||
standWebSocket.loop();
|
||
stopErrorMarker(SOCKETS_ERRORMARKER);
|
||
#endif
|
||
if (benchTaskItem) benchTaskItem->postTaskFunction("webSocket");
|
||
if (benchTaskItem) benchTaskItem->preTaskFunction("mqtt");
|
||
initErrorMarker(MQTT_ERRORMARKER);
|
||
mqttLoop();
|
||
stopErrorMarker(MQTT_ERRORMARKER);
|
||
if (benchTaskItem) benchTaskItem->postTaskFunction("mqtt");
|
||
initErrorMarker(MODULES_ERRORMARKER);
|
||
elementsLoop();
|
||
stopErrorMarker(MODULES_ERRORMARKER);
|
||
if (benchLoadItem) benchLoadItem->postLoadFunction();
|
||
// #ifdef LOOP_DEBUG
|
||
// loopPeriod = millis() - st;
|
||
// if (loopPeriod > 2) Serial.println(loopPeriod);
|
||
// #endif
|
||
}
|
||
|
||
// отправка json
|
||
// #ifdef QUEUE_FROM_STR
|
||
// if (sendJsonFiles) sendJsonFiles->loop();
|
||
// #endif
|
||
|
||
// 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"));
|