MQTT binding for cloud IP camera alarms — Things, Items, and a motion rule

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:

  1. Holds appId / appSecret and signs vendor cloud OpenAPI calls

  2. On startup: obtains accessToken, calls setMessageCallback with your public HTTPS URL

  3. On alarm POST: returns HTTP 200 immediately, dedupes by msgId, publishes MQTT

  4. Every ~15 min: listDeviceDetailsByPage to 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.

If this is meant to be a tutorial and solution I will gladly move it to the Tutorials and Examples section. However, as written I’m not sure anyone could follow it and some up with a working system. Details like what sidecar are you using to bridge between the camera and MQTT?

The Generic MQTT Thing supports doing this mapping on the Channel config itself. You do not need to install the Map transformation and use a profile for this.

Also, you;ve defined a .map file but you don’t use it in your example.

The alternative rule doesn’t do the same thing as the DSL rule at all. It’s not an alternative, it’s completely different.

What version of OH are you running? org.eclipse.smarthome.binding.mqtt has not been a valid logger/package name since OH 2.5.

You mention Home Assistant. Are you aware that there is a Home Assistant binding for openHAB that will be able to discover and automatically create the MQTT Things for those systems that publish using the Home Assistant MQTT standard?

Sir Goodenough, you were absolutely right. I’ve made the adjustments and re-edited per your suggestions. Much appreciated! When you have a moment, could you kindly glance at the new version to see if I’ve missed anything?