Skip to content
Version 6.1.0
Contact Us

BACnetStack_RegisterCallbackNetworkPortCommand

void BACnetStack_RegisterCallbackNetworkPortCommand(
bool (*FPCallbackNetworkPortCommand)(const uint32_t deviceInstance, const uint32_t networkPortInstance, const uint32_t command, uint32_t *errorCode));

Registers the callback that carries the host’s part of a WriteProperty of a Network Port object’s Command property (135-2024 cl. 12.56.16).

Called synchronously from inside the WriteProperty service, before the stack answers it.

EXACTLY TWO COMMANDS ARE FORWARDED: DISCARD_CHANGES (1) and GENERATE_CSR_FILE (9). No other Command value ever reaches this callback. Each is forwarded only after the stack’s own checks have passed - IDLE is refused with VALUE_OUT_OF_RANGE, a command for the wrong Network_Type with VALUE_OUT_OF_RANGE, and GENERATE_CSR_FILE while Changes_Pending is TRUE with INVALID_VALUE_IN_THIS_STATE - so the callback never sees a write the stack would refuse.

DISCARD_CHANGES (1) - forwarded for EVERY Network Port type (IPv4, Ethernet, MS/TP, Virtual and BACnet/SC), because every port executes it. The callback runs BEFORE the stack reverts anything. In v6 the certificate file data of a BACnet/SC port lives in the host, and cl. 12.56.101 (12.56.100 likewise for the operational certificate file) requires DISCARD_CHANGES to restore the referenced File objects’ data to what it was when Changes_Pending was last FALSE - only the host can do that. Return true once your part is reverted: the stack then reverts the pending changes of THIS port only (its pending Network_Number and, on a BACnet/SC port, its pending certificate File bindings and configuration), Changes_Pending reads FALSE and the write answers Result(+). Return false to refuse: the write answers Result(-) with errorCode and nothing on the port changes - Changes_Pending stays TRUE. The callback is called even when the port has no pending changes. With no callback registered, DISCARD_CHANGES reverts the port’s pending changes as it always has.

GENERATE_CSR_FILE (9) - forwarded only for a BACnet/SC port whose Changes_Pending is FALSE (cl. 12.56.16: while Changes_Pending is TRUE, any supported command other than DISCARD_CHANGES or VALIDATE_CHANGES is refused with Result(-) PROPERTY / INVALID_VALUE_IN_THIS_STATE). Generate a new private/public key pair and write the new certificate signing request into the File object bound to Certificate_Signing_Request_File (cl. 12.56.102), and only then return true. The write answers Result(+) and Command reads IDLE again, as cl. 12.56.16 requires: Command keeps its value until the CSR file has been generated, then returns to IDLE, and this command leaves Changes_Pending unchanged. The stack does not touch Changes_Pending for this command. Return false to refuse with errorCode. With no callback registered - or on any port that is not BACnet/SC - GENERATE_CSR_FILE answers PROPERTY / OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED. Generation is synchronous: there is no way to hold Command at GENERATE_CSR_FILE and complete it later.

ERROR MAPPING on a false return. The stack presets errorCode to success (84). ABORT_OTHER (56) answers Abort(other). A code left at success, or one that cannot be sent as an Error code (above 65535, or an abort- or reject-type code), answers PROPERTY / WRITE_ACCESS_DENIED. Any other code is sent with an error class chosen from the code: a code that clause 18 lists under exactly one of the DEVICE, OBJECT, RESOURCES, SECURITY and SERVICES classes gets that class - for example DEVICE for DEVICE_BUSY, OBJECT for UNKNOWN_OBJECT, SERVICES for SERVICE_REQUEST_DENIED, SECURITY for PASSWORD_FAILURE, RESOURCES for NO_SPACE_TO_WRITE_PROPERTY, NO_SPACE_FOR_OBJECT, NO_SPACE_TO_ADD_LIST_ELEMENT and OUT_OF_MEMORY - and every other code, including one clause 18 lists under several of those classes, gets PROPERTY. This is the same mapping as a declined Network Port property write callback.

RE-ENTRANCY: the callback runs inside the WriteProperty service. As for every callback (see “Callbacks” and “Threading” in docs/_doxygen/api-reference/conventions.md), it must not call back into the stack - in particular it must not add or delete objects, including the Network Port being written. A STACK_OPTION_THREAD_SAFE build refuses BACnetStack_RemoveObject and BACnetStack_RemoveDevice from here (they return false).

Pass NULL to unregister.

See also: CASBACnetStack::FPCallbackNetworkPortCommand

BACnet reference: ANSI/ASHRAE 135-2024 clause 12.56 (Network Port Object Type).

Parameter Direction Description
FPCallbackNetworkPortCommand in The function pointer for the CallbackNetworkPortCommand function, or NULL. Its parameters are deviceInstance (the device that owns the port), networkPortInstance (the Network Port object whose Command was written), command (a BACnetNetworkPortCommand value, cl. 21: 1 = DISCARD_CHANGES or 9 = GENERATE_CSR_FILE) and errorCode (out: the BACnet error code to answer with on a false return). See CASBACnetStack::FPCallbackNetworkPortCommand for more info.

FPCallbackNetworkPortCommand

Topic: Service callbacks. Declared in CASBACnetStackDLL.h.