When to use which binding
| Column 1 | Column 2 |
|---|---|
| ONVIF Thing | Camera on LAN, RTSP stable, you control credentials |
| HTTP binding | Polling a small JSON status endpoint you host |
| MQTT binding | Your bridge normalizes alarms to topics like camera/alarm/# |
| Home Assistant MQTT Binding | Bridge publishes HA discovery under homeassistant/… (optional shortcut — see below) |
Step 0 — The sidecar (what it is, what it is not)
The sidecar is not an openHAB add-on, Node-RED flow, or HACS package. It is a small service (I use Node.js 18 + Express on the same host as Mosquitto) that:
-
Holds
appId/appSecretand signs vendor cloud OpenAPI calls -
On startup: obtains
accessToken, callssetMessageCallbackwith your public HTTPS URL -
On alarm POST: returns HTTP 200 immediately, dedupes by
msgId, publishes MQTT -
Every ~15 min:
listDeviceDetailsByPageto sync device ids
MQTT topic contract (verify before touching openHAB):
camera/bridge/online → ON | OFF (retained)
camera/alarm/porch/motion → ON | OFF
camera/alarm/porch/event → raw JSON string
mosquitto_sub -h 127.0.0.1 -t 'camera/#' -v
# wave at camera → expect camera/alarm/porch/motion ON
If this step fails, openHAB config will not help.
Step 1 — MQTT Thing (Generic MQTT, correct Contact mapping)
Generic MQTT Thing channels map ON/OFF → Contact OPEN/CLOSED on the Channel itself. No Map transformation add-on, no profile, no .map file.
mqtt.things:
Bridge mqtt:broker:home "Home MQTT" [ host="127.0.0.1", port=1883 ] {
Thing topic porch_alarm "Porch alarm feed" {
Channels:
Type contact : motion "Motion" [
stateTopic="camera/alarm/porch/motion",
on="ON",
off="OFF"
]
Type string : last_event "Last event" [
stateTopic="camera/alarm/porch/event"
]
Type switch : online "Bridge online" [
stateTopic="camera/bridge/online",
on="ON",
off="OFF"
]
}
}
porch.items:
Group gPorch "Porch"
Contact Porch_Motion "Motion" (gPorch) { channel="mqtt:topic:porch_alarm:motion" }
String Porch_LastEvent "Last event [%s]" (gPorch) { channel="mqtt:topic:porch_alarm:last_event" }
Switch CameraBridge_Online "Bridge up" (gPorch) { channel="mqtt:topic:porch_alarm:online" }
Switch Siren_Switch "Siren" (gPorch)
Step 2 — Rule: motion triggers siren (DSL)
porch.rules:
rule "Porch motion from cloud MQTT"
when
Item Porch_Motion changed to OPEN
then
logInfo("porch", "Motion OPEN — pulse siren")
sendCommand(Siren_Switch, ON)
createTimer(now.plusSeconds(30), [ |
sendCommand(Siren_Switch, OFF)
])
end
Step 3 — Optional: same siren logic in JavaScript (OH 4.x)
Equivalent to the DSL rule above — not a different behavior:
const { rules, triggers, items } = require('openhab');
rules.JSRule({
name: "Porch motion — pulse siren (JS)",
triggers: [triggers.ItemStateChangeTrigger('Porch_Motion')],
execute: (event) => {
if (event.itemState.toString() !== 'OPEN') return;
items.getItem('Siren_Switch').sendCommand('ON');
setTimeout(() => items.getItem('Siren_Switch').sendCommand('OFF'), 30000);
}
});
Step 4 — Optional: person-filtered alarms (separate use case)
Only if the sidecar publishes rich JSON on event and you want filtering without changing the motion topic. This is not a drop-in replacement for the siren rule:
rules.JSRule({
name: "Person alarm from JSON event topic",
triggers: [triggers.ItemStateUpdateTrigger('Porch_LastEvent')],
execute: (event) => {
let body;
try { body = JSON.parse(event.itemState.toString()); } catch (e) { return; }
if (body.type === "person") {
items.getItem('Siren_Switch').sendCommand('ON');
}
}
});
Optional shortcut — Home Assistant MQTT discovery
If your sidecar can publish Home Assistant MQTT discovery payloads under homeassistant/..., openHAB’s Home Assistant MQTT Binding can auto-discover and create Things/Channels — less hand-written mqtt.things per camera. Trade-off: sidecar must emit HA-compliant discovery JSON. Manual Generic MQTT Things give full control over topic names.
Pitfalls
| Column 1 | Column 2 | Column 3 |
|---|---|---|
| Issue | Symptom | Fix |
| Thing ONLINE, Item NULL | Rule never fires | Wrong topic (camera/alarm/porch vs …/motion); check with mosquitto_sub |
| JSONPath on Channel | Silent NULL | Test transform in console; wrong path gives no ERROR log |
| Callback 503 during deploy | Alarms stop for hours | Re-register setMessageCallback after sidecar restart |
| PTZ slider Rule | API throttled | Rate-limit controlMovePTZ in sidecar, not in openHAB UI |
HTTP binding: point at your sidecar (http://127.0.0.1:8080/api/devices), never at the vendor cloud — signing belongs server-side.
Debugging (OH 4.x)
log:set org.openhab.binding.mqtt INFO
Do not use org.eclipse.smarthome.binding.mqtt — that package name ended with OH 2.5.
Sitemap fragment
sitemap porch label="Porch" {
Switch item=CameraBridge_Online label="Cloud bridge"
Contact item=Porch_Motion label="Motion"
Text item=Porch_LastEvent label="Last event"
}
openHAB keeps Things/Items/Rules declarative; the sidecar owns cloud auth and MQTT normalization. Get mosquitto_sub showing ON first, then add Things.