#pragma once #define DEBUGLOG_DEFAULT_LOG_LEVEL_DEBUG #include #include #include #include #include #include #include #include class MQTTwrapper { public: using Topic = std::string; using Message = std::string; using MessageCallback = std::function; using ActionCallback = std::function; // the actions receive a JsonObject containing the received message using StateChangeCallback = std::function; using ActionMap = std::map; private: const std::map stateMap = { {-4, "MQTT_CONNECTION_TIMEOUT"}, {-3, "MQTT_CONNECTION_LOST"}, {-2, "MQTT_CONNECT_FAILED"}, {-1, "MQTT_DISCONNECTED"}, {0, "MQTT_CONNECTED"}, {1, "MQTT_CONNECT_BAD_PROTOCOL"}, {2, "MQTT_CONNECT_BAD_CLIENT_ID"}, {3, "MQTT_CONNECT_UNAVAILABLE"}, {4, "MQTT_CONNECT_BAD_CREDENTIALS"}, {5, "MQTT_CONNECT_UNAUTHORIZED"}}; private: static MQTTwrapper * getInstance(MQTTwrapper *inst = nullptr) { static std::unique_ptr m_instance; if (inst) m_instance.reset(inst); if (m_instance) return m_instance.get(); return nullptr; } public: MQTTwrapper(); ~MQTTwrapper(); const bool connect(); const bool disconnect(); const bool connected(); const bool subscribe(const Topic &topic, const ActionCallback action); const bool unsubscribe(const Topic &topic); const bool publish(const Topic &topic, const ArduinoJson::JsonDocument obj); void setOnMessageCb(MessageCallback cb); void setOnPublishCb(MessageCallback cb); private: static void callback(char *topic, uint8_t *payload, unsigned int length); // C-style callback only to invoke onMessage void onMessage(const std::string topic, const std::string message); // infinite loop to call the client loop method in a taskHandle static void clientLoop(void *params); private: const Config &m_config; ActionMap m_actionMap; NetworkClient m_tcp; PubSubClient m_client; TaskHandle_t m_loopHandle; MessageCallback m_onPublish; MessageCallback m_onReceive; };