Cameleer / Use cases / MQTT edge gateways
Edge and IoT
MQTT edge gateways that keep working when the uplink doesn't
Gateways sit between machines and the cloud. They speak local protocols, keep working offline, and share small hardware with other software. Cameleer runs Apache Camel's routes there without a JVM: five tested patterns, one binary, about 10 MB of memory.
Five tested patterns
Each is a complete route file in examples/edge/, run by the test suite against the embedded MQTT and Kafka brokers and HTTP mocks. The edge cookbook walks through each one.
| pattern | what the route does | file |
|---|---|---|
| Sensor rollups | subscribe to sensors/+/temperature, drop malformed and out-of-range readings, aggregate five readings per sensor (or a minute's worth) into count, min, max and average, publish to Kafka keyed by sensor | mqtt-sensor-rollup.camel.yaml |
| Store and forward | telemetry into a seda queue, post to the cloud with retries and back-off, dead-letter to a buffer folder, replay every 30 seconds and move to .sent on success | store-and-forward.camel.yaml |
| Syslog to Kafka | receive RFC 5424 and 3164 syslog over UDP, TCP or TLS, parse it, keep warnings and above, publish to Kafka | syslog-to-kafka.camel.yaml |
| HL7 over MLLP | hospital gateway: MLLP in, HTTP to the EHR, acknowledge after delivery (own page) | hl7-mllp-to-http.camel.yaml |
| Gateway presence | publish a retained online status with a last-will offline, plus a heartbeat on a timer | gateway-heartbeat.camel.yaml |
Store and forward, the part that matters
From store-and-forward.camel.yaml: the uplink route's error handler. When the post fails three times, the original message becomes a file in the buffer; a second route replays the buffer.
- route:
id: uplink
errorHandler:
deadLetterChannel:
deadLetterUri: "file:{{env:BUFFER_DIR:buffer}}?fileName=${date:now:yyyyMMddHHmmssSSS}-${exchangeId}.msg"
useOriginalMessage: true
redeliveryPolicy:
maximumRedeliveries: 3
redeliveryDelay: "{{env:RETRY_DELAY_MS:1000}}"
useExponentialBackOff: true
from:
uri: "seda:uplink?size=10000"
steps:
# ... set headers, post to {{env:UPLINK_URL}}/ingest
Why it holds up
- The MQTT consumer hands off to a bounded
sedaqueue, so a slow uplink never blocks the broker subscription. useOriginalMessagebuffers what arrived, not a half-transformed body.- The buffer is a folder: it survives a restart, and it is the only thing the container writes, so the image runs
--read-onlywith one volume.
Footprint on the device
| build | binary | HTTP route ready | memory, HTTP route |
|---|---|---|---|
| all components, glibc | 23.9 MB | 1.17 ms | 10.4 MB |
--features cloud, static musl | 11.8 MB | 0.75 ms | 5.3 MB |
--features core, static musl | 7.5 MB | 0.69 ms | 4.2 MB |
Measured on Linux x86-64 with cameleer-bench coldstart; method and the full table in BENCHMARKS. The container image is about 20 MB to download with every component, 12.5 MB with FEATURES=core. For a gateway, --features kafka-mqtt,protocols keeps MQTT, syslog, MLLP and the core; the build features guide lists every family.
Common questions
Does Cameleer run on a Raspberry Pi?
Yes, on a 64-bit OS. The image is published for linux/arm64 (Raspberry Pi 3, 4 and 5 with 64-bit Raspberry Pi OS, NVIDIA Jetson, Graviton) and a running route uses about 10 MB of memory. There is no 32-bit ARM image.
Which MQTT versions and brokers are supported?
paho speaks MQTT 3.1.1 and paho-mqtt5 speaks MQTT 5.0, with QoS 0 to 2, retained messages, last will, persistent sessions and TLS. They are tested against Mosquitto, RabbitMQ and ActiveMQ and work with any broker, including EMQX, HiveMQ and AWS IoT Core.
What happens to messages when the uplink is down?
The store-and-forward route retries with back-off, then writes the original message to a buffer folder through a dead letter channel. A replay route polls the folder every 30 seconds and moves each file to .sent once the cloud accepted it. The buffer is on disk, so it survives restarts.
Can a gateway bridge protocols?
Yes. The tested routes bridge MQTT into Kafka and HTTP, and syslog (RFC 5424 and 3164 over UDP, TCP or TLS) into Kafka with severity filtering. HL7 over MLLP, AMQP, STOMP and files are available on the same gateway.
Is there a Modbus or OPC UA component?
No. Field protocols are expected to arrive through a local broker or an HTTP, TCP or UDP adapter; the netty component handles raw TCP and UDP.
Run it
The buffer is the only thing written, on its own volume; everything else is read-only.
export MQTT_BROKER=tcp://localhost:1883 UPLINK_URL=https://ingest.example.com GATEWAY_ID=plant-7 docker run --rm --network host --read-only -e MQTT_BROKER -e UPLINK_URL -e GATEWAY_ID \ -e BUFFER_DIR=/buffer -v cameleer-buffer:/buffer -v "$PWD:/routes:ro" \ pmsudhi/cameleer run /routes/store-and-forward.camel.yaml