コード例 #1
0
        public static async Task <IButtplugDeviceImpl> Create(IButtplugLogManager aLogManager,
                                                              BluetoothLEProtocolConfiguration aConfig,
                                                              IDevice aDevice)
        {
            var device = new XamarinBluetoothDeviceInterface(aLogManager, aDevice);
            await device.InitializeDevice(aConfig).ConfigureAwait(false);

            return(device);
        }
コード例 #2
0
        protected async Task InitializeDevice(BluetoothLEProtocolConfiguration aConfig)
        {
            foreach (var serviceInfo in aConfig.Services)
            {
                // If we don't have any characteristic configuration, assume we're using
                // characteristic detection.
                if (serviceInfo.Value == null || serviceInfo.Value.Count == 0)
                {
                    await AddDefaultCharacteristics(serviceInfo.Key).ConfigureAwait(false);
                }
                else
                {
                    var serviceGuid = serviceInfo.Key;


                    IService service;

                    try
                    {
                        service = await GetService(serviceGuid).ConfigureAwait(false);
                    }
                    catch (ButtplugDeviceException)
                    {
                        // In this case, we may have a whole bunch of services that aren't valid for
                        // a device and only one that is. We can ignore the exception here, and throw
                        // later if we don't get anything from any service in the list.
                        continue;
                    }

                    var chrResult = await service.GetCharacteristicsAsync();

                    if (service.Device.State != DeviceState.Connected)
                    {
                        throw new ButtplugDeviceException(BpLogger,
                                                          $"Cannot connect to characteristics for {serviceGuid} of {_bleDevice.Name}: {service.Device.State}");
                    }

                    foreach (var chr in chrResult)
                    {
                        foreach (var indexChr in serviceInfo.Value)
                        {
                            if (Guid.Parse(chr.Uuid) != indexChr.Value)
                            {
                                continue;
                            }

                            if (_indexedChars.ContainsKey(indexChr.Key))
                            {
                                // We've somehow doubled up endpoint names. Freak out.
                                throw new ButtplugDeviceException(BpLogger, $"Found repeated endpoint name {indexChr.Key} on {Name}");
                            }

                            BpLogger.Debug($"Found characteristic {indexChr.Key} {chr.Uuid} ({_bleDevice.Name})");
                            _indexedChars.Add(indexChr.Key, chr);
                        }
                    }
                }
            }

            // If we've exited characteristic finding without any characteristics to use, something
            // is wrong with our configuration and we won't be able to talk to the device. Don't
            // continue connection.
            if (!_indexedChars.Any())
            {
                throw new ButtplugDeviceException(BpLogger, $"No characteristics to connect to for device {Name}");
            }
        }
コード例 #3
0
        private async void _adapter_DeviceAdvertised(object sender, Plugin.BLE.Abstractions.EventArgs.DeviceEventArgs e)
        {
            if (e?.Device == null)
            {
                BpLogger.Debug("Null BLE advertisement received: skipping");
                return;
            }
            string advertName = e.Device.GetPropValue <string>("BluetoothDevice.Name");

            var advertGUIDs = new List <Guid>();

            advertGUIDs.Add(e.Device.Id);
            var btAddr = e.Device.GetPropValue <string>("BluetoothDevice.Address");

            BpLogger.Trace($"Got BLE Advertisement for device: {advertName} / {btAddr}");
            if (_seenAddresses.Contains(btAddr))
            {
                BpLogger.Trace($"Ignoring advertisement for already connecting device: {btAddr}");
                return;
            }
            _seenAddresses.Add(btAddr);
            BpLogger.Trace("BLE device found: " + advertName);

            // We always need a name to match against.
            if (String.IsNullOrEmpty(advertName))
            {
                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}.");
                return;
            }

            // 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
            {
                await _adapter.ConnectToDeviceAsync(e.Device);

                bleDevice = await XamarinBluetoothDeviceInterface.Create(LogManager, bleConfig, e.Device).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}");
            }
        }
コード例 #4
0
        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}");
            }
        }