The EventFilter data type can be generated automatically by adding it (and its dependencies) to /tools/schema/datatypes_minimal.txt.
I didn't change anything else, except playing around with samplingInterval, discardOldest etc. I've set those at both positions in the code to the values shown in the SoftIng Client.
To subscribe I use
UA_UInt32 subId = 0;
UA_Client_Subscriptions_new(client, UA_SubscriptionSettings_standard, &subId);
if (subId)
printf("Create subscription succeeded, id %u\n", subId);
UA_NodeId monitorThis = UA_NODEID_NUMERIC(0, 2253); // Server
UA_UInt32 monId = 0;
retval = UA_Client_Subscriptions_addMonitoredEventTEST(client, subId, monitorThis, UA_ATTRIBUTEID_EVENTNOTIFIER, &handler_Event, NULL, &monId);
Here's my full function code with marked changes from original UA_Client_Subscriptions_addMonitoredItem function
UA_StatusCode
UA_Client_Subscriptions_addMonitoredEventTEST(UA_Client *client, UA_UInt32 subscriptionId,
UA_NodeId nodeId, UA_UInt32 attributeID,
UA_MonitoredItemHandlingFunction hf,
void *hfContext, UA_UInt32 *newMonitoredItemId) {
UA_Client_Subscription *sub;
LIST_FOREACH(sub, &client->subscriptions, listEntry) {
if(sub->subscriptionID == subscriptionId)
break;
}
if(!sub)
return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
/* Send the request */
UA_CreateMonitoredItemsRequest request;
UA_CreateMonitoredItemsRequest_init(&request);
request.subscriptionId = subscriptionId;
UA_MonitoredItemCreateRequest item;
UA_MonitoredItemCreateRequest_init(&item);
item.itemToMonitor.nodeId = nodeId;
item.itemToMonitor.attributeId = attributeID;
item.monitoringMode = UA_MONITORINGMODE_REPORTING;
item.requestedParameters.clientHandle = ++(client->monitoredItemHandles);
item.requestedParameters.samplingInterval = 0; // mbreiter: changed
item.requestedParameters.discardOldest = false; // mbreiter: changed
item.requestedParameters.queueSize = 0; // mbreiter: changed
// ---------------------------------------------------------------------
//mbreiter:
UA_EventFilter * eFilter = UA_EventFilter_new();
UA_EventFilter_init(eFilter);
// creating a single element array for the select clause of length 1
const size_t nSelectClauses = 1;
UA_SimpleAttributeOperand * selectClauses = UA_Array_new(nSelectClauses, &UA_TYPES[UA_TYPES_SIMPLEATTRIBUTEOPERAND]);
if(selectClauses == 0)
{
// TODO: error handling: array could not be created
}
// set and init
eFilter->selectClausesSize = nSelectClauses;
for(size_t i =0; i<nSelectClauses; ++i )
{
UA_SimpleAttributeOperand_init(&selectClauses[i]);
}
selectClauses[0].typeDefinitionId = UA_NODEID_NUMERIC(0, 2041) ; // mbreiter: BaseEventType hardcoded
selectClauses[0].browsePathSize = 1; // mbreiter: hardcoded single browsePath for testing
{
selectClauses[0].browsePath = (UA_QualifiedName*)UA_Array_new(selectClauses[0].browsePathSize, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]);
if(selectClauses[0].browsePath == 0)
{
// TODO: error handling: array could not be created
}
selectClauses[0].browsePath[0] = UA_QUALIFIEDNAME(0, "EventId");
}
selectClauses[0].attributeId = UA_ATTRIBUTEID_VALUE;
// selectClauses[0].indexRange = ???
eFilter->selectClauses = selectClauses;
eFilter->selectClausesSize = nSelectClauses;
eFilter->whereClause.elementsSize = 0;
// mbreiter: setting the requestedParameters filter information previously created
item.requestedParameters.filter.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE; // UA_EXTENSIONOBJECT_ENCODED_NOBODY = 0, UA_EXTENSIONOBJECT_ENCODED_BYTESTRING = 1, UA_EXTENSIONOBJECT_ENCODED_XML = 2, UA_EXTENSIONOBJECT_DECODED = 3, UA_EXTENSIONOBJECT_DECODED_NODELETE = 4
item.requestedParameters.filter.content.decoded.type = &UA_TYPES[UA_TYPES_EVENTFILTER];
item.requestedParameters.filter.content.decoded.data = eFilter;
// ---------------------------------------------------------------------
request.itemsToCreate = &item;
request.itemsToCreateSize = 1;
UA_CreateMonitoredItemsResponse response = UA_Client_Service_createMonitoredItems(client, request);
// slight misuse of retval here to check if the deletion was successfull.
UA_StatusCode retval;
if(response.resultsSize == 0)
retval = response.responseHeader.serviceResult;
else
retval = response.results[0].statusCode;
if(retval != UA_STATUSCODE_GOOD) {
UA_CreateMonitoredItemsResponse_deleteMembers(&response);
return retval;
}
/* Create the handler */
UA_Client_MonitoredItem *newMon = (UA_Client_MonitoredItem *)UA_malloc(sizeof(UA_Client_MonitoredItem));
newMon->monitoringMode = UA_MONITORINGMODE_REPORTING;
UA_NodeId_copy(&nodeId, &newMon->monitoredNodeId);
newMon->attributeID = attributeID;
newMon->clientHandle = client->monitoredItemHandles;
newMon->samplingInterval = 0; // mbreiter: changed // = sub->publishingInterval;
newMon->queueSize = 0; // mbreiter: changed // = 1; // mbreiter: should be set to same value as above instead of hardcoding?!?
newMon->discardOldest = false; // mbreiter: changed // = true;
newMon->handler = hf;
newMon->handlerContext = hfContext;
newMon->monitoredItemId = response.results[0].monitoredItemId;
LIST_INSERT_HEAD(&sub->monitoredItems, newMon, listEntry);
*newMonitoredItemId = newMon->monitoredItemId;
UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_CLIENT,
"Created a monitored item with client handle %u", client->monitoredItemHandles);
UA_CreateMonitoredItemsResponse_deleteMembers(&response);
return UA_STATUSCODE_GOOD;
}
if(msg->notificationData[k].encoding != UA_EXTENSIONOBJECT_DECODED)