moved state variables to struct

This commit is contained in:
Nickiel12 2024-03-26 18:56:33 -07:00
parent 423ef593de
commit bab184f140
2 changed files with 130 additions and 57 deletions

View file

@ -4,6 +4,7 @@ use crate::JoystickThreadUpdate;
use async_channel::{Receiver, Sender};
use gilrs::{ev::filter::FilterFn, Axis, Button, Event, EventType, Filter, Gilrs, GilrsBuilder};
use std::net::TcpStream;
use std::panic::{self, AssertUnwindSafe};
use std::{
sync::{atomic::AtomicBool, Arc},
@ -12,8 +13,66 @@ use std::{
use websocket::client::{sync::Client, ClientBuilder};
use websocket::Message;
struct UnknownSlayer;
static MAX_RETRY_ATTEMPTS: u32 = 10;
struct SocketState {
pub ip: String,
pub port: i32,
pub socket: Option<Client<TcpStream>>,
}
impl SocketState {
fn is_connected(&self ) -> bool {
self.socket.is_some()
}
fn close_websocket(&mut self) {
if let Some(ref mut x) = self.socket {
println!("closing websocket");
x.send_message(&Message::close()).unwrap();
x.shutdown().unwrap();
self.socket = None;
}
}
fn reconnect_websocket(&mut self) -> bool {
if self.ip.is_empty() {
self.socket = None;
return false
}
if let Ok(mut val) =
ClientBuilder::new(format!("ws://{}:{}", &self.ip, self.port).as_str())
{
if let Ok(val2) = val.connect_insecure() {
self.socket = Some(val2);
true
} else {
println!("couldn't connect websocket! : Step 1");
self.socket = None;
false
}
} else {
println!("couldn't connect websocket! : Step 2");
self.socket = None;
false
}
}
}
struct JTState {
pub socket: SocketState,
pub try_reconnect: bool,
pub retry_attempts: u32,
pub curr_x: i32,
pub curr_y: i32,
pub last_update_time: Instant,
}
struct UnknownSlayer;
impl FilterFn for UnknownSlayer {
fn filter(&self, ev: Option<Event>, _gilrs: &mut Gilrs) -> Option<Event> {
match ev {
@ -37,6 +96,7 @@ impl FilterFn for UnknownSlayer {
}
}
pub fn joystick_websocket_loop(
tx: Sender<JoystickThreadUpdate>,
do_run: Arc<AtomicBool>,
@ -44,109 +104,120 @@ pub fn joystick_websocket_loop(
) {
let mut gilrs = GilrsBuilder::new().set_update_state(false).build().unwrap();
let mut ip: String;
let mut port: u32;
let mut state = JTState {
socket: SocketState {
ip: String::new(),
port: 0,
socket: None
},
try_reconnect: false,
retry_attempts: 0,
curr_x: 0,
curr_y: 0,
let mut websocket: Option<Client<websocket::stream::sync::TcpStream>> = None;
last_update_time: Instant::now(),
};
let mut curr_x: i32 = 0;
let mut curr_y: i32 = 0;
let mut last_update_time = Instant::now();
loop {
match rx.try_recv() {
Ok(msg) => {
ip = msg.ip;
port = msg.port;
state.socket.ip = msg.ip;
state.socket.port = msg.port as i32;
save_config(&AppState {
ip: ip.clone(),
port,
ip: state.socket.ip.clone(),
port: state.socket.port as u32,
});
println!("ws://{}:{}", ip, port);
println!("ws://{}:{}", state.socket.ip, state.socket.port);
if let Some(mut x) = websocket {
println!("closing websocket");
x.send_message(&Message::close()).unwrap();
x.shutdown().unwrap();
websocket = None;
} else {
websocket = {
if let Ok(mut val) =
ClientBuilder::new(format!("ws://{}:{}", ip, port).as_str())
{
if let Ok(val2) = val.connect_insecure() {
Some(val2)
} else {
println!("couldn't connect websocket! : Step 1");
None
}
} else {
println!("couldn't connect websocket! : Step 2");
None
}
};
if msg.start_websocket {
if !state.socket.is_connected() {
state.socket.reconnect_websocket();
}
} else if state.socket.is_connected() {
state.socket.close_websocket();
}
}
Err(async_channel::TryRecvError::Closed) => break,
Err(async_channel::TryRecvError::Empty) => {}
}
if state.try_reconnect {
if state.retry_attempts > MAX_RETRY_ATTEMPTS { state.try_reconnect = false; }
if state.socket.is_connected() {
state.try_reconnect = false;
} else if state.socket.reconnect_websocket() {
state.try_reconnect = false;
state.retry_attempts = 0;
}
else {
state.retry_attempts += 1;
}
}
// catch unwind because some buttons on the joystick will panic the gilrs object
match panic::catch_unwind(AssertUnwindSafe(|| {
// get the next event, and if it is an axis we are interested in, update the
// corresponding variable
while let Some(evt) = gilrs.next_event().filter_ev(&UnknownSlayer {}, &mut gilrs) {
match evt.event {
gilrs::EventType::AxisChanged(gilrs::Axis::LeftStickY, val, _) => {
curr_y = (val * 100.0) as i32;
if curr_y > -10 && curr_y < 10 {
curr_y = 0;
state.curr_y = (val * 100.0) as i32;
if state.curr_y > -10 && state.curr_y < 10 {
state.curr_y = 0;
}
}
gilrs::EventType::AxisChanged(gilrs::Axis::LeftStickX, val, _) => {
curr_x = (val * 100.0) as i32;
if curr_x > -10 && curr_x < 10 {
curr_x = 0;
state.curr_x = (val * 100.0) as i32;
if state.curr_x > -10 && state.curr_x < 10 {
state.curr_x = 0;
}
}
_ => {}
}
}
})) {
Ok(_) => {}
Ok(_) => { }
Err(_) => {
println!("panic-causing event captured")
println!("panic-causing event captured in gilrs event handler")
}
}
if websocket.is_some()
&& Instant::now().duration_since(last_update_time) >= Duration::from_millis(150)
if state.socket.is_connected()
&& Instant::now().duration_since(state.last_update_time) >= Duration::from_millis(150)
{
let mut message: String;
if curr_y > 0 {
message = format!("D{}:", curr_y);
if state.curr_y > 0 {
message = format!("D{}:", state.curr_y);
} else {
message = format!("U{}:", curr_y.abs());
message = format!("U{}:", state.curr_y.abs());
}
if curr_x > 0 {
message.push_str(&format!("R{}", curr_x));
if state.curr_x > 0 {
message.push_str(&format!("R{}", state.curr_x));
} else {
message.push_str(&format!("L{}", curr_x.abs()));
message.push_str(&format!("L{}", state.curr_x.abs()));
}
if let Some(mut websocket_tx) = websocket {
websocket_tx.send_message(&Message::text(message)).unwrap();
websocket = Some(websocket_tx);
if let Some(ref mut websocket_tx) = state.socket.socket {
if websocket_tx.send_message(&Message::text(message)).is_ok() {
} else {
state.socket.close_websocket();
}
}
last_update_time = Instant::now();
state.last_update_time = Instant::now();
continue;
}
match tx.try_send(JoystickThreadUpdate {
connected: websocket.is_some(),
x_axis: Some(curr_x.to_string()),
y_axis: Some(curr_y.to_string()),
connected: state.socket.is_connected(),
x_axis: Some(state.curr_x.to_string()),
y_axis: Some(state.curr_y.to_string()),
}) {
Ok(_) => {}
Err(async_channel::TrySendError::Closed(_)) => break,

View file

@ -10,6 +10,7 @@ use crate::{joystick_loop, JoystickThreadUpdate};
pub struct SocketConnectionUpdate {
pub ip: String,
pub port: u32,
pub start_websocket: bool,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
@ -92,6 +93,7 @@ pub fn build_ui(app: &Application) {
match tx2.try_send(SocketConnectionUpdate {
ip: ip_text.to_string(),
port: val,
start_websocket: ip_entry.get_sensitive(),
}) {
Ok(_) => { }
Err(async_channel::TrySendError::Closed(_)) => {panic!("Joystick thread was closed. Unrecoverable")}