Skip to content

Commit 16d0d22

Browse files
committed
feat(pishock): allow configuring multiple codes
1 parent 51c575f commit 16d0d22

File tree

3 files changed

+72
-27
lines changed

3 files changed

+72
-27
lines changed

src/config.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ impl Default for OscConfig {
2222
pub struct PiShockConfig {
2323
pub username: String,
2424
pub api_key: String,
25-
pub code: String,
25+
pub code: Option<String>,
26+
pub codes: Option<Vec<String>>,
2627
pub duration: u8,
2728
}
2829

@@ -31,7 +32,8 @@ impl Default for PiShockConfig {
3132
Self {
3233
username: "".to_string(),
3334
api_key: "".to_string(),
34-
code: "".to_string(),
35+
code: None,
36+
codes: Some(vec!["".to_string()]),
3537
duration: 4,
3638
}
3739
}

src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use clap::Parser;
1717
use directories::BaseDirs;
1818
use file_rotate::compression::Compression;
1919
use file_rotate::suffix::{AppendTimestamp, FileLimit};
20-
use file_rotate::{ContentLimit, FileRotate, TimeFrequency};
20+
use file_rotate::{ContentLimit, FileRotate};
2121
use log::{debug, error, info, LevelFilter};
2222
use simplelog::{ColorChoice, CombinedLogger, TermLogger, TerminalMode, WriteLogger};
2323
use std::path::PathBuf;

src/plugins/pishock.rs

Lines changed: 67 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use crate::config::Config;
22
use crate::osc_query::{OscAccess, OscQueryService};
3-
use anyhow::{bail, Context, Result};
3+
use anyhow::{anyhow, bail, Context, Result};
44
use async_osc::{prelude::OscMessageExt, OscMessage, OscType};
55
use debounced::debounced;
6-
use log::{debug, info, warn};
6+
use log::{debug, error, info, warn};
77
use serde::{Deserialize, Serialize};
88
use std::path::PathBuf;
99
use std::sync::Arc;
@@ -12,6 +12,7 @@ use tokio::fs::{metadata, File};
1212
use tokio::io::{AsyncReadExt, AsyncWriteExt};
1313
use tokio::sync::broadcast::error::RecvError;
1414
use tokio::sync::{broadcast, mpsc, oneshot};
15+
use tokio::task::JoinSet;
1516
use tokio::time::sleep;
1617
use tokio::{select, spawn};
1718
use tokio_graceful_shutdown::{errors::CancelledByShutdown, FutureExt, SubsystemHandle};
@@ -287,24 +288,19 @@ struct ShockBody {
287288
intensity: u8,
288289
}
289290

290-
async fn send_shock(
291-
config: &Arc<Config>,
292-
intensity: f32,
293-
duration: u8,
294-
activity_tx: &mpsc::Sender<u8>,
295-
) {
291+
async fn send_shock(config: Arc<Config>, code: String, intensity: f32, duration: u8) -> Result<()> {
296292
let intensity = 1 + (99. * intensity) as u8;
297293
let duration = duration.clamp(1, 15);
298294

299295
info!(
300-
"Sending shock with intensity {} and duration {}",
301-
intensity, duration
296+
"Sending shock to {} with intensity {} and duration {}",
297+
code, intensity, duration
302298
);
303299

304300
let body = ShockBody {
305301
username: config.pishock.username.clone(),
306302
api_key: config.pishock.api_key.clone(),
307-
code: config.pishock.code.clone(),
303+
code,
308304
name: "OSC Manager - PiShock Plugin".to_string(),
309305
op: 0,
310306
duration,
@@ -324,22 +320,69 @@ async fn send_shock(
324320

325321
match status {
326322
Ok(status) => match status.as_str() {
327-
"Not Authorized." => warn!("Invalid credentials"),
328-
"Operation Succeeded." => {
329-
debug!("Shock succeeded");
330-
let _ = activity_tx.send(duration).await;
331-
}
332-
_ => warn!("Unknown response: {}", status),
323+
"Not Authorized." => Err(anyhow!("Invalid credentials")),
324+
"Operation Succeeded." => Ok(()),
325+
"Operation Attempted." => Ok(()),
326+
_ => Err(anyhow!("Unknown response: {}", status)),
333327
},
334-
Err(_) => {
335-
warn!("Failed to parse response");
336-
}
328+
Err(_) => Err(anyhow!("Failed to parse response")),
337329
}
338330
}
339-
Err(_) => {
340-
warn!("Failed to contact pishock API");
331+
Err(_) => Err(anyhow!("Failed to contact pishock API")),
332+
}
333+
}
334+
335+
async fn send_shocks(
336+
config: &Arc<Config>,
337+
intensity: f32,
338+
duration: u8,
339+
activity_tx: &mpsc::Sender<u8>,
340+
) {
341+
let codes = if let Some(codes) = config.pishock.codes.clone() {
342+
codes
343+
} else if let Some(code) = config.pishock.code.clone() {
344+
vec![code]
345+
} else {
346+
warn!("Neither single nor multiple codes configured");
347+
return;
348+
};
349+
350+
if codes.is_empty() {
351+
warn!("No codes configured");
352+
return;
353+
}
354+
355+
let mut set = JoinSet::new();
356+
357+
for code in codes {
358+
set.spawn(send_shock(
359+
config.clone(),
360+
code.clone(),
361+
intensity,
362+
duration,
363+
));
364+
}
365+
366+
let mut succeeded = false;
367+
368+
while let Some(res) = set.join_next().await {
369+
match res {
370+
Ok(Ok(())) => {
371+
debug!("Shock succeeded");
372+
succeeded = true;
373+
}
374+
Ok(Err(error)) => {
375+
warn!("{}", error);
376+
}
377+
Err(error) => {
378+
error!("{}", error);
379+
}
341380
}
342381
}
382+
383+
if succeeded {
384+
let _ = activity_tx.send(duration).await;
385+
}
343386
}
344387

345388
async fn handle_shock(
@@ -370,7 +413,7 @@ async fn handle_shock(
370413
loop {
371414
let settings = get_settings(&settings_tx).await.unwrap();
372415

373-
send_shock(
416+
send_shocks(
374417
&config,
375418
settings.intensity,
376419
config.pishock.duration,
@@ -549,7 +592,7 @@ impl PiShock {
549592
if value >= 0. {
550593
let settings = get_settings(&settings_tx).await?;
551594

552-
send_shock(
595+
send_shocks(
553596
&self.config,
554597
value.clamp(0., settings.intensity_cap),
555598
1,

0 commit comments

Comments
 (0)