Skip to content
Contact Us

CAS BACnet Stack

Native BACnet for your devices and applications

A royalty-free C/C++ library with the source code included. Add BACnet server and client communication over BACnet/IP, BACnet MS/TP (Multidrop Serial Bus/Token Passing) and BACnet/SC (BACnet Secure Connect), from bare metal microcontrollers to embedded Linux or Windows.

Diagram of BACnet devices on a corporate BACnet/IP network, drawn in blue, an MS/TP trunk, drawn in red and dashed, and a BACnet/SC connection, drawn in gold and dotted, with messages moving quickly between the devices
device installations
1,000,000+
of BACnet experience
25+ years
BACnet device profiles
39

Who uses it

Used by the largest companies around the world

Manufacturers of building controls, HVAC equipment and industrial systems embed the stack in the products they ship.

  • Schindler
  • Honeywell
  • Big Ass Fans
  • Yaskawa
  • WindowMaster
  • Johnson Controls

What it is

What is the CAS BACnet Stack?

The CAS BACnet Stack is a royalty-free C/C++ library, with the source code included, that adds native BACnet server and client communication to your embedded device or your application.

  • BACnet without writing a protocol stack

    Royalty-free, with the full C/C++ source code: no per-device fees, and nothing hidden from your engineers.

  • One library from microcontroller to server

    The same stack runs in Zephyr firmware on an ESP32-S3, on embedded Linux and on Windows.

  • BACnet Secure Connect built in

    BACnet/SC beside BACnet/IP and MS/TP, with Chipkin’s own hub and certificate authority for the sites that need them.

  • The device profile you need

    39 device profiles with every required building block, each one published on this page.

Supported scope of the CAS BACnet Stack
StandardANSI/ASHRAE Standard 135-2024. A build reports Protocol Revision 30 by default, and can report any revision from 24, the lowest a build accepts.
Device profiles39 device profiles in Annex L of the standard have every required building block (BIBB) implemented, from the 160 BIBBs the stack implements.
DecodingDecodes BACnet messages to JSON or XML, which suits logging and web-based tools.

Chipkin has built BACnet software for 25+ years, and the stack is part of 1,000,000+ device installations.

It also powers Chipkin's own CAS BACnet Explorer, which thousands of people a day use to discover and interrogate their BACnet devices.

Download an example binaryTalk to an engineer

Fully featured

Everything a BACnet device needs, in one library

One library covers the roles, the data links and the objects a BACnet product needs, from a microcontroller to a server application.

  • Server and client

    Answers requests as a BACnet server, the role of a field device, and sends them as a client, the role of an HMI or a data logger.

  • BACnet/IP, MS/TP and BACnet/SC

    BACnet/IP with BBMD and foreign device registration, BACnet MS/TP, and BACnet Secure Connect, all from one library.

  • Objects from Analog Input to Trend Log

    61 of the standard's object types supported in full and 3 in part, so a device presents the objects its type calls for.

  • Router, BBMD and hub roles

    The same library builds a BACnet router, a broadcast management device and a BACnet/SC hub, each with a public example project.

  • C/C++, C#, Java, Python, Node.js, Go and Rust

    Call the stack from the language your product already uses.

  • Fits a microcontroller

    The embedded build target turns every object type, service and data link off until you enable the ones you use, and a Zephyr module runs the stack on an ESP32-S3 over BACnet/IP and MS/TP.

Hello world

BACnet in your language

  1. Register the callbacks
  2. Add a device and its objects
  3. Call the stack in a loop

C/C++

#include "CASBACnetStackAdapter.h"

const uint32_t DEVICE_INSTANCE = 389001;
const uint16_t OBJECT_TYPE_ANALOG_INPUT = 0;
const uint16_t OBJECT_TYPE_BINARY_OUTPUT = 4;
const uint16_t OBJECT_TYPE_MULTI_STATE_VALUE = 19;

// The stack calls this when a client reads a REAL property. Answer from your own data.
bool CallbackGetPropertyReal(const uint32_t deviceInstance, const uint16_t objectType, const uint32_t objectInstance, const uint32_t propertyIdentifier, float* value, const bool useArrayIndex, const uint32_t propertyArrayIndex, uint32_t* errorCode) {
	if (propertyIdentifier == BACnetPropertyIdentifier_presentValue && objectType == OBJECT_TYPE_ANALOG_INPUT && objectInstance == 101) {
		*value = 99.6f;
		return true;
	}
	return false;
}

