private async void ConnectButton_Click() { ConnectButton.IsEnabled = false; if (!await ClearBluetoothLEDeviceAsync()) { rootPage.NotifyUser("Error: Unable to reset state, try again.", NotifyType.ErrorMessage); ConnectButton.IsEnabled = true; return; } try { // BT_Code: BluetoothLEDevice.FromIdAsync must be called from a UI thread because it may prompt for consent. bluetoothLeDevice = await BluetoothLEDevice.FromIdAsync(rootPage.SelectedBleDeviceId); if (bluetoothLeDevice == null) { rootPage.NotifyUser("Failed to connect to device.", NotifyType.ErrorMessage); } } catch (Exception ex) when(ex.HResult == E_DEVICE_NOT_AVAILABLE) { rootPage.NotifyUser("Bluetooth radio is not on.", NotifyType.ErrorMessage); } if (bluetoothLeDevice != null) { // Note: BluetoothLEDevice.GattServices property will return an empty list for unpaired devices. For all uses we recommend using the GetGattServicesAsync method. // BT_Code: GetGattServicesAsync returns a list of all the supported services of the device (even if it's not paired to the system). // If the services supported by the device are expected to change during BT usage, subscribe to the GattServicesChanged event. GattDeviceServicesResult result = await bluetoothLeDevice.GetGattServicesAsync(BluetoothCacheMode.Uncached); if (result.Status == GattCommunicationStatus.Success) { var services = result.Services; rootPage.NotifyUser(String.Format("Found {0} services", services.Count), NotifyType.StatusMessage); foreach (var service in services) { ServiceList.Items.Add(new ComboBoxItem { Content = DisplayHelpers.GetServiceName(service), Tag = service }); } ConnectButton.Visibility = Visibility.Collapsed; ServiceList.Visibility = Visibility.Visible; } else { rootPage.NotifyUser("Device unreachable", NotifyType.ErrorMessage); } } ConnectButton.IsEnabled = true; }
public async void Connect(string id) { try { // BT_Code: BluetoothLEDevice.FromIdAsync must be called from a UI thread because it may prompt for consent. bluetoothLeDevice = await BluetoothLEDevice.FromIdAsync(id); if (bluetoothLeDevice == null) { Log.d("Failed to connect to device.", NotifyType.ErrorMessage); return; } bluetoothLeDevice.ConnectionStatusChanged += ConnectionStatusChangedHandler; mBluetoothGatt = await GattSession.FromDeviceIdAsync(bluetoothLeDevice.BluetoothDeviceId); mBluetoothGatt.MaintainConnection = true; } catch (Exception ex) when(ex.HResult == E_DEVICE_NOT_AVAILABLE) { Log.d("Bluetooth radio is not on.", NotifyType.ErrorMessage); return; } if (bluetoothLeDevice != null) { // Note: BluetoothLEDevice.GattServices property will return an empty list for unpaired devices. For all uses we recommend using the GetGattServicesAsync method. // BT_Code: GetGattServicesAsync returns a list of all the supported services of the device (even if it's not paired to the system). // If the services supported by the device are expected to change during BT usage, subscribe to the GattServicesChanged event. GattDeviceServicesResult result = await bluetoothLeDevice.GetGattServicesForUuidAsync(RX_SERVICE_UUID); if (result.Status == GattCommunicationStatus.Success) { _services.Clear(); _services.AddRange(result.Services); Log.d(String.Format("Found {0} services", _services.Count), NotifyType.StatusMessage); foreach (var service in _services) { Log.d("SERVICE: " + DisplayHelpers.GetServiceName(service)); GetCharachteristics(service); } } else { Log.d("Device unreachable", NotifyType.ErrorMessage); } } }
/// <summary> /// It looks for the compatible devices (discovery + analysis). Then, it asks /// for the user to choose the device. The selected device is returned /// through a CompatibleEndPoint object. It contains the id, service and /// characteristic name. /// </summary> /// <returns>The complete device id (or CompatibleEndPoint with all fields set as null if none were selected)</returns> static async Task <CompatibleEndPoint> AutomaticScan() { BleUtility.Discovery bleDiscovery = new BleUtility.Discovery(); bleDiscovery.Start(); LogHelper.Overwrite(true); LogHelper.NewLine(false); while (!bleDiscovery.HasEnded()) { Thread.Sleep(50); } LogHelper.Overwrite(false); LogHelper.NewLine(true); LogHelper.Log(""); LogHelper.Ok("Devices:"); LogHelper.IncrementIndentLevel(); List <DeviceInformation> devices = bleDiscovery.GetDevices(); foreach (DeviceInformation device in devices) { LogHelper.Ok(device.Id + " " + device.Name); } LogHelper.DecrementIndentLevel(); List <CompatibleEndPoint> compatibleEndPoints = new List <CompatibleEndPoint>(); LogHelper.Pending("Checking compatibility of each device"); LogHelper.IncrementIndentLevel(); foreach (DeviceInformation device in devices) { LogHelper.Pending("Checking compatibility of device " + device.Id.Split("-").Last()); LogHelper.IncrementIndentLevel(); LogHelper.Pending("Connecting to device..."); BluetoothLEDevice connection = await BleUtility.Connect(device.Id); if (connection == null) { LogHelper.DecrementIndentLevel(); LogHelper.Warn("Failed to connect (doesn't mean that it's incompatible)"); continue; } LogHelper.Ok("Connected"); LogHelper.Pending("Looking for services..."); IReadOnlyList <GattDeviceService> services = await BleUtility.GetServices(connection); if (services == null) { LogHelper.DecrementIndentLevel(); LogHelper.Warn("Gatt communication failed"); continue; } else if (services.Count == 0) { LogHelper.DecrementIndentLevel(); LogHelper.Warn("No services found"); continue; } LogHelper.Ok(services.Count + " service(s) found"); LogHelper.Pending("Looking for characteristics for each service..."); LogHelper.IncrementIndentLevel(); foreach (GattDeviceService service in services) { LogHelper.Pending("Looking for characteristics of service " + DisplayHelpers.GetServiceName(service)); LogHelper.IncrementIndentLevel(); IReadOnlyList <GattCharacteristic> characteristics = await BleUtility.GetCharacteristics(service); if (characteristics == null) { LogHelper.DecrementIndentLevel(); LogHelper.Warn("Failed to retrieve characteristics"); service.Dispose(); continue; } else if (characteristics.Count == 0) { LogHelper.DecrementIndentLevel(); LogHelper.Warn("No characteristics found"); service.Dispose(); continue; } LogHelper.Ok(characteristics.Count + " characteristic(s) found"); LogHelper.Pending("Checking compatibility of each characteristic..."); LogHelper.IncrementIndentLevel(); int compatibleCpt = 0; foreach (GattCharacteristic characteristic in characteristics) { LogHelper.Pending("Checking characteristic " + DisplayHelpers.GetCharacteristicName(characteristic) + "..."); if (BleUtility.IsWriteableCharateristic(characteristic)) { CompatibleEndPoint endPoint = new CompatibleEndPoint( device.Id, device.Name, DisplayHelpers.GetServiceName(service), DisplayHelpers.GetCharacteristicName(characteristic) ); compatibleCpt++; compatibleEndPoints.Add(endPoint); LogHelper.Ok("Compatible!"); } else { LogHelper.Warn("Not compatible"); } } service.Dispose(); LogHelper.DecrementIndentLevel(); LogHelper.Ok(compatibleCpt + " compatible endpoint(s) found"); LogHelper.DecrementIndentLevel(); } LogHelper.Ok("Finished looking for characteristics"); LogHelper.DecrementIndentLevel(); LogHelper.Ok("Finished compatibility check of device " + device.Id.Split('-').Last()); LogHelper.DecrementIndentLevel(); } LogHelper.DecrementIndentLevel(); LogHelper.Ok("Finished analyzing devices"); if (compatibleEndPoints.Count == 0) { LogHelper.Error("No compatible device found"); LogHelper.Error("Make sure that you're not already connected to it"); return(new CompatibleEndPoint(null, null, null, null)); } else { LogHelper.Ok("Compatible device(s):"); LogHelper.IncrementIndentLevel(); string[] ids = new string[compatibleEndPoints.Count]; for (int i = 0; i < compatibleEndPoints.Count; i++) { CompatibleEndPoint compatibleEndPoint = compatibleEndPoints.ElementAt(i); LogHelper.Ok("name = '" + compatibleEndPoint.deviceName + "' id = '" + compatibleEndPoint.deviceId + "'"); ids[i] = compatibleEndPoint.deviceId + (compatibleEndPoint.deviceName != "" ? (" " + compatibleEndPoint.deviceName) : ""); } LogHelper.DecrementIndentLevel(); int choice = LogHelper.AskUserToChoose("Choose the device to use: ", ids); bleDiscovery.Dispose(); return(compatibleEndPoints.ElementAt(choice)); } }
/// <summary> /// The actual program, needs to be waited /// </summary> /// <param name="args"></param> /// <returns></returns> static async Task Run(string[] args) { LogHelper.PrintHeader(); LogHelper.PrintTitle("Configuration"); bool configSucceed = await Configure(args); if (!configSucceed) { LogHelper.Error("Something went wrong during configuration"); } else { #region connection LogHelper.PrintTitle("Connection"); LogHelper.Pending("Looking for BLE device of id " + Configuration.device.deviceId); device = await BleUtility.Connect(Configuration.device.deviceId); if (device == null) { LogHelper.Error("Failed to connect to device"); } #endregion #region services GattDeviceService targettedService = null; if (device != null) { LogHelper.PrintTitle("Services"); LogHelper.Pending("Looking for service " + Configuration.device.deviceServiceName + "..."); IReadOnlyList <GattDeviceService> services = await BleUtility.GetServices(device); if (services != null) { LogHelper.Ok(String.Format("Found {0} service(s)", services.Count)); foreach (var service in services) { if (DisplayHelpers.GetServiceName(service) == Configuration.device.deviceServiceName) { LogHelper.Ok("Found service " + Configuration.device.deviceServiceName); targettedService = service; break; } } if (targettedService == null) { LogHelper.Error("Couldn't find service " + Configuration.device.deviceServiceName); } } else { LogHelper.Error("Device unreachable"); } } #endregion #region caracteristics GattCharacteristic characteristic = null; if (targettedService != null) { LogHelper.PrintTitle("Caracteristics"); LogHelper.Pending("Looking for characteristic " + Configuration.device.deviceCharacteristicName + "..."); IReadOnlyList <GattCharacteristic> characteristics = await BleUtility.GetCharacteristics(targettedService); if (characteristics == null) { LogHelper.Error("Could not find characteristics of " + Configuration.device.deviceName); } else { foreach (var charact in characteristics) { if (DisplayHelpers.GetCharacteristicName(charact) == Configuration.device.deviceCharacteristicName) { LogHelper.Ok("Found characteristic"); characteristic = charact; } } if (characteristic == null) { LogHelper.Error("Could not find characteristic " + Configuration.device.deviceCharacteristicName); } } } #endregion #region show config LogHelper.PrintTitle("Save your config"); LogHelper.Ok("Using configuration:"); LogHelper.Log(Configuration.GetArgumentDetails()); LogHelper.Log("\"" + Configuration.ToArgument() + "\""); LogHelper.Ok("Copy the line below, and run the program with this argument to [...]"); LogHelper.Ok("[...] start the program automatically with the current configuration"); #endregion #region communication if (characteristic != null) { LogHelper.PrintTitle("Communication"); if (BleUtility.IsWriteableCharateristic(characteristic)) { Loop(characteristic); } else { LogHelper.Error("This characteristic does not have either the 'Write' or 'WriteWithoutResponse' properties"); } } #endregion } #region cleanup LogHelper.PrintTitle("Cleanup"); LogHelper.Pending("Exiting properly"); device?.Dispose(); LogHelper.Ok("Done. Type a key to exit"); Console.ReadKey(true); #endregion }