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, binary
and 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?