ESP8266 MQTT Publications

The PlanIn my last blog I referred to publishing temperature etc and there is one issue with the existing MQTT library that makes that an issue: The MQTT publications are not queued.

For the benefit of anyone still not into the MQTT thing – by publications I mean “sending a message” comprising a topic and a message. The topic might be “BathroomTemperatureReading” and the message might be “20.6”.

What happens right now – and Tuan has said he’ll fix this… if you send 2 messages out in a row IMMEDIATELY after each other – only the last one will go. Well, that’s fine unless you have to send one message off to a thermometer display and another message off to a humidity display.

So… this evening I wrote a queue. This is possible because of a “callback routine”. When you fire a message off it is handled in the background and when it’s done it calls an empty routine. I’ve trapped that.. the basic idea is this.  

Clear a “done” flag at the start and from there on..

If the done flag is clear, set it and send out a publication. If it is NOT clear, put the message in a queue.

In the callback routine, clear the flag – check a queue, if there is anything to go – send out the publication.

Simple really.

So here’s the code I’ve added to the start of the MQTT package..

#define QUEMAX 10  // 10 messages -  need more? – increase
#define QUESIZE 50 // my topics and messages are never more than 50 chars
struct Queues{
    MQTT_Client* cli;
    char top[QUESIZE];
    char mes[QUESIZE];
};

struct Queues myQueue[QUEMAX];

int queuein=0;
int queueout=0;
int isPublished=0; // my flag to see if I can publish or need to put in a queue

All simple enough – the queue can be maximum 10 deep (it’s rotary – when I get to the end I roll around to the start). I save the client pointer, the topic text and the message text in an array of simple structs.

At the beginning both the in pointer and out pointers for the queue are cleared and isPublished is clear.

Instead of the main publish routine – I have my own – which checks the flag before sending off a message.

void petesPub(MQTT_Client* cli, char *top, char *mes)
{
if (isPublished==0)    { isPublished=1; MQTT_Publish(cli, top,mes,strlen(mes), 0, 0); }
else
    {
    myQueue[queuein].cli=cli;
    strcpy(myQueue[queuein].top,top);
    strcpy(myQueue[queuein].mes,mes);
    if (++queuein>=QUEMAX) queuein=0;
    }
}

You can see the message going in the queue unless the flag is clear… and in the callback routine, called when a message has gone…

void mqttPublishedCb(uint32_t *args)
{
    MQTT_Client* client = (MQTT_Client*)args;
    INFO("MQTT: Published\r\n");
    isPublished=0;
    if (queuein!=queueout)
    {
        petesPub(myQueue[queueout].cli,myQueue[queueout].top,myQueue[queueout].mes);
        if (++queueout>=QUEMAX) queueout=0;
    }
}

The first two lines were there already – I don’t think I actually need to store the client info – I think it gets passed – however – what I have works for now.

So you can see I clear the published flag, look to see if there is anything in the queue and if there is – publish it. I’m sure there’s a bit of recursion going on there – but it all works.

And that’s me done for the day. Meetings again this week so I’ll not get much more done now until the weekend but DHT22, RTC and message queue – not a bad start for the week.

I’m still begging anyone with assembly skills to look at the WS2812B code to see if they can make an accurate job of it Smile