// Your transport: copy one received UDP datagram into the buffer, or return 0 when none is waiting.
uint16_t CallbackReceiveMessage(...) {
	return 0; // ...
}
uint16_t CallbackSendMessage(...) {
	return 0; // ...
}
CASBACnetTime CallbackGetSystemTime() {
	return time(NULL);
}

int main() {
	LoadBACnetFunctions();
	BACnetStack_RegisterCallbackReceiveMessageForPort(CallbackReceiveMessage);
	BACnetStack_RegisterCallbackSendMessageForPort(CallbackSendMessage);
	BACnetStack_RegisterCallbackGetSystemTime(CallbackGetSystemTime);
	BACnetStack_RegisterCallbackGetPropertyReal(CallbackGetPropertyReal);

	BACnetStack_AddDevice(DEVICE_INSTANCE);
	BACnetStack_AddObject(DEVICE_INSTANCE, OBJECT_TYPE_ANALOG_INPUT, 101);
	BACnetStack_AddObject(DEVICE_INSTANCE, OBJECT_TYPE_BINARY_OUTPUT, 102);
	BACnetStack_AddObject(DEVICE_INSTANCE, OBJECT_TYPE_MULTI_STATE_VALUE, 103);

	for (;;) {
		BACnetStack_Tick();
	}
}

C#

using System;
using CASBACnetStack;

unsafe class Hello
{
    const uint DeviceInstance = 389001;

    // The stack calls this when a client reads a REAL property. Answer from your own data.
    static bool GetPropertyReal(uint deviceInstance, ushort objectType, uint objectInstance, uint propertyIdentifier, float* value, bool useArrayIndex, uint propertyArrayIndex, uint* errorCode)
    {
        if (propertyIdentifier == (uint)BACnetPropertyIdentifier.presentValue && objectType == CASBACnetStackAdapter.OBJECT_TYPE_ANALOG_INPUT && objectInstance == 101)
        {
            *value = 99.6f;
            return true;
        }
        return false;
    }

    // Your transport: copy one received UDP datagram into the buffer, or return 0 when none is waiting.
    static ushort ReceiveMessage(...)
    {
        return 0; // ...
    }
    static ushort SendMessage(...)
    {
        return 0; // ...
    }
    static long GetSystemTime()
    {
        return DateTimeOffset.UtcNow.ToUnixTimeSeconds();
    }

    static void Main()
    {
        // Keep the delegates in fields or variables that live as long as the stack does.
        var receiveMessage = new CASBACnetStackAdapter.FPCallbackReceiveMessageForPort(ReceiveMessage);
        var sendMessage = new CASBACnetStackAdapter.FPCallbackSendMessageForPort(SendMessage);
        var getSystemTime = new CASBACnetStackAdapter.FPCallbackGetSystemTime(GetSystemTime);
        var getPropertyReal = new CASBACnetStackAdapter.FPCallbackGetPropertyReal(GetPropertyReal);
        CASBACnetStackAdapter.BACnetStack_RegisterCallbackReceiveMessageForPort(receiveMessage);
        CASBACnetStackAdapter.BACnetStack_RegisterCallbackSendMessageForPort(sendMessage);
        CASBACnetStackAdapter.BACnetStack_RegisterCallbackGetSystemTime(getSystemTime);
        CASBACnetStackAdapter.BACnetStack_RegisterCallbackGetPropertyReal(getPropertyReal);

        CASBACnetStackAdapter.BACnetStack_AddDevice(DeviceInstance);
        CASBACnetStackAdapter.BACnetStack_AddObject(DeviceInstance, CASBACnetStackAdapter.OBJECT_TYPE_ANALOG_INPUT, 101);
        CASBACnetStackAdapter.BACnetStack_AddObject(DeviceInstance, CASBACnetStackAdapter.OBJECT_TYPE_BINARY_OUTPUT, 102);
        CASBACnetStackAdapter.BACnetStack_AddObject(DeviceInstance, CASBACnetStackAdapter.OBJECT_TYPE_MULTI_STATE_VALUE, 103);

        for (;;)
        {
            CASBACnetStackAdapter.BACnetStack_Tick();
        }
    }
}

