2020-01-26 15:01:34 +00:00
|
|
|
extern crate clap;
|
|
|
|
|
|
|
|
use clap::{App, Arg};
|
2020-01-26 16:52:43 +00:00
|
|
|
use futures::{future, pin_mut, StreamExt};
|
2020-01-26 15:01:34 +00:00
|
|
|
use rand::random;
|
|
|
|
use serde_json::json;
|
2020-01-11 11:38:22 +00:00
|
|
|
use std::i64;
|
2020-01-26 15:01:34 +00:00
|
|
|
use std::io;
|
2020-01-01 20:36:10 +00:00
|
|
|
use std::io::Write;
|
|
|
|
use std::net;
|
2020-01-26 17:43:14 +00:00
|
|
|
use std::net::SocketAddr;
|
2020-01-26 15:47:35 +00:00
|
|
|
use std::time::Instant;
|
2020-01-26 16:52:43 +00:00
|
|
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
2020-01-26 17:43:14 +00:00
|
|
|
use tokio::net::UdpSocket;
|
2020-01-26 16:52:43 +00:00
|
|
|
use tokio_tungstenite::connect_async;
|
|
|
|
use tungstenite::protocol::Message;
|
2020-01-26 15:01:34 +00:00
|
|
|
use url::Url;
|
2020-01-01 20:36:10 +00:00
|
|
|
|
2020-01-26 17:43:14 +00:00
|
|
|
async fn listen(senddata: futures::channel::mpsc::UnboundedSender<Message>) {
|
2020-01-26 17:28:35 +00:00
|
|
|
// Setup the UDP Socket
|
2020-01-26 17:43:14 +00:00
|
|
|
let mut now = Instant::now();
|
|
|
|
let mut udpsocket = UdpSocket::bind("0.0.0.0:0").await.unwrap();
|
|
|
|
udpsocket.connect("127.0.0.1:9000").await.unwrap();
|
2020-01-01 20:36:10 +00:00
|
|
|
|
2020-01-26 17:28:35 +00:00
|
|
|
let msg = String::from("ok").into_bytes();
|
2020-01-26 17:43:14 +00:00
|
|
|
udpsocket.send(&msg).await.unwrap();
|
2020-01-01 20:36:10 +00:00
|
|
|
|
2020-01-26 17:28:35 +00:00
|
|
|
loop {
|
|
|
|
// Handle Sending part
|
|
|
|
//senddata
|
|
|
|
/*
|
|
|
|
let msg = String::from("ok").into_bytes();
|
|
|
|
udpsocket
|
|
|
|
.send_to(&msg, "192.168.0.141:9000")
|
|
|
|
.expect("cannot send");*/
|
|
|
|
// -------------
|
|
|
|
let mut buf: [u8; 20] = [0; 20];
|
|
|
|
let mut result: Vec<u8> = Vec::new();
|
2020-01-26 17:43:14 +00:00
|
|
|
let len = udpsocket.recv(&mut buf).await.unwrap();
|
|
|
|
result = Vec::from(&buf[0..len]);
|
2020-01-26 17:28:35 +00:00
|
|
|
|
|
|
|
let display_result = result.clone();
|
|
|
|
let result_str = String::from_utf8(display_result).unwrap();
|
|
|
|
println!("received message: {:?}", result_str);
|
|
|
|
|
|
|
|
if result_str.contains("S0R1") {
|
2020-01-26 17:43:14 +00:00
|
|
|
//senddata.unbounded_send("RaceStart".to_string()).unwrap();
|
|
|
|
|
|
|
|
let source_id = "LAPTIME";
|
|
|
|
let request = json!({"request-type":"SetTextFreetype2Properties", "source":source_id,"message-id": random::<f64>().to_string(), "text": now.elapsed().as_millis().to_string() });
|
|
|
|
now = Instant::now();
|
|
|
|
senddata
|
|
|
|
.unbounded_send(Message::Text(request.to_string()))
|
|
|
|
.unwrap();
|
|
|
|
|
2020-01-26 17:28:35 +00:00
|
|
|
write_file("Race active".to_string(), "racestate.txt");
|
|
|
|
write_file("0".to_string(), "rx1.txt");
|
|
|
|
write_file("0".to_string(), "rx2.txt");
|
|
|
|
write_file("0".to_string(), "rx3.txt");
|
2020-01-02 21:14:38 +00:00
|
|
|
}
|
2020-01-26 17:28:35 +00:00
|
|
|
if result_str.contains("S0R0") {
|
|
|
|
write_file("Race inactive".to_string(), "racestate.txt");
|
2020-01-11 11:38:22 +00:00
|
|
|
}
|
2020-01-26 17:28:35 +00:00
|
|
|
|
|
|
|
if result_str.contains("S0L") {
|
|
|
|
// zb sS1L0000000DAF
|
|
|
|
let lap_time = i64::from_str_radix(&result_str[5..13], 16).unwrap_or(-1);
|
|
|
|
if lap_time != -1 {
|
|
|
|
let lap_seconds = (lap_time as f64) / (1000 as f64);
|
|
|
|
write_file(lap_seconds.to_string(), "rx1_laptime.txt");
|
|
|
|
}
|
|
|
|
let intval = &result_str[3..5].parse::<i32>().unwrap_or(-1);
|
|
|
|
if *intval != -1 {
|
|
|
|
write_file((intval + 1).to_string(), "rx1.txt");
|
|
|
|
}
|
2020-01-11 11:38:22 +00:00
|
|
|
}
|
2020-01-26 17:28:35 +00:00
|
|
|
if result_str.contains("S1L") {
|
|
|
|
let lap_time = i64::from_str_radix(&result_str[5..13], 16).unwrap_or(-1);
|
|
|
|
if lap_time != -1 {
|
|
|
|
let lap_seconds = (lap_time as f64) / (1000 as f64);
|
|
|
|
write_file(lap_seconds.to_string(), "rx2_laptime.txt");
|
|
|
|
}
|
|
|
|
let intval = &result_str[3..5].parse::<i32>().unwrap_or(-1);
|
|
|
|
if *intval != -1 {
|
|
|
|
write_file((intval + 1).to_string(), "rx2.txt");
|
|
|
|
}
|
2020-01-11 11:38:22 +00:00
|
|
|
}
|
2020-01-26 17:28:35 +00:00
|
|
|
if result_str.contains("S2L") {
|
|
|
|
let lap_time = i64::from_str_radix(&result_str[5..13], 16).unwrap_or(-1);
|
|
|
|
if lap_time != -1 {
|
|
|
|
let lap_seconds = (lap_time as f64) / (1000 as f64);
|
|
|
|
write_file(lap_seconds.to_string(), "rx3_laptime.txt");
|
|
|
|
}
|
|
|
|
let intval = &result_str[3..5].parse::<i32>().unwrap_or(-1);
|
|
|
|
if *intval != -1 {
|
|
|
|
write_file((intval + 1).to_string(), "rx3.txt");
|
|
|
|
}
|
2020-01-02 21:14:38 +00:00
|
|
|
}
|
2020-01-01 20:36:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-01 21:20:43 +00:00
|
|
|
fn write_file(text: String, filename: &str) {
|
2020-01-01 20:36:10 +00:00
|
|
|
let mut file = std::fs::File::create(filename).expect("create failed");
|
|
|
|
file.write_all(text.as_bytes()).expect("write failed");
|
|
|
|
//println!("data written to file");
|
|
|
|
}
|
|
|
|
|
2020-01-26 16:52:43 +00:00
|
|
|
#[tokio::main]
|
|
|
|
async fn main() {
|
2020-01-26 15:01:34 +00:00
|
|
|
let matches = App::new("chorusOBSsync")
|
|
|
|
.version("1.0")
|
|
|
|
.author("Lukas B. <lukas@lbsfilm.at>")
|
|
|
|
.about("Get data from the CHorus32 Laptimer Project and use it to control OBS")
|
|
|
|
.arg(
|
|
|
|
Arg::with_name("config")
|
|
|
|
.short("c")
|
|
|
|
.long("config")
|
|
|
|
.value_name("FILE")
|
|
|
|
.help("Sets a custom config file")
|
|
|
|
.takes_value(true),
|
|
|
|
)
|
|
|
|
.arg(
|
|
|
|
Arg::with_name("INPUT")
|
|
|
|
.help("Sets the input file to use")
|
|
|
|
.required(false)
|
|
|
|
.index(1),
|
|
|
|
)
|
|
|
|
.arg(
|
|
|
|
Arg::with_name("v")
|
|
|
|
.short("v")
|
|
|
|
.multiple(true)
|
|
|
|
.help("Sets the level of verbosity"),
|
|
|
|
)
|
|
|
|
.get_matches();
|
|
|
|
|
|
|
|
// Gets a value for config if supplied by user, or defaults to "default.conf"
|
|
|
|
let config = matches.value_of("config").unwrap_or("default.conf");
|
|
|
|
println!("Value for config: {}", config);
|
|
|
|
|
|
|
|
// Calling .unwrap() is safe here because "INPUT" is required (if "INPUT" wasn't
|
|
|
|
// required we could have used an 'if let' to conditionally get the value)
|
|
|
|
if let Some(input) = matches.value_of("INPUT") {
|
|
|
|
println!("Using input file: {}", input);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Vary the output based on how many times the user used the "verbose" flag
|
|
|
|
// (i.e. 'myprog -v -v -v' or 'myprog -vvv' vs 'myprog -v'
|
|
|
|
match matches.occurrences_of("v") {
|
|
|
|
0 => println!("No verbose info"),
|
|
|
|
1 => println!("Some verbose info"),
|
|
|
|
2 => println!("Tons of verbose info"),
|
|
|
|
3 | _ => println!("Don't be crazy"),
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////----------------
|
2020-01-01 21:20:43 +00:00
|
|
|
write_file("Race inactive".to_string(), "racestate.txt");
|
|
|
|
write_file("0".to_string(), "rx1.txt");
|
|
|
|
write_file("0".to_string(), "rx2.txt");
|
|
|
|
write_file("0".to_string(), "rx3.txt");
|
2020-01-01 20:36:10 +00:00
|
|
|
|
2020-01-11 11:38:22 +00:00
|
|
|
write_file("-.-".to_string(), "rx1_laptime.txt");
|
|
|
|
write_file("-.-".to_string(), "rx2_laptime.txt");
|
|
|
|
write_file("-.-".to_string(), "rx3_laptime.txt");
|
|
|
|
|
2020-01-26 15:01:34 +00:00
|
|
|
// Setup websocket for OBS
|
2020-01-26 16:52:43 +00:00
|
|
|
let (ws_stream, _) = connect_async(Url::parse("ws://localhost:4444/").unwrap())
|
|
|
|
.await
|
|
|
|
.expect("Could not connect to OBS");
|
|
|
|
println!("WebSocket handshake has been successfully completed");
|
|
|
|
|
|
|
|
let (write, read) = ws_stream.split();
|
|
|
|
let (obstx, obsrx) = futures::channel::mpsc::unbounded();
|
2020-01-26 17:43:14 +00:00
|
|
|
//let (udpsockettx, udpsocketrx) = futures::channel::mpsc::unbounded();
|
2020-01-26 16:52:43 +00:00
|
|
|
|
|
|
|
let ws_to_stdout = {
|
|
|
|
read.for_each(|message| {
|
|
|
|
async {
|
|
|
|
let data = message.unwrap().into_data();
|
2020-01-26 17:28:35 +00:00
|
|
|
println!("Messg");
|
2020-01-26 16:52:43 +00:00
|
|
|
tokio::io::stdout().write_all(&data).await.unwrap();
|
|
|
|
}
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
2020-01-26 17:28:35 +00:00
|
|
|
let programm_to_ws = obsrx.map(Ok).forward(write);
|
2020-01-26 15:47:35 +00:00
|
|
|
|
2020-01-26 17:28:35 +00:00
|
|
|
pin_mut!(programm_to_ws, ws_to_stdout);
|
2020-01-26 16:52:43 +00:00
|
|
|
|
2020-01-26 17:43:14 +00:00
|
|
|
tokio::spawn(listen(obstx));
|
2020-01-26 15:01:34 +00:00
|
|
|
|
2020-01-26 17:28:35 +00:00
|
|
|
println!("Will wait now");
|
|
|
|
future::select(programm_to_ws, ws_to_stdout).await;
|
|
|
|
|
|
|
|
/*
|
|
|
|
loop {
|
2020-01-26 15:01:34 +00:00
|
|
|
if now.elapsed().as_secs() >= 5 {
|
|
|
|
let request = json!({"request-type":"SetTextFreetype2Properties", "source":source_id,"message-id": random::<f64>().to_string(), "text": now.elapsed().as_millis().to_string() });
|
2020-01-26 16:52:43 +00:00
|
|
|
obstx
|
|
|
|
.unbounded_send(Message::Text(request.to_string()))
|
2020-01-26 15:01:34 +00:00
|
|
|
.unwrap();
|
|
|
|
println!("{}", now.elapsed().as_secs());
|
|
|
|
now = Instant::now();
|
|
|
|
}
|
2020-01-01 20:36:10 +00:00
|
|
|
}
|
2020-01-26 17:28:35 +00:00
|
|
|
*/
|
2020-01-01 20:36:10 +00:00
|
|
|
}
|