Skip to content
Version 6.1.0
Contact Us

BACnet/SC reference

Reference material for the BACnet/SC chapter. The BACnet/SC terms it uses (VMAC, device UUID, hub connector, hub function, direct connect, CSR, mTLS) are defined in the manual’s Glossary.

Appendix A - BACnet/SC Network Port Property Reference

Section titled “Appendix A - BACnet/SC Network Port Property Reference”

Properties marked R/W support WriteProperty. Writes typically become pending and are activated by ReinitializeDevice(WARMSTART | ACTIVATE_CHANGES). Property identifiers are listed in the Enumerations reference.

Object_Name is read-only on a Network Port by default, as on every object type; make it writable with BACnetStack_SetPropertyWritable if your product needs that.

Property ID Datatype RW Notes
Object_Identifier 75 ObjectID R network-port,instance
Object_Name 77 CharString R Human-readable; not writable by default (see above)
Object_Type 79 Enum R network-port (56)
Status_Flags 111 BitString R in-alarm, fault, overridden, out-of-service
Reliability 103 Enum R no-fault-detected (0) etc.
Out_Of_Service 81 Boolean R/W Standard out-of-service flag; enabled and writable on an SC Network Port
Network_Type 427 Enum R secure-connect (11)
Protocol_Level 482 Enum R bacnet-application (2)
Reference_Port 483 Unsigned R Lower-layer Network Port reference
Network_Number 425 Unsigned16 R BACnet network number; not writable by default
Network_Number_Quality 426 Enum R unknown(0) / learned(1) / learned-configured(2) / configured(3)
Changes_Pending 416 Boolean R True if pending writes are present
MAC_Address 423 OctetString R VMAC
APDU_Length 399 Unsigned R Negotiated max APDU

The standard makes these mandatory. The stack enables SC_Primary_Hub_Connection_Status itself, and SC_Failover_Hub_Connection_Status while a failover hub URI is configured (it re-checks whenever the SC hub connector settings change). It does not enable Current_Health: the application turns that on with BACnetStack_SetPropertyEnabled.

Property ID Datatype RW Notes
Max_BVLC_Length_Accepted 4194304 Unsigned16 R/W Default 6144 in a STACK_OPTION_TARGET_FULL build, 1600 otherwise
Max_NPDU_Length_Accepted 4194305 Unsigned16 R/W Default 1497
SC_Connect_Wait_Timeout 4194308 Unsigned16 R/W Connect-Request timeout
SC_Disconnect_Wait_Timeout 4194314 Unsigned16 R/W Disconnect-ACK timeout
SC_Heartbeat_Timeout 4194323 Unsigned16 R/W Heartbeat interval
SC_Minimum_Reconnect_Time 4194327 Unsigned16 R/W Backoff floor
SC_Maximum_Reconnect_Time 4194326 Unsigned16 R/W Backoff ceiling
SC_Primary_Hub_URI 4194325 CharString R/W wss://...
SC_Failover_Hub_URI 4194317 CharString R/W wss://... or empty
SC_Primary_Hub_Connection_Status 4194324 Constructed R error, last connect timestamp
SC_Failover_Hub_Connection_Status 4194316 Constructed R Same for failover
SC_Hub_Connector_State 4194318 Enum R 0=no, 1=primary, 2=failover
Operational_Certificate_File 4194306 ObjectID R Reference to File; not directly writable (§16.3)
Issuer_Certificate_Files 511 Array of ObjectID R Exactly two; not directly writable (§16.3)
Certificate_Signing_Request_File 509 ObjectID R Reference to File
Property ID RW Used when
Device_Address_Proxy_Enable 4194338 R/W Present while the device’s physical router is enabled, which is when it proxies device addresses (cl. 19.9)
Device_Address_Proxy_Timeout 4194340 R/W As above
Link_Speed 420 R Effective WebSocket link speed (Real)
Routing_Table 428 R Routing-aware deployments
SC_Failed_Connection_Requests 4194315 R Hub function or direct-accept diagnostics
SC_Hub_Function_Enable 4194322 R Cl. 12.56.90 requires it to be configurable, not writable - configured via BACnetStack_SetBACnetSCHubFunctionConfig, not WriteProperty
SC_Hub_Function_Accept_URIs 4194319 R Only when hub function enabled
SC_Hub_Function_Binding 4194320 R Only when hub function enabled. Every configured hub-function accept URI, comma-separated, whatever the listener’s state
SC_Hub_Function_Connection_Status 4194321 R Constructed, list. Only when hub function enabled
SC_Direct_Connect_Initiate_Enable 4194313 R/W See §16.5/§22
SC_Direct_Connect_Accept_Enable 4194309 R/W See §16.5/§22
SC_Direct_Connect_Accept_URIs 4194310 R Only when direct connect accept enabled
SC_Direct_Connect_Binding 4194311 R Only when direct connect accept enabled. Every configured direct-connect accept URI, comma-separated; never the URI of a peer this node connected to
SC_Direct_Connect_Connection_Status 4194312 R Constructed, list. Only when direct connect enabled

