/// <summary> /// Reads the processed data history. /// </summary> public StatusCode ReadHistory(HdaHistoryReadProcessedRequest request) { if (request == null) { return StatusCodes.BadNothingToDo; } HdaItem[] items = GetItems(request.ItemId); if (items == null || items[0].Error < 0) { return StatusCodes.BadNodeIdUnknown; } request.ServerHandle = items[0].ServerHandle; try { return ReadProcessed(request); } catch (Exception) { return StatusCodes.BadUnexpectedError; } finally { ReleaseItemHandles(request.ServerHandle); request.ServerHandle = 0; } }
/// <summary> /// Reads the raw data for an item. /// </summary> private StatusCode ReadProcessed(HdaHistoryReadProcessedRequest request) { string methodName = "IOPCHDA_SyncRead.ReadProcessed"; DateTime startTime = request.StartTime; DateTime endTime = request.EndTime; // adjust the resample interval. if (m_maxReturnValues > 0 && request.ResampleInterval > 0) { double range = (startTime - endTime).TotalMilliseconds; double resampleInterval = request.ResampleInterval; if (Math.Abs(range/resampleInterval) > m_maxReturnValues) { range = resampleInterval*m_maxReturnValues; if (startTime > endTime) { range = -range; } endTime = startTime.AddMilliseconds(range); } } OPCHDA_TIME htStartTime = ConvertTime(startTime); OPCHDA_TIME htEndTime = ConvertTime(endTime); System.Runtime.InteropServices.ComTypes.FILETIME ftResampleInterval; ulong ticks = (ulong)request.ResampleInterval*TimeSpan.TicksPerMillisecond; ftResampleInterval.dwHighDateTime = (int)((0xFFFFFFFF00000000 & ticks) >> 32); ftResampleInterval.dwLowDateTime = (int)(ticks & 0x00000000FFFFFFFF); IntPtr ppItemValues; IntPtr ppErrors; try { IOPCHDA_SyncRead server = BeginComCall<IOPCHDA_SyncRead>(methodName, true); server.ReadProcessed( ref htStartTime, ref htEndTime, ftResampleInterval, 1, new int[] { request.ServerHandle }, new int[] { Utils.ToInt32(request.AggregateId) }, out ppItemValues, out ppErrors); } catch (Exception e) { ComCallError(methodName, e); return StatusCodes.BadUnexpectedError; } finally { EndComCall(methodName); } // check for error. int[] errors = ComUtils.GetInt32s(ref ppErrors, 1, true); if (errors[0] < 0) { if (errors[0] == ResultIds.E_NOT_AVAIL) { return StatusCodes.BadAggregateNotSupported; } return StatusCodes.BadNodeIdUnknown; } // check if operation halted. request.Completed = endTime == request.EndTime; // unmarshal the results. OPCHDA_ITEM result = (OPCHDA_ITEM)Marshal.PtrToStructure(ppItemValues, typeof(OPCHDA_ITEM)); if (result.dwCount > 0) { object[] values = ComUtils.GetVARIANTs(ref result.pvDataValues, result.dwCount, true); int[] qualities = ComUtils.GetInt32s(ref result.pdwQualities, result.dwCount, true); DateTime[] timestamps = ComUtils.GetDateTimes(ref result.pftTimeStamps, result.dwCount, true); request.Results = new DataValueCollection(result.dwCount); for (int ii = 0; ii < result.dwCount; ii++) { DataValue value = new DataValue(); value.Value = ComUtils.ProcessComValue(values[ii]); value.StatusCode = ComUtils.GetHdaQualityCode(Utils.ToUInt32(qualities[ii])); value.SourceTimestamp = timestamps[ii]; request.Results.Add(value); } if (!request.Completed) { request.StartTime = endTime; } } Marshal.FreeCoTaskMem(ppItemValues); if (result.dwCount == 0) { return StatusCodes.GoodNoData; } if (!request.Completed) { return StatusCodes.GoodMoreData; } return StatusCodes.Good; }
/// <summary> /// Reads the history of an HDA item. /// </summary> private ServiceResult HistoryReadProcessedItem( ServerSystemContext context, ComHdaClient client, ReadProcessedDetails details, TimestampsToReturn timestampsToReturn, uint aggregateId, HistoryReadValueId nodeToRead, HdaParsedNodeId parsedNodeId, HistoryReadResult result) { // create the request or load it from a continuation point. HdaHistoryReadProcessedRequest request = null; if (nodeToRead.ContinuationPoint == null) { request = new HdaHistoryReadProcessedRequest(parsedNodeId.RootId, aggregateId, details, nodeToRead); } else { request = LoadContinuationPoint(context, nodeToRead.ContinuationPoint) as HdaHistoryReadProcessedRequest; if (request == null) { return StatusCodes.BadContinuationPointInvalid; } } // fetch the data. result.StatusCode = client.ReadHistory(request); // fill in the results. if (request.Results != null) { HistoryData data = new HistoryData(); data.DataValues = request.Results; result.HistoryData = new ExtensionObject(data); } // create a new continuation point. if (!request.Completed) { result.ContinuationPoint = SaveContinuationPoint(context, request); } return result.StatusCode; }