I’ve implemented chunked firmware delivery over data streams for similar constraints. Here’s the complete solution:
Understanding Payload Size Configuration:
The 10MB limit in oiot-pm is enforced at the message broker level and cannot be increased through configuration. However, chunked upload support is the designed approach for large payloads.
Server-Side Implementation:
Prepare firmware package with chunking:
# Split firmware into chunks
chunk_size = 8 * 1024 * 1024 # 8MB chunks
firmware_chunks = split_firmware(firmware_file, chunk_size)
total_chunks = len(firmware_chunks)
# Publish chunks via data stream
for idx, chunk in enumerate(firmware_chunks):
message = {
"chunkIndex": idx,
"totalChunks": total_chunks,
"data": base64.encode(chunk),
"checksum": sha256(chunk)
}
data_stream.publish(device_id, "firmware-update", message)
Device-Side Implementation:
Device receives and assembles chunks:
// Device firmware update handler
void onDataStreamMessage(message) {
int chunkIndex = message.get("chunkIndex");
byte[] chunkData = base64.decode(message.get("data"));
// Verify chunk integrity
if (!verifyChecksum(chunkData, message.get("checksum"))) {
requestChunkRetransmit(chunkIndex);
return;
}
// Store chunk
firmwareBuffer.writeChunk(chunkIndex, chunkData);
}
Firmware Compression Strategy:
Your compression from 18MB to 12MB isn’t optimal. Apply compression per-chunk:
- Split firmware into logical sections (bootloader, application, resources)
- Compress each section separately using LZMA or XZ (better ratios than gzip)
- This typically achieves 40-60% size reduction for firmware binaries
- Chunk the compressed sections into 8MB pieces
Chunked Upload Support - Complete Flow:
-
Initiation Phase:
- Server sends metadata message with total chunks, firmware version, full hash
- Device acknowledges and prepares storage
-
Transfer Phase:
- Server publishes chunks sequentially with 2-second intervals
- Device acknowledges each chunk or requests retransmit
- Implement sliding window protocol (allow 3 chunks in-flight)
-
Verification Phase:
- Device assembles all chunks
- Validates complete firmware hash
- Sends confirmation or requests missing chunks
-
Installation Phase:
- Device applies firmware update
- Reboots and validates new version
Payload Size Configuration Workaround:
While you can’t change the 10MB broker limit, optimize chunk size based on network conditions:
# Adaptive chunk sizing
if device.network_quality == "excellent":
chunk_size = 9 * 1024 * 1024 # 9MB chunks
elif device.network_quality == "good":
chunk_size = 6 * 1024 * 1024 # 6MB chunks
else:
chunk_size = 3 * 1024 * 1024 # 3MB chunks for poor networks
Error Handling:
- Implement exponential backoff for failed chunks
- Store chunk state on device (persist across restarts)
- Set overall timeout (e.g., 24 hours) for complete download
- Allow resume from last successful chunk
Testing Recommendations:
- Test with network disruptions (simulate packet loss)
- Verify behavior when device restarts mid-download
- Validate chunk reassembly with various firmware sizes
- Monitor memory usage during chunk buffering
Production Deployment:
For your 300+ devices:
- Roll out to 10 devices first (pilot group)
- Monitor chunk transfer success rates
- Adjust chunk size based on observed network performance
- Implement rate limiting (update 50 devices concurrently max)
This approach has successfully delivered 25MB+ firmware updates to thousands of edge devices in restricted networks. The key is robust chunk management and per-chunk compression to stay well under the 10MB limit.