diff --git a/cpu/esp32/doc.txt b/cpu/esp32/doc.txt
index c2cdfbea10..e56d63f2bd 100644
--- a/cpu/esp32/doc.txt
+++ b/cpu/esp32/doc.txt
@@ -1260,6 +1260,9 @@ the verification of the AP certificate is not yet supported.
[ESP-NOW network interface](#esp32_esp_now_network_interface) (module `esp_now`)
can be used simultaneously, for example, to realize a border router for
a mesh network which uses ESP-NOW.
+In this case the ESP-NOW interface must use the same channel as the AP of the
+infrastructure WiFi network. All ESP-NOW nodes must therefore be compiled with
+the channel of the AP as value for the parameter 'ESP_NOW_CHANNEL'.
\anchor esp32_esp_now_network_interface
## ESP-NOW Network Interface [[TOC](#esp32_toc)]
@@ -1294,6 +1297,9 @@ ESP_NOW_KEY | NULL | Defines a key that is used for encrypted communication betw
[Wifi network interface](#esp32_wifi_network_interface) (module `esp_wifi` or `esp_wifi_enterprise`)
can be used simultaneously, for example, to realize a border router for
a mesh network which uses ESP-NOW.
+In this case the ESP-NOW interface must use the same channel as the AP of the
+infrastructure WiFi network. All ESP-NOW nodes must therefore be compiled with
+the channel of the AP asvalue for the parameter 'ESP_NOW_CHANNEL'.
## Other Network Devices [[TOC](#esp32_toc)]
diff --git a/cpu/esp8266/doc.txt b/cpu/esp8266/doc.txt
index 1ff4fa90fa..943dccb30b 100644
--- a/cpu/esp8266/doc.txt
+++ b/cpu/esp8266/doc.txt
@@ -710,6 +710,9 @@ make -C examples/gnrc_networking BOARD=...
[ESP-NOW network interface](#esp8266_esp_now_network_interface)
(module `esp_now`) can be used simultaneously, for example, to realize a
border router for a mesh network which uses ESP-NOW.
+In this case the ESP-NOW interface must use the same channel as the AP of the
+infrastructure WiFi network. All ESP-NOW nodes must therefore be compiled with
+the channel of the AP asvalue for the parameter 'ESP_NOW_CHANNEL'.
\anchor esp8266_esp_now_network_interface
## ESP-NOW Network Interface [[TOC](#esp8266_toc)]
@@ -756,6 +759,9 @@ Parameter | Default | Description
[Wifi network interface](#esp8266_wifi_network_interface) (module `esp_wifi`)
can be used simultaneously, for example, to realize a border router for
a mesh network which uses ESP-NOW.
+In this case the ESP-NOW interface must use the same channel as the AP of the
+infrastructure WiFi network. All ESP-NOW nodes must therefore be compiled with
+the channel of the AP asvalue for the parameter 'ESP_NOW_CHANNEL'.
# Preconfigured Devices [[TOC](#esp8266_toc)]
diff --git a/cpu/esp_common/esp-now/doc.txt b/cpu/esp_common/esp-now/doc.txt
index 61cd86e9f5..e0403853b6 100644
--- a/cpu/esp_common/esp-now/doc.txt
+++ b/cpu/esp_common/esp-now/doc.txt
@@ -45,5 +45,8 @@ ESP_NOW_KEY | NULL | Defines a key that is used for encrypted communication betw
Wifi network interface (module `esp_wifi`)
can be used simultaneously, for example, to realize a border router for
a mesh network which uses ESP-NOW.
+In this case the ESP-NOW interface must use the same channel as the AP of the
+infrastructure WiFi network. All ESP-NOW nodes must therefore be compiled with
+the channel of the AP asvalue for the parameter 'ESP_NOW_CHANNEL'.
*/
diff --git a/cpu/esp_common/esp-now/esp_now_netdev.c b/cpu/esp_common/esp-now/esp_now_netdev.c
index 2cdc9f698c..e988326e6c 100644
--- a/cpu/esp_common/esp-now/esp_now_netdev.c
+++ b/cpu/esp_common/esp-now/esp_now_netdev.c
@@ -100,7 +100,7 @@ static bool _esp_now_scan_peers_done = false;
static wifi_ap_record_t* aps = NULL;
static uint32_t aps_size = 0;
-static const wifi_scan_config_t scan_cfg = {
+static wifi_scan_config_t scan_cfg = {
.ssid = NULL,
.bssid = NULL,
.channel = ESP_NOW_CHANNEL,
@@ -290,6 +290,9 @@ static esp_err_t IRAM_ATTR _esp_system_event_handler(void *ctx, system_event_t *
extern esp_err_t esp_system_event_add_handler(system_event_cb_t handler,
void *arg);
+/* ESP-NOW SoftAP configuration */
+static wifi_config_t wifi_config_ap = {};
+
esp_now_netdev_t *netdev_esp_now_setup(void)
{
esp_now_netdev_t* dev = &_esp_now_dev;
@@ -360,9 +363,7 @@ esp_now_netdev_t *netdev_esp_now_setup(void)
/* get SoftAP interface mac address and store it as device address */
esp_read_mac(dev->addr, ESP_MAC_WIFI_SOFTAP);
- /* prepare the ESP_NOW configuration for SoftAP */
- wifi_config_t wifi_config_ap = {};
-
+ /* prepare initial ESP_NOW configuration for SoftAP */
strcpy ((char*)wifi_config_ap.ap.password, esp_now_params.softap_pass);
sprintf((char*)wifi_config_ap.ap.ssid, "%s%02x%02x%02x%02x%02x%02x",
ESP_NOW_AP_PREFIX,
@@ -452,6 +453,31 @@ esp_now_netdev_t *netdev_esp_now_setup(void)
return dev;
}
+int esp_now_set_channel(uint8_t channel)
+{
+#ifdef ESP_NOW_UNICAST
+ scan_cfg.channel = channel;
+#endif
+#ifdef MODULE_ESP_WIFI
+ /* channel is controlled by `esp_wifi`, only update SoftAP info */
+ wifi_config_ap.ap.channel = channel;
+ return ESP_ERR_NOT_SUPPORTED;
+#else
+ /* channel is controlled by `esp_now`, try to reconfigure SoftAP */
+ uint8_t old_channel = wifi_config_ap.ap.channel;
+ wifi_config_ap.ap.channel = channel;
+ esp_err_t result = esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config_ap);
+ if (result != ESP_OK) {
+ LOG_TAG_ERROR("esp_now",
+ "esp_wifi_set_config softap failed with return value %d\n",
+ result);
+ wifi_config_ap.ap.channel = old_channel;
+ return result;
+ }
+ return ESP_OK;
+#endif
+}
+
static int _init(netdev_t *netdev)
{
DEBUG("%s: %p\n", __func__, netdev);
@@ -636,6 +662,12 @@ static int _get(netdev_t *netdev, netopt_t opt, void *val, size_t max_len)
res = sizeof(dev->addr);
break;
+ case NETOPT_CHANNEL:
+ CHECK_PARAM_RET(max_len >= sizeof(uint16_t), -EOVERFLOW);
+ *((uint16_t *)val) = wifi_config_ap.ap.channel;
+ res = sizeof(uint16_t);
+ break;
+
default:
DEBUG("%s: %s not supported\n", __func__, netopt2str(opt));
break;
@@ -669,6 +701,15 @@ static int _set(netdev_t *netdev, netopt_t opt, const void *val, size_t max_len)
res = sizeof(dev->addr);
break;
+ case NETOPT_CHANNEL:
+ CHECK_PARAM_RET(max_len >= sizeof(uint16_t), -EOVERFLOW);
+ uint16_t channel = *((uint16_t *)val);
+ if (esp_now_set_channel(channel) != ESP_OK) {
+ return -ENOTSUP;
+ }
+ res = sizeof(uint16_t);
+ break;
+
default:
DEBUG("%s: %s not supported\n", __func__, netopt2str(opt));
break;
diff --git a/cpu/esp_common/esp-now/esp_now_netdev.h b/cpu/esp_common/esp-now/esp_now_netdev.h
index c2637e3477..547c4758af 100644
--- a/cpu/esp_common/esp-now/esp_now_netdev.h
+++ b/cpu/esp_common/esp-now/esp_now_netdev.h
@@ -94,17 +94,25 @@ typedef struct
mutex_t dev_lock; /**< device is already in use */
- uint8_t scan_event; /**< ESP-NOW peers have to be scannged */
+ uint8_t scan_event; /**< ESP-NOW peers have to be scanned */
} esp_now_netdev_t;
/**
- * @brief netdev <-> esp_npw glue code initialization function
+ * @brief ESP-NOW netdev initialization function
*
- * @return NULL on error, pointer to esp_now_netdev on success
+ * @return NULL on error, pointer to esp_now_netdev on success
*/
esp_now_netdev_t *netdev_esp_now_setup(void);
+/**
+ * @brief Set the channel used by ESP-NOW netdev
+ *
+ * @param channel Channel to be used
+ * @return ESP_OK on success, an ESP error code otherwise
+ */
+int esp_now_set_channel(uint8_t channel);
+
#ifdef __cplusplus
}
#endif
diff --git a/cpu/esp_common/esp-wifi/doc.txt b/cpu/esp_common/esp-wifi/doc.txt
index 86532f0bdd..670698cfb5 100644
--- a/cpu/esp_common/esp-wifi/doc.txt
+++ b/cpu/esp_common/esp-wifi/doc.txt
@@ -114,4 +114,8 @@ the verification of the AP certificate is not yet supported.
ESP-NOW network interface (module `esp_now`)
can be used simultaneously, for example, to realize a border router for
a mesh network which uses ESP-NOW.
+In this case the ESP-NOW interface must use the same channel as the AP of the
+infrastructure WiFi network. All ESP-NOW nodes must therefore be compiled with
+the channel of the AP asvalue for the parameter 'ESP_NOW_CHANNEL'.
+
*/
diff --git a/cpu/esp_common/esp-wifi/esp_wifi_netdev.c b/cpu/esp_common/esp-wifi/esp_wifi_netdev.c
index 3a11995387..bf41a2127a 100644
--- a/cpu/esp_common/esp-wifi/esp_wifi_netdev.c
+++ b/cpu/esp_common/esp-wifi/esp_wifi_netdev.c
@@ -402,8 +402,12 @@ static const char *_esp_wifi_disc_reasons [] = {
"HANDSHAKE_TIMEOUT" /* 204 */
};
+/* indicator whether the WiFi interface is started */
static unsigned _esp_wifi_started = 0;
+/* current channel used by the WiFi interface */
+static unsigned _esp_wifi_channel = 0;
+
/*
* Event handler for esp system events.
*/
@@ -440,7 +444,11 @@ static esp_err_t IRAM_ATTR _esp_system_event_handler(void *ctx, system_event_t *
ESP_WIFI_LOG_INFO("WiFi connected to ssid %s, channel %d",
event->event_info.connected.ssid,
event->event_info.connected.channel);
-
+ _esp_wifi_channel = event->event_info.connected.channel;
+#ifdef MODULE_ESP_NOW
+ extern void esp_now_set_channel(uint8_t channel);
+ esp_now_set_channel(_esp_wifi_channel);
+#endif
/* register RX callback function */
esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, _esp_wifi_rx_cb);
@@ -623,6 +631,10 @@ static int _esp_wifi_get(netdev_t *netdev, netopt_t opt, void *val, size_t max_l
switch (opt) {
case NETOPT_IS_WIRED:
return -ENOTSUP;
+ case NETOPT_CHANNEL:
+ CHECK_PARAM_RET(max_len >= sizeof(uint16_t), -EOVERFLOW);
+ *((uint16_t *)val) = _esp_wifi_channel;
+ return sizeof(uint16_t);
case NETOPT_ADDRESS:
assert(max_len >= ETHERNET_ADDR_LEN);
esp_wifi_get_mac(ESP_MAC_WIFI_STA,(uint8_t *)val);