/// <summary>
        /// Validates the nodes and reads the values from the underlying source.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="nodesToRead">The nodes to read.</param>
        /// <param name="values">The values.</param>
        /// <param name="errors">The errors.</param>
        /// <param name="nodesToValidate">The nodes to validate.</param>
        /// <param name="cache">The cache.</param>
        protected override void Read(
            ServerSystemContext context,
            IList<ReadValueId> nodesToRead,
            IList<DataValue> values,
            IList<ServiceResult> errors,
            List<NodeHandle> nodesToValidate,
            IDictionary<NodeId, NodeState> cache)
        {
            ComHdaClientManager system = (ComHdaClientManager)this.SystemContext.SystemHandle;
            ComHdaClient client = (ComHdaClient)system.SelectClient((ServerSystemContext)SystemContext, false);

            HdaReadRequestCollection requests = new HdaReadRequestCollection();

            for (int ii = 0; ii < nodesToValidate.Count; ii++)
            {
                NodeHandle handle = nodesToValidate[ii];

                lock (Lock)
                {
                    NodeState source = ValidateNode(context, handle, cache);

                    if (source == null)
                    {
                        continue;
                    }

                    DataValue value = values[handle.Index];
                    ReadValueId nodeToRead = nodesToRead[handle.Index];

                    // determine if request can be sent to the server.
                    bool queued = false;
                    errors[handle.Index] = requests.Add(source, nodeToRead, out queued);

                    if (queued)
                    {
                        continue;
                    }

                    // read built-in metadata.
                    errors[handle.Index] = source.ReadAttribute(
                        context,
                        nodeToRead.AttributeId,
                        nodeToRead.ParsedIndexRange,
                        nodeToRead.DataEncoding,
                        value);
                }
            }

            // read the attributes.
            if (requests.Count > 0)
            {
                client.Read(requests, false);
            }

            // extract the values from the results.
            for (int ii = 0; ii < nodesToValidate.Count; ii++)
            {
                NodeHandle handle = nodesToValidate[ii];
                DataValue value = values[handle.Index];
                ReadValueId nodeToRead = nodesToRead[handle.Index];

                lock (Lock)
                {
                    if (!requests.HasResult(nodeToRead))
                    {
                        continue;
                    }

                    errors[handle.Index] = requests.GetResult(context, handle.Node, nodeToRead, value, context.DiagnosticsMask);
                }
            }
        }
Example #2
0
        /// <summary>
        /// Reads the specified requests.
        /// </summary>
        /// <param name="requests">The requests.</param>
        /// <param name="useExistingHandles">if set to <c>true</c> use the handles specified in the request objects.</param>
        public void Read(HdaReadRequestCollection requests, bool useExistingHandles)
        {
            // check if nothing to do.
            if (requests == null || requests.Count == 0)
            {
                return;
            }

            int[] serverHandles = new int[requests.Count];
            int[] itemErrors = null;
            HdaItem[] items = null;

            // check if using existing handles.
            if (useExistingHandles)
            {
                for (int ii = 0; ii < requests.Count; ii++)
                {
                    serverHandles[ii] = requests[ii].ServerHandle;
                }
            }

            // create new handles to use for the request.
            else
            {
                string[] itemIds = new string[requests.Count];
                itemErrors = new int[requests.Count];

                for (int ii = 0; ii < requests.Count; ii++)
                {
                    itemIds[ii] = requests[ii].ItemId;
                }

                items = GetItems(itemIds);

                for (int ii = 0; ii < requests.Count; ii++)
                {
                    serverHandles[ii] = items[ii].ServerHandle;
                    itemErrors[ii] = items[ii].Error;
                }
            }

            // read attributes.
            try
            {
                for (int ii = 0; ii < serverHandles.Length; ii++)
                {
                    HdaReadRequest request = requests[ii];

                    if (itemErrors != null && itemErrors[ii] < 0)
                    {
                        request.SetError(request.AttributeIds.Count);
                        continue;
                    }

                    try
                    {
                        int[] attributeIds = new int[request.AttributeIds.Count];

                        for (int jj = 0; jj < attributeIds.Length; jj++)
                        {
                            attributeIds[jj] = Utils.ToInt32(request.AttributeIds[jj]);
                        }

                        request.AttributeValues = ReadAttributeValues(serverHandles[ii], attributeIds);
                    }
                    catch (Exception e)
                    {
                        request.SetError(Marshal.GetHRForException(e));
                    }
                }
            }
            finally
            {
                if (items != null)
                {
                    ReleaseItemHandles(items);
                }
            }
        }
        /// <summary>
        /// Called when the scan attributes timer expires.
        /// </summary>
        private void DoScan(Dictionary<string, HdaSubscribeAttributeRequest> requests, bool initialUpdate)
        {
            try
            {
                ComHdaClientManager system = (ComHdaClientManager)m_context.SystemHandle;
                ComHdaClient client = (ComHdaClient)system.SelectClient(m_context, false);

                // ensure all requests have valid handles.
                AssignHandles(client, requests);

                // collect the list of attributes that need reading.
                HdaReadRequestCollection itemsToRead = new HdaReadRequestCollection();
                List<HdaSubscribeAttributeRequest> subscribeRequests = new List<HdaSubscribeAttributeRequest>();
                List<HdaReadRequest> readRequestsForSubscribeRequests = new List<HdaReadRequest>();

                lock (m_lock)
                {
                    DateTime now = DateTime.UtcNow;

                    foreach (KeyValuePair<string,HdaSubscribeAttributeRequest> entry in requests)
                    {
                        // check if it is time for an update.
                        if (!initialUpdate && entry.Value.NextUpdateTime > now)
                        {
                            continue;
                        }

                        // create a read request for each monitored item.
                        bool somethingToDo = false;

                        for (int ii = 0; ii < entry.Value.MonitoredItems.Count; ii++)
                        {
                            MonitoredItem monitoredItem = entry.Value.MonitoredItems[ii];

                            NodeHandle handle = monitoredItem.ManagerHandle as NodeHandle;

                            if (handle == null)
                            {
                                continue;
                            }

                            // check if item is not valid.
                            if (entry.Value.ServerHandle == null)
                            {
                                monitoredItem.QueueValue(null, StatusCodes.BadNodeIdUnknown);
                                continue;
                            }

                            ReadValueId valueToRead = monitoredItem.GetReadValueId();

                            bool queued = false;
                            StatusCode error = itemsToRead.Add(handle.Node, valueToRead, out queued);

                            if (StatusCode.IsBad(error))
                            {
                                monitoredItem.QueueValue(null, error);
                                continue;
                            }

                            if (!somethingToDo && queued)
                            {
                                // add server handle to read request.
                                HdaReadRequest request = (HdaReadRequest)valueToRead.Handle;
                                request.ServerHandle = entry.Value.ServerHandle.Value;

                                // save mapping between subscribe request and read requests.
                                subscribeRequests.Add(entry.Value);
                                readRequestsForSubscribeRequests.Add(request);
                                somethingToDo = true;
                            }
                        }
                    }

                    // check if nothing to do.
                    if (requests.Count == 0)
                    {
                        return;
                    }
                }
                
                // read the attributes from the server.
                client.Read(itemsToRead, true);

                // update the monitored items.
                lock (m_lock)
                {
                    for (int ii = 0; ii < subscribeRequests.Count; ii++)
                    {
                        subscribeRequests[ii].QueueValues(m_context, readRequestsForSubscribeRequests[ii], initialUpdate);
                    }
                }
            }
            catch (Exception e)
            {
                Utils.Trace(e, "Unexpected error scanning attributes in HDA COM server.");
            }
        }