Skip to content

Commit 13ffa87

Browse files
blackspherefollowerqdot
authored andcommitted
Releasing BLE devices on connection close
This means that you can now discoonect the session and after reconnecting, access the devices you had connected before the disconnect. Fixes #170 Also added some error handling around the xbox controller so that pulling the plug out doesn't cause an exception.
1 parent 5430147 commit 13ffa87

10 files changed

Lines changed: 87 additions & 7 deletions

File tree

Buttplug.Components.WebsocketServer/ButtplugWebsocketServer.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ private async Task HandleConnectionAsync(WebSocket ws, CancellationToken cancell
111111
finally
112112
{
113113
buttplug.MessageReceived -= msgReceived;
114+
buttplug.Shutdown();
114115
buttplug = null;
115116
ws.Dispose();
116117
}

Buttplug.Core/ButtplugDevice.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,5 +67,7 @@ public virtual Task<ButtplugMessage> Initialize()
6767
// ReSharper disable once AssignNullToNotNullAttribute
6868
return Task.FromResult<ButtplugMessage>(new Ok(ButtplugConsts.SystemMsgId));
6969
}
70+
71+
public abstract void Disconnect();
7072
}
7173
}

Buttplug.Core/IButtplugDevice.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,7 @@ public interface IButtplugDevice
2424

2525
[NotNull]
2626
Task<ButtplugMessage> Initialize();
27+
28+
void Disconnect();
2729
}
2830
}

Buttplug.Server.Managers.UWPBluetoothManager/UWPBluetoothDeviceInterface.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ internal class UWPBluetoothDeviceInterface : IBluetoothDeviceInterface
1515
{
1616
public string Name => _bleDevice.Name;
1717

18-
[NotNull]
19-
private readonly BluetoothLEDevice _bleDevice;
18+
[CanBeNull]
19+
private BluetoothLEDevice _bleDevice;
2020
[NotNull]
2121
private readonly GattCharacteristic[] _gattCharacteristics;
2222
[NotNull]
@@ -40,7 +40,7 @@ public UWPBluetoothDeviceInterface(
4040

4141
private void ConnectionStatusChangedHandler([NotNull] BluetoothLEDevice aDevice, [NotNull] object aObj)
4242
{
43-
if (_bleDevice.ConnectionStatus == BluetoothConnectionStatus.Disconnected)
43+
if (_bleDevice?.ConnectionStatus == BluetoothConnectionStatus.Disconnected)
4444
{
4545
DeviceRemoved?.Invoke(this, new EventArgs());
4646
}
@@ -87,5 +87,17 @@ public async Task<ButtplugMessage> WriteValue(uint aMsgId,
8787

8888
return new Ok(aMsgId);
8989
}
90+
91+
public void Disconnect()
92+
{
93+
DeviceRemoved?.Invoke(this, new EventArgs());
94+
for (int i = 0; i < _gattCharacteristics.Length; i++)
95+
{
96+
_gattCharacteristics[i] = null;
97+
}
98+
99+
_bleDevice.Dispose();
100+
_bleDevice = null;
101+
}
90102
}
91103
}

Buttplug.Server.Managers.XInputGamepadManager/XInputGamepadDevice.cs

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Threading.Tasks;
1+
using System;
2+
using System.Threading.Tasks;
23
using Buttplug.Core;
34
using Buttplug.Core.Messages;
45
using SharpDX.XInput;
@@ -7,7 +8,7 @@ namespace Buttplug.Server.Managers.XInputGamepadManager
78
{
89
internal class XInputGamepadDevice : ButtplugDevice
910
{
10-
private readonly Controller _device;
11+
private Controller _device;
1112

1213
public XInputGamepadDevice(IButtplugLogManager aLogManager, Controller aDevice)
1314
: base(aLogManager, "XBox Compatible Gamepad (XInput)", aDevice.UserIndex.ToString())
@@ -35,8 +36,43 @@ private Task<ButtplugMessage> HandleSingleMotorVibrateCmd(ButtplugDeviceMessage
3536
LeftMotorSpeed = (ushort)(cmdMsg.Speed * ushort.MaxValue),
3637
RightMotorSpeed = (ushort)(cmdMsg.Speed * ushort.MaxValue),
3738
};
38-
_device.SetVibration(v);
39+
40+
try
41+
{
42+
_device?.SetVibration(v);
43+
}
44+
catch (Exception e)
45+
{
46+
if (_device?.IsConnected != true)
47+
{
48+
InvokeDeviceRemoved();
49+
50+
// Don't throw a spanner in the works
51+
return Task.FromResult<ButtplugMessage>(new Ok(aMsg.Id));
52+
}
53+
54+
return Task.FromResult<ButtplugMessage>(BpLogger.LogErrorMsg(aMsg.Id, Error.ErrorClass.ERROR_DEVICE, e.Message));
55+
}
56+
3957
return Task.FromResult<ButtplugMessage>(new Ok(aMsg.Id));
4058
}
59+
60+
public override void Disconnect()
61+
{
62+
var v = new Vibration
63+
{
64+
LeftMotorSpeed = 0,
65+
RightMotorSpeed = 0,
66+
};
67+
try
68+
{
69+
_device?.SetVibration(v);
70+
_device = null;
71+
}
72+
finally
73+
{
74+
_device = null;
75+
}
76+
}
4177
}
4278
}

