Trying to insert a WiFiEvent callback inside my class.

Hi, i am in the process of making my a library that will control my wifi behavior over a multitude of different bord with ESP32 chip.

In my normal setup, i set the WiFi event to call a function like this:

void setup(){
    WiFi.onEvent(WiFiEvent);
}

void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
  Serial.printf("[WiFi-event] event: %d\n", event);
  switch (event) {
    case SYSTEM_EVENT_WIFI_READY:
      Serial.println("WiFi interface ready");
      break;
    default:
      break;
  }
}

This is working pretty well! Now i would like to remove that from my normal code and add this into my library.

So here is my .h file:

/*
  EraIoT_WiFi.h - Library for controlling WiFi for all EraIoT module..
  Created by Martin Chicoine, January 19, 2020.
*/

#ifndef EraIoT_WiFi_h
#define EraIoT_Wifi_h

#include "Arduino.h"
#include <WiFi.h>


class EraIoT_WiFi{
  public:
    EraIoT_WiFi();
    EraIoT_WiFi(const char *ssid, const char *password);
    char* getSSID(void);
    char* getPSWD(void);
    void connect();
  private:
    char ssid[50];
    char password[15];
    char serial[10];
    void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info);
};

#endif

And here is my .cpp file:

#include "Arduino.h"
#include "WiFi.h"
#include "EraIoT_WiFi.h"

EraIoT_WiFi::EraIoT_WiFi(){
    strcpy(this->ssid, "EraIoT");
    strcpy(this->password, "VfWw6ga5fW");
}

EraIoT_WiFi::EraIoT_WiFi(const char * ssid, const char * password){
    strcpy(this->ssid, (char*)ssid);
    strcpy(this->password, (char*)password);
}

char* EraIoT_WiFi::getSSID(void){
    return this->ssid;
}

char* EraIoT_WiFi::getPSWD(void){
    return this->password;
}

void EraIoT_WiFi::connect(){
    //WiFi.onEvent(WiFiEvent);
    WiFi.persistent(true);
    WiFi.mode(WIFI_AP_STA);
    if(this->serial[0] != '\0'){
        WiFi.setHostname(this->serial);
        WiFi.softAP(this->serial);
    }
    WiFi.begin(this->ssid, this->password);
}

void EraIoT_WiFi::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
  switch (event) {
    case SYSTEM_EVENT_WIFI_READY:
      //Serial.println("WiFi interface ready");
      break;
     default:
       Serial.print("Unknown");
       break;
      }
  }
}

But as you can think of it is nor working at all and i am a little lost about this one since i am just starting to split my code!

You aren't sharing everything, but I can guess you use a wifi class in your body of code. So, you need to include that object or include a pointer to it in your constructor.

And how can i do that ? I am reading a lot and trying to figure out everything, but is don't understand everything very well yet!

The callback function must be either a regular function or a static class function. It can't be a class instance function.

Is it possible to give me a exemple because right now, like i said i am just starting in the class and there is a lot more then in the normal loop, and i want to learn as much as i can!

Thanx!

In .h file:

#ifndef EraIoT_WiFi_h
#define EraIoT_Wifi_h

#include "Arduino.h"
#include <WiFi.h>


class EraIoT_WiFi{
  public:
    EraIoT_WiFi();
    EraIoT_WiFi(const char *ssid, const char *password);
    char* getSSID(void);
    char* getPSWD(void);
    void connect();
  private:
    char ssid[50];
    char password[15];
    char serial[10];
    static void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info);
};

#endif

In .cpp file:

void EraIoT_WiFi::connect(){
  WiFi.onEvent(WiFiEvent);
  //  .
  //  .
  //  .
}

void EraIoT_WiFi::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
// Handel WiFi Events here
}

Wow! :o That simple!!! Thanx a lot!!! It works perfect!!!

Well, the only problem right now with this solution, is that i can't set any non static variable in this static function!

It is very anoying! is there any other solutions ?

Thanx!

How many instances of this class do you intend to create?

Only 1

Then, you have a few choices:

  1. Don't use a class at all. You don't need to build a bridge to cross a stream once. You can implement it as a traditional 'C' library. The .h file would contain the interface and the .cpp file would implement standard functions. You can use the 'static' keyword to restrict private functions / variables to file-scope.

  2. Make a class and have all the functions and variables be Class Members (i.e. all 'static').

  3. Make a class and only allow a singleton instance to be created. Then you'll know the name of the instance and will be able to call an instance function on it from the static WiFiEvent() callback function. User @PieterP presented a pretty slick technique for doing this in Reply #1 of this thread. Here's a skeletal implementation of that:

Main Program:

#include "Arduino.h"

#include "MyMySingletonClass.h"

void setup() {
  MySingletonClass::examplePublicClassVariable = 100;
  singleton.examplePublicInstanceVariable = 200;

  MySingletonClass::examplePublicClassFunction();
  singleton.examplePublicInstanceFunction();
}

void loop() {
}

.h file:

#ifndef MYMYSINGLETONCLASS_H_
#define MYMYSINGLETONCLASS_H_

#include "Arduino.h"

class MySingletonClass {
public:
  MySingletonClass(const MySingletonClass &) = delete; // no copying allowed
  MySingletonClass &operator=(const MySingletonClass &) = delete; // no assignment allowed
  static MySingletonClass &getInstance(); // Accessor for singleton instance

  void examplePublicInstanceFunction();
  static void examplePublicClassFunction();

  uint8_t examplePublicInstanceVariable {0};
  static uint8_t examplePublicClassVariable;

private:
  MySingletonClass();  // Constructor is private
  void examplePrivateInstanceFunction();
  static void examplePrivateClassFunction();

  uint8_t examplePrivateInstanceVariable {0};
  static uint8_t examplePrivateClassVariable;
};

extern MySingletonClass &singleton;

#endif /* MYMYSINGLETONCLASS_H_ */

.cpp file:

#include "MyMySingletonClass.h"

uint8_t MySingletonClass::examplePrivateClassVariable { 0 };
uint8_t MySingletonClass::examplePublicClassVariable { 0 };

MySingletonClass::MySingletonClass() {  // Private constructor
}

MySingletonClass & MySingletonClass::getInstance() {
  static MySingletonClass instance;
  return instance;
}

void MySingletonClass::examplePublicInstanceFunction() {
}

void MySingletonClass::examplePublicClassFunction() {
}

void MySingletonClass::examplePrivateInstanceFunction() {
}

void MySingletonClass::examplePrivateClassFunction() {
}

MySingletonClass &singleton {MySingletonClass::getInstance()};

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.