/// <summary>
        /// Releases the history continuation point.
        /// </summary>
        protected override void HistoryReleaseContinuationPoints(
            ServerSystemContext context,
            IList <HistoryReadValueId> nodesToRead,
            IList <ServiceResult> errors,
            List <NodeHandle> nodesToProcess,
            IDictionary <NodeId, NodeState> cache)
        {
            for (int ii = 0; ii < nodesToProcess.Count; ii++)
            {
                NodeHandle         handle     = nodesToProcess[ii];
                HistoryReadValueId nodeToRead = nodesToRead[handle.Index];

                // find the continuation point.
                HistoryReadRequest request = LoadContinuationPoint(context, nodeToRead.ContinuationPoint);

                if (request == null)
                {
                    errors[handle.Index] = StatusCodes.BadContinuationPointInvalid;
                    continue;
                }

                // all done.
                errors[handle.Index] = StatusCodes.Good;
            }
        }
Exemple #2
0
        public static LogEntry For(HistoryReadRequest request)
        {
            LogEntry entry = new LogEntry("HistoryReadRequest");

            entry.Add("RequestHeader", For(request.RequestHeader));
            entry.Add("HistoryReadDetails", For(request.HistoryReadDetails));
            entry.Add("TimestampsToReturn", For(request.TimestampsToReturn));
            entry.Add("ReleaseContinuationPoints", For(request.ReleaseContinuationPoints));
            entry.Add("NodesToRead", For(request.NodesToRead));
            return(entry);
        }
Exemple #3
0
        public async Task HistoryReadAsync()
        {
            var response = new HistoryReadResponse();
            var request  = new HistoryReadRequest();
            var channel  = new TestRequestChannel(response);

            var ret = await channel.HistoryReadAsync(request);

            ret
            .Should().BeSameAs(response);

            channel.Request
            .Should().BeSameAs(request);
        }
        /// <summary>
        /// Saves a history continuation point.
        /// </summary>
        private byte[] SaveContinuationPoint(
            ServerSystemContext context,
            HistoryReadRequest request)
        {
            Session session = context.OperationContext.Session;

            if (session == null)
            {
                return(null);
            }

            Guid id = Guid.NewGuid();

            session.SaveHistoryContinuationPoint(id, request);
            request.ContinuationPoint = id.ToByteArray();
            return(request.ContinuationPoint);
        }
        /// <summary>
        /// Loads a history continuation point.
        /// </summary>
        private HistoryReadRequest LoadContinuationPoint(
            ServerSystemContext context,
            byte[] continuationPoint)
        {
            Session session = context.OperationContext.Session;

            if (session == null)
            {
                return(null);
            }

            HistoryReadRequest request = session.RestoreHistoryContinuationPoint(continuationPoint) as HistoryReadRequest;

            if (request == null)
            {
                return(null);
            }

            return(request);
        }
        /// <summary>
        /// Fetches the requested event fields from the event.
        /// </summary>
        private HistoryEventFieldList GetEventFields(HistoryReadRequest request, IFilterTarget instance)
        {
            // fetch the event fields.
            HistoryEventFieldList fields = new HistoryEventFieldList();

            foreach (SimpleAttributeOperand clause in request.Filter.SelectClauses)
            {
                // get the value of the attribute (apply localization).
                object value = instance.GetAttributeValue(
                    request.FilterContext,
                    clause.TypeDefinitionId,
                    clause.BrowsePath,
                    clause.AttributeId,
                    clause.ParsedIndexRange);

                // add the value to the list of event fields.
                if (value != null)
                {
                    // translate any localized text.
                    LocalizedText text = value as LocalizedText;

                    if (text != null)
                    {
                        value = Server.ResourceManager.Translate(request.FilterContext.PreferredLocales, text);
                    }

                    // add value.
                    fields.EventFields.Add(new Variant(value));
                }

                // add a dummy entry for missing values.
                else
                {
                    fields.EventFields.Add(Variant.Null);
                }
            }

            return(fields);
        }
Exemple #7
0
        /// <summary>
        /// Reads historical values or Events of one or more Nodes.
        /// </summary>
        /// <param name="client">A instance of <see cref="IRequestChannel"/>.</param>
        /// <param name="request">A <see cref="HistoryReadRequest"/>.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation that returns a <see cref="HistoryReadResponse"/>.</returns>
        public static async Task <HistoryReadResponse> HistoryReadAsync(this IRequestChannel client, HistoryReadRequest request)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            return((HistoryReadResponse)await client.RequestAsync(request).ConfigureAwait(false));
        }
