From ce46fa93ca609fdae754081bd90f5a0fe5a42f12 Mon Sep 17 00:00:00 2001 From: Jaroslaw Konik Date: Wed, 29 May 2024 19:11:56 +0200 Subject: [PATCH] mqtt --- Cargo.lock | 13 +++++++ Cargo.toml | 1 + rust-analyzer.json | 3 ++ src/main.rs | 92 ++++++++++++++++++++++++++++------------------ 4 files changed, 74 insertions(+), 35 deletions(-) create mode 100644 rust-analyzer.json diff --git a/Cargo.lock b/Cargo.lock index 9bfb5fd..ea98619 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1087,6 +1087,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "rust-mqtt" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f71160765f368fd9a84e0955e2ddb6d64ac9018fee1c5323354d6d08c816b40" +dependencies = [ + "embedded-io", + "embedded-io-async", + "heapless", + "rand_core", +] + [[package]] name = "rustversion" version = "1.0.15" @@ -1109,6 +1121,7 @@ dependencies = [ "esp-hal", "esp-println", "esp-wifi", + "rust-mqtt", "static_cell", ] diff --git a/Cargo.toml b/Cargo.toml index ae78889..9fb0a29 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ embassy-net-driver = "0.2.0" const_format = "0.2.32" embedded-hal-async = "1.0.0" embassy-sync = "0.5.0" +rust-mqtt = { version = "0.3.0", default-features = false } [profile.dev] # Rust debug is too slow. diff --git a/rust-analyzer.json b/rust-analyzer.json new file mode 100644 index 0000000..2decb06 --- /dev/null +++ b/rust-analyzer.json @@ -0,0 +1,3 @@ +{ + "rust-analyzer.cargo.features": "all" +} diff --git a/src/main.rs b/src/main.rs index 2b56e1f..7f9a2a7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,6 @@ use embassy_net::{Config, Ipv4Address, Stack, StackResources}; use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex}; use esp_hal::{self, IO}; -use const_format::formatcp; use embassy_time::{Duration, Timer}; use embedded_hal_async::digital::Wait; use esp_backtrace as _; @@ -20,10 +19,18 @@ use esp_println::println; use esp_wifi::wifi::{ClientConfiguration, Configuration}; use esp_wifi::wifi::{WifiController, WifiDevice, WifiEvent, WifiStaDevice, WifiState}; use esp_wifi::{initialize, EspWifiInitFor}; +use rust_mqtt::client::client::MqttClient; +use rust_mqtt::client::client_config::ClientConfig; +use rust_mqtt::packet::v5::publish_packet::QualityOfService; +use rust_mqtt::utils::rng_generator::CountingRng; use static_cell::make_static; const SSID: &str = env!("SSID"); const PASSWORD: &str = env!("PASSWORD"); +const MQTT_PASSWORD: &str = env!("MQTT_PASSWORD"); + +const MQTT_TOPIC_NAME: &str = "home/doorbell/state"; +const MQTT_AVAILABILITY_TOPIC_NAME: &str = "home/doorbell/available"; #[main] async fn main(spawner: Spawner) { @@ -57,7 +64,8 @@ async fn main(spawner: Spawner) { let config = Config::dhcpv4(Default::default()); - let seed = 1234; // very random, very secure seed + // TODO: generate random + let seed = 0x50EA111DA6CC1D83; // Init network stack let stack = &*make_static!(Stack::new( @@ -107,7 +115,7 @@ async fn ring(stack: &'static Stack>) -> Resu socket.set_timeout(Some(embassy_time::Duration::from_secs(10))); - let remote_endpoint = (Ipv4Address::new(104, 20, 43, 236), 80); + let remote_endpoint = (Ipv4Address::new(192, 168, 1, 3), 80); println!("connecting..."); let r = socket.connect(remote_endpoint).await; if let Err(e) = r { @@ -115,38 +123,52 @@ async fn ring(stack: &'static Stack>) -> Resu return Err("connect error"); } - const JSON: &str = "{ - \"token\": \"ahgvt9acdx5sowxfobadt9cmpqhrzp\", - \"user\": \"ud2btptjwvy92xi8y77tfurfew6z7a\", - \"message\": \"DOOR BELL!!!\" - }"; - const JSON_LEN: usize = JSON.len(); + // https://github.com/JurajSadel/esp32c3-no-std-async-mqtt-demo/blob/main/src/main.rs + let mut config = ClientConfig::new( + rust_mqtt::client::client_config::MqttVersion::MQTTv5, + CountingRng(20000), + ); + config.add_password(MQTT_PASSWORD); - println!("connected!"); - let mut buf = [0; 1024]; - loop { - use embedded_io_async::Write; - let req = formatcp!("POST /1/messages.json HTTP/1.0\r\nHost: api.pushover.net\r\nContent-Type: application/json\r\nContent-Length: {}\r\n\r\n{}\r\n\r\n", JSON_LEN, JSON); - println!("{}", req); - let r = socket.write_all(req.as_bytes()).await; - if let Err(e) = r { - println!("write error: {:?}", e); - break; - } - let n = match socket.read(&mut buf).await { - Ok(0) => { - println!("read EOF"); - break; - } - Ok(n) => n, - Err(e) => { - println!("read error: {:?}", e); - break; - } - }; - println!("{}", core::str::from_utf8(&buf[..n]).unwrap()); + // Do we need those? + // config.add_max_subscribe_qos(rust_mqtt::packet::v5::publish_packet::QualityOfService::QoS1); + // config.add_client_id("clientId-8rhWgBODCl"); + // config.max_packet_size = 100; + + let mut recv_buffer = [0; 80]; + let mut write_buffer = [0; 80]; + + let mut client = + MqttClient::<_, 5, _>::new(socket, &mut write_buffer, 80, &mut recv_buffer, 80, config); + + if let Err(e) = client.connect_to_broker().await { + println!("connect error: {:?}", e); + return Err("connect error"); } + + // TODO: This should be done at boot + client + .send_message( + MQTT_AVAILABILITY_TOPIC_NAME, + "online".as_bytes(), + QualityOfService::QoS0, + true, + ) + .await + .unwrap(); + + client + .send_message( + MQTT_TOPIC_NAME, + "\"event_type\": \"press\"".as_bytes(), + QualityOfService::QoS0, + true, + ) + .await + .unwrap(); + Timer::after(Duration::from_millis(5000)).await; + Ok(()) } @@ -211,10 +233,10 @@ async fn connection(mut controller: WifiController<'static>) { println!("Device capabilities: {:?}", controller.get_capabilities()); loop { if esp_wifi::wifi::get_wifi_state() == WifiState::StaConnected { - // wait until we're no longer connected - controller.wait_for_event(WifiEvent::StaDisconnected).await; - Timer::after(Duration::from_millis(5000)).await + controller.wait_for_event(WifiEvent::StaDisconnected).await; + Timer::after(Duration::from_millis(5000)).await } + if !matches!(controller.is_started(), Ok(true)) { let client_config = Configuration::Client(ClientConfiguration { ssid: SSID.try_into().unwrap(),