Class event calling

I have a problem with the onEvent function from the WebSocketClient lib. Here is my code and my error message.

header:

[
#ifndef Lamp_Alexa_h
#define Lamp_Alexa_h

// including Amazon Alexa necessary libaries
#include <WebSocketsClient.h> // get it from https://github.com/Links2004/arduinoWebSockets/releases 
#include <ArduinoJson.h> // get it from https://arduinojson.org/ or install via Arduino library manager
#include <StreamString.h>

// define parameters for sinric
#define API_ENDPOINT "http://sinric.com"
#define HEARTBEAT_INTERVAL 300000 // 5 Minutes


class Lamp_Alexa{
  public:
    Lamp_Alexa(String apiKey, String deviceId);
    void turnOn();
    void turnOff();
    void init();
  private:
    WebSocketsClient webSocket;
    String state;
    void webSocketEvent(WStype_t type, uint8_t * payload, size_t length);
    String _deviceId;
    String _apiKey;
    bool isConnected;
};

#endif

cpp:

#include "Lamp_Alexa.h"

Lamp_Alexa::Lamp_Alexa(String apiKey, String deviceId){
  _deviceId = deviceId;
  _apiKey = apiKey;
}

void Lamp_Alexa::init(){
  // server address, port and URL
  webSocket.begin("iot.sinric.com", 80, "/");

  // event handler
  webSocket.onEvent(this->webSocketEvent);
  webSocket.setAuthorization("apikey", _apiKey);
  
  // try again every 5000ms if connection has failed
  webSocket.setReconnectInterval(5000);
}

void Lamp_Alexa::webSocketEvent(WStype_t type, uint8_t * payload, size_t length){
  switch(type) {
    case WStype_DISCONNECTED:
      isConnected = false;    
      Serial.printf("[WSc] Webservice disconnected from sinric.com!\n");
      break;
    case WStype_CONNECTED: {
      isConnected = true;
      Serial.printf("[WSc] Service connected to sinric.com at url: %s\n", payload);
      Serial.printf("Waiting for commands from sinric.com ...\n");        
      }
      break;
    case WStype_TEXT: {
        Serial.printf("[WSc] get text: %s\n", payload);
                
        DynamicJsonBuffer jsonBuffer;
        JsonObject& json = jsonBuffer.parseObject((char*)payload); 
        String deviceId = json ["deviceId"];     
        String action = json ["action"];
        
        if(action == "setPowerState") { // Switch or Light
            String value = json ["value"];
            if(value == "ON") {
                ;
            } else {
                ;
            }
        }
        else if(action == "SetColor") {
            // Alexa, set the device name to red (0) / green (120) / blue (240)
            // get text: {"deviceId":"xxxx","action":"SetColor","value":{"hue":0,"saturation":1,"brightness":1}}
            String hue = json ["value"]["hue"];
            String saturation = json ["value"]["saturation"];
            String brightness = json ["value"]["brightness"];

            Serial.println("[WSc] hue: " + hue);
            Serial.println("[WSc] saturation: " + saturation);
            Serial.println("[WSc] brightness: " + brightness);

            if(hue == "0"){
              ;
            }
            else if(hue == "120"){
              ;
            }
            else if(hue == "240"){
              ;
            }
        }// end SetColor
        
        else if(action == "setBrightness") {
          ;
        }// end brightness
        
        else if(action == "AdjustBrightness") {
          ;
        }
        
        else if (action == "test") {
            Serial.println("[WSc] received test command from sinric.com");
        }
      }
      break;
    case WStype_BIN:
      Serial.printf("[WSc] get binary length: %u\n", length);
      break;
  } 
}

error message:

C:\Users\xanix\AppData\Local\Temp\arduino_build_362415\sketch\Lamp_Alexa.cpp: In member function 'void Lamp_Alexa::init()':

Lamp_Alexa.cpp:13: error: no matching function for call to 'WebSocketsClient::onEvent(<unresolved overloaded function type>)'

   webSocket.onEvent(this->webSocketEvent);

                                         ^

C:\Users\xanix\AppData\Local\Temp\arduino_build_362415\sketch\Lamp_Alexa.cpp:13:41: note: candidate is:

In file included from C:\Users\xanix\AppData\Local\Temp\arduino_build_362415\sketch\Lamp_Alexa.h:11:0,

                 from C:\Users\xanix\AppData\Local\Temp\arduino_build_362415\sketch\Lamp_Alexa.cpp:1:

C:\Users\xanix\Documents\Arduino\libraries\arduinoWebSockets-2.1.1\src/WebSocketsClient.h:66:14: note: void WebSocketsClient::onEvent(WebSocketsClient::WebSocketClientEvent)

         void onEvent(WebSocketClientEvent cbEvent);

              ^

C:\Users\xanix\Documents\Arduino\libraries\arduinoWebSockets-2.1.1\src/WebSocketsClient.h:66:14: note:   no known conversion for argument 1 from '<unresolved overloaded function type>' to 'WebSocketsClient::WebSocketClientEvent {aka std::function<void(WStype_t, unsigned char*, unsigned int)>}'

Lamp_Alexa.cpp:14: error: no matching function for call to 'WebSocketsClient::setAuthorization(const char [7], String&)'

   webSocket.setAuthorization("apikey", _apiKey);

                                               ^

C:\Users\xanix\AppData\Local\Temp\arduino_build_362415\sketch\Lamp_Alexa.cpp:14:47: note: candidates are:

In file included from C:\Users\xanix\AppData\Local\Temp\arduino_build_362415\sketch\Lamp_Alexa.h:11:0,

                 from C:\Users\xanix\AppData\Local\Temp\arduino_build_362415\sketch\Lamp_Alexa.cpp:1:

C:\Users\xanix\Documents\Arduino\libraries\arduinoWebSockets-2.1.1\src/WebSocketsClient.h:82:14: note: void WebSocketsClient::setAuthorization(const char*, const char*)

         void setAuthorization(const char * user, const char * password);

              ^

C:\Users\xanix\Documents\Arduino\libraries\arduinoWebSockets-2.1.1\src/WebSocketsClient.h:82:14: note:   no known conversion for argument 2 from 'String' to 'const char*'

C:\Users\xanix\Documents\Arduino\libraries\arduinoWebSockets-2.1.1\src/WebSocketsClient.h:83:14: note: void WebSocketsClient::setAuthorization(const char*)

         void setAuthorization(const char * auth);

              ^

C:\Users\xanix\Documents\Arduino\libraries\arduinoWebSockets-2.1.1\src/WebSocketsClient.h:83:14: note:   candidate expects 1 argument, 2 provided

Bibliothek arduinoWebSockets-2.1.1 in Version 2.1.1 im Ordner: C:\Users\xanix\Documents\Arduino\libraries\arduinoWebSockets-2.1.1  wird verwendet
Bibliothek ESP8266WiFi in Version 1.0 im Ordner: C:\Users\xanix\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.1\libraries\ESP8266WiFi  wird verwendet
Bibliothek ArduinoJson in Version 5.13.2 im Ordner: C:\Users\xanix\Documents\Arduino\libraries\ArduinoJson  wird verwendet
Bibliothek Adafruit_NeoPixel in Version 1.1.6 im Ordner: C:\Users\xanix\Documents\Arduino\libraries\Adafruit_NeoPixel  wird verwendet
Bibliothek Hash in Version 1.0 im Ordner: C:\Users\xanix\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.1\libraries\Hash  wird verwendet
exit status 1
no matching function for call to 'WebSocketsClient::onEvent(<unresolved overloaded function type>)'

Not a bootloader problem!

void webSocketEvent(WStype_t type, uint8_t * payload, size_t length);

This is not a free function. It is a member function, so the first parameter is always a pointer to the instance. This means that it doesn't match the signature of the callback you're trying to assign it to.

Either make it static, or use std::bind. In the latter case, you have to be very careful that the lifetime of the websocket instance doesn't exceed the lifetime of the callback instance.

Pieter

Sorry but i dont get it. I'm just a newbie writing classes and i cant follow you 100%.

I changed it to a static void: static void Lamp_Alexa::webSocketEvent(WStype_t type, uint8_t * payload, size_t length) and it seem it worked but now i've got a new error message.

error message:

sketch\Lamp_Alexa.cpp: In member function 'void Lamp_Alexa::init()':

Lamp_Alexa.cpp:14: error: no matching function for call to 'WebSocketsClient::setAuthorization(const char [7], String&)'

   webSocket.setAuthorization("apikey", _apiKey);

                                               ^

sketch\Lamp_Alexa.cpp:14:47: note: candidates are:

In file included from sketch\Lamp_Alexa.h:11:0,

                 from sketch\Lamp_Alexa.cpp:1:

C:\Users\xanix\Documents\Arduino\libraries\WebSockets\src/WebSocketsClient.h:81:14: note: void WebSocketsClient::setAuthorization(const char*, const char*)

         void setAuthorization(const char * user, const char * password);

              ^

C:\Users\xanix\Documents\Arduino\libraries\WebSockets\src/WebSocketsClient.h:81:14: note:   no known conversion for argument 2 from 'String' to 'const char*'

C:\Users\xanix\Documents\Arduino\libraries\WebSockets\src/WebSocketsClient.h:82:14: note: void WebSocketsClient::setAuthorization(const char*)

         void setAuthorization(const char * auth);

              ^

C:\Users\xanix\Documents\Arduino\libraries\WebSockets\src/WebSocketsClient.h:82:14: note:   candidate expects 1 argument, 2 provided

sketch\Lamp_Alexa.cpp: At global scope:

Lamp_Alexa.cpp:20: error: cannot declare member function 'static void Lamp_Alexa::webSocketEvent(WStype_t, uint8_t*, size_t)' to have static linkage [-fpermissive]

 static void Lamp_Alexa::webSocketEvent(WStype_t type, uint8_t * payload, size_t length){

                                                                                       ^

In file included from sketch\Lamp_Alexa.cpp:1:0:

sketch\Lamp_Alexa.h: In static member function 'static void Lamp_Alexa::webSocketEvent(WStype_t, uint8_t*, size_t)':

Lamp_Alexa.h:32: error: invalid use of member 'Lamp_Alexa::isConnected' in static member function

     bool isConnected;

          ^

Lamp_Alexa.cpp:23: error: from this location

       isConnected = false;    

       ^

In file included from sketch\Lamp_Alexa.cpp:1:0:

Lamp_Alexa.h:32: error: invalid use of member 'Lamp_Alexa::isConnected' in static member function

     bool isConnected;

          ^

Lamp_Alexa.cpp:27: error: from this location

       isConnected = true;

       ^

exit status 1
no matching function for call to 'WebSocketsClient::setAuthorization(const char [7], String&)'

in this section:

void Lamp_Alexa::init(){
  // server address, port and URL
  webSocket.begin("iot.sinric.com", 80, "/");

  // event handler
  webSocket.onEvent(this->webSocketEvent);
  webSocket.setAuthorization("apikey", _apiKey);
  
  // try again every 5000ms if connection has failed
  webSocket.setReconnectInterval(5000);
}
webSocket.setAuthorization("apikey", _apiKey);

Why is _apiKey a String? Just change it to a const char *. I find it very unlikely that your username is "apikey", but I could be wrong, I've never used Alexa.

webSocket.onEvent(this->webSocketEvent);

Not sure if that compiles or not, but even if it does, it doesn't reflect what you're doing. Don't call static class methods from an instance pointer.

Going back to your original issue - if making the method static isn't an option because it's interacting with instance-scoped data/methods/variables, i believe this is the syntax to handle calling a member function as the handler for WebSocketClient::onEvent. (I'm away from my full dev environment ATM and not able to 100% verify)

webSocket.onEvent([&](WStype_t t, uint8_t * p, size_t l) {
    webSocketEvent(t, p, l);
  });

Where webSocket is your instance of WebSocketClient, and webSocketEvent() is an instance method of your class (presumably Lamp::Alexa) with the proper signature that WebSocketClientEvent expects. Basically what you're doing here is popping an anonymous function into existence, and
delegating to your other instance method.

Good Luck.