Files
Mapo-IOB-WIN/IOB-OPC-UA/Applications/ClientControls.Net4/Common/Client/GdsDiscoverServersDlg.cs
T
2021-03-25 18:25:25 +01:00

539 lines
18 KiB
C#

/* ========================================================================
* 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.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Opc.Ua.Client;
using Opc.Ua.Client.Controls;
using System.Threading.Tasks;
namespace Opc.Ua.Client.Controls
{
/// <summary>
/// Searches for the servers in a GDS.
/// </summary>
public partial class GdsDiscoverServersDlg : Form
{
#region Constructors
/// <summary>
/// Constructs the form.
/// </summary>
public GdsDiscoverServersDlg()
{
InitializeComponent();
this.Icon = ClientUtils.GetAppIcon();
ServersLV.SmallImageList = new ClientUtils().ImageList;
List<object> items = new List<object>();
foreach (object value in Enum.GetValues(typeof(Match)))
{
items.Add(value);
}
ApplicationNameCB.Items.AddRange(items.ToArray());
MachineNameCB.Items.AddRange(items.ToArray());
ApplicationUriCB.Items.AddRange(items.ToArray());
ProductUriCB.Items.AddRange(items.ToArray());
ApplicationNameCB.SelectedIndex = 0;
MachineNameCB.SelectedIndex = 0;
ApplicationUriCB.SelectedIndex = 0;
ProductUriCB.SelectedIndex = 0;
}
#endregion
#region Match Enumeration
private enum Match
{
StartsWith,
IsExactly,
EndsWith,
Contains
}
#endregion
#region Private Fields
private ApplicationDescription m_application;
#endregion
#region Private Constants
/// <summary>
/// The identifier for the Directory Object.
/// </summary>
private const uint GdsId_Directory = 584;
/// <summary>
/// The identifier for the Directory_Applications Object.
/// </summary>
private const uint GdsId_Directory_Applications = 586;
/// <summary>
/// The identifier for the RootDirectoryEntryType_QueryServers Method.
/// </summary>
private const uint GdsId_RootDirectoryEntryType_QueryServers = 550;
/// <summary>
/// The identifier for the ApplicationElementType ObjectType.
/// </summary>
public const uint GdsId_ApplicationElementType = 572;
#endregion
#region Public Interface
/// <summary>
/// Shows the dialog.
/// </summary>
public async Task<ApplicationDescription> ShowDialog(ApplicationConfiguration configuration, bool showSearchPanel)
{
List<string> urls = new List<string>();
foreach (EndpointDescription endpoint in configuration.ClientConfiguration.DiscoveryServers)
{
urls.Add(endpoint.EndpointUrl);
}
if (urls.Count == 0)
{
// TODO find servers with LDS
urls.Add("opc.tcp://localhost:58800/GlobalDiscoveryServer");
}
ServerCTRL.Configuration = configuration;
ServerCTRL.SetAvailableUrls(urls);
try
{
await ServerCTRL.Connect();
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
OkBTN.Visible = true;
CancelBTN.Visible = true;
BrowseCK.Checked = showSearchPanel;
BrowseCK.Checked = !showSearchPanel;
if (base.ShowDialog() != DialogResult.OK)
{
return null;
}
return m_application;
}
#endregion
#region Private Methods
/// <summary>
/// Adds the results to the control.
/// </summary>
private void UpdateResults(ApplicationDescription[] descriptions)
{
ServersLV.Items.Clear();
if (descriptions == null)
{
return;
}
for (int ii = 0; ii < descriptions.Length; ii++)
{
ApplicationDescription description = descriptions[ii];
if (description == null)
{
continue;
}
ListViewItem item = new ListViewItem();
item.Text = Utils.Format("{0}", description.ApplicationName);
item.ImageIndex = ClientUtils.GetImageIndex(ServerCTRL.Session, NodeClass.Object, null, false);
item.SubItems.Add(new ListViewItem.ListViewSubItem());
item.SubItems.Add(new ListViewItem.ListViewSubItem());
item.SubItems.Add(new ListViewItem.ListViewSubItem());
item.Tag = description;
ServersLV.Items.Add(item);
item.SubItems[1].Text = description.ApplicationType.ToString();
if (description.DiscoveryUrls == null)
{
continue;
}
// collect the domains and protocols.
List<string> domains = new List<string>();
List<string> protocols = new List<string>();
foreach (string discoveryUrl in description.DiscoveryUrls)
{
Uri url = Utils.ParseUri(discoveryUrl);
if (url != null)
{
if (!domains.Contains(url.DnsSafeHost))
{
domains.Add(url.DnsSafeHost);
}
if (!protocols.Contains(url.Scheme))
{
protocols.Add(url.Scheme);
}
}
}
// format the domains.
StringBuilder buffer = new StringBuilder();
foreach (string domain in domains)
{
if (buffer.Length > 0)
{
buffer.Append(", ");
}
buffer.Append(domain);
}
item.SubItems[2].Text = buffer.ToString();
// format the protocols.
buffer = new StringBuilder();
foreach (string protocol in protocols)
{
if (buffer.Length > 0)
{
buffer.Append(", ");
}
buffer.Append(protocol);
}
item.SubItems[3].Text = buffer.ToString();
}
// adjust column widths.
for (int ii = 0; ii < ServersLV.Columns.Count; ii++)
{
ServersLV.Columns[ii].Width = -2;
}
}
/// <summary>
/// Adds wildcards to the filter.
/// </summary>
private string ProcessFilter(ComboBox selection, TextBox filter)
{
if (String.IsNullOrEmpty(filter.Text))
{
return String.Empty;
}
string text = filter.Text;
Match match = (Match)selection.SelectedItem;
if (match == Match.Contains || match == Match.StartsWith)
{
if (!text.EndsWith("%"))
{
text = text + "%";
}
}
if (match == Match.Contains || match == Match.EndsWith)
{
if (!text.StartsWith("%"))
{
text = "%" + text;
}
}
return text;
}
/// <summary>
/// Searches the server for servers.
/// </summary>
private void Search()
{
Session session = ServerCTRL.Session;
if (session == null)
{
return;
}
NodeId elementId = null;
ReferenceDescription reference = SystemElementBTN.SelectedReference;
if (reference != null && !reference.NodeId.IsAbsolute)
{
elementId = (NodeId)reference.NodeId;
}
ushort namespaceIndex = (ushort)session.NamespaceUris.GetIndex(Namespaces.OpcUaGds);
IList<object> outputArguments = session.Call(
new NodeId(GdsId_Directory, namespaceIndex),
new NodeId(GdsId_RootDirectoryEntryType_QueryServers, namespaceIndex),
elementId,
ProcessFilter(ApplicationNameCB, ApplicationNameTB),
ProcessFilter(MachineNameCB, MachineNameTB),
ProcessFilter(ApplicationUriCB, ApplicationUriTB),
ProcessFilter(ProductUriCB, ProductUriTB));
if (outputArguments != null && outputArguments.Count == 1)
{
ExtensionObject[] extensions = outputArguments[0] as ExtensionObject[];
ApplicationDescription[] descriptions = (ApplicationDescription[])ExtensionObject.ToArray(extensions, typeof(ApplicationDescription));
UpdateResults(descriptions);
}
}
/// <summary>
/// Reads the application description from the GDS.
/// </summary>
private ApplicationDescription Read(NodeId nodeId)
{
NamespaceTable wellKnownNamespaceUris = new NamespaceTable();
wellKnownNamespaceUris.Append(Namespaces.OpcUaGds);
string[] browsePaths = new string[]
{
"1:ApplicationName",
"1:ApplicationType",
"1:ApplicationUri",
"1:ProductUri",
"1:GatewayServerUri",
"1:DiscoveryUrls"
};
List<NodeId> propertyIds = ClientUtils.TranslateBrowsePaths(
ServerCTRL.Session,
nodeId,
wellKnownNamespaceUris,
browsePaths);
ReadValueIdCollection nodesToRead = new ReadValueIdCollection();
foreach (NodeId propertyId in propertyIds)
{
ReadValueId nodeToRead = new ReadValueId();
nodeToRead.NodeId = propertyId;
nodeToRead.AttributeId = Attributes.Value;
nodesToRead.Add(nodeToRead);
}
DataValueCollection results = null;
DiagnosticInfoCollection diagnosticInfos = null;
ServerCTRL.Session.Read(
null,
0,
TimestampsToReturn.Neither,
nodesToRead,
out results,
out diagnosticInfos);
ClientBase.ValidateResponse(results, nodesToRead);
ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead);
ApplicationDescription application = new ApplicationDescription();
application.ApplicationName = results[0].GetValue<LocalizedText>(null);
application.ApplicationType = (ApplicationType)results[1].GetValue<int>((int)ApplicationType.Server);
application.ApplicationUri = results[2].GetValue<string>(null);
application.ProductUri = results[3].GetValue<string>(null);
application.GatewayServerUri = results[4].GetValue<string>(null);
string[] discoveryUrls = results[5].GetValue<string[]>(null);
if (discoveryUrls != null)
{
application.DiscoveryUrls = new StringCollection(discoveryUrls);
}
return application;
}
#endregion
#region Event Handlers
private void SearchBTN_Click(object sender, EventArgs e)
{
try
{
Search();
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
private void CloseBTN_Click(object sender, EventArgs e)
{
try
{
Close();
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
private void ServerCTRL_ConnectComplete(object sender, EventArgs e)
{
try
{
Session session = ServerCTRL.Session;
if (session != null)
{
ushort namespaceIndex = (ushort)session.NamespaceUris.GetIndex(Opc.Ua.Namespaces.OpcUaGds);
NodeId rootId = new NodeId(GdsId_Directory_Applications, namespaceIndex);
NodeId[] referenceTypeIds = new NodeId[] { Opc.Ua.ReferenceTypeIds.Organizes, Opc.Ua.ReferenceTypeIds.HasChild };
BrowseCTRL.Initialize(session, rootId, referenceTypeIds);
SystemElementBTN.Session = session;
SystemElementBTN.RootId = rootId;
SystemElementBTN.ReferenceTypeIds = referenceTypeIds;
}
else
{
BrowseCTRL.ChangeSession(session);
SystemElementBTN.Session = session;
}
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
private void ServerCTRL_ReconnectComplete(object sender, EventArgs e)
{
try
{
Session session = ServerCTRL.Session;
BrowseCTRL.ChangeSession(session);
SystemElementBTN.Session = session;
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
private void BrowseCK_CheckedChanged(object sender, EventArgs e)
{
try
{
SearchPN.Visible = !BrowseCK.Checked;
SearchBTN.Enabled = !BrowseCK.Checked;
BrowseCTRL.Visible = BrowseCK.Checked;
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
private void ServersLV_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
if (ServerCTRL.Session == null)
{
return;
}
foreach (ListViewItem item in ServersLV.SelectedItems)
{
m_application = item.Tag as ApplicationDescription;
OkBTN.Enabled = m_application.ApplicationType == ApplicationType.Server || m_application.ApplicationType == ApplicationType.ClientAndServer;
return;
}
m_application = null;
OkBTN.Enabled = false;
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
private void BrowseCTRL_AfterSelect(object sender, EventArgs e)
{
try
{
if (ServerCTRL.Session == null)
{
return;
}
ushort namespaceIndex = (ushort)ServerCTRL.Session.NamespaceUris.GetIndex(Opc.Ua.Namespaces.OpcUaGds);
NodeId typeId = new NodeId(GdsId_ApplicationElementType, namespaceIndex);
ReferenceDescription reference = BrowseCTRL.SelectedNode;
if (reference != null)
{
if (reference.TypeDefinition == typeId)
{
m_application = Read((NodeId)reference.NodeId);
OkBTN.Enabled = m_application.ApplicationType == ApplicationType.Server || m_application.ApplicationType == ApplicationType.ClientAndServer;
return;
}
}
m_application = null;
OkBTN.Enabled = false;
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
#endregion
}
}