Connect Coreflux to Building Automation
The BACnet route connects Coreflux to building automation controllers (ASHRAE 135) using the unified OT TAG system. Define the BACnet configuration, add Tags for continuous polling or COV subscriptions, and handle alarm operations.When to use this
Use the BACnet route when you need to integrate HVAC, lighting, metering, or access-control controllers that expose BACnet/IP — read live values on a schedule, subscribe to change notifications, write setpoints from MQTT, receive intrinsic alarms, or run ad-hoc reads and writes triggered by MQTT commands.Key capabilities
- BACnet/IP over UDP — standard port 47808 (0xBAC0) with broadcast or direct-IP discovery
- TAG-based polling — per-point MQTT topics with a configurable polling interval
- Change-of-Value (COV) — push subscriptions per tag (
WITH COV true) without polling - Event alarms — BACnet Event-Notifications to MQTT with per-tag or device-wide streams
- Bidirectional writes — MQTT-triggered writes to analog, binary, and value objects
- On-demand events —
ADD EVENTwithREAD,WRITE, andACKqueries triggered by any MQTT publish - Operator ACK workflow — auto-registered ACK handler per alarming tag
- Direct IP mode — connect to controllers that do not respond to Who-Is/I-Am
- Docker and hostname support — resolve container service names before opening the BACnet socket
Quick Start
Pick the starting point that matches what you need. Each tag publishes to{SOURCE_TOPIC}/{tagName} unless the tag sets its own SOURCE_TOPIC.
- Poll sensor values
- Read and write
- Updates on change
- Connect directly
- On-demand read/write
- Per-tag alarms
Connect to a controller and read a room temperature every five seconds:
Protocol Overview
BACnet (Building Automation and Control networks) is an open protocol for building automation, standardized as ANSI/ASHRAE 135 and ISO 16484-5. It enables interoperability between devices from different manufacturers in HVAC, lighting, fire detection, access control, and energy management.BACnet variants
Coreflux supports BACnet/IP (UDP). MS/TP parameters are parsed but the transport is not validated. Use BACnet/IP for all production deployments.
Supported controllers and platforms
Configuration
OnlyDEVICE_ID is strictly required. For a working route, also set IP and add at least one ADD MAPPING with tags.
All configuration options
Configuration parameters
Network setup: IP, PORT, and LOCAL_PORT
BACnet/IP is UDP. Three settings control two different endpoints — the BACnet device (remote) and the Coreflux broker (local).Direct IP mode
Use when the controller does not respond to Who-Is/I-Am but accepts ReadProperty at a known UDP endpoint:Write priority
Present-value writes use BACnet priority slots (1 = highest, 16 = lowest). If a device holds a value at a higher priority, a write at a lower priority will not override the active present value. The IOTech sandbox profile seedsAO:0 at priority 1 — use WITH WRITE_PRIORITY 1 for that test device.
TAG System
Mapping parameters
* You may set
SOURCE_TOPIC on each tag instead of on the mapping, but one of the two is required.
Tag parameters
Object address format
ADDRESS_TYPE is the BACnet property (e.g. PRESENT_VALUE, OBJECT_NAME), not the object type.Change-of-Value (COV)
Tags withWITH COV true subscribe to BACnet Change-of-Value notifications instead of polling. A mapping with only COV tags does not need WITH EVERY. Mixed mappings poll non-COV tags on EVERY and receive COV tags via push.
COV requires support on the device side. If you receive no change notifications, confirm the controller supports COV and that
WITH COV true is set on the tag.Alarms and Event Notifications
The broker receives BACnet Event-Notification messages from the field device and publishes them to MQTT. Alarm limits and Notification Class membership are configured on the controller — the broker only needs the device to send events to itsLOCAL_DEVICE_ID.
Alarm message format
Every time the BACnet device reports an alarm or state change, the broker publishes one JSON object to the alarm topic. Subscribe to that topic to see events as they happen, or subscribe to{alarm_topic}/active for a retained snapshot of alarms that are still open.
Example — a room temperature crosses its high limit (bacnet/bms/RoomTemp/alarms):
Common
to_state_short values:
Setting Alarms on BACnet ROUTE
Both modes can coexist. When both are enabled for the same object, the event is published to both topics.
- Device-wide
- Per-tag
Publish every Event-Notification from the device to a single MQTT topic — useful for commissioning and catch-all monitoring:Alarm events appear on
bacnet/bms/alarms. Operator ACK via bacnet/bms/alarms/ack.LOCAL_DEVICE_ID is set, the broker sends a directed I-Am so Notification Class recipients learn the broker’s UDP endpoint.
Active alarm list
In addition to live events on{alarm_topic}, the broker maintains a retained snapshot on {alarm_topic}/active. Subscribe here to build an alarm panel — late subscribers receive the current state immediately without waiting for the next transition.
How the list updates:
Per-tag lists usually hold 0 or 1 entry (one BACnet object per tag). Device-wide lists hold one entry per alarming object on the device.
Example — device-wide active list on
bacnet/bms/alarms/active:
alarms array uses the same fields as a single live alarm event. When no alarms are active, count is 0 and alarms is [] — the broker still publishes valid retained JSON.
Acknowledging alarms
When a BACnet device raises an alarm, the broker publishes it to MQTT. To clear or acknowledge it on the device, an operator publishes to the ACK topic. The broker sendsAcknowledgeAlarm to the controller and replies with a result.
How it works:
- Subscribe to the alarm topic (live events) or
{alarm_topic}/active(current alarm list). - Publish your acknowledgement to
{alarm_topic}/ack. - Check
{alarm_topic}/ack/resultforsuccess: trueorfalse.
WITH ALARM true.
- Recommended — echo the alarm
- Explicit command
Copy the alarm JSON you received, add an 2. Publish to Use any MQTT client (such as MQTT Explorer) to publish the payload above to the ACK topic.3. Result on
ack_text note, and publish it to the ACK topic. This is the safest approach because you keep all fields the device expects (event_state_to_ack, bacnet_timestamp, and so on).1. An alarm arrives on bacnet/bms/RoomTemp/alarms:bacnet/bms/RoomTemp/alarms/ack — same JSON, plus your note:bacnet/bms/RoomTemp/alarms/ack/result:If
success is true, the device accepted the acknowledgement. The alarm is removed from {alarm_topic}/active.Field device prerequisites
Field device prerequisites
Before expecting MQTT alarms, confirm on the BMS or engineering tool:
- Notification Class — recipient list includes
LOCAL_DEVICE_ID - Intrinsic alarming on each object —
NOTIFICATION_CLASS,HIGH_LIMIT/LOW_LIMIT,EVENT_ENABLE,LIMIT_ENABLE - Present value actually crosses a configured limit
On-Demand Events
UseADD EVENT when you need a single read, write, or alarm acknowledgement triggered by an MQTT publish — instead of continuous TAG polling.
Query formats
Supported operations: READ, WRITE, and ACK (alarm acknowledgement).
bacnet/cmd/read and the result appears on bacnet/cmd/read/result:
When to use what
Examples
- Simple polling
- COV subscriptions
- Device-wide alarms
- Sandbox (Docker)
Reads two analog inputs and one analog value every five seconds:Publishes to
bacnet/bms/RoomTemp → 22.5, bacnet/bms/Humidity → 55.0, bacnet/bms/Setpoint → 21.0.Combining with Models and Actions
A BACnet route publishes each point to its own MQTT topic, so the rest of LoT can use that data like any other topic.- Aggregate into a model
- Monitor alarm streams
First, the route publishes each point under Then the model aggregates those topics into one object on
bacnet/bms:bacnet/bms/Info:Best Practices
Always set WITH IP explicitly
Always set WITH IP explicitly
The default
192.168.1.1 is rarely correct. On Docker or routed networks, broadcast Who-Is may never reach the device. Set WITH IP to the controller’s address or hostname.Use Direct IP for unresponsive controllers
Use Direct IP for unresponsive controllers
If a device does not answer Who-Is/I-Am, set
WITH DIRECT_IP true to connect to IP:PORT and verify with ReadProperty. Otherwise the route waits on discovery timeout every connect.Use COV for fast-changing points
Use COV for fast-changing points
Polling at one-second intervals wastes bandwidth on BACnet/IP. Use
WITH COV true for occupancy sensors, fast process variables, and alarm-related points.Set LOCAL_DEVICE_ID before enabling alarms
Set LOCAL_DEVICE_ID before enabling alarms
The broker must announce itself as a BACnet device via directed I-Am so the field device knows where to send Event-Notifications.
Choose write priority deliberately
Choose write priority deliberately
If a BMS holds a point at priority 1, a write at priority 8 will not change the present value. Match priority to your application and verify on the device.
Omit WITH EVERY from COV-only mappings
Omit WITH EVERY from COV-only mappings
COV-only mappings do not need a polling interval. Adding
WITH EVERY on a COV-only mapping adds confusion without benefit.Use per-tag alarms for production points
Use per-tag alarms for production points
Per-tag alarms (
WITH ALARM true) give each monitoring point its own ACK topic. Use device-wide (WITH ALARMS true) as a catch-all or for commissioning.Echo alarm JSON when acknowledging
Echo alarm JSON when acknowledging
Include
event_state_to_ack and bacnet_timestamp from the received alarm message. Wrong state or missing timestamp causes ACK to fail.Troubleshooting
Connection check
Publish-checkRouteConnection BMS to $SYS/Coreflux/Command. The broker returns a JSON status for the named route indicating whether the BACnet device was reached.
Discovery and connection issues
Discovery and connection issues
Data issues
Data issues
Alarm issues
Alarm issues
Networking issues
Networking issues
Additional resources
- ASHRAE 135 Standard — official BACnet standard
- BACnet International — conformance testing and product listings
Next Steps
Industrial Overview
Learn the patterns shared across all OT routes.
OPC UA
Connect to cross-platform industrial servers with OPC UA.

