public async Task RequestDeviceList() { var resp = await SendMessage(new RequestDeviceList(nextMsgId)); if (!(resp is DeviceList) || (resp as DeviceList).Devices == null) { if (resp is Error) { _owningDispatcher.Invoke(() => { ErrorReceived?.Invoke(this, new ErrorEventArgs(resp as Error)); }); } return; } foreach (var d in (resp as DeviceList).Devices) { if (!_devices.ContainsKey(d.DeviceIndex)) { var device = new ButtplugClientDevice(d); if (_devices.TryAdd(d.DeviceIndex, device)) { _owningDispatcher.Invoke(() => { DeviceAdded?.Invoke(this, new DeviceEventArgs(device, DeviceAction.ADDED)); }); } } } }
/// <summary> /// Message Received event handler. Either tries to match incoming messages as replies to /// messages we've sent, or fires an event related to an incoming event, like device /// additions/removals, log messages, etc. /// </summary> /// <param name="aSender">Object sending the open event, unused.</param> /// <param name="aArgs">Event parameters, including the data received.</param> private async void MessageReceivedHandler(object aSender, MessageReceivedEventArgs aArgs) { var msg = aArgs.Message; switch (msg) { case Log l: Log?.Invoke(this, new LogEventArgs(l)); break; case DeviceAdded d: var dev = new ButtplugClientDevice(_bpLogManager, this, SendDeviceMessageAsync, d); _devices.Add(d.DeviceIndex, dev); DeviceAdded?.Invoke(this, new DeviceAddedEventArgs(dev)); break; case DeviceRemoved d: if (!_devices.ContainsKey(d.DeviceIndex)) { ErrorReceived?.Invoke(this, new ButtplugExceptionEventArgs( new ButtplugDeviceException(_bpLogger, "Got device removed message for unknown device.", msg.Id))); return; } var oldDev = _devices[d.DeviceIndex]; _devices.Remove(d.DeviceIndex); DeviceRemoved?.Invoke(this, new DeviceRemovedEventArgs(oldDev)); break; case ScanningFinished _: // The scanning finished event is self explanatory and doesn't require extra arguments. ScanningFinished?.Invoke(this, new EventArgs()); break; case Error e: // This will both log the error and fire it from our ErrorReceived event handler. ErrorReceived?.Invoke(this, new ButtplugExceptionEventArgs(ButtplugException.FromError(_bpLogger, e))); if (e.ErrorCode == Error.ErrorClass.ERROR_PING) { PingTimeout?.Invoke(this, EventArgs.Empty); await DisconnectAsync().ConfigureAwait(false); } break; default: ErrorReceived?.Invoke(this, new ButtplugExceptionEventArgs( new ButtplugMessageException(_bpLogger, $"Got unhandled message: {msg}", msg.Id))); break; } }
private void MessageReceivedHandler(object aSender, WebSocket4Net.MessageReceivedEventArgs aArgs) { var msgs = Deserialize(aArgs.Message); foreach (var msg in msgs) { if (msg.Id > 0 && _waitingMsgs.TryRemove(msg.Id, out TaskCompletionSource <ButtplugMessage> queued)) { queued.TrySetResult(msg); continue; } switch (msg) { case Log l: _owningDispatcher.Send(_ => { Log?.Invoke(this, new LogEventArgs(l)); }, null); break; case DeviceAdded d: var dev = new ButtplugClientDevice(d); _devices.AddOrUpdate(d.DeviceIndex, dev, (idx, old) => dev); _owningDispatcher.Send(_ => { DeviceAdded?.Invoke(this, new DeviceEventArgs(dev, DeviceAction.ADDED)); }, null); break; case DeviceRemoved d: if (_devices.TryRemove(d.DeviceIndex, out ButtplugClientDevice oldDev)) { _owningDispatcher.Send(_ => { DeviceRemoved?.Invoke(this, new DeviceEventArgs(oldDev, DeviceAction.REMOVED)); }, null); } break; case ScanningFinished sf: _owningDispatcher.Send(_ => { ScanningFinished?.Invoke(this, new ScanningFinishedEventArgs(sf)); }, null); break; case Error e: _owningDispatcher.Send(_ => { ErrorReceived?.Invoke(this, new ErrorEventArgs(e)); }, null); break; } } }
/// <summary> /// Sends a DeviceMessage (e.g. <see cref="VibrateCmd"/> or <see cref="LinearCmd"/>). Handles /// constructing some parts of the message for the user. /// </summary> /// <param name="aDevice">The device to be controlled by the message.</param> /// <param name="aDeviceMsg">The device message (Id and DeviceIndex will be overriden).</param> /// <returns> /// <see cref="Ok"/> message on success, <see cref="Error"/> message with error info otherwise. /// </returns> public async Task <ButtplugMessage> SendDeviceMessage(ButtplugClientDevice aDevice, ButtplugDeviceMessage aDeviceMsg) { if (!_devices.TryGetValue(aDevice.Index, out ButtplugClientDevice dev)) { return(new Error("Device not available.", Error.ErrorClass.ERROR_DEVICE, ButtplugConsts.SystemMsgId)); } if (!dev.AllowedMessages.ContainsKey(aDeviceMsg.GetType().Name)) { return(new Error("Device does not accept message type: " + aDeviceMsg.GetType().Name, Error.ErrorClass.ERROR_DEVICE, ButtplugConsts.SystemMsgId)); } aDeviceMsg.DeviceIndex = aDevice.Index; return(await SendMessage(aDeviceMsg)); }
public async Task RequestDeviceList() { var deviceList = (await SendMessage(new RequestDeviceList(nextMsgId))) as DeviceList; if (deviceList.Devices == null) { return; } foreach (var d in deviceList.Devices) { if (!_devices.ContainsKey(d.DeviceIndex)) { var device = new ButtplugClientDevice(d); if (_devices.TryAdd(d.DeviceIndex, device)) { _owningDispatcher.Invoke(() => { DeviceAdded?.Invoke(this, new DeviceEventArgs(device, DeviceAction.ADDED)); }); } } } }
private async void wsReader(CancellationToken aToken) { var sb = new StringBuilder(); while (_ws != null && _ws.State == WebSocketState.Open && !aToken.IsCancellationRequested) { try { var buffer = new byte[5]; var segment = new ArraySegment <byte>(buffer); WebSocketReceiveResult result; try { result = await _ws.ReceiveAsync(segment, aToken); } catch (OperationCanceledException) { // If the operation is cancelled, just continue so we fall out of the loop continue; } var input = Encoding.UTF8.GetString(buffer, 0, result.Count); sb.Append(input); if (result.EndOfMessage) { var msgs = Deserialize(sb.ToString()); foreach (var msg in msgs) { if (msg.Id > 0 && _waitingMsgs.TryRemove(msg.Id, out TaskCompletionSource <ButtplugMessage> queued)) { queued.TrySetResult(msg); continue; } switch (msg) { case Log l: _owningDispatcher.Invoke(() => { Log?.Invoke(this, new LogEventArgs(l)); }); break; case DeviceAdded d: var dev = new ButtplugClientDevice(d); _devices.AddOrUpdate(d.DeviceIndex, dev, (idx, old) => dev); _owningDispatcher.Invoke(() => { DeviceAdded?.Invoke(this, new DeviceEventArgs(dev, DeviceAction.ADDED)); }); break; case DeviceRemoved d: if (_devices.TryRemove(d.DeviceIndex, out ButtplugClientDevice oldDev)) { _owningDispatcher.Invoke(() => { DeviceRemoved?.Invoke(this, new DeviceEventArgs(oldDev, DeviceAction.REMOVED)); }); } break; case ScanningFinished sf: _owningDispatcher.Invoke(() => { ScanningFinished?.Invoke(this, new ScanningFinishedEventArgs(sf)); }); break; case Error e: _owningDispatcher.Invoke(() => { ErrorReceived?.Invoke(this, new ErrorEventArgs(e)); }); break; } } sb.Clear(); } } catch (WebSocketException) { // Noop - WS probably closed on us during read } } }
/// <summary> /// Sends a DeviceMessage (e.g. <see cref="VibrateCmd"/> or <see cref="LinearCmd"/>). Handles /// constructing some parts of the message for the user. /// </summary> /// <param name="aDevice">The device to be controlled by the message.</param> /// <param name="aDeviceMsg">The device message (Id and DeviceIndex will be overriden).</param> /// <param name="aToken">Cancellation token, for cancelling action externally if it is not yet finished.</param> /// <returns> /// Void on success, throws <see cref="ButtplugClientException" /> otherwise. /// </returns> protected async Task SendDeviceMessageAsync(ButtplugClientDevice aDevice, ButtplugDeviceMessage aDeviceMsg, CancellationToken aToken = default(CancellationToken)) { await SendMessageExpectOk(aDeviceMsg, aToken).ConfigureAwait(false); }
// ReSharper disable once UnusedMember.Global public async Task ConnectAsync(CancellationToken aToken = default(CancellationToken)) { if (Connected) { throw new ButtplugHandshakeException(_bpLogger, "Client already connected to a server."); } _connector.MessageReceived += MessageReceivedHandler; await _connector.ConnectAsync(aToken).ConfigureAwait(false); var res = await SendMessageAsync(new RequestServerInfo(Name), aToken).ConfigureAwait(false); switch (res) { case ServerInfo si: if (si.MaxPingTime > 0) { _pingTimer = new Timer(OnPingTimer, null, 0, Convert.ToInt32(Math.Round(((double)si.MaxPingTime) / 2, 0))); } if (si.MessageVersion < ButtplugConsts.CurrentSpecVersion) { await DisconnectAsync().ConfigureAwait(false); throw new ButtplugHandshakeException(_bpLogger, $"B******g Server's schema version ({si.MessageVersion}) is less than the client's ({ButtplugConsts.CurrentSpecVersion}). A newer server is required.", res.Id); } // Get full device list and populate internal list var resp = await SendMessageAsync(new RequestDeviceList()).ConfigureAwait(false); if (!(resp is DeviceList)) { await DisconnectAsync().ConfigureAwait(false); if (resp is Error errResp) { throw ButtplugException.FromError(_bpLogger, errResp); } throw new ButtplugHandshakeException(_bpLogger, "Received unknown response to DeviceList handshake query"); } foreach (var d in (resp as DeviceList).Devices) { if (_devices.ContainsKey(d.DeviceIndex)) { continue; } var device = new ButtplugClientDevice(_bpLogManager, this, SendDeviceMessageAsync, d); _devices[d.DeviceIndex] = device; DeviceAdded?.Invoke(this, new DeviceAddedEventArgs(device)); } break; case Error e: await DisconnectAsync().ConfigureAwait(false); throw ButtplugException.FromError(_bpLogger, e); default: await DisconnectAsync().ConfigureAwait(false); throw new ButtplugHandshakeException(_bpLogger, $"Unrecognized message {res.Name} during handshake", res.Id); } }
public DeviceEventArgs(ButtplugClientDevice aDevice, DeviceAction aAction) { device = aDevice; action = aAction; }
/// <summary> /// Initializes a new instance of the <see cref="DeviceRemovedEventArgs"/> class. /// </summary> /// <param name="aDevice">Device being removed.</param> public DeviceRemovedEventArgs(ButtplugClientDevice aDevice) { Device = aDevice; }
private async void ScanToolStripMenuItem_ClickAsync(object sender, EventArgs e) { void HandleDeviceAdded(object aObj, DeviceAddedEventArgs aArgs) { Console.WriteLine($"Device connected: {aArgs.Device.Name}"); } client.DeviceAdded += HandleDeviceAdded; void HandleDeviceRemoved(object aObj, DeviceRemovedEventArgs aArgs) { Console.WriteLine($"Device removed: {aArgs.Device.Name}"); } client.DeviceRemoved += HandleDeviceRemoved; async Task ScanForDevices() { Console.WriteLine("Scanning for devices"); toolStripStatusLabel1.Text = "Scanning for devices"; await client.StartScanningAsync(); for (int a = 0; a < 10; a = a + 1) { Console.WriteLine(a); await Task.Delay(TimeSpan.FromMilliseconds(1000)); } await client.StopScanningAsync(); if (client.Devices.Any()) { toolStripStatusLabel1.Text = "Scanning complete, device(s) found"; } else { Console.WriteLine("No devices available. Please scan for a device."); toolStripStatusLabel1.Text = "Scanning complete, no devices found"; return; } } if (client.Connected == true) { await ScanForDevices(); if (!client.Devices.Any()) { return; } Form2 scanForm = new Form2(); scanForm.listBox1.Items.Clear(); foreach (var dev in client.Devices) { scanForm.listBox1.Items.Add(dev.Name); } DialogResult dr = scanForm.ShowDialog(this); if (dr == DialogResult.Cancel) { toolStripStatusLabel2.Text = "No device"; toolStripStatusLabel1.Text = "No device selected"; scanForm.Close(); } else if (dr == DialogResult.OK) { if (scanForm.getText() != "") { toolStripStatusLabel2.Text = scanForm.getText(); device = client.Devices[scanForm.listBox1.SelectedIndex]; toolStripStatusLabel1.Text = "Ready"; } else { toolStripStatusLabel2.Text = "No device"; toolStripStatusLabel1.Text = "No device selected"; } scanForm.Close(); } } else { toolStripStatusLabel1.Text = "Not connected to Intiface"; connectToolStripMenuItem.Enabled = true; scanToolStripMenuItem.Enabled = false; } }
public async Task Connect(Uri aURL, bool aIgnoreSSLErrors = false) { if (_ws != null && (_ws.State == WebSocketState.Connecting || _ws.State == WebSocketState.Open)) { throw new InvalidOperationException("Already connected!"); } _ws = new WebSocket(aURL.ToString()); _waitingMsgs.Clear(); _devices.Clear(); _counter = 1; _connectedOrFailed = new TaskCompletionSource <bool>(); _disconnected = new TaskCompletionSource <bool>(); _ws.Opened += OpenedHandler; _ws.Closed += ClosedHandler; _ws.Error += ErrorHandler; if (aIgnoreSSLErrors) { _ws.Security.AllowNameMismatchCertificate = true; _ws.Security.AllowUnstrustedCertificate = true; } _ws.Open(); _connecting = true; await _connectedOrFailed.Task; _connecting = false; if (_ws.State != WebSocketState.Open) { throw new Exception("Connection failed!"); } _ws.MessageReceived += MessageReceivedHandler; var res = await SendMessage(new RequestServerInfo(_clientName)); switch (res) { case ServerInfo si: if (si.MaxPingTime > 0) { _pingTimer = new Timer(OnPingTimer, null, 0, Convert.ToInt32(Math.Round(((double)si.MaxPingTime) / 2, 0))); } _messageSchemaVersion = si.MessageVersion; if (_messageSchemaVersion < ButtplugMessage.CurrentSchemaVersion) { throw new Exception("B******g Server's schema version (" + _messageSchemaVersion + ") is less than the client's (" + ButtplugMessage.CurrentSchemaVersion + "). A newer server is required."); } // Get full device list and populate internal list var resp = await SendMessage(new RequestDeviceList()); if ((resp as DeviceList)?.Devices == null) { if (resp is Error) { _owningDispatcher.Send(_ => { ErrorReceived?.Invoke(this, new ErrorEventArgs(resp as Error)); }, null); } return; } foreach (var d in (resp as DeviceList).Devices) { if (_devices.ContainsKey(d.DeviceIndex)) { continue; } var device = new ButtplugClientDevice(d); if (_devices.TryAdd(d.DeviceIndex, device)) { _owningDispatcher.Send(_ => { DeviceAdded?.Invoke(this, new DeviceEventArgs(device, DeviceAction.ADDED)); }, null); } } break; case Error e: throw new Exception(e.ErrorMessage); default: throw new Exception("Unexpecte message returned: " + res.GetType()); } }
/// <summary> /// Initializes a new instance of the <see cref="DeviceAddedEventArgs"/> class. /// </summary> /// <param name="aDevice">Device being added.</param> public DeviceAddedEventArgs(ButtplugClientDevice aDevice) { Device = aDevice; }