Skip to main content

Controller BACnet/IP Server

The Aida Controller BACnet/IP Server exposes Inspextor lighting zones to a municipal or commercial Building Management System (BMS) over BACnet/IP (UDP port 47808).

Each controller acts as a single BACnet device that aggregates many PoE nodes into cluster-level control and sensor points — similar to how the Aida Home Hub Matter bridge exposes zone-level controls.

:::info Parallel integration paths

PathProtocolTypical use
BACnet/IP Server (this doc)BACnet/IPBMS graphics, schedules, municipal submittals
Controller Public APIHTTPS RESTScripts, legacy 1.0 clients, non-BACnet integrators
Aida Platform APICloud HTTPSMulti-site management — not per-controller BACnet

PoE nodes use CoAP/MQTT at runtime; they never speak BACnet directly. AIDA is always the northbound gateway.

Municipal submittals: Municipal BMS Integration Brief · Level 1 PICS Addendum · Commissioning Checklist :::

Integration levels

Level 1 (available today)Level 2 (planned)
State sourceController-native: health-check poll, INX events, command echo → device_statesAuthoritative state from Realtime Controller (RTC)
BMS readsReadProperty on cached presentValue (poll interval, default 30 s)ReadProperty + SubscribeCOV
BMS writesWriteProperty → same INX commands as Public APISame + priority array, BMS override, demand response
SensorsOccupancy, lux, temperature, sound (when present)Adds CO₂, humidity, zone status
RTC requiredNoYes

Default deployment: Level 1 on all Controller 2.0 sites. Choose Level 2 when the Owner requires COV, CO₂-driven DCV, or full municipal commissioning per project PICS.

:::warning Level 1 limitations SubscribeCOV, CO₂/humidity BACnet points, scene MSO, BMS override, and demand-response BACnet objects are Level 2 only. See Municipal BMS Integration Brief — Level 1 limitations. :::

Architecture (Level 1)

State is eventually consistent: updated when devices are polled online, when INX events arrive (mot/vac, lux/temp/sound sentype), and when commands succeed (BACnet write, Public API, or UI).

Enabling the server

The BACnet/IP server is a controller module (bacnet-server):

  1. Log in to the controller as SAdmin (or a role with module management).
  2. Open Modules and enable BACnet/IP Server.
  3. Configure module settings (device instance, UDP bind, exported clusters) — see Configuration.
  4. Ensure UDP 47808 is open on the controller VLAN (firewall / switch ACLs).

The server starts when the module is enabled and stops when disabled.

BACnet device identity

PropertyDefaultNotes
Device instance389001Must be unique on the BACnet network
Device nameAIDA-CTRL-01Configurable
Vendor nameMHT Technologies
Model nameInspextor AIDA Controller
Firmware revisionController software versionAutomatic

The controller responds to Who-Is with I-Am when the module is running.

Level 1 object model

Objects are allocated in instance blocks per cluster (default block size 100):

base = legacy_cluster_id × instance_block_size # e.g. cluster legacy id 2 → base 200
ObjectBACnet typeInstanceName patternBMS readBMS write
Zone powerbinary-outputbase + 1{cluster}-PWRYesYes
Zone dimanalog-outputbase + 2{cluster}-DIMYesYes (0–100 %)
Zone CCTanalog-outputbase + 3{cluster}-CCTYes¹Yes (3000–5000 K)
Occupancybinary-inputbase + 10{cluster}-OCCYesNo
Illuminanceanalog-inputbase + 11{cluster}-LUXYes²No
Temperatureanalog-inputbase + 13{cluster}-TEMPYes²No
Soundanalog-inputbase + 15{cluster}-SNDYes²No

¹ Marked out-of-service if the cluster has no tunable-white fixtures reporting CCT.
² Marked out-of-service if no sensor of that type exists in the cluster.

Not in Level 1: scene MSO, CO₂, humidity, SubscribeCOV, BMS override / demand-response points.

Aggregation rules

When the BMS reads a cluster point, values are aggregated from all devices in that cluster:

PointRule
DimMean of online lighting devices (dim / pp); prefers keyw_cluster_match devices
Powertrue if any device is on or dim > 0
CCTMean of devices reporting color temperature
Occupancytrue if any device reports occupied (last mot/vac/on/off event)
LuxMax across sensors
TemperatureMean across sensors
SoundMax across sensors

