/// <summary> /// Check whether valid node and return service result if not. /// </summary> /// <param name="endpoint"></param> /// <param name="request"></param> /// <returns></returns> private Task <ServiceResultModel> TestPublishNodeAsync(EndpointModel endpoint, PublishStartRequestModel request) { // Test whether value exists and fail if not return(_opc.ExecuteServiceAsync(endpoint, null, TimeSpan.FromSeconds(10), async session => { var readNode = request.Item.NodeId.ToNodeId(session.MessageContext); if (NodeId.IsNull(readNode)) { throw new ArgumentException(nameof(request.Item.NodeId)); } var diagnostics = new List <OperationResultModel>(); var response = await session.ReadAsync( (request.Header?.Diagnostics).ToStackModel(), 0, TimestampsToReturn.Both, new ReadValueIdCollection { new ReadValueId { NodeId = readNode, AttributeId = Attributes.Value } }); OperationResultEx.Validate("Publish_" + readNode, diagnostics, response.Results.Select(r => r.StatusCode), response.DiagnosticInfos, false); SessionClientEx.Validate(response.Results, response.DiagnosticInfos); if (response.Results == null || response.Results.Count == 0) { return diagnostics.ToServiceModel(request.Header?.Diagnostics, session.MessageContext); } return null; })); }
/// <summary> /// Load references /// </summary> /// <param name="nodeModel"></param> /// <param name="ct"></param> /// <returns></returns> public async Task FetchReferencesAsync(BaseNodeModel nodeModel, CancellationToken ct) { try { // Read node with value var response = await _client.ExecuteServiceAsync(_endpoint, _elevation, _priority, ct, session => { _encoder.Context.UpdateFromSession(session); return(session.BrowseAsync(_diagnostics.ToStackModel(), null, nodeModel.NodeId, 0u, Opc.Ua.BrowseDirection.Both, ReferenceTypeIds.References, true, 0u)); }); SessionClientEx.Validate(response.Results, response.DiagnosticInfos); OperationResultEx.Validate("Browse_" + nodeModel.NodeId, Diagnostics, response.Results.Select(r => r.StatusCode), null, false); while (true) { foreach (var reference in response.Results[0].References) { nodeModel.AddReference(reference.ReferenceTypeId, !reference.IsForward, reference.NodeId); _references++; } if (response.Results[0].ContinuationPoint == null) { break; } response = await _client.ExecuteServiceAsync(_endpoint, _elevation, _priority, ct, session => { _encoder.Context.UpdateFromSession(session); return(session.BrowseNextAsync(_diagnostics.ToStackModel(), false, new ByteStringCollection { response.Results[0].ContinuationPoint })); }); SessionClientEx.Validate(response.Results, response.DiagnosticInfos); OperationResultEx.Validate("BrowseNext_" + nodeModel.NodeId, Diagnostics, response.Results.Select(r => r.StatusCode), null, false); } } catch (Exception ex) { _logger.Error(ex, "Failed browsing node object for node {nodeId}.", nodeModel.NodeId); } }
/// <summary> /// Validates responses against requests /// </summary> /// <typeparam name="T"></typeparam> /// <param name="operation"></param> /// <param name="results"></param> /// <param name="diagnostics"></param> /// <param name="requested"></param> /// <param name="operations"></param> /// <param name="traceOnly"></param> public static void Validate <T>(string operation, List <OperationResultModel> operations, IEnumerable <StatusCode> results, DiagnosticInfoCollection diagnostics, IEnumerable <T> requested, bool traceOnly) { if (operations == null) { SessionClientEx.Validate(results, diagnostics, requested); return; } if (diagnostics == null) { diagnostics = new DiagnosticInfoCollection(); } var resultsWithStatus = results?.ToList(); if (resultsWithStatus == null || (resultsWithStatus.Count == 0 && diagnostics.Count == 0)) { throw new ServiceResultException(StatusCodes.BadUnexpectedError, "The server returned no results or diagnostics information."); } // Add diagnostics var ids = requested?.ToArray() ?? new T[0]; for (var index = resultsWithStatus.Count; index < diagnostics.Count; index++) { resultsWithStatus.Add(diagnostics[index] == null ? StatusCodes.Good : StatusCodes.BadUnexpectedError); } operations.AddRange(results .Select((status, index) => new OperationResultModel { Operation = index < ids.Length ? $"{operation}_{ids[index]}" : operation, DiagnosticsInfo = index < diagnostics.Count ? diagnostics[index] : null, StatusCode = status, TraceOnly = traceOnly }) .Where(o => o.StatusCode != StatusCodes.Good || o.DiagnosticsInfo != null)); }