#pragma once #include #include #include "esp_now.h" #include "esp_wifi.h" /** * @brief ESP-NOW peer link (ported from the Arduino/ESP-NOW version). * * Runs ESP-NOW on the station interface of channel 14 with a broadcast peer * used for pairing requests, plus a stored unicast peer used for the normal * game traffic. */ class Air { public: /** * Over-the-air packet. The original declared it `alignas(1)`; `packed` * expresses the same intent (sizeof == 19, no trailing padding) in a way * that is portable C++. */ struct __attribute__((packed)) packet_t { uint32_t color = 0; uint32_t hit_cnt = 0; uint8_t dbus[10] = {0}; int8_t rssi = 0; }; static packet_t my_packet, peer_packet; static volatile uint32_t last_air_ms; static volatile bool is_pairing; static volatile bool pairing_found; static void begin(); static void entryPairing(); static void savePairing(); static void onLoop(); // The USB-CDC task writes my_packet.dbus while the application task reads // it, so the copy/clear are serialised here instead of being done inline. static void dbusSet(const uint8_t *src, size_t len); static void dbusClear(); private: static const uint8_t empty_mac[6]; static const uint8_t pairing_data[4]; static esp_now_peer_info_t broadcast_peer; static esp_now_peer_info_t peer; static volatile int8_t pairing_best_rssi; static void onRecv(const esp_now_recv_info_t *info, const uint8_t *data, int data_len); static void promiscuous_rx_cb(void *buf, wifi_promiscuous_pkt_type_t type); };