### Lovense Get Device Information Return Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/stpihkal/protocols/lovense/index.md Example of the return format for the 'DeviceType;' command, showing toy model, firmware version, and Bluetooth MAC address. The format is a colon-delimited list. ```text C:11:0082059AD3BD; ``` -------------------------------- ### Install and Run Buttplug Dev Server Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/CLAUDE.md Use these commands to manage dependencies and start the development server with hot reloading. ```bash yarn install # Install dependencies yarn start # Start dev server (hot reload) ``` -------------------------------- ### Run Programmed Pattern Return Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/stpihkal/protocols/lovense/index.md Example return for the Preset command, indicating successful execution. ```text OK; ``` -------------------------------- ### WSDM Python Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/dev-guide/inflating-buttplug/devices/websocket-device-manager.mdx A full Python script demonstrating a WSDM setup. It connects to the WSDM server, identifies as a Lovense Hush, handles protocol initialization, and responds to vibration and battery level commands. ```python import asyncio import json import logging import sys import uuid from buttplug.client import ButtplugClient, ButtplugClientDevice from buttplug.core.messages import ( DeviceSpecifier, DeviceSpecifierType, ErrorEvent, ErrorSeverity, ErrorSource, MessageManager, RequestDevice, StopDevice, VibrateCmd, BatteryLevelCmd, BatteryLevelReading, DeviceType, ProtocolSpec, ProtocolSpecVersion, StopAllDevices, ButtplugMessage, ButtplugMessageProto, ButtplugMessageProtoVersion, ButtplugMessageProtoType, ButtplugMessageProtoError, ButtplugMessageProtoErrorSeverity, ButtplugMessageProtoErrorSource, ButtplugMessageProtoRequestDevice, ButtplugMessageProtoStopDevice, ButtplugMessageProtoVibrateCmd, ButtplugMessageProtoBatteryLevelCmd, ButtplugMessageProtoBatteryLevelReading, ButtplugMessageProtoDeviceType, ButtplugMessageProtoStopAllDevices, ButtplugMessageProtoProtocolSpec, ButtplugMessageProtoProtocolSpecVersion, ButtplugMessageProtoDeviceSpecifier, ButtplugMessageProtoDeviceSpecifierType, ButtplugMessageProtoErrorEvent ) # This is a simplified example. A real WSDM device would likely need to handle # more complex protocol initialization and device messages. class LovenseHushWSDMDevice(ButtplugClientDevice): def __init__(self, client: ButtplugClient, name: str, address: str): super().__init__(client, name, address) self.device_type = DeviceType.Vibrator self.features = { "VibrateCmd": True, "BatteryLevelCmd": True } self.max_speed = 1.0 async def vibrate(self, duration: int, speed: float) -> None: logging.info(f"Received VibrateCmd: Duration={duration}, Speed={speed}") # In a real device, this would send a command to the physical device. # For this example, we just log it. await asyncio.sleep(duration / 1000.0) logging.info("Vibration finished.") async def battery_level(self) -> BatteryLevelReading: logging.info("Received BatteryLevelCmd") # In a real device, this would query the physical device for its battery level. # For this example, we return a dummy value. return BatteryLevelReading(battery_level=0.85) class LovenseHushWSDMProtocol(ProtocolSpec): def __init__(self): super().__init__( "lovense", ProtocolSpecVersion.V0_1, [DeviceSpecifier(DeviceSpecifierType.Name, "LVSDevice")] ) async def initialize_device(self, client: ButtplugClient, device: ButtplugClientDevice) -> None: logging.info("Initializing Lovense Hush WSDM Device") # The Lovense protocol expects a "DeviceType;" command to be sent back # during initialization. We'll simulate that here. # In a real WSDM, this would be sent over the websocket. logging.info("Sending dummy 'DeviceType;' response.") # await device.send_raw_message("DeviceType;\n") # Example of sending raw logging.info("Lovense Hush WSDM Device Initialized.") async def run_wsdm_example(): logging.basicConfig(level=logging.INFO) # Create a client client = ButtplugClient("WSDM Python Example") # Add the Lovense Hush WSDM protocol client.add_protocol(LovenseHushWSDMProtocol()) # Connect to the WSDM server # For this example, we'll assume the WSDM server is running on localhost:12345 # and that the device identifier is 'Z' and address is a random string. # In a real application, these would be dynamically determined or configured. device_identifier = "Z" device_address = str(uuid.uuid4()) logging.info(f"Connecting to WSDM server with identifier: {device_identifier}, address: {device_address}") try: await client.connect( "ws://localhost:12345", # The WSDM handshake requires a specific JSON packet. # This is sent as the first message after connection. # The client library handles this automatically if the server # is configured as a WSDM server. # However, for a direct WSDM connection, you may need to send it manually. # For this example, we assume the client library handles it. # If not, you would do something like: # await client.send_raw_message(json.dumps({ # "identifier": device_identifier, # "address": device_address, # "version": 0 # })) ) except Exception as e: logging.error(f"Failed to connect to WSDM server: {e}") return # Wait for devices to be found. The WSDM server will send device info. # We expect our Lovense Hush device to be found. await asyncio.sleep(2) # Give the server time to announce devices # Find our Lovense Hush device lovense_device = None for dev in client.devices: if dev.name == "LVSDevice" and dev.address == device_address: lovense_device = dev break if lovense_device is None: logging.error("Lovense Hush device not found. Did the WSDM server start correctly?") await client.disconnect() return logging.info(f"Found Lovense Hush device: {lovense_device.name} ({lovense_device.address})") # Example: Send a vibration command logging.info("Sending vibration command...") await lovense_device.vibrate(duration=1000, speed=0.7) # Example: Query battery level logging.info("Querying battery level...") battery_reading = await lovense_device.battery_level() logging.info(f"Battery level: {battery_reading.battery_level}") # Disconnect from the server logging.info("Disconnecting from WSDM server.") await client.disconnect() if __name__ == "__main__": # Check if running in a context that supports asyncio event loop (like Jupyter) try: loop = asyncio.get_running_loop() loop.create_task(run_wsdm_example()) except RuntimeError: asyncio.run(run_wsdm_example()) ``` -------------------------------- ### Sync Buttplug Examples Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/CLAUDE.md Shell script to synchronize v4 examples from sibling client repositories. ```bash ./scripts/sync-examples.sh ``` -------------------------------- ### Lovense Get Battery Level Return Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/stpihkal/protocols/lovense/index.md Example of the return format for the 'Battery;' command, indicating the remaining battery percentage. A value of '85;' means 85% battery remaining. ```text 85; ``` -------------------------------- ### Get Production Batch Number Return Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/stpihkal/protocols/lovense/index.md Example of the return format for the GetBatch command, showing the production batch number. ```text 190124; ``` -------------------------------- ### Start Local Development Server Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/README.md Starts a local development server that reflects changes live without requiring a restart. ```bash $ yarn start ``` -------------------------------- ### Import Raw Example File in MDX Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/CLAUDE.md Demonstrates how to import raw code files into MDX using raw-loader for displaying examples. ```javascript import RustExample from '!!raw-loader!/examples/v4/rust/connection.rs'; ``` -------------------------------- ### Install Dependencies with Yarn Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/README.md Run this command to install project dependencies using Yarn. ```bash $ yarn ``` -------------------------------- ### Shockspot Example Command Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/stpihkal/protocols/shockspot/index.md An example of a command sent to the Shockspot device. Commands are formatted as plain-text ASCII hex strings. ```text 01050407FF00F0 ``` -------------------------------- ### InputReading Serialization Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/spec/input.md This JSON example shows how InputReading messages are serialized. It includes examples for battery level and pressure readings. ```json [ { "InputReading": { "Id": 1, "DeviceIndex": 0, "FeatureIndex": 1, "Reading": { "Battery": { "Value": 50 } } } }, { "InputReading": { "Id": 0, "DeviceIndex": 1, "FeatureIndex": 0, "Reading": { "Pressure": { "Value": 200 } } } } ] ``` -------------------------------- ### Lovense Device Status Return Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/stpihkal/protocols/lovense/index.md Example of the return format for the 'Status:1;' command. A return value of '2;' indicates the toy is in a normal status. ```text 2; ``` -------------------------------- ### TryFun Yaun Command Examples Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/stpihkal/protocols/tryfun/index.md Provides concrete examples of BLE commands for various functions including heat control, thrust speed, spin speed, pause/restart, and pattern playback. These examples demonstrate the correct byte sequences for each mode. ```plaintext # Heat on aa 02 06 01 f9 ``` ```plaintext # Heat off aa 02 06 00 fa ``` ```plaintext # Thrust speed 1 aa 02 07 01 f8 ``` ```plaintext # Thrust speed 9 aa 02 07 09 f0 ``` ```plaintext # Spin speed 0 (stop) aa 02 08 00 f8 ``` ```plaintext # Spin speed 9 aa 02 08 09 ef ``` ```plaintext # Pause aa 02 03 00 fd ``` ```plaintext # Restart aa 02 03 01 fc ``` ```plaintext # Pattern 1 aa 02 09 01 f6 ``` ```plaintext # Pattern 5 aa 02 09 05 f2 ``` -------------------------------- ### Python Buttplug Connection Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/dev-guide/writing-buttplug-applications/connecting.mdx Demonstrates how to connect to a Buttplug server using Python. This example requires a Buttplug server to be running and accessible. ```python import asyncio from buttplug.client import ButtplugClient async def main(): # Replace with your server's address server_address = "ws://127.0.0.1:12345/buttplug" client = ButtplugClient("Python Example Client") try: # Connect to the server await client.connect(server_address) print("Connected to Buttplug server!") # You can now interact with the client, e.g., enumerate devices devices = await client.get_devices() print(f"Found devices: {len(devices)}") for device in devices: print(f"- {device.name}") # Keep the connection alive for a bit await asyncio.sleep(5) # Disconnect when done await client.disconnect() print("Disconnected from Buttplug server.") except Exception as e: print(f"Error: {e}") if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### FleshlightLaunchFW12Cmd Serialization Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/spec/deprecated.md Serialization example for the deprecated FleshlightLaunchFW12Cmd. This command is superseded by LinearCmd for easier reasoning about movement time and position. ```json [ { "FleshlightLaunchFW12Cmd": { "Id": 1, "DeviceIndex": 0, "Position": 95, "Speed": 90 } } ] ``` -------------------------------- ### TypeScript Buttplug Connection Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/dev-guide/writing-buttplug-applications/connecting.mdx Provides an example of connecting to a Buttplug server using TypeScript. This code requires a running Buttplug server instance. ```typescript import { ButtplugClient, ButtplugClientError } from "buttplug"; async function connectButtplug() { // Replace with your server's address const serverAddress = "ws://127.0.0.1:12345/buttplug"; const client = new ButtplugClient("TypeScript Example Client"); try { // Connect to the server await client.connect(serverAddress); console.log("Connected to Buttplug server!"); // You can now interact with the client, e.g., enumerate devices const devices = await client.getDevices(); console.log(`Found devices: ${devices.length}`); devices.forEach(device => { console.log(`- ${device.name}`); }); // Keep the connection alive for a bit await new Promise(resolve => setTimeout(resolve, 5000)); // Disconnect when done await client.disconnect(); console.log("Disconnected from Buttplug server."); } catch (e) { if (e instanceof ButtplugClientError) { console.error("Buttplug Client Error:", e.message); } else { console.error("An unexpected error occurred:", e); } } } connectButtplug(); ``` -------------------------------- ### Python Error Handling Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/dev-guide/writing-buttplug-applications/api-basics.mdx Demonstrates how to catch and handle Buttplug errors in Python. This example assumes the Buttplug Python library is installed. ```python from buttplug import ButtplugClient, ButtplugClientError async def run_example(): client = ButtplugClient("My Python App") try: # In a real application, you would connect here: # await client.connect(ButtplugWebsocketConnector("ws://127.0.0.1:12345")) print("Simulating connection...") # Simulate an error, e.g., sending a command to a disconnected device # This is a placeholder for an actual error that might occur raise ButtplugClientError("Device disconnected", ButtplugClientError.ErrorType.DEVICE_ERROR) except ButtplugClientError as e: print(f"Caught Buttplug Client Error: {e.message} (Type: {e.error_type})") if e.error_type == ButtplugClientError.ErrorType.DEVICE_ERROR: print("This is a device error.") except Exception as e: print(f"Caught an unexpected error: {e}") finally: # In a real application, you would disconnect here: # await client.disconnect() print("Simulating disconnection...") # To run this async function: # import asyncio # asyncio.run(run_example()) ``` -------------------------------- ### Connect to Remote Buttplug Server in TypeScript Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/dev-guide/writing-buttplug-applications/connectors.mdx Example of connecting to a remote Buttplug server using websockets in TypeScript. Ensure you have the Buttplug.js library and its types installed. ```typescript import ButtplugClient from 'buttplug'; async function connect() { // Replace with your server address const serverAddress: string = "ws://127.0.0.1:12345/"; // Create a websocket connector const connector = new ButtplugClient.ButtplugWebsocketConnector(serverAddress); // Create a new Buttplug client const client = new ButtplugClient("TSExample", connector); // Register message handler client.addListener('message', (msg: ButtplugMessage) => { console.log(`Received message: ${JSON.stringify(msg)}`); // Handle Buttplug messages here }); // Connect to the server try { await client.connect(); console.log("Connected to Buttplug server."); // Keep the client connected (e.g., by not closing the page) // You can add logic here to send commands or handle device events } catch (error) { console.error(`Error connecting: ${error}`); } // To disconnect later: // await client.disconnect(); // console.log("Disconnected from Buttplug server."); } connect(); ``` -------------------------------- ### Command Format Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/stpihkal/protocols/_template.md Illustrates the byte-level format for a specific command, including command ID, parameter, and checksum calculation. ```text 0xAA 0xBB 0xCC ``` -------------------------------- ### Get Software Version Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/stpihkal/protocols/kiiroo/kiiroo-bootloader.md Retrieves the version of the firmware currently installed on the hardware. The return format can be 6 or 12 bytes, with the major and minor versions located at different byte offsets. ```APIDOC ## Get Software Version ### Description Retrieves information about the version of the firmware currently on the hardware. ### Command - Command Index: 0x05 - Command Data: 0x00 ### Returns If return is 6 bytes: - Byte[4] - Major Version - Byte[5] - Minor Version If return is 12 bytes: - Byte[10] - Major Version - Byte[11] - Minor Version For example, if the firmware version is v1.3, and the return is 6 bytes, we expect it to look like 0xXX 0xXX 0xXX 0xXX 0x01 0x03 ``` -------------------------------- ### Rust Embedded Connector Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/dev-guide/cookbook/connections/embedding.mdx This example demonstrates setting up an embedded server with a Bluetooth device manager using the library's built-in configuration. It is currently only available in Rust. ```rust use buttplug::core::connector::ButtplugConnector; use buttplug::core::server::ButtplugServer; use buttplug::server::device_manager::DeviceManager; use buttplug::server::device_manager::DeviceManagerBuilder; use buttplug::server::logging::Logger; use buttplug::server::ButtplugServerBuilder; use std::sync::{Arc, Mutex}; #[tokio::main] async fn main() -> Result<(), Box> { // Create a logger let logger = Logger::new(); // Create a device manager let device_manager = DeviceManagerBuilder::new(logger.clone()).build(); // Create a Buttplug server let server = ButtplugServerBuilder::new("embedded_server_example", logger.clone()) .device_manager(device_manager) .finish() .await?; // Wrap the server in an Arc for shared access let server = Arc::new(Mutex::new(server)); // Create an embedded connector let connector = buttplug::core::connector::embedded::EmbeddedConnector::new(server.clone()); // Start the server let mut server_handle = buttplug::core::server::ButtplugServerHandle::new(server.clone(), connector.into_inner()); server_handle.start().await?; println!("Buttplug server started in embedded mode."); // Keep the server running (e.g., for a specific duration or until a signal) // In a real application, you would have a more robust way to keep the server alive. tokio::time::sleep(tokio::time::Duration::from_secs(60)).await; // Stop the server server_handle.stop().await?; println!("Buttplug server stopped."); Ok(()) } ``` -------------------------------- ### Start Accelerometer Data Stream Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/stpihkal/protocols/lovense/index.md Starts a stream of accelerometer data from the toy. ```APIDOC ## Start Accelerometer Data Stream ### Description Starts a stream of accelerometer data. Will send constantly until stop command is sent. Incoming accelerometer data starts with the letter G, followed by 3 16-bit little-endian numbers. ### Command Format ``` StartMove:1; ``` ### Return Example ``` GEF008312ED00; ``` Denotes [0x00EF, 0x1283, 0x00ED] accelerometer readings. ``` -------------------------------- ### Rust Buttplug Connection Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/dev-guide/writing-buttplug-applications/connecting.mdx Demonstrates how to establish a connection to a Buttplug server using Rust. Ensure the Buttplug server is running and accessible. ```rust use buttplug::client::{ButtplugClient, ButtplugClientError}; use buttplug::core::messages::ButtplugMessage; use futures::StreamExt; #[tokio::main] async fn main() -> Result<(), ButtplugClientError> { // Replace with your server's address let server_address = "ws://127.0.0.1:12345/buttplug"; let mut client = ButtplugClient::new("Rust Example Client"); // Connect to the server client.connect(server_address).await?; println!("Connected to Buttplug server!"); // You can now interact with the client, e.g., enumerate devices let devices = client.get_devices().await?; println!("Found devices: {:?}", devices); // Keep the connection alive for a bit or process messages // For a real application, you'd likely have a message loop here tokio::time::sleep(tokio::time::Duration::from_secs(5)).await; // Disconnect when done client.disconnect().await?; println!("Disconnected from Buttplug server."); Ok(()) } ``` -------------------------------- ### Start AGUI Angel's Wing Device (V1.8) Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/stpihkal/protocols/agui/index.md Use this command to initialize the V1.8 hardware version of the device for reading sensor data. Successful initialization is indicated by read responses starting with `0x55 0xAA 0xAA`. ```bash 0x87 0xAA 0xAA 0x06 0xF1 0xD2 ``` -------------------------------- ### RSSILevelReading Serialization Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/spec/deprecated.md Example of how to serialize an RSSILevelReading message. This message is deprecated and superseded by SensorReading. ```json [ { "RSSILevelReading": { "Id": 1, "DeviceIndex": 0, "RSSILevel": -40 } } ] ``` -------------------------------- ### RSSILevelCmd Serialization Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/spec/deprecated.md Example of how to serialize an RSSILevelCmd message. This command is deprecated and superseded by SensorReadCmd. ```json [ { "RSSILevelCmd": { "Id": 1, "DeviceIndex": 0 } } ] ``` -------------------------------- ### BatteryLevelReading Serialization Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/spec/deprecated.md Example of how to serialize a BatteryLevelReading message. This message is deprecated and superseded by SensorReading. ```json [ { "BatteryLevelReading": { "Id": 1, "DeviceIndex": 0, "BatteryLevel": 0.5 } } ] ``` -------------------------------- ### C# Buttplug Connection Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/dev-guide/writing-buttplug-applications/connecting.mdx Illustrates how to connect to a Buttplug server using C#. This example assumes a running Buttplug server is available at the specified address. ```csharp using ButtplugIo.Client; using ButtplugIo.Core.Messages; using System; using System.Threading.Tasks; public class Program { public static async Task Main(string[] args) { // Replace with your server's address var serverAddress = new Uri("ws://127.0.0.1:12345/buttplug"); var client = new ButtplugClient("C# Example Client"); try { // Connect to the server await client.ConnectAsync(serverAddress); Console.WriteLine("Connected to Buttplug server!"); // You can now interact with the client, e.g., enumerate devices var devices = await client.GetDevicesAsync(); Console.WriteLine($"Found devices: {devices.Count}"); foreach (var device in devices) { Console.WriteLine($"- {device.Name}"); } // Keep the connection alive for a bit await Task.Delay(TimeSpan.FromSeconds(5)); // Disconnect when done await client.DisconnectAsync(); Console.WriteLine("Disconnected from Buttplug server."); } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); } } } ``` -------------------------------- ### Rust Device Enumeration Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/dev-guide/writing-buttplug-applications/device-enum.mdx Demonstrates how to enumerate devices in a Rust application using the Buttplug client library. Ensure event handlers are set up before connecting to catch initial device lists. ```rust use buttplug::client::{ButtplugClient, ButtplugClientError, ButtplugClientEvent}; use buttplug::core::messages::Device; use std::error::Error; #[tokio::main] async fn main() -> Result<(), Box> { let mut client = ButtplugClient::new("Device Enumeration Example"); // Set up event handlers BEFORE connecting client.add_event_handler(|event| async move { match event { ButtplugClientEvent::DeviceAdded(device) => { println!("Device Added: {}", device.name); } ButtplugClientEvent::DeviceRemoved(device) => { println!("Device Removed: {}", device.name); } _ => {} // Ignore other events for this example } Ok(()) }); // Connect to the server (replace with your server address if not local) client.connect("ws://127.0.0.1:12345/buttplug").await?; // Start scanning for devices client.start_scanning().await?; // Keep the application running to receive events // In a real application, you'd have a more robust way to keep the client alive // and handle user interaction. tokio::time::sleep(tokio::time::Duration::from_secs(10)).await; // Stop scanning (optional, scanning may stop on its own) client.stop_scanning().await?; // Disconnect from the server client.disconnect().await?; Ok(()) } ``` -------------------------------- ### BatteryLevelCmd Serialization Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/spec/deprecated.md Example of how to serialize a BatteryLevelCmd message. This command is deprecated and superseded by SensorReadCmd. ```json [ { "BatteryLevelCmd": { "Id": 1, "DeviceIndex": 0 } } ] ``` -------------------------------- ### VibrateCmd Serialization Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/spec/deprecated.md Example of how to serialize a VibrateCmd message. This command is deprecated and superseded by ScalarCmd. ```json [ { "VibrateCmd": { "Id": 1, "DeviceIndex": 0, "Speeds": [ { "Index": 0, "Speed": 0.5 }, { "Index": 1, "Speed": 1.0 } ] } } ] ``` -------------------------------- ### Initialize Fleshlight Launch Device Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/stpihkal/protocols/fleshlight/index.md Send this command to the Command Characteristic on bootup to put the Launch in user mode. ```plaintext 0x00 ``` -------------------------------- ### Setup PatternV2 Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/stpihkal/network/lovense-game-mode.md Defines a sequence of position keyframes for a pattern. This command must be called before the Play command. ```APIDOC ## Setup PatternV2 ### Description Defines a sequence of position keyframes. Must be called before Play. ### Request Example ```json { "command": "PatternV2", "type": "Setup", "actions": [ { "ts": 0, "pos": 0 }, { "ts": 1000, "pos": 100 }, { "ts": 2000, "pos": 0 }, { "ts": 3000, "pos": 100 }, { "ts": 4000, "pos": 0 } ], "apiVer": 1 } ``` ### Response Example ```json { "code": 200, "type": "ok" } ``` ### Parameters #### Request Body - **command** (string) - Required - Must be "PatternV2" - **type** (string) - Required - Must be "Setup" - **actions** (array) - Required - Array of action objects, each with `ts` (timestamp in ms) and `pos` (0-100). - **ts** (integer) - Timestamp in milliseconds relative to start. Must be > previous value. Maximum 7,200,000 (2 hours). - **pos** (integer) - Strength/position level, 0-100. - **apiVer** (integer) - Required - Must be 1 ``` -------------------------------- ### RawReading Serialization Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/spec/deprecated.md Example of how to serialize a RawReading message. This message is a response to RawReadCmd or received after RawSubscribe. ```json [ { "RawReading": { "Id": 1, "DeviceIndex": 0, "Endpoint": "rx", "Data": [0, 1, 0] } } ] ``` -------------------------------- ### Python Device Enumeration Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/dev-guide/writing-buttplug-applications/device-enum.mdx Demonstrates device enumeration in Python using the Buttplug client library. It's important to set up event handlers for device additions and removals before connecting to the server. ```python import asyncio from buttplug.client import ButtplugClient async def run_device_enumeration(): client = ButtplugClient("Device Enumeration Example Python") # Set up event handlers BEFORE connecting def device_added_handler(device): print(f"Device Added: {device.name}") def device_removed_handler(device): print(f"Device Removed: {device.name}") client.device_added_event += device_added_handler client.device_removed_event += device_removed_handler try: # Connect to the server (replace with your server address if not local) await client.connect("ws://127.0.0.1:12345/buttplug") print("Connected to Buttplug server.") # Start scanning for devices await client.start_scanning() print("Scanning started.") # Keep the application running to receive events for 10 seconds await asyncio.sleep(10) # Stop scanning (optional) await client.stop_scanning() print("Scanning stopped.") # Disconnect from the server await client.disconnect() print("Disconnected.") except Exception as e: print(f"Error: {e}") if __name__ == "__main__": asyncio.run(run_device_enumeration()) ``` -------------------------------- ### VorzeA10CycloneCmd Serialization Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/spec/deprecated.md Serialization example for the deprecated VorzeA10CycloneCmd. This command is superseded by a combination of VibrateCmd and RotateCmd. ```json [ { "VorzeA10CycloneCmd": { "Id": 1, "DeviceIndex": 0, "Speed": 50, "Clockwise": true } } ] ``` -------------------------------- ### LED Command Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/spec/output.md Example of an LED command to set the brightness of an LED. Value 0 always denotes turning off the LED. Different color LEDs will appear as multiple LED features. ```json [{ "OutputCmd": { "Id": 1, "DeviceIndex": 0, "FeatureIndex": 0, "Command": { "Led": { "Value": 10 } } } }] ``` -------------------------------- ### Basic Arithmetic Example in Python Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/dev-guide/intro/how-to-read.mdx A simple arithmetic operation in Python. This example demonstrates basic syntax. ```python # This is some Python a = 1 + 2 ``` -------------------------------- ### Basic Arithmetic Example in C# Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/dev-guide/intro/how-to-read.mdx A simple arithmetic operation in C#. This example demonstrates basic syntax. ```csharp // This is some C# var a = 1 + 2; ``` -------------------------------- ### Async Client Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/dev-guide/writing-buttplug-applications/api-basics.mdx Demonstrates asynchronous client operations for Buttplug. This pattern is used for handling potentially long-running requests and server-sent events. ```rust use buttplug::client::{ButtplugClient, ButtplugClientConnector, ButtplugClientError}; use buttplug::core::messages::ButtplugMessage; use futures::StreamExt; #[tokio::main] async fn main() -> Result<(), ButtplugClientError> { // Use the default connector for the example let connector = ButtplugClientConnector::new(); let mut client = ButtplugClient::new("my-rust-client", connector).await?; // Connect to the server client.connect("ws://127.0.0.1:12345/buttplug").await?; // Wait for the server to send us a device list update let mut message_stream = client.message_stream(); while let Some(msg) = message_stream.next().await { match msg { ButtplugMessage::DeviceList(dl) => { println!("Device List Update: {:?}", dl); // We have devices, we can now control them break; } _ => {} } } // Disconnect from the server client.disconnect().await?; Ok(()) } ``` ```csharp using ButtplugIo.Client; using ButtplugIo.Core.Messages; using System; using System.Threading.Tasks; namespace AsyncExample { class Program { static async Task Main(string[] args) { // Use the default connector for the example var connector = new ButtplugClientConnector(); var client = new ButtplugClient("my-csharp-client", connector); // Connect to the server await client.ConnectAsync("ws://127.0.0.1:12345/buttplug"); // Wait for the server to send us a device list update client.DeviceListChanged += (sender, args) => { Console.WriteLine($"Device List Update: {args.DeviceList}"); // We have devices, we can now control them }; // Keep the application running for a bit to receive events await Task.Delay(5000); // Disconnect from the server await client.DisconnectAsync(); } } } ``` ```js // NOTE: These are browser examples. Include Buttplug via CDN in your HTML: // // Use the default connector for the example const connector = new Buttplug.ButtplugClientConnector(); const client = new Buttplug.ButtplugClient("my-js-client", connector); // Connect to the server client.connect("ws://127.0.0.1:12345/buttplug").then(() => { console.log("Connected to server!"); // Wait for the server to send us a device list update client.addListener('deviceListUpdate', (deviceList) => { console.log("Device List Update:", deviceList); // We have devices, we can now control them }); }).catch((e) => { console.error("Failed to connect:", e); }); // Disconnect from the server (example) // setTimeout(() => { // client.disconnect(); // console.log("Disconnected from server."); // }, 5000); ``` ```typescript import { ButtplugClient, ButtplugClientConnector } from "buttplug"; async function run() { // Use the default connector for the example const connector = new ButtplugClientConnector(); const client = new ButtplugClient("my-ts-client", connector); try { // Connect to the server await client.connect("ws://127.0.0.1:12345/buttplug"); console.log("Connected to server!"); // Wait for the server to send us a device list update client.addListener('deviceListUpdate', (deviceList) => { console.log("Device List Update:", deviceList); // We have devices, we can now control them }); // Keep the application running for a bit to receive events await new Promise(resolve => setTimeout(resolve, 5000)); // Disconnect from the server await client.disconnect(); console.log("Disconnected from server."); } catch (e) { console.error("Failed to connect or run:", e); } } run(); ``` ```python import asyncio from buttplug import ButtplugClient, ButtplugClientConnector async def main(): # Use the default connector for the example connector = ButtplugClientConnector() client = ButtplugClient("my-python-client", connector) try: # Connect to the server await client.connect("ws://127.0.0.1:12345/buttplug") print("Connected to server!") # Wait for the server to send us a device list update async def device_list_handler(device_list): print(f"Device List Update: {device_list}") # We have devices, we can now control them client.add_device_list_update_callback(device_list_handler) # Keep the application running for a bit to receive events await asyncio.sleep(5) # Disconnect from the server await client.disconnect() print("Disconnected from server.") except Exception as e: print(f"Failed to connect or run: {e}") if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Position Command Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/spec/output.md Example of a Position command to move a device to a certain position as quickly as possible. This is expected to be used for very small movements and run at a maximum update rate. ```json [{ "OutputCmd": { "Id": 1, "DeviceIndex": 0, "FeatureIndex": 0, "Command": { "Position": { "Value": 10 } } } }] ``` -------------------------------- ### Basic Arithmetic Example in Rust Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/dev-guide/intro/how-to-read.mdx A simple arithmetic operation in Rust. This example demonstrates basic syntax. ```rust // This is some Rust let a = 1 + 2; ``` -------------------------------- ### C# Device Enumeration Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/dev-guide/writing-buttplug-applications/device-enum.mdx Illustrates device enumeration in a C# application using the Buttplug client library. Event handlers for device additions and removals should be registered prior to establishing a connection. ```csharp using ButtplugIo.Client; using ButtplugIo.Core.Messages; using System; using System.Threading.Tasks; namespace DeviceEnumerationExample { class Program { static async Task Main(string[] args) { var client = new ButtplugClient("Device Enumeration Example C#"); // Set up event handlers BEFORE connecting client.DeviceAdded += (sender, e) => { Console.WriteLine($"Device Added: {e.Device.Name}"); return Task.CompletedTask; }; client.DeviceRemoved += (sender, e) => { Console.WriteLine($"Device Removed: {e.Device.Name}"); return Task.CompletedTask; }; // Connect to the server (replace with your server address if not local) await client.ConnectAsync("ws://127.0.0.1:12345/buttplug"); // Start scanning for devices await client.StartScanningAsync(); // Keep the application running to receive events Console.WriteLine("Scanning for devices for 10 seconds..."); await Task.Delay(10000); // Stop scanning (optional) await client.StopScanningAsync(); // Disconnect from the server await client.DisconnectAsync(); Console.WriteLine("Disconnected."); } } } ``` -------------------------------- ### Internal Wiggler Full Speed Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/stpihkal/protocols/lelo/index.md Example command to set the internal wiggling motor to full speed. ```plaintext 0x0A 0x12 0x02 0x08 0x00 0x00 0x00 0x00 0x64 0x00 ``` -------------------------------- ### View Programmed Pattern Return Example (Lush 2) Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/stpihkal/protocols/lovense/index.md Example return for viewing a programmed pattern on a Lush 2 toy, using two-digit part indices. The response format is similar to the Domi but with padded indices. ```text P4:01/01:346797643; ``` -------------------------------- ### External Vibe Full Speed Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/stpihkal/protocols/lelo/index.md Example command to set the external vibration motor to full speed. ```plaintext 0x0A 0x12 0x01 0x08 0x00 0x00 0x00 0x00 0x64 0x00 ``` -------------------------------- ### Javascript Device Enumeration Example (Web) Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/dev-guide/writing-buttplug-applications/device-enum.mdx Shows how to enumerate devices in a web browser using Buttplug's Javascript client. Remember to include the Buttplug library via CDN and set up event handlers before connecting. ```javascript // NOTE: Include Buttplug via CDN in your HTML: // async function runDeviceEnumeration() { const client = new Buttplug.ButtplugClient("Device Enumeration Example JS"); // Set up event handlers BEFORE connecting client.addListener("deviceadded", (device) => { console.log(`Device Added: ${device.name}`); }); client.addListener("deviceremoved", (device) => { console.log(`Device Removed: ${device.name}`); }); try { // Connect to the server (replace with your server address if not local) await client.connect("ws://127.0.0.1:12345/buttplug"); console.log("Connected to Buttplug server."); // Start scanning for devices await client.startScanning(); console.log("Scanning started."); // Keep the browser tab open to receive events for 10 seconds await new Promise(resolve => setTimeout(resolve, 10000)); // Stop scanning (optional) await client.stopScanning(); console.log("Scanning stopped."); // Disconnect from the server await client.disconnect(); console.log("Disconnected."); } catch (e) { console.error("Error:", e); } } runDeviceEnumeration(); ``` -------------------------------- ### Live Control Commands Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/stpihkal/protocols/tcode/index.md Use these commands for quick, instant responses during live control. Append '\n' for the fastest execution. ```text L277 R09 V317439 ``` -------------------------------- ### RawUnsubscribeCmd Serialization Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/spec/deprecated.md Example of how to serialize a RawUnsubscribeCmd message. This command was used to unsubscribe from data from a device endpoint. ```json [ { "RawUnsubscribeCmd": { "Id": 1, "DeviceIndex": 0, "Endpoint": "tx" } } ] ``` -------------------------------- ### RawSubscribeCmd Serialization Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/docs/spec/deprecated.md Example of how to serialize a RawSubscribeCmd message. This command was used to subscribe to data from a device endpoint. ```json [ { "RawSubscribeCmd": { "Id": 1, "DeviceIndex": 0, "Endpoint": "tx" } } ] ``` -------------------------------- ### Count Programmed Patterns Return Example Source: https://github.com/buttplugio/docs.buttplug.io/blob/master/stpihkal/protocols/lovense/index.md Example return for the GetPatten command, indicating the number and indices of programmed patterns. ```text P:01234; ```