When all contributing devices are offline or data is older than the staleness threshold, objects set reliability=no-confidence.

Command translation (writes)

BACnet WriteProperty on writable objects dispatches the same INX events as the Public API:

BACnet pointINX eventExample
Power ON/OFFon / off{"e": {"on": "Lobby"}}
Dimfl{"e": {"fl": "Lobby,1,75"}}
CCTattune{"e": {"attune": "Lobby,4000"}}

All writes pass through the controller ExecutionGateway to PoE nodes.

:::note RGBW and shades RGBW and shade control are available via the Public API today. BACnet write mapping for RGBW and shade objects is planned for a later phase. :::

Discovery and commissioning (Level 1)

  1. Enable the BACnet/IP Server module on the controller.
  2. From the BMS subnet, send Who-Is (or browse by IP) — confirm I-Am from the configured device instance.
  3. Export the object inventory: GET /api/v1/bacnet/inventory (authenticated) or GET /api/v1/bacnet/pics.md.
  4. Write dim/power on {cluster}-DIM / {cluster}-PWR — confirm zone lighting responds.
  5. Read dim — value updates within one state refresh cycle (default 30 s) when devices are online.
  6. Trigger occupancy or sentype events in a zone — confirm {cluster}-OCC, {cluster}-LUX, etc.
  7. Document in submittal PICS that reads are last-known controller state (poll + event memory), not a certified live sensor stream.
  8. Confirm SubscribeCOV is not advertised (Level 1).

REST helpers (controller UI API)

These endpoints help commissioning and submittals (require controller JWT, not BACnet):

MethodPathDescription
GET/api/v1/bacnet/statusModule health, bind address, object count, last sync
GET/api/v1/bacnet/inventoryJSON object list (cluster, instance, name, read/write)
GET/api/v1/bacnet/picsPICS JSON (Level 1 services and object types)
GET/api/v1/bacnet/pics.mdPICS markdown for submittal packages

Example (after POST /api/v1/auth/login):

curl -s "https://192.168.1.77/api/v1/bacnet/inventory" \
-H "Authorization: Bearer $ACCESS_TOKEN" | jq '.objectCount'

Configuration

Module config is stored under the bacnet-server module entry (JSON in modules.config):

{
"device_instance": 389001,
"device_name": "AIDA-CTRL-01",
"integration_level": 1,
"udp_port": 47808,
"bind_address": "0.0.0.0",
"state_refresh_sec": 30,
"instance_block_size": 100,
"exported_cluster_ids": [],
"health_check_interval_sec": 300,
"stale_multiplier": 3
}
SettingDescription
device_instanceBACnet device object instance (unique on network)
exported_cluster_idsEmpty = all clusters with devices; or list of cluster UUIDs
state_refresh_secHow often BACnet presentValue is refreshed from device_states
instance_block_sizeSpacing between cluster instance blocks

Per-cluster overrides in clusters.metadata.bacnet:

{
"export": true,
"base_instance": 500,
"name_prefix": "North-Wing-Lobby"
}

Set "export": false to exclude a cluster from BACnet export.

Network requirements

  • Port: UDP 47808 on the controller management/lighting VLAN.
  • Discovery: BMS Who-Is on the same subnet, or directed to the controller IP.
  • Cross-subnet: BACnet/IP router or BBMD (future phase).

Choosing Level 1 vs Level 2

Owner requirementLevel
BMS commands dim / on / off / CCT1
BMS graphics show occupancy or daylight (poll-based)1 (with PICS caveats)
Demand-controlled ventilation from CO₂2
SubscribeCOV / near-real-time lux step response2
Full Oakland County–style PICS with override / DR2

Document the selected level in project submittals.

Implementation status (Controller 2.0)

ComponentStatus
Level 1 state pipeline (cluster_state: poll, INX ingest, command echo)Implemented
BACnet/IP server module (bacpypes3, Read/WriteProperty, I-Am)Implemented
Level 1 point export and aggregationImplemented
PICS / inventory REST exportImplemented
Public API read of occupancy/lux/temp/soundPartial (dim/CCT on routes; full sensor fields pending)
Passive SENSOR-STATUS-REQUEST ingestPending
Level 2 + Realtime Controller mirror + COVPlanned
RGBW / shade BACnet objectsPlanned

Vendor: MHT Technologies · Product: Inspextor AIDA Controller 2.0