adafruit / Adafruit_MQTT_Library

Arduino library for MQTT support
MIT License
573 stars 291 forks source link

subscription problem using readSubscription function (SOLVED) #76

Open lorenbis opened 7 years ago

lorenbis commented 7 years ago

I'm using a nodeMCU board and I tried to subscribe a MQTT topic by using the "readSubscription" function from this library. Everything works fine if the mqtt packet length does not exceed 127 byte. In case of longer packet I got NULL from the function. Debugging the readSubscription function I saw that it looks for the topic length (the topiclen variable) into the forth cell of the array, called "buffer", (buffer[3]). It is like this only if the packet lenght is less than 127 byte. Whereas if it is longer, the mqtt broker adds further bytes to code the overall packet lenght, so that the "topiclen" field is no more in the forth cell of the acquired "buffer" but it results in one of the next cells of the array. To solve this problem I made some changes in the readFullPacket function that is called by the readSubscription function to acquire the new packet from the mqtt broker.
This is the code of the function:

uint16_t Adafruit_MQTT::readFullPacket(uint8_t buffer, uint16_t maxsize, uint16_t timeout) { // will read a packet and Do The Right Thing with length uint8_t pbuff = buffer; uint8_t rlen; // read the packet type: rlen = readPacket(pbuff, 1, timeout); if (rlen != 1) return 0; DEBUG_PRINT(F("Packet Type:\t")); DEBUG_PRINTBUFFER(pbuff, rlen); pbuff++;

uint32_t value = 0; uint32_t multiplier = 1; uint8_t encodedByte;

do { rlen = readPacket(pbuff, 1, timeout); if (rlen != 1) return 0; encodedByte = pbuff[0]; // save the last read val pbuff++; // get ready for reading the next byte uint32_t intermediate = encodedByte & 0x7F; intermediate = multiplier; value + = intermediate; multiplier = 128; if (multiplier > (128UL 128UL 128UL)) { DEBUG_PRINT(F("Malformed packet len\n")); return 0; } } while (encodedByte & 0x80);

DEBUG_PRINT(F("Packet Length:\t")); DEBUG_PRINTLN(value);

*_if (multiplier == (128UL 128UL)) pbuff --;
else if (multiplier == (128UL 128UL 128UL)) pbuff -=2;_**

if (value > (maxsize - (pbuff-buffer) - 1)) { DEBUG_PRINTLN(F("Packet too big for buffer")); rlen = readPacket(pbuff, (maxsize - (pbuff-buffer) - 1), timeout); } else { rlen = readPacket(pbuff, value, timeout); } //DEBUG_PRINT(F("Remaining packet:\t")); DEBUG_PRINTBUFFER(pbuff, rlen);

return ((pbuff - buffer)+rlen); }

The lines I added are the two lines in bold italic. In other words I overwrite the extra bytes that the mqtt broker adds to code the packet lenght so that the packet header keep always the same lenght and the "topiclen" field is always in the forth cell of the buffer (buffer[3]). This is possible since the overall packet length is one of the output of the readSubscription function and thus it has not to be recomputed.

In this way it works even if the packet is longer than 127 bytes.