Skip to content

About

CAS BACnet Stack profile example: B-AS (Authorization Server) — C++ (planned)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

BACnet B-AS (Authorization Server) - C++ example

Blocked Example. The CAS BACnet Stack cannot yet perform the B-AS Profile Function - issuing access tokens to authorization clients (ASHRAE 135-2024 Annex L.14.1, Clause 17) - through its customer interface, so this example stays published but is blocked on that stack gap (cas-bacnet-stack#2043). At stack 6.x @ 64b2cfac5 the AuthRequest service handler and the authorization-policy exports compile only into the stack's test-tool build, so a customer build refuses AuthRequest and has no way to configure a policy; on 2026-10-15 the stack owner ruled that they are not promoted to the customer interface for now. What it does today:

  • It is a discoverable BACnet/IP device that serves its Device, Network Port and three sensor objects to any client - ReadProperty, Who-Is/I-Am, Who-Has/I-Have and DeviceCommunicationControl (the profile's DS/DM base).
  • It does not answer AuthRequest and issues no tokens. AA-AS-B is not claimed.

A minimal, copy-paste-friendly example showing how to implement the BACnet B-AS (BACnet Authorization Server) device profile's DS/DM base in C++ using the CAS BACnet Stack. It listens on BACnet/IP (UDP 47808), answers ReadProperty requests, is discoverable via Who-Is / I-Am and Who-Has / I-Have, and responds to DeviceCommunicationControl.

Download a prebuilt binary (Windows and Linux x64) - or build it yourself, see Build below.

  • TUTORIAL.md - how to extend this example and how to review it for conformance. Read it when you start turning this into your own device.
  • docs/PICS.md - the Protocol Implementation Conformance Statement: every object, every property, and who answers it.

This example claims only the B-AS profile's DS/DM base - see What this example supports for the one BIBB (AA-AS-B) it does not implement, and why.

Versions: this document describes example v1.1.0, built and verified against CAS BACnet Stack 6.0.23 (6.x @ 64b2cfac5), at Protocol_Revision 30, with the vendored common/ helper at v3.4.0. Running the example prints all three - if what it prints disagrees with this line, trust the program and check CHANGELOG.md.

What is the B-AS (Authorization Server) profile?

B-AS (BACnet Authorization Server), defined in Annex L.14.1 of ANSI/ASHRAE 135-2024, is "an authorization server that issues access tokens to authorization clients or their helpers" (Clause 17): the server side of the AuthRequest exchange. L.14.1 also requires a persistent database of access policies and a user interface for configuring them.

DeviceCommunicationControl (DM-DCC-B)

DeviceCommunicationControl lets a management station tell a device to stop (or resume) communicating - useful to quiet a device during commissioning. The CAS BACnet Stack runs the actual enable/disable state machine (and the optional re-enable timer); this example's DeviceCommunicationControl callback in main.cpp validates the optional password and logs what was asked. At Protocol_Revision 30 the plain "disable" value is deprecated - the stack itself rejects it and only enable and disable-initiation take effect - see the callback's comments in main.cpp for the full detail. This example's password is empty (DCC_PASSWORD = ""), so it accepts any request; set it to require one.

The device this example creates

Device 389023  "Chipkin Example B-AS"   (Vendor 389 - Chipkin Automation Systems)
    │
    ├── Analog Input 1       "Bronze"      Present_Value  21.5    (REAL, degrees Celsius)
    ├── Binary Input 1       "Emerald"     Present_Value  inactive  (0 = inactive / 1 = active)
    ├── Multi-State Input 1  "Hot Pink"    Present_Value  1       (state, 1..3)
    └── Network Port 1       "Vermilion"   the BACnet/IP port     (required on every device)

These are the same base-series sensor objects every example in the series carries; a real Authorization Server would also carry the Access User / Access Rights / Access Credential objects Clause 17 defines, but those only matter once AA-AS-B itself can be executed (see below) - adding them without a working service exchange behind them would not demonstrate anything.

What this example supports

The example implements the capabilities below - and, deliberately, not AA-AS-B. This is not the full B-AS profile; it is the DS/DM base plus an honestly-documented gap.

BIBBs (BACnet Interoperability Building Blocks)

BIBB Description Supported
DS-RP-B Data Sharing - ReadProperty - B ✅
DM-DDB-B Device Management - Dynamic Device Binding - B ✅
DM-DOB-B Device Management - Dynamic Object Binding - B ✅
DM-DCC-B Device Management - DeviceCommunicationControl - B ✅
AA-AS-B Authorization - Authorization Server - B ❌ blocked on stack #2043 - see TODO.md

AA-AS-B: blocked on the stack. At the Stack Pin (6.x @ 64b2cfac5, 6.0.23) the policy exports (BACnetStack_AddAuthorizationPolicy, SetAuthorizationPolicyEntry, SetAuthorizationPolicyEnabled) exist only in CASBACnetStackTestToolDLL.h, and the AuthRequest service handler itself (BACnetAuthRequestProcessor) compiles only with BACNET_STACK_TESTTOOL. A customer build - the only kind this series uses - therefore refuses AuthRequest and cannot configure a policy for it to be evaluated against. The stack owner ruled on 2026-10-15 that these are not promoted to the customer interface for now. Full evidence is in TODO.md. Stack issue: chipkin/cas-bacnet-stack#2043.

Services (executed / B-side)

Service Notes
ReadProperty Responds to property reads (DS-RP-B).
Who-Is / I-Am Answers Who-Is with I-Am, and broadcasts an I-Am on start-up (DM-DDB-B).
Who-Has / I-Have Answers Who-Has with I-Have (DM-DOB-B).
DeviceCommunicationControl Stops/resumes communication, optionally timed/passworded (DM-DCC-B).

Object types

Object type Instance Name
Device 389023 Chipkin Example B-AS
Analog Input 1 Bronze
Binary Input 1 Emerald
Multi-State Input 1 Hot Pink
Network Port 1 Vermilion

Every required property of every object, and who answers it, is in docs/PICS.md.

Requires the CAS BACnet Stack (licensed product)

This example builds against the CAS BACnet Stack, which is a commercial Chipkin product - it is not free or open source, and there is no public/trial build. The stack is referenced here as the private git submodule submodules/cas-bacnet-stack; you can only fetch and build it once you have a CAS BACnet Stack license and access to that repository.

To get the CAS BACnet Stack (and access to build this example), contact Chipkin: https://store.chipkin.com/services/stacks/bacnet-stack or sales@chipkin.com.

You do not need a stack licence to read this example, or to run a prebuilt release binary. The licence is what lets you build it - that is the part the stack submodule gates.

What's in this repository

This is a self-contained project. It ships:

  • main.cpp - the example device.
  • common/ - the shared helper (UDP, callbacks, CLI, keyboard) vendored in.
  • CMakeLists.txt - the build, the same on Windows, Linux, and macOS.
  • docs/PICS.md - the conformance statement.
  • TODO.md - the AA-AS-B gap, with evidence and the filed stack issue.
  • tests/ - the Wire Tests (see Wire Tests), and wiretest/, the series' shared Python harness they are written against (vendored, like common/).
  • submodules/cas-bacnet-stack/ - the CAS BACnet Stack as a git submodule (private; requires a license - see above). Its sources are compiled into the executable, so there is no library or DLL to build, ship, or install.

Prerequisites

  • A C++17 compiler (MSVC, GCC, or Clang).
  • CMake >= 3.15.
  • Git (to fetch the stack submodule).

Windows

Linux / macOS

  • Debian/Ubuntu: sudo apt install build-essential cmake git
  • macOS: xcode-select --install and brew install cmake

Build

CMake only, and the same two commands on every platform:

git clone --recursive https://github.com/chipkin/BACnetProfileExample-B-AS-CPP.git
cd BACnetProfileExample-B-AS-CPP

cmake -B build -S .
cmake --build build --config Release

Already cloned without --recursive? Run git submodule update --init --recursive first - the build needs the stack submodule.

The first build takes a few minutes - it compiles the entire CAS BACnet Stack (~600 source files) into the executable. Rebuilds after that are incremental and take seconds.

If your CAS BACnet Stack lives somewhere other than the bundled submodule, point CMake at it: cmake -B build -S . -D CAS_STACK_DIR=/path/to/cas-bacnet-stack.

Run

# Linux / macOS
./build/BACnetExampleBAS

# Windows
.\build\Release\BACnetExampleBAS.exe

Expected output:

BACnet Authorization Server (B-AS) Example - C++ v1.1.0
CAS BACnet Stack version: 6.0.23.0
Common helper (common/) version: 3.4.0
FYI: Listening for BACnet/IP on UDP port 47808 (Network Port 1).
TX 21 bytes to 192.168.3.255:47808 (broadcast) (Network Port 1) - Unconfirmed: I-Am
FYI: Device 389023 ("Chipkin Example B-AS") ready. Vendor ID 389. Press 'h' for help.

The TX line is the start-up I-Am the device broadcasts to announce itself. It goes to the local subnet broadcast address (here 192.168.3.255, computed from the Network Port's interface), not the global 255.255.255.255. As clients talk to the device you'll see RX ... bytes from ... and TX ... bytes to ... lines showing the traffic.

The device listens on UDP 47808 (BACnet/IP). Allow that port through your firewall. To use a different port, pass --port (see below).

A wall of red Error: lines at start-up is expected and is not your bug - it is the stack's own debug logging (the device hearing its own broadcast I-Am, and a one-time BACnet/SC UUID notice). TUTORIAL.md explains both.

Command-line options

Option Default Meaning
--port <n> 47808 UDP port to listen on (BACnet/IP).
--deviceID <n> 389023 The device's BACnet instance number (BACnet requires this to be configurable).
--help, -h - Show usage and exit.
--version - Print the example, stack, and common/ helper versions, then exit.

Interactive commands

While the example runs, these keys are available:

Key Action
h Show the version information and this command list.
q Quit.
up arrow Increase Analog Input 1 (Bronze) by 1.1.
down arrow Decrease Analog Input 1 (Bronze) by 1.1.

The up/down keys change the live Present_Value of the analog input, so a client re-reading it sees the new value.

Verify

Use a BACnet client such as the CAS BACnet Explorer:

  1. Discover - send a Who-Is. The device replies with I-Am from instance 389023 (vendor 389). It also broadcasts an I-Am at start-up.
  2. Who-Has / I-Have - send a Who-Has for object name Bronze. The device replies with I-Have.
  3. Browse the object model - the device shows five objects: the Device (Chipkin Example B-AS), the three sensors, and the Network Port (Vermilion). Reading the Device's Object_List returns all five.
  4. Read the Device - ReadProperty 389023 -> Object_Name returns "Chipkin Example B-AS"; Protocol_Revision returns 30; Description returns the profile description string; Protocol_Services_Supported lists read-property, device-communication-control, i-am, i-have, who-has, who-is - and nothing else.
  5. Read a sensor - ReadProperty Analog Input 1 -> Present_Value returns 21.5; Units returns degrees-Celsius. Repeat for Binary Input 1 ("Emerald") and Multi-State Input 1 ("Hot Pink").
  6. Confirm the profile boundary - a WriteProperty or ReadPropertyMultiple to any object is rejected with unrecognized-service - neither is part of this profile's required set.
  7. DeviceCommunicationControl (DM-DCC-B) - send DeviceCommunicationControl with enableDisable = disable-initiation. The device answers with a SimpleACK and logs the request; send enable to restore normal operation.

For a property-by-property review against the conformance statement, see TUTORIAL.md.

Wire Tests

Part of the checks above, automated: a Python BACnet client drives the running example over BACnet/IP from outside it, the way a client discovers a device - Who-Is, the Device's Object_List, then for every object its Property_List and a ReadProperty of every property it lists. Every read must come back as a value; an Error, Reject or Abort fails the run. Python 3 standard library only:

python3 tests/run_wire_tests.py --exe build/BACnetExampleBAS          # Linux/macOS
python tests\run_wire_tests.py --exe build\Release\BACnetExampleBAS.exe   # Windows

It ends with ALL WIRE TESTS PASSED (exit 0). CI runs it on Linux after the smoke test. tests/README.md says what each check proves. It tests the DS/DM base only: there is no AuthRequest to test (see the Blocked Example note at the top).

The BACnet profile example series

There is one example repository per standardized device profile in ASHRAE 135-2024 Annex L. An example marked ⛔ is blocked: the stack cannot yet perform that profile's function through its customer interface, and the example's README says what it does today. Pick the profile your device claims, then the language you build in. "Ask" means the example hasn't been built yet for that language - contact Chipkin if you need one.

Controllers (Annex L.4)

Profile C++ Node.js C# Rust Python Go
B-SS Smart Sensor B-SS-CPP B-SS-Node B-SS-CS B-SS-Rust B-SS-Python B-SS-Go
B-SA Smart Actuator B-SA-CPP Ask Ask Ask Ask Ask
B-ASC Application Specific Controller B-ASC-CPP B-ASC-Node Ask Ask Ask Ask
B-AAC Advanced Application Controller B-AAC-CPP Ask Ask Ask Ask Ask
B-BC Building Controller B-BC-CPP Ask Ask Ask Ask Ask

Life safety controllers (Annex L.5)

Profile C++ Node.js C# Rust Python Go
B-LSC Life Safety Controller B-LSC-CPP 🚧 Ask Ask Ask Ask Ask
B-ALSC Advanced Life Safety Controller B-ALSC-CPP Ask Ask Ask Ask Ask

Access control controllers (Annex L.6)

Profile C++ Node.js C# Rust Python Go
B-ACC Access Control Controller B-ACC-CPP ⛔ blocked on stack #2150, #2044 Ask Ask Ask Ask Ask
B-AACC Advanced Access Control Controller B-AACC-CPP ⛔ blocked on stack #2150, #2044 Ask Ask Ask Ask Ask

Lighting controllers (Annex L.11)

Profile C++ Node.js C# Rust Python Go
B-LD Lighting Device B-LD-CPP Ask Ask Ask Ask Ask
B-LS Lighting Supervisor B-LS-CPP Ask Ask Ask Ask Ask

Elevator controllers (Annex L.13)

Profile C++ Node.js C# Rust Python Go
B-EM Elevator Monitor B-EM-CPP Ask Ask Ask Ask Ask
B-EC Elevator Controller B-EC-CPP Ask Ask Ask Ask Ask
B-AEC Advanced Elevator Controller B-AEC-CPP Ask Ask Ask Ask Ask

Authentication and authorization (Annex L.14)

Profile C++ Node.js C# Rust Python Go
B-AS Authorization Server B-AS-CPP ⛔ blocked on stack #2043 Ask Ask Ask Ask Ask

Miscellaneous (Annex L.7, combinable with any one family)

Profile C++ Node.js C# Rust Python Go
B-BBMD Broadcast Management Device B-BBMD-CPP Ask Ask Ask Ask Ask
B-ACDC Access Control Door Controller B-ACDC-CPP Ask Ask Ask Ask Ask
B-ACCR Access Control Credential Reader B-ACCR-CPP ⛔ blocked on stack #3934 Ask Ask Ask Ask Ask
B-RTR Router B-RTR-CPP Ask Ask Ask Ask Ask
B-GW Gateway B-GW-CPP Ask Ask Ask Ask Ask
B-DAP Device Address Proxy B-DAP-CPP ⛔ blocked on stack #2032 Ask Ask Ask Ask Ask
B-SCHUB BACnet/SC Hub B-SCHUB-CPP Ask Ask Ask Ask Ask
B-GENERAL General device (Annex L.8) (satisfied by every example above) — — — — —

Operator interfaces and workstations (Annex L.1–L.3, L.9–L.10, L.12)

Client-side profiles.

Profile C++ Node.js C# Rust Python Go
B-OD Operator Display B-OD-CPP Ask Ask Ask Ask Ask
B-OWS Operator Workstation planned — — — — —
B-AWS Advanced Operator Workstation planned — — — — —
B-XAWS Extended Advanced Operator Workstation planned — — — — —
B-LSAP Life Safety Annunciator Panel planned — — — — —
B-LSWS Life Safety Workstation planned — — — — —
B-ALSWS Advanced Life Safety Workstation planned — — — — —
B-ACSD Access Control Security Display planned — — — — —
B-ACWS Access Control Workstation planned — — — — —
B-AACWS Advanced Access Control Workstation planned — — — — —
B-LOD Lighting Operator Display planned — — — — —
B-ALWS Advanced Lighting Workstation planned — — — — —
B-LCS Lighting Control Station planned — — — — —
B-ALCS Advanced Lighting Control Station planned — — — — —
B-ED Elevator Display planned — — — — —
B-EWS Elevator Workstation planned — — — — —
B-AEWS Advanced Elevator Workstation planned — — — — —

🚧 = in progress. ⛔ = Blocked Example (blocked on the named stack gap). "Ask" = not yet built for that language; contact Chipkin if you need it. Profile definitions: ANSI/ASHRAE 135-2024 Annex L. BIBB definitions: Annex K. Get the stack: https://store.chipkin.com/services/stacks/bacnet-stack.

References

See also TUTORIAL.md, docs/PICS.md, CHANGELOG.md, AGENTS.md, and TODO.md.

About

CAS BACnet Stack profile example: B-AS (Authorization Server) — C++ (planned)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages