Boot phase: Add more error handling + provide verbose output in error cases (#2020)

* WLAN: add error handling

* WLAN: parameter global struct

* WLAN.ini -> more info text

* RSSIThreshold

* Rename logs

* Boot process: error handling

* Update texts

* Comments

* Init sequence

* Prepare for check dir creation

* add check makedir, update logs

* Blink code for OTA+SoftAP

* Blink code for missing time snyc

* Update

* reboot -> switch LED off

* Update log texts

* Update

* Update log texts

* create empty default folders at startup

* Update

* Adapt log level

* Print log level switch

* Update

* Update text

* Add SD free space to log

* WIFI/MQTT disconnect message set to WARN (+ ERROR)
This commit is contained in:
Slider0007
2023-02-25 21:12:52 +01:00
committed by GitHub
parent a8f8189543
commit 7a9f61a8d8
25 changed files with 1101 additions and 747 deletions

View File

@@ -7,6 +7,7 @@
#include "esp_log.h" #include "esp_log.h"
#include "Helper.h" #include "Helper.h"
#include "statusled.h"
#include "CImageBasis.h" #include "CImageBasis.h"
#include "server_ota.h" #include "server_ota.h"
@@ -557,15 +558,17 @@ void CCamera::LightOnOff(bool status)
void CCamera::LEDOnOff(bool status) void CCamera::LEDOnOff(bool status)
{ {
// Init the GPIO if (xHandle_task_StatusLED == NULL) {
gpio_pad_select_gpio(BLINK_GPIO); // Init the GPIO
/* Set the GPIO as a push/pull output */ gpio_pad_select_gpio(BLINK_GPIO);
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT); /* Set the GPIO as a push/pull output */
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
if (!status) if (!status)
gpio_set_level(BLINK_GPIO, 1); gpio_set_level(BLINK_GPIO, 1);
else else
gpio_set_level(BLINK_GPIO, 0); gpio_set_level(BLINK_GPIO, 0);
}
} }

View File

@@ -39,6 +39,7 @@
#include "ClassLogFile.h" #include "ClassLogFile.h"
#include "Helper.h" #include "Helper.h"
#include "statusled.h"
#include "../../include/defines.h" #include "../../include/defines.h"
/*an ota data write buffer ready to write to the flash*/ /*an ota data write buffer ready to write to the flash*/
@@ -66,6 +67,8 @@ static void infinite_loop(void)
void task_do_Update_ZIP(void *pvParameter) void task_do_Update_ZIP(void *pvParameter)
{ {
StatusLED(AP_OR_OTA, 1, true); // Signaling an OTA update
std::string filetype = toUpper(getFileType(_file_name_update)); std::string filetype = toUpper(getFileType(_file_name_update));
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "File: " + _file_name_update + " Filetype: " + filetype); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "File: " + _file_name_update + " Filetype: " + filetype);
@@ -87,13 +90,13 @@ void task_do_Update_ZIP(void *pvParameter)
ota_update_task(retfirmware); ota_update_task(retfirmware);
} }
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Trigger reboot due to firmware update."); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Trigger reboot due to firmware update");
doRebootOTA(); doRebootOTA();
} else if (filetype == "BIN") } else if (filetype == "BIN")
{ {
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Do firmware update - file: " + _file_name_update); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Do firmware update - file: " + _file_name_update);
ota_update_task(_file_name_update); ota_update_task(_file_name_update);
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Trigger reboot due to firmware update."); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Trigger reboot due to firmware update");
doRebootOTA(); doRebootOTA();
} }
else else
@@ -108,7 +111,7 @@ void CheckUpdate()
FILE *pfile; FILE *pfile;
if ((pfile = fopen("/sdcard/update.txt", "r")) == NULL) if ((pfile = fopen("/sdcard/update.txt", "r")) == NULL)
{ {
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "No update triggered."); LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "No pending update");
return; return;
} }
@@ -120,13 +123,14 @@ void CheckUpdate()
std::string _szw = std::string(zw); std::string _szw = std::string(zw);
if (_szw == "init") if (_szw == "init")
{ {
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Inital Setup triggered."); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Inital setup triggered");
initial_setup = true; } initial_setup = true;
}
} }
fclose(pfile); fclose(pfile);
DeleteFile("/sdcard/update.txt"); // Prevent Boot Loop!!! DeleteFile("/sdcard/update.txt"); // Prevent Boot Loop!!!
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Update during boot triggered - Update File: " + _file_name_update); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Start update process (" + _file_name_update + ")");
xTaskCreate(&task_do_Update_ZIP, "task_do_Update_ZIP", configMINIMAL_STACK_SIZE * 35, NULL, tskIDLE_PRIORITY+1, NULL); xTaskCreate(&task_do_Update_ZIP, "task_do_Update_ZIP", configMINIMAL_STACK_SIZE * 35, NULL, tskIDLE_PRIORITY+1, NULL);
@@ -586,6 +590,9 @@ void task_reboot(void *KillAutoFlow)
KillTFliteTasks(); // Kill autoflow task if executed in extra task, if not don't kill parent task KillTFliteTasks(); // Kill autoflow task if executed in extra task, if not don't kill parent task
} }
Camera.LightOnOff(false);
StatusLEDOff();
/* Stop service tasks */ /* Stop service tasks */
#ifdef ENABLE_MQTT #ifdef ENABLE_MQTT
MQTTdestroy_client(true); MQTTdestroy_client(true);
@@ -607,7 +614,7 @@ void task_reboot(void *KillAutoFlow)
void doReboot() void doReboot()
{ {
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Reboot triggered by Software (5s)."); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Reboot triggered by Software (5s)");
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Reboot in 5sec"); LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Reboot in 5sec");
BaseType_t xReturned = xTaskCreate(&task_reboot, "task_reboot", configMINIMAL_STACK_SIZE * 3, (void*) true, 10, NULL); BaseType_t xReturned = xTaskCreate(&task_reboot, "task_reboot", configMINIMAL_STACK_SIZE * 3, (void*) true, 10, NULL);
@@ -624,6 +631,8 @@ void doRebootOTA()
{ {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Reboot in 5sec"); LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Reboot in 5sec");
Camera.LightOnOff(false);
StatusLEDOff();
esp_camera_deinit(); esp_camera_deinit();
vTaskDelay(5000 / portTICK_PERIOD_MS); vTaskDelay(5000 / portTICK_PERIOD_MS);

View File

@@ -25,6 +25,7 @@ extern "C" {
#endif //ENABLE_MQTT #endif //ENABLE_MQTT
#include "server_help.h" #include "server_help.h"
#include "server_tflite.h"
#include "../../include/defines.h" #include "../../include/defines.h"
static const char* TAG = "CTRL"; static const char* TAG = "CTRL";
@@ -599,6 +600,10 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
{ {
LogFile.setLogLevel(ESP_LOG_DEBUG); LogFile.setLogLevel(ESP_LOG_DEBUG);
} }
/* If system reboot was not triggered by user and reboot was caused by execption -> keep log level to DEBUG */
if (!getIsPlannedReboot() && (esp_reset_reason() == ESP_RST_PANIC))
LogFile.setLogLevel(ESP_LOG_DEBUG);
} }
if ((toUpper(splitted[0]) == "LOGFILESRETENTION") && (splitted.size() > 1)) if ((toUpper(splitted[0]) == "LOGFILESRETENTION") && (splitted.size() > 1))
{ {
@@ -607,18 +612,21 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
/* TimeServer and TimeZone got already read from the config, see setupTime () */ /* TimeServer and TimeZone got already read from the config, see setupTime () */
#ifdef WLAN_USE_MESH_ROAMING
if ((toUpper(splitted[0]) == "RSSITHRESHOLD") && (splitted.size() > 1)) if ((toUpper(splitted[0]) == "RSSITHRESHOLD") && (splitted.size() > 1))
{ {
if (ChangeRSSIThreshold(WLAN_CONFIG_FILE, atoi(splitted[1].c_str()))) int RSSIThresholdTMP = atoi(splitted[1].c_str());
RSSIThresholdTMP = min(0, max(-100, RSSIThresholdTMP)); // Verify input limits (-100 - 0)
if (ChangeRSSIThreshold(WLAN_CONFIG_FILE, RSSIThresholdTMP))
{ {
// reboot necessary so that the new wlan.ini is also used !!! // reboot necessary so that the new wlan.ini is also used !!!
fclose(pfile); fclose(pfile);
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Rebooting to activate new RSSITHRESHOLD ..."); LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Rebooting to activate new RSSITHRESHOLD ...");
esp_restart();
hard_restart();
doReboot(); doReboot();
} }
} }
#endif
if ((toUpper(splitted[0]) == "HOSTNAME") && (splitted.size() > 1)) if ((toUpper(splitted[0]) == "HOSTNAME") && (splitted.size() > 1))
{ {
@@ -626,9 +634,7 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
{ {
// reboot necessary so that the new wlan.ini is also used !!! // reboot necessary so that the new wlan.ini is also used !!!
fclose(pfile); fclose(pfile);
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Rebooting to activate new HOSTNAME..."); LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Rebooting to activate new HOSTNAME...");
esp_restart();
hard_restart();
doReboot(); doReboot();
} }
} }

View File

@@ -5,6 +5,7 @@
#include "ClassFlowMQTT.h" #include "ClassFlowMQTT.h"
#include "Helper.h" #include "Helper.h"
#include "connect_wlan.h" #include "connect_wlan.h"
#include "read_wlanini.h"
#include "ClassLogFile.h" #include "ClassLogFile.h"
#include "time_sntp.h" #include "time_sntp.h"
@@ -31,7 +32,7 @@ void ClassFlowMQTT::SetInitialParameter(void)
topicError = ""; topicError = "";
topicRate = ""; topicRate = "";
topicTimeStamp = ""; topicTimeStamp = "";
maintopic = hostname; maintopic = wlan_config.hostname;
topicUptime = ""; topicUptime = "";
topicFreeMem = ""; topicFreeMem = "";

View File

@@ -258,7 +258,7 @@ bool MakeDir(std::string path)
break; break;
default: default:
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to create folder: " + path); LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to create folder: " + path + " (errno: " + std::to_string(errno) + ")");
bSuccess = false; bSuccess = false;
break; break;
} }

View File

@@ -0,0 +1,148 @@
#include "statusled.h"
#include <sys/types.h>
#include <sys/stat.h>
#include "driver/gpio.h"
#include "ClassLogFile.h"
#include "../../include/defines.h"
static const char* TAG = "STATUSLED";
TaskHandle_t xHandle_task_StatusLED = NULL;
struct StatusLEDData StatusLEDData = {};
void task_StatusLED(void *pvParameter)
{
//ESP_LOGD(TAG, "task_StatusLED - create");
while (StatusLEDData.bProcessingRequest)
{
//ESP_LOGD(TAG, "task_StatusLED - start");
struct StatusLEDData StatusLEDDataInt = StatusLEDData;
gpio_pad_select_gpio(BLINK_GPIO); // Init the GPIO
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT); // Set the GPIO as a push/pull output
gpio_set_level(BLINK_GPIO, 1);// LED off
for (int i=0; i<3; ) // Default: repeat 3 times
{
if (!StatusLEDDataInt.bInfinite)
++i;
for (int j = 0; j < StatusLEDDataInt.iSourceBlinkCnt; ++j)
{
gpio_set_level(BLINK_GPIO, 0);
vTaskDelay(StatusLEDDataInt.iBlinkTime / portTICK_PERIOD_MS);
gpio_set_level(BLINK_GPIO, 1);
vTaskDelay(StatusLEDDataInt.iBlinkTime / portTICK_PERIOD_MS);
}
vTaskDelay(500 / portTICK_PERIOD_MS); // Delay between module code and error code
for (int j = 0; j < StatusLEDDataInt.iCodeBlinkCnt; ++j)
{
gpio_set_level(BLINK_GPIO, 0);
vTaskDelay(StatusLEDDataInt.iBlinkTime / portTICK_PERIOD_MS);
gpio_set_level(BLINK_GPIO, 1);
vTaskDelay(StatusLEDDataInt.iBlinkTime / portTICK_PERIOD_MS);
}
vTaskDelay(1500 / portTICK_PERIOD_MS); // Delay to signal new round
}
StatusLEDData.bProcessingRequest = false;
//ESP_LOGD(TAG, "task_StatusLED - done/wait");
vTaskDelay(10000 / portTICK_PERIOD_MS); // Wait for an upcoming request otherwise continue and delete task to save memory
}
//ESP_LOGD(TAG, "task_StatusLED - delete");
xHandle_task_StatusLED = NULL;
vTaskDelete(NULL); // Delete this task due to no request
}
void StatusLED(StatusLedSource _eSource, int _iCode, bool _bInfinite)
{
//ESP_LOGD(TAG, "StatusLED - start");
if (_eSource == WLAN_CONN) {
StatusLEDData.iSourceBlinkCnt = WLAN_CONN;
StatusLEDData.iCodeBlinkCnt = _iCode;
StatusLEDData.iBlinkTime = 250;
StatusLEDData.bInfinite = _bInfinite;
}
else if (_eSource == WLAN_INIT) {
StatusLEDData.iSourceBlinkCnt = WLAN_INIT;
StatusLEDData.iCodeBlinkCnt = _iCode;
StatusLEDData.iBlinkTime = 250;
StatusLEDData.bInfinite = _bInfinite;
}
else if (_eSource == SDCARD_INIT) {
StatusLEDData.iSourceBlinkCnt = SDCARD_INIT;
StatusLEDData.iCodeBlinkCnt = _iCode;
StatusLEDData.iBlinkTime = 250;
StatusLEDData.bInfinite = _bInfinite;
}
else if (_eSource == SDCARD_CHECK) {
StatusLEDData.iSourceBlinkCnt = SDCARD_CHECK;
StatusLEDData.iCodeBlinkCnt = _iCode;
StatusLEDData.iBlinkTime = 250;
StatusLEDData.bInfinite = _bInfinite;
}
else if (_eSource == CAM_INIT) {
StatusLEDData.iSourceBlinkCnt = CAM_INIT;
StatusLEDData.iCodeBlinkCnt = _iCode;
StatusLEDData.iBlinkTime = 250;
StatusLEDData.bInfinite = _bInfinite;
}
else if (_eSource == PSRAM_INIT) {
StatusLEDData.iSourceBlinkCnt = PSRAM_INIT;
StatusLEDData.iCodeBlinkCnt = _iCode;
StatusLEDData.iBlinkTime = 250;
StatusLEDData.bInfinite = _bInfinite;
}
else if (_eSource == TIME_CHECK) {
StatusLEDData.iSourceBlinkCnt = TIME_CHECK;
StatusLEDData.iCodeBlinkCnt = _iCode;
StatusLEDData.iBlinkTime = 250;
StatusLEDData.bInfinite = _bInfinite;
}
else if (_eSource == AP_OR_OTA) {
StatusLEDData.iSourceBlinkCnt = AP_OR_OTA;
StatusLEDData.iCodeBlinkCnt = _iCode;
StatusLEDData.iBlinkTime = 350;
StatusLEDData.bInfinite = _bInfinite;
}
if (xHandle_task_StatusLED && !StatusLEDData.bProcessingRequest) {
StatusLEDData.bProcessingRequest = true;
BaseType_t xReturned = xTaskAbortDelay(xHandle_task_StatusLED); // Reuse still running status LED task
/*if (xReturned == pdPASS)
ESP_LOGD(TAG, "task_StatusLED - abort waiting delay");*/
}
else if (xHandle_task_StatusLED == NULL) {
StatusLEDData.bProcessingRequest = true;
BaseType_t xReturned = xTaskCreate(&task_StatusLED, "task_StatusLED", 1280, NULL, tskIDLE_PRIORITY+1, &xHandle_task_StatusLED);
if(xReturned != pdPASS)
{
xHandle_task_StatusLED = NULL;
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "task_StatusLED failed to create");
LogFile.WriteHeapInfo("task_StatusLED failed");
}
}
else {
ESP_LOGD(TAG, "task_StatusLED still processing, request skipped"); // Requests with high frequency could be skipped, but LED is only helpful for static states
}
//ESP_LOGD(TAG, "StatusLED - done");
}
void StatusLEDOff(void)
{
if (xHandle_task_StatusLED)
vTaskDelete(xHandle_task_StatusLED); // Delete task for StatusLED to force stop of blinking
gpio_pad_select_gpio(BLINK_GPIO); // Init the GPIO
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT); // Set the GPIO as a push/pull output
gpio_set_level(BLINK_GPIO, 1);// LED off
}

