为什么将"Gatt特性"设置为“值已更改",为什么值未在预期范围内 [英] Why value does not fall within the expected range when setting Value Changed for Gatt Characteristic

查看:176
本文介绍了为什么将"Gatt特性"设置为“值已更改",为什么值未在预期范围内的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过在Visual Studio 2017的Universal Windows Platform C#中使用ValueChanged回调,继续从BLE 4.0设备中读取特征的特征/设置值更改的事件处理程序.

I would like to keep on reading characteristic/set value changed event handlers for characteristics from my BLE 4.0 device, by using the ValueChanged callback in Universal Windows Platform C# in Visual Studio 2017.

我遵循了这些网站的一些教程: Damian Blog's带有BLE的Windows Universal 蓝牙Gatt的Git Hub 蓝牙通用属性配置文件-心率服务博士. Jukka在BLE上的移动博客.他们所有人都在使用ValueChanged,而我尝试遵循他们所做的.

I followed some tutorial from these sites: Damian Blog's Windows Universal with BLE, Bluetooth Gatt's Git Hub, Bluetooth Generic Attribute Profile - Heart Rate Service and Dr. Jukka's mobile Blog on BLE. All of them are using ValueChanged and I have tried to follow what they did.

不幸的是,使用ValueChanged回调时,我收到以下错误,而不是触发ValueChanged.

Unfortunately, instead of ValueChanged being triggered, I receive the following error when using the ValueChanged callback.

System.ArgumentException: 'Value does not fall within the expected range.'

这行代码产生了错误:

characteristic.ValueChanged += Oncharacteristic_ValueChanged;

这是我的源代码的更多详细信息:

Here is more details of my source code:

注意::我正在使用COM 7作为加密狗,并且我的程序可以发现BLE的设备名称,并且可以发现服务和特征的Uuid.

NOTE: I am using COM 7 for my dongler and my program could discover the BLE's device name, and could discover the Uuid of the services and characteristics.

    public List<string> serviceList = new List<string>();
    public List<string> characteristicList = new List<string>();
    public BluetoothLEDevice myDevice { get; set; }

    public MainPage()
    {
        this.InitializeComponent();
    }

        private async void Page_Loaded(object sender, RoutedEventArgs e)
    {
        // Find the com port
        string selector = SerialDevice.GetDeviceSelector("COM7");
        DeviceInformationCollection devices = await DeviceInformation.FindAllAsync(selector);
        if (devices.Count > 0)
        {
            var dialog = new MessageDialog("Com Device found");
            await dialog.ShowAsync();

            DeviceInformation deviceInfo = devices[0];
            SerialDevice serialDevice = await SerialDevice.FromIdAsync(deviceInfo.Id);
            serialDevice.BaudRate = 9600;
            serialDevice.DataBits = 8;
            serialDevice.StopBits = SerialStopBitCount.One;
            serialDevice.Parity = SerialParity.None;
        }
        else
        {
            MessageDialog popup = new MessageDialog("Sorry, no device found.");
            await popup.ShowAsync();
        }

        // After com port is found, search for device
        foreach (DeviceInformation di in await DeviceInformation.FindAllAsync(BluetoothLEDevice.GetDeviceSelector()))
        {
            BluetoothLEDevice bleDevice = await BluetoothLEDevice.FromIdAsync(di.Id);

            // Display BLE device name
            var dialogBleDeviceName = new MessageDialog("BLE Device Name " + bleDevice.Name);
            await dialogBleDeviceName.ShowAsync();

            myDevice = bleDevice;
        }

        // Check device connection
        myDevice.ConnectionStatusChanged += OnConnectionStatusChanged;

        foreach (var service in myDevice.GattServices)
        {
            serviceList.Add(service.Uuid.ToString());

            // Verify if service is discovered by displaying a popup
            MessageDialog serviceUuidPopUp = new MessageDialog("Adding Service Uuid to list " + service.Uuid.ToString() );
            await serviceUuidPopUp.ShowAsync();

            foreach (var characteristic in service.GetAllCharacteristics())
            {
                var characteristicUuid = characteristic.Uuid.ToString().ToLowerInvariant();
                characteristicList.Add(characteristicUuid);

                // Verify if characteristic is discovered by displaying a popup 
                MessageDialog charUuidPopUp = new MessageDialog("Adding characteristic Uuid to list " + characteristicUuid);
                await charUuidPopUp.ShowAsync();

                // set value changed event handlers for characteristics
                characteristic.ValueChanged += Oncharacteristic_ValueChanged;

            }
        }
    }

    private void OnConnectionStatusChanged(BluetoothLEDevice sender, object args)
    {
        if (sender.ConnectionStatus == BluetoothConnectionStatus.Connected)
        {
            System.Diagnostics.Debug.WriteLine("Connected");
        }
        else
        {
            System.Diagnostics.Debug.WriteLine("Disconnected");
        }
    }    

    private void Oncharacteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
    {
        byte[] data = new byte[args.CharacteristicValue.Length];
        DataReader.FromBuffer(
            args.CharacteristicValue).ReadBytes(data);
        string text = Encoding.UTF8.GetString(data, 0, data.Length);
    }

更新1 我尝试按照不幸的是,该IF语句未执行.

Unfortunately, this IF statement is not executed.

更新2 我试图删除 Oncharacteristic_ValueChanged 方法中的 ALL 代码.但这仍然给我同样的错误

