LoRaWAN to BACnet: Bridge Wireless Sensors into a BMS

Bridge LoRaWAN sensors into a BACnet/IP BMS: middleware subscribes to ChirpStack MQTT, decodes payloads and exposes BACnet objects the building system can poll.

LoRaWAN
Architecture

The data flow

A building management system speaks BACnet/IP, a LoRaWAN sensor does not. A middleware bridge sits between them: it subscribes to the ChirpStack MQTT stream, reads the decoded values and exposes them as BACnet objects the BMS can poll. This guide shows the honest path and a working Node-RED bridge.

Sensor / controller

Measures or controls in the field and sends LoRaWAN uplinks.

LoRaWAN gateway

Receives the radio packets and forwards them to the server.

ChirpStack

Network server: manages sessions and decodes the payload.

ThingsBoard / Grafana

Dashboards, alarms, rules and reports.

Why a bridge is unavoidable

LoRaWAN and BACnet solve different problems. LoRaWAN is a low-power radio protocol: a sensor wakes up, sends a few compact bytes, and sleeps. BACnet/IP is a wired building-automation protocol that runs over Ethernet and expects devices it can discover and poll continuously. There is no direct mapping between the two, so something has to sit in the middle, subscribe to the LoRaWAN side, and present a BACnet face to the BMS. That something is the bridge, and being honest about it up front avoids the common expectation that a sensor "just appears" in the building management system.

The data flow

The chain has four stages: the sensor sends an uplink, a gateway forwards it to ChirpStack, ChirpStack decodes the payload and publishes it over MQTT, and the bridge turns the decoded values into BACnet objects. The prerequisite for the bridge to do anything useful is a working ChirpStack payload decoder on the device profile, because the bridge reads the clean object field, not the raw hex.

Step 1: ChirpStack MQTT stream

In the ChirpStack application under Integrations, enable the MQTT integration with the marshaler set to JSON. Every decoded uplink is then published to application/{ApplicationID}/device/{DevEUI}/event/up, with the decoded values in the object field:

{
  "deviceInfo": {
    "deviceProfileName": "AM103",
    "deviceName": "office-201",
    "devEui": "24e124710c123456"
  },
  "object": { "temperature": 21.4, "humidity": 48, "co2": 720 }
}

Step 2: the Node-RED bridge

The most transparent bridge is Node-RED. It subscribes to the ChirpStack MQTT topic, reads msg.payload.object, and pushes each value into a BACnet object. A small flow looks like this:

[ mqtt in: application/+/device/+/event/up ]
        │
        ▼
[ json ]  →  parse the ChirpStack event
        │
        ▼
[ function: map to BACnet points ]
        │
        ▼
[ bacnet out ]  →  write Analog/Binary/Multi-state values

The function node turns the decoded object into the points the BMS will read. The instance number is derived from the device so each sensor occupies a stable, non-overlapping block of object instances:

// msg.payload is the decoded ChirpStack event
var obj = msg.payload.object;
var devEui = msg.payload.deviceInfo.devEui;

// stable per-device offset (e.g. from a lookup table)
var base = deviceInstance[devEui] || 0;   // e.g. 100, 200, 300...

var points = [
  { type: "analogValue", instance: base + 0, value: obj.temperature, name: "temperature" },
  { type: "analogValue", instance: base + 1, value: obj.humidity,    name: "humidity" },
  { type: "analogValue", instance: base + 2, value: obj.co2,         name: "co2" }
];

// drop undefined values so the BMS never reads a stale point
msg.payload = points.filter(function (p) { return p.value !== undefined; });
return msg;

The open-source LoRaBAC flow follows the same idea but with a JSON configuration that maps each payload field to a BACnet object and derives the instance number per device. It acts as a BACnet client and writes into an existing controller on each uplink, which keeps the BACnet traffic low. A gateway-resident bridge (for example Node-RED on a Milesight UG65) usually does the opposite: it runs a small BACnet server so the BMS discovers it as a native device and polls it over BACnet/IP.

Step 3: object mapping that the BMS understands