View File

@@ -0,0 +1,34 @@
#pragma once
#ifndef STATUSLED_H
#define STATUSLED_H
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
extern TaskHandle_t xHandle_task_StatusLED;
enum StatusLedSource {
WLAN_CONN = 1,
WLAN_INIT = 2,
SDCARD_INIT = 3,
SDCARD_CHECK = 4,
CAM_INIT = 5,
PSRAM_INIT = 6,
TIME_CHECK = 7,
AP_OR_OTA = 8
};
struct StatusLEDData {
int iSourceBlinkCnt = 1;
int iCodeBlinkCnt = 1;
int iBlinkTime = 250;
bool bInfinite = false;
bool bProcessingRequest = false;
};
void StatusLED(StatusLedSource _eSource, int _iCode, bool _bInfinite);
void StatusLEDOff(void);
#endif //STATUSLED_H

View File

@@ -78,11 +78,11 @@ void ClassLogFile::WriteToData(std::string _timestamp, std::string _name, std::s
} }
void ClassLogFile::setLogLevel(esp_log_level_t _logLevel){ void ClassLogFile::setLogLevel(esp_log_level_t _logLevel)
loglevel = _logLevel; {
std::string levelText; std::string levelText;
// Print log level to log file
switch(_logLevel) { switch(_logLevel) {
case ESP_LOG_WARN: case ESP_LOG_WARN:
levelText = "WARNING"; levelText = "WARNING";
@@ -95,13 +95,16 @@ void ClassLogFile::setLogLevel(esp_log_level_t _logLevel){
case ESP_LOG_DEBUG: case ESP_LOG_DEBUG:
levelText = "DEBUG"; levelText = "DEBUG";
break; break;
case ESP_LOG_ERROR: case ESP_LOG_ERROR:
default: default:
levelText = "ERROR"; levelText = "ERROR";
break; break;
} }
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Set log level to " + levelText);
ESP_LOGI(TAG, "Log Level set to %s", levelText.c_str()); // set new log level
loglevel = _logLevel;
/* /*
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Test"); LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Test");
@@ -386,14 +389,17 @@ void ClassLogFile::RemoveOldDataLog()
} }
void ClassLogFile::CreateLogDirectories() bool ClassLogFile::CreateLogDirectories()
{ {
MakeDir("/sdcard/log"); bool bRetval = false;
MakeDir("/sdcard/log/data"); bRetval = MakeDir("/sdcard/log");
MakeDir("/sdcard/log/analog"); bRetval = MakeDir("/sdcard/log/data");
MakeDir("/sdcard/log/digit"); bRetval = MakeDir("/sdcard/log/analog");
MakeDir("/sdcard/log/message"); bRetval = MakeDir("/sdcard/log/digit");
MakeDir("/sdcard/log/source"); bRetval = MakeDir("/sdcard/log/message");
bRetval = MakeDir("/sdcard/log/source");
return bRetval;
} }

View File

@@ -35,7 +35,7 @@ public:
void CloseLogFileAppendHandle(); void CloseLogFileAppendHandle();
void CreateLogDirectories(); bool CreateLogDirectories();
void RemoveOldLogFile(); void RemoveOldLogFile();
void RemoveOldDataLog(); void RemoveOldDataLog();

View File

@@ -14,6 +14,7 @@ std::map<std::string, std::function<void()>>* connectFunktionMap = NULL;
std::map<std::string, std::function<bool(std::string, char*, int)>>* subscribeFunktionMap = NULL; std::map<std::string, std::function<bool(std::string, char*, int)>>* subscribeFunktionMap = NULL;
int failedOnRound = -1; int failedOnRound = -1;
int MQTTReconnectCnt = 0;
esp_mqtt_event_id_t esp_mqtt_ID = MQTT_EVENT_ANY; esp_mqtt_event_id_t esp_mqtt_ID = MQTT_EVENT_ANY;
// ESP_EVENT_ANY_ID // ESP_EVENT_ANY_ID
@@ -89,29 +90,39 @@ static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event) {
std::string topic = ""; std::string topic = "";
switch (event->event_id) { switch (event->event_id) {
case MQTT_EVENT_BEFORE_CONNECT: case MQTT_EVENT_BEFORE_CONNECT:
ESP_LOGD(TAG, "MQTT_EVENT_BEFORE_CONNECT");
mqtt_initialized = true; mqtt_initialized = true;
break; break;
case MQTT_EVENT_CONNECTED: case MQTT_EVENT_CONNECTED:
ESP_LOGD(TAG, "MQTT_EVENT_CONNECTED"); MQTTReconnectCnt = 0;
mqtt_initialized = true; mqtt_initialized = true;
mqtt_connected = true; mqtt_connected = true;
MQTTconnected(); MQTTconnected();
break; break;
case MQTT_EVENT_DISCONNECTED: case MQTT_EVENT_DISCONNECTED:
ESP_LOGD(TAG, "MQTT_EVENT_DISCONNECTED");
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Disconnected from broker");
mqtt_connected = false; mqtt_connected = false;
MQTTReconnectCnt++;
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Disconnected, trying to reconnect");
if (MQTTReconnectCnt >= 5) {
MQTTReconnectCnt = 0;
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Disconnected, multiple reconnect attempts failed, still retrying...");
}
break; break;
case MQTT_EVENT_SUBSCRIBED: case MQTT_EVENT_SUBSCRIBED:
ESP_LOGD(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id); ESP_LOGD(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
break; break;
case MQTT_EVENT_UNSUBSCRIBED: case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGD(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); ESP_LOGD(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break; break;
case MQTT_EVENT_PUBLISHED: case MQTT_EVENT_PUBLISHED:
ESP_LOGD(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); ESP_LOGD(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break; break;
case MQTT_EVENT_DATA: case MQTT_EVENT_DATA:
ESP_LOGD(TAG, "MQTT_EVENT_DATA"); ESP_LOGD(TAG, "MQTT_EVENT_DATA");
ESP_LOGD(TAG, "TOPIC=%.*s", event->topic_len, event->topic); ESP_LOGD(TAG, "TOPIC=%.*s", event->topic_len, event->topic);
@@ -126,6 +137,7 @@ static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event) {
ESP_LOGW(TAG, "no handler available\r\n"); ESP_LOGW(TAG, "no handler available\r\n");
} }
break; break;
case MQTT_EVENT_ERROR: case MQTT_EVENT_ERROR:
#ifdef DEBUG_DETAIL_ON #ifdef DEBUG_DETAIL_ON
ESP_LOGD(TAG, "MQTT_EVENT_ERROR - esp_mqtt_error_codes:"); ESP_LOGD(TAG, "MQTT_EVENT_ERROR - esp_mqtt_error_codes:");
@@ -136,8 +148,9 @@ static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event) {
ESP_LOGD(TAG, "esp_tls_stack_err:%d", event->error_handle->esp_tls_stack_err); ESP_LOGD(TAG, "esp_tls_stack_err:%d", event->error_handle->esp_tls_stack_err);
ESP_LOGD(TAG, "esp_tls_cert_verify_flags:%d", event->error_handle->esp_tls_cert_verify_flags); ESP_LOGD(TAG, "esp_tls_cert_verify_flags:%d", event->error_handle->esp_tls_cert_verify_flags);
#endif #endif
mqtt_connected = false; //mqtt_connected = false;
break; break;
default: default:
ESP_LOGD(TAG, "Other event id:%d", event->event_id); ESP_LOGD(TAG, "Other event id:%d", event->event_id);
break; break;

View File

@@ -7,6 +7,7 @@
#include "esp_log.h" #include "esp_log.h"
#include "ClassLogFile.h" #include "ClassLogFile.h"
#include "connect_wlan.h" #include "connect_wlan.h"
#include "read_wlanini.h"
#include "server_mqtt.h" #include "server_mqtt.h"
#include "interface_mqtt.h" #include "interface_mqtt.h"
#include "time_sntp.h" #include "time_sntp.h"
@@ -201,7 +202,7 @@ void publishStaticData() {
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Publishing static MQTT topics..."); LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Publishing static MQTT topics...");
MQTTPublish(maintopic + "/" + "MAC", getMac(), retainFlag); MQTTPublish(maintopic + "/" + "MAC", getMac(), retainFlag);
MQTTPublish(maintopic + "/" + "IP", *getIPAddress(), retainFlag); MQTTPublish(maintopic + "/" + "IP", *getIPAddress(), retainFlag);
MQTTPublish(maintopic + "/" + "hostname", hostname, retainFlag); MQTTPublish(maintopic + "/" + "hostname", wlan_config.hostname, retainFlag);
std::stringstream stream; std::stringstream stream;
stream << std::fixed << std::setprecision(1) << roundInterval; // minutes stream << std::fixed << std::setprecision(1) << roundInterval; // minutes

View File

@@ -10,6 +10,7 @@
#include "../../include/defines.h" #include "../../include/defines.h"
#include "Helper.h" #include "Helper.h"
#include "statusled.h"
#include "esp_camera.h" #include "esp_camera.h"
#include "time_sntp.h" #include "time_sntp.h"
@@ -21,8 +22,11 @@
#include "server_GPIO.h" #include "server_GPIO.h"
#include "server_file.h" #include "server_file.h"
#include "read_wlanini.h"
#include "connect_wlan.h" #include "connect_wlan.h"
ClassFlowControll tfliteflow; ClassFlowControll tfliteflow;
TaskHandle_t xHandletask_autodoFlow = NULL; TaskHandle_t xHandletask_autodoFlow = NULL;
@@ -44,20 +48,24 @@ static const char *TAG = "TFLITE SERVER";
void CheckIsPlannedReboot() void CheckIsPlannedReboot()
{ {
FILE *pfile; FILE *pfile;
if ((pfile = fopen("/sdcard/reboot.txt", "r")) == NULL) if ((pfile = fopen("/sdcard/reboot.txt", "r")) == NULL) {
{ //LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Initial boot or not a planned reboot");
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Not a planned reboot.");
isPlannedReboot = false; isPlannedReboot = false;
} }
else else {
{ LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Planned reboot");
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Planned reboot.");
DeleteFile("/sdcard/reboot.txt"); // Prevent Boot Loop!!! DeleteFile("/sdcard/reboot.txt"); // Prevent Boot Loop!!!
isPlannedReboot = true; isPlannedReboot = true;
} }
} }
bool getIsPlannedReboot()
{
return isPlannedReboot;
}
int getCountFlowRounds() int getCountFlowRounds()
{ {
return countRounds; return countRounds;
@@ -837,21 +845,15 @@ void task_autodoFlow(void *pvParameter)
bTaskAutoFlowCreated = true; bTaskAutoFlowCreated = true;
if (!isPlannedReboot) if (!isPlannedReboot && (esp_reset_reason() == ESP_RST_PANIC))
{ {
if (esp_reset_reason() == ESP_RST_PANIC) { tfliteflow.setActStatus("Initialization (delayed)");
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Restarted due to an Exception/panic! Postponing first round start by 5 minutes to allow for an OTA Update or to fetch the log!"); //#ifdef ENABLE_MQTT
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Setting logfile level to DEBUG until the next reboot!"); //MQTTPublish(mqttServer_getMainTopic() + "/" + "status", "Initialization (delayed)", false); // Right now, not possible -> MQTT Service is going to be started later
LogFile.setLogLevel(ESP_LOG_DEBUG); //#endif //ENABLE_MQTT
tfliteflow.setActStatus("Initialization (delayed)"); vTaskDelay(60*5000 / portTICK_PERIOD_MS); // Wait 5 minutes to give time to do an OTA update or fetch the log
//#ifdef ENABLE_MQTT
//MQTTPublish(mqttServer_getMainTopic() + "/" + "status", "Initialization (delayed)", false); // Right now, not possible -> MQTT Service is going to be started later
//#endif //ENABLE_MQTT
vTaskDelay(60*5000 / portTICK_RATE_MS); // Wait 5 minutes to give time to do an OTA Update or fetch the log
}
} }
ESP_LOGD(TAG, "task_autodoFlow: start"); ESP_LOGD(TAG, "task_autodoFlow: start");
doInit(); doInit();
@@ -891,16 +893,22 @@ void task_autodoFlow(void *pvParameter)
LogFile.RemoveOldLogFile(); LogFile.RemoveOldLogFile();
LogFile.RemoveOldDataLog(); LogFile.RemoveOldDataLog();
} }
//Round finished -> Logfile
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Round #" + std::to_string(countRounds) +
" completed (" + std::to_string(getUpTime() - roundStartTime) + " seconds)");
//CPU Temp -> Logfile //CPU Temp -> Logfile
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CPU Temperature: " + std::to_string((int)temperatureRead()) + "°C"); LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CPU Temperature: " + std::to_string((int)temperatureRead()) + "°C");
// WIFI Signal Strength (RSSI) -> Logfile // WIFI Signal Strength (RSSI) -> Logfile
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "WIFI Signal (RSSI): " + std::to_string(get_WIFI_RSSI()) + "dBm"); LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "WIFI Signal (RSSI): " + std::to_string(get_WIFI_RSSI()) + "dBm");
//Round finished -> Logfile // Check if time is synchronized (if NTP is configured)
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Round #" + std::to_string(countRounds) + if (getUseNtp() && !getTimeIsSet()) {
" completed (" + std::to_string(getUpTime() - roundStartTime) + " seconds)"); LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Time server is configured, but time is not yet set. Check configuration");
StatusLED(TIME_CHECK, 1, false);
}
fr_delta_ms = (esp_timer_get_time() - fr_start) / 1000; fr_delta_ms = (esp_timer_get_time() - fr_start) / 1000;
if (auto_interval > fr_delta_ms) if (auto_interval > fr_delta_ms)

View File

@@ -21,6 +21,7 @@ bool isSetupModusActive();
int getCountFlowRounds(); int getCountFlowRounds();
void CheckIsPlannedReboot(); void CheckIsPlannedReboot();
bool getIsPlannedReboot();
esp_err_t GetJPG(std::string _filename, httpd_req_t *req); esp_err_t GetJPG(std::string _filename, httpd_req_t *req);
esp_err_t GetRawJPG(httpd_req_t *req); esp_err_t GetRawJPG(httpd_req_t *req);

View File

@@ -1,12 +1,24 @@
#include "connect_wlan.h" #include "connect_wlan.h"
#include <string.h> #include <string.h>
#include <stdlib.h>
#include <fstream>
#include <vector>
#include <sstream>
#include <iostream>
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/event_groups.h" #include "freertos/event_groups.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "esp_system.h" #include "esp_system.h"
#include "esp_wifi.h" #include "esp_wifi.h"
#include "esp_wnm.h"
#include "esp_rrm.h"
#include "esp_mbo.h"
#include "esp_mac.h"
#include "esp_netif.h"
#include "esp_event.h" #include "esp_event.h"
#include "esp_log.h" #include "esp_log.h"
#include "nvs_flash.h" #include "nvs_flash.h"
@@ -17,56 +29,20 @@
#include "interface_mqtt.h" #include "interface_mqtt.h"
#endif //ENABLE_MQTT #endif //ENABLE_MQTT
#include <fstream> #include "ClassLogFile.h"
#include <string> #include "read_wlanini.h"
#include <vector> #include "Helper.h"
#include <sstream> #include "statusled.h"
#include <iostream>
//////////////////////
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_wnm.h"
#include "esp_rrm.h"
#include "esp_mbo.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_mac.h"
#include "nvs_flash.h"
#include "esp_netif.h"
/////////////////////
#include "../../include/defines.h" #include "../../include/defines.h"
/* FreeRTOS event group to signal when we are connected*/
static EventGroupHandle_t s_wifi_event_group;
static const char *TAG = "WIFI"; static const char *TAG = "WIFI";
static int s_retry_num = 0;
bool WIFIConnected = false; bool WIFIConnected = false;
int WIFIReconnectCnt = 0;
///////////////////////////////////////////////////////////
int BlinkDauer;
int BlinkAnzahl;
bool BlinkOff;
bool BlinkIsRunning = false;
std::string hostname = "";
std::string std_hostname = "watermeter";
std::string ipadress = "";
std::string ssid = "";
int RSSIThreshold;
/////////////////////////////////
/////////////////////////////////
#ifdef WLAN_USE_MESH_ROAMING #ifdef WLAN_USE_MESH_ROAMING
@@ -301,97 +277,87 @@ static void esp_bss_rssi_low_handler(void* arg, esp_event_base_t event_base,
std::string* getIPAddress() std::string* getIPAddress()
{ {
return &ipadress; return &wlan_config.ipaddress;
} }
std::string* getSSID() std::string* getSSID()
{ {
return &ssid; return &wlan_config.ssid;
} }
void task_doBlink(void *pvParameter) static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
{ {
ESP_LOGI("BLINK", "Flash - start"); if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
while (BlinkIsRunning) {
{
// ESP_LOGI("BLINK", "Blinken - wait");
vTaskDelay(100 / portTICK_PERIOD_MS);
}
BlinkIsRunning = true;
// Init the GPIO
gpio_pad_select_gpio(BLINK_GPIO);
/* Set the GPIO as a push/pull output */
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
for (int i = 0; i < BlinkAnzahl; ++i)
{
if (BlinkAnzahl > 1)
{
gpio_set_level(BLINK_GPIO, 1);
vTaskDelay(BlinkDauer / portTICK_PERIOD_MS);
}
gpio_set_level(BLINK_GPIO, 0);
vTaskDelay(BlinkDauer / portTICK_PERIOD_MS);
}
if (BlinkOff)
gpio_set_level(BLINK_GPIO, 1);
ESP_LOGI("BLINK", "Flash - done");
BlinkIsRunning = false;
vTaskDelete(NULL); //Delete this task if it exits from the loop above
}
void LEDBlinkTask(int _dauer, int _anz, bool _off)
{
BlinkDauer = _dauer;
BlinkAnzahl = _anz;
BlinkOff = _off;
xTaskCreate(&task_doBlink, "task_doBlink", 4 * 1024, NULL, tskIDLE_PRIORITY+1, NULL);
}
/////////////////////////////////////////////////////////
static void event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
WIFIConnected = false; WIFIConnected = false;
LEDBlinkTask(200, 1, true);
esp_wifi_connect(); esp_wifi_connect();
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { }
WIFIConnected = false;
// if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) { else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
esp_wifi_connect(); {
s_retry_num++; /* Disconnect reason: https://github.com/espressif/esp-idf/blob/d825753387c1a64463779bbd2369e177e5d59a79/components/esp_wifi/include/esp_wifi_types.h */
ESP_LOGI(TAG, "retrying connection to the AP"); wifi_event_sta_disconnected_t *disconn = (wifi_event_sta_disconnected_t *)event_data;
// } else { if (disconn->reason == WIFI_REASON_ROAMING) {
// xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Disconnected (" + std::to_string(disconn->reason) + ", Roaming)");
// } // --> no reconnect neccessary, it should automatically reconnect to new AP
ESP_LOGI(TAG,"connection to the AP failed"); }
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { else {
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; WIFIConnected = false;
ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); if (disconn->reason == WIFI_REASON_NO_AP_FOUND) {
ipadress = std::string(ip4addr_ntoa((const ip4_addr*) &event->ip_info.ip)); LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Disconnected (" + std::to_string(disconn->reason) + ", No AP)");
s_retry_num = 0; StatusLED(WLAN_CONN, 1, false);
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); }
LEDBlinkTask(1000, 5, true); else if (disconn->reason == WIFI_REASON_AUTH_EXPIRE ||
disconn->reason == WIFI_REASON_AUTH_FAIL ||
disconn->reason == WIFI_REASON_NOT_AUTHED ||
disconn->reason == WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT ||
disconn->reason == WIFI_REASON_HANDSHAKE_TIMEOUT) {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Disconnected (" + std::to_string(disconn->reason) + ", Auth fail)");
StatusLED(WLAN_CONN, 2, false);
}
else if (disconn->reason == WIFI_REASON_BEACON_TIMEOUT) {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Disconnected (" + std::to_string(disconn->reason) + ", Timeout)");
StatusLED(WLAN_CONN, 3, false);
}
else {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Disconnected (" + std::to_string(disconn->reason) + ")");
StatusLED(WLAN_CONN, 4, false);
}
WIFIReconnectCnt++;
esp_wifi_connect(); // Try to connect again
}
if (WIFIReconnectCnt >= 10) {
WIFIReconnectCnt = 0;
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Disconnected, multiple reconnect attempts failed (" +
std::to_string(disconn->reason) + "), still retrying...");
}
}
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED)
{
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Connected to: " + wlan_config.ssid + ", RSSI: " +
std::to_string(get_WIFI_RSSI()));
}
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
{
WIFIConnected = true; WIFIConnected = true;
#ifdef ENABLE_MQTT WIFIReconnectCnt = 0;
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
wlan_config.ipaddress = std::string(ip4addr_ntoa((const ip4_addr*) &event->ip_info.ip));
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Got IP: " + wlan_config.ipaddress);
#ifdef ENABLE_MQTT
if (getMQTTisEnabled()) { if (getMQTTisEnabled()) {
vTaskDelay(5000 / portTICK_PERIOD_MS); vTaskDelay(5000 / portTICK_PERIOD_MS);
MQTT_Init(); // Init when WIFI is getting connected MQTT_Init(); // Init when WIFI is getting connected
} }
#endif //ENABLE_MQTT #endif //ENABLE_MQTT
} }
} }
@@ -403,148 +369,148 @@ void strinttoip4(const char *ip, int &a, int &b, int &c, int &d) {
} }
void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostname, const char *_ipadr, const char *_gw, const char *_netmask, const char *_dns, int _rssithreshold) esp_err_t wifi_init_sta(void)
{ {
RSSI_Threshold = _rssithreshold; esp_err_t retval = esp_netif_init();
s_wifi_event_group = xEventGroupCreate(); if (retval != ESP_OK) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "esp_netif_init: Error: " + std::to_string(retval));
return retval;
}
ESP_ERROR_CHECK(esp_netif_init()); retval = esp_event_loop_create_default();
if (retval != ESP_OK) {
ESP_ERROR_CHECK(esp_event_loop_create_default()); LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "esp_event_loop_create_default: Error: " + std::to_string(retval));
return retval;
}
esp_netif_t *my_sta = esp_netif_create_default_wifi_sta(); esp_netif_t *my_sta = esp_netif_create_default_wifi_sta();
if ((_ipadr != NULL) && (_gw != NULL) && (_netmask != NULL)) if (!wlan_config.ipaddress.empty() && !wlan_config.gateway.empty() && !wlan_config.netmask.empty())
{ {
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Manual interface config -> IP: " + wlan_config.ipaddress + ", Gateway: " +
ESP_LOGI(TAG, "set IP %s, GW %s, Netmask %s manual", _ipadr, _gw, _netmask); std::string(wlan_config.gateway) + ", Netmask: " + std::string(wlan_config.netmask));
esp_netif_dhcpc_stop(my_sta); esp_netif_dhcpc_stop(my_sta); // Stop DHCP service
esp_netif_ip_info_t ip_info; esp_netif_ip_info_t ip_info;
int a, b, c, d; int a, b, c, d;
strinttoip4(_ipadr, a, b, c, d); strinttoip4(wlan_config.ipaddress.c_str(), a, b, c, d);
IP4_ADDR(&ip_info.ip, a, b, c, d); IP4_ADDR(&ip_info.ip, a, b, c, d); // Set static IP address
strinttoip4(_gw, a, b, c, d);
IP4_ADDR(&ip_info.gw, a, b, c, d);
strinttoip4(_netmask, a, b, c, d);
IP4_ADDR(&ip_info.netmask, a, b, c, d);
esp_netif_set_ip_info(my_sta, &ip_info); strinttoip4(wlan_config.gateway.c_str(), a, b, c, d);
IP4_ADDR(&ip_info.gw, a, b, c, d); // Set gateway
strinttoip4(wlan_config.netmask.c_str(), a, b, c, d);
IP4_ADDR(&ip_info.netmask, a, b, c, d); // Set netmask
esp_netif_set_ip_info(my_sta, &ip_info); // Set static IP configuration
} }
else {
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Automatic interface config --> Use DHCP service");
}
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg)); retval = esp_wifi_init(&cfg);
if (retval != ESP_OK) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "esp_wifi_init: Error: " + std::to_string(retval));
return retval;
}
if ((_ipadr != NULL) && (_gw != NULL) && (_netmask != NULL)) if (!wlan_config.ipaddress.empty() && !wlan_config.gateway.empty() && !wlan_config.netmask.empty())
{ {
if (_dns == NULL) if (wlan_config.dns.empty()) {
_dns = _gw; LogFile.WriteToFile(ESP_LOG_INFO, TAG, "No DNS server, use gateway");
wlan_config.dns = wlan_config.gateway;
ESP_LOGI(TAG, "set DNS manual"); }
else {
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Manual interface config -> DNS: " + wlan_config.dns);
}
esp_netif_dns_info_t dns_info; esp_netif_dns_info_t dns_info;
ip4_addr_t ip; ip4_addr_t ip;
ip.addr = esp_ip4addr_aton(_dns); ip.addr = esp_ip4addr_aton(wlan_config.dns.c_str());
ip_addr_set_ip4_u32(&dns_info.ip, ip.addr); ip_addr_set_ip4_u32(&dns_info.ip, ip.addr);
ESP_ERROR_CHECK(esp_netif_set_dns_info(my_sta, ESP_NETIF_DNS_MAIN, &dns_info));
}
esp_event_handler_instance_t instance_any_id; retval = esp_netif_set_dns_info(my_sta, ESP_NETIF_DNS_MAIN, &dns_info);
esp_event_handler_instance_t instance_got_ip; if (retval != ESP_OK) {
esp_event_handler_instance_t instance_bss_rssi_low; LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "esp_netif_set_dns_info: Error: " + std::to_string(retval));
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, return retval;
ESP_EVENT_ANY_ID, }
&event_handler, }
NULL,
&instance_any_id)); retval = esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID,
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, &event_handler, NULL, NULL);
IP_EVENT_STA_GOT_IP, if (retval != ESP_OK) {
&event_handler, LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "esp_event_handler_instance_register - WIFI_ANY: Error: " + std::to_string(retval));
NULL, return retval;
&instance_got_ip)); }
retval = esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP,
&event_handler, NULL, NULL);
if (retval != ESP_OK) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "esp_event_handler_instance_register - GOT_IP: Error: " + std::to_string(retval));
return retval;
}
#ifdef WLAN_USE_MESH_ROAMING #ifdef WLAN_USE_MESH_ROAMING
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, retval = esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_STA_BSS_RSSI_LOW,
WIFI_EVENT_STA_BSS_RSSI_LOW, &esp_bss_rssi_low_handler, NULL, NULL);
&esp_bss_rssi_low_handler, if (retval != ESP_OK) {
NULL, LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "esp_event_handler_instance_register - BSS_RSSI_LOW: Error: " + std::to_string(retval));
&instance_bss_rssi_low)); return retval;
}
#endif #endif
wifi_config_t wifi_config = { }; wifi_config_t wifi_config = { };
strcpy((char*)wifi_config.sta.ssid, (const char*)_ssid); strcpy((char*)wifi_config.sta.ssid, (const char*)wlan_config.ssid.c_str());
strcpy((char*)wifi_config.sta.password, (const char*)_password); strcpy((char*)wifi_config.sta.password, (const char*)wlan_config.password.c_str());
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); retval = esp_wifi_set_mode(WIFI_MODE_STA);
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); if (retval != ESP_OK) {
ESP_ERROR_CHECK(esp_wifi_start() ); LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "esp_wifi_set_mode: Error: " + std::to_string(retval));
return retval;
}
if (_hostname != NULL) retval = esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
if (retval != ESP_OK) {
if (retval == ESP_ERR_WIFI_PASSWORD) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "esp_wifi_set_config: SSID password invalid! Error: " + std::to_string(retval));
}
else {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "esp_wifi_set_config: Error: " + std::to_string(retval));
}
return retval;
}
retval = esp_wifi_start();
if (retval != ESP_OK) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "esp_wifi_start: Error: " + std::to_string(retval));
return retval;
}
if (!wlan_config.hostname.empty())
{ {
esp_err_t ret = tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA , _hostname); retval = tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA , wlan_config.hostname.c_str());
hostname = std::string(_hostname); if(retval != ESP_OK ) {
if(ret != ESP_OK ){ LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to set hostname! Error: " + std::to_string(retval));
ESP_LOGE(TAG,"Failed to set hostname: %d",ret);
} }
else { else {
ESP_LOGI(TAG,"Set hostname to: %s", _hostname); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Set hostname to: " + wlan_config.hostname);
} }
} }
ESP_LOGI(TAG, "wifi_init_sta finished."); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Init successful");
return ESP_OK;
/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
pdFALSE,
pdFALSE,
portMAX_DELAY);
/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
* happened. */
if (bits & WIFI_CONNECTED_BIT) {
#ifdef __HIDE_PASSWORD
ESP_LOGI(TAG, "Connected with AP: %s, password: XXXXXXX", _ssid);
#else
ESP_LOGI(TAG, "Connected with AP: %s, password: %s", _ssid, _password);
#endif
} else if (bits & WIFI_FAIL_BIT) {
#ifdef __HIDE_PASSWORD
ESP_LOGI(TAG, "Failed to connect with AP: %s, password: XXXXXXXX", _ssid);
#else
ESP_LOGI(TAG, "Failed to connect with AP: %s, password: %s", _ssid, _password);
#endif
} else {
ESP_LOGE(TAG, "UNEXPECTED EVENT");
}
ssid = std::string(_ssid);
/* The event will not be processed after unregister */
// ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip));
// ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id));
// vEventGroupDelete(s_wifi_event_group);
} }
int get_WIFI_RSSI() int get_WIFI_RSSI()
{ {
wifi_ap_record_t ap; wifi_ap_record_t ap;
esp_wifi_sta_get_ap_info(&ap); if (esp_wifi_sta_get_ap_info(&ap) == ESP_OK)
return ap.rssi; return ap.rssi;
} else
return -127; // Return -127 if no info available e.g. not connected
void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostname)
{
wifi_init_sta(_ssid, _password, _hostname, NULL, NULL, NULL, NULL, 0);
}
void wifi_init_sta(const char *_ssid, const char *_password)
{
wifi_init_sta(_ssid, _password, NULL, NULL, NULL, NULL, NULL, 0);
} }
@@ -556,14 +522,13 @@ bool getWIFIisConnected()
void WIFIDestroy() void WIFIDestroy()
{ {
esp_wifi_disconnect();
esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, event_handler); esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, event_handler);
esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, event_handler); esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, event_handler);
#ifdef WLAN_USE_MESH_ROAMING #ifdef WLAN_USE_MESH_ROAMING
esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_BSS_RSSI_LOW, esp_bss_rssi_low_handler); esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_BSS_RSSI_LOW, esp_bss_rssi_low_handler);
#endif #endif
esp_wifi_disconnect();
esp_wifi_stop(); esp_wifi_stop();
esp_wifi_deinit(); esp_wifi_deinit();
} }

