Files
UA-.NETStandard/SampleApplications/Workshop/DataAccess/Client/MainForm.cs
T
2020-05-11 13:56:18 +03:00

1194 lines
43 KiB
C#

/* ========================================================================
* Copyright (c) 2005-2019 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.Drawing;
using System.Security.Cryptography.X509Certificates;
using System.Windows.Forms;
using System.IO;
using Opc.Ua;
using Opc.Ua.Client;
using Opc.Ua.Client.Controls;
namespace Quickstarts.DataAccessClient
{
/// <summary>
/// The main form for a simple Data Access Client application.
/// </summary>
public partial class MainForm : Form
{
#region Constructors
/// <summary>
/// Creates an empty form.
/// </summary>
private MainForm()
{
InitializeComponent();
this.Icon = ClientUtils.GetAppIcon();
}
/// <summary>
/// Creates a form which uses the specified client configuration.
/// </summary>
/// <param name="configuration">The configuration to use.</param>
public MainForm(ApplicationConfiguration configuration)
{
InitializeComponent();
this.Icon = ClientUtils.GetAppIcon();
ConnectServerCTRL.Configuration = m_configuration = configuration;
ConnectServerCTRL.ServerUrl = "opc.tcp://localhost:62548/Quickstarts/DataAccessServer";
this.Text = m_configuration.ApplicationName;
// create the callback.
m_MonitoredItem_Notification = new MonitoredItemNotificationEventHandler(MonitoredItem_Notification);
}
#endregion
#region Private Fields
private ApplicationConfiguration m_configuration;
private Session m_session;
private bool m_connectedOnce;
private Subscription m_subscription;
private MonitoredItemNotificationEventHandler m_MonitoredItem_Notification;
#endregion
#region Private Methods
#endregion
#region Event Handlers
/// <summary>
/// Connects to a server.
/// </summary>
private async void Server_ConnectMI_ClickAsync(object sender, EventArgs e)
{
try
{
await ConnectServerCTRL.Connect();
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Disconnects from the current session.
/// </summary>
private void Server_DisconnectMI_Click(object sender, EventArgs e)
{
try
{
ConnectServerCTRL.Disconnect();
m_subscription.Dispose();
m_subscription = null;
m_session = null;
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Prompts the user to choose a server on another host.
/// </summary>
private void Server_DiscoverMI_Click(object sender, EventArgs e)
{
try
{
ConnectServerCTRL.Discover(null);
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Updates the application after connecting to or disconnecting from the server.
/// </summary>
private void Server_ConnectComplete(object sender, EventArgs e)
{
try
{
m_session = ConnectServerCTRL.Session;
if (m_session == null)
{
MonitoredItemsLV.Items.Clear();
BrowseNodesTV.Nodes.Clear();
BrowseNodesTV.Enabled = false;
MonitoredItemsLV.Enabled = false;
return;
}
// set a suitable initial state.
if (m_session != null && !m_connectedOnce)
{
m_connectedOnce = true;
}
// populate the browse view.
PopulateBranch(ObjectIds.ObjectsFolder, BrowseNodesTV.Nodes);
BrowseNodesTV.Enabled = true;
MonitoredItemsLV.Enabled = true;
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Updates the application after a communicate error was detected.
/// </summary>
private void Server_ReconnectStarting(object sender, EventArgs e)
{
try
{
BrowseNodesTV.Enabled = false;
MonitoredItemsLV.Enabled = false;
AttributesLV.Items.Clear();
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Updates the application after reconnecting to the server.
/// </summary>
private void Server_ReconnectComplete(object sender, EventArgs e)
{
try
{
m_session = ConnectServerCTRL.Session;
foreach (Subscription subscription in m_session.Subscriptions)
{
m_subscription = subscription;
break;
}
BrowseNodesTV.Enabled = true;
MonitoredItemsLV.Enabled = true;
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Cleans up when the main form closes.
/// </summary>
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
ConnectServerCTRL.Disconnect();
}
#endregion
#region Private Methods
/// <summary>
/// Populates the branch in the tree view.
/// </summary>
/// <param name="sourceId">The NodeId of the Node to browse.</param>
/// <param name="nodes">The node collect to populate.</param>
private void PopulateBranch(NodeId sourceId, TreeNodeCollection nodes)
{
try
{
nodes.Clear();
// find all of the components of the node.
BrowseDescription nodeToBrowse1 = new BrowseDescription();
nodeToBrowse1.NodeId = sourceId;
nodeToBrowse1.BrowseDirection = BrowseDirection.Forward;
nodeToBrowse1.ReferenceTypeId = ReferenceTypeIds.Aggregates;
nodeToBrowse1.IncludeSubtypes = true;
nodeToBrowse1.NodeClassMask = (uint)(NodeClass.Object | NodeClass.Variable);
nodeToBrowse1.ResultMask = (uint)BrowseResultMask.All;
// find all nodes organized by the node.
BrowseDescription nodeToBrowse2 = new BrowseDescription();
nodeToBrowse2.NodeId = sourceId;
nodeToBrowse2.BrowseDirection = BrowseDirection.Forward;
nodeToBrowse2.ReferenceTypeId = ReferenceTypeIds.Organizes;
nodeToBrowse2.IncludeSubtypes = true;
nodeToBrowse2.NodeClassMask = (uint)(NodeClass.Object | NodeClass.Variable);
nodeToBrowse2.ResultMask = (uint)BrowseResultMask.All;
BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection();
nodesToBrowse.Add(nodeToBrowse1);
nodesToBrowse.Add(nodeToBrowse2);
// fetch references from the server.
ReferenceDescriptionCollection references = FormUtils.Browse(m_session, nodesToBrowse, false);
// process results.
for (int ii = 0; ii < references.Count; ii++)
{
ReferenceDescription target = references[ii];
// add node.
TreeNode child = new TreeNode(Utils.Format("{0}", target));
child.Tag = target;
child.Nodes.Add(new TreeNode());
nodes.Add(child);
}
// update the attributes display.
DisplayAttributes(sourceId);
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Displays the attributes and properties in the attributes view.
/// </summary>
/// <param name="sourceId">The NodeId of the Node to browse.</param>
private void DisplayAttributes(NodeId sourceId)
{
try
{
AttributesLV.Items.Clear();
ReadValueIdCollection nodesToRead = new ReadValueIdCollection();
// attempt to read all possible attributes.
for (uint ii = Attributes.NodeClass; ii <= Attributes.UserExecutable; ii++)
{
ReadValueId nodeToRead = new ReadValueId();
nodeToRead.NodeId = sourceId;
nodeToRead.AttributeId = ii;
nodesToRead.Add(nodeToRead);
}
int startOfProperties = nodesToRead.Count;
// find all of the pror of the node.
BrowseDescription nodeToBrowse1 = new BrowseDescription();
nodeToBrowse1.NodeId = sourceId;
nodeToBrowse1.BrowseDirection = BrowseDirection.Forward;
nodeToBrowse1.ReferenceTypeId = ReferenceTypeIds.HasProperty;
nodeToBrowse1.IncludeSubtypes = true;
nodeToBrowse1.NodeClassMask = 0;
nodeToBrowse1.ResultMask = (uint)BrowseResultMask.All;
BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection();
nodesToBrowse.Add(nodeToBrowse1);
// fetch property references from the server.
ReferenceDescriptionCollection references = FormUtils.Browse(m_session, nodesToBrowse, false);
if (references == null)
{
return;
}
for (int ii = 0; ii < references.Count; ii++)
{
// ignore external references.
if (references[ii].NodeId.IsAbsolute)
{
continue;
}
ReadValueId nodeToRead = new ReadValueId();
nodeToRead.NodeId = (NodeId)references[ii].NodeId;
nodeToRead.AttributeId = Attributes.Value;
nodesToRead.Add(nodeToRead);
}
// read all values.
DataValueCollection results = null;
DiagnosticInfoCollection diagnosticInfos = null;
m_session.Read(
null,
0,
TimestampsToReturn.Neither,
nodesToRead,
out results,
out diagnosticInfos);
ClientBase.ValidateResponse(results, nodesToRead);
ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead);
// process results.
for (int ii = 0; ii < results.Count; ii++)
{
string name = null;
string datatype = null;
string value = null;
// process attribute value.
if (ii < startOfProperties)
{
// ignore attributes which are invalid for the node.
if (results[ii].StatusCode == StatusCodes.BadAttributeIdInvalid)
{
continue;
}
// get the name of the attribute.
name = Attributes.GetBrowseName(nodesToRead[ii].AttributeId);
// display any unexpected error.
if (StatusCode.IsBad(results[ii].StatusCode))
{
datatype = Utils.Format("{0}", Attributes.GetDataTypeId(nodesToRead[ii].AttributeId));
value = Utils.Format("{0}", results[ii].StatusCode);
}
// display the value.
else
{
TypeInfo typeInfo = TypeInfo.Construct(results[ii].Value);
datatype = typeInfo.BuiltInType.ToString();
if (typeInfo.ValueRank >= ValueRanks.OneOrMoreDimensions)
{
datatype += "[]";
}
value = Utils.Format("{0}", results[ii].Value);
}
}
// process property value.
else
{
// ignore properties which are invalid for the node.
if (results[ii].StatusCode == StatusCodes.BadNodeIdUnknown)
{
continue;
}
// get the name of the property.
name = Utils.Format("{0}", references[ii-startOfProperties]);
// display any unexpected error.
if (StatusCode.IsBad(results[ii].StatusCode))
{
datatype = String.Empty;
value = Utils.Format("{0}", results[ii].StatusCode);
}
// display the value.
else
{
TypeInfo typeInfo = TypeInfo.Construct(results[ii].Value);
datatype = typeInfo.BuiltInType.ToString();
if (typeInfo.ValueRank >= ValueRanks.OneOrMoreDimensions)
{
datatype += "[]";
}
value = Utils.Format("{0}", results[ii].Value);
}
}
// add the attribute name/value to the list view.
ListViewItem item = new ListViewItem(name);
item.SubItems.Add(datatype);
item.SubItems.Add(value);
AttributesLV.Items.Add(item);
}
// adjust width of all columns.
for (int ii = 0; ii < AttributesLV.Columns.Count; ii++)
{
AttributesLV.Columns[ii].Width = -2;
}
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Converts a monitoring filter to text for display.
/// </summary>
/// <param name="filter">The filter.</param>
/// <returns>The deadback formatted as a string.</returns>
private string DeadbandFilterToText(MonitoringFilter filter)
{
DataChangeFilter datachangeFilter = filter as DataChangeFilter;
if (datachangeFilter != null)
{
if (datachangeFilter.DeadbandType == (uint)DeadbandType.Absolute)
{
return Utils.Format("{0:##.##}", datachangeFilter.DeadbandValue);
}
if (datachangeFilter.DeadbandType == (uint)DeadbandType.Percent)
{
return Utils.Format("{0:##.##}%", datachangeFilter.DeadbandValue);
}
}
return "None";
}
#endregion
#region Event Handlers
/// <summary>
/// Handles the Click event of the Help_ContentsMI control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void Help_ContentsMI_Click(object sender, EventArgs e)
{
try
{
System.Diagnostics.Process.Start( Path.GetDirectoryName(Application.ExecutablePath) + "\\WebHelp\\daclientoverview.htm");
}
catch (Exception ex)
{
MessageBox.Show("Unable to launch help documentation. Error: " + ex.Message);
}
}
/// <summary>
/// Fetches the children for a node the first time the node is expanded in the tree view.
/// </summary>
private void BrowseNodesTV_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{
try
{
// check if node has already been expanded once.
if (e.Node.Nodes.Count != 1 || e.Node.Nodes[0].Text != String.Empty)
{
return;
}
// get the source for the node.
ReferenceDescription reference = e.Node.Tag as ReferenceDescription;
if (reference == null || reference.NodeId.IsAbsolute)
{
e.Cancel = true;
return;
}
// populate children.
PopulateBranch((NodeId)reference.NodeId, e.Node.Nodes);
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Updates the display after a node is selected.
/// </summary>
private void BrowseNodesTV_AfterSelect(object sender, TreeViewEventArgs e)
{
try
{
// get the source for the node.
ReferenceDescription reference = e.Node.Tag as ReferenceDescription;
if (reference == null || reference.NodeId.IsAbsolute)
{
return;
}
// populate children.
PopulateBranch((NodeId)reference.NodeId, e.Node.Nodes);
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Ensures the correct node is selected before displaying the context menu.
/// </summary>
private void BrowseNodesTV_MouseDown(object sender, MouseEventArgs e)
{
try
{
BrowseNodesTV.SelectedNode = BrowseNodesTV.GetNodeAt(e.X, e.Y);
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Handles the Click event of the Browse_MonitorMI control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void Browse_MonitorMI_Click(object sender, EventArgs e)
{
try
{
// check if operation is currently allowed.
if (m_session == null || BrowseNodesTV.SelectedNode == null)
{
return;
}
// can only subscribe to local variables.
ReferenceDescription reference = (ReferenceDescription)BrowseNodesTV.SelectedNode.Tag;
if (reference.NodeId.IsAbsolute || reference.NodeClass != NodeClass.Variable)
{
return;
}
ListViewItem item = CreateMonitoredItem((NodeId)reference.NodeId, Utils.Format("{0}", reference));
m_subscription.ApplyChanges();
MonitoredItem monitoredItem = (MonitoredItem)item.Tag;
if (ServiceResult.IsBad(monitoredItem.Status.Error))
{
item.SubItems[8].Text = monitoredItem.Status.Error.StatusCode.ToString();
}
item.SubItems.Add(monitoredItem.DisplayName);
item.SubItems[1].Text = monitoredItem.MonitoringMode.ToString();
item.SubItems[2].Text = monitoredItem.SamplingInterval.ToString();
item.SubItems[3].Text = DeadbandFilterToText(monitoredItem.Filter);
MonitoredItemsLV.Columns[0].Width = -2;
MonitoredItemsLV.Columns[1].Width = -2;
MonitoredItemsLV.Columns[8].Width = -2;
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Creates the monitored item.
/// </summary>
private ListViewItem CreateMonitoredItem(NodeId nodeId, string displayName)
{
if (m_subscription == null)
{
m_subscription = new Subscription(m_session.DefaultSubscription);
m_subscription.PublishingEnabled = true;
m_subscription.PublishingInterval = 1000;
m_subscription.KeepAliveCount = 10;
m_subscription.LifetimeCount = 10;
m_subscription.MaxNotificationsPerPublish = 1000;
m_subscription.Priority = 100;
m_session.AddSubscription(m_subscription);
m_subscription.Create();
}
// add the new monitored item.
MonitoredItem monitoredItem = new MonitoredItem(m_subscription.DefaultItem);
monitoredItem.StartNodeId = nodeId;
monitoredItem.AttributeId = Attributes.Value;
monitoredItem.DisplayName = displayName;
monitoredItem.MonitoringMode = MonitoringMode.Reporting;
monitoredItem.SamplingInterval = 1000;
monitoredItem.QueueSize = 0;
monitoredItem.DiscardOldest = true;
monitoredItem.Notification += m_MonitoredItem_Notification;
m_subscription.AddItem(monitoredItem);
// add the attribute name/value to the list view.
ListViewItem item = new ListViewItem(monitoredItem.ClientHandle.ToString());
monitoredItem.Handle = item;
item.SubItems.Add(monitoredItem.DisplayName);
item.SubItems.Add(monitoredItem.MonitoringMode.ToString());
item.SubItems.Add(monitoredItem.SamplingInterval.ToString());
item.SubItems.Add(DeadbandFilterToText(monitoredItem.Filter));
item.SubItems.Add(String.Empty);
item.SubItems.Add(String.Empty);
item.SubItems.Add(String.Empty);
item.SubItems.Add(String.Empty);
item.Tag = monitoredItem;
MonitoredItemsLV.Items.Add(item);
if (ServiceResult.IsBad(monitoredItem.Status.Error))
{
item.SubItems[8].Text = monitoredItem.Status.Error.StatusCode.ToString();
}
return item;
}
/// <summary>
/// Prompts the use to write the value of a varible.
/// </summary>
private void Browse_WriteMI_Click(object sender, EventArgs e)
{
try
{
// check if operation is currently allowed.
if (m_session == null || BrowseNodesTV.SelectedNode == null)
{
return;
}
// can only subscribe to local variables.
ReferenceDescription reference = (ReferenceDescription)BrowseNodesTV.SelectedNode.Tag;
if (reference.NodeId.IsAbsolute || reference.NodeClass != NodeClass.Variable)
{
return;
}
new WriteValueDlg().ShowDialog(m_session, (NodeId)reference.NodeId, Attributes.Value);
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Handles the Click event of the Browse_ReadHistoryMI control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void Browse_ReadHistoryMI_Click(object sender, EventArgs e)
{
try
{
// check if operation is currently allowed.
if (m_session == null || BrowseNodesTV.SelectedNode == null)
{
return;
}
// can only subscribe to local variables.
ReferenceDescription reference = (ReferenceDescription)BrowseNodesTV.SelectedNode.Tag;
if (reference.NodeId.IsAbsolute || reference.NodeClass != NodeClass.Variable)
{
return;
}
new ReadHistoryDlg().ShowDialog(m_session, (NodeId)reference.NodeId);
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Updates the display with a new value for a monitored variable.
/// </summary>
private void MonitoredItem_Notification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new MonitoredItemNotificationEventHandler(MonitoredItem_Notification), monitoredItem, e);
return;
}
try
{
if (m_session == null)
{
return;
}
MonitoredItemNotification notification = e.NotificationValue as MonitoredItemNotification;
if (notification == null)
{
return;
}
ListViewItem item = (ListViewItem)monitoredItem.Handle;
item.SubItems[5].Text = Utils.Format("{0}", notification.Value.WrappedValue);
item.SubItems[6].Text = Utils.Format("{0}", notification.Value.StatusCode);
item.SubItems[7].Text = Utils.Format("{0:HH:mm:ss.fff}", notification.Value.SourceTimestamp.ToLocalTime());
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Changes the monitoring mode for the currently selected monitored items.
/// </summary>
private void Monitoring_MonitoringMode_Click(object sender, EventArgs e)
{
try
{
// check if operation is currently allowed.
if (m_session == null || m_subscription == null || MonitoredItemsLV.SelectedItems.Count == 0)
{
return;
}
// determine the monitoring mode being requested.
MonitoringMode monitoringMode = MonitoringMode.Disabled;
if (sender == Monitoring_MonitoringMode_ReportingMI)
{
monitoringMode = MonitoringMode.Reporting;
}
if (sender == Monitoring_MonitoringMode_SamplingMI)
{
monitoringMode = MonitoringMode.Sampling;
}
// update the monitoring mode.
List<MonitoredItem> itemsToChange = new List<MonitoredItem>();
for (int ii = 0; ii < MonitoredItemsLV.SelectedItems.Count; ii++)
{
MonitoredItem monitoredItem = MonitoredItemsLV.SelectedItems[ii].Tag as MonitoredItem;
if (monitoredItem != null)
{
itemsToChange.Add(monitoredItem);
}
}
// apply the changes to the server.
m_subscription.SetMonitoringMode(monitoringMode, itemsToChange);
// update the display.
for (int ii = 0; ii < itemsToChange.Count; ii++)
{
ListViewItem item = itemsToChange[ii].Handle as ListViewItem;
if (item != null)
{
item.SubItems[8].Text = String.Empty;
if (ServiceResult.IsBad(itemsToChange[ii].Status.Error))
{
item.SubItems[8].Text = itemsToChange[ii].Status.Error.StatusCode.ToString();
}
item.SubItems[2].Text = itemsToChange[ii].Status.MonitoringMode.ToString();
}
}
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Changes the sampling interval for the currently selected monitored items.
/// </summary>
private void Monitoring_SamplingInterval_Click(object sender, EventArgs e)
{
try
{
// check if operation is currently allowed.
if (m_session == null || m_subscription == null || MonitoredItemsLV.SelectedItems.Count == 0)
{
return;
}
// determine the sampling interval being requested.
double samplingInterval = 0;
if (sender == Monitoring_SamplingInterval_1000MI)
{
samplingInterval = 1000;
}
else if (sender == Monitoring_SamplingInterval_2500MI)
{
samplingInterval = 2500;
}
else if (sender == Monitoring_SamplingInterval_5000MI)
{
samplingInterval = 5000;
}
// update the monitoring mode.
List<MonitoredItem> itemsToChange = new List<MonitoredItem>();
for (int ii = 0; ii < MonitoredItemsLV.SelectedItems.Count; ii++)
{
MonitoredItem monitoredItem = MonitoredItemsLV.SelectedItems[ii].Tag as MonitoredItem;
if (monitoredItem != null)
{
monitoredItem.SamplingInterval = (int)samplingInterval;
itemsToChange.Add(monitoredItem);
}
}
// apply the changes to the server.
m_subscription.ApplyChanges();
// update the display.
for (int ii = 0; ii < itemsToChange.Count; ii++)
{
ListViewItem item = itemsToChange[ii].Handle as ListViewItem;
if (item != null)
{
item.SubItems[8].Text = String.Empty;
if (ServiceResult.IsBad(itemsToChange[ii].Status.Error))
{
item.SubItems[8].Text = itemsToChange[ii].Status.Error.StatusCode.ToString();
}
item.SubItems[3].Text = itemsToChange[ii].Status.SamplingInterval.ToString();
}
}
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Changes the deadband for the currently selected monitored items.
/// </summary>
private void Monitoring_Deadband_Click(object sender, EventArgs e)
{
try
{
// check if operation is currently allowed.
if (m_session == null || m_subscription == null || MonitoredItemsLV.SelectedItems.Count == 0)
{
return;
}
// determine the filter being requested.
DataChangeFilter filter = new DataChangeFilter();
filter.Trigger = DataChangeTrigger.StatusValue;
if (sender == Monitoring_Deadband_Absolute_5MI)
{
filter.DeadbandType = (uint)DeadbandType.Absolute;
filter.DeadbandValue = 5.0;
}
else if (sender == Monitoring_Deadband_Absolute_10MI)
{
filter.DeadbandType = (uint)DeadbandType.Absolute;
filter.DeadbandValue = 10.0;
}
else if (sender == Monitoring_Deadband_Absolute_25MI)
{
filter.DeadbandType = (uint)DeadbandType.Absolute;
filter.DeadbandValue = 25.0;
}
else if (sender == Monitoring_Deadband_Percentage_1MI)
{
filter.DeadbandType = (uint)DeadbandType.Percent;
filter.DeadbandValue = 1.0;
}
else if (sender == Monitoring_Deadband_Percentage_5MI)
{
filter.DeadbandType = (uint)DeadbandType.Percent;
filter.DeadbandValue = 5.0;
}
else if (sender == Monitoring_Deadband_Percentage_10MI)
{
filter.DeadbandType = (uint)DeadbandType.Percent;
filter.DeadbandValue = 10.0;
}
else
{
filter = null;
}
// update the monitoring mode.
List<MonitoredItem> itemsToChange = new List<MonitoredItem>();
for (int ii = 0; ii < MonitoredItemsLV.SelectedItems.Count; ii++)
{
MonitoredItem monitoredItem = MonitoredItemsLV.SelectedItems[ii].Tag as MonitoredItem;
if (monitoredItem != null)
{
monitoredItem.Filter = filter;
itemsToChange.Add(monitoredItem);
}
}
// apply the changes to the server.
m_subscription.ApplyChanges();
// update the display.
for (int ii = 0; ii < itemsToChange.Count; ii++)
{
ListViewItem item = itemsToChange[ii].Handle as ListViewItem;
if (item != null)
{
item.SubItems[8].Text = String.Empty;
if (ServiceResult.IsBad(itemsToChange[ii].Status.Error))
{
itemsToChange[ii].Filter = null;
item.SubItems[8].Text = itemsToChange[ii].Status.Error.StatusCode.ToString();
}
item.SubItems[4].Text = DeadbandFilterToText(itemsToChange[ii].Status.Filter);
}
}
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Handles the Click event of the Monitoring_DeleteMI control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void Monitoring_DeleteMI_Click(object sender, EventArgs e)
{
try
{
// check if operation is currently allowed.
if (MonitoredItemsLV.SelectedItems.Count == 0)
{
return;
}
// collect the items to delete.
List<ListViewItem> itemsToDelete = new List<ListViewItem>();
for (int ii = 0; ii < MonitoredItemsLV.SelectedItems.Count; ii++)
{
MonitoredItem monitoredItem = MonitoredItemsLV.SelectedItems[ii].Tag as MonitoredItem;
if (monitoredItem != null)
{
monitoredItem.Notification -= m_MonitoredItem_Notification;
itemsToDelete.Add(MonitoredItemsLV.SelectedItems[ii]);
if (m_subscription != null)
{
m_subscription.RemoveItem(monitoredItem);
}
}
}
// update the server.
if (m_subscription != null)
{
m_subscription.ApplyChanges();
// check the status.
for (int ii = 0; ii < itemsToDelete.Count; ii++)
{
MonitoredItem monitoredItem = itemsToDelete[ii].Tag as MonitoredItem;
if (ServiceResult.IsBad(monitoredItem.Status.Error))
{
itemsToDelete[ii].SubItems[8].Text = monitoredItem.Status.Error.StatusCode.ToString();
continue;
}
}
}
// remove the items.
for (int ii = 0; ii < itemsToDelete.Count; ii++)
{
itemsToDelete[ii].Remove();
}
MonitoredItemsLV.Columns[0].Width = -2;
MonitoredItemsLV.Columns[1].Width = -2;
MonitoredItemsLV.Columns[8].Width = -2;
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
private void BrowsingMenu_Opening(object sender, System.ComponentModel.CancelEventArgs e)
{
Browse_MonitorMI.Enabled = true;
Browse_ReadHistoryMI.Enabled = true;
Browse_WriteMI.Enabled = true;
if (m_session == null || BrowseNodesTV.SelectedNode == null)
{
Browse_MonitorMI.Enabled = false;
Browse_ReadHistoryMI.Enabled = false;
Browse_WriteMI.Enabled = false;
return;
}
ReferenceDescription reference = (ReferenceDescription)BrowseNodesTV.SelectedNode.Tag;
if (reference.NodeId.IsAbsolute || reference.NodeClass != NodeClass.Variable)
{
Browse_MonitorMI.Enabled = false;
Browse_ReadHistoryMI.Enabled = false;
Browse_WriteMI.Enabled = false;
return;
}
}
private void Monitoring_WriteMI_Click(object sender, EventArgs e)
{
try
{
// check if operation is currently allowed.
if (m_session == null || m_subscription == null || MonitoredItemsLV.SelectedItems.Count == 0)
{
return;
}
MonitoredItem monitoredItem = MonitoredItemsLV.SelectedItems[0].Tag as MonitoredItem;
if (monitoredItem != null)
{
new WriteValueDlg().ShowDialog(m_session, (NodeId)monitoredItem.ResolvedNodeId, Attributes.Value);
}
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Creates monitored items from a saved list of node ids.
/// </summary>
private void File_LoadMI_Click(object sender, EventArgs e)
{
try
{
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Saves the current monitored items.
/// </summary>
private void File_SaveMI_Click(object sender, EventArgs e)
{
try
{
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
/// <summary>
/// Sets the locale to use.
/// </summary>
private void Server_SetLocaleMI_Click(object sender, EventArgs e)
{
try
{
if (m_session == null)
{
return;
}
string locale = new SelectLocaleDlg().ShowDialog(m_session);
if (locale == null)
{
return;
}
ConnectServerCTRL.PreferredLocales = new string[] { locale };
m_session.ChangePreferredLocales(new StringCollection(ConnectServerCTRL.PreferredLocales));
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
private void Server_SetUserMI_Click(object sender, EventArgs e)
{
try
{
}
catch (Exception exception)
{
ClientUtils.HandleException(this.Text, exception);
}
}
#endregion
private void ExitToolStripMenuItem_Click(object sender, EventArgs e)
{
if (MessageBox.Show("Exit the application?", "UA Sample Client", MessageBoxButtons.YesNoCancel) == DialogResult.Yes)
{
Application.Exit();
}
}
}
}