Anthony Limon
Anthony Limon

Reputation: 1

AWS IoT Core - MQTT Test Client not receiving full JSON payload

Currently am successfully sending short messages to the AWS IoT Core MQTT test client using an Arduino MKR WiFi 1010 and the libraries described here. (The code and steps needed to be followed can all be found within the link.)

I have had success in also moving this data from the MQTT client to an AWS Dynamo DB table.

The problem arises when I try to send a payload longer than ~250 characters long. I know it is possible as I have sent 400 characters before but I am unsure of what I am doing wrong/differently.

Upvotes: 0

Views: 419

Answers (1)

Brits
Brits

Reputation: 18380

On the wire each MQTT message has a fixed header that contains:

  • byte 1 - Packet type and Flags - For a PUBLISH the packet type is 50 and flags are things like the QOS level.
  • byte 2... (variable length) - Remaining Length - the number of bytes remaining within the current packet, including data in the variable header and the payload.

Because of this a client needs to know the total packet size before it can transmit a message. With a publish message (where the payload size may vary significantly) there are two possible approaches for a library:

  1. Wait until the whole message is available before sending (so we know the size).
  2. Allow the user to provide the size (allowing the body to be transmitted in multiple chunks).

ArduinoMqttClient supports both through a range of beginMessage signatures:

int beginMessage(const char* topic, unsigned long size, bool retain = false, uint8_t qos = 0, bool dup = false);
int beginMessage(const String& topic, unsigned long size, bool retain = false, uint8_t qos = 0, bool dup = false);
int beginMessage(const char* topic, bool retain = false, uint8_t qos = 0, bool dup = false);
int beginMessage(const String& topic, bool retain = false, uint8_t qos = 0, bool dup = false);

If you pass a size then the message will be streamed (see here and here). This means that the header will be sent when you call beginMessage and then each call to write will result in data being sent out. If you know the size of the data to be sent this is the best approach, because it avoids the need to copy the data into a buffer.

If no size is passed then each call to write copies data into a buffer (and it's sent when endMessage is called). Should the data passed in exceed the capacity of the buffer (by default 128 or 256 bytes) then data will be lost. In more recent versions of the library you can set the buffer size with void setTxPayloadSize(unsigned short size).

Upvotes: 0

Related Questions