Files used in this lesson:
Step 1: Create Subscription with a Event Monitored Item
Sample client creates a subscription with EventMonitoredItem. The Event filter is set to receive only events of type "HeaterSwitchedEventType"(included in tutorial lesson05 server) and the event fields to include in the notification message are specified.
{
SampleSubscription *pSampleSubscription = OpcUa_Null;
pSampleSubscription = OpcUa_Alloc(sizeof(*pSampleSubscription));
if (pSampleSubscription == OpcUa_Null)
{
return OpcUa_Null;
}
OpcUa_MemSet(&subscriptionCallback, 0, sizeof(subscriptionCallback));
subscriptionCallback.pfStatusChanged_CB = SampleSubscription_StatusChanged_CB;
subscriptionCallback.pfDataChange_CB = SampleSubscription_DataChange_CB;
subscriptionCallback.pfNewEvents_CB = SampleSubscription_NewEvent_CB;
if (OpcUa_IsBad(uStatus))
{
OpcUa_Free(pSampleSubscription);
return OpcUa_Null;
}
pSampleSubscription->pSubscription = pSubscription;
pSampleSubscription->uDataCount = 0;
pSampleSubscription->uMonitoredItemId = 0;
pSampleSubscription->State = State_SampleSubscription_Idle;
pSubscription->
pUserData = pSampleSubscription;
return pSampleSubscription;
}
OpcUa_StatusCode SampleSubscription_CreateSubscription(SampleSubscription *a_pSampleSubscription)
{
a_pSampleSubscription->State = State_SampleSubscription_SubscriptionCreate;
OpcUa_Null,
SampleSubscription_Created_CB,
OpcUa_Null);
}
OpcUa_StatusCode SampleSubscription_CreateMonitoredItem(SampleSubscription *a_pSampleSubscription)
{
OpcUa_Int32 i;
OpcUa_Int32 numItemsToCreate = 1;
OpcUa_LiteralOperand *pRawOperand = OpcUa_Null;
OpcUa_Int32 noOfSelectClauses = 3;
OpcUa_InitializeStatus(OpcUa_Module_Client, "SampleSubscription_CreateMonitoredItem");
a_pSampleSubscription->State = State_SampleSubscription_MonitoredItemCreate;
OpcUa_MonitoredItemCreateRequest_Initialize(&itemsToCreate);
(OpcUa_Void**)&pEventFilter);
OpcUa_GotoErrorIfBad(uStatus);
pEventFilter->NoOfSelectClauses = noOfSelectClauses;
for (i = 0; i < noOfSelectClauses; i++)
{
OpcUa_SimpleAttributeOperand_Initialize(&pEventFilter->
SelectClauses[i]);
}
OpcUa_GotoErrorIfBad(uStatus);
OpcUa_GotoErrorIfBad(uStatus);
OpcUa_GotoErrorIfBad(uStatus);
(OpcUa_Void**)&pRawOperand);
OpcUa_GotoErrorIfBad(uStatus);
pRawOperand->Value.Datatype = OpcUaType_NodeId;
OpcUa_GotoErrorIfAllocFailed(pRawOperand->Value.Value.NodeId);
OpcUa_NodeId_Initialize(pRawOperand->Value.Value.NodeId);
pRawOperand->Value.Value.NodeId->NamespaceIndex = 4;
pRawOperand->Value.Value.NodeId->Identifier.Numeric = 2;
OpcUa_Null,
numItemsToCreate,
&itemsToCreate,
SampleSubscription_MonitoredItems_Created_CB,
OpcUa_Null);
OpcUa_GotoErrorIfBad(uStatus);
OpcUa_MonitoredItemCreateRequest_Clear(&itemsToCreate);
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_MonitoredItemCreateRequest_Clear(&itemsToCreate);
OpcUa_FinishErrorHandling;
}
Step 2: Receive Event Notifications via UaClient_Subscription_Callback.pfNewEvents_CB
Sample client receives event notifications in NewEvents callback.
OpcUa_Int32 a_noOfEvents,
OpcUa_EventFieldList *a_pEvents)
{
SampleSubscription *pSampleSubscription = a_pSubscription->
pUserData;
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "\n--> SampleSubscription_NewEvent_CB\n\n");
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " noOfEvents: %i\n", a_noOfEvents);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING,
"Message = %s\n", OpcUa_String_GetRawString(&message.
Value.LocalizedText->Text));
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING,
"SourceName = %s\n", OpcUa_String_GetRawString(&sourceName.
Value.String));
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING,
"Severity = %u\n", severity.
Value.UInt16);
if (pSampleSubscription->State == State_SampleSubscription_WaitForNewEvent)
pSampleSubscription->State = State_SampleSubscription_NewEventReceived;
else
pSampleSubscription->State = State_SampleSubscription_Error;
}
Step 3: Call Methods to Trigger Events on Server
To test the event monitored item set up in the previous steps, Sample client calls method SetSwitchState of MyCustomMachine object that triggers an event matching filter criteria.
{
OpcUa_InitializeStatus(OpcUa_Module_Client, "Sample_MethodCall");
OpcUa_CallMethodRequest_Initialize(&callMethodRequest);
callMethodRequest.NoOfInputArguments = 1;
OpcUa_Null,
&callMethodRequest,
Sample_MethodCall_CB,
OpcUa_Null);
OpcUa_GotoErrorIfBad(uStatus);
OpcUa_CallMethodRequest_Clear(&callMethodRequest);
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_CallMethodRequest_Clear(&callMethodRequest);
OpcUa_FinishErrorHandling;
}
Step 4: Integration in Main loop
{
switch (clientContext.State)
{
case State_Idle:
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "UA Client: Connecting to %s ...\n", SERVER_ENDPOINT_URL);
OpcUa_GotoErrorIfBad(uStatus);
clientContext.State = State_Connect;
break;
case State_Connected:
pSampleSubscription = SampleSubscription_Create(pSession);
OpcUa_GotoErrorIfArgumentNull(pSampleSubscription);
uStatus = SampleSubscription_CreateSubscription(pSampleSubscription);
OpcUa_GotoErrorIfBad(uStatus);
clientContext.State = State_Subscription;
break;
case State_Subscription:
switch (pSampleSubscription->State)
{
case State_SampleSubscription_SubscriptionCreateDone:
uStatus = SampleSubscription_CreateMonitoredItem(pSampleSubscription);
OpcUa_GotoErrorIfBad(uStatus);
break;
case State_SampleSubscription_MonitoredItemCreateDone:
uStatus = Sample_MethodCall(pSession);
OpcUa_GotoErrorIfBad(uStatus);
pSampleSubscription->State = State_SampleSubscription_WaitForNewEvent;
clientContext.State = State_MethodCall;
break;
case State_SampleSubscription_NewEventReceived:
uStatus = SampleSubscription_DeleteMonitoredItem(pSampleSubscription);
OpcUa_GotoErrorIfBad(uStatus);
break;
case State_SampleSubscription_MonitoredItemDeleteDone:
uStatus = SampleSubscription_DeleteSubscription(pSampleSubscription);
OpcUa_GotoErrorIfBad(uStatus);
break;
case State_SampleSubscription_SubscriptionDeleteDone:
SampleSubscription_Delete(&pSampleSubscription);
pSampleSubscription = OpcUa_Null;
OpcUa_GotoErrorIfBad(uStatus);
clientContext.State = State_Disconnect;
break;
case State_SampleSubscription_Error:
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "An error occured. Terminating now.\n");
bComplete = OpcUa_True;
break;
default:
break;
}
break;
case State_MethodCallDone:
clientContext.State = State_Subscription;
break;
case State_Disconnected:
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "Sample successfully completed. Terminating now.\n");
bComplete = OpcUa_True;
break;
case State_Error:
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;
}
if (OpcUa_IsBad(uStatus))
{
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "UaBase_DoCom failed (0x%08x)\n", uStatus);
bComplete = OpcUa_True;
}
}