View File

@@ -5,18 +5,11 @@
#include <string> #include <string>
void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostname, const char *_ipadr, const char *_gw, const char *_netmask, const char *_dns, int _rssithreshold); int wifi_init_sta(void);
void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostname);
void wifi_init_sta(const char *_ssid, const char *_password);
std::string* getIPAddress(); std::string* getIPAddress();
std::string* getSSID(); std::string* getSSID();
int get_WIFI_RSSI(); int get_WIFI_RSSI();
bool getWIFIisConnected(); bool getWIFIisConnected();
void WIFIDestroy(); void WIFIDestroy();
extern std::string hostname;
extern std::string std_hostname;
extern int RSSIThreshold;
#endif //CONNECT_WLAN_H #endif //CONNECT_WLAN_H

View File

@@ -11,9 +11,14 @@
#include <iostream> #include <iostream>
#include <string.h> #include <string.h>
#include "esp_log.h" #include "esp_log.h"
#include "ClassLogFile.h"
#include "../../include/defines.h" #include "../../include/defines.h"
static const char *TAG = "WLAN.INI"; static const char *TAG = "WLANINI";
struct wlan_config wlan_config = {};
std::vector<string> ZerlegeZeileWLAN(std::string input, std::string _delimiter = "") std::vector<string> ZerlegeZeileWLAN(std::string input, std::string _delimiter = "")
{ {
@@ -40,207 +45,189 @@ std::vector<string> ZerlegeZeileWLAN(std::string input, std::string _delimiter =
} }
int LoadWlanFromFile(std::string fn)
bool LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_hostname, char *&_ipadr, char *&_gw, char *&_netmask, char *&_dns, int &_rssithreshold)
{ {
std::string ssid = "";
std::string passphrase = "";
std::string ipaddress = "";
std::string gw = "";
std::string netmask = "";
std::string dns = "";
int rssithreshold = 0;
std::string line = ""; std::string line = "";
std::string tmp = "";
std::vector<string> splitted; std::vector<string> splitted;
hostname = std_hostname;
FILE* pFile;
fn = FormatFileName(fn); fn = FormatFileName(fn);
FILE* pFile = fopen(fn.c_str(), "r");
if (pFile == NULL) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Unable to open file (read). Device init aborted!");
return -1;
}
pFile = fopen(fn.c_str(), "r"); ESP_LOGD(TAG, "LoadWlanFromFile: wlan.ini opened");
if (!pFile)
return false;
ESP_LOGD(TAG, "file loaded"); char zw[256];
if (fgets(zw, sizeof(zw), pFile) == NULL) {
if (pFile == NULL) line = "";
return false; LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "file opened, but empty or content not readable. Device init aborted!");
fclose(pFile);
char zw[1024]; return -1;
fgets(zw, 1024, pFile); }
line = std::string(zw); else {
line = std::string(zw);
}
while ((line.size() > 0) || !(feof(pFile))) while ((line.size() > 0) || !(feof(pFile)))
{ {
// ESP_LOGD(TAG, "%s", line.c_str()); //ESP_LOGD(TAG, "line: %s", line.c_str());
splitted = ZerlegeZeileWLAN(line, "="); if (line[0] != ';') { // Skip lines which starts with ';'
splitted[0] = trim(splitted[0], " ");
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "HOSTNAME")){ splitted = ZerlegeZeileWLAN(line, "=");
hostname = trim(splitted[1]); splitted[0] = trim(splitted[0], " ");
if ((hostname[0] == '"') && (hostname[hostname.length()-1] == '"')){
hostname = hostname.substr(1, hostname.length()-2); if ((splitted.size() > 1) && (toUpper(splitted[0]) == "SSID")){
tmp = trim(splitted[1]);
if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
tmp = tmp.substr(1, tmp.length()-2);
}
wlan_config.ssid = tmp;
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "SSID: " + wlan_config.ssid);
} }
else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "PASSWORD")){
tmp = splitted[1];
if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
tmp = tmp.substr(1, tmp.length()-2);
}
wlan_config.password = tmp;
#ifndef __HIDE_PASSWORD
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Password: " + wlan_config.password);
#else
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Password: XXXXXXXX");
#endif
}
else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "HOSTNAME")){
tmp = trim(splitted[1]);
if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
tmp = tmp.substr(1, tmp.length()-2);
}
wlan_config.hostname = tmp;
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Hostname: " + wlan_config.hostname);
}
else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "IP")){
tmp = splitted[1];
if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
tmp = tmp.substr(1, tmp.length()-2);
}
wlan_config.ipaddress = tmp;
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "IP-Address: " + wlan_config.ipaddress);
}
else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "GATEWAY")){
tmp = splitted[1];
if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
tmp = tmp.substr(1, tmp.length()-2);
}
wlan_config.gateway = tmp;
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Gateway: " + wlan_config.gateway);
}
else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "NETMASK")){
tmp = splitted[1];
if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
tmp = tmp.substr(1, tmp.length()-2);
}
wlan_config.netmask = tmp;
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Netmask: " + wlan_config.netmask);
}
else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "DNS")){
tmp = splitted[1];
if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
tmp = tmp.substr(1, tmp.length()-2);
}
wlan_config.dns = tmp;
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "DNS: " + wlan_config.dns);
}
#ifdef WLAN_USE_MESH_ROAMING
else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "RSSITHRESHOLD")) {
tmp = trim(splitted[1]);
if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
tmp = tmp.substr(1, tmp.length()-2);
}
wlan_config.rssi_threshold = atoi(tmp.c_str());
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "RSSIThreshold: " + std::to_string(wlan_config.rssi_threshold));
}
#endif
} }
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "SSID")){ /* read next line */
ssid = trim(splitted[1]); if (fgets(zw, sizeof(zw), pFile) == NULL) {
if ((ssid[0] == '"') && (ssid[ssid.length()-1] == '"')){
ssid = ssid.substr(1, ssid.length()-2);
}
}
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "RSSITHRESHOLD")){
string _s = trim(splitted[1]);
if ((_s[0] == '"') && (_s[_s.length()-1] == '"')){
_s = _s.substr(1, ssid.length()-2);
}
rssithreshold = atoi(_s.c_str());
}
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "PASSWORD")){
passphrase = splitted[1];
if ((passphrase[0] == '"') && (passphrase[passphrase.length()-1] == '"')){
passphrase = passphrase.substr(1, passphrase.length()-2);
}
}
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "IP")){
ipaddress = splitted[1];
if ((ipaddress[0] == '"') && (ipaddress[ipaddress.length()-1] == '"')){
ipaddress = ipaddress.substr(1, ipaddress.length()-2);
}
}
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "GATEWAY")){
gw = splitted[1];
if ((gw[0] == '"') && (gw[gw.length()-1] == '"')){
gw = gw.substr(1, gw.length()-2);
}
}
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "NETMASK")){
netmask = splitted[1];
if ((netmask[0] == '"') && (netmask[netmask.length()-1] == '"')){
netmask = netmask.substr(1, netmask.length()-2);
}
}
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "DNS")){
dns = splitted[1];
if ((dns[0] == '"') && (dns[dns.length()-1] == '"')){
dns = dns.substr(1, dns.length()-2);
}
}
if (fgets(zw, 1024, pFile) == NULL)
{
line = ""; line = "";
} }
else else {
{
line = std::string(zw); line = std::string(zw);
} }
} }
fclose(pFile); fclose(pFile);
// Check if Hostname was empty in .ini if yes set to std_hostname /* Check if SSID is empty (mandatory parameter) */
if(hostname.length() == 0){ if (wlan_config.ssid.empty()) {
hostname = std_hostname; LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "SSID empty. Device init aborted!");
return -2;
} }
_hostname = new char[hostname.length() + 1]; /* Check if password is empty (mandatory parameter) */
strcpy(_hostname, hostname.c_str()); if (wlan_config.password.empty()) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Password empty. Device init aborted!");
_ssid = new char[ssid.length() + 1]; return -2;
strcpy(_ssid, ssid.c_str());
_password = new char[passphrase.length() + 1];
strcpy(_password, passphrase.c_str());
if (ipaddress.length() > 0)
{
_ipadr = new char[ipaddress.length() + 1];
strcpy(_ipadr, ipaddress.c_str());
} }
else
_ipadr = NULL;
if (gw.length() > 0) return 0;
{
_gw = new char[gw.length() + 1];
strcpy(_gw, gw.c_str());
}
else
_gw = NULL;
if (netmask.length() > 0)
{
_netmask = new char[netmask.length() + 1];
strcpy(_netmask, netmask.c_str());
}
else
_netmask = NULL;
if (dns.length() > 0)
{
_dns = new char[dns.length() + 1];
strcpy(_dns, dns.c_str());
}
else
_dns = NULL;
_rssithreshold = rssithreshold;
RSSIThreshold = rssithreshold;
return true;
} }
bool ChangeHostName(std::string fn, std::string _newhostname) bool ChangeHostName(std::string fn, std::string _newhostname)
{ {
if (_newhostname == hostname) if (_newhostname == wlan_config.hostname)
return false; return false;
string line = ""; std::string line = "";
std::vector<string> splitted; std::vector<string> splitted;
std::vector<string> neuesfile;
bool found = false; bool found = false;
std::vector<string> neuesfile; FILE* pFile = NULL;
FILE* pFile;
fn = FormatFileName(fn); fn = FormatFileName(fn);
pFile = fopen(fn.c_str(), "r"); pFile = fopen(fn.c_str(), "r");
if (pFile == NULL) {
ESP_LOGD(TAG, "file loaded\n"); LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ChangeHostName: Unable to open file wlan.ini (read)");
if (pFile == NULL)
return false; return false;
}
char zw[1024]; ESP_LOGD(TAG, "ChangeHostName: wlan.ini opened");
fgets(zw, 1024, pFile);
line = std::string(zw); char zw[256];
if (fgets(zw, sizeof(zw), pFile) == NULL) {
line = "";
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ChangeHostName: File opened, but empty or content not readable");
return false;
}
else {
line = std::string(zw);
}
while ((line.size() > 0) || !(feof(pFile))) while ((line.size() > 0) || !(feof(pFile)))
{ {
ESP_LOGD(TAG, "%s", line.c_str()); //ESP_LOGD(TAG, "ChangeHostName: line: %s", line.c_str());
splitted = ZerlegeZeileWLAN(line, "="); splitted = ZerlegeZeileWLAN(line, "=");
splitted[0] = trim(splitted[0], " "); splitted[0] = trim(splitted[0], " ");
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "HOSTNAME")){ if ((splitted.size() > 1) && ((toUpper(splitted[0]) == "HOSTNAME") || (toUpper(splitted[0]) == ";HOSTNAME"))){
line = "hostname = \"" + _newhostname + "\"\n"; line = "hostname = \"" + _newhostname + "\"\n";
found = true; found = true;
} }
neuesfile.push_back(line); neuesfile.push_back(line);
if (fgets(zw, 1024, pFile) == NULL) if (fgets(zw, sizeof(zw), pFile) == NULL)
{ {
line = ""; line = "";
} }
@@ -252,52 +239,64 @@ bool ChangeHostName(std::string fn, std::string _newhostname)
if (!found) if (!found)
{ {
line = "\nhostname = \"" + _newhostname + "\"\n"; line = "\n;++++++++++++++++++++++++++++++++++\n";
line += "; Hostname: Name of device in network\n";
line += "; This parameter can be configured via WebUI configuration\n";
line += "; Default: \"watermeter\", if nothing is configured\n\n";
line = "hostname = \"" + _newhostname + "\"\n";
neuesfile.push_back(line); neuesfile.push_back(line);
} }
fclose(pFile); fclose(pFile);
pFile = fopen(fn.c_str(), "w+"); pFile = fopen(fn.c_str(), "w+");
if (pFile == NULL) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ChangeHostName: Unable to open file wlan.ini (write)");
return false;
}
for (int i = 0; i < neuesfile.size(); ++i) for (int i = 0; i < neuesfile.size(); ++i)
{ {
ESP_LOGD(TAG, "%s", neuesfile[i].c_str()); //ESP_LOGD(TAG, "%s", neuesfile[i].c_str());
fputs(neuesfile[i].c_str(), pFile); fputs(neuesfile[i].c_str(), pFile);
} }
fclose(pFile); fclose(pFile);
ESP_LOGD(TAG, "*** Hostname update done ***"); ESP_LOGD(TAG, "ChangeHostName done");
return true; return true;
} }
#ifdef WLAN_USE_MESH_ROAMING
bool ChangeRSSIThreshold(std::string fn, int _newrssithreshold) bool ChangeRSSIThreshold(std::string fn, int _newrssithreshold)
{ {
if (RSSIThreshold == _newrssithreshold) if (wlan_config.rssi_threshold == _newrssithreshold)
return false; return false;
string line = ""; std::string line = "";
std::vector<string> splitted; std::vector<string> splitted;
std::vector<string> neuesfile;
bool found = false; bool found = false;
std::vector<string> neuesfile; FILE* pFile = NULL;
FILE* pFile;
fn = FormatFileName(fn); fn = FormatFileName(fn);
pFile = fopen(fn.c_str(), "r"); pFile = fopen(fn.c_str(), "r");
if (pFile == NULL) {
ESP_LOGD(TAG, "file loaded\n"); LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ChangeRSSIThreshold: Unable to open file wlan.ini (read)");
if (pFile == NULL)
return false; return false;
}
char zw[1024]; ESP_LOGD(TAG, "ChangeRSSIThreshold: wlan.ini opened");
fgets(zw, 1024, pFile);
line = std::string(zw); char zw[256];
if (fgets(zw, sizeof(zw), pFile) == NULL) {
line = "";
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ChangeRSSIThreshold: File opened, but empty or content not readable");
return false;
}
else {
line = std::string(zw);
}
while ((line.size() > 0) || !(feof(pFile))) while ((line.size() > 0) || !(feof(pFile)))
{ {
@@ -305,43 +304,68 @@ bool ChangeRSSIThreshold(std::string fn, int _newrssithreshold)
splitted = ZerlegeZeileWLAN(line, "="); splitted = ZerlegeZeileWLAN(line, "=");
splitted[0] = trim(splitted[0], " "); splitted[0] = trim(splitted[0], " ");
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "RSSITHRESHOLD")){ /* Workaround to eliminate line with typo "RSSIThreashold" or "rssi" if existing */
if (((splitted.size() > 1) && (toUpper(splitted[0]) == "RSSITHREASHOLD")) ||
((splitted.size() > 1) && (toUpper(splitted[0]) == ";RSSITHREASHOLD")) ||
((splitted.size() > 1) && (toUpper(splitted[0]) == "RSSI")) ||
((splitted.size() > 1) && (toUpper(splitted[0]) == ";RSSI"))) {
if (fgets(zw, sizeof(zw), pFile) == NULL) {
line = "";
}
else {
line = std::string(zw);
}
continue;
}
if ((splitted.size() > 1) && ((toUpper(splitted[0]) == "RSSITHRESHOLD") || (toUpper(splitted[0]) == ";RSSITHRESHOLD"))) {
line = "RSSIThreshold = " + to_string(_newrssithreshold) + "\n"; line = "RSSIThreshold = " + to_string(_newrssithreshold) + "\n";
found = true; found = true;
} }
neuesfile.push_back(line); neuesfile.push_back(line);
if (fgets(zw, 1024, pFile) == NULL) if (fgets(zw, sizeof(zw), pFile) == NULL) {
{
line = ""; line = "";
} }
else else {
{
line = std::string(zw); line = std::string(zw);
} }
} }
if (!found) if (!found)
{ {
line = "RSSIThreshold = " + to_string(_newrssithreshold) + "\n"; line = "\n;++++++++++++++++++++++++++++++++++\n";
line += "; WIFI Roaming:\n";
line += "; Network assisted roaming protocol is activated by default\n";
line += "; AP / mesh system needs to support roaming protocol 802.11k/v\n";
line += ";\n";
line += "; Optional feature (usually not neccessary):\n";
line += "; RSSI Threshold for client requested roaming query (RSSI < RSSIThreshold)\n";
line += "; Note: This parameter can be configured via WebUI configuration\n";
line += "; Default: 0 = Disable client requested roaming query\n\n";
line += "RSSIThreshold = " + to_string(_newrssithreshold) + "\n";
neuesfile.push_back(line); neuesfile.push_back(line);
} }
fclose(pFile); fclose(pFile);
pFile = fopen(fn.c_str(), "w+"); pFile = fopen(fn.c_str(), "w+");
if (pFile == NULL) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ChangeRSSIThreshold: Unable to open file wlan.ini (write)");
return false;
}
for (int i = 0; i < neuesfile.size(); ++i) for (int i = 0; i < neuesfile.size(); ++i)
{ {
ESP_LOGD(TAG, "%s", neuesfile[i].c_str()); //ESP_LOGD(TAG, "%s", neuesfile[i].c_str());
fputs(neuesfile[i].c_str(), pFile); fputs(neuesfile[i].c_str(), pFile);
} }
fclose(pFile); fclose(pFile);
ESP_LOGD(TAG, "*** RSSIThreshold update done ***"); ESP_LOGD(TAG, "ChangeRSSIThreshold done");
return true; return true;
} }
#endif

