Skip to content

Commit

Permalink
publishing to mqtt is now working
Browse files Browse the repository at this point in the history
  • Loading branch information
adenoz committed Jan 11, 2023
1 parent d704895 commit 143b6fa
Showing 1 changed file with 125 additions and 53 deletions.
178 changes: 125 additions & 53 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ use reqwest::{self, header::CONTENT_TYPE};
use std::{error::Error, fs};
use serde::{Deserialize, Serialize};
use toml;
use rumqttc::v5::mqttbytes::{LastWill, QoS};
use rumqttc::v5::mqttbytes::QoS; // LastWill
use rumqttc::v5::{MqttOptions, AsyncClient};
use std::time::Duration;
use std::thread;
use tokio::{task, time};
// use std::thread;
// use tokio::{task, time};
//use serde_json;

#[derive(Deserialize, Debug)]
Expand All @@ -17,14 +17,14 @@ struct Config {

#[derive(Deserialize, Debug)]
struct Location {
name: String,
// name: String,
hash: String,
}

#[derive(Deserialize, Debug)]
struct Broker {
ip: String,
port: u16,
// port: u16,
}

#[derive(Serialize, Deserialize, Debug)]
Expand Down Expand Up @@ -66,15 +66,16 @@ struct MinTemp {
value: Option<f32>,
}

async fn get_weather() -> Result<APIData, Box<dyn Error>> {
// Result<APIData, Box<dyn Error>> // saving this result type in case I need it again, likely wont need
async fn get_weather() -> Result<(), Box<dyn Error>> {
// Start by grabbing data from the config.toml file
let config: Config = {
let config_text = fs::read_to_string("config.toml")
.expect("Could not read the file");
toml::from_str(&config_text)
.expect("Could not parse toml")
};
let loc_name = config.location.name;
// let loc_name = config.location.name;
let loc_hash = config.location.hash;
// println!("location name is {}", &loc_name);
// println!("location hash is {}", &loc_hash);
Expand All @@ -97,7 +98,7 @@ async fn get_weather() -> Result<APIData, Box<dyn Error>> {
// Setup MQTT client to be ready to send messages
let ip = config.broker.ip;
// println!("ip is {}", ip);
let port = config.broker.port;
// let port = config.broker.port; // for some reason the MqttOptions won't take this as a variable even though it needs a u16
// println!("port is {}", port);
//let mut mqttoptions = MqttOptions::new("RusQTTbom", "192.168.1.44", 1883);
//mqttoptions.set_keep_alive(Duration::from_secs(5));
Expand All @@ -116,120 +117,191 @@ async fn get_weather() -> Result<APIData, Box<dyn Error>> {
// MQTT messages along their own MQTT topics.
// At that point, we will no longer need the println! lines
// as those lines are temporary only.


let mut mqttoptions = MqttOptions::new("mqtt-play", ip, 1883);
mqttoptions.set_keep_alive(Duration::from_secs(5));
let (client, mut eventloop) = AsyncClient::new(mqttoptions, 10);

let temp_c_topic = "outside/weather/current-temp";
let current_temp = &response.data.temp;
//let current_tempz = current_temp.to_string();
match &current_temp {
Some(current_temp) => println!("The current temperature at {} is {:?} degrees", loc_name, &current_temp),
Some(current_temp) => client
.publish(temp_c_topic, QoS::AtMostOnce, false, current_temp.to_string())
.await
.unwrap(),
// println!("The current temperature at {} is {:?} degrees", loc_name, &current_temp),
None => println!("None value for current temp"),
}




let temp_feels_topic = "outside/weather/temp-feels";
let temp_feels = &response.data.temp_feels_like;
match &temp_feels {
Some(temp_feels) => println!("The current temperature feels like {:?} degrees", &temp_feels),
Some(temp_feels) => client
.publish(temp_feels_topic, QoS::AtMostOnce, false, temp_feels.to_string())
.await
.unwrap(),
None => println!("None value for temp feels"),
}

let min_temp_topic = "outside/weather/min-temp";
let min_temp = &response.data.min_temp.value;
match &min_temp {
Some(min_temp) => println!("The minimum temperature today has been {:?} degrees", &min_temp),
Some(min_temp) => client
.publish(min_temp_topic, QoS::AtMostOnce, false, min_temp.to_string())
.await
.unwrap(),
None => println!("None value for min temp"),
}

let max_temp_topic = "outside/weather/min-temp";
let max_temp = &response.data.max_temp.value;
match &max_temp {
Some(max_temp) => println!("The maximum temperature today has been {:?} degrees", &max_temp),
Some(max_temp) => client
.publish(max_temp_topic, QoS::AtMostOnce, false, max_temp.to_string())
.await
.unwrap(),
None => println!("None value for max temp"),
}

let humidity_topic = "outside/weather/humidity";
let humidity = &response.data.humidity;
match &humidity {
Some(humidity) => println!("The current humidity is {:?} percent", &humidity),
Some(humidity) => client
.publish(humidity_topic, QoS::AtMostOnce, false, humidity.to_string())
.await
.unwrap(),
None => println!("None value for humidity"),
}

let rain_today_topic = "outside/weather/rain-today";
let rain_today = &response.data.rain_since_9am;
match &rain_today {
Some(rain_today) => println!("Today, there has been {:?}mm of rain", &rain_today),
Some(rain_today) => client
.publish(rain_today_topic, QoS::AtMostOnce, false, rain_today.to_string())
.await
.unwrap(),
None => println!("None value for rain today"),
}

let wind_km_topic = "outside/weather/wind-kms";
let wind_kms = &response.data.wind.speed_kilometre;
match &wind_kms {
Some(wind_kms) => println!("The wind speed is {:?}km/h", &wind_kms),
Some(wind_kms) => client
.publish(wind_km_topic, QoS::AtMostOnce, false, wind_kms.to_string())
.await
.unwrap(),
None => println!("None value for wind kms"),
}

let wind_kts_topic = "outside/weather/wind-kts";
let wind_kts = &response.data.wind.speed_knot;
match &wind_kts {
Some(wind_kts) => println!("the wind speed is {:?}knots", &wind_kts),
Some(wind_kts) => client
.publish(wind_kts_topic, QoS::AtMostOnce, false, wind_kts.to_string())
.await
.unwrap(),
None => println!("None value for wind kts"),
}

let wind_dir_topic = "outside/weather/wind-dir";
let wind_direction = &response.data.wind.direction;
match &wind_direction {
Some(wind_direction) => println!("The wind is coming from the {:?} direction", &wind_direction),
Some(wind_direction) => client
.publish(wind_dir_topic, QoS::AtMostOnce, false, wind_direction.to_string())
.await
.unwrap(),
None => println!("None value for wind direction"),
}

let gusts_topic = "outside/weather/gusts";
let gusts = &response.data.gust;
// Later, when sending MQTT messages, we can just send when the pattern matches
match &gusts {
Some(gusts) => println!("The wind is gusting at {:?}km an hour", &gusts),
Some(gusts) => client
.publish(gusts_topic, QoS::AtMostOnce, false, gusts.to_string())
.await
.unwrap(),
None => println!("None value for gusts"), // this can later be a log message
}

let max_gust_topic = "outside/weather/max-gust";
let max_gust = &response.data.max_gust;
// Later, when sending MQTT messages, we can just send when the pattern matches
match &max_gust {
Some(max_gust) => println!("The wind is gusting at up to {:?}km an hour", &max_gust),
Some(max_gust) => client
.publish(max_gust_topic, QoS::AtMostOnce, false, max_gust.to_string())
.await
.unwrap(),
None => println!("None value for max gusts"), // this can later be a log message
}

// This endless eventloop is required to publish the messages
// The count needs to give enough times to receive the ConnAck and complete this program and wait for any failed messages to process
let mut n = 15; loop {
let event = eventloop.poll().await;
n -= 1; // this countdown allows us to break out of the endless loop closing the program
match &event {
Ok(v) => {
if n < 1 {
println!("breaking out");
return Ok(());
}
println!("Event = {:?}", v);
}
Err(e) => {
println!("Error = {:?}", e);
return Ok(());
}
}
}

// The below works well and correct
// We can build on the below later for error checking etc.
//match &response.json::<APIData>().await {
// Ok(parsed) => println!("Success! {:?}", parsed),
// Err(_) => println!("didn't parse"),
//};
Ok(response)
// Ok(response)
}

async fn send_mqtt() {
let mut mqttoptions = MqttOptions::new("mqtt-play", "192.168.1.44", 1883);
mqttoptions.set_keep_alive(Duration::from_secs(5));
let (client, mut eventloop) = AsyncClient::new(mqttoptions, 10);
let topicz = "mqtt/more";
let payloadz = 22.7;
let new = payloadz.to_string();
// async fn send_mqtt() -> Result<(), Box<dyn Error>> {
// let mut mqttoptions = MqttOptions::new("mqtt-play", "192.168.1.44", 1883);
// mqttoptions.set_keep_alive(Duration::from_secs(5));
// let (client, mut eventloop) = AsyncClient::new(mqttoptions, 10);

// This below publish now works, though need to convert float to string
client
.publish(topicz, QoS::AtMostOnce, false, new)
.await
.unwrap();

loop {
let event = eventloop.poll().await;
match &event {
Ok(v) => {
println!("Event = {:?}", v);
}
Err(e) => {
println!("Error = {:?}", e);
//return Ok(());
}
}
}
}
//client
// .publish(topicz, QoS::AtMostOnce, false, payloadz)
// .await
// .unwrap();

// This endless eventloop is required to publish the messages
// let mut n = 10; // this count seems to give enough time to complete this program and wait for any failed messages to process
// loop {
// let event = eventloop.poll().await;
// n -= 1; // this countdown allows us to break out of the endless loop closing the program
// match &event {
// Ok(v) => {
// if n < 1 {
// println!("breaking out");
// return Ok(());
// }
// println!("Event = {:?}", v);
// }
// Err(e) => {
// println!("Error = {:?}", e);
// return Ok(());
// }
// }
// }
//}

#[tokio::main]
async fn main() {
let detail = get_weather().await;
println!("weather = {:#?}", detail);

send_mqtt().await;
get_weather().await;
// println!("weather = {:#?}", detail);
// send_mqtt().await;
}
//let mut mqttoptions = MqttOptions::new("mqtt-play", "192.168.1.44", 1883);
//mqttoptions.set_keep_alive(Duration::from_secs(5));
Expand Down

0 comments on commit 143b6fa

Please sign in to comment.