ANSI C Based OPC UA Client/Server/PubSub SDK  1.9.4.474
Lesson 5: Register Nodes

Files used in this lesson:

Step 1: Call RegisterNodes to Get Optimised NodeId

The RegisterNodes Service can be used by Clients to register the Nodes that they know they will access repeatedly (e.g. Write, Call). It allows Servers to set up anything needed so that the access operations will be more efficient. Sample client calls RegisterNodes to get optimized NodeId.

OpcUa_StatusCode Sample_Register(UaClient_Session* a_pSession)
{
OpcUa_Int32 numNodesToRegister = 1;
OpcUa_NodeId nodesToRegister[1];
OpcUa_InitializeStatus(OpcUa_Module_Client, "Sample_Register");
OpcUa_NodeId_Initialize(&nodesToRegister[0]);
nodesToRegister[0].NamespaceIndex = 4;
OpcUa_String_StrnCpy(&nodesToRegister[0].Identifier.String, OpcUa_String_FromCString("Demo.Static.Scalar.Int32"), OPCUA_STRING_LENDONTCARE);
uStatus = UaClient_Session_BeginRegisterNodes(a_pSession, /* Session */
OpcUa_Null, /* ServiceSettings */
numNodesToRegister, /* NoOfNodesToRegister */
nodesToRegister, /* NodesToRegister */
Sample_Register_CB, /* Callback Function */
OpcUa_Null); /* Callback UserData */
OpcUa_GotoErrorIfBad(uStatus);
OpcUa_NodeId_Clear(&nodesToRegister[0]);
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_NodeId_Clear(&nodesToRegister[0]);
OpcUa_FinishErrorHandling;
}
OpcUa_Void Sample_Register_CB(const UaClient_Session *a_pSession,
OpcUa_ResponseHeader *a_pResponseHeader,
OpcUa_Int32 a_NoOfRegisteredNodeIds,
OpcUa_NodeId *a_pRegisteredNodeIds,
OpcUa_Void *a_pUserData)
{
SampleClientContext *pClientContext = a_pSession->pUserData;
OpcUa_ReferenceParameter(a_pUserData);
if (OpcUa_IsGood(a_pResponseHeader->ServiceResult))
{
OpcUa_Int32 i;
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "Sample_Register_CB:\n");
if (pClientContext->State == State_Register)
{
pClientContext->State = State_RegisterDone;
pClientContext->noOfRegisteredNodeIds = a_NoOfRegisteredNodeIds;
for (i = 0; i < a_NoOfRegisteredNodeIds; i++)
{
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " [%i]:\n", i);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " IdentifierType: 0x%08x\n", a_pRegisteredNodeIds[i].IdentifierType);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " NamespaceIndex: 0x%08x\n", a_pRegisteredNodeIds[i].NamespaceIndex);
pClientContext->registeredNodeId[i].IdentifierType = a_pRegisteredNodeIds[i].IdentifierType;
pClientContext->registeredNodeId[i].NamespaceIndex = a_pRegisteredNodeIds[i].NamespaceIndex;
switch (a_pRegisteredNodeIds[i].IdentifierType)
{
pClientContext->registeredNodeId[i].Identifier.Numeric = a_pRegisteredNodeIds[i].Identifier.Numeric;
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " Identifier: 0x%08x\n", a_pRegisteredNodeIds[i].Identifier.Numeric);
break;
OpcUa_String_StrnCpy(&pClientContext->registeredNodeId[i].Identifier.String, &a_pRegisteredNodeIds[i].Identifier.String, OPCUA_STRING_LENDONTCARE);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " Identifier: %s\n", OpcUa_String_GetRawString(&a_pRegisteredNodeIds[i].Identifier.String));
break;
default:
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "Sample_Write: Unsupported IdentifierType\n");
break;
}
}
}
else
{
pClientContext->State = State_Error;
}
}
else
{
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "Sample_Register_CB failed (0x%08x)\n", a_pResponseHeader->ServiceResult);
pClientContext->State = State_Error;
}
}

Step 2: Write Value Using Optimised NodeId

Sample client uses optimized NodeId returned by Server to write value.

