Use URL objects instead of formatted strings
Use `request::Url` for this, so we don't have to depend on the `url` crate ourselves. Also, make the URL constants more uniform.
This commit is contained in:
parent
66abc9c4db
commit
d432bb4cd6
2 changed files with 28 additions and 20 deletions
36
src/maps.rs
36
src/maps.rs
|
@ -7,6 +7,7 @@ use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use chrono::DurationRound;
|
use chrono::DurationRound;
|
||||||
use image::DynamicImage;
|
use image::DynamicImage;
|
||||||
|
use reqwest::Url;
|
||||||
use rocket::tokio::time::{sleep, Duration, Instant};
|
use rocket::tokio::time::{sleep, Duration, Instant};
|
||||||
|
|
||||||
/// A handle to access the in-memory cached maps.
|
/// A handle to access the in-memory cached maps.
|
||||||
|
@ -18,8 +19,8 @@ const REFRESH_INTERVAL: Duration = Duration::from_secs(60);
|
||||||
/// The base URL for retrieving the pollen maps from Buienradar.
|
/// The base URL for retrieving the pollen maps from Buienradar.
|
||||||
const POLLEN_BASE_URL: &str =
|
const POLLEN_BASE_URL: &str =
|
||||||
"https://image.buienradar.nl/2.0/image/sprite/WeatherMapPollenRadarHourlyNL\
|
"https://image.buienradar.nl/2.0/image/sprite/WeatherMapPollenRadarHourlyNL\
|
||||||
?height=988&width=820&extension=png&renderBackground=False&renderBranding=False\
|
?width=820&height=988&extension=png&renderBackground=False&renderBranding=False\
|
||||||
&renderText=False&history=0&forecast=24&skip=0×tamp=";
|
&renderText=False&history=0&forecast=24&skip=0";
|
||||||
|
|
||||||
/// The interval for retrieving pollen maps.
|
/// The interval for retrieving pollen maps.
|
||||||
const POLLEN_INTERVAL: Duration = Duration::from_secs(600);
|
const POLLEN_INTERVAL: Duration = Duration::from_secs(600);
|
||||||
|
@ -33,8 +34,8 @@ const PRECIPITATION_INTERVAL: Duration = Duration::from_secs(300);
|
||||||
|
|
||||||
/// The base URL for retrieving the UV index maps from Buienradar.
|
/// The base URL for retrieving the UV index maps from Buienradar.
|
||||||
const UVI_BASE_URL: &str = "https://image.buienradar.nl/2.0/image/sprite/WeatherMapUVIndexNL\
|
const UVI_BASE_URL: &str = "https://image.buienradar.nl/2.0/image/sprite/WeatherMapUVIndexNL\
|
||||||
?extension=png&width=820&height=988&renderText=False&renderBranding=False\
|
?width=820&height=988extension=png&&renderBackground=False&renderBranding=False\
|
||||||
&renderBackground=False&history=0&forecast=5&skip=0×tamp=";
|
&renderText=False&history=0&forecast=5&skip=0";
|
||||||
|
|
||||||
/// The interval for retrieving UV index maps.
|
/// The interval for retrieving UV index maps.
|
||||||
const UVI_INTERVAL: Duration = Duration::from_secs(3600);
|
const UVI_INTERVAL: Duration = Duration::from_secs(3600);
|
||||||
|
@ -144,7 +145,7 @@ impl MapsRefresh for MapsHandle {
|
||||||
///
|
///
|
||||||
/// This returns [`None`] if it fails in either performing the request, retrieving the bytes from
|
/// This returns [`None`] if it fails in either performing the request, retrieving the bytes from
|
||||||
/// the image or loading and the decoding the data into [`DynamicImage`].
|
/// the image or loading and the decoding the data into [`DynamicImage`].
|
||||||
async fn retrieve_image(url: &str) -> Option<DynamicImage> {
|
async fn retrieve_image(url: Url) -> Option<DynamicImage> {
|
||||||
// TODO: Handle or log errors!
|
// TODO: Handle or log errors!
|
||||||
let response = reqwest::get(url).await.ok()?;
|
let response = reqwest::get(url).await.ok()?;
|
||||||
let bytes = response.bytes().await.ok()?;
|
let bytes = response.bytes().await.ok()?;
|
||||||
|
@ -156,11 +157,12 @@ async fn retrieve_image(url: &str) -> Option<DynamicImage> {
|
||||||
///
|
///
|
||||||
/// See [`POLLEN_BASE_URL`] for the base URL and [`retrieve_image`] for the retrieval function.
|
/// See [`POLLEN_BASE_URL`] for the base URL and [`retrieve_image`] for the retrieval function.
|
||||||
async fn retrieve_pollen_maps() -> Option<DynamicImage> {
|
async fn retrieve_pollen_maps() -> Option<DynamicImage> {
|
||||||
let timestamp = chrono::Local::now().format("%y%m%d%H%M");
|
let timestamp = format!("{}", chrono::Local::now().format("%y%m%d%H%M"));
|
||||||
let url = format!("{POLLEN_BASE_URL}{timestamp}");
|
let mut url = Url::parse(POLLEN_BASE_URL).unwrap();
|
||||||
|
url.query_pairs_mut().append_pair("timestamp", ×tamp);
|
||||||
|
|
||||||
println!("🔽 Refreshing pollen maps from: {}", url);
|
println!("🔽 Refreshing pollen maps from: {}", url);
|
||||||
retrieve_image(&url).await
|
retrieve_image(url).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the pollen maps from Weerplaza.
|
/// Retrieves the pollen maps from Weerplaza.
|
||||||
|
@ -172,14 +174,17 @@ async fn retrieve_precipitation_maps() -> [Option<DynamicImage>; 24] {
|
||||||
// This only fails if timestamps and durations exceed limits!
|
// This only fails if timestamps and durations exceed limits!
|
||||||
.duration_trunc(chrono::Duration::minutes(5))
|
.duration_trunc(chrono::Duration::minutes(5))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let timestamp = just_before.format("%Y%m%d%H%M");
|
let timestamp_prefix = just_before.format("%Y%m%d%H%M");
|
||||||
|
let base_url = Url::parse(PRECIPITATION_BASE_URL).unwrap();
|
||||||
|
|
||||||
let mut precipitation: [Option<DynamicImage>; 24] = Default::default();
|
let mut precipitation: [Option<DynamicImage>; 24] = Default::default();
|
||||||
for (index, map) in precipitation.iter_mut().enumerate() {
|
for (index, map) in precipitation.iter_mut().enumerate() {
|
||||||
let suffix = format!("{:03}", index * 5);
|
let timestamp = format!("{timestamp_prefix}_{:03}", index * 5);
|
||||||
let url = format!("{PRECIPITATION_BASE_URL}/{timestamp}_{suffix}");
|
let mut url = base_url.clone();
|
||||||
|
url.path_segments_mut().unwrap().push(×tamp);
|
||||||
|
|
||||||
println!("🔽 Refreshing precipitation map from: {}", url);
|
println!("🔽 Refreshing precipitation map from: {}", url);
|
||||||
*map = retrieve_image(&url).await;
|
*map = retrieve_image(url).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
precipitation
|
precipitation
|
||||||
|
@ -189,11 +194,12 @@ async fn retrieve_precipitation_maps() -> [Option<DynamicImage>; 24] {
|
||||||
///
|
///
|
||||||
/// See [`UVI_BASE_URL`] for the base URL and [`retrieve_image`] for the retrieval function.
|
/// See [`UVI_BASE_URL`] for the base URL and [`retrieve_image`] for the retrieval function.
|
||||||
async fn retrieve_uvi_maps() -> Option<DynamicImage> {
|
async fn retrieve_uvi_maps() -> Option<DynamicImage> {
|
||||||
let timestamp = chrono::Local::now().format("%y%m%d%H%M");
|
let timestamp = format!("{}", chrono::Local::now().format("%y%m%d%H%M"));
|
||||||
let url = format!("{UVI_BASE_URL}{timestamp}");
|
let mut url = Url::parse(UVI_BASE_URL).unwrap();
|
||||||
|
url.query_pairs_mut().append_pair("timestamp", ×tamp);
|
||||||
|
|
||||||
println!("🔽 Refreshing UV index maps from: {}", url);
|
println!("🔽 Refreshing UV index maps from: {}", url);
|
||||||
retrieve_image(&url).await
|
retrieve_image(url).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs a loop that keeps refreshing the maps when necessary.
|
/// Runs a loop that keeps refreshing the maps when necessary.
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use chrono::serde::ts_seconds;
|
use chrono::serde::ts_seconds;
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
|
use reqwest::Url;
|
||||||
use rocket::serde::{Deserialize, Serialize};
|
use rocket::serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::Metric;
|
use crate::Metric;
|
||||||
|
@ -48,13 +49,14 @@ pub(crate) async fn get(lat: f64, lon: f64, metric: Metric) -> Option<Vec<Item>>
|
||||||
Metric::PM10 => "pm10",
|
Metric::PM10 => "pm10",
|
||||||
_ => return None, // Unsupported metric
|
_ => return None, // Unsupported metric
|
||||||
};
|
};
|
||||||
let url = format!(
|
let mut url = Url::parse(LUCHTMEETNET_BASE_URL).unwrap();
|
||||||
"{LUCHTMEETNET_BASE_URL}?formula={formula}&latitude={:.05}&longitude={:.05}",
|
url.query_pairs_mut()
|
||||||
lat, lon
|
.append_pair("formula", formula)
|
||||||
);
|
.append_pair("latitude", &format!("{:.05}", lat))
|
||||||
|
.append_pair("longitude", &format!("{:.05}", lon));
|
||||||
|
|
||||||
println!("▶️ Retrieving Luchtmeetnet data from {url}");
|
println!("▶️ Retrieving Luchtmeetnet data from {url}");
|
||||||
let response = reqwest::get(&url).await.ok()?;
|
let response = reqwest::get(url).await.ok()?;
|
||||||
let root: Container = match response.error_for_status() {
|
let root: Container = match response.error_for_status() {
|
||||||
Ok(res) => res.json().await.ok()?,
|
Ok(res) => res.json().await.ok()?,
|
||||||
Err(_err) => return None,
|
Err(_err) => return None,
|
||||||
|
|
Loading…
Reference in a new issue