宜昌华友-原料库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

973 lines
41 KiB

using System;
using System.Collections;
using System.Security.Cryptography.X509Certificates;
using Opc.Ua;
using Opc.Ua.Client;
using Siemens.OpcUA.Helper;
namespace Siemens.OpcUA
{
/// <summary>
/// Event handler for the event that the client received a value change.
/// </summary>
public delegate void valueChanged(object clientHandle, DataValue value);
/// <summary>
/// Event handler for the event that the client received a untrusted server certificate.
/// </summary>
public delegate void certificateValidation(CertificateValidator validator, CertificateValidationEventArgs e);
/// <summary>
/// This class encapsulates a connection to an OPC UA server and access to particular Services of it.
/// </summary>
public class Server
{
public object lockThis = new object();
#region Construction
public Server()
{ }
#endregion
#region Fields
/// <summary>
/// Keeps a session with an UA server.
/// </summary>
private Session m_Session = null;
/// <summary>
/// Interface which encapsulates the use of the browse service of an UA server.
/// </summary>
private Browser m_Browser = null;
/// <summary>
/// Keeps a hash table for attribute names.
/// </summary>
private Hashtable m_hashAttributeNames = null;
#endregion
#region Properties
/// <summary>
/// Use the certificateValidation delegate as event.
/// </summary>
public event certificateValidation CertificateEvent = null;
/// <summary>
/// Provides the session being established with an OPC UA server.
/// </summary>
public Session Session
{
get { return m_Session; }
}
#endregion
#region Connect
/// <summary>Establishes the connection to an OPC UA server.</summary>
/// <param name="url">The Url of the endpoint.</param>
/// <returns>Result code.</returns>
/// <exception cref="Exception">Throws and forwards any exception with short error description.</exception>
public void Connect(string Url)
{
try
{
// Create the configuration.
ApplicationConfiguration configuration = Helpers.CreateClientConfiguration();
// Create the endpoint description.
EndpointDescription endpointDescription = Helpers.CreateEndpointDescription(Url);
// Create the endpoint configuration (use the application configuration to provide default values).
EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(configuration);
// The default timeout for a requests sent using the channel.
endpointConfiguration.OperationTimeout = 300000;
// Use the pure binary encoding on the wire.
endpointConfiguration.UseBinaryEncoding = true;
// Create the endpoint.
ConfiguredEndpoint endpoint = new ConfiguredEndpoint(null, endpointDescription, endpointConfiguration);
// Create the binding factory.
BindingFactory bindingFactory = BindingFactory.Create(configuration);
// Update endpoint description using the discovery endpoint.
if (endpoint.UpdateBeforeConnect)
{
endpoint.UpdateFromServer(bindingFactory);
endpointDescription = endpoint.Description;
endpointConfiguration = endpoint.Configuration;
}
X509Certificate2 clientCertificate = configuration.SecurityConfiguration.ApplicationCertificate.Find();
// Set up a callback to handle certificate validation errors.
configuration.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation);
// Initialize the channel which will be created with the server.
SessionChannel channel = SessionChannel.Create(
configuration,
endpointDescription,
endpointConfiguration,
bindingFactory,
clientCertificate,
null);
// Wrap the channel with the session object.
// This call will fail if the server does not trust the client certificate.
m_Session = new Session(channel, configuration, endpoint);
m_Session.ReturnDiagnostics = DiagnosticsMasks.All;
// Register keep alive callback.
m_Session.KeepAlive += new KeepAliveEventHandler(Session_KeepAlive);
UserIdentity identity = new UserIdentity();
// Create the session. This actually connects to the server.
// Passing null for the user identity will create an anonymous session.
m_Session.Open("Siemens OPC UA sample client - main session", identity);
}
catch (Exception e)
{
throw e;
}
}
/// <summary>Establishes the connection to an OPC UA server.</summary>
/// <param name="url">The Url of the endpoint.</param>
/// <returns>Result code.</returns>
/// <exception cref="Exception">Throws and forwards any exception with short error description.</exception>
public void Connect(EndpointDescription endpointDescription)
{
try
{
// Create the configuration.
ApplicationConfiguration configuration = Helpers.CreateClientConfiguration();
// Create the endpoint configuration (use the application configuration to provide default values).
EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(configuration);
// The default timeout for a requests sent using the channel.
endpointConfiguration.OperationTimeout = 300000;
// Use the pure binary encoding on the wire.
endpointConfiguration.UseBinaryEncoding = true;
// Create the endpoint.
ConfiguredEndpoint endpoint = new ConfiguredEndpoint(null, endpointDescription, endpointConfiguration);
// Create the binding factory.
BindingFactory bindingFactory = BindingFactory.Create(configuration);
X509Certificate2 clientCertificate = configuration.SecurityConfiguration.ApplicationCertificate.Find();
// Set up a callback to handle certificate validation errors.
configuration.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation);
// Initialize the channel which will be created with the server.
SessionChannel channel = SessionChannel.Create(
configuration,
endpointDescription,
endpointConfiguration,
bindingFactory,
clientCertificate,
null);
// Wrap the channel with the session object.
// This call will fail if the server does not trust the client certificate.
m_Session = new Session(channel, configuration, endpoint);
m_Session.ReturnDiagnostics = DiagnosticsMasks.All;
// Register keep alive callback.
m_Session.KeepAlive += new KeepAliveEventHandler(Session_KeepAlive);
UserIdentity identity = new UserIdentity();
// Create the session. This actually connects to the server.
// Passing null for the user identity will create an anonymous session.
m_Session.Open("Siemens OPC UA sample client - main session", identity);
}
catch (Exception e)
{
throw e;
}
}
/// <summary>Releases the connection to an OPC UA server.</summary>
/// <returns>Result code.</returns>
/// <exception cref="Exception">Throws and forwards any exception with short error description.</exception>
public int Disconnect()
{
int result = 0;
// Close the session.
try
{
m_Session.Close(10000);
}
catch (Exception e)
{
return -1;
throw e;
}
// Delete browser.
m_Browser = null;
return result;
}
#endregion
#region Browse
/// <summary>
/// Navigates through the address space of an OPC UA server.
/// </summary>
/// <param name="nodeId">The starting node.</param>
/// <param name="browseResults">A list of results for the passed starting node and filters.</param>
/// <returns>Result code.</returns>
/// <exception cref="Exception">Throws and forwards any exception with short error description.</exception>
public int Browse(NodeId nodeId, out ReferenceDescriptionCollection browseResults)
{
int result = 0;
if (m_Browser == null)
{
// Instantiate browser.
m_Browser = new Browser(m_Session);
}
// Browse filter: only follow hierarchical references.
m_Browser.ReferenceTypeId = ReferenceTypes.HierarchicalReferences;
browseResults = null;
try
{
// The actual call to the server.
browseResults = m_Browser.Browse(nodeId);
}
catch (Exception e)
{
result = -1;
throw e;
}
return result;
}
#endregion
#region Read / Write
/// <summary>
/// Reads any attribute of one or more nodes.
/// </summary>
/// <param name="nodesToRead">A list of nodes to read.</param>
/// <param name="results">A list of read results.</param>
/// <exception cref="Exception">Throws and forwards any exception with short error description.</exception>
public void Read(
ReadValueIdCollection nodesToRead,
out DataValueCollection results)
{
results = null;
DiagnosticInfoCollection diagnosticInfos = null;
try
{
// The actual call to the server.
m_Session.Read(
null,
0,
TimestampsToReturn.Both,
nodesToRead,
out results,
out diagnosticInfos);
}
catch (Exception e)
{
throw e;
}
}
/// <summary>
/// Reads the value attribute of one or more nodes.
/// </summary>
/// <param name="nodesToRead">A list of nodes to read.</param>
/// <param name="results">A list of data values.</param>
/// <exception cref="Exception">Throws and forwards any exception with short error description.</exception>
public ResponseHeader ReadValues(
NodeIdCollection nodesToRead,
out DataValueCollection results)
{
ResponseHeader response = null;
results = null;
DiagnosticInfoCollection diagnosticInfos;
// build list of attributes to read.
ReadValueIdCollection valueIdsToRead = new ReadValueIdCollection();
try
{
for (int i = 0; i < nodesToRead.Count; i++)
{
ReadValueId attributeToRead = new ReadValueId();
attributeToRead.NodeId = nodesToRead[i];
attributeToRead.AttributeId = Attributes.Value;
attributeToRead.Handle = attributeIdToString(Attributes.Value);
valueIdsToRead.Add(attributeToRead);
}
response = m_Session.Read(
null,
0,
TimestampsToReturn.Both,
valueIdsToRead,
out results,
out diagnosticInfos);
}
catch (Exception e)
{
throw e;
}
return response;
}
/// <summary>
/// Writes the Value attribute of one or more nodes.
/// </summary>
/// <param name="nodesToWrite">A list of nodes to write.</param>
/// <param name="results">A list of values to write.</param>
/// <exception cref="Exception">Throws and forwards any exception with short error description.</exception>
public void WriteValues(
NodeIdCollection nodesToWrite,
DataValueCollection values,
out StatusCodeCollection results)
{
results = null;
DiagnosticInfoCollection diagnosticInfos = null;
// Build list of attributes to write.
WriteValueCollection valuesToWrite = new WriteValueCollection();
try
{
for (int i = 0; i < nodesToWrite.Count; i++)
{
WriteValue attributeToWrite = new WriteValue();
attributeToWrite.NodeId = nodesToWrite[i];
// We have to write the Value attribute only:
attributeToWrite.AttributeId = Attributes.Value;
attributeToWrite.Handle = attributeIdToString(Attributes.Value);
// Set the according value:
attributeToWrite.Value = values[i];
valuesToWrite.Add(attributeToWrite);
}
// Actual call to server.
m_Session.Write(
null,
valuesToWrite,
out results,
out diagnosticInfos);
}
catch (Exception e)
{
throw e;
}
}
#endregion
#region 20220518 asynchronous Writes
/// <summary>
/// asynchronous Writes the Value attribute of one or more nodes.
/// </summary>
/// <param name="nodesToWrite">A list of nodes to write.</param>
/// <param name="results">A list of values to write.</param>
/// <exception cref="Exception">Throws and forwards any exception with short error description.</exception>
public void AsyWriteValues(
NodeIdCollection nodesToWrite,
DataValueCollection values,
out StatusCodeCollection results)
{
results = null;
//DiagnosticInfoCollection diagnosticInfos = null;
// Build list of attributes to write.
WriteValueCollection valuesToWrite = new WriteValueCollection();
try
{
for (int i = 0; i < nodesToWrite.Count; i++)
{
WriteValue attributeToWrite = new WriteValue();
attributeToWrite.NodeId = nodesToWrite[i];
// We have to write the Value attribute only:
attributeToWrite.AttributeId = Attributes.Value;
attributeToWrite.Handle = attributeIdToString(Attributes.Value);
// Set the according value:
attributeToWrite.Value = values[i];
valuesToWrite.Add(attributeToWrite);
}
// Actual call to server. AsyWriteValues
m_Session.BeginWrite(
null,
valuesToWrite,
null, // miss the call back function
null); // miss the call back function
}
catch (Exception e)
{
throw e;
}
}
#endregion
#region Subscribe for Data Changes
/// <summary>
/// Creates a subscription and associate it with the current session.
/// </summary>
/// <param name="publishingInterval">The requested publishing interval.</param>
/// <returns>Instance of class Subscription.</returns>
/// <exception cref="Exception">Throws and forwards any exception with short error description.</exception>
public Subscription AddSubscription(int publishingInterval)
{
Subscription newSubscription = null;
try
{
Opc.Ua.Client.Subscription innerSubscription = new Opc.Ua.Client.Subscription(m_Session.DefaultSubscription);
innerSubscription.DisplayName = "My Subscription Name";
innerSubscription.PublishingEnabled = true;
innerSubscription.PublishingInterval = publishingInterval; // in milliseconds.
innerSubscription.KeepAliveCount = 10; // 10*UaRefreshRate = 5s if UaRefreshRate = 500
innerSubscription.LifetimeCount = 100; // UaRefreshRate*100 = 50s if UaRefreshRate = 500;
innerSubscription.MaxNotificationsPerPublish = 1000;//ÿ�ζ��ķ��أ�������������������//20151120
// Associate the subscription with the session.
m_Session.AddSubscription(innerSubscription);
// Call the server and create the subscription.
innerSubscription.Create();
// At this point the subscription is sending publish requests at the keep alive rate.
// Use the Notification event the session to receive updates when a publish completes.
m_Session.Notification += new NotificationEventHandler(Session_Notification);
newSubscription = new Subscription();
newSubscription.Session = m_Session;
newSubscription.innerSubscription = innerSubscription;
}
catch (Exception e)
{
throw e;
}
return newSubscription;
}
// Modifies the publishing interval of a subscription.
/// <summary>
/// Creates a subscription and associates it with the current session.
/// </summary>
/// <param name="subscription">The subscription object.</param>
/// <param name="subscription">The newly requested publishing interval.</param>
/// <exception cref="Exception">Throws and forwards any exception with short error description.</exception>
public void ModifySubscription(Subscription subscription,int publishingInterval)
{
try
{
// Modify publishing interval
subscription.innerSubscription.PublishingInterval = publishingInterval;
// Apply change
subscription.innerSubscription.Modify();
}
catch (Exception e)
{
throw e;
}
}
/// <summary>
/// Removes a subscription from the session.
/// </summary>
/// <param name="subscription">The subscription object.</param>
/// <exception cref="Exception">Throws and forwards any exception with short error description.</exception>
public void RemoveSubscription(Subscription subscription)
{
try
{
// Remove the subscription from the corresponding session.
m_Session.RemoveSubscription(subscription.innerSubscription);
}
catch (Exception e)
{
throw e;
}
}
#endregion
#region Event Handlers
/// <summary>
/// Will be raised when a certificate is classified as untrusted.
/// </summary>
/// <param name="validator">The event handler.</param>
/// <param name="e">The <see cref="Opc.Ua.CertificateValidationEventArgs"/>Instance containing the event data.</param>
private void CertificateValidator_CertificateValidation(CertificateValidator validator, CertificateValidationEventArgs e)
{
if (CertificateEvent != null)
{
CertificateEvent(validator, e);
}
else
{
e.Accept = false;
}
}
/// <summary>
/// Keep-alive callback.
/// </summary>
/// <param name="session">The target of the event.</param>
/// <param name="e">The <see cref="Opc.Ua.KeepAliveEventArgs"/>Instance containing the event data.</param>
private void Session_KeepAlive(Session session, KeepAliveEventArgs e)
{
}
/// <summary>
/// Raised when a publish response arrives from the server.
/// </summary>
/// <param name="session">The target of the event.</param>
/// <param name="e">The <see cref="Opc.Ua.Client.NotifacationEventArgs"/>Instance containing the event data.</param>
private void Session_Notification(Session session, NotificationEventArgs e)
{
lock (lockThis)
{
NotificationMessage message = e.NotificationMessage;
// Check for keep alive.
if (message.NotificationData.Count == 0)
{
return;
}
// Get the data changes (oldest to newest).
foreach (MonitoredItemNotification datachange in message.GetDataChanges(false))
{
// Lookup the monitored item.
MonitoredItem monitoredItem = e.Subscription.FindItemByClientHandle(datachange.ClientHandle);
if (monitoredItem == null)
{
continue;
}
ClientMonitoredItemData clientData = monitoredItem.Handle as ClientMonitoredItemData;
clientData.callback(clientData.clientHandle, datachange.Value);
}
}
}
#endregion
#region Helper Methods
/// <summary>
/// Converts an attribute id to string.
/// </summary>
/// <param name="attributeId">The attribute id.</param>
/// <returns>The attribute name as string.</returns>
public string attributeIdToString(uint attributeId)
{
// Populate hashtable if called for the first time
if (m_hashAttributeNames == null)
{
m_hashAttributeNames = new Hashtable();
m_hashAttributeNames.Add(Attributes.AccessLevel, "AccessLevel");
m_hashAttributeNames.Add(Attributes.ArrayDimensions, "ArrayDimensions");
m_hashAttributeNames.Add(Attributes.BrowseName, "BrowseName");
m_hashAttributeNames.Add(Attributes.ContainsNoLoops, "ContainsNoLoops");
m_hashAttributeNames.Add(Attributes.DataType, "DataType");
m_hashAttributeNames.Add(Attributes.Description, "Description");
m_hashAttributeNames.Add(Attributes.DisplayName, "DisplayName");
m_hashAttributeNames.Add(Attributes.EventNotifier, "EventNotifier");
m_hashAttributeNames.Add(Attributes.Executable, "Executable");
m_hashAttributeNames.Add(Attributes.Historizing, "Historizing");
m_hashAttributeNames.Add(Attributes.InverseName, "InverseName");
m_hashAttributeNames.Add(Attributes.IsAbstract, "IsAbstract");
m_hashAttributeNames.Add(Attributes.MinimumSamplingInterval, "MinimumSamplingInterval");
m_hashAttributeNames.Add(Attributes.NodeClass, "NodeClass");
m_hashAttributeNames.Add(Attributes.NodeId, "NodeId");
m_hashAttributeNames.Add(Attributes.Symmetric, "Symmetric");
m_hashAttributeNames.Add(Attributes.UserAccessLevel, "UserAccessLevel");
m_hashAttributeNames.Add(Attributes.UserExecutable, "UserExecutable");
m_hashAttributeNames.Add(Attributes.UserWriteMask, "UserWriteMask");
m_hashAttributeNames.Add(Attributes.Value, "Value");
m_hashAttributeNames.Add(Attributes.ValueRank, "ValueRank");
m_hashAttributeNames.Add(Attributes.WriteMask, "WriteMask");
}
string ret = (string)m_hashAttributeNames[attributeId];
return ret;
}
//
/// <summary>
/// Converts an attribute value to an user readable string.
/// </summary>
/// <param name="nodeRead">Contains the attriute id.</param>
/// <param name="nodeRead">The value to convert.</param>
/// <returns>The attribute value as string.</returns>
public string attributeValueToString(ReadValueId nodeRead, DataValue result)
{
if (result == null || result.Value == null)
{
return "";
}
string ret = "";
switch (nodeRead.AttributeId)
{
case Attributes.AccessLevel:
case Attributes.UserAccessLevel:
{
// Check datatype.
if (result.Value.GetType() == typeof(byte))
{
if (((byte)result.Value & AccessLevels.CurrentRead) == AccessLevels.CurrentRead)
{
ret = "Readable";
}
if (((byte)result.Value & AccessLevels.CurrentWrite) == AccessLevels.CurrentWrite)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "Writeable";
}
if (((byte)result.Value & AccessLevels.HistoryRead) == AccessLevels.HistoryRead)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "HistoryReadable";
}
if (((byte)result.Value & AccessLevels.HistoryWrite) == AccessLevels.HistoryWrite)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "HistoryWriteable";
}
if (ret.Length == 0)
{
ret = "None";
}
}
else
{
ret = "Invalid Datatype: Expected Byte, Received " + result.Value.GetType().ToString();
}
}
break;
case Attributes.WriteMask:
case Attributes.UserWriteMask:
{
// Check datatype.
if (result.Value.GetType() == typeof(uint))
{
if (((uint)result.Value & (uint)AttributeWriteMask.AccessLevel) == (uint)AttributeWriteMask.AccessLevel)
{
ret = "AccessLevel";
}
if (((uint)result.Value & (uint)AttributeWriteMask.BrowseName) == (uint)AttributeWriteMask.BrowseName)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "BrowseName";
}
if (((uint)result.Value & (uint)AttributeWriteMask.ContainsNoLoops) == (uint)AttributeWriteMask.ContainsNoLoops)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "ContainsNoLoops";
}
if (((uint)result.Value & (uint)AttributeWriteMask.DataType) == (uint)AttributeWriteMask.DataType)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "DataType";
}
if (((uint)result.Value & (uint)AttributeWriteMask.Description) == (uint)AttributeWriteMask.Description)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "Description";
}
if (((uint)result.Value & (uint)AttributeWriteMask.DisplayName) == (uint)AttributeWriteMask.DisplayName)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "DisplayName";
}
if (((uint)result.Value & (uint)AttributeWriteMask.EventNotifier) == (uint)AttributeWriteMask.EventNotifier)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "EventNotifier";
}
if (((uint)result.Value & (uint)AttributeWriteMask.Executable) == (uint)AttributeWriteMask.Executable)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "Executable";
}
if (((uint)result.Value & (uint)AttributeWriteMask.Historizing) == (uint)AttributeWriteMask.Historizing)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "Historizing";
}
if (((uint)result.Value & (uint)AttributeWriteMask.InverseName) == (uint)AttributeWriteMask.InverseName)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "InverseName";
}
if (((uint)result.Value & (uint)AttributeWriteMask.IsAbstract) == (uint)AttributeWriteMask.IsAbstract)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "IsAbstract";
}
if (((uint)result.Value & (uint)AttributeWriteMask.MinimumSamplingInterval) == (uint)AttributeWriteMask.MinimumSamplingInterval)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "MinimumSamplingInterval";
}
if (((uint)result.Value & (uint)AttributeWriteMask.Symmetric) == (uint)AttributeWriteMask.Symmetric)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "Symmetric";
}
if (((uint)result.Value & (uint)AttributeWriteMask.UserAccessLevel) == (uint)AttributeWriteMask.UserAccessLevel)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "UserAccessLevel";
}
if (((uint)result.Value & (uint)AttributeWriteMask.UserExecutable) == (uint)AttributeWriteMask.UserExecutable)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "UserExecutable";
}
if (((uint)result.Value & (uint)AttributeWriteMask.UserWriteMask) == (uint)AttributeWriteMask.UserWriteMask)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "UserWriteMask";
}
if (((uint)result.Value & (uint)AttributeWriteMask.ValueRank) == (uint)AttributeWriteMask.ValueRank)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "ValueRank";
}
if (((uint)result.Value & (uint)AttributeWriteMask.WriteMask) == (uint)AttributeWriteMask.WriteMask)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "WriteMask";
}
if (ret.Length == 0)
{
ret = "None";
}
}
else
{
ret = "Invalid Datatype: Expected Uint32, Received " + result.Value.GetType().ToString();
}
}
break;
case Attributes.NodeClass:
{
// Check datatype.
if (result.Value.GetType() == typeof(Int32))
{
switch ((Int32)result.Value)
{
case (int)NodeClass.DataType:
ret = "DataType";
break;
case (int)NodeClass.Method:
ret = "Method";
break;
case (int)NodeClass.Object:
ret = "Object";
break;
case (int)NodeClass.ObjectType:
ret = "ObjectType";
break;
case (int)NodeClass.ReferenceType:
ret = "ReferenceType";
break;
case (int)NodeClass.Unspecified:
ret = "Unspecified";
break;
case (int)NodeClass.Variable:
ret = "Variable";
break;
case (int)NodeClass.VariableType:
ret = "VariableType";
break;
case (int)NodeClass.View:
ret = "View";
break;
default:
ret = "Invalid NodeClass";
break;
}
}
else
{
ret = "Invalid Datatype: Expected Int32, Received " + result.Value.GetType().ToString();
}
}
break;
case Attributes.EventNotifier:
{
// Check datatype.
if (result.Value.GetType() == typeof(byte))
{
if (((byte)result.Value & EventNotifiers.HistoryRead) == EventNotifiers.HistoryRead)
{
ret = "HistoryRead";
}
if (((byte)result.Value & EventNotifiers.HistoryWrite) == EventNotifiers.HistoryWrite)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "HistoryWrite";
}
if (((byte)result.Value & EventNotifiers.SubscribeToEvents) == EventNotifiers.SubscribeToEvents)
{
if (ret.Length > 0)
{
ret += ", ";
}
ret += "SubscribeToEvents";
}
if (ret.Length == 0)
{
ret += "None";
}
}
else
{
ret = "Invalid Datatype: Expected Byte, Received " + result.Value.GetType().ToString();
}
}
break;
case Attributes.DataType:
{
// Check datatype.
if (result.Value.GetType() == typeof(NodeId))
{
NodeId node = (NodeId)result.Value;
INode datatype = m_Session.NodeCache.Find(node);
if (datatype != null)
{
ret = String.Format("{0}", datatype);
}
else
{
ret = String.Format("{0}", node);
}
}
else
{
ret = "Invalid Datatype: Expected NodeId, Received " + result.Value.GetType().ToString();
}
}
break;
case Attributes.ArrayDimensions:
case Attributes.BrowseName:
case Attributes.ContainsNoLoops:
case Attributes.Description:
case Attributes.DisplayName:
case Attributes.Executable:
case Attributes.Historizing:
case Attributes.InverseName:
case Attributes.IsAbstract:
case Attributes.MinimumSamplingInterval:
case Attributes.NodeId:
case Attributes.Symmetric:
case Attributes.UserExecutable:
case Attributes.Value:
case Attributes.ValueRank:
default:
ret = result.Value.ToString();
break;
}
return ret;
}
#endregion
}
}