My C# application uses the OPC UA Core stack as a Client to connect with a PLC running as a Server. I am not using the OPC UA SDK because the application is WPF and the SDK is incomprehensible.
I've consulted various references (including the OPC UA SDK and Converter Systems LLC WPF toolkit) and cobbled together my own method for configuring an ITransportChannel
object to pass to the Opc.UaSessionClient
constructor.
The problem I'm facing is that, in order to obtain an endpoint description and configuration that match the Server's expected values, I use the ConfiguredEndpoint.UpdateFromServer
, but this throws a ServiceResultException(BadSecureChannelClosed)
when its DiscoveryClient
object is closed.
I don't see this exception being reported by the SimpleOpClient
project included with the SDK (which is not in any way simple).
Any ideas what could be wrong with this function?
private static ITransportChannel CreateTransportChannel(
ApplicationConfiguration appConfig,
String discoveryUrl)
{
// parse the selected URL.
Uri uri = new Uri(discoveryUrl);
EndpointDescription endpointDescription = new EndpointDescription
{
EndpointUrl = uri.ToString(),
SecurityMode = MessageSecurityMode.None,
SecurityPolicyUri = "http://opcfoundation.org/UA/SecurityPolicy#None"
};
// Configure the endpoint.
ServiceMessageContext messageContext = appConfig.CreateMessageContext();
EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(appConfig);
ConfiguredEndpoint endpoint = new ConfiguredEndpoint(null, endpointDescription, endpointConfiguration);
// The server may require that the endpoint configuration be adjusted
// to match its own settings.
if (endpoint.UpdateBeforeConnect)
{
// Update endpoint description using the discovery endpoint.
// EXCEPTION thrown during this call.
endpoint.UpdateFromServer(BindingFactory.Create(appConfig, messageContext));
endpointDescription = endpoint.Description;
endpointConfiguration = endpoint.Configuration;
}
// Sanity check for the presence of required security certificates.
X509Certificate2 clientCertificate = null;
if (endpointDescription.SecurityPolicyUri != SecurityPolicies.None)
{
if (appConfig.SecurityConfiguration.ApplicationCertificate == null)
{
Utils.Trace("ApplicationCertificate missing from Configuration.");
throw ServiceResultException.Create(StatusCodes.BadConfigurationError,
"ApplicationCertificate must be specified.");
}
clientCertificate = appConfig.SecurityConfiguration.ApplicationCertificate.Find(true);
if (clientCertificate == null)
{
Utils.Trace("ApplicationCertificate file could not be found.");
throw ServiceResultException.Create(StatusCodes.BadConfigurationError,
"ApplicationCertificate cannot be found.");
}
}
// Create a transport channel.
return SessionChannel.Create(
appConfig,
endpointDescription,
endpointConfiguration,
clientCertificate,
messageContext);
}
Is it the server returning a BadSecureChannelClosed
result? If so, why? Or is it one of the multitude of internal exceptions that are thrown by the stack?