using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Net; using System.Text; using System.Threading.Tasks; using Opc.Ua; using Opc.Ua.Client; using Siemens.OpcUA; using Subscription = Opc.Ua.Client.Subscription; namespace IMCS_CCS.Utils.DeviceProtocol { public class OpcUaClient : AProtocolBase { public OpcUaClient(ushort index) { mServer = new Server(); namespaceIndex = index; mServer.CertificateEvent += m_Server_CertificateEvent; mServer.serverMessage += m_Server_serverMessage; } public override void ConnectAsync() { try { var task = Task.Run(() => { if (string.IsNullOrEmpty(UserName) || string.IsNullOrEmpty(UserPassword)) mServer.Connect(IpEndPort); else mServer.Connect(IpEndPort, UserName, UserPassword); }); IsConnected = task.Wait(5000); } catch (Exception ex) { IsConnected = false; } finally { if (IsConnected) { mSession = mServer.Session; StartAlarmMonitor(); } else mSession = null; } } public override void CloseConnect() { try { if (mAlarmMonitorItem == null) { mServer?.Disconnect(); mSession = this.mServer?.Session; IsConnected = false; return; } this.mAlarmSubscription?.RemoveItem(this.mAlarmMonitorItem); this.mAlarmSubscription?.Delete(true); mAlarmSubscription?.Dispose(); this.mAlarmSubscription = (Subscription)null; this.mAlarmMonitorItem = (MonitoredItem)null; mFilter = null; this.eventMonitorStart = false; mServer?.Disconnect(); mSession = this.mServer?.Session; IsConnected = false; } catch (Exception ex) { IsConnected = false; } } public override object ReadData(int dataType, object dataParameter) { try { List resultList = new List(); var dataAddress = dataParameter as List; NodeIdCollection nodesToRead = new NodeIdCollection(); if (dataAddress != null) foreach (var item in dataAddress) { var nodeId = new NodeId(item, namespaceIndex); nodesToRead.Add(nodeId); } mServer.ReadValues(nodesToRead, out var results); if (results.Any()) { foreach (var value in results) { if (typeof(int[]) == value.Value.GetType()) { resultList.Add(((int[])(value.Value))[1]); continue; } if (typeof(double[]) == value.Value.GetType()) { resultList.Add(((double[])value.Value)[0]); continue; } if (typeof(UInt16[]) == value.Value.GetType()) { resultList.Add(value.Value); continue; } resultList.Add(value?.Value); } } return resultList; } catch (Exception ex) { CloseConnect(); return null; } } public override bool WriteData(object obj) { return false; } private string ReadFilesData(string valueStr) { string ncFileStream = ""; if (mServer == null) return ncFileStream; try { DiagnosticInfoCollection diagnosticInfos = (DiagnosticInfoCollection)null; CallMethodRequestCollection methodsToCall = new CallMethodRequestCollection(); CallMethodResultCollection results = new CallMethodResultCollection(); CallMethodRequest callMethodRequest = new CallMethodRequest(); callMethodRequest.MethodId = new NodeId("/Methods/CopyFileFromServer", 2); callMethodRequest.ObjectId = new NodeId("/Methods", 2); callMethodRequest.InputArguments.Add((Opc.Ua.Variant)valueStr); methodsToCall.Add(callMethodRequest); RequestHeader requestHeader = new RequestHeader(); mServer.Session.Call((RequestHeader)null, methodsToCall, out results, out diagnosticInfos); if (results.Count > 0) ncFileStream = Encoding.Default.GetString((byte[])results[0].OutputArguments[0].Value); return ncFileStream; } catch (Exception ex) { CloseConnect(); return ncFileStream; } } #region Alarm Event private bool eventMonitorStart = false; private Subscription mAlarmSubscription; private Session mSession; private FilterDefinition mFilter; private MonitoredItem mAlarmMonitorItem; public override event MonitoredItemNotificationEventHandler OpcUaAlarmNotificationHandle; private void StartAlarmMonitor() { if (!this.eventMonitorStart) { try { if (this.mAlarmSubscription == null) { this.mAlarmSubscription = new Subscription { DisplayName = "AlarmSubscription", PublishingInterval = 1000, KeepAliveCount = 10U, LifetimeCount = 100U, MaxNotificationsPerPublish = 1000U, PublishingEnabled = true, TimestampsToReturn = TimestampsToReturn.Server }; this.mSession?.AddSubscription(this.mAlarmSubscription); this.mFilter = new FilterDefinition { AreaId = new NodeId("Sinumerik", (ushort)2), Severity = EventSeverity.Min, IgnoreSuppressedOrShelved = true, EventTypes = (IList)new NodeId[1] { ObjectTypeIds.ConditionType } }; this.mFilter.SelectClauses = this.mFilter.ConstructSelectClauses(this.mSession, ObjectTypeIds.ConditionType); } if (!mAlarmSubscription.Created) this.mAlarmSubscription.Create(); this.mAlarmMonitorItem = this.mFilter.CreateMonitoredItem(this.mSession); this.mAlarmMonitorItem.DisplayName = "AlarmMonitorItem"; this.mAlarmMonitorItem.Notification += new MonitoredItemNotificationEventHandler(this.Notification_MonitoredAlarm); this.mAlarmSubscription?.AddItem(this.mAlarmMonitorItem); this.mAlarmSubscription?.ApplyChanges(); this.RefreshAlarmCall(); this.eventMonitorStart = true; } catch (Exception ex) { } } } private void RefreshAlarmCall() { CallMethodRequestCollection methodsToCall = new CallMethodRequestCollection(1); CallMethodRequest callMethodRequest = new CallMethodRequest { ObjectId = new NodeId(ObjectTypeIds.ConditionType), MethodId = new NodeId(MethodIds.ConditionType_ConditionRefresh) }; callMethodRequest.InputArguments.Add((Opc.Ua.Variant)this.mAlarmSubscription.Id); methodsToCall.Add(callMethodRequest); this.mSession.Call((RequestHeader)null, methodsToCall, out _, out _); } private void Notification_MonitoredAlarm( MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e) { try { EventFieldList notificationValue = e.NotificationValue as EventFieldList; if (notificationValue == null) return; lock (this) OpcUaAlarmNotificationHandle?.Invoke(monitoredItem, e); this.eventMonitorStart = true; } catch (Exception ex) { } } #endregion #region Props public override bool IsConnected { get; set; } = false; private readonly Server mServer; private readonly ushort namespaceIndex; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } private void m_Server_CertificateEvent( CertificateValidator validator, CertificateValidationEventArgs e) { e.Accept = true; } private void m_Server_serverMessage(string message) { } private void ReleaseUnmanagedResources() { CloseConnect(); // TODO release unmanaged resources here } protected virtual void Dispose(bool disposing) { ReleaseUnmanagedResources(); if (disposing) { } } ~OpcUaClient() { Dispose(false); } #endregion } }