ReinitializeDevice
ReinitializeDevice is how a BACnet client activates the Network Port changes it wrote, so read that chapter’s Writable properties and Changes_Pending first if your device has writable Network Port properties.
The ReinitializeDevice service
Section titled “The ReinitializeDevice service”ReinitializeDevice asks a device to restart, activate pending changes, or step through backup and restore. To answer it, register the callback and enable the service (service number 20):
DllExport void BACnetStack_RegisterCallbackReinitializeDevice(bool(*FPCallbackReinitializeDevice) (const uint32_t deviceInstance, const uint32_t reinitializedState, const char* password, const uint32_t passwordLength, uint32_t* errorCode));DllExport bool BACnetStack_SetServiceEnabled(const uint32_t deviceInstance, const uint32_t service, const bool enabled);The callback is mandatory. Without it the stack answers every ReinitializeDevice with Error SERVICES / SERVICE_REQUEST_DENIED.
States
Section titled “States”| Value | State | What to do |
|---|---|---|
| 0 | COLDSTART |
Restart. What a cold start means is your product’s decision; often the same as a warm start. Pending Network Port values are not activated. |
| 1 | WARMSTART |
Restart, keeping the data a short power cut would keep. Pending Network Port values are activated first. |
| 2–6 | STARTBACKUP, ENDBACKUP, STARTRESTORE, ENDRESTORE, ABORTRESTORE |
Backup and restore. The stack drives these through the backup and restore callbacks after the SimpleAck. |
| 7 | ACTIVATE_CHANGES |
Nothing beyond accepting: the stack activates the pending values. |
A state above 7 is rejected by the stack before your callback is called.
Order of events
Section titled “Order of events”When a ReinitializeDevice arrives, the stack:
- checks the request, the backup/restore preconditions and the DeviceCommunicationControl rules;
- checks that every pending Network Port value can be activated (for
ACTIVATE_CHANGESandWARMSTART). If not, it answers Error(PROPERTY, INVALID_CONFIGURATION_DATA) and does not call you; - calls your
CallbackReinitializeDevice. If you return false, it answers with your error and activates nothing; - activates the pending values, calling your Set callbacks. If one is refused it answers Error(PROPERTY, INVALID_CONFIGURATION_DATA), even though your callback returned true;
- re-enables communication if a
WARMSTARTorCOLDSTARTended a DeviceCommunicationControl disable; - sends the SimpleAck.
So the stack does the password relay, the pending-change checks, the activation and the reply. Your application does the password check, the restart, and the persistence of the values it receives in step 4.
Password
Section titled “Password”The stack does not check the password against anything; it passes it to you. password is NULL with passwordLength 0
when the request carried none. The stack rejects a password that is empty, longer than 20 characters, or not
well-formed UTF-8 before calling you. A password is
optional in BACnet, but a device that ships with one should check it here.
Return value and error codes
Section titled “Return value and error codes”Return true to accept. Return false and set *errorCode to refuse. The stack sends these codes with these
classes:
*errorCode |
Value | Sent as |
|---|---|---|
PASSWORD_FAILURE |
26 | SECURITY, PASSWORD_FAILURE |
MISSING_REQUIRED_PARAMETER |
16 | SERVICES, MISSING_REQUIRED_PARAMETER (a password is required and none was sent) |
CONFIGURATION_IN_PROGRESS |
2 | DEVICE, CONFIGURATION_IN_PROGRESS |
COMMUNICATION_DISABLED |
83 | SERVICES, COMMUNICATION_DISABLED |
OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED |
45 | SERVICES, OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED (a state you do not support) |
INVALID_CONFIGURATION_DATA |
46 | PROPERTY, INVALID_CONFIGURATION_DATA |
Any other code is sent with its own error class, as the other service callbacks send it. No code (the preset
SUCCESS), OTHER, a value above 65535, or an abort-type or reject-type code is sent as SERVICES,
SERVICE_REQUEST_DENIED. ABORT_OTHER (56) asks for an Abort(other) instead. A refusal is never answered with an
Abort otherwise.
Restarting
Section titled “Restarting”Do not restart inside the callback. The stack still has to activate the pending values and send the SimpleAck
after you return. Set a flag, and restart after BACnetStack_Tick() returns. If one of your Set callbacks
refused a value during activation, the client received an error, and you may choose not to restart.
Example on GitHub
Section titled “Example on GitHub”Chipkin keeps its examples on GitHub up to date with the stack, so this manual does not copy their code.
BACnetProfileExample-B-BC-CPP, a BACnet Building Controller, handles ReinitializeDevice in
main.cpp. Its ReinitializeDevice() callback checks the password,
accepts ACTIVATE_CHANGES, COLDSTART, WARMSTART and the backup and restore states, and only arms the
restart. Its main loop restarts the device later, after the SimpleAck has had time to go out. The password is the
DCC_PASSWORD constant, and the same check guards DeviceCommunicationControl.
An MS/TP port follows the same pattern as an IPv4 port, with Max_Master and Max_Info_Frames served and
activated through the unsigned-integer callbacks. Store them in the Set callback. In byte mode the stack’s own MS/TP
engine reads them again from your Get callback after the activation, so there is nothing more to do; in packet mode,
apply them to your own MS/TP engine as well. See the MS/TP Network Port.
Practical notes
Section titled “Practical notes”- Persist in the Set callback, not in
CallbackReinitializeDevice. The values are not handed to you until after your ReinitializeDevice callback returns. COLDSTARTdoes not activate pending values. If your product wants a cold start to apply them, callBACnetStack_ActivateNetworkPortPendingChanges()before restarting.- Sending ReinitializeDevice to another device is
BACnetStack_SendReinitializeDevice(); see its doc comment insource/CASBACnetStackDLL.h.