Buttplug.Server.Test/TestDevice.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Threading.Tasks;
1+
using System;
2+
using System.Threading.Tasks;
23
using Buttplug.Core;
34
using Buttplug.Core.Messages;
45

@@ -22,5 +23,10 @@ public void RemoveDevice()
2223
{
2324
InvokeDeviceRemoved();
2425
}
26+
27+
public override void Disconnect()
28+
{
29+
RemoveDevice();
30+
}
2531
}
2632
}

Buttplug.Server/Bluetooth/ButtplugBluetoothDevice.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ protected ButtplugBluetoothDevice([NotNull] IButtplugLogManager aLogManager,
2020
Interface.DeviceRemoved += DeviceRemovedHandler;
2121
}
2222

23+
public override void Disconnect()
24+
{
25+
Interface.Disconnect();
26+
}
27+
2328
private void DeviceRemovedHandler(object aObject, EventArgs aEvent)
2429
{
2530
InvokeDeviceRemoved();

Buttplug.Server/Bluetooth/IBluetoothDeviceInterface.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,7 @@ public interface IBluetoothDeviceInterface
1313
ulong GetAddress();
1414

1515
event EventHandler DeviceRemoved;
16+
17+
void Disconnect();
1618
}
1719
}

Buttplug.Server/ButtplugService.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,11 @@ public async Task<ButtplugMessage> SendMessage([NotNull] ButtplugMessage aMsg)
153153
return await _deviceManager.SendMessage(aMsg);
154154
}
155155

156+
public void Shutdown()
157+
{
158+
_deviceManager.RemoveAllDevices();
159+
}
160+
156161
[ItemNotNull]
157162
public async Task<ButtplugMessage[]> SendMessage(string aJsonMsgs)
158163
{

Buttplug.Server/DeviceManager.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,15 @@ public async Task<ButtplugMessage> SendMessage(ButtplugMessage aMsg)
174174
return _bpLogger.LogErrorMsg(id, Error.ErrorClass.ERROR_MSG, $"Message type {aMsg.GetType().Name} unhandled by this server.");
175175
}
176176

177+
internal void RemoveAllDevices()
178+
{
179+
StopScanning();
180+
foreach (var d in _devices.Values)
181+
{
182+
d.Disconnect();
183+
}
184+
}
185+
177186
private void StartScanning()
178187
{
179188
_sentFinished = false;

0 commit comments

Comments
 (0)