From c9d3eaf30075d2dd97bece5dd88bf049d482d929 Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Thu, 29 Apr 2021 17:10:43 +0200 Subject: [PATCH] Update gestione IOB-WIN x start OpcUa method --- .../ConsoleReferenceClient/Program.cs | 35 +- .../ConsoleReferenceClient/UAClient.cs | 110 ++- .../ConsoleReferenceClient/UAClient.cs.bak | 670 ++++++++++++++++++ IOB-UT/ToMapo.cs | 4 +- IOB-WIN-NEXT/IOB-WIN-NEXT.csproj | 3 + IOB-WIN-NEXT/IobOpcUa.cs | 103 ++- IOB-WIN-NEXT/UAClient.cs | 9 +- IOB-WIN-NEXT/UAClient.cs.bak | 643 +++++++++++++++++ IOB-WIN-NEXT/packages.config | 1 + 9 files changed, 1475 insertions(+), 103 deletions(-) create mode 100644 IOB-OPC-UA/Applications/ConsoleReferenceClient/UAClient.cs.bak create mode 100644 IOB-WIN-NEXT/UAClient.cs.bak diff --git a/IOB-OPC-UA/Applications/ConsoleReferenceClient/Program.cs b/IOB-OPC-UA/Applications/ConsoleReferenceClient/Program.cs index 759e1695..7bb08cd0 100644 --- a/IOB-OPC-UA/Applications/ConsoleReferenceClient/Program.cs +++ b/IOB-OPC-UA/Applications/ConsoleReferenceClient/Program.cs @@ -28,6 +28,7 @@ * ======================================================================*/ using System; +using System.Collections.Generic; using System.Threading.Tasks; using Opc.Ua; using Opc.Ua.Configuration; @@ -36,6 +37,15 @@ namespace Quickstarts.ConsoleReferenceClient { public static class Program { + #region Private Fields + + /// + /// Elenco degli items da monitorare come risultato del browse iniziale + /// + private static Dictionary selectedItemList = new Dictionary(); + + #endregion Private Fields + #region Public Methods public static async Task Main(string[] args) @@ -73,10 +83,29 @@ namespace Quickstarts.ConsoleReferenceClient // Run tests for available methods. uaClient.ReadNodes(); uaClient.WriteNodes(); - uaClient.Browse(); - //uaClient.CallMethod(); - uaClient.SubscribeToDataChanges(); + console.WriteLine("Please enter NodeId Value (enter for next option) (ex: ns=4,i=5001)"); + console.WriteLine("Please enter INT Value (ex: 5001 --> i=5001)"); + string valIn01 = Console.ReadLine(); + console.WriteLine("Please enter Namespace index (ex: 4 --> ns=4)"); + string valIn02 = Console.ReadLine(); + uint iValue = 5001; + ushort nsVal = 4; + if (!string.IsNullOrEmpty(valIn01)) + { + uint.TryParse(valIn01, out iValue); + } + if (!string.IsNullOrEmpty(valIn02)) + { + ushort.TryParse(valIn02, out nsVal); + } + selectedItemList = uaClient.Browse(nsVal, iValue); + console.WriteLine("Press ENTER to continue..."); + Console.ReadLine(); + + //uaClient.CallMethod(); + List subscribedItems = uaClient.SubscribeToDataChanges(selectedItemList); + // Wait for some DataChange notifications from MonitoredItems await Task.Delay(20_000 * 3 * 15); diff --git a/IOB-OPC-UA/Applications/ConsoleReferenceClient/UAClient.cs b/IOB-OPC-UA/Applications/ConsoleReferenceClient/UAClient.cs index cbef3e62..72e09fa2 100644 --- a/IOB-OPC-UA/Applications/ConsoleReferenceClient/UAClient.cs +++ b/IOB-OPC-UA/Applications/ConsoleReferenceClient/UAClient.cs @@ -31,11 +31,66 @@ using System; using System.Collections; using System.Collections.Generic; using System.Threading.Tasks; +using System.Collections; using Opc.Ua; using Opc.Ua.Client; namespace Quickstarts.ConsoleReferenceClient { + /// + /// Evento per incapsulare dati x refresh pagina + /// + public class opcUaMonitItemChange : EventArgs + { + #region Private Fields + + /// + /// Monitored Item da notificare + /// + private readonly MonitoredItem _monitoredItem; + + /// + /// Valore notifica + /// + private readonly MonitoredItemNotification _notification; + + #endregion Private Fields + + #region Public Constructors + + /// + /// salvataggio obj + /// + /// + public opcUaMonitItemChange(MonitoredItem monitoredItem, MonitoredItemNotification notification) + { + _monitoredItem = monitoredItem; + _notification = notification; + } + + #endregion Public Constructors + + #region Public Properties + + /// + /// Proprietà lettura del MonitoredItem + /// + public MonitoredItem CurrMonitoredItem + { + get { return _monitoredItem; } + } + + /// + /// Proprietà lettura della notifica + /// + public MonitoredItemNotification CurrNotify + { + get { return _notification; } + } + + #endregion Public Properties + } + /// /// OPC UA Client with examples of basic functionality. /// @@ -53,12 +108,6 @@ namespace Quickstarts.ConsoleReferenceClient #endregion Private Fields - #region Protected Fields - - protected Dictionary DataList = new Dictionary(); - - #endregion Protected Fields - #region Public Constructors /// @@ -74,6 +123,15 @@ namespace Quickstarts.ConsoleReferenceClient #endregion Public Constructors + #region Public Events + + /// + /// Evento notifica variazione MonitoredItem + /// + public event EventHandler eh_MonItChange; + + #endregion Public Events + #region Public Properties /// @@ -128,6 +186,12 @@ namespace Quickstarts.ConsoleReferenceClient { // Log MonitoredItem Notification event MonitoredItemNotification notification = e.NotificationValue as MonitoredItemNotification; + + // sollevo evento notifica vaziazione MonitoredItem + if (eh_MonItChange != null) + { + eh_MonItChange(this, new opcUaMonitItemChange(monitoredItem, notification)); + } m_output.WriteLine("Notification Received for Variable \"{0}\" and Value = {1}.", monitoredItem.DisplayName, notification.Value); } catch (Exception ex) @@ -143,12 +207,13 @@ namespace Quickstarts.ConsoleReferenceClient /// /// Browse Server nodes /// - public void Browse() + public Dictionary Browse(ushort startNodeNS, uint startNodeVal) { + Dictionary nodeIdNameList = new Dictionary(); if (m_session == null || m_session.Connected == false) { m_output.WriteLine("Session not connected!"); - return; + return nodeIdNameList; } try @@ -161,25 +226,9 @@ namespace Quickstarts.ConsoleReferenceClient browser.NodeClassMask = (int)NodeClass.Object | (int)NodeClass.Variable; browser.ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences; - NodeId nodeToBrowse = ObjectIds.Server; + //NodeId nodeToBrowse = ObjectIds.Server; //NodeId nodeToBrowse = new NodeId("ns=4,i=5001"); - - m_output.WriteLine("Please enter NodeId Value (enter for next option) (ex: ns=4,i=5001)"); - m_output.WriteLine("Please enter INT Value (ex: 5001 --> i=5001)"); - string valIn01 = Console.ReadLine(); - m_output.WriteLine("Please enter Namespace index (ex: 4 --> ns=4)"); - string valIn02 = Console.ReadLine(); - uint iValue = 5001; - ushort nsVal = 4; - if (!string.IsNullOrEmpty(valIn01)) - { - uint.TryParse(valIn01, out iValue); - } - if (!string.IsNullOrEmpty(valIn02)) - { - ushort.TryParse(valIn02, out nsVal); - } - nodeToBrowse = new NodeId(iValue, nsVal); + NodeId nodeToBrowse = new NodeId(startNodeVal, startNodeNS); // Call Browse service m_output.WriteLine("Browsing {0} node...", nodeToBrowse); @@ -191,17 +240,16 @@ namespace Quickstarts.ConsoleReferenceClient foreach (ReferenceDescription result in browseResults) { m_output.WriteLine($" NodeId = {result.NodeId}, DisplayName = {result.DisplayName.Text}, NodeClass = {result.NodeClass}, Others: {result.BinaryEncodingId} | {result.BrowseName}"); - DataList.Add(result.NodeId.ToString(), result.DisplayName.Text); + nodeIdNameList.Add(result.NodeId.ToString(), result.DisplayName.Text); } - - m_output.WriteLine("Press ENTER to continue..."); - Console.ReadLine(); } catch (Exception ex) { // Log Error m_output.WriteLine($"Browse Error : {ex.Message}."); } + + return nodeIdNameList; } /// @@ -399,7 +447,7 @@ namespace Quickstarts.ConsoleReferenceClient /// /// Create Subscription and MonitoredItems for DataChanges /// - public List SubscribeToDataChanges() + public List SubscribeToDataChanges(Dictionary DataList) { List monItList = new List(); if (m_session == null || m_session.Connected == false) diff --git a/IOB-OPC-UA/Applications/ConsoleReferenceClient/UAClient.cs.bak b/IOB-OPC-UA/Applications/ConsoleReferenceClient/UAClient.cs.bak new file mode 100644 index 00000000..11cd47d7 --- /dev/null +++ b/IOB-OPC-UA/Applications/ConsoleReferenceClient/UAClient.cs.bak @@ -0,0 +1,670 @@ +/* ======================================================================== + * Copyright (c) 2005-2020 The OPC Foundation, Inc. All rights reserved. + * + * OPC Foundation MIT License 1.00 + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * The complete license agreement can be found here: + * http://opcfoundation.org/License/MIT/1.00/ + * ======================================================================*/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Threading.Tasks; +using Opc.Ua; +using Opc.Ua.Client; + +namespace Quickstarts.ConsoleReferenceClient +{ + /// + /// Evento per incapsulare dati x refresh pagina + /// + public class opcUaMonitItemChange : EventArgs + { + #region Private Fields + + /// + /// Monitored Item da notificare + /// + private readonly MonitoredItem _monitoredItem; + + /// + /// Valore notifica + /// + private readonly MonitoredItemNotification _notification; + + #endregion Private Fields + + #region Public Constructors + + /// + /// salvataggio obj + /// + /// + public opcUaMonitItemChange(MonitoredItem monitoredItem, MonitoredItemNotification notification) + { + _monitoredItem = monitoredItem; + _notification = notification; + } + + #endregion Public Constructors + + #region Public Properties + + /// + /// Proprietà lettura del MonitoredItem + /// + public MonitoredItem CurrMonitoredItem + { + get { return _monitoredItem; } + } + + /// + /// Proprietà lettura della notifica + /// + public MonitoredItemNotification CurrNotify + { + get { return _notification; } + } + + #endregion Public Properties + } + + /// + /// OPC UA Client with examples of basic functionality. + /// + internal class UAClient + { + #region Private Fields + + private readonly IOutput m_output; + + private readonly Action m_validateResponse; + + private ApplicationConfiguration m_configuration; + + private Session m_session; + + #endregion Private Fields + + #region Public Constructors + + /// + /// Initializes a new instance of the UAClient class. + /// + public UAClient(ApplicationConfiguration configuration, IOutput output, Action validateResponse) + { + m_validateResponse = validateResponse; + m_output = output; + m_configuration = configuration; + m_configuration.CertificateValidator.CertificateValidation += CertificateValidation; + } + + #endregion Public Constructors + + #region Public Events + + /// + /// Evento notifica variazione MonitoredItem + /// + public event EventHandler eh_MonItChange; + + #endregion Public Events + + #region Public Properties + + /// + /// Gets or sets the server URL. + /// + public string ServerUrl { get; set; } = "opc.tcp://localhost:62541/Quickstarts/ReferenceServer"; + + /// + /// Gets the client session. + /// + public Session Session => m_session; + + #endregion Public Properties + + #region Private Methods + + /// + /// Handles the certificate validation event. + /// This event is triggered every time an untrusted certificate is received from the server. + /// + private void CertificateValidation(CertificateValidator sender, CertificateValidationEventArgs e) + { + bool certificateAccepted = true; + + // **** + // Implement a custom logic to decide if the certificate should be + // accepted or not and set certificateAccepted flag accordingly. + // The certificate can be retrieved from the e.Certificate field + // *** + + ServiceResult error = e.Error; + while (error != null) + { + m_output.WriteLine(error); + error = error.InnerResult; + } + + if (certificateAccepted) + { + m_output.WriteLine("Untrusted Certificate accepted. SubjectName = {0}", e.Certificate.SubjectName); + } + + e.AcceptAll = certificateAccepted; + } + + /// + /// Handle DataChange notifications from Server + /// + private void OnMonitoredItemNotification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e) + { + try + { + // Log MonitoredItem Notification event + MonitoredItemNotification notification = e.NotificationValue as MonitoredItemNotification; + + // sollevo evento notifica vaziazione MonitoredItem + if (eh_MonItChange != null) + { + eh_MonItChange(this, new opcUaMonitItemChange(monitoredItem, notification)); + } + m_output.WriteLine("Notification Received for Variable \"{0}\" and Value = {1}.", monitoredItem.DisplayName, notification.Value); + } + catch (Exception ex) + { + m_output.WriteLine("OnMonitoredItemNotification error: {0}", ex.Message); + } + } + + #endregion Private Methods + + #region Public Methods + + /// + /// Browse Server nodes + /// + public Dictionary Browse(ushort startNodeNS, uint startNodeVal) + { + Dictionary nodeIdNameList = new Dictionary(); + if (m_session == null || m_session.Connected == false) + { + m_output.WriteLine("Session not connected!"); + return nodeIdNameList; + } + + try + { + // Create a Browser object + Browser browser = new Browser(m_session); + + // Set browse parameters + browser.BrowseDirection = BrowseDirection.Forward; + browser.NodeClassMask = (int)NodeClass.Object | (int)NodeClass.Variable; + browser.ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences; + + //NodeId nodeToBrowse = ObjectIds.Server; + //NodeId nodeToBrowse = new NodeId("ns=4,i=5001"); + NodeId nodeToBrowse = new NodeId(startNodeVal, startNodeNS); + + // Call Browse service + m_output.WriteLine("Browsing {0} node...", nodeToBrowse); + ReferenceDescriptionCollection browseResults = browser.Browse(nodeToBrowse); + + // Display the results + m_output.WriteLine("Browse returned {0} results:", browseResults.Count); + + foreach (ReferenceDescription result in browseResults) + { + m_output.WriteLine($" NodeId = {result.NodeId}, DisplayName = {result.DisplayName.Text}, NodeClass = {result.NodeClass}, Others: {result.BinaryEncodingId} | {result.BrowseName}"); + nodeIdNameList.Add(result.NodeId.ToString(), result.DisplayName.Text); + } + } + catch (Exception ex) + { + // Log Error + m_output.WriteLine($"Browse Error : {ex.Message}."); + } + + return nodeIdNameList; + } + + /// + /// Call UA method + /// + public void CallMethod() + { + if (m_session == null || m_session.Connected == false) + { + m_output.WriteLine("Session not connected!"); + return; + } + + try + { + // Define the UA Method to call + // Parent node - Objects\CTT\Methods + // Method node - Objects\CTT\Methods\Add + NodeId objectId = new NodeId("ns=2;s=Methods"); + NodeId methodId = new NodeId("ns=2;s=Methods_Add"); + + // Define the method parameters + // Input argument requires a Float and an UInt32 value + object[] inputArguments = new object[] { (float)10.5, (uint)10 }; + IList outputArguments = null; + + // Invoke Call service + m_output.WriteLine("Calling UAMethod for node {0} ...", methodId); + outputArguments = m_session.Call(objectId, methodId, inputArguments); + + // Display results + m_output.WriteLine("Method call returned {0} output argument(s):", outputArguments.Count); + + foreach (var outputArgument in outputArguments) + { + m_output.WriteLine(" OutputValue = {0}", outputArgument.ToString()); + } + } + catch (Exception ex) + { + m_output.WriteLine("Method call error: {0}", ex.Message); + } + } + + /// + /// Creates a session with the UA server + /// + public async Task ConnectAsync() + { + try + { + if (m_session != null && m_session.Connected == true) + { + m_output.WriteLine("Session already connected!"); + } + else + { + m_output.WriteLine("Connecting..."); + + // Get the endpoint by connecting to server's discovery endpoint. + // Try to find the first endopint without security. + EndpointDescription endpointDescription = CoreClientUtils.SelectEndpoint(ServerUrl, false); + + EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(m_configuration); + ConfiguredEndpoint endpoint = new ConfiguredEndpoint(null, endpointDescription, endpointConfiguration); + + // Create the session + Session session = await Session.Create( + m_configuration, + endpoint, + false, + false, + m_configuration.ApplicationName, + 30 * 60 * 1000, + new UserIdentity(), + null + ); + + // Assign the created session + if (session != null && session.Connected) + { + m_session = session; + } + + // Session created successfully. + m_output.WriteLine($"New Session Created with SessionName = {m_session.SessionName}"); + } + + return true; + } + catch (Exception ex) + { + // Log Error + m_output.WriteLine($"Create Session Error : {ex.Message}"); + return false; + } + } + + /// + /// Disconnects the session. + /// + public void Disconnect() + { + try + { + if (m_session != null) + { + m_output.WriteLine("Disconnecting..."); + + m_session.Close(); + m_session.Dispose(); + m_session = null; + + // Log Session Disconnected event + m_output.WriteLine("Session Disconnected."); + } + else + { + m_output.WriteLine("Session not created!"); + } + } + catch (Exception ex) + { + // Log Error + m_output.WriteLine($"Disconnect Error : {ex.Message}"); + } + } + + /// + /// Read a list of nodes from Server + /// + public void ReadNodes() + { + if (m_session == null || m_session.Connected == false) + { + m_output.WriteLine("Session not connected!"); + return; + } + + try + { + #region Read a node by calling the Read Service + + // build a list of nodes to be read + ReadValueIdCollection nodesToRead = new ReadValueIdCollection() + { + // Value of ServerStatus + new ReadValueId() { NodeId = Variables.Server_ServerStatus, AttributeId = Attributes.Value }, + // BrowseName of ServerStatus_StartTime + new ReadValueId() { NodeId = Variables.Server_ServerStatus_StartTime, AttributeId = Attributes.BrowseName }, + // Value of ServerStatus_StartTime + new ReadValueId() { NodeId = Variables.Server_ServerStatus_StartTime, AttributeId = Attributes.Value } + }; + + // Read the node attributes + m_output.WriteLine("Reading nodes..."); + + // Call Read Service + m_session.Read( + null, + 0, + TimestampsToReturn.Both, + nodesToRead, + out DataValueCollection resultsValues, + out DiagnosticInfoCollection diagnosticInfos); + + // Validate the results + m_validateResponse(resultsValues, nodesToRead); + + // Display the results. + foreach (DataValue result in resultsValues) + { + m_output.WriteLine("Read Value = {0} , StatusCode = {1}", result.Value, result.StatusCode); + } + + #endregion Read a node by calling the Read Service + + #region Read the Value attribute of a node by calling the Session.ReadValue method + + // Read Server NamespaceArray + m_output.WriteLine("Reading Value of NamespaceArray node..."); + DataValue namespaceArray = m_session.ReadValue(Variables.Server_NamespaceArray); + // Display the result + m_output.WriteLine($"NamespaceArray Value = {namespaceArray}"); + + #endregion Read the Value attribute of a node by calling the Session.ReadValue method + } + catch (Exception ex) + { + // Log Error + m_output.WriteLine($"Read Nodes Error : {ex.Message}."); + } + } + + /// + /// Create Subscription and MonitoredItems for DataChanges + /// + public List SubscribeToDataChanges(Dictionary DataList) + { + List monItList = new List(); + if (m_session == null || m_session.Connected == false) + { + m_output.WriteLine("Session not connected!"); + return monItList; + } + + try + { + // Create a subscription for receiving data change notifications + + // Define Subscription parameters + Subscription subscription = new Subscription(m_session.DefaultSubscription); + + subscription.DisplayName = "Steamware Console Subscription"; + subscription.PublishingEnabled = true; + subscription.PublishingInterval = 1000; + + m_session.AddSubscription(subscription); + + // Create the subscription on Server side + subscription.Create(); + m_output.WriteLine("New Subscription created with SubscriptionId = {0}.", subscription.Id); + + // Create MonitoredItems for data changes + foreach (var item in DataList) + { + MonitoredItem currMonIt = new MonitoredItem(subscription.DefaultItem); + // Int32 Node - Objects\CTT\Scalar\Simulation\Int32 + currMonIt.StartNodeId = new NodeId(item.Key); + currMonIt.AttributeId = Attributes.Value; + currMonIt.DisplayName = item.Value; + currMonIt.SamplingInterval = 1000; + currMonIt.Notification += OnMonitoredItemNotification; + subscription.AddItem(currMonIt); + monItList.Add(currMonIt); + } + +#if false + MonitoredItem IO_120_00_MonitoredItem = new MonitoredItem(subscription.DefaultItem); + // Int32 Node - Objects\CTT\Scalar\Simulation\Int32 + IO_120_00_MonitoredItem.StartNodeId = new NodeId("ns=4;s=IO_120.00"); + IO_120_00_MonitoredItem.AttributeId = Attributes.Value; + IO_120_00_MonitoredItem.DisplayName = "IO_120 Variable"; + IO_120_00_MonitoredItem.SamplingInterval = 1000; + IO_120_00_MonitoredItem.Notification += OnMonitoredItemNotification; + subscription.AddItem(IO_120_00_MonitoredItem); + + MonitoredItem IO_120_01_MonitoredItem = new MonitoredItem(subscription.DefaultItem); + // Int32 Node - Objects\CTT\Scalar\Simulation\Int32 + IO_120_01_MonitoredItem.StartNodeId = new NodeId("ns=4;s=IO_120.01"); + IO_120_01_MonitoredItem.AttributeId = Attributes.Value; + IO_120_01_MonitoredItem.DisplayName = "IO_120_01 Variable"; + IO_120_01_MonitoredItem.SamplingInterval = 1000; + IO_120_01_MonitoredItem.Notification += OnMonitoredItemNotification; + subscription.AddItem(IO_120_01_MonitoredItem); + + MonitoredItem IO_130_MonitoredItem = new MonitoredItem(subscription.DefaultItem); + // Int32 Node - Objects\CTT\Scalar\Simulation\Int32 + IO_130_MonitoredItem.StartNodeId = new NodeId("ns=4;s=IO_130"); + IO_130_MonitoredItem.AttributeId = Attributes.Value; + IO_130_MonitoredItem.DisplayName = "IO_130 Variable"; + IO_130_MonitoredItem.SamplingInterval = 1000; + IO_130_MonitoredItem.Notification += OnMonitoredItemNotification; + subscription.AddItem(IO_130_MonitoredItem); + + MonitoredItem IO_135_MonitoredItem = new MonitoredItem(subscription.DefaultItem); + // Int32 Node - Objects\CTT\Scalar\Simulation\Int32 + IO_135_MonitoredItem.StartNodeId = new NodeId("ns=4;s=IO_135"); + IO_135_MonitoredItem.AttributeId = Attributes.Value; + IO_135_MonitoredItem.DisplayName = "IO_135 Variable"; + IO_135_MonitoredItem.SamplingInterval = 1000; + IO_135_MonitoredItem.Notification += OnMonitoredItemNotification; + subscription.AddItem(IO_135_MonitoredItem); + + MonitoredItem IO_140_MonitoredItem = new MonitoredItem(subscription.DefaultItem); + // Int32 Node - Objects\CTT\Scalar\Simulation\Int32 + IO_140_MonitoredItem.StartNodeId = new NodeId("ns=4;s=IO_140"); + IO_140_MonitoredItem.AttributeId = Attributes.Value; + IO_140_MonitoredItem.DisplayName = "IO_140 Variable"; + IO_140_MonitoredItem.SamplingInterval = 1000; + IO_140_MonitoredItem.Notification += OnMonitoredItemNotification; + subscription.AddItem(IO_140_MonitoredItem); + + //MonitoredItem intMonitoredItem = new MonitoredItem(subscription.DefaultItem); + //// Int32 Node - Objects\CTT\Scalar\Simulation\Int32 + //intMonitoredItem.StartNodeId = new NodeId("ns=2;s=Scalar_Simulation_Int32"); + //intMonitoredItem.AttributeId = Attributes.Value; + //intMonitoredItem.DisplayName = "Int32 Variable"; + //intMonitoredItem.SamplingInterval = 1000; + //intMonitoredItem.Notification += OnMonitoredItemNotification; + + //subscription.AddItem(intMonitoredItem); + + //MonitoredItem floatMonitoredItem = new MonitoredItem(subscription.DefaultItem); + //// Float Node - Objects\CTT\Scalar\Simulation\Float + //floatMonitoredItem.StartNodeId = new NodeId("ns=2;s=Scalar_Simulation_Float"); + //floatMonitoredItem.AttributeId = Attributes.Value; + //floatMonitoredItem.DisplayName = "Float Variable"; + //floatMonitoredItem.SamplingInterval = 1000; + //floatMonitoredItem.Notification += OnMonitoredItemNotification; + + //subscription.AddItem(floatMonitoredItem); + + //MonitoredItem stringMonitoredItem = new MonitoredItem(subscription.DefaultItem); + //// String Node - Objects\CTT\Scalar\Simulation\String + //stringMonitoredItem.StartNodeId = new NodeId("ns=2;s=Scalar_Simulation_String"); + //stringMonitoredItem.AttributeId = Attributes.Value; + //stringMonitoredItem.DisplayName = "String Variable"; + //stringMonitoredItem.SamplingInterval = 1000; + //stringMonitoredItem.Notification += OnMonitoredItemNotification; + + //subscription.AddItem(stringMonitoredItem); +#endif + + // Create the monitored items on Server side + subscription.ApplyChanges(); + m_output.WriteLine("MonitoredItems created for SubscriptionId = {0}.", subscription.Id); + } + catch (Exception ex) + { + m_output.WriteLine("Subscribe error: {0}", ex.Message); + } + return monItList; + } + + /// + /// Write a list of nodes to the Server + /// + public void WriteNodes() + { + if (m_session == null || m_session.Connected == false) + { + m_output.WriteLine("Session not connected!"); + return; + } + + try + { + // Write the configured nodes + WriteValueCollection nodesToWrite = new WriteValueCollection(); + + // Int32 Node - Objects\CTT\Scalar\Scalar_Static\Int32 + WriteValue commWriteVal = new WriteValue(); + commWriteVal.NodeId = new NodeId("ns=4;s=IO_151"); + commWriteVal.AttributeId = Attributes.Value; + commWriteVal.Value = new DataValue(); + commWriteVal.Value.Value = (int)111; + nodesToWrite.Add(commWriteVal); + + WriteValue artWriteVal = new WriteValue(); + artWriteVal.NodeId = new NodeId("ns=4;s=IO_151"); + artWriteVal.AttributeId = Attributes.Value; + artWriteVal.Value = new DataValue(); + artWriteVal.Value.Value = (int)222; + nodesToWrite.Add(artWriteVal); + + WriteValue qtyWriteVal = new WriteValue(); + qtyWriteVal.NodeId = new NodeId("ns=4;s=IO_153"); + qtyWriteVal.AttributeId = Attributes.Value; + qtyWriteVal.Value = new DataValue(); + qtyWriteVal.Value.Value = (int)333; + nodesToWrite.Add(qtyWriteVal); + + //// Int32 Node - Objects\CTT\Scalar\Scalar_Static\Int32 + //WriteValue intWriteVal = new WriteValue(); + //intWriteVal.NodeId = new NodeId("ns=2;s=Scalar_Static_Int32"); + //intWriteVal.AttributeId = Attributes.Value; + //intWriteVal.Value = new DataValue(); + //intWriteVal.Value.Value = (int)100; + //nodesToWrite.Add(intWriteVal); + + //// Float Node - Objects\CTT\Scalar\Scalar_Static\Float + //WriteValue floatWriteVal = new WriteValue(); + //floatWriteVal.NodeId = new NodeId("ns=2;s=Scalar_Static_Float"); + //floatWriteVal.AttributeId = Attributes.Value; + //floatWriteVal.Value = new DataValue(); + //floatWriteVal.Value.Value = (float)100.5; + //nodesToWrite.Add(floatWriteVal); + + //// String Node - Objects\CTT\Scalar\Scalar_Static\String + //WriteValue stringWriteVal = new WriteValue(); + //stringWriteVal.NodeId = new NodeId("ns=2;s=Scalar_Static_String"); + //stringWriteVal.AttributeId = Attributes.Value; + //stringWriteVal.Value = new DataValue(); + //stringWriteVal.Value.Value = "String Test"; + //nodesToWrite.Add(stringWriteVal); + + // Write the node attributes + StatusCodeCollection results = null; + DiagnosticInfoCollection diagnosticInfos; + m_output.WriteLine("Writing nodes..."); + + // Call Write Service + m_session.Write(null, + nodesToWrite, + out results, + out diagnosticInfos); + + // Validate the response + m_validateResponse(results, nodesToWrite); + + // Display the results. + m_output.WriteLine("Write Results :"); + + foreach (StatusCode writeResult in results) + { + m_output.WriteLine(" {0}", writeResult); + } + } + catch (Exception ex) + { + // Log Error + m_output.WriteLine($"Write Nodes Error : {ex.Message}."); + } + } + + #endregion Public Methods + } +} diff --git a/IOB-UT/ToMapo.cs b/IOB-UT/ToMapo.cs index 7f1d528e..e6932345 100644 --- a/IOB-UT/ToMapo.cs +++ b/IOB-UT/ToMapo.cs @@ -114,12 +114,12 @@ namespace IOB_UT /// /// Indice NS da cui fare il browse dei file /// - public uint BrowseNSIndex { get; set; } = 4; + public ushort BrowseNSIndex { get; set; } = 4; /// /// ID del nodo da cui partire x il browse di identificazione nodi iniziale /// - public ushort BrowseValue { get; set; } = 5001; + public uint BrowseValue { get; set; } = 5001; /// /// Struttura dati x check condizione Errore diff --git a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj index 686eeb39..de57b759 100644 --- a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj +++ b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj @@ -118,6 +118,9 @@ ..\packages\OPCFoundation.NetStandard.Opc.Ua.Client.1.4.365.48\lib\net462\Opc.Ua.Client.dll + + ..\packages\OPCFoundation.NetStandard.Opc.Ua.Configuration.1.4.365.48\lib\net462\Opc.Ua.Configuration.dll + ..\packages\OPCFoundation.NetStandard.Opc.Ua.Core.1.4.365.48\lib\net462\Opc.Ua.Core.dll diff --git a/IOB-WIN-NEXT/IobOpcUa.cs b/IOB-WIN-NEXT/IobOpcUa.cs index 5641d762..1ea27ecd 100644 --- a/IOB-WIN-NEXT/IobOpcUa.cs +++ b/IOB-WIN-NEXT/IobOpcUa.cs @@ -98,22 +98,6 @@ namespace IOB_WIN_NEXT // leggo il file... loadOpcUaConf(jsonFileName); } - - // !!!FARE FIXME TODO Spostare DOPO connect - - // faccio un primo browse dei dati... - selectedItemList = UA_ref.Browse(opcUaParams.BrowseNSIndex, opcUaParams.BrowseValue); - // sottoscrivo a rilevazione cambio dati - List subscribedItems = UA_ref.SubscribeToDataChanges(selectedItemList); - // aggiungo come DataItems - int dSamplePeriod = 0; - int threshDBand = 0; - string uuid = ""; - foreach (var item in subscribedItems) - { - OpcUaDataItemExt newItem = formatDataItem(ref dSamplePeriod, ref threshDBand, ref uuid, item); - dataItemMem.Add(uuid, newItem); - } } #endregion Public Constructors @@ -437,55 +421,54 @@ namespace IOB_WIN_NEXT /// Vera connessione ad MTC /// /// - private short doConnect() + private async Task doConnect() { + IOutput console = new ConsoleOutput(); short esitoLink = 0; // reset memoria dataItem.. - dataItemMem = new Dictionary(); + dataItemMem = new Dictionary(); // predisposizione conf oggetto di comunicazione MTC short port = 5000; short.TryParse(cIobConf.cncPort, out port); - // test probe! - try - { - var probe = new Probe($"http://{cIobConf.cncIpAddr}:{port}").Execute(); - // se valido loggo! - if (probe != null) - { - lgInfo($"Effettuata correttamente PROBE per device MTC all'URL {probe.Url} | vers: {probe.Version} | send: {probe.Header.Sender}"); - lgInfo($"---------------- Elenco Devices ----------------"); - // loggo devices principali... - logDevicesList(probe.Devices); - } - } - catch (Exception exc) - { - lgError($"Eccezione durante test probe:{Environment.NewLine}{exc}"); - } - // attendo 1 sec... - Thread.Sleep(1000); // ora avvio try { - lgInfo($"Chiamata apertura MTC Client: {cIobConf.cncIpAddr}:{port}"); - UA_ref = new MTConnectClient($"http://{cIobConf.cncIpAddr}:{port}"); + lgInfo("Start init OpcUa Client"); + // Define the UA Client application + ApplicationInstance application = new ApplicationInstance(); + application.ApplicationName = "Steamware IOB-WIN Client"; + application.ApplicationType = ApplicationType.Client; - // gestire init da con + browse e discovery post connessione + // load the application configuration. + await application.LoadApplicationConfiguration("ConsoleReferenceClient.Config.xml", silent: false); + // check the application certificate. + await application.CheckApplicationInstanceCertificate(silent: false, minimumKeySize: 0); - // chiamare --> checkAndSend(e.CurrMonitoredItem, e.CurrNotify, true); + lgInfo($"Chiamata UAClient con configurazione standard: {application.ApplicationConfiguration.ApplicationName}"); + UA_ref = new UAClient(application.ApplicationConfiguration, console, ClientBase.ValidateResponse); - // gestire eventi change + lgInfo($"Chiamata apertura OpcUa Client: {cIobConf.cncIpAddr}:{port}"); + UA_ref.ServerUrl = $"opc.tcp://{cIobConf.cncIpAddr}:{port}"; + bool connected = await UA_ref.ConnectAsync(); + if (connected) + { + // faccio un primo browse dei dati... + selectedItemList = UA_ref.Browse(opcUaParams.BrowseNSIndex, opcUaParams.BrowseValue); + // sottoscrivo a rilevazione cambio dati + List subscribedItems = UA_ref.SubscribeToDataChanges(selectedItemList); + // aggiungo come DataItems + int dSamplePeriod = 0; + int threshDBand = 0; + string uuid = ""; + foreach (var item in subscribedItems) + { + OpcUaDataItemExt newItem = formatDataItem(ref dSamplePeriod, ref threshDBand, ref uuid, item); + dataItemMem.Add(uuid, newItem); + } + // gestione eventi change + UA_ref.eh_MonItChange += UA_ref_eh_MonItChange; + } - UA_ref.eh_MonItChange += UA_ref_eh_MonItChange; - - // Subscribe to the Event handlers to receive the MTConnect documents - UA_ref.ProbeReceived += DevicesSuccessful; - UA_ref.CurrentReceived += CurrentSuccessful; - UA_ref.SampleReceived += StreamsSuccessful; - - // attendo 1 sec... - Thread.Sleep(1000); - UA_ref.Start(); esitoLink = 1; // fix tempi! @@ -897,15 +880,6 @@ namespace IOB_WIN_NEXT } } - /// - /// Ricevuta modifica come stream da campionamenti ricevuti - /// - /// - protected void StreamsSuccessful(MTConnectStreams.Document document) - { - checkAndSend(document, false); - } - #endregion Protected Methods #region Public Methods @@ -1040,7 +1014,12 @@ namespace IOB_WIN_NEXT { // ora provo connessione... parentForm.commPlcActive = true; - short esitoLink = doConnect(); + var task = Task.Run(async () => + { + return await doConnect(); + }); + + short esitoLink = task.Result; // use returned result from async method here lgInfo($"szStatusConnection OpcUa, esitoLink: {esitoLink}"); parentForm.commPlcActive = false; connectionOk = true; diff --git a/IOB-WIN-NEXT/UAClient.cs b/IOB-WIN-NEXT/UAClient.cs index 81cb4ef3..517e495d 100644 --- a/IOB-WIN-NEXT/UAClient.cs +++ b/IOB-WIN-NEXT/UAClient.cs @@ -179,7 +179,7 @@ namespace IOB_WIN_NEXT /// /// Browse Server nodes /// - public Dictionary Browse(uint startNodeNS, ushort startNodeVal) + public Dictionary Browse(ushort startNodeNS, uint startNodeVal) { Dictionary nodeIdNameList = new Dictionary(); if (m_session == null || m_session.Connected == false) @@ -200,7 +200,7 @@ namespace IOB_WIN_NEXT //NodeId nodeToBrowse = ObjectIds.Server; //NodeId nodeToBrowse = new NodeId("ns=4,i=5001"); - NodeId nodeToBrowse = new NodeId(startNodeNS, startNodeVal); + NodeId nodeToBrowse = new NodeId(startNodeVal, startNodeNS); // Call Browse service m_output.WriteLine("Browsing {0} node...", nodeToBrowse); @@ -211,8 +211,7 @@ namespace IOB_WIN_NEXT foreach (ReferenceDescription result in browseResults) { - m_output.WriteLine($" NodeId = {result.NodeId}, DisplayName = {result.DisplayName.Text}, NodeClass = {result.NodeClass}, Others: {result.NodeClass} | {result.NodeId} | {result.BinaryEncodingId} | {result.BrowseName}"); - + m_output.WriteLine($" NodeId = {result.NodeId}, DisplayName = {result.DisplayName.Text}, NodeClass = {result.NodeClass}, Others: {result.BinaryEncodingId} | {result.BrowseName}"); nodeIdNameList.Add(result.NodeId.ToString(), result.DisplayName.Text); } } @@ -641,4 +640,4 @@ namespace IOB_WIN_NEXT #endregion Public Methods } -} \ No newline at end of file +} diff --git a/IOB-WIN-NEXT/UAClient.cs.bak b/IOB-WIN-NEXT/UAClient.cs.bak new file mode 100644 index 00000000..0561dd7b --- /dev/null +++ b/IOB-WIN-NEXT/UAClient.cs.bak @@ -0,0 +1,643 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Collections; +using Opc.Ua; +using Opc.Ua.Client; + +namespace IOB_WIN_NEXT +{ + /// + /// Evento per incapsulare dati x refresh pagina + /// + public class opcUaMonitItemChange : EventArgs + { + #region Private Fields + + /// + /// Monitored Item da notificare + /// + private readonly MonitoredItem _monitoredItem; + + /// + /// Valore notifica + /// + private readonly MonitoredItemNotification _notification; + + #endregion Private Fields + + #region Public Constructors + + /// + /// salvataggio obj + /// + /// + public opcUaMonitItemChange(MonitoredItem monitoredItem, MonitoredItemNotification notification) + { + _monitoredItem = monitoredItem; + _notification = notification; + } + + #endregion Public Constructors + + #region Public Properties + + /// + /// Proprietà lettura del MonitoredItem + /// + public MonitoredItem CurrMonitoredItem + { + get { return _monitoredItem; } + } + + /// + /// Proprietà lettura della notifica + /// + public MonitoredItemNotification CurrNotify + { + get { return _notification; } + } + + #endregion Public Properties + } + + /// + /// OPC UA Client with examples of basic functionality. + /// + public class UAClient + { + #region Private Fields + + private readonly IOutput m_output; + + private readonly Action m_validateResponse; + + private ApplicationConfiguration m_configuration; + + private Session m_session; + + #endregion Private Fields + + #region Public Constructors + + /// + /// Initializes a new instance of the UAClient class. + /// + public UAClient(ApplicationConfiguration configuration, IOutput output, Action validateResponse) + { + m_validateResponse = validateResponse; + m_output = output; + m_configuration = configuration; + m_configuration.CertificateValidator.CertificateValidation += CertificateValidation; + } + + #endregion Public Constructors + + #region Public Events + + /// + /// Evento notifica variazione MonitoredItem + /// + public event EventHandler eh_MonItChange; + + #endregion Public Events + + #region Public Properties + + /// + /// Gets or sets the server URL. + /// + public string ServerUrl { get; set; } = "opc.tcp://localhost:62541/Quickstarts/ReferenceServer"; + + /// + /// Gets the client session. + /// + public Session Session => m_session; + + #endregion Public Properties + + #region Private Methods + + /// + /// Handles the certificate validation event. + /// This event is triggered every time an untrusted certificate is received from the server. + /// + private void CertificateValidation(CertificateValidator sender, CertificateValidationEventArgs e) + { + bool certificateAccepted = true; + + // **** + // Implement a custom logic to decide if the certificate should be + // accepted or not and set certificateAccepted flag accordingly. + // The certificate can be retrieved from the e.Certificate field + // *** + + ServiceResult error = e.Error; + while (error != null) + { + m_output.WriteLine(error); + error = error.InnerResult; + } + + if (certificateAccepted) + { + m_output.WriteLine("Untrusted Certificate accepted. SubjectName = {0}", e.Certificate.SubjectName); + } + + e.AcceptAll = certificateAccepted; + } + + /// + /// Handle DataChange notifications from Server + /// + private void OnMonitoredItemNotification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e) + { + try + { + // Log MonitoredItem Notification event + MonitoredItemNotification notification = e.NotificationValue as MonitoredItemNotification; + + // sollevo evento notifica vaziazione MonitoredItem + if (eh_MonItChange != null) + { + eh_MonItChange(this, new opcUaMonitItemChange(monitoredItem, notification)); + } + m_output.WriteLine("Notification Received for Variable \"{0}\" and Value = {1}.", monitoredItem.DisplayName, notification.Value); + } + catch (Exception ex) + { + m_output.WriteLine("OnMonitoredItemNotification error: {0}", ex.Message); + } + } + + #endregion Private Methods + + #region Public Methods + + /// + /// Browse Server nodes + /// + public Dictionary Browse(ushort startNodeNS, uint startNodeVal) + { + Dictionary nodeIdNameList = new Dictionary(); + if (m_session == null || m_session.Connected == false) + { + m_output.WriteLine("Session not connected!"); + return nodeIdNameList; + } + + try + { + // Create a Browser object + Browser browser = new Browser(m_session); + + // Set browse parameters + browser.BrowseDirection = BrowseDirection.Forward; + browser.NodeClassMask = (int)NodeClass.Object | (int)NodeClass.Variable; + browser.ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences; + + //NodeId nodeToBrowse = ObjectIds.Server; + //NodeId nodeToBrowse = new NodeId("ns=4,i=5001"); + NodeId nodeToBrowse = new NodeId(startNodeVal, startNodeNS); + + // Call Browse service + m_output.WriteLine("Browsing {0} node...", nodeToBrowse); + ReferenceDescriptionCollection browseResults = browser.Browse(nodeToBrowse); + + // Display the results + m_output.WriteLine("Browse returned {0} results:", browseResults.Count); + + foreach (ReferenceDescription result in browseResults) + { + m_output.WriteLine($" NodeId = {result.NodeId}, DisplayName = {result.DisplayName.Text}, NodeClass = {result.NodeClass}, Others: {result.BinaryEncodingId} | {result.BrowseName}"); + nodeIdNameList.Add(result.NodeId.ToString(), result.DisplayName.Text); + } + } + catch (Exception ex) + { + // Log Error + m_output.WriteLine($"Browse Error : {ex.Message}."); + } + + return nodeIdNameList; + } + + /// + /// Call UA method + /// + public void CallMethod() + { + if (m_session == null || m_session.Connected == false) + { + m_output.WriteLine("Session not connected!"); + return; + } + + try + { + // Define the UA Method to call + // Parent node - Objects\CTT\Methods + // Method node - Objects\CTT\Methods\Add + NodeId objectId = new NodeId("ns=2;s=Methods"); + NodeId methodId = new NodeId("ns=2;s=Methods_Add"); + + // Define the method parameters + // Input argument requires a Float and an UInt32 value + object[] inputArguments = new object[] { (float)10.5, (uint)10 }; + IList outputArguments = null; + + // Invoke Call service + m_output.WriteLine("Calling UAMethod for node {0} ...", methodId); + outputArguments = m_session.Call(objectId, methodId, inputArguments); + + // Display results + m_output.WriteLine("Method call returned {0} output argument(s):", outputArguments.Count); + + foreach (var outputArgument in outputArguments) + { + m_output.WriteLine(" OutputValue = {0}", outputArgument.ToString()); + } + } + catch (Exception ex) + { + m_output.WriteLine("Method call error: {0}", ex.Message); + } + } + + /// + /// Creates a session with the UA server + /// + public async Task ConnectAsync() + { + try + { + if (m_session != null && m_session.Connected == true) + { + m_output.WriteLine("Session already connected!"); + } + else + { + m_output.WriteLine("Connecting..."); + + // Get the endpoint by connecting to server's discovery endpoint. + // Try to find the first endopint without security. + EndpointDescription endpointDescription = CoreClientUtils.SelectEndpoint(ServerUrl, false); + + EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(m_configuration); + ConfiguredEndpoint endpoint = new ConfiguredEndpoint(null, endpointDescription, endpointConfiguration); + + // Create the session + Session session = await Session.Create( + m_configuration, + endpoint, + false, + false, + m_configuration.ApplicationName, + 30 * 60 * 1000, + new UserIdentity(), + null + ); + + // Assign the created session + if (session != null && session.Connected) + { + m_session = session; + } + + // Session created successfully. + m_output.WriteLine($"New Session Created with SessionName = {m_session.SessionName}"); + } + + return true; + } + catch (Exception ex) + { + // Log Error + m_output.WriteLine($"Create Session Error : {ex.Message}"); + return false; + } + } + + /// + /// Disconnects the session. + /// + public void Disconnect() + { + try + { + if (m_session != null) + { + m_output.WriteLine("Disconnecting..."); + + m_session.Close(); + m_session.Dispose(); + m_session = null; + + // Log Session Disconnected event + m_output.WriteLine("Session Disconnected."); + } + else + { + m_output.WriteLine("Session not created!"); + } + } + catch (Exception ex) + { + // Log Error + m_output.WriteLine($"Disconnect Error : {ex.Message}"); + } + } + + /// + /// Read a list of nodes from Server + /// + public void ReadNodes() + { + if (m_session == null || m_session.Connected == false) + { + m_output.WriteLine("Session not connected!"); + return; + } + + try + { + #region Read a node by calling the Read Service + + // build a list of nodes to be read + ReadValueIdCollection nodesToRead = new ReadValueIdCollection() + { + // Value of ServerStatus + new ReadValueId() { NodeId = Variables.Server_ServerStatus, AttributeId = Attributes.Value }, + // BrowseName of ServerStatus_StartTime + new ReadValueId() { NodeId = Variables.Server_ServerStatus_StartTime, AttributeId = Attributes.BrowseName }, + // Value of ServerStatus_StartTime + new ReadValueId() { NodeId = Variables.Server_ServerStatus_StartTime, AttributeId = Attributes.Value } + }; + + // Read the node attributes + m_output.WriteLine("Reading nodes..."); + + // Call Read Service + m_session.Read( + null, + 0, + TimestampsToReturn.Both, + nodesToRead, + out DataValueCollection resultsValues, + out DiagnosticInfoCollection diagnosticInfos); + + // Validate the results + m_validateResponse(resultsValues, nodesToRead); + + // Display the results. + foreach (DataValue result in resultsValues) + { + m_output.WriteLine("Read Value = {0} , StatusCode = {1}", result.Value, result.StatusCode); + } + + #endregion Read a node by calling the Read Service + + #region Read the Value attribute of a node by calling the Session.ReadValue method + + // Read Server NamespaceArray + m_output.WriteLine("Reading Value of NamespaceArray node..."); + DataValue namespaceArray = m_session.ReadValue(Variables.Server_NamespaceArray); + // Display the result + m_output.WriteLine($"NamespaceArray Value = {namespaceArray}"); + + #endregion Read the Value attribute of a node by calling the Session.ReadValue method + } + catch (Exception ex) + { + // Log Error + m_output.WriteLine($"Read Nodes Error : {ex.Message}."); + } + } + + /// + /// Create Subscription and MonitoredItems for DataChanges + /// + public List SubscribeToDataChanges(Dictionary DataList) + { + List monItList = new List(); + if (m_session == null || m_session.Connected == false) + { + m_output.WriteLine("Session not connected!"); + return monItList; + } + + try + { + // Create a subscription for receiving data change notifications + + // Define Subscription parameters + Subscription subscription = new Subscription(m_session.DefaultSubscription); + + subscription.DisplayName = "Steamware IOB-WIN Subscription"; + subscription.PublishingEnabled = true; + subscription.PublishingInterval = 1000; + + m_session.AddSubscription(subscription); + + // Create the subscription on Server side + subscription.Create(); + m_output.WriteLine("New Subscription created with SubscriptionId = {0}.", subscription.Id); + + // Create MonitoredItems for data changes + foreach (var item in DataList) + { + MonitoredItem currMonIt = new MonitoredItem(subscription.DefaultItem); + // Int32 Node - Objects\CTT\Scalar\Simulation\Int32 + currMonIt.StartNodeId = new NodeId(item.Key); + currMonIt.AttributeId = Attributes.Value; + currMonIt.DisplayName = item.Value; + currMonIt.SamplingInterval = 1000; + currMonIt.Notification += OnMonitoredItemNotification; + subscription.AddItem(currMonIt); + monItList.Add(currMonIt); + } + +#if false + MonitoredItem IO_120_00_MonitoredItem = new MonitoredItem(subscription.DefaultItem); + // Int32 Node - Objects\CTT\Scalar\Simulation\Int32 + IO_120_00_MonitoredItem.StartNodeId = new NodeId("ns=4;s=IO_120.00"); + IO_120_00_MonitoredItem.AttributeId = Attributes.Value; + IO_120_00_MonitoredItem.DisplayName = "IO_120 Variable"; + IO_120_00_MonitoredItem.SamplingInterval = 1000; + IO_120_00_MonitoredItem.Notification += OnMonitoredItemNotification; + subscription.AddItem(IO_120_00_MonitoredItem); + + MonitoredItem IO_120_01_MonitoredItem = new MonitoredItem(subscription.DefaultItem); + // Int32 Node - Objects\CTT\Scalar\Simulation\Int32 + IO_120_01_MonitoredItem.StartNodeId = new NodeId("ns=4;s=IO_120.01"); + IO_120_01_MonitoredItem.AttributeId = Attributes.Value; + IO_120_01_MonitoredItem.DisplayName = "IO_120_01 Variable"; + IO_120_01_MonitoredItem.SamplingInterval = 1000; + IO_120_01_MonitoredItem.Notification += OnMonitoredItemNotification; + subscription.AddItem(IO_120_01_MonitoredItem); + + MonitoredItem IO_130_MonitoredItem = new MonitoredItem(subscription.DefaultItem); + // Int32 Node - Objects\CTT\Scalar\Simulation\Int32 + IO_130_MonitoredItem.StartNodeId = new NodeId("ns=4;s=IO_130"); + IO_130_MonitoredItem.AttributeId = Attributes.Value; + IO_130_MonitoredItem.DisplayName = "IO_130 Variable"; + IO_130_MonitoredItem.SamplingInterval = 1000; + IO_130_MonitoredItem.Notification += OnMonitoredItemNotification; + subscription.AddItem(IO_130_MonitoredItem); + + MonitoredItem IO_135_MonitoredItem = new MonitoredItem(subscription.DefaultItem); + // Int32 Node - Objects\CTT\Scalar\Simulation\Int32 + IO_135_MonitoredItem.StartNodeId = new NodeId("ns=4;s=IO_135"); + IO_135_MonitoredItem.AttributeId = Attributes.Value; + IO_135_MonitoredItem.DisplayName = "IO_135 Variable"; + IO_135_MonitoredItem.SamplingInterval = 1000; + IO_135_MonitoredItem.Notification += OnMonitoredItemNotification; + subscription.AddItem(IO_135_MonitoredItem); + + MonitoredItem IO_140_MonitoredItem = new MonitoredItem(subscription.DefaultItem); + // Int32 Node - Objects\CTT\Scalar\Simulation\Int32 + IO_140_MonitoredItem.StartNodeId = new NodeId("ns=4;s=IO_140"); + IO_140_MonitoredItem.AttributeId = Attributes.Value; + IO_140_MonitoredItem.DisplayName = "IO_140 Variable"; + IO_140_MonitoredItem.SamplingInterval = 1000; + IO_140_MonitoredItem.Notification += OnMonitoredItemNotification; + subscription.AddItem(IO_140_MonitoredItem); + + //MonitoredItem intMonitoredItem = new MonitoredItem(subscription.DefaultItem); + //// Int32 Node - Objects\CTT\Scalar\Simulation\Int32 + //intMonitoredItem.StartNodeId = new NodeId("ns=2;s=Scalar_Simulation_Int32"); + //intMonitoredItem.AttributeId = Attributes.Value; + //intMonitoredItem.DisplayName = "Int32 Variable"; + //intMonitoredItem.SamplingInterval = 1000; + //intMonitoredItem.Notification += OnMonitoredItemNotification; + + //subscription.AddItem(intMonitoredItem); + + //MonitoredItem floatMonitoredItem = new MonitoredItem(subscription.DefaultItem); + //// Float Node - Objects\CTT\Scalar\Simulation\Float + //floatMonitoredItem.StartNodeId = new NodeId("ns=2;s=Scalar_Simulation_Float"); + //floatMonitoredItem.AttributeId = Attributes.Value; + //floatMonitoredItem.DisplayName = "Float Variable"; + //floatMonitoredItem.SamplingInterval = 1000; + //floatMonitoredItem.Notification += OnMonitoredItemNotification; + + //subscription.AddItem(floatMonitoredItem); + + //MonitoredItem stringMonitoredItem = new MonitoredItem(subscription.DefaultItem); + //// String Node - Objects\CTT\Scalar\Simulation\String + //stringMonitoredItem.StartNodeId = new NodeId("ns=2;s=Scalar_Simulation_String"); + //stringMonitoredItem.AttributeId = Attributes.Value; + //stringMonitoredItem.DisplayName = "String Variable"; + //stringMonitoredItem.SamplingInterval = 1000; + //stringMonitoredItem.Notification += OnMonitoredItemNotification; + + //subscription.AddItem(stringMonitoredItem); +#endif + + // Create the monitored items on Server side + subscription.ApplyChanges(); + m_output.WriteLine("MonitoredItems created for SubscriptionId = {0}.", subscription.Id); + } + catch (Exception ex) + { + m_output.WriteLine("Subscribe error: {0}", ex.Message); + } + return monItList; + } + + /// + /// Write a list of nodes to the Server + /// + public void WriteNodes() + { + if (m_session == null || m_session.Connected == false) + { + m_output.WriteLine("Session not connected!"); + return; + } + + try + { + // Write the configured nodes + WriteValueCollection nodesToWrite = new WriteValueCollection(); + + // Int32 Node - Objects\CTT\Scalar\Scalar_Static\Int32 + WriteValue commWriteVal = new WriteValue(); + commWriteVal.NodeId = new NodeId("ns=4;s=IO_151"); + commWriteVal.AttributeId = Attributes.Value; + commWriteVal.Value = new DataValue(); + commWriteVal.Value.Value = (int)111; + nodesToWrite.Add(commWriteVal); + + WriteValue artWriteVal = new WriteValue(); + artWriteVal.NodeId = new NodeId("ns=4;s=IO_151"); + artWriteVal.AttributeId = Attributes.Value; + artWriteVal.Value = new DataValue(); + artWriteVal.Value.Value = (int)222; + nodesToWrite.Add(artWriteVal); + + WriteValue qtyWriteVal = new WriteValue(); + qtyWriteVal.NodeId = new NodeId("ns=4;s=IO_153"); + qtyWriteVal.AttributeId = Attributes.Value; + qtyWriteVal.Value = new DataValue(); + qtyWriteVal.Value.Value = (int)333; + nodesToWrite.Add(qtyWriteVal); + + //// Int32 Node - Objects\CTT\Scalar\Scalar_Static\Int32 + //WriteValue intWriteVal = new WriteValue(); + //intWriteVal.NodeId = new NodeId("ns=2;s=Scalar_Static_Int32"); + //intWriteVal.AttributeId = Attributes.Value; + //intWriteVal.Value = new DataValue(); + //intWriteVal.Value.Value = (int)100; + //nodesToWrite.Add(intWriteVal); + + //// Float Node - Objects\CTT\Scalar\Scalar_Static\Float + //WriteValue floatWriteVal = new WriteValue(); + //floatWriteVal.NodeId = new NodeId("ns=2;s=Scalar_Static_Float"); + //floatWriteVal.AttributeId = Attributes.Value; + //floatWriteVal.Value = new DataValue(); + //floatWriteVal.Value.Value = (float)100.5; + //nodesToWrite.Add(floatWriteVal); + + //// String Node - Objects\CTT\Scalar\Scalar_Static\String + //WriteValue stringWriteVal = new WriteValue(); + //stringWriteVal.NodeId = new NodeId("ns=2;s=Scalar_Static_String"); + //stringWriteVal.AttributeId = Attributes.Value; + //stringWriteVal.Value = new DataValue(); + //stringWriteVal.Value.Value = "String Test"; + //nodesToWrite.Add(stringWriteVal); + + // Write the node attributes + StatusCodeCollection results = null; + DiagnosticInfoCollection diagnosticInfos; + m_output.WriteLine("Writing nodes..."); + + // Call Write Service + m_session.Write(null, + nodesToWrite, + out results, + out diagnosticInfos); + + // Validate the response + m_validateResponse(results, nodesToWrite); + + // Display the results. + m_output.WriteLine("Write Results :"); + + foreach (StatusCode writeResult in results) + { + m_output.WriteLine(" {0}", writeResult); + } + } + catch (Exception ex) + { + // Log Error + m_output.WriteLine($"Write Nodes Error : {ex.Message}."); + } + } + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/IOB-WIN-NEXT/packages.config b/IOB-WIN-NEXT/packages.config index 2751b3e6..7b57a8f1 100644 --- a/IOB-WIN-NEXT/packages.config +++ b/IOB-WIN-NEXT/packages.config @@ -16,6 +16,7 @@ +