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 (Web)
- TypeScript
- Python
use buttplug_client::{
ButtplugClient,
ButtplugClientError,
connector::ButtplugRemoteClientConnector,
serializer::ButtplugClientJSONSerializer,
};
use buttplug_core::errors::ButtplugError;
use buttplug_transport_websocket_tungstenite::ButtplugWebsocketClientTransport;
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 = ButtplugRemoteClientConnector::<
ButtplugWebsocketClientTransport,
ButtplugClientJSONSerializer,
>::new(ButtplugWebsocketClientTransport::new_insecure_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(());
}
},
_ => {
// None of the other errors are valid in this instance.
}
}
};
// 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(())
}
// Buttplug C# - Connection Example
//
// This example demonstrates how to connect to a Buttplug server
// (like Intiface Central) and handle connection errors.
using Buttplug.Client;
using Buttplug.Core;
// Create a client with your application's name.
// This name will be shown in Intiface Central.
var client = new ButtplugClient("Connection Example");
try
{
// Connect to the server. The extension method creates a WebSocket connector
// automatically from the URI string. Default port for Intiface Central is 12345.
await client.ConnectAsync("ws://127.0.0.1:12345");
Console.WriteLine("Connected! Check Intiface Central for the client name.");
Console.WriteLine("Press Enter to disconnect...");
Console.ReadLine();
// Disconnect cleanly
await client.DisconnectAsync();
}
catch (ButtplugClientConnectorException ex)
{
// Connection failed - server not running, wrong address, network issues, etc.
Console.WriteLine($"Can't connect to server: {ex.Message}");
Console.WriteLine("Make sure Intiface Central is running and the server is started.");
}
catch (ButtplugHandshakeException ex)
{
// Client/server version mismatch - need to upgrade one or the other
Console.WriteLine($"Handshake failed: {ex.Message}");
Console.WriteLine("Client and server versions may be incompatible.");
}
catch (ButtplugException ex)
{
// Other Buttplug-specific errors
Console.WriteLine($"Buttplug error: {ex.Message}");
}
Console.WriteLine("Press Enter to exit...");
Console.ReadLine();
// Buttplug Web - Remote Websocket Connector Example
//
// This example demonstrates how to connect to a remote Buttplug server
// using the websocket connector. This is the standard way to connect
// from a browser to Intiface Central.
//
// Include Buttplug via CDN:
// <script src="https://cdn.jsdelivr.net/npm/buttplug@4.0.0/dist/web/buttplug.min.js"></script>
const runWebsocketConnectionExample = async () => {
// This is the default insecure address for Intiface Central (https://intiface.com/central).
// You can connect to it via most browsers.
const address = "ws://localhost:12345";
// Create the connector with the server address
const connector = new Buttplug.ButtplugBrowserWebsocketClientConnector(address);
const client = new Buttplug.ButtplugClient("Websocket Connection Example");
// Set up disconnect handler before connecting
client.addListener("disconnect", () => {
console.log("Server connection lost!");
});
// Now we connect. If anything goes wrong here, we'll either throw:
//
// - A ButtplugClientConnectorException if there's a problem with
// the connector, like the network address being wrong, server not
// being up, etc.
// - A ButtplugInitError if there is a client/server version mismatch.
try {
console.log(`Connecting to ${address}...`);
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 could also mean our client is newer than our server, and we need to
// upgrade the server we're connecting to.
console.log("Connection failed:", ex);
return;
}
// We're connected!
console.log("Connected!");
console.log("Connection will disconnect automatically in 3 seconds...");
// Demonstrate we can use the connection
await client.startScanning();
console.log("Scanning for devices...");
// Disconnect after a delay
setTimeout(async () => {
console.log("Stopping scan...");
await client.stopScanning();
// Show any devices that were found
if (client.devices.size > 0) {
console.log("Devices found:");
for (const [index, device] of client.devices) {
console.log(` - ${device.name} (Index: ${index})`);
}
}
console.log("Disconnecting...");
await client.disconnect();
console.log("Disconnected.");
}, 3000);
};
// Buttplug TypeScript - Connection Example
//
// This example demonstrates how to connect to a Buttplug server
// (like Intiface Central) and handle connection errors.
//
// Prerequisites:
// 1. Install Intiface Central: https://intiface.com/central
// 2. Start the server in Intiface Central
// 3. Run: npx ts-node --esm connection-example.ts
import {
ButtplugClient,
ButtplugNodeWebsocketClientConnector,
ButtplugClientConnectorException,
ButtplugError,
ButtplugInitError,
} from 'buttplug';
import * as readline from 'readline';
async function waitForEnter(prompt: string): Promise<void> {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
return new Promise((resolve) => {
rl.question(prompt, () => {
rl.close();
resolve();
});
});
}
async function main(): Promise<void> {
// Create a client with your application's name.
// This name will be shown in Intiface Central.
const client = new ButtplugClient('Connection Example');
try {
// Create a connector to the server. Default port for Intiface Central is 12345.
const connector = new ButtplugNodeWebsocketClientConnector(
'ws://127.0.0.1:12345'
);
console.log('Connecting to Intiface Central...');
await client.connect(connector);
// We're connected!
console.log('Connected! Check Intiface Central for the client name.');
await waitForEnter('Press Enter to disconnect...');
// Disconnect cleanly
await client.disconnect();
console.log('Disconnected.');
} catch (e) {
if (e instanceof ButtplugClientConnectorException) {
// Connection failed - server not running, wrong address, network issues, etc.
console.log(`Can't connect to server: ${e.message}`);
console.log(
'Make sure Intiface Central is running and the server is started.'
);
} else if (e instanceof ButtplugInitError) {
// Client/server version mismatch - need to upgrade one or the other
console.log(`Handshake failed: ${e.message}`);
console.log('Client and server versions may be incompatible.');
} else if (e instanceof ButtplugError) {
// Other Buttplug-specific errors
console.log(`Buttplug error: ${e.message}`);
} else {
throw e;
}
}
await waitForEnter('Press Enter to exit...');
}
main().catch(console.error);
"""Connection - Connect to a Buttplug server.
This is the simplest possible Buttplug example. It connects to a
Buttplug server (like Intiface Central) and shows connection status.
Prerequisites:
1. Install Intiface Central: https://intiface.com/central/
2. Start Intiface Central and click "Start Server"
3. Run this script: python connection.py
"""
import asyncio
from buttplug import ButtplugClient, ButtplugError
async def main() -> None:
# Create a client with your application's name
client = ButtplugClient("Connection Example")
try:
# Connect to the server (Intiface Central default address)
print("Connecting to server...")
await client.connect("ws://127.0.0.1:12345")
print(f"Connected to: {client.server_name}")
# Connection is established - you can now scan for devices
print("Connection successful!")
except ButtplugError as e:
# Handle connection errors
print(f"Failed to connect: {e}")
return
finally:
# Always disconnect when done
if client.connected:
await client.disconnect()
print("Disconnected.")
if __name__ == "__main__":
asyncio.run(main())
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!