The full list of property identifiers is in the Enumerations reference.

SC_Direct_Connect_Connection_Status and SC_Hub_Function_Connection_Status keep a connection’s entry after it ends, with its final state, its Disconnect Timestamp (for a failed initiated attempt, FAILED_TO_CONNECT with the Connect Timestamp of the attempt) and, when it ended with an error, its Error and Error Details. A live connection stays listed, as CONNECTED, while it disconnects, until its finished entry replaces it. A peer that connects again replaces its own entry. Each list keeps at most 8 finished entries, dropping the oldest first; entries for live connections are never dropped.

A direct connection this port is initiating is listed from the start of the attempt, while its WebSocket opens and while it waits for the Connect-Accept: NOT_CONNECTED (the connection-state list has no “attempting” value), with the URI it is using, both timestamps unspecified and no Peer VMAC or UUID. The same entry becomes CONNECTED when the peer accepts or, if the attempt fails, is recorded as FAILED_TO_CONNECT; an attempt the port abandons itself (for example, initiation switched off) is not recorded. While a new attempt to a peer is in progress, that peer’s earlier finished entry is not listed beside it.

Appendix B - Compile Flag and Size Estimates

Section titled “Appendix B - Compile Flag and Size Estimates”
Configuration Approx. flash delta Approx. RAM delta Notes
BACnet/SC disabled 0 KB 0 KB Baseline
Hub connector only (node) +40–50 KB +8–12 KB Recommended for server devices
+ Hub function (runtime-enabled) +15–20 KB +4–8 KB + per-conn Adds listener / forwarder
+ Direct connect (runtime-enabled) +10–15 KB +2–4 KB + per-conn Adds peer-to-peer paths

Per-connection RAM overhead is roughly 1–2 KB (frame buffer, state, timers) for each active SC connection.

These are rough estimates, not measurements of this release. Measure on your own target compiler and link configuration.

Required for any BACnet/SC integration (in source/CIBuildSettings.h or as CMake options; see Build presets):

#define STACK_OPTION_DATA_LINK_LAYER_SC
#define STACK_OPTION_OBJECT_TYPE_NETWORK_PORT // also turned on automatically by SC
#define STACK_OPTION_OBJECT_TYPE_FILE
#define STACK_OPTION_NM_SCCM_A // turns on AtomicReadFile/AtomicWriteFile and ReinitializeDevice
#define STACK_OPTION_DATA_LINK_LAYER_IPV4 // currently required by shared utility code

STACK_OPTION_NM_SCCM_A (or STACK_OPTION_ENABLE_ALL_BIBBS, which includes it in an SC build) turns on the AtomicReadFile/AtomicWriteFile support. Without it BACnetStack_AddFileObject returns false and the read and write file callbacks are never called, so the certificate File objects cannot be served. It also turns on ReinitializeDevice, which a client uses to activate certificate changes.

Hub function and direct connect have no compile flags of their own: they are configured at runtime with BACnetStack_SetBACnetSCHubFunctionConfig and BACnetStack_SetBACnetSCDirectConnectConfig (Appendix C.2), or, after commissioning, by a WriteProperty to the two direct-connect enables (§16.5). BACnet/SC debug output uses the stack-wide STACK_OPTION_API_DEBUG_LOGGING.

Appendix C - BACnet/SC Public API Cheat Sheet

Section titled “Appendix C - BACnet/SC Public API Cheat Sheet”

All functions are declared in source/CASBACnetStackDLL.h and are exported in every build. Without STACK_OPTION_DATA_LINK_LAYER_SC, each BACnet/SC function returns false (or does nothing, for the void registration functions) and reports through the debug-message callback that the feature was not compiled in. The three generic File-object entries in C.1 (BACnetStack_AddFileObject and the read and write file callbacks) depend on STACK_OPTION_ATOMIC_FILE_IO with STACK_OPTION_OBJECT_TYPE_FILE instead; see B.1.

