working everything properly well
This commit is contained in:
@@ -8,90 +8,159 @@
|
||||
)]
|
||||
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_futures::select::{select, Either};
|
||||
use embassy_futures::select::{select3, Either3};
|
||||
use embassy_net::{Runner, StackResources};
|
||||
use embassy_time::{Duration, Timer};
|
||||
use projekt_final::bus::I2cInner;
|
||||
|
||||
use esp_alloc as _;
|
||||
use esp_backtrace as _;
|
||||
use esp_hal::{clock::CpuClock, rng::Rng, timer::timg::TimerGroup};
|
||||
|
||||
use esp_hal::{
|
||||
clock::CpuClock,
|
||||
i2c::master::{Config as I2cConfig, I2c},
|
||||
rng::Rng,
|
||||
timer::timg::TimerGroup,
|
||||
};
|
||||
use esp_wifi::{
|
||||
init,
|
||||
wifi::{ClientConfiguration, Configuration, WifiController, WifiDevice, WifiEvent, WifiState},
|
||||
EspWifiController,
|
||||
};
|
||||
|
||||
use log::info;
|
||||
use rust_mqtt::packet::v5::publish_packet::QualityOfService;
|
||||
use projekt_final::mqtt::client::{
|
||||
mqtt_events, mqtt_publish, mqtt_subscribe, mqtt_task, IncomingMsg,
|
||||
use static_cell::StaticCell;
|
||||
use core::cell::RefCell;
|
||||
|
||||
// Our crate
|
||||
use projekt_final::{
|
||||
bus,
|
||||
display,
|
||||
mpu,
|
||||
mqtt::client::{mqtt_events, mqtt_publish, mqtt_subscribe, mqtt_task, IncomingMsg},
|
||||
};
|
||||
use projekt_final::i2c::com::i2c_check;
|
||||
use projekt_final::i2c::com::display_task;
|
||||
use defmt_rtt as _;
|
||||
|
||||
extern crate alloc;
|
||||
use alloc::format;
|
||||
|
||||
esp_bootloader_esp_idf::esp_app_desc!();
|
||||
static I2C_BUS: StaticCell<RefCell<I2cInner>> = StaticCell::new();
|
||||
|
||||
macro_rules! mk_static {
|
||||
($t:ty,$val:expr) => {{
|
||||
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
|
||||
#[deny(unused_attributes)]
|
||||
let x = STATIC_CELL.uninit().write(($val));
|
||||
x
|
||||
($t:ty, $val:expr) => {{
|
||||
static STATIC_CELL: StaticCell<$t> = StaticCell::new();
|
||||
STATIC_CELL.init($val)
|
||||
}};
|
||||
}
|
||||
|
||||
const SSID: &str = env!("SSID");
|
||||
const PASSWORD: &str = env!("PASSWORD");
|
||||
const MQTT_PUBLISH_DIVIDER: u32 = 10;
|
||||
|
||||
esp_bootloader_esp_idf::esp_app_desc!();
|
||||
|
||||
#[esp_hal_embassy::main]
|
||||
async fn main(spawner: Spawner) -> ! {
|
||||
esp_println::logger::init_logger_from_env();
|
||||
info!("═══════════════════════════════════════════════════════════");
|
||||
info!(" ESP32 IoT Firmware Starting");
|
||||
info!("═══════════════════════════════════════════════════════════");
|
||||
|
||||
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
|
||||
let peripherals = esp_hal::init(config);
|
||||
|
||||
esp_alloc::heap_allocator!(size: 72 * 1024);
|
||||
|
||||
info!("Initializing I2C bus...");
|
||||
let i2c = I2c::new(peripherals.I2C0, I2cConfig::default())
|
||||
.expect("Failed to create I2C instance")
|
||||
.with_sda(peripherals.GPIO21)
|
||||
.with_scl(peripherals.GPIO22)
|
||||
.into_async();
|
||||
|
||||
let i2c_bus = I2C_BUS.init(RefCell::new(i2c));
|
||||
let display_i2c = bus::new_device(i2c_bus);
|
||||
let mpu_i2c = bus::new_device(i2c_bus);
|
||||
|
||||
info!("Initializing WiFi...");
|
||||
let timg0 = TimerGroup::new(peripherals.TIMG0);
|
||||
let mut rng = Rng::new(peripherals.RNG);
|
||||
|
||||
let esp_wifi_ctrl = &*mk_static!(
|
||||
let esp_wifi_ctrl = mk_static!(
|
||||
EspWifiController<'static>,
|
||||
init(timg0.timer0, rng.clone()).unwrap()
|
||||
esp_wifi::init(timg0.timer0, rng.clone()).unwrap()
|
||||
);
|
||||
|
||||
let (controller, interfaces) =
|
||||
esp_wifi::wifi::new(&esp_wifi_ctrl, peripherals.WIFI).unwrap();
|
||||
esp_wifi::wifi::new(esp_wifi_ctrl, peripherals.WIFI).unwrap();
|
||||
|
||||
let wifi_interface = interfaces.sta;
|
||||
|
||||
let timg1 = TimerGroup::new(peripherals.TIMG1);
|
||||
esp_hal_embassy::init(timg1.timer0);
|
||||
|
||||
let config = embassy_net::Config::dhcpv4(Default::default());
|
||||
|
||||
let net_config = embassy_net::Config::dhcpv4(Default::default());
|
||||
let seed = (rng.random() as u64) << 32 | rng.random() as u64;
|
||||
|
||||
// Init network stack
|
||||
let (stack, runner) = embassy_net::new(
|
||||
wifi_interface,
|
||||
config,
|
||||
net_config,
|
||||
mk_static!(StackResources<3>, StackResources::<3>::new()),
|
||||
seed,
|
||||
);
|
||||
|
||||
spawner.spawn(connection(controller)).ok();
|
||||
spawner.spawn(net_task(runner)).ok();
|
||||
spawner.spawn(connection_task(controller)).expect("spawn connection_task");
|
||||
spawner.spawn(net_task(runner)).expect("spawn net_task");
|
||||
|
||||
wait_for_network(stack).await;
|
||||
|
||||
spawner.spawn(mqtt_task(stack)).expect("spawn mqtt_task");
|
||||
spawner.spawn(display::task::display_task(display_i2c)).expect("spawn display_task");
|
||||
spawner.spawn(mpu::task::mpu_task(mpu_i2c)).expect("spawn mpu_task");
|
||||
|
||||
display::api::set_status("Booting...").await;
|
||||
mqtt_subscribe("esp32/cmd").await;
|
||||
mqtt_publish("esp32/status", b"online", QualityOfService::QoS1, false).await;
|
||||
|
||||
display::api::set_status("Running").await;
|
||||
display::api::set_mqtt_status(true, 0).await;
|
||||
|
||||
let mqtt_rx = mqtt_events();
|
||||
let imu_rx = mpu::api::events();
|
||||
let mut imu_reading_count: u32 = 0;
|
||||
let mut mqtt_msg_count: u32 = 0;
|
||||
|
||||
// Wait for link up
|
||||
loop {
|
||||
if stack.is_link_up() {
|
||||
break;
|
||||
match select3(
|
||||
mqtt_rx.receive(),
|
||||
imu_rx.receive(),
|
||||
Timer::after(Duration::from_secs(30)),
|
||||
).await {
|
||||
Either3::First(msg) => {
|
||||
mqtt_msg_count += 1;
|
||||
handle_mqtt_message(msg).await;
|
||||
display::api::set_mqtt_status(true, mqtt_msg_count).await;
|
||||
}
|
||||
Either3::Second(reading) => {
|
||||
imu_reading_count += 1;
|
||||
display::api::show_imu(reading).await;
|
||||
if imu_reading_count % MQTT_PUBLISH_DIVIDER == 0 {
|
||||
let payload = format!(
|
||||
"{{\"ax\":{:.2},\"ay\":{:.2},\"az\":{:.2},\"t\":{:.1}}}",
|
||||
reading.accel_g[0], reading.accel_g[1], reading.accel_g[2], reading.temp_c
|
||||
);
|
||||
mqtt_publish("esp32/imu", payload.as_bytes(), QualityOfService::QoS0, false).await;
|
||||
}
|
||||
}
|
||||
Either3::Third(_) => {
|
||||
info!("Heartbeat: {} IMU readings", imu_reading_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn wait_for_network(stack: embassy_net::Stack<'static>) {
|
||||
loop {
|
||||
if stack.is_link_up() { break; }
|
||||
Timer::after(Duration::from_millis(500)).await;
|
||||
}
|
||||
|
||||
info!("Waiting to get IP address...");
|
||||
loop {
|
||||
if let Some(config) = stack.config_v4() {
|
||||
info!("Got IP: {}", config.address);
|
||||
@@ -99,63 +168,24 @@ async fn main(spawner: Spawner) -> ! {
|
||||
}
|
||||
Timer::after(Duration::from_millis(500)).await;
|
||||
}
|
||||
}
|
||||
|
||||
spawner.spawn(mqtt_task(stack)).expect("failed to spawn MQTT task");
|
||||
info!("MQTT task started");
|
||||
|
||||
spawner.spawn(display_task()).expect("failed to spawn Display task");
|
||||
info!("I2C scan task started");
|
||||
|
||||
mqtt_publish("esp32/topic", b"hello from ESP32 (init)", QualityOfService::QoS1, false).await;
|
||||
info!("Sent initial MQTT message");
|
||||
|
||||
mqtt_subscribe("esp32/topic").await;
|
||||
|
||||
// Get a receiver for incoming MQTT messages
|
||||
let mqtt_rx = mqtt_events();
|
||||
|
||||
loop {
|
||||
// Drive both: either process an MQTT message or publish periodically
|
||||
match select(mqtt_rx.receive(), Timer::after(Duration::from_secs(5))).await
|
||||
{
|
||||
// Received inbound MQTT message (from broker)
|
||||
Either::First(msg) => {
|
||||
handle_incoming(msg);
|
||||
}
|
||||
// Time-based example publish
|
||||
Either::Second(_) => {
|
||||
// mqtt_publish(
|
||||
// "esp32/topic",
|
||||
// b"hello from main",
|
||||
// QualityOfService::QoS1,
|
||||
// false,
|
||||
// )
|
||||
// .await;
|
||||
}
|
||||
async fn handle_mqtt_message(msg: IncomingMsg) {
|
||||
if let Ok(txt) = core::str::from_utf8(&msg.payload) {
|
||||
match txt {
|
||||
"clear" => { display::api::clear().await; }
|
||||
"status" => { mqtt_publish("esp32/status", b"running", QualityOfService::QoS1, false).await; }
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_incoming(msg: IncomingMsg) {
|
||||
if let Ok(txt) = core::str::from_utf8(&msg.payload) {
|
||||
info!("MAIN RX [{}]: {}", msg.topic.as_str(), txt);
|
||||
info!("Received MQTT message -> topic: '{}', payload: '{}'", msg.topic.as_str(), txt);
|
||||
} else {
|
||||
info!("MAIN RX [{}]: {:?}", msg.topic.as_str(), msg.payload);
|
||||
}
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn connection(mut controller: WifiController<'static>) {
|
||||
info!("start connection task");
|
||||
info!("Device capabilities: {:?}", controller.capabilities());
|
||||
async fn connection_task(mut controller: WifiController<'static>) {
|
||||
loop {
|
||||
match esp_wifi::wifi::wifi_state() {
|
||||
WifiState::StaConnected => {
|
||||
controller.wait_for_event(WifiEvent::StaDisconnected).await;
|
||||
Timer::after(Duration::from_millis(5000)).await
|
||||
}
|
||||
_ => {}
|
||||
if esp_wifi::wifi::wifi_state() == WifiState::StaConnected {
|
||||
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 {
|
||||
@@ -164,18 +194,13 @@ async fn connection(mut controller: WifiController<'static>) {
|
||||
..Default::default()
|
||||
});
|
||||
controller.set_configuration(&client_config).unwrap();
|
||||
info!("Starting wifi");
|
||||
info!("Wi-Fi starting...");
|
||||
controller.start_async().await.unwrap();
|
||||
info!("Wifi started!");
|
||||
}
|
||||
info!("About to connect...");
|
||||
|
||||
match controller.connect_async().await {
|
||||
Ok(_) => info!("Wifi connected!"),
|
||||
Err(e) => {
|
||||
info!("Failed to connect to wifi: {e:?}");
|
||||
Timer::after(Duration::from_millis(5000)).await
|
||||
}
|
||||
if let Err(e) = controller.connect_async().await {
|
||||
info!("Wi-Fi reconnect failed: {:?}", e);
|
||||
} else {
|
||||
info!("Wi-Fi connected.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user