Exemple #8
0
        public async Task ReadHistorical()
        {
            var channel = new UaTcpSessionChannel(
                this.localDescription,
                this.certificateStore,
                null,
                EndpointUrl);

            await channel.OpenAsync();

            Console.WriteLine($"Opened session with endpoint '{channel.RemoteEndpoint.EndpointUrl}'.");
            Console.WriteLine($"SecurityPolicy: '{channel.RemoteEndpoint.SecurityPolicyUri}'.");
            Console.WriteLine($"SecurityMode: '{channel.RemoteEndpoint.SecurityMode}'.");
            Console.WriteLine($"Activated session '{channel.SessionId}'.");

            var historyReadRequest = new HistoryReadRequest
            {
                HistoryReadDetails = new ReadRawModifiedDetails
                {
                    StartTime      = DateTime.UtcNow - TimeSpan.FromMinutes(10),
                    EndTime        = DateTime.UtcNow,
                    ReturnBounds   = true,
                    IsReadModified = false
                },
                NodesToRead = new[]
                {
                    new HistoryReadValueId
                    {
                        NodeId = NodeId.Parse("ns=2;s=MyLevel")
                    }
                },
            };
            var historyReadResponse = await channel.HistoryReadAsync(historyReadRequest);

            var result = historyReadResponse.Results[0];

            Assert.IsTrue(StatusCode.IsGood(result.StatusCode));
            Console.WriteLine($"HistoryRead response status code: {result.StatusCode}, HistoryData count: {((HistoryData)result.HistoryData.Body).DataValues.Length}.");

            var historyReadRequest2 = new HistoryReadRequest
            {
                HistoryReadDetails = new ReadEventDetails
                {
                    StartTime = DateTime.UtcNow - TimeSpan.FromMinutes(10),
                    EndTime   = DateTime.UtcNow,
                    Filter    = new EventFilter // Use EventHelper to select all the fields of AlarmCondition.
                    {
                        SelectClauses = EventHelper.GetSelectClauses <AlarmCondition>()
                    }
                },
                NodesToRead = new[]
                {
                    new HistoryReadValueId
                    {
                        NodeId = NodeId.Parse("ns=2;s=MyDevice")
                    }
                },
            };
            var historyReadResponse2 = await channel.HistoryReadAsync(historyReadRequest2);

            var result2 = historyReadResponse2.Results[0];

            Assert.IsTrue(StatusCode.IsGood(result2.StatusCode));
            Console.WriteLine($"HistoryRead response status code: {result2.StatusCode}, HistoryEvent count: {((HistoryEvent)result2.HistoryData.Body).Events.Length}.");

            // Use EventHelper to create AlarmConditions from the HistoryEventFieldList
            var alarms = ((HistoryEvent)result2.HistoryData.Body).Events.Select(e => EventHelper.Deserialize <AlarmCondition>(e.EventFields));

            Console.WriteLine($"Closing session '{channel.SessionId}'.");
            await channel.CloseAsync();
        }
        /// <summary>
        /// Creates a new history request.
        /// </summary>
        private HistoryReadRequest CreateHistoryReadRequest(
            ServerSystemContext context,
            ReadEventDetails details,
            NodeHandle handle,
            HistoryReadValueId nodeToRead)
        {
            FilterContext filterContext        = new FilterContext(context.NamespaceUris, context.TypeTable, context.PreferredLocales);
            LinkedList <BaseEventState> events = new LinkedList <BaseEventState>();

            for (ReportType ii = ReportType.FluidLevelTest; ii <= ReportType.InjectionTest; ii++)
            {
                DataView view = null;

                if (handle.Node is WellState)
                {
                    view = m_generator.ReadHistoryForWellId(
                        ii,
                        (string)handle.Node.NodeId.Identifier,
                        details.StartTime,
                        details.EndTime);
                }
                else
                {
                    view = m_generator.ReadHistoryForArea(
                        ii,
                        handle.Node.NodeId.Identifier as string,
                        details.StartTime,
                        details.EndTime);
                }

                LinkedListNode <BaseEventState> pos = events.First;
                bool sizeLimited = (details.StartTime == DateTime.MinValue || details.EndTime == DateTime.MinValue);

                foreach (DataRowView row in view)
                {
                    // check if reached max results.
                    if (sizeLimited)
                    {
                        if (events.Count >= details.NumValuesPerNode)
                        {
                            break;
                        }
                    }

                    BaseEventState e = m_generator.GetReport(context, NamespaceIndex, ii, row.Row);

                    if (details.Filter.WhereClause != null && details.Filter.WhereClause.Elements.Count > 0)
                    {
                        if (!details.Filter.WhereClause.Evaluate(filterContext, e))
                        {
                            continue;
                        }
                    }

                    bool inserted = false;

                    for (LinkedListNode <BaseEventState> jj = pos; jj != null; jj = jj.Next)
                    {
                        if (jj.Value.Time.Value > e.Time.Value)
                        {
                            events.AddBefore(jj, e);
                            pos      = jj;
                            inserted = true;
                            break;
                        }
                    }

                    if (!inserted)
                    {
                        events.AddLast(e);
                        pos = null;
                    }
                }
            }

            HistoryReadRequest request = new HistoryReadRequest();

            request.Events            = events;
            request.TimeFlowsBackward = details.StartTime == DateTime.MinValue || (details.EndTime != DateTime.MinValue && details.EndTime < details.StartTime);
            request.NumValuesPerNode  = details.NumValuesPerNode;
            request.Filter            = details.Filter;
            request.FilterContext     = filterContext;
            return(request);
        }
        /// <summary>
        /// Reads history events.
        /// </summary>
        protected override void HistoryReadEvents(
            ServerSystemContext context,
            ReadEventDetails details,
            TimestampsToReturn timestampsToReturn,
            IList <HistoryReadValueId> nodesToRead,
            IList <HistoryReadResult> results,
            IList <ServiceResult> errors,
            List <NodeHandle> nodesToProcess,
            IDictionary <NodeId, NodeState> cache)
        {
            for (int ii = 0; ii < nodesToProcess.Count; ii++)
            {
                NodeHandle         handle     = nodesToProcess[ii];
                HistoryReadValueId nodeToRead = nodesToRead[handle.Index];
                HistoryReadResult  result     = results[handle.Index];

                HistoryReadRequest request = null;

                // load an exising request.
                if (nodeToRead.ContinuationPoint != null)
                {
                    request = LoadContinuationPoint(context, nodeToRead.ContinuationPoint);

                    if (request == null)
                    {
                        errors[handle.Index] = StatusCodes.BadContinuationPointInvalid;
                        continue;
                    }
                }

                // create a new request.
                else
                {
                    request = CreateHistoryReadRequest(
                        context,
                        details,
                        handle,
                        nodeToRead);
                }

                // process events until the max is reached.
                HistoryEvent events = new HistoryEvent();

                while (request.NumValuesPerNode == 0 || events.Events.Count < request.NumValuesPerNode)
                {
                    if (request.Events.Count == 0)
                    {
                        break;
                    }

                    BaseEventState e = null;

                    if (request.TimeFlowsBackward)
                    {
                        e = request.Events.Last.Value;
                        request.Events.RemoveLast();
                    }
                    else
                    {
                        e = request.Events.First.Value;
                        request.Events.RemoveFirst();
                    }

                    events.Events.Add(GetEventFields(request, e));
                }

                errors[handle.Index] = ServiceResult.Good;

                // check if a continuation point is requred.
                if (request.Events.Count > 0)
                {
                    // only set if both end time and start time are specified.
                    if (details.StartTime != DateTime.MinValue && details.EndTime != DateTime.MinValue)
                    {
                        result.ContinuationPoint = SaveContinuationPoint(context, request);
                    }
                }

                // check if no data returned.
                else
                {
                    errors[handle.Index] = StatusCodes.GoodNoData;
                }

                // return the data.
                result.HistoryData = new ExtensionObject(events);
            }
        }