bool BACnetStack_SetBACnetSCUuid(
const uint8_t* uuid, uint8_t uuidLength); // 16
bool BACnetStack_SetBACnetSCHubConnector(
const uint8_t* vmac, uint8_t vmacLength, // 6
const char* primaryHubUri, uint16_t primaryHubUriLength,
const char* failoverHubUri, uint16_t failoverHubUriLength);
bool BACnetStack_SetBACnetSCSettings(
uint16_t maximumBVLCLength, // 6144 default (TARGET_FULL), else 1600
uint16_t maximumNPDULength, // 1497 default
uint16_t connectTimeoutSec, // 10 default
uint16_t wsConnectTimeoutSec, // 10 default
uint16_t wsReconnectTimeoutSec, // 10 default
uint16_t heartbeatTimeoutSec); // 300 default
bool BACnetStack_SetBACnetSCHelloCapabilities(uint8_t cap);
bool BACnetStack_SetBACnetSCCertificateFileObjects(
uint32_t deviceInstance,
uint32_t scPortInstance,
bool hasOperationalCertificateFile,
uint32_t operationalCertificateFileInstance,
bool hasCertificateSigningRequestFile,
uint32_t certificateSigningRequestFileInstance,
const uint32_t* issuerCertificateFileInstances,
uint16_t issuerCertificateFileCount); // normally 2
// Creates a File object AND stores File_Access_Method / File_Read_Only - use this instead of
// AddObject(..., OBJECT_TYPE_FILE, ...) for every certificate file (see section 16.1 of the BACnet/SC certificates page).
bool BACnetStack_AddFileObject(
uint32_t deviceInstance,
uint32_t objectInstance,
bool isWritable,
bool isConfigurationFile, // = false
uint8_t fileAccessMethod); // = 1 (streamAccess); property enum, record=0/stream=1
// Register once; the stack calls it on demand instead of holding a copy of the bytes (section 16.2 of the BACnet/SC certificates page).
void BACnetStack_RegisterCallbackReadFile(bool(*fp)(
uint32_t deviceInstance, uint32_t fileInstance,
uint32_t fileStart, uint32_t requestedCount,
uint8_t* fileData, uint32_t* fileDataLength, uint32_t maxFileDataLength,
bool* endOfFile, uint32_t* errorCode));
void BACnetStack_RegisterCallbackWriteFile(bool(*fp)(
uint32_t deviceInstance, uint32_t fileInstance,
int32_t fileStart, const uint8_t* fileData, uint32_t fileDataLength,
int32_t* ackFileStart, uint32_t* errorCode));

C.2 Optional hub function / direct connect (server roles)

Section titled “C.2 Optional hub function / direct connect (server roles)”
bool BACnetStack_SetBACnetSCHubFunctionConfig(
uint32_t deviceInstance,
uint32_t scPortInstance,
bool enabled,
uint16_t maxConnections);
// Startup configuration only - sets the current AND active enable state immediately, with no
// Changes_Pending step. For FIELD reconfiguration after commissioning, use WriteProperty on
// SC_Direct_Connect_Initiate_Enable / SC_Direct_Connect_Accept_Enable instead (see section 16.5 of the BACnet/SC certificates page).
bool BACnetStack_SetBACnetSCDirectConnectConfig(
uint32_t deviceInstance,
uint32_t scPortInstance,
bool initiateEnabled,
bool acceptEnabled);
// Accept URIs are a list per role (SC_Hub_Function_Accept_URIs / SC_Direct_Connect_Accept_URIs), set separately.
// connectionRole: 0 = hub function, 1 = direct connect.
bool BACnetStack_AddBACnetSCAcceptUri(
uint32_t deviceInstance,
uint32_t scPortInstance,
uint8_t connectionRole,
const char* acceptUri, uint32_t acceptUriLength);
bool BACnetStack_ClearBACnetSCAcceptUris(
uint32_t deviceInstance,
uint32_t scPortInstance,
uint8_t connectionRole);

Hub function forwarding has no rate limit. Cl. AB.5.1 has the hub function forward unicast messages and copy every broadcast to the other hub connections. The stack does this unconditionally: it applies no per-peer rate or volume limit, and BACnet/SC has no result code for “rate limited”. One connected peer’s broadcast therefore goes out (N−1) times across N hub connections, so size the hub host’s bandwidth and CPU for the broadcast load of the whole network. Flood control is the deployment’s responsibility: issue operational certificates only to trusted devices, revoke or remove the certificate of a device that misbehaves, and monitor hub traffic.

bool BACnetStack_SetBACnetSCWebSocketStatus(
const char* uri, uint16_t uriLength,
uint8_t status, // 1=Connecting, 2=Connected, 3=Disconnected, 4=Error (see section 19 of the BACnet/SC transport callbacks page)
uint32_t errorCode); // RFC 6455 close code with Error; otherwise 0

