Buttplug sex toy control library

chore: Split message attrs into client/server versions

Instead of requiring the only message attributes class to conform to
what both the client AND server need, split attributes into server
(which will handle configuration) and client (which is what we'll fly
over the protocol).

+434 -172
+3 -3
buttplug/src/client/device.rs
··· 24 24 ButtplugCurrentSpecServerMessage, 25 25 ButtplugDeviceMessageType, 26 26 ButtplugMessage, 27 - DeviceMessageAttributes, 27 + ClientDeviceMessageAttributes, 28 28 DeviceMessageInfo, 29 29 Endpoint, 30 30 LinearCmd, ··· 159 159 /// Map of messages the device can take, along with the attributes of those 160 160 /// messages. 161 161 #[getset(get = "pub")] 162 - message_attributes: DeviceMessageAttributes, 162 + message_attributes: ClientDeviceMessageAttributes, 163 163 /// Sends commands from the [ButtplugClientDevice] instance to the 164 164 /// [ButtplugClient][super::ButtplugClient]'s event loop, which will then send 165 165 /// the message on to the [ButtplugServer][crate::server::ButtplugServer] ··· 192 192 pub(super) fn new( 193 193 name: &str, 194 194 index: u32, 195 - message_attributes: &DeviceMessageAttributes, 195 + message_attributes: &ClientDeviceMessageAttributes, 196 196 message_sender: broadcast::Sender<ButtplugClientRequest>, 197 197 ) -> Self { 198 198 info!(
+4 -4
buttplug/src/core/messages/device_added.rs
··· 29 29 device_name: String, 30 30 #[cfg_attr(feature = "serialize-json", serde(rename = "DeviceMessages"))] 31 31 #[getset(get = "pub")] 32 - device_messages: DeviceMessageAttributes, 32 + device_messages: ClientDeviceMessageAttributes, 33 33 } 34 34 35 35 impl DeviceAdded { 36 36 pub fn new( 37 37 device_index: u32, 38 38 device_name: &str, 39 - device_messages: &DeviceMessageAttributes, 39 + device_messages: &ClientDeviceMessageAttributes, 40 40 ) -> Self { 41 41 Self { 42 42 id: 0, ··· 66 66 device_name: String, 67 67 #[cfg_attr(feature = "serialize-json", serde(rename = "DeviceMessages"))] 68 68 #[getset(get = "pub")] 69 - device_messages: DeviceMessageAttributesV2, 69 + device_messages: ClientDeviceMessageAttributesV2, 70 70 } 71 71 72 72 impl From<DeviceAdded> for DeviceAddedV2 { ··· 103 103 device_name: String, 104 104 #[cfg_attr(feature = "serialize-json", serde(rename = "DeviceMessages"))] 105 105 #[getset(get = "pub")] 106 - device_messages: DeviceMessageAttributesV1, 106 + device_messages: ClientDeviceMessageAttributesV1, 107 107 } 108 108 109 109 impl From<DeviceAdded> for DeviceAddedV1 {
+4 -4
buttplug/src/core/messages/device_message_info.rs
··· 22 22 device_name: String, 23 23 #[cfg_attr(feature = "serialize-json", serde(rename = "DeviceMessages"))] 24 24 #[getset(get = "pub")] 25 - device_messages: DeviceMessageAttributes, 25 + device_messages: ClientDeviceMessageAttributes, 26 26 } 27 27 28 28 impl DeviceMessageInfo { 29 29 pub fn new( 30 30 device_index: u32, 31 31 device_name: &str, 32 - device_messages: DeviceMessageAttributes, 32 + device_messages: ClientDeviceMessageAttributes, 33 33 ) -> Self { 34 34 Self { 35 35 device_index, ··· 60 60 device_name: String, 61 61 #[cfg_attr(feature = "serialize-json", serde(rename = "DeviceMessages"))] 62 62 #[getset(get = "pub")] 63 - device_messages: DeviceMessageAttributesV2, 63 + device_messages: ClientDeviceMessageAttributesV2, 64 64 } 65 65 66 66 impl From<DeviceAdded> for DeviceMessageInfoV2 { ··· 103 103 device_name: String, 104 104 #[cfg_attr(feature = "serialize-json", serde(rename = "DeviceMessages"))] 105 105 #[getset(get = "pub")] 106 - device_messages: DeviceMessageAttributesV1, 106 + device_messages: ClientDeviceMessageAttributesV1, 107 107 } 108 108 109 109 impl From<DeviceAdded> for DeviceMessageInfoV1 {
+44 -119
buttplug/src/core/messages/message_attributes.rs buttplug/src/core/messages/client_device_message_attributes.rs
··· 37 37 // Gyro, 38 38 } 39 39 40 - // Unlike other message components, MessageAttributes is always turned on for 41 - // serialization, because it's used by device configuration files also. 40 + // This will look almost exactly like ServerDeviceMessageAttributes. However, it will only contain 41 + // information we want the client to know, i.e. step counts versus specific step ranges. This is 42 + // what will be sent to the client as part of DeviceAdded/DeviceList messages. It should not be used 43 + // for outside configuration/serialization, rather it should be a subset of that information. 44 + // 45 + // For many messages, client and server configurations may be exactly the same. If they are not, 46 + // then we denote this by prefixing the type with Client/Server. Server attributes will usually be 47 + // hosted in the server/device/configuration module. 42 48 #[derive( 43 - Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, Getters, MutGetters, Setters, 49 + Clone, Debug, Default, PartialEq, Eq, Getters, MutGetters, Setters, 44 50 )] 45 - pub struct DeviceMessageAttributes { 51 + #[cfg_attr(feature = "serialize-json", derive(Serialize, Deserialize))] 52 + pub struct ClientDeviceMessageAttributes { 46 53 // Generic commands 47 54 #[getset(get = "pub", get_mut = "pub")] 48 55 #[serde(rename = "ScalarCmd")] 49 56 #[serde(skip_serializing_if = "Option::is_none")] 50 - scalar_cmd: Option<Vec<GenericDeviceMessageAttributes>>, 57 + scalar_cmd: Option<Vec<ClientGenericDeviceMessageAttributes>>, 51 58 #[getset(get = "pub", get_mut = "pub")] 52 59 #[serde(rename = "RotateCmd")] 53 60 #[serde(skip_serializing_if = "Option::is_none")] 54 - rotate_cmd: Option<Vec<GenericDeviceMessageAttributes>>, 61 + rotate_cmd: Option<Vec<ClientGenericDeviceMessageAttributes>>, 55 62 #[getset(get = "pub", get_mut = "pub")] 56 63 #[serde(rename = "LinearCmd")] 57 64 #[serde(skip_serializing_if = "Option::is_none")] 58 - linear_cmd: Option<Vec<GenericDeviceMessageAttributes>>, 65 + linear_cmd: Option<Vec<ClientGenericDeviceMessageAttributes>>, 59 66 60 67 // Sensor Messages 61 68 #[getset(get = "pub")] ··· 103 110 vorze_a10_cyclone_cmd: Option<NullDeviceMessageAttributes>, 104 111 } 105 112 106 - impl DeviceMessageAttributes { 113 + impl ClientDeviceMessageAttributes { 107 114 pub fn raw_unsubscribe_cmd(&self) -> &Option<RawDeviceMessageAttributes> { 108 115 self.raw_subscribe_cmd() 109 116 } ··· 151 158 ButtplugDeviceMessageType::LovenseCmd => false, 152 159 } 153 160 } 154 - 155 - pub fn merge(&self, child: &DeviceMessageAttributes) -> DeviceMessageAttributes { 156 - Self { 157 - rotate_cmd: child 158 - .rotate_cmd() 159 - .clone() 160 - .or_else(|| self.rotate_cmd().clone()), 161 - linear_cmd: child 162 - .linear_cmd() 163 - .clone() 164 - .or_else(|| self.linear_cmd().clone()), 165 - scalar_cmd: child 166 - .scalar_cmd() 167 - .clone() 168 - .or_else(|| self.scalar_cmd().clone()), 169 - sensor_read_cmd: child 170 - .sensor_read_cmd() 171 - .clone() 172 - .or_else(|| self.sensor_read_cmd().clone()), 173 - sensor_subscribe_cmd: child 174 - .sensor_subscribe_cmd() 175 - .clone() 176 - .or_else(|| self.sensor_subscribe_cmd().clone()), 177 - stop_device_cmd: NullDeviceMessageAttributes::default(), 178 - raw_read_cmd: child 179 - .raw_read_cmd() 180 - .clone() 181 - .or_else(|| self.raw_read_cmd().clone()), 182 - raw_write_cmd: child 183 - .raw_write_cmd() 184 - .clone() 185 - .or_else(|| self.raw_write_cmd().clone()), 186 - raw_subscribe_cmd: child 187 - .raw_subscribe_cmd() 188 - .clone() 189 - .or_else(|| self.raw_subscribe_cmd().clone()), 190 - fleshlight_launch_fw12_cmd: child 191 - .fleshlight_launch_fw12_cmd() 192 - .clone() 193 - .or_else(|| self.fleshlight_launch_fw12_cmd().clone()), 194 - vorze_a10_cyclone_cmd: child 195 - .vorze_a10_cyclone_cmd() 196 - .clone() 197 - .or_else(|| self.vorze_a10_cyclone_cmd().clone()), 198 - } 199 - } 161 + } 200 162 201 - pub fn add_raw_messages(&mut self, endpoints: &[Endpoint]) { 202 - let raw_attrs = RawDeviceMessageAttributes { 203 - endpoints: endpoints.clone().to_vec(), 204 - }; 205 - self.raw_read_cmd = Some(raw_attrs.clone()); 206 - self.raw_write_cmd = Some(raw_attrs.clone()); 207 - self.raw_subscribe_cmd = Some(raw_attrs.clone()); 208 - } 209 - } 210 163 211 164 #[derive(Default)] 212 - pub struct DeviceMessageAttributesBuilder { 213 - attrs: DeviceMessageAttributes, 165 + pub struct ClientDeviceMessageAttributesBuilder { 166 + attrs: ClientDeviceMessageAttributes, 214 167 } 215 168 216 - impl DeviceMessageAttributesBuilder { 217 - pub fn scalar_cmd(&mut self, attrs: &Vec<GenericDeviceMessageAttributes>) -> &Self { 169 + impl ClientDeviceMessageAttributesBuilder { 170 + pub fn scalar_cmd(&mut self, attrs: &Vec<ClientGenericDeviceMessageAttributes>) -> &Self { 218 171 self.attrs.scalar_cmd = Some(attrs.clone()); 219 172 self 220 173 } 221 174 222 - pub fn rotate_cmd(&mut self, attrs: &Vec<GenericDeviceMessageAttributes>) -> &Self { 175 + pub fn rotate_cmd(&mut self, attrs: &Vec<ClientGenericDeviceMessageAttributes>) -> &Self { 223 176 self.attrs.rotate_cmd = Some(attrs.clone()); 224 177 self 225 178 } 226 179 227 - pub fn linear_cmd(&mut self, attrs: &Vec<GenericDeviceMessageAttributes>) -> &Self { 180 + pub fn linear_cmd(&mut self, attrs: &Vec<ClientGenericDeviceMessageAttributes>) -> &Self { 228 181 self.attrs.linear_cmd = Some(attrs.clone()); 229 182 self 230 183 } ··· 254 207 self 255 208 } 256 209 257 - pub fn finish(&self) -> DeviceMessageAttributes { 210 + pub fn finish(&self) -> ClientDeviceMessageAttributes { 258 211 self.attrs.clone() 259 212 } 260 213 } 261 214 215 + 262 216 #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] 263 217 pub struct NullDeviceMessageAttributes {} 264 218 ··· 267 221 } 268 222 269 223 #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Getters, Setters)] 270 - pub struct GenericDeviceMessageAttributes { 224 + pub struct ClientGenericDeviceMessageAttributes { 271 225 #[getset(get = "pub")] 272 226 #[serde(rename = "FeatureDescriptor")] 273 227 #[serde(default = "unspecified_feature")] ··· 275 229 #[getset(get = "pub")] 276 230 #[serde(rename = "ActuatorType")] 277 231 actuator_type: ActuatorType, 278 - #[serde(rename = "StepRange")] 279 - #[serde(skip_serializing)] 280 - #[getset(get = "pub", set = "pub")] 281 - step_range: RangeInclusive<u32>, 232 + #[serde(rename = "StepCount")] 233 + #[getset(get = "pub")] 234 + step_count: u32 282 235 } 283 236 284 - impl GenericDeviceMessageAttributes { 237 + impl ClientGenericDeviceMessageAttributes { 285 238 pub fn new( 286 239 feature_descriptor: &str, 287 - step_range: &RangeInclusive<u32>, 240 + step_count: u32, 288 241 actuator_type: ActuatorType, 289 242 ) -> Self { 290 243 Self { 291 244 feature_descriptor: feature_descriptor.to_owned(), 292 245 actuator_type, 293 - step_range: step_range.clone(), 246 + step_count 294 247 } 295 - } 296 - 297 - pub fn step_count(&self) -> u32 { 298 - self.step_range.end() - self.step_range.start() 299 248 } 300 249 301 250 pub fn is_valid( 302 251 &self, 303 252 message_type: &ButtplugDeviceMessageType, 304 253 ) -> Result<(), ButtplugDeviceError> { 305 - if self.step_range.is_empty() { 306 - Err(ButtplugDeviceError::DeviceConfigurationError(format!( 307 - "Step range out of order for {}, must be start <= x <= end.", 308 - message_type 309 - ))) 310 - } else { 311 - Ok(()) 312 - } 254 + Ok(()) 313 255 } 314 256 } 315 257 ··· 350 292 */ 351 293 352 294 #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Getters, Setters)] 353 - pub struct DeviceMessageAttributesV2 { 295 + pub struct ClientDeviceMessageAttributesV2 { 354 296 // Generic commands 355 297 #[getset(get = "pub")] 356 298 #[serde(rename = "VibrateCmd")] ··· 405 347 vorze_a10_cyclone_cmd: Option<NullDeviceMessageAttributes>, 406 348 } 407 349 408 - impl From<DeviceMessageAttributes> for DeviceMessageAttributesV2 { 409 - fn from(other: DeviceMessageAttributes) -> Self { 350 + impl From<ClientDeviceMessageAttributes> for ClientDeviceMessageAttributesV2 { 351 + fn from(other: ClientDeviceMessageAttributes) -> Self { 410 352 Self { 411 353 vibrate_cmd: other 412 354 .scalar_cmd() ··· 469 411 } 470 412 471 413 impl GenericDeviceMessageAttributesV2 { 472 - pub fn vibrate_cmd_from_scalar_cmd(attributes_vec: Vec<GenericDeviceMessageAttributes>) -> Self { 414 + pub fn vibrate_cmd_from_scalar_cmd(attributes_vec: Vec<ClientGenericDeviceMessageAttributes>) -> Self { 473 415 let mut feature_count = 0u32; 474 416 let mut step_count = vec![]; 475 417 for attr in attributes_vec { 476 418 if *attr.actuator_type() == ActuatorType::Vibrate { 477 419 feature_count += 1; 478 - step_count.push(attr.step_count()); 420 + step_count.push(*attr.step_count()); 479 421 } 480 422 } 481 423 Self { 482 424 feature_count, 483 - step_count, 425 + step_count 484 426 } 485 427 } 486 428 } 487 429 488 - impl From<Vec<GenericDeviceMessageAttributes>> for GenericDeviceMessageAttributesV2 { 489 - fn from(attributes_vec: Vec<GenericDeviceMessageAttributes>) -> Self { 430 + impl From<Vec<ClientGenericDeviceMessageAttributes>> for GenericDeviceMessageAttributesV2 { 431 + fn from(attributes_vec: Vec<ClientGenericDeviceMessageAttributes>) -> Self { 490 432 Self { 491 433 feature_count: attributes_vec.len() as u32, 492 - step_count: attributes_vec.iter().map(|x| x.step_count()).collect(), 434 + step_count: attributes_vec.iter().map(|x| *x.step_count()).collect(), 493 435 } 494 436 } 495 437 } 496 438 497 439 #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Getters, Setters)] 498 - pub struct DeviceMessageAttributesV1 { 440 + pub struct ClientDeviceMessageAttributesV1 { 499 441 // Generic commands 500 442 #[getset(get = "pub")] 501 443 #[serde(rename = "VibrateCmd")] ··· 526 468 vorze_a10_cyclone_cmd: Option<NullDeviceMessageAttributes>, 527 469 } 528 470 529 - impl From<DeviceMessageAttributesV2> for DeviceMessageAttributesV1 { 530 - fn from(other: DeviceMessageAttributesV2) -> Self { 471 + impl From<ClientDeviceMessageAttributesV2> for ClientDeviceMessageAttributesV1 { 472 + fn from(other: ClientDeviceMessageAttributesV2) -> Self { 531 473 Self { 532 474 vibrate_cmd: other 533 475 .vibrate_cmd() ··· 566 508 } 567 509 } 568 510 } 569 - 570 - #[cfg(test)] 571 - mod test { 572 - use super::*; 573 - 574 - #[test] 575 - pub fn test_step_count_calculation() { 576 - let mut vibrate_attributes = GenericDeviceMessageAttributes::new( 577 - "test", 578 - &RangeInclusive::new(0, 10), 579 - ActuatorType::Vibrate, 580 - ); 581 - assert_eq!(vibrate_attributes.step_count(), 10); 582 - vibrate_attributes.set_step_range(RangeInclusive::new(3u32, 7)); 583 - assert_eq!(vibrate_attributes.step_count(), 4); 584 - } 585 - }
+13 -11
buttplug/src/core/messages/mod.rs
··· 27 27 mod log; 28 28 mod log_level; 29 29 mod lovense_cmd; 30 - mod message_attributes; 30 + mod client_device_message_attributes; 31 31 mod ok; 32 32 mod ping; 33 33 mod raw_read_cmd; ··· 72 72 pub use linear_cmd::{LinearCmd, VectorSubcommand}; 73 73 pub use log_level::LogLevel; 74 74 pub use lovense_cmd::LovenseCmd; 75 - pub use message_attributes::{ 75 + pub use client_device_message_attributes::{ 76 76 ActuatorType, 77 - DeviceMessageAttributes, 78 - DeviceMessageAttributesBuilder, 79 - DeviceMessageAttributesV1, 80 - DeviceMessageAttributesV2, 81 - GenericDeviceMessageAttributes, 77 + ClientDeviceMessageAttributes, 78 + ClientDeviceMessageAttributesBuilder, 79 + ClientDeviceMessageAttributesV1, 80 + ClientDeviceMessageAttributesV2, 81 + ClientGenericDeviceMessageAttributes, 82 + NullDeviceMessageAttributes, 83 + RawDeviceMessageAttributes, 82 84 SensorDeviceMessageAttributes, 83 85 SensorType, 84 86 }; ··· 528 530 TryFromButtplugClientMessage, 529 531 )] 530 532 #[cfg_attr(feature = "serialize-json", derive(Serialize, Deserialize))] 531 - pub(crate) enum ButtplugSpecV1ClientMessage { 533 + pub enum ButtplugSpecV1ClientMessage { 532 534 // Handshake messages 533 535 RequestServerInfo(RequestServerInfo), 534 536 Ping(Ping), ··· 556 558 Debug, Clone, PartialEq, Eq, ButtplugMessage, ButtplugMessageValidator, ButtplugServerMessageType, 557 559 )] 558 560 #[cfg_attr(feature = "serialize-json", derive(Serialize, Deserialize))] 559 - pub(crate) enum ButtplugSpecV1ServerMessage { 561 + pub enum ButtplugSpecV1ServerMessage { 560 562 // Status messages 561 563 Ok(Ok), 562 564 Error(ErrorV0), ··· 615 617 TryFromButtplugClientMessage, 616 618 )] 617 619 #[cfg_attr(feature = "serialize-json", derive(Serialize, Deserialize))] 618 - pub(crate) enum ButtplugSpecV0ClientMessage { 620 + pub enum ButtplugSpecV0ClientMessage { 619 621 RequestLog(RequestLog), 620 622 Ping(Ping), 621 623 // Handshake messages ··· 641 643 Debug, Clone, PartialEq, Eq, ButtplugMessage, ButtplugMessageValidator, ButtplugServerMessageType, 642 644 )] 643 645 #[cfg_attr(feature = "serialize-json", derive(Serialize, Deserialize))] 644 - pub(crate) enum ButtplugSpecV0ServerMessage { 646 + pub enum ButtplugSpecV0ServerMessage { 645 647 // Status messages 646 648 Ok(Ok), 647 649 Error(ErrorV0),
+11 -9
buttplug/src/server/device/configuration/mod.rs
··· 138 138 //! 139 139 140 140 pub mod specifier; 141 + mod server_device_message_attributes; 141 142 pub use specifier::*; 143 + 144 + pub use server_device_message_attributes::{ServerDeviceMessageAttributes, ServerGenericDeviceMessageAttributes, ServerDeviceMessageAttributesBuilder}; 142 145 143 146 use super::protocol::{get_default_protocol_map, ProtocolIdentifierFactory, ProtocolSpecializer}; 144 147 use crate::{ 145 148 core::{ 146 149 errors::ButtplugDeviceError, 147 - messages::{ButtplugDeviceMessageType, DeviceMessageAttributes, Endpoint}, 150 + messages::{ButtplugDeviceMessageType, Endpoint}, 148 151 }, 149 152 server::device::ServerDeviceIdentifier, 150 153 }; ··· 252 255 /// User configured name of the device this instance represents, assuming one exists. 253 256 display_name: Option<String>, 254 257 /// Message attributes for this device instance. 255 - pub(super) message_attributes: DeviceMessageAttributes, 258 + pub(super) message_attributes: ServerDeviceMessageAttributes, 256 259 } 257 260 258 261 impl ProtocolDeviceAttributes { ··· 261 264 identifier: ProtocolAttributesType, 262 265 name: Option<String>, 263 266 display_name: Option<String>, 264 - message_attributes: DeviceMessageAttributes, 267 + message_attributes: ServerDeviceMessageAttributes, 265 268 parent: Option<Arc<ProtocolDeviceAttributes>>, 266 269 ) -> Self { 267 270 Self { ··· 349 352 } 350 353 351 354 /// Retreive a map of all message attributes for this instance. 352 - pub fn message_attributes(&self) -> DeviceMessageAttributes { 355 + pub fn message_attributes(&self) -> ServerDeviceMessageAttributes { 353 356 if let Some(parent) = &self.parent { 354 357 parent.message_attributes().merge(&self.message_attributes) 355 358 } else { ··· 711 714 712 715 #[cfg(test)] 713 716 mod test { 714 - use super::*; 715 - use crate::core::messages::{DeviceMessageAttributesBuilder, GenericDeviceMessageAttributes}; 717 + use super::{*, server_device_message_attributes::{ServerDeviceMessageAttributesBuilder, ServerGenericDeviceMessageAttributes}}; 716 718 use std::{ 717 719 collections::{HashMap, HashSet}, 718 720 ops::RangeInclusive, ··· 739 741 ProtocolAttributesType::Identifier("P".to_owned()), 740 742 Some("Lovense Edge".to_owned()), 741 743 None, 742 - DeviceMessageAttributesBuilder::default() 744 + ServerDeviceMessageAttributesBuilder::default() 743 745 .scalar_cmd(&vec![ 744 - GenericDeviceMessageAttributes::new( 746 + ServerGenericDeviceMessageAttributes::new( 745 747 "Edge Vibrator 1", 746 748 &RangeInclusive::new(0, 20), 747 749 crate::core::messages::ActuatorType::Vibrate, 748 750 ), 749 - GenericDeviceMessageAttributes::new( 751 + ServerGenericDeviceMessageAttributes::new( 750 752 "Edge Vibrator 2", 751 753 &RangeInclusive::new(0, 20), 752 754 crate::core::messages::ActuatorType::Vibrate,
+335
buttplug/src/server/device/configuration/server_device_message_attributes.rs
··· 1 + use std::ops::RangeInclusive; 2 + 3 + use serde::{Serialize, Deserialize}; 4 + use getset::{Getters, MutGetters, Setters}; 5 + 6 + use crate::core::{messages::{SensorDeviceMessageAttributes, NullDeviceMessageAttributes, RawDeviceMessageAttributes, ButtplugDeviceMessageType, SensorType, Endpoint, ActuatorType, ClientGenericDeviceMessageAttributes, ClientDeviceMessageAttributes, ClientDeviceMessageAttributesBuilder}, errors::ButtplugDeviceError}; 7 + 8 + // Unlike other message components, MessageAttributes is always turned on for 9 + // serialization, because it's used by device configuration files also. 10 + #[derive( 11 + Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, Getters, MutGetters, Setters, 12 + )] 13 + pub struct ServerDeviceMessageAttributes { 14 + // Generic commands 15 + #[getset(get = "pub", get_mut = "pub")] 16 + #[serde(rename = "ScalarCmd")] 17 + #[serde(skip_serializing_if = "Option::is_none")] 18 + scalar_cmd: Option<Vec<ServerGenericDeviceMessageAttributes>>, 19 + #[getset(get = "pub", get_mut = "pub")] 20 + #[serde(rename = "RotateCmd")] 21 + #[serde(skip_serializing_if = "Option::is_none")] 22 + rotate_cmd: Option<Vec<ServerGenericDeviceMessageAttributes>>, 23 + #[getset(get = "pub", get_mut = "pub")] 24 + #[serde(rename = "LinearCmd")] 25 + #[serde(skip_serializing_if = "Option::is_none")] 26 + linear_cmd: Option<Vec<ServerGenericDeviceMessageAttributes>>, 27 + 28 + // Sensor Messages 29 + #[getset(get = "pub")] 30 + #[serde(rename = "SensorReadCmd")] 31 + #[serde(skip_serializing_if = "Option::is_none")] 32 + sensor_read_cmd: Option<Vec<SensorDeviceMessageAttributes>>, 33 + #[getset(get = "pub")] 34 + #[serde(rename = "SensorSubscribeCmd")] 35 + #[serde(skip_serializing_if = "Option::is_none")] 36 + sensor_subscribe_cmd: Option<Vec<SensorDeviceMessageAttributes>>, 37 + 38 + // StopDeviceCmd always exists 39 + #[getset(get = "pub")] 40 + #[serde(rename = "StopDeviceCmd")] 41 + #[serde(skip_deserializing)] 42 + stop_device_cmd: NullDeviceMessageAttributes, 43 + 44 + // Raw commands are only added post-serialization 45 + #[getset(get = "pub")] 46 + #[serde(rename = "RawReadCmd")] 47 + #[serde(skip_deserializing)] 48 + #[serde(skip_serializing_if = "Option::is_none")] 49 + raw_read_cmd: Option<RawDeviceMessageAttributes>, 50 + // Raw commands are only added post-serialization 51 + #[getset(get = "pub")] 52 + #[serde(rename = "RawWriteCmd")] 53 + #[serde(skip_deserializing)] 54 + #[serde(skip_serializing_if = "Option::is_none")] 55 + raw_write_cmd: Option<RawDeviceMessageAttributes>, 56 + // Raw commands are only added post-serialization 57 + #[getset(get = "pub")] 58 + #[serde(rename = "RawSubscribeCmd")] 59 + #[serde(skip_deserializing)] 60 + #[serde(skip_serializing_if = "Option::is_none")] 61 + raw_subscribe_cmd: Option<RawDeviceMessageAttributes>, 62 + 63 + // Needed to load from config for fallback, but unused here. 64 + #[getset(get = "pub")] 65 + #[serde(rename = "FleshlightLaunchFW12Cmd")] 66 + #[serde(skip_serializing)] 67 + fleshlight_launch_fw12_cmd: Option<NullDeviceMessageAttributes>, 68 + #[getset(get = "pub")] 69 + #[serde(rename = "VorzeA10CycloneCmd")] 70 + #[serde(skip_serializing)] 71 + vorze_a10_cyclone_cmd: Option<NullDeviceMessageAttributes>, 72 + } 73 + 74 + impl ServerDeviceMessageAttributes { 75 + pub fn raw_unsubscribe_cmd(&self) -> &Option<RawDeviceMessageAttributes> { 76 + self.raw_subscribe_cmd() 77 + } 78 + 79 + pub fn message_allowed(&self, message_type: &ButtplugDeviceMessageType) -> bool { 80 + match message_type { 81 + ButtplugDeviceMessageType::ScalarCmd => self.scalar_cmd.is_some(), 82 + // VibrateCmd and SingleMotorVibrateCmd will derive from Scalars, so errors will be thrown in 83 + // the scalar parser if the actuator isn't correct. 84 + ButtplugDeviceMessageType::VibrateCmd => self.scalar_cmd.is_some(), 85 + ButtplugDeviceMessageType::SingleMotorVibrateCmd => self.scalar_cmd.is_some(), 86 + ButtplugDeviceMessageType::SensorReadCmd => self.sensor_read_cmd.is_some(), 87 + ButtplugDeviceMessageType::SensorSubscribeCmd => self.sensor_subscribe_cmd.is_some(), 88 + ButtplugDeviceMessageType::SensorUnsubscribeCmd => self.sensor_subscribe_cmd.is_some(), 89 + ButtplugDeviceMessageType::LinearCmd => self.linear_cmd.is_some(), 90 + ButtplugDeviceMessageType::RotateCmd => self.rotate_cmd.is_some(), 91 + ButtplugDeviceMessageType::BatteryLevelCmd => { 92 + if let Some(sensor_info) = &self.sensor_read_cmd { 93 + sensor_info 94 + .iter() 95 + .any(|x| *x.sensor_type() == SensorType::Battery) 96 + } else { 97 + false 98 + } 99 + } 100 + ButtplugDeviceMessageType::FleshlightLaunchFW12Cmd => { 101 + self.fleshlight_launch_fw12_cmd.is_some() 102 + } 103 + ButtplugDeviceMessageType::RSSILevelCmd => { 104 + if let Some(sensor_info) = &self.sensor_read_cmd { 105 + sensor_info 106 + .iter() 107 + .any(|x| *x.sensor_type() == SensorType::RSSI) 108 + } else { 109 + false 110 + } 111 + } 112 + ButtplugDeviceMessageType::RawReadCmd => self.raw_read_cmd.is_some(), 113 + ButtplugDeviceMessageType::RawSubscribeCmd => self.raw_subscribe_cmd.is_some(), 114 + ButtplugDeviceMessageType::RawUnsubscribeCmd => self.raw_subscribe_cmd.is_some(), 115 + ButtplugDeviceMessageType::RawWriteCmd => self.raw_write_cmd.is_some(), 116 + ButtplugDeviceMessageType::VorzeA10CycloneCmd => self.vorze_a10_cyclone_cmd.is_some(), 117 + ButtplugDeviceMessageType::StopDeviceCmd => true, 118 + ButtplugDeviceMessageType::KiirooCmd => false, 119 + ButtplugDeviceMessageType::LovenseCmd => false, 120 + } 121 + } 122 + 123 + pub fn merge(&self, child: &ServerDeviceMessageAttributes) -> ServerDeviceMessageAttributes { 124 + Self { 125 + rotate_cmd: child 126 + .rotate_cmd() 127 + .clone() 128 + .or_else(|| self.rotate_cmd().clone()), 129 + linear_cmd: child 130 + .linear_cmd() 131 + .clone() 132 + .or_else(|| self.linear_cmd().clone()), 133 + scalar_cmd: child 134 + .scalar_cmd() 135 + .clone() 136 + .or_else(|| self.scalar_cmd().clone()), 137 + sensor_read_cmd: child 138 + .sensor_read_cmd() 139 + .clone() 140 + .or_else(|| self.sensor_read_cmd().clone()), 141 + sensor_subscribe_cmd: child 142 + .sensor_subscribe_cmd() 143 + .clone() 144 + .or_else(|| self.sensor_subscribe_cmd().clone()), 145 + stop_device_cmd: NullDeviceMessageAttributes::default(), 146 + raw_read_cmd: child 147 + .raw_read_cmd() 148 + .clone() 149 + .or_else(|| self.raw_read_cmd().clone()), 150 + raw_write_cmd: child 151 + .raw_write_cmd() 152 + .clone() 153 + .or_else(|| self.raw_write_cmd().clone()), 154 + raw_subscribe_cmd: child 155 + .raw_subscribe_cmd() 156 + .clone() 157 + .or_else(|| self.raw_subscribe_cmd().clone()), 158 + fleshlight_launch_fw12_cmd: child 159 + .fleshlight_launch_fw12_cmd() 160 + .clone() 161 + .or_else(|| self.fleshlight_launch_fw12_cmd().clone()), 162 + vorze_a10_cyclone_cmd: child 163 + .vorze_a10_cyclone_cmd() 164 + .clone() 165 + .or_else(|| self.vorze_a10_cyclone_cmd().clone()), 166 + } 167 + } 168 + 169 + pub fn add_raw_messages(&mut self, endpoints: &[Endpoint]) { 170 + let raw_attrs = RawDeviceMessageAttributes::new(&endpoints.to_vec()); 171 + self.raw_read_cmd = Some(raw_attrs.clone()); 172 + self.raw_write_cmd = Some(raw_attrs.clone()); 173 + self.raw_subscribe_cmd = Some(raw_attrs.clone()); 174 + } 175 + } 176 + 177 + impl Into<ClientDeviceMessageAttributes> for ServerDeviceMessageAttributes { 178 + fn into(self) -> ClientDeviceMessageAttributes { 179 + let mut builder = ClientDeviceMessageAttributesBuilder::default(); 180 + if let Some(scalar_cmd) = self.scalar_cmd { 181 + builder.scalar_cmd(&scalar_cmd.iter().cloned().map(|x| x.into()).collect()); 182 + } 183 + if let Some(rotate_cmd) = self.rotate_cmd { 184 + builder.rotate_cmd(&rotate_cmd.iter().cloned().map(|x| x.into()).collect()); 185 + } 186 + if let Some(linear_cmd) = self.linear_cmd { 187 + builder.linear_cmd(&linear_cmd.iter().cloned().map(|x| x.into()).collect()); 188 + } 189 + if let Some(sensor_read_cmd) = self.sensor_read_cmd { 190 + builder.sensor_read_cmd(&sensor_read_cmd); 191 + } 192 + if let Some(sensor_subscribe_cmd) = self.sensor_subscribe_cmd { 193 + builder.sensor_subscribe_cmd(&sensor_subscribe_cmd); 194 + } 195 + if let Some(raw_read_cmd) = self.raw_read_cmd { 196 + builder.raw_read_cmd(raw_read_cmd.endpoints()); 197 + } 198 + if let Some(raw_write_cmd) = self.raw_write_cmd { 199 + builder.raw_write_cmd(raw_write_cmd.endpoints()); 200 + } 201 + if let Some(raw_subscribe_cmd) = self.raw_subscribe_cmd { 202 + builder.raw_subscribe_cmd(raw_subscribe_cmd.endpoints()); 203 + } 204 + builder.finish() 205 + } 206 + } 207 + 208 + #[derive(Default)] 209 + pub struct ServerDeviceMessageAttributesBuilder { 210 + attrs: ServerDeviceMessageAttributes, 211 + } 212 + 213 + impl ServerDeviceMessageAttributesBuilder { 214 + pub fn scalar_cmd(&mut self, attrs: &Vec<ServerGenericDeviceMessageAttributes>) -> &Self { 215 + self.attrs.scalar_cmd = Some(attrs.clone()); 216 + self 217 + } 218 + 219 + pub fn rotate_cmd(&mut self, attrs: &Vec<ServerGenericDeviceMessageAttributes>) -> &Self { 220 + self.attrs.rotate_cmd = Some(attrs.clone()); 221 + self 222 + } 223 + 224 + pub fn linear_cmd(&mut self, attrs: &Vec<ServerGenericDeviceMessageAttributes>) -> &Self { 225 + self.attrs.linear_cmd = Some(attrs.clone()); 226 + self 227 + } 228 + 229 + pub fn sensor_read_cmd(&mut self, attrs: &Vec<SensorDeviceMessageAttributes>) -> &Self { 230 + self.attrs.sensor_read_cmd = Some(attrs.clone()); 231 + self 232 + } 233 + 234 + pub fn sensor_subscribe_cmd(&mut self, attrs: &Vec<SensorDeviceMessageAttributes>) -> &Self { 235 + self.attrs.sensor_subscribe_cmd = Some(attrs.clone()); 236 + self 237 + } 238 + 239 + pub fn raw_read_cmd(&mut self, endpoints: &Vec<Endpoint>) -> &Self { 240 + self.attrs.raw_read_cmd = Some(RawDeviceMessageAttributes::new(endpoints)); 241 + self 242 + } 243 + 244 + pub fn raw_write_cmd(&mut self, endpoints: &Vec<Endpoint>) -> &Self { 245 + self.attrs.raw_write_cmd = Some(RawDeviceMessageAttributes::new(endpoints)); 246 + self 247 + } 248 + 249 + pub fn raw_subscribe_cmd(&mut self, endpoints: &Vec<Endpoint>) -> &Self { 250 + self.attrs.raw_subscribe_cmd = Some(RawDeviceMessageAttributes::new(endpoints)); 251 + self 252 + } 253 + 254 + pub fn finish(&self) -> ServerDeviceMessageAttributes { 255 + self.attrs.clone() 256 + } 257 + } 258 + 259 + fn unspecified_feature() -> String { 260 + "No description available for feature".to_string() 261 + } 262 + 263 + #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Getters, Setters)] 264 + pub struct ServerGenericDeviceMessageAttributes { 265 + #[getset(get = "pub")] 266 + #[serde(rename = "FeatureDescriptor")] 267 + #[serde(default = "unspecified_feature")] 268 + feature_descriptor: String, 269 + #[getset(get = "pub")] 270 + #[serde(rename = "ActuatorType")] 271 + actuator_type: ActuatorType, 272 + #[serde(rename = "StepRange")] 273 + #[serde(skip_serializing)] 274 + #[getset(get = "pub", set = "pub")] 275 + step_range: RangeInclusive<u32>, 276 + } 277 + 278 + impl Into<ClientGenericDeviceMessageAttributes> for ServerGenericDeviceMessageAttributes { 279 + fn into(self) -> ClientGenericDeviceMessageAttributes { 280 + ClientGenericDeviceMessageAttributes::new( 281 + &self.feature_descriptor, 282 + self.step_count(), 283 + self.actuator_type, 284 + ) 285 + } 286 + } 287 + 288 + impl ServerGenericDeviceMessageAttributes { 289 + pub fn new( 290 + feature_descriptor: &str, 291 + step_range: &RangeInclusive<u32>, 292 + actuator_type: ActuatorType, 293 + ) -> Self { 294 + Self { 295 + feature_descriptor: feature_descriptor.to_owned(), 296 + actuator_type, 297 + step_range: step_range.clone(), 298 + } 299 + } 300 + 301 + pub fn step_count(&self) -> u32 { 302 + self.step_range.end() - self.step_range.start() 303 + } 304 + 305 + pub fn is_valid( 306 + &self, 307 + message_type: &ButtplugDeviceMessageType, 308 + ) -> Result<(), ButtplugDeviceError> { 309 + if self.step_range.is_empty() { 310 + Err(ButtplugDeviceError::DeviceConfigurationError(format!( 311 + "Step range out of order for {}, must be start <= x <= end.", 312 + message_type 313 + ))) 314 + } else { 315 + Ok(()) 316 + } 317 + } 318 + } 319 + 320 + #[cfg(test)] 321 + mod test { 322 + use super::*; 323 + 324 + #[test] 325 + pub fn test_step_count_calculation() { 326 + let mut vibrate_attributes = ServerGenericDeviceMessageAttributes::new( 327 + "test", 328 + &RangeInclusive::new(0, 10), 329 + ActuatorType::Vibrate, 330 + ); 331 + assert_eq!(vibrate_attributes.step_count(), 10); 332 + vibrate_attributes.set_step_range(RangeInclusive::new(3u32, 7)); 333 + assert_eq!(vibrate_attributes.step_count(), 4); 334 + } 335 + }
+11 -13
buttplug/src/server/device/protocol/generic_command_manager.rs
··· 11 11 messages::{ 12 12 ActuatorType, 13 13 ButtplugDeviceCommandMessageUnion, 14 - GenericDeviceMessageAttributes, 14 + ClientGenericDeviceMessageAttributes, 15 15 LinearCmd, 16 16 RotateCmd, 17 17 RotationSubcommand, ··· 19 19 ScalarSubcommand, 20 20 }, 21 21 }, 22 - server::device::configuration::ProtocolDeviceAttributes, 22 + server::device::configuration::{ProtocolDeviceAttributes, ServerGenericDeviceMessageAttributes}, 23 23 }; 24 24 use getset::Getters; 25 25 use std::{ ··· 36 36 } 37 37 38 38 impl ScalarGenericCommand { 39 - pub fn new(attributes: &GenericDeviceMessageAttributes) -> Self { 39 + pub fn new(attributes: &ServerGenericDeviceMessageAttributes) -> Self { 40 40 Self { 41 41 actuator: attributes.actuator_type().clone(), 42 42 step_range: attributes.step_range().clone(), ··· 325 325 use crate::{ 326 326 core::messages::{ 327 327 ActuatorType, 328 - DeviceMessageAttributesBuilder, 329 - GenericDeviceMessageAttributes, 330 328 RotateCmd, 331 329 RotationSubcommand, 332 330 ScalarCmd, 333 331 ScalarSubcommand, 334 332 }, 335 - server::device::configuration::ProtocolAttributesType, 333 + server::device::configuration::{ProtocolAttributesType, ServerGenericDeviceMessageAttributes, ServerDeviceMessageAttributesBuilder}, 336 334 }; 337 335 use std::ops::RangeInclusive; 338 336 339 337 #[test] 340 338 pub fn test_command_generator_vibration() { 341 - let scalar_attrs = GenericDeviceMessageAttributes::new( 339 + let scalar_attrs = ServerGenericDeviceMessageAttributes::new( 342 340 "Test", 343 341 &RangeInclusive::new(0, 20), 344 342 ActuatorType::Vibrate, 345 343 ); 346 - let scalar_attributes = DeviceMessageAttributesBuilder::default() 344 + let scalar_attributes = ServerDeviceMessageAttributesBuilder::default() 347 345 .scalar_cmd(&vec![scalar_attrs.clone(), scalar_attrs.clone()]) 348 346 .finish(); 349 347 let device_attributes = ProtocolDeviceAttributes::new( ··· 406 404 407 405 #[test] 408 406 pub fn test_command_generator_vibration_step_range() { 409 - let mut vibrate_attrs_1 = GenericDeviceMessageAttributes::new( 407 + let mut vibrate_attrs_1 = ServerGenericDeviceMessageAttributes::new( 410 408 "Test", 411 409 &RangeInclusive::new(0, 20), 412 410 ActuatorType::Vibrate, 413 411 ); 414 412 vibrate_attrs_1.set_step_range(RangeInclusive::new(10, 15)); 415 - let mut vibrate_attrs_2 = GenericDeviceMessageAttributes::new( 413 + let mut vibrate_attrs_2 = ServerGenericDeviceMessageAttributes::new( 416 414 "Test", 417 415 &RangeInclusive::new(0, 20), 418 416 ActuatorType::Vibrate, 419 417 ); 420 418 vibrate_attrs_2.set_step_range(RangeInclusive::new(10, 20)); 421 419 422 - let vibrate_attributes = DeviceMessageAttributesBuilder::default() 420 + let vibrate_attributes = ServerDeviceMessageAttributesBuilder::default() 423 421 .scalar_cmd(&vec![vibrate_attrs_1, vibrate_attrs_2]) 424 422 .finish(); 425 423 let device_attributes = ProtocolDeviceAttributes::new( ··· 482 480 483 481 #[test] 484 482 pub fn test_command_generator_rotation() { 485 - let rotate_attrs = GenericDeviceMessageAttributes::new( 483 + let rotate_attrs = ServerGenericDeviceMessageAttributes::new( 486 484 "Test", 487 485 &RangeInclusive::new(0, 20), 488 486 ActuatorType::Rotate, 489 487 ); 490 488 491 - let rotate_attributes = DeviceMessageAttributesBuilder::default() 489 + let rotate_attributes = ServerDeviceMessageAttributesBuilder::default() 492 490 .rotate_cmd(&vec![rotate_attrs.clone(), rotate_attrs]) 493 491 .finish(); 494 492 let device_attributes = ProtocolDeviceAttributes::new(
+3 -3
buttplug/src/server/device/server_device.rs
··· 21 21 ButtplugDeviceMessageType, 22 22 ButtplugMessage, 23 23 ButtplugServerDeviceMessage, 24 - DeviceMessageAttributes, 24 + ClientDeviceMessageAttributes, 25 25 Endpoint, 26 26 RawReading, 27 27 RawSubscribeCmd, ··· 50 50 use tokio_stream::StreamExt; 51 51 52 52 use super::{ 53 - configuration::ProtocolDeviceAttributes, 53 + configuration::{ProtocolDeviceAttributes, ServerDeviceMessageAttributes}, 54 54 protocol::generic_command_manager::GenericCommandManager, 55 55 }; 56 56 ··· 263 263 } 264 264 265 265 /// Retreive the message attributes for the device. 266 - pub fn message_attributes(&self) -> DeviceMessageAttributes { 266 + pub fn message_attributes(&self) -> ServerDeviceMessageAttributes { 267 267 self.attributes.message_attributes() 268 268 } 269 269
+1 -1
buttplug/src/server/device/server_device_manager.rs
··· 286 286 .iter() 287 287 .map(|device| { 288 288 let dev = device.value(); 289 - DeviceMessageInfo::new(*device.key(), &dev.name(), dev.message_attributes()) 289 + DeviceMessageInfo::new(*device.key(), &dev.name(), dev.message_attributes().clone().into()) 290 290 }) 291 291 .collect(); 292 292 let mut device_list = DeviceList::new(devices);
+1 -1
buttplug/src/server/device/server_device_manager_event_loop.rs
··· 265 265 266 266 info!("Assigning index {} to {}", device_index, device.name()); 267 267 let device_added_message = 268 - DeviceAdded::new(device_index, &device.name(), &device.message_attributes()); 268 + DeviceAdded::new(device_index, &device.name(), &device.message_attributes().clone().into()); 269 269 self.device_map.insert(device_index, device); 270 270 // After that, we can send out to the server's event listeners to let 271 271 // them know a device has been added.
+4 -4
buttplug/src/util/device_configuration.rs
··· 7 7 8 8 use super::json::JSONValidator; 9 9 use crate::{ 10 - core::{errors::ButtplugDeviceError, messages::DeviceMessageAttributes}, 10 + core::errors::ButtplugDeviceError, 11 11 server::device::{ 12 12 configuration::{ 13 13 BluetoothLESpecifier, ··· 22 22 SerialSpecifier, 23 23 USBSpecifier, 24 24 WebsocketSpecifier, 25 - XInputSpecifier, 25 + XInputSpecifier, ServerDeviceMessageAttributes, 26 26 }, 27 27 ServerDeviceIdentifier, 28 28 }, ··· 88 88 deny: Option<bool>, 89 89 #[serde(skip_serializing_if = "Option::is_none")] 90 90 #[serde(default)] 91 - messages: Option<DeviceMessageAttributes>, 91 + messages: Option<ServerDeviceMessageAttributes>, 92 92 #[serde(skip_serializing_if = "Option::is_none")] 93 93 #[serde(default)] 94 94 index: Option<u32>, ··· 102 102 #[serde(skip_serializing_if = "Option::is_none")] 103 103 name: Option<String>, 104 104 #[serde(skip_serializing_if = "Option::is_none")] 105 - messages: Option<DeviceMessageAttributes>, 105 + messages: Option<ServerDeviceMessageAttributes>, 106 106 } 107 107 108 108 #[derive(Deserialize, Serialize, Debug, Clone, Default, Getters, Setters, MutGetters)]