/// <summary> /// Unmarshals and deallocates a OPCITEMSTATE structures. /// </summary> internal static DaValue[] GetItemValues(ref IntPtr pInput, int count, bool deallocate) { DaValue[] output = null; if (pInput != IntPtr.Zero && count > 0) { output = new DaValue[count]; IntPtr pos = pInput; for (int ii = 0; ii < count; ii++) { OpcRcw.Da.OPCITEMSTATE result = (OpcRcw.Da.OPCITEMSTATE)Marshal.PtrToStructure(pos, typeof(OpcRcw.Da.OPCITEMSTATE)); DaValue value = new DaValue(); value.Value = ComUtils.ProcessComValue(result.vDataValue); value.Quality = result.wQuality; value.Timestamp = ComUtils.GetDateTime(result.ftTimeStamp); output[ii] = value; if (deallocate) { Marshal.DestroyStructure(pos, typeof(OpcRcw.Da.OPCITEMSTATE)); } pos = (IntPtr)(pos.ToInt32() + Marshal.SizeOf(typeof(OpcRcw.Da.OPCITEMSTATE))); } if (deallocate) { Marshal.FreeCoTaskMem(pInput); pInput = IntPtr.Zero; } } return(output); }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////// //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^// #region IOPCSyncIO Members /// <summary> /// IOPCSyncIO::Read - Reads the value, quality and timestamp information for one or more items in a group /// </summary> public void Read( OpcRcw.Da.OPCDATASOURCE dwSource, int dwCount, int[] phServer, out System.IntPtr ppItemValues, out System.IntPtr ppErrors) { // validate arguments. if (dwCount == 0 || phServer == null || dwCount != phServer.Length) { throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); } try { OpcRcw.Da.OPCITEMSTATE[] results = new OpcRcw.Da.OPCITEMSTATE[dwCount]; int[] errors = new int[dwCount]; VarEnum[] reqTypes = new VarEnum[dwCount]; // use the minimum max age for all items. int maxAge = (dwSource == OPCDATASOURCE.OPC_DS_CACHE)?Int32.MaxValue:0; // build list of values to read. ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); List<Item> itemsToRead = new List<Item>(); lock (m_lock) { if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); for (int ii = 0; ii < dwCount; ii++) { results[ii].hClient = 0; results[ii].vDataValue = null; results[ii].wQuality = OpcRcw.Da.Qualities.OPC_QUALITY_BAD; results[ii].ftTimeStamp = ComUtils.GetFILETIME(DateTime.MinValue); results[ii].wReserved = 0; Item itemToRead = null; if (!m_items.TryGetValue(phServer[ii], out itemToRead)) { errors[ii] = ResultIds.E_INVALIDHANDLE; continue; } results[ii].hClient = itemToRead.ClientHandle; // check if reading from the cache. if (dwSource == OPCDATASOURCE.OPC_DS_CACHE) { // read the value from cache. DataValue cachedValue = ReadCachedValue(itemToRead, Int32.MaxValue); if (cachedValue != null) { // get value from the cache. object value = null; short quality = Qualities.OPC_QUALITY_BAD; DateTime timestamp = DateTime.MinValue; errors[ii] = ProcessReadResult( phServer[ii], itemToRead.ReqType, cachedValue, out value, out quality, out timestamp); // all done if a suitable value is in the cache. if (!m_active || !itemToRead.Active) { quality = Qualities.OPC_QUALITY_OUT_OF_SERVICE; } results[ii].vDataValue = value; results[ii].wQuality = quality; results[ii].ftTimeStamp = ComUtils.GetFILETIME(timestamp); continue; } } // save the requested data type. reqTypes[ii] = itemToRead.ReqType; ReadValueId nodeToRead = new ReadValueId(); nodeToRead.NodeId = itemToRead.MonitoredItem.ResolvedNodeId; nodeToRead.AttributeId = Attributes.Value; // needed to correlate results to input. nodeToRead.Handle = ii; nodesToRead.Add(nodeToRead); itemsToRead.Add(itemToRead); } } // read values from server. DataValueCollection values = null; DiagnosticInfoCollection diagnosticInfos = null; if (nodesToRead.Count > 0) { m_session.Read( null, maxAge, TimestampsToReturn.Both, nodesToRead, out values, out diagnosticInfos); // validate response from the UA server. ClientBase.ValidateResponse(values, nodesToRead); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); } for (int ii = 0; ii < nodesToRead.Count; ii++) { // get index in original array. int index = (int)nodesToRead[ii].Handle; // process the read result. object value = null; short quality = Qualities.OPC_QUALITY_BAD; DateTime timestamp = DateTime.MinValue; int error = ProcessReadResult( phServer[index], reqTypes[index], values[ii], out value, out quality, out timestamp); // update the cache. UpdateCachedValue(itemsToRead[ii], values[ii]); // check for error. if (error < 0) { errors[index] = error; continue; } // update response. results[index].vDataValue = value; results[index].wQuality = quality; results[index].ftTimeStamp = ComUtils.GetFILETIME(timestamp); errors[index] = ResultIds.S_OK; } // marshal the results. ppItemValues = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(OPCITEMSTATE))*dwCount); IntPtr pos = ppItemValues; for (int ii = 0; ii < dwCount; ii++) { Marshal.StructureToPtr(results[ii], pos, false); pos = (IntPtr)(pos.ToInt32() + Marshal.SizeOf(typeof(OpcRcw.Da.OPCITEMSTATE))); } // marshal error codes. ppErrors = ComUtils.GetInt32s(errors); } catch (Exception e) { Utils.Trace(e, "Error reading items."); throw ComUtils.CreateComException(e); } }