/// <summary> /// Checks the type of the data. /// </summary> /// <param name="expectedType">The expected type.</param> /// <param name="value">The value.</param> /// <returns>True if the value can be written to the server.</returns> private bool CheckDataType(short expectedType, Variant value) { if (value.Value == null) { return(true); } if (expectedType == (short)VarEnum.VT_CY) { expectedType = (short)VarEnum.VT_BSTR; } if (expectedType == (short)(VarEnum.VT_ARRAY | VarEnum.VT_CY)) { expectedType = (short)(VarEnum.VT_ARRAY | VarEnum.VT_BSTR); } TypeInfo typeInfo = value.TypeInfo; VarEnum vtType = ComUtils.GetVarType(typeInfo); if (vtType == VarEnum.VT_EMPTY) { return(false); } if (expectedType == (short)(VarEnum.VT_ARRAY | VarEnum.VT_VARIANT)) { // must be an array. Array array = value.Value as Array; if (array == null || (typeInfo.BuiltInType == BuiltInType.ByteString && typeInfo.ValueRank == ValueRanks.Scalar)) { return(false); } // nothing more to for fixed type arrays. if (typeInfo.BuiltInType != BuiltInType.Variant) { return(true); } // must check each element. for (int ii = 0; ii < array.GetLength(0); ii++) { object element = array.GetValue(ii); if (!CheckDataType((short)VarEnum.VT_VARIANT, new Variant(element))) { return(false); } } } if (expectedType == (short)vtType || expectedType == (short)VarEnum.VT_VARIANT) { return(true); } return(false); }
/// <summary> /// Converts a UA value to an HDA attribute value. /// </summary> /// <param name="session">The session.</param> /// <param name="attributeId">The attribute id.</param> /// <param name="values">The values.</param> /// <param name="index">The index.</param> /// <returns></returns> private DaValue GetAttributeValue(Session session, uint attributeId, DataValueCollection values, int index) { switch (attributeId) { case Constants.OPCHDA_DATA_TYPE: { DaValue result = new DaValue(); DataValue value = values[index]; // check for valid node. if (StatusCode.IsBad(value.StatusCode)) { result.Error = ResultIds.E_UNKNOWNITEMID; return(result); } // covert to var type. NodeId dataTypeId = value.GetValue <NodeId>(DataTypeIds.BaseDataType); int valueRank = values[index + 1].GetValue <int>(ValueRanks.Scalar); BuiltInType builtInType = DataTypes.GetBuiltInType(dataTypeId, session.TypeTree); TypeInfo typeInfo = new TypeInfo(builtInType, valueRank); short varType = (short)ComUtils.GetVarType(typeInfo); result.Value = varType; result.Quality = ComUtils.GetQualityCode(value.StatusCode); result.Timestamp = value.ServerTimestamp; result.Error = ResultIds.S_OK; return(result); } case Constants.OPCHDA_DESCRIPTION: { DataValue value = values[index]; if (value.StatusCode == StatusCodes.BadAttributeIdInvalid) { DaValue result = new DaValue(); result.Error = ResultIds.E_INVALIDATTRID; return(result); } return(m_mapper.GetLocalDataValue(value)); } default: { return(ComHdaProxy.GetAttributeValue(session, m_mapper, attributeId, values[index])); } } }
/// <summary> /// Validates the items by reading the attributes required to add them to the group. /// </summary> /// <param name="session">The session.</param> /// <param name="group">The group.</param> /// <param name="requests">The requests.</param> /// <param name="items">The items.</param> /// <param name="start">The start index.</param> /// <param name="count">The number of items to process.</param> private void ValidateItems( Session session, ComDaGroup group, ComDaCreateItemRequest[] requests, ComDaGroupItem[] items, int start, int count) { // build list of the UA attributes that need to be read. ReadValueIdCollection attributesToRead = new ReadValueIdCollection(); for (int ii = start; ii < start + count && ii < requests.Length; ii++) { // create the group item. ComDaCreateItemRequest request = requests[ii]; ComDaGroupItem item = items[ii] = new ComDaGroupItem(group, request.ItemId); item.NodeId = m_mapper.GetRemoteNodeId(request.ItemId); item.Active = request.Active; item.ClientHandle = request.ClientHandle; item.RequestedDataType = request.RequestedDataType; item.SamplingRate = -1; item.Deadband = -1; // add attributes. ReadValueId attributeToRead; attributeToRead = new ReadValueId(); attributeToRead.NodeId = item.NodeId; attributeToRead.AttributeId = Attributes.NodeClass; attributesToRead.Add(attributeToRead); attributeToRead = new ReadValueId(); attributeToRead.NodeId = item.NodeId; attributeToRead.AttributeId = Attributes.DataType; attributesToRead.Add(attributeToRead); attributeToRead = new ReadValueId(); attributeToRead.NodeId = item.NodeId; attributeToRead.AttributeId = Attributes.ValueRank; attributesToRead.Add(attributeToRead); attributeToRead = new ReadValueId(); attributeToRead.NodeId = item.NodeId; attributeToRead.AttributeId = Attributes.UserAccessLevel; attributesToRead.Add(attributeToRead); } // read attribute values from the server. DataValueCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; try { session.Read( null, 0, TimestampsToReturn.Neither, attributesToRead, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, attributesToRead); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, attributesToRead); } catch (Exception e) { Utils.Trace(e, "Unexpected error reading attributes for items."); // set default values on error. for (int ii = start; ii < start + count && ii < requests.Length; ii++) { requests[ii].Error = ResultIds.E_INVALIDITEMID; } return; } // process results. int first = 0; for (int ii = start; ii < start + count && ii < requests.Length; ii++, first += 4) { ComDaGroupItem item = items[ii]; // verify node class. NodeClass nodeClass = (NodeClass)results[first].GetValue <int>((int)NodeClass.Unspecified); if (nodeClass != NodeClass.Variable) { requests[ii].Error = ResultIds.E_INVALIDITEMID; continue; } // verify data type. NodeId dataTypeId = results[first + 1].GetValue <NodeId>(null); if (dataTypeId == null) { requests[ii].Error = ResultIds.E_INVALIDITEMID; continue; } // get value rank. int valueRank = results[first + 2].GetValue <int>(ValueRanks.Scalar); // update datatypes. BuiltInType builtInType = DataTypes.GetBuiltInType(dataTypeId, session.TypeTree); item.RemoteDataType = new TypeInfo(builtInType, valueRank); item.CanonicalDataType = (short)ComUtils.GetVarType(item.RemoteDataType); // update access rights. byte userAccessLevel = results[first + 3].GetValue <byte>(0); if ((userAccessLevel & AccessLevels.CurrentRead) != 0) { item.AccessRights |= OpcRcw.Da.Constants.OPC_READABLE; } if ((userAccessLevel & AccessLevels.CurrentWrite) != 0) { item.AccessRights |= OpcRcw.Da.Constants.OPC_WRITEABLE; } } }