For the BACnet B-SS (Smart Sensor) Rust example - see README.md.
This is the PICS for the example as shipped. It describes a tutorial device announcing itself as a Chipkin demo, not a product. When you turn this example into your own device, this document is one of the things you rewrite: the vendor, model and version rows all come from the
CHANGE ALL OF THIS BEFORE YOU SHIPblock at the top ofsrc/main.rs. The example has not been submitted for BTL certification.
| Vendor Name | Chipkin Automation Systems |
| Vendor Identifier | 389 |
| Product Name | CAS BACnet Stack Example - B-SS |
| Product Model Number | CAS BACnet Stack Example - B-SS |
| Application Software Version | 1.2.0 |
| Firmware Revision | 6.0.23.0 (the CAS BACnet Stack version) |
| BACnet Protocol Version | 1 |
| BACnet Protocol Revision | 30 |
Product Description: a minimal read-only BACnet/IP sensing device built on the CAS BACnet Stack. It presents three sensor objects (Analog Input, Binary Input, Multi-State Input) whose readings follow a sensor Simulation, answers ReadProperty for every required property of every object, reports a broken sensor through Analog Input 1's Reliability and the FAULT bit of Status_Flags, and is discoverable by Who-Is / I-Am and Who-Has / I-Have. It is a tutorial for implementers of the B-SS profile.
B-SS - BACnet Smart Sensor.
This device claims exactly one profile. Because the B-SS requirements are a superset of B-GENERAL's, a conformant B-SS device also satisfies B-GENERAL (Annex L.8); that is subsumption, not a second claim.
| BIBB | Description |
|---|---|
| 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 |
No other BIBBs are supported. In particular this device does not support DS-WP-B (WriteProperty), DS-RPM-B (ReadPropertyMultiple), DS-COV-B, any alarm and event (AE-) BIBB, scheduling (SCHED-), trending (T-*), or DM-DCC-B (DeviceCommunicationControl).
| Service | Initiate | Execute |
|---|---|---|
| ReadProperty | no | yes |
| Who-Is | no | yes |
| I-Am | yes | - |
| Who-Has | no | yes |
| I-Have | yes | - |
An unsolicited I-Am is broadcast to the local subnet at start-up, as well as in response to Who-Is.
Any other confirmed service - including WriteProperty - is rejected. That rejection is part of the profile boundary, not a limitation to work around.
Segmentation is supported in both directions
(Segmentation_Supported = segmented-both), by the stack: at 6.x @
69b6249f the customer build (the stack's CMake defaults,
STACK_OPTION_TARGET_FULL) compiles STACK_OPTION_SEGMENTATION in (stack
#2992), and this example keeps the stack's defaults - Max_Segments_Accepted
16 and APDU_Segment_Timeout 5000 ms, both read on the wire. Table 12-13
footnote 1: "These properties are required if, and shall be present only if,
segmentation of any kind is supported" - they are not rows in section 11
because its generator lists only unconditionally required properties.
Max_APDU_Length_Accepted is 1476 octets, the BACnet/IP maximum. (At the
previous pin, abd4cee1, this example answered no-segmentation.)
No object is dynamically creatable or deletable, and no property of any object is writable.
| Object type | Instance | Object_Name | Optional properties supported |
|---|---|---|---|
| Device | 389001 | Chipkin Example B-SS | Description |
| Analog Input | 1 | Bronze | Reliability |
| Binary Input | 1 | Emerald | - |
| Multi-State Input | 1 | Hot Pink | State_Text |
| Network Port | 1 | Vermilion | - |
The device instance is configurable at start-up with --deviceID, and the
Device's Object_Name with --deviceName (BACnet requires both to be
configurable, cl. 12.1.1.3 and 12.1.1.4). Changing either means restarting
the device; neither is writable over the network. The table shows the
defaults.
BACnet/IP (Annex J), UDP port 47808 (0xBAC0) by default, configurable at run
time with --port.
BBMD is not supported, Foreign Device registration is not supported, and BACnet/SC, MS/TP, Ethernet (Annex H) and PTP are not supported.
The stack's Network Port object still lists its BACnet/IP properties in
Property_List - including IP_DNS_Server, FD_BBMD_Address and
FD_Subscription_Lifetime - and every one of them reads as a value
(FD_BBMD_Address is a Null host, port 0: no BBMD configured). The Wire Tests
read every listed property of every object.
Static device binding is not supported. The device answers Who-Is/Who-Has and does not initiate any confirmed request, so it never needs to bind a peer.
None. The device is not a router, not a BBMD, and does not register as a foreign device.
UTF-8 (ANSI X3.4). Supporting a character set does not imply the device can handle data in all character sets.
Every object this example creates, and every REQUIRED property of each (per ANSI/ASHRAE 135-2024 clause 12 and the CAS BACnet Stack's property profiles), plus the optional properties the example turns on. Served by says who answers a ReadProperty: the stack generates it, or the app serves it from a get_property_* callback in src/main.rs. A ⚠ row is a required property the app does not serve and the stack would fill with a default - that is a defect, not a feature.
Device 389001 "Chipkin Example B-SS" - the device itself; the instance is configurable with --deviceID and the Object_Name with --deviceName (both at start-up; the heading shows the defaults). The stack rows are device-wide facts only the stack knows - the protocol version and revision it implements, the services and object types it was configured with, the live object list and address-binding table, and Database_Revision, which the stack starts at 0 and increments for each object added at start-up: it reads 5 (the Device and its four objects) and stays 5, because nothing creates, deletes or renames an object afterwards. The accepted rows are the stack's configured defaults for APDU limits, segmentation and system status; an application that answered them from its own constants could contradict the stack, so this example does not
| Property | Datatype | Served by | Writable |
|---|---|---|---|
| Object_Identifier | BACnetObjectIdentifier | stack | no |
| Object_Name | CharacterString | app | no |
| Object_Type | BACnetObjectType | stack | no |
| System_Status | BACnetDeviceStatus | stack default, accepted (Generic Enumerated default: 0) |
no |
| Vendor_Name | CharacterString | app | no |
| Vendor_Identifier | Unsigned16 | app | no |
| Model_Name | CharacterString | app | no |
| Firmware_Revision | CharacterString | app | no |
| Application_Software_Version | CharacterString | app | no |
| Description (optional, enabled) | CharacterString | app | no |
| Protocol_Version | Unsigned | stack | no |
| Protocol_Revision | Unsigned | stack | no |
| Protocol_Services_Supported | BACnetServicesSupported | stack | no |
| Protocol_Object_Types_Supported | BACnetObjectTypesSupported | stack | no |
| Object_List | BACnetARRAY[N] of BACnetObjectIdentifier | stack | no |
| Max_APDU_Length_Accepted | Unsigned | stack default, accepted (CAS_BACNET_DEVICE_DEFAULT_MAX_APDU_LENGTH_ACCEPTED) |
no |
| Segmentation_Supported | BACnetSegmentation | stack default, accepted (BACnetSegmentation::segmentedBoth with `STACK_OPTION_SEGME) |
no |
| APDU_Timeout | Unsigned | stack default, accepted (CAS_BACNET_DEVICE_DEFAULT_APDU_TIMEOUT) |
no |
| Number_Of_APDU_Retries | Unsigned | stack default, accepted (CAS_BACNET_DEVICE_DEFAULT_NUMBER_OF_APDU_RETRIES) |
no |
| Device_Address_Binding | BACnetLIST of BACnetAddressBinding | stack | no |
| Database_Revision | Unsigned | stack | no |
| Property_List | BACnetARRAY[N] of BACnetPropertyIdentifier | stack | no |
Analog Input 1 "Bronze" - REAL, degrees Celsius; the sensor Simulation ramps it 18.0 .. 26.0 at 0.5 C a second. Reliability reads no-fault-detected, or open-loop while the simulated sensor wire is broken; the stack derives Status_Flags FAULT from it
| Property | Datatype | Served by | Writable |
|---|---|---|---|
| Object_Identifier | BACnetObjectIdentifier | stack | no |
| Object_Name | CharacterString | app | no |
| Object_Type | BACnetObjectType | stack | no |
| Present_Value | Real | app | no |
| Status_Flags | BACnetStatusFlags | stack | no |
| Event_State | BACnetEventState | stack default, accepted (Generic Enumerated default: 0) |
no |
| Reliability (optional, enabled) | BACnetReliability | app | no |
| Out_Of_Service | Boolean | app | no |
| Units | BACnetEngineeringUnits | app | no |
| Property_List | BACnetARRAY[N] of BACnetPropertyIdentifier | stack | no |
| Property | Datatype | Served by | Writable |
|---|---|---|---|
| Object_Identifier | BACnetObjectIdentifier | stack | no |
| Object_Name | CharacterString | app | no |
| Object_Type | BACnetObjectType | stack | no |
| Present_Value | BACnetBinaryPV | app | no |
| Status_Flags | BACnetStatusFlags | stack | no |
| Event_State | BACnetEventState | stack default, accepted (Generic Enumerated default: 0) |
no |
| Out_Of_Service | Boolean | app | no |
| Polarity | BACnetPolarity | app | no |
| Property_List | BACnetARRAY[N] of BACnetPropertyIdentifier | stack | no |
Multi-state Input 1 "Hot Pink" - 3 states: On, Off, Auto; the sensor Simulation steps 1 -> 2 -> 3 -> 1 every 4 s
| Property | Datatype | Served by | Writable |
|---|---|---|---|
| Object_Identifier | BACnetObjectIdentifier | stack | no |
| Object_Name | CharacterString | app | no |
| Object_Type | BACnetObjectType | stack | no |
| Present_Value | Unsigned | app | no |
| Status_Flags | BACnetStatusFlags | stack | no |
| Event_State | BACnetEventState | stack default, accepted (Generic Enumerated default: 0) |
no |
| Out_Of_Service | Boolean | app | no |
| Number_Of_States | Unsigned | app | no |
| State_Text (optional, enabled) | BACnetARRAY[N] of CharacterString | app | no |
| Property_List | BACnetARRAY[N] of BACnetPropertyIdentifier | stack | no |
Network Port 1 "Vermilion" - BACnet/IP; Network_Type and Protocol_Level are set from BACnetStack_AddNetworkPortObject()'s arguments (IPv4, BACnet Application) at start-up, not a GetProperty callback like the object's other app-served rows; Changes_Pending is likewise computed and answered natively by the stack's Network Port object. Reliability has no fault condition this example detects, so it is accepted at the generic default (normal)
| Property | Datatype | Served by | Writable |
|---|---|---|---|
| Object_Identifier | BACnetObjectIdentifier | stack | no |
| Object_Name | CharacterString | app | no |
| Object_Type | BACnetObjectType | stack | no |
| Status_Flags | BACnetStatusFlags | stack | no |
| Reliability | BACnetReliability | stack default, accepted (Generic Enumerated default: 0) |
no |
| Out_Of_Service | Boolean | app | no |
| Network_Type | BACnetNetworkType | app | no |
| Protocol_Level | BACnetProtocolLevel | app | no |
| Changes_Pending | Boolean | app | no |
| Property_List | BACnetARRAY[N] of BACnetPropertyIdentifier | stack | no |
- ANSI/ASHRAE Standard 135-2024, Annex A (PICS template), Annex K (BIBBs), Annex L (device profiles), Clause 12 (object types).
- README.md - what this example is and how to build it.
- TUTORIAL.md - how to extend it, and how to keep this document honest when you do.