protected override void RunScan() { try { // TODO this should scan in a loop on a timer until told to stop var controllers = new[] { new Controller(UserIndex.One), new Controller(UserIndex.Two), new Controller(UserIndex.Three), new Controller(UserIndex.Four), }; foreach (var c in controllers) { if (!c.IsConnected) { continue; } BpLogger.Debug($"Found connected XInput Gamepad for Index {c.UserIndex}"); var deviceImpl = new XInputGamepadDevice(LogManager, c); var device = new ButtplugDevice(LogManager, new XInputProtocol(LogManager, deviceImpl), deviceImpl); InvokeDeviceAdded(new DeviceAddedEventArgs(device)); // Do not invoke ScanningFinished here, the parent class will handle that for us. } } catch (DllNotFoundException e) { // TODO Should we maybe try testing for this in construction instead of during scanning? BpLogger.Error($"Required DirectX DLL not found: {e.Message}\nThis probably means you need to install the DirectX Runtime from June 2010: https://www.microsoft.com/en-us/download/details.aspx?id=8109"); throw e; } }
public override void StartScanning() { BpLogger.Info("XInputGamepadManager start scanning"); try { var controllers = new[] { new Controller(UserIndex.One), new Controller(UserIndex.Two), new Controller(UserIndex.Three), new Controller(UserIndex.Four), }; foreach (var c in controllers) { if (!c.IsConnected) { continue; } BpLogger.Debug($"Found connected XInput Gamepad for Index {c.UserIndex}"); var device = new XInputGamepadDevice(LogManager, c); InvokeDeviceAdded(new DeviceAddedEventArgs(device)); InvokeScanningFinished(); } } catch (DllNotFoundException e) { // TODO Should we maybe try testing for this in construction instead of during scanning? BpLogger.Error($"Required DirectX DLL not found: {e.Message}\nThis probably means you need to install the DirectX Runtime from June 2010: https://www.microsoft.com/en-us/download/details.aspx?id=8109"); InvokeScanningFinished(); } }
private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg, CancellationToken aToken) { BpLogger.Debug("Stopping Device " + Name); await HandleSingleMotorVibrateCmd(new SingleMotorVibrateCmd(aMsg.DeviceIndex, 0, aMsg.Id), aToken).ConfigureAwait(false); await HandleRotateCmd(RotateCmd.Create(0, false, 1), aToken); return(new Ok(aMsg.Id)); }
private Task <ButtplugMessage> HandleStopDeviceCmd([NotNull] ButtplugDeviceMessage aMsg) { // Right now, this is a nop. The Onyx doesn't have any sort of permanent movement state, // and its longest movement is like 150ms or so. The Pearl is supposed to vibrate but I've // never gotten that to work. So for now, we just return ok. BpLogger.Debug("Stopping Device " + Name); return(Task.FromResult <ButtplugMessage>(new Ok(aMsg.Id))); }
private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg, CancellationToken aToken) { BpLogger.Debug("Stopping Device " + Name); await Interface.WriteValueAsync(new byte[] { (byte)_deviceType, (byte)_commandType, 0 }, aToken).ConfigureAwait(false); return(new Ok(aMsg.Id)); }
private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg, CancellationToken aToken) { BpLogger.Debug("Stopping Device " + Name); // Stop commands start with 0x01 var cmd = GetCommandArray(new[] { (byte)0x01, (byte)RealTouchComponents.A }); await Interface.WriteValueAsync(cmd, aToken); return(new Ok(aMsg.Id)); //return await HandleRotateCmd(new RotateCmd(aMsg.DeviceIndex, 0, _clockwise, aMsg.Id), aToken).ConfigureAwait(false); }
private Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg) { // This probably shouldn't be a nop, but right now we don't have a good way to know // if the launch is moving or not, and surprisingly enough, setting speed to 0 does not // actually stop movement. It just makes it move really slow. // However, since each move it makes is finite (unlike setting vibration on some devices), // so we can assume it will be a short move, similar to what we do for the Kiiroo toys. BpLogger.Debug("Stopping Device " + Name); return(Task.FromResult <ButtplugMessage>(new Ok(aMsg.Id))); }
private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg, CancellationToken aToken) { BpLogger.Debug("Stopping Device " + Name); if (_deviceType == LovenseDeviceType.Nora) { await HandleRotateCmd(RotateCmd.Create(aMsg.DeviceIndex, aMsg.Id, 0, _clockwise, 1), aToken).ConfigureAwait(false); } return(await HandleSingleMotorVibrateCmd(new SingleMotorVibrateCmd(aMsg.DeviceIndex, 0, aMsg.Id), aToken).ConfigureAwait(false)); }
public override void StartScanning() { _scanning = true; var hidDevices = new HidEnumerator(); foreach (var hid in hidDevices.Enumerate()) { try { hid.ReadProduct(out var product); hid.ReadManufacturer(out var vendor); var prod = Encoding.Unicode.GetString(product); var vend = Encoding.Unicode.GetString(vendor); prod = prod.Substring(0, prod.IndexOf('\0')); vend = vend.Substring(0, vend.IndexOf('\0')); BpLogger.Trace("Found HID device (" + hid.Attributes.VendorHexId + ":" + hid.Attributes.ProductHexId + "): " + vend + " - " + prod); var factories = _deviceFactories.Where(x => x.MayBeDevice(hid.Attributes.VendorId, hid.Attributes.ProductId)); var buttplugHidDeviceFactories = factories as HidDeviceFactory[] ?? factories.ToArray(); if (buttplugHidDeviceFactories.Length != 1) { if (buttplugHidDeviceFactories.Any()) { BpLogger.Warn($"Found multiple HID factories for {hid.Attributes.VendorHexId}:{hid.Attributes.ProductHexId}"); buttplugHidDeviceFactories.ToList().ForEach(x => BpLogger.Warn(x.GetType().Name)); } else { // BpLogger.Trace("No BLE factories found for device."); } continue; } var factory = buttplugHidDeviceFactories.First(); BpLogger.Debug($"Found HID factory: {factory.GetType().Name}"); var d = factory.CreateDevice(hid); InvokeDeviceAdded(new DeviceAddedEventArgs(d)); } catch (Exception e) { // TODO Figure out what exceptions can actually be thrown here. BpLogger.Error(e.Message); } } _scanning = false; InvokeScanningFinished(); }
private async Task <ButtplugMessage> HandleStopDeviceCmd([NotNull] ButtplugDeviceMessage aMsg) { BpLogger.Debug("Stopping Device " + Name); return(await HandleVibrateCmd(new VibrateCmd(aMsg.DeviceIndex, new List <VibrateCmd.VibrateSubcommand>() { new VibrateCmd.VibrateSubcommand(0, 0), new VibrateCmd.VibrateSubcommand(1, 0), }, aMsg.Id))); }
private async Task <ButtplugMessage> HandleStopDeviceCmd([NotNull] ButtplugDeviceMessage aMsg, CancellationToken aToken) { BpLogger.Debug($"Stopping Device {Name}"); if (_devInfo.VibeCount == 0) { return(new Ok(aMsg.Id)); } return(await HandleVibrateCmd(VibrateCmd.Create(aMsg.DeviceIndex, aMsg.Id, 0, _devInfo.VibeCount), aToken).ConfigureAwait(false)); }
private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg) { BpLogger.Debug("Stopping Device " + Name); if (_deviceType == LovenseDeviceType.Nora) { await HandleRotateCmd(RotateCmd.Create(aMsg.DeviceIndex, aMsg.Id, 0, _clockwise, 1)); } return(await HandleSingleMotorVibrateCmd(new SingleMotorVibrateCmd(aMsg.DeviceIndex, 0, aMsg.Id))); }
private async Task <ButtplugMessage> HandleStopDeviceCmd([NotNull] ButtplugDeviceMessage aMsg) { BpLogger.Debug("Stopping Device " + Name); var vCmds = new List <VibrateCmd.VibrateSubcommand>(); for (uint i = 0; i < _devInfo.VibeCount; i++) { vCmds.Add(new VibrateCmd.VibrateSubcommand(i, 0)); } return(await HandleVibrateCmd(new VibrateCmd(aMsg.DeviceIndex, vCmds, aMsg.Id))); }
private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg, CancellationToken aToken) { BpLogger.Debug("Stopping Device " + Name); if (_speed == 0) { return(new Ok(aMsg.Id)); } return(await Interface.WriteValueAsync(aMsg.Id, (uint)VorzeSABluetoothInfo.Chrs.Tx, new byte[] { (byte)_deviceType, (byte)_commandType, 0 }, false, aToken).ConfigureAwait(false)); }
private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg) { BpLogger.Debug("Stopping Device " + Name); if (FriendlyNames[Interface.Name] == "Nora") { await Interface.WriteValue(aMsg.Id, Info.Characteristics[(uint)LovenseRev1BluetoothInfo.Chrs.Tx], Encoding.ASCII.GetBytes($"Rotate:0;")); } return(await HandleSingleMotorVibrateCmd(new SingleMotorVibrateCmd(aMsg.DeviceIndex, 0, aMsg.Id))); }
public UWPBluetoothManager(IButtplugLogManager aLogManager) : base(aLogManager) { BpLogger.Info("Loading UWP Bluetooth Manager"); _currentlyConnecting = new List <ulong>(); // Introspect the ButtplugDevices namespace for all Factory classes, then create // instances of all of them. _deviceFactories = new List <UWPBluetoothDeviceFactory>(); BuiltinDevices.ForEach(aDeviceFactory => { BpLogger.Debug($"Loading Bluetooth Device Factory: {aDeviceFactory.GetType().Name}"); _deviceFactories.Add(new UWPBluetoothDeviceFactory(aLogManager, aDeviceFactory)); }); _bleWatcher = new BluetoothLEAdvertisementWatcher { ScanningMode = BluetoothLEScanningMode.Active }; // We can't filter device advertisements because you can only add one LocalName filter at // a time, meaning we would have to set up multiple watchers for multiple devices. We'll // handle our own filtering via the factory classes whenever we receive a device. _bleWatcher.Received += OnAdvertisementReceived; _bleWatcher.Stopped += OnWatcherStopped; var adapterTask = Task.Run(() => BluetoothAdapter.GetDefaultAsync().AsTask()); adapterTask.Wait(); var adapter = adapterTask.Result; if (adapter == null) { BpLogger.Warn("No bluetooth adapter available for UWP Bluetooth Manager Connection"); return; } if (!adapter.IsLowEnergySupported) { BpLogger.Warn("Bluetooth adapter available but does not support Bluetooth Low Energy."); return; } BpLogger.Debug("UWP Manager found working Bluetooth LE Adapter"); // Only run radio information lookup if we're actually logging at the level it will show. if (aLogManager.Level >= ButtplugLogLevel.Debug) { // Do radio lookup in a background task, as the search query is very slow. // TODO Should probably try and cancel this if it's still running on object destruction, but the Get() call is uninterruptable? _radioTask = Task.Run(() => LogBluetoothRadioInfo()); } }
private async Task <ButtplugMessage> HandleStopDeviceCmd([NotNull] ButtplugDeviceMessage aMsg, CancellationToken aToken) { // Right now, this is a nop. The Onyx doesn't have any sort of permanent movement state, // and its longest movement is like 150ms or so. The Pearl is supposed to vibrate but I've // never gotten that to work. So for now, we just return ok. BpLogger.Debug("Stopping Device " + Name); if (Interface.Name == "PEARL" && _deviceSpeed > 0) { return(await HandleKiirooRawCmd(new KiirooCmd(aMsg.DeviceIndex, 0, aMsg.Id), aToken).ConfigureAwait(false)); } return(new Ok(aMsg.Id)); }
public XamarinBluetoothManager(IButtplugLogManager aLogManager) : base(aLogManager) { BpLogger.Info("Loading UWP Bluetooth Manager"); _adapter = CrossBluetoothLE.Current.Adapter; if (_adapter == null) { BpLogger.Warn("No bluetooth adapter available for UWP Bluetooth Manager Connection"); return; } _adapter.DeviceAdvertised += _adapter_DeviceAdvertised; BpLogger.Debug("UWP Manager found working Bluetooth LE Adapter"); }
private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg) { BpLogger.Debug("Stopping Device " + Name); if (FriendlyNames[Interface.Name] == "Nora") { await HandleRotateCmd(new RotateCmd(aMsg.DeviceIndex, new List <RotateCmd.RotateSubcommand> { new RotateCmd.RotateSubcommand(0, 0, _clockwise) }, aMsg.Id)); } return(await HandleSingleMotorVibrateCmd(new SingleMotorVibrateCmd(aMsg.DeviceIndex, 0, aMsg.Id))); }
private void LogBluetoothRadioInfo() { // Log all bluetooth radios on the system, in case we need the information from the user later. var objSearcher = new ManagementObjectSearcher("Select * from Win32_PnPSignedDriver where DeviceName like '%Bluetooth%'"); var objCollection = objSearcher.Get(); BpLogger.Debug("Bluetooth Radio Information:"); foreach (var obj in objCollection) { var info = $"Device='{obj["DeviceName"]}',Manufacturer='{obj["Manufacturer"]}',DriverVersion='{obj["DriverVersion"]}' "; BpLogger.Debug(info); } }
private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg, CancellationToken aToken) { BpLogger.Debug("Stopping Device " + Name); if (_deviceType == DeviceType.Piston) { // Forced transition to the front await Interface.WriteValueAsync(new byte[] { (byte)_deviceType, 0, 60 }, aToken).ConfigureAwait(false); } else { await Interface.WriteValueAsync(new byte[] { (byte)_deviceType, (byte)_commandType, 0 }, aToken).ConfigureAwait(false); } isEnable = false; return(new Ok(aMsg.Id)); }
public UWPBluetoothManager(IButtplugLogManager aLogManager) : base(aLogManager) { BpLogger.Info("Loading UWP Bluetooth Manager"); _currentlyConnecting = new List <ulong>(); // Introspect the ButtplugDevices namespace for all Factory classes, then create instances of all of them. _deviceFactories = new List <UWPBluetoothDeviceFactory>(); BuiltinDevices.ForEach(aDeviceFactory => { BpLogger.Debug($"Loading Bluetooth Device Factory: {aDeviceFactory.GetType().Name}"); _deviceFactories.Add(new UWPBluetoothDeviceFactory(aLogManager, aDeviceFactory)); }); _bleWatcher = new BluetoothLEAdvertisementWatcher { ScanningMode = BluetoothLEScanningMode.Active }; // We can't filter device advertisements because you can only add one LocalName filter at a time, meaning we // would have to set up multiple watchers for multiple devices. We'll handle our own filtering via the factory // classes whenever we receive a device. _bleWatcher.Received += OnAdvertisementReceived; _bleWatcher.Stopped += OnWatcherStopped; var adapterTask = Task.Run(() => BluetoothAdapter.GetDefaultAsync().AsTask()); adapterTask.Wait(); var adapter = adapterTask.Result; if (adapter == null) { BpLogger.Warn("No bluetooth adapter available for UWP Bluetooth Manager Connection"); return; } if (!adapter.IsLowEnergySupported) { BpLogger.Warn("Bluetooth adapter available but does not support Bluetooth Low Energy."); return; } BpLogger.Debug("UWP Manager found working Bluetooth LE Adapter"); }
public UWPBluetoothManager(IButtplugLogManager aLogManager) : base(aLogManager) { BpLogger.Info("Loading UWP Bluetooth Manager"); // We can't filter device advertisements because you can only add one LocalName filter at // a time, meaning we would have to set up multiple watchers for multiple devices. We'll // handle our own filtering via the factory classes whenever we receive a device. _bleWatcher.Received += OnAdvertisementReceived; _bleWatcher.Stopped += OnWatcherStopped; var adapterTask = Task.Run(() => BluetoothAdapter.GetDefaultAsync().AsTask()); adapterTask.Wait(); var adapter = adapterTask.Result; if (adapter == null) { BpLogger.Warn("No bluetooth adapter available for UWP Bluetooth Manager Connection"); return; } if (!adapter.IsLowEnergySupported) { BpLogger.Warn("Bluetooth adapter available but does not support Bluetooth Low Energy."); return; } BpLogger.Debug("UWP Manager found working Bluetooth LE Adapter"); // Only run radio information lookup if we're actually logging at the level it will show. if (aLogManager.MaxLevel >= ButtplugLogLevel.Debug) { // Do radio lookup in a background task, as the search query is very slow. TODO // Should probably try and cancel this if it's still running on object destruction, // but the Get() call is uninterruptable? _radioTask = Task.Run(() => LogBluetoothRadioInfo()); } }
public UWPBluetoothManager(IButtplugLogManager aLogManager) : base(aLogManager) { BpLogger.Debug("Loading UWP Bluetooth Manager"); _currentlyConnecting = new List <ulong>(); // Introspect the ButtplugDevices namespace for all Factory classes, then create instances of all of them. _deviceFactories = new List <UWPBluetoothDeviceFactory>(); BuiltinDevices.ForEach(aDeviceFactory => { BpLogger.Debug($"Loading Bluetooth Device Factory: {aDeviceFactory.GetType().Name}"); _deviceFactories.Add(new UWPBluetoothDeviceFactory(aLogManager, aDeviceFactory)); }); _bleWatcher = new BluetoothLEAdvertisementWatcher { ScanningMode = BluetoothLEScanningMode.Active }; // We can't filter device advertisements because you can only add one LocalName filter at a time, meaning we // would have to set up multiple watchers for multiple devices. We'll handle our own filtering via the factory // classes whenever we receive a device. _bleWatcher.Received += OnAdvertisementReceived; _bleWatcher.Stopped += OnWatcherStopped; }
public override void StartScanning() { BpLogger.Info("XInputGamepadManager start scanning"); var controllers = new[] { new Controller(UserIndex.One), new Controller(UserIndex.Two), new Controller(UserIndex.Three), new Controller(UserIndex.Four), }; foreach (var c in controllers) { if (!c.IsConnected) { continue; } BpLogger.Debug($"Found connected XInput Gamepad for Index {c.UserIndex}"); var device = new XInputGamepadDevice(LogManager, c); InvokeDeviceAdded(new DeviceAddedEventArgs(device)); InvokeScanningFinished(); } }
public override async Task <ButtplugMessage> Initialize() { BpLogger.Trace($"Initializing {Name}"); // Subscribing to read updates await Interface.SubscribeToUpdates(); Interface.BluetoothNotifyReceived += NotifyReceived; // Retreiving device type info for identification. var writeMsg = await Interface.WriteValue(ButtplugConsts.SystemMsgId, Encoding.ASCII.GetBytes($"DeviceType;"), true); if (writeMsg is Error) { BpLogger.Error($"Error requesting device info from Lovense {Name}"); return(writeMsg); } var(msg, result) = await Interface.ReadValue(ButtplugConsts.SystemMsgId); string deviceInfoString = string.Empty; if (msg is Ok) { deviceInfoString = Encoding.ASCII.GetString(result); } else { // The device info notification isn't available immediately. // TODO Turn this into a task semaphore with cancellation/timeout, let system handle check timing. int timeout = 500; while (timeout > 0) { if (_lastNotifyReceived != string.Empty) { deviceInfoString = _lastNotifyReceived; break; } timeout -= 5; await Task.Delay(5); } } if (deviceInfoString != string.Empty) { BpLogger.Debug($"Received device query return for {Interface.Name}"); // Expected Format X:YY:ZZZZZZZZZZZZ X is device type leter YY is firmware version Z // is bluetooth address var deviceInfo = deviceInfoString.Split(':'); // If we don't get back the amount of tokens we expect, identify as unknown, log, bail. if (deviceInfo.Length != 3 || deviceInfo[0].Length != 1) { return(BpLogger.LogErrorMsg(ButtplugConsts.SystemMsgId, Error.ErrorClass.ERROR_DEVICE, $"Unknown Lovense DeviceType of {deviceInfoString} found. Please report to B******g Developers by filing an issue at https://github.com/metafetish/b******g/")); } var deviceTypeLetter = deviceInfo[0][0]; if (deviceTypeLetter == 'C') { deviceTypeLetter = 'A'; } int.TryParse(deviceInfo[1], out var deviceVersion); BpLogger.Trace($"Lovense DeviceType Return: {deviceTypeLetter}"); if (!Enum.IsDefined(typeof(LovenseDeviceType), (uint)deviceTypeLetter)) { // If we don't know what device this is, just assume it has a single vibrator, // call it unknown, log something. return(BpLogger.LogErrorMsg(ButtplugConsts.SystemMsgId, Error.ErrorClass.ERROR_DEVICE, $"Unknown Lovense Device of Type {deviceTypeLetter} found. Please report to B******g Developers by filing an issue at https://github.com/metafetish/b******g/")); } Name = $"Lovense {Enum.GetName(typeof(LovenseDeviceType), (uint)deviceTypeLetter)} v{deviceVersion}"; _deviceType = (LovenseDeviceType)deviceTypeLetter; } else { // If we for some reason don't get a device info query back, use fallback method. // // TODO Remove this branch at some point? Not sure we'll need it now since device queries seem stable. BpLogger.Warn($"Error retreiving device info from Lovense {Name}, using fallback method"); // Some of the older devices seem to have issues with info lookups? Not sure why, so // for now use fallback method. switch (Interface.Name.Substring(0, 6)) { case "LVS-B0": _deviceType = LovenseDeviceType.Max; break; case "LVS-A0": case "LVS-C0": _deviceType = LovenseDeviceType.Nora; break; case "LVS-L0": _deviceType = LovenseDeviceType.Ambi; break; default: _deviceType = LovenseDeviceType.Unknown; break; } Name = $"Lovense {Enum.GetName(typeof(LovenseDeviceType), (uint)_deviceType)} v{Interface.Name.Substring(Interface.Name.Length - 2)}"; } if (_deviceType == LovenseDeviceType.Unknown) { BpLogger.Error("Lovense device type unknown, treating as single vibrator device. Please contact developers for more info."); } switch (_deviceType) { case LovenseDeviceType.Edge: // Edge has 2 vibrators _vibratorCount++; MsgFuncs.Remove(typeof(VibrateCmd)); MsgFuncs.Add(typeof(VibrateCmd), new ButtplugDeviceWrapper(HandleVibrateCmd, new MessageAttributes() { FeatureCount = _vibratorCount })); break; case LovenseDeviceType.Nora: // Nora has a rotator MsgFuncs.Add(typeof(RotateCmd), new ButtplugDeviceWrapper(HandleRotateCmd, new MessageAttributes() { FeatureCount = 1 })); break; } return(new Ok(ButtplugConsts.SystemMsgId)); }
private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg) { BpLogger.Debug("Stopping Device " + Name); return(await HandleVorzeA10CycloneCmd(new VorzeA10CycloneCmd(aMsg.DeviceIndex, 0, _clockwise, aMsg.Id))); }
private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher aObj, BluetoothLEAdvertisementReceivedEventArgs aEvent) { if (aEvent?.Advertisement == null) { BpLogger.Debug("Null BLE advertisement recieved: 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 (_currentlyConnecting.Contains(btAddr)) { // BpLogger.Trace($"Ignoring advertisement for already connecting device: {aEvent.Advertisement.LocalName} / {aEvent.BluetoothAddress}"); return; } BpLogger.Trace("BLE device found: " + advertName); var factories = from x in _deviceFactories where x.MayBeDevice(advertName, advertGUIDs) select x; // We should always have either 0 or 1 factories. var buttplugBluetoothDeviceFactories = factories as UWPBluetoothDeviceFactory[] ?? factories.ToArray(); if (buttplugBluetoothDeviceFactories.Length != 1) { if (buttplugBluetoothDeviceFactories.Any()) { BpLogger.Warn($"Found multiple BLE factories for {advertName} {btAddr}:"); buttplugBluetoothDeviceFactories.ToList().ForEach(x => BpLogger.Warn(x.GetType().Name)); } else { // BpLogger.Trace("No BLE factories found for device."); } return; } _currentlyConnecting.Add(btAddr); var factory = buttplugBluetoothDeviceFactories.First(); BpLogger.Debug($"Found BLE factory: {factory.GetType().Name}"); // If we actually have a factory for this device, go ahead and create the device var fromBluetoothAddressAsync = BluetoothLEDevice.FromBluetoothAddressAsync(btAddr); if (fromBluetoothAddressAsync != null) { 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. try { var d = await factory.CreateDeviceAsync(dev); InvokeDeviceAdded(new DeviceAddedEventArgs(d)); } catch (Exception ex) { BpLogger.Error( $"Cannot connect to device {advertName} {btAddr}: {ex.Message}"); _currentlyConnecting.Remove(btAddr); return; } } _currentlyConnecting.Remove(btAddr); }
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}"); } }
private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg) { BpLogger.Debug("Stopping Device " + Name); return(await HandleSingleMotorVibrateCmd(new SingleMotorVibrateCmd(aMsg.DeviceIndex, 0, aMsg.Id))); }