我正在尝试与外围设备进行通信而不将其与Windows配对,我正在使用BluetoothLEAdvertisementWatcher扫描范围内的设备。这是我的WatcherOnReceived方法:
async private void WatcherOnReceived(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args)
{
BluetoothLEDevice device = null;
BluetoothDevice basicDevice = null;
GattDeviceService services = null;
if (args.Advertisement.LocalName != "Nexus 6")
return;
_watcher.Stop();
device = await BluetoothLEDevice.FromBluetoothAddressAsync(args.BluetoothAddress);
device.GattServicesChanged += Device_GattServicesChanged;
//basicDevice = await BluetoothDevice.FromBluetoothAddressAsync(args.BluetoothAddress);
//services = await GattDeviceService.FromIdAsync(device.DeviceId);
lock (m_syncObj)
{
Debug.WriteLine("");
Debug.WriteLine("----------- DEVICE --------------");
Debug.WriteLine(args.ToString());
Debug.WriteLine(args.Advertisement.DataSections.Count);
foreach (var item in args.Advertisement.DataSections)
{
var data = new byte[item.Data.Length];
using (var reader = DataReader.FromBuffer(item.Data))
{
reader.ReadBytes(data);
}
Debug.WriteLine("Manufacturer data: " + BitConverter.ToString(data));
//Debug.WriteLine("Data : " + item.Data.ToString());
//Debug.WriteLine("Data capacity: " + item.Data.Capacity);
Debug.WriteLine("Data Type: " + item.DataType);
}
foreach (var md in args.Advertisement.ManufacturerData)
{
var data = new byte[md.Data.Length];
using (var reader = DataReader.FromBuffer(md.Data))
{
reader.ReadBytes(data);
}
Debug.WriteLine("Manufacturer data: " + BitConverter.ToString(data));
}
foreach (Guid id in args.Advertisement.ServiceUuids)
{
Debug.WriteLine("UUIDs: " + id.ToString() + " Count: " + args.Advertisement.ServiceUuids.Count);
//services = device.GetGattService(id);
}
Debug.WriteLine("Receive event...");
Debug.WriteLine("BluetoothAddress: " + args.BluetoothAddress.ToString("X"));
Debug.WriteLine("Advertisement.LocalName: " + args.Advertisement.LocalName);
Debug.WriteLine("AdvertisementType: " + args.AdvertisementType);
Debug.WriteLine("RawSignalStrengthInDBm: " + args.RawSignalStrengthInDBm);
if (device != null)
{
Debug.WriteLine("Bluetooth Device: " + device.Name);
Debug.WriteLine("Bluetooth Device conn status: " + device.ConnectionStatus);
Debug.WriteLine("Bluetooth DeviceId: " + device.DeviceId);
Debug.WriteLine("Bluetooth GettServices Count: " + device.GattServices.Count);
}
}
}
当收到设备时,我从args.BlutoothAddress成功创建了BluetoothLEDevice,但是device.GattServices总是为空,因此我无法使用它们与设备通信。是设备或Windows API中的问题,还有什么可以尝试?
答案 0 :(得分:4)
更新04/17 - 创建者更新 微软刚刚更新了他们的蓝牙API。我们现在有未配对的BLE设备通讯!
目前他们的文档很少,但这是一个非常简化的新结构:
BleWatcher = new BluetoothLEAdvertisementWatcher
{
ScanningMode = BluetoothLEScanningMode.Active
};
BleWatcher.Start();
BleWatcher.Received += async (w, btAdv) => {
var device = await BluetoothLEDevice.FromBluetoothAddressAsync(btAdv.BluetoothAddress);
Debug.WriteLine($"BLEWATCHER Found: {device.name}");
// SERVICES!!
var gatt = await device.GetGattServicesAsync();
Debug.WriteLine($"{device.Name} Services: {gatt.Services.Count}, {gatt.Status}, {gatt.ProtocolError}");
// CHARACTERISTICS!!
var characs = await gatt.Services.Single(s => s.Uuid == SAMPLESERVICEUUID).GetCharacteristicsAsync();
var charac = characs.Single(c => c.Uuid == SAMPLECHARACUUID);
await charac.WriteValueAsync(SOMEDATA);
};
现在好多了。正如我所说,目前没有文档,我有一个奇怪的问题,我的ValueChanged回调在30秒左右后停止被调用,尽管这似乎是一个单独的范围问题。
更新2 - 一些不确定性
在更多关于新创作者更新的内容之后,在构建BLE应用时还需要考虑更多的事情。
您不再需要在UI线程上运行蓝牙功能。对于没有配对的BLE,似乎没有任何权限窗口,因此不再需要在UI线程上运行。 您可能会发现应用程序在一段时间后停止从设备接收更新。这是一个范围问题,在这个问题中,对象被处理掉了。在上面的代码中,如果你在charac上听ValueChanged,你可能会遇到这个问题。这是因为GattCharacteristic在它应该被处理之前被处理掉,将特征设置为全局而不是依赖于它被复制。 断开连接似乎有点破碎。退出应用程序不会终止连接。因此,请确保使用App.xml.cs OnSuspended回调来终止连接。否则你会进入一个奇怪的状态,Windows似乎维护(并继续阅读!!)BLE连接。 它有它的怪癖,但它的确有效!
这仍然是Windows Universal应用程序的一个问题,最初的问题是设备必须配对(不绑定)才能发现GattServices。但是,还需要使用Windows设备而不是BLE API来发现它们。微软已经意识到并且正在开发一种新的BLE API,它不需要配对,但坦率地说,在准备就绪之前,他们的BLE支持是无用的。
尝试在控制面板中手动配对设备,然后再次列出服务。出于某些原因,在Windows Universal Apps中,您只能列出配对设备的Gatt服务,尽管BLE的一个优点是您在使用其服务之前无需与设备配对。
您可以以编程方式配对设备,但是根据运行应用程序的平台,这需要UI提示。因此,在后台询问BLE服务是不可行的。这需要修复,因为它真的阻碍了UWP中的BLE支持。
它奇怪但是有效!
OLD ANSWER
以下是一些带有工作BLE设备连接的示例代码:
private void StartWatcher()
{
ConnectedDevices = new List<string>();
Watcher = new BluetoothLEAdvertisementWatcher { ScanningMode = BluetoothLEScanningMode.Active };
Watcher.Received += DeviceFound;
DeviceWatcher = DeviceInformation.CreateWatcher();
DeviceWatcher.Added += DeviceAdded;
DeviceWatcher.Updated += DeviceUpdated;
StartScanning();
}
private void StartScanning()
{
Watcher.Start();
DeviceWatcher.Start();
}
private async void DeviceFound(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs btAdv)
{
if (!ConnectedDevices.Contains(btAdv.Advertisement.LocalName) && _devices.Contains(btAdv.Advertisement.LocalName))
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Low, async () =>
{
var device = await BluetoothLEDevice.FromBluetoothAddressAsync(btAdv.BluetoothAddress);
if (device.GattServices.Any())
{
ConnectedDevices.Add(device.Name);
device.ConnectionStatusChanged += (sender, args) =>
{
ConnectedDevices.Remove(sender.Name);
};
SetupWaxStream(device);
} else if (device.DeviceInformation.Pairing.CanPair && !device.DeviceInformation.Pairing.IsPaired)
{
await device.DeviceInformation.Pairing.PairAsync(DevicePairingProtectionLevel.None);
}
});
}
}
private async void DeviceAdded(DeviceWatcher watcher, DeviceInformation device)
{
if (_devices.Contains(device.Name))
{
try
{
var service = await GattDeviceService.FromIdAsync(device.Id);
var characteristics = service.GetAllCharacteristics();
}
catch
{
Debug.WriteLine("Failed to open service.");
}
}
}
private async void DeviceUpdated(DeviceWatcher watcher, DeviceInformationUpdate update)
{
var device = await DeviceInformation.CreateFromIdAsync(update.Id);
if (_devices.Contains(device.Name))
{
try
{
var service = await GattDeviceService.FromIdAsync(device.Id);
var characteristics = service.GetAllCharacteristics();
}
catch
{
Debug.WriteLine("Failed to open service.");
}
}
}