В настоящей статье рассмотрим как использовать в своих приложениях на С Sharp BLE в Windows. Напишем небольшую программу по сканированию BLE устройств. Подключимся к сервису и прочитаем его характеристики.
Подключение библиотеки BLE
Для того, что бы иметь возможность работать с BLE в windows, в разделе using подключите следующее пространство имен
using Windows.Devices.Bluetooth.Advertisement;
using Windows.Devices.Bluetooth;
ВНИМАНИЕ! Данное пространство имен можно использовать только в Windows 10 и выше.
Сканирование BLE в Windows
Рассмотрим пример кода на C Sharp по сканированию BLE устройств.
private BluetoothLEAdvertisementWatcher _watcher; private Dictionary<ulong, BluetoothLEDevice> _devices; private BluetoothLEDevice dev; private List<String> AdressBLE = new List<String>(); private void btnSearchBLE_Click(object sender, EventArgs e) { listDevice.Items.Clear(); AdressBLE.Clear(); _devices.Clear(); if (_watcher == null) _watcher = new BluetoothLEAdvertisementWatcher(); _watcher.Stop(); _watcher.SignalStrengthFilter.InRangeThresholdInDBm = -110; _watcher.SignalStrengthFilter.OutOfRangeThresholdInDBm = -110; _watcher.ScanningMode = BluetoothLEScanningMode.Active; _watcher.Received += Wather_Recived; _watcher.Start(); } private async void Wather_Recived(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args) { dev = await BluetoothLEDevice.FromBluetoothAddressAsync(args.BluetoothAddress); if (dev != null) { if (!_devices.ContainsKey(args.BluetoothAddress)) { _devices.Add(args.BluetoothAddress, dev); listDevice.Invoke(new Action(() => { String Name = ""; String Addrr = dev.BluetoothAddress.ToString(); AdressBLE.Add(Addrr); if (dev.Name == null) Name = "None"; else Name = dev.Name; int item = listDevice.Items.IndexOf(Addrr + " " + Name); if (item == -1) listDevice.Items.Add(dev.BluetoothAddress + " " + Name); })); } } }
Результат выполнения данного кода представлен на рисунке ниже:
Сканирование показало 5 устройств поддерживающих BLE.
Подключение к BLE в Windows
Подключение к BLE в Windows приведено в следующем коде:
private async void btnConnectBLE_Click(object sender, EventArgs e) { trView.Nodes.Clear(); // Подключаемся к устройству по адресу dev = await BluetoothLEDevice.FromBluetoothAddressAsync(Convert.ToUInt64(AdressBLE.ElementAt(IndexBLENow))); if (dev != null) { //получаем все возможные сервисы var servisesResult = await dev.GetGattServicesAsync(); if (servisesResult.Status == Windows.Devices.Bluetooth.GenericAttributeProfile.GattCommunicationStatus.Success) { // Проходим по всем сервисам и получаем характеристики var services = servisesResult.Services; for (int j = 0; j < services.Count;j++) { var service = services[j]; trView.Nodes.Add($"Служба - {service.Uuid}"); var characteristicsResult = await service.GetCharacteristicsAsync(); if (characteristicsResult.Status == Windows.Devices.Bluetooth.GenericAttributeProfile.GattCommunicationStatus.Success) { var characteristics = characteristicsResult.Characteristics; var characteristic = characteristics[0]; for (int i = 0; i < characteristics.Count; i++) { trView.Nodes[trView.Nodes.Count - 1].Nodes.Add($"Характеристика - {characteristic.Uuid}"); } characteristic.Service.Dispose(); } service.Session.Dispose(); } } }else MessageBox.Show("Не могу подключить устройство!"); }
После подключения, мы получаем все сервисы данного устройства, а так же их характеристики. Ниже приведен рисунок с результатом работы данного кода.
Чтение и запись в характеристику BLE
Прочитать и записать можно в характеристику, если она имеет модификатор записи и чтения. Если не знать протокола обмена с устройством, то наши попытки записи прибор проигнорирует. Ниже приведен код для записи в характеристику с нужным номером сервиса.
private void frMain_Load(object sender, EventArgs e) { _devices = new Dictionary<ulong, BluetoothLEDevice>(); } private async void btnSendtxt_Click(object sender, EventArgs e) { String guu = value; if (guu.Contains("Характеристика")) { guu = guu.Replace("Характеристика - ", ""); String GuuiServis = "000000ff-0000-1000-8000-00805f9b34fb"; if (dev != null) dev.Dispose(); dev = await BluetoothLEDevice.FromBluetoothAddressAsync(Convert.ToUInt64(AdressBLE.ElementAt(IndexBLENow))); if (dev != null) { var servisesResult = await dev.GetGattServicesForUuidAsync(Guid.Parse(GuuiServis)); if (servisesResult.Status == Windows.Devices.Bluetooth.GenericAttributeProfile.GattCommunicationStatus.Success) { var services = servisesResult.Services; var service = services[0]; try { var characteristicsResult = await service.GetCharacteristicsForUuidAsync(Guid.Parse(guu)); if (characteristicsResult.Status == Windows.Devices.Bluetooth.GenericAttributeProfile.GattCommunicationStatus.Success) { var characteristics = characteristicsResult.Characteristics; for (int i = 0; i < characteristics.Count; i++) { var characteristic = characteristics[i]; if (characteristic.Uuid == Guid.Parse(guu)) { var property = characteristic.CharacteristicProperties; String Data = tbSendTxt.Text; byte[] input = new byte[Data.Length]; input = Encoding.Default.GetBytes(Data); var writer = new DataWriter(); writer.WriteBytes(input); var result = await characteristic.WriteValueAsync(writer.DetachBuffer()); } } } service.Dispose(); } catch { } } } } }
Так же приведем пример кода для чтения характеристики:
if (dev != null) { var servisesResult = await dev.GetGattServicesForUuidAsync(Guid.Parse(GuuiServis)); if (servisesResult.Status == Windows.Devices.Bluetooth.GenericAttributeProfile.GattCommunicationStatus.Success) { var services = servisesResult.Services; var service = services[0]; try { //var characteristicsResult = await service.GetCharacteristicsForUuidAsync(Guid.Parse(guu)); var characteristicsResult = await service.GetCharacteristicsAsync(); if (characteristicsResult.Status == Windows.Devices.Bluetooth.GenericAttributeProfile.GattCommunicationStatus.Success) { var characteristics = characteristicsResult.Characteristics; for (int i = 0; i < characteristics.Count; i++) { var characteristic = characteristics[i]; if (characteristic.Uuid == Guid.Parse(guu)) { var result = await characteristic.ReadValueAsync(BluetoothCacheMode.Uncached); if (result.Status == Windows.Devices.Bluetooth.GenericAttributeProfile.GattCommunicationStatus.Success) { var val = DataReader.FromBuffer(result.Value); byte[] input = new byte[val.UnconsumedBufferLength]; val.ReadBytes(input); label1.Text = "Значение характеристики: " + System.Text.Encoding.ASCII.GetString(input); } characteristic.Service.Dispose(); } } } service.Session.Dispose(); characteristicsResult = null; servisesResult = null; } catch { } } } }
ВНИМАНИЕ! Обратите внимание на модификатор BluetoothCacheMode.Uncached. Если данные изменяются постоянно, то необходимо его использовать. С другим модификатором данные не будут обновляться.
У меня не получилось добиться высокой скорости взаимодействия с устройством через BLE. Скорее всего, это из-за того, что я постоянно переподключаюсь к устройству. Что занимает время. К сожалению данная библиотека не работает в системах ниже Windows 10.