Set BearSSL as ESP8266 HTTPS library for notifications

Fix M117 not used for printer output
Add WiFi Off / Radio Off printer message when starting without radio mode
Add BT On when starting BT
Fix starting WIFi STA on ESP32 raise wifi not start and hostname set failed when  network previously set to OFF
Use Serial instead of all clients  for starting network message
Set version to 43
This commit is contained in:
Luc 2020-05-31 18:03:45 +02:00
parent 6f5a24160f
commit 70a72ff8f3
9 changed files with 100 additions and 43 deletions

View File

@ -147,10 +147,10 @@
#define DIRECT_PIN_FEATURE #define DIRECT_PIN_FEATURE
//TIMESTAMP_FEATURE: set time system //TIMESTAMP_FEATURE: set time system
//#define TIMESTAMP_FEATURE #define TIMESTAMP_FEATURE
//FILESYSTEM_TIMESTAMP_FEATURE: display last write time from Flash files //FILESYSTEM_TIMESTAMP_FEATURE: display last write time from Flash files
//#define FILESYSTEM_TIMESTAMP_FEATURE #define FILESYSTEM_TIMESTAMP_FEATURE
//FILESYSTEM_TIMESTAMP_FEATURE:display last write time from SD files //FILESYSTEM_TIMESTAMP_FEATURE:display last write time from SD files
//#define SD_TIMESTAMP_FEATURE //#define SD_TIMESTAMP_FEATURE
@ -175,6 +175,13 @@
//NOTIFICATION_FEATURE : allow to push notifications //NOTIFICATION_FEATURE : allow to push notifications
#define NOTIFICATION_FEATURE #define NOTIFICATION_FEATURE
//For ESP8266 Only, it define which secure client to use AXTls or BearSSL
//#define USING_AXTLS
//if not using AXTLS need to decrease size of packet to not be OOM
#define BEARSSL_MFLN_SIZE 512
#define BEARSSL_MFLN_SIZE_FALLBACK 4096
//CAMERA_DEVICE: Enable the support of connected camera //CAMERA_DEVICE: Enable the support of connected camera
//CAMERA_MODEL_CUSTOM 0 //Edit the pins in include/pins.h //CAMERA_MODEL_CUSTOM 0 //Edit the pins in include/pins.h
//CAMERA_MODEL_ESP_EYE 1 //CAMERA_MODEL_ESP_EYE 1

View File