OpcUa_StatusCode Sample_Write(UaClient_Session* a_pSession)
{
OpcUa_Int32 numNodesToWrite = 1;
OpcUa_WriteValue nodesToWrite[1];
SampleClientContext *pClientContext = a_pSession->pUserData;
OpcUa_InitializeStatus(OpcUa_Module_Client, "Sample_Write");
OpcUa_WriteValue_Initialize(&nodesToWrite[0]);
nodesToWrite[0].AttributeId = OpcUa_Attributes_Value;
nodesToWrite[0].NodeId.NamespaceIndex = pClientContext->registeredNodeId[0].NamespaceIndex;
nodesToWrite[0].NodeId.IdentifierType = pClientContext->registeredNodeId[0].IdentifierType;
switch (nodesToWrite[0].NodeId.IdentifierType)
{
nodesToWrite[0].NodeId.Identifier.Numeric = pClientContext->registeredNodeId[0].Identifier.Numeric;
break;
OpcUa_String_StrnCpy(&nodesToWrite[0].NodeId.Identifier.String, &pClientContext->registeredNodeId[0].Identifier.String, OPCUA_STRING_LENDONTCARE);
break;
default:
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "Sample_Write: Unsupported IdentifierType\n");
break;
}
nodesToWrite[0].Value.Value.Datatype = OpcUaType_Int32;
nodesToWrite[0].Value.Value.ArrayType = OpcUa_VariantArrayType_Scalar;
nodesToWrite[0].Value.Value.Value.Int32 = 6789;
uStatus = UaClient_Session_BeginWrite(a_pSession, /* Session */
OpcUa_Null, /* ServiceSettings */
numNodesToWrite, /* NoOfNodesToWrite */
nodesToWrite, /* NodesToWrite */
Sample_Write_CB, /* Callback Function */
OpcUa_Null); /* Callback UserData */
OpcUa_GotoErrorIfBad(uStatus);
OpcUa_WriteValue_Clear(&nodesToWrite[0]);
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_WriteValue_Clear(&nodesToWrite[0]);
OpcUa_FinishErrorHandling;
}

Step 3: Call UnregisterNodes

Sample client calls UnregisterNodes to unregister NodeId obtained via the RegisterNodes service.

OpcUa_StatusCode Sample_Unregister(UaClient_Session* a_pSession)
{
OpcUa_Int32 numNodesToUnregister = 1;
OpcUa_NodeId nodesToUnregister[1];
OpcUa_InitializeStatus(OpcUa_Module_Client, "Sample_Unregister");
OpcUa_NodeId_Initialize(&nodesToUnregister[0]);
nodesToUnregister[0].NamespaceIndex = 4;
OpcUa_String_StrnCpy(&nodesToUnregister[0].Identifier.String, OpcUa_String_FromCString("Demo.Static.Scalar.Int32"), OPCUA_STRING_LENDONTCARE);
uStatus = UaClient_Session_BeginUnregisterNodes(a_pSession, /* Session */
OpcUa_Null, /* ServiceSettings */
numNodesToUnregister, /* NoOfNodesToUnregister */
nodesToUnregister, /* NodesToUnregister */
Sample_Unregister_CB, /* Callback Function */
OpcUa_Null); /* Callback UserData */
OpcUa_GotoErrorIfBad(uStatus);
OpcUa_NodeId_Clear(&nodesToUnregister[0]);
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_NodeId_Clear(&nodesToUnregister[0]);
OpcUa_FinishErrorHandling;
}

Step 4: Integration in Main loop

while (!(bComplete && pSession->ConnectionStatus == UaClient_ConnectionStatus_Disconnected))
{
/* process sample state machine */
switch (clientContext.State)
{
case State_Idle:
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "UA Client: Connecting to %s ...\n", SERVER_ENDPOINT_URL);
uStatus = UaClient_Session_BeginConnect(pSession);
OpcUa_GotoErrorIfBad(uStatus);
clientContext.State = State_Connect;
break;
case State_Connected:
uStatus = Sample_Register(pSession);
OpcUa_GotoErrorIfBad(uStatus);
clientContext.State = State_Register;
break;
case State_RegisterDone:
uStatus = Sample_Write(pSession);
OpcUa_GotoErrorIfBad(uStatus);
clientContext.State = State_Write;
break;
case State_WriteDone:
uStatus = Sample_Unregister(pSession);
OpcUa_GotoErrorIfBad(uStatus);
clientContext.State = State_Unregister;
break;
case State_UnregisterDone:
uStatus = UaClient_Session_BeginDisconnect(pSession, OpcUa_False);
OpcUa_GotoErrorIfBad(uStatus);
clientContext.State = State_Disconnect;
break;
case State_Disconnected:
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "Sample successfully completed. Terminating now.\n");
bComplete = OpcUa_True;
break;
case State_Error:
uStatus = UaClient_Session_BeginDisconnect(pSession, OpcUa_True);
if (OpcUa_IsBad(uStatus) && uStatus != OpcUa_BadInvalidState) {OpcUa_GotoError;}
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "An error occured. Terminating now.\n");
bComplete = OpcUa_True;
break;
default:
break;
}
/* Process Ua Client events */
uStatus = UaBase_DoCom();
if (OpcUa_IsBad(uStatus))
{
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "UaBase_DoCom failed (0x%08x)\n", uStatus);
bComplete = OpcUa_True;
}
}