rhasspy-skill-server/src/weather.rs

95 lines
2.7 KiB
Rust

use reqwest::{Client, Response, Url};
use serde::Deserialize;
use std::error::Error;
use crate::Context;
const LATITUDE: &'static str = "51.43";
const LONGITUDE: &'static str = "5.47";
#[derive(Debug, Deserialize)]
struct Current {
weather: Vec<Weather>,
main: Main,
}
#[derive(Debug, Deserialize)]
struct Weather {
description: String,
}
#[derive(Debug, Deserialize)]
struct Main {
temp: f32,
feels_like: f32,
}
#[derive(Debug, Deserialize)]
struct OneCall {
daily: Vec<Daily>,
}
#[derive(Debug, Deserialize)]
struct Daily {
temp: Temp,
weather: Vec<Weather>,
pop: f32,
}
#[derive(Debug, Deserialize)]
struct Temp {
day: f32,
}
async fn request(context: &Context, url: &str) -> reqwest::Result<Response> {
let client = Client::new();
let mut url = Url::parse(url).unwrap();
url.query_pairs_mut()
.append_pair("appid", &context.openweather_api_key)
.append_pair("lat", LATITUDE)
.append_pair("lon", LONGITUDE)
.append_pair("units", "metric")
.append_pair("lang", "nl");
client.get(url).send().await
}
pub async fn get_weather(context: &Context) -> Result<String, Box<dyn Error + 'static>> {
let url = "https://api.openweathermap.org/data/2.5/weather";
let resp = request(&context, &url).await?;
let cur_weather: Current = resp.json().await?;
let description = cur_weather.weather.first().unwrap().description.clone();
let temperature = cur_weather.main.temp.round() as u32;
let temperature_feel = cur_weather.main.feels_like.round() as u32;
let weather = format!(
"Het weer in Eindhoven is op het moment {description} en het is {temperature} graden \
buiten en dat voelt als {temperature_feel} graden",
description = description,
temperature = temperature,
temperature_feel = temperature_feel,
);
Ok(weather)
}
pub async fn get_forecast(context: &Context) -> Result<String, Box<dyn Error + 'static>> {
let url = "https://api.openweathermap.org/data/2.5/onecall";
let resp = request(&context, &url).await?;
let weather_forecast: OneCall = resp.json().await?;
let today = weather_forecast.daily.first().unwrap();
let description = today.weather.first().unwrap().description.clone();
let temperature_day = today.temp.day.round() as u32;
let rain_pct = (today.pop * 100.0).round() as u8;
let forecast = format!(
"De weersverwachting van vandaag voor Eindhoven is {description} met een \
middagtemperatuur van {temperature_day} graden en {rain_pct} procent kans op regen",
description = description,
temperature_day = temperature_day,
rain_pct = rain_pct,
);
Ok(forecast)
}