Java

import com.chipkin.bacnet.BACnetConstants;
import com.chipkin.bacnet.CASBACnetStackAdapter;
import com.chipkin.bacnet.ICASBACnetStackLibrary;
import com.sun.jna.Pointer;

public class Hello {
    static final int DEVICE_INSTANCE = 389001;
    static final short OBJECT_TYPE_MULTI_STATE_VALUE = 19;

    public static void main(String[] args) throws Exception {
        ICASBACnetStackLibrary stack = new CASBACnetStackAdapter().getLibrary();

        // Your transport: copy one received UDP datagram into the buffer, or return 0 when none is waiting.
        // Keep each callback in a variable that lives as long as the stack does, or JNA may free it.
        ICASBACnetStackLibrary.FPCallbackReceiveMessageForPort receiveMessage = new ICASBACnetStackLibrary.FPCallbackReceiveMessageForPort() {
            public short callback(...) {
                return 0; // ...
            }
        };
        ICASBACnetStackLibrary.FPCallbackSendMessageForPort sendMessage = new ICASBACnetStackLibrary.FPCallbackSendMessageForPort() {
            public short callback(...) {
                return 0; // ...
            }
        };
        ICASBACnetStackLibrary.FPCallbackGetSystemTime getSystemTime = new ICASBACnetStackLibrary.FPCallbackGetSystemTime() {
            public long callback() {
                return System.currentTimeMillis() / 1000L;
            }
        };
        // The stack calls this when a client reads a REAL property. Answer from your own data.
        ICASBACnetStackLibrary.FPCallbackGetPropertyReal getPropertyReal = new ICASBACnetStackLibrary.FPCallbackGetPropertyReal() {
            public byte callback(int deviceInstance, short objectType, int objectInstance, int propertyIdentifier, Pointer value, byte useArrayIndex, int propertyArrayIndex, Pointer errorCode) {
                if (propertyIdentifier == ICASBACnetStackLibrary.BACnetPropertyIdentifier.presentValue && objectType == BACnetConstants.OBJECT_TYPE_ANALOG_INPUT && objectInstance == 101) {
                    value.setFloat(0, 99.6f);
                    return 1;
                }
                return 0;
            }
        };
        stack.BACnetStack_RegisterCallbackReceiveMessageForPort(receiveMessage);
        stack.BACnetStack_RegisterCallbackSendMessageForPort(sendMessage);
        stack.BACnetStack_RegisterCallbackGetSystemTime(getSystemTime);
        stack.BACnetStack_RegisterCallbackGetPropertyReal(getPropertyReal);

        stack.BACnetStack_AddDevice(DEVICE_INSTANCE);
        stack.BACnetStack_AddObject(DEVICE_INSTANCE, BACnetConstants.OBJECT_TYPE_ANALOG_INPUT, 101);
        stack.BACnetStack_AddObject(DEVICE_INSTANCE, BACnetConstants.OBJECT_TYPE_BINARY_OUTPUT, 102);
        stack.BACnetStack_AddObject(DEVICE_INSTANCE, OBJECT_TYPE_MULTI_STATE_VALUE, 103);

        for (;;) {
            stack.BACnetStack_Tick();
        }
    }
}

Python

import ctypes
import time
from CASBACnetStackAdapter import libname, bacnet_objectType
import CASBACnetStackAdapterBindings as bacnet

DEVICE_INSTANCE = 389001

bacnet.bind(ctypes.CDLL(libname))


# The stack calls this when a client reads a REAL property. Answer from your own data.
@bacnet.FPCallbackGetPropertyReal
def get_property_real(device_instance, object_type, object_instance, property_identifier, value, use_array_index, property_array_index, error_code):
    if property_identifier == bacnet.BACnetPropertyIdentifier.presentValue and object_type == bacnet_objectType["analogInput"] and object_instance == 101:
        value[0] = 99.6
        return True
    return False


# Your transport: copy one received UDP datagram into the buffer, or return 0 when none is waiting.
@bacnet.FPCallbackReceiveMessageForPort
def receive_message(...):
    return 0  # ...


@bacnet.FPCallbackSendMessageForPort
def send_message(...):
    return 0  # ...


