Fixes in new API functions

This commit is contained in:
Martin Bauer 2021-07-22 18:38:28 +02:00
parent 06c3015d22
commit fb0b455910
7 changed files with 96 additions and 42 deletions

View File

@ -1,8 +1,9 @@
#include "WifiManager.h" #include "WifiManager.h"
void WifiManager::begin(const String &hostname) void WifiManager::begin(const String &hostname, const String & wifiStaModeName)
{ {
hostname_ = hostname; hostname_ = hostname;
wifiStaModeName_ = wifiStaModeName;
prefs_.begin("st_wifi_manager"); prefs_.begin("st_wifi_manager");
startWifi(); startWifi();
} }
@ -20,19 +21,24 @@ void WifiManager::startWifi()
// station mode // station mode
WiFi.mode(WIFI_STA); WiFi.mode(WIFI_STA);
WiFi.begin(staSSID.c_str(), staPassword.c_str()); WiFi.begin(staSSID.c_str(), staPassword.c_str());
Serial.printf("Starting WiFi station mode to ssid %s, hostname %s\n", staSSID.c_str(), hostname_.c_str());
WiFi.setHostname(hostname_.c_str()); WiFi.setHostname(hostname_.c_str());
int connectCounter = 0; int connectCounter = 0;
bool successful = true; bool successful = true;
delay(5000);
while (WiFi.status() != WL_CONNECTED) while (WiFi.status() != WL_CONNECTED)
{ {
delay(2000); Serial.printf("WiFI connection problem %d\n", WiFi.status());
WiFi.begin(staSSID.c_str(), staPassword.c_str()); WiFi.begin(staSSID.c_str(), staPassword.c_str());
connectCounter += 1; connectCounter += 1;
if (connectCounter >= 60) // for two minutes no connection if (connectCounter >= 60) // for two minutes no connection
{ {
successful = false; successful = false;
break; // fallback to AP mode break; // fallback to AP mode
} }
delay(5000);
} }
state_ = STA; state_ = STA;
if (successful) if (successful)
@ -42,14 +48,17 @@ void WifiManager::startWifi()
WiFi.mode(WIFI_AP); WiFi.mode(WIFI_AP);
WiFi.softAPConfig(IPAddress(192, 168, 42, 1), IPAddress(192, 168, 42, 1), IPAddress(255, 255, 255, 0)); WiFi.softAPConfig(IPAddress(192, 168, 42, 1), IPAddress(192, 168, 42, 1), IPAddress(255, 255, 255, 0));
WiFi.softAPsetHostname(hostname_.c_str()); WiFi.softAPsetHostname(hostname_.c_str());
if (apPassword.length() > 0) if (apPassword.length() > 0)
{ {
WiFi.softAP(hostname_.c_str(), apPassword.c_str()); Serial.printf("Secured AP mode, name %s\n", wifiStaModeName_.c_str());
WiFi.softAP(wifiStaModeName_.c_str(), apPassword.c_str());
state_ = AP_SECURE; state_ = AP_SECURE;
} }
else else
{ {
WiFi.softAP(hostname_.c_str()); Serial.printf("Provisioning AP mode, name %s\n", wifiStaModeName_.c_str());
WiFi.softAP(wifiStaModeName_.c_str());
state_ = AP_PROVISIONING; state_ = AP_PROVISIONING;
} }
} }
@ -80,15 +89,14 @@ void WifiManager::resetToApProvisioning()
void WifiManager::iteration() void WifiManager::iteration()
{ {
if (state_ == STA && WiFi.status() != WL_CONNECTED) { if (state_ == STA && WiFi.status() != WL_CONNECTED)
{
startWifi(); startWifi();
Serial.println("Connection lost - Restarting WIFI"); Serial.println("Connection lost - Restarting WIFI");
} }
} }
const char *WifiManager::stateToString(WifiManager::State state)
const char * WifiManager::stateToString(WifiManager::State state)
{ {
switch (state) switch (state)
{ {

View File

@ -28,7 +28,7 @@ public:
}; };
WifiManager() : state_(INVALID) {} WifiManager() : state_(INVALID) {}
void begin(const String &hostname); void begin(const String &hostname, const String & wifiStaModeName);
void setStaCredentials(const char *wifiName, const char *password); void setStaCredentials(const char *wifiName, const char *password);
void setApCredentials(const char *password); void setApCredentials(const char *password);
@ -48,4 +48,5 @@ private:
Preferences prefs_; Preferences prefs_;
State state_; State state_;
String hostname_; String hostname_;
String wifiStaModeName_;
}; };

