/// <summary> /// Unmarshals and deallocates a OPCITEMRESULT structures. /// </summary> internal static int[] GetItemResults(ref IntPtr pInput, int count, bool deallocate) { int[] output = null; if (pInput != IntPtr.Zero && count > 0) { output = new int[count]; IntPtr pos = pInput; for (int ii = 0; ii < count; ii++) { OpcRcw.Da.OPCITEMRESULT result = (OpcRcw.Da.OPCITEMRESULT)Marshal.PtrToStructure(pos, typeof(OpcRcw.Da.OPCITEMRESULT)); output[ii] = result.hServer; if (deallocate) { if (result.pBlob != IntPtr.Zero) { Marshal.FreeCoTaskMem(result.pBlob); result.pBlob = IntPtr.Zero; result.dwBlobSize = 0; } Marshal.DestroyStructure(pos, typeof(OpcRcw.Da.OPCITEMRESULT)); } pos = (IntPtr)(pos.ToInt32() + Marshal.SizeOf(typeof(OpcRcw.Da.OPCITEMRESULT))); } if (deallocate) { Marshal.FreeCoTaskMem(pInput); pInput = IntPtr.Zero; } } return(output); }
/// <summary> /// IOPCItemMgt::ValidateItems - Determines if an item is valid. /// Also returns information about the item such as canonical datatype, etc. /// </summary> public void ValidateItems( int dwCount, OPCITEMDEF[] pItemArray, int bBlobUpdate, out System.IntPtr ppValidationResults, out System.IntPtr ppErrors) { lock (m_lock) { if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); // validate arguments. if (dwCount == 0 || pItemArray == null || dwCount != pItemArray.Length) { throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); } try { int[] errors = new int[dwCount]; OPCITEMRESULT[] results = new OPCITEMRESULT[dwCount]; for (int ii = 0; ii < dwCount; ii++) { results[ii].hServer = 0; results[ii].dwBlobSize = 0; results[ii].pBlob = IntPtr.Zero; results[ii].vtCanonicalDataType = (short)VarEnum.VT_EMPTY; results[ii].dwAccessRights = 0; results[ii].wReserved = 0; // parse node id. NodeId nodeId = Server.ItemIdToNodeId(pItemArray[ii].szItemID); if (nodeId == null) { errors[ii] = ResultIds.E_INVALIDITEMID; continue; } // find node. VariableNode variable = m_session.NodeCache.Find(nodeId) as VariableNode; if (variable == null) { errors[ii] = ResultIds.E_INVALIDITEMID; continue; } // validated the requested datatype. if (pItemArray[ii].vtRequestedDataType != 0) { if (ComUtils.GetSystemType(pItemArray[ii].vtRequestedDataType) == null) { errors[ii] = ResultIds.E_BADTYPE; continue; } } // fill in metadata. results[ii].vtCanonicalDataType = (short)m_server.DataTypeToVarType(variable.DataType, variable.ValueRank); results[ii].dwAccessRights = ComUtils.GetAccessRights(variable.AccessLevel); if (results[ii].vtCanonicalDataType == (short)VarEnum.VT_VARIANT) { results[ii].vtCanonicalDataType = (short)VarEnum.VT_EMPTY; } errors[ii] = ResultIds.S_OK; } // marshal the results. ppValidationResults = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(OPCITEMRESULT))*dwCount); IntPtr pos = ppValidationResults; for (int ii = 0; ii < dwCount; ii++) { Marshal.StructureToPtr(results[ii], pos, false); pos = (IntPtr)(pos.ToInt32() + Marshal.SizeOf(typeof(OpcRcw.Da.OPCITEMRESULT))); } // marshal error codes. ppErrors = ComUtils.GetInt32s(errors); } catch (Exception e) { throw ComUtils.CreateComException(e); } } }
/// <summary> /// IOPCItemMgt::AddItems - Adds one or more items to a group. /// </summary> public void AddItems( int dwCount, OPCITEMDEF[] pItemArray, out System.IntPtr ppAddResults, out System.IntPtr ppErrors) { lock (m_lock) { if (m_subscription == null) throw ComUtils.CreateComException(ResultIds.E_FAIL); // validate arguments. if (dwCount == 0 || pItemArray == null || dwCount != pItemArray.Length) { throw ComUtils.CreateComException(ResultIds.E_INVALIDARG); } try { // compile set of item modifications. int[] errors = new int[dwCount]; OPCITEMRESULT[] results = new OPCITEMRESULT[dwCount]; List<Item> itemsToAdd = new List<Item>(); for (int ii = 0; ii < dwCount; ii++) { OPCITEMDEF itemToAdd = pItemArray[ii]; // initialize result structure. results[ii].hServer = 0; results[ii].dwBlobSize = 0; results[ii].pBlob = IntPtr.Zero; results[ii].vtCanonicalDataType = (short)VarEnum.VT_EMPTY; results[ii].dwAccessRights = 0; results[ii].wReserved = 0; // parse node id. NodeId nodeId = Server.ItemIdToNodeId(itemToAdd.szItemID); if (nodeId == null) { errors[ii] = ResultIds.E_INVALIDITEMID; continue; } // find node. VariableNode variable = m_session.NodeCache.Find(nodeId) as VariableNode; if (variable == null) { errors[ii] = ResultIds.E_INVALIDITEMID; continue; } // validated the requested datatype. if (itemToAdd.vtRequestedDataType != 0) { if (ComUtils.GetSystemType(itemToAdd.vtRequestedDataType) == null) { errors[ii] = ResultIds.E_BADTYPE; continue; } } // fill in metadata. results[ii].vtCanonicalDataType = (short)m_server.DataTypeToVarType(variable.DataType, variable.ValueRank); results[ii].dwAccessRights = ComUtils.GetAccessRights(variable.AccessLevel); if (results[ii].vtCanonicalDataType == (short)VarEnum.VT_VARIANT) { results[ii].vtCanonicalDataType = (short)VarEnum.VT_EMPTY; } // create an item. Item item = new Item(); item.ItemId = itemToAdd.szItemID; item.ClientHandle = itemToAdd.hClient; item.ServerHandle = ii; // save this temporarily to correlate response to request list. item.Active = itemToAdd.bActive != 0; item.ReqType = (VarEnum)itemToAdd.vtRequestedDataType; item.Variable = variable; // check if the item supports deadband. INode euRange = m_session.NodeCache.Find(nodeId, ReferenceTypeIds.HasProperty, false, true, Opc.Ua.BrowseNames.EURange); if (euRange != null) { item.DeadbandSupported = true; } // create a monitored item. MonitoredItem monitoredItem = new MonitoredItem(); monitoredItem.StartNodeId = nodeId; monitoredItem.AttributeId = Attributes.Value; monitoredItem.MonitoringMode = (item.Active)?MonitoringMode.Reporting:MonitoringMode.Disabled; monitoredItem.SamplingInterval = m_updateRate; monitoredItem.QueueSize = 0; monitoredItem.DiscardOldest = true; monitoredItem.Encoding = null; monitoredItem.Filter = null; monitoredItem.IndexRange = null; if (m_deadband != 0 && item.DeadbandSupported) { DataChangeFilter filter = new DataChangeFilter(); filter.DeadbandType = (uint)(int)DeadbandType.Percent; filter.DeadbandValue = m_deadband; filter.Trigger = DataChangeTrigger.StatusValue; monitoredItem.Filter = filter; } item.MonitoredItem = monitoredItem; itemsToAdd.Add(item); // update the subscription. m_subscription.AddItem(monitoredItem); } if (itemsToAdd.Count > 0) { // create monitored items on the UA server. m_subscription.ApplyChanges(); foreach (Item item in itemsToAdd) { // check for error during add. int index = item.ServerHandle; MonitoredItem monitoredItem = item.MonitoredItem; if (ServiceResult.IsBad(monitoredItem.Status.Error)) { errors[index] = Server.MapReadStatusToErrorCode(monitoredItem.Status.Error.StatusCode); m_subscription.RemoveItem(monitoredItem); continue; } // save server handle. results[index].hServer = item.ServerHandle = Utils.ToInt32(monitoredItem.ClientHandle); // add an entry in the cache. CreateCacheEntry(item); // index item. m_items[item.ServerHandle] = item; } } // marshal the results. ppAddResults = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(OPCITEMRESULT))*dwCount); IntPtr pos = ppAddResults; for (int ii = 0; ii < dwCount; ii++) { Marshal.StructureToPtr(results[ii], pos, false); pos = (IntPtr)(pos.ToInt32() + Marshal.SizeOf(typeof(OpcRcw.Da.OPCITEMRESULT))); } // marshal error codes. ppErrors = ComUtils.GetInt32s(errors); } catch (Exception e) { throw ComUtils.CreateComException(e); } } }