@bacnet.FPCallbackGetSystemTime
def get_system_time():
    return int(time.time())


bacnet.BACnetStack_RegisterCallbackReceiveMessageForPort(receive_message)
bacnet.BACnetStack_RegisterCallbackSendMessageForPort(send_message)
bacnet.BACnetStack_RegisterCallbackGetSystemTime(get_system_time)
bacnet.BACnetStack_RegisterCallbackGetPropertyReal(get_property_real)

bacnet.BACnetStack_AddDevice(DEVICE_INSTANCE)
bacnet.BACnetStack_AddObject(DEVICE_INSTANCE, bacnet_objectType["analogInput"], 101)
bacnet.BACnetStack_AddObject(DEVICE_INSTANCE, bacnet_objectType["binaryOutput"], 102)
bacnet.BACnetStack_AddObject(DEVICE_INSTANCE, bacnet_objectType["multiStateValue"], 103)

while True:
    bacnet.BACnetStack_Tick()

Node.js

const bacnet = require('@chipkin/cas-bacnet-stack');

const DEVICE_INSTANCE = 389001;
const OBJECT_TYPE_ANALOG_INPUT = 0;
const OBJECT_TYPE_BINARY_OUTPUT = 4;
const OBJECT_TYPE_MULTI_STATE_VALUE = 19;

// Your transport: copy one received UDP datagram into the buffer, or return 0 when none is waiting.
bacnet.BACnetStack_RegisterCallbackReceiveMessageForPort((...) => {
    return 0; // ...
});
bacnet.BACnetStack_RegisterCallbackSendMessageForPort((...) => {
    return 0; // ...
});
bacnet.BACnetStack_RegisterCallbackGetSystemTime(() => Math.floor(Date.now() / 1000));

// The stack calls this when a client reads a REAL property. Answer from your own data.
bacnet.BACnetStack_RegisterCallbackGetPropertyReal((deviceInstance, objectType, objectInstance, propertyIdentifier, value, useArrayIndex, propertyArrayIndex, errorCode) => {
    if (propertyIdentifier === bacnet.BACnetPropertyIdentifier.presentValue && objectType === OBJECT_TYPE_ANALOG_INPUT && objectInstance === 101) {
        value.writeFloatLE(99.6, 0);
        return true;
    }
    return false;
});

bacnet.BACnetStack_AddDevice(DEVICE_INSTANCE);
bacnet.BACnetStack_AddObject(DEVICE_INSTANCE, OBJECT_TYPE_ANALOG_INPUT, 101);
bacnet.BACnetStack_AddObject(DEVICE_INSTANCE, OBJECT_TYPE_BINARY_OUTPUT, 102);
bacnet.BACnetStack_AddObject(DEVICE_INSTANCE, OBJECT_TYPE_MULTI_STATE_VALUE, 103);

setInterval(() => bacnet.BACnetStack_Tick(), 10);

Go

package main

/*
#include "CASBACnetStackDLL.h"
*/
import "C"

import (
	"time"

	casbacnetstack "github.com/chipkin/cas-bacnet-stack/adapters/golang"
)

const deviceInstance = 389001
const objectTypeAnalogInput = 0
const objectTypeBinaryOutput = 4
const objectTypeMultiStateValue = 19

// The stack calls this when a client reads a REAL property. Answer from your own data.
func getPropertyReal(deviceInstance uint32, objectType uint16, objectInstance uint32, propertyIdentifier uint32, value *float32, useArrayIndex bool, propertyArrayIndex uint32, errorCode *uint32) bool {
	if propertyIdentifier == C.BACnetPropertyIdentifier_presentValue && objectType == objectTypeAnalogInput && objectInstance == 101 {
		*value = 99.6
		return true
	}
	return false
}

// Your transport: copy one received UDP datagram into the buffer, or return 0 when none is waiting.
func receiveMessage(...) uint16 {
	return 0 // ...
}

func sendMessage(...) uint16 {
	return 0 // ...
}

func getSystemTime() int64 {
	return time.Now().Unix()
}

