public HdaItemHandle[] GetItemHandles(Session session, string[] itemIds, int[] clientHandles, bool validateOnly)
{
HdaItemHandle[] handles = new HdaItemHandle[itemIds.Length];
ReadValueIdCollection nodesToRead = new ReadValueIdCollection();
for (int ii = 0; ii < itemIds.Length; ii++)
{
InternalHandle handle = new InternalHandle();
handles[ii] = handle;
if (clientHandles != null)
{
handle.ClientHandle = clientHandles[ii];
}
string itemId = itemIds[ii];
if (String.IsNullOrEmpty(itemId))
{
handle.Error = ResultIds.E_INVALIDITEMID;
continue;
}
// check if item has already been assigned.
Item item = null;
if (!validateOnly)
{
lock (m_lock)
{
if (m_items.TryGetValue(itemId, out item))
{
handle.NodeId = item.NodeId;
handle.ServerHandle = ++m_lastServerHandle;
handle.Item = item;
item.Refs++;
m_handles[handle.ServerHandle] = handle;
Utils.Trace("Created Handle: {0} {1}", handle.ServerHandle, handle.NodeId);
continue;
}
}
}
// create a new item.
handle.Item = item = new Item();
item.ItemId = itemId;
handle.Error = ResultIds.S_OK; // assume valid for no - set to an error when detected.
handle.NodeId = item.NodeId = m_mapper.GetRemoteNodeId(itemId);
nodesToRead.Add(Construct(handle, Attributes.UserAccessLevel));
nodesToRead.Add(Construct(handle, Attributes.DisplayName));
nodesToRead.Add(Construct(handle, Attributes.Description));
nodesToRead.Add(Construct(handle, Attributes.DataType));
nodesToRead.Add(Construct(handle, Attributes.ValueRank));
nodesToRead.Add(Construct(handle, Attributes.Historizing));
}
// check if nothing to do.
if (nodesToRead.Count == 0)
{
return handles;
}
DataValueCollection values = null;
DiagnosticInfoCollection diagnosticInfos = null;
// read values from the UA server.
session.Read(
null,
0,
TimestampsToReturn.Neither,
nodesToRead,
out values,
out diagnosticInfos);
// validate response from the UA server.
ClientBase.ValidateResponse(values, nodesToRead);
ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead);
// assign a local handle to all valid items.
NodeIdCollection nodesToRegister = new NodeIdCollection();
List<InternalHandle> items = new List<InternalHandle>();
for (int ii = 0; ii < nodesToRead.Count; ii++)
{
InternalHandle handle = (InternalHandle)nodesToRead[ii].Handle;
DataValue value = values[ii];
Item item = handle.Item;
// check status codes.
if (StatusCode.IsBad(value.StatusCode))
{
// description is an optional attribute.
if (nodesToRead[ii].AttributeId != Attributes.Description)
{
handle.Error = ResultIds.E_UNKNOWNITEMID;
}
continue;
}
// check access level.
if (nodesToRead[ii].AttributeId == Attributes.UserAccessLevel)
{
byte accessLevel = value.GetValue<byte>(AccessLevels.None);
if ((accessLevel & AccessLevels.HistoryRead) == 0)
{
handle.Error = ResultIds.E_UNKNOWNITEMID;
continue;
}
}
// save attribute.
switch (nodesToRead[ii].AttributeId)
{
case Attributes.DisplayName: { item.DisplayName = value.GetValue<LocalizedText>(null); break; }
case Attributes.Description: { item.Description = value.GetValue<LocalizedText>(null); break; }
case Attributes.DataType: { item.DataType = value.GetValue<NodeId>(null); break; }
case Attributes.ValueRank: { item.ValueRank = value.GetValue<int>(ValueRanks.Scalar); break; }
case Attributes.Historizing: { item.Historizing = value.GetValue<bool>(false); break; }
}
// should have all item metadata when processing the historizing attribute result.
if (nodesToRead[ii].AttributeId == Attributes.Historizing)
{
// check for a fatal error with one or more mandatory attributes.
if (handle.Error != ResultIds.S_OK)
{
continue;
}
BuiltInType builtInType = DataTypes.GetBuiltInType(item.DataType, session.TypeTree);
item.RemoteType = new TypeInfo(builtInType, item.ValueRank);
if (!validateOnly)
{
nodesToRegister.Add(item.NodeId);
items.Add(handle);
lock (m_lock)
{
m_items[handle.Item.ItemId] = handle.Item;
handle.ServerHandle = ++m_lastServerHandle;
handle.NodeId = handle.Item.NodeId;
handle.Item.Refs++;
m_handles[handle.ServerHandle] = handle;
Utils.Trace("Created Handle: {0} {1}", handle.ServerHandle, handle.NodeId);
}
}
}
}
return handles;
}