Skip to content
Version 6.1.0
Contact Us

BACnetStack_AddChannelObject

bool BACnetStack_AddChannelObject(
const uint32_t deviceInstance,
const uint32_t channelObjectInstance,
const uint8_t presentValueDatatype);

Configures a Channel object’s stack-held data: the concrete primitive datatype of its Present_Value (a BACnetChannelValue CHOICE) and an initially-empty List_Of_Object_Property_References.

Note: the datatype is fixed here, at configuration time. 135-2024 cl. 12.53.5 defines Present_Value as whatever was most recently written to it, so a Channel whose clients write more than one datatype cannot be modelled through this export - the stored code is what the stack uses to dispatch every Present_Value read to a typed Get callback.

The only Channel properties that are handled and stored by the CAS BACnet Stack are:

  • ObjectIdentifier, ObjectType, PropertyList, StatusFlags
  • the PresentValue BACnetChannelValue CHOICE selector (set by presentValueDatatype), which the stack uses to pick the typed callbacks below
  • ListOfObjectPropertyReferences (maintained by BACnetStack_AddObjectPropertyReferenceToChannel(), writable in place by a client WriteProperty, and used by the stack to pass every Present_Value write on to the referenced properties - see the IMPORTANT note below the table)
  • WriteStatus (kept by the stack from how those writes end - see the IMPORTANT note below the table)

The optional ExecutionDelay and AllowGroupDelayInhibit properties are not presented: the stack applies no execution delay, and a read or write of either answers UNKNOWN_PROPERTY.

Everything else is served by the application - including ChannelNumber and ControlGroups, which are required and writable:

--------------------------------------------------------------------------------
Property Datatype Callback
--------------------------------------------------------------------------------
ObjectName CharacterString CallbackGetPropertyCharacterString
PresentValue BACnetChannelValue Reads:
CallbackGetPropertyBool (the NULL-slot flag)
CallbackGetProperty<T>, T = presentValueDatatype
Both are called with
propertyIdentifier = PriorityArray,
useArrayIndex = true, index 1..16.
Not for presentValueDatatype 97 or 12:
see presentValueDatatype below.
Writes (WriteProperty, WritePropertyMultiple,
WriteGroup):
CallbackSetProperty<T> / CallbackSetPropertyNull
called with propertyIdentifier = PresentValue,
useArrayIndex = false and the command priority
in priority. A Null value relinquishes that
priority.
The application keeps the 16 priority slots that
both shapes address - except for presentValueDatatype
97 or 12, where it keeps the last value written
and serves it to the plain Get callback.
LastPriority Unsigned CallbackGetPropertyUnsignedInteger
OutOfService Boolean CallbackGetPropertyBool
ChannelNumber Unsigned16 CallbackGetPropertyUnsignedInteger
CallbackSetPropertyUnsignedInteger
ControlGroups Unsigned32 array CallbackGetPropertyUnsignedInteger
CallbackSetPropertyUnsignedInteger
Array index 0 is the element count.
--------------------------------------------------------------------------------

IMPORTANT: every write of PresentValue - WriteProperty, WritePropertyMultiple, WriteGroup, or a Schedule or Timer in this device whose reference names it - is passed on to each member of ListOfObjectPropertyReferences at the write’s priority (clause 12.53.5): a member in this device through its own CallbackSetProperty<T> or CallbackSetPropertyNull (the stack itself for a stack-held Lighting Output, Binary Lighting Output or Access Door), a member in another device through a WriteProperty. Nothing is passed on while OutOfService is TRUE. Before, only a WriteGroup was passed on; an application that passed WriteProperty writes on itself must stop, or each member is written twice.

