Initial Version

This commit is contained in:
Dimitris
2026-06-12 08:28:49 +02:00
commit de697b2cfc
5 changed files with 2597 additions and 0 deletions
+183
View File
@@ -0,0 +1,183 @@
mod weather_data;
use crate::weather_data::{DwdWeather, MucWeather};
use rumqttc::{AsyncClient, EventLoop, MqttOptions, QoS};
use scraper::{Html as HtmlScraper, Selector};
use std::time::Duration;
use tokio::{task, time};
const METEO_MUNICH_API_URL: &str =
"https://www.meteorologie.lmu.de/~quicklooks/aktuelle_messwerte/messwerte_stadt.html";
#[tokio::main(flavor = "current_thread")]
async fn main() {
let (client, mut eventloop) = create_conn();
match meteo_weather(48.163142, 11.542922).await {
Ok(weather) => {
task::spawn(async move {
publish(client.clone(), &weather).await;
time::sleep(Duration::from_secs(3)).await;
});
let mut count = 0;
loop {
let event = eventloop.poll().await;
match &event {
Ok(_) => {
if count == 10 {
break;
}
count = count + 1;
}
Err(e) => {
println!("Error = {e:?}");
}
}
}
}
Err(e) => {
println!("{}", e);
}
}
}
pub async fn meteo_weather(latitude: f64, longitude: f64) -> Result<MucWeather, reqwest::Error> {
let response = trpl::get(METEO_MUNICH_API_URL).await;
let response_text = response.text().await;
let fragment = HtmlScraper::parse_fragment(&response_text);
let mut temperature = 999.0;
let mut humidity = 0.0;
let mut pressure = 0.0;
let mut precipitation = 0.0;
let profilwerte = Selector::parse("#messwerte-profilwerte").unwrap();
let winddruck = Selector::parse("#messwerte-winddruck").unwrap();
let niederschlag = Selector::parse("#messwerte-niederschlag").unwrap();
let row_selector = Selector::parse("tr").unwrap();
let cell_selector = Selector::parse("td").unwrap();
if let Some(table) = fragment.select(&profilwerte).next() {
for row in table.select(&row_selector) {
let mut row_data = Vec::new();
for cell in row.select(&cell_selector) {
let text = cell.text().collect::<Vec<_>>().join(" ");
row_data.push(text.trim().to_string());
}
if row_data[0] == "Lufttemperatur" {
temperature = row_data[1].replace(" °C", "").trim().parse::<f64>().unwrap();
}
if row_data[0] == "Relative Feuchte" {
humidity = row_data[1].replace(" %", "").trim().parse::<f64>().unwrap();
}
}
}
if let Some(table) = fragment.select(&winddruck).next() {
for row in table.select(&row_selector) {
let mut row_data = Vec::new();
for cell in row.select(&cell_selector) {
let text = cell.text().collect::<Vec<_>>().join(" ");
row_data.push(text.trim().to_string());
}
if row_data[0] == "Luftdruck NN" {
pressure = row_data[1].replace(" hPa", "").trim().parse::<f64>().unwrap();
}
}
}
if let Some(table) = fragment.select(&niederschlag).next() {
for row in table.select(&row_selector) {
let mut row_data = Vec::new();
for cell in row.select(&cell_selector) {
let text = cell.text().collect::<Vec<_>>().join(" ");
row_data.push(text.trim().to_string());
}
if row_data.len() > 1 && row_data[1].contains(" mm") {
precipitation = row_data[1].replace(" mm", "").trim().parse::<f64>().unwrap();
}
}
}
if temperature == 999.0 {
let url = format!(
"https://api.brightsky.dev/current_weather?lat={}&lon={}",
latitude, longitude
);
println!("Fetching {}", url);
let result = trpl::get(&url).await.text().await;
let dwd_weather: DwdWeather = serde_json::from_str(&result).unwrap();
temperature = dwd_weather.weather.temperature.unwrap();
pressure = dwd_weather.weather.pressure_msl;
humidity = dwd_weather.weather.relative_humidity as f64;
precipitation = dwd_weather.weather.precipitation;
}
let weather = MucWeather {
temperature,
pressure,
humidity,
precipitation,
};
println!("Zeile: {:?}", weather);
Ok(weather)
}
async fn publish(client: AsyncClient, muc: &MucWeather) {
// Serialize it to a JSON string.
let json = serde_json::to_string(&muc);
client
.publish("munich/weather", QoS::AtLeastOnce, false, json.unwrap())
.await
.unwrap();
client
.publish(
"munich/temperature",
QoS::AtLeastOnce,
false,
muc.temperature.to_string(),
)
.await
.unwrap();
client
.publish(
"munich/pressure",
QoS::AtLeastOnce,
false,
muc.pressure.to_string(),
)
.await
.unwrap();
client
.publish(
"munich/humidity",
QoS::AtLeastOnce,
false,
muc.humidity.to_string(),
)
.await
.unwrap();
client
.publish(
"munich/precipitation",
QoS::AtLeastOnce,
false,
muc.precipitation.to_string(),
)
.await
.unwrap();
time::sleep(Duration::from_secs(2)).await;
}
fn create_conn() -> (AsyncClient, EventLoop) {
let mut mqttoptions = MqttOptions::new("rust-mqqt", "192.168.1.37", 1883);
mqttoptions
.set_keep_alive(Duration::from_secs(5))
.set_manual_acks(false)
.set_credentials("mqtt", "delta32#")
.set_clean_session(false);
AsyncClient::new(mqttoptions, 10)
}