use crate::error::ManifoldResult; use reqwest::Client; use reqwest::header::CONTENT_TYPE; pub struct Weather { base_url: String, api_key: String, } #[derive(Debug, Deserialize)] pub struct CurrentConditionInformation { pub text: String, pub icon: String, pub code: i64, } #[derive(Debug, Deserialize)] pub struct CurrentWeatherInformation { pub last_updated: String, pub last_updated_epoch: i64, pub temp_c: f64, pub temp_f: f64, pub feelslike_c: f64, pub feelslike_f: f64, pub condition: CurrentConditionInformation, pub wind_mph: f64, pub wind_kph: f64, pub wind_degree: i64, pub wind_dir: String, pub pressure_mb: f64, pub pressure_in: f64, pub precip_mm: f64, pub precip_in: f64, pub humidity: i64, pub cloud: i64, pub is_day: i64, pub uv: f64, pub gust_mph: f64, pub gust_kph: f64, pub dewpoint_c: Option, pub dewpoint_f: Option, } #[derive(Debug, Deserialize)] pub struct ForecastHour { pub time_epoch: i64, pub time: String, pub temp_c: f64, pub temp_f: f64, pub condition: CurrentConditionInformation, pub wind_mph: f64, pub wind_kph: f64, pub wind_degree: i64, pub wind_dir: String, pub pressure_mb: f64, pub pressure_in: f64, pub precip_mm: f64, pub precip_in: f64, pub humidity: i64, pub cloud: i64, pub feelslike_c: f64, pub feelslike_f: f64, pub windchill_c: f64, pub windchill_f: f64, pub heatindex_c: f64, pub heatindex_f: f64, pub dewpoint_c: f64, pub dewpoint_f: f64, pub will_it_rain: i64, pub will_it_snow: i64, pub is_day: i64, pub vis_km: f64, pub vis_miles: f64, pub chance_of_rain: i64, pub chance_of_snow: i64, pub gust_mph: f64, pub gust_kph: f64, } #[derive(Debug, Deserialize)] pub struct DayWeather { pub maxtemp_c: f64, pub maxtemp_f: f64, pub mintemp_c: f64, pub mintemp_f: f64, pub avgtemp_c: f64, pub avgtemp_f: f64, pub maxwind_mph: f64, pub maxwind_kph: f64, pub totalprecip_mm: f64, pub totalprecip_in: f64, pub avgvis_km: f64, pub avgvis_miles: f64, pub avghumidity: f64, pub condition: CurrentConditionInformation, pub uv: f64, } #[derive(Debug, Deserialize)] pub struct DayAstro { pub sunrise: String, pub sunset: String, pub moonrise: String, pub moonset: String, pub moon_phase: String, pub moon_illumination: String } #[derive(Debug, Deserialize)] pub struct ForecastDayWrapper { pub forecastday: Vec } #[derive(Debug, Deserialize)] pub struct ForecastDay { pub date: String, pub date_epoch: i64, pub day: DayWeather, pub astro: DayAstro, pub hour: Vec } #[derive(Debug, Deserialize)] pub struct LocationInformation { pub name: String, pub region: String, pub country: String, pub lat: f64, pub lon: f64, pub tz_id: String, pub localtime_epoch: i64, pub localtime: String, } #[derive(Debug, Deserialize)] pub struct WeatherRequestResponse { pub location: LocationInformation, pub current: CurrentWeatherInformation, } #[derive(Debug, Deserialize)] pub struct WeatherForecastRequestResponse { pub location: LocationInformation, pub current: CurrentWeatherInformation, pub forecast: ForecastDayWrapper, } impl Weather { pub fn new(api_key:String, base_url: String) -> Self { Weather { base_url, api_key, } } pub async fn get_weather_forecast(&self, target: String, days: Option) -> ManifoldResult { let target_url: String; if let Some(d) = days { target_url = format!("{}/forecast.json?key={}&q={}&days={}", self.base_url, self.api_key, &target, d); } else { target_url = format!("{}/forecast.json?key={}&q={}&days=3", self.base_url, self.api_key, &target); } let client = Client::new(); let result = client.get(target_url) .header(CONTENT_TYPE, "application/json") .send() .await? .text() .await?; debug!("{:?}", result); let mut decoded_result: WeatherForecastRequestResponse = serde_json::from_str(&*result)?; let temp = decoded_result.current.temp_c; let humid = decoded_result.current.humidity as f64; decoded_result.current.dewpoint_c = Some(&temp - (14.55 + 0.114 * &temp) * (1.0 - (0.01 * &humid)) - num::pow((2.5 + 0.007 * &temp) * (1.0 - (0.01 * &humid)),3) - (15.9 + 0.117 * &temp) * num::pow(1.0 - (0.01 * &humid), 14)); decoded_result.current.dewpoint_f = Some((decoded_result.current.dewpoint_c.unwrap() * 1.8) + 32.0); debug!("{:?}", decoded_result); Ok(decoded_result) } }