View File

@@ -5,8 +5,20 @@
#include <string> #include <string>
bool LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_hostname, char *&_ipadr, char *&_gw, char *&_netmask, char *&_dns, int &_rssithreshold); struct wlan_config {
std::string ssid = "";
std::string password = "";
std::string hostname = "watermeter"; // Default: watermeter
std::string ipaddress = "";
std::string gateway = "";
std::string netmask = "";
std::string dns = "";
int rssi_threshold = 0; // Default: 0 -> ROAMING disabled
};
extern struct wlan_config wlan_config;
int LoadWlanFromFile(std::string fn);
bool ChangeHostName(std::string fn, std::string _newhostname); bool ChangeHostName(std::string fn, std::string _newhostname);
bool ChangeRSSIThreshold(std::string fn, int _newrssithreshold); bool ChangeRSSIThreshold(std::string fn, int _newrssithreshold);

View File

@@ -62,7 +62,7 @@
#define FLASH_GPIO GPIO_NUM_4 #define FLASH_GPIO GPIO_NUM_4
#define BLINK_GPIO GPIO_NUM_33 #define BLINK_GPIO GPIO_NUM_33
//ClassFlowMQTT + interface_mqtt + connect_wlan + main //interface_mqtt + read_wlanini
#define __HIDE_PASSWORD #define __HIDE_PASSWORD
//ClassControllCamera //ClassControllCamera
@@ -164,12 +164,7 @@
//connect_wlan //connect_wlan
#define WLAN_USE_MESH_ROAMING #define WLAN_USE_MESH_ROAMING
#define WLAN_WIFI_RSSI_THRESHOLD -50 #define WLAN_WIFI_RSSI_THRESHOLD -50
#define EXAMPLE_ESP_MAXIMUM_RETRY 1000
/* The event group allows multiple bits for each event, but we only care about two events:
* - we are connected to the AP with an IP
* - we failed to connect after the maximum amount of retries */
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1
//ClassFlowCNNGeneral //ClassFlowCNNGeneral
#define Analog_error 3 #define Analog_error 3