Exemple #11
0
 /// <summary>
 /// Initializes the message with the body.
 /// </summary>
 public HistoryReadMessage(HistoryReadRequest HistoryReadRequest)
 {
     this.HistoryReadRequest = HistoryReadRequest;
 }
        /// <summary>
        /// Saves a history continuation point.
        /// </summary>
        private byte[] SaveContinuationPoint(
            ServerSystemContext context,
            HistoryReadRequest request)
        {
            Session session = context.OperationContext.Session;

            if (session == null)
            {
                return null;
            }

            Guid id = Guid.NewGuid();
            session.SaveHistoryContinuationPoint(id, request);
            request.ContinuationPoint = id.ToByteArray();
            return request.ContinuationPoint;
        }
        /// <summary>
        /// Creates a new history request.
        /// </summary>
        private HistoryReadRequest CreateHistoryReadRequest(
            ServerSystemContext context,
            ReadRawModifiedDetails details,
            NodeHandle handle,
            HistoryReadValueId nodeToRead)
        {
            bool sizeLimited = (details.StartTime == DateTime.MinValue || details.EndTime == DateTime.MinValue);
            bool applyIndexRangeOrEncoding = (nodeToRead.ParsedIndexRange != NumericRange.Empty || !QualifiedName.IsNull(nodeToRead.DataEncoding));
            bool returnBounds = !details.IsReadModified && details.ReturnBounds;
            bool timeFlowsBackward = (details.StartTime == DateTime.MinValue) || (details.EndTime != DateTime.MinValue && details.EndTime < details.StartTime);

            // find the archive item.
            ArchiveItemState item = Reload(context, handle);

            if (item == null)
            {
                throw new ServiceResultException(StatusCodes.BadNotSupported);
            }

            LinkedList<DataValue> values = new LinkedList<DataValue>();
            LinkedList<ModificationInfo> modificationInfos = null;

            if (details.IsReadModified)
            {
                modificationInfos = new LinkedList<ModificationInfo>();
            }

            // read history. 
            DataView view = item.ReadHistory(details.StartTime, details.EndTime, details.IsReadModified, handle.Node.BrowseName);

            int startBound = -1;
            int endBound = -1;
            int ii = (timeFlowsBackward)?view.Count-1:0;

            while (ii >= 0 && ii < view.Count)
            {
                try
                {
                    DateTime timestamp = (DateTime)view[ii].Row[0];

                    // check if looking for start of data.
                    if (values.Count == 0)
                    {
                        if (timeFlowsBackward)
                        {
                            if ((details.StartTime != DateTime.MinValue && timestamp >= details.StartTime) || (details.StartTime == DateTime.MinValue &&  timestamp >= details.EndTime))
                            {
                                startBound = ii;

                                if (timestamp > details.StartTime)
                                {
                                    continue;
                                }
                            }
                        }
                        else
                        {
                            if (timestamp <= details.StartTime)
                            {
                                startBound = ii;

                                if (timestamp < details.StartTime)
                                {
                                    continue;
                                }
                            }
                        }
                    }

                    // check if absolute max values specified.
                    if (sizeLimited)
                    {
                        if (details.NumValuesPerNode > 0 && details.NumValuesPerNode < values.Count)
                        {
                            break;
                        }
                    }

                    // check for end bound.
                    if (details.EndTime != DateTime.MinValue && timestamp >= details.EndTime)
                    {
                        if (timeFlowsBackward)
                        {
                            if (timestamp <= details.EndTime)
                            {
                                endBound = ii;
                                break;
                            }
                        }
                        else
                        {
                            if (timestamp >= details.EndTime)
                            {
                                endBound = ii;
                                break;
                            }
                        }
                    }

                    // check if the start bound needs to be returned.
                    if (returnBounds && values.Count == 0 && startBound != ii && details.StartTime != DateTime.MinValue)
                    {
                        // add start bound.
                        if (startBound == -1)
                        {
                            values.AddLast(new DataValue(Variant.Null, StatusCodes.BadBoundNotFound, details.StartTime, details.StartTime));
                        }
                        else
                        {
                            values.AddLast(RowToDataValue(context, nodeToRead, view[startBound], applyIndexRangeOrEncoding));
                        }

                        // check if absolute max values specified.
                        if (sizeLimited)
                        {
                            if (details.NumValuesPerNode > 0 && details.NumValuesPerNode < values.Count)
                            {
                                break;
                            }
                        }
                    }

                    // add value.
                    values.AddLast(RowToDataValue(context, nodeToRead, view[ii], applyIndexRangeOrEncoding));

                    if (modificationInfos != null)
                    {
                        modificationInfos.AddLast((ModificationInfo)view[ii].Row[6]);
                    }
                }
                finally
                {
                    if (timeFlowsBackward)
                    {
                        ii--;
                    }
                    else
                    {
                        ii++;
                    }
                }
            }

            // add late bound.
            while (returnBounds && details.EndTime != DateTime.MinValue)
            {
                // add start bound.
                if (values.Count == 0)
                {
                    if (startBound == -1)
                    {
                        values.AddLast(new DataValue(Variant.Null, StatusCodes.BadBoundNotFound, details.StartTime, details.StartTime));
                    }
                    else
                    {
                        values.AddLast(RowToDataValue(context, nodeToRead, view[startBound], applyIndexRangeOrEncoding));
                    }
                }

                // check if absolute max values specified.
                if (sizeLimited)
                {
                    if (details.NumValuesPerNode > 0 && details.NumValuesPerNode < values.Count)
                    {
                        break;
                    }
                }

                // add end bound.
                if (endBound == -1)
                {
                    values.AddLast(new DataValue(Variant.Null, StatusCodes.BadBoundNotFound, details.EndTime, details.EndTime));
                }
                else
                {
                    values.AddLast(RowToDataValue(context, nodeToRead, view[endBound], applyIndexRangeOrEncoding));
                }

                break;
            }

            HistoryReadRequest request = new HistoryReadRequest();
            request.Values = values;
            request.ModificationInfos = modificationInfos;
            request.NumValuesPerNode = details.NumValuesPerNode;
            request.Filter = null;
            return request;
        }
        /// <summary>
        /// Creates a new history request.
        /// </summary>
        private HistoryReadRequest CreateHistoryReadRequest(
            ServerSystemContext context,
            ReadProcessedDetails details,
            NodeHandle handle,
            HistoryReadValueId nodeToRead,
            NodeId aggregateId)
        {
            bool applyIndexRangeOrEncoding = (nodeToRead.ParsedIndexRange != NumericRange.Empty || !QualifiedName.IsNull(nodeToRead.DataEncoding));
            bool timeFlowsBackward = (details.EndTime < details.StartTime);

            ArchiveItemState item = handle.Node as ArchiveItemState;

            if (item == null)
            {
                throw new ServiceResultException(StatusCodes.BadNotSupported);
            }

            item.ReloadFromSource(context);

            LinkedList<DataValue> values = new LinkedList<DataValue>();

            // read history. 
            DataView view = item.ReadHistory(details.StartTime, details.EndTime, false);

            int ii = (timeFlowsBackward) ? view.Count - 1 : 0;

            // choose the aggregate configuration.
            AggregateConfiguration configuration = (AggregateConfiguration)details.AggregateConfiguration.Clone();
            ReviseAggregateConfiguration(context, item, configuration);

            // create the aggregate calculator.
            IAggregateCalculator calculator = Server.AggregateManager.CreateCalculator(
                aggregateId,
                details.StartTime,
                details.EndTime,
                details.ProcessingInterval,
                item.ArchiveItem.Stepped,
                configuration);

            while (ii >= 0 && ii < view.Count)
            {
                try
                {
                    DataValue value = (DataValue)view[ii].Row[2];
                    calculator.QueueRawValue(value);

                    // queue any processed values.
                    QueueProcessedValues(
                        context,
                        calculator,
                        nodeToRead.ParsedIndexRange,
                        nodeToRead.DataEncoding,
                        applyIndexRangeOrEncoding,
                        false,
                        values);
                }
                finally
                {
                    if (timeFlowsBackward)
                    {
                        ii--;
                    }
                    else
                    {
                        ii++;
                    }
                }
            }

            // queue any processed values beyond the end of the data.
            QueueProcessedValues(
                context,
                calculator,
                nodeToRead.ParsedIndexRange,
                nodeToRead.DataEncoding,
                applyIndexRangeOrEncoding,
                true,
                values);

            HistoryReadRequest request = new HistoryReadRequest();
            request.Values = values;
            request.NumValuesPerNode = 0;
            request.Filter = null;
            return request;
        }
