tangled
alpha
login
or
join now
buttplug.io
/
buttplug
20
fork
atom
Buttplug sex toy control library
20
fork
atom
overview
issues
pulls
pipelines
chore: Clean up rest device list, commands, etc...
qdot.tngl.sh
6 months ago
ed2f5d56
b01cdb46
+119
-90
3 changed files
expand all
collapse all
unified
split
crates
buttplug_client
src
device
command.rs
buttplug_core
src
message
device_feature.rs
intiface_engine
src
rest_server.rs
+26
-18
crates/buttplug_client/src/device/command.rs
···
1
1
use buttplug_core::message::OutputType;
2
2
3
3
+
use crate::ButtplugClientError;
4
4
+
3
5
pub enum ClientDeviceCommandValue {
4
6
Int(u32),
5
7
Float(f64),
···
42
44
PositionWithDurationFloat(f64, u32),
43
45
}
44
46
45
45
-
impl From<&ClientDeviceOutputCommand> for OutputType {
46
46
-
fn from(val: &ClientDeviceOutputCommand) -> Self {
47
47
-
match val {
48
48
-
ClientDeviceOutputCommand::Vibrate(_) | ClientDeviceOutputCommand::VibrateFloat(_) => {
49
49
-
OutputType::Vibrate
50
50
-
}
51
51
-
ClientDeviceOutputCommand::Oscillate(_) | ClientDeviceOutputCommand::OscillateFloat(_) => {
52
52
-
OutputType::Oscillate
53
53
-
}
54
54
-
ClientDeviceOutputCommand::Rotate(_) | ClientDeviceOutputCommand::RotateFloat(_) => {
55
55
-
OutputType::Rotate
56
56
-
}
57
57
-
ClientDeviceOutputCommand::Constrict(_) | ClientDeviceOutputCommand::ConstrictFloat(_) => {
58
58
-
OutputType::Constrict
59
59
-
}
60
60
-
ClientDeviceOutputCommand::Heater(_) | ClientDeviceOutputCommand::HeaterFloat(_) => {
61
61
-
OutputType::Heater
62
62
-
}
47
47
+
impl ClientDeviceOutputCommand {
48
48
+
pub fn from_command_value_float(output_type: OutputType, value: f64) -> Result<Self, ButtplugClientError> {
49
49
+
match output_type {
50
50
+
OutputType::Vibrate => Ok(ClientDeviceOutputCommand::VibrateFloat(value)),
51
51
+
OutputType::Oscillate => Ok(ClientDeviceOutputCommand::OscillateFloat(value)),
52
52
+
OutputType::Rotate => Ok(ClientDeviceOutputCommand::RotateFloat(value)),
53
53
+
OutputType::Constrict => Ok(ClientDeviceOutputCommand::ConstrictFloat(value)),
54
54
+
OutputType::Heater => Ok(ClientDeviceOutputCommand::HeaterFloat(value)),
55
55
+
OutputType::Led => Ok(ClientDeviceOutputCommand::LedFloat(value)),
56
56
+
OutputType::Spray => Ok(ClientDeviceOutputCommand::SprayFloat(value)),
57
57
+
OutputType::Position => Ok(ClientDeviceOutputCommand::PositionFloat(value)),
58
58
+
_ => Err(ButtplugClientError::ButtplugOutputCommandConversionError("Cannot use PositionWithDuration or RotateWithDirection with this method".to_owned()))
59
59
+
}
60
60
+
}
61
61
+
}
62
62
+
63
63
+
impl Into<OutputType> for &ClientDeviceOutputCommand {
64
64
+
fn into(self) -> OutputType {
65
65
+
match self {
66
66
+
ClientDeviceOutputCommand::Vibrate(_) | ClientDeviceOutputCommand::VibrateFloat(_) => OutputType::Vibrate,
67
67
+
ClientDeviceOutputCommand::Oscillate(_) | ClientDeviceOutputCommand::OscillateFloat(_) => OutputType::Oscillate,
68
68
+
ClientDeviceOutputCommand::Rotate(_) | ClientDeviceOutputCommand::RotateFloat(_) => OutputType::Rotate,
69
69
+
ClientDeviceOutputCommand::Constrict(_) | ClientDeviceOutputCommand::ConstrictFloat(_) => OutputType::Constrict,
70
70
+
ClientDeviceOutputCommand::Heater(_) | ClientDeviceOutputCommand::HeaterFloat(_) => OutputType::Heater,
63
71
ClientDeviceOutputCommand::Led(_) | ClientDeviceOutputCommand::LedFloat(_) => OutputType::Led,
64
72
ClientDeviceOutputCommand::Spray(_) | ClientDeviceOutputCommand::SprayFloat(_) => {
65
73
OutputType::Spray
+1
-1
crates/buttplug_core/src/message/device_feature.rs
···
11
11
use serde::{Deserialize, Serialize, Serializer, ser::SerializeSeq};
12
12
use std::{collections::HashSet, hash::Hash, ops::RangeInclusive};
13
13
14
14
-
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash, EnumIter)]
14
14
+
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash, EnumIter, EnumString)]
15
15
pub enum OutputType {
16
16
Unknown,
17
17
#[serde(alias = "vibrate")]
+92
-71
crates/intiface_engine/src/rest_server.rs
···
1
1
-
use std::{collections::BTreeMap, io, net::SocketAddr, process::Output, str::FromStr, sync::Arc};
1
1
+
use std::{collections::BTreeMap, io, net::SocketAddr, str::FromStr, sync::Arc};
2
2
3
3
-
use anyhow::Context;
4
3
use axum::{
5
4
Json, Router,
6
5
extract::{Path, State, rejection::JsonRejection},
···
8
7
response::{IntoResponse, Response},
9
8
routing::{get, put},
10
9
};
11
11
-
use buttplug_client::{device::ClientDeviceOutputCommand, ButtplugClient, ButtplugClientDevice, ButtplugClientError};
10
10
+
use buttplug_client::{
11
11
+
ButtplugClient, ButtplugClientDevice, ButtplugClientError, device::ClientDeviceOutputCommand,
12
12
+
};
12
13
use buttplug_client_in_process::ButtplugInProcessClientConnectorBuilder;
13
14
use buttplug_core::message::{DeviceFeature, OutputType};
14
15
use buttplug_server::ButtplugServer;
···
90
91
91
92
pub struct IntifaceRestServer {}
92
93
93
93
-
async fn start_scanning(State(client): State<Arc<ButtplugClient>>) {
94
94
-
client.start_scanning().await;
94
94
+
fn get_device(
95
95
+
client: &ButtplugClient,
96
96
+
index: u32,
97
97
+
) -> Result<ButtplugClientDevice, IntifaceRestError> {
98
98
+
client
99
99
+
.devices()
100
100
+
.get(&index)
101
101
+
.ok_or(IntifaceRestError::InvalidDevice(index))
102
102
+
.cloned()
95
103
}
96
104
97
97
-
async fn stop_scanning(State(client): State<Arc<ButtplugClient>>) {
98
98
-
client.stop_scanning().await;
105
105
+
async fn start_scanning(
106
106
+
State(client): State<Arc<ButtplugClient>>,
107
107
+
) -> Result<(), IntifaceRestError> {
108
108
+
client
109
109
+
.start_scanning()
110
110
+
.await
111
111
+
.map_err(|e| IntifaceRestError::ButtplugClientError(e))
99
112
}
100
113
101
101
-
async fn stop_all_devices(State(client): State<Arc<ButtplugClient>>) {
102
102
-
client.stop_all_devices().await;
114
114
+
async fn stop_scanning(State(client): State<Arc<ButtplugClient>>) -> Result<(), IntifaceRestError> {
115
115
+
client
116
116
+
.stop_scanning()
117
117
+
.await
118
118
+
.map_err(|e| IntifaceRestError::ButtplugClientError(e))
119
119
+
}
120
120
+
121
121
+
async fn stop_all_devices(
122
122
+
State(client): State<Arc<ButtplugClient>>,
123
123
+
) -> Result<(), IntifaceRestError> {
124
124
+
client
125
125
+
.stop_all_devices()
126
126
+
.await
127
127
+
.map_err(|e| IntifaceRestError::ButtplugClientError(e))
103
128
}
104
129
105
130
async fn stop_device(
···
107
132
Path(index): Path<u32>,
108
133
) -> Result<(), IntifaceRestError> {
109
134
Ok(
110
110
-
client
111
111
-
.devices()
112
112
-
.get(&index)
113
113
-
.ok_or(IntifaceRestError::InvalidDevice(index))?
135
135
+
get_device(&client, index)?
114
136
.stop()
115
137
.await
116
138
.map_err(|e| IntifaceRestError::ButtplugClientError(e))?,
···
121
143
State(client): State<Arc<ButtplugClient>>,
122
144
Path((index, command, level)): Path<(u32, String, f64)>,
123
145
) -> Result<(), IntifaceRestError> {
124
124
-
let command_type = OutputType::from_str(&command).map_err(|_|
125
125
-
IntifaceRestError::InvalidOutputType(
126
126
-
command,
127
127
-
OutputType::iter().collect::<Vec<OutputType>>()
128
128
-
)
129
129
-
)?;
146
146
+
let command_type = OutputType::from_str(&command).map_err(|_| {
147
147
+
IntifaceRestError::InvalidOutputType(command, OutputType::iter().collect::<Vec<OutputType>>())
148
148
+
})?;
130
149
131
131
-
Ok(())
132
132
-
/*
133
133
-
let cmd = ClientDeviceOutputCommand::
150
150
+
let cmd = ClientDeviceOutputCommand::from_command_value_float(command_type, level)
151
151
+
.map_err(|e| IntifaceRestError::ButtplugClientError(e))?;
134
152
135
135
-
Ok(client
136
136
-
.devices()
137
137
-
.get(&index)
138
138
-
.ok_or(IntifaceRestError::InvalidDevice(index))?
139
139
-
.send_command(client_device_command)
140
140
-
.await
141
141
-
.map_err(|e| IntifaceRestError::ButtplugClientError(e))?)
142
142
-
*/
153
153
+
Ok(
154
154
+
get_device(&client, index)?
155
155
+
.send_command(&cmd)
156
156
+
.await
157
157
+
.map_err(|e| IntifaceRestError::ButtplugClientError(e))?,
158
158
+
)
143
159
}
144
160
145
161
async fn get_devices(
···
153
169
.into()
154
170
}
155
171
156
156
-
async fn get_device(
172
172
+
async fn get_device_info(
157
173
State(client): State<Arc<ButtplugClient>>,
158
174
Path(index): Path<u32>,
159
175
) -> Result<Json<IntifaceRestDevice>, IntifaceRestError> {
160
160
-
Ok(IntifaceRestDevice::from(client.devices().get(&index).ok_or(IntifaceRestError::InvalidDevice(index))?).into())
176
176
+
Ok(
177
177
+
IntifaceRestDevice::from(
178
178
+
client
179
179
+
.devices()
180
180
+
.get(&index)
181
181
+
.ok_or(IntifaceRestError::InvalidDevice(index))?,
182
182
+
)
183
183
+
.into(),
184
184
+
)
161
185
}
162
186
163
187
async fn get_features(
···
165
189
Path(index): Path<u32>,
166
190
) -> Result<Json<BTreeMap<u32, DeviceFeature>>, IntifaceRestError> {
167
191
Ok(
168
168
-
client
169
169
-
.devices()
170
170
-
.get(&index)
171
171
-
.ok_or(IntifaceRestError::InvalidDevice(index))?
192
192
+
get_device(&client, index)?
172
193
.device_features()
173
194
.iter()
174
195
.map(|(i, f)| (*i, f.feature().clone()))
···
182
203
Path((index, feature_index)): Path<(u32, u32)>,
183
204
) -> Result<Json<DeviceFeature>, IntifaceRestError> {
184
205
Ok(
185
185
-
client
186
186
-
.devices()
187
187
-
.get(&index)
188
188
-
.ok_or(IntifaceRestError::InvalidDevice(index))?
206
206
+
get_device(&client, index)?
189
207
.device_features()
190
208
.get(&feature_index)
191
209
.ok_or(IntifaceRestError::InvalidFeature(index, feature_index))?
···
204
222
client.connect(connector).await.unwrap();
205
223
info!("Setting up app!");
206
224
// pass incoming GET requests on "/hello-world" to "hello_world" handler.
207
207
-
let app = Router::new()
208
208
-
.route("/start-scanning", get(start_scanning))
209
209
-
.route("/stop-scanning", get(stop_scanning))
210
210
-
.route("/devices", get(get_devices))
211
211
-
.route("/devices/stop", put(stop_all_devices))
212
212
-
.route("/devices/{index}", put(get_device))
213
213
-
.route("/devices/{index}/stop", put(stop_device))
214
214
-
.route("/devices/{index}/features", get(get_features))
215
215
-
.route("/devices/{index}/features/{index}/", put(get_feature))
216
216
-
.route(
217
217
-
"/devices/{index}/outputs/{output_type}/",
218
218
-
put(set_device_output),
219
219
-
)
220
220
-
/*
221
221
-
.route(
222
222
-
"/devices/{index}/features/{index}/outputs/{output_type}/",
223
223
-
put(set_feature_output),
224
224
-
)
225
225
-
.route(
226
226
-
"/devices/{index}/inputs/{input_type}/{input_command}",
227
227
-
put(set_device_input),
228
228
-
)
229
229
-
.route(
230
230
-
"/devices/{index}/features/{index}/inputs/{input_type}/{input_command}",
231
231
-
put(set_feature_input),
232
232
-
)
233
233
-
.route("/devices/{index}/events", get(device_sse))
234
234
-
.route("/events", get(server_sse))
235
235
-
*/
236
236
-
//.route("/devices/{*index}/vibrate", post(set_feature_vibrate_speed))
237
237
-
.with_state(Arc::new(client));
225
225
+
let app = Router::new().nest(
226
226
+
"/api/v1",
227
227
+
Router::new()
228
228
+
.route("/start-scanning", get(start_scanning))
229
229
+
.route("/stop-scanning", get(stop_scanning))
230
230
+
.route("/devices", get(get_devices))
231
231
+
.route("/devices/stop", put(stop_all_devices))
232
232
+
.route("/devices/{index}", get(get_device_info))
233
233
+
.route("/devices/{index}/stop", put(stop_device))
234
234
+
.route("/devices/{index}/features", get(get_features))
235
235
+
.route("/devices/{index}/features/{index}/", put(get_feature))
236
236
+
.route(
237
237
+
"/devices/{index}/outputs/{output_type}/",
238
238
+
put(set_device_output),
239
239
+
)
240
240
+
/*
241
241
+
.route(
242
242
+
"/devices/{index}/features/{index}/outputs/{output_type}/",
243
243
+
put(set_feature_output),
244
244
+
)
245
245
+
.route(
246
246
+
"/devices/{index}/inputs/{input_type}/{input_command}",
247
247
+
put(set_device_input),
248
248
+
)
249
249
+
.route(
250
250
+
"/devices/{index}/features/{index}/inputs/{input_type}/{input_command}",
251
251
+
put(set_feature_input),
252
252
+
)
253
253
+
.route("/devices/{index}/events", get(device_sse))
254
254
+
.route("/events", get(server_sse))
255
255
+
*/
256
256
+
//.route("/devices/{*index}/vibrate", post(set_feature_vibrate_speed))
257
257
+
.with_state(Arc::new(client)),
258
258
+
);
238
259
239
260
// write address like this to not make typos
240
261
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));