75 lines
2.6 KiB
Rust
75 lines
2.6 KiB
Rust
use std::{sync::Arc, time::Duration};
|
|
|
|
use common::{Endpoint, Inbox, WeatherMsg, WeatherPayload, WeatherResponse, Wire};
|
|
use iced::{
|
|
futures::{channel::mpsc, SinkExt},
|
|
Subscription,
|
|
};
|
|
use tokio::time::interval;
|
|
|
|
pub const NAMESPACE: &str = "weather.";
|
|
|
|
const FORECAST_URL: &str = "https://api.open-meteo.com/v1/forecast\
|
|
?latitude=51.3714&longitude=-0.2302\
|
|
&hourly=temperature_2m,rain,showers,precipitation,relative_humidity_2m";
|
|
|
|
pub struct WeatherService {
|
|
client: reqwest::Client,
|
|
}
|
|
|
|
impl WeatherService {
|
|
fn new() -> Self {
|
|
Self {
|
|
client: reqwest::Client::default(),
|
|
}
|
|
}
|
|
pub fn run(inbox: Inbox) -> Subscription<Wire> {
|
|
Subscription::run_with(inbox, |inbox| {
|
|
let key = inbox.key();
|
|
let mut _rx = inbox.take().expect("cant take");
|
|
|
|
iced::stream::channel(0, move |mut sender: mpsc::Sender<Wire>| async move {
|
|
let weather = WeatherService::new();
|
|
let mut interval = interval(Duration::from_mins(30));
|
|
tracing::info!(key = key, "weather service started");
|
|
loop {
|
|
tokio::select! {
|
|
_ = interval.tick() => {
|
|
if let Some(resp) = weather.get_weather().await {
|
|
let env = WeatherPayload {
|
|
kind: WeatherMsg::State,
|
|
payload: Arc::new(resp),
|
|
};
|
|
let wire = Wire::topic(Endpoint::service(key), key, env);
|
|
if sender.send(wire).await.is_err() {
|
|
tracing::warn!(key, "weather send failed; stopping service");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|
|
})
|
|
}
|
|
async fn get_weather(&self) -> Option<WeatherResponse> {
|
|
tracing::debug!(url = FORECAST_URL, "fetching weather");
|
|
match self.client.get(FORECAST_URL).send().await {
|
|
Ok(resp) => match resp.json::<WeatherResponse>().await {
|
|
Ok(parsed) => {
|
|
tracing::debug!("weather fetched");
|
|
Some(parsed)
|
|
}
|
|
Err(e) => {
|
|
tracing::warn!(error = %e, "weather response decode failed");
|
|
None
|
|
}
|
|
},
|
|
Err(e) => {
|
|
tracing::warn!(error = %e, "weather request failed");
|
|
None
|
|
}
|
|
}
|
|
}
|
|
}
|