diff --git a/platformio.ini b/platformio.ini index 5ff4d9028c..9a8f0becf8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -134,9 +134,6 @@ lib_deps = marvinroger/AsyncMqttClient @ 0.9.0 # for I2C interface ;Wire - # ESP-NOW library - ;gmag11/QuickESPNow @ ~0.7.0 - https://github.com/blazoncek/QuickESPNow.git#optional-debug #For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line #TFT_eSPI #For compatible OLED display uncomment following @@ -255,7 +252,6 @@ lib_deps_compat = ESP8266PWM IRremoteESP8266 @ 2.8.2 makuna/NeoPixelBus @ 2.7.9 - https://github.com/blazoncek/QuickESPNow.git#optional-debug https://github.com/tignioj/ArduinoUZlib.git#20aff95cd80c141f80bdbf66895409a0046d2c2f https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.4.0 diff --git a/wled00/src/dependencies/espnow_wled/espnow_wled.cpp b/wled00/src/dependencies/espnow_wled/espnow_wled.cpp new file mode 100644 index 0000000000..a2ba985650 --- /dev/null +++ b/wled00/src/dependencies/espnow_wled/espnow_wled.cpp @@ -0,0 +1,303 @@ +#include "wled.h" // includes espnow_wled.h +/* + * Lightweight ESP-NOW driver for WLED + * by @dedehai (2026) licensed under EUPL 1.2 license (same as WLED) + * note: currently supports only broadcast sending, callback kept compatible with quickEspNow + */ + +#ifndef WLED_DISABLE_ESPNOW + +WledEspNow espNow; +//WledEspNowBroadcast espnowBroadcast; // note: WledEspNowBroadcast was added using AI with the goal of enabling porting the WLEDtubes usermod but I did not investigate if this is viable or useful so commented out for now + +static const uint8_t BCAST[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // static broadcast MAC + +// ========================================================================= +// 802.11 Action frame layout for ESP-NOW — used to walk backwards from the payload pointer to reach the wifi_pkt_rx_ctrl_t (which carries RSSI). +// Reference: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_now.html +typedef struct { + uint16_t frame_head; + uint16_t duration; + uint8_t destination_address[6]; + uint8_t source_address[6]; + uint8_t broadcast_address[6]; + uint16_t sequence_control; + uint8_t category_code; + uint8_t organization_identifier[3]; // 0x18fe34 + uint8_t random_values[4]; + struct { + uint8_t element_id; // 0xdd + uint8_t length; + uint8_t organization_identifier[3]; // 0x18fe34 + uint8_t type; // 4 + uint8_t version; + uint8_t body[0]; + } vendor_specific_content; +} __attribute__((packed)) espnow_frame_format_t; + +// ========================================================================= +// Platform-specific SDK callbacks +// ========================================================================= + +#ifdef ARDUINO_ARCH_ESP32 + +// ----- ESP32 sent callback ----------------------------------------------- +static void _espnowSentCB(const uint8_t *mac, esp_now_send_status_t status) { + if (espNow._inFlight > 0) espNow._inFlight--; + if (espNow._sentCB) + espNow._sentCB(const_cast(mac), (uint8_t)status); +} + +// ----- ESP32 recv callback ----------------------------------------------- +// Signature changed in IDF 5.0: the first parameter became esp_now_recv_info_t* +// which carries the source address, destination address (useful to detect +// broadcast) and the rx_ctrl struct with RSSI. +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) +// note: IDF V5 code is AI generated, unreviewed and untested +static void _espnowRecvCB(const esp_now_recv_info_t *info, const uint8_t *data, int len) { + if (!info || !data || len <= 0) return; + const uint8_t *mac = info->src_addr; + // rx_ctrl is a pointer to wifi_pkt_rx_ctrl_t; cast to int8_t to get signed RSSI. + int8_t rssi = (info->rx_ctrl) ? (int8_t)info->rx_ctrl->rssi : 0; + // Broadcast when the destination address has all bits set. + bool isBroadcast = (info->des_addr && memcmp(info->des_addr, BCAST, 6) == 0); + + //espnowBroadcast.dispatch(mac, data, (uint8_t)len, rssi); + if (espNow._rcvdCB) + espNow._rcvdCB(const_cast(mac), const_cast(data), (uint8_t)len, (signed int)rssi, isBroadcast); +} + +#else // IDF < 5.0 + +static void _espnowRecvCB(const uint8_t *mac, const uint8_t *data, int len) { + if (!mac || !data || len <= 0) return; + // Walk back through the WiFi frame buffer to reach wifi_pkt_rx_ctrl_t to get RSSI. Reference: https://github.com/gmag11/QuickESPNow + const espnow_frame_format_t *espnow_data = (const espnow_frame_format_t *)(data - sizeof(espnow_frame_format_t)); + const wifi_promiscuous_pkt_t *promiscuous_pkt = (const wifi_promiscuous_pkt_t *)(data - sizeof(wifi_pkt_rx_ctrl_t) - sizeof(espnow_frame_format_t)); + const wifi_pkt_rx_ctrl_t *rx_ctrl = &promiscuous_pkt->rx_ctrl; + int8_t rssi = (int8_t)rx_ctrl->rssi; + bool isBroadcast = (memcmp(espnow_data->destination_address, BCAST, 6) == 0); + //espnowBroadcast.dispatch(mac, data, (uint8_t)len, rssi); + if (espNow._rcvdCB) + espNow._rcvdCB(const_cast(mac), const_cast(data), (uint8_t)len, (signed int)rssi, isBroadcast); +} + +#endif // ESP_IDF_VERSION + +#else // ESP8266 + +// define wifi_pkt_rx_ctrl_t to match the hardware layout so we can extract RSSI +// https://github.com/espressif/ESP8266_RTOS_SDK/blob/master/components/esp8266/include/esp_wifi_types.h + +typedef struct { + signed rssi: 8; /**< signal intensity of packet */ + unsigned rate: 4; /**< data rate */ + unsigned is_group: 1; /**< usually not used */ + unsigned : 1; /**< reserve */ + unsigned sig_mode: 2; /**< 0:is not 11n packet; 1:is 11n packet */ + unsigned legacy_length: 12; /**< Length of 11bg mode packet */ + unsigned damatch0: 1; /**< usually not used */ + unsigned damatch1: 1; /**< usually not used */ + unsigned bssidmatch0: 1; /**< usually not used */ + unsigned bssidmatch1: 1; /**< usually not used */ + unsigned mcs: 7; /**< if is 11n packet, shows the modulation(range from 0 to 76) */ + unsigned cwb: 1; /**< if is 11n packet, shows if is HT40 packet or not */ + unsigned HT_length: 16; /**< Length of 11n mode packet */ + unsigned smoothing: 1; /**< reserve */ + unsigned not_sounding: 1; /**< reserve */ + unsigned : 1; /**< reserve */ + unsigned aggregation: 1; /**< Aggregation */ + unsigned stbc: 2; /**< STBC */ + unsigned fec_coding: 1; /**< Flag is set for 11n packets which are LDPC */ + unsigned sgi: 1; /**< SGI */ + unsigned rxend_state: 8; /**< usually not used */ + unsigned ampdu_cnt: 8; /**< ampdu cnt */ + unsigned channel: 4; /**< which channel this packet in */ + unsigned : 4; /**< reserve */ + signed noise_floor: 8; /**< usually not used */ +} wifi_pkt_rx_ctrl_t; + +typedef struct { + wifi_pkt_rx_ctrl_t rx_ctrl; + uint8_t payload[0]; /* ieee80211 packet buff */ +} wifi_promiscuous_pkt_t; + + +// ----- ESP8266 sent callback --------------------------------------------- +static void _espnowSentCB(uint8_t *mac, uint8_t status) { + if (espNow._inFlight > 0) espNow._inFlight--; + if (espNow._sentCB) + espNow._sentCB(mac, status); +} + +// ----- ESP8266 recv callback --------------------------------------------- +static void _espnowRecvCB(uint8_t *mac, uint8_t *data, uint8_t len) { + if (!mac || !data || len == 0) return; + // Walk back through the WiFi frame buffer to reach the rx control header to get RSSI. + const espnow_frame_format_t *espnow_data = (const espnow_frame_format_t *)(data - sizeof(espnow_frame_format_t)); + bool isBroadcast = (memcmp(espnow_data->destination_address, BCAST, 6) == 0); + const wifi_promiscuous_pkt_t *promiscuous_pkt = (const wifi_promiscuous_pkt_t *)(data - sizeof(wifi_pkt_rx_ctrl_t) - sizeof(espnow_frame_format_t)); + const wifi_pkt_rx_ctrl_t *rx_ctrl = &promiscuous_pkt->rx_ctrl; + int8_t rssi = (int8_t)(rx_ctrl->rssi - 100); // ESP8266: raw RSSI is offset by ~+100 dBm vs actual signal strength + //espnowBroadcast.dispatch(mac, data, len, rssi); + if (espNow._rcvdCB) + espNow._rcvdCB(mac, data, len, (signed int)rssi, isBroadcast); +} + +#endif + +bool WledEspNow::begin(uint8_t channel, uint8_t iface) { + if (_running) stop(); // clean up before re-init + +// note: channel must be 0-14 (14: used in Japan only), channel = 0 means "use current WiFi channel" (both on ESP8266 and ESP32, in AP and STA mode) +#ifdef ARDUINO_ARCH_ESP32 + if (esp_now_init() != ESP_OK) { + DEBUG_PRINTLN(F("ESP-NOW esp_now_init() failed")); + return false; + } + if (esp_now_register_recv_cb(_espnowRecvCB) != ESP_OK) { + esp_now_deinit(); + return false; + } + if (esp_now_register_send_cb(_espnowSentCB) != ESP_OK) { + esp_now_unregister_recv_cb(); + esp_now_deinit(); + return false; + } + esp_now_peer_info_t peer = {}; + memcpy(peer.peer_addr, BCAST, 6); + peer.channel = channel; + peer.ifidx = (wifi_interface_t)iface; + peer.encrypt = false; + if (esp_now_add_peer(&peer) != ESP_OK) { + esp_now_unregister_recv_cb(); + esp_now_unregister_send_cb(); + esp_now_deinit(); + return false; + } + _running = true; + return true; + +#else // ESP8266 + if (esp_now_init() != 0) { + DEBUG_PRINTLN(F("ESP-NOW esp_now_init() failed")); + return false; + } + esp_now_set_self_role(ESP_NOW_ROLE_COMBO); // TODO: found no official documentation on this... quickespnow ESP_NOW_ROLE_SLAVE in STA mode and ESP_NOW_ROLE_CONTROLLER in AP mode + esp_now_register_recv_cb(_espnowRecvCB); + esp_now_register_send_cb(_espnowSentCB); + esp_now_add_peer(const_cast(BCAST), ESP_NOW_ROLE_COMBO, channel, nullptr, 0); + _running = true; + return true; +#endif +} + +// STA mode: derives the channel from the current WiFi connection (channel 0 means "use current channel" for both ESP32 and ESP8266). +bool WledEspNow::begin() { + return begin(0, WIFI_IF_STA); +} + +void WledEspNow::stop() { + if (!_running) return; + _running = false; + esp_now_unregister_recv_cb(); + esp_now_unregister_send_cb(); + _inFlight = 0; // reset after unregistering callbacks + esp_now_del_peer(const_cast(BCAST)); + esp_now_deinit(); // esp_now_deinit() frees any pending TX buffers +} + +uint8_t WledEspNow::send(const uint8_t * /*addr*/, const uint8_t *data, uint8_t len) { + static bool isretransmit = false; + int err = 1; // default to error + // addr is ignored — we only support broadcast. + // len must be < ESP_NOW_MAX_DATA_LEN (250 bytes). + if (!_running) return err; + // ESP8266 SDK uses non-const uint8_t* parameters; const_cast is safe here. + if ( _inFlight < ESPNOW_MAX_INFLIGHT) { + err = esp_now_send(const_cast(BCAST), const_cast(data), len); + } + if (err == 0) _inFlight++; // ESP_OK == 0 on both platforms + else if (_inFlight > 0 && !isretransmit) { + uint8_t lastInFlight = _inFlight; + delay(2); // wait for a queued message to be sent, found that 2ms is usually enough, dont want to be too cautios (burst send is currently an edge case) + // note: delay and general approach might need some tweaking for real world use, based on burst tests sending 16 messages + if (_inFlight < lastInFlight) { + isretransmit = true; // try once more + err = esp_now_send(const_cast(BCAST), const_cast(data), len); // A message was sent and the sent callback was called, so we can retry now. + } + } + if (err != 0 && isretransmit) Serial.printf("ESP-NOW send failed with error %d, inflight=%d\n", err, (int)espNow._inFlight); + // TODO: should monitor somehow if sending fails repeatedly and do something about it + isretransmit = false; // reset flag + return err; +} + +#ifdef ARDUINO_ARCH_ESP32 +void WledEspNow::setWiFiBandwidth(uint8_t iface, uint8_t bw) { + esp_wifi_set_bandwidth((wifi_interface_t)iface, (wifi_bandwidth_t)bw); +} +#endif + +/* +// start AI code, unreviewed, untested +// ========================================================================= +// WledEspNowBroadcast — implementation +// ========================================================================= + +bool WledEspNowBroadcast::send(const uint8_t *msg, size_t len) { + if (len > 250) return false; // ESP-NOW max payload + return espNow.send(BCAST, msg, (uint8_t)len) == 0; +} + +WledEspNowBroadcast::STATE WledEspNowBroadcast::getState() const { + switch (statusESPNow) { + case ESP_NOW_STATE_ON: return STARTED; + case ESP_NOW_STATE_UNINIT: // fall through + case ESP_NOW_STATE_ERROR: + default: return STOPPED; + } +} + +bool WledEspNowBroadcast::registerCallback(receive_callback_t cb) { + for (size_t i = 0; i < WLED_ESPNOW_MAX_REGISTERED_CALLBACKS - 1; i++) { + if (_callbacks[i] == cb) return true; // already registered + if (_callbacks[i] == nullptr) { + _callbacks[i] = cb; + return true; + } + } + return false; // array full +} + +bool WledEspNowBroadcast::removeCallback(receive_callback_t cb) { + size_t found = WLED_ESPNOW_MAX_REGISTERED_CALLBACKS; + for (size_t i = 0; i < WLED_ESPNOW_MAX_REGISTERED_CALLBACKS - 1; i++) { + if (_callbacks[i] == cb) { found = i; break; } + } + if (found == WLED_ESPNOW_MAX_REGISTERED_CALLBACKS) return false; + // Shift remaining entries left to close the gap. + for (size_t i = found; i < WLED_ESPNOW_MAX_REGISTERED_CALLBACKS - 1; i++) + _callbacks[i] = _callbacks[i + 1]; + _callbacks[WLED_ESPNOW_MAX_REGISTERED_CALLBACKS - 1] = nullptr; + return true; +} + +WledEspNowBroadcast::receive_filter_t +WledEspNowBroadcast::registerFilter(receive_filter_t filter) { + receive_filter_t old = _filter; + _filter = filter; + return old; +} + +void WledEspNowBroadcast::dispatch(const uint8_t *mac, const uint8_t *data, + uint8_t len, int8_t rssi) { + if (_filter && !_filter(mac, data, len, rssi)) return; + for (size_t i = 0; i < WLED_ESPNOW_MAX_REGISTERED_CALLBACKS - 1; i++) { + if (_callbacks[i]) _callbacks[i](mac, data, len, rssi); + } +} +// end AI code, unreviewed, untested +*/ + +#endif // WLED_DISABLE_ESPNOW diff --git a/wled00/src/dependencies/espnow_wled/espnow_wled.h b/wled00/src/dependencies/espnow_wled/espnow_wled.h new file mode 100644 index 0000000000..950b860291 --- /dev/null +++ b/wled00/src/dependencies/espnow_wled/espnow_wled.h @@ -0,0 +1,123 @@ +#pragma once + +// ESPnow WLED: Lightweight ESP-NOW driver. Only the API surface actually used by WLED is implemented. +// by @dedehai (2026) licensed under EUPL 1.2 license (same as WLED) + +#ifndef WLED_DISABLE_ESPNOW +#ifdef ESP8266 + #include +#else + #include +#endif +// Broadcast MAC address constant +static const uint8_t ESPNOW_BROADCAST_ADDRESS[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + +// Maximum number of ESP-NOW frames that may be in-flight (queued by esp driver) note: might need some tweaking for real world use, based on burst tests +#define ESPNOW_MAX_INFLIGHT 8 // note: ESP32 have a larger buffer (16 work no problem) but ESP8266 struggles receiving more than 6 without any pause, also depends on msg length (longer=better) + +#ifdef ESP8266 + // Map ESP32 wifi_interface_t names to ESP8266 SDK interface + #ifndef WIFI_IF_STA + #define WIFI_IF_STA STATION_IF + #endif + #ifndef WIFI_IF_AP + #define WIFI_IF_AP SOFTAP_IF + #endif +#endif + +class WledEspNow { +public: + // Callback types + typedef void (*sent_cb_t)(uint8_t *address, uint8_t status); + typedef void (*rcvd_cb_t)(uint8_t *address, uint8_t *data, uint8_t len, signed int rssi, bool broadcast); + + // Register callbacks before calling begin(). + void onDataSent(sent_cb_t cb) { _sentCB = cb; } + void onDataRcvd(rcvd_cb_t cb) { _rcvdCB = cb; } + + // Start ESP-NOW on the given WiFi interface. Note: on ESP8266 the interface is currently not used, it is only needed to determine ROLE which is fixed to COMBO + bool begin(uint8_t channel, uint8_t iface); + + // Start ESP-NOW in STA mode, inheriting the current WiFi channel. + bool begin(); + + // Stop ESP-NOW and release SDK resources. + void stop(); + + // Send data as a broadcast. addr is accepted for API compatibility but is always ignored — only the broadcast peer is used. Returns 0 on success. + uint8_t send(const uint8_t *addr, const uint8_t *data, uint8_t len); + +#ifdef ARDUINO_ARCH_ESP32 + // Narrow the AP-interface WiFi bandwidth for coexistence with ESP8266 peers used with iface: WIFI_IF_AP; bw: WIFI_BW_HT20 in wled.cpp + void setWiFiBandwidth(uint8_t iface, uint8_t bw); +#endif + + // Accessible from file-static SDK callbacks in espnow.cpp: + sent_cb_t _sentCB = nullptr; + rcvd_cb_t _rcvdCB = nullptr; + volatile int8_t _inFlight {0}; // frames queued in driver, not yet confirmed + +private: + bool _running = false; +}; + +/* +// start AI code, unreviewed, untested +// --- WledEspNowBroadcast ----------------------------------------------- +// Thin facade matching the ESPNOWBroadcast interface from WLEDtubes so the +// Tubes usermod can be ported upstream with minimal modifications. +// Delegates actual sending to espNow; state is derived from statusESPNow. + +// Allow override of callback array size before including this header. +#ifndef WLED_ESPNOW_MAX_REGISTERED_CALLBACKS + #ifndef WLED_MAX_USERMODS + // const.h is not included yet at this point; provide a safe default that + // will be overridden by the actual WLED_MAX_USERMODS value once const.h + // defines it. The array is fixed-size, so use the larger ESP32 default. + #define WLED_MAX_USERMODS 6 + #endif + #define WLED_ESPNOW_MAX_REGISTERED_CALLBACKS (WLED_MAX_USERMODS + 1) +#endif + +class WledEspNowBroadcast { +public: + enum STATE { STOPPED = 0, STARTING, STARTED, MAX }; + + // Broadcast a raw message (delegates to espNow.send). + bool send(const uint8_t *msg, size_t len); + + // Receive callback type: (sender_mac, data, len, rssi) + typedef void (*receive_callback_t)(const uint8_t *sender, + const uint8_t *data, + uint8_t len, int8_t rssi); + bool registerCallback(receive_callback_t cb); + bool removeCallback(receive_callback_t cb); + + // Optional filter invoked from within the ESP-NOW recv handler before the + // registered callbacks. Return false to discard the packet. + // Only a single filter is active at a time; returns the previous filter. + typedef bool (*receive_filter_t)(const uint8_t *sender, + const uint8_t *data, + uint8_t len, int8_t rssi); + receive_filter_t registerFilter(receive_filter_t filter = nullptr); + + // Return the current broadcast state derived from the WLED statusESPNow flag. + STATE getState() const; + bool isStarted() const { return getState() == STARTED; } + + // Dispatch received data to all registered callbacks (after filter). + // Called from the ESP-NOW recv handler in espnow.cpp. + void dispatch(const uint8_t *mac, const uint8_t *data, + uint8_t len, int8_t rssi); + +private: + receive_callback_t _callbacks[WLED_ESPNOW_MAX_REGISTERED_CALLBACKS] = {nullptr}; + receive_filter_t _filter = nullptr; +}; +// end AI code, unreviewed, untested +*/ +// Global instances (defined in espnow.cpp) +extern WledEspNow espNow; +//extern WledEspNowBroadcast espnowBroadcast; + +#endif // WLED_DISABLE_ESPNOW diff --git a/wled00/udp.cpp b/wled00/udp.cpp index ed8bc6c8f3..f0f27b631d 100644 --- a/wled00/udp.cpp +++ b/wled00/udp.cpp @@ -165,27 +165,24 @@ void notify(byte callMode, bool followUp) s0++; } if (s > s0) buffer.noOfPackets += 1 + ((s - s0) * UDP_SEG_SIZE) / bufferSize; // set number of packets - auto err = quickEspNow.send(ESPNOW_BROADCAST_ADDRESS, reinterpret_cast(&buffer), packetSize+3); + auto err = espNow.send(ESPNOW_BROADCAST_ADDRESS, reinterpret_cast(&buffer), packetSize+3); if (!err && s0 < s) { // send rest of the segments buffer.packet++; packetSize = 0; - // WARNING: this will only work for up to 3 messages (~17 segments) as QuickESPNOW only has a ring buffer capable of holding 3 queued messages - // to work around that limitation it is mandatory to utilize onDataSent() callback which should reduce number queued messages - // and wait until at least one space is available in the buffer for (size_t i = s0; i < s; i++) { memcpy(buffer.data + packetSize, &udpOut[41+i*UDP_SEG_SIZE], UDP_SEG_SIZE); packetSize += UDP_SEG_SIZE; if (packetSize + UDP_SEG_SIZE < bufferSize) continue; DEBUG_PRINTF_P(PSTR("ESP-NOW sending packet: %d (%u)\n"), (int)buffer.packet, packetSize+3); - err = quickEspNow.send(ESPNOW_BROADCAST_ADDRESS, reinterpret_cast(&buffer), packetSize+3); + err = espNow.send(ESPNOW_BROADCAST_ADDRESS, reinterpret_cast(&buffer), packetSize+3); buffer.packet++; packetSize = 0; if (err) break; } if (!err && packetSize > 0) { DEBUG_PRINTF_P(PSTR("ESP-NOW sending last packet: %d (%d)\n"), (int)buffer.packet, packetSize+3); - err = quickEspNow.send(ESPNOW_BROADCAST_ADDRESS, reinterpret_cast(&buffer), packetSize+3); + err = espNow.send(ESPNOW_BROADCAST_ADDRESS, reinterpret_cast(&buffer), packetSize+3); } } if (err) { diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 493c687700..c7d5283cc4 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -692,7 +692,7 @@ void WLED::initConnection() #ifndef WLED_DISABLE_ESPNOW if (statusESPNow == ESP_NOW_STATE_ON) { DEBUG_PRINTLN(F("ESP-NOW stopping.")); - quickEspNow.stop(); + espNow.stop(); statusESPNow = ESP_NOW_STATE_UNINIT; } #endif @@ -802,18 +802,18 @@ void WLED::initConnection() #ifndef WLED_DISABLE_ESPNOW if (enableESPNow) { - quickEspNow.onDataSent(espNowSentCB); // see udp.cpp - quickEspNow.onDataRcvd(espNowReceiveCB); // see udp.cpp + espNow.onDataSent(espNowSentCB); // see udp.cpp + espNow.onDataRcvd(espNowReceiveCB); // see udp.cpp bool espNowOK; if (apActive) { DEBUG_PRINTLN(F("ESP-NOW initing in AP mode.")); #ifdef ESP32 - quickEspNow.setWiFiBandwidth(WIFI_IF_AP, WIFI_BW_HT20); // Only needed for ESP32 in case you need coexistence with ESP8266 in the same network + espNow.setWiFiBandwidth(WIFI_IF_AP, WIFI_BW_HT20); // Only needed for ESP32 in case you need coexistence with ESP8266 in the same network #endif //ESP32 - espNowOK = quickEspNow.begin(apChannel, WIFI_IF_AP); // Same channel must be used for both AP and ESP-NOW + espNowOK = espNow.begin(apChannel, WIFI_IF_AP); // Same channel must be used for both AP and ESP-NOW note: could also pass channel 0, which means "use current WiFi channel" (both on ESP8266 and ESP32) } else { DEBUG_PRINTLN(F("ESP-NOW initing in STA mode.")); - espNowOK = quickEspNow.begin(); // Use no parameters to start ESP-NOW on same channel as WiFi, in STA mode + espNowOK = espNow.begin(); // Use no parameters to start ESP-NOW on same channel as WiFi, in STA mode } statusESPNow = espNowOK ? ESP_NOW_STATE_ON : ESP_NOW_STATE_ERROR; } diff --git a/wled00/wled.h b/wled00/wled.h index 1a5f1b143e..43e92723ff 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -87,12 +87,6 @@ { #include } - #ifndef WLED_DISABLE_ESPNOW - #include - #define WIFI_MODE_STA WIFI_STA - #define WIFI_MODE_AP WIFI_AP - #include - #endif #else // ESP32 #include // ensure we have the correct "Serial" on new MCUs (depends on ARDUINO_USB_MODE and ARDUINO_USB_CDC_ON_BOOT) #include @@ -109,11 +103,6 @@ #include #endif #include "esp_task_wdt.h" - - #ifndef WLED_DISABLE_ESPNOW - #include - #include - #endif #endif #include #include @@ -188,6 +177,9 @@ using PSRAMDynamicJsonDocument = BasicJsonDocument; #define USE_GET_MILLISECOND_TIMER #include "const.h" +#ifndef WLED_DISABLE_ESPNOW + #include "src/dependencies/espnow_wled/espnow_wled.h" +#endif #include "colors.h" #include "fcn_declare.h" #ifndef WLED_DISABLE_OTA