Added framework for TMClient struct/impl

master
noah metz 2024-01-18 20:20:19 -07:00
parent 005fb13e21
commit bfc9b9ec5b
1 changed files with 131 additions and 39 deletions

@ -2,6 +2,7 @@ use rumqttc::{MqttOptions, Client, QoS, LastWill};
use bytes::Bytes; use bytes::Bytes;
use std::time::Duration; use std::time::Duration;
use std::thread; use std::thread;
use std::sync::mpsc;
use std::collections::hash_map::HashMap; use std::collections::hash_map::HashMap;
use prost::Message; use prost::Message;
use std::io::Cursor; use std::io::Cursor;
@ -130,6 +131,61 @@ struct MQTTMessage {
payload: String, payload: String,
} }
struct Event {
name: String,
divisions: Vec<Division>,
}
struct Division {
name: String,
matches: Vec<Match>,
field_set: FieldSet,
}
struct FieldSet {
fields: Vec<Field>,
}
struct Field {
name: String,
current_match: u32,
}
struct Match {
name: String,
}
struct TMClient {
notices: mpsc::Sender<tm::Notice>,
}
struct BackendMessage {
}
impl TMClient {
fn new() -> (TMClient, mpsc::Receiver<tm::Notice>) {
let (tx, rx) = mpsc::channel();
(TMClient {
notices: tx,
}, rx)
}
fn process(self: &TMClient) {
match self.notices.send(tm::Notice::default()) {
Ok(_) => println!("Received notice"),
Err(error) => println!("Recv error {}", error),
}
}
// TODO: make send functionality
fn send(request: BackendMessage) -> BackendMessage {
request
}
}
type NoticeCallback = fn(tm::Notice, Event, ) -> (Vec<MQTTMessage>, Event);
fn get_game_score(scores: tm::MatchScore) -> Option<GameScore> { fn get_game_score(scores: tm::MatchScore) -> Option<GameScore> {
if scores.alliances.len() != 2 { if scores.alliances.len() != 2 {
return None; return None;
@ -142,7 +198,6 @@ fn get_game_score(scores: tm::MatchScore) -> Option<GameScore> {
// 2) Get score object and fill AllianceScore struct // 2) Get score object and fill AllianceScore struct
// 3) Compute total scores // 3) Compute total scores
let out = GameScore{ let out = GameScore{
autonomous_winner: None, autonomous_winner: None,
red_total: 0, red_total: 0,
@ -187,35 +242,49 @@ fn on_score_change(notice: tm::Notice, event: Event) -> (Vec<MQTTMessage>, Event
} }
} }
fn get_next_notice() -> tm::Notice { fn on_match_start(notice: tm::Notice, event: Event) -> (Vec<MQTTMessage>, Event) {
thread::sleep(Duration::from_millis(1000)); return (Vec::new(), event);
return tm::Notice::default();
} }
struct Event<'a> { fn on_match_cancel(notice: tm::Notice, event: Event) -> (Vec<MQTTMessage>, Event) {
name: String, return (Vec::new(), event);
divisions: Vec<Division<'a>>,
} }
type NoticeCallback = fn(tm::Notice, Event) -> (Vec<MQTTMessage>, Event); fn on_match_reset(notice: tm::Notice, event: Event) -> (Vec<MQTTMessage>, Event) {
return (Vec::new(), event);
}
struct Division<'a> { fn on_match_assigned(notice: tm::Notice, event: Event) -> (Vec<MQTTMessage>, Event) {
name: String, return (Vec::new(), event);
matches: Vec<Match>,
field_set: FieldSet<'a>,
} }
struct FieldSet<'a> { fn on_active_field_changed(notice: tm::Notice, event: Event) -> (Vec<MQTTMessage>, Event) {
fields: Vec<Field<'a>>, return (Vec::new(), event);
} }
struct Field<'a> { fn on_rankings_updated(notice: tm::Notice, event: Event) -> (Vec<MQTTMessage>, Event) {
name: String, return (Vec::new(), event);
current_match: &'a Match,
} }
struct Match { fn on_event_status_updated(notice: tm::Notice, event: Event) -> (Vec<MQTTMessage>, Event) {
name: String, return (Vec::new(), event);
}
fn on_elim_alliance_update(notice: tm::Notice, event: Event) -> (Vec<MQTTMessage>, Event) {
return (Vec::new(), event);
}
fn on_elim_unavail_teams_update(notice: tm::Notice, event: Event) -> (Vec<MQTTMessage>, Event) {
return (Vec::new(), event);
}
fn on_match_list_update(notice: tm::Notice, event: Event) -> (Vec<MQTTMessage>, Event) {
return (Vec::new(), event);
}
fn get_next_notice() -> tm::Notice {
thread::sleep(Duration::from_millis(1000));
return tm::Notice::default();
} }
fn main() { fn main() {
@ -226,6 +295,16 @@ fn main() {
let mut callbacks: HashMap<tm::NoticeId, NoticeCallback> = HashMap::new(); let mut callbacks: HashMap<tm::NoticeId, NoticeCallback> = HashMap::new();
callbacks.insert(tm::NoticeId::NoticeRealtimeScoreChanged, on_score_change); callbacks.insert(tm::NoticeId::NoticeRealtimeScoreChanged, on_score_change);
callbacks.insert(tm::NoticeId::NoticeFieldTimerStarted, on_match_start);
callbacks.insert(tm::NoticeId::NoticeFieldTimerStopped, on_match_cancel);
callbacks.insert(tm::NoticeId::NoticeFieldResetTimer, on_match_reset);
callbacks.insert(tm::NoticeId::NoticeFieldMatchAssigned, on_match_assigned);
callbacks.insert(tm::NoticeId::NoticeActiveFieldChanged, on_active_field_changed);
callbacks.insert(tm::NoticeId::NoticeRankingsUpdated, on_rankings_updated);
callbacks.insert(tm::NoticeId::NoticeEventStatusUpdated, on_event_status_updated);
callbacks.insert(tm::NoticeId::NoticeElimAllianceUpdated, on_elim_alliance_update);
callbacks.insert(tm::NoticeId::NoticeElimUnavailTeamsUpdated, on_elim_unavail_teams_update);
callbacks.insert(tm::NoticeId::NoticeMatchListUpdated, on_match_list_update);
let mut mqttoptions = MqttOptions::new("vex-bridge", "localhost", 1883); let mut mqttoptions = MqttOptions::new("vex-bridge", "localhost", 1883);
mqttoptions.set_keep_alive(Duration::from_secs(5)); mqttoptions.set_keep_alive(Duration::from_secs(5));
@ -240,36 +319,49 @@ fn main() {
client.subscribe("bridge", QoS::AtLeastOnce).unwrap(); client.subscribe("bridge", QoS::AtLeastOnce).unwrap();
client.publish("bridge/status", QoS::AtLeastOnce, true, "{\"online\": true}").unwrap(); client.publish("bridge/status", QoS::AtLeastOnce, true, "{\"online\": true}").unwrap();
let mqtt_thread = thread::spawn(move || let mqtt_recv_thread = thread::spawn(move ||
for message in connection.iter() { for message in connection.iter() {
println!("Message = {:?}", message); println!("Message = {:?}", message);
} }
); );
let running = true; let running = true;
let (tm_client, tm_notices) = TMClient::new();
let tm_thread = thread::spawn(move ||
while running {
tm_client.process();
}
);
while running { while running {
let notice = get_next_notice(); match tm_notices.recv() {
let callback = callbacks.get(&notice.id()); Ok(notice) => {
match callback { let callback = callbacks.get(&notice.id());
None => { match callback {
match notice.id { None => {
None => println!("Notice without NoticeId received"), match notice.id {
Some(notice_id) => println!("Unhandled NoticeId: {}", notice_id), None => println!("Notice without NoticeId received"),
} Some(notice_id) => println!("Unhandled NoticeId: {}", notice_id),
}, }
Some(callback) => { },
let (messages, next_event) = callback(notice, event); Some(callback) => {
event = next_event; let (messages, next_event) = callback(notice, event);
for message in messages { event = next_event;
let result = client.publish(message.topic, QoS::AtMostOnce, true, message.payload); for message in messages {
match result { let result = client.publish(message.topic, QoS::AtMostOnce, true, message.payload);
Ok(_) => {}, match result {
Err(error) => println!("Publish error: {}", error), Ok(_) => {},
} Err(error) => println!("Publish error: {}", error),
}
}
},
} }
}, },
Err(error) => println!("Notice recv error: {}", error),
} }
} }
mqtt_thread.join().expect("Failed to join mqtt thread"); mqtt_recv_thread.join().expect("Failed to join mqtt thread");
tm_thread.join().expect("Failed to join tm connection thread");
} }