func main() {
	casbacnetstack.CallbackReceiveMessageForPort = receiveMessage
	casbacnetstack.CallbackSendMessageForPort = sendMessage
	casbacnetstack.CallbackGetSystemTime = getSystemTime
	casbacnetstack.CallbackGetPropertyReal = getPropertyReal
	casbacnetstack.RegisterBACnetStackCallbacks()

	C.BACnetStack_AddDevice(deviceInstance)
	C.BACnetStack_AddObject(deviceInstance, objectTypeAnalogInput, 101)
	C.BACnetStack_AddObject(deviceInstance, objectTypeBinaryOutput, 102)
	C.BACnetStack_AddObject(deviceInstance, objectTypeMultiStateValue, 103)

	for {
		C.BACnetStack_Tick()
		time.Sleep(10 * time.Millisecond)
	}
}

Rust

use cas_bacnet_stack_adapters::*;
use std::time::{SystemTime, UNIX_EPOCH};

const DEVICE_INSTANCE: u32 = 389001;
const OBJECT_TYPE_ANALOG_INPUT: u16 = 0;
const OBJECT_TYPE_BINARY_OUTPUT: u16 = 4;
const OBJECT_TYPE_MULTI_STATE_VALUE: u16 = 19;

// The stack calls this when a client reads a REAL property. Answer from your own data.
extern "C" fn get_property_real(_device_instance: u32, object_type: u16, object_instance: u32, property_identifier: u32, value: *mut f32, _use_array_index: bool, _property_array_index: u32, _error_code: *mut u32) -> bool {
    if property_identifier == BACnetPropertyIdentifier::presentValue && object_type == OBJECT_TYPE_ANALOG_INPUT && object_instance == 101 {
        unsafe { *value = 99.6 };
        return true;
    }
    false
}

// Your transport: copy one received UDP datagram into the buffer, or return 0 when none is waiting.
extern "C" fn receive_message(...) -> u16 {
    0 // ...
}
extern "C" fn send_message(...) -> u16 {
    0 // ...
}
extern "C" fn get_system_time() -> i64 {
    SystemTime::now().duration_since(UNIX_EPOCH).map(|elapsed| elapsed.as_secs() as i64).unwrap_or(0)
}

fn main() -> BACnetResult<()> {
    load()?;
    BACnetStack_RegisterCallbackReceiveMessageForPort(Some(receive_message))?;
    BACnetStack_RegisterCallbackSendMessageForPort(Some(send_message))?;
    BACnetStack_RegisterCallbackGetSystemTime(Some(get_system_time))?;
    BACnetStack_RegisterCallbackGetPropertyReal(Some(get_property_real))?;

    BACnetStack_AddDevice(DEVICE_INSTANCE)?;
    BACnetStack_AddObject(DEVICE_INSTANCE, OBJECT_TYPE_ANALOG_INPUT, 101)?;
    BACnetStack_AddObject(DEVICE_INSTANCE, OBJECT_TYPE_BINARY_OUTPUT, 102)?;
    BACnetStack_AddObject(DEVICE_INSTANCE, OBJECT_TYPE_MULTI_STATE_VALUE, 103)?;

    loop {
        BACnetStack_Tick()?;
    }
}

Zephyr

#include "cas_bacnet_zephyr.h"
#include "CASBACnetStackAdapter.h"

const uint32_t DEVICE_INSTANCE = 389001;
const uint16_t OBJECT_TYPE_ANALOG_INPUT = 0;

// The stack calls this when a client reads a REAL property. Answer from your own data.
bool CallbackGetPropertyReal(const uint32_t deviceInstance, const uint16_t objectType, const uint32_t objectInstance, const uint32_t propertyIdentifier, float* value, const bool useArrayIndex, const uint32_t propertyArrayIndex, uint32_t* errorCode) {
	if (propertyIdentifier == BACnetPropertyIdentifier_presentValue && objectType == OBJECT_TYPE_ANALOG_INPUT && objectInstance == 101) {
		*value = 99.6f;
		return true;
	}
	return false;
}

// Register the callback, add the device and its objects, then open the data link.
static bool Setup() {
	BACnetStack_RegisterCallbackGetPropertyReal(CallbackGetPropertyReal);
	BACnetStack_AddDevice(DEVICE_INSTANCE);
	BACnetStack_AddObject(DEVICE_INSTANCE, OBJECT_TYPE_ANALOG_INPUT, 101);

	// MS/TP over a UART with an RS-485 driver-enable pin, described in the devicetree.
	const cbz::mstp::Settings mstp = { 10, 38400, 127, 1 };
	return cbz::mstp::Open(1, mstp); // or, for BACnet/IP over Zephyr sockets: cbz::bip::Open(1, 47808)
}

