Skip to content
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

PicoMQTT Server - on connect, on subscribe #41

Closed
andrzejbluszcz opened this issue Jul 4, 2024 · 13 comments
Closed

PicoMQTT Server - on connect, on subscribe #41

andrzejbluszcz opened this issue Jul 4, 2024 · 13 comments

Comments

@andrzejbluszcz
Copy link

Hi!
How to know what are current subscriptions? Or, does Server notify about a new connection/subscription?

Thank you.

@mlesniew
Copy link
Owner

mlesniew commented Jul 5, 2024

You can subclass PicoMQTT::Server and override on_connected and on_subscribe, see:

@andrzejbluszcz
Copy link
Author

Thank you for the suggestion. I wish I knew C++ enough to make it.
I see that in server.h the functins on_connected() and on_subscribe() are declared only. There are apparently no definitions for them in server.cpp.
Does that mean that I should write those to suit my purpose?

@mlesniew
Copy link
Owner

mlesniew commented Jul 7, 2024

No, on_connected and on_subscribe are both declared and defined in server.h, but their bodies are empty (note the {} after the function names).

Here's how you can override these functions and add a custom logic when a client connects or subscribes to a topic:

class CustomMQTTServer: public PicoMQTT::Server {
    protected:
        virtual void on_connected(const char * client_id) override {
            Serial.println("A new client connected");
        }

        virtual void on_subscribe(const char * client_id, const char * topic) override {
            Serial.println("A client set up a new subscription");
        }
};

CustomMQTTServer mqtt;

void setup() {
    Serial.begin(115200);
    mqtt.begin();
}

void loop() {
    mqtt.loop();
}

You can override any other function marked virtual in the same way.

@andrzejbluszcz
Copy link
Author

Thank you very much for your help and patience. I think that closes the issue.

mhaberler pushed a commit to mhaberler/PicoMQTT that referenced this issue Jul 8, 2024
@mhaberler
Copy link

@mlesniew would you mind giving this a try? the above seems not to work for me

master...mhaberler:PicoMQTT:custom-server-example

@mhaberler
Copy link

I stumbled on some c++ compiler issue - see updated example with devkit-c config from previous post
this conatins a bleeding-edge Arduino platfrom and toolchain as per below:

Executing task: platformio run --environment custom-server-devkitc 