View File

@ -10,6 +10,8 @@
[platformio] [platformio]
data_dir = data data_dir = data
default_envs = esp32
[env:esp32] [env:esp32]
platform = espressif32 platform = espressif32

View File

@ -16,6 +16,8 @@ public:
SessionAPI(SessionManager<SessionT> &sessionManager) SessionAPI(SessionManager<SessionT> &sessionManager)
: sessionManager_(sessionManager) : sessionManager_(sessionManager)
{ {
for (int i = 0; i < MAX_WEBSOCKET_CONNECTIONS; ++i)
numSentMeasurements_[i] = 0;
} }
void onClientConnect(websockets::WebsocketsClient &client); void onClientConnect(websockets::WebsocketsClient &client);
@ -60,7 +62,7 @@ void SessionAPI<T>::onClientConnect(websockets::WebsocketsClient &client)
char *writeHead = msg; char *writeHead = msg;
*writeHead = MessageCode::INITIAL_INFO; *writeHead = static_cast<char>(MessageCode::INITIAL_INFO);
writeHead += sizeof(uint8_t); writeHead += sizeof(uint8_t);
*writeHead = sessionManager_.isMeasuring(); *writeHead = sessionManager_.isMeasuring();
@ -81,17 +83,22 @@ template <typename T>
bool SessionAPI<T>::handleMessage(websockets::WebsocketsClient &client, MessageCode code, bool SessionAPI<T>::handleMessage(websockets::WebsocketsClient &client, MessageCode code,
const char *payload, size_t size) const char *payload, size_t size)
{ {
Serial.println("Handling message in SessionAPI");
switch (code) switch (code)
{ {
case MessageCode::START_SESSION: case MessageCode::START_SESSION:
Serial.println("SessionAPI: starting measurement session");
this->sessionManager_.startMeasurements(); this->sessionManager_.startMeasurements();
return true; return true;
case MessageCode::STOP_SESSION: case MessageCode::STOP_SESSION:
Serial.println("SessionAPI: stopping measurement session");
this->sessionManager_.stopMeasurements(); this->sessionManager_.stopMeasurements();
return true; return true;
case MessageCode::TARE: case MessageCode::TARE:
this->sessionManager_.tare(); this->sessionManager_.tare();
return true; return true;
default:
return false;
} }
return false; return false;
} }
@ -105,12 +112,14 @@ void SessionAPI<T>::iteration(TServer &server)
sendSessionStartMessages(server); sendSessionStartMessages(server);
for (int i = 0; i < MAX_WEBSOCKET_CONNECTIONS; ++i) for (int i = 0; i < MAX_WEBSOCKET_CONNECTIONS; ++i)
numSentMeasurements_[i] = 0; numSentMeasurements_[i] = 0;
running_ = true;
} }
else if (running_ && !sessionManager_.isMeasuring()) else if (running_ && !sessionManager_.isMeasuring())
{ {
sendSessionStopMessages(server); sendSessionStopMessages(server);
for (int i = 0; i < MAX_WEBSOCKET_CONNECTIONS; ++i) for (int i = 0; i < MAX_WEBSOCKET_CONNECTIONS; ++i)
numSentMeasurements_[i] = 0; numSentMeasurements_[i] = 0;
running_ = false;
} }
sendNewDataMessages(server); sendNewDataMessages(server);
} }
@ -121,7 +130,7 @@ void SessionAPI<T>::sendSessionStartMessages(TServer &server)
{ {
StaticJsonDocument<128> data; StaticJsonDocument<128> data;
data["sessionId"] = sessionManager_.session().getStartTime(); data["sessionId"] = sessionManager_.session().getStartTime();
server.sendToAll<32>(MessageCode::SESSION_STARTED, data); server.template sendToAll<32>(MessageCode::SESSION_STARTED, data);
} }
template <typename T> template <typename T>
@ -129,14 +138,15 @@ template <typename TServer>
void SessionAPI<T>::sendSessionStopMessages(TServer &server) void SessionAPI<T>::sendSessionStopMessages(TServer &server)
{ {
MessageCode code = MessageCode::SESSION_STOPPED; MessageCode code = MessageCode::SESSION_STOPPED;
server.sendToAll<32>(code); server.template sendToAll(code);
} }
template <typename T> template <typename T>
template <typename TServer> template <typename TServer>
void SessionAPI<T>::sendNewDataMessages(TServer &server) void SessionAPI<T>::sendNewDataMessages(TServer &server)
{ {
constexpr size_t MAX_MEASUREMENTS_PER_MSG = 16;
constexpr size_t MAX_MEASUREMENTS_PER_MSG = 15;
constexpr size_t WAIT_UNTIL_AT_LEAST_NUM_MEASUREMENTS = 1; constexpr size_t WAIT_UNTIL_AT_LEAST_NUM_MEASUREMENTS = 1;
// new data messages are the only messages not sent in msgpack format // new data messages are the only messages not sent in msgpack format
@ -144,8 +154,8 @@ void SessionAPI<T>::sendNewDataMessages(TServer &server)
using MeasurementT = typename T::MeasurementType; using MeasurementT = typename T::MeasurementType;
auto &session = sessionManager_.session(); auto &session = sessionManager_.session();
char buffer[1 + MAX_MEASUREMENTS_PER_MSG]; char buffer[1 + MAX_MEASUREMENTS_PER_MSG * sizeof(MeasurementT)];
buffer[0] = MessageCode::SESSION_NEW_DATA; buffer[0] = static_cast<char>(MessageCode::SESSION_NEW_DATA);
constexpr int headerSize = 1; constexpr int headerSize = 1;
for (int i = 0; i < MAX_WEBSOCKET_CONNECTIONS; ++i) for (int i = 0; i < MAX_WEBSOCKET_CONNECTIONS; ++i)
@ -155,14 +165,20 @@ void SessionAPI<T>::sendNewDataMessages(TServer &server)
{ {
MeasurementT *dataToSend = session.getDataPointer() + numSentMeasurements_[i]; MeasurementT *dataToSend = session.getDataPointer() + numSentMeasurements_[i];
int32_t numMeasurementsToSend = int32_t(session.numMeasurements()) - int32_t(numSentMeasurements_[i]); int32_t numMeasurementsToSend = int32_t(session.numMeasurements()) - int32_t(numSentMeasurements_[i]);
if (numMeasurementsToSend >= WAIT_UNTIL_AT_LEAST_NUM_MEASUREMENTS) if (numMeasurementsToSend >= WAIT_UNTIL_AT_LEAST_NUM_MEASUREMENTS)
{ {
//Serial.printf("-> i=%d, numSentMeasurements_[i]=%d, to send %d\n", i, numSentMeasurements_[i], numMeasurementsToSend);
if (numMeasurementsToSend > MAX_MEASUREMENTS_PER_MSG) if (numMeasurementsToSend > MAX_MEASUREMENTS_PER_MSG)
numMeasurementsToSend = MAX_MEASUREMENTS_PER_MSG; numMeasurementsToSend = MAX_MEASUREMENTS_PER_MSG;
//Serial.printf(" Sending %d measurements\n", numMeasurementsToSend);
memcpy(buffer + headerSize, dataToSend, sizeof(MeasurementT) * numMeasurementsToSend); memcpy(buffer + headerSize, dataToSend, sizeof(MeasurementT) * numMeasurementsToSend);
c.sendBinary(buffer, headerSize + sizeof(MeasurementT) * numMeasurementsToSend); c.sendBinary(buffer, headerSize + sizeof(MeasurementT) * numMeasurementsToSend);
numSentMeasurements_[i] += numMeasurementsToSend; numSentMeasurements_[i] += numMeasurementsToSend;
//Serial.printf(" Sent measurements %d\n", numSentMeasurements_[i]);
} }
} }
} }

View File

@ -40,7 +40,7 @@ public:
const size_t length = message.length(); const size_t length = message.length();
MessageCode msgCode = MessageCode((uint8_t)(data[0])); MessageCode msgCode = MessageCode((uint8_t)(data[0]));
this->handlMessageImpl(client, msgCode, data + 1, length - 1); this->handleMessageImpl(client, msgCode, data + 1, length - 1);
} }
else else
client.close(CloseReason_UnsupportedData); client.close(CloseReason_UnsupportedData);
@ -96,34 +96,34 @@ public:
private: private:
// -- Tuple calls // -- Tuple calls
template <size_t managerIdx = std::tuple_size<ApiManagerTuple>::value - 1, typename std::enable_if<managerIdx != 0, bool>::type = true> template <size_t managerIdx = 0, typename std::enable_if<(managerIdx < std::tuple_size<ApiManagerTuple>::value), bool>::type = true>
void iterationImpl() void iterationImpl()
{ {
std::get<managerIdx>(apiManagers_).iteration(*this); std::get<managerIdx>(apiManagers_).iteration(*this);
iterationImpl<managerIdx - 1>(); iterationImpl<managerIdx + 1>();
} }
template <size_t managerIdx, typename std::enable_if<managerIdx == 0, bool>::type = true> template <size_t managerIdx, typename std::enable_if<managerIdx == std::tuple_size<ApiManagerTuple>::value, bool>::type = true>
void iterationImpl() {} void iterationImpl() {}
template <size_t managerIdx = std::tuple_size<ApiManagerTuple>::value - 1, typename std::enable_if<managerIdx != 0, bool>::type = true> template <size_t managerIdx = 0, typename std::enable_if<(managerIdx < std::tuple_size<ApiManagerTuple>::value), bool>::type = true>
bool handlMessageImpl(websockets::WebsocketsClient &client, MessageCode code, const char *payload, size_t size) bool handleMessageImpl(websockets::WebsocketsClient &client, MessageCode code, const char *payload, size_t size)
{ {
bool handled = std::get<managerIdx>(apiManagers_).handleMessage(client, code, payload, size); bool handled = std::get<managerIdx>(apiManagers_).handleMessage(client, code, payload, size);
if (handled) if (handled)
return true; return true;
else else
return handlMessageImpl<managerIdx - 1>(client, code, payload, size); return handleMessageImpl<managerIdx + 1>(client, code, payload, size);
} }
template <size_t managerIdx, typename std::enable_if<managerIdx == 0, bool>::type = true> template <size_t managerIdx, typename std::enable_if<managerIdx == std::tuple_size<ApiManagerTuple>::value, bool>::type = true>
bool handlMessageImpl(websockets::WebsocketsClient &, MessageCode, const char *, size_t) { return false; } bool handleMessageImpl(websockets::WebsocketsClient &, MessageCode, const char *, size_t) { return false; }
template <size_t managerIdx = std::tuple_size<ApiManagerTuple>::value - 1, typename std::enable_if<managerIdx != 0, bool>::type = true> template <size_t managerIdx = 0, typename std::enable_if<(managerIdx < std::tuple_size<ApiManagerTuple>::value), bool>::type = true>
void onClientConnectImpl(websockets::WebsocketsClient &client) void onClientConnectImpl(websockets::WebsocketsClient &client)
{ {
std::get<managerIdx>(apiManagers_).onClientConnect(client); std::get<managerIdx>(apiManagers_).onClientConnect(client);
onClientConnectImpl<managerIdx - 1>(client); onClientConnectImpl<managerIdx + 1>(client);
} }
template <size_t managerIdx, typename std::enable_if<managerIdx == 0, bool>::type = true> template <size_t managerIdx, typename std::enable_if<managerIdx == std::tuple_size<ApiManagerTuple>::value, bool>::type = true>
void onClientConnectImpl(websockets::WebsocketsClient &client) {} void onClientConnectImpl(websockets::WebsocketsClient &client) {}
// -- Members // -- Members