int main() {
	cbz::Start(Setup, NULL);
	return 0;
}

Real-world applications

What manufacturers build with it

These are anonymized examples of products that embed the CAS BACnet Stack, on embedded Linux, on microcontrollers and on custom industrial platforms.

On a real network

Whatever part your device plays

A whole building on one BACnet network. The corporate BACnet/IP network, drawn in blue, carries the operator workstation, building and plant controllers, a Modbus gateway, an elevator controller and a lighting controller. Routers join it to two MS/TP trunks, drawn in red, with room and fan coil controllers, a smart sensor and actuators. A secure connect hub joins it, over BACnet/SC connections drawn in gold, to two secure controllers. Every one of them can run the CAS BACnet Stack.

Diagram of a building's BACnet network: seventeen devices on a corporate BACnet/IP network, drawn in blue, two MS/TP trunks, drawn in red and dashed, and BACnet/SC connections, drawn in gold and dotted, with messages moving between the devices

Performance

Measured on a Linux build

Chipkin measures a Linux build of the stack configured as a BACnet Building Controller (B-BC) with the objects of its B-BC example, over BACnet/IP, with no network in between: the time is from handing the stack a request to getting its reply.

heap after setup, Linux 32-bit build
7.8 KiB
static RAM, Linux 32-bit build
1.3 KiB
median ReadProperty reply, Linux 64-bit build
9.7 µs
median ReadPropertyMultiple reply (20 properties), Linux 64-bit build
46.8 µs
in the unit suite, which runs 77.9% of the stack's source lines
13,185 tests

Measured for stack version 6.0.23

Professional support

Get professional support from the engineers who maintain the stack

The engineers who maintain the stack answer your questions. Pick the help that fits where your project is.

  • Consultation

    Talk directly with BACnet specialists about your project before you write code.

  • Expert support

    Remote desktop sessions, email and phone calls with Chipkin engineers, from your first build through troubleshooting.

  • Integration assistance

    Help registering callbacks, adding objects and bringing your first device onto the network.

  • Custom development

    A BACnet feature, object or platform port built to your requirements by the engineers who maintain the stack.

  • Long-term maintenance

    Chipkin continuously adds features and maintains the stack, with new versions released regularly.

  • Manual and example projects

    A manual that covers every function, callback and constant, a Quick Start that builds a working server, and public example projects on GitHub.

Tell Chipkin what you are building and which of these would help. An engineer replies with the next step.

Contact Us

Products and services

Everything around the stack that gets your device to market

Discover and test your device, run BACnet/SC with a hub and your own certificates, and have it tested before it goes to the test lab. The Explorer is free.

  • Discover it: CAS BACnet Explorer

    Find your device on the network, test it and debug it. Built on the CAS BACnet Stack, and used by thousands of people a day. Free, with no licence key, and commercial use is allowed.

  • Cross subnets: CAS BACnet BBMD

    Gets BACnet/IP broadcast messages across subnets, so a test lab with more than one subnet behaves like the site you are building for.

  • Connect securely: Chipkin BACnet SC Hub

    The central connection point for BACnet/SC devices, relaying their encrypted traffic, on Windows or Linux.

  • Issue certificates: Chipkin BACnet SC Certificate Authority

    Signs certificates for BACnet/SC hubs and devices, tracks the requests and manages revocation, offline, on Windows or Linux.

  • Test it: VeriBACnet

    The test harness Chipkin uses to test the stack, pointed at your own device before you submit it for testing, after a firmware change or in your build pipeline.

  • Pre-test services: device testing service

    Chipkin engineers run the standard test plans against your device and help with the documentation, so it arrives at the test lab ready.

Get started

Run an example, then build your own

  1. Run an example

    Every device profile example publishes a Windows and a Linux binary. Run one and a BACnet device is on your network before you write any code.

    Download the B-SS example
  2. Build the Quick Start

    Build a working BACnet server device of your own, step by step.

    Open the Quick Start
  3. Look it up

    Every function, callback and constant of the interface, with its signature.

    Open the API reference

