Mercurial > core / rust/lib/tenex/models/nws/lib.rs
changeset 698: |
96958d3eb5b0 |
parent: |
3d78bed56188
|
author: |
Richard Westhaver <ellis@rwest.io> |
date: |
Fri, 04 Oct 2024 22:04:59 -0400 |
permissions: |
-rw-r--r-- |
description: |
fixes |
1 use chrono::{DateTime, Local}; 3 use reqwest::{Client, Error}; 4 use serde::{Deserialize, Serialize}; 7 /// Geo-coordinate Point object type 8 #[derive(Serialize, Deserialize, Debug, Default, PartialEq)] 15 /// Create a new Point from (f32, f32) 16 pub fn new(lat: f32, lng: f32) -> Self { 22 /// Used to parse City metadata from datasets acquired on the internet 23 #[derive(Deserialize, Serialize, Debug)] 32 /// Convert a City to Point. 34 /// Returns Ok(Point) on success. Note that only f32 values are 35 /// accepted (0. 1. -- not 0 1). 36 pub fn into_point(&self) -> Point { 44 /// Result of a GET /point request 45 #[derive(Serialize, Deserialize, Debug)] 46 pub struct PointInfo { 48 pub properties: PointProps, 51 /// Inner properties object of PointInfo 52 #[derive(Serialize, Deserialize, Debug)] 53 pub struct PointProps { 54 #[serde(rename(deserialize = "forecastOffice"))] 55 pub forecast_office: String, 57 #[serde(rename(deserialize = "forecastHourly"))] 58 pub forecast_hourly: String, 59 #[serde(rename(deserialize = "forecastGridData"))] 60 pub forecast_grid_data: String, 61 #[serde(rename(deserialize = "observationStations"))] 62 pub observation_stations: String, 63 #[serde(rename(deserialize = "relativeLocation"))] 64 pub relative_location: RelativeLocation, 65 #[serde(rename(deserialize = "forecastZone"))] 66 pub forecast_zone: String, 68 #[serde(rename(deserialize = "fireWeatherZone"))] 69 pub fire_weather_zone: String, 70 #[serde(rename(deserialize = "timeZone"))] 71 pub time_zone: String, 72 #[serde(rename(deserialize = "radarStation"))] 73 pub radar_station: String, 76 /// inner relative_location object of PointProps 77 #[derive(Debug, Serialize, Deserialize)] 78 pub struct RelativeLocation { 80 pub properties: RelativeProps, 83 /// inner properties object of RelativeLocation 84 #[derive(Debug, Serialize, Deserialize)] 85 pub struct RelativeProps { 92 /// Result of GET /forecast 93 #[derive(Debug, Serialize, Deserialize)] 95 pub properties: ForecastProps, 98 /// Inner properties object of Forecast 99 #[derive(Debug, Serialize, Deserialize)] 100 pub struct ForecastProps { 101 pub updated: DateTime<Local>, 103 #[serde(rename(deserialize = "generatedAt"))] 104 pub generated_at: DateTime<Local>, 105 pub elevation: Value, 106 pub periods: Vec<ForecastPeriod>, 109 /// Single instance of item in periods object of ForecastProps 110 #[derive(Debug, Serialize, Deserialize)] 111 pub struct ForecastPeriod { 114 #[serde(rename(deserialize = "startTime"))] 115 pub start_time: DateTime<Local>, 116 #[serde(rename(deserialize = "endTime"))] 117 pub end_time: DateTime<Local>, 118 #[serde(rename(deserialize = "isDaytime"))] 119 pub is_day_time: bool, 121 #[serde(rename(deserialize = "temperatureUnit"))] 122 pub temperature_unit: String, 123 #[serde(rename(deserialize = "windSpeed"))] 124 pub wind_speed: Option<String>, 125 #[serde(rename(deserialize = "windDirection"))] 126 pub wind_direction: Option<String>, 128 #[serde(rename(deserialize = "shortForecast"))] 129 pub short_forecast: String, 130 #[serde(rename(deserialize = "detailedForecast"))] 131 pub detailed_forecast: String, 134 /// Forecast output representation 135 #[derive(Debug, Serialize, Deserialize)] 136 pub struct ForecastBundle { 137 pub start: DateTime<Local>, 138 pub end: DateTime<Local>, 140 pub wind_speed: String, // TODO parse from string to int "30 mph" -> 30 141 pub wind_direction: String, 142 pub short_forecast: String, 145 /// WeatherForecast output representation tied to a specific City. 147 /// This struct is passed directly into an embedded Database 148 #[derive(Debug, Serialize, Deserialize)] 149 pub struct WeatherBundle { 151 pub forecast: Vec<ForecastBundle>, 152 pub updated: DateTime<Local>, 156 /// Create a new WeatherBundle from a City and Forecast 157 pub fn new(loc: City, fcb: Forecast) -> Self { 158 let mut vec = Vec::new(); 159 for i in fcb.properties.periods.iter() { 160 let i = ForecastBundle { 163 temperature: i.temperature, 164 wind_speed: i.wind_speed.as_ref().unwrap().to_string(), 165 wind_direction: i.wind_direction.as_ref().unwrap().to_string(), 166 short_forecast: i.short_forecast.to_string(), 173 updated: fcb.properties.updated, 178 pub async fn get_point( 181 ) -> Result<PointInfo, Error> { 182 let mut url: String = String::from("http://api.weather.gov/"); 183 for i in &["points/", &pnt.lat.to_string(), ",", &pnt.lng.to_string()] { 186 let response = client.get(&url).send().await?; 187 let body = response.text().await?; 189 let res: PointInfo = serde_json::from_str(&body).unwrap(); 193 pub async fn get_forecast( 196 ) -> Result<Forecast, Error> { 197 let response = client.get(&pnt.properties.forecast).send().await?; 198 let body = response.text().await?; 200 let res: Forecast = serde_json::from_str(&body).unwrap(); 204 pub async fn get_forecast_hourly( 207 ) -> Result<Forecast, Error> { 208 let response = client.get(&pnt.properties.forecast_hourly).send().await?; 209 let body = response.text().await?; 210 let res: Forecast = serde_json::from_str(&body).unwrap(); 214 /// TODO [2021-08-21] - get_alerts 215 pub async fn get_alerts(_state: &str) -> Result<(), Error> { 219 pub async fn weather_report(lat: f32, lng: f32) -> Result<(), Error> { 220 let client = Client::builder().user_agent("thunderman").build()?; 222 let point = Point { lat, lng }; 224 let res = get_point(&point, &client).await?; 225 let resf = get_forecast_hourly(&res, &client).await?; 226 for i in resf.properties.periods[0..10].iter() { 228 "{:#?}-{:#?} = {:#?}°F :: {:#?}", 229 &i.start_time.time(),