diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp index c73ec9385d..362929f073 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp @@ -22,6 +22,8 @@ */ +#include +#include #include "ESP8266WiFi.h" #include "ESP8266WiFiGeneric.h" @@ -40,68 +42,164 @@ extern "C" { #include "WiFiClient.h" #include "WiFiUdp.h" - #include "debug.h" -#undef min -#undef max -#include - extern "C" void esp_schedule(); extern "C" void esp_yield(); + // ----------------------------------------------------------------------------------------------------------------------- // ------------------------------------------------- Generic WiFi function ----------------------------------------------- // ----------------------------------------------------------------------------------------------------------------------- -// arduino dont like std::vectors move static here -static std::vector cbEventList; +struct WiFiEventHandlerOpaque +{ + WiFiEventHandlerOpaque(WiFiEvent_t event, std::function handler) + : mEvent(event), mHandler(handler) + { + } + + void operator()(System_Event_t* e) + { + if (static_cast(e->event) == mEvent || mEvent == WIFI_EVENT_ANY) { + mHandler(e); + } + } + + bool canExpire() + { + return mCanExpire; + } + + WiFiEvent_t mEvent; + std::function mHandler; + bool mCanExpire = true; /* stopgap solution to handle deprecated void onEvent(cb, evt) case */ +}; + +static std::list sCbEventList; bool ESP8266WiFiGenericClass::_persistent = true; WiFiMode_t ESP8266WiFiGenericClass::_forceSleepLastMode = WIFI_OFF; -ESP8266WiFiGenericClass::ESP8266WiFiGenericClass() { +ESP8266WiFiGenericClass::ESP8266WiFiGenericClass() +{ wifi_set_event_handler_cb((wifi_event_handler_cb_t) &ESP8266WiFiGenericClass::_eventCallback); } -/** - * set callback function - * @param cbEvent WiFiEventCb - * @param event optional filter (WIFI_EVENT_MAX is all events) - */ -void ESP8266WiFiGenericClass::onEvent(WiFiEventCb cbEvent, WiFiEvent_t event) { - if(!cbEvent) { - return; - } - WiFiEventCbList_t newEventHandler; - newEventHandler.cb = cbEvent; - newEventHandler.event = event; - cbEventList.push_back(newEventHandler); +void ESP8266WiFiGenericClass::onEvent(WiFiEventCb f, WiFiEvent_t event) +{ + WiFiEventHandler handler = std::make_shared(event, [f](System_Event_t* e) { + (*f)(static_cast(e->event)); + }); + handler->mCanExpire = false; } -/** - * removes a callback form event handler - * @param cbEvent WiFiEventCb - * @param event optional filter (WIFI_EVENT_MAX is all events) - */ -void ESP8266WiFiGenericClass::removeEvent(WiFiEventCb cbEvent, WiFiEvent_t event) { - if(!cbEvent) { - return; - } +WiFiEventHandler ESP8266WiFiGenericClass::onStationModeConnected(std::function f) +{ + WiFiEventHandler handler = std::make_shared(WIFI_EVENT_STAMODE_CONNECTED, [f](System_Event_t* e) { + auto& src = e->event_info.connected; + WiFiEventStationModeConnected dst; + dst.ssid = String(reinterpret_cast(src.ssid)); + memcpy(dst.bssid, src.bssid, 6); + dst.channel = src.channel; + f(dst); + }); + sCbEventList.push_back(handler); + return handler; +} - for(uint32_t i = 0; i < cbEventList.size(); i++) { - WiFiEventCbList_t entry = cbEventList[i]; - if(entry.cb == cbEvent && entry.event == event) { - cbEventList.erase(cbEventList.begin() + i); - } - } +WiFiEventHandler ESP8266WiFiGenericClass::onStationModeDisconnected(std::function f) +{ + WiFiEventHandler handler = std::make_shared(WIFI_EVENT_STAMODE_DISCONNECTED, [f](System_Event_t* e){ + auto& src = e->event_info.disconnected; + WiFiEventStationModeDisconnected dst; + dst.ssid = String(reinterpret_cast(src.ssid)); + memcpy(dst.bssid, src.bssid, 6); + dst.reason = static_cast(src.reason); + f(dst); + }); + sCbEventList.push_back(handler); + return handler; +} + +WiFiEventHandler ESP8266WiFiGenericClass::onStationModeAuthModeChanged(std::function f) +{ + WiFiEventHandler handler = std::make_shared(WIFI_EVENT_STAMODE_AUTHMODE_CHANGE, [f](System_Event_t* e){ + auto& src = e->event_info.auth_change; + WiFiEventStationModeAuthModeChanged dst; + dst.oldMode = src.old_mode; + dst.newMode = src.new_mode; + f(dst); + }); + sCbEventList.push_back(handler); + return handler; +} + +WiFiEventHandler ESP8266WiFiGenericClass::onStationModeGotIP(std::function f) +{ + WiFiEventHandler handler = std::make_shared(WIFI_EVENT_STAMODE_GOT_IP, [f](System_Event_t* e){ + auto& src = e->event_info.got_ip; + WiFiEventStationModeGotIP dst; + dst.ip = src.ip.addr; + dst.mask = src.mask.addr; + dst.gw = src.gw.addr; + f(dst); + }); + sCbEventList.push_back(handler); + return handler; } +WiFiEventHandler onStationModeDHCPTimeout(std::function f) +{ + WiFiEventHandler handler = std::make_shared(WIFI_EVENT_STAMODE_DHCP_TIMEOUT, [f](System_Event_t* e){ + f(); + }); + sCbEventList.push_back(handler); + return handler; +} + +WiFiEventHandler ESP8266WiFiGenericClass::onSoftAPModeStationConnected(std::function f) +{ + WiFiEventHandler handler = std::make_shared(WIFI_EVENT_SOFTAPMODE_STACONNECTED, [f](System_Event_t* e){ + auto& src = e->event_info.sta_connected; + WiFiEventSoftAPModeStationConnected dst; + memcpy(dst.mac, src.mac, 6); + dst.aid = src.aid; + f(dst); + }); + sCbEventList.push_back(handler); + return handler; +} + +WiFiEventHandler ESP8266WiFiGenericClass::onSoftAPModeStationDisconnected(std::function f) +{ + WiFiEventHandler handler = std::make_shared(WIFI_EVENT_SOFTAPMODE_STADISCONNECTED, [f](System_Event_t* e){ + auto& src = e->event_info.sta_disconnected; + WiFiEventSoftAPModeStationDisconnected dst; + memcpy(dst.mac, src.mac, 6); + dst.aid = src.aid; + f(dst); + }); + sCbEventList.push_back(handler); + return handler; +} + +// WiFiEventHandler ESP8266WiFiGenericClass::onWiFiModeChange(std::function f) +// { +// WiFiEventHandler handler = std::make_shared(WIFI_EVENT_MODE_CHANGE, [f](System_Event_t* e){ +// WiFiEventModeChange& dst = *reinterpret_cast(&e->event_info); +// f(dst); +// }); +// sCbEventList.push_back(handler); +// return handler; +// } + /** * callback for WiFi events * @param arg */ -void ESP8266WiFiGenericClass::_eventCallback(void* arg) { +void ESP8266WiFiGenericClass::_eventCallback(void* arg) +{ System_Event_t* event = reinterpret_cast(arg); DEBUG_WIFI("wifi evt: %d\n", event->event); @@ -110,12 +208,14 @@ void ESP8266WiFiGenericClass::_eventCallback(void* arg) { WiFiClient::stopAll(); } - for(uint32_t i = 0; i < cbEventList.size(); i++) { - WiFiEventCbList_t entry = cbEventList[i]; - if(entry.cb) { - if(entry.event == (WiFiEvent_t) event->event || entry.event == WIFI_EVENT_MAX) { - entry.cb((WiFiEvent_t) event->event); - } + for(auto it = std::begin(sCbEventList); it != std::end(sCbEventList); ) { + WiFiEventHandler &handler = *it; + if (handler->canExpire() && handler.unique()) { + it = sCbEventList.erase(it); + } + else { + (*handler)(event); + ++it; } } } diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.h b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.h index 7519605231..335d416b55 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.h +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.h @@ -24,6 +24,8 @@ #define ESP8266WIFIGENERIC_H_ #include "ESP8266WiFiType.h" +#include +#include #ifdef DEBUG_ESP_WIFI #ifdef DEBUG_ESP_PORT @@ -35,12 +37,10 @@ #define DEBUG_WIFI_GENERIC(...) #endif -typedef void (*WiFiEventCb)(WiFiEvent_t event); +struct WiFiEventHandlerOpaque; +typedef std::shared_ptr WiFiEventHandler; -typedef struct { - WiFiEventCb cb; - WiFiEvent_t event; -} WiFiEventCbList_t; +typedef void (*WiFiEventCb)(WiFiEvent_t); class ESP8266WiFiGenericClass { // ---------------------------------------------------------------------------------------------- @@ -48,11 +48,20 @@ class ESP8266WiFiGenericClass { // ---------------------------------------------------------------------------------------------- public: - ESP8266WiFiGenericClass(); - void onEvent(WiFiEventCb cbEvent, WiFiEvent_t event = WIFI_EVENT_MAX); - void removeEvent(WiFiEventCb cbEvent, WiFiEvent_t event = WIFI_EVENT_MAX); + // Note: this function is deprecated. Use one of the functions below instead. + void onEvent(WiFiEventCb cb, WiFiEvent_t event = WIFI_EVENT_ANY) __attribute__((deprecated)); + + // Subscribe to specific event and get event information as an argument to the callback + WiFiEventHandler onStationModeConnected(std::function); + WiFiEventHandler onStationModeDisconnected(std::function); + WiFiEventHandler onStationModeAuthModeChanged(std::function); + WiFiEventHandler onStationModeGotIP(std::function); + WiFiEventHandler onStationModeDHCPTimeout(std::function); + WiFiEventHandler onSoftAPModeStationConnected(std::function); + WiFiEventHandler onSoftAPModeStationDisconnected(std::function); + // WiFiEventHandler onWiFiModeChange(std::function); int32_t channel(void); diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiType.h b/libraries/ESP8266WiFi/src/ESP8266WiFiType.h index 03e16bea65..6854ab8544 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiType.h +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiType.h @@ -28,23 +28,28 @@ #define WIFI_SCAN_RUNNING (-1) #define WIFI_SCAN_FAILED (-2) -// Note: -// this enums need to be in sync with the SDK! +// Note: these enums need to be in sync with the SDK! -typedef enum WiFiMode { +// TODO: replace/deprecate/remove enum typedefs ending with _t below + +typedef enum WiFiMode +{ WIFI_OFF = 0, WIFI_STA = 1, WIFI_AP = 2, WIFI_AP_STA = 3 } WiFiMode_t; -typedef enum { +typedef enum WiFiPhyMode +{ WIFI_PHY_MODE_11B = 1, WIFI_PHY_MODE_11G = 2, WIFI_PHY_MODE_11N = 3 } WiFiPhyMode_t; -typedef enum { - WIFI_NONE_SLEEP = 0, WIFI_LIGHT_SLEEP =1, WIFI_MODEM_SLEEP = 2 +typedef enum WiFiSleepType +{ + WIFI_NONE_SLEEP = 0, WIFI_LIGHT_SLEEP = 1, WIFI_MODEM_SLEEP = 2 } WiFiSleepType_t; -typedef enum { +typedef enum WiFiEvent +{ WIFI_EVENT_STAMODE_CONNECTED = 0, WIFI_EVENT_STAMODE_DISCONNECTED, WIFI_EVENT_STAMODE_AUTHMODE_CHANGE, @@ -53,9 +58,94 @@ typedef enum { WIFI_EVENT_SOFTAPMODE_STACONNECTED, WIFI_EVENT_SOFTAPMODE_STADISCONNECTED, WIFI_EVENT_SOFTAPMODE_PROBEREQRECVED, - WIFI_EVENT_MAX + WIFI_EVENT_MAX, + WIFI_EVENT_ANY = WIFI_EVENT_MAX, + WIFI_EVENT_MODE_CHANGE } WiFiEvent_t; +enum WiFiDisconnectReason +{ + WIFI_DISCONNECT_REASON_UNSPECIFIED = 1, + WIFI_DISCONNECT_REASON_AUTH_EXPIRE = 2, + WIFI_DISCONNECT_REASON_AUTH_LEAVE = 3, + WIFI_DISCONNECT_REASON_ASSOC_EXPIRE = 4, + WIFI_DISCONNECT_REASON_ASSOC_TOOMANY = 5, + WIFI_DISCONNECT_REASON_NOT_AUTHED = 6, + WIFI_DISCONNECT_REASON_NOT_ASSOCED = 7, + WIFI_DISCONNECT_REASON_ASSOC_LEAVE = 8, + WIFI_DISCONNECT_REASON_ASSOC_NOT_AUTHED = 9, + WIFI_DISCONNECT_REASON_DISASSOC_PWRCAP_BAD = 10, /* 11h */ + WIFI_DISCONNECT_REASON_DISASSOC_SUPCHAN_BAD = 11, /* 11h */ + WIFI_DISCONNECT_REASON_IE_INVALID = 13, /* 11i */ + WIFI_DISCONNECT_REASON_MIC_FAILURE = 14, /* 11i */ + WIFI_DISCONNECT_REASON_4WAY_HANDSHAKE_TIMEOUT = 15, /* 11i */ + WIFI_DISCONNECT_REASON_GROUP_KEY_UPDATE_TIMEOUT = 16, /* 11i */ + WIFI_DISCONNECT_REASON_IE_IN_4WAY_DIFFERS = 17, /* 11i */ + WIFI_DISCONNECT_REASON_GROUP_CIPHER_INVALID = 18, /* 11i */ + WIFI_DISCONNECT_REASON_PAIRWISE_CIPHER_INVALID = 19, /* 11i */ + WIFI_DISCONNECT_REASON_AKMP_INVALID = 20, /* 11i */ + WIFI_DISCONNECT_REASON_UNSUPP_RSN_IE_VERSION = 21, /* 11i */ + WIFI_DISCONNECT_REASON_INVALID_RSN_IE_CAP = 22, /* 11i */ + WIFI_DISCONNECT_REASON_802_1X_AUTH_FAILED = 23, /* 11i */ + WIFI_DISCONNECT_REASON_CIPHER_SUITE_REJECTED = 24, /* 11i */ + + WIFI_DISCONNECT_REASON_BEACON_TIMEOUT = 200, + WIFI_DISCONNECT_REASON_NO_AP_FOUND = 201, + WIFI_DISCONNECT_REASON_AUTH_FAIL = 202, + WIFI_DISCONNECT_REASON_ASSOC_FAIL = 203, + WIFI_DISCONNECT_REASON_HANDSHAKE_TIMEOUT = 204, +}; + +struct WiFiEventModeChange +{ + WiFiMode oldMode; + WiFiMode newMode; +}; + +struct WiFiEventStationModeConnected +{ + String ssid; + uint8 bssid[6]; + uint8 channel; +}; + +struct WiFiEventStationModeDisconnected +{ + String ssid; + uint8 bssid[6]; + WiFiDisconnectReason reason; +}; + +struct WiFiEventStationModeAuthModeChanged +{ + uint8 oldMode; + uint8 newMode; +}; + +struct WiFiEventStationModeGotIP +{ + IPAddress ip; + IPAddress mask; + IPAddress gw; +}; + +struct WiFiEventSoftAPModeStationConnected +{ + uint8 mac[6]; + uint8 aid; +}; + +struct WiFiEventSoftAPModeStationDisconnected +{ + uint8 mac[6]; + uint8 aid; +}; + +struct WiFiEventSoftAPModeProbeRequestReceived +{ + int rssi; + uint8 mac[6]; +}; extern "C" {