A BMS expects standard object types, so the mapping matters more than it looks:

  • Analog Value / Analog Input for numeric readings: temperature, humidity, CO2, level, power.
  • Binary Value / Binary Input for on/off and contact states: door open, occupancy, leak detected.
  • Multi-state Value for discrete modes: fan low/medium/high, valve open/closed/auto.

Give each device a fixed instance block so points stay stable when you add or rename sensors. The integrator binds those instances to graphics, trends and alarms in the BMS.

Downlink: commands from the BMS

Bridging is not strictly read-only. A BACnet write (a new setpoint on a WT102 thermostatic valve, for example) can become a LoRaWAN downlink. The catch is LoRaWAN timing: a Class A device only receives in the short window after its next uplink, while a Class C device receives in near real time. Schedules, setpoints and occupancy modes work well, but the BMS cannot expect instant actuation across a battery-powered fleet. The bridge enqueues the downlink on application/{ApplicationID}/device/{DevEUI}/command/down.

Pitfalls from the field

  • Decoder first: The bridge reads the decoded object field. With no working codec on the device profile there is nothing to map, so the decoder is a hard prerequisite.
  • Instance collisions: Reusing the same BACnet instance for two devices makes the BMS overwrite points. Give every device a fixed block.
  • Topic template: The ChirpStack v4 application event topic is application/{ApplicationID}/device/{DevEUI}/event/up with no region prefix. The eu868/ style prefix applies to the gateway-side topics, not these application events. If you set a custom event_topic template in the MQTT integration config, the bridge subscription has to match it exactly or nothing arrives.
  • Stale points: A sensor that misses uplinks should not silently hold an old value. Use a reliability flag or a timeout so the BMS can tell a point is out of date.
  • Server vs client: Decide early whether the bridge is a BACnet server the BMS polls or a client that writes into an existing controller. The two need different network and firewall setups.

How merkaio runs this for you

We run ChirpStack and the BACnet bridge as one managed stack on European infrastructure: the decoder on the device profile, the MQTT integration, the bridge middleware and the object mapping. The BMS integrator receives a clean BACnet device with documented, stable points instead of a pile of radio payloads. Talk to us about ChirpStack managed hosting with the bridge included.

Frequently asked questions

No. LoRaWAN devices send compact radio payloads, BACnet/IP is a wired building protocol over Ethernet. A middleware bridge between them is always required, there is no direct protocol mapping.
It subscribes to the ChirpStack MQTT stream, takes the decoded uplink values and writes them into BACnet objects (Analog Value, Binary Value, Multi-state Value). The BMS then polls those objects as if they came from a native BACnet controller.
Both patterns exist. A gateway-resident bridge usually presents itself as a BACnet server (device) that the BMS discovers and polls. The open-source LoRaBAC flow acts as a BACnet client and writes values into an existing controller on each uplink. We pick the one that fits your BMS topology.
Yes, but inside LoRaWAN limits. A BACnet write becomes a LoRaWAN downlink, which reaches a Class A device only after its next uplink and a Class C device in near real time. Schedules and setpoints work, instant actuation across a battery fleet does not.
Numeric readings (temperature, humidity, CO2) map to Analog Value or Analog Input, on/off and contact states to Binary Value or Binary Input, and discrete modes to Multi-state Value. The instance numbering is derived per device so the BMS sees stable points.
Yes. We run ChirpStack and the BACnet bridge as managed hosting on European infrastructure, configure the object mapping and hand the BMS integrator a clean BACnet device. You keep ownership of the data.

Let's discuss your infrastructure. Digital and on-site.

Whether it's IoT platform development, hardware selection, managed hosting for ChirpStack, ThingsBoard, Grafana or NetBird VPN, or migration from a self-hosted setup - we'll find the right solution for your use case. Book a free 30-minute consultation, no commitment required.

Timo Wevelsiep

Your contact

Timo Wevelsiep

Founder, merkaio

15 minutes, no commitment, directly with Timo.

By submitting, you agree to our Privacy Policy.

merkaio is an independent integrator and is not affiliated with Milesight.