From abaf38c3d5d27825f13f084a0c4e7c9ce49f9c13 Mon Sep 17 00:00:00 2001 From: Carl Andersson Date: Sat, 4 Mar 2023 21:31:34 +0100 Subject: [PATCH] Add option to save mounting location on server. This will save sensor id's in the config file, and send that to SlimeVR Server. Needs version v0.6.1 of server or newser. --- Cargo.lock | 37 ++++++++++++++++--------------- src/joycon/communication.rs | 32 ++++++++++++++------------- src/main.rs | 9 ++++++++ src/settings.rs | 43 ++++++++++++++++++++++++++++++++++--- 4 files changed, 84 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fbf6967..c3bdfd0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -163,12 +163,11 @@ dependencies = [ [[package]] name = "async-lock" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" +checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" dependencies = [ "event-listener", - "futures-lite", ] [[package]] @@ -190,9 +189,9 @@ checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" [[package]] name = "async-trait" -version = "0.1.64" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" +checksum = "095183a3539c7c7649b2beb87c2d3f0591f3a7fed07761cc546d244e27e0238c" dependencies = [ "proc-macro2", "quote", @@ -1972,9 +1971,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "jni-sys" @@ -3171,9 +3170,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] name = "rayon" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" dependencies = [ "either", "rayon-core", @@ -3181,9 +3180,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.10.2" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -3325,9 +3324,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.36.8" +version = "0.36.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" +checksum = "fd5c6ff11fecd55b40746d1995a02f2eb375bf8c00d192d521ee09f42bef37bc" dependencies = [ "bitflags", "errno", @@ -3361,9 +3360,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] name = "safe_arch" @@ -3709,9 +3708,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" dependencies = [ "libc", "winapi", @@ -4168,9 +4167,9 @@ checksum = "07547e3ee45e28326cc23faac56d44f58f16ab23e413db526debce3b0bfd2742" [[package]] name = "unicode-ident" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +checksum = "775c11906edafc97bc378816b94585fbd9a054eabaf86fdd0ced94af449efab7" [[package]] name = "unicode-linebreak" diff --git a/src/joycon/communication.rs b/src/joycon/communication.rs index 504f84b..5adde1b 100644 --- a/src/joycon/communication.rs +++ b/src/joycon/communication.rs @@ -57,7 +57,7 @@ impl Display for DeviceStatus { struct Device { imu: Imu, design: JoyconDesign, - id: u8, + send_id: u8, battery: Battery, status: DeviceStatus, imu_times: Vec, @@ -67,7 +67,7 @@ impl Device { pub fn handshake(&self, socket: &UdpSocket, address: &SocketAddr) { let sensor_info = PacketType::SensorInfo { packet_id: 0, - sensor_id: self.id, + sensor_id: self.send_id, sensor_status: 1, sensor_type: 0, }; @@ -99,13 +99,6 @@ pub enum ChannelInfo { Reset, Disconnected, } -/* -fn serial_number_to_mac(serial: &str) -> [u8; 6] { - let mut hasher = Md5::new(); - hasher.update(serial); - hasher.finalize()[0..6].try_into().unwrap() -} -*/ #[derive(Debug, Copy, Clone)] struct Xyz { @@ -156,6 +149,7 @@ pub struct Communication { devices: HashMap, + use_keep_ids: bool, socket: UdpSocket, address: SocketAddr, connected: ServerStatus, @@ -177,6 +171,7 @@ impl Communication { let socket = UdpSocket::bind(&addrs[..]).unwrap(); socket.set_nonblocking(true).ok(); let address = { settings.load().get_socket_address() }; + let use_keep_ids = { settings.load().keep_ids }; server_tx.send(ServerStatus::Disconnected).ok(); @@ -186,6 +181,7 @@ impl Communication { server_tx, settings, devices: HashMap::new(), + use_keep_ids, socket, address, connected: ServerStatus::Disconnected, @@ -232,15 +228,21 @@ impl Communication { device.imu_times = vec![]; return; } - let id = self.devices.len() as _; + + let send_id = if self.use_keep_ids { + self.settings.joycon_keep_id(sn.clone()) + } else { + self.devices.len() as _ + }; let device = Device { - design, imu: Imu::new(), - id, + design, + send_id, battery: Battery::Full, status: DeviceStatus::NoIMU, imu_times: vec![], }; + device.handshake(&self.socket, &self.address); self.devices.insert(sn, device); } @@ -262,7 +264,7 @@ impl Communication { let rotation_packet = PacketType::RotationData { packet_id: 0, - sensor_id: device.id, + sensor_id: device.send_id, data_type: 1, quat: (*rotated_quat).into(), calibration_info: 0, @@ -275,7 +277,7 @@ impl Communication { let acceleration_packet = PacketType::Acceleration { packet_id: 0, vector: (acc.x as f32, acc.y as f32, acc.z as f32), - sensor_id: Some(device.id), + sensor_id: Some(device.send_id), }; self.socket .send_to(&acceleration_packet.to_bytes().unwrap(), self.address) @@ -339,7 +341,7 @@ impl Communication { { self.last_handshake = Instant::now(); self.send_handshake(); - for device in self.devices.values().sorted_by_key(|d| d.id) { + for device in self.devices.values().sorted_by_key(|d| d.send_id) { device.handshake(&self.socket, &self.address); } } diff --git a/src/main.rs b/src/main.rs index 7e47514..3d5397b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -81,6 +81,7 @@ enum Message { JoyconRotate(String, bool), JoyconScale(String, f64), SettingsResetToggled(bool), + SettingsIdsToggled(bool), } #[derive(Default)] @@ -170,6 +171,9 @@ impl Application for MainState { Message::SettingsResetToggled(new) => { self.settings.change(|ws| ws.send_reset = new); } + Message::SettingsIdsToggled(new) => { + self.settings.change(|ws| ws.keep_ids = new); + } } Command::none() } @@ -238,6 +242,11 @@ impl MainState { self.settings.load().send_reset, Message::SettingsResetToggled, )) + .push(checkbox( + "Save mounting location on server. Requires SlimeVR Server v0.6.1 or newer. (Restart wrangler after changing this)", + self.settings.load().keep_ids, + Message::SettingsIdsToggled, + )) } } diff --git a/src/settings.rs b/src/settings.rs index 6da7793..7a890ba 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -10,10 +10,17 @@ use serde::{Deserialize, Serialize}; fn file_name() -> Option { ProjectDirs::from("", "", "SlimeVR Wrangler").map(|pd| pd.config_dir().join("config.json")) } -#[derive(Serialize, Deserialize, Clone)] +#[derive(Serialize, Deserialize, Clone, Debug)] pub struct Joycon { + #[serde(default)] pub rotation: i32, + #[serde(default = "return_f64_one")] pub gyro_scale_factor: f64, + #[serde(default)] + pub keep_id: u8, +} +fn return_f64_one() -> f64 { + 1.0 } impl Default for Joycon { @@ -21,6 +28,7 @@ impl Default for Joycon { Joycon { rotation: 0, gyro_scale_factor: 1.0, + keep_id: 0, } } } @@ -34,12 +42,16 @@ pub struct WranglerSettings { pub send_reset: bool, #[serde(default = "return_mac")] pub emulated_mac: [u8; 6], + #[serde(default = "return_false")] + pub keep_ids: bool, } fn return_true() -> bool { true } - +fn return_false() -> bool { + false +} fn return_mac() -> [u8; 6] { let mut r = rand::thread_rng(); [0x00, 0x0F, r.gen(), r.gen(), r.gen(), r.gen()] @@ -55,7 +67,7 @@ impl WranglerSettings { } File::create(file) .ok() - .and_then(|file| serde_json::to_writer(file, self).ok()); + .and_then(|file| serde_json::to_writer_pretty(file, self).ok()); } pub fn load_and_save() -> Self { let settings = file_name() @@ -66,6 +78,7 @@ impl WranglerSettings { joycon: HashMap::new(), send_reset: true, emulated_mac: return_mac(), + keep_ids: false, }); settings.save(); settings @@ -86,6 +99,15 @@ impl WranglerSettings { .get(serial_number) .map_or(1.0, |j| j.gyro_scale_factor) } + fn joycon_keep_id_set_new(&mut self, serial_number: String) { + let max = self.joycon.values().map(|j| j.keep_id).max(); + let entry = self.joycon.entry(serial_number).or_default(); + entry.keep_id = max.unwrap_or_default().saturating_add(1); + if entry.keep_id == u8::MAX { + println!("\x1b[0;31m[ERROR]\x1b[0m TOO MANY JOYCONS SAVED! THIS WILL BREAK THINGS!"); + println!(" YOU NEED TO DISABLE THE \"Save mounting location on server\" SETTING!!!"); + } + } pub fn get_socket_address(&self) -> SocketAddr { self.address .parse::() @@ -115,4 +137,19 @@ impl Handler { current.save(); self.arc.store(Arc::new(current)); } + pub fn joycon_keep_id(&self, serial_number: String) -> u8 { + let keep_id = self + .load() + .joycon + .get(&serial_number) + .map_or(0, |j| j.keep_id); + if keep_id != 0 { + return keep_id; + } + self.change(|ws| ws.joycon_keep_id_set_new(serial_number.clone())); + self.load() + .joycon + .get(&serial_number) + .map_or(0, |j| j.keep_id) + } }