示例#1
0
        /// <summary>
        /// Establishes a subscription for the current set of items.
        /// </summary>
        private ItemValueResultList Subscribe(ArrayList items)
        {
            lock (this)
            {
                // cancel any current subscription.
                Unsubscribe();

                // check if there is nothing to do.
                if (items == null || items.Count == 0)
                {
                    return(new ItemValueResultList());
                }

                // create a single item list and use the subscription state to set list level parameters.
                ItemList itemList = new ItemList();

                itemList.ClientHandle             = Guid.NewGuid().ToString();
                itemList.ItemPath                 = null;
                itemList.ReqType                  = null;
                itemList.Deadband                 = m_state.Deadband;
                itemList.DeadbandSpecified        = true;
                itemList.SamplingRate             = m_state.UpdateRate;
                itemList.SamplingRateSpecified    = true;
                itemList.EnableBuffering          = false;
                itemList.EnableBufferingSpecified = false;

                // set the ping rate based on the keep alive (if specified) or five times update rate.
                m_pingRate = (m_state.KeepAlive != 0)?m_state.KeepAlive:m_state.UpdateRate * 5;

                // stop any existing timer.
                if (m_pollTimer != null)
                {
                    m_pollTimer.Dispose();
                    m_pollTimer = null;
                }

                // create copies of each and replace the client handle with the server handle.
                foreach (Item item in items)
                {
                    Item clone = (Item)item.Clone();
                    clone.ClientHandle = clone.ServerHandle;
                    itemList.Add(clone);
                }

                string subscription = null;

                // establish the subscription on the server.
                OpcXml.Da10.RequestOptions         options   = OpcXml.Da10.Request.GetRequestOptions(m_state.Locale, m_filters);
                OpcXml.Da10.SubscribeReplyItemList replyList = null;
                OpcXml.Da10.OPCError[]             errors    = null;

                OpcXml.Da10.ReplyBase reply = m_proxy.Subscribe(
                    options,
                    OpcXml.Da10.Request.GetSubscribeList(itemList),
                    true,
                    m_pingRate * 2,
                    out replyList,
                    out errors,
                    out subscription);

                // cache results with the server object.
                m_server.CacheResponse(m_state.Locale, reply, errors);

                // save subscription handle.
                m_state.ServerHandle = subscription;

                // check for valid response.
                if (replyList == null)
                {
                    throw new InvalidResponseException();
                }

                // save the revised update rate.
                if (replyList.RevisedSamplingRateSpecified)
                {
                    m_state.UpdateRate = (int)replyList.RevisedSamplingRate;
                }

                // update items.
                ItemValueResultList resultList = OpcXml.Da10.Request.GetSubscribeResultList(replyList);

                for (int ii = 0; ii < itemList.Count; ii++)
                {
                    SubscribeItemValueResult resultItem = (SubscribeItemValueResult)resultList[ii];

                    // restore the client/server handles in the result.
                    resultItem.ServerHandle = resultItem.ClientHandle;
                    resultItem.ClientHandle = ((Item)items[ii]).ClientHandle;

                    // check if the requested sampling rate was accepted.
                    if (!resultItem.SamplingRateSpecified)
                    {
                        resultItem.SamplingRate          = itemList[ii].SamplingRate;
                        resultItem.SamplingRateSpecified = itemList[ii].SamplingRateSpecified;
                    }
                }

                // schedule polling.
                SchedulePoll();

                // return result list.
                return(resultList);
            }
        }
示例#2
0
        /// <summary>
        /// Removes items from the subscription.
        /// </summary>
        /// <param name="items">The identifiers (i.e. server handles) for the items being removed.</param>
        /// <returns>The results of the remove item operation for each item.</returns>
        public IdentifiedResult[] RemoveItems(ItemIdentifier[] items)
        {
            if (items == null)
            {
                throw new ArgumentNullException("items");
            }

            // check if nothing to do.
            if (items.Length == 0)
            {
                return(new IdentifiedResult[0]);
            }

            lock (this)
            {
                if (m_proxy == null)
                {
                    throw new NotConnectedException();
                }

                // initialize results list.
                IdentifiedResult[] results = new IdentifiedResult[items.Length];

                // build the remaining list of items.
                ArrayList itemList = new ArrayList(items.Length);

                foreach (Item item in m_items)
                {
                    // search the list of items to remove for a matching server handle.
                    bool found = false;

                    for (int ii = 0; ii < items.Length; ii++)
                    {
                        if (item.ServerHandle.Equals(items[ii].ServerHandle))
                        {
                            results[ii] = new IdentifiedResult(items[ii]);
                            found       = true;
                            break;
                        }
                    }

                    // add copy to the item list.
                    if (!found)
                    {
                        itemList.Add(item);
                    }
                }

                // create a new subscription.
                ItemValueResultList resultList = Subscribe(itemList);

                // update remaining items.
                for (int ii = 0; ii < resultList.Count; ii++)
                {
                    // the current item value result object.
                    SubscribeItemValueResult result = (SubscribeItemValueResult)resultList[ii];

                    // the matching item object.
                    Item item = (Item)itemList[ii];

                    // save revised sampling rates.
                    item.SamplingRate          = result.SamplingRate;
                    item.SamplingRateSpecified = result.SamplingRateSpecified;
                }

                // look for uninitialized results - must have an invalid or duplicate server handles.
                for (int ii = 0; ii < results.Length; ii++)
                {
                    if (results[ii] == null)
                    {
                        results[ii]                = new IdentifiedResult(items[ii]);
                        results[ii].ResultID       = ResultID.Da.E_INVALIDHANDLE;
                        results[ii].DiagnosticInfo = null;
                    }
                }

                // save modified list of items.
                m_items = itemList;

                // send data change notifications.
                OnDataChange(resultList);

                // return results.
                return(results);
            }
        }
