gotransit support

This commit is contained in:
Evan Pratten 2022-12-19 17:37:58 -05:00
parent 09f78647d5
commit 5763f5f705
8 changed files with 124 additions and 21 deletions

1
.gitignore vendored
View File

@ -16,3 +16,4 @@ Cargo.lock
/target
#Cargo.lock
/test.xml

20
.vscode/tasks.json vendored
View File

@ -20,9 +20,25 @@
"args": [
"--",
"-c",
"VA3UJF-1",
"TRAINS",
"-p",
"23728"
"10410"
]
},
{
"type": "cargo",
"command": "run",
"problemMatcher": [
"$rustc"
],
"label": "rust: cargo run (dry run)",
"args": [
"--",
"-c",
"N0CALL",
"-p",
"12345",
"--dry-run"
]
}
]

View File

@ -17,6 +17,7 @@ reqwest = { version = "^0.11.13", features = ["json"] }
serde = { version = "^1.0.126", features = ["derive"] }
tokio = { version = "^1.23.0", features = ["macros", "rt-multi-thread"] }
clap = { version = "^4.0.29", features = ["derive"] }
# chrono = "^0.4.23"
aprs-encode = "^0.1.2"
arrayvec = "^0.7"
serde-xml-rs = "^0.6.0"
regex = "^1.7.0"

View File

@ -11,4 +11,8 @@ pub struct Args {
/// The password to use for the callsign
#[clap(short, long)]
pub password: String,
/// Do a dry run (no publishing)
#[clap(short, long)]
pub dry_run: bool,
}

View File

@ -32,6 +32,7 @@ pub async fn main() {
println!("{}", packet);
// Push the packet to the server
if !args.dry_run {
let response = client
.post("http://rotate.aprs.net:8080/")
.header("Accept-Type", "text/plain")
@ -55,4 +56,5 @@ pub async fn main() {
}
}
}
}
}

75
src/sources/gotransit.rs Normal file
View File

@ -0,0 +1,75 @@
//! Data source: http://gotracker.ca/gotracker/web/
use regex::Regex;
use crate::train::TrainInfo;
const CORRIDOR_IDS: [u8; 7] = [
65, // Barrie
31, // Kitchener
09, // Lakeshore East
01, // Lakeshore West
21, // Milton
61, // Richmond Hill
71, // Stouffville
];
#[derive(Debug, serde::Deserialize)]
struct InServiceTripPublic {
#[serde(rename = "EquipmentCode")]
equipment_code: String,
#[serde(rename = "Latitude")]
latitude: f32,
#[serde(rename = "Longitude")]
longitude: f32,
#[serde(rename = "StartStation")]
start_station: String,
#[serde(rename = "EndStation")]
end_station: String,
#[serde(rename = "TripNumber")]
trip_number: String,
#[serde(rename = "TripName")]
trip_name: String,
#[serde(rename = "CorridorCode")]
corridor_code: String,
}
/// Get all trains from GO Transit
pub async fn get_trains() -> Result<Vec<TrainInfo>, reqwest::Error> {
// Allocate output
let mut output = Vec::new();
// Handle each corridor
for corridor_id in CORRIDOR_IDS.iter() {
// Make a request to the gotracker API
println!("Requesting data for GO transit corridor {}", corridor_id);
let response = reqwest::get(&format!("http://gotracker.ca/GOTracker/web/GODataAPIProxy.svc/TripLocation/Service/Lang/{:02}/en", corridor_id)).await?;
let response_text = response.text().await?;
// Get only the data portion
if let Some(data_xml) = Regex::new(r"<Data>(.*)</Data>")
.unwrap()
.captures(&response_text)
{
let data_xml = data_xml.get(1).unwrap().as_str();
// Convert to something workable
let parsed_data: Vec<InServiceTripPublic> = serde_xml_rs::from_str(data_xml).unwrap();
// Convert to TrainInfo format
for train in parsed_data {
output.push(TrainInfo {
identifier: format!("GO-{}{}", train.corridor_code, train.equipment_code),
speed: 0.0,
latitude: train.latitude,
longitude: train.longitude,
course: None,
status: format!("{} to {}", train.start_station, train.end_station),
});
}
}
}
// Return output
Ok(output)
}

View File

@ -1,6 +1,7 @@
use crate::train::TrainInfo;
mod viarail;
mod gotransit;
pub async fn get_trains() -> Result<Vec<TrainInfo>, reqwest::Error> {
// Build output
@ -8,6 +9,7 @@ pub async fn get_trains() -> Result<Vec<TrainInfo>, reqwest::Error> {
// Collect data
output.extend(viarail::get_trains().await?);
output.extend(gotransit::get_trains().await?);
// Return output
Ok(output)

View File

@ -1,3 +1,5 @@
//! Data source: https://tsimobile.viarail.ca
use std::collections::HashMap;
use crate::train::TrainInfo;