public async Task <IButtplugDevice> CreateDeviceAsync([NotNull] BluetoothLEDevice aDevice) { // GetGattServicesForUuidAsync is 15063 only var services = await aDevice.GetGattServicesAsync(BluetoothCacheMode.Cached); List <Guid> uuids = new List <Guid>(); foreach (var s in services.Services) { _bpLogger.Trace($"Found service UUID: {s.Uuid} ({aDevice.Name})"); uuids.Add(s.Uuid); } var srvs = (from x in services.Services from y in _deviceInfo.Services where x.Uuid == y select x).ToArray(); if (srvs.Length != 1) { // Somehow we've gotten multiple services back, something we don't currently support. _bpLogger.Error($"Found {srvs.Length} services for {aDevice.Name}, which is more/less than 1. Please fix this in the bluetooth definition."); return(null); } var service = srvs[0]; var chrResult = await service.GetCharacteristicsAsync(); if (chrResult.Status != GattCommunicationStatus.Success) { _bpLogger.Error($"Cannot connect to service {service.Uuid} of {aDevice.Name}."); return(null); } foreach (var s in chrResult.Characteristics) { _bpLogger.Trace($"Found characteristics UUID: {s.Uuid} ({aDevice.Name})"); } var chrs = chrResult.Characteristics.ToArray(); // If there aren't any characteristics by this point, something has gone wrong. if (!chrs.Any()) { _bpLogger.Error($"Cannot find characteristics for service {service.Uuid} of {aDevice.Name}."); return(null); } var bleInterface = new UWPBluetoothDeviceInterface(_buttplugLogManager, _deviceInfo, aDevice, chrs); var device = _deviceInfo.CreateDevice(_buttplugLogManager, bleInterface); // If initialization fails, don't actually send the message back. Just return null, we'll // have the info in the logs. return(await device.InitializeAsync().ConfigureAwait(false) is Ok ? device : null); }
public async Task <IButtplugDevice> CreateDeviceAsync([NotNull] BluetoothLEDevice aDevice) { // GetGattServicesForUuidAsync is 15063 only var services = await aDevice.GetGattServicesAsync(BluetoothCacheMode.Cached); foreach (var s in services.Services) { _bpLogger.Debug("Found service UUID: " + s.Uuid + " (" + aDevice.Name + ")"); } var srvResult = await aDevice.GetGattServicesForUuidAsync(_deviceInfo.Services[0], BluetoothCacheMode.Cached); if (srvResult.Status != GattCommunicationStatus.Success || !srvResult.Services.Any()) { _bpLogger.Debug("Cannot find service for device (" + aDevice.Name + ")"); return(null); } var service = srvResult.Services.First(); var chrResult = await service.GetCharacteristicsAsync(); if (chrResult.Status != GattCommunicationStatus.Success) { return(null); } foreach (var s in chrResult.Characteristics) { _bpLogger.Trace("Found characteristics UUID: " + s.Uuid + " (" + aDevice.Name + ")"); } var chrs = from x in chrResult.Characteristics where _deviceInfo.Characteristics.Contains(x.Uuid) select x; var gattCharacteristics = chrs as GattCharacteristic[] ?? chrs.ToArray(); if (!gattCharacteristics.Any()) { return(null); } // TODO This assumes we're always planning on having the UUIDs sorted in the Info classes, which is probably not true. var bleInterface = new UWPBluetoothDeviceInterface(_buttplugLogManager, aDevice, gattCharacteristics.OrderBy((aChr) => aChr.Uuid).ToArray()); var device = _deviceInfo.CreateDevice(_buttplugLogManager, bleInterface); if (await device.Initialize() is Ok) { return(device); } // If initialization fails, don't actually send the message back. Just return null, we'll have the info in the logs. return(null); }
public static async Task <IButtplugDeviceImpl> Create(IButtplugLogManager aLogManager, BluetoothLEProtocolConfiguration aConfig, BluetoothLEDevice aDevice) { var device = new UWPBluetoothDeviceInterface(aLogManager, aDevice); await device.InitializeDevice(aConfig).ConfigureAwait(false); return(device); }
private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher aObj, BluetoothLEAdvertisementReceivedEventArgs aEvent) { if (aEvent?.Advertisement == null) { BpLogger.Debug("Null BLE advertisement received: skipping"); return; } var advertName = aEvent.Advertisement.LocalName ?? string.Empty; var advertGUIDs = new List <Guid>(); advertGUIDs.AddRange(aEvent.Advertisement.ServiceUuids ?? new Guid[] { }); var btAddr = aEvent.BluetoothAddress; // BpLogger.Trace($"Got BLE Advertisement for device: {aEvent.Advertisement.LocalName} / {aEvent.BluetoothAddress}"); if (_seenAddresses.Contains(btAddr)) { // BpLogger.Trace($"Ignoring advertisement for already connecting device: // {aEvent.Advertisement.LocalName} / {aEvent.BluetoothAddress}"); return; } BpLogger.Trace("BLE device found: " + advertName); // We always need a name to match against. if (advertName == string.Empty) { return; } // todo Add advertGUIDs back in. Not sure that ever really gets used though. var deviceCriteria = new BluetoothLEProtocolConfiguration(advertName); var deviceFactory = DeviceConfigurationManager.Manager.Find(deviceCriteria); // If we don't have a protocol to match the device, we can't do anything with it. if (deviceFactory == null || !(deviceFactory.Config is BluetoothLEProtocolConfiguration bleConfig)) { BpLogger.Debug($"No usable device factory available for {advertName}."); // If we've got an actual name this time around, and we don't have any factories // available that match the info we have, add to our seen list so we won't keep // rechecking. If a device does have a factory, but doesn't connect, we still want to // try again. _seenAddresses.Add(btAddr); return; } var fromBluetoothAddressAsync = BluetoothLEDevice.FromBluetoothAddressAsync(btAddr); // Can return null if the device no longer exists, for instance if it turned off between // advertising and us getting here. Since we didn't get a chance to try to connect, // remove it from seen devices, since the user may turn it back on during this scanning period. if (fromBluetoothAddressAsync == null) { return; } var dev = await fromBluetoothAddressAsync; // If a device is turned on after scanning has started, windows seems to lose the device // handle the first couple of times it tries to deal with the advertisement. Just log the // error and hope it reconnects on a later retry. IButtplugDeviceImpl bleDevice = null; IButtplugDevice btDevice = null; try { bleDevice = await UWPBluetoothDeviceInterface.Create(LogManager, bleConfig, dev).ConfigureAwait(false); btDevice = await deviceFactory.CreateDevice(LogManager, bleDevice).ConfigureAwait(false); InvokeDeviceAdded(new DeviceAddedEventArgs(btDevice)); } catch (Exception ex) { if (btDevice != null) { btDevice.Disconnect(); } else { bleDevice?.Disconnect(); } BpLogger.Error( $"Cannot connect to device {advertName} {btAddr}: {ex.Message}"); } }