MQTT publish error on larger packet sizes on P2, but not on the Argon

I have been tracking down an MQTT issue and believe I have isolated it to the P2. Here is my scenario.

I need to send about 17K bytes of data (lets call this a packet) over WiFi using the MQTT protocol to a broker in the cloud. When I need to do this I may be needing to do this at rapid succession for around 4,000 - 5,000 packets.

What I experience is that the P2 will stop publishing after a small number of packets has been sent, lets say 100. (This can vary on each run). The P2 believes that it still has the connection to the broker mqtt_client.isConnected() still returns true and it calls the publish but nothing is actually published.

When I put this exact same code on an Argon, it runs perfectly. This is all on device OS 5.8.0.
To set this up for testing to ensure it wasn't an issue with the cloud broker on GCP or something else cloud related I set up my own broker on my laptop using aedes npm module. I then have another process which is my mqtt listener using mqtt npm module. I have two topics, binaryand log that the firmware publishes to and the mqtt listener listens on.

Here is my broker code:

import aedes from 'aedes';
import { createServer } from 'net';
import os from 'os';

const broker = aedes();
const server = createServer(broker.handle);

const port = 1883;

// Function to get the local network IP address
function getLocalIPAddress() {
  const interfaces = os.networkInterfaces();
  for (const interfaceName of Object.keys(interfaces)) {
    for (const iface of interfaces[interfaceName]) {
      if (iface.family === 'IPv4' && !iface.internal) {
        return iface.address;
      }
    }
  }
  return '127.0.0.1';
}

server.listen(port, () => {
  const ipAddress = getLocalIPAddress();
  console.log(`MQTT broker started on ${ipAddress}:${port}`);
});

Here is my mqtt listener code

import mqtt from 'mqtt';

// Connect to the broker
const client = mqtt.connect('mqtt://192.168.0.127:1883', options);

// Subscribe to the 'binary' topic
client.on('connect', () => {
    console.log('Connected to broker');
    client.subscribe(['binary', 'log'], (err) => {
        if (err) {
            console.error('Subscription error:', err);
        } else {
            console.log('Subscribed to topics: binary, log');
        }
    });
});

// Handle incoming messages
client.on('message', (topic, message) => {
    if (topic === 'binary') {
        console.log(message); // message is a Buffer (binary data)
    } else if (topic === 'log') {
        console.log(message.toString()); // Assuming log is text, converting buffer to string
    }
});

// Handle connection errors
client.on('error', (err) => {
    console.error('Connection error:', err);
});

And here is the firmware without any changes going from Argon to P2 and back

#include "Particle.h"
#include "MQTT.h"

SYSTEM_MODE(SEMI_AUTOMATIC);
SYSTEM_THREAD(ENABLED);

// Define a constant for the size of the large string
const int BUFFER_SIZE = 8000;

void mqtt_callback(char* topic, byte* payload, unsigned int length);

MQTT mqtt_client("192.168.0.127", 1883, BUFFER_SIZE + 100, mqtt_callback);
int count = 0;
uint8_t data[BUFFER_SIZE];

void setup() {
  WiFi.clearCredentials();
  WiFi.setCredentials("localaccesspoint","password");
  WiFi.connect();
  Serial.begin();

  for (int i=0; i < BUFFER_SIZE; i++) {
	  data[i] = i % 256;
  }

}

void loop() {
  if (mqtt_client.isConnected()) {
	  count++;
    Serial.println("publishing...");

    // Publish the message to the "log" topic
    mqtt_client.publish("binary", data, BUFFER_SIZE);
    mqtt_client.publish("log", String(count));
   
  } else {
    Serial.println("attempting to connect...");
    mqtt_client.connect(System.deviceID());
  }
  count++;
}

void mqtt_callback(char* topic, byte* payload, unsigned int length) {
  // Handle incoming messages here
}

Has anybody run into this on the P2 or have any ideas on why this doesn't work properly on the P2?

If anybody is interested, this weekend I worked on an alternate implementation of MQTT based on my research of MQTT-SN. This sits on top of UDP rather than TCP/IP and is lighter weight. I didn't see a library for MQTT-SN with particle so I decided to roll my own which would allow me to implement it exactly the way I need for this project.

Interestingly I used o1-preview and with us working together was an absolutely amazing experience. I have both a client running on the P2 and a Node.js broker app running in the cloud.

So far, seems to work perfectly on the P2 without any degradation or hanging.

This weekend, I worked on an alternate implementation of MQTT, drawing from research into MQTT-SN, which uses UDP instead of TCP/IP, making it more lightweight. Since I couldn’t find an existing MQTT-SN library for Particle, I decided to build my own to meet the specific needs of this project.

I used the o1-preview AI assistant, and collaborating with it was an amazing experience. I now have both a client running on the P2 and a Node.js broker in the cloud, and so far, everything is working perfectly on the P2 without any degradation or hanging.

Interestingly, my original MQTT client, which constantly fails on the P2, runs fine on the Argon with the exact same code. The P2 has integrated Wi-Fi, which in theory should make for a more efficient and less complex implementation than dealing with a coprocessor like the Argon’s ESP32. So, I wouldn’t expect any performance degradation. This leads me to believe the issue is likely a bug in the OS, as the Wi-Fi implementation between the two architectures is probably quite different.

If anybody has any additional thoughts on this I would very appreciate hearing them.

@rickkas7 I'd be curious if anyone else has reported issues with the WiFi on the P2.

Hey Kevin, I have seen issues with Wi-Fi on 5.8 and that improved with 5.9.0.
I have also experienced issues in a particular FW with logging. It uses BLE instensively and logging somehow was getting in the way of proper functioning. All those issues went away again with 5.9.0 and this:

SerialLogHandler logHandler(LOG_LEVEL_NONE);

Eventhough I removed all logging from BLE handlers, as I discussed here, issues remained so I turned off all logging.
I started to suspect something wrong with logging when the firmware behaved somewhat better when I had my laptop with the serial logs opened. As soon as I disconnected my laptop, things would start to misbehave - I could "see" this from the cloud. Then I reconnected my laptop, things would go back to normal. And so on. I cannot explain this phenomenon, but it may be getting in the way of your MQTT tests. Who knows.

Best,

Hey @gusgonnet. Thanks for that feedback although I don't use the SerialLogHandler in my test that I posted. Is there some default that I need to include like you supplied with parameter NONE?

Also, my Particle Workbench does not give me the choice to use 5.9.0 although I do see that I can flash it using Chrome on the device.

How do I get 5.9 to show as an OS option in Particle Workbench?

I guess I am also curious why the Photon 2 which is the new successor to the EOL'ed Argon is not getting 6.X OS updates. Did I miss some message to the community about why 6 doesn't apply to the new tech?

I didn't get that. I use:
SerialLogHandler logHandler(LOG_LEVEL_NONE);

For 5.9 on Workbench, you need to enable pre-releases from the settings:

1 Like

What I meant to say was that my sample code I posted to duplicate the issue does not actually declare a SerialLogHandler.

And thanks for that tip on the pre-release. On it right now to see what happens.

1 Like

@gusgonnet Unfortunately, same behavior. Note that this is all WiFi related, a different issue from my previous post on BLE.

1 Like