A specialized client object builds on top of a general-purpose client object (such as EasyUAClient) and provides functionality that is relevant for specific problem domain. It contains, in a sense, pre-packaged pieces of reusable code that the developer would typically need to write, whenever he needs to develop a solution for that problem domain.
In OPC UA, the problem domain addressed by the specialized client object is often a selected part of the OPC UA specification. This is due to the layered architecture of OPC UA, where additional informational models can be used to enhance the functionality and address new problem domains, while the basic set of services (covered by the general-purpose client object) remains static and relatively small.
Specialized Client Derivation
A specialized client object can be created from an existing general-purpose client (such as when you have the IEasyUAClient Interface) using so-called derivation. For derivation, there is a method (or an extension method) on the general-purpose client, that returns the specialized client needed. For example, you can call the AsGlobalDiscoveryClient (Extension) Method on the IEasyUAClient Interface, and you will receive back a specialized client object for OPC UA global discovery.
A specialized client object created using derivation performs its operations using the general-purpose client object that it was derived from, and therefore also uses all its settings, always shares the same connections, etc. You can then think of the specialized client simply as a functionality extension of the general-purpose client object.
It is recommended that you use the specialized client derivation whenever you have a suitable general-purpose client object available.
Standalone Specialized Clients
A specialized client object can also be created standalone, without having a general-purpose client object first. This is done simply by instantiating the specialized client object, e.g. EasyUAGlobalDiscoveryClient. When created in this way, the specialized client object will use an internal general-purpose client to perform its operations. The parameters of such general-purpose client object, if they are of interest to you, are available in the ClientSelector Property of the specialized client. Note that if you want to change any of these parameters, you must do so before you perform the first operation on the specialized client object. Also note that the internal general-purpose client object may be used for multiple purposes by QuickOPC.
The example below uses a standalone specialized client object to perform OPC UA global discovery operation.
.NET
// Shows how to unregister all clients from a GDS.
using System;
using System.Collections.Generic;
using System.Linq;
using OpcLabs.BaseLib.Collections.Generic.Extensions;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.AddressSpace;
using OpcLabs.EasyOpc.UA.Discovery;
using OpcLabs.EasyOpc.UA.Extensions;
using OpcLabs.EasyOpc.UA.Gds;
using OpcLabs.EasyOpc.UA.OperationModel;
namespace UADocExamples.Gds._EasyUAGlobalDiscoveryClient
{
class UnregisterApplication
{
public static void Main1()
{
// Define which GDS we will work with.
UAEndpointDescriptor gdsEndpointDescriptor =
((UAEndpointDescriptor)"opc.tcp://opcua.demo-this.com:58810/GlobalDiscoveryServer")
.WithUserNameIdentity("appadmin", "demo");
// Instantiate the global discovery client object
var globalDiscoveryClient = new EasyUAGlobalDiscoveryClient();
// Find application IDs of all client applications registered in the GDS.
var clientApplicationIds = new HashSet<UANodeId>();
try
{
globalDiscoveryClient.QueryApplications(
gdsEndpointDescriptor: gdsEndpointDescriptor,
startingRecordId: 0,
maximumRecordsToReturn: 0,
applicationName: "",
applicationUriString: "",
applicationTypes: UAApplicationTypes.Client,
productUriString: "",
serverCapabilities: new string[0],
lastCounterResetTime: out _,
nextRecordId: out _,
applications: out UAApplicationDescription[] applicationDescriptionArray);
foreach (UAApplicationDescription applicationDescription in applicationDescriptionArray)
{
var applicationRecordArray = globalDiscoveryClient.FindApplications(
gdsEndpointDescriptor,
applicationDescription.ApplicationUriString);
clientApplicationIds.AddRange(applicationRecordArray.Select(description => description.ApplicationId));
}
}
catch (UAException uaException)
{
Console.WriteLine("*** Failure: {0}", uaException.GetBaseException().Message);
return;
}
// Unregister all client applications found.
foreach (UANodeId applicationId in clientApplicationIds)
{
Console.WriteLine();
Console.WriteLine("Application ID: {0}", applicationId);
try
{
globalDiscoveryClient.UnregisterApplication(gdsEndpointDescriptor, applicationId);
}
catch (UAException uaException)
{
Console.WriteLine("*** Failure: {0}", uaException.GetBaseException().Message);
continue;
}
Console.WriteLine("Unregistered.");
}
}
}
}
# Shows how to unregister all clients from a GDS.
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc
# Import .NET namespaces.
from System import *
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.Discovery import *
from OpcLabs.EasyOpc.UA.Extensions import *
from OpcLabs.EasyOpc.UA.Gds import *
from OpcLabs.EasyOpc.UA.OperationModel import *
# Define which GDS we will work with.
gdsEndpointDescriptor = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:58810/GlobalDiscoveryServer')
gdsEndpointDescriptor = UAEndpointDescriptorExtension.WithUserNameIdentity(gdsEndpointDescriptor,
'appadmin', 'demo')
# Instantiate the global discovery client object.
globalDiscoveryClient = EasyUAGlobalDiscoveryClient()
# Find application IDs of all client applications registered in the GDS.
clientApplicationIds = set()
try:
_, _, _, applicationDescriptionArray = globalDiscoveryClient.QueryApplications(
gdsEndpointDescriptor,
0, # startingRecordId
0, # maximumRecordsToReturn
'', # applicationName
'', # applicationUriString
UAApplicationTypes.Client, # applicationTypes
'', # productUriString
Array.Empty[String](), # serverCapabilities
DateTime(), # out lastCounterResetTime
0, # out nextRecordId
Array.Empty[UAApplicationDescription]()) # out applications
for applicationDescription in applicationDescriptionArray:
applicationRecordArray = globalDiscoveryClient.FindApplications(
gdsEndpointDescriptor,
applicationDescription.ApplicationUriString)
for applicationRecord in applicationRecordArray:
clientApplicationIds.add(applicationRecord.ApplicationId)
except UAException as uaException:
print('*** Failure: ' + uaException.GetBaseException().Message)
exit()
# Unregister all client applications found.
for applicationId in clientApplicationIds:
print()
print('Application ID: ', applicationId, sep='')
try:
globalDiscoveryClient.UnregisterApplication(gdsEndpointDescriptor, applicationId)
except UAException as uaException:
print('*** Failure: ' + uaException.GetBaseException().Message)
continue
print('Application unregistered.')
print()
print('Finished.')
' Shows how to unregister all clients from a GDS.
Imports System.Linq
Imports OpcLabs.BaseLib.Collections.Generic.Extensions
Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.AddressSpace
Imports OpcLabs.EasyOpc.UA.Discovery
Imports OpcLabs.EasyOpc.UA.Extensions
Imports OpcLabs.EasyOpc.UA.Gds
Imports OpcLabs.EasyOpc.UA.OperationModel
Namespace Gds._EasyUAGlobalDiscoveryClient
Friend Class UnregisterApplication
Public Shared Sub Main1()
' Define which GDS we will work with.
Dim gdsEndpointDescriptor As UAEndpointDescriptor =
New UAEndpointDescriptor("opc.tcp://opcua.demo-this.com:58810/GlobalDiscoveryServer") _
.WithUserNameIdentity("appadmin", "demo")
' Instantiate the global discovery client object
Dim globalDiscoveryClient = New EasyUAGlobalDiscoveryClient()
' Find application IDs of all client applications registered in the GDS.
Dim clientApplicationIds = New HashSet(Of UANodeId)
Try
Dim lastCounterResetTime As DateTime
Dim nextRecordId As Long
Dim applicationDescriptionArray() As UAApplicationDescription = Nothing
globalDiscoveryClient.QueryApplications(
gdsEndpointDescriptor:=gdsEndpointDescriptor,
startingRecordId:=0,
maximumRecordsToReturn:=0,
applicationName:="",
applicationUriString:="",
applicationTypes:=UAApplicationTypes.Client,
productUriString:="",
serverCapabilities:=New String() {},
lastCounterResetTime:=lastCounterResetTime,
nextRecordId:=nextRecordId,
applications:=applicationDescriptionArray)
For Each applicationDescription As UAApplicationDescription In applicationDescriptionArray
Dim applicationRecordArray = globalDiscoveryClient.FindApplications(
gdsEndpointDescriptor,
applicationDescription.ApplicationUriString)
clientApplicationIds.AddRange(applicationRecordArray.Select(Function(description) description.ApplicationId))
Next applicationDescription
Catch uaException As UAException
Console.WriteLine("*** Failure: {0}", uaException.GetBaseException.Message)
Exit Sub
End Try
' Unregister all client applications found.
For Each applicationId As UANodeId In clientApplicationIds
Console.WriteLine()
Console.WriteLine("Application ID: {0}", applicationId)
Try
globalDiscoveryClient.UnregisterApplication(gdsEndpointDescriptor, applicationId)
Catch uaException As UAException
Console.WriteLine("*** Failure: {0}", uaException.GetBaseException.Message)
Continue For
End Try
Console.WriteLine("Unregistered.")
Next applicationId
End Sub
End Class
End Namespace
COM
// Shows how to unregister all clients from a GDS.
class procedure UnregisterApplication.Main;
var
ApplicationDescription: _UAApplicationDescription;
ApplicationDescriptionArray: OleVariant;
ApplicationId: _UANodeId;
ApplicationName: WideString;
ApplicationRecord: _UAApplicationRecordDataType;
ApplicationRecordArray: OleVariant;
ApplicationUriString: WideString;
ClientApplicationIds: TList<_UANodeID>;
GlobalDiscoveryClient: OpcLabs_EasyOpcUA_TLB._EasyUAGlobalDiscoveryClient;
GdsEndpointDescriptor: _UAEndpointDescriptor;
I, J: integer;
LastCounterResetTime: TDateTime;
MaximumRecordsToReturn: Integer;
NextRecordId: Integer;
ProductUriString: WideString;
ServerCapabilities: array of string;
StartingRecordId: Integer;
begin
// Define which GDS we will work with.
GdsEndpointDescriptor := CoUAEndpointDescriptor.Create;
GdsEndpointDescriptor.UrlString := 'opc.tcp://opcua.demo-this.com:58810/GlobalDiscoveryServer';
GdsEndpointDescriptor.UserIdentity.UserNameTokenInfo.UserName := 'appadmin';
GdsEndpointDescriptor.UserIdentity.UserNameTokenInfo.Password := 'demo';
// Instantiate the global discovery client object
GlobalDiscoveryClient := CoEasyUAGlobalDiscoveryClient.Create;
// Find application IDs of all client applications registered in the GDS.
ClientApplicationIds := TList<_UANodeID>.Create();
StartingRecordId := 0;
MaximumRecordsToReturn := 0;
ApplicationName := '';
ApplicationUriString := '';
ProductUriString := '';
try
GlobalDiscoveryClient.QueryApplications(
GdsEndpointDescriptor,
StartingRecordId,
MaximumRecordsToReturn,
ApplicationName,
ApplicationUriString,
UAApplicationTypes_Client,
ProductUriString,
ServerCapabilities,
LastCounterResetTime,
NextRecordId,
ApplicationDescriptionArray);
for I := VarArrayLowBound(ApplicationDescriptionArray,1) to VarArrayHighBound(ApplicationDescriptionArray,1) do
begin
ApplicationDescription := IUnknown(ApplicationDescriptionArray[I]) as _UAApplicationDescription;
TVarData(ApplicationRecordArray).VType := varArray or varVariant;
TVarData(ApplicationRecordArray).VArray := PVarArray(GlobalDiscoveryClient.FindApplications(
GdsEndpointDescriptor, ApplicationDescription.ApplicationUriString));
for J := VarArrayLowBound(ApplicationRecordArray,1) to VarArrayHighBound(ApplicationRecordArray,1) do
begin
ApplicationRecord := IUnknown(ApplicationRecordArray[J]) as _UAApplicationRecordDataType;
ClientApplicationIds.Add(ApplicationRecord.ApplicationId);
end;
end;
except
on E: EOleException do
begin
WriteLn(Format('*** Failure: %s', [E.GetBaseException.Message]));
end;
end;
// Unregister all client applications found.
for ApplicationId in ClientApplicationIds do
begin
WriteLn;
WriteLn('Application ID: ', ApplicationId.ToString);
try
GlobalDiscoveryClient.UnregisterApplication(
GdsEndpointDescriptor, ApplicationId);
except
on E: EOleException do
begin
WriteLn(Format('*** Failure: %s', [E.GetBaseException.Message]));
Continue;
end;
end;
WriteLn('Unregistered.');
end;
FreeAndNil(ClientApplicationIds);
end;
Visual Studio Toolbox
The standalone specialized clients are also available as icons in the Visual Studio Toolbox. This means that in certain types of projects, they can be dragged from the Toolbox to the design surface, and Visual Studio will create code to instantiate and configure the specialized client object. Component properties are then also editable from the Visual Studio (in the Properties tool window).
Reverting to the General-Purpose Client Object
In a similar as you can derive a specialized client object from a general-purpose client, you can go in the opposite direction. If you have a specialized client object at hand, you can use its AsClient method to obtain the client object upon which the specialized client is built. If the specialized client object has been derived from a general-purpose client, this method returns the original general-purpose client object used in derivation. If the specialized client object us standalone, this method returns the internal general-purpose client object used by this specialized client.
The IsDerived Property determines whether a given specialized client object has been derived from a general-purpose client object.
Specialized Clients Catalog
There are currently following specialized client objects available:
The features discussed here, or some of them, may not be available in all editions of the product. Check the
Product Editions page for differences between the editions. The trial license has all features enabled (and is limited in period for which it provides valid data), but licenses for specific commercial editions may have functionality limitations.
See Also
Examples - OPC UA File Transfer