diff --git a/Documentation/UserManual/BasicMenu.jpg b/Documentation/UserManual/BasicMenu.jpg index 1fc5421..f5136d6 100644 Binary files a/Documentation/UserManual/BasicMenu.jpg and b/Documentation/UserManual/BasicMenu.jpg differ diff --git a/platformio.ini b/platformio.ini index b244765..dc89ea9 100644 --- a/platformio.ini +++ b/platformio.ini @@ -19,7 +19,8 @@ upload_speed = 921600 ;upload_port = 192.168.20.120 ;upload_flags = ; --port=3232 -upload_port = COM5 +upload_port = COM14 +;upload_port = COM5 upload_protocol = esptool ;monitor_speed = 115200 extra_scripts = post:add_CRC.py diff --git a/src/Afterburner.cpp b/src/Afterburner.cpp index 129daab..ae5eb18 100644 --- a/src/Afterburner.cpp +++ b/src/Afterburner.cpp @@ -118,6 +118,7 @@ #include "Utility/MQTTsetup.h" #include #include "RTC/TimerManager.h" +#include "Utility/GetLine.h" // SSID & password now stored in NV storage - these are still the default values. //#define AP_SSID "Afterburner" @@ -197,7 +198,6 @@ CMQTTsetup MQTTmenu; -sRxLine PCline; long lastRxTime; // used to observe inter character delays bool bHasOEMController = false; bool bHasOEMLCDController = false; @@ -439,11 +439,9 @@ void setup() { #if USE_WIFI == 1 - sCredentials creds = NVstore.getCredentials(); // local AP credentials -// if(NVstore.getUserSettings().enableWifi) { if(NVstore.getUserSettings().wifiMode) { - initWifi(creds.SSID, creds.APpassword); // SSID and passowrd the the ESP32's inbuilt AP + initWifi(); #if USE_OTA == 1 if(NVstore.getUserSettings().enableOTA) { initOTA(); @@ -523,6 +521,8 @@ void setup() { pHourMeter->init(bESP32PowerUpInit || RTC_Store.getBootInit()); // ensure persistent memory variable are reset after powerup, or OTA update RTC_Store.setBootInit(false); + reqDemand(RTC_Store.getDesiredTemp()); // bug fix: was not applying saved set point! + // Check for solo DS18B20 // store it's serial number as the primary sensor // This allows seamless standard operation, and marks the iniital sensor @@ -1366,6 +1366,7 @@ void checkDebugCommands() static uint8_t nGetConf = 0; static String pw1; static String pw2; + static CGetLine line; // check for test commands received over Debug serial port or telnet char rxVal; @@ -1390,6 +1391,7 @@ void checkDebugCommands() if(nGetConf) { DebugPort.print(rxVal); bool bSave = (rxVal == 'y') || (rxVal == 'Y'); + DebugPort.println(""); if(!bSave) { DebugPort.println(" ABORTED!"); nGetConf = 0; @@ -1397,7 +1399,7 @@ void checkDebugCommands() } switch(nGetConf) { case 1: - setSSID(PCline.Line); + setSSID(line.getString()); break; case 2: setAPpassword(pw2.c_str()); @@ -1408,75 +1410,77 @@ void checkDebugCommands() } else if(nGetString) { DebugPort.enable(true); - if(rxVal < ' ') { - if(rxVal == 0x1b) { // ESCAPE - nGetString = 0; - DebugPort.println("\r\nABORTED!"); - return; - } - if(rxVal == '\n' || rxVal == '\r') { - switch(nGetString) { - case 1: - if(PCline.Len <= 31) { - nGetConf = 1; - DebugPort.printf("\r\nSet AP SSID to %s? (y/n) - ", PCline.Line); - } - else { - DebugPort.println("\r\nNew name is longer than 31 characters - ABORTING"); - } - nGetString = 0; - return; - case 2: - pw1 = PCline.Line; - PCline.clear(); - pw2 = NVstore.getCredentials().APpassword; - if(pw1 != pw2) { - DebugPort.println("\r\nPassword does not match existing - ABORTING"); - nGetString = 0; - } - else { - nGetString = 3; - DebugPort.print("\r\nPlease enter new password - "); - DebugPort.enable(false); // block other debug msgs whilst we get the password - } - return; - case 3: - pw1 = PCline.Line; - if(PCline.Len <= 31) { - nGetString = 4; - DebugPort.print("\r\nPlease confirm new password - "); - DebugPort.enable(false); // block other debug msgs whilst we get the password - } - else { - DebugPort.println("\r\nNew password is longer than 31 characters - ABORTING"); - nGetString = 0; - } - PCline.clear(); - return; - case 4: - pw2 = PCline.Line; - PCline.clear(); - if(pw1 != pw2) { - DebugPort.println("\r\nNew passwords do not match - ABORTING"); - } - else { - nGetConf = 2; - DebugPort.print("\r\nSet new password (y/n) - "); - } - nGetString = 0; - return; - } - } - } - else { - if(nGetString == 1) - DebugPort.print(rxVal); - else - DebugPort.print('*'); - PCline.append(rxVal); - DebugPort.enable(false); // block other debug msgs whilst we get strings + + if(rxVal == 0x1b) { // ESCAPE + nGetString = 0; + DebugPort.println("\r\nABORTED!"); return; } + + if(line.handle(rxVal)) { + switch(nGetString) { + case 1: + if(line.getLen() <= 31) { + nGetConf = 1; + DebugPort.printf("\r\nSet AP SSID to %s? (y/n) - ", line.getString()); + } + else { + DebugPort.println("\r\nNew name is longer than 31 characters - ABORTING"); + } + nGetString = 0; + return; + case 2: + pw1 = line.getString(); + pw2 = NVstore.getCredentials().APpassword; + if(pw1 != pw2) { + DebugPort.println("\r\nPassword does not match existing - ABORTING"); + nGetString = 0; + } + else { + nGetString = 3; + DebugPort.print("\r\nPlease enter new password - "); + DebugPort.enable(false); // block other debug msgs whilst we get the password + } + line.reset(); + line.maskEntry(); + return; + case 3: + pw1 = line.getString(); + if(line.getLen() < 8) { + // ABORT - too short + DebugPort.println("\r\nNew password must be at least 8 characters - ABORTING"); + nGetString = 0; + } + else if(line.getLen() > 31) { + // ABORT - too long! + DebugPort.println("\r\nNew password is longer than 31 characters - ABORTING"); + nGetString = 0; + } + else { + nGetString = 4; + DebugPort.print("\r\nPlease confirm new password - "); + DebugPort.enable(false); // block other debug msgs whilst we get the password + } + line.reset(); + line.maskEntry(); + return; + case 4: + pw2 = line.getString(); + line.reset(); + if(pw1 != pw2) { + DebugPort.println("\r\nNew passwords do not match - ABORTING"); + } + else { + nGetConf = 2; + DebugPort.print("\r\nSet new password (y/n) - "); + } + nGetString = 0; + return; + } + } + DebugPort.enable(false); + return; + } rxVal = toLowerCase(rxVal); @@ -1486,10 +1490,10 @@ void checkDebugCommands() #endif if(rxVal == '\n') { // "End of Line" #ifdef PROTOCOL_INVESTIGATION - String convert(PCline.Line); + String convert(line.getString()); val = convert.toInt(); bSendVal = true; - PCline.clear(); + line.reset(); #endif } else { @@ -1498,7 +1502,7 @@ void checkDebugCommands() } #ifdef PROTOCOL_INVESTIGATION else if(isDigit(rxVal)) { - PCline.append(rxVal); + line.handle(rxVal); } else if(rxVal == 'p') { DebugPort.println("Test Priming Byte... "); @@ -1549,9 +1553,9 @@ void checkDebugCommands() } else if(rxVal == 'n') { DebugPort.print("Please enter new SSID name for Access Point - "); + line.reset(); nGetString = 1; DebugPort.enable(false); // block other debug msgs whilst we get strings - PCline.clear(); } else if(rxVal == 'm') { MQTTmenu.setActive(); @@ -1562,9 +1566,10 @@ void checkDebugCommands() } else if(rxVal == 'p') { DebugPort.print("Please enter current AP password - "); + line.reset(); + line.maskEntry(); nGetString = 2; DebugPort.enable(false); // block other debug msgs whilst we get strings - PCline.clear(); } else if(rxVal == 's') { CommState.toggleReporting(); @@ -1835,11 +1840,10 @@ void doStreaming() { #if USE_WIFI == 1 -// if(NVstore.getUserSettings().enableWifi) { if(NVstore.getUserSettings().wifiMode) { doWiFiManager(); #if USE_OTA == 1 - DoOTA(); + doOTA(); #endif // USE_OTA #if USE_WEBSERVER == 1 bHaveWebClient = doWebServer(); @@ -1970,8 +1974,8 @@ void resetFuelGauge() void setSSID(const char* name) { sCredentials creds = NVstore.getCredentials(); - strncpy(creds.SSID, name, 31); - creds.SSID[31] = 0; + strncpy(creds.APSSID, name, 31); + creds.APSSID[31] = 0; NVstore.setCredentials(creds); NVstore.save(); NVstore.doSave(); // ensure NV storage @@ -2006,7 +2010,7 @@ void showMainmenu() DebugPort.printf(" - toggle reporting of blue wire timeout/recycling event, currently %s\r\n", bReportRecyleEvents ? "ON" : "OFF"); DebugPort.printf(" - toggle reporting of OEM resync event, currently %s\r\n", bReportOEMresync ? "ON" : "OFF"); DebugPort.printf(" - toggle reporting of state machine transits %s\r\n", CommState.isReporting() ? "ON" : "OFF"); - DebugPort.printf(" - change AP SSID, currently \"%s\"\r\n", NVstore.getCredentials().SSID); + DebugPort.printf(" - change AP SSID, currently \"%s\"\r\n", NVstore.getCredentials().APSSID); DebugPort.println("

