Skip to content

Commit f5d5340

Browse files
amateras977qdot
authored andcommitted
feat: Adding support for Vorze PistonSA
1 parent 431db3f commit f5d5340

2 files changed

Lines changed: 128 additions & 3 deletions

File tree

Buttplug.Server.Managers.UWPBluetoothManager/UWPBluetoothDeviceInterface.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ internal class UWPBluetoothDeviceInterface : ButtplugDeviceImpl
3535
[CanBeNull]
3636
private BluetoothLEDevice _bleDevice;
3737

38-
public override bool Connected => _bleDevice != null && _bleDevice.ConnectionStatus == BluetoothConnectionStatus.Connected;
38+
public override bool Connected => _bleDevice != null;
3939

4040
protected UWPBluetoothDeviceInterface(
4141
[NotNull] IButtplugLogManager aLogManager,

Buttplug/Devices/Protocols/VorzeSAProtocol.cs

Lines changed: 127 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// </copyright>
66

77
using System;
8+
using System.Collections.Generic;
89
using System.Threading;
910
using System.Threading.Tasks;
1011
using Buttplug.Core.Logging;
@@ -21,18 +22,33 @@ private enum DeviceType
2122
{
2223
CycloneOrUnknown = 1,
2324
UFO = 2,
25+
Piston = 3,
2426
Bach = 6,
2527
}
2628

2729
public enum CommandType
2830
{
2931
Rotate = 1,
3032
Vibrate = 3,
33+
Linear = 10,
3134
}
3235

36+
public struct VorzePistonCommand
37+
{
38+
public uint parentMsgId;
39+
public LinearCmd.VectorSubcommand cmd;
40+
public CancellationToken aToken;
41+
}
42+
private DateTime _currentTime;
43+
private DateTime _nextDispatchTime;
44+
private Queue<VorzePistonCommand> _linearCmdQueue;
45+
private byte _beforeLinearCmdPosition;
46+
3347
private DeviceType _deviceType = DeviceType.CycloneOrUnknown;
3448
private CommandType _commandType = CommandType.Rotate;
3549

50+
private bool isEnable = false;
51+
3652
public VorzeSAProtocol(IButtplugLogManager aLogManager,
3753
IButtplugDeviceImpl aInterface)
3854
: base(aLogManager,
@@ -53,6 +69,11 @@ public VorzeSAProtocol(IButtplugLogManager aLogManager,
5369
Name = "Vorze UFO SA";
5470
break;
5571

72+
case "VorzePiston":
73+
_deviceType = DeviceType.Piston;
74+
_commandType = CommandType.Linear;
75+
Name = "Vorze A10 Piston SA";
76+
break;
5677
case "Bach smart":
5778
_deviceType = DeviceType.Bach;
5879
_commandType = CommandType.Vibrate;
@@ -76,6 +97,10 @@ public VorzeSAProtocol(IButtplugLogManager aLogManager,
7697
AddMessageHandler<SingleMotorVibrateCmd>(HandleSingleMotorVibrateCmd);
7798
AddMessageHandler<VibrateCmd>(HandleVibrateCmd, new MessageAttributes() { FeatureCount = 1 });
7899
break;
100+
case CommandType.Linear:
101+
AddMessageHandler<LinearCmd>(HandleLinearCmd, new MessageAttributes() { FeatureCount = 1 });
102+
_linearCmdQueue = new Queue<VorzePistonCommand>();
103+
break;
79104

80105
default:
81106
BpLogger.Error("Unhandled command type.");
@@ -85,12 +110,38 @@ public VorzeSAProtocol(IButtplugLogManager aLogManager,
85110
AddMessageHandler<StopDeviceCmd>(HandleStopDeviceCmd);
86111
}
87112

113+
114+
private async void ObserveLinearCmdQueue()
115+
{
116+
while (isEnable)
117+
{
118+
_currentTime = DateTime.Now;
119+
if (this._linearCmdQueue.Count > 0 && _currentTime >= _nextDispatchTime)
120+
{
121+
var cmd = _linearCmdQueue.Dequeue();
122+
await DispatchLinearCmd(cmd.cmd, cmd.aToken, cmd.parentMsgId);
123+
_nextDispatchTime = _currentTime.AddMilliseconds(cmd.cmd.Duration);
124+
}
125+
await Task.Delay(TimeSpan.FromMilliseconds(10));
126+
}
127+
}
128+
129+
88130
private async Task<ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg, CancellationToken aToken)
89131
{
90132
BpLogger.Debug("Stopping Device " + Name);
91133

92-
await Interface.WriteValueAsync(new byte[] { (byte)_deviceType, (byte)_commandType, 0 },
93-
aToken).ConfigureAwait(false);
134+
if (_deviceType == DeviceType.Piston)
135+
{
136+
// Forced transition to the front
137+
await Interface.WriteValueAsync(new byte[] { (byte)_deviceType, 0, 60 }, aToken).ConfigureAwait(false);
138+
}
139+
else
140+
{
141+
await Interface.WriteValueAsync(new byte[] { (byte)_deviceType, (byte)_commandType, 0 }, aToken).ConfigureAwait(false);
142+
}
143+
isEnable = false;
144+
94145
return new Ok(aMsg.Id);
95146
}
96147

@@ -158,5 +209,79 @@ await Interface.WriteValueAsync(new[] { (byte)_deviceType, (byte)_commandType, (
158209
aToken).ConfigureAwait(false);
159210
return new Ok(aMsg.Id);
160211
}
212+
213+
214+
private async Task<ButtplugMessage> HandleLinearCmd(ButtplugDeviceMessage aMsg, CancellationToken aToken)
215+
{
216+
if (!isEnable && _commandType == CommandType.Linear)
217+
{
218+
_linearCmdQueue.Clear();
219+
}
220+
221+
var cmdMsg = CheckMessageHandler<LinearCmd>(aMsg);
222+
foreach (var cmd in cmdMsg.Vectors)
223+
{
224+
VorzePistonCommand cmdWrapper;
225+
cmdWrapper.parentMsgId = aMsg.Id;
226+
cmdWrapper.cmd = cmd;
227+
cmdWrapper.aToken = aToken;
228+
_linearCmdQueue.Enqueue(cmdWrapper);
229+
}
230+
231+
if (!isEnable && _commandType == CommandType.Linear)
232+
{
233+
_currentTime = DateTime.Now;
234+
_nextDispatchTime = _currentTime;
235+
isEnable = true;
236+
await Task.Run(async () => { ObserveLinearCmdQueue(); });
237+
}
238+
239+
return new Ok(aMsg.Id);
240+
}
241+
private async Task<ButtplugMessage> DispatchLinearCmd(LinearCmd.VectorSubcommand cmd, CancellationToken aToken, uint parentMsgId)
242+
{
243+
//byte position = (byte)Math.Ceiling((1d / 200d) * (cmd.Position * 100) * 100);
244+
byte position = (byte)Math.Ceiling(cmd.Position * 200);
245+
byte direction = (byte)(_beforeLinearCmdPosition > position ? 0 : 1);
246+
byte speed = ResolveLinearCmdSpeed(cmd.Duration, direction);
247+
248+
await Interface.WriteValueAsync(new[] { (byte)_deviceType, position, speed }, aToken).ConfigureAwait(false);
249+
_beforeLinearCmdPosition = position;
250+
251+
return new Ok(parentMsgId);
252+
}
253+
254+
public byte ResolveLinearCmdSpeed(uint duration, byte direction)
255+
{
256+
// Convert back to stroke speed from the interval.
257+
//
258+
// Front and back stroke speed is asymmetric.
259+
// (From back to front is slower than front to back.)
260+
//
261+
byte speed = 10; // defaults. minimum.
262+
263+
if (duration <= 200)
264+
{
265+
speed = 60;
266+
}
267+
else if (duration <= 300)
268+
{
269+
speed = direction > 0 ? (byte)20 : (byte)30;
270+
}
271+
else if (duration <= 550)
272+
{
273+
speed = direction > 0 ? (byte)15 : (byte)20;
274+
}
275+
else if (duration <= 700)
276+
{
277+
speed = direction > 0 ? (byte)13 : (byte)20;
278+
}
279+
else
280+
{
281+
speed = 10;
282+
}
283+
284+
return speed;
285+
}
161286
}
162287
}

0 commit comments

Comments
 (0)