DataNode can no longer have Bad status and its last known data...

Questions regarding the use of the C++ SDK for Server or Client development or integration into customer products ...

Moderator: uasdkcpp

Post Reply
tommys
Hero Member
Hero Member
Posts: 40
Joined: 03 Oct 2023, 16:42

DataNode can no longer have Bad status and its last known data...

Post by tommys »

We initialize the status for all our dataNodes to either OpcUa_BadNotSupported or OpcUa_BadWaitingForInitialData. When the nodes that have been initialized with BadWaitingForInitialData get updated with data their status changes to OpcUa_Good if data was valid. This is trivial and used to work really fine, but recently we discovered that these nodes all have status OpcUa_Good, no matter wether they have received any data or not!

So I had to investigate what is going on. It turns out that when we now initialize a dataNode, we now get a BadTypeMismatch error causing the initialization of dataNodes to fail! Because we have not modified our source code involved, I suspect that something in the SDK has changed regarding this, since the only change we have made is to upgrade the C++ Server SDK to v1.8.5. This feels a bit scary.

So, this is how we initialize our dataNodes:

Code: Select all

statusCode = OpcUa_BadWaitingForInitialData;
value = 0.0;

UaVariant varval;
varval.setDouble(value);
UaDataValue dataValue;
dataValue.setValue(varval, OpcUa_True, OpcUa_True);
dataValue.setStatusCode(statusCode);
dataNode->setValue(NULL, dataValue, OpcUa_False);
The call dataNode->setValue leads to a call to UaVariable::checkAttributesForWrite, which has the if-statement:

Code: Select all

if (OpcUa_IsBad(dataValue.statusCode()) && pNewValue->Datatype != OpcUaType_Null)
{
    ret = OpcUa_BadTypeMismatch;
}
Since dataValue.statusCode is OpcUa_BadWaitingForInitialData and pNewValue->Datatype is OpcUaType_Double, this causes the method to return OpcUa_BadTypeMismatch!
And this has the effect that the dataNode is not updated, hence we can quite surprisingly no longer initialize the dataNodes like we previously could!

Fortunately, I've found a work-around, which simply is to check if, and only if the statusCode isn't Bad, we set the data. Otherwise the data type and its value will automatically become null:

Code: Select all

UaVariant varval;
if (OpcUa_IsNotBad(statusCode))
{
    varval.setDouble(value);
}
UaDataValue dataValue;
dataValue.setValue(varval, OpcUa_True, OpcUa_True);
dataValue.setStatusCode(statusCode);
dataNode->setValue(NULL, dataValue, OpcUa_False);
This causes our dataNodes to be initialized as they used to be. There is a slight difference however. Previously the dataType was in this example set to Double and its value was 0.0; while using this new way of initializing the dataNode sets both the dataType and its value to null. For me personally I think this new dataNode handling is better! However, the semantics have been modified making it nowadays impossible(?) to set a Bad status and and the same time set the last known data! Or I have missed something?

I now see that the changelog in v1.8.5 mentions that:
UaVariable - Fix method checkAttributesForWrite to allow writing NULL values if DataType is BaseDataType.

Well, this is what I have observed I guess. What changelog does not mention is the behaviour changes I described above. It would be really nice if you care to explain this change in more detail, for example, shall it no longer be possible to set Bad status and last known data?

Regards,
/Tommy

User avatar
Support Team
Hero Member
Hero Member
Posts: 3268
Joined: 18 Mar 2011, 15:09

Re: DataNode can no longer have Bad status and its last known data...

Post by Support Team »

Hi,

yes the changes in the SDK were required due to some clarifications in the specification. We added some further checks to the SDK to reflect such clarifications in the specification:

namely Part 4, Chapter 7.11.5: "If the Server has no known value - in particular when Severity is BAD, it shall return a NULL value. If the DataType of the Variable is not BaseDataType, the Severity shall be BAD if the value is NULL. If a Variable is created and no default value or initial value is available, the StatusCode shall be Bad_NoValue".

As you already noticed, this is change is an improvement (and avoids bug), plus is reflecting the latest spec.
Best regards
Unified Automation Support Team

tommys
Hero Member
Hero Member
Posts: 40
Joined: 03 Oct 2023, 16:42

Re: DataNode can no longer have Bad status and its last known data...

Post by tommys »

Ok, it really makes sense then. Thank you for your prompt answer and link to relevant part of spec.! :-)

Regards,
/Tommy

Post Reply