mirror of
https://github.com/wled/WLED.git
synced 2025-04-19 12:27:17 +00:00
Add ability to enter desired BSSID
- add event handling (debug) - fixes #2151
This commit is contained in:
parent
88738327fd
commit
272129f66c
@ -20,11 +20,11 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
|
||||
//long vid = doc[F("vid")]; // 2010020
|
||||
|
||||
#ifdef WLED_USE_ETHERNET
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET)
|
||||
JsonObject ethernet = doc[F("eth")];
|
||||
CJSON(ethernetType, ethernet["type"]);
|
||||
// NOTE: Ethernet configuration takes priority over other use of pins
|
||||
WLED::instance().initEthernet();
|
||||
initEthernet();
|
||||
#endif
|
||||
|
||||
JsonObject id = doc["id"];
|
||||
@ -53,9 +53,11 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
JsonArray sn = wifi["sn"];
|
||||
char ssid[33] = "";
|
||||
char pass[65] = "";
|
||||
char bssid[13] = "";
|
||||
IPAddress nIP = (uint32_t)0U, nGW = (uint32_t)0U, nSN = (uint32_t)0x00FFFFFF; // little endian
|
||||
getStringFromJson(ssid, wifi[F("ssid")], 33);
|
||||
getStringFromJson(pass, wifi["psk"], 65); // password is not normally present but if it is, use it
|
||||
getStringFromJson(bssid, wifi[F("bssid")], 13);
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
CJSON(nIP[i], ip[i]);
|
||||
CJSON(nGW[i], gw[i]);
|
||||
@ -63,6 +65,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
}
|
||||
if (strlen(ssid) > 0) strlcpy(multiWiFi[n].clientSSID, ssid, 33); // this will keep old SSID intact if not present in JSON
|
||||
if (strlen(pass) > 0) strlcpy(multiWiFi[n].clientPass, pass, 65); // this will keep old password intact if not present in JSON
|
||||
if (strlen(bssid) > 0) fillStr2MAC(multiWiFi[n].bssid, bssid);
|
||||
multiWiFi[n].staticIP = nIP;
|
||||
multiWiFi[n].staticGW = nGW;
|
||||
multiWiFi[n].staticSN = nSN;
|
||||
@ -702,8 +705,8 @@ void deserializeConfigFromFS() {
|
||||
UsermodManager::readFromConfig(empty);
|
||||
serializeConfig();
|
||||
// init Ethernet (in case default type is set at compile time)
|
||||
#ifdef WLED_USE_ETHERNET
|
||||
WLED::instance().initEthernet();
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET)
|
||||
initEthernet();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@ -751,6 +754,9 @@ void serializeConfig() {
|
||||
JsonObject wifi = nw_ins.createNestedObject();
|
||||
wifi[F("ssid")] = multiWiFi[n].clientSSID;
|
||||
wifi[F("pskl")] = strlen(multiWiFi[n].clientPass);
|
||||
char bssid[13];
|
||||
fillMAC2Str(bssid, multiWiFi[n].bssid);
|
||||
wifi[F("bssid")] = bssid;
|
||||
JsonArray wifi_ip = wifi.createNestedArray("ip");
|
||||
JsonArray wifi_gw = wifi.createNestedArray("gw");
|
||||
JsonArray wifi_sn = wifi.createNestedArray("sn");
|
||||
@ -786,7 +792,7 @@ void serializeConfig() {
|
||||
wifi[F("txpwr")] = txPower;
|
||||
#endif
|
||||
|
||||
#ifdef WLED_USE_ETHERNET
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET)
|
||||
JsonObject ethernet = root.createNestedObject("eth");
|
||||
ethernet["type"] = ethernetType;
|
||||
if (ethernetType != WLED_ETH_NONE && ethernetType < WLED_NUM_ETH_TYPES) {
|
||||
|
@ -109,12 +109,13 @@
|
||||
gId("wifi_add").style.display = (i<maxNetworks) ? "inline":"none";
|
||||
gId("wifi_rem").style.display = (i>1) ? "inline":"none";
|
||||
}
|
||||
function addWiFi(ssid="",pass="",ip=0,gw=0,sn=0x00ffffff) { // little endian
|
||||
function addWiFi(ssid="",pass="",bssid="",ip=0,gw=0,sn=0x00ffffff) { // little endian
|
||||
var i = gId("wifi_entries").childNodes.length;
|
||||
if (i >= maxNetworks) return;
|
||||
var b = `<div id="net${i}"><hr class="sml">
|
||||
Network name (SSID${i==0?", empty to not connect":""}):<br><input type="text" id="CS${i}" name="CS${i}" maxlength="32" value="${ssid}" ${i>0?"required":""}><br>
|
||||
Network password:<br><input type="password" name="PW${i}" maxlength="64" value="${pass}"><br>
|
||||
BSSID (optional):<br><input type="text" id="BS${i}" name="BS${i}" maxlength="12" value="${bssid}"><br>
|
||||
Static IP (leave at 0.0.0.0 for DHCP)${i==0?"<br>Also used by Ethernet":""}:<br>
|
||||
<input name="IP${i}0" type="number" class="s" min="0" max="255" value="${ip&0xFF}" required>.<input name="IP${i}1" type="number" class="s" min="0" max="255" value="${(ip>>8)&0xFF}" required>.<input name="IP${i}2" type="number" class="s" min="0" max="255" value="${(ip>>16)&0xFF}" required>.<input name="IP${i}3" type="number" class="s" min="0" max="255" value="${(ip>>24)&0xFF}" required><br>
|
||||
Static gateway:<br>
|
||||
|
@ -52,6 +52,7 @@ bool getJsonValue(const JsonVariant& element, DestType& destination, const Defau
|
||||
typedef struct WiFiConfig {
|
||||
char clientSSID[33];
|
||||
char clientPass[65];
|
||||
uint8_t bssid[6];
|
||||
IPAddress staticIP;
|
||||
IPAddress staticGW;
|
||||
IPAddress staticSN;
|
||||
@ -62,6 +63,7 @@ typedef struct WiFiConfig {
|
||||
{
|
||||
strncpy(clientSSID, ssid, 32); clientSSID[32] = 0;
|
||||
strncpy(clientPass, pass, 64); clientPass[64] = 0;
|
||||
memset(bssid, 0, sizeof(bssid));
|
||||
}
|
||||
} wifi_config;
|
||||
|
||||
@ -340,7 +342,12 @@ void espNowReceiveCB(uint8_t* address, uint8_t* data, uint8_t len, signed int rs
|
||||
#endif
|
||||
|
||||
//network.cpp
|
||||
int getSignalQuality(int rssi);
|
||||
bool initEthernet(); // result is informational
|
||||
int getSignalQuality(int rssi);
|
||||
void fillMAC2Str(char *str, const uint8_t *mac);
|
||||
void fillStr2MAC(uint8_t *mac, const char *str);
|
||||
int findWiFi(bool doScan = false);
|
||||
bool isWiFiConfigured();
|
||||
void WiFiEvent(WiFiEvent_t event);
|
||||
|
||||
//um_manager.cpp
|
||||
@ -464,6 +471,7 @@ void userLoop();
|
||||
#include "soc/wdev_reg.h"
|
||||
#define HW_RND_REGISTER REG_READ(WDEV_RND_REG)
|
||||
#endif
|
||||
#define hex2int(a) (((a)>='0' && (a)<='9') ? (a)-'0' : ((a)>='A' && (a)<='F') ? (a)-'A'+10 : ((a)>='a' && (a)<='f') ? (a)-'a'+10 : 0)
|
||||
int getNumVal(const String* req, uint16_t pos);
|
||||
void parseNumber(const char* str, byte* val, byte minv=0, byte maxv=255);
|
||||
bool getVal(JsonVariant elem, byte* val, byte minv=0, byte maxv=255); // getVal supports inc/decrementing and random ("X~Y(r|~[w][-][Z])" form)
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "wled_ethernet.h"
|
||||
|
||||
|
||||
#ifdef WLED_USE_ETHERNET
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET)
|
||||
// The following six pins are neither configurable nor
|
||||
// can they be re-assigned through IOMUX / GPIO matrix.
|
||||
// See https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-ethernet-kit-v1.1.html#ip101gri-phy-interface
|
||||
@ -146,6 +146,101 @@ const ethernet_settings ethernetBoards[] = {
|
||||
ETH_CLOCK_GPIO0_OUT // eth_clk_mode
|
||||
}
|
||||
};
|
||||
|
||||
bool initEthernet()
|
||||
{
|
||||
static bool successfullyConfiguredEthernet = false;
|
||||
|
||||
if (successfullyConfiguredEthernet) {
|
||||
// DEBUG_PRINTLN(F("initE: ETH already successfully configured, ignoring"));
|
||||
return false;
|
||||
}
|
||||
if (ethernetType == WLED_ETH_NONE) {
|
||||
return false;
|
||||
}
|
||||
if (ethernetType >= WLED_NUM_ETH_TYPES) {
|
||||
DEBUG_PRINTF_P(PSTR("initE: Ignoring attempt for invalid ethernetType (%d)\n"), ethernetType);
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG_PRINTF_P(PSTR("initE: Attempting ETH config: %d\n"), ethernetType);
|
||||
|
||||
// Ethernet initialization should only succeed once -- else reboot required
|
||||
ethernet_settings es = ethernetBoards[ethernetType];
|
||||
managed_pin_type pinsToAllocate[10] = {
|
||||
// first six pins are non-configurable
|
||||
esp32_nonconfigurable_ethernet_pins[0],
|
||||
esp32_nonconfigurable_ethernet_pins[1],
|
||||
esp32_nonconfigurable_ethernet_pins[2],
|
||||
esp32_nonconfigurable_ethernet_pins[3],
|
||||
esp32_nonconfigurable_ethernet_pins[4],
|
||||
esp32_nonconfigurable_ethernet_pins[5],
|
||||
{ (int8_t)es.eth_mdc, true }, // [6] = MDC is output and mandatory
|
||||
{ (int8_t)es.eth_mdio, true }, // [7] = MDIO is bidirectional and mandatory
|
||||
{ (int8_t)es.eth_power, true }, // [8] = optional pin, not all boards use
|
||||
{ ((int8_t)0xFE), false }, // [9] = replaced with eth_clk_mode, mandatory
|
||||
};
|
||||
// update the clock pin....
|
||||
if (es.eth_clk_mode == ETH_CLOCK_GPIO0_IN) {
|
||||
pinsToAllocate[9].pin = 0;
|
||||
pinsToAllocate[9].isOutput = false;
|
||||
} else if (es.eth_clk_mode == ETH_CLOCK_GPIO0_OUT) {
|
||||
pinsToAllocate[9].pin = 0;
|
||||
pinsToAllocate[9].isOutput = true;
|
||||
} else if (es.eth_clk_mode == ETH_CLOCK_GPIO16_OUT) {
|
||||
pinsToAllocate[9].pin = 16;
|
||||
pinsToAllocate[9].isOutput = true;
|
||||
} else if (es.eth_clk_mode == ETH_CLOCK_GPIO17_OUT) {
|
||||
pinsToAllocate[9].pin = 17;
|
||||
pinsToAllocate[9].isOutput = true;
|
||||
} else {
|
||||
DEBUG_PRINTF_P(PSTR("initE: Failing due to invalid eth_clk_mode (%d)\n"), es.eth_clk_mode);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!PinManager::allocateMultiplePins(pinsToAllocate, 10, PinOwner::Ethernet)) {
|
||||
DEBUG_PRINTLN(F("initE: Failed to allocate ethernet pins"));
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
For LAN8720 the most correct way is to perform clean reset each time before init
|
||||
applying LOW to power or nRST pin for at least 100 us (please refer to datasheet, page 59)
|
||||
ESP_IDF > V4 implements it (150 us, lan87xx_reset_hw(esp_eth_phy_t *phy) function in
|
||||
/components/esp_eth/src/esp_eth_phy_lan87xx.c, line 280)
|
||||
but ESP_IDF < V4 does not. Lets do it:
|
||||
[not always needed, might be relevant in some EMI situations at startup and for hot resets]
|
||||
*/
|
||||
#if ESP_IDF_VERSION_MAJOR==3
|
||||
if(es.eth_power>0 && es.eth_type==ETH_PHY_LAN8720) {
|
||||
pinMode(es.eth_power, OUTPUT);
|
||||
digitalWrite(es.eth_power, 0);
|
||||
delayMicroseconds(150);
|
||||
digitalWrite(es.eth_power, 1);
|
||||
delayMicroseconds(10);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!ETH.begin(
|
||||
(uint8_t) es.eth_address,
|
||||
(int) es.eth_power,
|
||||
(int) es.eth_mdc,
|
||||
(int) es.eth_mdio,
|
||||
(eth_phy_type_t) es.eth_type,
|
||||
(eth_clock_mode_t) es.eth_clk_mode
|
||||
)) {
|
||||
DEBUG_PRINTLN(F("initC: ETH.begin() failed"));
|
||||
// de-allocate the allocated pins
|
||||
for (managed_pin_type mpt : pinsToAllocate) {
|
||||
PinManager::deallocatePin(mpt.pin, PinOwner::Ethernet);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
successfullyConfiguredEthernet = true;
|
||||
DEBUG_PRINTLN(F("initC: *** Ethernet successfully configured! ***"));
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -170,19 +265,136 @@ int getSignalQuality(int rssi)
|
||||
}
|
||||
|
||||
|
||||
void fillMAC2Str(char *str, const uint8_t *mac) {
|
||||
sprintf_P(str, PSTR("%02x%02x%02x%02x%02x%02x"), MAC2STR(mac));
|
||||
byte nul = 0;
|
||||
for (int i = 0; i < 6; i++) nul |= *mac++; // do we have 0
|
||||
if (!nul) str[0] = '\0'; // empty string
|
||||
}
|
||||
|
||||
void fillStr2MAC(uint8_t *mac, const char *str) {
|
||||
for (int i = 0; i < 6; i++) *mac++ = 0; // clear
|
||||
if (!str) return; // null string
|
||||
uint64_t MAC = strtoull(str, nullptr, 16);
|
||||
for (int i = 0; i < 6; i++) { *--mac = MAC & 0xFF; MAC >>= 8; }
|
||||
}
|
||||
|
||||
|
||||
// performs asynchronous scan for available networks (which may take couple of seconds to finish)
|
||||
// returns configured WiFi ID with the strongest signal (or default if no configured networks available)
|
||||
int findWiFi(bool doScan) {
|
||||
if (multiWiFi.size() <= 1) {
|
||||
DEBUG_PRINTF_P(PSTR("WiFi: Defaulf SSID (%s) used.\n"), multiWiFi[0].clientSSID);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int status = WiFi.scanComplete(); // complete scan may take as much as several seconds (usually <6s with not very crowded air)
|
||||
|
||||
if (doScan || status == WIFI_SCAN_FAILED) {
|
||||
DEBUG_PRINTF_P(PSTR("WiFi: Scan started. @ %lus\n"), millis()/1000);
|
||||
WiFi.scanNetworks(true); // start scanning in asynchronous mode (will delete old scan)
|
||||
} else if (status >= 0) { // status contains number of found networks (including duplicate SSIDs with different BSSID)
|
||||
DEBUG_PRINTF_P(PSTR("WiFi: Found %d SSIDs. @ %lus\n"), status, millis()/1000);
|
||||
int rssi = -9999;
|
||||
int selected = selectedWiFi;
|
||||
for (int o = 0; o < status; o++) {
|
||||
DEBUG_PRINTF_P(PSTR(" SSID: %s (BSSID: %s) RSSI: %ddB\n"), WiFi.SSID(o).c_str(), WiFi.BSSIDstr(o).c_str(), WiFi.RSSI(o));
|
||||
for (unsigned n = 0; n < multiWiFi.size(); n++)
|
||||
if (!strcmp(WiFi.SSID(o).c_str(), multiWiFi[n].clientSSID)) {
|
||||
bool foundBSSID = memcmp(multiWiFi[n].bssid, WiFi.BSSID(o), 6) == 0;
|
||||
// find the WiFi with the strongest signal (but keep priority of entry if signal difference is not big)
|
||||
if (foundBSSID || (n < selected && WiFi.RSSI(o) > rssi-10) || WiFi.RSSI(o) > rssi) {
|
||||
rssi = foundBSSID ? 0 : WiFi.RSSI(o); // RSSI is only ever negative
|
||||
selected = n;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
DEBUG_PRINTF_P(PSTR("WiFi: Selected SSID: %s RSSI: %ddB\n"), multiWiFi[selected].clientSSID, rssi);
|
||||
return selected;
|
||||
}
|
||||
//DEBUG_PRINT(F("WiFi scan running."));
|
||||
return status; // scan is still running or there was an error
|
||||
}
|
||||
|
||||
|
||||
bool isWiFiConfigured() {
|
||||
return multiWiFi.size() > 1 || (strlen(multiWiFi[0].clientSSID) >= 1 && strcmp_P(multiWiFi[0].clientSSID, PSTR(DEFAULT_CLIENT_SSID)) != 0);
|
||||
}
|
||||
|
||||
#if defined(ESP8266)
|
||||
#define ARDUINO_EVENT_WIFI_AP_STADISCONNECTED WIFI_EVENT_SOFTAPMODE_STADISCONNECTED
|
||||
#define ARDUINO_EVENT_WIFI_AP_STACONNECTED WIFI_EVENT_SOFTAPMODE_STACONNECTED
|
||||
#define ARDUINO_EVENT_WIFI_STA_GOT_IP WIFI_EVENT_STAMODE_GOT_IP
|
||||
#define ARDUINO_EVENT_WIFI_STA_CONNECTED WIFI_EVENT_STAMODE_CONNECTED
|
||||
#define ARDUINO_EVENT_WIFI_STA_DISCONNECTED WIFI_EVENT_STAMODE_DISCONNECTED
|
||||
#elif defined(ARDUINO_ARCH_ESP32) && !defined(ESP_ARDUINO_VERSION_MAJOR) //ESP_IDF_VERSION_MAJOR==3
|
||||
// not strictly IDF v3 but Arduino core related
|
||||
#define ARDUINO_EVENT_WIFI_AP_STADISCONNECTED SYSTEM_EVENT_AP_STADISCONNECTED
|
||||
#define ARDUINO_EVENT_WIFI_AP_STACONNECTED SYSTEM_EVENT_AP_STACONNECTED
|
||||
#define ARDUINO_EVENT_WIFI_STA_GOT_IP SYSTEM_EVENT_STA_GOT_IP
|
||||
#define ARDUINO_EVENT_WIFI_STA_CONNECTED SYSTEM_EVENT_STA_CONNECTED
|
||||
#define ARDUINO_EVENT_WIFI_STA_DISCONNECTED SYSTEM_EVENT_STA_DISCONNECTED
|
||||
#define ARDUINO_EVENT_WIFI_AP_START SYSTEM_EVENT_AP_START
|
||||
#define ARDUINO_EVENT_WIFI_AP_STOP SYSTEM_EVENT_AP_STOP
|
||||
#define ARDUINO_EVENT_WIFI_SCAN_DONE SYSTEM_EVENT_SCAN_DONE
|
||||
#define ARDUINO_EVENT_ETH_START SYSTEM_EVENT_ETH_START
|
||||
#define ARDUINO_EVENT_ETH_CONNECTED SYSTEM_EVENT_ETH_CONNECTED
|
||||
#define ARDUINO_EVENT_ETH_DISCONNECTED SYSTEM_EVENT_ETH_DISCONNECTED
|
||||
#endif
|
||||
|
||||
//handle Ethernet connection event
|
||||
void WiFiEvent(WiFiEvent_t event)
|
||||
{
|
||||
switch (event) {
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET)
|
||||
case SYSTEM_EVENT_ETH_START:
|
||||
DEBUG_PRINTLN(F("ETH Started"));
|
||||
case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED:
|
||||
// AP client disconnected
|
||||
if (--apClients == 0 && isWiFiConfigured()) forceReconnect = true; // no clients reconnect WiFi if awailable
|
||||
DEBUG_PRINTF_P(PSTR("WiFi-E: AP Client Disconnected (%d) @ %lus.\n"), (int)apClients, millis()/1000);
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_CONNECTED:
|
||||
case ARDUINO_EVENT_WIFI_AP_STACONNECTED:
|
||||
// AP client connected
|
||||
apClients++;
|
||||
DEBUG_PRINTF_P(PSTR("WiFi-E: AP Client Connected (%d) @ %lus.\n"), (int)apClients, millis()/1000);
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
||||
DEBUG_PRINT(F("WiFi-E: IP address: ")); DEBUG_PRINTLN(Network.localIP());
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
|
||||
// followed by IDLE and SCAN_DONE
|
||||
DEBUG_PRINTF_P(PSTR("WiFi-E: Connected! @ %lus\n"), millis()/1000);
|
||||
wasConnected = true;
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||
if (wasConnected && interfacesInited) {
|
||||
DEBUG_PRINTF_P(PSTR("WiFi-E: Disconnected! @ %lus\n"), millis()/1000);
|
||||
if (interfacesInited && multiWiFi.size() > 1 && WiFi.scanComplete() >= 0) {
|
||||
findWiFi(true); // reinit WiFi scan
|
||||
forceReconnect = true;
|
||||
}
|
||||
interfacesInited = false;
|
||||
}
|
||||
break;
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
case ARDUINO_EVENT_WIFI_SCAN_DONE:
|
||||
// also triggered when connected to selected SSID
|
||||
DEBUG_PRINTLN(F("WiFi-E: SSID scan completed."));
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_AP_START:
|
||||
DEBUG_PRINTLN(F("WiFi-E: AP Started"));
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_AP_STOP:
|
||||
DEBUG_PRINTLN(F("WiFi-E: AP Stopped"));
|
||||
break;
|
||||
#if defined(WLED_USE_ETHERNET)
|
||||
case ARDUINO_EVENT_ETH_START:
|
||||
DEBUG_PRINTLN(F("ETH-E: Started"));
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_CONNECTED:
|
||||
{
|
||||
DEBUG_PRINTLN(F("ETH Connected"));
|
||||
DEBUG_PRINTLN(F("ETH-E: Connected"));
|
||||
if (!apActive) {
|
||||
WiFi.disconnect(true);
|
||||
WiFi.disconnect(true); // disable WiFi entirely
|
||||
}
|
||||
if (multiWiFi[0].staticIP != (uint32_t)0x00000000 && multiWiFi[0].staticGW != (uint32_t)0x00000000) {
|
||||
ETH.config(multiWiFi[0].staticIP, multiWiFi[0].staticGW, multiWiFi[0].staticSN, dnsAddress);
|
||||
@ -196,18 +408,20 @@ void WiFiEvent(WiFiEvent_t event)
|
||||
showWelcomePage = false;
|
||||
break;
|
||||
}
|
||||
case SYSTEM_EVENT_ETH_DISCONNECTED:
|
||||
DEBUG_PRINTLN(F("ETH Disconnected"));
|
||||
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
||||
DEBUG_PRINTLN(F("ETH-E: Disconnected"));
|
||||
// This doesn't really affect ethernet per se,
|
||||
// as it's only configured once. Rather, it
|
||||
// may be necessary to reconnect the WiFi when
|
||||
// ethernet disconnects, as a way to provide
|
||||
// alternative access to the device.
|
||||
if (interfacesInited && WiFi.scanComplete() >= 0) findWiFi(true); // reinit WiFi scan
|
||||
forceReconnect = true;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
default:
|
||||
DEBUG_PRINTF_P(PSTR("Network event: %d\n"), (int)event);
|
||||
DEBUG_PRINTF_P(PSTR("WiFi-E: Event %d\n"), (int)event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
for (size_t n = 0; n < WLED_MAX_WIFI_COUNT; n++) {
|
||||
char cs[4] = "CS"; cs[2] = 48+n; cs[3] = 0; //client SSID
|
||||
char pw[4] = "PW"; pw[2] = 48+n; pw[3] = 0; //client password
|
||||
char bs[4] = "BS"; bs[2] = 48+n; bs[3] = 0; //BSSID
|
||||
char ip[5] = "IP"; ip[2] = 48+n; ip[4] = 0; //IP address
|
||||
char gw[5] = "GW"; gw[2] = 48+n; gw[4] = 0; //GW address
|
||||
char sn[5] = "SN"; sn[2] = 48+n; sn[4] = 0; //subnet mask
|
||||
@ -39,6 +40,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
strlcpy(multiWiFi[n].clientPass, request->arg(pw).c_str(), 65);
|
||||
forceReconnect = true;
|
||||
}
|
||||
fillStr2MAC(multiWiFi[n].bssid, request->arg(bs).c_str());
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
ip[3] = 48+i;
|
||||
gw[3] = 48+i;
|
||||
@ -93,9 +95,9 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
strlwr(linked_remote); //Normalize MAC format to lowercase
|
||||
#endif
|
||||
|
||||
#ifdef WLED_USE_ETHERNET
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET)
|
||||
ethernetType = request->arg(F("ETH")).toInt();
|
||||
WLED::instance().initEthernet();
|
||||
initEthernet();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
140
wled00/wled.cpp
140
wled00/wled.cpp
@ -632,146 +632,6 @@ void WLED::initAP(bool resetAP)
|
||||
apActive = true;
|
||||
}
|
||||
|
||||
bool WLED::initEthernet()
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET)
|
||||
|
||||
static bool successfullyConfiguredEthernet = false;
|
||||
|
||||
if (successfullyConfiguredEthernet) {
|
||||
// DEBUG_PRINTLN(F("initE: ETH already successfully configured, ignoring"));
|
||||
return false;
|
||||
}
|
||||
if (ethernetType == WLED_ETH_NONE) {
|
||||
return false;
|
||||
}
|
||||
if (ethernetType >= WLED_NUM_ETH_TYPES) {
|
||||
DEBUG_PRINTF_P(PSTR("initE: Ignoring attempt for invalid ethernetType (%d)\n"), ethernetType);
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG_PRINTF_P(PSTR("initE: Attempting ETH config: %d\n"), ethernetType);
|
||||
|
||||
// Ethernet initialization should only succeed once -- else reboot required
|
||||
ethernet_settings es = ethernetBoards[ethernetType];
|
||||
managed_pin_type pinsToAllocate[10] = {
|
||||
// first six pins are non-configurable
|
||||
esp32_nonconfigurable_ethernet_pins[0],
|
||||
esp32_nonconfigurable_ethernet_pins[1],
|
||||
esp32_nonconfigurable_ethernet_pins[2],
|
||||
esp32_nonconfigurable_ethernet_pins[3],
|
||||
esp32_nonconfigurable_ethernet_pins[4],
|
||||
esp32_nonconfigurable_ethernet_pins[5],
|
||||
{ (int8_t)es.eth_mdc, true }, // [6] = MDC is output and mandatory
|
||||
{ (int8_t)es.eth_mdio, true }, // [7] = MDIO is bidirectional and mandatory
|
||||
{ (int8_t)es.eth_power, true }, // [8] = optional pin, not all boards use
|
||||
{ ((int8_t)0xFE), false }, // [9] = replaced with eth_clk_mode, mandatory
|
||||
};
|
||||
// update the clock pin....
|
||||
if (es.eth_clk_mode == ETH_CLOCK_GPIO0_IN) {
|
||||
pinsToAllocate[9].pin = 0;
|
||||
pinsToAllocate[9].isOutput = false;
|
||||
} else if (es.eth_clk_mode == ETH_CLOCK_GPIO0_OUT) {
|
||||
pinsToAllocate[9].pin = 0;
|
||||
pinsToAllocate[9].isOutput = true;
|
||||
} else if (es.eth_clk_mode == ETH_CLOCK_GPIO16_OUT) {
|
||||
pinsToAllocate[9].pin = 16;
|
||||
pinsToAllocate[9].isOutput = true;
|
||||
} else if (es.eth_clk_mode == ETH_CLOCK_GPIO17_OUT) {
|
||||
pinsToAllocate[9].pin = 17;
|
||||
pinsToAllocate[9].isOutput = true;
|
||||
} else {
|
||||
DEBUG_PRINTF_P(PSTR("initE: Failing due to invalid eth_clk_mode (%d)\n"), es.eth_clk_mode);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!PinManager::allocateMultiplePins(pinsToAllocate, 10, PinOwner::Ethernet)) {
|
||||
DEBUG_PRINTLN(F("initE: Failed to allocate ethernet pins"));
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
For LAN8720 the most correct way is to perform clean reset each time before init
|
||||
applying LOW to power or nRST pin for at least 100 us (please refer to datasheet, page 59)
|
||||
ESP_IDF > V4 implements it (150 us, lan87xx_reset_hw(esp_eth_phy_t *phy) function in
|
||||
/components/esp_eth/src/esp_eth_phy_lan87xx.c, line 280)
|
||||
but ESP_IDF < V4 does not. Lets do it:
|
||||
[not always needed, might be relevant in some EMI situations at startup and for hot resets]
|
||||
*/
|
||||
#if ESP_IDF_VERSION_MAJOR==3
|
||||
if(es.eth_power>0 && es.eth_type==ETH_PHY_LAN8720) {
|
||||
pinMode(es.eth_power, OUTPUT);
|
||||
digitalWrite(es.eth_power, 0);
|
||||
delayMicroseconds(150);
|
||||
digitalWrite(es.eth_power, 1);
|
||||
delayMicroseconds(10);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!ETH.begin(
|
||||
(uint8_t) es.eth_address,
|
||||
(int) es.eth_power,
|
||||
(int) es.eth_mdc,
|
||||
(int) es.eth_mdio,
|
||||
(eth_phy_type_t) es.eth_type,
|
||||
(eth_clock_mode_t) es.eth_clk_mode
|
||||
)) {
|
||||
DEBUG_PRINTLN(F("initC: ETH.begin() failed"));
|
||||
// de-allocate the allocated pins
|
||||
for (managed_pin_type mpt : pinsToAllocate) {
|
||||
PinManager::deallocatePin(mpt.pin, PinOwner::Ethernet);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
successfullyConfiguredEthernet = true;
|
||||
DEBUG_PRINTLN(F("initC: *** Ethernet successfully configured! ***"));
|
||||
return true;
|
||||
#else
|
||||
return false; // Ethernet not enabled for build
|
||||
#endif
|
||||
}
|
||||
|
||||
// performs asynchronous scan for available networks (which may take couple of seconds to finish)
|
||||
// returns configured WiFi ID with the strongest signal (or default if no configured networks available)
|
||||
int8_t WLED::findWiFi(bool doScan) {
|
||||
if (multiWiFi.size() <= 1) {
|
||||
DEBUG_PRINTLN(F("Defaulf WiFi used."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (doScan) WiFi.scanDelete(); // restart scan
|
||||
|
||||
int status = WiFi.scanComplete(); // complete scan may take as much as several seconds (usually <3s with not very crowded air)
|
||||
|
||||
if (status == WIFI_SCAN_FAILED) {
|
||||
DEBUG_PRINTLN(F("WiFi scan started."));
|
||||
WiFi.scanNetworks(true); // start scanning in asynchronous mode
|
||||
} else if (status >= 0) { // status contains number of found networks
|
||||
DEBUG_PRINT(F("WiFi scan completed: ")); DEBUG_PRINTLN(status);
|
||||
int rssi = -9999;
|
||||
unsigned selected = selectedWiFi;
|
||||
for (int o = 0; o < status; o++) {
|
||||
DEBUG_PRINT(F(" WiFi available: ")); DEBUG_PRINT(WiFi.SSID(o));
|
||||
DEBUG_PRINT(F(" RSSI: ")); DEBUG_PRINT(WiFi.RSSI(o)); DEBUG_PRINTLN(F("dB"));
|
||||
for (unsigned n = 0; n < multiWiFi.size(); n++)
|
||||
if (!strcmp(WiFi.SSID(o).c_str(), multiWiFi[n].clientSSID)) {
|
||||
// find the WiFi with the strongest signal (but keep priority of entry if signal difference is not big)
|
||||
if ((n < selected && WiFi.RSSI(o) > rssi-10) || WiFi.RSSI(o) > rssi) {
|
||||
rssi = WiFi.RSSI(o);
|
||||
selected = n;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
DEBUG_PRINT(F("Selected: ")); DEBUG_PRINT(multiWiFi[selected].clientSSID);
|
||||
DEBUG_PRINT(F(" RSSI: ")); DEBUG_PRINT(rssi); DEBUG_PRINTLN(F("dB"));
|
||||
return selected;
|
||||
}
|
||||
//DEBUG_PRINT(F("WiFi scan running."));
|
||||
return status; // scan is still running or there was an error
|
||||
}
|
||||
|
||||
void WLED::initConnection()
|
||||
{
|
||||
DEBUG_PRINTF_P(PSTR("initConnection() called @ %lus.\n"), millis()/1000);
|
||||
|
@ -355,7 +355,7 @@ WLED_GLOBAL wifi_options_t wifiOpt _INIT_N(({0, 1, false, AP_BEHAVIOR_BOOT_NO_CO
|
||||
#define noWifiSleep wifiOpt.noWifiSleep
|
||||
#define force802_3g wifiOpt.force802_3g
|
||||
#else
|
||||
WLED_GLOBAL uint8_t selectedWiFi _INIT(0);
|
||||
WLED_GLOBAL int8_t selectedWiFi _INIT(0);
|
||||
WLED_GLOBAL byte apChannel _INIT(1); // 2.4GHz WiFi AP channel (1-13)
|
||||
WLED_GLOBAL byte apHide _INIT(0); // hidden AP SSID
|
||||
WLED_GLOBAL byte apBehavior _INIT(AP_BEHAVIOR_BOOT_NO_CONN); // access point opens when no connection after boot by default
|
||||
@ -373,9 +373,9 @@ WLED_GLOBAL uint8_t txPower _INIT(WIFI_POWER_8_5dBm);
|
||||
WLED_GLOBAL uint8_t txPower _INIT(WIFI_POWER_19_5dBm);
|
||||
#endif
|
||||
#endif
|
||||
#define WLED_WIFI_CONFIGURED (strlen(multiWiFi[0].clientSSID) >= 1 && strcmp(multiWiFi[0].clientSSID, DEFAULT_CLIENT_SSID) != 0)
|
||||
#define WLED_WIFI_CONFIGURED isWiFiConfigured()
|
||||
|
||||
#ifdef WLED_USE_ETHERNET
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET)
|
||||
#ifdef WLED_ETH_DEFAULT // default ethernet board type if specified
|
||||
WLED_GLOBAL int ethernetType _INIT(WLED_ETH_DEFAULT); // ethernet board type
|
||||
#else
|
||||
@ -567,6 +567,7 @@ WLED_GLOBAL uint16_t userVar0 _INIT(0), userVar1 _INIT(0); //available for use i
|
||||
// internal global variable declarations
|
||||
// wifi
|
||||
WLED_GLOBAL bool apActive _INIT(false);
|
||||
WLED_GLOBAL byte apClients _INIT(0);
|
||||
WLED_GLOBAL bool forceReconnect _INIT(false);
|
||||
WLED_GLOBAL unsigned long lastReconnectAttempt _INIT(0);
|
||||
WLED_GLOBAL bool interfacesInited _INIT(false);
|
||||
@ -1038,11 +1039,9 @@ public:
|
||||
|
||||
void beginStrip();
|
||||
void handleConnection();
|
||||
bool initEthernet(); // result is informational
|
||||
void initAP(bool resetAP = false);
|
||||
void initConnection();
|
||||
void initInterfaces();
|
||||
int8_t findWiFi(bool doScan = false);
|
||||
#if defined(STATUSLED)
|
||||
void handleStatusLED();
|
||||
#endif
|
||||
|
@ -110,7 +110,7 @@ void appendGPIOinfo(Print& settingsScript) {
|
||||
settingsScript.print(hardwareTX); // debug output (TX) pin
|
||||
firstPin = false;
|
||||
#endif
|
||||
#ifdef WLED_USE_ETHERNET
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET)
|
||||
if (ethernetType != WLED_ETH_NONE && ethernetType < WLED_NUM_ETH_TYPES) {
|
||||
if (!firstPin) settingsScript.print(',');
|
||||
for (unsigned p=0; p<WLED_ETH_RSVD_PINS_COUNT; p++) { settingsScript.printf("%d,",esp32_nonconfigurable_ethernet_pins[p].pin); }
|
||||
@ -178,9 +178,12 @@ void getSettingsJS(byte subPage, Print& settingsScript)
|
||||
char fpass[l+1]; //fill password field with ***
|
||||
fpass[l] = 0;
|
||||
memset(fpass,'*',l);
|
||||
settingsScript.printf_P(PSTR("addWiFi(\"%s\",\"%s\",0x%X,0x%X,0x%X);"),
|
||||
char bssid[13];
|
||||
fillMAC2Str(bssid, multiWiFi[n].bssid);
|
||||
settingsScript.printf_P(PSTR("addWiFi(\"%s\",\"%s\",\"%s\",0x%X,0x%X,0x%X);"),
|
||||
multiWiFi[n].clientSSID,
|
||||
fpass,
|
||||
bssid,
|
||||
(uint32_t) multiWiFi[n].staticIP, // explicit cast required as this is a struct
|
||||
(uint32_t) multiWiFi[n].staticGW,
|
||||
(uint32_t) multiWiFi[n].staticSN);
|
||||
@ -219,7 +222,7 @@ void getSettingsJS(byte subPage, Print& settingsScript)
|
||||
settingsScript.print(F("toggle('ESPNOW');")); // hide ESP-NOW setting
|
||||
#endif
|
||||
|
||||
#ifdef WLED_USE_ETHERNET
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET)
|
||||
printSetFormValue(settingsScript,PSTR("ETH"),ethernetType);
|
||||
#else
|
||||
//hide ethernet setting if not compiled in
|
||||
|
Loading…
x
Reference in New Issue
Block a user