UPDATE 2 I have tried to remove ALL the codes inside Oncharacteristic_ValueChanged method. But it still gives me the same error

System.ArgumentException: 'Value does not fall within the expected range.'

我一直在花很多时间尝试解决这个问题.如果有人可以帮助我,我将非常高兴.谢谢!

I have been spending a lot of time trying to solve this problem. I will be very happy if anyone can help me on this. Thank you!

推荐答案

在阅读前一个问题中的工作后,我可以提供一个有效的示例,但首先提供一些解释. 不需要 myDevice.ConnectionStatusChanged ,它仅用于通知连接丢失或已连接.您必须先连接到设备,然后使用连接方法进行处理.

Reading your efforts in the former question I can provide a working example, but first some explanation. myDevice.ConnectionStatusChanged is not needed, it is only used to notice a connection is lost or connected. You have to connect to your device first and handle things in the connection method.

成功连接后,您必须获得包含要用于读取,写入,通知或指示的特征的服务.

After you have succeeded in connecting you have to get the service that contains the characteristic you want to use for read, write, notify or indicate.

选择服务后,您可以获取该服务的特征.

When you have selected the service You can get the characteristics of that service.

通过 Uuid 选择特征,或者在我的示例中为 CharacteristicProperties.HasFlag . 在我的示例中,该标记为通知. 在代码注释中,您会找到更多信息.

Select the characteristic by Uuid, or in my example with CharacteristicProperties.HasFlag. This flag in my example is Notify. In the code comments you find extra info.

using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Devices.Enumeration;
using Windows.UI.Popups;
using Windows.UI.Xaml.Controls;

namespace App1
{
public sealed partial class MainPage : Page
{
   GattDeviceServicesResult serviceResult = null;
  private BluetoothLEDevice myDevice;
  private GattCharacteristic selectedCharacteristic;

  public MainPage()
  {
     this.InitializeComponent();
     ConnectDevice();
  }

  private async void ConnectDevice()
  {
     //This works only if your device is already paired!
     foreach (DeviceInformation di in await DeviceInformation.FindAllAsync(BluetoothLEDevice.GetDeviceSelector()))
     {
        BluetoothLEDevice bleDevice = await BluetoothLEDevice.FromIdAsync(di.Id);
        // Display BLE device name
        var dialogBleDeviceName = new MessageDialog("BLE Device Name " + bleDevice.Name);
        await dialogBleDeviceName.ShowAsync();
        myDevice = bleDevice;
     }

     if (myDevice != null)
     {
        int servicesCount = 3;//Fill in the amount of services from your device!!!!!
        int tryCount = 0;
        bool connected = false;
        while (!connected)//This is to make sure all services are found.
        {
           tryCount++;
           serviceResult = await myDevice.GetGattServicesAsync();
           if (serviceResult.Status == GattCommunicationStatus.Success && serviceResult.Services.Count >= servicesCount)
           {
              connected = true;
              Debug.WriteLine("Connected in " + tryCount + " tries");
           }
           if (tryCount > 5)//make this larger if faild
           {
              Debug.WriteLine("Failed to connect to device ");
              return;
           }
        }
        if (connected)
        {
           for (int i = 0; i < serviceResult.Services.Count; i++)
           {
              var service = serviceResult.Services[i];
              //This must be the service that contains the Gatt-Characteristic you want to read from or write to !!!!!!!.
              string myServiceUuid = "0000ffe0-0000-1000-8000-00805f9b34fb";
              if (service.Uuid.ToString() == myServiceUuid)
              {
                 Get_Characteriisics(service);
                 break;
              }
           }
        }
     }
  }
  private async void Get_Characteriisics(GattDeviceService myService)
  {
     var CharResult = await myService.GetCharacteristicsAsync();
     if (CharResult.Status == GattCommunicationStatus.Success)
     {
        foreach (GattCharacteristic c in CharResult.Characteristics)
        {
           if (c.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Notify))
           {
              selectedCharacteristic = c;
              break;
           }
        }
        try
        {
           // Write the ClientCharacteristicConfigurationDescriptor in order for server to send notifications.               
           var result = await selectedCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(
                                                     GattClientCharacteristicConfigurationDescriptorValue.Notify);
           if (result == GattCommunicationStatus.Success)
           {
              var dialogNotifications = new MessageDialog("Successfully registered for notifications");
              await dialogNotifications.ShowAsync();
              selectedCharacteristic.ValueChanged += SelectedCharacteristic_ValueChanged;
           }
           else
           {
              var dialogNotifications = new MessageDialog($"Error registering for notifications: {result}");
              await dialogNotifications.ShowAsync();
           }
        }
        catch (Exception ex)
        {
           // This usually happens when not all characteristics are found
           // or selected characteristic has no Notify.
           var dialogNotifications = new MessageDialog(ex.Message);
           await dialogNotifications.ShowAsync();
           await Task.Delay(100);
           Get_Characteriisics(myService); //try again
           //!!! Add a max try counter to prevent infinite loop!!!!!!!
        }
     }
     else
     {
        var dialogNotifications = new MessageDialog("Restricted service. Can't read characteristics");
        await dialogNotifications.ShowAsync();
     }
  }

  private void SelectedCharacteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
  {

  }
 }
}

如果您对此代码有疑问,请随时在注释中提问.

If you have problems with this code feel free to ask in comments.

这篇关于为什么将"Gatt特性"设置为“值已更改",为什么值未在预期范围内的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