Connecting to a Buttplug Server
Once you've created a connector, it's time to connect to a server!
As all connector setup was done via the Connector setup, this is now just down to dealing with whether the connection process actually worked or not.
Network connections for websockets can fail due to usual connection issues (wrong address, server not up, network not on, etc...). There is also a chance that the client and server could have a version mismatch. We'll cover this in the next section.
- Rust
- C#
- Javascript
use buttplug::{
client::{ButtplugClient, ButtplugClientError},
core::{
connector::{ButtplugRemoteClientConnector, ButtplugWebsocketClientTransport, new_json_ws_client_connector},
errors::ButtplugError,
message::serializer::ButtplugClientJSONSerializer,
},
};
use tokio::io::{self, AsyncBufReadExt, BufReader};
async fn wait_for_input() {
BufReader::new(io::stdin())
.lines()
.next_line()
.await
.unwrap();
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// After you've created a connector, the connection looks the same no
// matter what, though the errors thrown may be different.
let connector = new_json_ws_client_connector("ws://127.0.0.1:12345");
// Now we connect. If anything goes wrong here, we'll get an Err with either
//
// - A ButtplugClientConnectionError if there's a problem with
// the Connector, like the network address being wrong, server not
// being up, etc.
// - A ButtplugHandshakeError if there is a client/server version
// mismatch.
let client = ButtplugClient::new("Example Client");
if let Err(e) = client.connect(connector).await {
match e {
ButtplugClientError::ButtplugConnectorError(error) => {
// If our connection failed, because the server wasn't turned on,
// SSL/TLS wasn't turned off, etc, we'll just print and exit
// here.
println!("Can't connect, exiting! Message: {}", error);
wait_for_input().await;
return Ok(());
}
ButtplugClientError::ButtplugError(error) => match error {
ButtplugError::ButtplugHandshakeError(error) => {
// This means our client is newer than our server, and we need to
// upgrade the server we're connecting to.
println!("Handshake issue, exiting! Message: {}", error);
wait_for_input().await;
return Ok(());
}
error => {
println!("Unexpected error type! {}", error);
wait_for_input().await;
return Ok(());
}
},
}
};
// We're connected, yay!
println!("Connected! Check Server for Client Name.");
wait_for_input().await;
// And now we disconnect as usual
client.disconnect().await?;
Ok(())
}
using System;
using System.Threading.Tasks;
using Buttplug.Core;
using Buttplug.Client;
namespace ConnectionExample
{
class Program
{
// Waits for the user to hit a key, so they can read whatever log
// messages might have been printed.
private static async Task WaitForKey()
{
Console.WriteLine("Press any key to continue.");
while (!Console.KeyAvailable)
{
await Task.Delay(1);
}
Console.ReadKey(true);
}
private static async Task RunExample()
{
// First, we create our Client
var client = new ButtplugClient("Example Client");
// After you've created a connector, the connection looks the same no
// matter what, though the errors thrown may be different.
var connector = new ButtplugWebsocketConnector(new Uri("ws://127.0.0.1:12345"));
// Now we connect. If anything goes wrong here, we'll either throw
//
// - A ButtplugClientConnectionException if there's a problem with
// the Connector, like the network address being wrong, server not
// being up, etc.
// - A ButtplugHandshakeException if there is a client/server version
// mismatch.
try
{
await client.ConnectAsync(connector);
}
catch (ButtplugClientConnectorException ex)
{
// If our connection failed, because the server wasn't turned on,
// SSL/TLS wasn't turned off, etc, we'll just print and exit
// here. This will most likely be a wrapped exception.
Console.WriteLine(
$"Can't connect, exiting! Message: {ex.InnerException.Message}");
await WaitForKey();
return;
}
catch (ButtplugHandshakeException ex)
{
// This means our client is newer than our server, and we need to
// upgrade the server we're connecting to.
Console.WriteLine(
$"Handshake issue, exiting! Message: {ex.InnerException.Message}");
await WaitForKey();
return;
}
// We're connected, yay!
Console.WriteLine("Connected! Check Server for Client Name.");
await WaitForKey();
// And now we disconnect as usual
await client.DisconnectAsync();
}
private static void Main()
{
RunExample().Wait();
}
}
}
// This example assumes Buttplug is brought in as a root namespace, via
// inclusion by a script tag, i.e.
//
// <script lang="javascript"
// src="https://cdn.jsdelivr.net/npm/buttplug@3.0.0/dist/web/buttplug.min.js">
// </script>
//
// If you're trying to load this, change the version to the latest available.
const runWebsocketConnectionExample = async () => {
// This is the default insecure address for Intiface Central (https://intiface.com/central). You
// can connect to it via most browsers.
let address = "ws://localhost:12345"
// After you've created a connector, the connection looks the same no matter what, though the
// errors thrown may be different.
let connector = new Buttplug.ButtplugBrowserWebsocketClientConnector(address);
let client = new Buttplug.ButtplugClient("Websocket Connection Example");
// Now we connect. If anything goes wrong here, we'll either throw
//
// - A ButtplugClientConnectionException if there's a problem with
// the Connector, like the network address being wrong, server not
// being up, etc.
// - A ButtplugHandshakeException if there is a client/server version
// mismatch.
try {
await client.connect(connector);
}
catch (ex)
{
// If our connection failed, because the server wasn't turned on, SSL/TLS
// wasn't turned off, etc, we'll just print and exit here. This will most
// likely be a wrapped exception.
//
// This could also mean our client is newer than our server, and we need to
// upgrade the server we're connecting to.
console.log(ex);
}
// We're connected, yay!
console.log("Connected!");
setTimeout(async () => {
// And now we disconnect as usual
console.log("Disconnecting");
await client.disconnect();
}, 3000);
};
Client/Server Compatibility
tl;dr As long as the server API version is equal to or greater (newer) than the client API version, things should be fine.
To see the full explanation and rules on API versioning, see the protocol portion of the architecture section.
What to Expect on Successful Connect
In most cases, connectors are only used for the initial connection setup, then you can pretty much forget about them after that. Everything will look the same across all connector types from here on out.
Now that you know how to get a Buttplug session running, you're ready to enumerate and control devices!