示例#3
0
        //======================================================================
        // Item Management

        /// <summary>
        /// Adds items to the subscription.
        /// </summary>
        /// <param name="items">The set of items to add to the subscription.</param>
        /// <returns>The results of the add item operation for each item.</returns>
        public ItemResult[] AddItems(Item[] items)
        {
            if (items == null)
            {
                throw new ArgumentNullException("items");
            }

            // check if nothing to do.
            if (items.Length == 0)
            {
                return(new ItemResult[0]);
            }

            lock (this)
            {
                if (m_proxy == null)
                {
                    throw new NotConnectedException();
                }

                // create complete item list.
                ItemList itemList = new ItemList();
                if (m_items != null)
                {
                    itemList.AddRange(m_items);
                }

                // add new items.
                for (int ii = 0; ii < items.Length; ii++)
                {
                    Item clone = (Item)items[ii].Clone();

                    // generate a unique item handle.
                    clone.ServerHandle = Guid.NewGuid().ToString();

                    // items must be active when first added.
                    clone.Active          = true;
                    clone.ActiveSpecified = true;

                    itemList.Add(clone);
                }

                // save the index of the first new item.
                int start = (m_items != null)?m_items.Count:0;

                // (re)establishes a subscription.
                ItemValueResultList resultList = Subscribe(itemList);

                if (resultList == null || resultList.Count != itemList.Count)
                {
                    throw new InvalidResponseException();
                }

                // clear existing item list.
                m_items.Clear();

                // process results.
                ItemResult[] results = new ItemResult[items.Length];

                for (int ii = 0; ii < resultList.Count; ii++)
                {
                    // the current item value result object.
                    SubscribeItemValueResult result = (SubscribeItemValueResult)resultList[ii];

                    // the matching item object.
                    Item item = itemList[ii];

                    // save revised sampling rates.
                    item.SamplingRate          = result.SamplingRate;
                    item.SamplingRateSpecified = result.SamplingRateSpecified;

                    // create item result object for new items.
                    if (ii >= start)
                    {
                        results[ii - start]                = new ItemResult(item);
                        results[ii - start].ResultID       = result.ResultID;
                        results[ii - start].DiagnosticInfo = result.DiagnosticInfo;
                    }

                    // existing items stay in the list; only add new items if successful.
                    if (ii < start || result.ResultID.Succeeded())
                    {
                        m_items.Add(item);
                    }
                }

                // cancel subscription if subscription is not active.
                if (!m_state.Active)
                {
                    Unsubscribe();
                }

                // send data change notifications if subscription is active.
                else
                {
                    OnDataChange(resultList);
                }

                // return the results for the new items.
                return(results);
            }
        }
