Buttplug sex toy control library
at master 3.7 kB view raw
1use buttplug_client::{ 2 ButtplugClient, 3 ButtplugClientError, 4 connector::ButtplugRemoteClientConnector, 5 serializer::ButtplugClientJSONSerializer, 6}; 7 8use buttplug_core::message::OutputType; 9use buttplug_transport_websocket_tungstenite::ButtplugWebsocketClientTransport; 10use strum::IntoEnumIterator; 11use tokio::io::{self, AsyncBufReadExt, BufReader}; 12 13async fn wait_for_input() { 14 BufReader::new(io::stdin()) 15 .lines() 16 .next_line() 17 .await 18 .unwrap(); 19} 20 21#[tokio::main] 22async fn main() -> anyhow::Result<()> { 23 let connector = ButtplugRemoteClientConnector::< 24 ButtplugWebsocketClientTransport, 25 ButtplugClientJSONSerializer, 26 >::new(ButtplugWebsocketClientTransport::new_insecure_connector( 27 "ws://127.0.0.1:12345", 28 )); 29 30 let client = ButtplugClient::new("Example Client"); 31 client.connect(connector).await?; 32 33 println!("Connected!"); 34 35 // You usually shouldn't run Start/Stop scanning back-to-back like 36 // this, but with TestDevice we know our device will be found when we 37 // call StartScanning, so we can get away with it. 38 client.start_scanning().await?; 39 client.stop_scanning().await?; 40 println!("Client currently knows about these devices:"); 41 let mut device_index: i32 = -1; 42 for (i, device) in client.devices() { 43 device_index = i as i32; 44 println!("- {}", device.name()); 45 } 46 wait_for_input().await; 47 48 for (_, device) in client.devices() { 49 println!("{} supports these outputs:", device.name()); 50 for output_type in OutputType::iter() { 51 for feature in device.device_features().values() { 52 if let Some(output) = feature.feature().output() 53 && output.contains(output_type) 54 { 55 println!("- {}", output_type); 56 } 57 } 58 } 59 } 60 61 println!("Sending commands"); 62 63 // Now that we know the message types for our connected device, we 64 // can send a message over! Seeing as we want to stick with the 65 // modern generic messages, we'll go with VibrateCmd. 66 // 67 // There's a couple of ways to send this message. 68 let devices = client.devices(); 69 let test_client_device = devices.get(&(device_index as u32)).unwrap(); 70 71 // We can use the convenience functions on ButtplugClientDevice to 72 // send the message. This version sets all of the motors on a 73 // vibrating device to the same speed. 74 test_client_device.vibrate(0.5f64).await?; 75 76 // If we wanted to just set one motor on and the other off, we could 77 // try this version that uses an array. It'll throw an exception if 78 // the array isn't the same size as the number of motors available as 79 // denoted by FeatureCount, though. 80 // 81 // You can get the vibrator count using the following code, though we 82 // know it's 2 so we don't really have to use it. 83 let vibrator_count = test_client_device.vibrate_features().len(); 84 85 println!( 86 "{} has {} vibrators.", 87 test_client_device.name(), 88 vibrator_count, 89 ); 90 91 // Just set all of the vibrators to full speed. 92 if vibrator_count > 0 { 93 test_client_device.vibrate(10).await?; 94 } else { 95 println!("Device does not have > 1 vibrators, not running multiple vibrator test."); 96 } 97 98 wait_for_input().await; 99 println!("Disconnecting"); 100 // And now we disconnect as usual. 101 client.disconnect().await?; 102 println!("Trying error"); 103 // If we try to send a command to a device after the client has 104 // disconnected, we'll get an exception thrown. 105 let vibrate_result = test_client_device.vibrate(30).await; 106 if let Err(ButtplugClientError::ButtplugConnectorError(error)) = vibrate_result { 107 println!("Tried to send after disconnection! Error: "); 108 println!("{}", error); 109 } 110 wait_for_input().await; 111 112 Ok(()) 113}