azalea_shell/service/
weather.rs1use tokio::sync::broadcast;
2
3#[derive(azalea_derive::StaticServiceManager)]
4pub struct Service {
5 client: open_meteo_rs::Client,
6}
7
8#[derive(Clone, Default)]
9pub struct Init {}
10
11#[derive(Clone, Debug)]
12pub enum Input {
13 Update,
14}
15
16#[derive(Clone, Debug)]
17pub enum Output {
18 Temperature((f64, String)),
19}
20
21impl azalea_service::Service for Service {
22 type Init = Init;
23 type Input = Input;
24 type Event = ();
25 type Output = Output;
26
27 const DISABLE_EVENTS: bool = true;
28
29 async fn new(
30 _init: Self::Init,
31 sender: flume::Sender<Self::Input>,
32 _output_sender: broadcast::Sender<Self::Output>,
33 ) -> Self {
34 let client = open_meteo_rs::Client::new();
35
36 drop(sender.send(Input::Update));
37
38 Self { client }
39 }
40
41 async fn message(
42 &mut self,
43 input: Self::Input,
44 output_sender: &broadcast::Sender<Self::Output>,
45 ) {
46 match input {
47 Input::Update => {
48 if let Some(temperature) = self.get_temperature().await {
49 drop(output_sender.send(Output::Temperature(temperature)));
50 }
51 }
52 }
53 }
54}
55
56impl Service {
57 async fn get_temperature(&self) -> Option<(f64, String)> {
58 let mut opts = open_meteo_rs::forecast::Options::default();
59
60 opts.location = open_meteo_rs::Location {
61 lat: -23.5558,
62 lng: -46.6396,
63 };
64
65 opts.temperature_unit = Some(open_meteo_rs::forecast::TemperatureUnit::Celsius); opts.wind_speed_unit = Some(open_meteo_rs::forecast::WindSpeedUnit::Kmh); opts.precipitation_unit = Some(open_meteo_rs::forecast::PrecipitationUnit::Millimeters); opts.current.push("temperature_2m".into());
69
70 let res = self.client.forecast(opts).await.unwrap();
71 res.current.and_then(|res| {
72 if let Some(temp) = res.values.get("temperature_2m") {
73 Some((
74 match temp.value.clone() {
75 serde_json::Value::Number(number) => number.as_f64().unwrap_or(0.),
76 _ => 0.,
77 },
78 temp.unit.clone().unwrap_or(format!("C°")),
79 ))
80 } else {
81 None
82 }
83 })
84 }
85}