View File

@ -26,7 +26,7 @@ bool WifiAPI::handleMessage(websockets::WebsocketsClient &client, MessageCode co
{ {
StaticJsonDocument<1024> json; StaticJsonDocument<1024> json;
DeserializationError err = deserializeJson(json, payload, size); DeserializationError err = deserializeMsgPack(json, payload, size);
if (err) if (err)
{ {
sendErrorToClient(client, "Deserialization Error"); sendErrorToClient(client, "Deserialization Error");
@ -34,18 +34,21 @@ bool WifiAPI::handleMessage(websockets::WebsocketsClient &client, MessageCode co
} }
if (json.containsKey("reset_to_provisioning") && json["reset_to_provisioning"].as<bool>()) if (json.containsKey("reset_to_provisioning") && json["reset_to_provisioning"].as<bool>())
{ {
Serial.println("wifi: reset_to_provisioning");
wifiManager_.resetToApProvisioning(); wifiManager_.resetToApProvisioning();
restartScheduled_ = true; restartScheduled_ = true;
return true; return true;
} }
else if (json.containsKey("ap_password")) else if (json.containsKey("ap_password"))
{ {
Serial.println("wifi: ap_password");
wifiManager_.setApCredentials(json["ap_password"].as<const char *>()); wifiManager_.setApCredentials(json["ap_password"].as<const char *>());
restartScheduled_ = true; restartScheduled_ = true;
return true; return true;
} }
else if (json.containsKey("sta_ssid") && json.containsKey("sta_password")) else if (json.containsKey("sta_ssid") && json.containsKey("sta_password"))
{ {
Serial.println("wifi: sta_ssid");
wifiManager_.setStaCredentials(json["sta_ssid"].as<const char *>(), // wifiManager_.setStaCredentials(json["sta_ssid"].as<const char *>(), //
json["sta_password"].as<const char *>()); json["sta_password"].as<const char *>());
restartScheduled_ = true; restartScheduled_ = true;

View File

@ -36,7 +36,6 @@ EspHttp espHttpServer;
WifiManager wifiManager; WifiManager wifiManager;
auto apiTuple = std::make_tuple(SessionAPI<Session_T>(sessionManager), WifiAPI(wifiManager)); auto apiTuple = std::make_tuple(SessionAPI<Session_T>(sessionManager), WifiAPI(wifiManager));
WebsocketServer<decltype(apiTuple)> websocketServer(81, apiTuple); WebsocketServer<decltype(apiTuple)> websocketServer(81, apiTuple);
@ -44,6 +43,15 @@ WebsocketServer<decltype(apiTuple)> websocketServer(81, apiTuple);
extern const uint8_t certificate_pem[] asm("_binary_certificate_pem_start"); extern const uint8_t certificate_pem[] asm("_binary_certificate_pem_start");
String getIdSuffix()
{
uint8_t baseMac[6];
esp_read_mac(baseMac, ESP_MAC_WIFI_STA);
char baseMacChr[18] = {0};
sprintf(baseMacChr, "-%02X%02X%02X", baseMac[3], baseMac[4], baseMac[5]);
return String(baseMacChr);
}
bool firmwareUpdate() bool firmwareUpdate()
{ {
esp_http_client_config_t config; esp_http_client_config_t config;
@ -178,6 +186,24 @@ void httpSetup(SessionManager<SessionT> *sessionManager, WifiManager *wifiManage
firmware["compile_date"] = descr->date; firmware["compile_date"] = descr->date;
firmware["compile_time"] = descr->time; firmware["compile_time"] = descr->time;
} }
// device ids
{
uint8_t baseMac[6];
esp_read_mac(baseMac, ESP_MAC_WIFI_STA);
char baseMacChr[18] = {0};
sprintf(baseMacChr, "%02X%02X%02X%02X%02X%02X",
baseMac[0], baseMac[1], baseMac[2], baseMac[3], baseMac[4], baseMac[5]);
esp_chip_info_t chipInfo;
esp_chip_info(&chipInfo);
char modelString[16];
sprintf(modelString, "%d.%d", chipInfo.model, chipInfo.revision);
JsonObject device = json.createNestedObject("device");
device["mac"] = baseMacChr;
device["chip"] = modelString;
device["unique_name"] = "swimtracker" + getIdSuffix();
}
char jsonText[512]; char jsonText[512];
auto bytesWritten = serializeJson(json, jsonText); auto bytesWritten = serializeJson(json, jsonText);
httpd_resp_send(req, jsonText, bytesWritten); httpd_resp_send(req, jsonText, bytesWritten);
@ -186,7 +212,7 @@ void httpSetup(SessionManager<SessionT> *sessionManager, WifiManager *wifiManage
{ {
auto sessionId = sessionManager->session().getStartTime(); auto sessionId = sessionManager->session().getStartTime();
uint32_t startIdx = getUrlQueryParameter(req, "startIdx", 0); uint32_t startIdx = getUrlQueryParameter(req, "startIdx", 0);
//Serial.printf("Data request, start index: %d\n", startIdx);
if (startIdx >= sessionManager->session().numMeasurements()) if (startIdx >= sessionManager->session().numMeasurements())
{ {
httpd_resp_send_404(req); httpd_resp_send_404(req);
@ -284,6 +310,8 @@ void httpSetup(SessionManager<SessionT> *sessionManager, WifiManager *wifiManage
json["autoStopNumMeasurements"] = prefs.getUInt("aStopCount", CONFIG_AUTO_STOP_NUM_MEASUREMENTS); json["autoStopNumMeasurements"] = prefs.getUInt("aStopCount", CONFIG_AUTO_STOP_NUM_MEASUREMENTS);
json["autoStartEnabled"] = prefs.getBool("aStartEnabled", true); json["autoStartEnabled"] = prefs.getBool("aStartEnabled", true);
json["autoStopEnabled"] = prefs.getBool("aStopEnabled", true); json["autoStopEnabled"] = prefs.getBool("aStopEnabled", true);
json["hostname"] = prefs.getString("hostname", CONFIG_HOSTNAME + getIdSuffix());
char jsonText[1024]; char jsonText[1024];
auto bytesWritten = serializeJson(json, jsonText); auto bytesWritten = serializeJson(json, jsonText);
httpd_resp_send(req, jsonText, bytesWritten); httpd_resp_send(req, jsonText, bytesWritten);
@ -329,6 +357,8 @@ void httpSetup(SessionManager<SessionT> *sessionManager, WifiManager *wifiManage
prefs.putBool("aStartEnabled", json["autoStartEnabled"].as<bool>()); prefs.putBool("aStartEnabled", json["autoStartEnabled"].as<bool>());
if (json.containsKey("autoStopEnabled")) if (json.containsKey("autoStopEnabled"))
prefs.putBool("aStopEnabled", json["autoStopEnabled"].as<bool>()); prefs.putBool("aStopEnabled", json["autoStopEnabled"].as<bool>());
if (json.containsKey("hostname"))
prefs.putString("hostname", json["hostname"].as<String>());
sessionManagerSetup(); sessionManagerSetup();
httpd_resp_send(req, "OK", -1); httpd_resp_send(req, "OK", -1);
@ -347,6 +377,7 @@ void httpSetup(SessionManager<SessionT> *sessionManager, WifiManager *wifiManage
prefs.putUInt("aStopCount", CONFIG_AUTO_STOP_NUM_MEASUREMENTS); prefs.putUInt("aStopCount", CONFIG_AUTO_STOP_NUM_MEASUREMENTS);
prefs.putBool("aStartEnabled", true); prefs.putBool("aStartEnabled", true);
prefs.putBool("aStopEnabled", true); prefs.putBool("aStopEnabled", true);
prefs.putBool("hostname", CONFIG_HOSTNAME + getIdSuffix());
httpd_resp_send(req, "OK", -1); httpd_resp_send(req, "OK", -1);
}; };
@ -386,15 +417,6 @@ void httpSetup(SessionManager<SessionT> *sessionManager, WifiManager *wifiManage
} }
} }
String getIdSuffix()
{
uint8_t baseMac[6];
esp_read_mac(baseMac, ESP_MAC_WIFI_STA);
char baseMacChr[18] = {0};
sprintf(baseMacChr, "-%02X%02X%02X", baseMac[3], baseMac[4], baseMac[5]);
return String(baseMacChr);
}
void mdnsSetup(const String &fullHostname) void mdnsSetup(const String &fullHostname)
{ {
if (!MDNS.begin(fullHostname.c_str())) if (!MDNS.begin(fullHostname.c_str()))
@ -427,13 +449,15 @@ void setup()
userStorage.init(); userStorage.init();
// WiFi // WiFi
String fullHostname = String(CONFIG_HOSTNAME) + getIdSuffix(); Preferences prefs;
wifiManager.begin(fullHostname); String uniqueName = "swimtracker" + getIdSuffix();
String configuredHostname = prefs.getString("hostname", CONFIG_HOSTNAME + getIdSuffix());
wifiManager.begin(configuredHostname, uniqueName);
Serial.print("Connected to WiFi. IP:"); Serial.print("Connected to WiFi. IP:");
Serial.println(WiFi.localIP()); Serial.println(WiFi.localIP());
Serial.printf("WIFI state: %s\n", wifiManager.stateStr()); Serial.printf("WIFI state: %s\n", wifiManager.stateStr());
mdnsSetup(fullHostname); mdnsSetup(configuredHostname);
sessionManagerSetup(); sessionManagerSetup();
sessionManager.tare(); sessionManager.tare();