Skip to content

Commit

Permalink
Only check map updates for NAC not for RCC, fixed bug for russia map …
Browse files Browse the repository at this point in the history
…updates
  • Loading branch information
zeld committed Sep 24, 2022
1 parent 58cc552 commit 1284163
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/interact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fn select(message: &str, items: &[&str]) -> Result<Option<usize>, Error> {

pub fn select_map() -> Result<Option<&'static str>, Error> {
let items: Vec<&str> = psa::MAPS.iter().map(|m| m.get_name()).collect();
let map_code = select("Check for a map update (NAC only, hit ESC to skip)", &items)?
let map_code = select("Check for a map update (hit ESC to skip)", &items)?
.map(|index| psa::MAPS[index].get_code());
Ok(map_code)
}
Expand Down
17 changes: 10 additions & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,14 @@ async fn main() -> Result<(), Error> {
}
let vin = vin.unwrap();

// Maps not provided on command line, asking interactively
let map = if !vin_provided_as_arg && map.is_none() && interactive {
let client = Client::builder()
.build()
.with_context(|| format!("Failed to create HTTP client"))?;
let device_info = psa::request_device_information(&client, &vin).await?;
let is_nac: bool = device_info.devices.map(|l| l.iter().any(|d| d.ecu_type.contains("NAC"))) == Some(true);

// Maps not provided on command line, asking interactively for NAC
let map = if map.is_none() && is_nac && interactive {
interact::select_map()?
} else {
map
Expand All @@ -79,10 +85,6 @@ async fn main() -> Result<(), Error> {
let extract_location = matches.value_of("extract");

// TODO investigate compression such as gzip for faster download
let client = Client::builder()
.build()
.with_context(|| format!("Failed to create HTTP client"))?;

let update_response = psa::request_available_updates(&client, &vin, map).await?;

if update_response.software.is_none() {
Expand All @@ -95,7 +97,7 @@ async fn main() -> Result<(), Error> {

for software in update_response.software.unwrap() {
for update in &software.update {
// A empty update can be sent by the server when there are no available update
// An empty update can be sent by the server when there is no available update
if !update.update_id.is_empty() {
psa::print(&software, update);
if !interactive || interact::confirm("Download update?")? {
Expand All @@ -114,6 +116,7 @@ async fn main() -> Result<(), Error> {
}

if selected_updates.is_empty() {
println!("No update available");
return Ok(());
}

Expand Down
58 changes: 57 additions & 1 deletion src/psa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ use tar::Archive;

use crate::download;

// URL to query vehicle device: NAC or RCC
const DEVICE_URL: &str = "https://api.groupe-psa.com/applications/majesticf/v1/devices/{VIN}?client_id=20a4cf7c-f5fb-41d5-9175-a6e23b9880e5";

// URL to query for firmware/map updates. The client_id below was extracted from the official Peugeot Update software
const UPDATE_URL: &str = "https://api.groupe-psa.com/applications/majesticf/v1/getAvailableUpdate?client_id=20a4cf7c-f5fb-41d5-9175-a6e23b9880e5";

Expand Down Expand Up @@ -73,7 +76,7 @@ pub const MAPS: &[Map] = &[
name: "Oceania",
},
Map {
code: "russa",
code: "russia",
name: "Russia",
},
Map {
Expand All @@ -82,6 +85,23 @@ pub const MAPS: &[Map] = &[
},
];

/*
Sample device response: {"vin":"xxx","requestDate":"2022-09-24T14:05:03+0200","devices":[{"ecuType":"NAC_EUR_WAVE2"}]}
*/
#[derive(Debug, Serialize, Deserialize)]
pub struct DeviceResponse {
pub vin: String,
#[serde(rename = "requestDate")]
pub request_date: Option<String>,
pub devices: Option<Vec<Device>>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Device {
#[serde(rename = "ecuType")]
pub ecu_type: String,
}

/*
Sample response:
{
Expand Down Expand Up @@ -200,6 +220,42 @@ pub fn print(software: &Software, update: &SoftwareUpdate) {
}
}

pub async fn request_device_information(
client: &reqwest::Client,
vin: &str
) -> Result<DeviceResponse, Error> {
let request = client
.get(DEVICE_URL.replace("{VIN}", vin))
.header("Content-type", "application/json")
.build()
.with_context(|| format!("Failed to build update request"))?;

debug!("Sending request {:?}", request);
let response = client.execute(request).await?;
if response.status() == 400 {
return Err(anyhow!(
"Failed to retrieve device information, make sure the VIN {} is correct.",
vin
))
}
if response.status() == 404 {
return Err(anyhow!(
"Device not found, make sure the VIN {} is correct.",
vin
))
}

debug!("Received response {:?}", response);

let response_text = response.text().await?;
debug!("Received response body {}", response_text);

let device_response: DeviceResponse = serde_json::from_str(&response_text)
.with_context(|| format!("Failed to parse device information"))?;

Ok(device_response)
}

pub async fn request_available_updates(
client: &reqwest::Client,
vin: &str,
Expand Down

0 comments on commit 1284163

Please sign in to comment.