/// <summary> /// Reads the raw data history. /// </summary> /// <param name="request">The request.</param> public StatusCode ReadAttributeHistory(HdaHistoryReadAttributeRequest request) { // check if nothing to do. if (request == null) { return StatusCodes.BadNothingToDo; } // create the handle. HdaItem[] items = GetItems(request.ItemId); if (items == null || items[0].Error < 0) { return StatusCodes.BadNodeIdUnknown; } request.ServerHandle = items[0].ServerHandle; try { // read modified not supported for attributes. if (request.IsReadModified) { return StatusCodes.BadNoData; } // convert the requested attribute to a list of attributes to read. int[] attributeIds = null; switch (request.AttributeId) { case Constants.OPCHDA_NORMAL_MAXIMUM: { attributeIds = new int[] { Constants.OPCHDA_NORMAL_MAXIMUM, Constants.OPCHDA_NORMAL_MINIMUM }; break; } case Constants.OPCHDA_HIGH_ENTRY_LIMIT: { attributeIds = new int[] { Constants.OPCHDA_HIGH_ENTRY_LIMIT, Constants.OPCHDA_LOW_ENTRY_LIMIT }; break; } default: { attributeIds = new int[] { Utils.ToInt32(request.AttributeId) }; break; } } // read the values and them in the request object. return ReadAttributes(request, attributeIds); } catch (Exception) { return StatusCodes.BadUnexpectedError; } finally { ReleaseItemHandles(request.ServerHandle); request.ServerHandle = 0; } }
/// <summary> /// Reads the raw modified data for an item. /// </summary> private StatusCode ReadAttributes(HdaHistoryReadAttributeRequest request, params int[] attributeIds) { string methodName = "IOPCHDA_SyncRead.ReadAttribute"; OPCHDA_TIME htStartTime = ConvertTime(request.StartTime); OPCHDA_TIME htEndTime = ConvertTime(request.EndTime); IntPtr ppAttributeValues; IntPtr ppErrors; try { IOPCHDA_SyncRead server = BeginComCall<IOPCHDA_SyncRead>(methodName, true); server.ReadAttribute( ref htStartTime, ref htEndTime, request.ServerHandle, attributeIds.Length, attributeIds, out ppAttributeValues, out ppErrors); } catch (Exception e) { ComCallError(methodName, e); return StatusCodes.BadUnexpectedError; } finally { EndComCall(methodName); } StatusCode status = StatusCodes.Good; // error in one attribute means operation failed. int[] errors = ComUtils.GetInt32s(ref ppErrors, attributeIds.Length, true); for (int ii = 0; ii < errors.Length; ii++) { if (errors[ii] < 0) { status = StatusCodes.BadNodeIdUnknown; break; } } // unmarshal results. HdaAttributeValue[][] results = new HdaAttributeValue[attributeIds.Length][]; IntPtr pos = ppAttributeValues; for (int ii = 0; ii < attributeIds.Length; ii++) { OPCHDA_ATTRIBUTE attributes = (OPCHDA_ATTRIBUTE)Marshal.PtrToStructure(pos, typeof(OPCHDA_ATTRIBUTE)); if (attributes.dwNumValues > 0) { results[ii] = new HdaAttributeValue[attributes.dwNumValues]; object[] values = ComUtils.GetVARIANTs(ref attributes.vAttributeValues, attributes.dwNumValues, true); DateTime[] timestamps = ComUtils.GetDateTimes(ref attributes.ftTimeStamps, attributes.dwNumValues, true); for (int jj = 0; jj < values.Length; jj++) { HdaAttributeValue result = results[ii][jj] = new HdaAttributeValue(); result.AttributeId = Utils.ToUInt32(attributeIds[ii]); result.Value = ComUtils.ProcessComValue(values[jj]); result.Timestamp = timestamps[jj]; result.Error = ResultIds.S_OK; } } else { results[ii] = new HdaAttributeValue[1]; HdaAttributeValue result = results[ii][0] = new HdaAttributeValue(); result.AttributeId = Utils.ToUInt32(attributeIds[ii]); result.Value = null; result.Timestamp = request.StartTime; result.Error = ResultIds.S_NODATA; } pos = (IntPtr)(pos.ToInt64() + Marshal.SizeOf(typeof(OPCHDA_ATTRIBUTE))); } Marshal.FreeCoTaskMem(ppAttributeValues); // save the results. request.SetHistoryResults(attributeIds, results); return StatusCodes.Good; }
/// <summary> /// Reads the history of an HDA attribute. /// </summary> private ServiceResult HistoryReadAttribute( ServerSystemContext context, ComHdaClient client, ReadRawModifiedDetails details, TimestampsToReturn timestampsToReturn, HistoryReadValueId nodeToRead, HdaParsedNodeId parsedNodeId, HistoryReadResult result) { // create the request or load it from a continuation point. HdaHistoryReadAttributeRequest request = null; if (nodeToRead.ContinuationPoint == null) { // create a new request. request = new HdaHistoryReadAttributeRequest(parsedNodeId.RootId, parsedNodeId.AttributeId, details, nodeToRead); // fetch all of the data at once. result.StatusCode = client.ReadAttributeHistory(request); } else { request = LoadContinuationPoint(context, nodeToRead.ContinuationPoint) as HdaHistoryReadAttributeRequest; if (request == null) { return StatusCodes.BadContinuationPointInvalid; } } // select a subset of the results. if (StatusCode.IsGood(result.StatusCode)) { request.Results = new DataValueCollection(); request.GetHistoryResults(context, nodeToRead, request.Results); } // 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; }