diff --git a/DccMQTT.cpp b/DccMQTT.cpp index dd2bb3a..62e3037 100644 --- a/DccMQTT.cpp +++ b/DccMQTT.cpp @@ -37,16 +37,20 @@ #include #include #include +#include //--------- // Variables //--------- +DccMQTT DccMQTT::singleton; +auto mqtt = DccMQTT::get(); + char topicName[MAXTBUF]; char topicMessage[MAXTMSG]; // char keyword[MAX_KEYWORD_LENGTH]; -DccMQTT DccMQTT::singleton; + /** * @brief Copies an byte array to a hex representation as string; used for generating the unique Arduino ID @@ -73,8 +77,21 @@ void mqttCallback(char *topic, byte *payload, unsigned int length) topicName[0] = '\0'; topicMessage[0] = '\0'; strcpy(topicName, topic); - strlcpy(topicMessage, (char *)payload, length + 1); - DIAG(F("MQTT Message arrived [%s]: [%s]"), topicName, topicMessage); + + auto pool = mqtt->getPool(); + auto q = mqtt->getIncomming(); + + csmsg_t tm; + strlcpy(tm.cmd, (char *)payload, length + 1); + // Add the recieved command to the pool + int idx = pool->setItem(tm); + if ( idx == -1) { + DIAG(F("MQTT Command pool full. Could not handle recieved command.")); + return; + } + // Add the index of the pool item to the incomming queue + q->push(idx); + DIAG(F("MQTT Message arrived [%s]: [%s]"), topicName, tm.cmd); } /** diff --git a/DccMQTT.h b/DccMQTT.h index 1564852..ee23d86 100644 --- a/DccMQTT.h +++ b/DccMQTT.h @@ -14,6 +14,7 @@ #include #include #include +#include #define MAXPAYLOAD 64 #define MAXDOMAINLENGTH 32 @@ -78,10 +79,9 @@ struct MQTTBroker }; }; -struct DccMQTTMsg -{ - char payload[MAXPAYLOAD]; -}; +typedef struct csmsg_t { + char cmd[MAXPAYLOAD]; +} csmsg_t; enum DccMQTTState { @@ -107,8 +107,9 @@ private: PubSubClient mqttClient; // PubSub Endpoint for data exchange MQTTBroker *broker; // Broker configuration object as set in config.h - Queue in; - Queue out; + ObjectPool pool; + Queue in; + Queue out; char clientID[(CLIENTIDSIZE*2)+1]; @@ -124,6 +125,11 @@ public: bool isConnected() { return mqState == CONNECTED; }; void setState(DccMQTTState s) { mqState = s; }; + ObjectPool *getPool() { return &pool; }; + Queue *getIncomming() { return ∈ }; + Queue *getOutgoing() { return &out; }; + + void setup(); // called at setup in the main ino file void loop(); diff --git a/ObjectPool.h b/ObjectPool.h new file mode 100644 index 0000000..5149a54 --- /dev/null +++ b/ObjectPool.h @@ -0,0 +1,91 @@ +#ifndef _ObjectPool_h_ +#define _ObjectPool_h_ + +#include + +#define MAXPOOLSIZE 32 + +template +class ObjectPool +{ + + // just make sure that we don't create a pool eating up all memory @compiletime + static_assert(length <= MAXPOOLSIZE); + + struct item + { + T i; + bool free = true; // boolean 1 free i.e. i can be reused; 0 occupied + }; + +private: + item p[length]; // MAXPOOLSIZE items of struct item + const int size = length; // size of the pool + + int findFreeIdx() + { // find the first free index or return -1 if there is none + for (int i = 0; i < length; i++) + { + if (p[i].free) + { + return i; + } + } + return -1; // if we are here there is no free slot available + } + +public: + int setItem(T i) + { // add an item to the pool at a free slot + int idx = findFreeIdx(); + if (idx != -1) + { + p[idx].i = i; + p[idx].free = false; + } + return idx; + } + + /** + * @brief returns the slot for an object to the pool i.e. frees the slot for reuse of the data member and + * clears out the memory + * + * @param idx + * @return true if the return is ok + * @return false otherwise + */ + bool returnItem(int idx) + { // clear item at pool index idx + if (idx > size) + { // can't return an item outside of the pool size; returns false; + return false; + } + memset(&p[idx].i, 0, sizeof(T)); // clear out the memory but keep the allocation for reuse + p[idx].free = true; + return true; // set the free flag + } + + /** + * @brief Obtain a pool item + * @note This should only be used for debugging. + * It allows to change actually the content of the pool item where this should only be allowed for the setItem method. + * @param idx Index of the pool item to retrieve + * @param state State of the pool item ( 1 available, 0 occupied) + * @return T* returns the pointer to the pool item + */ + T *getItem(int idx, bool *state) + { + *state = p[idx].free; + return &p[idx].i; + } + + int getSize() + { + return size; + } + + ObjectPool() = default; + ~ObjectPool() = default; +}; + +#endif \ No newline at end of file