From 345c694ea744270d8496cfa1bf0a9036a19648e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Caruso?= <nicolo.caruso@skywarder.eu> Date: Tue, 22 Apr 2025 09:04:15 +0200 Subject: [PATCH] [fr-api] Added response deserialization Added response deserialization from the flight radar API response. Also added the creation of the ROCKET_STATS_TM and ROCKET_FLIGHT_TM packets to be later send on to track the aircraft. --- on-host/src/fr_api.rs | 206 ++++++++++++++++++++++++++++-------------- 1 file changed, 137 insertions(+), 69 deletions(-) diff --git a/on-host/src/fr_api.rs b/on-host/src/fr_api.rs index f771edd..78a4e99 100644 --- a/on-host/src/fr_api.rs +++ b/on-host/src/fr_api.rs @@ -1,69 +1,137 @@ -use std::time::Duration; - -use reqwest::{header, redirect::Policy}; - -use log::{error, info}; - -pub async fn api_request(flight_nr: String) -> () { - // TODO: Set your token - let token: String = String::from("YOUR API TOKEN"); - - // TODO: remove after changing your API - error!("Just to remind you to change the API token ;)\n"); - - let mut token_str: String = String::from("Bearer "); - token_str.push_str(&token); - - loop { - // Headers for the CURL request, needed from FR-API and can be set - let mut headers = header::HeaderMap::new(); - headers.insert("Accept", "application/json".parse().unwrap()); - headers.insert("Accept-Version", "v1".parse().unwrap()); - headers.insert("Authorization", token_str.parse().unwrap()); - - // Creating a new client - let client = reqwest::Client::builder() - .redirect(Policy::none()) - .build() - .unwrap(); - - // Url for the light-flight telemetry from FR24 - let mut url: String = String::from( - "https://fr24api.flightradar24.com/api/live/flight-positions/light?flights=", - ); - url.push_str(&flight_nr); - info!("URL: {}", url); - - print!("{}", url); - - // Waiting for a response - let response = client.get(url).headers(headers).send().await; - - info!("Got response"); - - // The response - // TODO: For now just printed, then used as telemetry - match response { - Ok(res) => { - info!("Ok"); - - let message = res.text().await; - match message { - Ok(string) => { - print!("{}", string); - info!("Got response {}", string); - } - Err(err) => { - error!("An error occurred in the message {}", err) - } - } - } - Err(err) => { - error!("An error occurred in the message {}", err) - } - } - - // Sleeping since request costs! - std::thread::sleep(Duration::from_millis(10000)); - } -} +use std::time::Duration; + +use reqwest::{header, redirect::Policy}; + +use log::{error, info}; + +use serde::Deserialize; +use skyward_mavlink::lyra::{MavMessage, ROCKET_FLIGHT_TM_DATA, ROCKET_STATS_TM_DATA}; +use crate::packet::TimedMessage; +// The message structure from the FR-API +#[derive(Debug, Deserialize)] +struct Message{ + message: String, + details: String, + data: String +} + +// The sub-message with the information about the aircraft position +#[derive(Debug, Deserialize)] +struct LightTelemetryMessage{ + fr24_id: String, + hex: String, + callsign: String, + lat: f32, + lon: f32, + track: i8, // Heading 0-360 [deg] + alt:f32, + gspeed: i32, // Ground speed in knots + vspeed: i32, // Vertical speed in feet + squawk: String, + timestamp: String, + source: String +} + +pub async fn api_request(flight_nr: String) -> () { + // TODO: Set your token + let token: String = String::from("YOUR API TOKEN"); + + // TODO: remove after changing your API + error!("Just to remind you to change the API token ;)\n"); + + let mut token_str: String = String::from("Bearer "); + token_str.push_str(&token); + + loop { + // Headers for the CURL request, needed from FR-API and can be set + let mut headers = header::HeaderMap::new(); + headers.insert("Accept", "application/json".parse().unwrap()); + headers.insert("Accept-Version", "v1".parse().unwrap()); + headers.insert("Authorization", token_str.parse().unwrap()); + + // Creating a new client + let client = reqwest::Client::builder() + .redirect(Policy::none()) + .build() + .unwrap(); + + // Url for the light-flight telemetry from FR24 + let mut url: String = String::from( + "https://fr24api.flightradar24.com/api/live/flight-positions/light?flights=", + ); + url.push_str(&flight_nr); + info!("URL: {}", url); + + print!("{}", url); + + // Waiting for a response + let response = client.get(url).headers(headers).send().await; + + info!("Got response"); + + // The response + // TODO: For now just printed, then used as telemetry + match response { + Ok(res) => { + info!("Ok"); + + let message = res.text().await; + match message { + Ok(string) => { + print!("{}", string); + info!("Got response {}", string); + let msg_payload : Result<Message, serde_json::Error> = serde_json::from_str(&string); + match msg_payload { + Ok(payload) =>{ + println!("Message received is: {:?}\n", payload); + println!("Singular fields: msg: {:?} dts: {:?} data:{:?}\n", payload.message, payload.details, payload.data); + let flight_data: Result<LightTelemetryMessage, serde_json::Error> = serde_json::from_str(&payload.data); + match flight_data { + Ok(data) =>{ + let mut packets = Vec::new(); + + // Send the current GPS as origin for the NAS + let origin_data = ROCKET_STATS_TM_DATA { + ref_lat: data.lat as f32, + ref_lon: data.lon as f32, + ref_alt: 0 as f32, + ..Default::default() + }; + let mav_msg = MavMessage::ROCKET_STATS_TM(origin_data); + packets.push(TimedMessage::new(0, mav_msg)); + + // Send as NAS the Down from altitude, NE=0 and speed considering the heading + let nas_data = ROCKET_FLIGHT_TM_DATA{ + nas_n: 0 as f32, + nas_e: 0 as f32, + nas_d: -data.alt as f32, + nas_vn: (data.track as f32).cos()*(data.gspeed as f32)/2 as f32, // From heading and knots to m/s + nas_ve: (data.track as f32).sin()*(data.gspeed as f32)/2 as f32, // From heading and knots to m/s + nas_vd: -60.0*(data.vspeed as f32)/3.2808399 as f32, // Converting feet/min to m/s + ..Default::default() + }; + + let mav_msg = MavMessage::ROCKET_FLIGHT_TM(nas_data); + packets.push(TimedMessage::new(0, mav_msg)); + } + Err(err)=>{error!("An error occured deserializing the data{}", err)} + } + } + Err(err) =>{error!("An error occurred deserializing the message {}", err)} + } + + } + Err(err) => { + error!("An error occurred in the message {}", err) + } + } + } + Err(err) => { + error!("An error occurred in the message {}", err) + } + } + + // Sleeping since request costs! + std::thread::sleep(Duration::from_millis(10000)); + } +} -- GitLab