static void IRAM_ATTR esp_now_scan_peers_done (void) { mutex_lock(&_esp_now_dev.dev_lock); esp_err_t ret; uint16_t ap_num; ret = esp_wifi_scan_get_ap_num(&ap_num); DEBUG("wifi_scan_get_ap_num ret=%d num=%d\n", ret ,ap_num); if (ret == ESP_OK && ap_num) { uint32_t state; /* reallocation of memory must not be disturbed */ critical_enter_var(state); /* allocate memory for APs record list blockwise and fetch them the list */ if (ap_num > aps_size) { if (aps) { /* free allocated AP record list memory */ aps_size = 0; free (aps); } /* allocate new memory */ aps_size = (ap_num & ~(ESP_NOW_APS_BLOCK_SIZE - 1)) + ESP_NOW_APS_BLOCK_SIZE; aps = malloc(sizeof(wifi_ap_record_t) * aps_size); ap_num = aps_size; } critical_exit_var(state); ret = esp_wifi_scan_get_ap_records(&ap_num, aps); DEBUG("wifi_scan_get_aps ret=%d num=%d\n", ret, ap_num); critical_enter_var(state); /* iterate over APs records */ for (uint16_t i = 0; i < ap_num; i++) { /* check whether the AP is an ESP_NOW node which is not already a peer */ if (strncmp((char*)aps[i].ssid, ESP_NOW_AP_PREFIX, ESP_NOW_AP_PREFIX_LEN) == 0 && !esp_now_is_peer_exist(aps[i].bssid)) { /* add the AP as peer */ _esp_now_add_peer(aps[i].bssid, aps[i].primary, esp_now_params.key); } } critical_exit_var(state); } #if ENABLE_DEBUG esp_now_peer_num_t peer_num; esp_now_get_peer_num (&peer_num); DEBUG("associated peers total=%d, encrypted=%d\n", peer_num.total_num, peer_num.encrypt_num); #endif _esp_now_scan_peers_done = true; /* set the time for next scan */ xtimer_set (&_esp_now_scan_peers_timer, esp_now_params.scan_period); mutex_unlock(&_esp_now_dev.dev_lock); }
static int _recv(netdev_t *netdev, void *buf, size_t len, void *info) { DEBUG("%s: %p %p %u %p\n", __func__, netdev, buf, len, info); CHECK_PARAM_RET (netdev != NULL, -ENODEV); esp_now_netdev_t* dev = (esp_now_netdev_t*)netdev; mutex_lock(&dev->dev_lock); uint8_t size = dev->rx_len; if (!buf && !len) { /* return the size without dropping received data */ mutex_unlock(&dev->dev_lock); return size; } if (!buf && len) { /* return the size and drop received data */ mutex_unlock(&dev->dev_lock); dev->rx_len = 0; return size; } if (buf && len && dev->rx_len) { if (dev->rx_len > len) { DEBUG("[esp_now] No space in receive buffers\n"); mutex_unlock(&dev->dev_lock); return -ENOBUFS; } #if ENABLE_DEBUG printf ("%s: received %d byte from %02x:%02x:%02x:%02x:%02x:%02x\n", __func__, dev->rx_len, dev->rx_mac[0], dev->rx_mac[1], dev->rx_mac[2], dev->rx_mac[3], dev->rx_mac[4], dev->rx_mac[5]); /* esp_hexdump (dev->rx_buf, dev->rx_len, 'b', 16); */ #endif if (esp_now_is_peer_exist(dev->rx_mac) <= 0) { _esp_now_add_peer(dev->rx_mac, esp_now_params.channel, esp_now_params.key); } memcpy(buf, dev->rx_buf, dev->rx_len); dev->rx_len = 0; #ifdef MODULE_NETSTATS_L2 netdev->stats.rx_count++; netdev->stats.rx_bytes += size; #endif mutex_unlock(&dev->dev_lock); return size; } mutex_unlock(&dev->dev_lock); return -EINVAL; }
int ICACHE_FLASH_ATTR demo_send(u8 * data, u8 len) { if (esp_now_is_peer_exist(slave_mac) == 0) { os_printf("The espnow peer does not exist\n"); return 0; } else { /* the demo will send to two devices which added by esp_now_add_peer() */ int ret = esp_now_send(NULL, data, len); return ret; } }
static bool _esp_now_add_peer (uint8_t* bssid, uint8_t channel, uint8_t* key) { if (esp_now_is_peer_exist(bssid)) { return false; } esp_now_peer_info_t peer = {}; memcpy(peer.peer_addr, bssid, ESP_NOW_ETH_ALEN); peer.channel = channel; peer.ifidx = ESP_IF_WIFI_AP; if (esp_now_params.key) { peer.encrypt = true; memcpy(peer.lmk, esp_now_params.key, ESP_NOW_KEY_LEN); } esp_err_t ret = esp_now_add_peer(&peer); DEBUG("esp_now_add_peer node %02x:%02x:%02x:%02x:%02x:%02x " "added with return value %d\n", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5], ret); return (ret == ESP_OK); }
static int _send(netdev_t *netdev, const iolist_t *iolist) { #if ESP_NOW_UNICAST if (!_esp_now_scan_peers_done) { return -ENODEV; } #endif DEBUG("%s: %p %p\n", __func__, netdev, iolist); CHECK_PARAM_RET (netdev != NULL, -ENODEV); CHECK_PARAM_RET (iolist != NULL, -EINVAL); esp_now_netdev_t* dev = (esp_now_netdev_t*)netdev; mutex_lock(&dev->dev_lock); dev->tx_len = 0; /* load packet data into TX buffer */ for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) { if (dev->tx_len + iol->iol_len > ESP_NOW_MAX_SIZE) { mutex_unlock(&dev->dev_lock); return -EOVERFLOW; } memcpy (dev->tx_buf + dev->tx_len, iol->iol_base, iol->iol_len); dev->tx_len += iol->iol_len; } #if ENABLE_DEBUG printf ("%s: send %d byte\n", __func__, dev->tx_len); /* esp_hexdump (dev->tx_buf, dev->tx_len, 'b', 16); */ #endif _esp_now_sending = 1; uint8_t* _esp_now_dst = 0; #if ESP_NOW_UNICAST ipv6_hdr_t* ipv6_hdr = (ipv6_hdr_t*)dev->tx_buf; uint8_t _esp_now_dst_from_iid[6]; if (ipv6_hdr->dst.u8[0] == 0xff) { /* packets to multicast prefix ff::/8 are sent to all peers */ DEBUG("multicast to all peers\n"); _esp_now_dst = 0; _esp_now_sending = dev->peers_all; #ifdef MODULE_NETSTATS_L2 netdev->stats.tx_mcast_count++; #endif } else if ((byteorder_ntohs(ipv6_hdr->dst.u16[0]) & 0xffc0) == 0xfe80) { /* for link local addresses fe80::/10, the MAC address is derived from dst address */ _get_mac_from_iid(&ipv6_hdr->dst.u8[8], _esp_now_dst_from_iid); DEBUG("link local to %02x:%02x:%02x:%02x:%02x:%02x\n", _esp_now_dst_from_iid[0], _esp_now_dst_from_iid[1], _esp_now_dst_from_iid[2], _esp_now_dst_from_iid[3], _esp_now_dst_from_iid[4], _esp_now_dst_from_iid[5]); _esp_now_dst = _esp_now_dst_from_iid; _esp_now_sending = 1; } else { #ifdef MODULE_GNRC_IPV6_NIB /* for other addresses, try to find an entry in NIB cache */ gnrc_ipv6_nib_nc_t nce; int ret = gnrc_ipv6_nib_get_next_hop_l2addr (&ipv6_hdr->dst, dev->netif, NULL, &nce); if (ret == 0) { /* entry was found in NIB, use MAC adress from the NIB cache entry */ DEBUG("global, next hop to neighbor %02x:%02x:%02x:%02x:%02x:%02x\n", nce.l2addr[0], nce.l2addr[1], nce.l2addr[2], nce.l2addr[3], nce.l2addr[4], nce.l2addr[5]); _esp_now_dst = nce.l2addr; _esp_now_sending = 1; } else { #endif /* entry was not found in NIB, send to all peers */ DEBUG("global, no neibhbor found, multicast to all peers\n"); _esp_now_dst = 0; _esp_now_sending = dev->peers_all; #ifdef MODULE_NETSTATS_L2 netdev->stats.tx_mcast_count++; #endif #ifdef MODULE_GNRC_IPV6_NIB } #endif } #else /* ESP_NOW_UNICAST */ ipv6_hdr_t* ipv6_hdr = (ipv6_hdr_t*)dev->tx_buf; uint8_t _esp_now_dst_from_iid[6]; _esp_now_dst = (uint8_t*)_esp_now_mac; _esp_now_sending = 1; if (ipv6_hdr->dst.u8[0] == 0xff) { /* packets to multicast prefix ff::/8 are sent to all peers */ DEBUG("multicast to all peers\n"); #ifdef MODULE_NETSTATS_L2 netdev->stats.tx_mcast_count++; #endif } else if ((byteorder_ntohs(ipv6_hdr->dst.u16[0]) & 0xffc0) == 0xfe80) { /* for link local addresses fe80::/10, the MAC address is derived from dst address */ _get_mac_from_iid(&ipv6_hdr->dst.u8[8], _esp_now_dst_from_iid); DEBUG("link local to %02x:%02x:%02x:%02x:%02x:%02x\n", _esp_now_dst_from_iid[0], _esp_now_dst_from_iid[1], _esp_now_dst_from_iid[2], _esp_now_dst_from_iid[3], _esp_now_dst_from_iid[4], _esp_now_dst_from_iid[5]); if (esp_now_is_peer_exist(_esp_now_dst_from_iid) > 0) { _esp_now_dst = _esp_now_dst_from_iid; } } else { /* for other addresses, try to find an entry in NIB cache */ gnrc_ipv6_nib_nc_t nce; int ret = gnrc_ipv6_nib_get_next_hop_l2addr (&ipv6_hdr->dst, dev->netif, NULL, &nce); if (ret == 0 && esp_now_is_peer_exist(nce.l2addr) > 0) { /* entry was found in NIB, use MAC adress from the NIB cache entry */ DEBUG("global, next hop to neighbor %02x:%02x:%02x:%02x:%02x:%02x\n", nce.l2addr[0], nce.l2addr[1], nce.l2addr[2], nce.l2addr[3], nce.l2addr[4], nce.l2addr[5]); _esp_now_dst = nce.l2addr; } else { /* entry was not found in NIB, send to all peers */ DEBUG("global, no neibhbor found, multicast to all peers\n"); #ifdef MODULE_NETSTATS_L2 netdev->stats.tx_mcast_count++; #endif } } #endif /* ESP_NOW_UNICAST */ if (_esp_now_dst) { DEBUG("%s: send to esp_now addr %02x:%02x:%02x:%02x:%02x:%02x\n", __func__, _esp_now_dst[0], _esp_now_dst[1], _esp_now_dst[2], _esp_now_dst[3], _esp_now_dst[4], _esp_now_dst[5]); } /* send the the packet to the peer(s) mac address */ if (esp_now_send (_esp_now_dst, dev->tx_buf, dev->tx_len) == 0) { while (_esp_now_sending > 0) { thread_yield_higher(); } #ifdef MODULE_NETSTATS_L2 netdev->stats.tx_bytes += dev->tx_len; netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE); #endif mutex_unlock(&dev->dev_lock); return dev->tx_len; } else { #ifdef MODULE_NETSTATS_L2 netdev->stats.tx_failed++; #endif } mutex_unlock(&dev->dev_lock); return -EIO; }