convertersystems / opc-ua-client

Visualize and control your enterprise using OPC Unified Architecture (OPC UA) and Visual Studio.
MIT License
397 stars 115 forks source link

Subscriptions - Error handling #188

Closed dubeg closed 3 years ago

dubeg commented 3 years ago

About subscriptions:

Also, it's kind of a bummer that StatusCodes are members of a static class instead of a proper enum, because then I could use its name to display in a log message. If it were an enum, I could do statusCode.ToString() to get BadNodeIdInvalid, for example.

awcullen commented 3 years ago

Hi, You can check the results of your call to CreateMonitoredItemsAsync. There is a Result for every element of ItemsToCreate.

var itemsResponse = await channel.CreateMonitoredItemsAsync(itemsRequest);
for (int i = 0; i < itemsRequest.ItemsToCreate.Length; i++)
{
    var req = itemsRequest.ItemsToCreate[i];
    var res = itemsResponse.Results[i];
    if (StatusCode.IsBad(res.StatusCode))
    {
        Console.WriteLine($"Unable to subscribe to req.ItemToMonitor.NodeId}.  {StatusCodes.GetDefaultMessage(res.StatusCode)}");
    }
}

OnError is triggered when the channel's internal loop that is calling PublishAsync raises an Exception. For instance, PublishAsync can raise a ServiceResultException with a status code 0x80850000 "Timeout occurred while processing the request." The channel may still be in Opened state at this point. You can call channel.Fault(ex) to cause the channel to change to Faulted state. You can call channel.AbortAsync().Wait() to change to the Closed state.

dubeg commented 3 years ago

Hi @awcullen, thank you for your help. It seems the Opc Ua server I'm coding against (BR Automation) isn't returning a correct CreateMonitoredItemsReponse when the nodeIds don't exist. Ah well.

Is AbortAsync().Wait() in onNext(...) really safe?

dubeg commented 3 years ago

Oh, I think I'll use channel.Fault(..) if StatusCode is InvalidNodeId in onNext(..) instead, based on what you said in the other thread.

Abort disposes the channel without communicating to the server ( which probably has closed it's session anyway)

dubeg commented 3 years ago

Just to note, calling Fault on the channel in onNext doesn't trigger channel.Faulted. I'll to read the src code a bit to understand how it all works :^)