diff --git a/code/components/config_handling/cfgDataStruct.h b/code/components/config_handling/cfgDataStruct.h
index 6b64ed293..ec9e38d8b 100644
--- a/code/components/config_handling/cfgDataStruct.h
+++ b/code/components/config_handling/cfgDataStruct.h
@@ -78,18 +78,18 @@ enum GpioSmartledType {
};
-enum NetworkConfig {
- NETWORK_CONFIG_DHCP = 0,
- NETWORK_CONFIG_STATIC = 1,
+enum NetworkWlanIpConfig {
+ NETWORK_WLAN_IP_CONFIG_DHCP = 0,
+ NETWORK_WLAN_IP_CONFIG_STATIC = 1,
};
-enum WlanOperationMode {
- WLAN_OPMODE_OFF = -1,
- WLAN_OPMODE_STATION_FULL = 0,
- WLAN_OPMODE_STATION_LIMITED = 1,
- WLAN_OPMODE_AP_FULL = 2,
- WLAN_OPMODE_AP_LIMITED = 3,
+enum NetworkOperationMode {
+ NETWORK_OPMODE_DISABLED = -1,
+ NETWORK_OPMODE_WLAN_CLIENT = 0,
+ NETWORK_OPMODE_WLAN_CLIENT_TIMED_OFF = 1,
+ NETWORK_OPMODE_WLAN_AP = 2,
+ NETWORK_OPMODE_WLAN_AP_TIMED_OFF = 3,
};
@@ -377,29 +377,38 @@ struct CfgData {
// Network
struct SectionNetwork {
+ int opmode = NETWORK_OPMODE_WLAN_CLIENT;
+ int timedOffDelay = 60; // Minutes
struct Wlan {
- int opmode = WLAN_OPMODE_STATION_FULL;
std::string ssid = "";
std::string password = "";
- std::string hostname = "watermeter";
- struct Ipv4 {
- int networkConfig = NETWORK_CONFIG_DHCP;
- std::string ipAddress = "";
- std::string subnetMask = "";
- std::string gatewayAddress = "";
- std::string dnsServer = "";
- } ipv4;
+ std::string hostname = "watermeter";
+ struct Ipv4 {
+ int networkConfig = NETWORK_WLAN_IP_CONFIG_DHCP;
+ std::string ipAddress = "";
+ std::string subnetMask = "";
+ std::string gatewayAddress = "";
+ std::string dnsServer = "";
+ } ipv4;
struct WlanRoaming {
bool enabled = false;
int rssiThreshold = -75;
} wlanRoaming;
} wlan;
+ struct WlanAp {
+ std::string ssid = "AI-on-the-Edge Device";
+ std::string password = "";
+ int channel = 11;
+ struct Ipv4 {
+ std::string ipAddress = "192.168.4.1";
+ } ipv4;
+ } wlanAp;
struct Time {
std::string timeZone = "CET-1CEST,M3.5.0,M10.5.0/3";
struct Ntp {
- bool timeSyncEnabled = true;
- std::string timeServer = ""; // IP-Address or DNS name, e.g. 192.168.x.x OR fritz.box
- bool processStartInterlock = true;
+ bool timeSyncEnabled = true;
+ std::string timeServer = ""; // IP-Address or DNS name, e.g. 192.168.x.x OR fritz.box
+ bool processStartInterlock = true;
} ntp;
} time;
} sectionNetwork;
diff --git a/code/components/config_handling/configClass.cpp b/code/components/config_handling/configClass.cpp
index 4c8f1ab8c..4ee884a2f 100644
--- a/code/components/config_handling/configClass.cpp
+++ b/code/components/config_handling/configClass.cpp
@@ -1284,10 +1284,13 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest)
// Network
- //@TODO FEATURE. WLAN operation modes not yet implemented
- /*objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlan"), "opmode");
+ objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "opmode");
if (cJSON_IsNumber(objEl))
- cfgDataTemp.sectionNetwork.wlan.enabled = objEl->valueint;*/
+ cfgDataTemp.sectionNetwork.opmode = std::clamp(objEl->valueint, -1, 3);
+
+ objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "timedoffdelay");
+ if (cJSON_IsNumber(objEl))
+ cfgDataTemp.sectionNetwork.timedOffDelay = std::max(objEl->valueint, 1);
bool ssidEmpty = false;
objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlan"), "ssid");
@@ -1339,11 +1342,11 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest)
cfgDataTemp.sectionNetwork.wlan.ipv4.gatewayAddress = objEl->valuestring;
// Static IP config selected, but IP config invalid --> Fallback to DHCP
- if (cfgDataTemp.sectionNetwork.wlan.ipv4.networkConfig == NETWORK_CONFIG_STATIC) {
+ if (cfgDataTemp.sectionNetwork.wlan.ipv4.networkConfig == NETWORK_WLAN_IP_CONFIG_STATIC) {
if (!isValidIpAddress(cfgDataTemp.sectionNetwork.wlan.ipv4.ipAddress.c_str()) ||
!isValidIpAddress(cfgDataTemp.sectionNetwork.wlan.ipv4.subnetMask.c_str()) ||
!isValidIpAddress(cfgDataTemp.sectionNetwork.wlan.ipv4.gatewayAddress.c_str())) {
- cfgDataTemp.sectionNetwork.wlan.ipv4.networkConfig = NETWORK_CONFIG_DHCP;
+ cfgDataTemp.sectionNetwork.wlan.ipv4.networkConfig = NETWORK_WLAN_IP_CONFIG_DHCP;
LogFile.writeToFile(ESP_LOG_WARN, TAG, "parseConfig: Static network config invalid. Use DHCP as fallback");
}
}
@@ -1360,6 +1363,22 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest)
if (cJSON_IsNumber(objEl))
cfgDataTemp.sectionNetwork.wlan.wlanRoaming.rssiThreshold = std::clamp(objEl->valueint, -100, 0);
+ objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlanap"), "ssid");
+ if (cJSON_IsString(objEl))
+ cfgDataTemp.sectionNetwork.wlanAp.ssid = objEl->valuestring;
+
+ objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlanap"), "password");
+ if (cJSON_IsString(objEl) && (strlen(objEl->valuestring) == 0 || strlen(objEl->valuestring) >= 8))
+ cfgDataTemp.sectionNetwork.wlanAp.password = objEl->valuestring;
+
+ objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlanap"), "channel");
+ if (cJSON_IsNumber(objEl))
+ cfgDataTemp.sectionNetwork.wlanAp.channel = std::clamp(objEl->valueint, 1, 14);
+
+ objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlanap"), "ipv4"), "ipaddress");
+ if (cJSON_IsString(objEl) && isValidIpAddress(objEl->valuestring))
+ cfgDataTemp.sectionNetwork.wlanAp.ipv4.ipAddress = objEl->valuestring;
+
objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "time"), "ntp"), "timesyncenabled");
if (cJSON_IsBool(objEl))
cfgDataTemp.sectionNetwork.time.ntp.timeSyncEnabled = objEl->valueint;
@@ -1949,13 +1968,15 @@ esp_err_t ConfigClass::serializeConfig(bool unityTest)
// Network
// ***************************
- cJSON *network, *networkIpv4, *networkWlan, *networkWlanRoaming, *networkTime, *networkTimeNtp;
+ cJSON *network, *networkWlan, *networkIpv4, *networkWlanRoaming, *networkWlanAp, *networkApIpv4, *networkTime, *networkTimeNtp;
if (!cJSON_AddItemToObject(cJsonObject, "network", network = cJSON_CreateObject()))
retVal = ESP_FAIL;
+ if (cJSON_AddNumberToObject(network, "opmode", cfgDataTemp.sectionNetwork.opmode) == NULL)
+ retVal = ESP_FAIL;
+ if (cJSON_AddNumberToObject(network, "timedoffdelay", cfgDataTemp.sectionNetwork.timedOffDelay) == NULL)
+ retVal = ESP_FAIL;
if (!cJSON_AddItemToObject(network, "wlan", networkWlan = cJSON_CreateObject()))
retVal = ESP_FAIL;
- /*if (cJSON_AddNumberToObject(networkWlan, "opmode", cfgDataTemp.sectionNetwork.wlan.opmode) == NULL) //@TODO FEATURE. Not yet implemented
- retVal = ESP_FAIL;*/
if (cJSON_AddStringToObject(networkWlan, "ssid", cfgDataTemp.sectionNetwork.wlan.ssid.c_str()) == NULL)
retVal = ESP_FAIL;
if (cJSON_AddStringToObject(networkWlan, "password", cfgDataTemp.sectionNetwork.wlan.password.empty() ? "" : "******") == NULL)
@@ -1980,6 +2001,18 @@ esp_err_t ConfigClass::serializeConfig(bool unityTest)
retVal = ESP_FAIL;
if (cJSON_AddNumberToObject(networkWlanRoaming, "rssithreshold", cfgDataTemp.sectionNetwork.wlan.wlanRoaming.rssiThreshold) == NULL)
retVal = ESP_FAIL;
+ if (!cJSON_AddItemToObject(network, "wlanap", networkWlanAp = cJSON_CreateObject()))
+ retVal = ESP_FAIL;
+ if (cJSON_AddStringToObject(networkWlanAp, "ssid", cfgDataTemp.sectionNetwork.wlanAp.ssid.c_str()) == NULL)
+ retVal = ESP_FAIL;
+ if (cJSON_AddStringToObject(networkWlanAp, "password", cfgDataTemp.sectionNetwork.wlanAp.password.c_str()) == NULL)
+ retVal = ESP_FAIL;
+ if (cJSON_AddNumberToObject(networkWlanAp, "channel", cfgDataTemp.sectionNetwork.wlanAp.channel) == NULL)
+ retVal = ESP_FAIL;
+ if (!cJSON_AddItemToObject(networkWlanAp, "ipv4", networkApIpv4 = cJSON_CreateObject()))
+ retVal = ESP_FAIL;
+ if (cJSON_AddStringToObject(networkApIpv4, "ipaddress", cfgDataTemp.sectionNetwork.wlanAp.ipv4.ipAddress.c_str()) == NULL)
+ retVal = ESP_FAIL;
if (!cJSON_AddItemToObject(network, "time", networkTime = cJSON_CreateObject()))
retVal = ESP_FAIL;
if (cJSON_AddStringToObject(networkTime, "timezone", cfgDataTemp.sectionNetwork.time.timeZone.c_str()) == NULL)
diff --git a/code/components/config_handling/configMigration.cpp b/code/components/config_handling/configMigration.cpp
index 1a94277ec..5c59e45ac 100644
--- a/code/components/config_handling/configMigration.cpp
+++ b/code/components/config_handling/configMigration.cpp
@@ -1217,7 +1217,7 @@ void migrateWlanIni()
!ConfigClass::getInstance()->cfgTmp()->sectionNetwork.wlan.ipv4.subnetMask.empty() &&
!ConfigClass::getInstance()->cfgTmp()->sectionNetwork.wlan.ipv4.gatewayAddress.empty())
{
- ConfigClass::getInstance()->cfgTmp()->sectionNetwork.wlan.ipv4.networkConfig = NETWORK_CONFIG_STATIC;
+ ConfigClass::getInstance()->cfgTmp()->sectionNetwork.wlan.ipv4.networkConfig = NETWORK_WLAN_IP_CONFIG_STATIC;
}
deleteFile(CONFIG_WIFI_FILE_BACKUP_LEGACY);
diff --git a/code/components/fileserver_ota/server_ota.cpp b/code/components/fileserver_ota/server_ota.cpp
index c6efe57b6..7842dddc2 100644
--- a/code/components/fileserver_ota/server_ota.cpp
+++ b/code/components/fileserver_ota/server_ota.cpp
@@ -618,7 +618,7 @@ void task_reboot(void *DeleteMainFlow)
/* Stop service tasks */
#ifdef ENABLE_MQTT
- MQTTdestroy_client(true);
+ deinitMqttClient(true);
#endif //ENABLE_MQTT
gpio_handler_destroy();
@@ -630,7 +630,7 @@ void task_reboot(void *DeleteMainFlow)
httpd_stop(server);
vTaskDelay(3000 / portTICK_PERIOD_MS);
- wifiDestroy();
+ deinitWifi();
vTaskDelay(1000 / portTICK_PERIOD_MS);
esp_restart(); // Reset type: CPU reset (Reset both CPUs)
diff --git a/code/components/gpio_ctrl/gpioControl.cpp b/code/components/gpio_ctrl/gpioControl.cpp
index 18e9597a6..c8c4cc73d 100644
--- a/code/components/gpio_ctrl/gpioControl.cpp
+++ b/code/components/gpio_ctrl/gpioControl.cpp
@@ -79,7 +79,8 @@ void GpioHandler::gpioInputStatePolling()
if (gpioMap != NULL) {
for(std::map::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it) {
if (it->second->getMode() == GPIO_PIN_MODE_INPUT || it->second->getMode() == GPIO_PIN_MODE_INPUT_PULLUP ||
- it->second->getMode() == GPIO_PIN_MODE_INPUT_PULLDOWN || it->second->getMode() == GPIO_PIN_MODE_TRIGGER_CYCLE_START)
+ it->second->getMode() == GPIO_PIN_MODE_INPUT_PULLDOWN || it->second->getMode() == GPIO_PIN_MODE_TRIGGER_CYCLE_START ||
+ it->second->getMode() == GPIO_PIN_MODE_RESUME_WLAN_CONNECTION)
{
it->second->updatePinState();
}
@@ -203,7 +204,8 @@ bool GpioHandler::init()
// Handler task is only needed to maintain input pin state (interrupt or polling)
if (it->second->getMode() == GPIO_PIN_MODE_INPUT || it->second->getMode() == GPIO_PIN_MODE_INPUT_PULLUP ||
- it->second->getMode() == GPIO_PIN_MODE_INPUT_PULLDOWN || it->second->getMode() == GPIO_PIN_MODE_TRIGGER_CYCLE_START)
+ it->second->getMode() == GPIO_PIN_MODE_INPUT_PULLDOWN || it->second->getMode() == GPIO_PIN_MODE_TRIGGER_CYCLE_START ||
+ it->second->getMode() == GPIO_PIN_MODE_RESUME_WLAN_CONNECTION)
{
initHandlerTask = true;
}
@@ -212,7 +214,7 @@ bool GpioHandler::init()
#ifdef ENABLE_MQTT
std::function f = std::bind(&GpioHandler::handleMQTTconnect, this);
- MQTTregisterConnectFunction("gpioHandler", f);
+ registerMqttConnectFunction("gpioHandler", f);
#endif //ENABLE_MQTT
// Handler task is only needed to maintain input pin state (interrupt or polling)
@@ -366,7 +368,7 @@ void GpioHandler::clearData()
void GpioHandler::deinit()
{
#ifdef ENABLE_MQTT
- MQTTunregisterConnectFunction("gpioHandler");
+ unregisterMqttConnectFunction("gpioHandler");
#endif //ENABLE_MQTT
clearData();
@@ -506,6 +508,8 @@ gpio_pin_mode_t GpioHandler::resolvePinMode(std::string input)
}
else if (input == "trigger-cycle-start")
return GPIO_PIN_MODE_TRIGGER_CYCLE_START;
+ else if (input == "resume-wlan-connection")
+ return GPIO_PIN_MODE_RESUME_WLAN_CONNECTION;
return GPIO_PIN_MODE_DISABLED;
}
@@ -534,6 +538,8 @@ std::string GpioHandler::getPinModeDecription(gpio_pin_mode_t _mode)
return FLASHLIGHT_DIGITAL;
case 9:
return "trigger-cycle-start";
+ case 10:
+ return "resume-wlan-connection";
default:
return "disabled";
}
diff --git a/code/components/gpio_ctrl/gpioPin.cpp b/code/components/gpio_ctrl/gpioPin.cpp
index 1d4f96bfe..37cd30411 100644
--- a/code/components/gpio_ctrl/gpioPin.cpp
+++ b/code/components/gpio_ctrl/gpioPin.cpp
@@ -8,6 +8,7 @@
#include "ClassLogFile.h"
#include "helper.h"
#include "MainFlowControl.h"
+#include "connect_wlan.h"
#ifdef ENABLE_MQTT
#include "interface_mqtt.h"
@@ -29,8 +30,10 @@ GpioPin::GpioPin(gpio_num_t _gpio, const char* _name, gpio_pin_mode_t _mode, gpi
gpioISR.gpio = gpio = _gpio;
name = _name;
mode = _mode;
- interruptType = mode == GPIO_PIN_MODE_TRIGGER_CYCLE_START ? GPIO_INTR_ANYEDGE : _interruptType;
- gpioISR.debounceTime = mode == GPIO_PIN_MODE_TRIGGER_CYCLE_START ? 1000 : _debounceTime;
+ interruptType = mode == GPIO_PIN_MODE_TRIGGER_CYCLE_START ||
+ mode == GPIO_PIN_MODE_RESUME_WLAN_CONNECTION ? GPIO_INTR_ANYEDGE : _interruptType;
+ gpioISR.debounceTime = mode == GPIO_PIN_MODE_TRIGGER_CYCLE_START ||
+ mode == GPIO_PIN_MODE_RESUME_WLAN_CONNECTION? 1000 : _debounceTime;
frequency = _frequency;
httpAccess = _httpAccess;
@@ -88,8 +91,8 @@ void GpioPin::init()
//set interrupt
io_conf.intr_type = mode == GPIO_PIN_MODE_INPUT || mode == GPIO_PIN_MODE_INPUT_PULLUP ||
- mode == GPIO_PIN_MODE_INPUT_PULLDOWN || mode == GPIO_PIN_MODE_TRIGGER_CYCLE_START ?
- interruptType : GPIO_INTR_DISABLE;
+ mode == GPIO_PIN_MODE_INPUT_PULLDOWN || mode == GPIO_PIN_MODE_TRIGGER_CYCLE_START ||
+ mode == GPIO_PIN_MODE_RESUME_WLAN_CONNECTION ? interruptType : GPIO_INTR_DISABLE;
//set input / output mode
io_conf.mode = mode == GPIO_PIN_MODE_OUTPUT || mode == GPIO_PIN_MODE_OUTPUT_PWM ||
@@ -101,11 +104,11 @@ void GpioPin::init()
//set pull-down mode
io_conf.pull_down_en = mode == GPIO_PIN_MODE_INPUT_PULLDOWN ?
- gpio_pulldown_t::GPIO_PULLDOWN_ENABLE : gpio_pulldown_t::GPIO_PULLDOWN_DISABLE;
+ gpio_pulldown_t::GPIO_PULLDOWN_ENABLE : gpio_pulldown_t::GPIO_PULLDOWN_DISABLE;
//set pull-up mode
- io_conf.pull_up_en = mode == GPIO_PIN_MODE_INPUT_PULLUP || mode == GPIO_PIN_MODE_TRIGGER_CYCLE_START ?
- gpio_pullup_t::GPIO_PULLUP_ENABLE : gpio_pullup_t::GPIO_PULLUP_DISABLE;
+ io_conf.pull_up_en = mode == GPIO_PIN_MODE_INPUT_PULLUP || mode == GPIO_PIN_MODE_TRIGGER_CYCLE_START ||
+ mode == GPIO_PIN_MODE_RESUME_WLAN_CONNECTION ? gpio_pullup_t::GPIO_PULLUP_ENABLE : gpio_pullup_t::GPIO_PULLUP_DISABLE;
//configure GPIO with the given settings
gpio_config(&io_conf);
@@ -123,7 +126,7 @@ void GpioPin::init()
// Subcribe to [mainTopic]/device/gpio/[GpioName]/ctrl
std::function func = std::bind(&GpioPin::mqttControlPinState, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3);
- MQTTregisterSubscribeFunction(mqttTopic + "/ctrl", func);
+ registerMqttSubscribeFunction(mqttTopic + "/ctrl", func);
}
#endif //ENABLE_MQTT
}
@@ -141,8 +144,15 @@ void GpioPin::updatePinState(int _state)
LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "updatePinState: GPIO" + std::to_string((int)gpio) +
", State: " + std::to_string(pinState));
- if (mode == GPIO_PIN_MODE_TRIGGER_CYCLE_START && pinState == 0) // Pullup enabled, trigger with falling edge / low level
- triggerFlowStartByGpio();
+ // Handle special modes
+ if (pinState == 0) { // Pullup enabled, trigger with falling edge / low level
+ if (mode == GPIO_PIN_MODE_TRIGGER_CYCLE_START) {
+ triggerFlowStartByGpio();
+ }
+ else if (mode == GPIO_PIN_MODE_RESUME_WLAN_CONNECTION) {
+ resumeWifiConnection("GPIO" + std::to_string((int)gpio));
+ }
+ }
#ifdef ENABLE_MQTT
mqttPublishPinState();
@@ -202,7 +212,7 @@ int GpioPin::getPinState()
#ifdef ENABLE_MQTT
bool GpioPin::mqttPublishPinState(int _pwmDuty)
{
- if (getMQTTisConnected() && mqttAccess) {
+ if (getMqttIsConnected() && mqttAccess) {
cJSON *cJSONObject = cJSON_CreateObject();
if (cJSONObject == NULL) {
LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to create JSON object");
@@ -224,7 +234,7 @@ bool GpioPin::mqttPublishPinState(int _pwmDuty)
cJSON_Delete(cJSONObject);
if (jsonChar != NULL) {
- retVal &= MQTTPublish(mqttTopic + "/state", std::string(jsonChar), 1);
+ retVal &= publishMqttData(mqttTopic + "/state", std::string(jsonChar), 1);
cJSON_free(jsonChar);
}
diff --git a/code/components/gpio_ctrl/gpioPin.h b/code/components/gpio_ctrl/gpioPin.h
index e6bfe8799..f49fd5028 100644
--- a/code/components/gpio_ctrl/gpioPin.h
+++ b/code/components/gpio_ctrl/gpioPin.h
@@ -20,7 +20,8 @@ typedef enum {
GPIO_PIN_MODE_FLASHLIGHT_SMARTLED = 7,
GPIO_PIN_MODE_FLASHLIGHT_DIGITAL = 8,
GPIO_PIN_MODE_TRIGGER_CYCLE_START = 9,
- GPIO_PIN_MODE_MAX = 10
+ GPIO_PIN_MODE_RESUME_WLAN_CONNECTION = 10,
+ GPIO_PIN_MODE_MAX = 11
} gpio_pin_mode_t;
diff --git a/code/components/mainprocess_ctrl/ClassFlowAlignment.cpp b/code/components/mainprocess_ctrl/ClassFlowAlignment.cpp
index 28ba2deba..9add139f1 100644
--- a/code/components/mainprocess_ctrl/ClassFlowAlignment.cpp
+++ b/code/components/mainprocess_ctrl/ClassFlowAlignment.cpp
@@ -122,7 +122,7 @@ bool ClassFlowAlignment::doFlow(std::string time)
if (imageTemp == NULL) {
imageTemp = new CImageBasis("imageTemp", ImageBasis, 1);
- if (imageTemp == NULL) {
+ if (imageTemp == NULL || imageTemp->rgb_image == NULL) {
LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to allocate imageTemp");
LogFile.writeHeapInfo("ClassFlowAlignment-doFlow");
return false;
diff --git a/code/components/mainprocess_ctrl/ClassFlowControl.cpp b/code/components/mainprocess_ctrl/ClassFlowControl.cpp
index 40f4da2a6..370551df7 100644
--- a/code/components/mainprocess_ctrl/ClassFlowControl.cpp
+++ b/code/components/mainprocess_ctrl/ClassFlowControl.cpp
@@ -315,7 +315,7 @@ bool ClassFlowControl::doFlowImageEvaluation(std::string time)
setActualProcessState(translateActualProcessState(FlowControlImage[i]->name()));
LogFile.writeToFile(ESP_LOG_INFO, TAG, "Process state: " + getActualProcessState());
#ifdef ENABLE_MQTT
- MQTTPublish(mqttServer_getMainTopic() + "/process/status/process_state", getActualProcessState(), 1, false);
+ publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", getActualProcessState(), 1, false);
#endif //ENABLE_MQTT
if (!FlowControlImage[i]->doFlow(time)) {
@@ -360,7 +360,7 @@ bool ClassFlowControl::doFlowPublishData(std::string time)
setActualProcessState(translateActualProcessState(FlowControlPublish[i]->name()));
LogFile.writeToFile(ESP_LOG_INFO, TAG, "Process state: " + getActualProcessState());
#ifdef ENABLE_MQTT
- MQTTPublish(mqttServer_getMainTopic() + "/process/status/process_state", getActualProcessState(), 1, false);
+ publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", getActualProcessState(), 1, false);
#endif //ENABLE_MQTT
if (!FlowControlPublish[i]->doFlow(time)) {
@@ -583,7 +583,7 @@ bool ClassFlowControl::initMqttService()
return true;
}
- return flowMQTT->initMqtt(cfgClassPtr->get()->sectionOperationMode.automaticProcessInterval);
+ return flowMQTT->initMqttService(cfgClassPtr->get()->sectionOperationMode.automaticProcessInterval);
}
#endif //ENABLE_MQTT
diff --git a/code/components/mainprocess_ctrl/ClassFlowMQTT.cpp b/code/components/mainprocess_ctrl/ClassFlowMQTT.cpp
index 2ff6d4d50..4ddcef3ad 100644
--- a/code/components/mainprocess_ctrl/ClassFlowMQTT.cpp
+++ b/code/components/mainprocess_ctrl/ClassFlowMQTT.cpp
@@ -73,7 +73,7 @@ bool ClassFlowMQTT::loadParameter()
}
-bool ClassFlowMQTT::initMqtt(float _processingInterval)
+bool ClassFlowMQTT::initMqttService(float _processingInterval)
{
std::stringstream stream;
@@ -89,8 +89,8 @@ bool ClassFlowMQTT::initMqtt(float _processingInterval)
"min -> MQTT keepAlive: " << ((float)keepAlive/60) << "min";
LogFile.writeToFile(ESP_LOG_DEBUG, TAG, stream.str());
- if (MQTT_Configure(cfgDataPtr, keepAlive)) {
- MQTT_Init();
+ if (configureMqttClient(cfgDataPtr, keepAlive)) {
+ startMqttClient();
return true;
}
@@ -103,7 +103,7 @@ bool ClassFlowMQTT::doFlow(std::string zwtime)
presetFlowStateHandler(false, zwtime);
bool retValCommon = true, retValStatus = true, retValData = true;
- if (!getMQTTisConnected()) {
+ if (!getMqttIsConnected()) {
LogFile.writeToFile(ESP_LOG_WARN, TAG, "Skip process state: Not connected to broker");
setFlowStateHandlerEvent(1); // Set warning event code, continue process flow
return false;
@@ -116,17 +116,17 @@ bool ClassFlowMQTT::doFlow(std::string zwtime)
// Publish process status
LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Publish process status");
- retValStatus &= MQTTPublish(cfgDataPtr->mainTopic + "/process/status/process_status",
+ retValStatus &= publishMqttData(cfgDataPtr->mainTopic + "/process/status/process_status",
getProcessStatus().c_str(), MQTT_QOS, false);
- retValStatus &= MQTTPublish(cfgDataPtr->mainTopic + "/process/status/process_interval",
+ retValStatus &= publishMqttData(cfgDataPtr->mainTopic + "/process/status/process_interval",
to_stringWithPrecision(flowctrl.getProcessInterval(), 1).c_str(), MQTT_QOS, false);
- retValStatus &= MQTTPublish(cfgDataPtr->mainTopic + "/process/status/process_time",
+ retValStatus &= publishMqttData(cfgDataPtr->mainTopic + "/process/status/process_time",
std::to_string(getFlowProcessingTime()).c_str(), MQTT_QOS, false);
- retValStatus &= MQTTPublish(cfgDataPtr->mainTopic + "/process/status/process_state",
+ retValStatus &= publishMqttData(cfgDataPtr->mainTopic + "/process/status/process_state",
flowctrl.getActualProcessState().c_str(), MQTT_QOS, false);
- retValStatus &= MQTTPublish(cfgDataPtr->mainTopic + "/process/status/process_error",
+ retValStatus &= publishMqttData(cfgDataPtr->mainTopic + "/process/status/process_error",
std::to_string(flowctrl.getFlowStateErrorOrDeviation()).c_str(), MQTT_QOS, false);
- retValStatus &= MQTTPublish(cfgDataPtr->mainTopic + "/process/status/cycle_counter",
+ retValStatus &= publishMqttData(cfgDataPtr->mainTopic + "/process/status/cycle_counter",
std::to_string(getFlowCycleCounter()).c_str(), MQTT_QOS, false);
if (!retValStatus)
@@ -135,7 +135,7 @@ bool ClassFlowMQTT::doFlow(std::string zwtime)
// Publish process data per sequence
LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Publish process data");
- retValData &= MQTTPublish(cfgDataPtr->mainTopic + "/process/data/number_sequences",
+ retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/number_sequences",
std::to_string(sequenceData.size()), MQTT_QOS, cfgDataPtr->retainProcessData);
for (const auto &sequence : sequenceData) {
@@ -175,36 +175,36 @@ bool ClassFlowMQTT::doFlow(std::string zwtime)
cJSON_Delete(cJSONObject);
if (jsonChar != NULL) {
- retValData &= MQTTPublish(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/json",
+ retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/json",
std::string(jsonChar), MQTT_QOS, cfgDataPtr->retainProcessData);
cJSON_free(jsonChar);
}
}
if (cfgDataPtr->processDataNotation == PROCESSDATA_TOPICS || cfgDataPtr->processDataNotation == PROCESSDATA_JSON_AND_TOPICS) {
- retValData &= MQTTPublish(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/sequence_name",
+ retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/sequence_name",
sequence->sequenceName.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData);
- retValData &= MQTTPublish(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/actual_value",
+ retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/actual_value",
sequence->sActualValue.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData);
- retValData &= MQTTPublish(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/fallback_value",
+ retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/fallback_value",
sequence->sFallbackValue.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData);
- retValData &= MQTTPublish(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/raw_value",
+ retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/raw_value",
sequence->sRawValue.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData);
- retValData &= MQTTPublish(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/value_status",
+ retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/value_status",
sequence->sValueStatus.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData);
- retValData &= MQTTPublish(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/rate_per_minute",
+ retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/rate_per_minute",
sequence->sRatePerMin.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData);
- retValData &= MQTTPublish(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/rate_per_interval",
+ retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/rate_per_interval",
sequence->sRatePerInterval.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData);
if (cfgDataPtr->homeAssistant.discoveryEnabled) { // Only used for Home Assistant integration
- retValData &= MQTTPublish(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/rate_per_time_unit",
+ retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/rate_per_time_unit",
(mqttServer_getTimeUnit() == "h") ? to_stringWithPrecision(sequence->ratePerMin * 60,
sequence->decimalPlaceCount).c_str() : sequence->sRatePerMin.c_str(),
MQTT_QOS, cfgDataPtr->retainProcessData);
}
- retValData &= MQTTPublish(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/timestamp_processed",
+ retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/timestamp_processed",
sequence->sTimeProcessed.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData);
- retValData &= MQTTPublish(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/timestamp_fallbackvalue",
+ retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/timestamp_fallbackvalue",
sequence->sTimeFallbackValue.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData);
}
}
@@ -232,7 +232,7 @@ void ClassFlowMQTT::doPostProcessEventHandling()
ClassFlowMQTT::~ClassFlowMQTT()
{
- MQTTdestroy_client(true);
+ deinitMqttClient(true);
}
#endif //ENABLE_MQTT
\ No newline at end of file
diff --git a/code/components/mainprocess_ctrl/ClassFlowMQTT.h b/code/components/mainprocess_ctrl/ClassFlowMQTT.h
index a5ea83dbf..d62446f8c 100644
--- a/code/components/mainprocess_ctrl/ClassFlowMQTT.h
+++ b/code/components/mainprocess_ctrl/ClassFlowMQTT.h
@@ -23,7 +23,7 @@ class ClassFlowMQTT : public ClassFlow
public:
ClassFlowMQTT();
virtual ~ClassFlowMQTT();
- bool initMqtt(float _processingInterval);
+ bool initMqttService(float _processingInterval);
bool loadParameter();
bool doFlow(std::string time);
diff --git a/code/components/mainprocess_ctrl/MainFlowControl.cpp b/code/components/mainprocess_ctrl/MainFlowControl.cpp
index 021ca3b0c..ba0e2a4be 100644
--- a/code/components/mainprocess_ctrl/MainFlowControl.cpp
+++ b/code/components/mainprocess_ctrl/MainFlowControl.cpp
@@ -890,7 +890,7 @@ void task_autodoFlow(void *pvParameter)
LogFile.writeToFile(ESP_LOG_INFO, TAG, "Process state: " + std::string(FLOW_SETUP_MODE));
flowctrl.setActualProcessState(std::string(FLOW_SETUP_MODE));
#ifdef ENABLE_MQTT
- MQTTPublish(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false);
+ publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false);
#endif //ENABLE_MQTT
while (true) { // Waiting for a REQUEST
@@ -940,8 +940,8 @@ void task_autodoFlow(void *pvParameter)
flowctrl.setActualProcessState(std::string(FLOW_INIT_FAILED));
flowctrl.setFlowStateError();
#ifdef ENABLE_MQTT
- if (getMQTTisConnected())
- MQTTPublish(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false);
+ if (getMqttIsConnected())
+ publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false);
#endif //ENABLE_MQTT
while (true) { // Waiting for a REQUEST
@@ -969,8 +969,8 @@ void task_autodoFlow(void *pvParameter)
LogFile.writeToFile(ESP_LOG_INFO, TAG, "Process start interlock: Waiting for time sync");
flowctrl.setActualProcessState(std::string(FLOW_INIT_WAITING_TIME_SYNC));
#ifdef ENABLE_MQTT
- if (getMQTTisConnected())
- MQTTPublish(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false);
+ if (getMqttIsConnected())
+ publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false);
#endif //ENABLE_MQTT
while (true) { // Waiting for time sync
@@ -1010,7 +1010,7 @@ void task_autodoFlow(void *pvParameter)
LogFile.writeToFile(ESP_LOG_INFO, TAG, "Process state: " + std::string(FLOW_IDLE_NO_AUTOSTART));
flowctrl.setActualProcessState(std::string(FLOW_IDLE_NO_AUTOSTART));
#ifdef ENABLE_MQTT
- MQTTPublish(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false);
+ publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false);
#endif //ENABLE_MQTT
while (true) { // Waiting for a REQUEST
@@ -1027,6 +1027,12 @@ void task_autodoFlow(void *pvParameter)
taskAutoFlowState = FLOW_TASK_STATE_IMG_PROCESSING; // Start manual triggered single cycle of "FLOW PROCESSING"
break;
}
+ else {
+ // WLAN suspention handling (if activated)
+ // Check whether WLAN set to suspended mode based on configured delay time
+ // ********************************************
+ suspendWifiConnection();
+ }
}
}
else {
@@ -1039,7 +1045,7 @@ void task_autodoFlow(void *pvParameter)
// ********************************************
else if (taskAutoFlowState == FLOW_TASK_STATE_IMG_PROCESSING) {
// Clear separation between runs
- LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "----------------------------------------------------------------");
+ LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "--------------------------------");
LogFile.writeToFile(ESP_LOG_INFO, TAG, "Cycle #" + std::to_string(++cycleCounter) + " started");
cycleStartTime = getUptime();
cylceStartActualTime = esp_timer_get_time();
@@ -1059,8 +1065,13 @@ void task_autodoFlow(void *pvParameter)
// ********************************************
else if (taskAutoFlowState == FLOW_TASK_STATE_PUBLISH_DATA) {
- if (!flowctrl.doFlowPublishData(getCurrentTimeString(DEFAULT_TIME_FORMAT))) {
- LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Publish data: Process error occured");
+ if (getWifiIsConnected()) { // Skip pusblishing services if WLAN connection is not connected or suspended
+ if (!flowctrl.doFlowPublishData(getCurrentTimeString(DEFAULT_TIME_FORMAT))) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Publish data: Process error occured");
+ }
+ }
+ else {
+ LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "No WLAN connection, skip publishing services");
}
taskAutoFlowState = FLOW_TASK_STATE_ADDITIONAL_TASKS; // Continue with TASKS after FLOW FINISHED
}
@@ -1076,7 +1087,7 @@ void task_autodoFlow(void *pvParameter)
LogFile.writeToFile(ESP_LOG_INFO, TAG, "Process state: " + std::string(FLOW_POST_EVENT_HANDLING));
flowctrl.setActualProcessState(std::string(FLOW_POST_EVENT_HANDLING));
#ifdef ENABLE_MQTT
- MQTTPublish(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false);
+ publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false);
#endif
flowctrl.postProcessEventHandler();
@@ -1085,7 +1096,7 @@ void task_autodoFlow(void *pvParameter)
else {
flowctrl.clearFlowStateEventInRowCounter();
#ifdef ENABLE_MQTT
- MQTTPublish(std::string(mqttServer_getMainTopic() + "/process/status/process_error"), "0", 1, false);
+ publishMqttData(std::string(mqttServer_getMainTopic() + "/process/status/process_error"), "0", 1, false);
#endif
}
@@ -1094,7 +1105,7 @@ void task_autodoFlow(void *pvParameter)
LogFile.writeToFile(ESP_LOG_INFO, TAG, "Process state: " + std::string(FLOW_ADDITIONAL_TASKS));
flowctrl.setActualProcessState(std::string(FLOW_ADDITIONAL_TASKS));
#ifdef ENABLE_MQTT
- MQTTPublish(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false);
+ publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false);
#endif //ENABLE_MQTT
// Cleanup outdated log and data files (retention policy)
@@ -1166,9 +1177,14 @@ void task_autodoFlow(void *pvParameter)
LogFile.writeToFile(ESP_LOG_INFO, TAG, "Process state: " + std::string(FLOW_IDLE_AUTOSTART));
flowctrl.setActualProcessState(std::string(FLOW_IDLE_AUTOSTART));
#ifdef ENABLE_MQTT
- MQTTPublish(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false);
+ publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false);
#endif //ENABLE_MQTT
+ // WLAN suspention handling (if activated)
+ // Check whether WLAN set to suspended mode based on configured delay time
+ // ********************************************
+ suspendWifiConnection();
+
int64_t processIntervalDeltaTime = (esp_timer_get_time() - cylceStartActualTime) / 1000;
if (automaticProcessInterval > processIntervalDeltaTime) {
vTaskDelay((automaticProcessInterval - processIntervalDeltaTime) / portTICK_PERIOD_MS);
diff --git a/code/components/mqtt_ctrl/interface_mqtt.cpp b/code/components/mqtt_ctrl/interface_mqtt.cpp
index bca19485a..4815be9ea 100644
--- a/code/components/mqtt_ctrl/interface_mqtt.cpp
+++ b/code/components/mqtt_ctrl/interface_mqtt.cpp
@@ -22,32 +22,41 @@
static const char *TAG = "MQTT_IF";
static const CfgData::SectionMqtt* cfgDataPtr;
-static int keepAlive;
+
static std::string LWTTopic;
static std::string TLSCACert;
static std::string TLSClientCert;
static std::string TLSClientKey;
-static strMqttState mqttState = {};
+static int keepAlive;
+
+static struct strMqttState {
+ bool mqttEnabled = false;
+ bool mqttInitialized = false;
+ bool mqttConnected = false;
-static std::map>* connectFunktionMap = NULL;
-static std::map>* subscribeFunktionMap = NULL;
+ int failedOnCycle = -1;
+ int mqttReconnectCnt = 0;
+} mqttState;
static esp_mqtt_client_handle_t mqttClient = NULL;
static const esp_mqtt_event_id_t mqttEventID = MQTT_EVENT_ANY;
+static std::map>* connectFunctionMap = NULL;
+static std::map>* subscribeFunctionMap = NULL;
-bool MQTTPublish(std::string _key, std::string _content, int _qos, bool _retainFlag)
+
+bool publishMqttData(std::string _key, std::string _content, int _qos, bool _retainFlag)
{
- if (!mqttState.mqttEnabled) { // MQTT sevice not started / configured (MQTT_Init not called before)
+ if (!mqttState.mqttEnabled) { // MQTT service disabled
return false;
}
- if (mqttState.failedOnCycle == getFlowCycleCounter()) { // we already failed in this cycle, do not retry until the next cycle
+ if (mqttState.failedOnCycle == getFlowCycleCounter()) { // Already a failed transmission in this cycle
return true; // Fail quietly
}
- MQTT_Init(); // Re-Init client if not initialized yet/anymore
+ startMqttClient(); // Restart client if not started yet/anymore
if (mqttState.mqttInitialized && mqttState.mqttConnected) {
#ifdef DEBUG_DETAIL_ON
@@ -100,17 +109,17 @@ static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
mqttState.mqttReconnectCnt = 0;
mqttState.mqttInitialized = true;
mqttState.mqttConnected = true;
- MQTTconnected();
+ isConnectedState();
break;
case MQTT_EVENT_DISCONNECTED:
mqttState.mqttConnected = false;
mqttState.mqttReconnectCnt++;
- LogFile.writeToFile(ESP_LOG_WARN, TAG, "Disconnected, retry to connect");
+ LogFile.writeToFile(ESP_LOG_WARN, TAG, "Disconnected. Retry to connect");
if (mqttState.mqttReconnectCnt >= 5) {
mqttState.mqttReconnectCnt = 0;
- LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Disconnected, multiple reconnect attempts failed. Retry");
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Multiple reconnect attempts failed. Retry to connect");
}
break;
@@ -133,10 +142,10 @@ static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
ESP_LOGI(TAG, "DATA=%.*s", event->data_len, event->data);
#endif
topic.assign(event->topic, event->topic_len);
- if (subscribeFunktionMap != NULL) {
- if (subscribeFunktionMap->find(topic) != subscribeFunktionMap->end()) {
+ if (subscribeFunctionMap != NULL) {
+ if (subscribeFunctionMap->find(topic) != subscribeFunctionMap->end()) {
//ESP_LOGD(TAG, "call subcribe function for topic %s", topic.c_str());
- (*subscribeFunktionMap)[topic](topic, event->data, event->data_len);
+ (*subscribeFunctionMap)[topic](topic, event->data, event->data_len);
}
else {
LogFile.writeToFile(ESP_LOG_WARN, TAG, "Skip request, topic not subscribed");
@@ -204,7 +213,7 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
}
-bool MQTT_Configure(const CfgData::SectionMqtt *_param, int keepAlive)
+bool configureMqttClient(const CfgData::SectionMqtt *_param, int keepAlive)
{
cfgDataPtr = _param;
keepAlive = keepAlive;
@@ -273,31 +282,29 @@ bool MQTT_Configure(const CfgData::SectionMqtt *_param, int keepAlive)
}
}
- mqttState.mqttConfigOK = true;
+ mqttState.mqttEnabled = true;
return true;
}
-int MQTT_Init()
+int startMqttClient(void)
{
if (mqttState.mqttInitialized) {
return 0;
}
- if (mqttState.mqttConfigOK) {
- mqttState.mqttEnabled = true;
- } else {
- LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Init called, but client is not yet configured.");
+ if (!mqttState.mqttEnabled) {
+ LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Init called, but service is not configured");
return 0;
}
- if (!getWIFIisConnected()) {
- LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Init called, but WIFI is not yet connected.");
+ if (!getWifiIsConnected()) {
+ LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Init called, but wlan is not yet connected");
return 0;
}
LogFile.writeToFile(ESP_LOG_INFO, TAG, "Init MQTT service");
- MQTTdestroy_client(false);
+ deinitMqttClient();
esp_mqtt_client_config_t mqtt_cfg = { };
@@ -372,39 +379,37 @@ int MQTT_Init()
}
-void MQTTdestroy_client(bool _disable = false)
+void deinitMqttClient(bool disable)
{
+ if (disable) {
+ mqttState.mqttEnabled = false;
+ }
+
+ mqttState.mqttInitialized = false;
+ mqttState.mqttConnected = false;
+
if (mqttClient) {
- if (mqttState.mqttConnected) {
- MQTTdestroySubscribeFunction();
- //esp_mqtt_client_disconnect(mqttClient);
- mqttState.mqttConnected = false;
- }
+ unregisterMqttSubscribeFunction();
esp_mqtt_client_stop(mqttClient);
esp_mqtt_client_destroy(mqttClient);
mqttClient = NULL;
- mqttState.mqttInitialized = false;
- mqttState.mqttEnabled = false;
}
-
- if (_disable) // Disable MQTT service, avoid restart with MQTTPublish
- mqttState.mqttConfigOK = false;
}
-bool getMQTTisEnabled()
+bool getMqttIsEnabled(void)
{
return mqttState.mqttEnabled;
}
-bool getMQTTisConnected()
+bool getMqttIsConnected(void)
{
return mqttState.mqttConnected;
}
-bool getMQTTisEncrypted()
+bool getMqttIsEncrypted(void)
{
if (cfgDataPtr != NULL && cfgDataPtr->authMode == AUTH_TLS)
return true;
@@ -464,14 +469,14 @@ bool mqtt_handler_set_fallbackvalue(std::string _topic, char* _data, int _data_l
}
-void MQTTconnected()
+void isConnectedState(void)
{
if (mqttState.mqttConnected) {
LogFile.writeToFile(ESP_LOG_INFO, TAG, "Connected to broker");
- MQTTPublish(cfgDataPtr->mainTopic + MQTT_STATUS_TOPIC, MQTT_STATUS_ONLINE, 1, false); // Send MQTT birth message "online"
+ publishMqttData(cfgDataPtr->mainTopic + MQTT_STATUS_TOPIC, MQTT_STATUS_ONLINE, 1, false); // Send MQTT birth message "online"
- if (connectFunktionMap != NULL) {
- for(std::map>::iterator it = connectFunktionMap->begin(); it != connectFunktionMap->end(); ++it) {
+ if (connectFunctionMap != NULL) {
+ for(std::map>::iterator it = connectFunctionMap->begin(); it != connectFunctionMap->end(); ++it) {
it->second();
//ESP_LOGD(TAG, "call connect function %s", it->first.c_str());
}
@@ -482,21 +487,21 @@ void MQTTconnected()
//*****************************************
// Subcribe to [mainTopic]/process/ctrl/flow_start
std::function subHandler1 = mqtt_handler_flow_start;
- MQTTregisterSubscribeFunction(cfgDataPtr->mainTopic + "/process/ctrl/cycle_start", subHandler1);
+ registerMqttSubscribeFunction(cfgDataPtr->mainTopic + "/process/ctrl/cycle_start", subHandler1);
// Subcribe to [mainTopic]/process/ctrl/set_fallbackvalue
std::function subHandler2 = mqtt_handler_set_fallbackvalue;
- MQTTregisterSubscribeFunction(cfgDataPtr->mainTopic + "/process/ctrl/set_fallbackvalue", subHandler2);
+ registerMqttSubscribeFunction(cfgDataPtr->mainTopic + "/process/ctrl/set_fallbackvalue", subHandler2);
// Subcribe to /homeassistant/status
if (cfgDataPtr->homeAssistant.discoveryEnabled) {
std::function subHandler3 = mqttServer_schedulePublishHADiscoveryFromMqtt;
- MQTTregisterSubscribeFunction(cfgDataPtr->homeAssistant.statusTopic, subHandler3);
+ registerMqttSubscribeFunction(cfgDataPtr->homeAssistant.statusTopic, subHandler3);
}
- if (subscribeFunktionMap != NULL) {
- for(std::map>::iterator it = subscribeFunktionMap->begin();
- it != subscribeFunktionMap->end(); ++it)
+ if (subscribeFunctionMap != NULL) {
+ for(std::map>::iterator it = subscribeFunctionMap->begin();
+ it != subscribeFunctionMap->end(); ++it)
{
int retVal = esp_mqtt_client_subscribe(mqttClient, it->first.c_str(), 0);
if (retVal >= 0)
@@ -509,19 +514,19 @@ void MQTTconnected()
}
-void MQTTregisterConnectFunction(std::string name, std::function func)
+void registerMqttConnectFunction(std::string name, std::function func)
{
//ESP_LOGD(TAG, "MQTTregisteronnectFunction %s\r\n", name.c_str());
- if (connectFunktionMap == NULL) {
- connectFunktionMap = new std::map>();
+ if (connectFunctionMap == NULL) {
+ connectFunctionMap = new std::map>();
}
- if ((*connectFunktionMap)[name] != NULL) {
+ if ((*connectFunctionMap)[name] != NULL) {
ESP_LOGD(TAG, "Connect function %s already registred", name.c_str());
return;
}
- (*connectFunktionMap)[name] = func;
+ (*connectFunctionMap)[name] = func;
if (mqttState.mqttConnected) {
func();
@@ -529,37 +534,37 @@ void MQTTregisterConnectFunction(std::string name, std::function func)
}
-void MQTTunregisterConnectFunction(std::string name)
+void unregisterMqttConnectFunction(std::string name)
{
ESP_LOGD(TAG, "unregisterConnnectFunction %s\r\n", name.c_str());
- if ((connectFunktionMap != NULL) && (connectFunktionMap->find(name) != connectFunktionMap->end())) {
- connectFunktionMap->erase(name);
+ if ((connectFunctionMap != NULL) && (connectFunctionMap->find(name) != connectFunctionMap->end())) {
+ connectFunctionMap->erase(name);
}
}
-void MQTTregisterSubscribeFunction(std::string topic, std::function func)
+void registerMqttSubscribeFunction(std::string topic, std::function func)
{
//ESP_LOGD(TAG, "registerSubscribeFunction %s", topic.c_str());
- if (subscribeFunktionMap == NULL) {
- subscribeFunktionMap = new std::map>();
+ if (subscribeFunctionMap == NULL) {
+ subscribeFunctionMap = new std::map>();
}
- if ((*subscribeFunktionMap)[topic] != NULL) {
+ if ((*subscribeFunctionMap)[topic] != NULL) {
ESP_LOGD(TAG, "Topic %s already registered for subscription", topic.c_str());
return;
}
- (*subscribeFunktionMap)[topic] = func;
+ (*subscribeFunctionMap)[topic] = func;
}
-void MQTTdestroySubscribeFunction()
+void unregisterMqttSubscribeFunction()
{
- if (subscribeFunktionMap != NULL) {
+ if (subscribeFunctionMap != NULL) {
if (mqttState.mqttConnected) {
- for(std::map>::iterator it = subscribeFunktionMap->begin();
- it != subscribeFunktionMap->end(); ++it)
+ for(std::map>::iterator it = subscribeFunctionMap->begin();
+ it != subscribeFunctionMap->end(); ++it)
{
int retVal = esp_mqtt_client_unsubscribe(mqttClient, it->first.c_str());
if (retVal >= 0)
@@ -569,9 +574,9 @@ void MQTTdestroySubscribeFunction()
}
}
- subscribeFunktionMap->clear();
- delete subscribeFunktionMap;
- subscribeFunktionMap = NULL;
+ subscribeFunctionMap->clear();
+ delete subscribeFunctionMap;
+ subscribeFunctionMap = NULL;
}
}
#endif //ENABLE_MQTT
diff --git a/code/components/mqtt_ctrl/interface_mqtt.h b/code/components/mqtt_ctrl/interface_mqtt.h
index eeff09aa5..43de2a602 100644
--- a/code/components/mqtt_ctrl/interface_mqtt.h
+++ b/code/components/mqtt_ctrl/interface_mqtt.h
@@ -11,32 +11,21 @@
#include "cfgDataStruct.h"
-struct strMqttState {
- bool mqttEnabled = false;
- bool mqttConfigOK = false;
- bool mqttInitialized = false;
- bool mqttConnected = false;
+bool publishMqttData(std::string _key, std::string _content, int qos, bool _retainFlag = false);
+bool configureMqttClient(const CfgData::SectionMqtt *cfgDataPtr, int keepAlive);
+int startMqttClient(void);
- int failedOnCycle = -1;
- int mqttReconnectCnt = 0;
-};
+bool getMqttIsEnabled(void);
+bool getMqttIsConnected(void);
+bool getMqttIsEncrypted(void);
+void registerMqttConnectFunction(std::string name, std::function func);
+void unregisterMqttConnectFunction(std::string name);
+void registerMqttSubscribeFunction(std::string topic, std::function func);
+void unregisterMqttSubscribeFunction();
+void isConnectedState(void);
-bool MQTTPublish(std::string _key, std::string _content, int qos, bool _retainFlag = false);
-bool MQTT_Configure(const CfgData::SectionMqtt *cfgDataPtr, int keepAlive);
-int MQTT_Init();
-
-bool getMQTTisEnabled();
-bool getMQTTisConnected();
-bool getMQTTisEncrypted();
-
-void MQTTregisterConnectFunction(std::string name, std::function func);
-void MQTTunregisterConnectFunction(std::string name);
-void MQTTregisterSubscribeFunction(std::string topic, std::function func);
-void MQTTdestroySubscribeFunction();
-void MQTTconnected();
-
-void MQTTdestroy_client(bool _disable);
+void deinitMqttClient(bool disable = false);
#endif //INTERFACE_MQTT_H
#endif //#ENABLE_MQTT
diff --git a/code/components/mqtt_ctrl/server_mqtt.cpp b/code/components/mqtt_ctrl/server_mqtt.cpp
index 9a0b74e72..7c134acf5 100644
--- a/code/components/mqtt_ctrl/server_mqtt.cpp
+++ b/code/components/mqtt_ctrl/server_mqtt.cpp
@@ -42,7 +42,7 @@ bool mqttServer_publishDeviceInfo(int _qos)
if (!publishDeviceInfoScheduled)
return true;
- if (!getMQTTisConnected()) {
+ if (!getMqttIsConnected()) {
LogFile.writeToFile(ESP_LOG_WARN, TAG, "Skip publish device info, not (yet) connected to broker");
return false;
}
@@ -102,7 +102,7 @@ bool mqttServer_publishDeviceInfo(int _qos)
cJSON_Delete(cJSONObject);
if (jsonChar != NULL) {
- retVal &= MQTTPublish(cfgDataPtr->mainTopic + deviceInfoTopic + "hardware", std::string(jsonChar), _qos, true);
+ retVal &= publishMqttData(cfgDataPtr->mainTopic + deviceInfoTopic + "hardware", std::string(jsonChar), _qos, true);
cJSON_free(jsonChar);
jsonChar = NULL;
}
@@ -116,7 +116,7 @@ bool mqttServer_publishDeviceInfo(int _qos)
}
if (cJSON_AddStringToObject(cJSONObject, "hostname", getHostname().c_str()) == NULL)
retVal = false;
- if (cJSON_AddStringToObject(cJSONObject, "ipv4_address", getIPAddress().c_str()) == NULL)
+ if (cJSON_AddStringToObject(cJSONObject, "ipv4_address", getIpAddress().c_str()) == NULL)
retVal = false;
if (cJSON_AddStringToObject(cJSONObject, "mac_address", getMac().c_str()) == NULL)
retVal = false;
@@ -125,7 +125,7 @@ bool mqttServer_publishDeviceInfo(int _qos)
cJSON_Delete(cJSONObject);
if (jsonChar != NULL) {
- retVal &= MQTTPublish(cfgDataPtr->mainTopic + deviceInfoTopic + "network", std::string(jsonChar), _qos, true);
+ retVal &= publishMqttData(cfgDataPtr->mainTopic + deviceInfoTopic + "network", std::string(jsonChar), _qos, true);
cJSON_free(jsonChar);
jsonChar = NULL;
}
@@ -136,7 +136,7 @@ bool mqttServer_publishDeviceInfo(int _qos)
if (firmwareVersion == "" || firmwareVersion == "N/A")
firmwareVersion = std::string(libfive_git_branch()) + " (" + std::string(libfive_git_revision()) + ")";
- retVal &= MQTTPublish(cfgDataPtr->mainTopic + deviceInfoTopic + "firmware_version", firmwareVersion, _qos, true);
+ retVal &= publishMqttData(cfgDataPtr->mainTopic + deviceInfoTopic + "firmware_version", firmwareVersion, _qos, true);
if (!retVal) {
LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to publish device info");
@@ -151,7 +151,7 @@ bool mqttServer_publishDeviceInfo(int _qos)
// Publish device status topics (common topics variable)
bool mqttServer_publishDeviceStatus(int _qos)
{
- if (!getMQTTisConnected()) {
+ if (!getMqttIsConnected()) {
LogFile.writeToFile(ESP_LOG_WARN, TAG, "Skip publish device status, not (yet) connected to broker");
return false;
}
@@ -161,10 +161,10 @@ bool mqttServer_publishDeviceStatus(int _qos)
const std::string deviceStatusTopic = "/device/status/";
bool retVal = true;
- retVal &= MQTTPublish(cfgDataPtr->mainTopic + MQTT_STATUS_TOPIC, MQTT_STATUS_ONLINE, _qos, false);
- retVal &= MQTTPublish(cfgDataPtr->mainTopic + deviceStatusTopic + "device_uptime", std::to_string(getUptime()), _qos, false);
- retVal &= MQTTPublish(cfgDataPtr->mainTopic + deviceStatusTopic + "wlan_rssi", std::to_string(getWifiRssi()), _qos, false);
- retVal &= MQTTPublish(cfgDataPtr->mainTopic + deviceStatusTopic + "chip_temp", to_stringWithPrecision(getSOCTemperature(), 0), _qos, false);
+ retVal &= publishMqttData(cfgDataPtr->mainTopic + MQTT_STATUS_TOPIC, MQTT_STATUS_ONLINE, _qos, false);
+ retVal &= publishMqttData(cfgDataPtr->mainTopic + deviceStatusTopic + "device_uptime", std::to_string(getUptime()), _qos, false);
+ retVal &= publishMqttData(cfgDataPtr->mainTopic + deviceStatusTopic + "wlan_rssi", std::to_string(getWifiRssi()), _qos, false);
+ retVal &= publishMqttData(cfgDataPtr->mainTopic + deviceStatusTopic + "chip_temp", to_stringWithPrecision(getSOCTemperature(), 0), _qos, false);
cJSON *cJSONObject = cJSON_CreateObject();
if (cJSONObject == NULL) {
@@ -190,12 +190,12 @@ bool mqttServer_publishDeviceStatus(int _qos)
cJSON_Delete(cJSONObject);
if (jsonChar != NULL) {
- retVal &= MQTTPublish(cfgDataPtr->mainTopic + deviceStatusTopic + "heap", std::string(jsonChar), _qos, false);
+ retVal &= publishMqttData(cfgDataPtr->mainTopic + deviceStatusTopic + "heap", std::string(jsonChar), _qos, false);
cJSON_free(jsonChar);
}
- retVal &= MQTTPublish(cfgDataPtr->mainTopic + deviceStatusTopic + "sd_partition_free", std::to_string(getSDCardFreePartitionSpace()), _qos, false);
- retVal &= MQTTPublish(cfgDataPtr->mainTopic + deviceStatusTopic + "ntp_syncstatus", getNTPSyncStatus().c_str(), _qos, false);
+ retVal &= publishMqttData(cfgDataPtr->mainTopic + deviceStatusTopic + "sd_partition_free", std::to_string(getSDCardFreePartitionSpace()), _qos, false);
+ retVal &= publishMqttData(cfgDataPtr->mainTopic + deviceStatusTopic + "ntp_syncstatus", getNTPSyncStatus().c_str(), _qos, false);
if (!retVal) {
LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to publish device status");
@@ -317,7 +317,7 @@ bool mqttServer_publishHADiscovery(int _qos)
if (!cfgDataPtr->homeAssistant.discoveryEnabled || !publishHADiscoveryScheduled) // Continue if enabled and scheduled
return true;
- if (!getMQTTisConnected()) {
+ if (!getMqttIsConnected()) {
LogFile.writeToFile(ESP_LOG_WARN, TAG, "Skip publish HA discovery, not (yet) connected to broker");
return false;
}
@@ -701,7 +701,7 @@ static bool publishHADiscoveryTopic(const strHADiscoveryData *_data, const int _
"\"mdl\":\"AI-on-the-Edge device [" + getBoardType() + "]\"," +
"\"mf\":\"AI-on-the-Edge\"," +
"\"sw\":\"" + firmwareVersion + " [SLFork]\"," +
- "\"cu\":\"http://" + getIPAddress() + "\"}";
+ "\"cu\":\"http://" + getIpAddress() + "\"}";
}
else { // Publish device reference only to group data together
payload += std::string(", \"dev\": {") +
@@ -710,7 +710,7 @@ static bool publishHADiscoveryTopic(const strHADiscoveryData *_data, const int _
payload += "}";
- if (MQTTPublish(configurationTopic, payload, _qos, cfgDataPtr->homeAssistant.retainDiscovery)) {
+ if (publishMqttData(configurationTopic, payload, _qos, cfgDataPtr->homeAssistant.retainDiscovery)) {
publishHADiscoveryTopicDeviceInfo = false;
return true;
}
diff --git a/code/components/openmetrics_ctrl/openmetrics.cpp b/code/components/openmetrics_ctrl/openmetrics.cpp
index 0af13e550..e04cd4537 100644
--- a/code/components/openmetrics_ctrl/openmetrics.cpp
+++ b/code/components/openmetrics_ctrl/openmetrics.cpp
@@ -45,7 +45,7 @@ std::string createNetworkInfoMetric(const std::string &metricNamePrefix)
return "# TYPE " + metricNamePrefix + "network_info gauge\n" +
"# HELP " + metricNamePrefix + "network_info Network info\n" +
metricNamePrefix + "network_info{hostname=\"" + getHostname() +
- "\",ipv4_address=\"" + getIPAddress() +
+ "\",ipv4_address=\"" + getIpAddress() +
"\",mac_address=\"" + getMac() + "\"} 1\n";
}
diff --git a/code/components/time_sntp/time_sntp.cpp b/code/components/time_sntp/time_sntp.cpp
index 11c641696..0fa62ecdc 100644
--- a/code/components/time_sntp/time_sntp.cpp
+++ b/code/components/time_sntp/time_sntp.cpp
@@ -122,9 +122,9 @@ void setTimeZone(std::string _tzstring)
void timeSyncNotificationCallback(struct timeval *tv)
{
if (timeWasNotSetAtBoot_PrintStartBlock) {
- LogFile.writeToFile(ESP_LOG_INFO, TAG, "=================================================");
- LogFile.writeToFile(ESP_LOG_INFO, TAG, "==================== Start ======================");
- LogFile.writeToFile(ESP_LOG_INFO, TAG, "== Logs before time sync -> log_1970-01-01.txt ==");
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "===================================");
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "============== Start ==============");
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "= Before sync: log_1970-01-01.txt =");
timeWasNotSetAtBoot_PrintStartBlock = false;
}
LogFile.writeToFile(ESP_LOG_INFO, TAG, "Time is synced with NTP server " +
@@ -168,7 +168,6 @@ bool initTime()
else {
LogFile.writeToFile(ESP_LOG_INFO, TAG, "NTP service disabled");
timeSyncEnabled = false;
- timeServer = "";
isTimeSynchonized = false;
}
diff --git a/code/components/webserver_softap/softAP.cpp b/code/components/webserver_softap/softAP.cpp
index 2b0fcabac..0a946ef29 100644
--- a/code/components/webserver_softap/softAP.cpp
+++ b/code/components/webserver_softap/softAP.cpp
@@ -1,7 +1,6 @@
#include "softAP.h"
#include "../../include/defines.h"
-#ifdef ENABLE_SOFTAP
#include
#include
#include
@@ -10,6 +9,7 @@
#include
#include
+#include "connect_wlan.h"
#include "configClass.h"
#include "server_help.h"
#include "helper.h"
@@ -23,60 +23,6 @@ static bool credentialsSet = false;
static bool SDCardContentExisting = false;
-static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
-{
- if (event_id == WIFI_EVENT_AP_STACONNECTED) {
- wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
- ESP_LOGI(TAG, "station " MACSTR " join, AID=%d", MAC2STR(event->mac), event->aid);
- }
- else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
- wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
- ESP_LOGI(TAG, "station " MACSTR " leave, AID=%d", MAC2STR(event->mac), event->aid);
- }
-}
-
-
-void wifiInitAP(void)
-{
- ESP_ERROR_CHECK(esp_event_loop_create_default());
- esp_netif_create_default_wifi_ap();
-
- wifi_init_config_t wifiInitCfg = WIFI_INIT_CONFIG_DEFAULT();
- ESP_ERROR_CHECK(esp_wifi_init(&wifiInitCfg));
-
- ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
-
- wifi_config_t wifiConfig = { };
- strcpy((char*)wifiConfig.ap.ssid, (const char*) AP_ESP_WIFI_SSID);
- strcpy((char*)wifiConfig.ap.password, (const char*) AP_ESP_WIFI_PASS);
- wifiConfig.ap.channel = AP_ESP_WIFI_CHANNEL;
- wifiConfig.ap.max_connection = AP_MAX_STA_CONN;
- wifiConfig.ap.authmode = WIFI_AUTH_WPA_WPA2_PSK;
-
- if (strlen(AP_ESP_WIFI_PASS) == 0) {
- wifiConfig.ap.authmode = WIFI_AUTH_OPEN;
- }
-
- ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
- ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifiConfig));
- ESP_ERROR_CHECK(esp_wifi_start());
-
- ESP_LOGI(TAG, "started with SSID \"%s\", password: \"%s\", channel: %d. Connect to AP and open http://192.168.4.1",
- AP_ESP_WIFI_SSID, AP_ESP_WIFI_PASS, AP_ESP_WIFI_CHANNEL);
-}
-
-
-void wifiDeinitAP(void)
-{
- esp_wifi_disconnect();
- esp_wifi_stop();
- esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler);
- esp_wifi_deinit();
- setStatusLedOff();
- credentialsSet = true;
-}
-
-
esp_err_t main_handler_AP(httpd_req_t *req)
{
std::string message = "AI on the Edge Device | Device Provisioning ";
@@ -270,7 +216,7 @@ httpd_handle_t start_webserverAP(void)
httpd_register_uri_handler(server, &config_handleAP);
httpd_uri_t file_uploadAP = {
- .uri = "/upload/*", // Match all URIs of type /upload/path/to/file
+ .uri = "/upload/*",
.method = HTTP_POST,
.handler = upload_handler_AP,
.user_ctx = NULL
@@ -289,16 +235,16 @@ httpd_handle_t start_webserverAP(void)
}
-void checkStartAPMode()
+void startAPForDeviceProvisioning()
{
SDCardContentExisting = fileExists("/sdcard/html/index.html");
if (!SDCardContentExisting)
- ESP_LOGW(TAG, "SD content not found (html/index.html)");
+ ESP_LOGW(TAG, "HTML content not found on SD card (html/index.html)");
if (ConfigClass::getInstance()->get()->sectionNetwork.wlan.ssid.empty() || !SDCardContentExisting) {
- ESP_LOGI(TAG, "Starting access point");
+ ESP_LOGI(TAG, "Starting access point for device provisioning");
setStatusLed(AP_OR_OTA, 2, true);
- wifiInitAP();
+ initWifiAp(true);
start_webserverAP();
while(1) { // wait until reboot
@@ -307,4 +253,14 @@ void checkStartAPMode()
}
}
-#endif //#ifdef ENABLE_SOFTAP
+
+/** This function is only used to switch the Improv provisioning service where
+* step 1, WLAN configuration, is provisioned via serial / USB console,
+* continued with step 2 and step 3 defined in softAP.cpp -> function 'main_handler_AP'
+*/
+void stopAPForDeviceProvisioning(void)
+{
+ setStatusLedOff();
+ deinitWifi();
+ credentialsSet = true; // Skip step 1
+}
diff --git a/code/components/webserver_softap/softAP.h b/code/components/webserver_softap/softAP.h
index f8bc64c1b..ec0d78287 100644
--- a/code/components/webserver_softap/softAP.h
+++ b/code/components/webserver_softap/softAP.h
@@ -1,13 +1,11 @@
#include "../../include/defines.h"
-#ifdef ENABLE_SOFTAP
#ifndef SOFTAP_H
#define SOFTAP_H
#include
-void checkStartAPMode(void);
-void wifiDeinitAP(void);
+void startAPForDeviceProvisioning(void);
+void stopAPForDeviceProvisioning(void);
-#endif //SOFTAP_H
-#endif //#ifdef ENABLE_SOFTAP
\ No newline at end of file
+#endif //SOFTAP_H
\ No newline at end of file
diff --git a/code/components/webserver_softap/webserver.cpp b/code/components/webserver_softap/webserver.cpp
index 9a1c84b64..fc2cfb06a 100644
--- a/code/components/webserver_softap/webserver.cpp
+++ b/code/components/webserver_softap/webserver.cpp
@@ -72,7 +72,7 @@ esp_err_t handler_get_info(httpd_req_t *req)
retVal = ESP_FAIL;
#ifdef ENABLE_MQTT
- if (cJSON_AddStringToObject(cJSONObject, "mqtt_status", getMQTTisEnabled() ? (getMQTTisConnected() ? (getMQTTisEncrypted() ?
+ if (cJSON_AddStringToObject(cJSONObject, "mqtt_status", getMqttIsEnabled() ? (getMqttIsConnected() ? (getMqttIsEncrypted() ?
"Connected (Encrypted)" : "Connected") : "Disconnected") : "Disabled") == NULL)
retVal = ESP_FAIL;
#else
@@ -112,23 +112,27 @@ esp_err_t handler_get_info(httpd_req_t *req)
retVal = ESP_FAIL;
if (cJSON_AddNumberToObject(cJSONObject, "device_uptime", getUptime()) == NULL)
retVal = ESP_FAIL;
- if (cJSON_AddStringToObject(cJSONObject, "wlan_status", getWIFIisConnected() ? "Connected" : "Disconnected") == NULL)
+ if (cJSON_AddStringToObject(cJSONObject, "network_opmode", getNetworkOpmode().c_str()) == NULL)
retVal = ESP_FAIL;
- if (cJSON_AddStringToObject(cJSONObject, "wlan_ssid", getSSID().c_str()) == NULL)
+ if (cJSON_AddStringToObject(cJSONObject, "connection_status", getWifiIsConnected() ? "Connected" : "Disconnected") == NULL)
+ retVal = ESP_FAIL;
+ if (cJSON_AddStringToObject(cJSONObject, "wlan_ssid", getWifiSsid().c_str()) == NULL)
retVal = ESP_FAIL;
if (cJSON_AddNumberToObject(cJSONObject, "wlan_rssi", getWifiRssi()) == NULL)
retVal = ESP_FAIL;
+ if (cJSON_AddNumberToObject(cJSONObject, "wlan_channel", getWifiChannel()) == NULL)
+ retVal = ESP_FAIL;
if (cJSON_AddStringToObject(cJSONObject, "mac_address", getMac().c_str()) == NULL)
retVal = ESP_FAIL;
- if (cJSON_AddStringToObject(cJSONObject, "network_config", getDHCPUsage() ? "DHCP" : "Static") == NULL)
+ if (cJSON_AddStringToObject(cJSONObject, "network_config", getDhcpStatus() ? "DHCP" : "Static") == NULL)
retVal = ESP_FAIL;
- if (cJSON_AddStringToObject(cJSONObject, "ipv4_address", getIPAddress().c_str()) == NULL)
+ if (cJSON_AddStringToObject(cJSONObject, "ipv4_address", getIpAddress().c_str()) == NULL)
retVal = ESP_FAIL;
if (cJSON_AddStringToObject(cJSONObject, "netmask_address", getNetmaskAddress().c_str()) == NULL)
retVal = ESP_FAIL;
if (cJSON_AddStringToObject(cJSONObject, "gateway_address", getGatewayAddress().c_str()) == NULL)
retVal = ESP_FAIL;
- if (cJSON_AddStringToObject(cJSONObject, "dns_address", getDNSAddress().c_str()) == NULL)
+ if (cJSON_AddStringToObject(cJSONObject, "dns_address", getDnsAddress().c_str()) == NULL)
retVal = ESP_FAIL;
if (cJSON_AddStringToObject(cJSONObject, "hostname", getHostname().c_str()) == NULL)
retVal = ESP_FAIL;
@@ -244,7 +248,7 @@ esp_err_t handler_get_info(httpd_req_t *req)
#ifdef ENABLE_MQTT
else if (type.compare("mqtt_status") == 0) {
- httpd_resp_sendstr(req, getMQTTisEnabled() ? (getMQTTisConnected() ? (getMQTTisEncrypted() ?
+ httpd_resp_sendstr(req, getMqttIsEnabled() ? (getMqttIsConnected() ? (getMqttIsEncrypted() ?
"Connected (Encrypted)" : "Connected") : "Disconnected") : "Disabled");
return ESP_OK;
}
@@ -289,28 +293,36 @@ esp_err_t handler_get_info(httpd_req_t *req)
httpd_resp_sendstr(req, std::to_string(getUptime()).c_str());
return ESP_OK;
}
- else if (type.compare("wlan_status") == 0) {
- httpd_resp_sendstr(req, getWIFIisConnected() ? "Connected" : "Disconnected");
+ else if (type.compare("network_opmode") == 0) {
+ httpd_resp_sendstr(req, getNetworkOpmode().c_str());
+ return ESP_OK;
+ }
+ else if (type.compare("connection_status") == 0) {
+ httpd_resp_sendstr(req, getWifiIsConnected() ? "Connected" : "Disconnected");
return ESP_OK;
}
else if (type.compare("wlan_ssid") == 0) {
- httpd_resp_sendstr(req, getSSID().c_str());
+ httpd_resp_sendstr(req, getWifiSsid().c_str());
return ESP_OK;
}
else if (type.compare("wlan_rssi") == 0) {
httpd_resp_sendstr(req, std::to_string(getWifiRssi()).c_str());
return ESP_OK;
}
+ else if (type.compare("wlan_channel") == 0) {
+ httpd_resp_sendstr(req, std::to_string(getWifiChannel()).c_str());
+ return ESP_OK;
+ }
else if (type.compare("mac_address") == 0) {
httpd_resp_sendstr(req, getMac().c_str());
return ESP_OK;
}
else if (type.compare("network_config") == 0) {
- httpd_resp_sendstr(req, getDHCPUsage() ? "DHCP" : "Static");
+ httpd_resp_sendstr(req, getDhcpStatus() ? "DHCP" : "Static");
return ESP_OK;
}
else if (type.compare("ipv4_address") == 0) {
- httpd_resp_sendstr(req, getIPAddress().c_str());
+ httpd_resp_sendstr(req, getIpAddress().c_str());
return ESP_OK;
}
else if (type.compare("netmask_address") == 0) {
@@ -322,7 +334,7 @@ esp_err_t handler_get_info(httpd_req_t *req)
return ESP_OK;
}
else if (type.compare("dns_address") == 0) {
- httpd_resp_sendstr(req, getDNSAddress().c_str());
+ httpd_resp_sendstr(req, getDnsAddress().c_str());
return ESP_OK;
}
else if (type.compare("hostname") == 0) {
diff --git a/code/components/wlan_ctrl/connect_wlan.cpp b/code/components/wlan_ctrl/connect_wlan.cpp
index f66eda365..567414a44 100644
--- a/code/components/wlan_ctrl/connect_wlan.cpp
+++ b/code/components/wlan_ctrl/connect_wlan.cpp
@@ -11,6 +11,7 @@
#include
#include
#include
+#include
#ifdef ENABLE_MQTT
#include "interface_mqtt.h"
@@ -23,16 +24,26 @@
#include "statusled.h"
-static const char *TAG = "WIFI";
+static const char *TAG = "WLAN";
-static bool APWithBetterRSSI = false;
-static bool WIFIConnected = false;
-static int WIFIReconnectCnt = 0;
-esp_netif_t *wifiStation;
-static const CfgData::SectionNetwork* cfgDataPtr;
+static const CfgData::SectionNetwork* cfgDataPtr = NULL;
-struct IpCfg {
+static struct strWifiState {
+ bool initialized = false;
+ bool connected = false;
+ bool connectionSucessful = false;
+ bool connectionSupended = false;
+ int64_t connectionSuspendBaseTime = 0LL;
+
+ int reconnectCnt = 0;
+ bool fallbackApActive = false;
+
+ bool accessPointWithBetterRSSI = false;
+} wifiState;
+
+
+static struct IpCfg {
std::string ipAddress = "";
std::string subnetMask = "";
std::string gatewayAddress = "";
@@ -40,11 +51,595 @@ struct IpCfg {
} ipCfg;
-std::string BssidToString(const char* c) {
- char cBssid[25];
- sprintf(cBssid, "%02x:%02x:%02x:%02x:%02x:%02x", c[0], c[1], c[2], c[3], c[4], c[5]);
- return std::string(cBssid);
+std::string bssidToString(const char* c) {
+ char cBssid[6 * 2 + 5 + 1]; // AA:BB:CC:DD:EE:FF
+ sprintf(cBssid, "%02x:%02x:%02x:%02x:%02x:%02x", c[0], c[1], c[2], c[3], c[4], c[5]);
+ return std::string(cBssid);
+}
+
+
+std::string macToString(uint8_t mac[6]) {
+ char macFormated[6 * 2 + 5 + 1]; // AA:BB:CC:DD:EE:FF
+ sprintf(macFormated, MACSTR, MAC2STR(mac));
+ return std::string(macFormated);
+}
+
+
+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) {
+ wifiState.connected = false;
+ esp_wifi_connect();
+ }
+ else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
+ wifi_event_sta_disconnected_t *disconn = (wifi_event_sta_disconnected_t *)event_data;
+ if (disconn->reason == WIFI_REASON_ROAMING) {
+ LogFile.writeToFile(ESP_LOG_WARN, TAG, "Disconnected (" + std::to_string(disconn->reason) + ", Roaming 802.11kv)");
+ // --> no reconnect neccessary, it should automatically reconnect to new AP
+ }
+ else {
+ wifiState.connected = false;
+ if (disconn->reason == WIFI_REASON_NO_AP_FOUND ||
+ disconn->reason == WIFI_REASON_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD ||
+ disconn->reason == WIFI_REASON_NO_AP_FOUND_IN_RSSI_THRESHOLD) {
+ LogFile.writeToFile(ESP_LOG_WARN, TAG, "Disconnected (" + std::to_string(disconn->reason) + ", No AP found)");
+ setStatusLed(WLAN_CONN, 1, false);
+ }
+ 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 ||
+ disconn->reason == WIFI_REASON_NO_AP_FOUND_W_COMPATIBLE_SECURITY) {
+ LogFile.writeToFile(ESP_LOG_WARN, TAG, "Disconnected (" + std::to_string(disconn->reason) + ", Auth fail)");
+ setStatusLed(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)");
+ setStatusLed(WLAN_CONN, 3, false);
+ }
+ else {
+ LogFile.writeToFile(ESP_LOG_WARN, TAG, "Disconnected (" + std::to_string(disconn->reason) + ")");
+ setStatusLed(WLAN_CONN, 4, false);
+ }
+
+ wifiState.reconnectCnt++;
+ esp_wifi_connect(); // Try to connect again
+ }
+
+ if (wifiState.connectionSucessful) { // Connection was never established (e.g. wrong password), switch to AP
+ if (wifiState.reconnectCnt >= WLAN_CONNECTION_RETRIES_ERROR_MSG) {
+ wifiState.reconnectCnt = 0;
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Multiple reconnect attempts failed. Retry to connect");
+ }
+ }
+ else {
+ if (wifiState.reconnectCnt >= WLAN_CONNECTION_RETRIES_INITIAL_CONNECT) {
+ wifiState.reconnectCnt = 0;
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to establish connection. Start access point (fallback)");
+ wifiState.fallbackApActive = true;
+ deinitWifi();
+ if (initWifiAp(wifiState.fallbackApActive) != ESP_OK) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Init WLAN access point failed");
+ }
+ else {
+ setStatusLedOff();
+ setStatusLed(AP_OR_OTA, 3, true);
+ }
+ }
+ }
+ }
+ else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED) {
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "Connected to: " + cfgDataPtr->wlan.ssid + ", RSSI: " +
+ std::to_string(getWifiRssi()));
+
+#ifdef WLAN_USE_MESH_ROAMING
+ printRoamingFeatureSupport();
+
+ #ifdef WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES
+ // wifiRoamingQuery(); // Avoid client triggered query during processing flow (reduce risk of heap shortage).
+ // Request will be triggered at the end of every cycle anyway
+ #endif //WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES
+#endif //WLAN_USE_MESH_ROAMING
+
+ wifiState.connectionSuspendBaseTime = esp_timer_get_time();
+ }
+ else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
+ wifiState.connectionSucessful = true;
+ wifiState.connected = true;
+ wifiState.reconnectCnt = 0;
+
+ if (cfgDataPtr->wlan.ipv4.networkConfig == NETWORK_WLAN_IP_CONFIG_DHCP) {
+ char buf[20];
+ ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
+
+ ipCfg.ipAddress = std::string(esp_ip4addr_ntoa(&event->ip_info.ip, buf, sizeof(buf)));
+ ipCfg.subnetMask = std::string(esp_ip4addr_ntoa(&event->ip_info.netmask, buf, sizeof(buf)));
+ ipCfg.gatewayAddress = std::string(esp_ip4addr_ntoa(&event->ip_info.gw, buf, sizeof(buf)));
+
+ esp_netif_dns_info_t dnsInfo;
+ esp_netif_get_dns_info(event->esp_netif, ESP_NETIF_DNS_MAIN, &dnsInfo);
+ ipCfg.dnsServer = std::string(esp_ip4addr_ntoa((const esp_ip4_addr_t*)&dnsInfo.ip, buf, sizeof(buf)));
+ }
+
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "Assigned IP: " + ipCfg.ipAddress + ", Subnet: " + ipCfg.subnetMask +
+ ", Gateway: " + ipCfg.gatewayAddress + ", DNS: " + ipCfg.dnsServer);
+
+ // Start NTP service
+ if (getUseNtp()) {
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "Start NTP service");
+ esp_netif_sntp_start();
+ }
+
+#ifdef ENABLE_MQTT
+ // Start MQTT serivce
+ if (getMqttIsEnabled()) {
+ vTaskDelay(pdMS_TO_TICKS(1000));
+ startMqttClient();
+ }
+#endif //ENABLE_MQTT
+ }
+ else if (event_id == WIFI_EVENT_AP_START) {
+ wifiState.connectionSuspendBaseTime = esp_timer_get_time();
+ }
+ else if (event_id == WIFI_EVENT_AP_STACONNECTED) {
+ wifi_event_ap_staconnected_t *event = (wifi_event_ap_staconnected_t *)event_data;
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "Access point: Client connected. MAC: " + macToString(event->mac));
+ wifiState.connectionSuspendBaseTime = esp_timer_get_time();
+ }
+ else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
+ wifi_event_ap_stadisconnected_t *event = (wifi_event_ap_stadisconnected_t *)event_data;
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "Access point: Client disconnected. MAC: " + macToString(event->mac) +
+ ", Reason: " + std::to_string(event->reason));
+ wifiState.connectionSuspendBaseTime = esp_timer_get_time();
+ }
+}
+
+
+bool suspendWifiConnection(void)
+{
+ if (wifiState.initialized && !wifiState.connectionSupended &&
+ (ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_CLIENT_TIMED_OFF ||
+ ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_AP_TIMED_OFF))
+ {
+ // Set base time to actual time if connection to AP is still established
+ if (ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_AP_TIMED_OFF && getWifiIsConnected()) {
+ wifiState.connectionSuspendBaseTime = esp_timer_get_time();
+ return false;
+ }
+
+ if ((int)((esp_timer_get_time() - wifiState.connectionSuspendBaseTime) / 60000000) >=
+ ConfigClass::getInstance()->get()->sectionNetwork.timedOffDelay) {
+ LogFile.writeToFile(ESP_LOG_WARN, TAG, "Suspending WLAN connection by time (parameter: Timed-Off Delay)");
+
+ wifiState.connected = false;
+ wifiState.connectionSupended = true;
+ setStatusLed(WLAN_CONN, 5, false);
+
+ // Stop MQTT client
+ if (getMqttIsEnabled()) {
+ deinitMqttClient();
+ }
+
+ // Disconnect WLAN
+ esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, event_handler);
+ esp_wifi_stop();
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+bool resumeWifiConnection(std::string source)
+{
+ if (wifiState.initialized && wifiState.connectionSupended &&
+ (ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_CLIENT_TIMED_OFF ||
+ ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_AP_TIMED_OFF))
+ {
+ wifiState.connectionSuspendBaseTime = esp_timer_get_time();
+ wifiState.connectionSupended = false;
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "Resuming WLAN connection | Source: " + source);
+
+ esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL);
+ esp_wifi_start();
+
+ // Underlaying wifi related services will be restarted within wifi event handler
+
+ return true;
+ }
+
+ return false;
+}
+
+
+esp_err_t initWifi(void)
+{
+ cfgDataPtr = &ConfigClass::getInstance()->get()->sectionNetwork;
+
+ if (cfgDataPtr->opmode == NETWORK_OPMODE_WLAN_CLIENT || cfgDataPtr->opmode == NETWORK_OPMODE_WLAN_CLIENT_TIMED_OFF) {
+ return initWifiClient();
+ }
+ else if (cfgDataPtr->opmode == NETWORK_OPMODE_WLAN_AP || cfgDataPtr->opmode == NETWORK_OPMODE_WLAN_AP_TIMED_OFF) {
+ return initWifiAp();
+ }
+ else if (cfgDataPtr->opmode == NETWORK_OPMODE_DISABLED) {
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "WLAN disabled");
+ return ESP_OK;
+ }
+
+ return ESP_FAIL;
+}
+
+
+esp_err_t initWifiClient(void)
+{
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "Init client mode");
+
+ cfgDataPtr = &ConfigClass::getInstance()->get()->sectionNetwork;
+
+ esp_err_t retVal = esp_event_loop_create_default();
+ if (retVal != ESP_OK && retVal != ESP_ERR_INVALID_STATE) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_event_loop_create_default: Error: " + intToHexString(retVal));
+ return retVal;
+ }
+
+ esp_netif_t *wifiStation = esp_netif_create_default_wifi_sta();
+
+ if (cfgDataPtr->wlan.ipv4.networkConfig == NETWORK_WLAN_IP_CONFIG_STATIC) {
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "Use static network config | IP: " + cfgDataPtr->wlan.ipv4.ipAddress +
+ ", Subnet: " + cfgDataPtr->wlan.ipv4.subnetMask + ", Gateway: " + cfgDataPtr->wlan.ipv4.gatewayAddress +
+ ", DNS: " + cfgDataPtr->wlan.ipv4.dnsServer);
+
+ retVal = esp_netif_dhcpc_stop(wifiStation); // Stop DHCP service
+ if (retVal != ESP_OK) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_netif_dhcpc_stop: Error: " + intToHexString(retVal));
+ return retVal;
+ }
+
+ esp_netif_ip_info_t ipInfo;
+ memset(&ipInfo, 0 , sizeof(esp_netif_ip_info_t));
+
+ ipCfg.ipAddress = cfgDataPtr->wlan.ipv4.ipAddress;
+ ipInfo.ip.addr = esp_ip4addr_aton(ipCfg.ipAddress.c_str());
+
+ ipCfg.subnetMask = cfgDataPtr->wlan.ipv4.subnetMask;
+ ipInfo.netmask.addr = esp_ip4addr_aton(ipCfg.subnetMask.c_str());
+
+ ipCfg.gatewayAddress = cfgDataPtr->wlan.ipv4.gatewayAddress;
+ ipInfo.gw.addr = esp_ip4addr_aton(ipCfg.gatewayAddress.c_str());
+
+ retVal = esp_netif_set_ip_info(wifiStation, &ipInfo);
+ if (retVal != ESP_OK) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_netif_set_ip_info: Error: " + intToHexString(retVal));
+ return retVal;
+ }
+
+ if (cfgDataPtr->wlan.ipv4.dnsServer.empty()) {
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "No DNS address set, use gateway address as DNS");
+ ipCfg.dnsServer = cfgDataPtr->wlan.ipv4.gatewayAddress;
+ }
+ else {
+ ipCfg.dnsServer = cfgDataPtr->wlan.ipv4.dnsServer;
+ }
+
+ esp_netif_dns_info_t dnsInfo;
+ dnsInfo.ip.u_addr.ip4.addr = esp_ip4addr_aton(ipCfg.dnsServer.c_str());
+
+ retVal = esp_netif_set_dns_info(wifiStation, ESP_NETIF_DNS_MAIN, &dnsInfo);
+ if (retVal != ESP_OK) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_netif_set_dns_info: Error: " + intToHexString(retVal));
+ return retVal;
+ }
+ }
+ else {
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "Use DHCP provided network config");
+ }
+
+ wifi_init_config_t wifiInitCfg = WIFI_INIT_CONFIG_DEFAULT();
+ retVal = esp_wifi_init(&wifiInitCfg);
+ if (retVal != ESP_OK) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_wifi_init: Error: " + intToHexString(retVal));
+ return retVal;
+ }
+
+ retVal = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL);
+ if (retVal != ESP_OK) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_event_handler_register - WIFI_ANY: Error: " + intToHexString(retVal));
+ return retVal;
+ }
+
+ retVal = esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL);
+ if (retVal != ESP_OK) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_event_handler_register - GOT_IP: Error: " + intToHexString(retVal));
+ return retVal;
+ }
+
+#ifdef WLAN_USE_MESH_ROAMING
+ retVal = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_BSS_RSSI_LOW, &esp_bss_rssi_low_handler, NULL);
+ if (retVal != ESP_OK) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_event_handler_register - BSS_RSSI_LOW: Error: " + std::to_string(retVal));
+ return retVal;
+ }
+#endif
+
+ retVal = esp_wifi_set_mode(WIFI_MODE_STA);
+ if (retVal != ESP_OK) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_wifi_set_mode: Error: " + intToHexString(retVal));
+ return retVal;
+ }
+
+ wifi_config_t wifiConfig = { };
+
+ wifiConfig.sta.scan_method = WIFI_ALL_CHANNEL_SCAN; // Scan all channels instead of stopping after first match
+ wifiConfig.sta.sort_method = WIFI_CONNECT_AP_BY_SIGNAL; // Sort by signal strength and keep up to 4 best APs
+ wifiConfig.sta.failure_retry_cnt = 5; // Number of connection retries station will do before moving to next AP
+
+#ifdef WLAN_USE_MESH_ROAMING
+ wifiConfig.sta.rm_enabled = 1; // 802.11k (Radio Resource Management)
+ wifiConfig.sta.btm_enabled = 1; // 802.11v (BSS Transition Management)
+ //wifiConfig.sta.mbo_enabled = 1; // Multiband Operation (better use of Wi-Fi network resources in roaming decisions) -> not activated to save heap
+ wifiConfig.sta.pmf_cfg.capable = 1; // 802.11w (Protected Management Frame, activated by default if other device also advertizes PMF capability)
+ //wifiConfig.sta.ft_enabled = 1; // 802.11r (BSS Fast Transition) -> Upcoming IDF version 5.0 will support 11r
+#endif
+
+ if (cfgDataPtr->wlan.ssid.empty()) {
+ LogFile.writeToFile(ESP_LOG_WARN, TAG, "SSID empty");
+ }
+
+ strcpy((char*)wifiConfig.sta.ssid, (const char*)cfgDataPtr->wlan.ssid.c_str());
+ strcpy((char*)wifiConfig.sta.password, (const char*)cfgDataPtr->wlan.password.c_str());
+
+ retVal = esp_wifi_set_config(WIFI_IF_STA, &wifiConfig);
+ if (retVal != ESP_OK) {
+ if (retVal == ESP_ERR_WIFI_PASSWORD) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_wifi_set_config: Password invalid | Error: " + intToHexString(retVal));
+ }
+ else {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_wifi_set_config: Error: " + intToHexString(retVal));
+ return retVal;
+ }
+ }
+
+ retVal = esp_wifi_start();
+ if (retVal != ESP_OK) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_wifi_start: Error: " + intToHexString(retVal));
+ return retVal;
+ }
+
+ if (!cfgDataPtr->wlan.hostname.empty()) {
+ retVal = esp_netif_set_hostname(wifiStation, cfgDataPtr->wlan.hostname.c_str());
+ if(retVal != ESP_OK ) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_netif_set_hostname: Error: " + intToHexString(retVal));
+ }
+ else {
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "Assigned hostname: " + cfgDataPtr->wlan.hostname);
+ }
+ }
+
+ wifiState.initialized = true;
+
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "Init client mode successful");
+ return ESP_OK;
+}
+
+
+esp_err_t initWifiAp(bool _useDefaultConfig)
+{
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "Init access point mode");
+
+ cfgDataPtr = &ConfigClass::getInstance()->get()->sectionNetwork;
+
+ esp_err_t retVal = esp_event_loop_create_default();
+ if (retVal != ESP_OK && retVal != ESP_ERR_INVALID_STATE) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_event_loop_create_default: Error: " + intToHexString(retVal));
+ return retVal;
+ }
+
+ esp_netif_t *wifiAp = esp_netif_create_default_wifi_ap();
+
+ retVal = esp_netif_dhcps_stop(wifiAp); // Stop DHCP server
+ if (retVal != ESP_OK) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_netif_dhcps_stop: Error: " + intToHexString(retVal));
+ return retVal;
+ }
+
+ esp_netif_ip_info_t ipInfo;
+ memset(&ipInfo, 0 , sizeof(esp_netif_ip_info_t));
+
+ if (_useDefaultConfig) { // Use default config
+ ipCfg.ipAddress = "192.168.4.1";
+ }
+ else {
+ ipCfg.ipAddress = cfgDataPtr->wlanAp.ipv4.ipAddress;
+ }
+ ipInfo.ip.addr = esp_ip4addr_aton(ipCfg.ipAddress.c_str());
+
+ ipCfg.subnetMask = "255.255.255.0";
+ ipInfo.netmask.addr = esp_ip4addr_aton(ipCfg.subnetMask.c_str());
+
+ ipCfg.gatewayAddress = ipCfg.ipAddress;
+ ipInfo.gw.addr = esp_ip4addr_aton(ipCfg.gatewayAddress.c_str());
+
+ retVal = esp_netif_set_ip_info(wifiAp, &ipInfo);
+ if (retVal != ESP_OK) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_netif_set_ip_info: Error: " + intToHexString(retVal));
+ return retVal;
+ }
+
+ esp_netif_dns_info_t dnsInfo;
+ memset(&dnsInfo, 0 , sizeof(esp_netif_dns_info_t));
+
+ ipCfg.dnsServer = ipCfg.ipAddress;
+ dnsInfo.ip.u_addr.ip4.addr = esp_ip4addr_aton(ipCfg.dnsServer.c_str());
+
+ retVal = esp_netif_set_dns_info(wifiAp, ESP_NETIF_DNS_MAIN, &dnsInfo);
+ if (retVal != ESP_OK) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_netif_set_dns_info: Error: " + intToHexString(retVal));
+ return retVal;
+ }
+
+ retVal = esp_netif_dhcps_start(wifiAp); // Restart DHCP server
+ if (retVal != ESP_OK) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_netif_dhcps_start: Error: " + intToHexString(retVal));
+ return retVal;
+ }
+
+ wifi_init_config_t wifiInitCfg = WIFI_INIT_CONFIG_DEFAULT();
+ retVal = esp_wifi_init(&wifiInitCfg);
+ if (retVal != ESP_OK) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_wifi_init: Error: " + intToHexString(retVal));
+ return retVal;
+ }
+
+ retVal = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL);
+ if (retVal != ESP_OK) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_event_handler_register - WIFI_ANY: Error: " + intToHexString(retVal));
+ return retVal;
+ }
+
+ retVal = esp_wifi_set_mode(WIFI_MODE_AP);
+ if (retVal != ESP_OK) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_wifi_set_mode: Error: " + intToHexString(retVal));
+ return retVal;
+ }
+
+ wifi_config_t wifiConfig = { };
+
+ if (_useDefaultConfig) { // Use default config
+ strcpy((char*)wifiConfig.ap.ssid, "AI-on-the-Edge Device");
+ strcpy((char*)wifiConfig.ap.password, "");
+ wifiConfig.ap.authmode = WIFI_AUTH_OPEN;
+ wifiConfig.ap.channel = 11;
+ wifiConfig.ap.max_connection = 1;
+ }
+ else {
+ if (cfgDataPtr->wlanAp.ssid.empty()) {
+ LogFile.writeToFile(ESP_LOG_WARN, TAG, "Access point SSID empty");
+ }
+
+ if (cfgDataPtr->wlanAp.password.empty()) {
+ wifiConfig.ap.authmode = WIFI_AUTH_OPEN;
+ }
+ else if (cfgDataPtr->wlanAp.password.length() < 8) {
+ LogFile.writeToFile(ESP_LOG_WARN, TAG, "Access point password less than 8 character");
+ wifiConfig.ap.authmode = WIFI_AUTH_WPA2_WPA3_PSK;
+ }
+ else {
+ wifiConfig.ap.authmode = WIFI_AUTH_WPA2_WPA3_PSK;
+ }
+
+ strcpy((char*)wifiConfig.ap.ssid, (const char*)cfgDataPtr->wlanAp.ssid.c_str());
+ strcpy((char*)wifiConfig.ap.password, (const char*)cfgDataPtr->wlanAp.password.c_str());
+
+ wifiConfig.ap.channel = cfgDataPtr->wlanAp.channel;
+ wifiConfig.ap.max_connection = 3;
+ }
+
+ retVal = esp_wifi_set_config(WIFI_IF_AP, &wifiConfig);
+ if (retVal != ESP_OK) {
+ if (retVal == ESP_ERR_WIFI_PASSWORD) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_wifi_set_config: Password invalid | Error: " + intToHexString(retVal));
+ }
+ else {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_wifi_set_config: Error: " + intToHexString(retVal));
+ return retVal;
+ }
+ }
+
+ retVal = esp_wifi_start();
+ if (retVal != ESP_OK) {
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_wifi_start: Error: " + intToHexString(retVal));
+ return retVal;
+ }
+
+ wifiState.initialized = true;
+
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "Init access point mode successful | SSID: " + std::string((char *)wifiConfig.ap.ssid) +
+ ", PW: " + std::string((char *)wifiConfig.ap.password) + ", CH: " + std::to_string(wifiConfig.ap.channel) + ", IP: " + ipCfg.ipAddress);
+ return ESP_OK;
+}
+
+
+#ifdef WLAN_USE_ROAMING_BY_SCANNING
+std::string getAuthModeName(const wifi_auth_mode_t authMode)
+{
+ std::string authModeNames[] = {"OPEN", "WEP", "WPA PSK", "WPA2 PSK", "WPA WPA2 PSK", "WPA2 ENTERPRISE",
+ "WPA3 PSK", "WPA2 WPA3 PSK", "WAPI_PSK", "MAX"};
+ return authModeNames[authMode];
+}
+
+
+void wifiScan(void)
+{
+ wifi_scan_config_t wifiScanConfig;
+ memset(&wifiScanConfig, 0, sizeof(wifiScanConfig));
+
+ wifiScanConfig.ssid = (uint8_t*)cfgDataPtr->wlan.ssid.c_str(); // only scan for configured SSID
+ wifiScanConfig.show_hidden = true; // scan also hidden SSIDs
+ wifiScanConfig.channel = 0; // scan all channels
+
+ esp_wifi_scan_start(&wifiScanConfig, true); // not using event handler SCAN_DONE by purpose to keep SYS_EVENT heap smaller
+ // and the calling task task_autodoFlow is after scan is finish in wait state anyway
+ // Scan duration: ca. (120ms + 30ms) * Number of channels -> ca. 1,5 - 2s
+
+ uint16_t maxNumberOfApFound = 10; // max. number of APs, value will be updated by function "esp_wifi_scan_get_ap_num"
+ esp_wifi_scan_get_ap_num(&maxNumberOfApFound); // get actual found APs
+ wifi_ap_record_t* wifiApRecords = new wifi_ap_record_t[maxNumberOfApFound]; // Allocate necessary record datasets
+ if (wifiApRecords == NULL) {
+ esp_wifi_scan_get_ap_records(0, NULL); // free internal heap
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "wifiScan: Failed to allocate heap for wifiApRecords");
+ return;
+ }
+ else {
+ if (esp_wifi_scan_get_ap_records(&maxNumberOfApFound, wifiApRecords) != ESP_OK) { // Retrieve results (and free internal heap)
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "wifiScan: esp_wifi_scan_get_ap_records: Error retrieving datasets");
+ delete[] wifiApRecords;
+ return;
+ }
+ }
+
+ wifi_ap_record_t currentAP;
+ esp_wifi_sta_get_ap_info(¤tAP);
+
+ LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Roaming: Current AP BSSID=" + bssidToString((char*)currentAP.bssid));
+ LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Roaming: Scan completed, APs found with configured SSID: " + std::to_string(maxNumberOfApFound));
+ for (int i = 0; i < maxNumberOfApFound; i++) {
+ LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Roaming: " + std::to_string(i+1) +
+ ": SSID=" + std::string((char*)wifiApRecords[i].ssid) +
+ ", BSSID=" + bssidToString((char*)wifiApRecords[i].bssid) +
+ ", RSSI=" + std::to_string(wifiApRecords[i].rssi) +
+ ", CH=" + std::to_string(wifiApRecords[i].primary) +
+ ", AUTH=" + getAuthModeName(wifiApRecords[i].authmode));
+ if (wifiApRecords[i].rssi > (currentAP.rssi + 5) && // RSSI is better than actual RSSI + 5 --> Avoid switching to AP with roughly same RSSI
+ (strcmp(bssidToString((char*)wifiApRecords[i].bssid).c_str(), bssidToString((char*)currentAP.bssid).c_str()) != 0))
+ {
+ wifiState.accessPointWithBetterRSSI = true;
+ }
+ }
+ delete[] wifiApRecords;
+}
+
+
+void wifiRoamByScanning(void)
+{
+ if (cfgDataPtr->wlan.wlanRoaming.enabled && getWifiRssi() != -127 && getWifiRssi() < cfgDataPtr->wlan.wlanRoaming.rssiThreshold) {
+ LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Roaming: Start scan of all channels for SSID " + cfgDataPtr->wlan.ssid);
+ wifiScan();
+
+ if (wifiState.accessPointWithBetterRSSI) {
+ wifiState.accessPointWithBetterRSSI = false;
+ LogFile.writeToFile(ESP_LOG_WARN, TAG, "Roaming: AP with better RSSI in range, disconnect to switch AP");
+ esp_wifi_disconnect();
+ }
+ else {
+ LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Roaming: Scan completed, stay on current AP");
+ }
+ }
}
+#endif // WLAN_USE_ROAMING_BY_SCANNING
#ifdef WLAN_USE_MESH_ROAMING
@@ -169,7 +764,7 @@ static char * get_btm_neighbor_list(uint8_t *report, size_t report_len)
civic[0] ? " civic=" : "", civic);
- LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Roaming: RMM neighbor report BSSID: " + BssidToString((char*)nr) +
+ LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Roaming: RMM neighbor report BSSID: " + bssidToString((char*)nr) +
", Channel: " + std::to_string(nr[ETH_ALEN + 5]));
/* neighbor start */
@@ -305,7 +900,7 @@ void printRoamingFeatureSupport(void)
void wifiRoamingQuery(void)
{
/* Query only if WIFI is connected and feature is supported by AP */
- if (WIFIConnected && (esp_rrm_is_rrm_supported_connection() || esp_wnm_is_btm_supported_connection())) {
+ if (wifiState.connected && (esp_rrm_is_rrm_supported_connection() || esp_wnm_is_btm_supported_connection())) {
/* Client is allowed to send query to AP for roaming request if RSSI is lower than threshold */
/* Note 1: Set RSSI threshold funtion needs to be called to trigger WIFI_EVENT_STA_BSS_RSSI_LOW */
/* Note 2: Additional querys will be sent after flow cycle is finshed --> server_tflite.cpp - function "task_autodoFlow" */
@@ -320,415 +915,204 @@ void wifiRoamingQuery(void)
#endif // WLAN_USE_MESH_ROAMING
-#ifdef WLAN_USE_ROAMING_BY_SCANNING
-std::string getAuthModeName(const wifi_auth_mode_t auth_mode)
-{
- std::string AuthModeNames[] = {"OPEN", "WEP", "WPA PSK", "WPA2 PSK", "WPA WPA2 PSK", "WPA2 ENTERPRISE",
- "WPA3 PSK", "WPA2 WPA3 PSK", "WAPI_PSK", "MAX"};
- return AuthModeNames[auth_mode];
-}
-
-
-void wifi_scan(void)
+std::string getNetworkOpmode(void)
{
- wifi_scan_config_t wifi_scan_config;
- memset(&wifi_scan_config, 0, sizeof(wifi_scan_config));
-
- wifi_scan_config.ssid = (uint8_t*)cfgDataPtr->wlan.ssid.c_str(); // only scan for configured SSID
- wifi_scan_config.show_hidden = true; // scan also hidden SSIDs
- wifi_scan_config.channel = 0; // scan all channels
-
- esp_wifi_scan_start(&wifi_scan_config, true); // not using event handler SCAN_DONE by purpose to keep SYS_EVENT heap smaller
- // and the calling task task_autodoFlow is after scan is finish in wait state anyway
- // Scan duration: ca. (120ms + 30ms) * Number of channels -> ca. 1,5 - 2s
-
- uint16_t max_number_of_ap_found = 10; // max. number of APs, value will be updated by function "esp_wifi_scan_get_ap_num"
- esp_wifi_scan_get_ap_num(&max_number_of_ap_found); // get actual found APs
- wifi_ap_record_t* wifi_ap_records = new wifi_ap_record_t[max_number_of_ap_found]; // Allocate necessary record datasets
- if (wifi_ap_records == NULL) {
- esp_wifi_scan_get_ap_records(0, NULL); // free internal heap
- LogFile.writeToFile(ESP_LOG_ERROR, TAG, "wifi_scan: Failed to allocate heap for wifi_ap_records");
- return;
+ if (ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_AP ||
+ ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_AP_TIMED_OFF || wifiState.fallbackApActive) {
+ return "WLAN Access Point";
}
- else {
- if (esp_wifi_scan_get_ap_records(&max_number_of_ap_found, wifi_ap_records) != ESP_OK) { // Retrieve results (and free internal heap)
- LogFile.writeToFile(ESP_LOG_ERROR, TAG, "wifi_scan: esp_wifi_scan_get_ap_records: Error retrieving datasets");
- delete[] wifi_ap_records;
- return;
- }
+ else if (ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_CLIENT ||
+ ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_CLIENT_TIMED_OFF) {
+ return "WLAN Client";
}
-
- wifi_ap_record_t currentAP;
- esp_wifi_sta_get_ap_info(¤tAP);
-
- LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Roaming: Current AP BSSID=" + BssidToString((char*)currentAP.bssid));
- LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Roaming: Scan completed, APs found with configured SSID: " + std::to_string(max_number_of_ap_found));
- for (int i = 0; i < max_number_of_ap_found; i++) {
- LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Roaming: " + std::to_string(i+1) +
- ": SSID=" + std::string((char*)wifi_ap_records[i].ssid) +
- ", BSSID=" + BssidToString((char*)wifi_ap_records[i].bssid) +
- ", RSSI=" + std::to_string(wifi_ap_records[i].rssi) +
- ", CH=" + std::to_string(wifi_ap_records[i].primary) +
- ", AUTH=" + getAuthModeName(wifi_ap_records[i].authmode));
- if (wifi_ap_records[i].rssi > (currentAP.rssi + 5) && // RSSI is better than actual RSSI + 5 --> Avoid switching to AP with roughly same RSSI
- (strcmp(BssidToString((char*)wifi_ap_records[i].bssid).c_str(), BssidToString((char*)currentAP.bssid).c_str()) != 0))
- {
- APWithBetterRSSI = true;
- }
+ else if (ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_DISABLED) {
+ return "Disabled";
}
- delete[] wifi_ap_records;
-}
-
-
-void wifiRoamByScanning(void)
-{
- if (cfgDataPtr->wlan.wlanRoaming.enabled && getWifiRssi() != -127 && getWifiRssi() < cfgDataPtr->wlan.wlanRoaming.rssiThreshold) {
- LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Roaming: Start scan of all channels for SSID " + cfgDataPtr->wlan.ssid);
- wifi_scan();
- if (APWithBetterRSSI) {
- APWithBetterRSSI = false;
- LogFile.writeToFile(ESP_LOG_WARN, TAG, "Roaming: AP with better RSSI in range, disconnect to switch AP");
- esp_wifi_disconnect();
- }
- else {
- LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Roaming: Scan completed, stay on current AP");
- }
- }
+ return "Unknown";
}
-#endif // WLAN_USE_ROAMING_BY_SCANNING
-std::string getMac()
+std::string getMac(void)
{
- uint8_t macInt[6];
- char macFormated[6*2 + 5 + 1]; // AA:BB:CC:DD:EE:FF
+ uint8_t macInt[6];
- esp_read_mac(macInt, ESP_MAC_WIFI_STA);
- sprintf(macFormated, "%02X:%02X:%02X:%02X:%02X:%02X", macInt[0], macInt[1], macInt[2], macInt[3], macInt[4], macInt[5]);
+ if (ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_AP ||
+ ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_AP_TIMED_OFF || wifiState.fallbackApActive) {
+ esp_read_mac(macInt, ESP_MAC_WIFI_SOFTAP);
+ return macToString(macInt);
+ }
+ else if (ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_CLIENT ||
+ ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_CLIENT_TIMED_OFF) {
+ esp_read_mac(macInt, ESP_MAC_WIFI_STA);
+ return macToString(macInt);
+ }
- return macFormated;
+ return "";
}
-bool getDHCPUsage()
+bool getDhcpStatus(void)
{
- if (cfgDataPtr != NULL && cfgDataPtr->wlan.ipv4.networkConfig == NETWORK_CONFIG_DHCP)
+ if (ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_AP ||
+ ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_AP_TIMED_OFF || wifiState.fallbackApActive) {
return true;
+ }
+ else if (ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_CLIENT ||
+ ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_CLIENT_TIMED_OFF) {
+ if (ConfigClass::getInstance()->get()->sectionNetwork.wlan.ipv4.networkConfig == NETWORK_WLAN_IP_CONFIG_DHCP) {
+ return true;
+ }
+ return false;
+ }
- return false;
+ return true;
}
-std::string getIPAddress()
+std::string getIpAddress(void)
{
return ipCfg.ipAddress;
}
-std::string getNetmaskAddress()
+std::string getNetmaskAddress(void)
{
- return ipCfg.subnetMask;
+ return ipCfg.subnetMask;
}
-std::string getGatewayAddress()
+std::string getGatewayAddress(void)
{
- return ipCfg.gatewayAddress;
+ return ipCfg.gatewayAddress;
}
-std::string getDNSAddress()
+std::string getDnsAddress(void)
{
- return ipCfg.dnsServer;
+ return ipCfg.dnsServer;
}
-std::string getSSID()
+std::string getWifiSsid(void)
{
- return cfgDataPtr->wlan.ssid;
+ if (ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_AP ||
+ ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_AP_TIMED_OFF || wifiState.fallbackApActive) {
+ return ConfigClass::getInstance()->get()->sectionNetwork.wlanAp.ssid;
+ }
+ else if (ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_CLIENT ||
+ ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_CLIENT_TIMED_OFF) {
+ return ConfigClass::getInstance()->get()->sectionNetwork.wlan.ssid;
+ }
+
+ return "";
}
-std::string getHostname()
+std::string getHostname(void)
{
- return cfgDataPtr->wlan.hostname;
+ return ConfigClass::getInstance()->get()->sectionNetwork.wlan.hostname;
}
-int getWifiRssi()
+int getWifiChannel(void)
{
- wifi_ap_record_t ap;
- if (esp_wifi_sta_get_ap_info(&ap) == ESP_OK) {
- return ap.rssi;
+ if (ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_AP ||
+ ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_AP_TIMED_OFF || wifiState.fallbackApActive) {
+ return ConfigClass::getInstance()->get()->sectionNetwork.wlanAp.channel;
}
- else {
- return -127; // Return -127 if no info available e.g. not connected
+ else if (ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_CLIENT ||
+ ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_CLIENT_TIMED_OFF) {
+ wifi_config_t wifiConfig;
+ if (esp_wifi_get_config(WIFI_IF_STA, &wifiConfig) == ESP_OK) {
+ return (int)wifiConfig.sta.channel;
+ }
}
-}
-
-bool getWIFIisConnected()
-{
- return WIFIConnected;
+ return -1;
}
-static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
+int getWifiRssi(void)
{
- if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
- WIFIConnected = false;
- esp_wifi_connect();
- }
- else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
- /* Disconnect reason: https://github.com/espressif/esp-idf/blob/d825753387c1a64463779bbd2369e177e5d59a79/components/esp_wifi/include/esp_wifi_types.h */
- wifi_event_sta_disconnected_t *disconn = (wifi_event_sta_disconnected_t *)event_data;
- if (disconn->reason == WIFI_REASON_ROAMING) {
- LogFile.writeToFile(ESP_LOG_WARN, TAG, "Disconnected (" + std::to_string(disconn->reason) + ", Roaming 802.11kv)");
- // --> no reconnect neccessary, it should automatically reconnect to new AP
- }
- else {
- WIFIConnected = false;
- if (disconn->reason == WIFI_REASON_NO_AP_FOUND ||
- disconn->reason == WIFI_REASON_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD ||
- disconn->reason == WIFI_REASON_NO_AP_FOUND_IN_RSSI_THRESHOLD) {
- LogFile.writeToFile(ESP_LOG_WARN, TAG, "Disconnected (" + std::to_string(disconn->reason) + ", No AP found)");
- setStatusLed(WLAN_CONN, 1, false);
- }
- 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 ||
- disconn->reason == WIFI_REASON_NO_AP_FOUND_W_COMPATIBLE_SECURITY) {
- LogFile.writeToFile(ESP_LOG_WARN, TAG, "Disconnected (" + std::to_string(disconn->reason) + ", Auth fail)");
- setStatusLed(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)");
- setStatusLed(WLAN_CONN, 3, false);
- }
- else {
- LogFile.writeToFile(ESP_LOG_WARN, TAG, "Disconnected (" + std::to_string(disconn->reason) + ")");
- setStatusLed(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");
+ if (ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_AP ||
+ ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_AP_TIMED_OFF || wifiState.fallbackApActive) {
+ wifi_sta_list_t clientList;
+ if (esp_wifi_ap_get_sta_list(&clientList) == ESP_OK && clientList.num > 0) {
+ return (int)clientList.sta[0].rssi; // Return RSSI of first connected client
}
}
- else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED) {
- LogFile.writeToFile(ESP_LOG_INFO, TAG, "Connected to: " + cfgDataPtr->wlan.ssid + ", RSSI: " +
- std::to_string(getWifiRssi()));
-
- #ifdef WLAN_USE_MESH_ROAMING
- printRoamingFeatureSupport();
-
- #ifdef WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES
- // wifiRoamingQuery(); // Avoid client triggered query during processing flow (reduce risk of heap shortage). Request will be triggered at the end of every cycle anyway
- #endif //WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES
-
- #endif //WLAN_USE_MESH_ROAMING
- }
- else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
- WIFIConnected = true;
- WIFIReconnectCnt = 0;
-
- if (cfgDataPtr->wlan.ipv4.networkConfig == NETWORK_CONFIG_DHCP) {
- char buf[20];
- ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
-
- ipCfg.ipAddress = std::string(esp_ip4addr_ntoa(&event->ip_info.ip, buf, sizeof(buf)));
- ipCfg.subnetMask = std::string(esp_ip4addr_ntoa(&event->ip_info.netmask, buf, sizeof(buf)));
- ipCfg.gatewayAddress = std::string(esp_ip4addr_ntoa(&event->ip_info.gw, buf, sizeof(buf)));
-
- esp_netif_dns_info_t dnsInfo;
- esp_netif_get_dns_info(event->esp_netif, ESP_NETIF_DNS_MAIN, &dnsInfo);
- ipCfg.dnsServer = std::string(esp_ip4addr_ntoa((const esp_ip4_addr_t*)&dnsInfo.ip, buf, sizeof(buf)));
- }
-
- LogFile.writeToFile(ESP_LOG_INFO, TAG, "Assigned IP: " + ipCfg.ipAddress +
- ", Subnet: " + ipCfg.subnetMask +
- ", Gateway: " + ipCfg.gatewayAddress +
- ", DNS: " + ipCfg.dnsServer);
-
- // Start NTP service
- if (getUseNtp()) {
- esp_netif_sntp_start();
- LogFile.writeToFile(ESP_LOG_INFO, TAG, "Start NTP service");
- }
-
-#ifdef ENABLE_MQTT
- // Start MQTT serivce
- if (getMQTTisEnabled()) {
- MQTT_Init();
+ else if (ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_CLIENT ||
+ ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_CLIENT_TIMED_OFF) {
+ wifi_ap_record_t apInfo;
+ if (esp_wifi_sta_get_ap_info(&apInfo) == ESP_OK) {
+ return apInfo.rssi;
}
-#endif //ENABLE_MQTT
}
+
+ return -127; // Not connected or no info
}
-esp_err_t initWifiStation(void)
+bool getWifiIsConnected(bool improvProvisioning)
{
- cfgDataPtr = &ConfigClass::getInstance()->get()->sectionNetwork;
-
- esp_err_t retVal = esp_event_loop_create_default();
- if (retVal != ESP_OK && retVal != ESP_ERR_INVALID_STATE) {
- LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_event_loop_create_default: Error: " + intToHexString(retVal));
- return retVal;
+ if (improvProvisioning) {
+ return wifiState.connected;
}
-
- wifiStation = esp_netif_create_default_wifi_sta();
-
- if (cfgDataPtr->wlan.ipv4.networkConfig == NETWORK_CONFIG_STATIC) {
- LogFile.writeToFile(ESP_LOG_INFO, TAG, "Use static network config");
-
- retVal = esp_netif_dhcpc_stop(wifiStation); // Stop DHCP service
- if (retVal != ESP_OK) {
- LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_netif_dhcpc_stop: Error: " + intToHexString(retVal));
- return retVal;
- }
-
- esp_netif_ip_info_t ipInfo;
- memset(&ipInfo, 0 , sizeof(esp_netif_ip_info_t));
-
- ipCfg.ipAddress = cfgDataPtr->wlan.ipv4.ipAddress;
- ipInfo.ip.addr = esp_ip4addr_aton(ipCfg.ipAddress.c_str());
-
- ipCfg.subnetMask = cfgDataPtr->wlan.ipv4.subnetMask;
- ipInfo.netmask.addr = esp_ip4addr_aton(ipCfg.subnetMask.c_str());
-
- ipCfg.gatewayAddress = cfgDataPtr->wlan.ipv4.gatewayAddress;
- ipInfo.gw.addr = esp_ip4addr_aton(ipCfg.gatewayAddress.c_str());
-
- retVal = esp_netif_set_ip_info(wifiStation, &ipInfo);
- if (retVal != ESP_OK) {
- LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_netif_set_ip_info: Error: " + intToHexString(retVal));
- return retVal;
- }
-
- if (cfgDataPtr->wlan.ipv4.dnsServer.empty()) {
- LogFile.writeToFile(ESP_LOG_INFO, TAG, "No DNS address set, use gateway address as DNS");
- ipCfg.dnsServer = cfgDataPtr->wlan.ipv4.gatewayAddress;
- }
- else {
- ipCfg.dnsServer = cfgDataPtr->wlan.ipv4.dnsServer;
- }
-
- esp_netif_dns_info_t dnsInfo;
- dnsInfo.ip.u_addr.ip4.addr = esp_ip4addr_aton(ipCfg.dnsServer.c_str());
-
- retVal = esp_netif_set_dns_info(wifiStation, ESP_NETIF_DNS_MAIN, &dnsInfo);
- if (retVal != ESP_OK) {
- LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_netif_set_dns_info: Error: " + intToHexString(retVal));
- return retVal;
+ else if (ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_AP ||
+ ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_AP_TIMED_OFF || wifiState.fallbackApActive) {
+ wifi_sta_list_t clientList;
+ if (esp_wifi_ap_get_sta_list(&clientList) == ESP_OK && clientList.num > 0) {
+ return true;
}
}
- else {
- LogFile.writeToFile(ESP_LOG_INFO, TAG, "Use DHCP provided network config");
- }
-
- wifi_init_config_t wifiInitCfg = WIFI_INIT_CONFIG_DEFAULT();
- retVal = esp_wifi_init(&wifiInitCfg);
- if (retVal != ESP_OK) {
- LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_wifi_init: Error: " + intToHexString(retVal));
- return retVal;
- }
-
- retVal = esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, NULL);
- if (retVal != ESP_OK) {
- LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_event_handler_instance_register - WIFI_ANY: Error: " + intToHexString(retVal));
- return retVal;
- }
-
- 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: " + intToHexString(retVal));
- return retVal;
- }
-
- #ifdef WLAN_USE_MESH_ROAMING
- retVal = esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_STA_BSS_RSSI_LOW, &esp_bss_rssi_low_handler, NULL, NULL);
- if (retVal != ESP_OK) {
- LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_event_handler_instance_register - BSS_RSSI_LOW: Error: " + std::to_string(retVal));
- return retVal;
+ else if (ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_CLIENT ||
+ ConfigClass::getInstance()->get()->sectionNetwork.opmode == NETWORK_OPMODE_WLAN_CLIENT_TIMED_OFF) {
+ return wifiState.connected;
}
- #endif
-
- wifi_config_t wifiConfig = { };
- wifiConfig.sta.scan_method = WIFI_ALL_CHANNEL_SCAN; // Scan all channels instead of stopping after first match
- wifiConfig.sta.sort_method = WIFI_CONNECT_AP_BY_SIGNAL; // Sort by signal strength and keep up to 4 best APs
- wifiConfig.sta.failure_retry_cnt = 5; // Number of connection retries station will do before moving to next AP
+ return false;
+}
- #ifdef WLAN_USE_MESH_ROAMING
- wifiConfig.sta.rm_enabled = 1; // 802.11k (Radio Resource Management)
- wifiConfig.sta.btm_enabled = 1; // 802.11v (BSS Transition Management)
- //wifiConfig.sta.mbo_enabled = 1; // Multiband Operation (better use of Wi-Fi network resources in roaming decisions) -> not activated to save heap
- wifiConfig.sta.pmf_cfg.capable = 1; // 802.11w (Protected Management Frame, activated by default if other device also advertizes PMF capability)
- //wifiConfig.sta.ft_enabled = 1; // 802.11r (BSS Fast Transition) -> Upcoming IDF version 5.0 will support 11r
- #endif
- if (cfgDataPtr->wlan.ssid.empty()) {
- LogFile.writeToFile(ESP_LOG_WARN, TAG, "SSID empty");
+/** Return Wifi connection status
+ * @return
+ * - WIFI_CONNECTION_NOT_INITIALIZED wifi not intialized
+ * - WIFI_CONNECTION_INITIALIZED wifi initialized
+ * - WIFI_CONNECTION_CONNECTED wifi connected
+ * - WIFI_CONNECTION_DISCONNECTED wifi disconnected
+ * - WIFI_CONNECTION_SUSPENDED wifi connection suspended
+ */
+wifi_connection_status_t getWifiConnectionStatus(void)
+{
+ if (wifiState.initialized && wifiState.connectionSupended) {
+ return WIFI_CONNECTION_SUSPENDED;
}
-
- strcpy((char*)wifiConfig.sta.ssid, (const char*)cfgDataPtr->wlan.ssid.c_str());
- strcpy((char*)wifiConfig.sta.password, (const char*)cfgDataPtr->wlan.password.c_str());
-
- retVal = esp_wifi_set_mode(WIFI_MODE_STA);
- if (retVal != ESP_OK) {
- LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_wifi_set_mode: Error: " + intToHexString(retVal));
- return retVal;
+ else if (wifiState.initialized && getWifiIsConnected()) {
+ return WIFI_CONNECTION_CONNECTED;
}
-
- retVal = esp_wifi_set_config(WIFI_IF_STA, &wifiConfig);
- if (retVal != ESP_OK) {
- if (retVal == ESP_ERR_WIFI_PASSWORD) {
- LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_wifi_set_config: Password invalid | Error: " + intToHexString(retVal));
- }
- else {
- LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_wifi_set_config: Error: " + intToHexString(retVal));
- }
- return retVal;
+ else if (wifiState.initialized && !getWifiIsConnected()) {
+ return WIFI_CONNECTION_DISCONNECTED;
}
-
- retVal = esp_wifi_start();
- if (retVal != ESP_OK) {
- LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_wifi_start: Error: " + intToHexString(retVal));
- return retVal;
+ else if (wifiState.initialized) {
+ return WIFI_CONNECTION_INITIALIZED;
}
- if (!cfgDataPtr->wlan.hostname.empty()) {
- retVal = esp_netif_set_hostname(wifiStation, cfgDataPtr->wlan.hostname.c_str());
- if(retVal != ESP_OK ) {
- LogFile.writeToFile(ESP_LOG_ERROR, TAG, "esp_netif_set_hostname: Error: " + intToHexString(retVal));
- }
- else {
- LogFile.writeToFile(ESP_LOG_INFO, TAG, "Assigned hostname: " + cfgDataPtr->wlan.hostname);
- }
- }
-
- LogFile.writeToFile(ESP_LOG_INFO, TAG, "Init successful");
- return ESP_OK;
+ return WIFI_CONNECTION_NOT_INITIALIZED;
}
-void wifiDestroy()
+void deinitWifi(void)
{
+ wifiState.initialized = false;
+
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);
- #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);
- #endif
+#endif
esp_wifi_disconnect();
esp_wifi_stop();
esp_wifi_deinit();
}
-
diff --git a/code/components/wlan_ctrl/connect_wlan.h b/code/components/wlan_ctrl/connect_wlan.h
index cfa50b22d..b06454e52 100644
--- a/code/components/wlan_ctrl/connect_wlan.h
+++ b/code/components/wlan_ctrl/connect_wlan.h
@@ -3,20 +3,23 @@
#include
+#include
-int initWifiStation(void);
-std::string getMac(void);
-bool getDHCPUsage();
-std::string getIPAddress();
-std::string getNetmaskAddress();
-std::string getGatewayAddress();
-std::string getDNSAddress();
-std::string getSSID();
-int getWifiRssi();
-std::string getHostname();
-bool getWIFIisConnected();
-
-void wifiDestroy();
+typedef enum WIFI_CONNECTION_STATUS {
+ WIFI_CONNECTION_NOT_INITIALIZED = 0,
+ WIFI_CONNECTION_INITIALIZED = 1,
+ WIFI_CONNECTION_CONNECTED = 2,
+ WIFI_CONNECTION_DISCONNECTED = 3,
+ WIFI_CONNECTION_SUSPENDED = 4
+} wifi_connection_status_t;
+
+
+esp_err_t initWifi(void);
+esp_err_t initWifiClient(void);
+esp_err_t initWifiAp(bool _useDefaultConfig = false);
+
+bool suspendWifiConnection(void);
+bool resumeWifiConnection(std::string source = "unknown");
#if (defined WLAN_USE_MESH_ROAMING && defined WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES)
void wifiRoamingQuery(void);
@@ -26,4 +29,20 @@ void wifiRoamingQuery(void);
void wifiRoamByScanning(void);
#endif
+std::string getNetworkOpmode(void);
+std::string getMac(void);
+bool getDhcpStatus(void);
+std::string getIpAddress(void);
+std::string getNetmaskAddress(void);
+std::string getGatewayAddress(void);
+std::string getDnsAddress(void);
+std::string getWifiSsid(void);
+std::string getHostname(void);
+int getWifiChannel(void);
+int getWifiRssi(void);
+bool getWifiIsConnected(bool improvProvisioning = false);
+wifi_connection_status_t getWifiConnectionStatus(void);
+
+void deinitWifi(void);
+
#endif //CONNECT_WLAN_H
\ No newline at end of file
diff --git a/code/components/wlan_ctrl/improvWifi.cpp b/code/components/wlan_ctrl/improvWifi.cpp
index 10a425b0e..158647128 100644
--- a/code/components/wlan_ctrl/improvWifi.cpp
+++ b/code/components/wlan_ctrl/improvWifi.cpp
@@ -118,10 +118,10 @@ void ImprovWiFi::setDeviceInfo(ImprovTypes::ChipFamily chipFamily, const char *f
}
-bool ImprovWiFi::isConnected()
+bool ImprovWiFi::isConnected(bool improvProvisioning)
{
if (customIsConnectedCallback) {
- return customIsConnectedCallback();
+ return customIsConnectedCallback(improvProvisioning);
}
return false;
diff --git a/code/components/wlan_ctrl/improvWifi.h b/code/components/wlan_ctrl/improvWifi.h
index 485e5657d..543fdac56 100644
--- a/code/components/wlan_ctrl/improvWifi.h
+++ b/code/components/wlan_ctrl/improvWifi.h
@@ -48,7 +48,7 @@ class ImprovWiFi {
// Callback functions to customize the wifi connection
typedef bool(CustomConnectWiFi)(const char *ssid, const char *password);
typedef void(CustomScanWiFi)(unsigned char *scanResponse, int bufLen, uint16_t *networkNum);
- typedef bool(CustomIsConnected)(void);
+ typedef bool(CustomIsConnected)(bool improvProvisioning);
typedef std::string(CustomGetLocalIpCallback)(void);
@@ -91,7 +91,7 @@ class ImprovWiFi {
void setCustomGetLocalIpCallback(CustomGetLocalIpCallback *getLocalIpCallback);
// Check if connection is established
- bool isConnected();
+ bool isConnected(bool improvProvisioning = true);
};
#endif /* IMPROV_WIFI_H */
diff --git a/code/components/wlan_ctrl/improvWifiProvisioning.cpp b/code/components/wlan_ctrl/improvWifiProvisioning.cpp
index 34c220e4a..5a6a844cc 100644
--- a/code/components/wlan_ctrl/improvWifiProvisioning.cpp
+++ b/code/components/wlan_ctrl/improvWifiProvisioning.cpp
@@ -52,33 +52,25 @@ static void improvEventHandler(void)
uart_event_t event;
if (xQueueReceive(uartQueueHandle, (void *)&event, (TickType_t)portMAX_DELAY) == pdPASS) {
- // ESP_LOGD(TAG, "uart[%d] event:", DEFAULT_UART_NUM);
switch (event.type) {
- // UART receving data
- case UART_DATA:
+ case UART_DATA: // UART receving data
bzero(evtData, evtBufferSize);
uart_read_bytes(DEFAULT_UART_NUM, evtData, event.size, portMAX_DELAY);
improvWifi->handleSerial(evtData, event.size);
// LogFile.writeToFile(ESP_LOG_ERROR, TAG, "IMPROV UART RX: " + std::string((char *)evtData, event.size));
break;
- // HW FIFO overflow detected
- case UART_FIFO_OVF:
- // ESP_LOGD(TAG, "hw fifo overflow");
+ case UART_FIFO_OVF: // HW FIFO overflow detected
uart_flush_input(DEFAULT_UART_NUM);
xQueueReset(uartQueueHandle);
break;
- // Ring buffer full
- case UART_BUFFER_FULL:
- //ESP_LOGD(TAG, "ring buffer full");
+ case UART_BUFFER_FULL: // Ring buffer full
uart_flush_input(DEFAULT_UART_NUM);
xQueueReset(uartQueueHandle);
break;
- // Other events
- default:
- // ESP_LOGD(TAG, "uart event type: %d", event.type);
+ default: // Other events
break;
}
}
@@ -88,7 +80,7 @@ static void improvEventHandler(void)
if (readBytes > 0) {
improvWifi->handleSerial(evtData, readBytes);
ESP_LOGI(TAG, "Data received"); // Workaround: Do not remove, otherwise it's not working (@TODO, FIXME, tested ESP-IDF 5.2.1)
- //LogFile.writeToFile(ESP_LOG_ERROR, TAG, "IMPROV USB RX: " + std::string((char *)evtData, readBytes));
+ // LogFile.writeToFile(ESP_LOG_ERROR, TAG, "IMPROV USB RX: " + std::string((char *)evtData, readBytes));
bzero(evtData, evtBufferSize);
readBytes = 0;
}
@@ -133,11 +125,11 @@ void improvWifiScan(unsigned char *scanResponse, int bufLen, uint16_t *networkNu
wifi_mode_t wifiMode;
esp_wifi_get_mode(&wifiMode);
- if(wifiMode == WIFI_MODE_AP) {
- wifiDeinitAP();
+ if (wifiMode == WIFI_MODE_AP) {
+ stopAPForDeviceProvisioning();
vTaskDelay(pdMS_TO_TICKS(500));
- initWifiStation();
+ initWifiClient();
vTaskDelay(pdMS_TO_TICKS(500));
}
@@ -250,7 +242,7 @@ bool improvWifiConnect(const char *ssid, const char *password)
// Check connection state
timeoutCnt = 0;
- while (!getWIFIisConnected()) {
+ while (!getWifiIsConnected(true)) {
vTaskDelay(pdMS_TO_TICKS(1000));
if (timeoutCnt > 30) { // Timeout 30s
return false;
@@ -290,8 +282,8 @@ void improvInit(void)
improvWifi->setCustomConnectWiFi(improvWifiConnect);
improvWifi->setCustomScanWiFi(improvWifiScan);
- improvWifi->setCustomisConnected(getWIFIisConnected);
- improvWifi->setCustomGetLocalIpCallback(getIPAddress);
+ improvWifi->setCustomisConnected(getWifiIsConnected);
+ improvWifi->setCustomGetLocalIpCallback(getIpAddress);
#ifndef USB_SERIAL
// Install UART driver using an event queue
diff --git a/code/include/defines.h b/code/include/defines.h
index 786c63705..f84006b09 100644
--- a/code/include/defines.h
+++ b/code/include/defines.h
@@ -29,19 +29,6 @@
#endif
-
-// Access point for initial setup (Default: enabled)
-#ifndef ENV_DISABLE_SOFTAP // Disable module by build_flag in platformio.ini
- #ifndef ENABLE_SOFTAP
- #define ENABLE_SOFTAP
- #endif
-#else
- // If disabled, set CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n in sdkconfig.defaults to save 28k of flash
- #define CONFIG_ESP_WIFI_SOFTAP_SUPPORT 0
-#endif
-
-
-
//**************************************************************************************
// GLOABL DEBUG FLAGS
//**************************************************************************************
@@ -184,6 +171,9 @@
// connect_wlan.cpp
//******************************
+#define WLAN_CONNECTION_RETRIES_INITIAL_CONNECT 5
+#define WLAN_CONNECTION_RETRIES_ERROR_MSG 10
+
/* WIFI roaming functionalities 802.11k+v (uses ca. 6kB - 8kB internal RAM; if SCAN CACHE activated: + 1kB / beacon)
PLEASE BE AWARE: The following CONFIG parameters have to to be set in
sdkconfig.defaults before use of this function is possible!!
@@ -260,16 +250,6 @@ CONFIG_WPA_11R_SUPPORT=n
// Process state misc
#define FLOWSTATE_ERROR_DEVIATION_IN_ROW_LIMIT 3
-
-// SoftAP for initial setup process
-#ifdef ENABLE_SOFTAP
- #define AP_ESP_WIFI_SSID "AI-on-the-Edge"
- #define AP_ESP_WIFI_PASS ""
- #define AP_ESP_WIFI_CHANNEL 11
- #define AP_MAX_STA_CONN 1
-#endif // ENABLE_SOFTAP
-
-
// Global flashlight definitions
#define FLASHLIGHT_DEFAULT_LEDC_TIMER LEDC_TIMER_1
#define FLASHLIGHT_DEFAULT_LEDC_CHANNEL LEDC_CHANNEL_1
diff --git a/code/main/main.cpp b/code/main/main.cpp
index df0c5d7d8..ee8bf30b8 100644
--- a/code/main/main.cpp
+++ b/code/main/main.cpp
@@ -36,10 +36,7 @@
#endif //ENABLE_MQTT
#include "openmetrics.h"
-
-#ifdef ENABLE_SOFTAP
- #include "softAP.h"
-#endif //ENABLE_SOFTAP
+#include "softAP.h"
static const char *TAG = "MAIN";
@@ -71,7 +68,7 @@ extern "C" void app_main(void)
// ********************************************
// Highlight start of app_main
// ********************************************
- ESP_LOGI(TAG, "================ Start app_main =================");
+ ESP_LOGI(TAG, "========= Start app_main ==========");
// Init NVS flash
// ********************************************
@@ -95,9 +92,9 @@ extern "C" void app_main(void)
// 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, "=================================================");
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "===================================");
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "============== Start ==============");
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "===================================");
// SD card: Create further mandatory directories (if not already existing)
// Correct creation of these folders will be checked with function "checkSdCardFolderFilePresence"
@@ -130,15 +127,15 @@ extern "C" void app_main(void)
// ********************************************
esp_netif_init();
- // Init improv service
+ // Init improv service for device provisioning via serial / USB interface
// ********************************************
improvInit();
- // Check for missing configuration
+ // Start access point for device provisioning if mandatory content / config is missing
+ // Missing HTML content: html/index.html
+ // Missing config: Empty SSID in config/config.json
// ********************************************
- #ifdef ENABLE_SOFTAP
- checkStartAPMode();
- #endif
+ startAPForDeviceProvisioning();
// SD card: basic R/W check
// ********************************************
@@ -204,12 +201,12 @@ extern "C" void app_main(void)
// ********************************************
initTime();
- // Init WIFI service
+ // Init WLAN connection (init client, access point or none depending on configuration)
// ********************************************
- LogFile.writeToFile(ESP_LOG_INFO, TAG, "Init WIFI service");
- esp_err_t retVal = initWifiStation();
+ LogFile.writeToFile(ESP_LOG_INFO, TAG, "Init WLAN network");
+ esp_err_t retVal = initWifi();
if (retVal != ESP_OK) {
- LogFile.writeToFile(ESP_LOG_ERROR, TAG, "WIFI init failed. Device init aborted");
+ LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Init WLAN network failed. Device init aborted");
setStatusLed(WLAN_INIT, 1, true);
return;
}
diff --git a/code/platformio.ini b/code/platformio.ini
index 9742745e6..5cacb9606 100644
--- a/code/platformio.ini
+++ b/code/platformio.ini
@@ -66,7 +66,6 @@ build_flags =
; ### Software modules: Uncomment to disable
;-D ENV_DISABLE_MQTT
;-D ENV_DISABLE_INFLUXDB
- ;-D ENV_DISABLE_SOFTAP
;-D ENV_DISABLE_WEBHOOK
board_build.partitions = partitions.csv
monitor_speed = 115200
@@ -114,7 +113,6 @@ build_flags =
; ### Software modules: Uncomment to disable
;-D ENV_DISABLE_MQTT
;-D ENV_DISABLE_INFLUXDB
- ;-D ENV_DISABLE_SOFTAP
;-D ENV_DISABLE_WEBHOOK
board_build.partitions = partitions.csv
monitor_speed = 115200
diff --git a/code/sdkconfig.defaults b/code/sdkconfig.defaults
index 9014a4a15..2bdfe3e69 100644
--- a/code/sdkconfig.defaults
+++ b/code/sdkconfig.defaults
@@ -128,8 +128,6 @@ CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM=16
#CONFIG_WPA_MBO_SUPPORT=n
#CONFIG_WPA_11R_SUPPORT=n // Will be supported with ESP-IDF v5.0
#CONFIG_WPA_DEBUG_PRINT=n
-
-# If ENABLE_SOFTAP = disabled, set this to "n" to save 28k of flash
CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y
diff --git a/code/test/components/config_handling/config_json_default_expected.txt b/code/test/components/config_handling/config_json_default_expected.txt
index e96678284..154e34c02 100644
--- a/code/test/components/config_handling/config_json_default_expected.txt
+++ b/code/test/components/config_handling/config_json_default_expected.txt
@@ -321,6 +321,8 @@ Modify JSON elements accordingly to test lower limits and stringfy as compact ve
}
},
"network": {
+ "opmode": 0,
+ "timedoffdelay": 60,
"wlan": {
"ssid": "",
"password": "",
@@ -337,6 +339,14 @@ Modify JSON elements accordingly to test lower limits and stringfy as compact ve
"rssithreshold": -75
}
},
+ "wlanap": {
+ "ssid": "AI-on-the-Edge Device",
+ "password": "",
+ "channel": 11,
+ "ipv4": {
+ "ipaddress": "192.168.4.1"
+ }
+ },
"time": {
"timezone": "CET-1CEST,M3.5.0,M10.5.0/3",
"ntp": {
diff --git a/code/test/components/config_handling/config_json_high_limit.txt b/code/test/components/config_handling/config_json_high_limit.txt
deleted file mode 100644
index f6a3bb7e4..000000000
--- a/code/test/components/config_handling/config_json_high_limit.txt
+++ /dev/null
@@ -1,364 +0,0 @@
-Modify JSON elements accordingly to test lower limits and stringfy as compact version: https://jsonformatter.org/json-stringify-online
-
-{
- "config": {
- "version": 3,
- "lastmodified": ""
- },
- "operationmode": {
- "opmode": 2,
- "automaticprocessinterval": "1.0",
- "usedemoimages": false
- },
- "takeimage": {
- "flashlight": {
- "flashtime": 2000,
- "flashintensity": 101
- },
- "camera": {
- "camerafrequency": 21,
- "imagequality": 64,
- "imagesize": "VGA",
- "brightness": 3,
- "contrast": 3,
- "saturation": 3,
- "sharpness": 4,
- "exposurecontrolmode": 2,
- "autoexposurelevel": 5,
- "manualexposurevalue": 1300,
- "gaincontrolmode": 2,
- "manualgainvalue": 1500,
- "specialeffect": 10,
- "mirrorimage": false,
- "flipimage": false,
- "zoommode": 4,
- "zoomoffsetx": 1000,
- "zoomoffsety": 1000
- },
- "debug": {
- "saverawimages": false,
- "rawimageslocation": "/log/source",
- "rawimagesretention": 3
- }
- },
- "imagealignment": {
- "alignmentalgo": 5,
- "searchfield": {
- "x": 20,
- "y": 20
- },
- "imagerotation": "189.9",
- "flipimagesize": false,
- "marker": [
- {
- "x": 1,
- "y": 1
- },
- {
- "x": 1,
- "y": 1
- }
- ],
- "debug": {
- "savedebuginfo": false
- }
- },
- "numbersequences": {
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main"
- }
- ]
- },
- "digit": {
- "enabled": true,
- "model": "dig-class100_0173_s2_q.tflite",
- "cnngoodthreshold": "1.10",
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "roi": []
- }
- ],
- "debug": {
- "saveroiimages": false,
- "roiimageslocation": "/log/digit",
- "roiimagesretention": 3
- }
- },
- "analog": {
- "enabled": true,
- "model": "ana-class100_0171_s1_q.tflite",
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "roi": []
- }
- ],
- "debug": {
- "saveroiimages": false,
- "roiimageslocation": "/log/analog",
- "roiimagesretention": 3
- }
- },
- "postprocessing": {
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "decimalshift": 10,
- "analogdigitsyncvalue": "10.0",
- "extendedresolution": true,
- "ignoreleadingnan": false,
- "checkdigitincreaseconsistency": false,
- "maxratechecktype": 4,
- "maxrate": "0.150",
- "allownegativerate": false,
- "usefallbackvalue": true,
- "fallbackvalueagestartup": 720
- }
- ],
- "debug": {
- "savedebuginfo": false
- }
- },
- "mqtt": {
- "enabled": false,
- "uri": "",
- "maintopic": "watermeter",
- "clientid": "watermeter",
- "authmode": 3,
- "username": "",
- "password": "",
- "tls": {
- "cacert": "",
- "clientcert": "",
- "clientkey": ""
- },
- "processdatanotation": 3,
- "retainprocessdata": false,
- "homeassistant": {
- "discoveryenabled": false,
- "discoveryprefix": "homeassistant",
- "statustopic": "homeassistant/status",
- "metertype": 12,
- "retaindiscovery": false
- }
- },
- "influxdbv1": {
- "enabled": false,
- "uri": "",
- "database": "",
- "authmode": 3,
- "username": "",
- "password": "",
- "tls": {
- "cacert": "",
- "clientcert": "",
- "clientkey": ""
- },
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "measurementname": "",
- "fieldkey1": ""
- }
- ]
- },
- "influxdbv2": {
- "enabled": false,
- "uri": "",
- "bucket": "",
- "organization": "",
- "authmode": 3,
- "token": "",
- "tls": {
- "cacert": "",
- "clientcert": "",
- "clientkey": ""
- },
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "measurementname": "",
- "fieldkey1": ""
- }
- ]
- },
- "webhook": {
- "enabled": false,
- "uri": "",
- "apikey": "",
- "publishimage": 3,
- "authmode": 3,
- "username": "",
- "password": "",
- "tls": {
- "cacert": "",
- "clientcert": "",
- "clientkey": ""
- }
- },
- "gpio": {
- "customizationenabled": false,
- "gpiopin": [
- {
- "gpionumber": 1,
- "gpiousage": "restricted: uart0-tx",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 5001,
- "pwmfrequency": 1000001,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 8,
- "quantity": 0,
- "colorredchannel": 256,
- "colorgreenchannel": 256,
- "colorbluechannel": 256
- },
- "intensitycorrectionfactor": 101
- },
- {
- "gpionumber": 3,
- "gpiousage": "restricted: uart0-rx",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 4,
- "gpiousage": "flashlight-pwm",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "flashlight-default",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 12,
- "gpiousage": "spare",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 13,
- "gpiousage": "spare",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- }
- ]
- },
- "log": {
- "debug": {
- "loglevel": 5,
- "logfilesretention": 5,
- "debugfilesretention": 5
- },
- "data": {
- "enabled": false,
- "datafilesretention": 30
- }
- },
- "network": {
- "wlan": {
- "ssid": "",
- "password": "",
- "hostname": "watermeter",
- "ipv4": {
- "networkconfig": 2,
- "ipaddress": "",
- "subnetmask": "",
- "gatewayaddress": "",
- "dnsserver": ""
- },
- "wlanroaming": {
- "enabled": false,
- "rssithreshold": 1
- }
- },
- "time": {
- "timezone": "CET-1CEST,M3.5.0,M10.5.0/3",
- "ntp": {
- "timesyncenabled": true,
- "timeserver": "",
- "processstartinterlock": true
- }
- }
- },
- "system": {
- "cpufrequency": 241
- },
- "webui": {
- "autorefresh": {
- "overviewpage": {
- "enabled": true,
- "refreshtime": 5
- },
- "datagraphpage": {
- "enabled": false,
- "refreshtime": 60
- }
- }
- }
-}
\ No newline at end of file
diff --git a/code/test/components/config_handling/config_json_high_limit_expected.txt b/code/test/components/config_handling/config_json_high_limit_expected.txt
deleted file mode 100644
index e9dccba30..000000000
--- a/code/test/components/config_handling/config_json_high_limit_expected.txt
+++ /dev/null
@@ -1,364 +0,0 @@
-Modify JSON elements accordingly to test lower limits and stringfy as compact version: https://jsonformatter.org/json-stringify-online
-
-{
- "config": {
- "version": 3,
- "lastmodified": ""
- },
- "operationmode": {
- "opmode": 1,
- "automaticprocessinterval": "1.0",
- "usedemoimages": false
- },
- "takeimage": {
- "flashlight": {
- "flashtime": 2000,
- "flashintensity": 100
- },
- "camera": {
- "camerafrequency": 20,
- "imagequality": 63,
- "imagesize": "VGA",
- "brightness": 2,
- "contrast": 2,
- "saturation": 2,
- "sharpness": 3,
- "exposurecontrolmode": 2,
- "autoexposurelevel": 2,
- "manualexposurevalue": 1200,
- "gaincontrolmode": 1,
- "manualgainvalue": 5,
- "specialeffect": 7,
- "mirrorimage": false,
- "flipimage": false,
- "zoommode": 2,
- "zoomoffsetx": 960,
- "zoomoffsety": 720
- },
- "debug": {
- "saverawimages": false,
- "rawimageslocation": "/log/source",
- "rawimagesretention": 3
- }
- },
- "imagealignment": {
- "alignmentalgo": 4,
- "searchfield": {
- "x": 20,
- "y": 20
- },
- "imagerotation": "180.0",
- "flipimagesize": false,
- "marker": [
- {
- "x": 1,
- "y": 1
- },
- {
- "x": 1,
- "y": 1
- }
- ],
- "debug": {
- "savedebuginfo": false
- }
- },
- "numbersequences": {
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main"
- }
- ]
- },
- "digit": {
- "enabled": true,
- "model": "dig-class100_0173_s2_q.tflite",
- "cnngoodthreshold": "1.00",
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "roi": []
- }
- ],
- "debug": {
- "saveroiimages": false,
- "roiimageslocation": "/log/digit",
- "roiimagesretention": 3
- }
- },
- "analog": {
- "enabled": true,
- "model": "ana-class100_0171_s1_q.tflite",
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "roi": []
- }
- ],
- "debug": {
- "saveroiimages": false,
- "roiimageslocation": "/log/analog",
- "roiimagesretention": 3
- }
- },
- "postprocessing": {
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "decimalshift": 9,
- "analogdigitsyncvalue": "9.9",
- "extendedresolution": true,
- "ignoreleadingnan": false,
- "checkdigitincreaseconsistency": false,
- "maxratechecktype": 2,
- "maxrate": "0.150",
- "allownegativerate": false,
- "usefallbackvalue": true,
- "fallbackvalueagestartup": 720
- }
- ],
- "debug": {
- "savedebuginfo": false
- }
- },
- "mqtt": {
- "enabled": false,
- "uri": "",
- "maintopic": "watermeter",
- "clientid": "watermeter",
- "authmode": 2,
- "username": "",
- "password": "",
- "tls": {
- "cacert": "",
- "clientcert": "",
- "clientkey": ""
- },
- "processdatanotation": 2,
- "retainprocessdata": false,
- "homeassistant": {
- "discoveryenabled": false,
- "discoveryprefix": "homeassistant",
- "statustopic": "homeassistant/status",
- "metertype": 10,
- "retaindiscovery": false
- }
- },
- "influxdbv1": {
- "enabled": false,
- "uri": "",
- "database": "",
- "authmode": 2,
- "username": "",
- "password": "",
- "tls": {
- "cacert": "",
- "clientcert": "",
- "clientkey": ""
- },
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "measurementname": "",
- "fieldkey1": ""
- }
- ]
- },
- "influxdbv2": {
- "enabled": false,
- "uri": "",
- "bucket": "",
- "organization": "",
- "authmode": 2,
- "token": "",
- "tls": {
- "cacert": "",
- "clientcert": "",
- "clientkey": ""
- },
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "measurementname": "",
- "fieldkey1": ""
- }
- ]
- },
- "webhook": {
- "enabled": false,
- "uri": "",
- "apikey": "",
- "publishimage": 2,
- "authmode": 2,
- "username": "",
- "password": "",
- "tls": {
- "cacert": "",
- "clientcert": "",
- "clientkey": ""
- }
- },
- "gpio": {
- "customizationenabled": false,
- "gpiopin": [
- {
- "gpionumber": 1,
- "gpiousage": "restricted: uart0-tx",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 5000,
- "pwmfrequency": 1000000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 5,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 3,
- "gpiousage": "restricted: uart0-rx",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 4,
- "gpiousage": "flashlight-pwm",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "flashlight-default",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 12,
- "gpiousage": "spare",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 13,
- "gpiousage": "spare",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- }
- ]
- },
- "log": {
- "debug": {
- "loglevel": 4,
- "logfilesretention": 5,
- "debugfilesretention": 5
- },
- "data": {
- "enabled": false,
- "datafilesretention": 30
- }
- },
- "network": {
- "wlan": {
- "ssid": "",
- "password": "",
- "hostname": "watermeter",
- "ipv4": {
- "networkconfig": 0,
- "ipaddress": "",
- "subnetmask": "",
- "gatewayaddress": "",
- "dnsserver": ""
- },
- "wlanroaming": {
- "enabled": false,
- "rssithreshold": 0
- }
- },
- "time": {
- "timezone": "CET-1CEST,M3.5.0,M10.5.0/3",
- "ntp": {
- "timesyncenabled": true,
- "timeserver": "",
- "processstartinterlock": true
- }
- }
- },
- "system": {
- "cpufrequency": 240
- },
- "webui": {
- "autorefresh": {
- "overviewpage": {
- "enabled": true,
- "refreshtime": 5
- },
- "datagraphpage": {
- "enabled": false,
- "refreshtime": 60
- }
- }
- }
-}
\ No newline at end of file
diff --git a/code/test/components/config_handling/config_json_low_limit.txt b/code/test/components/config_handling/config_json_low_limit.txt
deleted file mode 100644
index 64636176d..000000000
--- a/code/test/components/config_handling/config_json_low_limit.txt
+++ /dev/null
@@ -1,364 +0,0 @@
-Modify JSON elements accordingly to test lower limits and stringfy as compact version: https://jsonformatter.org/json-stringify-online
-
-{
- "config": {
- "version": 3,
- "lastmodified": ""
- },
- "operationmode": {
- "opmode": -2,
- "automaticprocessinterval": "-1.0",
- "usedemoimages": false
- },
- "takeimage": {
- "flashlight": {
- "flashtime": -100,
- "flashintensity": -1
- },
- "camera": {
- "camerafrequency": -20,
- "imagequality": -12,
- "imagesize": "VGA",
- "brightness": -3,
- "contrast": -3,
- "saturation": -3,
- "sharpness": -5,
- "exposurecontrolmode": -1,
- "autoexposurelevel": -3,
- "manualexposurevalue": -1,
- "gaincontrolmode": -1,
- "manualgainvalue": -1,
- "specialeffect": -1,
- "mirrorimage": false,
- "flipimage": false,
- "zoommode": -1,
- "zoomoffsetx": -1,
- "zoomoffsety": -1
- },
- "debug": {
- "saverawimages": false,
- "rawimageslocation": "/log/source",
- "rawimagesretention": -3
- }
- },
- "imagealignment": {
- "alignmentalgo": -1,
- "searchfield": {
- "x": -20,
- "y": -20
- },
- "imagerotation": "-189.9",
- "flipimagesize": false,
- "marker": [
- {
- "x": 0,
- "y": 0
- },
- {
- "x": -1,
- "y": -1
- }
- ],
- "debug": {
- "savedebuginfo": false
- }
- },
- "numbersequences": {
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main"
- }
- ]
- },
- "digit": {
- "enabled": true,
- "model": "dig-class100_0173_s2_q.tflite",
- "cnngoodthreshold": "-0.10",
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "roi": []
- }
- ],
- "debug": {
- "saveroiimages": false,
- "roiimageslocation": "/log/digit",
- "roiimagesretention": -3
- }
- },
- "analog": {
- "enabled": true,
- "model": "ana-class100_0171_s1_q.tflite",
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "roi": []
- }
- ],
- "debug": {
- "saveroiimages": false,
- "roiimageslocation": "/log/analog",
- "roiimagesretention": -3
- }
- },
- "postprocessing": {
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "decimalshift": -10,
- "analogdigitsyncvalue": "5.9",
- "extendedresolution": true,
- "ignoreleadingnan": false,
- "checkdigitincreaseconsistency": false,
- "maxratechecktype": -1,
- "maxrate": "0.000",
- "allownegativerate": false,
- "usefallbackvalue": true,
- "fallbackvalueagestartup": -1
- }
- ],
- "debug": {
- "savedebuginfo": false
- }
- },
- "mqtt": {
- "enabled": false,
- "uri": "",
- "maintopic": "watermeter",
- "clientid": "watermeter",
- "authmode": -1,
- "username": "",
- "password": "",
- "tls": {
- "cacert": "",
- "clientcert": "",
- "clientkey": ""
- },
- "processdatanotation": -1,
- "retainprocessdata": false,
- "homeassistant": {
- "discoveryenabled": false,
- "discoveryprefix": "homeassistant",
- "statustopic": "homeassistant/status",
- "metertype": -1,
- "retaindiscovery": false
- }
- },
- "influxdbv1": {
- "enabled": false,
- "uri": "",
- "database": "",
- "authmode": -1,
- "username": "",
- "password": "",
- "tls": {
- "cacert": "",
- "clientcert": "",
- "clientkey": ""
- },
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "measurementname": "",
- "fieldkey1": ""
- }
- ]
- },
- "influxdbv2": {
- "enabled": false,
- "uri": "",
- "bucket": "",
- "organization": "",
- "authmode": -1,
- "token": "",
- "tls": {
- "cacert": "",
- "clientcert": "",
- "clientkey": ""
- },
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "measurementname": "",
- "fieldkey1": ""
- }
- ]
- },
- "webhook": {
- "enabled": false,
- "uri": "",
- "apikey": "",
- "publishimage": -1,
- "authmode": -1,
- "username": "",
- "password": "",
- "tls": {
- "cacert": "",
- "clientcert": "",
- "clientkey": ""
- }
- },
- "gpio": {
- "customizationenabled": false,
- "gpiopin": [
- {
- "gpionumber": 1,
- "gpiousage": "restricted: uart0-tx",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": -1,
- "pwmfrequency": -1,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": -1,
- "quantity": 0,
- "colorredchannel": -1,
- "colorgreenchannel": -1,
- "colorbluechannel": -1
- },
- "intensitycorrectionfactor": -1
- },
- {
- "gpionumber": 3,
- "gpiousage": "restricted: uart0-rx",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 4,
- "gpiousage": "flashlight-pwm",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "flashlight-default",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 12,
- "gpiousage": "spare",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 13,
- "gpiousage": "spare",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- }
- ]
- },
- "log": {
- "debug": {
- "loglevel": -1,
- "logfilesretention": -1,
- "debugfilesretention": -1
- },
- "data": {
- "enabled": false,
- "datafilesretention": -1
- }
- },
- "network": {
- "wlan": {
- "ssid": "",
- "password": "",
- "hostname": "watermeter",
- "ipv4": {
- "networkconfig": -1,
- "ipaddress": "",
- "subnetmask": "",
- "gatewayaddress": "",
- "dnsserver": ""
- },
- "wlanroaming": {
- "enabled": false,
- "rssithreshold": -101
- }
- },
- "time": {
- "timezone": "CET-1CEST,M3.5.0,M10.5.0/3",
- "ntp": {
- "timesyncenabled": true,
- "timeserver": "",
- "processstartinterlock": true
- }
- }
- },
- "system": {
- "cpufrequency": 159
- },
- "webui": {
- "autorefresh": {
- "overviewpage": {
- "enabled": true,
- "refreshtime": -1
- },
- "datagraphpage": {
- "enabled": false,
- "refreshtime": -1
- }
- }
- }
-}
\ No newline at end of file
diff --git a/code/test/components/config_handling/config_json_low_limit_expected.txt b/code/test/components/config_handling/config_json_low_limit_expected.txt
deleted file mode 100644
index d473e9045..000000000
--- a/code/test/components/config_handling/config_json_low_limit_expected.txt
+++ /dev/null
@@ -1,364 +0,0 @@
-Modify JSON elements accordingly to test lower limits and stringfy as compact version: https://jsonformatter.org/json-stringify-online
-
-{
- "config": {
- "version": 3,
- "lastmodified": ""
- },
- "operationmode": {
- "opmode": -1,
- "automaticprocessinterval": "0.1",
- "usedemoimages": false
- },
- "takeimage": {
- "flashlight": {
- "flashtime": 100,
- "flashintensity": 0
- },
- "camera": {
- "camerafrequency": 5,
- "imagequality": 8,
- "imagesize": "VGA",
- "brightness": -2,
- "contrast": -2,
- "saturation": -2,
- "sharpness": -4,
- "exposurecontrolmode": 0,
- "autoexposurelevel": -2,
- "manualexposurevalue": 0,
- "gaincontrolmode": 0,
- "manualgainvalue": 0,
- "specialeffect": 0,
- "mirrorimage": false,
- "flipimage": false,
- "zoommode": 0,
- "zoomoffsetx": 0,
- "zoomoffsety": 0
- },
- "debug": {
- "saverawimages": false,
- "rawimageslocation": "/log/source",
- "rawimagesretention": 0
- }
- },
- "imagealignment": {
- "alignmentalgo": 0,
- "searchfield": {
- "x": 1,
- "y": 1
- },
- "imagerotation": "-180.0",
- "flipimagesize": false,
- "marker": [
- {
- "x": 1,
- "y": 1
- },
- {
- "x": 1,
- "y": 1
- }
- ],
- "debug": {
- "savedebuginfo": false
- }
- },
- "numbersequences": {
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main"
- }
- ]
- },
- "digit": {
- "enabled": true,
- "model": "dig-class100_0173_s2_q.tflite",
- "cnngoodthreshold": "0.00",
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "roi": []
- }
- ],
- "debug": {
- "saveroiimages": false,
- "roiimageslocation": "/log/digit",
- "roiimagesretention": 0
- }
- },
- "analog": {
- "enabled": true,
- "model": "ana-class100_0171_s1_q.tflite",
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "roi": []
- }
- ],
- "debug": {
- "saveroiimages": false,
- "roiimageslocation": "/log/analog",
- "roiimagesretention": 0
- }
- },
- "postprocessing": {
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "decimalshift": -9,
- "analogdigitsyncvalue": "6.0",
- "extendedresolution": true,
- "ignoreleadingnan": false,
- "checkdigitincreaseconsistency": false,
- "maxratechecktype": 0,
- "maxrate": "0.001",
- "allownegativerate": false,
- "usefallbackvalue": true,
- "fallbackvalueagestartup": 0
- }
- ],
- "debug": {
- "savedebuginfo": false
- }
- },
- "mqtt": {
- "enabled": false,
- "uri": "",
- "maintopic": "watermeter",
- "clientid": "watermeter",
- "authmode": 0,
- "username": "",
- "password": "",
- "tls": {
- "cacert": "",
- "clientcert": "",
- "clientkey": ""
- },
- "processdatanotation": 0,
- "retainprocessdata": false,
- "homeassistant": {
- "discoveryenabled": false,
- "discoveryprefix": "homeassistant",
- "statustopic": "homeassistant/status",
- "metertype": 0,
- "retaindiscovery": false
- }
- },
- "influxdbv1": {
- "enabled": false,
- "uri": "",
- "database": "",
- "authmode": 0,
- "username": "",
- "password": "",
- "tls": {
- "cacert": "",
- "clientcert": "",
- "clientkey": ""
- },
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "measurementname": "",
- "fieldkey1": ""
- }
- ]
- },
- "influxdbv2": {
- "enabled": false,
- "uri": "",
- "bucket": "",
- "organization": "",
- "authmode": 1,
- "token": "",
- "tls": {
- "cacert": "",
- "clientcert": "",
- "clientkey": ""
- },
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "measurementname": "",
- "fieldkey1": ""
- }
- ]
- },
- "webhook": {
- "enabled": false,
- "uri": "",
- "apikey": "",
- "publishimage": 0,
- "authmode": 0,
- "username": "",
- "password": "",
- "tls": {
- "cacert": "",
- "clientcert": "",
- "clientkey": ""
- }
- },
- "gpio": {
- "customizationenabled": false,
- "gpiopin": [
- {
- "gpionumber": 1,
- "gpiousage": "restricted: uart0-tx",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 0,
- "pwmfrequency": 5,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 0,
- "colorgreenchannel": 0,
- "colorbluechannel": 0
- },
- "intensitycorrectionfactor": 1
- },
- {
- "gpionumber": 3,
- "gpiousage": "restricted: uart0-rx",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 4,
- "gpiousage": "flashlight-pwm",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "flashlight-default",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 12,
- "gpiousage": "spare",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 13,
- "gpiousage": "spare",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- }
- ]
- },
- "log": {
- "debug": {
- "loglevel": 1,
- "logfilesretention": 0,
- "debugfilesretention": 0
- },
- "data": {
- "enabled": false,
- "datafilesretention": 0
- }
- },
- "network": {
- "wlan": {
- "ssid": "",
- "password": "",
- "hostname": "watermeter",
- "ipv4": {
- "networkconfig": 0,
- "ipaddress": "",
- "subnetmask": "",
- "gatewayaddress": "",
- "dnsserver": ""
- },
- "wlanroaming": {
- "enabled": false,
- "rssithreshold": -100
- }
- },
- "time": {
- "timezone": "CET-1CEST,M3.5.0,M10.5.0/3",
- "ntp": {
- "timesyncenabled": true,
- "timeserver": "",
- "processstartinterlock": true
- }
- }
- },
- "system": {
- "cpufrequency": 160
- },
- "webui": {
- "autorefresh": {
- "overviewpage": {
- "enabled": true,
- "refreshtime": 1
- },
- "datagraphpage": {
- "enabled": false,
- "refreshtime": 1
- }
- }
- }
-}
\ No newline at end of file
diff --git a/code/test/components/config_handling/config_json_special.txt b/code/test/components/config_handling/config_json_special.txt
deleted file mode 100644
index bafddbb20..000000000
--- a/code/test/components/config_handling/config_json_special.txt
+++ /dev/null
@@ -1,364 +0,0 @@
-Modify JSON elements accordingly to test lower limits and stringfy as compact version: https://jsonformatter.org/json-stringify-online
-
-{
- "config": {
- "version": 3,
- "lastmodified": ""
- },
- "operationmode": {
- "opmode": -1,
- "automaticprocessinterval": "1.0",
- "usedemoimages": false
- },
- "takeimage": {
- "flashlight": {
- "flashtime": 2000,
- "flashintensity": 50
- },
- "camera": {
- "camerafrequency": 20,
- "imagequality": 12,
- "imagesize": "VGA",
- "brightness": 0,
- "contrast": 0,
- "saturation": 0,
- "sharpness": 0,
- "exposurecontrolmode": 1,
- "autoexposurelevel": 0,
- "manualexposurevalue": 300,
- "gaincontrolmode": 1,
- "manualgainvalue": 0,
- "specialeffect": 0,
- "mirrorimage": false,
- "flipimage": false,
- "zoommode": 0,
- "zoomoffsetx": 0,
- "zoomoffsety": 0
- },
- "debug": {
- "saverawimages": false,
- "rawimageslocation": "/log/source/",
- "rawimagesretention": 3
- }
- },
- "imagealignment": {
- "alignmentalgo": 0,
- "searchfield": {
- "x": 20,
- "y": 20
- },
- "imagerotation": "0.0",
- "flipimagesize": false,
- "marker": [
- {
- "x": 1,
- "y": 1
- },
- {
- "x": 1,
- "y": 1
- }
- ],
- "debug": {
- "savedebuginfo": false
- }
- },
- "numbersequences": {
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main"
- }
- ]
- },
- "digit": {
- "enabled": true,
- "model": "dig-class100_0173_s2_q.tflite",
- "cnngoodthreshold": "0.00",
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "roi": []
- }
- ],
- "debug": {
- "saveroiimages": false,
- "roiimageslocation": "/log/digit/",
- "roiimagesretention": 3
- }
- },
- "analog": {
- "enabled": true,
- "model": "ana-class100_0171_s1_q.tflite",
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "roi": []
- }
- ],
- "debug": {
- "saveroiimages": false,
- "roiimageslocation": "/log/analog/",
- "roiimagesretention": 3
- }
- },
- "postprocessing": {
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "decimalshift": 0,
- "analogdigitsyncvalue": "9.2",
- "extendedresolution": true,
- "ignoreleadingnan": false,
- "checkdigitincreaseconsistency": false,
- "maxratechecktype": 1,
- "maxrate": "0.150",
- "allownegativerate": false,
- "usefallbackvalue": true,
- "fallbackvalueagestartup": 720
- }
- ],
- "debug": {
- "savedebuginfo": false
- }
- },
- "mqtt": {
- "enabled": false,
- "uri": "",
- "maintopic": "/watermeter/",
- "clientid": "123456789012345678901234",
- "authmode": 0,
- "username": "",
- "password": "",
- "tls": {
- "cacert": "/ca.crt/",
- "clientcert": "/client.crt/",
- "clientkey": "/client.key/"
- },
- "processdatanotation": 0,
- "retainprocessdata": false,
- "homeassistant": {
- "discoveryenabled": false,
- "discoveryprefix": "/homeassistant/",
- "statustopic": "/homeassistant/status/",
- "metertype": 1,
- "retaindiscovery": false
- }
- },
- "influxdbv1": {
- "enabled": false,
- "uri": "",
- "database": "",
- "authmode": 0,
- "username": "",
- "password": "",
- "tls": {
- "cacert": "/ca.crt/",
- "clientcert": "/client.crt/",
- "clientkey": "/client.key/"
- },
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "measurementname": "/test/",
- "fieldkey1": "/test/"
- }
- ]
- },
- "influxdbv2": {
- "enabled": false,
- "uri": "",
- "bucket": "",
- "organization": "",
- "authmode": 1,
- "token": "",
- "tls": {
- "cacert": "/ca.crt/",
- "clientcert": "/client.crt/",
- "clientkey": "/client.key/"
- },
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "measurementname": "/test/",
- "fieldkey1": "/test/"
- }
- ]
- },
- "webhook": {
- "enabled": false,
- "uri": "",
- "apikey": "",
- "publishimage": 0,
- "authmode": 0,
- "username": "",
- "password": "",
- "tls": {
- "cacert": "",
- "clientcert": "",
- "clientkey": ""
- }
- },
- "gpio": {
- "customizationenabled": false,
- "gpiopin": [
- {
- "gpionumber": 1,
- "gpiousage": "restricted: uart0-tx",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 3,
- "gpiousage": "restricted: uart0-rx",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 4,
- "gpiousage": "flashlight-pwm",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "flashlight-default",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 12,
- "gpiousage": "spare",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 13,
- "gpiousage": "spare",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- }
- ]
- },
- "log": {
- "debug": {
- "loglevel": 2,
- "logfilesretention": 5,
- "debugfilesretention": 5
- },
- "data": {
- "enabled": false,
- "datafilesretention": 30
- }
- },
- "network": {
- "wlan": {
- "ssid": "",
- "password": "",
- "hostname": "watermeter",
- "ipv4": {
- "networkconfig": 0,
- "ipaddress": "",
- "subnetmask": "",
- "gatewayaddress": "",
- "dnsserver": ""
- },
- "wlanroaming": {
- "enabled": false,
- "rssithreshold": -75
- }
- },
- "time": {
- "timezone": "CET-1CEST,M3.5.0,M10.5.0/3",
- "ntp": {
- "timesyncenabled": true,
- "timeserver": "",
- "processstartinterlock": true
- }
- }
- },
- "system": {
- "cpufrequency": 160
- },
- "webui": {
- "autorefresh": {
- "overviewpage": {
- "enabled": true,
- "refreshtime": 5
- },
- "datagraphpage": {
- "enabled": false,
- "refreshtime": 60
- }
- }
- }
-}
\ No newline at end of file
diff --git a/code/test/components/config_handling/config_json_special_expected.txt b/code/test/components/config_handling/config_json_special_expected.txt
deleted file mode 100644
index 1f76f7f95..000000000
--- a/code/test/components/config_handling/config_json_special_expected.txt
+++ /dev/null
@@ -1,364 +0,0 @@
-Modify JSON elements accordingly to test lower limits and stringfy as compact version: https://jsonformatter.org/json-stringify-online
-
-{
- "config": {
- "version": 3,
- "lastmodified": ""
- },
- "operationmode": {
- "opmode": -1,
- "automaticprocessinterval": "1.0",
- "usedemoimages": false
- },
- "takeimage": {
- "flashlight": {
- "flashtime": 2000,
- "flashintensity": 50
- },
- "camera": {
- "camerafrequency": 20,
- "imagequality": 12,
- "imagesize": "VGA",
- "brightness": 0,
- "contrast": 0,
- "saturation": 0,
- "sharpness": 0,
- "exposurecontrolmode": 1,
- "autoexposurelevel": 0,
- "manualexposurevalue": 300,
- "gaincontrolmode": 1,
- "manualgainvalue": 0,
- "specialeffect": 0,
- "mirrorimage": false,
- "flipimage": false,
- "zoommode": 0,
- "zoomoffsetx": 0,
- "zoomoffsety": 0
- },
- "debug": {
- "saverawimages": false,
- "rawimageslocation": "/log/source",
- "rawimagesretention": 3
- }
- },
- "imagealignment": {
- "alignmentalgo": 0,
- "searchfield": {
- "x": 20,
- "y": 20
- },
- "imagerotation": "0.0",
- "flipimagesize": false,
- "marker": [
- {
- "x": 1,
- "y": 1
- },
- {
- "x": 1,
- "y": 1
- }
- ],
- "debug": {
- "savedebuginfo": false
- }
- },
- "numbersequences": {
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main"
- }
- ]
- },
- "digit": {
- "enabled": true,
- "model": "dig-class100_0173_s2_q.tflite",
- "cnngoodthreshold": "0.00",
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "roi": []
- }
- ],
- "debug": {
- "saveroiimages": false,
- "roiimageslocation": "/log/digit",
- "roiimagesretention": 3
- }
- },
- "analog": {
- "enabled": true,
- "model": "ana-class100_0171_s1_q.tflite",
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "roi": []
- }
- ],
- "debug": {
- "saveroiimages": false,
- "roiimageslocation": "/log/analog",
- "roiimagesretention": 3
- }
- },
- "postprocessing": {
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "decimalshift": 0,
- "analogdigitsyncvalue": "9.2",
- "extendedresolution": true,
- "ignoreleadingnan": false,
- "checkdigitincreaseconsistency": false,
- "maxratechecktype": 1,
- "maxrate": "0.150",
- "allownegativerate": false,
- "usefallbackvalue": true,
- "fallbackvalueagestartup": 720
- }
- ],
- "debug": {
- "savedebuginfo": false
- }
- },
- "mqtt": {
- "enabled": false,
- "uri": "",
- "maintopic": "watermeter",
- "clientid": "watermeter",
- "authmode": 0,
- "username": "",
- "password": "",
- "tls": {
- "cacert": "ca.crt",
- "clientcert": "client.crt",
- "clientkey": "client.key"
- },
- "processdatanotation": 0,
- "retainprocessdata": false,
- "homeassistant": {
- "discoveryenabled": false,
- "discoveryprefix": "homeassistant",
- "statustopic": "homeassistant/status",
- "metertype": 1,
- "retaindiscovery": false
- }
- },
- "influxdbv1": {
- "enabled": false,
- "uri": "",
- "database": "",
- "authmode": 0,
- "username": "",
- "password": "",
- "tls": {
- "cacert": "ca.crt",
- "clientcert": "client.crt",
- "clientkey": "client.key"
- },
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "measurementname": "test",
- "fieldkey1": "test"
- }
- ]
- },
- "influxdbv2": {
- "enabled": false,
- "uri": "",
- "bucket": "",
- "organization": "",
- "authmode": 1,
- "token": "",
- "tls": {
- "cacert": "ca.crt",
- "clientcert": "client.crt",
- "clientkey": "client.key"
- },
- "sequence": [
- {
- "sequenceid": 0,
- "sequencename": "main",
- "measurementname": "test",
- "fieldkey1": "test"
- }
- ]
- },
- "webhook": {
- "enabled": false,
- "uri": "",
- "apikey": "",
- "publishimage": 0,
- "authmode": 0,
- "username": "",
- "password": "",
- "tls": {
- "cacert": "",
- "clientcert": "",
- "clientkey": ""
- }
- },
- "gpio": {
- "customizationenabled": false,
- "gpiopin": [
- {
- "gpionumber": 1,
- "gpiousage": "restricted: uart0-tx",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 3,
- "gpiousage": "restricted: uart0-rx",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 4,
- "gpiousage": "flashlight-pwm",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "flashlight-default",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 12,
- "gpiousage": "spare",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- },
- {
- "gpionumber": 13,
- "gpiousage": "spare",
- "pinenabled": false,
- "pinname": "",
- "pinmode": "input",
- "capturemode": "cyclic-polling",
- "inputdebouncetime": 200,
- "pwmfrequency": 5000,
- "exposetomqtt": false,
- "exposetorest": false,
- "smartled": {
- "type": 0,
- "quantity": 1,
- "colorredchannel": 255,
- "colorgreenchannel": 255,
- "colorbluechannel": 255
- },
- "intensitycorrectionfactor": 100
- }
- ]
- },
- "log": {
- "debug": {
- "loglevel": 2,
- "logfilesretention": 5,
- "debugfilesretention": 5
- },
- "data": {
- "enabled": false,
- "datafilesretention": 30
- }
- },
- "network": {
- "wlan": {
- "ssid": "",
- "password": "",
- "hostname": "watermeter",
- "ipv4": {
- "networkconfig": 0,
- "ipaddress": "",
- "subnetmask": "",
- "gatewayaddress": "",
- "dnsserver": ""
- },
- "wlanroaming": {
- "enabled": false,
- "rssithreshold": -75
- }
- },
- "time": {
- "timezone": "CET-1CEST,M3.5.0,M10.5.0/3",
- "ntp": {
- "timesyncenabled": true,
- "timeserver": "",
- "processstartinterlock": true
- }
- }
- },
- "system": {
- "cpufrequency": 160
- },
- "webui": {
- "autorefresh": {
- "overviewpage": {
- "enabled": true,
- "refreshtime": 5
- },
- "datagraphpage": {
- "enabled": false,
- "refreshtime": 60
- }
- }
- }
-}
\ No newline at end of file
diff --git a/code/test/components/config_handling/test_configClass.cpp b/code/test/components/config_handling/test_configClass.cpp
index e4f3786d6..4d6133ecd 100644
--- a/code/test/components/config_handling/test_configClass.cpp
+++ b/code/test/components/config_handling/test_configClass.cpp
@@ -18,72 +18,21 @@ void test_configJsonParseAndSerialization()
*
* 2. Needs to be added to CMakeList.txt of component:
* EMBED_TXTFILES config_json_default_expected.txt
- * config_json_high_limit_expected.txt
- * config_json_high_limit.txt
- * config_json_low_limit_expected.txt
- * config_json_low_limit.txt
- * config_json_special_expected.txt
- * config_json_special.txt
*
* Workaround: Add content as string into code
// Embedded file: Default config
extern const char config_json_default_expected_start[] asm("_binary_config_json_default_expected_txt_start");
extern const char config_json_default_expected_end[] asm("_binary_config_json_default_expected_txt_end");
-
- // Embedded file: Config to check high limits
- extern const char config_json_high_limit_expected_start[] asm("_binary_config_json_high_limit_expected_txt_start");
- extern const char config_json_high_limit_expected_end[] asm("_binary_config_json_high_limit_expected_txt_end");
- extern const char config_json_high_limit_start[] asm("_binary_config_json_high_limit_txt_start");
- extern const char config_json_high_limit_end[] asm("_binary_config_json_high_limit_txt_end");
-
- // Embedded file: Config to check low limits
- extern const char config_json_low_limit_expected_start[] asm("_binary_config_json_low_limit_expected_txt_start");
- extern const char config_json_low_limit_expected_end[] asm("_binary_config_json_low_limit_expected_txt_end");
- extern const char config_json_low_limit_start[] asm("_binary_config_json_low_limit_txt_start");
- extern const char config_json_low_limit_end[] asm("_binary_config_json_low_limit_txt_end");
-
- // Embedded file: Config to check special validation handlings
- extern const char config_json_special_expected_start[] asm("_binary_ config_json_special_expected_txt_start");
- extern const char config_json_special_expected_end[] asm("_binary_ config_json_special_expected_txt_end");
- extern const char config_json_special_start[] asm("_binary_ config_json_special_txt_start");
- extern const char config_json_special_end[] asm("_binary_config_json_special_txt_end");
*/
// Check default values (ESP32CAM device)
ESP_LOGI(TAG_CFGTEST, "TEST 1: Check default values");
- std::string cfgDataExpexcted = "{\"config\":{\"version\":3,\"lastmodified\":\"\"},\"operationmode\":{\"opmode\":-1,\"automaticprocessinterval\":\"1.0\",\"usedemoimages\":false},\"takeimage\":{\"flashlight\":{\"flashtime\":2000,\"flashintensity\":50},\"camera\":{\"camerafrequency\":20,\"imagequality\":12,\"imagesize\":\"VGA\",\"brightness\":0,\"contrast\":0,\"saturation\":0,\"sharpness\":0,\"exposurecontrolmode\":1,\"autoexposurelevel\":0,\"manualexposurevalue\":300,\"gaincontrolmode\":1,\"manualgainvalue\":0,\"specialeffect\":0,\"mirrorimage\":false,\"flipimage\":false,\"zoommode\":0,\"zoomoffsetx\":0,\"zoomoffsety\":0},\"debug\":{\"saverawimages\":false,\"rawimageslocation\":\"/log/source\",\"rawimagesretention\":3}},\"imagealignment\":{\"alignmentalgo\":0,\"searchfield\":{\"x\":20,\"y\":20},\"imagerotation\":\"0.0\",\"flipimagesize\":false,\"marker\":[{\"x\":1,\"y\":1},{\"x\":1,\"y\":1}],\"debug\":{\"savedebuginfo\":false}},\"numbersequences\":{\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\"}]},\"digit\":{\"enabled\":true,\"model\":\"dig-class100_0173_s2_q.tflite\",\"cnngoodthreshold\":\"0.00\",\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"roi\":[]}],\"debug\":{\"saveroiimages\":false,\"roiimageslocation\":\"/log/digit\",\"roiimagesretention\":3}},\"analog\":{\"enabled\":true,\"model\":\"ana-class100_0171_s1_q.tflite\",\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"roi\":[]}],\"debug\":{\"saveroiimages\":false,\"roiimageslocation\":\"/log/analog\",\"roiimagesretention\":3}},\"postprocessing\":{\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"decimalshift\":0,\"analogdigitsyncvalue\":\"9.2\",\"extendedresolution\":true,\"ignoreleadingnan\":false,\"checkdigitincreaseconsistency\":false,\"maxratechecktype\":1,\"maxrate\":\"0.150\",\"allownegativerate\":false,\"usefallbackvalue\":true,\"fallbackvalueagestartup\":720}],\"debug\":{\"savedebuginfo\":false}},\"mqtt\":{\"enabled\":false,\"uri\":\"\",\"maintopic\":\"watermeter\",\"clientid\":\"watermeter\",\"authmode\":0,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"},\"processdatanotation\":0,\"retainprocessdata\":false,\"homeassistant\":{\"discoveryenabled\":false,\"discoveryprefix\":\"homeassistant\",\"statustopic\":\"homeassistant/status\",\"metertype\":1,\"retaindiscovery\":false}},\"influxdbv1\":{\"enabled\":false,\"uri\":\"\",\"database\":\"\",\"authmode\":0,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"},\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"measurementname\":\"\",\"fieldkey1\":\"\"}]},\"influxdbv2\":{\"enabled\":false,\"uri\":\"\",\"bucket\":\"\",\"organization\":\"\",\"authmode\":1,\"token\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"},\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"measurementname\":\"\",\"fieldkey1\":\"\"}]},\"webhook\":{\"enabled\":false,\"uri\":\"\",\"apikey\":\"\",\"publishimage\":0,\"authmode\":0,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"}},\"gpio\":{\"customizationenabled\":false,\"gpiopin\":[{\"gpionumber\":1,\"gpiousage\":\"restricted: uart0-tx\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":3,\"gpiousage\":\"restricted: uart0-rx\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":4,\"gpiousage\":\"flashlight-pwm\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"flashlight-default\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":12,\"gpiousage\":\"spare\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":13,\"gpiousage\":\"spare\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100}]},\"log\":{\"debug\":{\"loglevel\":2,\"logfilesretention\":5,\"debugfilesretention\":5},\"data\":{\"enabled\":false,\"datafilesretention\":30}},\"network\":{\"wlan\":{\"ssid\":\"\",\"password\":\"\",\"hostname\":\"watermeter\",\"ipv4\":{\"networkconfig\":0,\"ipaddress\":\"\",\"subnetmask\":\"\",\"gatewayaddress\":\"\",\"dnsserver\":\"\"},\"wlanroaming\":{\"enabled\":false,\"rssithreshold\":-75}},\"time\":{\"timezone\":\"CET-1CEST,M3.5.0,M10.5.0/3\",\"ntp\":{\"timesyncenabled\":true,\"timeserver\":\"\",\"processstartinterlock\":true}}},\"system\":{\"cpufrequency\":160},\"webui\":{\"autorefresh\":{\"overviewpage\":{\"enabled\":true,\"refreshtime\":5},\"datagraphpage\":{\"enabled\":false,\"refreshtime\":60}}}}";
+ std::string cfgDataExpexcted = "{\"config\":{\"version\":3,\"lastmodified\":\"\"},\"operationmode\":{\"opmode\":-1,\"automaticprocessinterval\":\"1.0\",\"usedemoimages\":false},\"takeimage\":{\"flashlight\":{\"flashtime\":2000,\"flashintensity\":50},\"camera\":{\"camerafrequency\":20,\"imagequality\":12,\"imagesize\":\"VGA\",\"brightness\":0,\"contrast\":0,\"saturation\":0,\"sharpness\":0,\"exposurecontrolmode\":1,\"autoexposurelevel\":0,\"manualexposurevalue\":300,\"gaincontrolmode\":1,\"manualgainvalue\":0,\"specialeffect\":0,\"mirrorimage\":false,\"flipimage\":false,\"zoommode\":0,\"zoomoffsetx\":0,\"zoomoffsety\":0},\"debug\":{\"saverawimages\":false,\"rawimageslocation\":\"/log/source\",\"rawimagesretention\":3}},\"imagealignment\":{\"alignmentalgo\":0,\"searchfield\":{\"x\":20,\"y\":20},\"imagerotation\":\"0.0\",\"flipimagesize\":false,\"marker\":[{\"x\":1,\"y\":1},{\"x\":1,\"y\":1}],\"debug\":{\"savedebuginfo\":false}},\"numbersequences\":{\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\"}]},\"digit\":{\"enabled\":true,\"model\":\"dig-class100_0173_s2_q.tflite\",\"cnngoodthreshold\":\"0.00\",\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"roi\":[]}],\"debug\":{\"saveroiimages\":false,\"roiimageslocation\":\"/log/digit\",\"roiimagesretention\":3}},\"analog\":{\"enabled\":true,\"model\":\"ana-class100_0171_s1_q.tflite\",\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"roi\":[]}],\"debug\":{\"saveroiimages\":false,\"roiimageslocation\":\"/log/analog\",\"roiimagesretention\":3}},\"postprocessing\":{\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"decimalshift\":0,\"analogdigitsyncvalue\":\"9.2\",\"extendedresolution\":true,\"ignoreleadingnan\":false,\"checkdigitincreaseconsistency\":false,\"maxratechecktype\":1,\"maxrate\":\"0.150\",\"allownegativerate\":false,\"usefallbackvalue\":true,\"fallbackvalueagestartup\":720}],\"debug\":{\"savedebuginfo\":false}},\"mqtt\":{\"enabled\":false,\"uri\":\"\",\"maintopic\":\"watermeter\",\"clientid\":\"watermeter\",\"authmode\":0,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"},\"processdatanotation\":0,\"retainprocessdata\":false,\"homeassistant\":{\"discoveryenabled\":false,\"discoveryprefix\":\"homeassistant\",\"statustopic\":\"homeassistant/status\",\"metertype\":1,\"retaindiscovery\":false}},\"influxdbv1\":{\"enabled\":false,\"uri\":\"\",\"database\":\"\",\"authmode\":0,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"},\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"measurementname\":\"\",\"fieldkey1\":\"\"}]},\"influxdbv2\":{\"enabled\":false,\"uri\":\"\",\"bucket\":\"\",\"organization\":\"\",\"authmode\":1,\"token\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"},\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"measurementname\":\"\",\"fieldkey1\":\"\"}]},\"webhook\":{\"enabled\":false,\"uri\":\"\",\"apikey\":\"\",\"publishimage\":0,\"authmode\":0,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"}},\"gpio\":{\"customizationenabled\":false,\"gpiopin\":[{\"gpionumber\":1,\"gpiousage\":\"restricted: uart0-tx\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":3,\"gpiousage\":\"restricted: uart0-rx\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":4,\"gpiousage\":\"flashlight-pwm\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"flashlight-default\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":12,\"gpiousage\":\"spare\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":13,\"gpiousage\":\"spare\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100}]},\"log\":{\"debug\":{\"loglevel\":2,\"logfilesretention\":5,\"debugfilesretention\":5},\"data\":{\"enabled\":false,\"datafilesretention\":30}},\"network\":{\"opmode\":0,\"timedoffdelay\":60,\"wlan\":{\"ssid\":\"\",\"password\":\"\",\"hostname\":\"watermeter\",\"ipv4\":{\"networkconfig\":0,\"ipaddress\":\"\",\"subnetmask\":\"\",\"gatewayaddress\":\"\",\"dnsserver\":\"\"},\"wlanroaming\":{\"enabled\":false,\"rssithreshold\":-75}},\"wlanap\":{\"ssid\":\"AI-on-the-Edge Device\",\"password\":\"\",\"channel\":11,\"ipv4\":{\"ipaddress\":\"192.168.4.1\"}},\"time\":{\"timezone\":\"CET-1CEST,M3.5.0,M10.5.0/3\",\"ntp\":{\"timesyncenabled\":true,\"timeserver\":\"\",\"processstartinterlock\":true}}},\"system\":{\"cpufrequency\":160},\"webui\":{\"autorefresh\":{\"overviewpage\":{\"enabled\":true,\"refreshtime\":5},\"datagraphpage\":{\"enabled\":false,\"refreshtime\":60}}}}";
//std::string cfgDataExpexcted(config_json_default_expected_start, config_json_default_expected_end - config_json_default_expected_start);
ConfigClass::getInstance()->readConfigFile(true); // Use default config
TEST_ASSERT_EQUAL_STRING(cfgDataExpexcted.c_str(), ConfigClass::getInstance()->getJsonBuffer());
-
- // Check low limit boundary correction (ESP32CAM device)
- ESP_LOGI(TAG_CFGTEST, "TEST 2: Check low limit boundery correction");
- std::string cfgData = "{\"config\":{\"version\":3,\"lastmodified\":\"\"},\"operationmode\":{\"opmode\":-2,\"automaticprocessinterval\":\"-1.0\",\"usedemoimages\":false},\"takeimage\":{\"flashlight\":{\"flashtime\":-100,\"flashintensity\":-1},\"camera\":{\"camerafrequency\":-20,\"imagequality\":-12,\"imagesize\":\"VGA\",\"brightness\":-3,\"contrast\":-3,\"saturation\":-3,\"sharpness\":-5,\"exposurecontrolmode\":-1,\"autoexposurelevel\":-3,\"manualexposurevalue\":-1,\"gaincontrolmode\":-1,\"manualgainvalue\":-1,\"specialeffect\":-1,\"mirrorimage\":false,\"flipimage\":false,\"zoommode\":-1,\"zoomoffsetx\":-1,\"zoomoffsety\":-1},\"debug\":{\"saverawimages\":false,\"rawimageslocation\":\"/log/source\",\"rawimagesretention\":-3}},\"imagealignment\":{\"alignmentalgo\":-1,\"searchfield\":{\"x\":-20,\"y\":-20},\"imagerotation\":\"-189.9\",\"flipimagesize\":false,\"marker\":[{\"x\":0,\"y\":0},{\"x\":-1,\"y\":-1}],\"debug\":{\"savedebuginfo\":false}},\"numbersequences\":{\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\"}]},\"digit\":{\"enabled\":true,\"model\":\"dig-class100_0173_s2_q.tflite\",\"cnngoodthreshold\":\"-0.10\",\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"roi\":[]}],\"debug\":{\"saveroiimages\":false,\"roiimageslocation\":\"/log/digit\",\"roiimagesretention\":-3}},\"analog\":{\"enabled\":true,\"model\":\"ana-class100_0171_s1_q.tflite\",\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"roi\":[]}],\"debug\":{\"saveroiimages\":false,\"roiimageslocation\":\"/log/analog\",\"roiimagesretention\":-3}},\"postprocessing\":{\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"decimalshift\":-10,\"analogdigitsyncvalue\":\"5.9\",\"extendedresolution\":true,\"ignoreleadingnan\":false,\"checkdigitincreaseconsistency\":false,\"maxratechecktype\":-1,\"maxrate\":\"0.000\",\"allownegativerate\":false,\"usefallbackvalue\":true,\"fallbackvalueagestartup\":-1}],\"debug\":{\"savedebuginfo\":false}},\"mqtt\":{\"enabled\":false,\"uri\":\"\",\"maintopic\":\"watermeter\",\"clientid\":\"watermeter\",\"authmode\":-1,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"},\"processdatanotation\":-1,\"retainprocessdata\":false,\"homeassistant\":{\"discoveryenabled\":false,\"discoveryprefix\":\"homeassistant\",\"statustopic\":\"homeassistant/status\",\"metertype\":-1,\"retaindiscovery\":false}},\"influxdbv1\":{\"enabled\":false,\"uri\":\"\",\"database\":\"\",\"authmode\":-1,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"},\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"measurementname\":\"\",\"fieldkey1\":\"\"}]},\"influxdbv2\":{\"enabled\":false,\"uri\":\"\",\"bucket\":\"\",\"organization\":\"\",\"authmode\":-1,\"token\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"},\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"measurementname\":\"\",\"fieldkey1\":\"\"}]},\"webhook\":{\"enabled\":false,\"uri\":\"\",\"apikey\":\"\",\"publishimage\":-1,\"authmode\":-1,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"}},\"gpio\":{\"customizationenabled\":false,\"gpiopin\":[{\"gpionumber\":1,\"gpiousage\":\"restricted: uart0-tx\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":-1,\"pwmfrequency\":-1,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":-1,\"quantity\":0,\"colorredchannel\":-1,\"colorgreenchannel\":-1,\"colorbluechannel\":-1},\"intensitycorrectionfactor\":-1},{\"gpionumber\":3,\"gpiousage\":\"restricted: uart0-rx\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":4,\"gpiousage\":\"flashlight-pwm\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"flashlight-default\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":12,\"gpiousage\":\"spare\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":13,\"gpiousage\":\"spare\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100}]},\"log\":{\"debug\":{\"loglevel\":-1,\"logfilesretention\":-1,\"debugfilesretention\":-1},\"data\":{\"enabled\":false,\"datafilesretention\":-1}},\"network\":{\"wlan\":{\"ssid\":\"\",\"password\":\"\",\"hostname\":\"watermeter\",\"ipv4\":{\"networkconfig\":-1,\"ipaddress\":\"\",\"subnetmask\":\"\",\"gatewayaddress\":\"\",\"dnsserver\":\"\"},\"wlanroaming\":{\"enabled\":false,\"rssithreshold\":-101}},\"time\":{\"timezone\":\"CET-1CEST,M3.5.0,M10.5.0/3\",\"ntp\":{\"timesyncenabled\":true,\"timeserver\":\"\",\"processstartinterlock\":true}}},\"system\":{\"cpufrequency\":159},\"webui\":{\"autorefresh\":{\"overviewpage\":{\"enabled\":true,\"refreshtime\":-1},\"datagraphpage\":{\"enabled\":false,\"refreshtime\":-1}}}}";
- //cfgData(config_json_low_limit_start, config_json_low_limit_end - config_json_low_limit_start);
- cfgDataExpexcted = "{\"config\":{\"version\":3,\"lastmodified\":\"\"},\"operationmode\":{\"opmode\":-1,\"automaticprocessinterval\":\"0.1\",\"usedemoimages\":false},\"takeimage\":{\"flashlight\":{\"flashtime\":100,\"flashintensity\":0},\"camera\":{\"camerafrequency\":5,\"imagequality\":8,\"imagesize\":\"VGA\",\"brightness\":-2,\"contrast\":-2,\"saturation\":-2,\"sharpness\":-4,\"exposurecontrolmode\":0,\"autoexposurelevel\":-2,\"manualexposurevalue\":0,\"gaincontrolmode\":0,\"manualgainvalue\":0,\"specialeffect\":0,\"mirrorimage\":false,\"flipimage\":false,\"zoommode\":0,\"zoomoffsetx\":0,\"zoomoffsety\":0},\"debug\":{\"saverawimages\":false,\"rawimageslocation\":\"/log/source\",\"rawimagesretention\":0}},\"imagealignment\":{\"alignmentalgo\":0,\"searchfield\":{\"x\":1,\"y\":1},\"imagerotation\":\"-180.0\",\"flipimagesize\":false,\"marker\":[{\"x\":1,\"y\":1},{\"x\":1,\"y\":1}],\"debug\":{\"savedebuginfo\":false}},\"numbersequences\":{\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\"}]},\"digit\":{\"enabled\":true,\"model\":\"dig-class100_0173_s2_q.tflite\",\"cnngoodthreshold\":\"0.00\",\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"roi\":[]}],\"debug\":{\"saveroiimages\":false,\"roiimageslocation\":\"/log/digit\",\"roiimagesretention\":0}},\"analog\":{\"enabled\":true,\"model\":\"ana-class100_0171_s1_q.tflite\",\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"roi\":[]}],\"debug\":{\"saveroiimages\":false,\"roiimageslocation\":\"/log/analog\",\"roiimagesretention\":0}},\"postprocessing\":{\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"decimalshift\":-9,\"analogdigitsyncvalue\":\"6.0\",\"extendedresolution\":true,\"ignoreleadingnan\":false,\"checkdigitincreaseconsistency\":false,\"maxratechecktype\":0,\"maxrate\":\"0.001\",\"allownegativerate\":false,\"usefallbackvalue\":true,\"fallbackvalueagestartup\":0}],\"debug\":{\"savedebuginfo\":false}},\"mqtt\":{\"enabled\":false,\"uri\":\"\",\"maintopic\":\"watermeter\",\"clientid\":\"watermeter\",\"authmode\":0,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"},\"processdatanotation\":0,\"retainprocessdata\":false,\"homeassistant\":{\"discoveryenabled\":false,\"discoveryprefix\":\"homeassistant\",\"statustopic\":\"homeassistant/status\",\"metertype\":0,\"retaindiscovery\":false}},\"influxdbv1\":{\"enabled\":false,\"uri\":\"\",\"database\":\"\",\"authmode\":0,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"},\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"measurementname\":\"\",\"fieldkey1\":\"\"}]},\"influxdbv2\":{\"enabled\":false,\"uri\":\"\",\"bucket\":\"\",\"organization\":\"\",\"authmode\":1,\"token\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"},\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"measurementname\":\"\",\"fieldkey1\":\"\"}]},\"webhook\":{\"enabled\":false,\"uri\":\"\",\"apikey\":\"\",\"publishimage\":0,\"authmode\":0,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"}},\"gpio\":{\"customizationenabled\":false,\"gpiopin\":[{\"gpionumber\":1,\"gpiousage\":\"restricted: uart0-tx\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":0,\"pwmfrequency\":5,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":0,\"colorgreenchannel\":0,\"colorbluechannel\":0},\"intensitycorrectionfactor\":1},{\"gpionumber\":3,\"gpiousage\":\"restricted: uart0-rx\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":4,\"gpiousage\":\"flashlight-pwm\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"flashlight-default\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":12,\"gpiousage\":\"spare\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":13,\"gpiousage\":\"spare\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100}]},\"log\":{\"debug\":{\"loglevel\":1,\"logfilesretention\":0,\"debugfilesretention\":0},\"data\":{\"enabled\":false,\"datafilesretention\":0}},\"network\":{\"wlan\":{\"ssid\":\"\",\"password\":\"\",\"hostname\":\"watermeter\",\"ipv4\":{\"networkconfig\":0,\"ipaddress\":\"\",\"subnetmask\":\"\",\"gatewayaddress\":\"\",\"dnsserver\":\"\"},\"wlanroaming\":{\"enabled\":false,\"rssithreshold\":-100}},\"time\":{\"timezone\":\"CET-1CEST,M3.5.0,M10.5.0/3\",\"ntp\":{\"timesyncenabled\":true,\"timeserver\":\"\",\"processstartinterlock\":true}}},\"system\":{\"cpufrequency\":160},\"webui\":{\"autorefresh\":{\"overviewpage\":{\"enabled\":true,\"refreshtime\":1},\"datagraphpage\":{\"enabled\":false,\"refreshtime\":1}}}}";
- //cfgDataExpexcted(config_json_high_limit_expected_start, config_json_high_limit_expected_end - config_json_high_limit_expected_start);
- ConfigClass::getInstance()->readConfigFile(true, cfgData);
- TEST_ASSERT_EQUAL_STRING(cfgDataExpexcted.c_str(), ConfigClass::getInstance()->getJsonBuffer());
-
- // Check high limit boundary correction
- ESP_LOGI(TAG_CFGTEST, "TEST 3: Check high limit boundery correction");
- cfgData = "{\"config\":{\"version\":3,\"lastmodified\":\"\"},\"operationmode\":{\"opmode\":2,\"automaticprocessinterval\":\"1.0\",\"usedemoimages\":false},\"takeimage\":{\"flashlight\":{\"flashtime\":2000,\"flashintensity\":101},\"camera\":{\"camerafrequency\":21,\"imagequality\":64,\"imagesize\":\"VGA\",\"brightness\":3,\"contrast\":3,\"saturation\":3,\"sharpness\":4,\"exposurecontrolmode\":2,\"autoexposurelevel\":5,\"manualexposurevalue\":1300,\"gaincontrolmode\":2,\"manualgainvalue\":1500,\"specialeffect\":10,\"mirrorimage\":false,\"flipimage\":false,\"zoommode\":4,\"zoomoffsetx\":1000,\"zoomoffsety\":1000},\"debug\":{\"saverawimages\":false,\"rawimageslocation\":\"/log/source\",\"rawimagesretention\":3}},\"imagealignment\":{\"alignmentalgo\":5,\"searchfield\":{\"x\":20,\"y\":20},\"imagerotation\":\"189.9\",\"flipimagesize\":false,\"marker\":[{\"x\":1,\"y\":1},{\"x\":1,\"y\":1}],\"debug\":{\"savedebuginfo\":false}},\"numbersequences\":{\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\"}]},\"digit\":{\"enabled\":true,\"model\":\"dig-class100_0173_s2_q.tflite\",\"cnngoodthreshold\":\"1.10\",\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"roi\":[]}],\"debug\":{\"saveroiimages\":false,\"roiimageslocation\":\"/log/digit\",\"roiimagesretention\":3}},\"analog\":{\"enabled\":true,\"model\":\"ana-class100_0171_s1_q.tflite\",\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"roi\":[]}],\"debug\":{\"saveroiimages\":false,\"roiimageslocation\":\"/log/analog\",\"roiimagesretention\":3}},\"postprocessing\":{\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"decimalshift\":10,\"analogdigitsyncvalue\":\"10.0\",\"extendedresolution\":true,\"ignoreleadingnan\":false,\"checkdigitincreaseconsistency\":false,\"maxratechecktype\":4,\"maxrate\":\"0.150\",\"allownegativerate\":false,\"usefallbackvalue\":true,\"fallbackvalueagestartup\":720}],\"debug\":{\"savedebuginfo\":false}},\"mqtt\":{\"enabled\":false,\"uri\":\"\",\"maintopic\":\"watermeter\",\"clientid\":\"watermeter\",\"authmode\":3,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"},\"processdatanotation\":3,\"retainprocessdata\":false,\"homeassistant\":{\"discoveryenabled\":false,\"discoveryprefix\":\"homeassistant\",\"statustopic\":\"homeassistant/status\",\"metertype\":12,\"retaindiscovery\":false}},\"influxdbv1\":{\"enabled\":false,\"uri\":\"\",\"database\":\"\",\"authmode\":3,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"},\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"measurementname\":\"\",\"fieldkey1\":\"\"}]},\"influxdbv2\":{\"enabled\":false,\"uri\":\"\",\"bucket\":\"\",\"organization\":\"\",\"authmode\":3,\"token\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"},\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"measurementname\":\"\",\"fieldkey1\":\"\"}]},\"webhook\":{\"enabled\":false,\"uri\":\"\",\"apikey\":\"\",\"publishimage\":3,\"authmode\":3,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"}},\"gpio\":{\"customizationenabled\":false,\"gpiopin\":[{\"gpionumber\":1,\"gpiousage\":\"restricted: uart0-tx\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":5001,\"pwmfrequency\":1000001,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":8,\"quantity\":0,\"colorredchannel\":256,\"colorgreenchannel\":256,\"colorbluechannel\":256},\"intensitycorrectionfactor\":101},{\"gpionumber\":3,\"gpiousage\":\"restricted: uart0-rx\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":4,\"gpiousage\":\"flashlight-pwm\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"flashlight-default\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":12,\"gpiousage\":\"spare\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":13,\"gpiousage\":\"spare\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100}]},\"log\":{\"debug\":{\"loglevel\":5,\"logfilesretention\":5,\"debugfilesretention\":5},\"data\":{\"enabled\":false,\"datafilesretention\":30}},\"network\":{\"wlan\":{\"ssid\":\"\",\"password\":\"\",\"hostname\":\"watermeter\",\"ipv4\":{\"networkconfig\":2,\"ipaddress\":\"\",\"subnetmask\":\"\",\"gatewayaddress\":\"\",\"dnsserver\":\"\"},\"wlanroaming\":{\"enabled\":false,\"rssithreshold\":1}},\"time\":{\"timezone\":\"CET-1CEST,M3.5.0,M10.5.0/3\",\"ntp\":{\"timesyncenabled\":true,\"timeserver\":\"\",\"processstartinterlock\":true}}},\"system\":{\"cpufrequency\":241},\"webui\":{\"autorefresh\":{\"overviewpage\":{\"enabled\":true,\"refreshtime\":5},\"datagraphpage\":{\"enabled\":false,\"refreshtime\":60}}}}";
- //cfgData(config_json_high_limit_start, config_json_high_limit_end - config_json_high_limit_start);
- cfgDataExpexcted = "{\"config\":{\"version\":3,\"lastmodified\":\"\"},\"operationmode\":{\"opmode\":1,\"automaticprocessinterval\":\"1.0\",\"usedemoimages\":false},\"takeimage\":{\"flashlight\":{\"flashtime\":2000,\"flashintensity\":100},\"camera\":{\"camerafrequency\":20,\"imagequality\":63,\"imagesize\":\"VGA\",\"brightness\":2,\"contrast\":2,\"saturation\":2,\"sharpness\":3,\"exposurecontrolmode\":2,\"autoexposurelevel\":2,\"manualexposurevalue\":1200,\"gaincontrolmode\":1,\"manualgainvalue\":5,\"specialeffect\":7,\"mirrorimage\":false,\"flipimage\":false,\"zoommode\":2,\"zoomoffsetx\":960,\"zoomoffsety\":720},\"debug\":{\"saverawimages\":false,\"rawimageslocation\":\"/log/source\",\"rawimagesretention\":3}},\"imagealignment\":{\"alignmentalgo\":4,\"searchfield\":{\"x\":20,\"y\":20},\"imagerotation\":\"180.0\",\"flipimagesize\":false,\"marker\":[{\"x\":1,\"y\":1},{\"x\":1,\"y\":1}],\"debug\":{\"savedebuginfo\":false}},\"numbersequences\":{\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\"}]},\"digit\":{\"enabled\":true,\"model\":\"dig-class100_0173_s2_q.tflite\",\"cnngoodthreshold\":\"1.00\",\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"roi\":[]}],\"debug\":{\"saveroiimages\":false,\"roiimageslocation\":\"/log/digit\",\"roiimagesretention\":3}},\"analog\":{\"enabled\":true,\"model\":\"ana-class100_0171_s1_q.tflite\",\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"roi\":[]}],\"debug\":{\"saveroiimages\":false,\"roiimageslocation\":\"/log/analog\",\"roiimagesretention\":3}},\"postprocessing\":{\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"decimalshift\":9,\"analogdigitsyncvalue\":\"9.9\",\"extendedresolution\":true,\"ignoreleadingnan\":false,\"checkdigitincreaseconsistency\":false,\"maxratechecktype\":2,\"maxrate\":\"0.150\",\"allownegativerate\":false,\"usefallbackvalue\":true,\"fallbackvalueagestartup\":720}],\"debug\":{\"savedebuginfo\":false}},\"mqtt\":{\"enabled\":false,\"uri\":\"\",\"maintopic\":\"watermeter\",\"clientid\":\"watermeter\",\"authmode\":2,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"},\"processdatanotation\":2,\"retainprocessdata\":false,\"homeassistant\":{\"discoveryenabled\":false,\"discoveryprefix\":\"homeassistant\",\"statustopic\":\"homeassistant/status\",\"metertype\":10,\"retaindiscovery\":false}},\"influxdbv1\":{\"enabled\":false,\"uri\":\"\",\"database\":\"\",\"authmode\":2,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"},\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"measurementname\":\"\",\"fieldkey1\":\"\"}]},\"influxdbv2\":{\"enabled\":false,\"uri\":\"\",\"bucket\":\"\",\"organization\":\"\",\"authmode\":2,\"token\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"},\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"measurementname\":\"\",\"fieldkey1\":\"\"}]},\"webhook\":{\"enabled\":false,\"uri\":\"\",\"apikey\":\"\",\"publishimage\":2,\"authmode\":2,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"}},\"gpio\":{\"customizationenabled\":false,\"gpiopin\":[{\"gpionumber\":1,\"gpiousage\":\"restricted: uart0-tx\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":5000,\"pwmfrequency\":1000000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":5,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":3,\"gpiousage\":\"restricted: uart0-rx\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":4,\"gpiousage\":\"flashlight-pwm\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"flashlight-default\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":12,\"gpiousage\":\"spare\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":13,\"gpiousage\":\"spare\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100}]},\"log\":{\"debug\":{\"loglevel\":4,\"logfilesretention\":5,\"debugfilesretention\":5},\"data\":{\"enabled\":false,\"datafilesretention\":30}},\"network\":{\"wlan\":{\"ssid\":\"\",\"password\":\"\",\"hostname\":\"watermeter\",\"ipv4\":{\"networkconfig\":0,\"ipaddress\":\"\",\"subnetmask\":\"\",\"gatewayaddress\":\"\",\"dnsserver\":\"\"},\"wlanroaming\":{\"enabled\":false,\"rssithreshold\":0}},\"time\":{\"timezone\":\"CET-1CEST,M3.5.0,M10.5.0/3\",\"ntp\":{\"timesyncenabled\":true,\"timeserver\":\"\",\"processstartinterlock\":true}}},\"system\":{\"cpufrequency\":240},\"webui\":{\"autorefresh\":{\"overviewpage\":{\"enabled\":true,\"refreshtime\":5},\"datagraphpage\":{\"enabled\":false,\"refreshtime\":60}}}}";
- //cfgDataExpexcted(config_json_special_expected_start, config_json_special_expected_end - config_json_special_expected_start);
- ConfigClass::getInstance()->readConfigFile(true, cfgData);
- TEST_ASSERT_EQUAL_STRING(cfgDataExpexcted.c_str(), ConfigClass::getInstance()->getJsonBuffer());
-
- // Check special input validation
- ESP_LOGI(TAG_CFGTEST, "TEST 4: Check special input validation");
- cfgData = "{\"config\":{\"version\":3,\"lastmodified\":\"\"},\"operationmode\":{\"opmode\":-1,\"automaticprocessinterval\":\"1.0\",\"usedemoimages\":false},\"takeimage\":{\"flashlight\":{\"flashtime\":2000,\"flashintensity\":50},\"camera\":{\"camerafrequency\":20,\"imagequality\":12,\"imagesize\":\"VGA\",\"brightness\":0,\"contrast\":0,\"saturation\":0,\"sharpness\":0,\"exposurecontrolmode\":1,\"autoexposurelevel\":0,\"manualexposurevalue\":300,\"gaincontrolmode\":1,\"manualgainvalue\":0,\"specialeffect\":0,\"mirrorimage\":false,\"flipimage\":false,\"zoommode\":0,\"zoomoffsetx\":0,\"zoomoffsety\":0},\"debug\":{\"saverawimages\":false,\"rawimageslocation\":\"/log/source/\",\"rawimagesretention\":3}},\"imagealignment\":{\"alignmentalgo\":0,\"searchfield\":{\"x\":20,\"y\":20},\"imagerotation\":\"0.0\",\"flipimagesize\":false,\"marker\":[{\"x\":1,\"y\":1},{\"x\":1,\"y\":1}],\"debug\":{\"savedebuginfo\":false}},\"numbersequences\":{\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\"}]},\"digit\":{\"enabled\":true,\"model\":\"dig-class100_0173_s2_q.tflite\",\"cnngoodthreshold\":\"0.00\",\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"roi\":[]}],\"debug\":{\"saveroiimages\":false,\"roiimageslocation\":\"/log/digit/\",\"roiimagesretention\":3}},\"analog\":{\"enabled\":true,\"model\":\"ana-class100_0171_s1_q.tflite\",\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"roi\":[]}],\"debug\":{\"saveroiimages\":false,\"roiimageslocation\":\"/log/analog/\",\"roiimagesretention\":3}},\"postprocessing\":{\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"decimalshift\":0,\"analogdigitsyncvalue\":\"9.2\",\"extendedresolution\":true,\"ignoreleadingnan\":false,\"checkdigitincreaseconsistency\":false,\"maxratechecktype\":1,\"maxrate\":\"0.150\",\"allownegativerate\":false,\"usefallbackvalue\":true,\"fallbackvalueagestartup\":720}],\"debug\":{\"savedebuginfo\":false}},\"mqtt\":{\"enabled\":false,\"uri\":\"\",\"maintopic\":\"/watermeter/\",\"clientid\":\"123456789012345678901234\",\"authmode\":0,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"/ca.crt/\",\"clientcert\":\"/client.crt/\",\"clientkey\":\"/client.key/\"},\"processdatanotation\":0,\"retainprocessdata\":false,\"homeassistant\":{\"discoveryenabled\":false,\"discoveryprefix\":\"/homeassistant/\",\"statustopic\":\"/homeassistant/status/\",\"metertype\":1,\"retaindiscovery\":false}},\"influxdbv1\":{\"enabled\":false,\"uri\":\"\",\"database\":\"\",\"authmode\":0,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"/ca.crt/\",\"clientcert\":\"/client.crt/\",\"clientkey\":\"/client.key/\"},\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"measurementname\":\"/test/\",\"fieldkey1\":\"/test/\"}]},\"influxdbv2\":{\"enabled\":false,\"uri\":\"\",\"bucket\":\"\",\"organization\":\"\",\"authmode\":1,\"token\":\"\",\"tls\":{\"cacert\":\"/ca.crt/\",\"clientcert\":\"/client.crt/\",\"clientkey\":\"/client.key/\"},\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"measurementname\":\"/test/\",\"fieldkey1\":\"/test/\"}]},\"webhook\":{\"enabled\":false,\"uri\":\"\",\"apikey\":\"\",\"publishimage\":0,\"authmode\":0,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"}},\"gpio\":{\"customizationenabled\":false,\"gpiopin\":[{\"gpionumber\":1,\"gpiousage\":\"restricted: uart0-tx\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":3,\"gpiousage\":\"restricted: uart0-rx\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":4,\"gpiousage\":\"flashlight-pwm\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"flashlight-default\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":12,\"gpiousage\":\"spare\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":13,\"gpiousage\":\"spare\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100}]},\"log\":{\"debug\":{\"loglevel\":2,\"logfilesretention\":5,\"debugfilesretention\":5},\"data\":{\"enabled\":false,\"datafilesretention\":30}},\"network\":{\"wlan\":{\"ssid\":\"\",\"password\":\"\",\"hostname\":\"watermeter\",\"ipv4\":{\"networkconfig\":0,\"ipaddress\":\"\",\"subnetmask\":\"\",\"gatewayaddress\":\"\",\"dnsserver\":\"\"},\"wlanroaming\":{\"enabled\":false,\"rssithreshold\":-75}},\"time\":{\"timezone\":\"CET-1CEST,M3.5.0,M10.5.0/3\",\"ntp\":{\"timesyncenabled\":true,\"timeserver\":\"\",\"processstartinterlock\":true}}},\"system\":{\"cpufrequency\":160},\"webui\":{\"autorefresh\":{\"overviewpage\":{\"enabled\":true,\"refreshtime\":5},\"datagraphpage\":{\"enabled\":false,\"refreshtime\":60}}}}";
- //cfgData(config_json_special_start, config_json_special_end - config_json_special_start);
- cfgDataExpexcted = "{\"config\":{\"version\":3,\"lastmodified\":\"\"},\"operationmode\":{\"opmode\":-1,\"automaticprocessinterval\":\"1.0\",\"usedemoimages\":false},\"takeimage\":{\"flashlight\":{\"flashtime\":2000,\"flashintensity\":50},\"camera\":{\"camerafrequency\":20,\"imagequality\":12,\"imagesize\":\"VGA\",\"brightness\":0,\"contrast\":0,\"saturation\":0,\"sharpness\":0,\"exposurecontrolmode\":1,\"autoexposurelevel\":0,\"manualexposurevalue\":300,\"gaincontrolmode\":1,\"manualgainvalue\":0,\"specialeffect\":0,\"mirrorimage\":false,\"flipimage\":false,\"zoommode\":0,\"zoomoffsetx\":0,\"zoomoffsety\":0},\"debug\":{\"saverawimages\":false,\"rawimageslocation\":\"/log/source\",\"rawimagesretention\":3}},\"imagealignment\":{\"alignmentalgo\":0,\"searchfield\":{\"x\":20,\"y\":20},\"imagerotation\":\"0.0\",\"flipimagesize\":false,\"marker\":[{\"x\":1,\"y\":1},{\"x\":1,\"y\":1}],\"debug\":{\"savedebuginfo\":false}},\"numbersequences\":{\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\"}]},\"digit\":{\"enabled\":true,\"model\":\"dig-class100_0173_s2_q.tflite\",\"cnngoodthreshold\":\"0.00\",\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"roi\":[]}],\"debug\":{\"saveroiimages\":false,\"roiimageslocation\":\"/log/digit\",\"roiimagesretention\":3}},\"analog\":{\"enabled\":true,\"model\":\"ana-class100_0171_s1_q.tflite\",\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"roi\":[]}],\"debug\":{\"saveroiimages\":false,\"roiimageslocation\":\"/log/analog\",\"roiimagesretention\":3}},\"postprocessing\":{\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"decimalshift\":0,\"analogdigitsyncvalue\":\"9.2\",\"extendedresolution\":true,\"ignoreleadingnan\":false,\"checkdigitincreaseconsistency\":false,\"maxratechecktype\":1,\"maxrate\":\"0.150\",\"allownegativerate\":false,\"usefallbackvalue\":true,\"fallbackvalueagestartup\":720}],\"debug\":{\"savedebuginfo\":false}},\"mqtt\":{\"enabled\":false,\"uri\":\"\",\"maintopic\":\"watermeter\",\"clientid\":\"watermeter\",\"authmode\":0,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"ca.crt\",\"clientcert\":\"client.crt\",\"clientkey\":\"client.key\"},\"processdatanotation\":0,\"retainprocessdata\":false,\"homeassistant\":{\"discoveryenabled\":false,\"discoveryprefix\":\"homeassistant\",\"statustopic\":\"homeassistant/status\",\"metertype\":1,\"retaindiscovery\":false}},\"influxdbv1\":{\"enabled\":false,\"uri\":\"\",\"database\":\"\",\"authmode\":0,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"ca.crt\",\"clientcert\":\"client.crt\",\"clientkey\":\"client.key\"},\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"measurementname\":\"test\",\"fieldkey1\":\"test\"}]},\"influxdbv2\":{\"enabled\":false,\"uri\":\"\",\"bucket\":\"\",\"organization\":\"\",\"authmode\":1,\"token\":\"\",\"tls\":{\"cacert\":\"ca.crt\",\"clientcert\":\"client.crt\",\"clientkey\":\"client.key\"},\"sequence\":[{\"sequenceid\":0,\"sequencename\":\"main\",\"measurementname\":\"test\",\"fieldkey1\":\"test\"}]},\"webhook\":{\"enabled\":false,\"uri\":\"\",\"apikey\":\"\",\"publishimage\":0,\"authmode\":0,\"username\":\"\",\"password\":\"\",\"tls\":{\"cacert\":\"\",\"clientcert\":\"\",\"clientkey\":\"\"}},\"gpio\":{\"customizationenabled\":false,\"gpiopin\":[{\"gpionumber\":1,\"gpiousage\":\"restricted: uart0-tx\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":3,\"gpiousage\":\"restricted: uart0-rx\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":4,\"gpiousage\":\"flashlight-pwm\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"flashlight-default\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":12,\"gpiousage\":\"spare\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100},{\"gpionumber\":13,\"gpiousage\":\"spare\",\"pinenabled\":false,\"pinname\":\"\",\"pinmode\":\"input\",\"capturemode\":\"cyclic-polling\",\"inputdebouncetime\":200,\"pwmfrequency\":5000,\"exposetomqtt\":false,\"exposetorest\":false,\"smartled\":{\"type\":0,\"quantity\":1,\"colorredchannel\":255,\"colorgreenchannel\":255,\"colorbluechannel\":255},\"intensitycorrectionfactor\":100}]},\"log\":{\"debug\":{\"loglevel\":2,\"logfilesretention\":5,\"debugfilesretention\":5},\"data\":{\"enabled\":false,\"datafilesretention\":30}},\"network\":{\"wlan\":{\"ssid\":\"\",\"password\":\"\",\"hostname\":\"watermeter\",\"ipv4\":{\"networkconfig\":0,\"ipaddress\":\"\",\"subnetmask\":\"\",\"gatewayaddress\":\"\",\"dnsserver\":\"\"},\"wlanroaming\":{\"enabled\":false,\"rssithreshold\":-75}},\"time\":{\"timezone\":\"CET-1CEST,M3.5.0,M10.5.0/3\",\"ntp\":{\"timesyncenabled\":true,\"timeserver\":\"\",\"processstartinterlock\":true}}},\"system\":{\"cpufrequency\":160},\"webui\":{\"autorefresh\":{\"overviewpage\":{\"enabled\":true,\"refreshtime\":5},\"datagraphpage\":{\"enabled\":false,\"refreshtime\":60}}}}";
- //cfgDataExpexcted(config_json_special_expected_start, config_json_special_expected_end - config_json_special_expected_start);
- ConfigClass::getInstance()->readConfigFile(true, cfgData);
- TEST_ASSERT_EQUAL_STRING(cfgDataExpexcted.c_str(), ConfigClass::getInstance()->getJsonBuffer());
}
/**
diff --git a/docs/Configuration/Parameter/GPIO/GPIOPin_PinMode.md b/docs/Configuration/Parameter/GPIO/GPIOPin_PinMode.md
index 598f40054..658598b2e 100644
--- a/docs/Configuration/Parameter/GPIO/GPIOPin_PinMode.md
+++ b/docs/Configuration/Parameter/GPIO/GPIOPin_PinMode.md
@@ -4,7 +4,7 @@
|:--- |:--- |:----
| Parameter Name | Pin Mode | pinmode
| Default Value | `input-pullup` | `input-pullup`
-| Input Options | `input` `input-pullup` `input-pulldown` `output` `output-pwm` `flashlight-default` `flashlight-pwm` `flashlight-smartled` `flashlight-digital` `trigger-cycle-start` | `input` `input-pullup` `input-pulldown` `output` `output-pwm` `flashlight-default` `flashlight-pwm` `flashlight-smartled` `flashlight-digital` `trigger-cycle-start`
+| Input Options | `Input` `Input Pullup` `Input Pulldown` `Output` `Output PWM` `Flashlight Default` `Flashlight PWM` `Flashlight Smartled` `Flashlight Digital` `Trigger Cycle Start` `Resume WLAN Connection` | `input` `input-pullup` `input-pulldown` `output` `output-pwm` `flashlight-default` `flashlight-pwm` `flashlight-smartled` `flashlight-digital` `trigger-cycle-start` `resume-wlan-connection`
## Description
@@ -16,23 +16,23 @@ GPIO operation mode
| Input Option | Direction | Description
|:--- |:--- |:---
-| `input` | input | Use as input, internal pullup and pulldown resistor is disabled
-| `input pullup` | input | Use as input, internal pullup resistor is enabled
-| `input pulldown` | input | Use as input, internal pulldown resistor is enabled
-| `output` | output | Use as output (digital states: 0, 1) -> controlable by REST API and/or MQTT
-| `output pwm` | output | Use as output which controlable by PWM duty (duty cycle: 0 .. Max duty resolution depending on PWM frequency) -> controlable by REST API and/or MQTT
-| `flashlight default` | output | This mode represents the board's default flashlight configuration, e.g. Default for board `ESP32CAM` -> GPIO4 as PWM controlled output. This mode is only visible on respective GPIO which is defined as default in firmware
-| `flashlight pwm` | output | Use for flashlight operation with regular LEDs (PWM controlled intensity)
-| `flashlight smartled` | output | Use for flashlight operation with smartLEDs
-| `flashlight digital` | output | Use for flashlight operation with regular LEDs (digital states: 0, 1)
-| `trigger cycle start` | input (pullup enabled) | Trigger a cycle start (by pulling signal to low)
-
+| `Input` | input | Use as input, internal pullup and pulldown resistor is disabled
+| `Input Pullup` | input | Use as input, internal pullup resistor is enabled
+| `Input Pulldown` | input | Use as input, internal pulldown resistor is enabled
+| `Output` | output | Use as output (digital states: 0, 1) -> controlable by REST API and/or MQTT
+| `Output PWM` | output | Use as output which controlable by PWM duty (duty cycle: 0 .. Max duty resolution depending on PWM frequency) -> controlable by REST API and/or MQTT
+| `Flashlight Default` | output | This mode represents the board's default flashlight configuration, e.g. Default for board `ESP32CAM` -> GPIO4 as PWM controlled output. This mode is only visible on respective GPIO which is defined as default in firmware
+| `Flashlight PWM` | output | Use for flashlight operation with regular LEDs (PWM controlled intensity)
+| `Flashlight Smartled` | output | Use for flashlight operation with smartLEDs
+| `Flashlight Digital` | output | Use for flashlight operation with regular LEDs (digital states: 0, 1)
+| `Trigger Cycle Start` | input (pullup enabled) | Trigger a cycle start (by pulling signal to low)
+| `Resume WLAN Connection` | input (pullup enabled) | Resume a suspended network connection (depending on network operation mode)
!!! Note
All flashlight modes are fully controlled by process cycle, no external manipulation allowed.
!!! Tip
- `Flashlight digital` / `Flashlight pwm` act like an output and are activated while
+ `Flashlight Digital` / `Flashlight PWM` act like an output and are activated while
flashlight is requested by process (before image gets taken). This could potentially
be used to control any mechanism to activate display before image gets taken.
\ No newline at end of file
diff --git a/docs/Configuration/Parameter/Network/OpMode.md b/docs/Configuration/Parameter/Network/OpMode.md
new file mode 100644
index 000000000..21543e8c9
--- /dev/null
+++ b/docs/Configuration/Parameter/Network/OpMode.md
@@ -0,0 +1,30 @@
+# Parameter: Operation Mode
+
+| | WebUI | REST API
+|:--- |:--- |:----
+| Parameter Name | Operation Mode | opmode
+| Default Value | `WLAN Client` | `0`
+| Input Options | `Disabled` `WLAN CLient` `WLAN Client (Timed-Off)` `WLAN Access Point` `WLAN Access Point (Timed-Off)` | `-1` `0` `1` `2` `3`
+
+
+## Description
+
+Select the network operation mode
+
+
+| Input Option | Description
+|:--- |:---
+| `Disabled` | All network connections are disabled (no interaction with device possible, but device is processing).
+| `WLAN Client` | WLAN connection is established to a wireless network in range.
+| `WLAN Client (Timed-Off)` | WLAN connection is established to a wireless network in range. Network is suspended after a configurable time is elapsed and actual cycle processing is completed (Parameter: Timed-Off Delay).
+| `WLAN Access Point` | Standalone mode. Device is providing an access point.
+| `WLAN Access Point (Timed-Off)` | Standalone mode. Device is providing an access point. Access point is suspended after a configurable time is elapsed, no client is connected and actual cycle processing is completed (Parameter: Timed-Off Delay).
+
+
+!!! Note
+ To apply this parameter a device reboot is required.
+
+
+!!! Tip
+ A suspended network connection can be resumed by GPIO using option `Resume WLAN connection`.
+ This can be configured in `GPIO` section
\ No newline at end of file
diff --git a/docs/Configuration/Parameter/Network/TimedOffDelay.md b/docs/Configuration/Parameter/Network/TimedOffDelay.md
new file mode 100644
index 000000000..83b7a6981
--- /dev/null
+++ b/docs/Configuration/Parameter/Network/TimedOffDelay.md
@@ -0,0 +1,14 @@
+# Parameter: Timed-Off Delay
+
+| | WebUI | REST API
+|:--- |:--- |:----
+| Parameter Name | Timed-Off Delay | timedoffdelay
+| Default Value | `60` | `60`
+| Input Range | `1` .. ∞ | `1` .. ∞
+| Unit | Minutes | Minutes
+
+## Description
+
+Define the delay after which the network shall be suspended.
+- WLAN Client: Suspend after the defined time is elapsed and actual processed cycle is completed.
+- Access Point: Suspend after the defined time with no client connected is elapsed and actual processed cycle is completed.
diff --git a/docs/Configuration/Parameter/Network/WLANAP_Channel.md b/docs/Configuration/Parameter/Network/WLANAP_Channel.md
new file mode 100644
index 000000000..42ca58cb6
--- /dev/null
+++ b/docs/Configuration/Parameter/Network/WLANAP_Channel.md
@@ -0,0 +1,16 @@
+# Parameter: Channel
+
+| | WebUI | REST API
+|:--- |:--- |:----
+| Parameter Name | Channel | channel
+| Default Value | `11` | `11`
+
+
+## Description
+
+Channel of the device's wireless network access point
+
+
+!!! Note
+ To apply this parameter a device reboot is required.
+
diff --git a/docs/Configuration/Parameter/Network/WLANAP_IPv4_IPAddress.md b/docs/Configuration/Parameter/Network/WLANAP_IPv4_IPAddress.md
new file mode 100644
index 000000000..8aef15436
--- /dev/null
+++ b/docs/Configuration/Parameter/Network/WLANAP_IPv4_IPAddress.md
@@ -0,0 +1,16 @@
+# Parameter: IP Address
+
+| | WebUI | REST API
+|:--- |:--- |:----
+| Parameter Name | IP Address | ipaddress
+| Default Value | empty | empty
+
+
+## Description
+
+IP address of the device's wireless network access point
+
+
+!!! Note
+ To apply this parameter a device reboot is required.
+
diff --git a/docs/Configuration/Parameter/Network/WLANAP_Password.md b/docs/Configuration/Parameter/Network/WLANAP_Password.md
new file mode 100644
index 000000000..3cf5df1e8
--- /dev/null
+++ b/docs/Configuration/Parameter/Network/WLANAP_Password.md
@@ -0,0 +1,15 @@
+# Parameter: Password
+
+| | WebUI | REST API
+|:--- |:--- |:----
+| Parameter Name | Password | password
+| Default Value | empty | empty
+
+
+## Description
+
+Password of the device's wireless network access point
+
+
+!!! Note
+ To apply this parameter a device reboot is required.
diff --git a/docs/Configuration/Parameter/Network/WLANAP_SSID.md b/docs/Configuration/Parameter/Network/WLANAP_SSID.md
new file mode 100644
index 000000000..1ffc6d8d0
--- /dev/null
+++ b/docs/Configuration/Parameter/Network/WLANAP_SSID.md
@@ -0,0 +1,16 @@
+# Parameter: SSID
+
+| | WebUI | REST API
+|:--- |:--- |:----
+| Parameter Name | SSID | ssid
+| Default Value | empty | empty
+
+
+## Description
+
+SSID of the device's wireless network access point
+
+
+!!! Note
+ To apply this parameter a device reboot is required.
+
diff --git a/docs/Configuration/Parameter/Network/WLAN_Password.md b/docs/Configuration/Parameter/Network/WLAN_Password.md
index e0eea463c..01305311c 100644
--- a/docs/Configuration/Parameter/Network/WLAN_Password.md
+++ b/docs/Configuration/Parameter/Network/WLAN_Password.md
@@ -8,7 +8,7 @@
## Description
-SSID (WLAN Name) of the wireless network
+Password of the wireless network
!!! Note
@@ -21,5 +21,6 @@ SSID (WLAN Name) of the wireless network
for a password set, dots are displayed as placeholder. An empty password results in an
empty parameter field, though.
+
!!! Warning
During initial transmission password is sent as cleartext.
diff --git a/docs/Configuration/Parameter/Network/WLAN_SSID.md b/docs/Configuration/Parameter/Network/WLAN_SSID.md
index f4ecce2e2..ad2426cdd 100644
--- a/docs/Configuration/Parameter/Network/WLAN_SSID.md
+++ b/docs/Configuration/Parameter/Network/WLAN_SSID.md
@@ -8,7 +8,7 @@
## Description
-SSID (WLAN Name) of the wireless network
+SSID (name of wireless network) of the wireless network
!!! Note
diff --git a/docs/Troubleshooting/StatusLED_BlinkCodes.md b/docs/Troubleshooting/StatusLED_BlinkCodes.md
index c877d9fd8..25afe26d6 100644
--- a/docs/Troubleshooting/StatusLED_BlinkCodes.md
+++ b/docs/Troubleshooting/StatusLED_BlinkCodes.md
@@ -16,10 +16,11 @@ The error code source definition can be found [here](https://github.com/Slider00
| **source** | source blink count| error / warning / status | status blink count| repeat infinite |
| ------------- | -------------------- |---------------------------------------| -------------------- | -------------------|
-| WLAN_CONN | 1 | Disconnected (No Access Point) | 1 |
-| WLAN_CONN | 1 | Disconnected (Authentication failure) | 2 |
-| WLAN_CONN | 1 | Disconnected (Timeout) | 3 |
+| WLAN_CONN | 1 | Disconnected (no access point) | 1 |
+| WLAN_CONN | 1 | Disconnected (authentication failure) | 2 |
+| WLAN_CONN | 1 | Disconnected (timeout) | 3 |
| WLAN_CONN | 1 | Disconnected (further reasons) | 4 |
+| WLAN_CONN | 1 | Disconnected (network suspended) | 5 |
| WLAN_INIT | 2 | WIFI init error (details console) | 1 | X
| SDCARD_NVS_INIT | 3 | SD card filesystem mount failed | 1 | X
| SDCARD_NVS_INIT | 3 | SD card not found (0x107) | 2 | X
@@ -37,7 +38,8 @@ The error code source definition can be found [here](https://github.com/Slider00
| PSRAM_INIT | 6 | Total heap < 4MB | 3 | X
| TIME_CHECK | 7 | Missing time sync (check every round) | 1 |
| OTA_OR_AP | 8 | OTA process ongoing | 1 | X
-| OTA_OR_AP | 8 | Soft AP started (for remote config) | 2 | X
+| OTA_OR_AP | 8 | AP mode (device provisioning) | 2 | X
+| OTA_OR_AP | 8 | AP mode (fallback due to connection failure) | 3 | X
| FLASHLIGHT | N/A | LED on when flashlight is on | solid, no blink |
diff --git a/sd-card/html/edit_config_param.html b/sd-card/html/edit_config_param.html
index 103854c2d..2de8c1c18 100644
--- a/sd-card/html/edit_config_param.html
+++ b/sd-card/html/edit_config_param.html
@@ -263,7 +263,8 @@ Configuration
Don't forget to save the changes with the button "Save And Apply" at the bottom of this page.
- The new configuration gets automatically applied. No reboot is required.
+ The new configuration gets automatically applied. No reboot is required. Only a few hardware related
+ parameter require a reboot indicated by the button labled with "Save And Reboot" .
@@ -2172,16 +2173,17 @@ Configuration
- flashlight-default
- flashlight-pwm
- flashlight-smartled
- flashlight-digital
- input
- input-pullup
- input-pulldown
- output
- output-pwm
- trigger-cycle-start
+ Flashlight Default
+ Flashlight PWM
+ Flashlight Smartled
+ Flashlight Digital
+ Input
+ Input Pullup
+ Input Pulldown
+ Output
+ Output PWM
+ Trigger Cycle Start
+ Resume WLAN Connection
@@ -2472,76 +2474,87 @@ Configuration
-
- WLAN Configuration
-
-
- Reboot required to apply changes!
-
-
-
-
+
+
+
+ Timed-Off Delay
+
+
+
+
+ $TOOLTIP_network_timedoffdelay
+
+
+
+
+ WLAN Client Configuration
+
+
+
+
SSID
$TOOLTIP_network_wlan_ssid
-
+
Password
$TOOLTIP_network_wlan_password
-
+
Hostname
$TOOLTIP_network_wlan_hostname
-
+
Network Configuration
@@ -2549,7 +2562,7 @@ Configuration
-
+
IP Address
$TOOLTIP_network_wlan_ipv4_ipaddress
-
+
Subnet Mask
$TOOLTIP_network_wlan_ipv4_subnetmask
-
+
Gateway Address
$TOOLTIP_network_wlan_ipv4_gatewayaddress
-
+
DNS Server
$TOOLTIP_network_wlan_ipv4_dnsserver
-
+
Roaming
-
+
RSSI Threshold
@@ -2641,6 +2655,67 @@ Configuration
$TOOLTIP_network_wlan_wlanroaming_rssithreshold
+
+
+ WLAN Access Point Configuration
+
+
+
+
+
+ SSID
+
+
+
+
+ $TOOLTIP_network_wlanap_ssid
+
+
+
+
+ Password
+
+
+
+
+ $TOOLTIP_network_wlanap_password
+
+
+
+
+ Channel
+
+
+
+
+ $TOOLTIP_network_wlanap_channel
+
+
+
+
+ IP Address
+
+
+
+
+ $TOOLTIP_network_wlanap_ipv4_ipaddress
+
+
Time Configuration
@@ -2728,7 +2803,7 @@ Configuration
- WLAN Status
+ Operation Mode
+
+
+
+
+
+ Connection Status
-
+
- WLAN Name (SSID)
+ Network Name (SSID)
- WLAN Signal (RSSI)
+ Signal Strength (RSSI)
+
+ WLAN Channel
+
+
+
+
MAC Address
@@ -603,14 +615,16 @@ Copyright
document.getElementById("device_uptime").value = formatUptime(_jsonData.device_uptime);
- document.getElementById("wlan_status").value = _jsonData.wlan_status;
- if (_jsonData.wlan_status == "Connected")
- addClassToElement("wlan_status", "badge-success");
+ document.getElementById("network_opmode").value = _jsonData.network_opmode;
+ document.getElementById("connection_status").value = _jsonData.connection_status;
+ if (_jsonData.connection_status == "Connected")
+ addClassToElement("connection_status", "badge-success");
else
- addClassToElement("wlan_status", "badge-error");
+ addClassToElement("connection_status", "badge-error");
document.getElementById("wlan_ssid").value = _jsonData.wlan_ssid;
document.getElementById("wlan_rssi").value = _jsonData.wlan_rssi + " dBm";
+ document.getElementById("wlan_channel").value = _jsonData.wlan_channel;
document.getElementById("mac_address").value = _jsonData.mac_address;
document.getElementById("network_config").value = _jsonData.network_config;
document.getElementById("ipv4_address").value = _jsonData.ipv4_address;
diff --git a/sd-card/html/sys_reboot_page.html b/sd-card/html/sys_reboot_page.html
index 75b1ef5f4..4692da10d 100644
--- a/sd-card/html/sys_reboot_page.html
+++ b/sd-card/html/sys_reboot_page.html
@@ -33,7 +33,7 @@
-
+
Reboot
@@ -108,6 +108,17 @@
Status: Rebooting
}, 10000);
}
+ // Trigger reboot with hash #reboot
+ function checkRebootTriggeredByHash()
+ {
+ if(window.location.hash) {
+ let hash = window.location.hash.substring(1); //Puts hash in variable, and removes the # character
+ if(hash == 'reboot') {
+ doReboot();
+ }
+ }
+ }
+