/// <summary>
        ///     Changes the requested data type for one or more items in a group.
        /// </summary>
        /// <param name="items">The group items.</param>
        /// <param name="requestedTypes">Array of new Requested Datatypes to be stored.</param>
        /// <returns>
        ///     Array of HRESULTs. Indicates which items were successfully affected.
        /// </returns>
        /// <exception cref="System.ArgumentException">Wrong size of requested types array.;requestedTypes</exception>
        public HRESULT[] SetDataTypes(IList <OpcDaItem> items, IList <Type> requestedTypes)
        {
            CheckItems(items);
            if (items.Count != requestedTypes.Count)
            {
                throw new ArgumentException("Wrong size of requested types array.", "requestedTypes");
            }

            int[]           serverHandles      = ArrayHelpers.GetServerHandles(items);
            IList <VarEnum> requestedDatatypes = requestedTypes.Select(TypeConverter.ToVarEnum).ToArray();

            HRESULT[] ppErrors = As <OpcItemMgt>().SetDatatypes(serverHandles, requestedDatatypes);

            var changedItems = new List <OpcDaItem>(items.Count);

            for (int index = 0; index < items.Count; index++)
            {
                if (ppErrors[index].Succeeded)
                {
                    OpcDaItem item = items[index];
                    item.RequestedDataType = requestedTypes[index];
                    changedItems.Add(item);
                }
            }

            OnItemsChanged(new OpcDaItemsChangedEventArgs(null, null, changedItems.ToArray()));
            return(ppErrors);
        }
        public Task <HRESULT[]> Start(IList <OpcDaItem> items, ICollection <object> values,
                                      CancellationToken token)
        {
            try
            {
                var serverHandles = ArrayHelpers.GetServerHandles(items);

                HRESULT[] ppErrors;
                int       cancelId = _asyncIO2.Write(serverHandles, values.ToArray(), TransactionId, out ppErrors);

                if (ppErrors.All(e => e.Failed)) // if all errors no callback will take place
                {
                    _requestManager.CompleteRequest(TransactionId);
                    _tcs.SetResult(ppErrors);
                }
                else
                {
                    CancellationId = cancelId;
                    RequestHelpers.SetCancellationHandler(token, Cancel);
                }
                return(Task);
            }
            catch (Exception ex)
            {
                _requestManager.CompleteRequest(TransactionId);
                _tcs.SetException(ex);
                return(Task);
            }
        }
 /// <summary>
 ///     Writes values to one or more items in a group.
 /// </summary>
 /// <param name="items">The group items.</param>
 /// <param name="values">The list of values to be written to the items.</param>
 /// <returns>
 ///     Array of HRESULTs indicating the success of the individual item Writes.
 /// </returns>
 public HRESULT[] Write(IList <OpcDaItem> items, object[] values)
 {
     CheckItems(items);
     CheckSupported(OpcDaGroupFeatures.Write);
     int[] serverHandles = ArrayHelpers.GetServerHandles(items);
     return(As <OpcSyncIO>().Write(serverHandles, values));
 }
        public Task <OpcDaItemValue[]> Start(IList <OpcDaItem> items, IList <TimeSpan> maxAge, CancellationToken token)
        {
            try
            {
                var       serverHandles = ArrayHelpers.GetServerHandles(items);
                HRESULT[] ppErrors;
                int       cancelId = _asyncIO3.ReadMaxAge(serverHandles, maxAge, TransactionId, out ppErrors);
                if (ppErrors.All(e => e.Failed)) // if all errors no callback will take place
                {
                    _requestManager.CompleteRequest(TransactionId);
                    var result = new OpcDaItemValue[ppErrors.Length];
                    for (var i = 0; i < result.Length; i++)
                    {
                        result[i] = new OpcDaItemValue {
                            Error = ppErrors[i], Item = items[i]
                        };
                    }
                    _tcs.SetResult(result);
                }
                else
                {
                    CancellationId = cancelId;
                    RequestHelpers.SetCancellationHandler(token, Cancel);
                }

                return(Task);
            }
            catch (Exception ex)
            {
                _requestManager.CompleteRequest(TransactionId);
                _tcs.SetException(ex);
                return(Task);
            }
        }
        /// <summary>
        ///     Reads the specified group items.
        /// </summary>
        /// <param name="items">The group items.</param>
        /// <param name="dataSource">The data source.</param>
        /// <returns>
        ///     The values of the group items.
        /// </returns>
        public OpcDaItemValue[] Read(IList <OpcDaItem> items, OpcDaDataSource dataSource = OpcDaDataSource.Cache)
        {
            CheckItems(items);
            CheckSupported(OpcDaGroupFeatures.Read);
            int[] serverHandles = ArrayHelpers.GetServerHandles(items);

            HRESULT[]        ppErrors;
            OPCITEMSTATE[]   ppItemValues = As <OpcSyncIO>().Read((OPCDATASOURCE)dataSource, serverHandles, out ppErrors);
            OpcDaItemValue[] result       = OpcDaItemValue.Create(this, ppItemValues, ppErrors);
            OnValuesChanged(new OpcDaItemValuesChangedEventArgs(result));
            return(result);
        }
 /// <summary>
 ///     Removes (deletes) items from the group.
 /// </summary>
 /// <param name="items">The group items.</param>
 /// <returns>
 ///     Array of HRESULTs. Indicates which items were successfully removed.
 /// </returns>
 public HRESULT[] RemoveItems(IList <OpcDaItem> items)
 {
     CheckItems(items);
     int[]     serverHandles = ArrayHelpers.GetServerHandles(items);
     HRESULT[] ppErrors      = As <OpcItemMgt>().RemoveItems(serverHandles);
     foreach (int serverHandle in serverHandles)
     {
         _items.RemoveAll(i => i.ServerHandle == serverHandle);
     }
     // Set client handles to index of items
     UpdateClientHandles();
     OnItemsChanged(new OpcDaItemsChangedEventArgs(null, items.ToArray(), null));
     return(ppErrors);
 }
        /// <summary>
        ///     Writes one or more values, qualities and timestamps for the items specified. If a client attempts to write VQ, VT,
        ///     or VQT it should expect that the server will write them all or none at all.
        /// </summary>
        /// <param name="items">The group items.</param>
        /// <param name="values">The list of values, qualities and timestamps.</param>
        /// <returns>
        ///     Array of HRESULTs indicating the success of the individual item Writes.
        /// </returns>
        /// <exception cref="System.ArgumentException">Invalid size of values;values</exception>
        public HRESULT[] WriteVQT(IList <OpcDaItem> items, IList <OpcDaVQT> values)
        {
            CheckSupported(OpcDaGroupFeatures.WriteVQT);
            CheckItems(items);
            int[] serverHandles = ArrayHelpers.GetServerHandles(items);

            if (serverHandles.Length != values.Count)
            {
                throw new ArgumentException("Invalid size of values", "values");
            }

            OPCITEMVQT[] vqts = ArrayHelpers.CreateOpcItemVQT(values);
            return(As <OpcSyncIO2>().WriteVQT(serverHandles, vqts));
        }
        /// <summary>
        ///     Sets one or more items in a group to active or inactive. This controls whether or not valid data can be obtained
        ///     from Read CACHE for those items and whether or not they are included in the OnDataChange subscription to the group.
        /// </summary>
        /// <param name="items">The group items.</param>
        /// <param name="isActive">If set to <c>true</c> items are to be activated, otherwise items are to be deactivated.</param>
        /// <returns>
        ///     Array of HRESULTs. Indicates which items were successfully affected.
        /// </returns>
        public HRESULT[] SetActiveItems(IList <OpcDaItem> items, bool isActive = true)
        {
            CheckItems(items);
            int[]     serverHandles = ArrayHelpers.GetServerHandles(items);
            HRESULT[] ppErrors      = As <OpcItemMgt>().SetActiveState(serverHandles, isActive);
            var       changedItems  = new List <OpcDaItem>(items.Count);

            for (int index = 0; index < items.Count; index++)
            {
                if (ppErrors[index].Succeeded)
                {
                    OpcDaItem item = items[index];
                    item.IsActive = isActive;
                    changedItems.Add(item);
                }
            }
            OnItemsChanged(new OpcDaItemsChangedEventArgs(null, null, changedItems.ToArray()));
            return(ppErrors);
        }
        /// <summary>
        ///     Reads the specified group items using MaxAge. If the information in the cache is within the MaxAge, then the data
        ///     will be obtained from the cache, otherwise the server must access the device for the requested information.
        /// </summary>
        /// <param name="items">The group items.</param>
        /// <param name="maxAge">The list of MaxAges for the group items.</param>
        /// <returns>
        ///     The values of the group items.
        /// </returns>
        /// <exception cref="System.ArgumentException">Invalid size of maxAge;maxAge</exception>
        public OpcDaItemValue[] ReadMaxAge(IList <OpcDaItem> items, IList <TimeSpan> maxAge)
        {
            CheckSupported(OpcDaGroupFeatures.ReadMaxAge);
            CheckItems(items);

            int[] serverHandles = ArrayHelpers.GetServerHandles(items);

            if (serverHandles.Length != maxAge.Count)
            {
                throw new ArgumentException("Invalid size of maxAge", "maxAge");
            }

//            int[] intMaxAge = ArrayHelpers.CreateMaxAgeArray(maxAge, items.Count);

            DateTimeOffset[] timestamps;
            HRESULT[]        errors;
            OpcDaQuality[]   qualities;
            object[]         ppvValues = As <OpcSyncIO2>()
                                         .ReadMaxAge(serverHandles, maxAge, out qualities, out timestamps, out errors);

            OpcDaItemValue[] result = OpcDaItemValue.Create(items, ppvValues, qualities, timestamps, errors);
            OnValuesChanged(new OpcDaItemValuesChangedEventArgs(result));
            return(result);
        }