C.4 Callbacks the application must implement

Section titled “C.4 Callbacks the application must implement”
// Required for: Node (outbound connect to Hub or Direct Connection peer).
// Optional for: Hub that also connects to another Hub as a client.
void BACnetStack_RegisterCallbackInitiateWebsocket(
bool(*fp)(const char* uri, uint32_t uriLength));
// Required for: every role. Closes outbound connections, and the accepted ones
// (<acceptUri>|client=<token>) that the hub function and direct-connect accept close.
void BACnetStack_RegisterCallbackDisconnectWebsocket(
void(*fp)(const char* uri, uint32_t uriLength));
// Required for: Hub (accept inbound Node connections).
// Required for: Node with Direct Connect Accept enabled.
// Not required for: Node-only devices that do not accept Direct Connections.
void BACnetStack_RegisterCallbackSCStartListening(
bool(*fp)(const char* uri, uint32_t uriLength));
// Required for: Hub, and any Node with Direct Connect Accept enabled.
// Not required for: Node-only devices that do not accept Direct Connections.
void BACnetStack_RegisterCallbackSCStopListening(
void(*fp)(const char* uri, uint32_t uriLength));
// For debug logging and observability of state-machine transitions.
// Not required for correct operation.
void BACnetStack_RegisterCallbackBACnetSCStateChange(
void(*fp)(uint32_t deviceInstance, uint32_t networkPortInstance,
uint8_t stateMachine,
uint8_t previousState, uint8_t newState,
const char* uri, uint32_t uriLength));
BACnetStack_RegisterCallback* // standard + SC callbacks (integration steps 3 and 4)
BACnetStack_AddDevice
BACnetStack_AddObject ... // application objects
BACnetStack_AddFileObject x 4 // op cert + 2 issuer certs + CSR (section 16.1 of the BACnet/SC certificates page)
BACnetStack_AddNetworkPortObject(SC, ..., networkNumber, networkNumberQuality, ...)
BACnetStack_RegisterCallbackReadFile(...) // serves the PEM bytes your app holds (section 16.2 of the BACnet/SC certificates page)
BACnetStack_RegisterCallbackWriteFile(...) // accepts/rejects writes into cert files
BACnetStack_SetBACnetSCUuid
BACnetStack_SetBACnetSCHubConnector
BACnetStack_SetBACnetSCSettings // optional
BACnetStack_SetBACnetSCCertificateFileObjects // leaves the port's Changes_Pending TRUE
BACnetStack_ActivateNetworkPortPendingChanges // activates the start-up configuration (section 16.3 of the BACnet/SC certificates page)
loop: BACnetStack_Tick

Appendix D - Conformance and Interoperability Statement

Section titled “Appendix D - Conformance and Interoperability Statement”

Standard: ANSI/ASHRAE Standard 135-2024 (BACnet), Protocol Revision 30 SC Specification: Annex AB of ANSI/ASHRAE 135-2024

The CAS BACnet Stack BACnet/SC implementation targets conformance with:

  • ANSI/ASHRAE 135-2024, Protocol Revision 30 — BACnet/SC transport specification
  • ASHRAE 135.1-2023 — BACnet Conformance Test Plan (Clause 12.5: BACnet/SC)
  • RFC 6455 — The WebSocket Protocol
  • RFC 8446 — TLS 1.3 (BACnet/SC requires TLS 1.3; TLS 1.2 is not supported)
Feature Status Notes
Hub connector (node) role Complete Connects to primary and failover hubs
Hub function (hub) role Complete Accepts inbound node connections
Direct connect (initiate) Complete Peer-to-peer BACnet/SC
Direct connect (accept) Complete Accepts inbound peer connections
TLS mutual authentication Host application Done by the application’s TLS library; the stack has no TLS code
X.509 certificate validation Host application Performed by the application’s TLS library during the handshake; the stack performs no certificate checks
BVLC/SC framing Complete All BVLC message types implemented
Heartbeat Complete Configurable interval
Reconnect with backoff Complete Configurable min/max backoff
Network Port object (SC) Complete Hub connector state, UUID, etc.
Certificate File Objects Complete Application-owned bytes (§2.7)
Remote certificate update Complete AtomicWriteFile/WriteProperty + ReinitializeDevice
On-device CSR generation Host application The generate-csr-file network port command is forwarded to BACnetStack_RegisterCallbackNetworkPortCommand (§16.6), where the application generates the CSR and writes it into the CSR File object; with no callback it answers optional-functionality-not-supported
UUID management Complete Property 507 (Device_UUID)
State-change notification callback Complete All connection state transitions