Skip to content

Commit

Permalink
Merge pull request #4 from lizard-brain/multi-device
Browse files Browse the repository at this point in the history
Multi Device Working
  • Loading branch information
me-sideways authored May 3, 2023
2 parents 39504f4 + 1292930 commit 328a4dc
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 100 deletions.
18 changes: 11 additions & 7 deletions config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,19 @@
#
[Setup]
#
# IP Address of Headpat Device
device_ip = 192.168.1.157
#
# Port listening for OSC [Default 9001]
port_rx = 9100
#
port_rx = 9001
#
proximity_parameter = /avatar/parameters/proximity_01
# IP Address of Headpat Device
device_ips = 192.168.1.151 192.168.1.157 192.168.1.153
#
max_speed_parameter = /avatar/parameters/max_speed
# Unity Proximity parameter[s]
proximity_parameters_multi = proximity_01 proximity_02 proximity_03
#
max_speed_parameter = max_speed
#
[Haptic_Config]
[Config]
#
# Min Speed of Haptic Motor [5-100]
min_speed = 2
Expand All @@ -30,4 +31,7 @@
#
# Max Speed Scalar [10-100]
max_speed_scale = 100
#
# OSC Timeout [seconds]
timeout = 5

6 changes: 5 additions & 1 deletion giggletech-router/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ authors = ["Giggle Tech <hello@giggletech.io>"

[dependencies]
rosc = "0.4.2"
async-std = "1.12.0"
async-std = { version = "1.8.0", features = ["attributes", "unstable"] }
#async-std = "1.12.0"
log = "0.4.14"
futures-lite = "1.11.3"
thiserror = "1.0.24"
Expand All @@ -22,6 +23,9 @@ tokio = { version = "1.13", features = ["full"] }
futures = "0.3"
#ini = "1.3.0"
anyhow = "1.0.44"
once_cell = "1.8.0"





Expand Down
107 changes: 76 additions & 31 deletions giggletech-router/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
// config.rs

use configparser::ini::Ini;
use std::{net::IpAddr};

// Banner
fn banner_txt(){
Expand All @@ -16,61 +19,103 @@ fn banner_txt(){
}

pub(crate) fn load_config() -> (
String, // headpat_device_ip
f32, // min_speed_float
f32, // max_speed_float
f32, // speed_scale_float
String, // port_rx
String, // proximity_parameter_address
String, // max_speed_parameter_address
f32, // Max Speed Low Limit
Vec<String>, // headpat_device_URIs
f32, // min_speed_float
f32, // max_speed_float
f32, // speed_scale_float
String, // port_rx
Vec<String>, // proximity_parameters_multi
String, // max_speed_parameter_address
f32, // Max Speed Low Limit
u64, // Timeout Setting
) {
let mut config = Ini::new();

match config.load("./config.ini") {
Err(why) => panic!("{}", why),
Ok(_) => {}
}
const MAX_SPEED_LOW_LIMIT_CONST: f32 = 0.05;

// Check the format of the IP URIs
let headpat_device_uris: Vec<String> = config.get("Setup", "device_ips")
.unwrap()
.split_whitespace()
.map(|s| s.to_string()) // convert &str to String
.filter_map(|s| {
match s.parse::<IpAddr>() {
Ok(_) => Some(s),
Err(_) => {
println!("Invalid IP address format: {}", s);
None
}
}
})
.collect();
if headpat_device_uris.is_empty() {
eprintln!("Error: no device URIs specified in config file");
// handle error here, e.g. return early from the function or exit the program
}

let proximity_parameters_multi: Vec<String> = config
.get("Setup", "proximity_parameters_multi")
.unwrap()
.split_whitespace()
.map(|s| format!("/avatar/parameters/{}", s))
.collect();

let headpat_device_ip = config.get("Setup", "device_ip").unwrap();
let headpat_device_port = "8888".to_string();
let min_speed = config.get("Haptic_Config", "min_speed").unwrap();
let min_speed_float = min_speed.parse::<f32>().unwrap() / 100.0;
let max_speed = config.get("Haptic_Config", "max_speed").unwrap();
let max_speed_float = max_speed.parse::<f32>().unwrap() / 100.0;
let max_speed_low_limit = MAX_SPEED_LOW_LIMIT_CONST;
let max_speed_float = max_speed_float.max(max_speed_low_limit);
let speed_scale = config.get("Haptic_Config", "max_speed_scale").unwrap();
let speed_scale_float = speed_scale.parse::<f32>().unwrap() / 100.0;
let port_rx = config.get("Setup", "port_rx").unwrap();

if headpat_device_uris.len() != proximity_parameters_multi.len() {
eprintln!("Error: number of device URIs does not match number of proximity parameters");
// handle error here, e.g. return early from the function or exit the program
}

const MAX_SPEED_LOW_LIMIT_CONST: f32 = 0.05;

let proximity_parameter_address = config
.get("Setup", "proximity_parameter")
.unwrap_or_else(|| "/avatar/parameters/proximity_01".into());
let max_speed_parameter_address = config
.get("Setup", "max_speed_parameter")
.unwrap_or_else(|| "/avatar/parameters/max_speed".into());
let min_speed = config.get("Config", "min_speed").unwrap();
let min_speed_float = min_speed.parse::<f32>().unwrap() / 100.0;

let max_speed = config.get("Config", "max_speed").unwrap().parse::<f32>().unwrap() / 100.0;
let max_speed_low_limit = MAX_SPEED_LOW_LIMIT_CONST;
let max_speed_float = max_speed.max(max_speed_low_limit);

let speed_scale = config.get("Config", "max_speed_scale").unwrap();
let speed_scale_float = speed_scale.parse::<f32>().unwrap() / 100.0;

let port_rx = config.get("Setup", "port_rx").unwrap();

let timeout_str = config.get("Config", "timeout").unwrap();
let timeout = timeout_str.parse::<u64>().unwrap_or(0);

let max_speed_parameter_address = format!("/avatar/parameters/{}", config.get("Setup", "max_speed_parameter").unwrap_or_else(|| "/avatar/parameters/max_speed".into()));

println!("\n");
banner_txt();
println!("\n");
println!(" Haptic Device: {}:{}", headpat_device_ip, headpat_device_port);
println!(" Listening for OSC on port: {}", port_rx);
println!(" Device Maps");
for (i, parameter) in proximity_parameters_multi.iter().enumerate() {
println!(" {} => {}", parameter.trim_start_matches("/avatar/parameters/"), headpat_device_uris[i]);
}

println!("\n Listening for OSC on port: {}", port_rx);
println!("\n Vibration Configuration");
println!(" Min Speed: {}%", min_speed);
println!(" Max Speed: {:?}%", max_speed_float * 100.0);
println!(" Scale Factor: {}%", speed_scale);
println!(" Timeout: {}s", timeout);
println!("\nWaiting for pats...");

(
headpat_device_ip,
headpat_device_uris,
min_speed_float,
max_speed_float,
speed_scale_float,
port_rx,
proximity_parameter_address,
proximity_parameters_multi,
max_speed_parameter_address,
max_speed_low_limit,
timeout,
)
}
}



8 changes: 5 additions & 3 deletions giggletech-router/src/data_processing.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// data_processing.rs


pub fn proximity_graph(proximity_signal: f32) -> String {
let num_dashes = (proximity_signal * 10.0) as usize;
let graph = "-".repeat(num_dashes) + ">";
Expand All @@ -19,12 +22,11 @@ pub fn print_speed_limit(headpat_max_rx: f32) {
// Pat Processor
const MOTOR_SPEED_SCALE: f32 = 0.66; // Overvolt Here, OEM config 0.66 going higher than this value will reduce your vibrator motor life

pub fn process_pat(proximity_signal: f32, max_speed: f32, min_speed: f32, speed_scale: f32) -> i32 {
pub fn process_pat(proximity_signal: f32, max_speed: f32, min_speed: f32, speed_scale: f32, proximity_parameter: &String) -> i32 {
let graph_str = proximity_graph(proximity_signal);
let headpat_tx = (((max_speed - min_speed) * proximity_signal + min_speed) * MOTOR_SPEED_SCALE * speed_scale * 255.0).round() as i32;
let proximity_signal = format!("{:.2}", proximity_signal);
let max_speed = format!("{:.2}", max_speed);
eprintln!("Prox: {:5} Motor Tx: {:3} Max Speed: {:5} |{:11}|", proximity_signal, headpat_tx, max_speed, graph_str);
eprintln!("{} Prox: {:5} Motor Tx: {:3} |{:11}|", proximity_parameter.trim_start_matches("/avatar/parameters/") , proximity_signal, headpat_tx, graph_str);

headpat_tx
}
Expand Down
2 changes: 2 additions & 0 deletions giggletech-router/src/giggletech_osc.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// giggletech_osc.rs

// GiggleTech OSC Module
// Data Sender, Tx & Rx Socket Setup

Expand Down
45 changes: 45 additions & 0 deletions giggletech-router/src/handle_proximity_parameter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// handle_proximity_parameter.rs

use async_osc::Result;
use async_std::sync::Arc;
use std::{
sync::atomic::{AtomicBool},
time::Instant,
};


use crate::osc_timeout;
use crate::terminator;
use crate::giggletech_osc;
use crate::data_processing;


pub(crate) async fn handle_proximity_parameter(
running: Arc<AtomicBool>,
device_ip: &Arc<String>,
value: f32,
max_speed: f32,
min_speed: f32,
speed_scale: f32,
proximity_parameters_multi: &String,
) -> Result<()> {
terminator::stop(running.clone()).await?;

// Update Last Signal Time for timeout clock
let mut device_last_signal_times = osc_timeout::DEVICE_LAST_SIGNAL_TIME.lock().unwrap();
device_last_signal_times.insert(device_ip.to_string(), Instant::now());

if value == 0.0 {
println!("Stopping pats...");
terminator::start(running.clone(), &device_ip).await?;

for _ in 0..5 {
giggletech_osc::send_data(&device_ip, 0i32).await?;
}
} else {
giggletech_osc::send_data(&device_ip,
data_processing::process_pat(value, max_speed, min_speed, speed_scale, proximity_parameters_multi)).await?;

}
Ok(())
}
Loading

0 comments on commit 328a4dc

Please sign in to comment.