Exemple #15
0
        /// <summary>
        /// Begins an asynchronous invocation of the HistoryRead service.
        /// </summary>
        public IAsyncResult BeginHistoryRead(
            RequestHeader                requestHeader,
            ExtensionObject              historyReadDetails,
            TimestampsToReturn           timestampsToReturn,
            bool                         releaseContinuationPoints,
            HistoryReadValueIdCollection nodesToRead,
            AsyncCallback                callback,
            object                       asyncState)
        {
            HistoryReadRequest request = new HistoryReadRequest();

            request.RequestHeader             = requestHeader;
            request.HistoryReadDetails        = historyReadDetails;
            request.TimestampsToReturn        = timestampsToReturn;
            request.ReleaseContinuationPoints = releaseContinuationPoints;
            request.NodesToRead               = nodesToRead;

            UpdateRequestHeader(request, requestHeader == null, "HistoryRead");

            if (UseTransportChannel)
            {
                return TransportChannel.BeginSendRequest(request, callback, asyncState);
            }

            return InnerChannel.BeginHistoryRead(new HistoryReadMessage(request), callback, asyncState);
        }
Exemple #16
0
        /// <summary>
        /// Invokes the HistoryRead service.
        /// </summary>
        public virtual ResponseHeader HistoryRead(
            RequestHeader                   requestHeader,
            ExtensionObject                 historyReadDetails,
            TimestampsToReturn              timestampsToReturn,
            bool                            releaseContinuationPoints,
            HistoryReadValueIdCollection    nodesToRead,
            out HistoryReadResultCollection results,
            out DiagnosticInfoCollection    diagnosticInfos)
        {
            HistoryReadRequest request = new HistoryReadRequest();
            HistoryReadResponse response = null;

            request.RequestHeader             = requestHeader;
            request.HistoryReadDetails        = historyReadDetails;
            request.TimestampsToReturn        = timestampsToReturn;
            request.ReleaseContinuationPoints = releaseContinuationPoints;
            request.NodesToRead               = nodesToRead;

            UpdateRequestHeader(request, requestHeader == null, "HistoryRead");

            try
            {
                if (UseTransportChannel)
                {
                    IServiceResponse genericResponse = TransportChannel.SendRequest(request);

                    if (genericResponse == null)
                    {
                        throw new ServiceResultException(StatusCodes.BadUnknownResponse);
                    }

                    ValidateResponse(genericResponse.ResponseHeader);
                    response = (HistoryReadResponse)genericResponse;
                }
                else
                {
                    HistoryReadResponseMessage responseMessage = InnerChannel.HistoryRead(new HistoryReadMessage(request));

                    if (responseMessage == null || responseMessage.HistoryReadResponse == null)
                    {
                        throw new ServiceResultException(StatusCodes.BadUnknownResponse);
                    }

                    response = responseMessage.HistoryReadResponse;
                    ValidateResponse(response.ResponseHeader);
                }

                results         = response.Results;
                diagnosticInfos = response.DiagnosticInfos;
            }
            finally
            {
                RequestCompleted(request, response, "HistoryRead");
            }

            return response.ResponseHeader;
        }
        /// <summary>
        /// Creates a new history request.
        /// </summary>
        private HistoryReadRequest CreateHistoryReadRequest(
            ServerSystemContext context,
            ReadAtTimeDetails details,
            NodeHandle handle,
            HistoryReadValueId nodeToRead)
        {
            bool applyIndexRangeOrEncoding = (nodeToRead.ParsedIndexRange != NumericRange.Empty || !QualifiedName.IsNull(nodeToRead.DataEncoding));

            ArchiveItemState item = handle.Node as ArchiveItemState;

            if (item == null)
            {
                throw new ServiceResultException(StatusCodes.BadNotSupported);
            }

            item.ReloadFromSource(context);

            // find the start and end times.
            DateTime startTime = DateTime.MaxValue;
            DateTime endTime = DateTime.MinValue;

            for (int ii = 0; ii < details.ReqTimes.Count; ii++)
            {
                if (startTime > details.ReqTimes[ii])
                {
                    startTime = details.ReqTimes[ii];
                }

                if (endTime < details.ReqTimes[ii])
                {
                    endTime = details.ReqTimes[ii];
                }
            }
            
            DataView view = item.ReadHistory(startTime, endTime, false);

            LinkedList<DataValue> values = new LinkedList<DataValue>();

            for (int ii = 0; ii < details.ReqTimes.Count; ii++)
            {
                bool dataBeforeIgnored = false;
                bool dataAfterIgnored = false;

                // find the value at the time.
                int index = item.FindValueAtOrBefore(view, details.ReqTimes[ii], !details.UseSimpleBounds, out dataBeforeIgnored);

                if (index < 0)
                {
                    values.AddLast(new DataValue(StatusCodes.BadNoData, details.ReqTimes[ii]));
                    continue;
                }

                // nothing more to do if a raw value exists.
                if ((DateTime)view[index].Row[0] == details.ReqTimes[ii])
                {
                    values.AddLast((DataValue)view[index].Row[2]);
                    continue;
                }
                
                DataValue before = (DataValue)view[index].Row[2];
                DataValue value;

                // find the value after the time.
                int afterIndex = item.FindValueAfter(view, index, !details.UseSimpleBounds, out dataAfterIgnored);

                if (afterIndex < 0)
                {
                    // use stepped interpolation if no end bound exists.
                    value = AggregateCalculator.SteppedInterpolate(details.ReqTimes[ii], before);

                    if (StatusCode.IsNotBad(value.StatusCode) && dataBeforeIgnored)
                    {
                        value.StatusCode = value.StatusCode.SetCodeBits(StatusCodes.UncertainDataSubNormal);
                    }

                    values.AddLast(value);
                    continue;
                }

                // use stepped or slopped interpolation depending on the value.
                if (item.ArchiveItem.Stepped)
                {
                    value = AggregateCalculator.SteppedInterpolate(details.ReqTimes[ii], before);

                    if (StatusCode.IsNotBad(value.StatusCode) && dataBeforeIgnored)
                    {
                        value.StatusCode = value.StatusCode.SetCodeBits(StatusCodes.UncertainDataSubNormal);
                    }
                }
                else
                {
                    value = AggregateCalculator.SlopedInterpolate(details.ReqTimes[ii], before, (DataValue)view[afterIndex].Row[2]);

                    if (StatusCode.IsNotBad(value.StatusCode) && (dataBeforeIgnored || dataAfterIgnored))
                    {
                        value.StatusCode = value.StatusCode.SetCodeBits(StatusCodes.UncertainDataSubNormal);
                    }
                }

                values.AddLast(value);
            }

            HistoryReadRequest request = new HistoryReadRequest();
            request.Values = values;
            request.NumValuesPerNode = 0;
            request.Filter = null;
            return request;
        }
        public async Task ReadHistoryRawValues()
        {
            // describe this client application.
            var clientDescription = new ApplicationDescription
            {
                ApplicationName = "Workstation.UaClient.FeatureTests",
                ApplicationUri  = $"urn:{System.Net.Dns.GetHostName()}:Workstation.UaClient.FeatureTests",
                ApplicationType = ApplicationType.Client
            };

            // place to store certificates
            var certificateStore = new DirectoryStore("./pki");

            // create a 'UaTcpSessionChannel', a client-side channel that opens a 'session' with the server.
            var channel = new UaTcpSessionChannel(
                clientDescription,
                certificateStore,
                new AnonymousIdentity(),      // the anonymous identity
                "opc.tcp://localhost:48010"); // the endpoint of Unified Automation's UaCPPServer.

            try
            {
                // try opening a session and reading a few nodes.
                await channel.OpenAsync();

                Console.WriteLine($"Opened session with endpoint '{channel.RemoteEndpoint.EndpointUrl}'.");
                Console.WriteLine($"SecurityPolicy: '{channel.RemoteEndpoint.SecurityPolicyUri}'.");
                Console.WriteLine($"SecurityMode: '{channel.RemoteEndpoint.SecurityMode}'.");
                Console.WriteLine($"UserIdentityToken: '{channel.UserIdentity}'.");

                Console.WriteLine("\nCheck if DataLogger active.");

                // check if DataLoggerActive is true. If not, then call method StartLogging.
                var req = new ReadRequest
                {
                    NodesToRead = new[] {
                        new ReadValueId {
                            NodeId = NodeId.Parse("ns=2;s=Demo.History.DataLoggerActive"), AttributeId = AttributeIds.Value
                        }
                    },
                };
                var res = await channel.ReadAsync(req);

                if (StatusCode.IsBad(res.Results[0].StatusCode))
                {
                    throw new InvalidOperationException("Error reading 'Demo.History.DataLoggerActive'. ");
                }
                var isActive = res.Results[0].GetValueOrDefault <bool>();

                if (!isActive)
                {
                    Console.WriteLine("Activating DataLogger.");

                    var req1 = new CallRequest
                    {
                        MethodsToCall = new[] {
                            new CallMethodRequest {
                                ObjectId = NodeId.Parse("ns=2;s=Demo.History"), // parent node
                                MethodId = NodeId.Parse("ns=2;s=Demo.History.StartLogging")
                            },
                        },
                    };
                    var res1 = await channel.CallAsync(req1);

                    if (StatusCode.IsBad(res1.Results[0].StatusCode))
                    {
                        throw new InvalidOperationException("Error calling method 'Demo.History.StartLogging'.");
                    }
                    Console.WriteLine("Note: Datalogger has just been activated, so there will be little or no history data to read.");
                    Console.WriteLine("      Try again in 1 minute.");
                }

                Console.WriteLine("\nReading history for last 1 minute(s).");

                // A continuation point is returned if there are more values to return than the
                // limit set by parameter NumValuesPerNode. A client should continue calling HistoryRead
                // until the continuation point returns null.
                byte[] cp = null;

                do
                {
                    var req2 = new HistoryReadRequest
                    {
                        HistoryReadDetails = new ReadRawModifiedDetails
                        {
                            StartTime        = DateTime.UtcNow.Add(TimeSpan.FromSeconds(-60)), // set start time to 1 minute ago
                            EndTime          = DateTime.UtcNow,
                            NumValuesPerNode = 100,                                            // sets limit. if there are more values to return then a continuation point is returned.
                            ReturnBounds     = false,                                          // set true to return interpolated values for the start and end times
                        },
                        TimestampsToReturn        = TimestampsToReturn.Both,
                        ReleaseContinuationPoints = false, // set true to abandon returning any remaining values from this interval
                        NodesToRead = new[] {
                            new HistoryReadValueId {
                                NodeId = NodeId.Parse("ns=2;s=Demo.History.DoubleWithHistory"), ContinuationPoint = cp
                            },
                        },
                    };

                    var res2 = await channel.HistoryReadAsync(req2);

                    if (StatusCode.IsGood(res2.Results[0].StatusCode))
                    {
                        var historyData = res2.Results[0].HistoryData as HistoryData;

                        Console.WriteLine($"Found {historyData.DataValues.Length} value(s) for node '{req2.NodesToRead[0].NodeId}':");

                        foreach (var dv in historyData.DataValues)
                        {
                            Console.WriteLine($"Read {dv.Value}, q: {dv.StatusCode}, ts: {dv.SourceTimestamp}");
                        }

                        cp = res2.Results[0].ContinuationPoint;
                        // if ContinuationPoint is null, then there is no more data to return.
                        if (cp == null)
                        {
                            break;
                        }
                    }
                    else
                    {
                        Console.WriteLine($"HistoryRead return statuscode: {res2.Results[0].StatusCode}");
                        break;
                    }
                } while (cp != null); // loop while ContinuationPoint is not null.

                Console.WriteLine($"\nClosing session '{channel.SessionId}'.");
                await channel.CloseAsync();
            }
            catch (Exception ex)
            {
                await channel.AbortAsync();

                Console.WriteLine(ex.Message);
            }
        }
        /// <summary>
        /// Fetches the requested event fields from the event.
        /// </summary>
        private HistoryEventFieldList GetEventFields(HistoryReadRequest request, IFilterTarget instance)
        {
            // fetch the event fields.
            HistoryEventFieldList fields = new HistoryEventFieldList();

            foreach (SimpleAttributeOperand clause in request.Filter.SelectClauses)
            {
                // get the value of the attribute (apply localization).
                object value = instance.GetAttributeValue(
                    request.FilterContext,
                    clause.TypeDefinitionId,
                    clause.BrowsePath,
                    clause.AttributeId,
                    clause.ParsedIndexRange);

                // add the value to the list of event fields.
                if (value != null)
                {
                    // translate any localized text.
                    LocalizedText text = value as LocalizedText;

                    if (text != null)
                    {
                        value = Server.ResourceManager.Translate(request.FilterContext.PreferredLocales, text);
                    }

                    // add value.
                    fields.EventFields.Add(new Variant(value));
                }

                // add a dummy entry for missing values.
                else
                {
                    fields.EventFields.Add(Variant.Null);
                }
            }

            return fields;
        }