IMPORTANT: the stack keeps WriteStatus (clause 12.53.7) and CallbackGetPropertyEnumerated is no longer asked for it. An application that still serves WriteStatus gives way to the stack’s value. It is IDLE until the first write while ListOfObjectPropertyReferences has elements, and reads IDLE while the list is empty. A list holding only empty references has elements and nothing to write: a write to it goes to SUCCESSFUL. A write sets IN_PROGRESS; once every member has been attempted it is SUCCESSFUL, or FAILED if any member could not be written: a coercion failure, a local member the application refused, a remote member the stack could not send to (DeviceCommunicationControl DISABLE_INITIATION, no room for the transaction), or a remote member that answered with an Error, Reject or Abort or never answered. A remote member whose device has no address yet is held: the stack sends the write if an I-Am binds the device within APDU_Timeout x (Number_Of_APDU_Retries + 1), and it is FAILED otherwise. While it is held the stack seeks the device with a Who-Is, but only once it has heard an I-Am from any device, which shows it the link to broadcast on; until then it sends none and waits out the limit. A Null write refused as INVALID_DATATYPE or INVALID_PARAMETER_DATA_TYPE, or refused in any way by a local member that is not commandable, does not count as a failure. Remote members finish through their replies, so WriteStatus can stay IN_PROGRESS for up to APDU_Timeout x (Number_Of_APDU_Retries + 1), twice that for a held member; the confirmed-request hooks still fire for those writes as before. While it is IN_PROGRESS, a WriteProperty or WritePropertyMultiple of PresentValue is answered OBJECT / BUSY by the stack, without calling the application; a WriteGroup, Schedule or Timer write, or a write from another Channel naming this one as a member, has no one to answer, so it is applied and starts again from IN_PROGRESS, and the earlier write’s result no longer counts. A write that is not passed on (OutOfService TRUE) leaves WriteStatus as it was. A SubscribeCOVProperty or Trend Log on WriteStatus is told of each change from BACnetStack_Tick. WriteStatus is held in memory: BACnetStack_Reset and a recreated Channel start from IDLE.

IMPORTANT: from a write that ends FAILED until a later one ends SUCCESSFUL, IN_PROGRESS between them included (clause 12.53.5), the stack also serves Reliability, if the application enabled it, with the cause (clause 12.53.9), so StatusFlags shows FAULT and, with intrinsic reporting, EventState goes to FAULT. COMMUNICATION_FAILURE: a member the stack could not reach or send to, a timeout, an Abort, an Error of class COMMUNICATION. CONFIGURATION_ERROR: a coercion failure, a member that names no device or holds a value the stack cannot write to it, or a member refused as an unknown object or property, a wrong datatype, a bad array index or not writable. PROCESS_ERROR: any other refusal. When members failed for different causes it reports the first of those three that applies, in the order CONFIGURATION_ERROR, COMMUNICATION_FAILURE, PROCESS_ERROR. The cause stays through a later fan-out until one succeeds. In every other state, while OutOfService is TRUE, and while reliability evaluation is inhibited, the application’s Reliability is served as before.

IMPORTANT: the WriteGroup service reads ChannelNumber and ControlGroups back through the callbacks above (ControlGroups at array index 0 for the count, then 1..N). An application that does not serve them reports channel number 0 and an empty ControlGroups, and the Channel then never matches a WriteGroup request.

IMPORTANT: a PresentValue read whose 16 priority slots are all NULL reads as NULL: a Channel has no RelinquishDefault, and its PresentValue starts out NULL (clause 12.53.5).

See also: BACnetStack_ObjectExists(), BACnetStack_RemoveObject()

BACnet reference: ANSI/ASHRAE 135-2024 clause 12.53 (Channel Object Type).

Parameter Direction Description
deviceInstance in The device instance that owns this Channel object.
channelObjectInstance in The Channel object’s instance. Add the BACnet object itself separately with BACnetStack_AddObject(): this call neither creates it nor checks that it exists, so a typo here silently creates stack data for an object that is not there and fails at read time. Calling this again for the same instance REPLACES the datatype without warning and keeps the existing List_Of_Object_Property_References.
presentValueDatatype in The primitive application datatype of Present_Value. Use a value from CASBACnetStack::BACnetTag::BACnetTagApplicationDatatypes (0 = Null through 12 = BACnetObjectIdentifier). NOT validated - any other value is stored and then matches no read dispatch, so Present_Value reads fail. One constructed BACnetChannelValue alternative can be selected: pass 97 for lighting-command. A write of such a Channel’s Present_Value drives its Lighting Output Lighting_Command members (stack-held, served through CallbackSetPropertyLightingCommand, or remote); any other member is skipped and logged. A WriteProperty or WritePropertyMultiple of that Channel’s Present_Value reaches CallbackSetPropertyLightingCommand. A Channel of lighting-command (97) or BACnetObjectIdentifier (12) has no priority slots: its Present_Value, the last value written to it (clause 12.53.5), is read through the plain Get callback for its datatype (CallbackGetPropertyLightingCommand, or CallbackGetPropertyObjectIdentifier without an array index), and reads as NULL while that callback serves nothing. Every other datatype reads Present_Value from the priority slots, as above. The other constructed alternatives (xy-color, color-command) are not supported.

True on success; false if no device has been added, allocation fails, or Channel support is not compiled.

Topic: Schedules, calendars, trend logs and other object configuration. Declared in CASBACnetStackDLL.h.