diff --git a/buttplug/buttplug-device-config/build-config/buttplug-device-config-v2.json b/buttplug/buttplug-device-config/build-config/buttplug-device-config-v2.json index 0ed32346b..bf4594b62 100644 --- a/buttplug/buttplug-device-config/build-config/buttplug-device-config-v2.json +++ b/buttplug/buttplug-device-config/build-config/buttplug-device-config-v2.json @@ -8948,6 +8948,9 @@ }, "00008000-0000-1000-8000-00805f9b34fb": { "rx": "00008001-0000-1000-8000-00805f9b34fb" + }, + "00006050-0000-1000-8000-00805f9b34fb": { + "rxblebattery": "00006051-0000-1000-8000-00805f9b34fb" } } }, @@ -8987,6 +8990,18 @@ ], "ActuatorType": "Vibrate" } + ], + "SensorReadCmd": [ + { + "FeatureDescriptor": "Battery Level", + "SensorType": "Battery", + "SensorRange": [ + [ + 0, + 100 + ] + ] + } ] } }, @@ -9072,7 +9087,30 @@ "identifier": [ "MP1N_QC_TL_P2" ], - "name": "Sistalk MonsterPub BeatHeart" + "name": "Sistalk MonsterPub BeatHeart", + "messages": { + "ScalarCmd": [ + { + "StepRange": [ + 0, + 100 + ], + "ActuatorType": "Vibrate" + } + ], + "SensorReadCmd": [ + { + "FeatureDescriptor": "Battery Level", + "SensorType": "Battery", + "SensorRange": [ + [ + 0, + 100 + ] + ] + } + ] + } } ] }, diff --git a/buttplug/buttplug-device-config/build-config/buttplug-device-config-v3.json b/buttplug/buttplug-device-config/build-config/buttplug-device-config-v3.json index 52b68cd2f..a0cc8e95d 100644 --- a/buttplug/buttplug-device-config/build-config/buttplug-device-config-v3.json +++ b/buttplug/buttplug-device-config/build-config/buttplug-device-config-v3.json @@ -13463,7 +13463,8 @@ "configurations": [ { "identifier": [ - "MP2_JK_N_P1" + "MP2_JK_N_P1", + "MP2_JK_N0_P1" ], "name": "Sistalk MonsterPub 2 Doctor Whale", "features": [ @@ -13490,6 +13491,36 @@ "ScalarCmd" ] } + }, + { + "feature-type": "Battery", + "description": "Battery Level", + "sensor": { + "value-range": [ + [ + 0, + 100 + ] + ], + "messages": [ + "SensorReadCmd" + ] + } + }, + { + "feature-type": "Pressure", + "description": "Pressure sensor", + "sensor": { + "value-range": [ + [ + 0, + 2047 + ] + ], + "messages": [ + "SensorReadCmd" + ] + } } ] }, @@ -13557,6 +13588,53 @@ } ] }, + { + "identifier": [ + "MP2_QC_N_P1" + ], + "name": "Sistalk MonsterPub 2 Master Godzilla", + "features": [ + { + "feature-type": "Vibrate", + "actuator": { + "step-range": [ + 0, + 100 + ], + "messages": [ + "ScalarCmd" + ] + } + }, + { + "feature-type": "Vibrate", + "actuator": { + "step-range": [ + 0, + 100 + ], + "messages": [ + "ScalarCmd" + ] + } + }, + { + "feature-type": "Battery", + "description": "Battery Level", + "sensor": { + "value-range": [ + [ + 0, + 100 + ] + ], + "messages": [ + "SensorReadCmd" + ] + } + } + ] + }, { "identifier": [ "MP_BABY_QC_N_P4" @@ -13599,7 +13677,36 @@ "identifier": [ "MP1N_QC_TL_P2" ], - "name": "Sistalk MonsterPub BeatHeart" + "name": "Sistalk MonsterPub BeatHeart", + "features": [ + { + "feature-type": "Vibrate", + "actuator": { + "step-range": [ + 0, + 100 + ], + "messages": [ + "ScalarCmd" + ] + } + }, + { + "feature-type": "Battery", + "description": "Battery Level", + "sensor": { + "value-range": [ + [ + 0, + 100 + ] + ], + "messages": [ + "SensorReadCmd" + ] + } + } + ] } ], "communication": [ @@ -13619,6 +13726,12 @@ }, "00008000-0000-1000-8000-00805f9b34fb": { "rx": "00008001-0000-1000-8000-00805f9b34fb" + }, + "00006050-0000-1000-8000-00805f9b34fb": { + "rxblebattery": "00006051-0000-1000-8000-00805f9b34fb" + }, + "00006030-0000-1000-8000-00805f9b34fb": { + "rxpressure": "00006031-0000-1000-8000-00805f9b34fb" } } } diff --git a/buttplug/buttplug-device-config/device-config-v2/buttplug-device-config-v2.yml b/buttplug/buttplug-device-config/device-config-v2/buttplug-device-config-v2.yml index bb7401663..1364d47f0 100644 --- a/buttplug/buttplug-device-config/device-config-v2/buttplug-device-config-v2.yml +++ b/buttplug/buttplug-device-config/device-config-v2/buttplug-device-config-v2.yml @@ -4459,6 +4459,8 @@ protocols: rxblemodel: 00006014-0000-1000-8000-00805f9b34fb 00008000-0000-1000-8000-00805f9b34fb: rx: 00008001-0000-1000-8000-00805f9b34fb + 00006050-0000-1000-8000-00805f9b34fb: + rxblebattery: 00006051-0000-1000-8000-00805f9b34fb defaults: name: Sistalk MonsterPub Device messages: @@ -4468,6 +4470,7 @@ protocols: configurations: - identifier: - MP2_JK_N_P1 + - MP2_JK_N0_P1 name: Sistalk MonsterPub 2 Doctor Whale messages: ScalarCmd: @@ -4475,6 +4478,10 @@ protocols: ActuatorType: Vibrate - StepRange: [0, 100] ActuatorType: Vibrate + SensorReadCmd: + - FeatureDescriptor: Battery Level + SensorType: Battery + SensorRange: [ [ 0, 100 ] ] - identifier: - MP_MW_TL_P2 name: Sistalk MonsterPub Magic Kiss @@ -4508,6 +4515,14 @@ protocols: - identifier: - MP1N_QC_TL_P2 name: Sistalk MonsterPub BeatHeart + messages: + ScalarCmd: + - StepRange: [ 0, 100 ] + ActuatorType: Vibrate + SensorReadCmd: + - FeatureDescriptor: Battery Level + SensorType: Battery + SensorRange: [ [ 0, 100 ] ] joyhub: btle: names: diff --git a/buttplug/buttplug-device-config/device-config-v3/buttplug-device-config-v3.yml b/buttplug/buttplug-device-config/device-config-v3/buttplug-device-config-v3.yml index 980bbc096..ac86d8ef1 100644 --- a/buttplug/buttplug-device-config/device-config-v3/buttplug-device-config-v3.yml +++ b/buttplug/buttplug-device-config/device-config-v3/buttplug-device-config-v3.yml @@ -7700,6 +7700,7 @@ protocols: configurations: - identifier: - MP2_JK_N_P1 + - MP2_JK_N0_P1 name: Sistalk MonsterPub 2 Doctor Whale features: - feature-type: Vibrate @@ -7716,6 +7717,22 @@ protocols: - 100 messages: - ScalarCmd + - feature-type: Battery + description: Battery Level + sensor: + value-range: + - - 0 + - 100 + messages: + - SensorReadCmd + - feature-type: Pressure + description: Pressure sensor + sensor: + value-range: + - - 0 + - 2047 + messages: + - SensorReadCmd - identifier: - MP_MW_TL_P2 name: Sistalk MonsterPub Magic Kiss @@ -7752,6 +7769,32 @@ protocols: - 100 messages: - ScalarCmd + - identifier: + - MP2_QC_N_P1 + name: Sistalk MonsterPub 2 Master Godzilla + features: + - feature-type: Vibrate + actuator: + step-range: + - 0 + - 100 + messages: + - ScalarCmd + - feature-type: Vibrate + actuator: + step-range: + - 0 + - 100 + messages: + - ScalarCmd + - feature-type: Battery + description: Battery Level + sensor: + value-range: + - - 0 + - 100 + messages: + - SensorReadCmd - identifier: - MP_BABY_QC_N_P4 name: Sistalk MonsterPub Baby Youth Health @@ -7776,6 +7819,22 @@ protocols: - identifier: - MP1N_QC_TL_P2 name: Sistalk MonsterPub BeatHeart + features: + - feature-type: Vibrate + actuator: + step-range: + - 0 + - 100 + messages: + - ScalarCmd + - feature-type: Battery + description: Battery Level + sensor: + value-range: + - - 0 + - 100 + messages: + - SensorReadCmd communication: - btle: names: @@ -7789,6 +7848,10 @@ protocols: rxblemodel: 00006014-0000-1000-8000-00805f9b34fb 00008000-0000-1000-8000-00805f9b34fb: rx: 00008001-0000-1000-8000-00805f9b34fb + 00006050-0000-1000-8000-00805f9b34fb: + rxblebattery: 00006051-0000-1000-8000-00805f9b34fb + 00006030-0000-1000-8000-00805f9b34fb: + rxpressure: 00006031-0000-1000-8000-00805f9b34fb joyhub: defaults: name: JoyHub Device diff --git a/buttplug/src/server/device/protocol/monsterpub.rs b/buttplug/src/server/device/protocol/monsterpub.rs index 808be46f2..a69f24beb 100644 --- a/buttplug/src/server/device/protocol/monsterpub.rs +++ b/buttplug/src/server/device/protocol/monsterpub.rs @@ -5,7 +5,12 @@ // Licensed under the BSD 3-Clause license. See LICENSE file in the project root // for full license information. -use crate::server::device::configuration::ProtocolCommunicationSpecifier; +use std::sync::Arc; + +use async_trait::async_trait; +use futures_util::{future, FutureExt}; +use futures_util::future::BoxFuture; + use crate::{ core::{ errors::ButtplugDeviceError, @@ -18,11 +23,14 @@ use crate::{ protocol::{ProtocolHandler, ProtocolIdentifier, ProtocolInitializer}, }, }; -use async_trait::async_trait; -use std::sync::Arc; +use crate::core::message; +use crate::core::message::{ButtplugDeviceMessage, ButtplugServerMessage, SensorReadCmd, SensorType}; +use crate::server::device::configuration::ProtocolCommunicationSpecifier; +use crate::server::device::hardware::{HardwareEvent, HardwareSubscribeCmd, HardwareUnsubscribeCmd}; pub mod setup { use crate::server::device::protocol::{ProtocolIdentifier, ProtocolIdentifierFactory}; + #[derive(Default)] pub struct MonsterPubIdentifierFactory {} @@ -131,8 +139,50 @@ pub struct MonsterPub { } impl MonsterPub { - pub fn new(tx: Endpoint) -> Self { - Self { tx } + pub fn new(tx: Endpoint) -> Self { Self { tx } } + + // pressure endpoint is notify-only and subscriptions are gonna be reworked in v4 + fn handle_pressure_read_cmd(&self, device: Arc, message: SensorReadCmd) -> BoxFuture> { + let mut device_notification_receiver = device.event_stream(); + async move { + device.subscribe(&HardwareSubscribeCmd::new(Endpoint::RxPressure)).await?; + while let Ok(event) = device_notification_receiver.recv().await { + return match event { + HardwareEvent::Notification(_, endpoint, data) => { + if endpoint != Endpoint::RxPressure { continue; } + if data.len() < 2 { + return Err(ButtplugDeviceError::ProtocolSpecificError( + "monsterpub".to_owned(), + "MonsterPub device returned unexpected data while getting pressure info.".to_owned(), + )); + } + device.unsubscribe(&HardwareUnsubscribeCmd::new(Endpoint::RxPressure)).await?; + + // value is u32 LE, but real value is in range from 0 to about 1000 (0x4ff) (i was scared to squeeze it harder) + let pressure_level = [data[0], data[1], 0, 0]; + let pressure_reading = message::SensorReading::new( + message.device_index(), + *message.sensor_index(), + SensorType::Pressure, + vec![i32::from_le_bytes(pressure_level)], + ); + + Ok(pressure_reading.into()) + } + HardwareEvent::Disconnected(_) => { + Err(ButtplugDeviceError::ProtocolSpecificError( + "monsterpub".to_owned(), + "MonsterPub device disconnected while getting pressure info.".to_owned(), + )) + } + } + } + Err(ButtplugDeviceError::ProtocolSpecificError( + "monsterpub".to_owned(), + "MonsterPub device disconnected while getting pressure info.".to_owned(), + )) + } + .boxed() } } @@ -171,4 +221,14 @@ impl ProtocolHandler for MonsterPub { ) .into()]) } + + fn handle_sensor_read_cmd(&self, device: Arc, message: SensorReadCmd) -> BoxFuture> { + match message.sensor_type() { + SensorType::Battery => self.handle_battery_level_cmd(device, message), + SensorType::Pressure => self.handle_pressure_read_cmd(device, message), + _ => future::ready(Err(ButtplugDeviceError::UnhandledCommand( + "Command not implemented for this protocol: SensorReadCmd".to_string(), + ))).boxed(), + } + } }