@ -211,13 +211,17 @@ size_t ESP3DOutput::printMSG(const char * s, bool withNL)
return 0; return 0;
} }
#endif //HTTP_FEATURE #endif //HTTP_FEATURE
if (_client == ESP_PRINTER_LCD_CLIENT) { if (_client & ESP_PRINTER_LCD_CLIENT) {
display = "M117 "; if (isOutput(ESP_PRINTER_LCD_CLIENT)) {
display+= s; display= "M117 ";
return printLN(display.c_str()); display+= s;
return printLN(display.c_str());
} else {
return printLN(s);
}
} }
if (_client == ESP_SCREEN_CLIENT) { if (_client & ESP_SCREEN_CLIENT) {
return print(s); print(s);
} }
switch(Settings_ESP3D::GetFirmwareTarget()) { switch(Settings_ESP3D::GetFirmwareTarget()) {
case GRBL: case GRBL:

View File

@ -22,7 +22,7 @@
#define _VERSION_ESP3D_H #define _VERSION_ESP3D_H
//version and sources location //version and sources location
#define FW_VERSION "3.0.0.a42" #define FW_VERSION "3.0.0.a43"
#define REPOSITORY "https://github.com/luc-github/ESP3D/tree/3.0" #define REPOSITORY "https://github.com/luc-github/ESP3D/tree/3.0"
#endif //_VERSION_ESP3D_H #endif //_VERSION_ESP3D_H

View File

@ -375,7 +375,7 @@ bool Camera::begin(bool forceinit)
log_esp3d("Cannot access camera sensor"); log_esp3d("Cannot access camera sensor");
} }
if (NetConfig::started() && (NetConfig::getMode()!= ESP_BT)) { if (NetConfig::started() && (NetConfig::getMode()!= ESP_BT)) {
ESP3DOutput output(ESP_ALL_CLIENTS); ESP3DOutput output(ESP_SERIAL_CLIENT);
httpd_config_t httpdconfig = HTTPD_DEFAULT_CONFIG(); httpd_config_t httpdconfig = HTTPD_DEFAULT_CONFIG();
httpdconfig.close_fn =&disconnected_uri; httpdconfig.close_fn =&disconnected_uri;
httpd_uri_t stream_uri = { httpd_uri_t stream_uri = {

View File

@ -90,7 +90,7 @@ bool EthConfig::StartSTA()
bool EthConfig::begin() bool EthConfig::begin()
{ {
bool res = false; bool res = false;
ESP3DOutput output(ESP_ALL_CLIENTS); ESP3DOutput output(ESP_SERIAL_CLIENT);
end(); end();
_started = ETH.begin(); _started = ETH.begin();
if (_started) { if (_started) {
@ -99,10 +99,7 @@ bool EthConfig::begin()
} else { } else {
output.printERROR("Failed Starting Ethernet"); output.printERROR("Failed Starting Ethernet");
} }
if (!ETH.setHostname(NetConfig::hostname(true))) { ETH.setHostname(NetConfig::hostname(true));
res = false;
log_esp3d("Set Hostname error");
}
int8_t espMode =Settings_ESP3D::read_byte(ESP_RADIO_MODE); int8_t espMode =Settings_ESP3D::read_byte(ESP_RADIO_MODE);
//DHCP is only for Client //DHCP is only for Client

View File

@ -25,8 +25,10 @@
#define WIFI_EVENT_STAMODE_DISCONNECTED SYSTEM_EVENT_STA_DISCONNECTED #define WIFI_EVENT_STAMODE_DISCONNECTED SYSTEM_EVENT_STA_DISCONNECTED
#define WIFI_EVENT_STAMODE_GOT_IP SYSTEM_EVENT_STA_GOT_IP #define WIFI_EVENT_STAMODE_GOT_IP SYSTEM_EVENT_STA_GOT_IP
#define WIFI_EVENT_SOFTAPMODE_STACONNECTED SYSTEM_EVENT_AP_STACONNECTED #define WIFI_EVENT_SOFTAPMODE_STACONNECTED SYSTEM_EVENT_AP_STACONNECTED
#define RADIO_OFF_MSG "Radio Off"
#endif //ARDUINO_ARCH_ESP32 #endif //ARDUINO_ARCH_ESP32
#ifdef ARDUINO_ARCH_ESP8266 #ifdef ARDUINO_ARCH_ESP8266
#define RADIO_OFF_MSG "WiFi Off"
#endif //ARDUINO_ARCH_ESP8266 #endif //ARDUINO_ARCH_ESP8266
#include "netconfig.h" #include "netconfig.h"
#if defined (WIFI_FEATURE) #if defined (WIFI_FEATURE)
@ -165,8 +167,6 @@ void NetConfig::onWiFiEvent(WiFiEvent_t event)
} }
break; break;
case WIFI_EVENT_STAMODE_GOT_IP: { case WIFI_EVENT_STAMODE_GOT_IP: {
output.printMSG ("Connected");
ESP3DGlobalOutput::SetStatus("Connected");
ESP3DGlobalOutput::display_IP(); ESP3DGlobalOutput::display_IP();
output.printMSG (WiFi.localIP().toString().c_str()); output.printMSG (WiFi.localIP().toString().c_str());
} }
@ -218,7 +218,7 @@ bool NetConfig::begin()
//clear everything //clear everything
end(); end();
int8_t espMode =Settings_ESP3D::read_byte(ESP_RADIO_MODE); int8_t espMode =Settings_ESP3D::read_byte(ESP_RADIO_MODE);
ESP3DOutput output(ESP_ALL_CLIENTS); ESP3DOutput output(ESP_SERIAL_CLIENT);
if (espMode != NO_NETWORK) { if (espMode != NO_NETWORK) {
output.printMSG("Starting Network"); output.printMSG("Starting Network");
} }
@ -240,7 +240,12 @@ bool NetConfig::begin()
_hostname = Settings_ESP3D::read_string(ESP_HOSTNAME); _hostname = Settings_ESP3D::read_string(ESP_HOSTNAME);
_mode = espMode; _mode = espMode;
if (espMode == NO_NETWORK) { if (espMode == NO_NETWORK) {
WiFi.mode(WIFI_OFF);
ESP3DGlobalOutput::display_IP(); ESP3DGlobalOutput::display_IP();
ESP3DOutput output(ESP_ALL_CLIENTS);
ESP3DGlobalOutput::SetStatus(RADIO_OFF_MSG);
output.printMSG(RADIO_OFF_MSG);
output.flush();
return true; return true;
} }
#if defined (WIFI_FEATURE) #if defined (WIFI_FEATURE)
@ -255,11 +260,18 @@ bool NetConfig::begin()
#if defined (ETH_FEATURE) #if defined (ETH_FEATURE)
//if ((espMode == ESP_ETH_STA) || (espMode == ESP_ETH_SRV)) { //if ((espMode == ESP_ETH_STA) || (espMode == ESP_ETH_SRV)) {
if ((espMode == ESP_ETH_STA)) { if ((espMode == ESP_ETH_STA)) {
WiFi.mode(WIFI_OFF);
res = EthConfig::begin(); res = EthConfig::begin();
} }
#endif //ETH_FEATURE #endif //ETH_FEATURE
#if defined (BLUETOOTH_FEATURE) #if defined (BLUETOOTH_FEATURE)
if ((espMode == ESP_BT)) { if ((espMode == ESP_BT)) {
WiFi.mode(WIFI_OFF);
ESP3DOutput output(ESP_ALL_CLIENTS);
String msg = "BT On";
ESP3DGlobalOutput::SetStatus(msg.c_str());
output.printMSG(msg.c_str());
output.flush();
res = bt_service.begin(); res = bt_service.begin();
} }
#endif //BLUETOOTH_FEATURE #endif //BLUETOOTH_FEATURE
@ -320,11 +332,9 @@ void NetConfig::end()
#if defined (ETH_FEATURE) #if defined (ETH_FEATURE)
EthConfig::end(); EthConfig::end();
#endif //ETH_FEATURE #endif //ETH_FEATURE
ESP3DOutput output(ESP_ALL_CLIENTS);
#if defined (BLUETOOTH_FEATURE) #if defined (BLUETOOTH_FEATURE)
bt_service.end(); bt_service.end();
#endif //BLUETOOTH_FEATURE #endif //BLUETOOTH_FEATURE
output.printMSG("Network Off");
_started = false; _started = false;
} }

View File

@ -87,7 +87,7 @@ bool NetServices::begin()
bool res = true; bool res = true;
_started = false; _started = false;
String hostname = Settings_ESP3D::read_string(ESP_HOSTNAME); String hostname = Settings_ESP3D::read_string(ESP_HOSTNAME);
ESP3DOutput output(ESP_ALL_CLIENTS); ESP3DOutput output(ESP_SERIAL_CLIENT);
end(); end();
#ifdef TIMESTAMP_FEATURE #ifdef TIMESTAMP_FEATURE
if (WiFi.getMode() != WIFI_AP) { if (WiFi.getMode() != WIFI_AP) {
@ -96,7 +96,7 @@ bool NetServices::begin()
output.printERROR("Failed contact time servers!"); output.printERROR("Failed contact time servers!");
} }
} else { } else {
String tmp = "Time set :"; String tmp = "Current time :";
tmp+=timeserver.current_time(); tmp+=timeserver.current_time();
output.printMSG(tmp.c_str()); output.printMSG(tmp.c_str());
} }
@ -241,7 +241,7 @@ bool NetServices::begin()
#ifdef MDNS_FEATURE #ifdef MDNS_FEATURE
if(WiFi.getMode() != WIFI_AP) { if(WiFi.getMode() != WIFI_AP) {
// Add service to MDNS-SD // Add service to MDNS-SD
MDNS.addService("http", "tcp", 80); MDNS.addService("http", "tcp", HTTP_Server::port());
// TODO add TXT records // TODO add TXT records
//MDNS.addServiceTxt("http", "tcp", Key, value); //MDNS.addServiceTxt("http", "tcp", Key, value);
} }
@ -307,12 +307,17 @@ void NetServices::end()
#endif //ARDUINO_ARCH_ESP32 #endif //ARDUINO_ARCH_ESP32
#endif //SSDP_FEATURE #endif //SSDP_FEATURE
#ifdef MDNS_FEATURE #ifdef MDNS_FEATURE
#if defined(ARDUINO_ARCH_ESP32)
if(WiFi.getMode() != WIFI_AP) { if(WiFi.getMode() != WIFI_AP) {
#if defined(ARDUINO_ARCH_ESP8266)
String hostname = Settings_ESP3D::read_string(ESP_HOSTNAME);
hostname.toLowerCase();
MDNS.removeService(hostname.c_str(),"http", "tcp");
#endif // ARDUINO_ARCH_ESP8266
#if defined(ARDUINO_ARCH_ESP32)
mdns_service_remove("_http", "_tcp"); mdns_service_remove("_http", "_tcp");
#endif // ARDUINO_ARCH_ESP32
MDNS.end(); MDNS.end();
} }
#endif // ARDUINO_ARCH_ESP32
#endif //MDNS_FEATURE #endif //MDNS_FEATURE
#ifdef OTA_FEATURE #ifdef OTA_FEATURE

