Skip to content

WiFi event handling refactoring #2119

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 143 additions & 43 deletions libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

*/

#include <list>
#include <string.h>
#include "ESP8266WiFi.h"
#include "ESP8266WiFiGeneric.h"

Expand All @@ -40,68 +42,164 @@ extern "C" {

#include "WiFiClient.h"
#include "WiFiUdp.h"

#include "debug.h"

#undef min
#undef max
#include <vector>

extern "C" void esp_schedule();
extern "C" void esp_yield();


// -----------------------------------------------------------------------------------------------------------------------
// ------------------------------------------------- Generic WiFi function -----------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------

// arduino dont like std::vectors move static here
static std::vector<WiFiEventCbList_t> cbEventList;
struct WiFiEventHandlerOpaque
{
WiFiEventHandlerOpaque(WiFiEvent_t event, std::function<void(System_Event_t*)> handler)
: mEvent(event), mHandler(handler)
{
}

void operator()(System_Event_t* e)
{
if (static_cast<WiFiEvent>(e->event) == mEvent || mEvent == WIFI_EVENT_ANY) {
mHandler(e);
}
}

bool canExpire()
{
return mCanExpire;
}

WiFiEvent_t mEvent;
std::function<void(System_Event_t*)> mHandler;
bool mCanExpire = true; /* stopgap solution to handle deprecated void onEvent(cb, evt) case */
};

static std::list<WiFiEventHandler> 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<WiFiEventHandlerOpaque>(event, [f](System_Event_t* e) {
(*f)(static_cast<WiFiEvent>(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<void(const WiFiEventStationModeConnected&)> f)
{
WiFiEventHandler handler = std::make_shared<WiFiEventHandlerOpaque>(WIFI_EVENT_STAMODE_CONNECTED, [f](System_Event_t* e) {
auto& src = e->event_info.connected;
WiFiEventStationModeConnected dst;
dst.ssid = String(reinterpret_cast<char*>(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<void(const WiFiEventStationModeDisconnected&)> f)
{
WiFiEventHandler handler = std::make_shared<WiFiEventHandlerOpaque>(WIFI_EVENT_STAMODE_DISCONNECTED, [f](System_Event_t* e){
auto& src = e->event_info.disconnected;
WiFiEventStationModeDisconnected dst;
dst.ssid = String(reinterpret_cast<char*>(src.ssid));
memcpy(dst.bssid, src.bssid, 6);
dst.reason = static_cast<WiFiDisconnectReason>(src.reason);
f(dst);
});
sCbEventList.push_back(handler);
return handler;
}

WiFiEventHandler ESP8266WiFiGenericClass::onStationModeAuthModeChanged(std::function<void(const WiFiEventStationModeAuthModeChanged&)> f)
{
WiFiEventHandler handler = std::make_shared<WiFiEventHandlerOpaque>(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<void(const WiFiEventStationModeGotIP&)> f)
{
WiFiEventHandler handler = std::make_shared<WiFiEventHandlerOpaque>(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<void(void)> f)
{
WiFiEventHandler handler = std::make_shared<WiFiEventHandlerOpaque>(WIFI_EVENT_STAMODE_DHCP_TIMEOUT, [f](System_Event_t* e){
f();
});
sCbEventList.push_back(handler);
return handler;
}

WiFiEventHandler ESP8266WiFiGenericClass::onSoftAPModeStationConnected(std::function<void(const WiFiEventSoftAPModeStationConnected&)> f)
{
WiFiEventHandler handler = std::make_shared<WiFiEventHandlerOpaque>(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<void(const WiFiEventSoftAPModeStationDisconnected&)> f)
{
WiFiEventHandler handler = std::make_shared<WiFiEventHandlerOpaque>(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<void(const WiFiEventModeChange&)> f)
// {
// WiFiEventHandler handler = std::make_shared<WiFiEventHandlerOpaque>(WIFI_EVENT_MODE_CHANGE, [f](System_Event_t* e){
// WiFiEventModeChange& dst = *reinterpret_cast<WiFiEventModeChange*>(&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<System_Event_t*>(arg);
DEBUG_WIFI("wifi evt: %d\n", event->event);

Expand All @@ -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;
}
}
}
Expand Down
25 changes: 17 additions & 8 deletions libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#define ESP8266WIFIGENERIC_H_

#include "ESP8266WiFiType.h"
#include <functional>
#include <memory>

#ifdef DEBUG_ESP_WIFI
#ifdef DEBUG_ESP_PORT
Expand All @@ -35,24 +37,31 @@
#define DEBUG_WIFI_GENERIC(...)
#endif

typedef void (*WiFiEventCb)(WiFiEvent_t event);
struct WiFiEventHandlerOpaque;
typedef std::shared_ptr<WiFiEventHandlerOpaque> WiFiEventHandler;

typedef struct {
WiFiEventCb cb;
WiFiEvent_t event;
} WiFiEventCbList_t;
typedef void (*WiFiEventCb)(WiFiEvent_t);

class ESP8266WiFiGenericClass {
// ----------------------------------------------------------------------------------------------
// -------------------------------------- Generic WiFi function ---------------------------------
// ----------------------------------------------------------------------------------------------

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<void(const WiFiEventStationModeConnected&)>);
WiFiEventHandler onStationModeDisconnected(std::function<void(const WiFiEventStationModeDisconnected&)>);
WiFiEventHandler onStationModeAuthModeChanged(std::function<void(const WiFiEventStationModeAuthModeChanged&)>);
WiFiEventHandler onStationModeGotIP(std::function<void(const WiFiEventStationModeGotIP&)>);
WiFiEventHandler onStationModeDHCPTimeout(std::function<void(void)>);
WiFiEventHandler onSoftAPModeStationConnected(std::function<void(const WiFiEventSoftAPModeStationConnected&)>);
WiFiEventHandler onSoftAPModeStationDisconnected(std::function<void(const WiFiEventSoftAPModeStationDisconnected&)>);
// WiFiEventHandler onWiFiModeChange(std::function<void(const WiFiEventModeChange&)>);

int32_t channel(void);

Expand Down
Loading