iot-data-generator (mer)
A developer-friendly IoT test data generator CLI written in Rust.
Generate realistic IoT sensor payloads and send them to your system over MQTT, HTTP, or TCP — with zero infrastructure required to get started.
This is not a load-testing tool. It is focused on high-quality, realistic IoT test data.
Demo
From setup to sending data over MQTT:

Features
- Random payload generation — temperature, humidity, voltage, current, power, energy, status
- Custom Handlebars templates — full control over payload structure
- Three protocols — MQTT (plain & TLS), HTTP, TCP
- Authentication — username/password, Bearer token, API key header
- Environment variable expansion — keep secrets out of config files with
${VAR_NAME} - Validation & preview — check config and see sample payloads before sending
- Run control — total message count, interval, or hard time limit
- Cross-platform — Linux, macOS, Windows (prebuilt binaries available)
- Docker ready — single image, compose with a local Mosquitto broker included
Installation
Option 1 — Prebuilt binary (recommended)
Download the latest binary for your platform from GitHub Releases. Binaries are built automatically when a release is published:
# Linux x86_64
|
# Linux ARM64
|
# macOS Apple Silicon
|
# macOS Intel
|
# Windows (PowerShell)
# Add mer.exe to your PATH
Option 2 — Build from source
Requires Rust (stable):
# Binary: ./target/release/mer
Option 3 — Docker
# Pull and run (no local Rust needed)
# Run an example against a local broker
Option 4 — Docker Compose (bring your own broker)
Runs mer in a container and connects to your existing broker:
For brokers that require auth, edit the command in docker-compose.yml to use docker/mer.docker-auth.yaml and fill in MQTT_USERNAME / MQTT_PASSWORD in your .env.
No broker is bundled —
merconnects to whatever broker you point it at.
Quickstart
1. Generate a starter config
2. Preview payloads
3. Validate the config
4. Send data
Commands
| Command | Description |
|---|---|
| `mer init --protocol <mqtt | http |
mer validate config -f <file> |
Validate a config file (exits 0 on success) |
mer preview payload -f <file> [-n N] |
Preview N generated payloads (default 3) |
mer mqtt run -f <file> |
Send MQTT messages |
mer http run -f <file> |
Send HTTP requests |
mer tcp run -f <file> |
Send TCP messages |
Config Reference
MQTT
protocol: mqtt
target:
broker: "mqtt://mqtt.iotmer.cloud:1883" # or mqtts:// for TLS (port 8883)
topic: "devices/{device_id}/telemetry"
client_id: "mer-{device_id}" # optional, auto-generated if omitted
qos: 1 # 0, 1, or 2
retain: false
device:
count: 5
id_prefix: device # device IDs: device-0000, device-0001, …
payload:
mode: random # or template
run:
total_messages: 100
interval_ms: 1000 # ms between messages
duration_secs: 60 # optional hard time limit
HTTP
protocol: http
target:
url: "http://ingest.iotmer.cloud:8080/api/v1/devices/{device_id}/data"
method: POST # GET, POST, PUT, PATCH
timeout_secs: 10
headers:
Content-Type: "application/json"
X-Custom-Header: "value"
device:
count: 3
id_prefix: sensor
payload:
mode: random
run:
total_messages: 50
interval_ms: 500
TCP
protocol: tcp
target:
host: localhost
port: 9000
timeout_secs: 5
line_delimiter: true # append \n to each message
device:
count: 2
id_prefix: node
payload:
mode: random
run:
total_messages: 20
interval_ms: 1000
Payload Modes
random (default)
Generates a realistic IoT JSON payload automatically:
Field ranges:
| Field | Range |
|---|---|
temperature |
15.0 – 45.0 °C |
humidity |
20.0 – 95.0 % |
voltage |
220.0 – 240.0 V |
current |
0.1 – 15.0 A |
power |
10.0 – 3600.0 W |
energy_total |
0.0 – 10000.0 kWh |
status |
online (4/6), offline (1/6), error (1/6) |
template
payload:
mode: template
template_inline: |
{
"device_id": "{{device_id}}",
"ts": "{{now_utc}}",
"temperature": {{random_float 18.0 35.0}},
"humidity": {{random_float 30.0 90.0}},
"active": {{random_bool}},
"seq": {{seq}},
"level": {{random_int 0 5}}
}
Or load from an external file:
payload:
mode: template
template_file: ./my-template.json
Template helpers
| Helper | Example | Output |
|---|---|---|
{{now_utc}} |
— | 2024-01-01T12:00:00Z |
{{random_int min max}} |
{{random_int 0 100}} |
42 |
{{random_float min max}} |
{{random_float 10.0 50.0}} |
27.35 |
{{random_bool}} |
— | true or false |
{{device_id}} |
— | sensor-0003 |
{{device.index}} |
— | 3 |
{{seq}} |
— | 17 |
Authentication
Username / Password (MQTT, HTTP)
auth:
type: username_password
username: myuser
password: "${MQTT_PASSWORD}"
For MQTT, you can also set credentials directly under target:
target:
broker: "mqtts://mqtt.iotmer.cloud:8883"
topic: "test/{device_id}"
auth:
username: myuser
password: "${MQTT_PASSWORD}"
Bearer Token (HTTP)
auth:
type: bearer
token: "${API_TOKEN}"
API Key Header (HTTP)
auth:
type: api_key
header: X-API-Key
value: "${API_KEY}"
Environment Variables
Use ${VAR_NAME} anywhere in your config to inject secrets at runtime:
auth:
type: bearer
token: "${MY_API_TOKEN}"
If a variable is not set, mer exits with a clear error:
Error: Environment variable 'MY_API_TOKEN' is not set
Run Summary
After each run, mer prints a summary:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Run Summary — MQTT
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Total sent : 100
Successful : 98
Failed : 2
Success rate : 98.0%
Errors : 2
Bytes sent : 24.5 KB
Elapsed : 100.12s
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Examples
The [examples/](examples/) directory contains ready-to-use configs:
| File | Description |
|---|---|
[mqtt-basic.yaml](examples/mqtt-basic.yaml) |
5 devices, 20 messages, random payload, MQTT localhost |
[demo-mqtt.yaml](examples/demo-mqtt.yaml) |
Demo: mqtt.iotmer.cloud, public broker, README GIF |
[mqtt-auth.yaml](examples/mqtt-auth.yaml) |
MQTT with username/password auth |
[mqtt-tls.yaml](examples/mqtt-tls.yaml) |
MQTT over TLS (mqtts://) with auth |
[http-basic.yaml](examples/http-basic.yaml) |
3 sensors, HTTP POST with custom header |
[http-bearer.yaml](examples/http-bearer.yaml) |
HTTP POST with Bearer token auth |
[http-api-key.yaml](examples/http-api-key.yaml) |
HTTP POST with API key header auth |
[tcp-basic.yaml](examples/tcp-basic.yaml) |
2 nodes, TCP with line delimiter |
[custom-template.yaml](examples/custom-template.yaml) |
MQTT with inline Handlebars template |
[smart-home.yaml](examples/smart-home.yaml) |
Smart home sensors (temp, plug, door, CO₂, lux) |
[industrial.yaml](examples/industrial.yaml) |
Factory floor machines (vibration, pressure, flow, RPM) |
[fleet-tracking.yaml](examples/fleet-tracking.yaml) |
Vehicle GPS tracking over HTTP |
[energy-meter.yaml](examples/energy-meter.yaml) |
Three-phase smart energy meters over MQTT |
[weather-station.yaml](examples/weather-station.yaml) |
Weather stations over TCP (wind, rain, UV, pressure) |
[duration-limited.yaml](examples/duration-limited.yaml) |
Time-capped run with duration_secs |
Development
# Build
# Run tests
# Lint
# Format
# All checks (same as CI)
See [CONTRIBUTING.md](CONTRIBUTING.md) for the full contribution guide.
Security
Please read our Security Policy before reporting vulnerabilities.
Key points:
- Never commit plaintext secrets — use
${ENV_VAR}in config files - Use
mqtts://for production MQTT connections - Use
https://for production HTTP endpoints
License
MIT © 2026 iotmertech