From 7c5186ed4969cf00a16b3a3f4ec647401442eefb Mon Sep 17 00:00:00 2001 From: Priec Date: Thu, 2 Oct 2025 12:17:36 +0200 Subject: [PATCH] final --- final/Cargo.lock | 25 +++----- final/Cargo.toml | 1 - final/src/bin/main.rs | 1 + final/src/mqtt/client.rs | 53 ++++++++++++++++ final/src/mqtt/mod.rs | 2 + test_tls_embassy/Cargo.toml | 32 ++++++++++ test_tls_embassy/README.md | 26 ++++++++ test_tls_embassy/src/main.rs | 116 +++++++++++++++++++++++++++++++++++ 8 files changed, 237 insertions(+), 19 deletions(-) create mode 100644 final/src/mqtt/client.rs create mode 100644 final/src/mqtt/mod.rs create mode 100644 test_tls_embassy/Cargo.toml create mode 100644 test_tls_embassy/README.md create mode 100644 test_tls_embassy/src/main.rs diff --git a/final/Cargo.lock b/final/Cargo.lock index 289141d..95e485a 100644 --- a/final/Cargo.lock +++ b/final/Cargo.lock @@ -326,7 +326,7 @@ dependencies = [ "embassy-time 0.5.0", "embedded-io-async", "embedded-nal-async", - "heapless 0.8.0", + "heapless", "log", "managed", "smoltcp", @@ -349,7 +349,7 @@ dependencies = [ "embedded-io-async", "futures-sink", "futures-util", - "heapless 0.8.0", + "heapless", ] [[package]] @@ -363,7 +363,7 @@ dependencies = [ "embedded-io-async", "futures-core", "futures-sink", - "heapless 0.8.0", + "heapless", ] [[package]] @@ -415,7 +415,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc55c748d16908a65b166d09ce976575fb8852cf60ccd06174092b41064d8f83" dependencies = [ "embassy-executor", - "heapless 0.8.0", + "heapless", ] [[package]] @@ -551,7 +551,7 @@ dependencies = [ "cfg-if", "esp-config", "esp-println", - "heapless 0.8.0", + "heapless", "semihosting", ] @@ -932,16 +932,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "heapless" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1edcd5a338e64688fbdcb7531a846cfd3476a54784dcb918a0844682bc7ada5" -dependencies = [ - "hash32", - "stable_deref_trait", -] - [[package]] name = "heck" version = "0.5.0" @@ -1254,7 +1244,7 @@ dependencies = [ "defmt 0.3.100", "embedded-io", "embedded-io-async", - "heapless 0.8.0", + "heapless", "rand_core 0.6.4", ] @@ -1322,7 +1312,7 @@ dependencies = [ "bitflags 1.3.2", "byteorder", "cfg-if", - "heapless 0.8.0", + "heapless", "log", "managed", ] @@ -1407,7 +1397,6 @@ dependencies = [ "esp-hal-embassy", "esp-println", "esp-wifi", - "heapless 0.9.1", "log", "rust-mqtt", "smoltcp", diff --git a/final/Cargo.toml b/final/Cargo.toml index e048ba7..902f222 100644 --- a/final/Cargo.toml +++ b/final/Cargo.toml @@ -65,7 +65,6 @@ smoltcp = { version = "0.12.0", default-features = false, features = [ ] } static_cell = "2.1.1" rust-mqtt = { version = "0.3.0", default-features = false, features = ["no_std"] } -heapless = "0.9.1" [build-dependencies] dotenvy = "0.15.7" diff --git a/final/src/bin/main.rs b/final/src/bin/main.rs index 53504aa..e0b7506 100644 --- a/final/src/bin/main.rs +++ b/final/src/bin/main.rs @@ -17,6 +17,7 @@ use esp_wifi::{ wifi::{ClientConfiguration, Configuration, WifiController, WifiDevice, WifiEvent, WifiState}, }; use log::info; +mod mqtt; extern crate alloc; diff --git a/final/src/mqtt/client.rs b/final/src/mqtt/client.rs new file mode 100644 index 0000000..7b47831 --- /dev/null +++ b/final/src/mqtt/client.rs @@ -0,0 +1,53 @@ +use embassy_time::{Duration, Timer}; +use embassy_net::{tcp::TcpSocket, Stack}; +use esp_wifi::wifi::WifiDevice; +use rust_mqtt::client::client::MqttClient; +use rust_mqtt::packet::v5::{connect::ConnectPacket, publish::PublishPacket}; +use rust_mqtt::utils::rng_generator::CountingRng32; +use log::info; + +#[embassy_executor::task] +pub async fn mqtt_task(stack: &'static Stack>) { + info!("MQTT task starting..."); + + static mut RX_BUFFER: [u8; 2048] = [0; 2048]; + static mut TX_BUFFER: [u8; 2048] = [0; 2048]; + + let mut socket = TcpSocket::new(stack, unsafe { &mut RX_BUFFER }, unsafe { &mut TX_BUFFER }); + + // TODO: replace with your broker IP + use embassy_net::Ipv4Address; + let broker_ip = Ipv4Address::new(192, 168, 1, 100); + let broker_port = 1883; + + if let Err(e) = socket.connect((broker_ip, broker_port)).await { + info!("TCP connect failed: {:?}", e); + return; + } + info!("Connected to MQTT broker"); + + let rng = CountingRng32::new(); + let mut client: MqttClient<_, _, 1024, 1024> = MqttClient::new(socket, rng); + + let connect = ConnectPacket::new("esp32-client"); + if client.connect(connect).await.is_ok() { + info!("MQTT CONNECT sent"); + } + + let publish = PublishPacket::new("esp32/topic", b"hello from esp32", 0); + if client.publish(publish).await.is_ok() { + info!("MQTT PUBLISH sent"); + } + + // Keep polling + loop { + match client.poll().await { + Ok(_) => {} + Err(e) => { + info!("MQTT error: {:?}", e); + break; + } + } + Timer::after(Duration::from_secs(5)).await; + } +} diff --git a/final/src/mqtt/mod.rs b/final/src/mqtt/mod.rs new file mode 100644 index 0000000..9cc7d66 --- /dev/null +++ b/final/src/mqtt/mod.rs @@ -0,0 +1,2 @@ + +pub mod client; diff --git a/test_tls_embassy/Cargo.toml b/test_tls_embassy/Cargo.toml new file mode 100644 index 0000000..0333205 --- /dev/null +++ b/test_tls_embassy/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "ping-embassy-net" +version = "0.5.0" +edition = "2021" +resolver = "2" + +[dependencies] +embedded-tls = { path = "../..", features = ["alloc", "std", "log"], default-features = false } +env_logger = "0.10" +rand = "0.8" +log = "0.4" +static_cell = "1" +embassy-executor = { version = "0.4", features = ["task-arena-size-32768", "arch-std", "executor-thread", "log", "integrated-timers"] } +embassy-time = { version = "0.2", default-features = false, features = ["std"] } +smoltcp = { version = "0.11.0", features = ["dns-max-server-count-4"] } +embassy-net = { version = "0.3.0", features=[ "std", "log", "medium-ethernet", "medium-ip", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] } +embassy-net-tuntap = { version = "0.1.0" } + +async-io = "1.6.0" +futures = { version = "0.3.17" } +libc = "0.2.101" +clap = { version = "3.0", features = ["derive", "color"] } +heapless = { version = "0.8", default-features = false } +embedded-io-async = { version = "0.6" } +embedded-io-adapters = { version = "0.6", features = ["futures-03"] } +critical-section = { version = "1.1", features = ["std"] } + +[patch.crates-io] +embassy-executor = { git = "https://github.com/embassy-rs/embassy.git", rev = "51de518bd3edf15ffc76a55b6d003a633556ae56" } +embassy-net = { git = "https://github.com/embassy-rs/embassy.git", rev = "51de518bd3edf15ffc76a55b6d003a633556ae56" } +embassy-net-tuntap = { git = "https://github.com/embassy-rs/embassy.git", rev = "51de518bd3edf15ffc76a55b6d003a633556ae56" } +embassy-time = { git = "https://github.com/embassy-rs/embassy.git", rev = "51de518bd3edf15ffc76a55b6d003a633556ae56" } diff --git a/test_tls_embassy/README.md b/test_tls_embassy/README.md new file mode 100644 index 0000000..aa7caab --- /dev/null +++ b/test_tls_embassy/README.md @@ -0,0 +1,26 @@ +# Embassy runtime example + +This example show how you can use embedded-tls with the embassy async runtime. It will attempt to connect to an endpoint, send a "ping" message, and expect a "pong" response. + +First, create the tap0 interface. You only need to do this once. + +```sh +sudo ip tuntap add name tap0 mode tap user $USER +sudo ip link set tap0 up +sudo ip addr add 192.168.69.100/24 dev tap0 +sudo ip -6 addr add fe80::100/64 dev tap0 +sudo ip -6 addr add fdaa::100/64 dev tap0 +sudo ip -6 route add fe80::/64 dev tap0 +sudo ip -6 route add fdaa::/64 dev tap0 +``` + +You can use the [rustls-mio](https://github.com/rustls/rustls/tree/main/examples) server example to test it as follows: + +```sh +# In the rustls-mio folder +openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 -keyout key.pem -out cert.pem -batch +cargo run --bin tlsserver-mio -- -p 12345 --certs cert.pem --key key.pem --protover 1.3 --tickets --verbose echo + +# In this folder +RUST_LOG=trace cargo run +``` diff --git a/test_tls_embassy/src/main.rs b/test_tls_embassy/src/main.rs new file mode 100644 index 0000000..8daee60 --- /dev/null +++ b/test_tls_embassy/src/main.rs @@ -0,0 +1,116 @@ +use clap::Parser; +use embassy_executor::{Executor, Spawner}; +use embassy_net::tcp::TcpSocket; +use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; +use embassy_net_tuntap::TunTapDevice; +use embassy_time::Duration; +use embedded_io_async::Write; +use embedded_tls::{Aes128GcmSha256, TlsConfig, TlsConnection, TlsContext, UnsecureProvider}; +use heapless::Vec; +use log::*; +use rand::{rngs::OsRng, RngCore}; +use static_cell::StaticCell; + +#[derive(Parser)] +#[clap(version = "1.0")] +struct Opts { + /// TAP device name + #[clap(long, default_value = "tap0")] + tap: String, + /// use a static IP instead of DHCP + #[clap(long)] + static_ip: bool, +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack) -> ! { + stack.run().await +} + +#[embassy_executor::task] +async fn main_task(spawner: Spawner) { + let opts: Opts = Opts::parse(); + + // Init network device + let device = TunTapDevice::new(&opts.tap).unwrap(); + + // Choose between dhcp or static ip + let config = if opts.static_ip { + Config::ipv4_static(embassy_net::StaticConfigV4 { + address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24), + dns_servers: Vec::new(), + gateway: Some(Ipv4Address::new(192, 168, 69, 1)), + }) + } else { + Config::dhcpv4(Default::default()) + }; + + // Generate random seed + let mut seed = [0; 8]; + OsRng.fill_bytes(&mut seed); + let seed = u64::from_le_bytes(seed); + + // Init network stack + static STACK: StaticCell> = StaticCell::new(); + static RESOURCES: StaticCell> = StaticCell::new(); + let stack = &*STACK.init(Stack::new( + device, + config, + RESOURCES.init(StackResources::<3>::new()), + seed, + )); + + // Launch network task + spawner.spawn(net_task(stack)).unwrap(); + + // Then we can use it! + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + + socket.set_timeout(Some(Duration::from_secs(10))); + + let remote_endpoint = (Ipv4Address::new(192, 168, 69, 100), 12345); + log::info!("connecting to {:?}...", remote_endpoint); + let r = socket.connect(remote_endpoint).await; + if let Err(e) = r { + warn!("connect error: {:?}", e); + return; + } + log::info!("TCP connected!"); + + let mut read_record_buffer = [0; 16384]; + let mut write_record_buffer = [0; 16384]; + let config = TlsConfig::new().with_server_name("example.com"); + let mut tls = TlsConnection::new(socket, &mut read_record_buffer, &mut write_record_buffer); + + tls.open(TlsContext::new( + &config, + UnsecureProvider::new::(OsRng), + )) + .await + .expect("error establishing TLS connection"); + + tls.write_all(b"ping").await.expect("error writing data"); + tls.flush().await.expect("error flushing data"); + + let mut rx_buf = [0; 128]; + let sz = tls.read(&mut rx_buf[..]).await.expect("error reading data"); + + log::info!("Read {} bytes: {:?}", sz, &rx_buf[..sz]); +} + +static EXECUTOR: StaticCell = StaticCell::new(); + +fn main() { + env_logger::builder() + .filter_level(log::LevelFilter::Debug) + .filter_module("async_io", log::LevelFilter::Info) + .format_timestamp_nanos() + .init(); + + let executor = EXECUTOR.init(Executor::new()); + executor.run(|spawner| { + spawner.spawn(main_task(spawner)).unwrap(); + }); +}