UWP应用程序在BLEWatcher重启时挂起

时间:2018-01-18 17:15:10

标签: uwp

我的应用程序是在Raspberry Pi3 SBC上运行Win 10 Iot build 10.0.17035.1000的无头UWP。有一段时间我试图在停止命令后解决BLEWatcher Start上的应用程序挂起。为了模拟我的应用程序行为,我将一些代码放在样本MS BluetoothAdvertisement解决方案中,并将其作为Raspberry Pi 3 SBC的独立应用程序运行。大约一个小时后,问题出现了 - 应用程序刚刚挂起。我认为停止当前的BluettothLEDevice BLE特性和处理这个对象可以得到改进。请告诉我,可能是什么问题。这是我的代码:public sealed partial class Scenario1_Watcher:Page     {
        // ------------------------------------------------ -------

    private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, 
                                                    BluetoothLEAdvertisementReceivedEventArgs eventArgs)
    {
        instalinkUUID = "";
        bool result = false;
        string message = "";          

        if (watcher.Status == BluetoothLEAdvertisementWatcherStatus.Started)
        {
            if (oneTime == false)
            {
                oneTime = true;
                watcher.Stop();
                rootPage.NotifyUser("BLEWatcher stopped!", NotifyType.StatusMessage);

                //
                // connect to the detected advertizing device!!!
                //
                device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);
                message = String.Format("BLE device with ID {0} is connected.", device.DeviceId);
                ETWLogging.LogToETWDiagnosticLoggingChannelProvider(message);
            }
            else
                return;
        }

        // We can obtain various information about the advertisement we just received by accessing 
        // the properties of the EventArgs class

        // The timestamp of the event
        DateTimeOffset timestamp = eventArgs.Timestamp;

        // The type of advertisement
        BluetoothLEAdvertisementType advertisementType = eventArgs.AdvertisementType;

        // The received signal strength indicator (RSSI)
        Int16 rssi = eventArgs.RawSignalStrengthInDBm;

        // The local name of the advertising device contained within the payload, if any
        string localName = eventArgs.Advertisement.LocalName;

        // Check if there are any manufacturer-specific sections.
        // If there is, print the raw data of the first manufacturer section (if there are multiple).
        string manufacturerDataString = "";
        var manufacturerSections = eventArgs.Advertisement.ManufacturerData;
        if (manufacturerSections.Count > 0)
        {
            // Only print the first one of the list
            var manufacturerData = manufacturerSections[0];
            var data = new byte[manufacturerData.Data.Length];
            using (var reader = DataReader.FromBuffer(manufacturerData.Data))
            {
                reader.ReadBytes(data);
            }
            // Print the company ID + the raw data in hex format
            manufacturerDataString = string.Format("0x{0}: {1}",
                manufacturerData.CompanyId.ToString("X"),
                BitConverter.ToString(data));
        }

        // Serialize UI update to the main UI thread
        await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            // Display these information on the list
            ReceivedAdvertisementListBox.Items.Add(string.Format("[{0}]: type={1}, rssi={2}, name={3}, manufacturerData=[{4}]",
                timestamp.ToString("yyyy MM dd hh\\:mm\\:ss\\.fff"),
                advertisementType.ToString(),
                rssi.ToString(),
                localName,
                manufacturerDataString));
        });

        //
        // simulate BLE device service processing
        //
        await Task.Delay(10000);

        //
        // disconnect BLE device
        //
        result = await DisconnectBLEDevice(device);

        message = String.Format("BLE device with ID {0} has been disconnected!", device.DeviceId);
        ETWLogging.LogToETWDiagnosticLoggingChannelProvider(message);

        if (watcher.Status == BluetoothLEAdvertisementWatcherStatus.Stopped)
        {
            watcher.Start();

            rootPage.NotifyUser("Try to start the BLEWatcher.", NotifyType.StatusMessage);

            await Task.Delay(1000);

            if (watcher.Status == BluetoothLEAdvertisementWatcherStatus.Aborted)
            {
                rootPage.NotifyUser("BLEWatcher aborted!", NotifyType.StatusMessage);

                message = "BLEWatcher aborted!";
                ETWLogging.LogToETWDiagnosticLoggingChannelProvider(message);
            }
            else if(watcher.Status == BluetoothLEAdvertisementWatcherStatus.Started)
            {
                rootPage.NotifyUser("BLEWatcher (re)started!", NotifyType.StatusMessage);
                oneTime = false;
            }
            else
            {
                rootPage.NotifyUser("BLEWatcher error!", NotifyType.StatusMessage);
            }
        }
        else if(watcher.Status == BluetoothLEAdvertisementWatcherStatus.Aborted)
        {
            rootPage.NotifyUser("BLEWatcher aborted!", NotifyType.StatusMessage);

            message = "BLEWatcher aborted!";
            ETWLogging.LogToETWDiagnosticLoggingChannelProvider(message);
        }
    }

    private async void OnAdvertisementWatcherStopped(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementWatcherStoppedEventArgs eventArgs)
    {
        string message = "";

        // Notify the user that the watcher was stopped
        await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            rootPage.NotifyUser(string.Format("Watcher stopped or aborted: {0}", eventArgs.Error.ToString()), NotifyType.StatusMessage);

            if (watcher.Status == BluetoothLEAdvertisementWatcherStatus.Aborted)
            {
                message = String.Format("Watcher aborted: {0}!!!", eventArgs.Error.ToString());
                ETWLogging.LogToETWDiagnosticLoggingChannelProvider(message);
                rootPage.NotifyUser(message, NotifyType.StatusMessage);
            }
        });
    }

    private async Task<bool> DisconnectBLEDevice(BluetoothLEDevice bleDevice)
    {
        bool result = false;
        string message = "";


        if (bleDevice == null)
        {
            message = "DisconnectBLEDevice(): BLE device is null!";
            rootPage.NotifyUser(message, NotifyType.StatusMessage);

            await Task.Delay(1000);

            return result;
        }

        try
        {
            result = await DisposeActiveServicesAndCharacteristics(device);
        }
        catch(Exception ex)
        {
            message = String.Format("DisconnectBLEDevice(): exception: {0}- FAILED", ex.ToString());
            rootPage.NotifyUser(message, NotifyType.StatusMessage);
        }
        finally
        {
            bleDevice.Dispose();
            bleDevice = null;
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
        }

        return result;
    }

    private async Task<bool> DisposeActiveServicesAndCharacteristics(
                                BluetoothLEDevice device)
    {
        bool result = false;
        string message = "";

        if (device == null)
        {
            message = string.Format("DisposeActiveServicesAndCharacteristics(): " +
                                        "BLE device with ID {0} is null!", device.DeviceId.ToString());
            rootPage.NotifyUser(message, NotifyType.StatusMessage);

            return result;
        }

        if (device.ConnectionStatus == BluetoothConnectionStatus.Disconnected)
        {
            message = string.Format("DisposeActiveServicesAndCharacteristics(): " +
                                        "BLE device with ID {0} is disconnected!", device.DeviceId.ToString());
            rootPage.NotifyUser(message, NotifyType.StatusMessage);

            return result;
        }

        try
        {
            var services = await device.GetGattServicesAsync();

            if ((services == null) || ((services.Services.Count == 0)))
            {
                message = String.Format("DisposeActiveServicesAndCharacteristics(): GATT Services " +
                                            "for Instadose device with ID {0} are incorrect.",
                                                 device.DeviceId.ToString());
                rootPage.NotifyUser(message, NotifyType.StatusMessage);
                return result;
            }

            if (services.Status == GattCommunicationStatus.Unreachable)
            {
                message = String.Format("DisposeActiveServicesAndCharacteristics(): Services " +
                                            "for Instadose device with ID {0} are unreachable.",
                                                device.DeviceId.ToString());
                rootPage.NotifyUser(message, NotifyType.StatusMessage);
                return result;
            }

            foreach (var service in services.Services)
            {
                // check if this service is active
                if (service?.Session.SessionStatus == GattSessionStatus.Active)
                {

                    // Not yet implemented in C#
                    // service?.GattSession.Close();

                    //service?.Dispose();
                }

                service?.Session?.Dispose();
                service?.Dispose();
            }

            result = true;
            message = String.Format("DisposeActiveServicesAndCharacteristics(): " +
                                        "Instadose device with ID {0} GATT " +
                                        "Services and Charteristics sucessfully disposed- PASSED",
                                            device.DeviceId.ToString());

        }
        catch (Exception ex)
        {
            message = ex.ToString();

            message = String.Format("DisposeActiveServicesAndCharacteristics(): exception: " +
                                        "{0} for device with ID {1}", message, device.DeviceId.ToString());
            rootPage.NotifyUser(message, NotifyType.StatusMessage);
        }

        return result;
    }
}

class ETWLogging
{
    static LoggingChannel lc = new LoggingChannel("My provider", null, new Guid("4bd2826e-54a1-4ba9-bf63-92b73ea1ac4a"));

    /// <summary>
    /// LogToETWDiagnosticLoggingChannelProvider
    /// </summary>
    public static void LogToETWDiagnosticLoggingChannelProvider(String message)
    {
        // get ETW trace for Device Portal display
        lc.LogMessage(message);
    }
}

0 个答案:

没有答案