View File

@@ -40,7 +40,9 @@
#ifdef ENABLE_MQTT #ifdef ENABLE_MQTT
#include "server_mqtt.h" #include "server_mqtt.h"
#endif //ENABLE_MQTT #endif //ENABLE_MQTT
//#include "Helper.h" #include "Helper.h"
#include "statusled.h"
#include "../../include/defines.h" #include "../../include/defines.h"
//#include "server_GPIO.h" //#include "server_GPIO.h"
@@ -83,7 +85,6 @@ extern std::string getFwVersion(void);
extern std::string getHTMLversion(void); extern std::string getHTMLversion(void);
extern std::string getHTMLcommit(void); extern std::string getHTMLcommit(void);
std::vector<std::string> splitString(const std::string& str); std::vector<std::string> splitString(const std::string& str);
bool replace(std::string& s, std::string const& toReplace, std::string const& replaceWith); bool replace(std::string& s, std::string const& toReplace, std::string const& replaceWith);
bool replace(std::string& s, std::string const& toReplace, std::string const& replaceWith, bool logIt); bool replace(std::string& s, std::string const& toReplace, std::string const& replaceWith, bool logIt);
@@ -93,6 +94,7 @@ void migrateConfiguration(void);
static const char *TAG = "MAIN"; static const char *TAG = "MAIN";
bool Init_NVS_SDCard() bool Init_NVS_SDCard()
{ {
esp_err_t ret = nvs_flash_init(); esp_err_t ret = nvs_flash_init();
@@ -100,9 +102,8 @@ bool Init_NVS_SDCard()
ESP_ERROR_CHECK(nvs_flash_erase()); ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init(); ret = nvs_flash_init();
} }
////////////////////////////////////////////////
ESP_LOGI(TAG, "Using SDMMC peripheral"); ESP_LOGD(TAG, "Using SDMMC peripheral");
sdmmc_host_t host = SDMMC_HOST_DEFAULT(); sdmmc_host_t host = SDMMC_HOST_DEFAULT();
// This initializes the slot without card detect (CD) and write protect (WP) signals. // This initializes the slot without card detect (CD) and write protect (WP) signals.
@@ -110,20 +111,19 @@ bool Init_NVS_SDCard()
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
// To use 1-line SD mode, uncomment the following line: // To use 1-line SD mode, uncomment the following line:
#ifdef __SD_USE_ONE_LINE_MODE__
#ifdef __SD_USE_ONE_LINE_MODE__ slot_config.width = 1;
slot_config.width = 1; #endif
#endif
// GPIOs 15, 2, 4, 12, 13 should have external 10k pull-ups. // GPIOs 15, 2, 4, 12, 13 should have external 10k pull-ups.
// Internal pull-ups are not sufficient. However, enabling internal pull-ups // Internal pull-ups are not sufficient. However, enabling internal pull-ups
// does make a difference some boards, so we do that here. // does make a difference some boards, so we do that here.
gpio_set_pull_mode(GPIO_NUM_15, GPIO_PULLUP_ONLY); // CMD, needed in 4- and 1- line modes gpio_set_pull_mode(GPIO_NUM_15, GPIO_PULLUP_ONLY); // CMD, needed in 4- and 1- line modes
gpio_set_pull_mode(GPIO_NUM_2, GPIO_PULLUP_ONLY); // D0, needed in 4- and 1-line modes gpio_set_pull_mode(GPIO_NUM_2, GPIO_PULLUP_ONLY); // D0, needed in 4- and 1-line modes
#ifndef __SD_USE_ONE_LINE_MODE__ #ifndef __SD_USE_ONE_LINE_MODE__
gpio_set_pull_mode(GPIO_NUM_4, GPIO_PULLUP_ONLY); // D1, needed in 4-line mode only gpio_set_pull_mode(GPIO_NUM_4, GPIO_PULLUP_ONLY); // D1, needed in 4-line mode only
gpio_set_pull_mode(GPIO_NUM_12, GPIO_PULLUP_ONLY); // D2, needed in 4-line mode only gpio_set_pull_mode(GPIO_NUM_12, GPIO_PULLUP_ONLY); // D2, needed in 4-line mode only
#endif #endif
gpio_set_pull_mode(GPIO_NUM_13, GPIO_PULLUP_ONLY); // D3, needed in 4- and 1-line modes gpio_set_pull_mode(GPIO_NUM_13, GPIO_PULLUP_ONLY); // D3, needed in 4- and 1-line modes
// Options for mounting the filesystem. // Options for mounting the filesystem.
@@ -135,246 +135,308 @@ bool Init_NVS_SDCard()
.allocation_unit_size = 16 * 1024 .allocation_unit_size = 16 * 1024
}; };
sdmmc_card_t* card;
// Use settings defined above to initialize SD card and mount FAT filesystem. // Use settings defined above to initialize SD card and mount FAT filesystem.
// Note: esp_vfs_fat_sdmmc_mount is an all-in-one convenience function. // Note: esp_vfs_fat_sdmmc_mount is an all-in-one convenience function.
// Please check its source code and implement error recovery when developing // Please check its source code and implement error recovery when developing
// production applications. // production applications.
sdmmc_card_t* card;
ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card); ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card);
if (ret != ESP_OK) { if (ret != ESP_OK) {
if (ret == ESP_FAIL) { if (ret == ESP_FAIL) {
ESP_LOGE(TAG, "Failed to mount filesystem. " ESP_LOGE(TAG, "Failed to mount FAT filesystem on SD card. Check SD card filesystem (only FAT supported) or try another card");
"If you want the card to be formatted, set format_if_mount_failed = true."); StatusLED(SDCARD_INIT, 1, true);
} else { }
ESP_LOGE(TAG, "Failed to initialize the card (%s). " else if (ret == 263) { // Error code: 0x107 --> usually: SD not found
"Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret)); ESP_LOGE(TAG, "SD card init failed. Check if SD card is properly inserted into SD card slot or try another card");
StatusLED(SDCARD_INIT, 2, true);
}
else {
ESP_LOGE(TAG, "SD card init failed. Check error code or try another card");
StatusLED(SDCARD_INIT, 3, true);
} }
return false; return false;
} }
sdmmc_card_print_info(stdout, card); //sdmmc_card_print_info(stdout, card); // With activated CONFIG_NEWLIB_NANO_FORMAT --> capacity not printed correctly anymore
SaveSDCardInfo(card); SaveSDCardInfo(card);
return true; return true;
} }
void task_MainInitError_blink(void *pvParameter)
{
gpio_pad_select_gpio(BLINK_GPIO);
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
TickType_t xDelay;
xDelay = 100 / portTICK_PERIOD_MS;
ESP_LOGD(TAG, "SD-Card could not be inialized - STOP THE PROGRAMM HERE");
while (1)
{
gpio_set_level(BLINK_GPIO, 1);
vTaskDelay( xDelay );
gpio_set_level(BLINK_GPIO, 0);
vTaskDelay( xDelay );
}
vTaskDelete(NULL); //Delete this task if it exits from the loop above
}
extern "C" void app_main(void) extern "C" void app_main(void)
{ {
//#ifdef CONFIG_HEAP_TRACING_STANDALONE
//#ifdef CONFIG_HEAP_TRACING_STANDALONE #if defined HEAP_TRACING_MAIN_WIFI || defined HEAP_TRACING_MAIN_START
#if defined HEAP_TRACING_MAIN_WIFI || defined HEAP_TRACING_MAIN_START //register a buffer to record the memory trace
//register a buffer to record the memory trace ESP_ERROR_CHECK( heap_trace_init_standalone(trace_record, NUM_RECORDS) );
ESP_ERROR_CHECK( heap_trace_init_standalone(trace_record, NUM_RECORDS) ); #endif
#endif
TickType_t xDelay; TickType_t xDelay;
#ifdef DISABLE_BROWNOUT_DETECTOR #ifdef DISABLE_BROWNOUT_DETECTOR
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
#endif #endif
ESP_LOGI(TAG, "\n\n\n\n\n"); // Add mark on log to see when it restarted #ifdef HEAP_TRACING_MAIN_START
ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
#endif
// ********************************************
// Highlight start of app_main
// ********************************************
ESP_LOGI(TAG, "\n\n\n\n================ Start app_main =================");
// Init camera
// ********************************************
PowerResetCamera(); PowerResetCamera();
esp_err_t camStatus = Camera.InitCam(); esp_err_t camStatus = Camera.InitCam();
Camera.LightOnOff(false); Camera.LightOnOff(false);
xDelay = 2000 / portTICK_PERIOD_MS;
ESP_LOGD(TAG, "After camera initialization: sleep for: %ldms", (long) xDelay);
vTaskDelay( xDelay );
xDelay = 2000 / portTICK_PERIOD_MS;
ESP_LOGD(TAG, "After camera initialization: sleep for: %ldms", (long) xDelay * CONFIG_FREERTOS_HZ/portTICK_PERIOD_MS);
vTaskDelay( xDelay );
// Init SD card
// ********************************************
if (!Init_NVS_SDCard()) if (!Init_NVS_SDCard())
{ {
xTaskCreate(&task_MainInitError_blink, "task_MainInitError_blink", configMINIMAL_STACK_SIZE * 64, NULL, tskIDLE_PRIORITY+1, NULL); ESP_LOGE(TAG, "Device init aborted!");
return; // No way to continue without SD-Card! return; // No way to continue without working SD card!
} }
// SD card: Create directories (if not already existing)
// ********************************************
bool bDirStatus = LogFile.CreateLogDirectories(); // needed for logging + image saving
bDirStatus = MakeDir("/sdcard/firmware"); // needed for firmware update
bDirStatus = MakeDir("/sdcard/img_tmp"); // needed for setting up alignment marks
bDirStatus = MakeDir("/sdcard/demo"); // needed for demo mode
if (!bDirStatus) {
StatusLED(SDCARD_CHECK, 1, false);
}
// ********************************************
// Highlight start of logfile logging
// Default Log Level: INFO -> Everything which needs to be logged during boot should be have level INFO, WARN OR ERROR
// ********************************************
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "==================== Start ======================");
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
// Migrate parameter in config.ini to new naming (firmware 14.1 and newer)
// ********************************************
migrateConfiguration(); migrateConfiguration();
setupTime(); // Init time (as early as possible, but SD card needs to be initialized)
// ********************************************
setupTime(); // NTP time service: Status of time synchronization will be checked after every round (server_tflite.cpp)
string versionFormated = getFwVersion() + ", Date/Time: " + std::string(BUILD_TIME) + \ // SD card: basic RW check
// ********************************************
// TODO
// Check for updates
// ********************************************
CheckOTAUpdate();
CheckUpdate();
// Start SoftAP for initial remote setup
// Note: Start AP if no wlan.ini and/or config.ini available, e.g. SD empty; function does not exit anymore until reboot
// ********************************************
#ifdef ENABLE_SOFTAP
CheckStartAPMode();
#endif
// SD card: Check folder structure
// ********************************************
// TODO
// Check version information
// ********************************************
std::string versionFormated = getFwVersion() + ", Date/Time: " + std::string(BUILD_TIME) + \
", Web UI: " + getHTMLversion(); ", Web UI: " + getHTMLversion();
if (std::string(GIT_TAG) != "") { // We are on a tag, add it as prefix if (std::string(GIT_TAG) != "") { // We are on a tag, add it as prefix
string versionFormated = "Tag: '" + std::string(GIT_TAG) + "', " + versionFormated; versionFormated = "Tag: '" + std::string(GIT_TAG) + "', " + versionFormated;
} }
LogFile.CreateLogDirectories();
MakeDir("/sdcard/demo"); // needed for demo mode
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "==================== Startup ====================");
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
LogFile.WriteToFile(ESP_LOG_INFO, TAG, versionFormated); LogFile.WriteToFile(ESP_LOG_INFO, TAG, versionFormated);
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Reset reason: " + getResetReason());
#ifdef DEBUG_ENABLE_SYSINFO
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL( 4, 0, 0 )
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Device Info : " + get_device_info() );
ESP_LOGD(TAG, "Device infos %s", get_device_info().c_str());
#endif
#endif //DEBUG_ENABLE_SYSINFO
#ifdef USE_HIMEM_IF_AVAILABLE
#ifdef DEBUG_HIMEM_MEMORY_CHECK
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Himem mem check : " + himem_memory_check() );
ESP_LOGD(TAG, "Himem mem check %s", himem_memory_check().c_str());
#endif
#endif
CheckIsPlannedReboot();
CheckOTAUpdate();
CheckUpdate();
#ifdef ENABLE_SOFTAP
CheckStartAPMode(); // if no wlan.ini and/or config.ini --> AP ist startet and this function does not exit anymore until reboot
#endif
#ifdef HEAP_TRACING_MAIN_WIFI
ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
#endif
char *ssid = NULL, *passwd = NULL, *hostname = NULL, *ip = NULL, *gateway = NULL, *netmask = NULL, *dns = NULL; int rssithreshold = 0;
LoadWlanFromFile(WLAN_CONFIG_FILE, ssid, passwd, hostname, ip, gateway, netmask, dns, rssithreshold);
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "WLAN-Settings - RSSI-Threshold: " + to_string(rssithreshold));
if (ssid != NULL && passwd != NULL)
#ifdef __HIDE_PASSWORD
ESP_LOGD(TAG, "WLan: %s, XXXXXX", ssid);
#else
ESP_LOGD(TAG, "WLan: %s, %s", ssid, passwd);
#endif
else
ESP_LOGD(TAG, "No SSID and PASSWORD set!!!");
if (hostname != NULL)
ESP_LOGD(TAG, "Hostname: %s", hostname);
else
ESP_LOGD(TAG, "Hostname not set");
if (ip != NULL && gateway != NULL && netmask != NULL)
ESP_LOGD(TAG, "Fixed IP: %s, Gateway %s, Netmask %s", ip, gateway, netmask);
if (dns != NULL)
ESP_LOGD(TAG, "DNS IP: %s", dns);
wifi_init_sta(ssid, passwd, hostname, ip, gateway, netmask, dns, rssithreshold);
xDelay = 2000 / portTICK_PERIOD_MS;
ESP_LOGD(TAG, "main: sleep for: %ldms", (long) xDelay);
vTaskDelay( xDelay );
#ifdef HEAP_TRACING_MAIN_WIFI
ESP_ERROR_CHECK( heap_trace_stop() );
heap_trace_dump();
#endif
#ifdef HEAP_TRACING_MAIN_START
ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
#endif
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "================== Main Started =================");
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
if (getHTMLcommit().substr(0, 7) == "?")
LogFile.WriteToFile(ESP_LOG_WARN, TAG, std::string("Failed to read file html/version.txt to parse Web UI version"));
if (getHTMLcommit().substr(0, 7) != std::string(GIT_REV).substr(0, 7)) { // Compare the first 7 characters of both hashes if (getHTMLcommit().substr(0, 7) != std::string(GIT_REV).substr(0, 7)) { // Compare the first 7 characters of both hashes
LogFile.WriteToFile(ESP_LOG_WARN, TAG, std::string("Web UI version (") + getHTMLcommit() + ") does not match firmware version (" + std::string(GIT_REV) + ") !"); LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Web UI version (" + getHTMLcommit() + ") does not match firmware version (" + std::string(GIT_REV) + ")");
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Please make sure to setup the SD-Card properly (check the documentation) or re-install using the AI-on-the-edge-device__update__*.zip!"); LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Recommendation: Repeat installation using AI-on-the-edge-device__update__*.zip");
} }
std::string zw = getCurrentTimeString("%Y%m%d-%H%M%S"); // Check reboot reason
ESP_LOGD(TAG, "time %s", zw.c_str()); // ********************************************
CheckIsPlannedReboot();
if (!getIsPlannedReboot() && (esp_reset_reason() == ESP_RST_PANIC)) { // If system reboot was not triggered by user and reboot was caused by execption
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Reset reason: " + getResetReason());
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Device was rebooted due to a software exception! Log level is set to DEBUG until the next reboot. "
"Flow init is delayed by 5 minutes to check the logs or do an OTA update");
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Keep device running until crash occurs again and check logs after device is up again");
LogFile.setLogLevel(ESP_LOG_DEBUG);
}
else {
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Reset reason: " + getResetReason());
}
#ifdef HEAP_TRACING_MAIN_START
ESP_ERROR_CHECK( heap_trace_stop() );
heap_trace_dump();
#endif
#ifdef HEAP_TRACING_MAIN_START #ifdef HEAP_TRACING_MAIN_WIFI
ESP_ERROR_CHECK( heap_trace_stop() ); ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
heap_trace_dump(); #endif
#endif
/* Check if PSRAM can be initalized */ // Read WLAN parameter and start WIFI
esp_err_t ret; // ********************************************
ret = esp_spiram_init(); int iWLANStatus = LoadWlanFromFile(WLAN_CONFIG_FILE);
if (ret == ESP_FAIL) { // Failed to init PSRAM, most likely not available or broken if (iWLANStatus == 0) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to initialize PSRAM (" + std::to_string(ret) + ")!"); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "WLAN config loaded, init WIFI...");
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Either your device misses the PSRAM chip or it is broken!"); if (wifi_init_sta() != ESP_OK) {
setSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD); LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "WIFI init failed. Device init aborted!");
} StatusLED(WLAN_INIT, 3, true);
else { // PSRAM init ok return;
/* Check if PSRAM provides at least 4 MB */
size_t psram_size = esp_spiram_get_size();
// size_t psram_size = esp_psram_get_size(); // comming in IDF 5.0
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "The device has " + std::to_string(psram_size/1024/1024) + " MBytes of PSRAM");
if (psram_size < (4*1024*1024)) { // PSRAM is below 4 MBytes
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "At least 4 MBytes are required!");
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Does the device really have a 4 Mbytes PSRAM?");
setSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD);
} }
} }
else if (iWLANStatus == -1) { // wlan.ini not available, potentially empty or content not readable
/* Check available Heap memory */ StatusLED(WLAN_INIT, 1, true);
size_t _hsize = getESPHeapSize(); return; // No way to continue without reading the wlan.ini
if (_hsize < 4000000) { // Check available Heap memory for a bit less than 4 MB (a test on a good device showed 4187558 bytes to be available) }
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Not enough Heap memory available. Expected around 4 MBytes, but only " + std::to_string(_hsize) + " Bytes are available! That is not enough for this firmware!"); else if (iWLANStatus == -2) { // SSID or password not configured
setSystemStatusFlag(SYSTEM_STATUS_HEAP_TOO_SMALL); StatusLED(WLAN_INIT, 2, true);
} else { // Heap memory is ok return; // No way to continue with empty SSID or password!
if (camStatus != ESP_OK) {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Failed to initialize camera module, retrying...");
PowerResetCamera();
esp_err_t camStatus = Camera.InitCam();
Camera.LightOnOff(false);
xDelay = 2000 / portTICK_PERIOD_MS;
ESP_LOGD(TAG, "After camera initialization: sleep for: %ldms", (long) xDelay);
vTaskDelay( xDelay );
if (camStatus != ESP_OK) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to initialize camera module!");
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Check that your camera module is working and connected properly!");
setSystemStatusFlag(SYSTEM_STATUS_CAM_BAD);
}
} else { // Test Camera
if (!Camera.testCamera()) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera Framebuffer cannot be initialized!");
/* Easiest would be to simply restart here and try again,
how ever there seem to be systems where it fails at startup but still work corectly later.
Therefore we treat it still as successed! */
setSystemStatusFlag(SYSTEM_STATUS_CAM_FB_BAD);
}
else {
Camera.LightOnOff(false);
}
}
} }
xDelay = 2000 / portTICK_PERIOD_MS; xDelay = 2000 / portTICK_PERIOD_MS;
ESP_LOGD(TAG, "main: sleep for: %ldms", (long) xDelay*10); ESP_LOGD(TAG, "main: sleep for: %ldms", (long) xDelay * CONFIG_FREERTOS_HZ/portTICK_PERIOD_MS);
vTaskDelay( xDelay );
// Set log level for wifi component to WARN level (default: INFO; only relevant for serial console)
// ********************************************
esp_log_level_set("wifi", ESP_LOG_WARN);
#ifdef HEAP_TRACING_MAIN_WIFI
ESP_ERROR_CHECK( heap_trace_stop() );
heap_trace_dump();
#endif
#ifdef DEBUG_ENABLE_SYSINFO
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL( 4, 0, 0 )
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Device Info : " + get_device_info() );
ESP_LOGD(TAG, "Device infos %s", get_device_info().c_str());
#endif
#endif //DEBUG_ENABLE_SYSINFO
#ifdef USE_HIMEM_IF_AVAILABLE
#ifdef DEBUG_HIMEM_MEMORY_CHECK
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Himem mem check : " + himem_memory_check() );
ESP_LOGD(TAG, "Himem mem check %s", himem_memory_check().c_str());
#endif
#endif
// Init external PSRAM
// ********************************************
esp_err_t PSRAMStatus = esp_spiram_init();
if (PSRAMStatus != ESP_OK) { // ESP_FAIL -> Failed to init PSRAM
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "PSRAM init failed (" + std::to_string(PSRAMStatus) + ")! PSRAM not found or defective");
setSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD);
StatusLED(PSRAM_INIT, 1, true);
}
else { // ESP_OK -> PSRAM init OK --> continue to check PSRAM size
size_t psram_size = esp_spiram_get_size(); // size_t psram_size = esp_psram_get_size(); // comming in IDF 5.0
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "PSRAM size: " + std::to_string(psram_size) + " byte (" + std::to_string(psram_size/1024/1024) +
"MB / " + std::to_string(psram_size/1024/1024*8) + "MBit)");
// Check PSRAM size
// ********************************************
if (psram_size < (4*1024*1024)) { // PSRAM is below 4 MBytes (32Mbit)
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "PSRAM size >= 4MB (32Mbit) is mandatory to run this application");
setSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD);
StatusLED(PSRAM_INIT, 2, true);
}
else { // PSRAM size OK --> continue to check heap size
size_t _hsize = getESPHeapSize();
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Total heap: " + std::to_string(_hsize) + " byte");
// Check heap memory
// ********************************************
if (_hsize < 4000000) { // Check available Heap memory for a bit less than 4 MB (a test on a good device showed 4187558 bytes to be available)
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Total heap >= 4000000 byte is mandatory to run this application");
setSystemStatusFlag(SYSTEM_STATUS_HEAP_TOO_SMALL);
StatusLED(PSRAM_INIT, 3, true);
}
else { // HEAP size OK --> continue to check camera init
// Check camera init
// ********************************************
if (camStatus != ESP_OK) { // Camera init failed, retry to init
char camStatusHex[33];
sprintf(camStatusHex,"0x%02x", camStatus);
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Camera init failed (" + std::string(camStatusHex) + "), retrying...");
PowerResetCamera();
camStatus = Camera.InitCam();
Camera.LightOnOff(false);
xDelay = 2000 / portTICK_PERIOD_MS;
ESP_LOGD(TAG, "After camera initialization: sleep for: %ldms", (long) xDelay * CONFIG_FREERTOS_HZ/portTICK_PERIOD_MS);
vTaskDelay( xDelay );
if (camStatus != ESP_OK) { // Camera init failed again
sprintf(camStatusHex,"0x%02x", camStatus);
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera init failed (" + std::string(camStatusHex) +
")! Check camera module and/or proper electrical connection");
setSystemStatusFlag(SYSTEM_STATUS_CAM_BAD);
StatusLED(CAM_INIT, 1, true);
}
}
else { // ESP_OK -> Camera init OK --> continue to perform camera framebuffer check
// Camera framebuffer check
// ********************************************
if (!Camera.testCamera()) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera framebuffer check failed");
// Easiest would be to simply restart here and try again,
// how ever there seem to be systems where it fails at startup but still work correctly later.
// Therefore we treat it still as successed! */
setSystemStatusFlag(SYSTEM_STATUS_CAM_FB_BAD);
StatusLED(CAM_INIT, 2, false);
}
Camera.LightOnOff(false); // make sure flashlight is off before start of flow
// Print camera infos
// ********************************************
char caminfo[50];
sensor_t * s = esp_camera_sensor_get();
sprintf(caminfo, "PID: 0x%02x, VER: 0x%02x, MIDL: 0x%02x, MIDH: 0x%02x", s->id.PID, s->id.VER, s->id.MIDH, s->id.MIDL);
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Camera info: " + std::string(caminfo));
}
}
}
}
// Print Device info
// ********************************************
esp_chip_info_t chipInfo;
esp_chip_info(&chipInfo);
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Device info: CPU frequency: " + std::to_string(CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ) +
"Mhz, CPU cores: " + std::to_string(chipInfo.cores) +
", Chip revision: " + std::to_string(chipInfo.revision));
// Print SD-Card info
// ********************************************
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "SD card info: Name: " + getSDCardName() + ", Capacity: " +
getSDCardCapacity() + "MB, Free: " + getSDCardFreePartitionSpace() + "MB");
xDelay = 2000 / portTICK_PERIOD_MS;
ESP_LOGD(TAG, "main: sleep for: %ldms", (long) xDelay * CONFIG_FREERTOS_HZ/portTICK_PERIOD_MS);
vTaskDelay( xDelay ); vTaskDelay( xDelay );
// Start webserver + register handler
// ********************************************
ESP_LOGD(TAG, "starting servers"); ESP_LOGD(TAG, "starting servers");
server = start_webserver(); server = start_webserver();
@@ -391,25 +453,23 @@ extern "C" void app_main(void)
ESP_LOGD(TAG, "Before reg server main"); ESP_LOGD(TAG, "Before reg server main");
register_server_main_uri(server, "/sdcard"); register_server_main_uri(server, "/sdcard");
// Only for testing purpose
/* Testing */
//setSystemStatusFlag(SYSTEM_STATUS_CAM_FB_BAD); //setSystemStatusFlag(SYSTEM_STATUS_CAM_FB_BAD);
//setSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD); //setSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD);
/* Main Init has successed or only an error which allows to continue operation */ // Check main init + start TFlite task
// ********************************************
if (getSystemStatus() == 0) { // No error flag is set if (getSystemStatus() == 0) { // No error flag is set
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Initialization completed successfully!"); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Initialization completed successfully! Starting flow task ...");
ESP_LOGD(TAG, "Before do autostart");
TFliteDoAutoStart(); TFliteDoAutoStart();
} }
else if (isSetSystemStatusFlag(SYSTEM_STATUS_CAM_FB_BAD) || // Non critical errors occured, we try to continue... else if (isSetSystemStatusFlag(SYSTEM_STATUS_CAM_FB_BAD) || // Non critical errors occured, we try to continue...
isSetSystemStatusFlag(SYSTEM_STATUS_NTP_BAD)) { isSetSystemStatusFlag(SYSTEM_STATUS_NTP_BAD)) {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Initialization completed with errors, but trying to continue..."); LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Initialization completed with errors! Starting flow task ...");
ESP_LOGD(TAG, "Before do autostart");
TFliteDoAutoStart(); TFliteDoAutoStart();
} }
else { // Any other error is critical and makes running the flow impossible. else { // Any other error is critical and makes running the flow impossible. Init is going to abort.
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Initialization failed. Not starting flows!"); LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Initialization failed. Flow task start aborted!");
} }
} }