示例#4
0
        /// <summary>
        /// Modifies the state of items in the subscription
        /// </summary>
        /// <param name="masks">Specifies which item state parameters are being modified.</param>
        /// <param name="items">The new state for each item.</param>
        /// <returns>The results of the modify item operation for each item.</returns>
        public ItemResult[] ModifyItems(int masks, Item[] items)
        {
            if (items == null)
            {
                throw new ArgumentNullException("items");
            }

            // check if nothing to do.
            if (items.Length == 0)
            {
                return(new ItemResult[0]);
            }

            lock (this)
            {
                if (m_proxy == null)
                {
                    throw new NotConnectedException();
                }

                // build the modified list of items.
                ArrayList itemList = new ArrayList(items.Length);

                foreach (Item item in m_items)
                {
                    // search the list of masks for a matching server handle.
                    bool found = false;

                    foreach (Item changes in items)
                    {
                        // apply the updates to an item copy.
                        if (item.ServerHandle.Equals(changes.ServerHandle))
                        {
                            Item clone = (Item)item.Clone();

                            // change requested data type.
                            if ((masks & (int)StateMask.ReqType) != 0)
                            {
                                clone.ReqType = changes.ReqType;
                            }

                            // deactivating items not supported at ths time.
                            if ((masks & (int)StateMask.Active) != 0)
                            {
                                clone.Active          = true;
                                clone.ActiveSpecified = true;
                            }

                            // change deadband.
                            if ((masks & (int)StateMask.Deadband) != 0)
                            {
                                clone.Deadband          = changes.Deadband;
                                clone.DeadbandSpecified = changes.DeadbandSpecified;
                            }

                            // change sampling rate
                            if ((masks & (int)StateMask.SamplingRate) != 0)
                            {
                                clone.SamplingRate          = changes.SamplingRate;
                                clone.SamplingRateSpecified = changes.SamplingRateSpecified;
                            }

                            // change buffering.
                            if ((masks & (int)StateMask.SamplingRate) != 0)
                            {
                                clone.EnableBuffering          = changes.EnableBuffering;
                                clone.EnableBufferingSpecified = changes.EnableBufferingSpecified;
                            }

                            itemList.Add(clone);
                            found = true;
                            break;
                        }
                    }

                    // original to the item list.
                    if (!found)
                    {
                        itemList.Add(item);
                    }
                }

                // create a new subscription.
                ItemValueResultList resultList = Subscribe(itemList);

                // construct result for each mask provided.
                ItemResult[] results = new ItemResult[items.Length];

                for (int ii = 0; ii < resultList.Count; ii++)
                {
                    // the current item value result object.
                    SubscribeItemValueResult result = (SubscribeItemValueResult)resultList[ii];

                    // the matching item object.
                    Item item = (Item)itemList[ii];

                    // save revised sampling rates.
                    item.SamplingRate          = result.SamplingRate;
                    item.SamplingRateSpecified = result.SamplingRateSpecified;

                    // search list of masks for a matching server handle.
                    for (int jj = 0; jj < items.Length; jj++)
                    {
                        if (result.ServerHandle.Equals(items[jj].ServerHandle))
                        {
                            results[jj]                = new ItemResult(item);
                            results[jj].ResultID       = result.ResultID;
                            results[jj].DiagnosticInfo = result.DiagnosticInfo;
                            break;
                        }
                    }
                }

                // look for masks without a result - must have an invalid or duplicate server handles.
                for (int ii = 0; ii < results.Length; ii++)
                {
                    if (results[ii] == null)
                    {
                        results[ii]                = new ItemResult(items[ii]);
                        results[ii].ResultID       = ResultID.Da.E_INVALIDHANDLE;
                        results[ii].DiagnosticInfo = null;
                    }
                }

                // save modified list of items.
                m_items = itemList;

                // send data change notifications.
                OnDataChange(resultList);

                // return results.
                return(results);
            }
        }
示例#5
0
        /// <summary>
        /// Called when a poll completes.
        /// </summary>
        private void  OnPollCompleted(IAsyncResult handle)
        {
            // restore async state parameters.
            string[] args = (string[])handle.AsyncState;

            try
            {
                lock (this)
                {
                    // check if object has been disposed.
                    if (m_proxy == null)
                    {
                        return;
                    }

                    // fetch the poll results.
                    string[] invalidHandles = null;
                    bool     bufferOverflow = false;

                    OpcXml.Da10.SubscribePolledRefreshReplyItemList[] replyLists = null;
                    OpcXml.Da10.OPCError[] errors = null;
                    OpcXml.Da10.ReplyBase  reply  = null;

                    reply = m_proxy.EndSubscriptionPolledRefresh(
                        handle,
                        out invalidHandles,
                        out replyLists,
                        out errors,
                        out bufferOverflow);

                    // cache results with the server object.
                    m_server.PollCompleted((string)args[1], reply, errors);

                    // check if the server handle has changed - ignore results in this case.
                    if (!args[0].Equals(m_state.ServerHandle))
                    {
                        return;
                    }

                    ItemValueResultList resultList = null;

                    // restore subscription if it has been dropped by the server for some reason.
                    if (invalidHandles != null && invalidHandles.Length > 0)
                    {
                        resultList = Subscribe(m_items);

                        if (resultList != null && resultList.Count == m_items.Count)
                        {
                            // replace the client handles.
                            for (int ii = 0; ii < m_items.Count; ii++)
                            {
                                SubscribeItemValueResult result = (SubscribeItemValueResult)resultList[ii];

                                if (result.ResultID.Succeeded())
                                {
                                    Item item = (Item)m_items[ii];

                                    // save revised sampling rate.
                                    item.SamplingRate          = result.SamplingRate;
                                    item.SamplingRateSpecified = result.SamplingRateSpecified;
                                }
                            }
                        }
                    }

                    // get the list of changed items.
                    else
                    {
                        ItemValueResultList[] resultLists = OpcXml.Da10.Request.GetSubscribeRefreshLists(replyLists);

                        // validate items and replace the client handles.
                        resultList = new ItemValueResultList();

                        if (resultLists != null && resultLists.Length == 1)
                        {
                            foreach (ItemValueResult result in resultLists[0])
                            {
                                foreach (Item item in m_items)
                                {
                                    if (item.ServerHandle.Equals(result.ClientHandle))
                                    {
                                        result.ServerHandle = item.ServerHandle;
                                        result.ClientHandle = item.ClientHandle;
                                        resultList.Add(result);
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    // send the data change notifications.
                    OnDataChange(resultList);

                    // check if a new poll should be scheduled.
                    if (args[2] != null)
                    {
                        SchedulePoll();
                    }
                }
            }
            catch (Exception e)
            {
                string message = e.Message;

                // schedule a new poll on exception.
                if (args[2] != null)
                {
                    SchedulePoll();
                }
            }
        }