From 0b33a9e580dee4d30f3e33849a1b8356b7977353 Mon Sep 17 00:00:00 2001 From: Noah Metz Date: Thu, 18 Jan 2024 14:58:54 -0700 Subject: [PATCH] Added structures for MQTT JSON messages --- Cargo.lock | 45 +++++++++++ Cargo.toml | 2 + src/main.rs | 209 ++++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 218 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 90eb33d..0c85bdb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -241,6 +241,12 @@ dependencies = [ "either", ] +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + [[package]] name = "libc" version = "0.2.152" @@ -568,6 +574,12 @@ dependencies = [ "untrusted", ] +[[package]] +name = "ryu" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" + [[package]] name = "schannel" version = "0.1.23" @@ -616,6 +628,37 @@ dependencies = [ "libc", ] +[[package]] +name = "serde" +version = "1.0.195" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.195" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "slab" version = "0.4.9" @@ -746,6 +789,8 @@ dependencies = [ "prost-types", "protoc", "rumqttc", + "serde", + "serde_json", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 024db45..ca4902e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,3 +13,5 @@ prost-build = "0.12.3" prost = "0.12.3" prost-types = "0.12.3" rumqttc = "0.23.0" +serde = { version = "1.0.195", features = ["derive"]} +serde_json = "1.0.111" diff --git a/src/main.rs b/src/main.rs index 18dbd28..6b6af20 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,9 @@ use rumqttc::{MqttOptions, Client, QoS}; use std::time::Duration; use std::thread; +use prost::Message; +use std::io::Cursor; +use serde::{Serialize, Deserialize}; // TODO: // 1) Represent state of division/fieldset/field/match(maybe save/load) @@ -21,50 +24,56 @@ use std::thread; // // Notice protobuf: // message Notice { -// optional .NoticeId id = 1; -// optional .MatchTuple affectedMatch = 2; -// optional .ElimAlliance elimAlliance = 3; -// optional .SideChallengeScore sideChallengeScore = 4; -// optional .EventConfig eventConfig = 5; -// optional .FieldHwState fieldState = 6; -// optional .FieldTime fieldTime = 7; -// optional .Field field = 8; -// optional .MatchTimeSchedList matchTimeSchedList = 9; -// optional .MatchTimeSchedList matchTimeSched = 10; -// optional .FieldSetList fieldSetList = 11; -// optional .PitDisplayList pitDisplayList = 12; -// optional .DisplayState displayState = 13; -// optional .AssignedObjectType.AssignedObjectEnum assignedType = 15; -// optional .PublishOptions publishOptions = 16; -// optional .Division division = 17; -// optional .MatchScore matchScore = 18; -// optional .Rankings rankings = 19; -// optional .MatchRound affectedRound = 20; -// optional .Award award = 21; -// optional .FieldSet fieldSet = 22; -// optional .TeamInfo teamInfo = 23; +// optional tm.NoticeId id = 1; +// optional tm.MatchTuple affectedMatch = 2; +// optional tm.ElimAlliance elimAlliance = 3; +// optional tm.SideChallengeScore sideChallengeScore = 4; +// optional tm.EventConfig eventConfig = 5; +// optional tm.FieldHwState fieldState = 6; +// optional tm.FieldTime fieldTime = 7; +// optional tm.Field field = 8; +// optional tm.MatchTimeSchedList matchTimeSchedList = 9; +// optional tm.MatchTimeSchedList matchTimeSched = 10; +// optional tm.FieldSetList fieldSetList = 11; +// optional tm.PitDisplayList pitDisplayList = 12; +// optional tm.DisplayState displayState = 13; +// optional tm.AssignedObjectType.AssignedObjectEnum assignedType = 15; +// optional tm.PublishOptions publishOptions = 16; +// optional tm.Division division = 17; +// optional tm.MatchScore matchScore = 18; +// optional tm.Rankings rankings = 19; +// optional tm.MatchRound affectedRound = 20; +// optional tm.Award award = 21; +// optional tm.FieldSet fieldSet = 22; +// optional tm.TeamInfo teamInfo = 23; // optional double obsolete_serverTime = 24; -// optional .TeamInspection teamInspection = 25; +// optional tm.TeamInspection teamInspection = 25; // optional int32 obsolete_serverTimeZoneInSecs = 27; -// optional .ElimQueueList elimQueueList = 28; -// optional .TextMessageNotice textMessage = 29; +// optional tm.ElimQueueList elimQueueList = 28; +// optional tm.TextMessageNotice textMessage = 29; // optional string originatingClient = 30; // optional bool isLocal = 31; -// optional .DisplaySlide displaySlide = 32; -// optional .AssignedMatchList assignedMatchList = 33; -// optional .MobileDeviceMatchLockList mobileMatchLocks = 34; -// optional .ElimWinsToAdvanceList elimWinsToAdvanceList = 35; +// optional tm.DisplaySlide displaySlide = 32; +// optional tm.AssignedMatchList assignedMatchList = 33; +// optional tm.MobileDeviceMatchLockList mobileMatchLocks = 34; +// optional tm.ElimWinsToAdvanceList elimWinsToAdvanceList = 35; // optional string temporaryCode = 36; -// optional .MatchScoreList matchScoreLog = 37; -// optional .PublishStatus publishStatus = 38; -// optional .MatchInfo matchInfo = 39; -// optional .AwardList awardList = 40; +// optional tm.MatchScoreList matchScoreLog = 37; +// optional tm.PublishStatus publishStatus = 38; +// optional tm.MatchInfo matchInfo = 39; +// optional tm.AwardList awardList = 40; // optional string eventName = 41; -// optional .FieldControlStatus fieldControlStatus = 42; +// optional tm.FieldControlStatus fieldControlStatus = 42; // } - -use prost::Message; -use std::io::Cursor; +// +// MQTT Topics: +// - division/{division_id} +// - division/{division_id}/ranking +// - arena/{arena_id}/score +// - arena/{arena_id}/state +// - arena/{arena_id} +// - game/{division_id}/{game_id}/score +// - team/{team_string} pub mod tm_proto { include!(concat!(env!("OUT_DIR"), "/tm.rs")); @@ -74,9 +83,133 @@ pub fn deserialize_notice(buf: &[u8]) -> Result, +} + +#[derive(Serialize, Deserialize, Debug)] +enum GameSide { + Red, + Blue, +} + +#[derive(Serialize, Deserialize, Debug)] +enum ElevationTier { + A = 0, + B = 1, + C = 2, + D = 3, + E = 4, + F = 5, + G = 6, + H = 7, + I = 8, + J = 9, +} + +#[derive(Serialize, Deserialize, Debug)] +struct AllianceScore { + team_goal: usize, + team_zone: usize, + green_goal: usize, + green_zone: usize, + elevation_tiers: [Option; 2], +} + +#[derive(Serialize, Deserialize, Debug)] +struct GameScore { + autonomous_winner: Option, + red_score: AllianceScore, + red_total: usize, + blue_score: AllianceScore, + blue_total: usize, +} + +#[derive(Serialize, Deserialize, Debug)] +enum GameState { + Scheduled, + Timeout, + Driver, + Driverdone, + Autonomous, + AutonomousDone, + Abandoned, +} + +#[derive(Serialize, Deserialize, Debug)] +struct ArenaStateInfo { + state: Option, + start_s: usize, + start_ns: usize, +} + +#[derive(Serialize, Deserialize, Debug)] +enum Round { + None = 0, + Practice = 1, + Qualification = 2, + QuarterFinals = 3, + SemiFinals = 4, + Finals = 5, + RoundOf16 = 6, + RoundOf32 = 7, + RoundOf64 = 8, + RoundOf128 = 9, + TopN = 15, + RoundRobin = 16, + PreEliminations = 20, + Eliminations = 21, +} + +#[derive(Serialize, Deserialize, Debug)] +struct MatchTuple { + division: String, + round: Round, + instance: usize, + match_num: usize, + session: usize, +} + +#[derive(Serialize, Deserialize, Debug)] +struct ArenaInfo { + red_teams: [String; 2], + blue_teams: [String; 2], + match_tuple: MatchTuple, +} + fn main() { + let score = GameScore{ + autonomous_winner: None, + red_score: AllianceScore{ + team_goal: 0, + team_zone: 0, + green_goal: 0, + green_zone: 0, + elevation_tiers: [None, None], + }, + blue_score: AllianceScore{ + team_goal: 0, + team_zone: 0, + green_goal: 0, + green_zone: 0, + elevation_tiers: [None, None], + }, + red_total: 0, + blue_total: 0, + }; + + let serialized = serde_json::to_string(&score).unwrap(); + println!("Serialized = {}", serialized); + // Set client options - let mut mqttoptions = MqttOptions::new("rumqttc", "localhost", 1883); + let mut mqttoptions = MqttOptions::new("vex-bridge", "localhost", 1883); mqttoptions.set_keep_alive(Duration::from_secs(5)); // Create a new client(10 is bounded channel capacity?)