-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Hide actual MQTT implementation behind trait+newtype (#42)
- Loading branch information
1 parent
9b2b6eb
commit b233e54
Showing
8 changed files
with
141 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
use crate::mqtt_config::MqttConfig; | ||
|
||
#[derive(Clone, Copy)] | ||
pub enum QoS { | ||
AtMostOnce, | ||
AtLeastOnce, | ||
ExactlyOnce, | ||
} | ||
|
||
// TODO: add an implementation of the MqttWrapper for testing | ||
// TODO: should this be renamed to MqttImplementation? | ||
pub trait MqttWrapper { | ||
// This trait provides an interface that the decouples library code from an | ||
// implementation of the MQTT client. On library calling code, one needs to | ||
// wrap the MQTT implementation, i.e. the client, in a new type that in | ||
// turn implements this trait. | ||
|
||
fn subscribe(&mut self, topic: &str, qos: QoS) -> anyhow::Result<()>; | ||
|
||
fn publish<S, V>(&mut self, topic: S, qos: QoS, retain: bool, payload: V) -> anyhow::Result<()> | ||
where | ||
S: Clone + Into<String>, | ||
V: Clone + Into<Vec<u8>>; | ||
|
||
fn new(config: &MqttConfig) -> Self; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
use anyhow::Ok; | ||
use hms_mqtt_publish::{ | ||
mqtt_config::MqttConfig, | ||
mqtt_wrapper::{self}, | ||
}; | ||
use rumqttc::{Client, MqttOptions}; | ||
use std::thread; | ||
use std::time::Duration; | ||
|
||
pub struct RumqttcWrapper { | ||
client: Client, | ||
} | ||
|
||
fn match_qos(qos: mqtt_wrapper::QoS) -> rumqttc::QoS { | ||
match qos { | ||
mqtt_wrapper::QoS::AtMostOnce => rumqttc::QoS::AtMostOnce, | ||
mqtt_wrapper::QoS::AtLeastOnce => rumqttc::QoS::AtLeastOnce, | ||
mqtt_wrapper::QoS::ExactlyOnce => rumqttc::QoS::ExactlyOnce, | ||
} | ||
} | ||
|
||
impl mqtt_wrapper::MqttWrapper for RumqttcWrapper { | ||
fn subscribe(&mut self, topic: &str, qos: mqtt_wrapper::QoS) -> anyhow::Result<()> { | ||
Ok(self.client.subscribe(topic, match_qos(qos))?) | ||
} | ||
|
||
fn publish<S, V>( | ||
&mut self, | ||
topic: S, | ||
qos: mqtt_wrapper::QoS, | ||
retain: bool, | ||
payload: V, | ||
) -> anyhow::Result<()> | ||
where | ||
S: Clone + Into<String>, | ||
V: Clone + Into<Vec<u8>>, | ||
{ | ||
// try publishing up to three times | ||
if let std::result::Result::Ok(_) = | ||
self.client | ||
.try_publish(topic.clone(), match_qos(qos), retain, payload.clone()) | ||
{ | ||
return Ok(()); | ||
} | ||
std::thread::sleep(Duration::from_millis(100)); | ||
if let std::result::Result::Ok(_) = | ||
self.client | ||
.try_publish(topic.clone(), match_qos(qos), retain, payload.clone()) | ||
{ | ||
return Ok(()); | ||
} | ||
std::thread::sleep(Duration::from_millis(100)); | ||
Ok(self | ||
.client | ||
.try_publish(topic, match_qos(qos), retain, payload)?) | ||
} | ||
|
||
fn new(config: &MqttConfig) -> Self { | ||
let mut mqttoptions = MqttOptions::new( | ||
"hms800wt2-mqtt-publisher", | ||
&config.host, | ||
config.port.unwrap_or(1883), | ||
); | ||
mqttoptions.set_keep_alive(Duration::from_secs(5)); | ||
|
||
//parse the mqtt authentication options | ||
if let Some((username, password)) = match (&config.username, &config.password) { | ||
(None, None) => None, | ||
(None, Some(_)) => None, | ||
(Some(username), None) => Some((username.clone(), "".into())), | ||
(Some(username), Some(password)) => Some((username.clone(), password.clone())), | ||
} { | ||
mqttoptions.set_credentials(username, password); | ||
} | ||
|
||
let (client, mut connection) = Client::new(mqttoptions, 10); | ||
|
||
thread::spawn(move || { | ||
// keep polling the event loop to make sure outgoing messages get sent | ||
// the call to .iter() blocks and suspends the thread effectively by | ||
// calling .recv() under the hood. This implies that the loop terminates | ||
// once the client unsubs | ||
for _ in connection.iter() {} | ||
}); | ||
|
||
Self { client } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters