|
|
@ -1,6 +1,9 @@
|
|
|
|
use rumqttc::{MqttOptions, Client, QoS};
|
|
|
|
use rumqttc::{MqttOptions, Client, QoS};
|
|
|
|
use std::time::Duration;
|
|
|
|
use std::time::Duration;
|
|
|
|
use std::thread;
|
|
|
|
use std::thread;
|
|
|
|
|
|
|
|
use prost::Message;
|
|
|
|
|
|
|
|
use std::io::Cursor;
|
|
|
|
|
|
|
|
use serde::{Serialize, Deserialize};
|
|
|
|
|
|
|
|
|
|
|
|
// TODO:
|
|
|
|
// TODO:
|
|
|
|
// 1) Represent state of division/fieldset/field/match(maybe save/load)
|
|
|
|
// 1) Represent state of division/fieldset/field/match(maybe save/load)
|
|
|
@ -21,50 +24,56 @@ use std::thread;
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Notice protobuf:
|
|
|
|
// Notice protobuf:
|
|
|
|
// message Notice {
|
|
|
|
// message Notice {
|
|
|
|
// optional .NoticeId id = 1;
|
|
|
|
// optional tm.NoticeId id = 1;
|
|
|
|
// optional .MatchTuple affectedMatch = 2;
|
|
|
|
// optional tm.MatchTuple affectedMatch = 2;
|
|
|
|
// optional .ElimAlliance elimAlliance = 3;
|
|
|
|
// optional tm.ElimAlliance elimAlliance = 3;
|
|
|
|
// optional .SideChallengeScore sideChallengeScore = 4;
|
|
|
|
// optional tm.SideChallengeScore sideChallengeScore = 4;
|
|
|
|
// optional .EventConfig eventConfig = 5;
|
|
|
|
// optional tm.EventConfig eventConfig = 5;
|
|
|
|
// optional .FieldHwState fieldState = 6;
|
|
|
|
// optional tm.FieldHwState fieldState = 6;
|
|
|
|
// optional .FieldTime fieldTime = 7;
|
|
|
|
// optional tm.FieldTime fieldTime = 7;
|
|
|
|
// optional .Field field = 8;
|
|
|
|
// optional tm.Field field = 8;
|
|
|
|
// optional .MatchTimeSchedList matchTimeSchedList = 9;
|
|
|
|
// optional tm.MatchTimeSchedList matchTimeSchedList = 9;
|
|
|
|
// optional .MatchTimeSchedList matchTimeSched = 10;
|
|
|
|
// optional tm.MatchTimeSchedList matchTimeSched = 10;
|
|
|
|
// optional .FieldSetList fieldSetList = 11;
|
|
|
|
// optional tm.FieldSetList fieldSetList = 11;
|
|
|
|
// optional .PitDisplayList pitDisplayList = 12;
|
|
|
|
// optional tm.PitDisplayList pitDisplayList = 12;
|
|
|
|
// optional .DisplayState displayState = 13;
|
|
|
|
// optional tm.DisplayState displayState = 13;
|
|
|
|
// optional .AssignedObjectType.AssignedObjectEnum assignedType = 15;
|
|
|
|
// optional tm.AssignedObjectType.AssignedObjectEnum assignedType = 15;
|
|
|
|
// optional .PublishOptions publishOptions = 16;
|
|
|
|
// optional tm.PublishOptions publishOptions = 16;
|
|
|
|
// optional .Division division = 17;
|
|
|
|
// optional tm.Division division = 17;
|
|
|
|
// optional .MatchScore matchScore = 18;
|
|
|
|
// optional tm.MatchScore matchScore = 18;
|
|
|
|
// optional .Rankings rankings = 19;
|
|
|
|
// optional tm.Rankings rankings = 19;
|
|
|
|
// optional .MatchRound affectedRound = 20;
|
|
|
|
// optional tm.MatchRound affectedRound = 20;
|
|
|
|
// optional .Award award = 21;
|
|
|
|
// optional tm.Award award = 21;
|
|
|
|
// optional .FieldSet fieldSet = 22;
|
|
|
|
// optional tm.FieldSet fieldSet = 22;
|
|
|
|
// optional .TeamInfo teamInfo = 23;
|
|
|
|
// optional tm.TeamInfo teamInfo = 23;
|
|
|
|
// optional double obsolete_serverTime = 24;
|
|
|
|
// optional double obsolete_serverTime = 24;
|
|
|
|
// optional .TeamInspection teamInspection = 25;
|
|
|
|
// optional tm.TeamInspection teamInspection = 25;
|
|
|
|
// optional int32 obsolete_serverTimeZoneInSecs = 27;
|
|
|
|
// optional int32 obsolete_serverTimeZoneInSecs = 27;
|
|
|
|
// optional .ElimQueueList elimQueueList = 28;
|
|
|
|
// optional tm.ElimQueueList elimQueueList = 28;
|
|
|
|
// optional .TextMessageNotice textMessage = 29;
|
|
|
|
// optional tm.TextMessageNotice textMessage = 29;
|
|
|
|
// optional string originatingClient = 30;
|
|
|
|
// optional string originatingClient = 30;
|
|
|
|
// optional bool isLocal = 31;
|
|
|
|
// optional bool isLocal = 31;
|
|
|
|
// optional .DisplaySlide displaySlide = 32;
|
|
|
|
// optional tm.DisplaySlide displaySlide = 32;
|
|
|
|
// optional .AssignedMatchList assignedMatchList = 33;
|
|
|
|
// optional tm.AssignedMatchList assignedMatchList = 33;
|
|
|
|
// optional .MobileDeviceMatchLockList mobileMatchLocks = 34;
|
|
|
|
// optional tm.MobileDeviceMatchLockList mobileMatchLocks = 34;
|
|
|
|
// optional .ElimWinsToAdvanceList elimWinsToAdvanceList = 35;
|
|
|
|
// optional tm.ElimWinsToAdvanceList elimWinsToAdvanceList = 35;
|
|
|
|
// optional string temporaryCode = 36;
|
|
|
|
// optional string temporaryCode = 36;
|
|
|
|
// optional .MatchScoreList matchScoreLog = 37;
|
|
|
|
// optional tm.MatchScoreList matchScoreLog = 37;
|
|
|
|
// optional .PublishStatus publishStatus = 38;
|
|
|
|
// optional tm.PublishStatus publishStatus = 38;
|
|
|
|
// optional .MatchInfo matchInfo = 39;
|
|
|
|
// optional tm.MatchInfo matchInfo = 39;
|
|
|
|
// optional .AwardList awardList = 40;
|
|
|
|
// optional tm.AwardList awardList = 40;
|
|
|
|
// optional string eventName = 41;
|
|
|
|
// optional string eventName = 41;
|
|
|
|
// optional .FieldControlStatus fieldControlStatus = 42;
|
|
|
|
// optional tm.FieldControlStatus fieldControlStatus = 42;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
//
|
|
|
|
use prost::Message;
|
|
|
|
// MQTT Topics:
|
|
|
|
use std::io::Cursor;
|
|
|
|
// - 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 {
|
|
|
|
pub mod tm_proto {
|
|
|
|
include!(concat!(env!("OUT_DIR"), "/tm.rs"));
|
|
|
|
include!(concat!(env!("OUT_DIR"), "/tm.rs"));
|
|
|
@ -74,9 +83,133 @@ pub fn deserialize_notice(buf: &[u8]) -> Result<tm_proto::Notice, prost::DecodeE
|
|
|
|
tm_proto::Notice::decode(&mut Cursor::new(buf))
|
|
|
|
tm_proto::Notice::decode(&mut Cursor::new(buf))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
|
|
|
|
|
|
struct DivisionInfo {
|
|
|
|
|
|
|
|
arena: String,
|
|
|
|
|
|
|
|
game_id: String,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
|
|
|
|
|
|
struct DivisionRankingInfo {
|
|
|
|
|
|
|
|
rankings: Vec<String>,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[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<ElevationTier>; 2],
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
|
|
|
|
|
|
struct GameScore {
|
|
|
|
|
|
|
|
autonomous_winner: Option<GameSide>,
|
|
|
|
|
|
|
|
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<GameState>,
|
|
|
|
|
|
|
|
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() {
|
|
|
|
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
|
|
|
|
// 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));
|
|
|
|
mqttoptions.set_keep_alive(Duration::from_secs(5));
|
|
|
|
|
|
|
|
|
|
|
|
// Create a new client(10 is bounded channel capacity?)
|
|
|
|
// Create a new client(10 is bounded channel capacity?)
|
|
|
|