From ec58e9e2680a929d4ef6f45c833c4ca5bf3d97c9 Mon Sep 17 00:00:00 2001 From: Thomas Klaehn Date: Wed, 26 Feb 2025 08:09:15 +0100 Subject: [PATCH] Add mqtt lib Signed-off-by: Thomas Klaehn --- Cargo.toml | 2 +- lib/mqtt/Cargo.toml | 17 +++++++++ lib/mqtt/src/lib.rs | 84 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 lib/mqtt/Cargo.toml create mode 100644 lib/mqtt/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 5f482b0..868b0b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ cargo-features = ["profile-rustflags"] [workspace] -members = ["hp-core", "lp-core"] +members = ["hp-core", "lib/mqtt", "lp-core"] resolver = "2" [profile.release] diff --git a/lib/mqtt/Cargo.toml b/lib/mqtt/Cargo.toml new file mode 100644 index 0000000..78c7b5c --- /dev/null +++ b/lib/mqtt/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "mqtt" +version = "0.1.0" +edition = "2024" +license = "MIT OR Apache-2.0" +publish = false + +[dependencies] +blocking-network-stack = { git = "https://github.com/bjoernQ/blocking-network-stack.git", rev = "b3ecefc222d8806edd221f266999ca339c52d34e" } +embedded-io = { version = "0.6.1", default-features = false } +mqttrust = "0.6.0" +smoltcp = { version = "0.12.0", default-features = false, features = [ "medium-ethernet", "socket-raw"] } + +[features] +ipv4 = ["smoltcp/proto-ipv4"] + +tcp = ["ipv4", "smoltcp/socket-tcp"] \ No newline at end of file diff --git a/lib/mqtt/src/lib.rs b/lib/mqtt/src/lib.rs new file mode 100644 index 0000000..8d5dffb --- /dev/null +++ b/lib/mqtt/src/lib.rs @@ -0,0 +1,84 @@ +#![no_std] + +use blocking_network_stack::IoError; +use embedded_io::{ + Read, + Write +}; +use mqttrust::encoding::v4::{ + encode_slice, + Connect, + Packet, + Protocol, + Publish, + QoS +}; +use smoltcp::wire::{ + IpAddress, + Ipv4Address +}; + +pub struct Mqtt <'a, 'n, D: smoltcp::phy::Device> { + socket: blocking_network_stack::Socket<'a, 'n, D>, + address: Ipv4Address, + port: u16 +} + +impl <'n, 'a: 'n, D: smoltcp::phy::Device> Mqtt<'a, 'a, D> { + pub fn new( + socket: blocking_network_stack::Socket<'a, 'n, D>, + address: Ipv4Address, + port: u16 + ) -> Self { + Self { + socket, + address, + port + } + } + + pub fn open(&mut self) -> Result<(), IoError> { + self.socket.open(IpAddress::Ipv4(self.address), self.port) + } + + pub fn connect(&mut self, client_id: &str) -> Result{ + let connect = Packet::Connect(Connect { + protocol: Protocol::MQTT311, + keep_alive: 10, + client_id, + clean_session: true, + last_will: None, + username: None, + password: None, + }); + let mut buf = [0u8; 1024]; + let len = encode_slice(&connect, &mut buf).unwrap(); + self.socket.write(&buf[..len]) + } + + pub fn publish(&mut self, topic: &str, payload: &[u8]) -> Result { + let packet = Packet::Publish(Publish { + dup: false, + qos: QoS::AtMostOnce, + pid: None, + retain: false, + topic_name: topic, + payload, + }); + let mut buf = [0u8; 1024]; + let len = encode_slice(&packet, &mut buf).unwrap(); + let written = match self.socket.write(&buf[..len]) { + Ok(value) => value, + Err(err) => return core::prelude::v1::Err(err), + }; + let _ = match self.socket.read(&mut buf) { + Ok(value) => value, + Err(err) => return core::prelude::v1::Err(err), + }; + Ok(written) + } + + pub fn disconnect(&mut self) { + self.socket.disconnect(); + } +}