Also in the manual:Object referenceData linksGuidesMoving from version 5C/C++ server and client example

Worked through the Quick Start and ready to plan your own product? Tell Chipkin what you are building and an engineer will help with the next step.

Contact Us

Device profiles

39 device profiles, every required building block implemented

Every device profile below has every BIBB it requires implemented in the stack. 21 of them have a public C++ example project you can download and run.

Controllerserver role

Life Safety Controllerserver role

Access Control Controllerserver role

Miscellaneousserver role

Lighting Controllerserver role

Elevator Controllerserver role

Authentication & Authorizationserver role

Operator Interfaceclient role

  • Cross-Domain Advanced WorkstationB-XAWS, every required BIBB implemented
  • Advanced Operator WorkstationB-AWS, every required BIBB implemented
  • Operator WorkstationB-OWS, every required BIBB implemented
  • Operator DisplayB-OD, every required BIBB implemented

Life Safety Operator Interfaceclient role

  • Advanced Life Safety WorkstationB-ALSWS, every required BIBB implemented
  • Life Safety WorkstationB-LSWS, every required BIBB implemented
  • Life Safety Annunciator PanelB-LSAP, every required BIBB implemented

Access Control Operator Interfaceclient role

  • Advanced Access Control WorkstationB-AACWS, every required BIBB implemented
  • Access Control WorkstationB-ACWS, every required BIBB implemented
  • Access Control Security DisplayB-ACSD, every required BIBB implemented

Generalserver role

  • GeneralB-GENERAL, every required BIBB implemented

Lighting Operator Interfaceclient role

  • Advanced Lighting WorkstationB-ALWS, every required BIBB implemented
  • Lighting Operator DisplayB-LOD, every required BIBB implemented

Lighting Control Stationclient role

  • Advanced Lighting Control StationB-ALCS, every required BIBB implemented
  • Lighting Control StationB-LCS, every required BIBB implemented

Elevator Operator Interfaceclient role

  • Advanced Elevator WorkstationB-AEWS, every required BIBB implemented
  • Elevator WorkstationB-EWS, every required BIBB implemented
  • Elevator DisplayB-ED, every required BIBB implemented

See every profile against every building block

Objects

BACnet objects supported

The stack supports 61 of the standard's object types in full and 3 in part. A half circle marks a type that is partly supported. Not supported: Network Security, which the 2024 edition of the standard removed.

  • Analog Input
  • Analog Output
  • Analog Value
  • Binary Input
  • Binary Output
  • Binary Value
  • Calendar
  • Command
  • Device
  • File
  • Group
  • Loop
  • Multi-state Input
  • Multi-state Output
  • Notification Class
  • Program
  • Schedule
  • Averaging
  • Multi-state Value
  • Trend Log
  • Life Safety Point
  • Life Safety Zone
  • Accumulator
  • Pulse Converter
  • Event Log
  • Global Group
  • Trend Log Multiple
  • Load Control
  • Structured View
  • Access Door
  • Timer
  • Access Credential
  • Access Point
  • Access Rights
  • Access User
  • Access Zone
  • Credential Data Input
  • BitString Value
  • CharacterString Value
  • Date Pattern Value
  • Date Value
  • DateTime Pattern Value
  • DateTime Value
  • Integer Value
  • Large Analog Value
  • OctetString Value
  • Positive Integer Value
  • Time Pattern Value
  • Time Value
  • Notification Forwarder
  • Alert Enrollment
  • Channel
  • Lighting Output
  • Binary Lighting Output
  • Network Port
  • Elevator Group
  • Escalator
  • Lift
  • Staging
  • Color
  • Color Temperature
  • Event Enrollment (partly supported)
  • Audit Log (partly supported)
  • Audit Reporter (partly supported)

Contact us

Start your BACnet integration

Tell Chipkin your platform, whether your device is a BACnet server or a client, and the data link you need: BACnet/IP, BACnet MS/TP or BACnet/SC. A Chipkin engineer replies with how the stack fits that combination and where to start.

  • Consultation: talk directly with BACnet specialists about your project.
  • Integration assistance: get help bringing your first device onto the network.
  • Support: remote desktop sessions, phone calls and email, with hands-on help when you need it.
  • Custom development: a BACnet feature or port built to your requirements.