View File

@ -38,7 +38,6 @@
#include "../network/netconfig.h" #include "../network/netconfig.h"
#if defined( ARDUINO_ARCH_ESP8266) #if defined( ARDUINO_ARCH_ESP8266)
#define USING_AXTLS
#if defined(USING_AXTLS) #if defined(USING_AXTLS)
#include "WiFiClientSecureAxTLS.h" #include "WiFiClientSecureAxTLS.h"
using namespace axTLS; using namespace axTLS;
@ -196,6 +195,13 @@ bool NotificationsService::sendPushoverMSG(const char * title, const char * mess
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#if defined(ARDUINO_ARCH_ESP8266) && !defined(USING_AXTLS) #if defined(ARDUINO_ARCH_ESP8266) && !defined(USING_AXTLS)
Notificationclient.setInsecure(); Notificationclient.setInsecure();
if (Notificationclient.probeMaxFragmentLength(_serveraddress.c_str(), _port, BEARSSL_MFLN_SIZE)) {
log_esp3d("Handshake success");
Notificationclient.setBufferSizes(BEARSSL_MFLN_SIZE, 512);
} else {
log_esp3d("Handshake failed");
Notificationclient.setBufferSizes(BEARSSL_MFLN_SIZE_FALLBACK, 512);
}
#endif //ARDUINO_ARCH_ESP8266 && !USING_AXTLS #endif //ARDUINO_ARCH_ESP8266 && !USING_AXTLS
if (!Notificationclient.connect(_serveraddress.c_str(), _port)) { if (!Notificationclient.connect(_serveraddress.c_str(), _port)) {
log_esp3d("Error connecting server %s:%d", _serveraddress.c_str(), _port); log_esp3d("Error connecting server %s:%d", _serveraddress.c_str(), _port);
@ -237,6 +243,13 @@ bool NotificationsService::sendTelegramMSG(const char * title, const char * mess
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#if defined(ARDUINO_ARCH_ESP8266) && !defined(USING_AXTLS) #if defined(ARDUINO_ARCH_ESP8266) && !defined(USING_AXTLS)
Notificationclient.setInsecure(); Notificationclient.setInsecure();
if (Notificationclient.probeMaxFragmentLength(_serveraddress.c_str(), _port, BEARSSL_MFLN_SIZE)) {
log_esp3d("Handshake success");
Notificationclient.setBufferSizes(BEARSSL_MFLN_SIZE, 512);
} else {
log_esp3d("Handshake failed");
Notificationclient.setBufferSizes(BEARSSL_MFLN_SIZE_FALLBACK, 512);
}
#endif //ARDUINO_ARCH_ESP8266 && !USING_AXTLS #endif //ARDUINO_ARCH_ESP8266 && !USING_AXTLS
if (!Notificationclient.connect(_serveraddress.c_str(), _port)) { if (!Notificationclient.connect(_serveraddress.c_str(), _port)) {
log_esp3d("Error connecting server %s:%d", _serveraddress.c_str(), _port); log_esp3d("Error connecting server %s:%d", _serveraddress.c_str(), _port);
@ -272,6 +285,13 @@ bool NotificationsService::sendEmailMSG(const char * title, const char * message
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#if defined(ARDUINO_ARCH_ESP8266) && !defined(USING_AXTLS) #if defined(ARDUINO_ARCH_ESP8266) && !defined(USING_AXTLS)
Notificationclient.setInsecure(); Notificationclient.setInsecure();
if (Notificationclient.probeMaxFragmentLength(_serveraddress.c_str(), _port, BEARSSL_MFLN_SIZE)) {
log_esp3d("Handshake success");
Notificationclient.setBufferSizes(BEARSSL_MFLN_SIZE, 512);
} else {
log_esp3d("Handshake failed");
Notificationclient.setBufferSizes(BEARSSL_MFLN_SIZE_FALLBACK, 512);
}
#endif //ARDUINO_ARCH_ESP8266 && !USING_AXTLS #endif //ARDUINO_ARCH_ESP8266 && !USING_AXTLS
log_esp3d("Connect to server"); log_esp3d("Connect to server");
if (!Notificationclient.connect(_serveraddress.c_str(), _port)) { if (!Notificationclient.connect(_serveraddress.c_str(), _port)) {
@ -368,6 +388,13 @@ bool NotificationsService::sendLineMSG(const char * title, const char * message)
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#if defined(ARDUINO_ARCH_ESP8266) && !defined(USING_AXTLS) #if defined(ARDUINO_ARCH_ESP8266) && !defined(USING_AXTLS)
Notificationclient.setInsecure(); Notificationclient.setInsecure();
if (Notificationclient.probeMaxFragmentLength(_serveraddress.c_str(), _port, BEARSSL_MFLN_SIZE)) {
log_esp3d("Handshake success");
Notificationclient.setBufferSizes(BEARSSL_MFLN_SIZE, 512);
} else {
log_esp3d("Handshake failed");
Notificationclient.setBufferSizes(BEARSSL_MFLN_SIZE_FALLBACK, 512);
}
#endif //ARDUINO_ARCH_ESP8266 && !USING_AXTLS #endif //ARDUINO_ARCH_ESP8266 && !USING_AXTLS
(void)title; (void)title;
if (!Notificationclient.connect(_serveraddress.c_str(), _port)) { if (!Notificationclient.connect(_serveraddress.c_str(), _port)) {

View File

@ -162,15 +162,26 @@ bool WiFiConfig::ConnectSTA2AP()
*/ */
bool WiFiConfig::StartSTA() bool WiFiConfig::StartSTA()
{ {
#if defined (ARDUINO_ARCH_ESP32)
esp_wifi_start();
#endif //ARDUINO_ARCH_ESP32
//Sanity check //Sanity check
if((WiFi.getMode() == WIFI_STA) || (WiFi.getMode() == WIFI_AP_STA)) { if((WiFi.getMode() == WIFI_STA) || (WiFi.getMode() == WIFI_AP_STA)) {
WiFi.disconnect(); if(WiFi.isConnected()) {
WiFi.disconnect();
} else {
WiFi.begin();
}
} }
if((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) { if((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) {
WiFi.softAPdisconnect(); WiFi.softAPdisconnect();
} }
WiFi.enableAP (false); WiFi.enableAP (false);
WiFi.enableSTA (true);
WiFi.mode(WIFI_STA); WiFi.mode(WIFI_STA);
#if defined (ARDUINO_ARCH_ESP32)
esp_wifi_start();
#endif //ARDUINO_ARCH_ESP32
//Get parameters for STA //Get parameters for STA
String SSID = Settings_ESP3D::read_string(ESP_STA_SSID); String SSID = Settings_ESP3D::read_string(ESP_STA_SSID);
String password = Settings_ESP3D::read_string(ESP_STA_PASSWORD); String password = Settings_ESP3D::read_string(ESP_STA_PASSWORD);
@ -182,16 +193,14 @@ bool WiFiConfig::StartSTA()
IPAddress ip(IP), mask(MK), gateway(GW); IPAddress ip(IP), mask(MK), gateway(GW);
WiFi.config(ip, gateway,mask); WiFi.config(ip, gateway,mask);
} }
ESP3DOutput output(ESP_ALL_CLIENTS); ESP3DOutput output(ESP_SERIAL_CLIENT);
String stmp; String stmp;
stmp = "Connecting to '" + SSID + "'";; stmp = "Connecting to '" + SSID + "'";;
output.printMSG(stmp.c_str()); output.printMSG(stmp.c_str());
if (WiFi.begin(SSID.c_str(), (password.length() > 0)?password.c_str():nullptr)) { if (WiFi.begin(SSID.c_str(), (password.length() > 0)?password.c_str():nullptr)) {
#if defined (ARDUINO_ARCH_ESP8266) #if defined (ARDUINO_ARCH_ESP8266)
WiFi.setSleepMode(WIFI_NONE_SLEEP); WiFi.setSleepMode(WIFI_NONE_SLEEP);
if (!WiFi.hostname(NetConfig::hostname(true))) { WiFi.hostname(NetConfig::hostname(true));
output.printERROR("Set hostname STA failed");
}
#endif //ARDUINO_ARCH_ESP8266 #endif //ARDUINO_ARCH_ESP8266
#if defined (ARDUINO_ARCH_ESP32) #if defined (ARDUINO_ARCH_ESP32)
WiFi.setSleep(false); WiFi.setSleep(false);
@ -213,7 +222,9 @@ bool WiFiConfig::StartAP()
ESP3DOutput output(ESP_ALL_CLIENTS); ESP3DOutput output(ESP_ALL_CLIENTS);
//Sanity check //Sanity check
if((WiFi.getMode() == WIFI_STA) || (WiFi.getMode() == WIFI_AP_STA)) { if((WiFi.getMode() == WIFI_STA) || (WiFi.getMode() == WIFI_AP_STA)) {
WiFi.disconnect(); if(WiFi.isConnected()) {
WiFi.disconnect();
}
} }
if((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) { if((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) {
WiFi.softAPdisconnect(); WiFi.softAPdisconnect();
@ -223,10 +234,6 @@ bool WiFiConfig::StartAP()
//Set Sleep Mode to none //Set Sleep Mode to none
#if defined (ARDUINO_ARCH_ESP8266) #if defined (ARDUINO_ARCH_ESP8266)
WiFi.setSleepMode(WIFI_NONE_SLEEP); WiFi.setSleepMode(WIFI_NONE_SLEEP);
//No API for it
//if(!WiFi.hostname(NetConfig::hostname(true))){
// output.printERROR("Set hostname AP failed");
//}
#endif //ARDUINO_ARCH_ESP8266 #endif //ARDUINO_ARCH_ESP8266
String SSID = Settings_ESP3D::read_string(ESP_AP_SSID); String SSID = Settings_ESP3D::read_string(ESP_AP_SSID);
@ -256,9 +263,7 @@ bool WiFiConfig::StartAP()
//must be done after starting AP not before //must be done after starting AP not before
#if defined (ARDUINO_ARCH_ESP32) #if defined (ARDUINO_ARCH_ESP32)
WiFi.setSleep(false); WiFi.setSleep(false);
if (!WiFi.softAPsetHostname(NetConfig::hostname(true))) { WiFi.softAPsetHostname(NetConfig::hostname(true));
output.printERROR("Set hostname AP failed");
}
#endif //ARDUINO_ARCH_ESP32 #endif //ARDUINO_ARCH_ESP32
return true; return true;
} else { } else {
@ -302,14 +307,16 @@ void WiFiConfig::end()
{ {
//Sanity check //Sanity check
if((WiFi.getMode() == WIFI_STA) || (WiFi.getMode() == WIFI_AP_STA)) { if((WiFi.getMode() == WIFI_STA) || (WiFi.getMode() == WIFI_AP_STA)) {
WiFi.disconnect(true); if(WiFi.isConnected()) {
WiFi.disconnect(true);
}
} }
if((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) { if((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) {
WiFi.softAPdisconnect(true); if(WiFi.isConnected()) {
WiFi.softAPdisconnect(true);
}
} }
WiFi.mode(WIFI_OFF); WiFi.mode(WIFI_OFF);
ESP3DOutput output(ESP_ALL_CLIENTS);
output.printMSG("WiFi Off");
} }
/** /**