OPCFoundation.NetStandard.Opc.Ua是OPC基金会发布的开源OPC UA包,提供Client读写库方便读写OPC 服务器数据。
OPCFoundation.NetStandard.Opc.Ua开源项目地址:https://github.com/OPCFoundation/UA-.NETStandard
使用时有几点需要注意。
1、订阅分组
OPC UA的数据订阅分组,和OPC DA的有所不同,每个组数据项有限,这个值具体是多少与服务器的配置有关,一般几百到上千。每个组的订阅名称也不能相同,需要考虑订阅名称分类。服务器对与订阅资源是有限的,有的服务器必须显式的释放订阅资源,不然会造成订阅资源耗尽而订阅失败,必须重启服务端软件才能解决。
2、连接断开
OPC Client与服务器连接断开有两种情况:主动断开和被动断开
客户端主动断开时,必须先注销订阅的数据分组项,再进行断开。目前这个库不能在连接关闭时自动释放所有服务器的连接资源,这个也是这个库不太友好的地方。 如果是服务端主动断开,很可能是服务器关闭了,这时直接关闭即可。
3、数据读取
数据读取有订阅、同步和异步几种方法。订阅较为复杂但性能高、占用的网络带宽也最少。同步与异步仅调用语法有差异,其他类似。
同步或异步都数据时,读多少数据点,就传入多少,然后到返回值中拿数据,C#可以作比较好的类型转换。
4、数据写入
OPC UA在数据写入时,对数据类型有严格要求,数据类型不会自动转换,会写入失败。如果仅在C#系统内部写入数据,且仅少数点写入这时读有次数据,记录返回的数据类型,固定编码写入。
在数据量较多,且有数据订阅的情况下,也可以记录每个点的数据类型,在写入数据时索引数据类型,然后自动转换。
在把数据接口封装为API的情况下,同一个数据可以解析为很多数据类型,比如数据123,可以是Byte,I2、U2、I4、U4、R4等很多类型,反序列化时一般会解析为Single,直接调用写入会因数据类型不正确而失败。这时除了使用索引,自己处理数据兼容性问题,也可以多写几个wrapper来处理数据类型转换问题。
示例的Controller类代码如下:
[ApiController]
[Route("[controller]/[action]")]
public class OpcUaControlServiceController : ControllerBase
{
private readonly ILogger _logger;
public OpcUaControlServiceController(ILogger logger)
{
_logger = logger;
}
///
/// 获取服务运行信息
///
/// 运行信息概览JSON
[HttpPost,HttpGet]
public string info()
{
return ApiContentResultMsg.Success(OpcUaControlService.Instance.Info());
}
///
/// 启动OpcUa 控制服务
///
/// 执行信息JSON
[HttpPost]
public string Start()
{
OpcUaControlService.Instance.Start();
return ApiContentResultMsg.Success();
}
///
/// 停止OpcUa 控制服务
///
/// 执行信息JSON
[HttpPost]
public string ShutDown()
{
OpcUaControlService.Instance.ShutDown();
return ApiContentResultMsg.Success();
}
///
/// 写入Int32 类型 OpcUa NodeId数据
///
/// 执行信息JSON
[HttpPost]
public string SyncWriteOpcUaInt32(String nodeId, Int32 value)
{
bool b = OpcUaControlService.Instance.SyncWriteOpcUaInt32(nodeId, value);
return b?ApiContentResultMsg.Success(): ApiContentResultMsg.Error("write fail!");
}
///
/// 写入float 类型 OpcUa NodeId数据
///
/// 执行信息JSON
[HttpPost]
public string SyncWriteOpcUaFloat(String nodeId, float value)
{
bool b = OpcUaControlService.Instance.SyncWriteOpcUaFloat(nodeId, value);
return b ? ApiContentResultMsg.Success() : ApiContentResultMsg.Error("write fail!");
}
///
/// 写入bool 类型 OpcUa NodeId数据
///
/// 执行信息JSON
[HttpPost]
public string SyncWriteOpcUaBool(String nodeId, bool value)
{
bool b = OpcUaControlService.Instance.SyncWriteOpcUaBool(nodeId, value);
return b ? ApiContentResultMsg.Success() : ApiContentResultMsg.Error("write fail!");
}
///
/// 写入String 类型 OpcUa NodeId数据
///
/// 执行信息JSON
[HttpPost]
public string SyncWriteOpcUaString(String nodeId, String value)
{
bool b = OpcUaControlService.Instance.SyncWriteOpcUaString(nodeId, value);
return b ? ApiContentResultMsg.Success() : ApiContentResultMsg.Error("write fail!");
}
}
5、参考资料
日本DeviceXPlorer OPC Server软件,在日系PLC和数控支持上比较友好,适用于1万点以内的采集服务,其自带了有个客户端的Demo,参考如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Opc.Ua.Client;
using Opc.Ua.Configuration;
using Opc.Ua;
using System.Security.Cryptography.X509Certificates;
namespace DxpUaSimpleAPI
{
public class DxpUaSimpleClass
{
public struct ReadItemResults
{
public object m_readResultValue;
public StatusCode m_resultCodes;
public DateTime m_sourceTimeStamp;
public DateTime m_serverTimeStamp;
}
public struct WriteItemResults
{
public StatusCode m_resultCodes;
}
public delegate void onAsyncReadCompleteDelegate(List asyncReadNodeName, List AsyncReadItemResults);
public delegate void onAsyncWriteCompleteDelegate(List asyncWriteNodeName, List asyncResultStatus);
public delegate void monitoredItemNotification(List monitoredItems, List monitoredItemValue);
private Session m_clientSession = null;
private Dictionary m_subscriptionMap = new Dictionary();
private ApplicationInstance m_application = new ApplicationInstance();
private List m_subscriptions = new List();
public onAsyncReadCompleteDelegate m_ReadEventHandler = null;
public onAsyncWriteCompleteDelegate m_WriteEventHandler = null;
public monitoredItemNotification m_MonitoredEventHandler = null;
public struct CertificateStore
{
public string m_applicationCertificateFileName;
public string m_applicationCertificateStore;
public string m_trustedIssuerCertificatesStore;
public string m_TrustedPeerCertificatesStore;
public string m_RejectedCertificateStore;
}
public struct BrowseNodeResults
{
public QualifiedName m_browseName;
public ExpandedNodeId m_nodeIdList;
public LocalizedText m_displayName;
public StatusCode m_statusCodes;
}
public void Initialize()
{
m_application.ApplicationType = ApplicationType.Client;
m_application.ConfigSectionName = "Opc.Ua.SampleClient";
try
{
m_application.LoadApplicationConfiguration(false);
m_application.CheckApplicationInstanceCertificate(false, 0);
}
catch (Exception ex)
{
Console.WriteLine(" Initialize Exception" + ex.Message);
}
}
public bool Initialize(string sApplicationName, string sApplicationUri, string sProductUri, CertificateStore newCertificateStore, string sStoreType)
{
try
{
m_application.ApplicationConfiguration = new ApplicationConfiguration();
if (sApplicationName == "")
{
m_application.ApplicationConfiguration.ApplicationName = "OPC UA User Client";
}
if (sApplicationUri == "")
{
m_application.ApplicationConfiguration.ApplicationUri = "urn:localhost:TAKEBISHI:UserClient";
}
if (sProductUri == "")
{
m_application.ApplicationConfiguration.ProductUri = "http://opcfoundation.org/UA/SampleClient";
}
m_application.ApplicationConfiguration.ApplicationType = ApplicationType.Client;
m_application.ApplicationConfiguration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier(new X509Certificate2(newCertificateStore.m_applicationCertificateFileName));
m_application.ApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StoreType = CertificateStoreType.Directory;
m_application.ApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StorePath = newCertificateStore.m_applicationCertificateStore;
m_application.ApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.OpenStore();
m_application.ApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StoreType = sStoreType;
m_application.ApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StorePath = newCertificateStore.m_trustedIssuerCertificatesStore;
m_application.ApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.OpenStore();
m_application.ApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StoreType = sStoreType;
m_application.ApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath = newCertificateStore.m_TrustedPeerCertificatesStore;
m_application.ApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.OpenStore();
m_application.ApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore = new CertificateStoreIdentifier();
m_application.ApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StoreType = sStoreType;
m_application.ApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StorePath = newCertificateStore.m_RejectedCertificateStore;
m_application.ApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.OpenStore();
m_application.ApplicationConfiguration.SecurityConfiguration.AutoAcceptUntrustedCertificates = false;
m_application.ApplicationConfiguration.CertificateValidator = new CertificateValidator();
StringCollection wellKnownDiscoveryUrls = new StringCollection();
wellKnownDiscoveryUrls.Add("http://{0}:52601/UADiscovery");
wellKnownDiscoveryUrls.Add("opc.tcp://{0}:4840");
wellKnownDiscoveryUrls.Add("http://{0}/UADiscovery/Default.svc");
m_application.ApplicationConfiguration.ClientConfiguration = new ClientConfiguration();
m_application.ApplicationConfiguration.ClientConfiguration.WellKnownDiscoveryUrls = wellKnownDiscoveryUrls;
m_application.CheckApplicationInstanceCertificate(false, 0);
}
catch (Exception ex)
{
Console.WriteLine(" Initialize Exception" + ex.Message);
return false;
}
return true;
}
public ConfiguredEndpoint GetEndPoint(string sUrl, MessageSecurityMode securityMode, string sSecurityPoricies)
{
try
{
ApplicationConfiguration configuration = m_application.ApplicationConfiguration;
EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(configuration);
EndpointDescription endpointDescription = null;
endpointDescription = new EndpointDescription();
endpointDescription.EndpointUrl = sUrl;
endpointDescription.SecurityLevel = 0;
endpointDescription.SecurityMode = securityMode;
endpointDescription.SecurityPolicyUri = sSecurityPoricies;
endpointDescription.Server.ApplicationName = endpointDescription.EndpointUrl;
endpointDescription.Server.ApplicationType = ApplicationType.Server;
endpointDescription.Server.ApplicationUri = endpointDescription.EndpointUrl;
ConfiguredEndpoint endpoint = new ConfiguredEndpoint(null, endpointDescription, endpointConfiguration);
return endpoint;
}
catch (Exception ex)
{
Console.WriteLine(" GetEndPoint Exception" + ex.Message);
return null;
}
}
public bool Connect(string sUrl, MessageSecurityMode securityMode, string sSecurityPoricies)
{
ApplicationConfiguration configuration = m_application.ApplicationConfiguration;
bool UpdateBeforeConnect = true;
string sSessionName = "session1";
uint nSessionTimeout = 3000;
UserIdentity userIdentity = null;
IList PreferredLocales = null;
ConfiguredEndpoint endpoint = GetEndPoint(sUrl, securityMode, sSecurityPoricies);
try
{
m_clientSession = Session.Create(configuration, endpoint, UpdateBeforeConnect, sSessionName, nSessionTimeout, userIdentity, PreferredLocales);
if (m_clientSession == null)
{
return false;
}
return true;
}
catch (Exception ex)
{
Console.WriteLine(" Session Create Exception" + ex.Message);
return false;
}
}
public bool DisConnect()
{
if (m_subscriptions.Count() > 0)
{
for (int i = 0; i < m_subscriptions.Count(); i++)
{
Subscription subscription = m_subscriptions[i];
if (m_subscriptionMap.ContainsKey(subscription.DisplayName))
{
subscription = m_subscriptionMap[subscription.DisplayName];
if (!RemoveAllMonitoredItems(subscription.DisplayName))
{
return false;
}
}
}
if (!m_clientSession.RemoveSubscriptions(m_subscriptions))
{
return false;
}
}
try
{
if (m_clientSession != null)
{
m_clientSession.Close();
m_clientSession.Dispose();
m_clientSession = null;
}
}
catch (Exception ex)
{
Console.WriteLine(" Session close Exception" + ex.Message);
return false;
}
return true;
}
public bool BrowseNode(NodeId targetNodeId, NodeId ReferenceType, out List results)
{
BrowseDescription nodeToBrowse = new BrowseDescription();
BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection();
RequestHeader BrowseRequestHeader = new RequestHeader();
ViewDescription BrowseView = new ViewDescription();
BrowseResultCollection BrowseResults = new BrowseResultCollection();
uint requestMaxReferencesPerNode = 0;
DiagnosticInfoCollection BrowseDiagnosticsInfos = new DiagnosticInfoCollection();
nodeToBrowse.ReferenceTypeId = ReferenceType;
nodeToBrowse.NodeId = targetNodeId;
nodeToBrowse.IncludeSubtypes = true;
nodeToBrowse.NodeClassMask = (uint)(NodeClass.Object | NodeClass.Variable);
nodeToBrowse.ResultMask = (uint)BrowseResultMask.All;
nodeToBrowse.BrowseDirection = BrowseDirection.Forward;
nodesToBrowse.Add(nodeToBrowse);
results = new List();
BrowseNodeResults browseNodeResults = new BrowseNodeResults();
browseNodeResults.m_browseName = null;
browseNodeResults.m_nodeIdList = null;
browseNodeResults.m_displayName = null;
browseNodeResults.m_statusCodes = new StatusCode();
try
{
m_clientSession.Browse(BrowseRequestHeader, BrowseView, requestMaxReferencesPerNode, nodesToBrowse, out BrowseResults, out BrowseDiagnosticsInfos);
browseNodeResults.m_statusCodes = BrowseResults[0].StatusCode;
for (int i = 0; i < BrowseResults[0].References.Count(); i++)
{
browseNodeResults.m_browseName = BrowseResults[0].References[i].BrowseName;
browseNodeResults.m_nodeIdList = BrowseResults[0].References[i].NodeId;
browseNodeResults.m_displayName = BrowseResults[0].References[i].DisplayName;
results.Add(browseNodeResults);
}
}
catch (Exception ex)
{
Console.WriteLine(" BrowseNode Exception" + ex.Message);
return false;
}
return true;
}
public bool SyncRead(List readItemList, out List results)
{
RequestHeader ReadRequestHeader = new RequestHeader();
ReadRequestHeader.ReturnDiagnostics = 5000;
ReadValueIdCollection nodesToRead = new ReadValueIdCollection();
DataValueCollection ReadResults = new DataValueCollection();
DiagnosticInfoCollection ReadDiagnosticsInfos = null;
results = new List();
ReadItemResults readItemResults = new ReadItemResults();
readItemResults.m_readResultValue = 0;
readItemResults.m_resultCodes = new StatusCode();
readItemResults.m_serverTimeStamp = new DateTime();
readItemResults.m_sourceTimeStamp = new DateTime();
try
{
foreach (NodeId nodeId in readItemList)
{
ReadValueId readId = new ReadValueId();
readId.NodeId = nodeId;
readId.AttributeId = (uint)Attributes.Value;
nodesToRead.Add(readId);
}
m_clientSession.Read(ReadRequestHeader, 0, TimestampsToReturn.Both, nodesToRead, out ReadResults, out ReadDiagnosticsInfos);
for (int i = 0; i < ReadResults.Count(); i++)
{
readItemResults.m_resultCodes = ReadResults[i].StatusCode;
if (!StatusCode.IsBad(ReadResults[i].StatusCode))
{
readItemResults.m_readResultValue = ReadResults[i].Value;
readItemResults.m_sourceTimeStamp = ReadResults[i].SourceTimestamp;
readItemResults.m_serverTimeStamp = ReadResults[i].ServerTimestamp;
}
else
{
readItemResults.m_readResultValue = null;
readItemResults.m_sourceTimeStamp = DateTime.MinValue;
readItemResults.m_serverTimeStamp = DateTime.MinValue;
}
results.Add(readItemResults);
}
}
catch (Exception ex)
{
Console.WriteLine(" SyncRead Exception" + ex.Message);
return false;
}
return true;
}
public bool SyncWrite(List writeNodeIdList, List writeValueList, out List Results)
{
RequestHeader WriteRequestHeader = null;
Results = new List();
WriteItemResults writeItemResults = new WriteItemResults();
writeItemResults.m_resultCodes = new StatusCode();
WriteValueCollection writeValueCollection = new WriteValueCollection();
StatusCodeCollection WriteResults = null;
DiagnosticInfoCollection WriteDiagnosticsInfos = null;
try
{
for (int i = 0; i < writeNodeIdList.Count(); i++)
{
WriteValue valueToWrite = new WriteValue();
valueToWrite.NodeId = writeNodeIdList[i];
valueToWrite.AttributeId = (uint)Attributes.Value;
valueToWrite.Value.Value = writeValueList[i];
valueToWrite.Value.StatusCode = StatusCodes.Good;
valueToWrite.Value.ServerTimestamp = DateTime.MinValue;
writeValueCollection.Add(valueToWrite);
}
m_clientSession.Write(WriteRequestHeader, writeValueCollection, out WriteResults, out WriteDiagnosticsInfos);
if (WriteResults.Count() > 0)
{
for (int m = 0; m < WriteResults.Count(); m++)
{
writeItemResults.m_resultCodes = WriteResults[0];
Results.Add(writeItemResults);
}
}
else
{
return false;
}
}
catch (Exception ex)
{
Console.WriteLine(" SyncWrite Exception" + ex.Message);
return false;
}
return true;
}
public void ASyncRead(List readItemList)
{
ReadValueIdCollection nodesToRead = new ReadValueIdCollection();
try
{
foreach (NodeId nodeId in readItemList)
{
ReadValueId readId = new ReadValueId();
readId.NodeId = nodeId;
readId.AttributeId = (uint)Attributes.Value;
nodesToRead.Add(readId);
}
m_clientSession.BeginRead(null, 0, TimestampsToReturn.Both, nodesToRead, new AsyncCallback(AsyncReadCompleted), nodesToRead);
}
catch (Exception ex)
{
Console.WriteLine(" ASyncRead Exception" + ex.Message);
}
}
public void AsyncReadCompleted(IAsyncResult result)
{
try
{
if (!result.IsCompleted)
{
return;
}
EndRead(result);
}
catch (Exception ex)
{
Console.WriteLine(" ASyncRead Exception" + ex.Message);
}
}
public ResponseHeader EndRead(IAsyncResult result)
{
ReadResponse response = null;
DataValueCollection results = new DataValueCollection();
DiagnosticInfoCollection diagnosticInfos = new DiagnosticInfoCollection();
ReadValueIdCollection nodesToRead = (ReadValueIdCollection)result.AsyncState;
List readResults = new List();
IServiceResponse genericResponse = m_clientSession.TransportChannel.EndSendRequest(result);
if (genericResponse == null)
{
throw new ServiceResultException(StatusCodes.BadUnknownResponse);
}
ValidateResponse(genericResponse.ResponseHeader);
response = (ReadResponse)genericResponse;
results = response.Results;
diagnosticInfos = response.DiagnosticInfos;
ClientBase.ValidateResponse(results, nodesToRead);
ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead);
ReadItemResults readItemResults = new ReadItemResults();
readItemResults.m_readResultValue = 0;
readItemResults.m_resultCodes = new StatusCode();
readItemResults.m_serverTimeStamp = new DateTime();
readItemResults.m_sourceTimeStamp = new DateTime();
List asyncReadNodeName = new List();
for (int i = 0; i < results.Count; i++)
{
asyncReadNodeName.Add(nodesToRead[i].NodeId.ToString());
readItemResults.m_resultCodes = results[i].StatusCode;
if (!StatusCode.IsBad(results[i].StatusCode))
{
readItemResults.m_readResultValue = results[i].Value;
readItemResults.m_sourceTimeStamp = results[i].SourceTimestamp;
readItemResults.m_serverTimeStamp = results[i].ServerTimestamp;
}
else
{
readItemResults.m_readResultValue = null;
readItemResults.m_sourceTimeStamp = DateTime.MinValue;
readItemResults.m_serverTimeStamp = DateTime.MinValue;
}
readResults.Add(readItemResults);
}
m_ReadEventHandler(asyncReadNodeName, readResults);
return response.ResponseHeader;
}
public static void ValidateResponse(ResponseHeader header)
{
if (header == null)
{
throw new ServiceResultException(StatusCodes.BadUnknownResponse, "Deficiencies in the response.");
}
if (StatusCode.IsBad(header.ServiceResult))
{
throw new ServiceResultException(new ServiceResult(header.ServiceResult, header.ServiceDiagnostics, header.StringTable));
}
}
public void RegisterReadEventHandler(onAsyncReadCompleteDelegate eventHandler)
{
m_ReadEventHandler = eventHandler;
}
public void UnRegisterReadEventHandler(onAsyncReadCompleteDelegate eventHandler)
{
m_ReadEventHandler -= eventHandler;
}
public bool ASyncWrite(List writeNodeIdList, List writeValueList)
{
RequestHeader AsyncWriteRequestHeader = null;
WriteValueCollection nodesToAsyncWrite = new WriteValueCollection();
try
{
for (int i = 0; i < writeNodeIdList.Count(); i++)
{
WriteValue valueToAsyncWrite = new WriteValue();
valueToAsyncWrite.NodeId = writeNodeIdList[i];
TypeInfo typeInfo = TypeInfo.Construct(writeValueList[i]);
valueToAsyncWrite.Value.Value = writeValueList[i];
valueToAsyncWrite.AttributeId = (uint)Attributes.Value;
valueToAsyncWrite.Value.StatusCode = StatusCodes.Good;
valueToAsyncWrite.Value.ServerTimestamp = DateTime.MinValue;
valueToAsyncWrite.Value.SourceTimestamp = DateTime.MinValue;
nodesToAsyncWrite.Add(valueToAsyncWrite);
}
m_clientSession.BeginWrite(AsyncWriteRequestHeader, nodesToAsyncWrite, new AsyncCallback(AsyncWriteCompleted), nodesToAsyncWrite);
}
catch (Exception ex)
{
Console.WriteLine(" ASyncWrite Exception" + ex.Message);
return false;
}
return true;
}
public void AsyncWriteCompleted(IAsyncResult result)
{
try
{
if (!result.IsCompleted)
{
return;
}
EndWrite(result);
}
catch (Exception ex)
{
Console.WriteLine(" ASyncWrite Exception" + ex.Message);
}
}
public ResponseHeader EndWrite(IAsyncResult result)
{
WriteResponse response = null;
StatusCodeCollection results = new StatusCodeCollection();
DiagnosticInfoCollection diagnosticInfos = new DiagnosticInfoCollection();
WriteValueCollection nodesToWrite = (WriteValueCollection)result.AsyncState;
List writeResults = new List();
IServiceResponse genericResponse = m_clientSession.TransportChannel.EndSendRequest(result);
if (genericResponse == null)
{
throw new ServiceResultException(StatusCodes.BadUnknownResponse);
}
ValidateResponse(genericResponse.ResponseHeader);
response = (WriteResponse)genericResponse;
results = response.Results;
diagnosticInfos = response.DiagnosticInfos;
List asyncWriteNodeName = new List();
WriteItemResults writeItemResults = new WriteItemResults();
writeItemResults.m_resultCodes = new StatusCode();
for (int ii = 0; ii < results.Count; ii++)
{
asyncWriteNodeName.Add(nodesToWrite[ii].NodeId.ToString());
writeItemResults.m_resultCodes = results[ii];
writeResults.Add(writeItemResults);
}
m_WriteEventHandler(asyncWriteNodeName, writeResults);
return response.ResponseHeader;
}
public void RegisterWriteEventHandler(onAsyncWriteCompleteDelegate eventHandler)
{
m_WriteEventHandler = eventHandler;
}
public void UnRegisterWriteEventHandler(onAsyncReadCompleteDelegate eventHandler)
{
m_ReadEventHandler = null;
}
public bool CreateSubscription(string sSubscriptionName, int nPublishInterval)
{
Subscription subscription = new Subscription(m_clientSession.DefaultSubscription);
subscription.DisplayName = sSubscriptionName;
subscription.PublishingInterval = nPublishInterval;
subscription.LifetimeCount = 100;
subscription.KeepAliveCount = 10;
subscription.MaxNotificationsPerPublish = 1000;
subscription.Priority = 1;
subscription.PublishingEnabled = true;
subscription.TimestampsToReturn = TimestampsToReturn.Both;
if (m_clientSession.AddSubscription(subscription))
{
subscription.Create();
m_subscriptions.Add(subscription);
m_subscriptionMap.Add(sSubscriptionName, subscription);
return true;
}
else
{
return false;
}
}
public bool DestroySubscription(string sSubscriptionName)
{
Subscription subscription = null;
if (m_subscriptionMap.ContainsKey(sSubscriptionName))
{
subscription = m_subscriptionMap[sSubscriptionName];
if (RemoveAllMonitoredItems(sSubscriptionName))
{
if (m_clientSession.RemoveSubscription(subscription))
{
m_subscriptionMap.Remove(sSubscriptionName);
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
else
{
return false;
}
}
public bool AddMonitoredItem(string sSubscriptionName, List NodeIdList)
{
Subscription subscription = null;
if (m_subscriptionMap.ContainsKey(sSubscriptionName))
subscription = m_subscriptionMap[sSubscriptionName];
try
{
for (int count = 0; count < NodeIdList.Count(); count++)
{
MonitoredItem monitoredItem = new MonitoredItem(subscription.DefaultItem);
monitoredItem.StartNodeId = NodeIdList[count];
string monitoredItemName = "MonitoredItem_" + count.ToString();
monitoredItem.AttributeId = Attributes.Value;
monitoredItem.DisplayName = monitoredItemName;
monitoredItem.MonitoringMode = MonitoringMode.Reporting;
monitoredItem.SamplingInterval = subscription.PublishingInterval;
monitoredItem.QueueSize = 0;
monitoredItem.DiscardOldest = true;
if (Contains(subscription, monitoredItem))
{
Console.WriteLine("The item is already added.");
}
subscription.AddItem(monitoredItem);
monitoredItem.Handle = this;
subscription.ApplyChanges();
if (ServiceResult.IsBad(monitoredItem.Status.Error))
{
throw new ServiceResultException(monitoredItem.Status.Error);
}
monitoredItem.Notification += monitoredItem_Notification;
}
}
catch (Exception ex)
{
Console.WriteLine(" AddMonitoredItem Exception" + ex.Message);
return false;
}
return true;
}
public void RegisterMontioredItemEventHandler(monitoredItemNotification eventHandler)
{
m_MonitoredEventHandler = eventHandler;
}
public void UnRegisterMontioredItemEventHandler(monitoredItemNotification eventHandler)
{
m_MonitoredEventHandler = null;
}
public void monitoredItem_Notification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e)
{
List monitoredItems = new List();
List monitoredValues = new List();
MonitoredItemNotification notification = e.NotificationValue as MonitoredItemNotification;
IList list = monitoredItem.DequeueValues();
DataValue data = list[0];
monitoredItems.Add(monitoredItem.DisplayName.ToString());
monitoredValues.Add(data.Value);
m_MonitoredEventHandler(monitoredItems, monitoredValues);
}
public bool RemoveMonitoredItems(string sSubscriptionName, List NodeIdList)
{
Subscription subscription = null;
if (m_subscriptionMap.ContainsKey(sSubscriptionName))
subscription = m_subscriptionMap[sSubscriptionName];
for (int count = 0; count < NodeIdList.Count(); count++)
{
foreach (MonitoredItem item in subscription.MonitoredItems)
{
if (NodeIdList[count] == item.StartNodeId)
{
Subscription removeSubscription = item.Subscription;
item.Subscription.RemoveItem(item);
removeSubscription.ApplyChanges();
}
}
}
return true;
}
public bool RemoveAllMonitoredItems(string sSubscriptionName)
{
Subscription subscription = null;
if (m_subscriptionMap.ContainsKey(sSubscriptionName))
subscription = m_subscriptionMap[sSubscriptionName];
foreach (MonitoredItem item in subscription.MonitoredItems)
{
MonitoredItem monitoredItem = item as MonitoredItem;
if (monitoredItem != null)
{
Subscription removeSubscription = monitoredItem.Subscription;
monitoredItem.Subscription.RemoveItem(monitoredItem);
removeSubscription.ApplyChanges();
}
}
return true;
}
public static bool Contains(Subscription subscription, MonitoredItem monitoredItem)
{
foreach (MonitoredItem item in subscription.MonitoredItems)
{
if (item.StartNodeId == monitoredItem.StartNodeId)
{
return true;
}
}
return false;
}
}
}