What you will build
You’ll collect DB01 edge events (temperature/humidity thresholds, motion/light, button/fall) through a webhook endpoint, translate them to MQTT topics, and render a simple dashboard (Node‑RED/Grafana or your own app). The pipeline is:
- DB01 advertises BLE packets (or gateway sends HTTP).
- A tiny Webhook Server parses the event.
- The server publishes to an MQTT Broker (e.g., Mosquitto).
- A Dashboard subscribes and visualizes alerts in real time.
(Insert the architecture image webhook_mqtt_architecture.png
near here.)
Why a webhook + MQTT split?
- Webhooks are easy to expose publicly (HTTPS + auth) and map cleanly to event semantics.
- MQTT provides lightweight fan‑out to any number of consumers (dashboards, mobile apps, cloud rules).
- You decouple ingest (webhook) from consumption (MQTT) and keep each part independently scalable.
Prerequisites
- A DB01 beacon and a BLE/Wi‑Fi/LTE gateway that can forward sensor/alert data as HTTP.
- A server/VM (Linux, macOS, or Windows) with Docker or Python/Node runtimes.
- An MQTT broker (local Mosquitto is fine).
- Optional: Node‑RED for a quick dashboard.
- Open ports: 1883 (MQTT), 1880 (Node‑RED), 8080 (webhook) – or adjust in the configs.
Topic & payload design
Create a small, consistent topic schema so alerts and telemetry are easy to route:
assets/{site}/{device_id}/alerts/{alert_type}
assets/{site}/{device_id}/telemetry
Alert payload (JSON):
{
"device_id": "DB01-ACME-00042",
"ts": 1733435152,
"alert": "TEMP_LOW",
"temp_c": -12.6,
"threshold": -10.0,
"humidity": 68.2,
"rssi": -63
}
Telemetry payload:
{
"device_id": "DB01-ACME-00042",
"ts": 1733435152,
"temp_c": -5.1,
"humidity": 61.0,
"light": 12,
"motion": 0,
"battery_v": 2.87
}
Option A — Python (FastAPI) webhook → MQTT
# fastapi_webhook.py
from fastapi import FastAPI, Request, HTTPException
import paho.mqtt.client as mqtt
import os, json, time
MQTT_HOST = os.getenv("MQTT_HOST", "localhost")
MQTT_PORT = int(os.getenv("MQTT_PORT", "1883"))
SITE = os.getenv("SITE", "warehouse-12")
app = FastAPI()
mq = mqtt.Client()
mq.connect(MQTT_HOST, MQTT_PORT, 60)
def topic_alert(dev, atype): # alert topic
return f"assets/{SITE}/{dev}/alerts/{atype}"
def topic_telemetry(dev): # telemetry topic
return f"assets/{SITE}/{dev}/telemetry"
@app.post("/webhook")
async def webhook(req: Request):
try:
body = await req.json()
except Exception:
raise HTTPException(status_code=400, detail="Bad JSON")
dev = body.get("device_id") or "unknown"
now = int(time.time())
body.setdefault("ts", now)
if "alert" in body:
atype = body["alert"]
mq.publish(topic_alert(dev, atype), json.dumps(body), qos=1, retain=False)
else:
mq.publish(topic_telemetry(dev), json.dumps(body), qos=0, retain=False)
return {"ok": True}
Run it:
pip install fastapi uvicorn paho-mqtt
uvicorn fastapi_webhook:app --host 0.0.0.0 --port 8080
Option B — Node.js (Express) webhook → MQTT
// express_webhook.js
const express = require("express");
const bodyParser = require("body-parser");
const mqtt = require("mqtt");
const MQTT_HOST = process.env.MQTT_HOST || "localhost";
const MQTT_PORT = process.env.MQTT_PORT || 1883;
const SITE = process.env.SITE || "warehouse-12";
const client = mqtt.connect(`mqtt://${MQTT_HOST}:${MQTT_PORT}`);
const app = express();
app.use(bodyParser.json());
function topicAlert(dev, atype) { return `assets/${SITE}/${dev}/alerts/${atype}`; }
function topicTelemetry(dev) { return `assets/${SITE}/${dev}/telemetry`; }
app.post("/webhook", (req, res) => {
const body = req.body || {};
const dev = body.device_id || "unknown";
body.ts = body.ts || Math.floor(Date.now() / 1000);
if (body.alert) {
client.publish(topicAlert(dev, body.alert), JSON.stringify(body), { qos: 1 });
} else {
client.publish(topicTelemetry(dev), JSON.stringify(body), { qos: 0 });
}
res.json({ ok: true });
});
app.listen(8080, () => console.log("Webhook listening on :8080"));
Run it:
npm i express body-parser mqtt
node express_webhook.js
Docker Compose (optional)
version: "3.8"
services:
broker:
image: eclipse-mosquitto:2
ports: ["1883:1883"]
webhook:
build: .
environment:
- MQTT_HOST=broker
- SITE=warehouse-12
ports: ["8080:8080"]
depends_on: [broker]
nodered:
image: nodered/node-red:latest
ports: ["1880:1880"]
depends_on: [broker]
Node‑RED dashboard sketch
- Add mqtt in nodes for
assets/+/+/alerts/#
andassets/+/+/telemetry
. - Parse JSON with a function node; route by
msg.topic
. - Connect to ui_chart, ui_text, or a custom template.
- Save flow & deploy. You’ll see alerts streaming in near real‑time.
(Insert the payload image mqtt_topic_payload.png
in this section.)
Security hardening checklist
- TLS termination for your webhook (reverse proxy or cloud LB).
- Sign webhook requests (HMAC header).
- Per‑tenant MQTT usernames/passwords and topic‑level ACLs.
- Secrets via env vars or secret manager.
- Rate‑limit abusive IPs; log rejects.
Troubleshooting
- Nothing arrives at MQTT → Check webhook logs; verify JSON.
- Broker refuses connections → Confirm port/credentials.
-
Dashboard shows stale data → Avoid
retain
for alerts. - High CPU → Disable verbose logging; batch telemetry.
Where to learn more
See families and coverage on the EELINK Official Website .
Top comments (0)