forked from paul/sinoptik
Add the Buienradar provider
This commit is contained in:
parent
d432bb4cd6
commit
6279d379ab
|
@ -206,6 +206,28 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chrono-tz"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58549f1842da3080ce63002102d5bc954c7bc843d4f47818e642abdc36253552"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"chrono-tz-build",
|
||||
"phf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chrono-tz-build"
|
||||
version = "0.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db058d493fb2f65f41861bfed7e3fe6335264a9f0f92710cab5bdf01fef09069"
|
||||
dependencies = [
|
||||
"parse-zoneinfo",
|
||||
"phf",
|
||||
"phf_codegen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "color-eyre"
|
||||
version = "0.5.11"
|
||||
|
@ -1355,6 +1377,15 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parse-zoneinfo"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41"
|
||||
dependencies = [
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pear"
|
||||
version = "0.2.3"
|
||||
|
@ -1384,6 +1415,45 @@ version = "2.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_codegen"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
"uncased",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.0.10"
|
||||
|
@ -1939,6 +2009,7 @@ name = "sinoptik"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"chrono-tz",
|
||||
"color-eyre",
|
||||
"geocoding",
|
||||
"image",
|
||||
|
@ -1946,6 +2017,12 @@ dependencies = [
|
|||
"rocket",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a86232ab60fa71287d7f2ddae4a7073f6b7aac33631c3015abb556f08c6d0a3e"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.5"
|
||||
|
|
|
@ -5,6 +5,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
chrono = "0.4.19"
|
||||
chrono-tz = "0.6.1"
|
||||
color-eyre = "0.5.6"
|
||||
geocoding = "0.3.1"
|
||||
image = "0.24.0"
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
//!
|
||||
//! Data is either provided via a direct (JSON) API or via looking up values on maps.
|
||||
|
||||
pub(crate) mod buienradar;
|
||||
pub(crate) mod luchtmeetnet;
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
//! The Buienradar data provider.
|
||||
//!
|
||||
//! For more information about Buienradar, see: <https://www.buienradar.nl/overbuienradar/contact>
|
||||
//! and <https://www.buienradar.nl/overbuienradar/gratis-weerdata>
|
||||
|
||||
use chrono::offset::TimeZone;
|
||||
use chrono::serde::ts_seconds;
|
||||
use chrono::{DateTime, Local, NaiveDate, NaiveTime, Utc};
|
||||
use chrono_tz::Europe;
|
||||
use reqwest::Url;
|
||||
use rocket::serde::Serialize;
|
||||
|
||||
use crate::Metric;
|
||||
|
||||
/// The base URL for the Buienradar API.
|
||||
const BUIENRADAR_BASE_URL: &str = "https://gpsgadget.buienradar.nl/data/raintext";
|
||||
|
||||
/// The Buienradar API precipitation data item.
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub(crate) struct Item {
|
||||
/// The time(stamp) of the forecast.
|
||||
#[serde(serialize_with = "ts_seconds::serialize")]
|
||||
time: DateTime<Utc>,
|
||||
|
||||
/// The forecasted value.
|
||||
///
|
||||
/// The unit is FIXME?
|
||||
value: f32,
|
||||
}
|
||||
|
||||
/// Parses a line of the Buienradar precipitation text interface into an item.
|
||||
///
|
||||
// Each line has the format: `val|HH:MM`, for example: `362|12:30`.
|
||||
fn parse_item(line: &str, today: &NaiveDate) -> Option<Item> {
|
||||
line.split_once('|')
|
||||
.map(|(v, t)| {
|
||||
let time = parse_time(t, today)?;
|
||||
let value = parse_value(v)?;
|
||||
|
||||
Some(Item { time, value })
|
||||
})
|
||||
.flatten()
|
||||
}
|
||||
|
||||
/// Parses a time string to date/time in the UTC time zone.
|
||||
///
|
||||
/// The provided time has the format `HH:MM` and is considered to be in the Europe/Amsterdam
|
||||
/// time zone.
|
||||
///
|
||||
/// Returns [`None`] if the time cannot be parsed.
|
||||
fn parse_time(t: &str, today: &NaiveDate) -> Option<DateTime<Utc>> {
|
||||
// First, get the naive date/time.
|
||||
let ntime = NaiveTime::parse_from_str(t, "%H:%M").ok()?;
|
||||
let ndtime = today.and_time(ntime);
|
||||
// Then, interpret the naive date/time in the Europe/Amsterdam time zone and convert it to the
|
||||
// UTC time zone.
|
||||
let ldtime = Europe::Amsterdam.from_local_datetime(&ndtime).unwrap();
|
||||
let dtime = ldtime.with_timezone(&Utc);
|
||||
|
||||
Some(dtime)
|
||||
}
|
||||
|
||||
/// Parses a precipitation value into an intensity value in mm/h.
|
||||
///
|
||||
/// For the conversion formula, see: <https://www.buienradar.nl/overbuienradar/gratis-weerdata>.
|
||||
///
|
||||
/// Returns [`None`] if the value cannot be parsed.
|
||||
fn parse_value(v: &str) -> Option<f32> {
|
||||
let value = v.parse::<f32>().ok()?;
|
||||
let base: f32 = 10.0;
|
||||
let value = base.powf((value - 109.0) / 32.0);
|
||||
let value = (value * 10.0).round() / 10.0;
|
||||
|
||||
Some(value)
|
||||
}
|
||||
|
||||
/// Retrieves the Buienradar forecasted precipitation items for the provided position.
|
||||
///
|
||||
/// It only supports the following metric:
|
||||
/// * [`Metric::Precipitation`]
|
||||
///
|
||||
/// Returns [`None`] if retrieval or deserialization fails, or if the metric is not supported by
|
||||
/// this provider.
|
||||
pub(crate) async fn get(lat: f64, lon: f64, metric: Metric) -> Option<Vec<Item>> {
|
||||
if metric != Metric::Precipitation {
|
||||
return None;
|
||||
}
|
||||
let mut url = Url::parse(BUIENRADAR_BASE_URL).unwrap();
|
||||
url.query_pairs_mut()
|
||||
.append_pair("lat", &format!("{:.02}", lat))
|
||||
.append_pair("lon", &format!("{:.02}", lon));
|
||||
|
||||
println!("▶️ Retrieving Buienradar data from {url}");
|
||||
let response = reqwest::get(url).await.ok()?;
|
||||
let output = match response.error_for_status() {
|
||||
Ok(res) => res.text().await.ok()?,
|
||||
Err(_err) => return None,
|
||||
};
|
||||
let today = Local::today().naive_utc();
|
||||
|
||||
output
|
||||
.lines()
|
||||
.map(|line| parse_item(line, &today))
|
||||
.collect()
|
||||
}
|
Loading…
Reference in New Issue