hirotakaster / MQTT

MQTT for Photon, Spark Core
Other
216 stars 118 forks source link

Can't write data payloads larger than 255 bytes #24

Closed fathym closed 8 years ago

fathym commented 8 years ago

In MQTT.h there is:

// MQTT_MAX_PACKET_SIZE : Maximum packet size
#define MQTT_MAX_PACKET_SIZE 128

You can increase this to increase the maximum packet size. On a Particle Photon you might want to send a much bigger payload. However values above 255 fail to work.

In the MQTT.cpp in there is:

bool MQTT::write(uint8_t header, uint8_t* buf, uint16_t length) {
    uint8_t lenBuf[4];
    uint8_t llen = 0;
    uint8_t digit;
    uint8_t pos = 0;
    uint8_t rc;
    uint8_t len = length;
    do {
        digit = len % 128;
        len = len / 128;
        if (len > 0) {
            digit |= 0x80;
        }
        lenBuf[pos++] = digit;
        llen++;
    } while(len > 0);

    buf[4-llen] = header;
    for (int i = 0; i < llen; i++) {
        buf[5-llen+i] = lenBuf[i];
    }
    rc = _client->write(buf+(4-llen), length+1+llen);

    lastOutActivity = millis();
    return (rc == 1+llen+length);
}

The method argument length is of type uint16_t in the function signature. However when the local variable len is of type uint8_t. The length type is reduced from a 16 bit value to an 8 bit value and length precision above 255 is lost on this line:

uint8_t len = length;

I was able to send data packets greater than 255 bytes on the Photon by changing all of the method's local variable types from uint8_t to uint16_t like this:

bool MQTT::write(uint8_t header, uint8_t* buf, uint16_t length) {
    uint16_t lenBuf[4];
    uint16_t llen = 0;
    uint16_t digit;
    uint16_t pos = 0;
    uint16_t rc;
    uint16_t len = length;
    do {
        digit = len % 128;
        len = len / 128;
        if (len > 0) {
            digit |= 0x80;
        }
        lenBuf[pos++] = digit;
        llen++;
    } while(len > 0);

    buf[4-llen] = header;
    for (int i = 0; i < llen; i++) {
        buf[5-llen+i] = lenBuf[i];
    }
    rc = _client->write(buf+(4-llen), length+1+llen);

    lastOutActivity = millis();
    return (rc == 1+llen+length);
}