Add WiFi network scan RPC command to Improv Serial (#3271)

This commit is contained in:
Christian Schwinne 2023-06-27 01:51:44 +02:00 committed by GitHub
parent f015227fc8
commit 481bd6f57a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 122 additions and 77 deletions

View File

@ -10,7 +10,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# CI binaries # 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 default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth, lolin_s2_mini, esp32c3dev, esp32s3dev_8MB
# Release binaries # Release binaries
@ -40,6 +40,8 @@ default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth, lolin_
; default_envs = esp32dev_qio80 ; default_envs = esp32dev_qio80
; default_envs = esp32_eth_ota1mapp ; default_envs = esp32_eth_ota1mapp
; default_envs = esp32s2_saola ; default_envs = esp32s2_saola
; default_envs = esp32c3dev
; default_envs = lolin_s2_mini
src_dir = ./wled00 src_dir = ./wled00
data_dir = ./wled00/data data_dir = ./wled00/data
@ -460,8 +462,8 @@ board = esp32-c3-devkitm-1
board_build.partitions = tools/WLED_ESP32_4MB_1MB_FS.csv board_build.partitions = tools/WLED_ESP32_4MB_1MB_FS.csv
build_flags = ${common.build_flags} ${esp32c3.build_flags} #-D WLED_RELEASE_NAME=ESP32-C3 build_flags = ${common.build_flags} ${esp32c3.build_flags} #-D WLED_RELEASE_NAME=ESP32-C3
-D WLED_WATCHDOG_TIMEOUT=0 -D WLED_WATCHDOG_TIMEOUT=0
; -DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB -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=0 ;; for serial-to-USB chip
upload_speed = 460800 upload_speed = 460800
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
lib_deps = ${esp32c3.lib_deps} lib_deps = ${esp32c3.lib_deps}
@ -573,10 +575,10 @@ platform = ${esp32s2.platform}
platform_packages = ${esp32s2.platform_packages} platform_packages = ${esp32s2.platform_packages}
board = lolin_s2_mini board = lolin_s2_mini
board_build.partitions = tools/WLED_ESP32_4MB_1MB_FS.csv 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 build_flags = ${common.build_flags} ${esp32s2.build_flags} #-D WLED_RELEASE_NAME=LolinS2
-DBOARD_HAS_PSRAM -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_MSC_ON_BOOT=0
-DARDUINO_USB_DFU_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0
-DLOLIN_WIFI_FIX ; seems to work much better with this -DLOLIN_WIFI_FIX ; seems to work much better with this

View File

@ -104,10 +104,20 @@ void sendHuePoll();
void onHueData(void* arg, AsyncClient* client, void *data, size_t len); void onHueData(void* arg, AsyncClient* client, void *data, size_t len);
//improv.cpp //improv.cpp
enum ImprovRPCType {
Command_Wifi = 0x01,
Request_State = 0x02,
Request_Info = 0x03,
Request_Scan = 0x04
};
void handleImprovPacket(); void handleImprovPacket();
void sendImprovRPCResult(ImprovRPCType type, uint8_t n_strings = 0, const char **strings = nullptr);
void sendImprovStateResponse(uint8_t state, bool error = false); void sendImprovStateResponse(uint8_t state, bool error = false);
void sendImprovInfoResponse(); void sendImprovInfoResponse();
void sendImprovRPCResponse(byte commandId); void startImprovWifiScan();
void handleImprovWifiScan();
void sendImprovIPRPCResult(ImprovRPCType type);
//ir.cpp //ir.cpp
void applyRepeatActions(); void applyRepeatActions();

View File

@ -10,6 +10,11 @@
#define DIMPROV_PRINTF(x...) #define DIMPROV_PRINTF(x...)
#endif #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 #define IMPROV_VERSION 1
void parseWiFiCommand(char *rpcData); void parseWiFiCommand(char *rpcData);
@ -28,20 +33,14 @@ enum ImprovPacketByte {
RPC_CommandType = 9 RPC_CommandType = 9
}; };
enum ImprovRPCType { #ifndef WLED_DISABLE_IMPROV_WIFISCAN
Command_Wifi = 0x01, static bool improvWifiScanRunning = false;
Request_State = 0x02, #endif
Request_Info = 0x03
};
//File dbgf;
//blocking function to parse an Improv Serial packet //blocking function to parse an Improv Serial packet
void handleImprovPacket() { void handleImprovPacket() {
uint8_t header[6] = {'I','M','P','R','O','V'}; uint8_t header[6] = {'I','M','P','R','O','V'};
//dbgf = WLED_FS.open("/improv.log","a");
bool timeout = false; bool timeout = false;
uint8_t waitTime = 25; uint8_t waitTime = 25;
uint16_t packetByte = 0; uint16_t packetByte = 0;
@ -62,12 +61,11 @@ void handleImprovPacket() {
byte next = Serial.read(); byte next = Serial.read();
DIMPROV_PRINT("Received improv byte: "); DIMPROV_PRINTF("%x\r\n",next); DIMPROV_PRINT("Received improv byte: "); DIMPROV_PRINTF("%x\r\n",next);
//f.write(next);
switch (packetByte) { switch (packetByte) {
case ImprovPacketByte::Version: { case ImprovPacketByte::Version: {
if (next != IMPROV_VERSION) { if (next != IMPROV_VERSION) {
DIMPROV_PRINTLN(F("Invalid version")); DIMPROV_PRINTLN(F("Invalid version"));
//dbgf.close();
return; return;
} }
break; break;
@ -75,7 +73,6 @@ void handleImprovPacket() {
case ImprovPacketByte::PacketType: { case ImprovPacketByte::PacketType: {
if (next != ImprovPacketType::RPC_Command) { if (next != ImprovPacketType::RPC_Command) {
DIMPROV_PRINTF("Non RPC-command improv packet type %i\n",next); DIMPROV_PRINTF("Non RPC-command improv packet type %i\n",next);
//dbgf.close();
return; return;
} }
if (!improvActive) improvActive = 1; if (!improvActive) improvActive = 1;
@ -89,7 +86,6 @@ void handleImprovPacket() {
if (checksum != next) { if (checksum != next) {
DIMPROV_PRINTF("Got RPC checksum %i, expected %i",next,checksum); DIMPROV_PRINTF("Got RPC checksum %i, expected %i",next,checksum);
sendImprovStateResponse(0x01, true); sendImprovStateResponse(0x01, true);
//dbgf.close();
return; return;
} }
@ -100,22 +96,23 @@ void handleImprovPacket() {
if (WLED_WIFI_CONFIGURED) improvState = 0x03; //provisioning if (WLED_WIFI_CONFIGURED) improvState = 0x03; //provisioning
if (Network.isConnected()) improvState = 0x04; //provisioned if (Network.isConnected()) improvState = 0x04; //provisioned
sendImprovStateResponse(improvState, false); sendImprovStateResponse(improvState, false);
if (improvState == 0x04) sendImprovRPCResponse(ImprovRPCType::Request_State); if (improvState == 0x04) sendImprovIPRPCResult(ImprovRPCType::Request_State);
break; break;
} }
case ImprovRPCType::Request_Info: sendImprovInfoResponse(); break; case ImprovRPCType::Request_Info: sendImprovInfoResponse(); break;
#ifndef WLED_DISABLE_IMPROV_WIFISCAN
case ImprovRPCType::Request_Scan: startImprovWifiScan(); break;
#endif
default: { default: {
DIMPROV_PRINTF("Unknown RPC command %i\n",next); DIMPROV_PRINTF("Unknown RPC command %i\n",next);
sendImprovStateResponse(0x02, true); sendImprovStateResponse(0x02, true);
} }
} }
//dbgf.close();
return; return;
} }
if (packetByte < 6) { //check header if (packetByte < 6) { //check header
if (next != header[packetByte]) { if (next != header[packetByte]) {
DIMPROV_PRINTLN(F("Invalid improv header")); DIMPROV_PRINTLN(F("Invalid improv header"));
//dbgf.close();
return; return;
} }
} else if (packetByte > 9) { //RPC data } else if (packetByte > 9) { //RPC data
@ -128,7 +125,6 @@ void handleImprovPacket() {
checksum += next; checksum += next;
packetByte++; packetByte++;
} }
//dbgf.close();
} }
void sendImprovStateResponse(uint8_t state, bool error) { void sendImprovStateResponse(uint8_t state, bool error) {
@ -147,79 +143,116 @@ void sendImprovStateResponse(uint8_t state, bool error) {
Serial.write('\n'); 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); if (improvError > 0 && improvError < 3) sendImprovStateResponse(0x00, true);
uint8_t packetLen = 12; 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[6] = IMPROV_VERSION;
out[7] = ImprovPacketType::RPC_Response; out[7] = ImprovPacketType::RPC_Response;
out[8] = 2; //Length (set below) //out[8] = 2; //Length (set below)
out[9] = commandId; out[9] = type;
out[10] = 0; //Data len (set below) //out[10] = 0; //Data len (set below)
out[11] = '\0'; //URL len (set below) uint16_t pos = 11;
if (Network.isConnected()) for (uint8_t s = 0; s < n_strings; s++) {
{ size_t len = strlen(strings[s]);
IPAddress localIP = Network.localIP(); if (pos + len > 254) continue; // simple buffer overflow guard
uint8_t len = sprintf(out+12, "http://%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]); out[pos++] = len;
if (len > 24) return; //sprintf fail? strcpy(out + pos, strings[s]);
out[11] = len; pos += len;
out[10] = 1 + len;
out[8] = 3 + len; //RPC command type + data len + url len + url
packetLen = 13 + 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; uint8_t checksum = 0;
for (uint8_t i = 0; i < packetLen -1; i++) checksum += out[i]; for (uint8_t i = 0; i < packetLen -1; i++) checksum += out[i];
out[packetLen -1] = checksum; out[packetLen -1] = checksum;
Serial.write((uint8_t*)out, packetLen); Serial.write((uint8_t*)out, packetLen);
Serial.write('\n'); 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 improvActive = 1; //no longer provisioning
} }
void sendImprovInfoResponse() { void sendImprovInfoResponse() {
if (improvError > 0 && improvError < 3) sendImprovStateResponse(0x00, true); const char* bString =
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 #ifdef ESP8266
strcpy(out+lengthSum+1,"esp8266"); "esp8266"
#else #elif CONFIG_IDF_TARGET_ESP32C3
hlen = 5; "esp32-c3"
strcpy(out+lengthSum+1,"esp32"); #elif CONFIG_IDF_TARGET_ESP32S2
"esp32-s2"
#elif CONFIG_IDF_TARGET_ESP32S3
"esp32-s3";
#else // ESP32
"esp32";
#endif #endif
out[lengthSum] = hlen; ;
lengthSum += hlen + 1;
//Use serverDescription if it has been changed from the default "WLED", else mDNS name //Use serverDescription if it has been changed from the default "WLED", else mDNS name
bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0); bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0);
strcpy(out+lengthSum+1,useMdnsName ? cmDNS : serverDescription); char vString[20];
uint8_t nlen = strlen(useMdnsName ? cmDNS : serverDescription); sprintf_P(vString, PSTR("0.14.0-b3/%i"), VERSION);
out[lengthSum] = nlen; const char *str[4] = {"WLED", vString, bString, useMdnsName ? cmDNS : serverDescription};
lengthSum += nlen + 1;
packetLen = lengthSum +1; sendImprovRPCResult(ImprovRPCType::Request_Info, 4, str);
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);
} }
#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) { void parseWiFiCommand(char* rpcData) {
uint8_t len = rpcData[0]; uint8_t len = rpcData[0];
if (!len || len > 126) return; if (!len || len > 126) return;

View File

@ -48,6 +48,7 @@ void WLED::loop()
handleConnection(); handleConnection();
handleRemote(); handleRemote();
handleSerial(); handleSerial();
handleImprovWifiScan();
handleNotifications(); handleNotifications();
handleTransitions(); handleTransitions();
#ifdef WLED_ENABLE_DMX #ifdef WLED_ENABLE_DMX
@ -646,7 +647,6 @@ void WLED::initConnection()
ws.onEvent(wsEvent); ws.onEvent(wsEvent);
#endif #endif
WiFi.disconnect(true); // close old connections WiFi.disconnect(true); // close old connections
#ifdef ESP8266 #ifdef ESP8266
WiFi.setPhyMode(WIFI_PHY_MODE_11N); WiFi.setPhyMode(WIFI_PHY_MODE_11N);
@ -845,7 +845,7 @@ void WLED::handleConnection()
if (improvActive) { if (improvActive) {
if (improvError == 3) sendImprovStateResponse(0x00, true); if (improvError == 3) sendImprovStateResponse(0x00, true);
sendImprovStateResponse(0x04); sendImprovStateResponse(0x04);
if (improvActive > 1) sendImprovRPCResponse(0x01); if (improvActive > 1) sendImprovIPRPCResult(ImprovRPCType::Command_Wifi);
} }
initInterfaces(); initInterfaces();
userConnected(); userConnected();