/// <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); } } }
/// <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."); } }