Processing custom-server-devkitc (platform: https://github.com/Jason2866/platform-espressif32/releases/download/2024.07.20/platform-espressif32.zip; board: esp32-s3-devkitc-1-32MB-8MB; framework: arduino)
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32-s3-devkitc-1-32MB-8MB.html
PLATFORM: Espressif 32 (2024.7.20) > Espressif ESP32-S3-DevKitC-2-opi
HARDWARE: ESP32S3 240MHz, 320KB RAM, 32MB Flash
DEBUG: Current (esp-builtin) On-board (esp-builtin) External (cmsis-dap, esp-bridge, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES: 
 - framework-arduinoespressif32 @ 3.0.2+sha.01c738d 
 - tool-esptoolpy @ 4.7.5 
 - tool-mklittlefs @ 3.2.0 
 - tool-openocd-esp32 @ 2.1100.20220706 (11.0) 
 - tool-riscv32-esp-elf-gdb @ 12.1.0+20221002 
 - tool-xtensa-esp-elf-gdb @ 12.1.0+20221002 
 - toolchain-riscv32-esp @ 13.2.0+20230928 
 - toolchain-xtensa-esp-elf @ 13.2.0+20230928
Converting custom_server.ino
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 28 compatible libraries
Scanning dependencies...
Dependency Graph
|-- PicoMQTT @ 0.3.8
Building in debug mode
Compiling .pio/build/custom-server-devkitc/src/custom_server.ino.cpp.o
Compiling .pio/build/custom-server-devkitc/lib932/PicoMQTT/PicoMQTT/connection.cpp.o
Compiling .pio/build/custom-server-devkitc/lib932/PicoMQTT/PicoMQTT/server.cpp.o
Compiling .pio/build/custom-server-devkitc/FrameworkArduino/FunctionalInterrupt.cpp.o
Compiling .pio/build/custom-server-devkitc/FrameworkArduino/HEXBuilder.cpp.o
Compiling .pio/build/custom-server-devkitc/FrameworkArduino/HWCDC.cpp.o
Compiling .pio/build/custom-server-devkitc/FrameworkArduino/HardwareSerial.cpp.o
Compiling .pio/build/custom-server-devkitc/FrameworkArduino/IPAddress.cpp.o
Compiling .pio/build/custom-server-devkitc/FrameworkArduino/MD5Builder.cpp.o
Compiling .pio/build/custom-server-devkitc/FrameworkArduino/MacAddress.cpp.o
Compiling .pio/build/custom-server-devkitc/FrameworkArduino/Print.cpp.o
Compiling .pio/build/custom-server-devkitc/FrameworkArduino/SHA1Builder.cpp.o
Compiling .pio/build/custom-server-devkitc/FrameworkArduino/Stream.cpp.o
Compiling .pio/build/custom-server-devkitc/FrameworkArduino/StreamString.cpp.o
lib/PicoMQTT/src/PicoMQTT/connection.cpp: In member function 'void PicoMQTT::Connection::wait_for_reply(PicoMQTT::Packet::Type, std::function<void(PicoMQTT::IncomingPacket&)>)':
lib/PicoMQTT/src/PicoMQTT/connection.cpp:67:24: error: cannot declare variable 'packet' to be of abstract type 'PicoMQTT::IncomingPacket'
   67 |         IncomingPacket packet(client);
      |                        ^~~~~~
In file included from lib/PicoMQTT/src/PicoMQTT/connection.h:8,
                 from lib/PicoMQTT/src/PicoMQTT/connection.cpp:2:
lib/PicoMQTT/src/PicoMQTT/incoming_packet.h:10:7: note:   because the following virtual functions are pure within 'PicoMQTT::IncomingPacket':
   10 | class IncomingPacket: public Packet, public Client {
      |       ^~~~~~~~~~~~~~
In file included from /Users/mah/.platformio/packages/framework-arduinoespressif32@src-c38c877b286c4329f2d3ff62747e7f12/cores/esp32/Arduino.h:197,
                 from lib/PicoMQTT/src/PicoMQTT/connection.h:5:
/Users/mah/.platformio/packages/framework-arduinoespressif32@src-c38c877b286c4329f2d3ff62747e7f12/cores/esp32/Client.h:29:15: note:     'virtual int Client::connect(IPAddress, uint16_t, int32_t)'
   29 |   virtual int connect(IPAddress ip, uint16_t port, int32_t timeout) = 0;
      |               ^~~~~~~
/Users/mah/.platformio/packages/framework-arduinoespressif32@src-c38c877b286c4329f2d3ff62747e7f12/cores/esp32/Client.h:31:15: note:     'virtual int Client::connect(const char*, uint16_t, int32_t)'
   31 |   virtual int connect(const char *host, uint16_t port, int32_t timeout) = 0;
      |               ^~~~~~~
lib/PicoMQTT/src/PicoMQTT/connection.cpp: In member function 'virtual void PicoMQTT::Connection::loop()':
lib/PicoMQTT/src/PicoMQTT/connection.cpp:171:24: error: cannot declare variable 'packet' to be of abstract type 'PicoMQTT::IncomingPacket'
  171 |         IncomingPacket packet(client);
      |                        ^~~~~~
*** [.pio/build/custom-server-devkitc/lib932/PicoMQTT/PicoMQTT/connection.cpp.o] Error 1
lib/PicoMQTT/src/PicoMQTT/server.cpp: In member function 'virtual void PicoMQTT::BasicServer::Client::on_message(const char*, PicoMQTT::IncomingPacket&)':
lib/PicoMQTT/src/PicoMQTT/server.cpp:133:25: error: cannot declare variable 'incoming_publish' to be of abstract type 'PicoMQTT::BasicServer::IncomingPublish'
  133 |         IncomingPublish incoming_publish(packet, publish);
      |                         ^~~~~~~~~~~~~~~~
In file included from lib/PicoMQTT/src/PicoMQTT/server.cpp:3:
lib/PicoMQTT/src/PicoMQTT/server.h:55:15: note:   because the following virtual functions are pure within 'PicoMQTT::BasicServer::IncomingPublish':
   55 |         class IncomingPublish: public IncomingPacket {
      |               ^~~~~~~~~~~~~~~
In file included from /Users/mah/.platformio/packages/framework-arduinoespressif32@src-c38c877b286c4329f2d3ff62747e7f12/cores/esp32/Arduino.h:197,
                 from lib/PicoMQTT/src/PicoMQTT/server.h:6:
/Users/mah/.platformio/packages/framework-arduinoespressif32@src-c38c877b286c4329f2d3ff62747e7f12/cores/esp32/Client.h:29:15: note:     'virtual int Client::connect(IPAddress, uint16_t, int32_t)'
   29 |   virtual int connect(IPAddress ip, uint16_t port, int32_t timeout) = 0;
      |               ^~~~~~~
/Users/mah/.platformio/packages/framework-arduinoespressif32@src-c38c877b286c4329f2d3ff62747e7f12/cores/esp32/Client.h:31:15: note:     'virtual int Client::connect(const char*, uint16_t, int32_t)'
   31 |   virtual int connect(const char *host, uint16_t port, int32_t timeout) = 0;
      |               ^~~~~~~
*** [.pio/build/custom-server-devkitc/lib932/PicoMQTT/PicoMQTT/server.cpp.o] Error 1
=================================================================================== [FAILED] Took 2.83 seconds ===================================================================================

Environment            Status    Duration
---------------------  --------  ------------
custom-server-devkitc  FAILED    00:00:02.825

@mlesniew
Copy link
Owner

From the build log it looks like you're not using the latest PicoMQTT version. Can you check if this also happens with version 1.1.1?

@mhaberler
Copy link

yes, sorry about that - switching to 1.1.1 adressed the first question

build succeeds with the 8.4 toolchain brought by platform = espressif32@6.7.0

PACKAGES: 
 - framework-arduinoespressif32 @ 3.20016.0 (2.0.16) 
 - tool-esptoolpy @ 1.40501.0 (4.5.1) 
 - tool-openocd-esp32 @ 2.1100.20220706 (11.0) 
 - toolchain-riscv32-esp @ 8.4.0+2021r2-patch5 
 - toolchain-xtensa-esp32s3 @ 8.4.0+2021r2-patch5

second issue still remains
but that is likely my low C++ fu - trying the (unsupported) platform package

platform = https://github.com/Jason2866/platform-espressif32/releases/download/2024.07.20/platform-espressif32.zip

brings in the 13.2.0 toolchain which seems to be more picky:

PACKAGES: 
 - framework-arduinoespressif32 @ 3.0.2+sha.01c738d 
 - tool-esptoolpy @ 4.7.5 
 - tool-mklittlefs @ 3.2.0 
 - tool-openocd-esp32 @ 2.1100.20220706 (11.0) 
 - tool-riscv32-esp-elf-gdb @ 12.1.0+20221002 
 - tool-xtensa-esp-elf-gdb @ 12.1.0+20221002 
 - toolchain-riscv32-esp @ 13.2.0+20230928 
 - toolchain-xtensa-esp-elf @ 13.2.0+20230928
In file included from lib/PicoMQTT/src/PicoMQTT/client.h:5,
                 from lib/PicoMQTT/src/PicoMQTT.h:19,
                 from /Users/mah/Ballon/src/BalloonWare/networking/PicoMQTT/examples/custom_server/custom_server.ino:5:
lib/PicoMQTT/src/PicoMQTT/connection.h:64:23: error: cannot declare field 'PicoMQTT::Connection::client' to be of abstract type 'PicoMQTT::ClientWrapper'
   64 |         ClientWrapper client;
      |                       ^~~~~~
In file included from lib/PicoMQTT/src/PicoMQTT/connection.h:8:
lib/PicoMQTT/src/PicoMQTT/client_wrapper.h:7:7: note:   because the following virtual functions are pure within 'PicoMQTT::ClientWrapper':
    7 | class ClientWrapper: public ::Client {
      |       ^~~~~~~~~~~~~

not sure it's worth investigating, I'd just like to understand why

@mhaberler
Copy link

that was too quick: with v1.1.1 and platform = espressif32@6.7.0 the example builds

however the callbacks are NOT executed

@mlesniew
Copy link
Owner

Try replacing
CustomMQTTServer::Server mqtt;

With
CustomMQTTServer mqtt;

mhaberler pushed a commit to mhaberler/PicoMQTT that referenced this issue Jul 10, 2024
@mhaberler
Copy link

that did it, sorry for the snafu

@mhaberler
Copy link

would you mind sketching how this would work in the multi_server example?

the subclassing as suggested above doesnt work in this case, looks like advanced templatology is required if I try like so:

CustomMQTTServer mqtt(mqtt_tcp_server, websocket_server);

 Compiling .pio/build/custom-server-devkitc/src/custom_server.ino.cpp.o
/Users/mah/Ballon/src/BalloonWare/networking/PicoMQTT/examples/custom_server/custom_server.ino:41:56: error: no matching function for call to 'CustomMQTTServer::CustomMQTTServer(WiFiServer&, WiFiServer&)'
 CustomMQTTServer mqtt(mqtt_tcp_server, websocket_server);
                                                        ^
/Users/mah/Ballon/src/BalloonWare/networking/PicoMQTT/examples/custom_server/custom_server.ino:20:7: note: candidate: 'CustomMQTTServer::CustomMQTTServer()'
 class CustomMQTTServer: public PicoMQTT::Server {
       ^~~~~~~~~~~~~~~~
/Users/mah/Ballon/src/BalloonWare/networking/PicoMQTT/examples/custom_server/custom_server.ino:20:7: note:   candidate expects 0 arguments, 2 provided
/Users/mah/Ballon/src/BalloonWare/networking/PicoMQTT/examples/custom_server/custom_server.ino:20:7: note: candidate: 'CustomMQTTServer::CustomMQTTServer(CustomMQTTServer&&)'
/Users/mah/Ballon/src/BalloonWare/networking/PicoMQTT/examples/custom_server/custom_server.ino:20:7: note:   candidate expects 1 argument, 2 provided
*** [.pio/build/custom-server-devkitc/src/custom_server.ino.cpp.o] Error 1

@mlesniew
Copy link
Owner

Sorry, I missed this question before.

There reason it's not working is that CustomMQTTServer doesn't have any constructor defined. This makes the compiler create a constructor automatically, which calls the default constructor ofPicoMQTT::Server.

To make CustomMQTTServer inherit its parent's constructors, we have to explicitly request it with the using keyword like this:

class CustomMQTTServer: public PicoMQTT::Server {

    using  PicoMQTT::Server::Server;
    ...
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants