From e721577bb2cdf288a7e88f8702a5a8b6314f9425 Mon Sep 17 00:00:00 2001 From: Greg Hormann Date: Fri, 10 Jan 2025 20:12:29 -0500 Subject: [PATCH] API to dump MosquittoClient:messageCache (#2115) * API to dump MosquittoClient:messageCache Add /api/fppd/mqtt/cache which will dump all the values of MosquittoClient:messageCache. This is intended for debugging, but could be used by Plugins to access cached MQTT topics Closes #2098 --- src/httpAPI.cpp | 50 ++++++++++++++++++++++++------------------ src/mqtt.cpp | 9 ++++++++ src/mqtt.h | 8 +++---- www/api/endpoints.json | 17 ++++++++++++-- 4 files changed, 56 insertions(+), 28 deletions(-) diff --git a/src/httpAPI.cpp b/src/httpAPI.cpp index e91e17a32..b8bc5df5b 100644 --- a/src/httpAPI.cpp +++ b/src/httpAPI.cpp @@ -15,8 +15,8 @@ #ifdef PLATFORM_OSX #include #else +#include #include -#include #endif #include @@ -307,18 +307,17 @@ void LogResponse(const http_request& req, int responseCode, const std::string& c } } - PlayerResource::PlayerResource() { -#ifdef PLATFORM_PI - #define DEVICE_FILE_NAME "/dev/vcio" - #define MAJOR_NUM 100 - #define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) - #define MAX_STRING 1024 - #define GET_GENCMD_RESULT 0x00030080 +#ifdef PLATFORM_PI +#define DEVICE_FILE_NAME "/dev/vcio" +#define MAJOR_NUM 100 +#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char*) +#define MAX_STRING 1024 +#define GET_GENCMD_RESULT 0x00030080 piPowerFile = open(DEVICE_FILE_NAME, 0); #else - piPowerFile = -1; -#endif + piPowerFile = -1; +#endif } PlayerResource::~PlayerResource() { if (piPowerFile > 0) { @@ -403,6 +402,15 @@ HTTP_RESPONSE_CONST std::shared_ptr PlayerResource::r SetOKResult(result, ""); } else if (url == "sequence") { LogDebug(VB_HTTP, "API - Getting list of running sequences\n"); + } else if (url == "mqtt/cache") { + LogDebug(VB_HTTP, "API - Getting MQTT Cached data\n"); + if (mqtt) { + mqtt->dumpMessageCache(result); + } else { + result["Status"] = "ERROR"; + result["respCode"] = 400; + result["Message"] = "Mqtt not Initialized"; + } } else { LogErr(VB_HTTP, "API - Error unknown GET request: %s\n", url.c_str()); @@ -858,24 +866,24 @@ void PlayerResource::PostSchedule(const Json::Value data, Json::Value& result) { void PlayerResource::periodicWork() { if (piPowerFile > 0) { - #ifdef PLATFORM_PI +#ifdef PLATFORM_PI int i = 0; - int32_t p[(MAX_STRING>>2) + 7]; - p[i++] = 0; // size + int32_t p[(MAX_STRING >> 2) + 7]; + p[i++] = 0; // size p[i++] = 0x00000000; // process request p[i++] = GET_GENCMD_RESULT; // (the tag id) - p[i++] = MAX_STRING;// buffer_len - p[i++] = 0; // request_len (set to response length) - p[i++] = 0; // error repsonse + p[i++] = MAX_STRING; // buffer_len + p[i++] = 0; // request_len (set to response length) + p[i++] = 0; // error repsonse - memcpy(p+i, "get_throttled", strlen("get_throttled") + 1); + memcpy(p + i, "get_throttled", strlen("get_throttled") + 1); i += MAX_STRING >> 2; - p[i++] = 0x00000000; // end tag - p[0] = i*sizeof *p; // actual size + p[i++] = 0x00000000; // end tag + p[0] = i * sizeof *p; // actual size int ret_val = ioctl(piPowerFile, IOCTL_MBOX_PROPERTY, p); - std::string s = (char *)&p[6]; + std::string s = (char*)&p[6]; if (s.starts_with("throttled=0x")) { s = s.substr(12); uint32_t res = std::stol(s, nullptr, 16); @@ -890,7 +898,7 @@ void PlayerResource::periodicWork() { piPowerWarningCount = 0; } } - #endif +#endif } } diff --git a/src/mqtt.cpp b/src/mqtt.cpp index 56087f334..f932bb262 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -460,3 +460,12 @@ bool MosquittoClient::CacheCheckMessage(std::string& topic, std::string& message return false; } + +void MosquittoClient::dumpMessageCache(Json::Value& result) { + // NOTE: This assumes that result is an Array + std::unique_lock lock(messageCacheLock); + + for (const auto& pair : messageCache) { + result[pair.first] = pair.second; + } +} \ No newline at end of file diff --git a/src/mqtt.h b/src/mqtt.h index 00829824f..fc39c1aaa 100644 --- a/src/mqtt.h +++ b/src/mqtt.h @@ -17,8 +17,8 @@ #include #include -#include "Warnings.h" #include "Events.h" +#include "Warnings.h" #include "mosquitto.h" @@ -29,20 +29,17 @@ class MosquittoClient : public EventHandler { int Init(const std::string& username, const std::string& password, const std::string& ca_file); - virtual bool Publish(const std::string &topic, const std::string &data) override; + virtual bool Publish(const std::string& topic, const std::string& data) override; virtual bool Publish(const std::string& subTopic, const int valueconst) override; virtual void RegisterCallback(const std::string& topic) override; virtual void RemoveCallback(const std::string& topic) override; - virtual void PrepareForShutdown() override; int PublishRaw(const std::string& topic, const std::string& msg, const bool retain = false, const int qos = 1); int Publish(const std::string& subTopic, const std::string& msg, const bool retain, const int qos = 1); int Publish(const std::string& subTopic, const int valueconst, bool retain, const int qos = 1); - - void LogCallback(void* userdata, int level, const char* str); void MessageCallback(void* obj, const struct mosquitto_message* message); @@ -54,6 +51,7 @@ class MosquittoClient : public EventHandler { void CacheSetMessage(std::string& topic, std::string& message); bool CacheCheckMessage(std::string& topic, std::string& message); + void dumpMessageCache(Json::Value& result); std::string GetBaseTopic() { return m_baseTopic; } diff --git a/www/api/endpoints.json b/www/api/endpoints.json index d2ff18da0..92ceae98f 100644 --- a/www/api/endpoints.json +++ b/www/api/endpoints.json @@ -628,7 +628,20 @@ } } }, - { + { + "endpoint": "fppd/mqtt/cache", + "fppd": true, + "methods": { + "GET": { + "desc": "Returns a JSON map of the cached MQTT topic and values that were captured from the 'Subscribe Topic' setting. Note: value is always stored internally as a string.", + "output": { + "/christmas/tag1": "true", + "/christmas/tag2": "12345" + } + } + } + }, + { "endpoint": "fppd/multiSyncStats", "fppd": true, "methods": { @@ -3013,4 +3026,4 @@ } } ] -} \ No newline at end of file +}