diff --git a/Cargo.lock b/Cargo.lock index 566e8bc..f623b8a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,17 @@ version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -49,9 +60,9 @@ name = "bambulab" version = "0.1.0" dependencies = [ "anyhow", - "bytes", + "futures", + "paho-mqtt", "rand", - "rumqttc", "tokio", ] @@ -61,12 +72,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bitflags" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" - [[package]] name = "bytes" version = "1.5.0" @@ -89,68 +94,106 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "core-foundation" -version = "0.9.3" +name = "cmake" +version = "0.1.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" dependencies = [ - "core-foundation-sys", - "libc", + "cc", ] [[package]] -name = "core-foundation-sys" -version = "0.8.4" +name = "concurrent-queue" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" +dependencies = [ + "crossbeam-utils", +] [[package]] -name = "errno" -version = "0.3.7" +name = "crossbeam-channel" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" dependencies = [ - "libc", - "windows-sys", + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", ] [[package]] -name = "fastrand" -version = "2.0.1" +name = "event-listener" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] -name = "flume" -version = "0.11.0" +name = "futures" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" dependencies = [ + "futures-channel", "futures-core", + "futures-executor", + "futures-io", "futures-sink", - "spin", + "futures-task", + "futures-util", ] [[package]] -name = "foreign-types" -version = "0.3.2" +name = "futures-channel" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ - "foreign-types-shared", + "futures-core", + "futures-sink", ] [[package]] -name = "foreign-types-shared" -version = "0.1.1" +name = "futures-core" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] -name = "futures-core" +name = "futures-executor" version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" + +[[package]] +name = "futures-macro" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "futures-sink" @@ -164,14 +207,25 @@ version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +[[package]] +name = "futures-timer" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" + [[package]] name = "futures-util" version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ + "futures-channel", "futures-core", + "futures-io", + "futures-macro", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", "slab", @@ -200,24 +254,12 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - [[package]] name = "libc" version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" -[[package]] -name = "linux-raw-sys" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" - [[package]] name = "lock_api" version = "0.4.11" @@ -260,24 +302,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "num_cpus" version = "1.16.0" @@ -298,53 +322,41 @@ dependencies = [ ] [[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "openssl" -version = "0.10.60" +name = "openssl-sys" +version = "0.9.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800" +checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f" dependencies = [ - "bitflags 2.4.1", - "cfg-if", - "foreign-types", + "cc", "libc", - "once_cell", - "openssl-macros", - "openssl-sys", + "pkg-config", + "vcpkg", ] [[package]] -name = "openssl-macros" -version = "0.1.1" +name = "paho-mqtt" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +checksum = "19e405de34b835fb6457d8b0169eda21949f855472b3e346556af9e29fac6eb2" dependencies = [ - "proc-macro2", - "quote", - "syn", + "async-channel", + "crossbeam-channel", + "futures", + "futures-timer", + "libc", + "log", + "paho-mqtt-sys", + "thiserror", ] [[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.96" +name = "paho-mqtt-sys" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f" +checksum = "5e482419d847af4ec43c07eed70f5f94f87dc712d267aecc91ab940944ab6bf4" dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", + "cmake", + "openssl-sys", ] [[package]] @@ -448,23 +460,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "rumqttc" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d8941c6791801b667d52bfe9ff4fc7c968d4f3f9ae8ae7abdaaa1c966feafc8" -dependencies = [ - "bytes", - "flume", - "futures-util", - "log", - "native-tls", - "thiserror", - "tokio", - "tokio-native-tls", + "bitflags", ] [[package]] @@ -473,57 +469,12 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" -[[package]] -name = "rustix" -version = "0.38.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" -dependencies = [ - "bitflags 2.4.1", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] - -[[package]] -name = "schannel" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" -dependencies = [ - "windows-sys", -] - [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "security-framework" -version = "2.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -558,15 +509,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] - [[package]] name = "syn" version = "2.0.39" @@ -578,19 +520,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "tempfile" -version = "3.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" -dependencies = [ - "cfg-if", - "fastrand", - "redox_syscall", - "rustix", - "windows-sys", -] - [[package]] name = "thiserror" version = "1.0.50" @@ -641,16 +570,6 @@ dependencies = [ "syn", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - [[package]] name = "unicode-ident" version = "1.0.12" diff --git a/Cargo.toml b/Cargo.toml index a58775d..78cae59 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,15 +13,11 @@ categories = ["iot", "hardware"] [dependencies] anyhow = "1.0.75" +futures = { version = "0.3.29", default-features = false } +paho-mqtt = "0.12.3" rand = "0.8.5" -rumqttc = { version = "0.23.0", default-features = false, features = [ - "use-native-tls", -] } tokio = { version = "1.34.0", features = ["full"] } -[dev-dependencies] -bytes = "1.5.0" - [profile.release] lto = true opt-level = "s" diff --git a/README.md b/README.md index 7de4c9d..0fcae71 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,9 @@ [![Crates.io Downloads](https://img.shields.io/crates/d/bambulab)](https://crates.io/crates/bambulab) [![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg)](#license) -bambulab is a Rust crate that provides an client for interacting with Bambu Lab devices. +🚧 **WORK IN PROGRESS** 🚧 + +bambulab is a asnyc Rust crate that provides an client for interacting with Bambu Lab devices. ## Features @@ -28,18 +30,19 @@ use bambulab::{client::Client, command::Command}; #[tokio::main] async fn main() -> Result<(), Box> { - let host = "your-bambu-printer-host"; + let host = "printer-ip-or-hostname"; let access_code = "printer-access-code"; let serial = "printer-serial-number"; - let client = Client::new(host, access_code, serial); - client.subscribe().await?; + let mut client = Client::new(host, access_code, serial); + + client.connect().await?; client.publish(Command::PushAll).await?; loop { - let message = client.poll().await?; - println!("{:?}", message); + let message = client.poll().await?; + println!("{message:?}"); } } ``` @@ -48,6 +51,16 @@ Please note that you need to call subscribe() to allow the API to listen to mess More examples available in the [examples](./../examples) directory. +## FAQ + +### How do I find the access code? + +The access code is a 6 digit code that is printed on the back of your printer. It is also available in the Bambu Lab app. + +### How do I find the serial number? + +The serial number is a 6 digit code that is printed on the back of your printer. It is also available in the Bambu Lab app. + ## Contributing See the [contributing guidelines](./../CONTRIBUTING.md) for more information. diff --git a/examples/basic.rs b/examples/basic.rs index 9da9222..b476732 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -4,9 +4,13 @@ use bambulab::{client::Client, command::Command}; #[tokio::main] async fn main() -> Result<()> { - let mut client = Client::new("", "", ""); + let host = "printer-ip-or-hostname"; + let access_code = "printer-access-code"; + let serial = "printer-serial-number"; - client.subscribe().await?; + let mut client = Client::new(host, access_code, serial); + + client.connect().await?; client.publish(Command::PushAll).await?; diff --git a/src/client.rs b/src/client.rs index 7c003e8..5a1a6cc 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,48 +1,88 @@ use std::time::Duration; use anyhow::Result; +use futures::stream::StreamExt; use rand::Rng; -use rumqttc::{AsyncClient, EventLoop, MqttOptions, QoS, TlsConfiguration, Transport}; -use crate::{command::Command, message::Message, parser::parse_event}; +use crate::{command::Command, message::Message, parser::parse_message}; pub struct Client { pub host: String, pub access_code: String, pub serial: String, - client_components: (AsyncClient, EventLoop), + client: paho_mqtt::AsyncClient, + stream: paho_mqtt::AsyncReceiver>, topic_device_request: String, topic_device_report: String, } impl Client { - pub fn new>(host: S, access_code: S, serial: S) -> Self { - let host: String = host.into(); + /// Creates a new Bambu printer MQTT client. + /// + /// # Panics + /// + /// Panics if the MQTT client cannot be created. + pub fn new>(ip: S, access_code: S, serial: S) -> Self { + let host: String = format!("mqtts://{}:8883", ip.into()); let access_code: String = access_code.into(); let serial: String = serial.into(); let client_id = format!("bambu-api-{}", rand::thread_rng().gen_range(0..100)); - let mut mqttoptions = MqttOptions::new(client_id, host.clone(), 8883); - mqttoptions.set_transport(Transport::Tls(TlsConfiguration::Native)); - mqttoptions.set_keep_alive(Duration::from_secs(5)); - mqttoptions.set_credentials("bblp", &access_code); + let create_opts = paho_mqtt::CreateOptionsBuilder::new() + .server_uri(&host) + .client_id(client_id) + .max_buffered_messages(25) + .finalize(); + + let mut client = paho_mqtt::AsyncClient::new(create_opts).expect("Failed to create client"); + let stream = client.get_stream(25); Self { host, access_code, serial: serial.clone(), - client_components: AsyncClient::new(mqttoptions, 25), + client, + stream, topic_device_request: format!("device/{}/request", &serial), topic_device_report: format!("device/{}/report", &serial), } } + /// Connects to the Bambu MQTT broker and subscribes to the device report topic. + /// + /// # Errors + /// + /// Returns an error if there was a problem connecting to the MQTT broker + /// or subscribing to the device report topic. + pub async fn connect(&mut self) -> Result<()> { + let ssl_opts = paho_mqtt::SslOptionsBuilder::new() + .disable_default_trust_store(true) + .enable_server_cert_auth(false) + .verify(false) + .finalize(); + + let conn_opts = paho_mqtt::ConnectOptionsBuilder::new() + .ssl_options(ssl_opts) + .keep_alive_interval(Duration::from_secs(10)) + .user_name("bblp") + .password(&self.access_code) + .finalize(); + + self.client.connect(conn_opts).await?; + + self.client + .subscribe(&self.topic_device_report, paho_mqtt::QOS_0); + + Ok(()) + } + /// Polls for a message from the MQTT event loop. /// You need to poll periodically to receive messages /// and to keep the connection alive. + /// This function also handles reconnects. /// /// **NOTE** Don't block this while iterating /// @@ -50,10 +90,24 @@ impl Client { /// /// Returns an error if there was a problem polling for a message or parsing the event. pub async fn poll(&mut self) -> Result { - let (_, ref mut eventloop) = &mut self.client_components; - let message = eventloop.poll().await?; - - parse_event(message) + let msg_opt = self.stream.next().await; + + let mut rconn_attempt: usize = 0; + + if let Some(msg) = msg_opt { + parse_message(msg) + } else { + // A "None" means we were disconnected. Try to reconnect... + println!("Lost connection. Attempting reconnect..."); + while let Err(err) = self.client.reconnect().await { + rconn_attempt += 1; + println!("Error reconnecting #{rconn_attempt}: {err}"); + tokio::time::sleep(Duration::from_secs(1)).await; + } + println!("Reconnected."); + + Ok(Message::Reconnected) + } } /// Publishes a command to the MQTT broker. @@ -62,31 +116,10 @@ impl Client { /// /// Returns an error if there was a problem publishing the command. pub async fn publish(&mut self, command: Command) -> Result<()> { - let (client, _) = &mut self.client_components; let payload = command.get_payload(); - client - .publish(&self.topic_device_request, QoS::AtMostOnce, false, payload) - .await?; - - Ok(()) - } - - /// Subscribes to the MQTT broker for device reports. - /// - /// **NOTE** This is required to receive messages from the device. - /// - /// # Errors - /// - /// Returns an error if there was a problem subscribing to the topic. - pub async fn subscribe(&mut self) -> Result<()> { - let (client, _) = &mut self.client_components; - - println!("{}", self.topic_device_report); - - client - .subscribe(self.topic_device_report.clone(), QoS::AtMostOnce) - .await?; + let msg = paho_mqtt::Message::new(&self.topic_device_request, payload, paho_mqtt::QOS_0); + self.client.publish(msg).await?; Ok(()) } diff --git a/src/message.rs b/src/message.rs index 4e4897d..db7b9e3 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1,8 +1,7 @@ #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum Message { Info(String), - Connected, - Disconnect, + Reconnected, Outgoing(String), Unknown(String), } diff --git a/src/parser.rs b/src/parser.rs index 10cd2bc..e623841 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,55 +1,37 @@ use anyhow::Result; -use rumqttc::{Event, Packet, Publish}; use crate::message::Message; -pub(crate) fn parse_event(event: Event) -> Result { - match event { - Event::Incoming(incoming) => match incoming { - Packet::Publish(message) => parse_publish(&message), - Packet::Connect(_) => Ok(Message::Connected), - Packet::Disconnect => Ok(Message::Disconnect), - other => Ok(Message::Unknown(format!("{other:?}"))), - }, - Event::Outgoing(outgoing) => Ok(Message::Outgoing(format!("{outgoing:?}"))), +pub(crate) fn parse_message(message: Option) -> Result { + if let Some(message) = message { + let payload_str = String::from_utf8(message.payload().to_vec())?; + Ok(Message::Info(payload_str)) + } else { + Ok(Message::Unknown("Unknown message".into())) } } -fn parse_publish(message: &Publish) -> Result { - let payload = String::from_utf8(message.payload.to_vec())?; - - Ok(Message::Info(payload)) -} - #[cfg(test)] mod tests { - use bytes::Bytes; - use rumqttc::{Outgoing, QoS}; - use super::*; #[test] - fn test_parse_event() { - let event = Event::Outgoing(Outgoing::Subscribe(0)); + fn test_parse_message_some() { + let message = paho_mqtt::Message::new( + "device/123456789/report", + r#"{ "hello": "world" }"#, + paho_mqtt::QOS_2, + ); - let result = parse_event(event).unwrap(); + let result = parse_message(Some(message)).unwrap(); - assert_eq!(result, Message::Outgoing("Subscribe(0)".into())); + assert_eq!(result, Message::Info(r#"{ "hello": "world" }"#.into())); } #[test] - fn test_parse_publish() { - let message = Publish { - dup: false, - qos: QoS::AtMostOnce, - retain: false, - topic: "device/123456789/report".to_string(), - pkid: 0, - payload: Bytes::from(r#"{ "hello": "world" }"#), - }; - - let result = parse_publish(&message).unwrap(); - - assert_eq!(result, Message::Info(r#"{ "hello": "world" }"#.to_string())); + fn test_parse_message_none() { + let result = parse_message(None).unwrap(); + + assert_eq!(result, Message::Unknown("Unknown message".into())); } }