diff --git a/platformio.ini b/platformio.ini index 8838b9a7..d3b71d3c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -10,7 +10,7 @@ # ------------------------------------------------------------------------------ # CI binaries -;; default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth # ESP32 variant builds are temporarily excluded from CI due to toolchain issues on the GitHub Actions Linux environment +; default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth # ESP32 variant builds are temporarily excluded from CI due to toolchain issues on the GitHub Actions Linux environment default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth, lolin_s2_mini, esp32c3dev, esp32s3dev_8MB # Release binaries @@ -40,6 +40,8 @@ default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth, lolin_ ; default_envs = esp32dev_qio80 ; default_envs = esp32_eth_ota1mapp ; default_envs = esp32s2_saola +; default_envs = esp32c3dev +; default_envs = lolin_s2_mini src_dir = ./wled00 data_dir = ./wled00/data @@ -460,8 +462,8 @@ board = esp32-c3-devkitm-1 board_build.partitions = tools/WLED_ESP32_4MB_1MB_FS.csv build_flags = ${common.build_flags} ${esp32c3.build_flags} #-D WLED_RELEASE_NAME=ESP32-C3 -D WLED_WATCHDOG_TIMEOUT=0 - ; -DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB - -DARDUINO_USB_CDC_ON_BOOT=0 ;; for serial-to-USB chip + -DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB + ;-DARDUINO_USB_CDC_ON_BOOT=0 ;; for serial-to-USB chip upload_speed = 460800 build_unflags = ${common.build_unflags} lib_deps = ${esp32c3.lib_deps} @@ -573,10 +575,10 @@ platform = ${esp32s2.platform} platform_packages = ${esp32s2.platform_packages} board = lolin_s2_mini board_build.partitions = tools/WLED_ESP32_4MB_1MB_FS.csv -build_unflags = ${common.build_unflags} -DARDUINO_USB_CDC_ON_BOOT=1 +build_unflags = ${common.build_unflags} #-DARDUINO_USB_CDC_ON_BOOT=1 build_flags = ${common.build_flags} ${esp32s2.build_flags} #-D WLED_RELEASE_NAME=LolinS2 -DBOARD_HAS_PSRAM - -DARDUINO_USB_CDC_ON_BOOT=0 + -DARDUINO_USB_CDC_ON_BOOT=1 # try disabling and enabling unflag above in case of board-specific issues, will disable Serial -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 -DLOLIN_WIFI_FIX ; seems to work much better with this diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 40a91c34..c67fdbf3 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -104,10 +104,20 @@ void sendHuePoll(); void onHueData(void* arg, AsyncClient* client, void *data, size_t len); //improv.cpp +enum ImprovRPCType { + Command_Wifi = 0x01, + Request_State = 0x02, + Request_Info = 0x03, + Request_Scan = 0x04 +}; + void handleImprovPacket(); +void sendImprovRPCResult(ImprovRPCType type, uint8_t n_strings = 0, const char **strings = nullptr); void sendImprovStateResponse(uint8_t state, bool error = false); void sendImprovInfoResponse(); -void sendImprovRPCResponse(byte commandId); +void startImprovWifiScan(); +void handleImprovWifiScan(); +void sendImprovIPRPCResult(ImprovRPCType type); //ir.cpp void applyRepeatActions(); diff --git a/wled00/improv.cpp b/wled00/improv.cpp index c2c391c8..d99be68d 100644 --- a/wled00/improv.cpp +++ b/wled00/improv.cpp @@ -10,6 +10,11 @@ #define DIMPROV_PRINTF(x...) #endif +#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3) +#undef WLED_DISABLE_IMPROV_WIFISCAN +#define WLED_DISABLE_IMPROV_WIFISCAN +#endif + #define IMPROV_VERSION 1 void parseWiFiCommand(char *rpcData); @@ -28,20 +33,14 @@ enum ImprovPacketByte { RPC_CommandType = 9 }; -enum ImprovRPCType { - Command_Wifi = 0x01, - Request_State = 0x02, - Request_Info = 0x03 -}; - -//File dbgf; +#ifndef WLED_DISABLE_IMPROV_WIFISCAN +static bool improvWifiScanRunning = false; +#endif //blocking function to parse an Improv Serial packet void handleImprovPacket() { uint8_t header[6] = {'I','M','P','R','O','V'}; - //dbgf = WLED_FS.open("/improv.log","a"); - bool timeout = false; uint8_t waitTime = 25; uint16_t packetByte = 0; @@ -62,12 +61,11 @@ void handleImprovPacket() { byte next = Serial.read(); DIMPROV_PRINT("Received improv byte: "); DIMPROV_PRINTF("%x\r\n",next); - //f.write(next); + switch (packetByte) { case ImprovPacketByte::Version: { if (next != IMPROV_VERSION) { DIMPROV_PRINTLN(F("Invalid version")); - //dbgf.close(); return; } break; @@ -75,7 +73,6 @@ void handleImprovPacket() { case ImprovPacketByte::PacketType: { if (next != ImprovPacketType::RPC_Command) { DIMPROV_PRINTF("Non RPC-command improv packet type %i\n",next); - //dbgf.close(); return; } if (!improvActive) improvActive = 1; @@ -89,7 +86,6 @@ void handleImprovPacket() { if (checksum != next) { DIMPROV_PRINTF("Got RPC checksum %i, expected %i",next,checksum); sendImprovStateResponse(0x01, true); - //dbgf.close(); return; } @@ -100,22 +96,23 @@ void handleImprovPacket() { if (WLED_WIFI_CONFIGURED) improvState = 0x03; //provisioning if (Network.isConnected()) improvState = 0x04; //provisioned sendImprovStateResponse(improvState, false); - if (improvState == 0x04) sendImprovRPCResponse(ImprovRPCType::Request_State); + if (improvState == 0x04) sendImprovIPRPCResult(ImprovRPCType::Request_State); break; } case ImprovRPCType::Request_Info: sendImprovInfoResponse(); break; + #ifndef WLED_DISABLE_IMPROV_WIFISCAN + case ImprovRPCType::Request_Scan: startImprovWifiScan(); break; + #endif default: { DIMPROV_PRINTF("Unknown RPC command %i\n",next); sendImprovStateResponse(0x02, true); } } - //dbgf.close(); return; } if (packetByte < 6) { //check header if (next != header[packetByte]) { DIMPROV_PRINTLN(F("Invalid improv header")); - //dbgf.close(); return; } } else if (packetByte > 9) { //RPC data @@ -128,7 +125,6 @@ void handleImprovPacket() { checksum += next; packetByte++; } - //dbgf.close(); } void sendImprovStateResponse(uint8_t state, bool error) { @@ -147,79 +143,116 @@ void sendImprovStateResponse(uint8_t state, bool error) { Serial.write('\n'); } -void sendImprovRPCResponse(byte commandId) { +// used by sendImprovIPRPCResult(), sendImprovInfoResponse(), and handleImprovWifiScan() +void sendImprovRPCResult(ImprovRPCType type, uint8_t n_strings, const char **strings) { if (improvError > 0 && improvError < 3) sendImprovStateResponse(0x00, true); uint8_t packetLen = 12; - char out[64] = {'I','M','P','R','O','V'}; + char out[256] = {'I','M','P','R','O','V'}; out[6] = IMPROV_VERSION; out[7] = ImprovPacketType::RPC_Response; - out[8] = 2; //Length (set below) - out[9] = commandId; - out[10] = 0; //Data len (set below) - out[11] = '\0'; //URL len (set below) + //out[8] = 2; //Length (set below) + out[9] = type; + //out[10] = 0; //Data len (set below) + uint16_t pos = 11; - if (Network.isConnected()) - { - IPAddress localIP = Network.localIP(); - uint8_t len = sprintf(out+12, "http://%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]); - if (len > 24) return; //sprintf fail? - out[11] = len; - out[10] = 1 + len; - out[8] = 3 + len; //RPC command type + data len + url len + url - packetLen = 13 + len; + for (uint8_t s = 0; s < n_strings; s++) { + size_t len = strlen(strings[s]); + if (pos + len > 254) continue; // simple buffer overflow guard + out[pos++] = len; + strcpy(out + pos, strings[s]); + pos += len; } + packetLen = pos +1; + out[8] = pos -9; // Length of packet (excluding first 9 header bytes and final checksum byte) + out[10] = pos -11; // Data len + uint8_t checksum = 0; for (uint8_t i = 0; i < packetLen -1; i++) checksum += out[i]; out[packetLen -1] = checksum; Serial.write((uint8_t*)out, packetLen); Serial.write('\n'); + DIMPROV_PRINT("RPC result checksum"); + DIMPROV_PRINTLN(checksum); +} + +void sendImprovIPRPCResult(ImprovRPCType type) { + if (Network.isConnected()) + { + char urlStr[64]; + IPAddress localIP = Network.localIP(); + uint8_t len = sprintf(urlStr, "http://%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]); + if (len > 24) return; //sprintf fail? + const char *str[1] = {urlStr}; + sendImprovRPCResult(type, 1, str); + } else { + sendImprovRPCResult(type, 0); + } + improvActive = 1; //no longer provisioning } void sendImprovInfoResponse() { - if (improvError > 0 && improvError < 3) sendImprovStateResponse(0x00, true); - uint8_t packetLen = 12; - char out[128] = {'I','M','P','R','O','V'}; - out[6] = IMPROV_VERSION; - out[7] = ImprovPacketType::RPC_Response; - //out[8] = 2; //Length (set below) - out[9] = ImprovRPCType::Request_Info; - //out[10] = 0; //Data len (set below) - out[11] = 4; //Firmware len ("WLED") - out[12] = 'W'; out[13] = 'L'; out[14] = 'E'; out[15] = 'D'; - uint8_t lengthSum = 17; - uint8_t vlen = sprintf_P(out+lengthSum,PSTR("0.14.0-b3/%i"),VERSION); - out[16] = vlen; lengthSum += vlen; - uint8_t hlen = 7; - #ifdef ESP8266 - strcpy(out+lengthSum+1,"esp8266"); - #else - hlen = 5; - strcpy(out+lengthSum+1,"esp32"); - #endif - out[lengthSum] = hlen; - lengthSum += hlen + 1; + const char* bString = + #ifdef ESP8266 + "esp8266" + #elif CONFIG_IDF_TARGET_ESP32C3 + "esp32-c3" + #elif CONFIG_IDF_TARGET_ESP32S2 + "esp32-s2" + #elif CONFIG_IDF_TARGET_ESP32S3 + "esp32-s3"; + #else // ESP32 + "esp32"; + #endif + ; + //Use serverDescription if it has been changed from the default "WLED", else mDNS name bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0); - strcpy(out+lengthSum+1,useMdnsName ? cmDNS : serverDescription); - uint8_t nlen = strlen(useMdnsName ? cmDNS : serverDescription); - out[lengthSum] = nlen; - lengthSum += nlen + 1; + char vString[20]; + sprintf_P(vString, PSTR("0.14.0-b3/%i"), VERSION); + const char *str[4] = {"WLED", vString, bString, useMdnsName ? cmDNS : serverDescription}; - packetLen = lengthSum +1; - out[8] = lengthSum -9; - out[10] = lengthSum -11; - - uint8_t checksum = 0; - for (uint8_t i = 0; i < packetLen -1; i++) checksum += out[i]; - out[packetLen -1] = checksum; - Serial.write((uint8_t*)out, packetLen); - Serial.write('\n'); - DIMPROV_PRINT("Info checksum"); - DIMPROV_PRINTLN(checksum); + sendImprovRPCResult(ImprovRPCType::Request_Info, 4, str); } +#ifndef WLED_DISABLE_IMPROV_WIFISCAN +void startImprovWifiScan() { + if (improvWifiScanRunning) return; + WiFi.scanNetworks(true); + improvWifiScanRunning = true; +} + +void handleImprovWifiScan() { + if (!improvWifiScanRunning) return; + int16_t status = WiFi.scanComplete(); + if (status == WIFI_SCAN_RUNNING) return; + // here scan completed or failed (-2) + improvWifiScanRunning = false; + + for (int i = 0; i < status; i++) { + char rssiStr[8]; + sprintf(rssiStr, "%d", WiFi.RSSI(i)); + #ifdef ESP8266 + bool isOpen = WiFi.encryptionType(i) == ENC_TYPE_NONE; + #else + bool isOpen = WiFi.encryptionType(i) == WIFI_AUTH_OPEN; + #endif + + char ssidStr[33]; + strcpy(ssidStr, WiFi.SSID(i).c_str()); + const char *str[3] = {ssidStr, rssiStr, isOpen ? "NO":"YES"}; + sendImprovRPCResult(ImprovRPCType::Request_Scan, 3, str); + } + sendImprovRPCResult(ImprovRPCType::Request_Scan, 0); + + WiFi.scanDelete(); +} +#else +void startImprovWifiScan() {} +void handleImprovWifiScan() {} +#endif + void parseWiFiCommand(char* rpcData) { uint8_t len = rpcData[0]; if (!len || len > 126) return; diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 6866a692..7b773ee9 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -48,6 +48,7 @@ void WLED::loop() handleConnection(); handleRemote(); handleSerial(); + handleImprovWifiScan(); handleNotifications(); handleTransitions(); #ifdef WLED_ENABLE_DMX @@ -646,7 +647,6 @@ void WLED::initConnection() ws.onEvent(wsEvent); #endif - WiFi.disconnect(true); // close old connections #ifdef ESP8266 WiFi.setPhyMode(WIFI_PHY_MODE_11N); @@ -845,7 +845,7 @@ void WLED::handleConnection() if (improvActive) { if (improvError == 3) sendImprovStateResponse(0x00, true); sendImprovStateResponse(0x04); - if (improvActive > 1) sendImprovRPCResponse(0x01); + if (improvActive > 1) sendImprovIPRPCResult(ImprovRPCType::Command_Wifi); } initInterfaces(); userConnected();