/// <summary> /// Reads the raw data history. /// </summary> /// <param name="request">The request.</param> public StatusCode ReadHistory(HdaHistoryReadRawModifiedRequest request) { // check if nothing to do. 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 { if (request.IsReadModified) { return ReadModified(request); } return ReadRaw(request); } catch (Exception) { return StatusCodes.BadUnexpectedError; } finally { ReleaseItemHandles(request.ServerHandle); request.ServerHandle = 0; } }
/// <summary> /// Reads the raw data for an item. /// </summary> private StatusCode ReadRaw(HdaHistoryReadRawModifiedRequest request) { string methodName = "IOPCHDA_SyncRead.ReadRaw"; OPCHDA_TIME htStartTime = ConvertTime(request.StartTime); OPCHDA_TIME htEndTime = ConvertTime(request.EndTime); int maxReturnValues = request.MaxReturnValues; if (m_maxReturnValues > 0 && maxReturnValues > m_maxReturnValues) { maxReturnValues = m_maxReturnValues; } // must have a least two values. if (request.MaxReturnValues == 1 && request.TotalValuesReturned > 0) { maxReturnValues = 2; } IntPtr ppItemValues; IntPtr ppErrors; try { IOPCHDA_SyncRead server = BeginComCall<IOPCHDA_SyncRead>(methodName, true); server.ReadRaw( ref htStartTime, ref htEndTime, maxReturnValues, (request.ReturnBounds)?1:0, 1, new int[] { request.ServerHandle }, 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) { return StatusCodes.BadNodeIdUnknown; } // check if operation halted. request.Completed = errors[0] != ResultIds.S_MOREDATA; // 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++) { // suppress previously returned values. if (ii == 0 && request.TotalValuesReturned > 0) { if (request.StartTime < request.EndTime && timestamps[ii] <= request.StartTime) { continue; } if (request.StartTime > request.EndTime && timestamps[ii] >= request.StartTime) { continue; } } 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); } request.TotalValuesReturned += request.Results.Count; if (!request.Completed) { request.StartTime = request.Results[request.Results.Count-1].SourceTimestamp; } } Marshal.FreeCoTaskMem(ppItemValues); if (result.dwCount == 0) { return StatusCodes.GoodNoData; } if (maxReturnValues > 0 && !request.Completed) { return StatusCodes.GoodMoreData; } return StatusCodes.Good; }
/// <summary> /// Reads the raw modified data for an item. /// </summary> private StatusCode ReadModified(HdaHistoryReadRawModifiedRequest request) { string methodName = "IOPCHDA_SyncRead.ReadModified"; OPCHDA_TIME htStartTime = ConvertTime(request.StartTime); OPCHDA_TIME htEndTime = ConvertTime(request.EndTime); int maxReturnValues = request.MaxReturnValues; if (m_maxReturnValues > 0 && maxReturnValues > m_maxReturnValues) { maxReturnValues = m_maxReturnValues; } IntPtr ppItemValues; IntPtr ppErrors; try { IOPCHDA_SyncRead server = BeginComCall<IOPCHDA_SyncRead>(methodName, true); server.ReadModified( ref htStartTime, ref htEndTime, maxReturnValues, 1, new int[] { request.ServerHandle }, out ppItemValues, out ppErrors); } catch (Exception e) { if (ComUtils.IsUnknownError(e, ResultIds.E_NOTIMPL)) { ComCallError(methodName, e); } return StatusCodes.BadNoData; } finally { EndComCall(methodName); } // check for error. int[] errors = ComUtils.GetInt32s(ref ppErrors, 1, true); if (errors[0] < 0) { return StatusCodes.BadNodeIdUnknown; } // check if operation halted. request.Completed = errors[0] != ResultIds.S_MOREDATA; // unmarshal the results. OPCHDA_MODIFIEDITEM result = (OPCHDA_MODIFIEDITEM)Marshal.PtrToStructure(ppItemValues, typeof(OPCHDA_MODIFIEDITEM)); 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); DateTime[] modificationTimes = ComUtils.GetDateTimes(ref result.pftModificationTime, result.dwCount, true); string[] userNames = ComUtils.GetUnicodeStrings(ref result.szUser, result.dwCount, true); int[] editTypes = ComUtils.GetInt32s(ref result.pEditType, result.dwCount, true); request.Results = new DataValueCollection(result.dwCount); request.ModificationInfos = new ModificationInfoCollection(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); ModificationInfo modification = new ModificationInfo(); modification.ModificationTime = modificationTimes[ii]; modification.UpdateType = (HistoryUpdateType)editTypes[ii]; modification.UserName = userNames[ii]; request.ModificationInfos.Add(modification); } if (!request.Completed) { request.StartTime = request.Results[request.Results.Count-1].SourceTimestamp; } } Marshal.FreeCoTaskMem(ppItemValues); if (result.dwCount == 0) { return StatusCodes.GoodNoData; } if (maxReturnValues > 0 && !request.Completed) { return StatusCodes.GoodMoreData; } return StatusCodes.Good; }
/// <summary> /// Reads the history of an HDA item. /// </summary> private ServiceResult HistoryReadItem( ServerSystemContext context, ComHdaClient client, ReadRawModifiedDetails details, TimestampsToReturn timestampsToReturn, HistoryReadValueId nodeToRead, HdaParsedNodeId parsedNodeId, HistoryReadResult result) { // create the request or load it from a continuation point. HdaHistoryReadRawModifiedRequest request = null; if (nodeToRead.ContinuationPoint == null) { request = new HdaHistoryReadRawModifiedRequest(parsedNodeId.RootId, details, nodeToRead); } else { request = LoadContinuationPoint(context, nodeToRead.ContinuationPoint) as HdaHistoryReadRawModifiedRequest; if (request == null) { return StatusCodes.BadContinuationPointInvalid; } } // fetch the data. result.StatusCode = client.ReadHistory(request); // fill in the results. if (request.Results != null) { HistoryData data = (request.IsReadModified)?new HistoryModifiedData():new HistoryData(); if (request.IsReadModified) { ((HistoryModifiedData)data).ModificationInfos = request.ModificationInfos; } 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; }