View File

@@ -8,6 +8,7 @@
#include "time_sntp.h" #include "time_sntp.h"
#include "connect_wlan.h" #include "connect_wlan.h"
#include "read_wlanini.h"
#include "version.h" #include "version.h"
@@ -83,7 +84,7 @@ esp_err_t info_get_handler(httpd_req_t *req)
else if (_task.compare("Hostname") == 0) else if (_task.compare("Hostname") == 0)
{ {
std::string zw; std::string zw;
zw = std::string(hostname); zw = std::string(wlan_config.hostname);
httpd_resp_sendstr(req, zw.c_str()); httpd_resp_sendstr(req, zw.c_str());
return ESP_OK; return ESP_OK;
} }

View File

@@ -27,6 +27,7 @@
#include "server_help.h" #include "server_help.h"
#include "defines.h" #include "defines.h"
#include "Helper.h" #include "Helper.h"
#include "statusled.h"
#include "server_ota.h" #include "server_ota.h"
#include "lwip/err.h" #include "lwip/err.h"
@@ -40,22 +41,24 @@
bool isConfigINI = false; bool isConfigINI = false;
bool isWlanINI = false; bool isWlanINI = false;
static const char *TAG = "wifi softAP"; static const char *TAG = "WIFI AP";
static void wifi_event_handler(void* arg, esp_event_base_t event_base, static void wifi_event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data) int32_t event_id, void* event_data)
{ {
if (event_id == WIFI_EVENT_AP_STACONNECTED) { if (event_id == WIFI_EVENT_AP_STACONNECTED) {
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data; wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d", ESP_LOGI(TAG, "station " MACSTR " join, AID=%d",
MAC2STR(event->mac), event->aid); MAC2STR(event->mac), event->aid);
} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) { } else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data; wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d", ESP_LOGI(TAG, "station " MACSTR " leave, AID=%d",
MAC2STR(event->mac), event->aid); MAC2STR(event->mac), event->aid);
} }
} }
void wifi_init_softAP(void) void wifi_init_softAP(void)
{ {
ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_netif_init());
@@ -87,7 +90,7 @@ void wifi_init_softAP(void)
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config)); ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start()); ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d", ESP_LOGI(TAG, "started with SSID \"%s\", password: \"%s\", channel: %d. Connect to AP and open http://192.168.4.1",
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL); EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL);
} }
@@ -136,18 +139,18 @@ void SendHTTPResponse(httpd_req_t *req)
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str())); httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
// message = "</tr><tr><td> Hostname</td><td><input type=\"text\" name=\"hostname\" id=\"hostname\"></td><td></td>"; // message = "</tr><tr><td> Hostname</td><td><input type=\"text\" name=\"hostname\" id=\"hostname\"></td><td></td>";
// message += "</tr><tr><td>Fixed IP</td><td><input type=\"text\" name=\"ip\" id=\"ip\"></td><td>Leave emtpy if set by router</td></tr>"; // message += "</tr><tr><td>Fixed IP</td><td><input type=\"text\" name=\"ip\" id=\"ip\"></td><td>Leave emtpy if set by router (DHCP)</td></tr>";
// message += "<tr><td>gateway</td><td><input type=\"text\" name=\"gateway\" id=\"gateway\"></td><td>Leave emtpy if set by router</td></tr>"; // message += "<tr><td>Gateway</td><td><input type=\"text\" name=\"gateway\" id=\"gateway\"></td><td>Leave emtpy if set by router (DHCP)</td></tr>";
// message += "<tr><td>netmask</td><td><input type=\"text\" name=\"netmask\" id=\"netmask\"></td><td>Leave emtpy if set by router</td>"; // message += "<tr><td>Netmask</td><td><input type=\"text\" name=\"netmask\" id=\"netmask\"></td><td>Leave emtpy if set by router (DHCP)</td>";
// message += "</tr><tr><td>DNS</td><td><input type=\"text\" name=\"dns\" id=\"dns\"></td><td>Leave emtpy if set by router</td></tr>"; // message += "</tr><tr><td>DNS</td><td><input type=\"text\" name=\"dns\" id=\"dns\"></td><td>Leave emtpy if set by router (DHCP)</td></tr>";
// message += "<tr><td>RSSI Threshold</td><td><input type=\"number\" name=\"name\" id=\"threshold\" min=\"-100\" max=\"0\" step=\"1\" value = \"0\"></td><td>WLAN Mesh Parameter: Threshold for RSSI value to check for start switching access point in a mesh system.Possible values: -100 to 0, 0 = disabled - Value will be transfered to wlan.ini at next startup)</td></tr>"; // message += "<tr><td>RSSI Threshold</td><td><input type=\"number\" name=\"name\" id=\"threshold\" min=\"-100\" max=\"0\" step=\"1\" value = \"0\"></td><td>WLAN Mesh Parameter: Threshold for RSSI value to check for start switching access point in a mesh system (if actual RSSI is lower). Possible values: -100 to 0, 0 = disabled - Value will be transfered to wlan.ini at next startup)</td></tr>";
// httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str())); // httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
message = "<button class=\"button\" type=\"button\" onclick=\"wr()\">Write wlan.ini</button>"; message = "<button class=\"button\" type=\"button\" onclick=\"wr()\">Write wlan.ini</button>";
message += "<script language=\"JavaScript\">async function wr(){"; message += "<script language=\"JavaScript\">async function wr(){";
message += "api = \"/config?\"+\"ssid=\"+document.getElementById(\"ssid\").value+\"&pwd=\"+document.getElementById(\"password\").value;"; message += "api = \"/config?\"+\"ssid=\"+document.getElementById(\"ssid\").value+\"&pwd=\"+document.getElementById(\"password\").value;";
// message += "api = \"/config?\"+\"ssid=\"+document.getElementById(\"ssid\").value+\"&pwd=\"+document.getElementById(\"password\").value+\"&hn=\"+document.getElementById(\"hostname\").value+\"&ip=\"+document.getElementById(\"ip\").value+\"&gw=\"+document.getElementById(\"gateway\").value+\"&nm=\"+document.getElementById(\"netmask\").value+\"&dns=\"+document.getElementById(\"dns\").value+\"&rssi=\"+document.getElementById(\"threshold\").value;"; // message += "api = \"/config?\"+\"ssid=\"+document.getElementById(\"ssid\").value+\"&pwd=\"+document.getElementById(\"password\").value+\"&hn=\"+document.getElementById(\"hostname\").value+\"&ip=\"+document.getElementById(\"ip\").value+\"&gw=\"+document.getElementById(\"gateway\").value+\"&nm=\"+document.getElementById(\"netmask\").value+\"&dns=\"+document.getElementById(\"dns\").value+\"&rssithreshold=\"+document.getElementById(\"threshold\").value;";
message += "fetch(api);await new Promise(resolve => setTimeout(resolve, 1000));location.reload();}</script>"; message += "fetch(api);await new Promise(resolve => setTimeout(resolve, 1000));location.reload();}</script>";
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str())); httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
return; return;
@@ -164,8 +167,6 @@ void SendHTTPResponse(httpd_req_t *req)
} }
esp_err_t test_handler(httpd_req_t *req) esp_err_t test_handler(httpd_req_t *req)
{ {
SendHTTPResponse(req); SendHTTPResponse(req);
@@ -182,7 +183,7 @@ esp_err_t reboot_handlerAP(httpd_req_t *req)
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Trigger reboot due to firmware update."); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Trigger reboot due to firmware update.");
doRebootOTA(); doRebootOTA();
return ESP_OK; return ESP_OK;
}; }
esp_err_t config_ini_handler(httpd_req_t *req) esp_err_t config_ini_handler(httpd_req_t *req)
@@ -201,9 +202,10 @@ esp_err_t config_ini_handler(httpd_req_t *req)
std::string hn = ""; // hostname std::string hn = ""; // hostname
std::string ip = ""; std::string ip = "";
std::string gw = ""; // gateway std::string gw = ""; // gateway
std::string nm = ""; // nm std::string nm = ""; // netmask
std::string dns = ""; std::string dns = "";
std::string rssi = ""; std::string rssithreshold = ""; //rssi threshold for WIFI roaming
std::string text = "";
if (httpd_req_get_url_query_str(req, _query, 400) == ESP_OK) if (httpd_req_get_url_query_str(req, _query, 400) == ESP_OK)
@@ -258,77 +260,106 @@ esp_err_t config_ini_handler(httpd_req_t *req)
dns = UrlDecode(std::string(_valuechar)); dns = UrlDecode(std::string(_valuechar));
} }
if (httpd_query_key_value(_query, "rssi", _valuechar, 30) == ESP_OK) if (httpd_query_key_value(_query, "rssithreshold", _valuechar, 30) == ESP_OK)
{ {
ESP_LOGD(TAG, "rssi is found: %s", _valuechar); ESP_LOGD(TAG, "rssithreshold is found: %s", _valuechar);
rssi = UrlDecode(std::string(_valuechar)); rssithreshold = UrlDecode(std::string(_valuechar));
} }
}; }
FILE* configfilehandle = fopen(WLAN_CONFIG_FILE, "w"); FILE* configfilehandle = fopen(WLAN_CONFIG_FILE, "w");
text = ";++++++++++++++++++++++++++++++++++\n";
text += "; AI on the edge - WLAN configuration\n";
text += "; ssid: Name of WLAN network (mandatory), e.g. \"WLAN-SSID\"\n";
text += "; password: Password of WLAN network (mandatory), e.g. \"PASSWORD\"\n\n";
fputs(text.c_str(), configfilehandle);
if (ssid.length()) if (ssid.length())
ssid = "ssid = \"" + ssid + "\"\n"; ssid = "ssid = \"" + ssid + "\"\n";
else else
ssid = ";ssid = \"\"\n"; ssid = "ssid = \"\"\n";
fputs(ssid.c_str(), configfilehandle); fputs(ssid.c_str(), configfilehandle);
if (pwd.length()) if (pwd.length())
pwd = "password = \"" + pwd + "\"\n"; pwd = "password = \"" + pwd + "\"\n";
else else
pwd = ";password = \"\"\n"; pwd = "password = \"\"\n";
fputs(pwd.c_str(), configfilehandle); fputs(pwd.c_str(), configfilehandle);
text = "\n;++++++++++++++++++++++++++++++++++\n";
text += "; Hostname: Name of device in network\n";
text += "; This parameter can be configured via WebUI configuration\n";
text += "; Default: \"watermeter\", if nothing is configured\n\n";
fputs(text.c_str(), configfilehandle);
if (hn.length()) if (hn.length())
hn = "hostname = \"" + hn + "\"\n"; hn = "hostname = \"" + hn + "\"\n";
else else
hn = ";hostname = \"\"\n"; hn = ";hostname = \"watermeter\"\n";
fputs(hn.c_str(), configfilehandle); fputs(hn.c_str(), configfilehandle);
text = "\n;++++++++++++++++++++++++++++++++++\n";
text += "; Fixed IP: If you like to use fixed IP instead of DHCP (default), the following\n";
text += "; parameters needs to be configured: ip, gateway, netmask are mandatory, dns optional\n\n";
fputs(text.c_str(), configfilehandle);
if (ip.length()) if (ip.length())
ip = "ip = \"" + ip + "\"\n"; ip = "ip = \"" + ip + "\"\n";
else else
ip = ";ip = \"\"\n"; ip = ";ip = \"xxx.xxx.xxx.xxx\"\n";
fputs(ip.c_str(), configfilehandle); fputs(ip.c_str(), configfilehandle);
if (gw.length()) if (gw.length())
gw = "gateway = \"" + gw + "\"\n"; gw = "gateway = \"" + gw + "\"\n";
else else
gw = ";gateway = \"\"\n"; gw = ";gateway = \"xxx.xxx.xxx.xxx\"\n";
fputs(gw.c_str(), configfilehandle); fputs(gw.c_str(), configfilehandle);
if (nm.length()) if (nm.length())
nm = "netmask = \"" + nm + "\"\n"; nm = "netmask = \"" + nm + "\"\n";
else else
nm = ";netmask = \"\"\n"; nm = ";netmask = \"xxx.xxx.xxx.xxx\"\n";
fputs(nm.c_str(), configfilehandle); fputs(nm.c_str(), configfilehandle);
text = "\n;++++++++++++++++++++++++++++++++++\n";
text += "; DNS server (optional, if no DNS is configured, gateway address will be used)\n\n";
fputs(text.c_str(), configfilehandle);
if (dns.length()) if (dns.length())
dns = "dns = \"" + dns + "\"\n"; dns = "dns = \"" + dns + "\"\n";
else else
dns = ";dns = \"\"\n"; dns = ";dns = \"xxx.xxx.xxx.xxx\"\n";
fputs(dns.c_str(), configfilehandle); fputs(dns.c_str(), configfilehandle);
if (rssi.length()) text = "\n;++++++++++++++++++++++++++++++++++\n";
rssi = "RSSIThreshold = \"" + rssi + "\"\n"; text += "; WIFI Roaming:\n";
text += "; Network assisted roaming protocol is activated by default\n";
text += "; AP / mesh system needs to support roaming protocol 802.11k/v\n";
text += ";\n";
text += "; Optional feature (usually not neccessary):\n";
text += "; RSSI Threshold for client requested roaming query (RSSI < RSSIThreshold)\n";
text += "; Note: This parameter can be configured via WebUI configuration\n";
text += "; Default: 0 = Disable client requested roaming query\n\n";
fputs(text.c_str(), configfilehandle);
if (rssithreshold.length())
rssithreshold = "RSSIThreshold = " + rssithreshold + "\n";
else else
rssi = ";rssi = \"\"\n"; rssithreshold = "RSSIThreshold = 0\n";
fputs(rssi.c_str(), configfilehandle); fputs(rssithreshold.c_str(), configfilehandle);
fflush(configfilehandle); fflush(configfilehandle);
fclose(configfilehandle); fclose(configfilehandle);
std::string zw = "ota without parameter - should not be the case!"; std::string zw = "ota without parameter - should not be the case!";
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
httpd_resp_send(req, zw.c_str(), strlen(zw.c_str())); httpd_resp_send(req, zw.c_str(), zw.length());
httpd_resp_send_chunk(req, NULL, 0);
ESP_LOGE(TAG, "end config.ini");
ESP_LOGD(TAG, "end config.ini");
return ESP_OK; return ESP_OK;
}; }
esp_err_t upload_post_handlerAP(httpd_req_t *req) esp_err_t upload_post_handlerAP(httpd_req_t *req)
@@ -470,21 +501,28 @@ httpd_handle_t start_webserverAP(void)
return NULL; return NULL;
} }
void CheckStartAPMode() void CheckStartAPMode()
{ {
isConfigINI = FileExists(CONFIG_FILE); isConfigINI = FileExists(CONFIG_FILE);
isWlanINI = FileExists(WLAN_CONFIG_FILE); isWlanINI = FileExists(WLAN_CONFIG_FILE);
if (!isConfigINI or !isWlanINI) if (!isConfigINI)
ESP_LOGW(TAG, "config.ini not found!");
if (!isWlanINI)
ESP_LOGW(TAG, "wlan.ini not found!");
if (!isConfigINI || !isWlanINI)
{ {
ESP_LOGI(TAG, "Starting access point for remote configuration");
StatusLED(AP_OR_OTA, 2, true);
wifi_init_softAP(); wifi_init_softAP();
start_webserverAP(); start_webserverAP();
while(1) { // wait until reboot within task_do_Update_ZIP while(1) { // wait until reboot within task_do_Update_ZIP
vTaskDelay(1000 / portTICK_PERIOD_MS); vTaskDelay(1000 / portTICK_PERIOD_MS);
} }
} }
} }
#endif //#ifdef ENABLE_SOFTAP #endif //#ifdef ENABLE_SOFTAP