- change AP password"); DebugPort.println(" - configure MQTT"); DebugPort.println(" <+> - request heater turns ON"); diff --git a/src/OLED/HumidityScreen.cpp b/src/OLED/HumidityScreen.cpp index 6f6793a..d6620ad 100644 --- a/src/OLED/HumidityScreen.cpp +++ b/src/OLED/HumidityScreen.cpp @@ -58,7 +58,7 @@ CHumidityScreen::show() else { sprintf(msg, "> %d%%", _humidityThresh); } - _printMenuText(62, 22, msg, _rowSel == 2); + _printMenuText(62, 22, msg, _rowSel == 1); return true; diff --git a/src/OLED/MQTTScreen.cpp b/src/OLED/MQTTScreen.cpp index 16790e5..32cb043 100644 --- a/src/OLED/MQTTScreen.cpp +++ b/src/OLED/MQTTScreen.cpp @@ -52,6 +52,8 @@ CMQTTScreen::onSelect() { CScreen::onSelect(); _initUI(); + _IPScrollPos = 0; + _UsernameScrollPos = 0; } @@ -66,31 +68,28 @@ CMQTTScreen::show() int yPos = 18; if(NVstore.getMQTTinfo().enabled) { - if(isWifiConnected()) { + if(isWifiSTAConnected()) { if(isMQTTconnected()) - _printMenuText(border, yPos, "CONNECTED"); + _printMenuText(0, yPos, "CONNECTED"); else - _printInverted(border, yPos, " DISCONNECTED ", true); + _printInverted(0, yPos, " DISCONNECTED ", true); } else { - _printInverted(border, yPos, " NO STA NETWORK ", true); + _printInverted(0, yPos, " STA NOT ACTIVE ", true); } } else { - _printMenuText(border, yPos, "DISABLED"); + _printMenuText(0, yPos, "DISABLED"); } char msg[40]; sprintf(msg, "QoS:%d", NVstore.getMQTTinfo().qos); _printMenuText(_display.width(), yPos, msg, false, eRightJustify); + yPos += _display.textHeight() + 2; - sprintf(msg, "%s:%d", NVstore.getMQTTinfo().host, NVstore.getMQTTinfo().port); - _printMenuText(border, yPos, msg); yPos += _display.textHeight() + 2; - sprintf(msg, "%s/%s", NVstore.getMQTTinfo().username, NVstore.getMQTTinfo().password); - _printMenuText(border, yPos, msg); yPos += _display.textHeight() + 2; - sprintf(msg, "%s", NVstore.getMQTTinfo().topicPrefix); - _printMenuText(border, yPos, msg); + _printMenuText(0, yPos, getTopicPrefix()); + return true; } @@ -98,7 +97,46 @@ CMQTTScreen::show() bool CMQTTScreen::animate() { - return false; + static bool subrate = false; + + subrate = !subrate; + + String scrollable; + int yPos = 18; + + scrollable = " "; + scrollable += NVstore.getMQTTinfo().host; + scrollable += ":"; + scrollable += NVstore.getMQTTinfo().port; + scrollable += " "; + if(scrollable.length() < 28) { + scrollable.trim(); // will fit OK, remove added padding that makes scrolled string more readable + } + if(subrate) { + _IPScrollPos++; + if(_IPScrollPos > ( (int)scrollable.length() - 21) ) + _IPScrollPos = 0; + } + yPos += _display.textHeight() + 2; + _printMenuText(0, yPos, scrollable.substring(_IPScrollPos, _IPScrollPos+21).c_str()); + + scrollable = " "; + scrollable += NVstore.getMQTTinfo().username; + scrollable += "/"; + scrollable += NVstore.getMQTTinfo().password; + scrollable += " "; + if(scrollable.length() < 28) { + scrollable.trim(); // will fit OK, remove added padding that makes scrolled string more readable + } + if(subrate) { + _UsernameScrollPos++; + if(_UsernameScrollPos > ( (int)scrollable.length() - 21) ) + _UsernameScrollPos = 0; + } + yPos += _display.textHeight() + 2; + _printMenuText(0, yPos, scrollable.substring(_UsernameScrollPos, _UsernameScrollPos+21).c_str()); + + return true; } bool diff --git a/src/OLED/MQTTScreen.h b/src/OLED/MQTTScreen.h index f0bfbe3..4c91f8e 100644 --- a/src/OLED/MQTTScreen.h +++ b/src/OLED/MQTTScreen.h @@ -37,6 +37,8 @@ public: bool keyHandler(uint8_t event); private: int _repeatCount; + int _IPScrollPos; + int _UsernameScrollPos; }; #endif diff --git a/src/OLED/Screen.cpp b/src/OLED/Screen.cpp index 719637a..5606aff 100644 --- a/src/OLED/Screen.cpp +++ b/src/OLED/Screen.cpp @@ -129,16 +129,16 @@ CScreen::_printInverted(int x, int y, const char* str, bool selected, eJUSTIFY j } void -CScreen::_scrollMessage(int y, const char* str, int& charOffset) +CScreen::_scrollMessage(int y, const char* str, int& charOffset, bool centred) { - char msg[20]; - int maxIndex = strlen(str) - 20; - strncpy(msg, &str[charOffset], 19); - msg[19] = 0; - _printMenuText(_display.xCentre(), y, msg, false, eCentreJustify); + char msg[22]; + int maxIndex = strlen(str) - 21; + strncpy(msg, &str[charOffset], 21); + msg[21] = 0; + _printMenuText(centred ? _display.xCentre() : 0, y, msg, false, centred ? eCentreJustify : eLeftJustify); charOffset++; - if(charOffset >= maxIndex) { + if(charOffset > maxIndex) { charOffset = 0; } } diff --git a/src/OLED/Screen.h b/src/OLED/Screen.h index 49a3c20..b7de73c 100644 --- a/src/OLED/Screen.h +++ b/src/OLED/Screen.h @@ -54,7 +54,7 @@ protected: void _adjustExtents(CRect& rect, eJUSTIFY justify, const char* str); void _drawMenuSelection(CRect extents, const char* str, int border = 3, int radius = 4); void _drawMenuSelection(const CRect& extents, int border, int radius); - void _scrollMessage(int y, const char* str, int& charOffset); + void _scrollMessage(int y, const char* str, int& charOffset, bool centred=true); void _reqOEMWarning(); void _drawBitmap(int x, int y, const BITMAP_INFO& info, uint16_t color = WHITE, uint16_t bg = 0xffff); void _showTitle(const char* title); diff --git a/src/OLED/ScreenHeader.cpp b/src/OLED/ScreenHeader.cpp index 954e9f5..fa1013d 100644 --- a/src/OLED/ScreenHeader.cpp +++ b/src/OLED/ScreenHeader.cpp @@ -278,7 +278,7 @@ CScreenHeader::showBTicon() void CScreenHeader::showWifiIcon() { - if(isWifiConnected() || isWifiAP()) { // STA or AP mode active + if(isWifiSTAConnected() || isWifiAPonly()) { // STA or AP mode active _drawBitmap(X_WIFI_ICON, Y_WIFI_ICON, WifiWideIconInfo, WHITE, BLACK); // wide icon erases annotations! int8_t RSSI = getWifiRSSI(); if(RSSI < -70) { @@ -356,7 +356,7 @@ CScreenHeader::showWifiIcon() _display.setCursor(X_WIFI_ICON+12, Y_WIFI_ICON+6); _display.print("CFG"); } - else if(isWifiAP()) { + else if(isWifiAPonly()) { // if AP only, show AP CTransientFont AF(_display, &MINIFONT); // temporarily use a mini font _display.setCursor(X_WIFI_ICON+12, Y_WIFI_ICON+6); diff --git a/src/OLED/WebPageUpdateScreen.cpp b/src/OLED/WebPageUpdateScreen.cpp index edb1559..b3a33ab 100644 --- a/src/OLED/WebPageUpdateScreen.cpp +++ b/src/OLED/WebPageUpdateScreen.cpp @@ -53,7 +53,7 @@ CWebPageUpdateScreen::show() int col = _display.xCentre(); if(_rowSel == 0) { - if(isWifiSTA()) { + if(isWifiSTAConnected()) { _printMenuText(col, 16, "Press Up to update", false, eCentreJustify); _printMenuText(col, 26, "web page content ", false, eCentreJustify); _printMenuText(col, 36, "stored in SPIFFS. ", false, eCentreJustify); @@ -115,7 +115,7 @@ CWebPageUpdateScreen::keyHandler(uint8_t event) // UP press if(event & key_Up) { if(_rowSel == 0) { - if(isWifiSTA()) + if(isWifiSTAConnected()) _rowSel = 1; } else { diff --git a/src/OLED/WiFiSTAScreen.cpp b/src/OLED/WiFiSTAScreen.cpp index 248679c..9b46ad2 100644 --- a/src/OLED/WiFiSTAScreen.cpp +++ b/src/OLED/WiFiSTAScreen.cpp @@ -53,7 +53,7 @@ CWiFiSTAScreen::show() if(NVstore.getUserSettings().wifiMode == 0 || !isWifiSTA()) { if(NVstore.getUserSettings().wifiMode == 0) - _printMenuText(border, yPos, "DISABLED"); + _printMenuText(border, yPos, "WiFi DISABLED"); else _printMenuText(border, yPos, "NOT CONNECTED"); } @@ -76,7 +76,7 @@ CWiFiSTAScreen::show() sprintf(RSSIstr, "%ddBm", RSSI); _printMenuText(31, yPos, RSSIstr); - int xPos = 90; +/* int xPos = 70; _drawBitmap(xPos, yPos, WifiIconInfo, WHITE, BLACK); // wide icon erases annotations! if(RSSI < -70) { _display.fillRect(xPos, yPos, WifiIconInfo.width, 6, BLACK); @@ -85,7 +85,17 @@ CWiFiSTAScreen::show() _display.fillRect(xPos, yPos, WifiWideIconInfo.width, 3, BLACK); _display.fillRect(xPos, yPos, 1, 4, BLACK); _display.fillRect(xPos+WifiIconInfo.width-1, yPos, 1, 4, BLACK); + }*/ + + const char* modeStr = ""; + switch(WiFi.getMode()) { + case WIFI_MODE_STA: modeStr = "STA only"; break; + case WIFI_MODE_AP: modeStr = "AP only"; break; + case WIFI_MODE_APSTA: modeStr = "STA+AP"; break; + default: break; } + _printMenuText(128, yPos, modeStr, false, eRightJustify); + } _printMenuText(_display.xCentre(), 53, "\021 \020", true, eCentreJustify); diff --git a/src/OLED/WiFiScreen.cpp b/src/OLED/WiFiScreen.cpp index fde8f2a..77d79aa 100644 --- a/src/OLED/WiFiScreen.cpp +++ b/src/OLED/WiFiScreen.cpp @@ -61,8 +61,8 @@ CWiFiScreen::_initUI() _OTAsel = NVstore.getUserSettings().enableOTA; _bShowMAC = false; - if(NVstore.getUserSettings().wifiMode) { - if(isWifiAP()) { + if(NVstore.getUserSettings().wifiMode) { // non zero => enabled wifi, maybe AP only or STA+AP or STA only + if(isWifiAPonly()) { if(isWifiConfigPortal()) { _colSel = 1; // " WiFi: CFG AP only " } @@ -71,11 +71,21 @@ CWiFiScreen::_initUI() } } else { - if(isWifiConfigPortal()) { - _colSel = 3; // " WiFi: CFG STA+AP " + if(NVstore.getUserSettings().wifiMode & 0x02) { // 0x02 set => STA only preferred + if(isWifiConfigPortal()) { + _colSel = 5; // " WiFi: CFG STA only " + } + else { + _colSel = 6; // " WiFi: STA only "; + } } else { - _colSel = 4; // " WiFi: STA+AP "; + if(isWifiConfigPortal()) { + _colSel = 3; // " WiFi: CFG STA+AP " + } + else { + _colSel = 4; // " WiFi: STA+AP "; + } } } } @@ -109,6 +119,12 @@ CWiFiScreen::show() case 4: pTitle = "STA+AP"; break; + case 5: + pTitle = "CFG STA only"; + break; + case 6: + pTitle = "STA only"; + break; } _printMenuText(border, yPos, pTitle, _rowSel==1); // selection box @@ -184,13 +200,13 @@ CWiFiScreen::keyHandler(uint8_t event) _ScreenManager.prevMenu(); break; case 1: - if(isWifiAP()) { + if(isWifiAPonly()) { _colSel--; WRAPLOWERLIMIT(_colSel, 0, 2); } else { _colSel--; - WRAPLOWERLIMIT(_colSel, 0, 4); + WRAPLOWERLIMIT(_colSel, 0, 6); } break; case 2: @@ -206,13 +222,13 @@ CWiFiScreen::keyHandler(uint8_t event) _ScreenManager.nextMenu(); break; case 1: - if(isWifiAP()) { + if(isWifiAPonly()) { _colSel++; WRAPUPPERLIMIT(_colSel, 2, 0); } else { _colSel++; - WRAPUPPERLIMIT(_colSel, 4, 0); + WRAPUPPERLIMIT(_colSel, 6, 0); } break; case 2: @@ -266,6 +282,12 @@ CWiFiScreen::keyHandler(uint8_t event) case 4: wifiEnterConfigPortal(false, false, 5000); // STA+AP: keep credentials, reboot into webserver break; + case 5: + wifiEnterConfigPortal(true, false, 5000, true); // CFG STA only: keep credentials, reboot into portal + break; + case 6: + wifiEnterConfigPortal(false, false, 5000, true); // STA only: keep credentials, reboot into webserver + break; } _rowSel = 3; // stop ticker display } diff --git a/src/Utility/BTC_JSON.cpp b/src/Utility/BTC_JSON.cpp index a568371..09bca87 100644 --- a/src/Utility/BTC_JSON.cpp +++ b/src/Utility/BTC_JSON.cpp @@ -336,7 +336,7 @@ bool makeJSONStringMQTT(CModerator& moderator, char* opStr, int len) bSend |= moderator.addJson("MUser", info.username, root); bSend |= moderator.addJson("MPasswd", info.password, root); bSend |= moderator.addJson("MQoS", info.qos, root); - bSend |= moderator.addJson("MTopic", info.topicPrefix, root); + bSend |= moderator.addJson("MTopic", getTopicPrefix(), root); if(bSend) { root.printTo(opStr, len); @@ -393,7 +393,7 @@ bool makeJSONStringIP(CModerator& moderator, char* opStr, int len) bSend |= moderator.addJson("IP_APMAC", getWifiAPMACStr(), root); bSend |= moderator.addJson("IP_STA", getWifiSTAAddrStr(), root); bSend |= moderator.addJson("IP_STAMAC", getWifiSTAMACStr(), root); - bSend |= moderator.addJson("IP_STASSID", getSSID().c_str(), root); + bSend |= moderator.addJson("IP_STASSID", getSTASSID().c_str(), root); bSend |= moderator.addJson("IP_STAGATEWAY", getWifiGatewayAddrStr(), root); bSend |= moderator.addJson("IP_STARSSI", getWifiRSSI(), root, 10000); bSend |= moderator.addJson("IP_OTA", NVstore.getUserSettings().enableOTA, root); diff --git a/src/Utility/GetLine.cpp b/src/Utility/GetLine.cpp new file mode 100644 index 0000000..18fe37c --- /dev/null +++ b/src/Utility/GetLine.cpp @@ -0,0 +1,149 @@ +/* + * This file is part of the "bluetoothheater" distribution + * (https://gitlab.com/mrjones.id.au/bluetoothheater) + * + * Copyright (C) 2020 Ray Jones + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "GetLine.h" +#include "DebugPort.h" +#include + +CGetLine::CGetLine() +{ + reset(); +} + +void +CGetLine::reset() +{ + _idx = 0; + _getMode = 0; + _pTarget = NULL; + _Numeric = 0; + _maxlen = sizeof(_buffer); + _showStars = false; +} + +void +CGetLine::reset(char* result, int maxlen) +{ + reset(); + _getMode = 1; + _pTarget = result; + _maxlen = maxlen > sizeof(_buffer) ? sizeof(_buffer) : maxlen; +} + +void +CGetLine::reset(int numeric) +{ + reset(); + _getMode = 2; + _Numeric = numeric; +} + +bool +CGetLine::handle(char rxVal) +{ + if(_getMode == 2) { + return _doNum(rxVal); + } + + if(rxVal < ' ') { + if(_idx == 0) { + if(_pTarget) + strcpy(_buffer, _pTarget); + } + if(rxVal == ('x' & 0x1f)) { // CTRL-X - erase string, return done + memset(_buffer, 0, sizeof(_buffer)); + _zeroTarget(); + return true; + } + if(rxVal == '\r') // ignore CR + return false; + if(rxVal == '\n') { // accept buffered string upon LF, return done + _copyTarget(); + return true; + } + if(rxVal == 0x1b) { // abort, no change upon ESC, return done + return true; + } + } + else { + if(_idx == 0) memset(_buffer, 0, sizeof(_buffer)); + if(_showStars) + DebugPort.print('*'); + else + DebugPort.print(rxVal); + _buffer[_idx++] = rxVal; + if(_idx == _maxlen) { + _copyTarget(); + return true; + } + } + return false; +} + + +bool +CGetLine::_doNum(char rxVal) +{ + if(rxVal < ' ') { + if(_idx == 0) sprintf(_buffer, "%d", _Numeric); + if(rxVal == '\n') { + int val = atoi(_buffer); + _Numeric = val; + return true; + } + if(rxVal == 0x1b) { + return true; + } + return false; + } + DebugPort.print(rxVal); + if(isdigit(rxVal)) { + if(_idx == 0) memset(_buffer, 0, sizeof(_buffer)); + _buffer[_idx++] = rxVal; + if(_idx == 5) { + int val = atoi(_buffer); + _Numeric = val; + return true; + } + } + else { + return true; + } + return false; +} + +void +CGetLine::_copyTarget() +{ + if(_pTarget) { + strncpy(_pTarget, _buffer, _maxlen); + _pTarget[_maxlen] = 0; + } +} + + +void +CGetLine::_zeroTarget() +{ + if(_pTarget) + memset(_pTarget, 0, _maxlen+1); +} + diff --git a/src/Utility/GetLine.h b/src/Utility/GetLine.h new file mode 100644 index 0000000..28ca437 --- /dev/null +++ b/src/Utility/GetLine.h @@ -0,0 +1,48 @@ +/* + * This file is part of the "bluetoothheater" distribution + * (https://gitlab.com/mrjones.id.au/bluetoothheater) + * + * Copyright (C) 2020 Ray Jones + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef __GETSTRINGLINE_H__ +#define __GETSTRINGLINE_H__ + +class CGetLine { + char _buffer[128]; + int _idx; + int _getMode; // 0: default string 1: targetted string, 2: numeric + int _maxlen; + char* _pTarget; + int _Numeric; + bool _showStars; + bool _doNum(char rxVal); + void _copyTarget(); + void _zeroTarget(); +public: + CGetLine(); + void reset(); + void reset(char* result, int maxlen); + void reset(int numeric); + bool handle(char rxVal); + int getNumeric() { return _Numeric; } + const char* getString() { return _buffer; } + int getLen() { return _idx; } + void maskEntry() { _showStars = true; }; +}; + +#endif \ No newline at end of file diff --git a/src/Utility/MQTTsetup.cpp b/src/Utility/MQTTsetup.cpp index e9c6d2f..39a381a 100644 --- a/src/Utility/MQTTsetup.cpp +++ b/src/Utility/MQTTsetup.cpp @@ -22,6 +22,7 @@ #include "NVStorage.h" #include "DebugPort.h" #include "MQTTsetup.h" +#include "../WiFi/ABMQTT.h" CMQTTsetup::CMQTTsetup() { @@ -50,7 +51,11 @@ CMQTTsetup::showMQTTmenu(bool init) DebugPort.printf(" <2> - set port, currently %d\r\n", _MQTTsetup.port); DebugPort.printf(" <3> - set username, currently \"%s\"\r\n", _MQTTsetup.username); DebugPort.printf(" <4> - set password, currently \"%s\"\r\n", _MQTTsetup.password); +#ifdef ALLOW_USER_TOPIC DebugPort.printf(" <5> - set root topic, currently \"%s\"\r\n", _MQTTsetup.topicPrefix); +#else + DebugPort.printf(" Fixed unique topic prefix: \"%s\"\r\n", getTopicPrefix()); +#endif DebugPort.printf(" <6> - set QoS, currently %d\r\n", _MQTTsetup.qos); DebugPort.printf(" <7> - set enabled, currently %s\r\n", _MQTTsetup.enabled ? "ON" : "OFF"); DebugPort.printf(" - save and exit\r\n"); @@ -91,16 +96,39 @@ CMQTTsetup::HandleMQTTsetup(char rxVal) } if(rxVal >= '1' && rxVal <= '7') { _mode = rxVal - '0'; - _idx = 0; DebugPort.print("\014"); switch(_mode) { - case 1: DebugPort.printf("Enter MQTT broker's IP address (%s)", _MQTTsetup.host); break; - case 2: DebugPort.printf("Enter MQTT broker's port (%d)", _MQTTsetup.port); break; - case 3: DebugPort.printf("Enter MQTT broker's username (currently '%s', CTRL-X to erase)", _MQTTsetup.username); break; - case 4: DebugPort.printf("Enter MQTT broker's password (currently '%s', CTRL-X to erase)", _MQTTsetup.password); break; - case 5: DebugPort.printf("Enter root topic name (%s)", _MQTTsetup.topicPrefix); break; - case 6: DebugPort.printf("Enter QoS level (%d)", _MQTTsetup.qos); break; - case 7: DebugPort.printf("Enable MQTT? (Y)es / (N)o (%s)", _MQTTsetup.enabled ? "YES" : "NO"); break; + case 1: + DebugPort.printf("Enter MQTT broker's IP address (%s)", _MQTTsetup.host); + _lineInput.reset(_MQTTsetup.host, 31); + break; + case 2: + DebugPort.printf("Enter MQTT broker's port (%d)", _MQTTsetup.port); + _lineInput.reset(_MQTTsetup.port); + break; + case 3: + DebugPort.printf("Enter MQTT broker's username (currently '%s', CTRL-X to erase)", _MQTTsetup.username); + _lineInput.reset(_MQTTsetup.username, 31); + break; + case 4: + DebugPort.printf("Enter MQTT broker's password (currently '%s', CTRL-X to erase)", _MQTTsetup.password); + _lineInput.reset(_MQTTsetup.password, 31); + break; + case 5: +#ifdef ALLOW_USER_TOPIC + DebugPort.printf("Enter root topic name (%s)", _MQTTsetup.topicPrefix); + _lineInput.reset(_MQTTsetup.topicPrefix, 31); +#else + _mode = 0; // topic prefix is now fixed, based upon our STA MAC + showMQTTmenu(); +#endif + return true; + case 6: + DebugPort.printf("Enter QoS level (%d)", _MQTTsetup.qos); + break; + case 7: + DebugPort.printf("Enable MQTT? (Y)es / (N)o (%s)", _MQTTsetup.enabled ? "YES" : "NO"); + break; } DebugPort.print("... "); } @@ -109,49 +137,28 @@ CMQTTsetup::HandleMQTTsetup(char rxVal) } return true; case 1: // enter MQTT broker IP - if(getMQTTstring(rxVal, 31, _MQTTsetup.host)) { + if(_lineInput.handle(rxVal)) { bJumptoMQTTmenuRoot = true; } break; case 2: // enter MQTT broker port - if(rxVal < ' ') { - if(_idx == 0) sprintf(_buffer, "%d", _MQTTsetup.port); - if(rxVal == '\n') { - int val = atoi(_buffer); - _MQTTsetup.port = val; - bJumptoMQTTmenuRoot = true; - } - if(rxVal == 0x1b) { - bJumptoMQTTmenuRoot = true; - } - break; - } - DebugPort.print(rxVal); - if(isdigit(rxVal)) { - if(_idx == 0) memset(_buffer, 0, sizeof(_buffer)); - _buffer[_idx++] = rxVal; - if(_idx == 5) { - int val = atoi(_buffer); - _MQTTsetup.port = val; - bJumptoMQTTmenuRoot = true; - } - } - else { + if(_lineInput.handle(rxVal)) { + _MQTTsetup.port = _lineInput.getNumeric(); bJumptoMQTTmenuRoot = true; } break; case 3: // enter MQTT broker username - if(getMQTTstring(rxVal, 31, _MQTTsetup.username)) { + if(_lineInput.handle(rxVal)) { bJumptoMQTTmenuRoot = true; } break; case 4: // enter MQTT broker username - if(getMQTTstring(rxVal, 31, _MQTTsetup.password)) { + if(_lineInput.handle(rxVal)) { bJumptoMQTTmenuRoot = true; } break; case 5: // enter root topic name - if(getMQTTstring(rxVal, 31, _MQTTsetup.topicPrefix)) { + if(_lineInput.handle(rxVal)) { bJumptoMQTTmenuRoot = true; } break; @@ -176,36 +183,3 @@ CMQTTsetup::HandleMQTTsetup(char rxVal) return true; } -bool -CMQTTsetup::getMQTTstring(char rxVal, int maxidx, char* pTargetString) -{ - if(rxVal < ' ') { - if(_idx == 0) strcpy(_buffer, pTargetString); - if(rxVal == ('x' & 0x1f)) { // CTRL-X - erase string, return done - memset(pTargetString, 0, maxidx+1); - return true; - } - if(rxVal == '\r') // ignore CR - return false; - if(rxVal == '\n') { // accept buffered string upon LF, return done - strncpy(pTargetString, _buffer, maxidx); - pTargetString[maxidx] = 0; - return true; - } - if(rxVal == 0x1b) { // abort, no change upon ESC, return done - return true; - } - } - else { - if(_idx == 0) memset(_buffer, 0, sizeof(_buffer)); - DebugPort.print(rxVal); - _buffer[_idx++] = rxVal; - if(_idx == maxidx) { - strncpy(pTargetString, _buffer, maxidx); - pTargetString[maxidx] = 0; - return true; - } - } - return false; -} - diff --git a/src/Utility/MQTTsetup.h b/src/Utility/MQTTsetup.h index 7855b85..047db45 100644 --- a/src/Utility/MQTTsetup.h +++ b/src/Utility/MQTTsetup.h @@ -20,17 +20,16 @@ */ #include "NVStorage.h" +#include "GetLine.h" class CMQTTsetup { - char _buffer[128]; - int _idx; + CGetLine _lineInput; int _mode; bool _active; sMQTTparams _MQTTsetup; bool HandleMQTTsetup(char rxVal); void showMQTTmenu(bool init = false); - bool getMQTTstring(char rxVal, int maxidx, char* pTargetString); public: CMQTTsetup(); bool Handle(char& rxVal); diff --git a/src/Utility/NVStorage.cpp b/src/Utility/NVStorage.cpp index 4d006bf..d8ee450 100644 --- a/src/Utility/NVStorage.cpp +++ b/src/Utility/NVStorage.cpp @@ -448,7 +448,6 @@ sUserSettings::load() DebugPort.printf("2) Window = %f\r\n", ThermostatWindow); validatedLoad("frostOn", FrostOn, 0, u8inBounds, 0, 10); validatedLoad("frostRise", FrostRise, 5, u8inBounds, 0, 20); -// validatedLoad("enableWifi", enableWifi, 1, u8inBounds, 0, 1); validatedLoad("enableWifi", wifiMode, 1, u8inBounds, 0, 3); validatedLoad("enableOTA", enableOTA, 0, u8inBounds, 0, 1); validatedLoad("cyclicStop", cyclic.Stop, 0, s8inBounds, 0, 10); @@ -518,7 +517,6 @@ sUserSettings::save() saveFloat("thermoWindow", ThermostatWindow); preferences.putUChar("frostOn", FrostOn); preferences.putUChar("frostRise", FrostRise); -// preferences.putUChar("enableWifi", enableWifi); preferences.putUChar("enableWifi", wifiMode); preferences.putUChar("enableOTA", enableOTA); preferences.putChar("cyclicStop", cyclic.Stop); @@ -585,7 +583,7 @@ sCredentials::load() { // **** MAX LENGTH is 15 for names **** preferences.begin("credentials", false); - validatedLoad("SSID", SSID, 31, "Afterburner"); + validatedLoad("SSID", APSSID, 31, "Afterburner"); validatedLoad("APpassword", APpassword, 31, "thereisnospoon"); validatedLoad("webUpdateUser", webUpdateUsername, 31, "Afterburner"); validatedLoad("webUpdatePass", webUpdatePassword, 31, "BurnBabyBurn"); @@ -597,7 +595,7 @@ sCredentials::save() { // **** MAX LENGTH is 15 for names **** preferences.begin("credentials", false); - preferences.putString("SSID", SSID); + preferences.putString("SSID", APSSID); preferences.putString("APpassword", APpassword); preferences.putString("webUpdateUser", webUpdateUsername); preferences.putString("webUpdatePass", webUpdatePassword); diff --git a/src/Utility/NVStorage.h b/src/Utility/NVStorage.h index a14c208..6c65a87 100644 --- a/src/Utility/NVStorage.h +++ b/src/Utility/NVStorage.h @@ -225,12 +225,12 @@ struct sJSONoptions { struct sCredentials : public CESP32_NVStorage { - char SSID[32]; + char APSSID[32]; char APpassword[32]; char webUpdateUsername[32]; char webUpdatePassword[32]; void init() { - strcpy(SSID, "Afterburner"); + strcpy(APSSID, "Afterburner"); strcpy(APpassword, "thereisnospoon"); strcpy(webUpdateUsername, "Afterburner"); strcpy(webUpdatePassword, "BurnBabyBurn"); @@ -239,7 +239,7 @@ struct sCredentials : public CESP32_NVStorage { void save(); bool valid(); sCredentials& operator=(const sCredentials& rhs) { - strcpy(SSID, rhs.SSID); + strcpy(APSSID, rhs.APSSID); strcpy(APpassword, rhs.APpassword); strcpy(webUpdateUsername, rhs.webUpdateUsername); strcpy(webUpdatePassword, rhs.webUpdatePassword); @@ -303,9 +303,8 @@ struct sUserSettings : public CESP32_NVStorage { uint8_t FrostOn; uint8_t FrostRise; uint8_t useThermostat; -// uint8_t enableWifi; uint8_t enableOTA; - uint8_t wifiMode; + uint8_t wifiMode; // general Wifi is enabled mode, may be AP only or STA+AP, 2 => STA only if possible, or AP only uint16_t FrameRate; sCyclicThermostat cyclic; sHomeMenuActions HomeMenu; @@ -325,7 +324,6 @@ struct sUserSettings : public CESP32_NVStorage { retval &= ThermostatMethod <= 3; // only modes 0, 1 or 2, 3 retval &= INBOUNDS(ThermostatWindow, 0.2f, 10.f); retval &= useThermostat < 2; -// retval &= (enableWifi == 0) || (enableWifi == 1); retval &= INBOUNDS(wifiMode, 0, 3); retval &= (enableOTA == 0) || (enableOTA == 1); retval &= GPIO.in1Mode < 4; @@ -348,8 +346,7 @@ struct sUserSettings : public CESP32_NVStorage { FrostOn = 0; FrostRise = 5; useThermostat = 1; -// enableWifi = 1; - wifiMode = 1; + wifiMode = 1; enableOTA = 0; GPIO.in1Mode = CGPIOin1::Disabled; GPIO.in2Mode = CGPIOin2::Disabled; @@ -379,7 +376,6 @@ struct sUserSettings : public CESP32_NVStorage { FrostOn = rhs.FrostOn; FrostRise = rhs.FrostRise; useThermostat = rhs.useThermostat; -// enableWifi = rhs.enableWifi; wifiMode = rhs.wifiMode; enableOTA = rhs.enableOTA; GPIO.in1Mode = rhs.GPIO.in1Mode; diff --git a/src/Utility/UtilClasses.cpp b/src/Utility/UtilClasses.cpp index ab3de57..1d10ce2 100644 --- a/src/Utility/UtilClasses.cpp +++ b/src/Utility/UtilClasses.cpp @@ -291,12 +291,14 @@ void DecodeCmd(const char* cmd, String& payload) NVstore.setMQTTinfo(info); } } +#ifdef ALLOW_USER_TOPIC else if(strcmp("MTopic", cmd) == 0) { sMQTTparams info = NVstore.getMQTTinfo(); strncpy(info.topicPrefix, payload.c_str(), 31); info.topicPrefix[31] = 0; NVstore.setMQTTinfo(info); } +#endif else if(strcmp("UploadSize", cmd) == 0) { setUploadSize(payload.toInt()); } diff --git a/src/WiFi/ABMQTT.cpp b/src/WiFi/ABMQTT.cpp index 8cfd346..d7f42bd 100644 --- a/src/WiFi/ABMQTT.cpp +++ b/src/WiFi/ABMQTT.cpp @@ -96,11 +96,12 @@ void onMqttConnect(bool sessionPresent) DebugPort.println("MQTT: Connected to broker."); // DebugPort.printf("Session present: %d\r\n", sessionPresent); - // create the topicname we use to accept incoming JSON - DebugPort.printf("MQTT: topic prefix name \"%s\"\r\n", NVstore.getMQTTinfo().topicPrefix); - sprintf(statusTopic, "%s/status", NVstore.getMQTTinfo().topicPrefix); - sprintf(topicnameJSONin, "%s/JSONin", NVstore.getMQTTinfo().topicPrefix); - sprintf(topicnameCmd, "%s/cmd/#", NVstore.getMQTTinfo().topicPrefix); + // apply the topicname we need to subscribe to incoming JSON + + DebugPort.printf("MQTT: topic prefix name \"%s\"\r\n", getTopicPrefix()); + sprintf(statusTopic, "%s/status", getTopicPrefix()); + sprintf(topicnameJSONin, "%s/JSONin", getTopicPrefix()); + sprintf(topicnameCmd, "%s/cmd/#", getTopicPrefix()); subscribe(topicnameJSONin); // subscribe to the JSONin topic subscribe(topicnameCmd); // subscribe to the basic command topic @@ -252,7 +253,7 @@ bool mqttPublishJSON(const char* str) if(MQTTclient.connected()) { const sMQTTparams params = NVstore.getMQTTinfo(); char topic[128]; - sprintf(topic, "%s/JSONout", params.topicPrefix); + sprintf(topic, "%s/JSONout", getTopicPrefix()); MQTTclient.publish(topic, params.qos, false, str); return true; } @@ -322,7 +323,7 @@ void pubTopic(const char* name, int value) if(MQTTmoderator.shouldSend(name, value)) { const sMQTTparams params = NVstore.getMQTTinfo(); char topic[128]; - sprintf(topic, "%s/sts/%s", params.topicPrefix, name); + sprintf(topic, "%s/sts/%s", getTopicPrefix(), name); char payload[128]; sprintf(payload, "%d", value); MQTTclient.publish(topic, params.qos, false, payload); @@ -336,7 +337,7 @@ void pubTopic(const char* name, float value) if(MQTTmoderator.shouldSend(name, value)) { const sMQTTparams params = NVstore.getMQTTinfo(); char topic[128]; - sprintf(topic, "%s/sts/%s", params.topicPrefix, name); + sprintf(topic, "%s/sts/%s", getTopicPrefix(), name); char payload[128]; sprintf(payload, "%.1f", value); MQTTclient.publish(topic, params.qos, false, payload); @@ -350,7 +351,7 @@ void pubTopic(const char* name, const char* payload) if(MQTTmoderator.shouldSend(name, payload)) { const sMQTTparams params = NVstore.getMQTTinfo(); char topic[128]; - sprintf(topic, "%s/sts/%s", params.topicPrefix, name); + sprintf(topic, "%s/sts/%s", getTopicPrefix(), name); MQTTclient.publish(topic, params.qos, false, payload); } } @@ -425,4 +426,24 @@ void requestMQTTrestart() MQTTrestart = (millis() + 1000) | 1; } +const char* getTopicPrefix() +{ +#ifdef ALLOW_USER_TOPIC + + return NVstore.getMQTTinfo().topicPrefix; + +#else + + static char prefix[32] = ""; + + if(strlen(prefix) == 0) { + uint8_t MAC[6]; + esp_read_mac(MAC, ESP_MAC_WIFI_STA); + sprintf(prefix, "Afterburner%02X%02X%02X", MAC[3], MAC[4], MAC[5]); + } + return prefix; + +#endif +} + #endif \ No newline at end of file diff --git a/src/WiFi/ABMQTT.h b/src/WiFi/ABMQTT.h index 8990800..34445b0 100644 --- a/src/WiFi/ABMQTT.h +++ b/src/WiFi/ABMQTT.h @@ -31,6 +31,7 @@ bool mqttPublishJSON(const char* str); void connectToMqtt(); void kickMQTT(); bool isMQTTconnected(); +const char* getTopicPrefix(); #endif diff --git a/src/WiFi/BTCWebServer.cpp b/src/WiFi/BTCWebServer.cpp index ef8364f..f972e7a 100644 --- a/src/WiFi/BTCWebServer.cpp +++ b/src/WiFi/BTCWebServer.cpp @@ -89,7 +89,7 @@ void build500Response(String& content, String file); const char* getWebContent(bool start) { - if(isWifiSTA() && start) { + if(isWifiSTAConnected() && start) { GetWebContent.start(); } diff --git a/src/WiFi/BTCWifi.cpp b/src/WiFi/BTCWifi.cpp index 9b0f640..1761e3f 100644 --- a/src/WiFi/BTCWifi.cpp +++ b/src/WiFi/BTCWifi.cpp @@ -49,8 +49,9 @@ unsigned long WifiReconnectHoldoff = 0; extern CScreenManager ScreenManager; -bool initWifi(const char *failedssid, const char *failedpassword) +bool initWifi() { + sCredentials creds = NVstore.getCredentials(); // local Soft AP credentials WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP @@ -83,7 +84,7 @@ bool initWifi(const char *failedssid, const char *failedpassword) DebugPort.println("Attempting to start STA mode (or config portal) via WifiManager..."); - wm.setHostname(failedssid); + wm.setHostname(creds.APSSID); // define Soft AP name wm.setDebugOutput(true); wm.setConfigPortalTimeout(20); wm.setConfigPortalBlocking(false); @@ -94,7 +95,7 @@ bool initWifi(const char *failedssid, const char *failedpassword) //REMOVED - UNSTABLE WHETHER WE GET 192.168.4.1 or 192.168.100.1 ???? // REMOVED wm.setAPStaticIPConfig(IPAddress(192, 168, 100, 1), IPAddress(192, 168, 100, 1), IPAddress(255,255,255,0)); - bool res = wm.autoConnect(failedssid, failedpassword); // auto generated AP name from chipid + bool res = wm.autoConnect(creds.APSSID, creds.APpassword); // User definable AP name & password DebugPort.printf("WifiMode after autoConnect = "); DebugPort.println(WiFi.getMode()); int chnl = 1; @@ -114,19 +115,28 @@ bool initWifi(const char *failedssid, const char *failedpassword) DebugPort.printf(" STA IP address: %s\r\n", getWifiSTAAddrStr()); // must use same radio channel as STA to go to STA+AP, otherwise we drop the STA! chnl = WiFi.channel(); - DebugPort.println("Now promoting to STA+AP mode..."); retval = true; } -#if USE_AP_ALWAYS == 1 - if(NVstore.getUserSettings().wifiMode & 0x01) { // Own AP enabled - startAP = true; + if(isSTA) { + if(NVstore.getUserSettings().wifiMode & 0x02) { // Check for STA only mode + DebugPort.println(" Using STA only mode."); + } + else { + DebugPort.println("Now promoting to STA+AP mode..."); + startAP = true; + } } +#if USE_AP_ALWAYS == 1 + startAP = true; + DebugPort.println("Forcing AP mode on!"); #endif + + // WiFi.softAP(failedssid, failedpassword, chnl); + // WiFi.softAP(creds.SSID, creds.APpassword, chnl); if(startAP) { // for STA+AP mode we *must* use the same RF channel as STA DebugPort.println("Starting AP mode"); - WiFi.softAP(failedssid, failedpassword, chnl); - WiFi.enableAP(true); + WiFi.softAP(creds.APSSID, creds.APpassword, chnl); DebugPort.printf(" AP SSID: %s\r\n", WiFi.softAPgetHostname()); DebugPort.printf(" AP IP address: %s\r\n", getWifiAPAddrStr()); DebugPort.printf("WifiMode after initWifi = %d\r\n", WiFi.getMode()); @@ -139,8 +149,8 @@ bool initWifi(const char *failedssid, const char *failedpassword) isPortalAP = true; // we started portal, we have to flag it! } -// WiFi.setTxPower(WIFI_POWER_MINUS_1dBm); - + // WiFi.setTxPower(WIFI_POWER_MINUS_1dBm); + WiFi.setTxPower(WIFI_POWER_19_5dBm); return retval; } @@ -151,7 +161,13 @@ void doWiFiManager() wm.process(); if(WiFi.status() != WL_CONNECTED) { - if(isSTA) DebugPort.println("STA lost"); + if(isSTA) { + DebugPort.println("STA lost"); + // ensure inbuilt AP is started if STA is down + sCredentials creds = NVstore.getCredentials(); // local AP credentials + int chnl = 1; + WiFi.softAP(creds.APSSID, creds.APpassword, chnl); // this will intrinsically enable AP + } isSTA = false; if(WifiReconnectHoldoff) { long tDelta = millis() - WifiReconnectHoldoff; @@ -170,7 +186,19 @@ void doWiFiManager() } } else { - if(!isSTA) DebugPort.println("STA established"); + if(!isSTA) { + // initial regain of STA connection detected + DebugPort.println("STA established"); + if(NVstore.getUserSettings().wifiMode & 0x02) { + WiFi.enableAP(false); // kill inbuilt AP if setup for STA only + } + else { + // ensure inbuilt AP is set to same channel as STA + int chnl = WiFi.channel(); + sCredentials creds = NVstore.getCredentials(); // local AP credentials + WiFi.softAP(creds.APSSID, creds.APpassword, chnl); // intrinsically enables Soft AP + } + } isSTA = true; WifiReconnectHoldoff = 0; } @@ -181,10 +209,10 @@ void doWiFiManager() void wifiDisable(long rebootDelay) { sUserSettings settings = NVstore.getUserSettings(); -// settings.enableWifi = 0; settings.wifiMode = 0; NVstore.setUserSettings(settings); NVstore.save(); + NVstore.doSave(); // ensure NV storage DebugPort.println("*** Disabling WiFi ***"); @@ -196,23 +224,29 @@ void wifiDisable(long rebootDelay) ScreenManager.showRebootMsg(content, rebootDelay); } -void wifiEnterConfigPortal(bool state, bool erase, long rebootDelay) +void wifiEnterConfigPortal(bool state, bool erase, long rebootDelay, bool STAonly) { wm.disconnect(); sUserSettings settings = NVstore.getUserSettings(); - settings.wifiMode = 1; + settings.wifiMode = STAonly ? 0x02 : 0x01; NVstore.setUserSettings(settings); NVstore.save(); + NVstore.doSave(); // ensure NV storage prepBootIntoConfigPortal(state); const char* content[2]; - if(isWifiSTA() && !erase) - content[0] = "WiFi Mode \032 STA+AP"; - else + if(isWifiSTA() && !erase) { + if(STAonly) + content[0] = "WiFi Mode \032 STA only"; + else + content[0] = "WiFi Mode \032 STA+AP"; + } + else { content[0] = "WiFi Mode \032 AP only"; + } if(erase) { wm.resetSettings(); @@ -238,10 +272,10 @@ void wifiFactoryDefault() wm.resetSettings(); prepBootIntoConfigPortal(false); sUserSettings settings = NVstore.getUserSettings(); -// settings.enableWifi = 1; settings.wifiMode = 1; NVstore.setUserSettings(settings); NVstore.save(); + NVstore.doSave(); // ensure NV storage } // callback is invoked by WiFiManager after new credentials are saved and verified @@ -258,7 +292,7 @@ void APstartedCallback(WiFiManager*) const char* getWifiAPAddrStr() { - if(NVstore.getUserSettings().wifiMode) { + if(NVstore.getUserSettings().wifiMode) { // check that wifi should be active IPAddress IPaddr = WiFi.softAPIP(); // use stepping stone - function returns an automatic stack var - LAME! static char APIPaddr[16]; sprintf(APIPaddr, "%d.%d.%d.%d", IPaddr[0], IPaddr[1], IPaddr[2], IPaddr[3]); @@ -270,7 +304,7 @@ const char* getWifiAPAddrStr() const char* getWifiSTAAddrStr() { - if(NVstore.getUserSettings().wifiMode) { + if(NVstore.getUserSettings().wifiMode) { // check that wifi should be active IPAddress IPaddr = WiFi.localIP(); // use stepping stone - function returns an automatic stack var - LAME! static char STAIPaddr[16]; sprintf(STAIPaddr, "%d.%d.%d.%d", IPaddr[0], IPaddr[1], IPaddr[2], IPaddr[3]); @@ -282,7 +316,7 @@ const char* getWifiSTAAddrStr() const char* getWifiGatewayAddrStr() { - if(NVstore.getUserSettings().wifiMode) { + if(NVstore.getUserSettings().wifiMode) { // check that wifi should be active IPAddress IPaddr = WiFi.gatewayIP(); // use stepping stone - function returns an automatic stack var - LAME! static char GWIPaddr[16]; sprintf(GWIPaddr, "%d.%d.%d.%d", IPaddr[0], IPaddr[1], IPaddr[2], IPaddr[3]); @@ -294,7 +328,7 @@ const char* getWifiGatewayAddrStr() int8_t getWifiRSSI() { - if(NVstore.getUserSettings().wifiMode) { + if(NVstore.getUserSettings().wifiMode) { // check that wifi should be active static unsigned long updateRSSI = millis() + 2500; static int8_t RSSI = 0; long tDelta = millis() - updateRSSI; @@ -322,9 +356,9 @@ const char* getWifiSTAMACStr() return MACstr[0]; } -String getSSID() +String getSTASSID() { - if(NVstore.getUserSettings().wifiMode) { + if(NVstore.getUserSettings().wifiMode) { // check that wifi should be active wifi_config_t conf; esp_wifi_get_config(WIFI_IF_STA, &conf); return String(reinterpret_cast(conf.sta.ssid)); @@ -333,22 +367,23 @@ String getSSID() return ""; } -bool isWifiConnected() +bool isWifiSTAConnected() { - if(NVstore.getUserSettings().wifiMode) + if(NVstore.getUserSettings().wifiMode) { // non zero => enabled wifi, maybe AP only or STA+AP or STA only return WiFi.status() == WL_CONNECTED; - else - return false; + } + + return false; } -bool isWifiAP() +bool isWifiAPonly() { - if(NVstore.getUserSettings().wifiMode) { + if(NVstore.getUserSettings().wifiMode) { // non zero => enabled wifi, maybe AP only or STA+AP or STA only int mode = WiFi.getMode(); return !isSTA && ((mode & WIFI_MODE_AP) != 0); } - else - return false; + + return false; } bool isWifiSTA() diff --git a/src/WiFi/BTCWifi.h b/src/WiFi/BTCWifi.h index 4f8d93f..5811f68 100644 --- a/src/WiFi/BTCWifi.h +++ b/src/WiFi/BTCWifi.h @@ -25,23 +25,23 @@ #include void doWiFiManager(); -bool initWifi(const char *failedssid, const char *failedpassword); +bool initWifi(); const char* getWifiAPAddrStr(); const char* getWifiSTAAddrStr(); const char* getWifiGatewayAddrStr(); const char* getWifiAPMACStr(); const char* getWifiSTAMACStr(); int8_t getWifiRSSI(); -String getSSID(); +String getSTASSID(); -bool isWifiConnected(); -bool isWifiAP(); +bool isWifiSTAConnected(); +bool isWifiAPonly(); bool isWifiSTA(); bool isWifiConfigPortal(); bool isWebClientConnected(); bool hasWebClientSpoken(bool reset = false); bool hasWebServerSpoken(bool reset = false); -void wifiEnterConfigPortal(bool state, bool erase = false, long timeout = 7000); +void wifiEnterConfigPortal(bool state, bool erase = false, long timeout = 7000, bool STAonly = false); void wifiDisable(long rebootDelay = 7000); void wifiFactoryDefault(); int isWifiButton(); diff --git a/src/WiFi/BTCota.cpp b/src/WiFi/BTCota.cpp index 9485732..68d8bf2 100644 --- a/src/WiFi/BTCota.cpp +++ b/src/WiFi/BTCota.cpp @@ -105,7 +105,7 @@ void initOTA(){ } -void DoOTA() +void doOTA() { ArduinoOTA.handle(); diff --git a/src/WiFi/BTCota.h b/src/WiFi/BTCota.h index 761755a..c57aecb 100644 --- a/src/WiFi/BTCota.h +++ b/src/WiFi/BTCota.h @@ -24,7 +24,7 @@ void initOTA(); void initFOTA(); -void DoOTA(); +void doOTA(); bool CheckFirmwareCRC(int size); #endif \ No newline at end of file diff --git a/src/cfg/BTCConfig.h b/src/cfg/BTCConfig.h index 8ab0b40..dc80c6c 100644 --- a/src/cfg/BTCConfig.h +++ b/src/cfg/BTCConfig.h @@ -42,7 +42,7 @@ // HC-05 works OK with WiFi // #define USE_WIFI 1 -#define USE_AP_ALWAYS 1 +#define USE_AP_ALWAYS 0 #define USE_OTA 1 #define USE_WEBSERVER 1 #define USE_MQTT 1