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));
                        });
                    }
                }
            }
        }
Example #2
0
        /// <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;
            }
        }
Example #3
0
        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;
                }
            }
        }
Example #4
0
        /// <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
                }
            }
        }
Example #7
0
 /// <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);
 }
Example #8
0
        // 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);
            }
        }
Example #9
0
 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;
 }
Example #11
0
        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;
            }
        }
Example #12
0
        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());
            }
        }
Example #13
0
 /// <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;
 }