Define Data Structures for the OpenWeather API

This commit is contained in:
Felix Suchert 2022-08-06 23:27:35 +02:00
parent 985b42c20b
commit a21a9c57cd
Signed by: feliix42
GPG key ID: 24363525EA0E8A99
3 changed files with 261 additions and 0 deletions

80
Cargo.lock generated
View file

@ -400,6 +400,8 @@ dependencies = [
"embedded-plots",
"linux-embedded-hal",
"profont",
"serde",
"serde_json",
"ssd1675",
"tinybmp",
]
@ -422,6 +424,12 @@ dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
[[package]]
name = "jpeg-decoder"
version = "0.1.22"
@ -635,6 +643,15 @@ dependencies = [
"miniz_oxide 0.3.7",
]
[[package]]
name = "proc-macro2"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [
"unicode-ident",
]
[[package]]
name = "profont"
version = "0.5.0"
@ -644,6 +661,15 @@ dependencies = [
"embedded-graphics",
]
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.6.5"
@ -839,6 +865,12 @@ dependencies = [
"semver 1.0.13",
]
[[package]]
name = "ryu"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
[[package]]
name = "scoped_threadpool"
version = "0.1.9"
@ -896,6 +928,37 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "serde"
version = "1.0.142"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e590c437916fb6b221e1d00df6e3294f3fccd70ca7e92541c475d6ed6ef5fee2"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.142"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34b5b8d809babe02f538c2cfec6f2c1ed10804c0e5a6a041a049a4f5588ccc2e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serial-core"
version = "0.4.0"
@ -953,6 +1016,17 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "syn"
version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "sysfs_gpio"
version = "0.6.1"
@ -992,6 +1066,12 @@ dependencies = [
"nom",
]
[[package]]
name = "unicode-ident"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
[[package]]
name = "vcell"
version = "0.1.3"

View file

@ -15,6 +15,10 @@ profont = "0.5.0"
ssd1675 = { git = "https://github.com/Feliix42/ssd1675" }
#ssd1675 = { path = "../ssd1675" }
# for parsing the weather api data
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
linux-embedded-hal = { version = "0.3.2", optional = true }
embedded-graphics-simulator = { version = "0.3.0", optional = true }

View file

@ -0,0 +1,177 @@
//! Rust data types representing a subset of the weather data returned by the OpenWeather [One
//! Call](https://openweathermap.org/api/one-call-3) API.
//!
//! The response fields are described in detail
//! [here](https://openweathermap.org/api/one-call-3#parameter).
#![allow(dead_code)]
use serde::Deserialize;
/// Response from the OpenWeather API with both current and forecast data for a given location.
#[derive(Deserialize)]
pub struct WeatherData {
/// Latitude
lat: f32,
/// Longitude
lon: f32,
/// Name of the current timezone
timezone: String,
/// Timezone offset from UTC
timezone_offset: i32,
/// Current weather situation
current: CurrentWeather,
/// Minutely wheather information (optional; unused and excluded by API call
#[serde(skip_deserializing)]
minutely: Vec<()>,
/// Weather Information for the coming hours
hourly: Vec<HourlyWeather>,
/// Weather information for the next days _(unused at the moment)_
#[serde(skip_deserializing)]
daily: Vec<()>,
/// Currently active wheather alerts
#[serde(default)]
alerts: Vec<WeatherAlert>
}
/// Current weather data.
#[derive(Deserialize)]
pub struct CurrentWeather {
#[serde(flatten)]
data: CommonWeatherInfo,
/// Sunrise time (Unix Timestamp, UTC)
sunrise: u64,
/// Sunset time (Unix Timestamp, UTC)
sunset: u64,
}
/// Weather Forecast for a specific hour in the future.
#[derive(Deserialize)]
pub struct HourlyWeather {
#[serde(flatten)]
data: CommonWeatherInfo,
/// Probability of precipitation (values range from 0 to 1).
pop: f32
}
/// Common weather information shared among different forecast types.
///
/// This struct is not instantiated by the API but merely introduced by the `Deserializer`.
#[derive(Deserialize)]
pub struct CommonWeatherInfo {
/// Current time (Unix Timestamp, UTC)
dt: u64,
/// Current temperature
temp: f32,
/// Temperature according to human perception
feels_like: f32,
/// Atmospheric Pressure at sea level (hPa)
pressure: u32,
/// Air Humidity in %
humidity: u8,
/// Dew Point (temperature below which water droplets begin to form)
dew_point: f32,
/// Cloudiness in %
clouds: u8,
/// Current UV Index
uvi: f32,
/// Average Visibility in metres (max: 10.000m)
visibility: u16,
/// Wind Speed
wind_speed: f32,
/// Wind Gust (optional)
wind_gust: f32,
/// Wind direction in degrees
wind_deg: u16,
/// Rain
rain: Option<Precipitation>,
/// Snow
snow: Option<Precipitation>,
/// Weather
weather: Vec<WeatherDetails>,
}
#[derive(Deserialize)]
pub struct WeatherAlert {
/// Name of the alert source.
sender_name: String,
/// Name of the Event
event: String,
/// Date and time of the start of the alert (Unix Timestamp, UTC)
start: u64,
/// Date and time of the end of the alert (Unix Timestamp, UTC)
end: u64,
/// Description of the alert (localized).
description: String,
/// Type(s) of severe weather.
tags: Vec<String>,
}
#[derive(Deserialize)]
pub struct Precipitation {
/// Precipitation volume in the last hour in mm
#[serde(rename = "1h")]
hour: u16,
}
#[derive(Deserialize)]
pub struct WeatherDetails {
#[serde(rename = "id")]
condition: WeatherCondition,
main: String,
description: String,
icon: String
}
/// Weather Condition
///
/// This information is deserialized from a unsigned int returned by the Open Weather API according
/// to [this
/// specification](https://openweathermap.org/weather-conditions#Weather-Condition-Codes-2).
/// It ignores the fine details within weather conditions (e.g. heavy thunderstorm and light
/// thunderstorm both map to `Thunderstorm`).
#[derive(Deserialize)] //Debug)]
#[serde(from = "u16")]
pub enum WeatherCondition {
Thunderstorm,
Drizzle,
Rain,
Snow,
Mist,
Smoke,
Haze,
SandDust,
Fog,
Sand,
Dust,
Ash,
Squall,
Tornado,
Clear,
Clouds,
}
impl From<u16> for WeatherCondition {
fn from(value: u16) -> Self {
match value {
200 ..= 299 => Self::Thunderstorm,
300 ..= 399 => Self::Drizzle,
500 ..= 599 => Self::Rain,
600 ..= 699 => Self::Snow,
701 => Self::Mist,
711 => Self::Smoke,
721 => Self::Haze,
731 => Self::SandDust,
741 => Self::Fog,
751 => Self::Sand,
761 => Self::Dust,
762 => Self::Ash,
771 => Self::Squall,
781 => Self::Tornado,
800 => Self::Clear,
801..=804 => Self::Clouds,
// NOTE(feliix42): There's no `Error` mapping or something like that.
_ => Self::Clear,
}
}
}