无法使用 Windows 蓝牙 API 读取 BLE 特性
Unable to read BLE characteristic with Windows Bluetooth APIs
我有一个 Adafruit Bluefruit UART Friend 模块(https://learn.adafruit.com/introducing-the-adafruit-bluefruit-le-uart-friend/introduction) and i am trying to make an Universal Windows App from which i can read the bluetooth data. I followed the steps showed on the microsoft page and succesfully connected to the device but when trying to read the data from the specific RX characteristic, i get System.ArgumentException in console. I checked the flags on the characteristic and it looks like th READ flag return false, only the NOTIFY flag being true. Is it possible that I am not reading the right characteristic? I got the UUID from Adafruit site: https://learn.adafruit.com/introducing-the-adafruit-bluefruit-le-uart-friend/uart-service 这是我的 C# 代码示例:`
public static async Task connectToAddress() {
Guid guid = new Guid("6e400001b5a3f393e0a9e50e24dcca9e"); // Base UUID for UART service
Guid charachID = new Guid("6e400003b5a3f393e0a9e50e24dcca9e"); // RX characteristic UUID
deviceReference = await BluetoothLEDevice.FromBluetoothAddressAsync(_deviceAddress);
GattDeviceServicesResult result = await deviceReference.GetGattServicesAsync();
var characs = await result.Services.Single(s => s.Uuid == guid).GetCharacteristicsAsync();
var charac = characs.Characteristics.Single(c => c.Uuid == charachID);
GattCharacteristicProperties properties = charac.CharacteristicProperties;
if (properties.HasFlag(GattCharacteristicProperties.Read))
{
Debug.Write("This characteristic supports reading from it.");
}
if (properties.HasFlag(GattCharacteristicProperties.Write))
{
Debug.Write("This characteristic supports writing.");
}
if (properties.HasFlag(GattCharacteristicProperties.Notify))
{
Debug.Write("This characteristic supports subscribing to notifications.");
}
GattReadResult data = await charac.ReadValueAsync();
Debug.WriteLine("DATA: " + data.ToString());
charac.ValueChanged += Characteristic_ValueChanged;
}`
因为刚连接就在读数据,所以可能没有什么可读的。
你的 Bledevice 是一个 UART 服务,所以我相信它会发送一个通知让你知道有东西要读,或者数据在通知本身。
如果数据在通知中,从Charac_ValueChanged事件中的GattValueChangedEventArgs获取。
否则在 Charac_ValueChanged.
中阅读
您收到的数据为IBuffer格式。要将 IBuffer 转换为字符串,我将在代码示例中展示。
使用 Windows.Security.Cryptographyto 添加您的代码。
代码示例编译正常,但不要指望它能工作 "out of the box",我看不到您的其余代码,也无法访问 Ble 设备。
使用调试器并设置断点来检查代码。
static GattCharacteristic charac = null;
public static async Task connectToAddress()
{
Guid guid = new Guid("6e400001b5a3f393e0a9e50e24dcca9e"); // Base UUID for UART service
Guid charachID = new Guid("6e400003b5a3f393e0a9e50e24dcca9e"); // RX characteristic UUID
deviceReference = await BluetoothLEDevice.FromBluetoothAddressAsync(_deviceAddress);
GattDeviceServicesResult result = await deviceReference.GetGattServicesAsync();
//Allways check result!
if (result.Status == GattCommunicationStatus.Success)
{
//Put following two lines in try/catch to or check for null!!
var characs = await result.Services.Single(s => s.Uuid == guid).GetCharacteristicsAsync();
//Make charac a field so you can use it in Charac_ValueChanged.
charac = characs.Characteristics.Single(c => c.Uuid == charachID);
GattCharacteristicProperties properties = charac.CharacteristicProperties;
if (properties.HasFlag(GattCharacteristicProperties.Read))
{
Debug.Write("This characteristic supports reading from it.");
}
if (properties.HasFlag(GattCharacteristicProperties.Write))
{
Debug.Write("This characteristic supports writing.");
}
if (properties.HasFlag(GattCharacteristicProperties.Notify))
{
Debug.Write("This characteristic supports subscribing to notifications.");
}
try
{
//Write the CCCD in order for server to send notifications.
var notifyResult = await charac.WriteClientCharacteristicConfigurationDescriptorAsync(
GattClientCharacteristicConfigurationDescriptorValue.Notify);
if (notifyResult == GattCommunicationStatus.Success)
{
Debug.Write("Successfully registered for notifications");
}
else
{
Debug.Write($"Error registering for notifications: {notifyResult}");
}
}
catch (UnauthorizedAccessException ex)
{
Debug.Write(ex.Message);
}
charac.ValueChanged += Charac_ValueChangedAsync; ;
}
else
{
Debug.Write("No services found");
}
}
private static async void Charac_ValueChangedAsync(GattCharacteristic sender, GattValueChangedEventArgs args)
{
CryptographicBuffer.CopyToByteArray(args.CharacteristicValue, out byte[] data);
string dataFromNotify;
try
{
//Asuming Encoding is in ASCII, can be UTF8 or other!
dataFromNotify = Encoding.ASCII.GetString(data);
Debug.Write(dataFromNotify);
}
catch (ArgumentException)
{
Debug.Write("Unknown format");
}
GattReadResult dataFromRead = await charac.ReadValueAsync();
CryptographicBuffer.CopyToByteArray(dataFromRead.Value, out byte[] dataRead);
string dataFromReadResult;
try
{
//Asuming Encoding is in ASCII, can be UTF8 or other!
dataFromReadResult = Encoding.ASCII.GetString(dataRead);
Debug.Write("DATA FROM READ: " + dataFromReadResult);
}
catch (ArgumentException)
{
Debug.Write("Unknown format");
}
}
也没有必要让你的方法静态化。我保留了 dat 原样,因此更容易将它与您的代码进行比较。
希望对您有所帮助。
我有一个 Adafruit Bluefruit UART Friend 模块(https://learn.adafruit.com/introducing-the-adafruit-bluefruit-le-uart-friend/introduction) and i am trying to make an Universal Windows App from which i can read the bluetooth data. I followed the steps showed on the microsoft page and succesfully connected to the device but when trying to read the data from the specific RX characteristic, i get System.ArgumentException in console. I checked the flags on the characteristic and it looks like th READ flag return false, only the NOTIFY flag being true. Is it possible that I am not reading the right characteristic? I got the UUID from Adafruit site: https://learn.adafruit.com/introducing-the-adafruit-bluefruit-le-uart-friend/uart-service 这是我的 C# 代码示例:`
public static async Task connectToAddress() {
Guid guid = new Guid("6e400001b5a3f393e0a9e50e24dcca9e"); // Base UUID for UART service
Guid charachID = new Guid("6e400003b5a3f393e0a9e50e24dcca9e"); // RX characteristic UUID
deviceReference = await BluetoothLEDevice.FromBluetoothAddressAsync(_deviceAddress);
GattDeviceServicesResult result = await deviceReference.GetGattServicesAsync();
var characs = await result.Services.Single(s => s.Uuid == guid).GetCharacteristicsAsync();
var charac = characs.Characteristics.Single(c => c.Uuid == charachID);
GattCharacteristicProperties properties = charac.CharacteristicProperties;
if (properties.HasFlag(GattCharacteristicProperties.Read))
{
Debug.Write("This characteristic supports reading from it.");
}
if (properties.HasFlag(GattCharacteristicProperties.Write))
{
Debug.Write("This characteristic supports writing.");
}
if (properties.HasFlag(GattCharacteristicProperties.Notify))
{
Debug.Write("This characteristic supports subscribing to notifications.");
}
GattReadResult data = await charac.ReadValueAsync();
Debug.WriteLine("DATA: " + data.ToString());
charac.ValueChanged += Characteristic_ValueChanged;
}`
因为刚连接就在读数据,所以可能没有什么可读的。
你的 Bledevice 是一个 UART 服务,所以我相信它会发送一个通知让你知道有东西要读,或者数据在通知本身。
如果数据在通知中,从Charac_ValueChanged事件中的GattValueChangedEventArgs获取。 否则在 Charac_ValueChanged.
中阅读您收到的数据为IBuffer格式。要将 IBuffer 转换为字符串,我将在代码示例中展示。 使用 Windows.Security.Cryptographyto 添加您的代码。
代码示例编译正常,但不要指望它能工作 "out of the box",我看不到您的其余代码,也无法访问 Ble 设备。 使用调试器并设置断点来检查代码。
static GattCharacteristic charac = null;
public static async Task connectToAddress()
{
Guid guid = new Guid("6e400001b5a3f393e0a9e50e24dcca9e"); // Base UUID for UART service
Guid charachID = new Guid("6e400003b5a3f393e0a9e50e24dcca9e"); // RX characteristic UUID
deviceReference = await BluetoothLEDevice.FromBluetoothAddressAsync(_deviceAddress);
GattDeviceServicesResult result = await deviceReference.GetGattServicesAsync();
//Allways check result!
if (result.Status == GattCommunicationStatus.Success)
{
//Put following two lines in try/catch to or check for null!!
var characs = await result.Services.Single(s => s.Uuid == guid).GetCharacteristicsAsync();
//Make charac a field so you can use it in Charac_ValueChanged.
charac = characs.Characteristics.Single(c => c.Uuid == charachID);
GattCharacteristicProperties properties = charac.CharacteristicProperties;
if (properties.HasFlag(GattCharacteristicProperties.Read))
{
Debug.Write("This characteristic supports reading from it.");
}
if (properties.HasFlag(GattCharacteristicProperties.Write))
{
Debug.Write("This characteristic supports writing.");
}
if (properties.HasFlag(GattCharacteristicProperties.Notify))
{
Debug.Write("This characteristic supports subscribing to notifications.");
}
try
{
//Write the CCCD in order for server to send notifications.
var notifyResult = await charac.WriteClientCharacteristicConfigurationDescriptorAsync(
GattClientCharacteristicConfigurationDescriptorValue.Notify);
if (notifyResult == GattCommunicationStatus.Success)
{
Debug.Write("Successfully registered for notifications");
}
else
{
Debug.Write($"Error registering for notifications: {notifyResult}");
}
}
catch (UnauthorizedAccessException ex)
{
Debug.Write(ex.Message);
}
charac.ValueChanged += Charac_ValueChangedAsync; ;
}
else
{
Debug.Write("No services found");
}
}
private static async void Charac_ValueChangedAsync(GattCharacteristic sender, GattValueChangedEventArgs args)
{
CryptographicBuffer.CopyToByteArray(args.CharacteristicValue, out byte[] data);
string dataFromNotify;
try
{
//Asuming Encoding is in ASCII, can be UTF8 or other!
dataFromNotify = Encoding.ASCII.GetString(data);
Debug.Write(dataFromNotify);
}
catch (ArgumentException)
{
Debug.Write("Unknown format");
}
GattReadResult dataFromRead = await charac.ReadValueAsync();
CryptographicBuffer.CopyToByteArray(dataFromRead.Value, out byte[] dataRead);
string dataFromReadResult;
try
{
//Asuming Encoding is in ASCII, can be UTF8 or other!
dataFromReadResult = Encoding.ASCII.GetString(dataRead);
Debug.Write("DATA FROM READ: " + dataFromReadResult);
}
catch (ArgumentException)
{
Debug.Write("Unknown format");
}
}
也没有必要让你的方法静态化。我保留了 dat 原样,因此更容易将它与您的代码进行比较。
希望对您有所帮助。