fix(server): report the ShutdownReason in the ServerStatus structure (Part 5, 12.10)

The application sets the reason in the ShutdownReason Variable. The
ServerStatus structure returned an empty shutdownReason regardless.
This commit is contained in:
Andreas Ebner
2026-10-16 23:04:34 +02:00
committed by Andreas Ebner
parent 9d608009da
commit 51750cdaee
2 changed files with 45 additions and 0 deletions
+15
View File
@@ -372,6 +372,21 @@ readStatus(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
((server->endTime - el->dateTime_now(el)) / UA_DATETIME_SEC);
}
#ifdef UA_GENERATED_NAMESPACE_ZERO
/* The application sets the reason in the ShutdownReason Variable */
UA_ReadValueId rvi;
UA_ReadValueId_init(&rvi);
rvi.nodeId = UA_NS0ID(SERVER_SERVERSTATUS_SHUTDOWNREASON);
rvi.attributeId = UA_ATTRIBUTEID_VALUE;
UA_DataValue reason = readWithSession(server, &server->adminSession, &rvi,
UA_TIMESTAMPSTORETURN_NEITHER);
if(UA_Variant_hasScalarType(&reason.value, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT])) {
statustype->shutdownReason = *(UA_LocalizedText*)reason.value.data;
UA_LocalizedText_init((UA_LocalizedText*)reason.value.data);
}
UA_DataValue_clear(&reason);
#endif
value->value.data = statustype;
value->value.type = &UA_TYPES[UA_TYPES_SERVERSTATUSDATATYPE];
value->hasValue = true;
+30
View File
@@ -238,6 +238,35 @@ START_TEST(readServerStatusDuringShutdown) {
UA_Variant_clear(&value);
} END_TEST
/* Part 5, 12.10: The ServerStatus structure has the ShutdownReason that the
* application set in the ShutdownReason Variable */
START_TEST(readServerStatusShutdownReason) {
initiateShutdown(10);
UA_LocalizedText reason = UA_LOCALIZEDTEXT("en-US", "Maintenance");
UA_Variant value;
UA_Variant_setScalar(&value, &reason, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
UA_StatusCode retval = UA_Server_writeValue(server,
UA_NS0ID(SERVER_SERVERSTATUS_SHUTDOWNREASON), value);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
retval = UA_Server_readValue(server,
UA_NS0ID(SERVER_SERVERSTATUS_SHUTDOWNREASON), &value);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert(UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]));
ck_assert(UA_equal(value.data, &reason, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]));
UA_Variant_clear(&value);
retval = UA_Server_readValue(server, UA_NS0ID(SERVER_SERVERSTATUS), &value);
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
ck_assert(UA_Variant_hasScalarType(&value,
&UA_TYPES[UA_TYPES_SERVERSTATUSDATATYPE]));
UA_ServerStatusDataType *status = (UA_ServerStatusDataType*)value.data;
ck_assert_int_eq(status->state, UA_SERVERSTATE_SHUTDOWN);
ck_assert(UA_equal(&status->shutdownReason, &reason,
&UA_TYPES[UA_TYPES_LOCALIZEDTEXT]));
UA_Variant_clear(&value);
} END_TEST
#ifdef UA_ENABLE_SUBSCRIPTIONS
static UA_ServerState lastServerState;
static size_t serverStateNotifications;
@@ -446,6 +475,7 @@ int main(void) {
tcase_add_test(tc_status, readServerStatusSecondsTillShutdown);
#ifdef UA_GENERATED_NAMESPACE_ZERO
tcase_add_test(tc_status, readServerStatusDuringShutdown);
tcase_add_test(tc_status, readServerStatusShutdownReason);
#ifdef UA_ENABLE_SUBSCRIPTIONS
tcase_add_test(tc_status, monitorServerStateDuringShutdown);
#endif