View File

@@ -133,6 +133,8 @@ CONFIG_GC032A_SUPPORT=n
CONFIG_GC0308_SUPPORT=n CONFIG_GC0308_SUPPORT=n
CONFIG_BF3005_SUPPORT=n CONFIG_BF3005_SUPPORT=n
CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4864
#only necessary for task analysis (include/defines -> TASK_ANALYSIS_ON) #only necessary for task analysis (include/defines -> TASK_ANALYSIS_ON)
#set in [env:esp32cam-dev-task-analysis] #set in [env:esp32cam-dev-task-analysis]
#CONFIG_FREERTOS_USE_TRACE_FACILITY=1 #CONFIG_FREERTOS_USE_TRACE_FACILITY=1

View File

@@ -1959,7 +1959,7 @@ function ReadParameterAll()
ReadParameter(param, "System", "TimeZone", true); ReadParameter(param, "System", "TimeZone", true);
ReadParameter(param, "System", "Hostname", true); ReadParameter(param, "System", "Hostname", true);
ReadParameter(param, "System", "TimeServer", true); ReadParameter(param, "System", "TimeServer", true);
ReadParameter(param, "System", "RSSIThreshold", true); ReadParameter(param, "System", "RSSIThreshold", true);
var sel = document.getElementById("Numbers_value1"); var sel = document.getElementById("Numbers_value1");

