convertersystems / opc-ua-samples

Sample HMIs using OPC Unified Architecture (OPC UA) and Visual Studio.
MIT License
107 stars 43 forks source link

Using UaTcpSessionClient constructor with EndpointDescription - MobileHmi.Droid sample does not work #15

Closed abrasat closed 7 years ago

abrasat commented 7 years ago

I tried to change the MobileHmi.Droid sample and use the UaTcpSessionClient constructor with EndpointDescription as parameter instead of the discovery URL. In this case the MobileHmi.Droid ends immediately after start. Here is what I changed in OnStart()

    protected override async void OnStart()

{ // Setup a logger. this.loggerFactory = new LoggerFactory(); this.loggerFactory.AddDebug(LogLevel.Trace); this.logger = this.loggerFactory.CreateLogger();

        bool useEndpoint = true;

        if (useEndpoint)
        {
            // discover available endpoints of server.
            var getEndpointsRequest = new GetEndpointsRequest
            {
                EndpointUrl = this.discoveryUrl,
                ProfileUris = new[] {TransportProfileUris.UaTcpTransport}
            };
            Console.WriteLine($"Discovering endpoints of '{getEndpointsRequest.EndpointUrl}'.");
            var getEndpointsResponse = await UaTcpDiscoveryClient.GetEndpointsAsync(getEndpointsRequest);
            var selectedEndpoint = getEndpointsResponse.Endpoints.OrderByDescending(e => e.SecurityLevel).First();

            // Create the session client for the app.
            this.session = new UaTcpSessionClient(
            new ApplicationDescription()
            {
                ApplicationName = "Workstation.MobileHmi",
                ApplicationUri = $"urn:{System.Net.Dns.GetHostName()}:Workstation.MobileHmi",
                ApplicationType = ApplicationType.Client
            },
            new DirectoryStore(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "pki"), loggerFactory: this.loggerFactory),
            this.ProvideUserIdentity,
            selectedEndpoint,
            this.loggerFactory);
        }
        else
        {
            // Create the session client for the app.
            this.session = new UaTcpSessionClient(
            new ApplicationDescription()
            {
                ApplicationName = "Workstation.MobileHmi",
                ApplicationUri = $"urn:{System.Net.Dns.GetHostName()}:Workstation.MobileHmi",
                ApplicationType = ApplicationType.Client
            },
            new DirectoryStore(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "pki"), loggerFactory: this.loggerFactory),
            this.ProvideUserIdentity,
            this.discoveryUrl,
            this.loggerFactory);
        }

        // Show the MainPage
        var viewModel = new MainPageViewModel(this.session);
        var view = new MainPage { BindingContext = viewModel };

        this.MainPage = new NavigationPage(view);
    }
awcullen commented 7 years ago

Apparently the base.OnStart() does not expect to be overridden with an 'async' version. You can get it to work if you remove the async keyword and change the line with the await to:

var getEndpointsResponse = UaTcpDiscoveryClient.GetEndpointsAsync(getEndpointsRequest).Result;
abrasat commented 7 years ago

Thank you for the hint. But why does the second constructor (with discovery url) work even with async OnStart ?

awcullen commented 7 years ago

I put a try / catch around the code you added. It caught a JavaException. All I could understand is that Xamarin Forms is doing a lot behind the scenes to make it easy to be cross platform.