Exemple #20
0
        public async Task ReadHistorical()
        {
            var channel = new UaTcpSessionChannel(
                localDescription,
                certificateStore,
                new AnonymousIdentity(),
                "opc.tcp://localhost:48010",
                loggerFactory: loggerFactory);

            await channel.OpenAsync();

            logger.LogInformation($"Opened session with endpoint '{channel.RemoteEndpoint.EndpointUrl}'.");
            logger.LogInformation($"SecurityPolicy: '{channel.RemoteEndpoint.SecurityPolicyUri}'.");
            logger.LogInformation($"SecurityMode: '{channel.RemoteEndpoint.SecurityMode}'.");
            logger.LogInformation($"Activated session '{channel.SessionId}'.");

            var historyReadRequest = new HistoryReadRequest
            {
                HistoryReadDetails = new ReadRawModifiedDetails
                {
                    StartTime      = DateTime.UtcNow - TimeSpan.FromMinutes(10),
                    EndTime        = DateTime.UtcNow,
                    ReturnBounds   = true,
                    IsReadModified = false
                },
                NodesToRead = new[]
                {
                    new HistoryReadValueId
                    {
                        NodeId = NodeId.Parse("ns=2;s=Demo.History.DoubleWithHistory")
                    }
                },
            };
            var historyReadResponse = await channel.HistoryReadAsync(historyReadRequest);

            var result = historyReadResponse.Results[0];

            StatusCode.IsGood(result.StatusCode)
            .Should().BeTrue();
            logger.LogInformation($"HistoryRead response status code: {result.StatusCode}, HistoryData count: {((HistoryData)result.HistoryData).DataValues.Length}.");

            if (false) // UaCPPserver does not appear to store event history.
            {
                var historyReadRequest2 = new HistoryReadRequest
                {
                    HistoryReadDetails = new ReadEventDetails
                    {
                        StartTime = DateTime.UtcNow - TimeSpan.FromMinutes(10),
                        EndTime   = DateTime.UtcNow,
                        Filter    = new EventFilter // Use EventHelper to select all the fields of AlarmCondition.
                        {
                            SelectClauses = EventHelper.GetSelectClauses <AlarmCondition>()
                        }
                    },
                    NodesToRead = new[]
                    {
                        new HistoryReadValueId
                        {
                            NodeId = NodeId.Parse("ns=2;s=Demo.History.DoubleWithHistory")
                        }
                    },
                };
                var historyReadResponse2 = await channel.HistoryReadAsync(historyReadRequest2);

                var result2 = historyReadResponse2.Results[0];
                StatusCode.IsGood(result2.StatusCode)
                .Should().BeTrue();
                logger.LogInformation($"HistoryRead response status code: {result2.StatusCode}, HistoryEvent count: {((HistoryEvent)result2.HistoryData).Events.Length}.");

                // Use EventHelper to create AlarmConditions from the HistoryEventFieldList
                var alarms = ((HistoryEvent)result2.HistoryData).Events.Select(e => EventHelper.Deserialize <AlarmCondition>(e.EventFields));
            }
            logger.LogInformation($"Closing session '{channel.SessionId}'.");
            await channel.CloseAsync();
        }
        /// <summary>
        /// Creates a new history request.
        /// </summary>
        private HistoryReadRequest CreateHistoryReadRequest(
            ServerSystemContext context,
            ReadEventDetails details,
            NodeHandle handle,
            HistoryReadValueId nodeToRead)
        {
            FilterContext filterContext = new FilterContext(context.NamespaceUris, context.TypeTable, context.PreferredLocales);
            LinkedList<BaseEventState> events = new LinkedList<BaseEventState>();

            for (ReportType ii = ReportType.FluidLevelTest; ii <= ReportType.InjectionTest; ii++)
            {
                DataView view = null;

                if (handle.Node is WellState)
                {
                    view = m_generator.ReadHistoryForWellId(
                        ii,
                        (string)handle.Node.NodeId.Identifier,
                        details.StartTime,
                        details.EndTime);
                }
                else
                {
                    view = m_generator.ReadHistoryForArea(
                        ii,
                        handle.Node.NodeId.Identifier as string,
                        details.StartTime,
                        details.EndTime);
                }

                LinkedListNode<BaseEventState> pos = events.First;
                bool sizeLimited = (details.StartTime == DateTime.MinValue || details.EndTime == DateTime.MinValue);

                foreach (DataRowView row in view)
                {
                    // check if reached max results.
                    if (sizeLimited)
                    {
                        if (events.Count >= details.NumValuesPerNode)
                        {
                            break;
                        }
                    }

                    BaseEventState e = m_generator.GetReport(context, NamespaceIndex, ii, row.Row);

                    if (details.Filter.WhereClause != null && details.Filter.WhereClause.Elements.Count > 0)
                    {
                        if (!details.Filter.WhereClause.Evaluate(filterContext, e))
                        {
                            continue;
                        }
                    }

                    bool inserted = false;

                    for (LinkedListNode<BaseEventState> jj = pos; jj != null; jj = jj.Next)
                    {
                        if (jj.Value.Time.Value > e.Time.Value)
                        {
                            events.AddBefore(jj, e);
                            pos = jj;
                            inserted = true;
                            break;
                        }
                    }

                    if (!inserted)
                    {
                        events.AddLast(e);
                        pos = null;
                    }
                }
            }

            HistoryReadRequest request = new HistoryReadRequest();
            request.Events = events;
            request.TimeFlowsBackward = details.StartTime == DateTime.MinValue || (details.EndTime != DateTime.MinValue && details.EndTime < details.StartTime);
            request.NumValuesPerNode = details.NumValuesPerNode;
            request.Filter = details.Filter;
            request.FilterContext = filterContext;
            return request;
        }