View File

@@ -283,7 +283,7 @@ function ParseConfig() {
aktline++; aktline++;
} }
// Make the downward compatiblity // Make the downward compatiblity with DataLogging
if (category["DataLogging"]["found"] == false) if (category["DataLogging"]["found"] == false)
{ {
category["DataLogging"]["found"] = true; category["DataLogging"]["found"] = true;
@@ -315,8 +315,16 @@ function ParseConfig() {
param["DataLogging"]["DataFilesRetention"]["value1"] = "3"; param["DataLogging"]["DataFilesRetention"]["value1"] = "3";
} }
// Downward compatiblity: Create RSSIThreshold if not available
if (param["System"]["RSSIThreshold"]["found"] == false)
{
param["System"]["RSSIThreshold"]["found"] = true;
param["System"]["RSSIThreshold"]["enabled"] = false;
param["System"]["RSSIThreshold"]["value1"] = "0";
}
} }
function ParamAddValue(param, _cat, _param, _anzParam = 1, _isNUMBER = false, _checkRegExList = null){ function ParamAddValue(param, _cat, _param, _anzParam = 1, _isNUMBER = false, _checkRegExList = null){
param[_cat][_param] = new Object(); param[_cat][_param] = new Object();
param[_cat][_param]["found"] = false; param[_cat][_param]["found"] = false;

View File

@@ -1,12 +1,38 @@
ssid = "SSID" ;++++++++++++++++++++++++++++++++++
password = "PASSWORD" ; AI on the edge - WLAN configuration
hostname = "watermeter" ;++++++++++++++++++++++++++++++++++
;hostname is optional ; ssid: Name of WLAN network (mandatory), e.g. "WLAN-SSID"
; password: Password of WLAN network (mandatory), e.g. "PASSWORD"
;if you want to use a fixed IP you need to specify the following 3 parameters (ip, gateway, netmask) with IP4-Addresses "123.456.789.012" ssid = ""
;ip = "IP4-ADDRESS" password = ""
;gateway = "IP4-ADDRESS"
;netmask = "255.255.255.0"
;in some cases you want to specify the DNS server as well (especially, if it is not identical to the gateway - this is optional for a fixed IP ;++++++++++++++++++++++++++++++++++
;dns = "IP4-ADDRESS" ; hostname: Name of device in network, e.g "watermeter"
; This parameter can be configured via WebUI configuration
; Default: "watermeter", if nothing is configured
;hostname = "watermeter"
;++++++++++++++++++++++++++++++++++
; Fixed IP: If you like to use fixed IP instead of DHCP (default), the following
; parameters needs to be configured: ip, gateway, netmask are mandatory, dns optional
;ip = "xxx.xxx.xxx.xxx"
;gateway = "xxx.xxx.xxx.xxx"
;netmask = "xxx.xxx.xxx.xxx"
; DNS server (optional, if no DNS is configured, gateway address will be used)
;dns = "xxx.xxx.xxx.xxx"
;++++++++++++++++++++++++++++++++++
; WIFI Roaming:
; Network assisted roaming protocol is activated by default
; AP / mesh system needs to support roaming protocol 802.11k/v
;
; Optional feature (usually not neccessary):
; RSSI Threshold for client requested roaming query (RSSI < RSSIThreshold)
; Note: This parameter can be configured via WebUI configuration
; Default: 0 = Disable client requested roaming query
RSSIThreshold = 0