From 420f739088bfebeb2df2e80df6306eddf3d81f56 Mon Sep 17 00:00:00 2001 From: Aleksandr Karavaev Date: Thu, 17 Apr 2025 23:34:46 +0200 Subject: [PATCH 1/2] feat: add boster-leds keep-on mode for mcu-util and set brightenss through cli --- mcu-util/src/main.rs | 21 +++- mcu-util/src/orb/main_board.rs | 204 +++++++++++++++++---------------- 2 files changed, 122 insertions(+), 103 deletions(-) diff --git a/mcu-util/src/main.rs b/mcu-util/src/main.rs index 63a6fdf6..484ab7f1 100644 --- a/mcu-util/src/main.rs +++ b/mcu-util/src/main.rs @@ -163,12 +163,22 @@ enum Camera { Face, } -/// Optics tests options +/// UI control options #[derive(Parser, Debug, Clone, Copy)] enum UiOpts { - /// Test front leds for 3 seconds + /// Control RGB LEDs (ring LEDs) #[clap(subcommand)] - Front(Leds), + RgbLed(Leds), + /// Control white booster LEDs (brightness 0-1000) + #[clap(action)] + Booster { + /// Brightness value (0-1000) + #[clap(short, long, default_value = "1000")] + brightness: u32, + /// Keep LEDs on (do not auto turn off after 3 seconds) + #[clap(short, long, default_value = "false")] + keep_on: bool, + }, } #[derive(Parser, Debug, Clone, Copy)] @@ -181,8 +191,6 @@ enum Leds { Blue, #[clap(action)] White, - #[clap(action)] - Booster, } /// Optics position @@ -304,7 +312,8 @@ async fn execute(args: Args) -> Result<()> { } }, SubCommand::Ui(opts) => match opts { - UiOpts::Front(leds) => orb.main_board_mut().front_leds(leds).await?, + UiOpts::RgbLed(leds) => orb.main_board_mut().front_leds(leds).await?, + UiOpts::Booster { brightness, keep_on } => orb.main_board_mut().white_leds(brightness, keep_on).await?, }, } diff --git a/mcu-util/src/orb/main_board.rs b/mcu-util/src/orb/main_board.rs index 3febcd6b..7c7dd45c 100644 --- a/mcu-util/src/orb/main_board.rs +++ b/mcu-util/src/orb/main_board.rs @@ -283,126 +283,136 @@ impl MainBoard { Ok(()) } - pub async fn front_leds(&mut self, leds: Leds) -> Result<()> { - if let Leds::Booster = leds { - match self - .isotp_iface - .send(McuPayload::ToMain( - main_messaging::jetson_to_mcu::Payload::WhiteLedsBrightness( - main_messaging::WhiteLeDsBrightness { brightness: 5 }, - ), - )) - .await - { - Ok(CommonAckError::Success) => { - info!("🚀 Booster LEDs enabled"); - } - Ok(e) => { - return Err(eyre!("Error enabling booster LEDs: ack {:?}", e)); - } - Err(e) => { - return Err(eyre!("Error enabling booster LEDs: {:?}", e)); + pub async fn white_leds(&mut self, brightness: u32, keep_on: bool) -> Result<()> { + // Cap brightness at 1000 + let brightness = std::cmp::min(brightness, 1000); + + // Send the command to set white LED brightness + match self + .isotp_iface + .send(McuPayload::ToMain( + main_messaging::jetson_to_mcu::Payload::WhiteLedsBrightness( + main_messaging::WhiteLeDsBrightness { brightness }, + ), + )) + .await + { + Ok(CommonAckError::Success) => { + if brightness > 0 { + info!("💡 White/booster LEDs set to brightness: {}", brightness); + } else { + info!("White/booster LEDs turned off"); } } - } else { - let pattern = match leds { - Leds::Red => { - main_messaging::user_le_ds_pattern::UserRgbLedPattern::AllRed - } - Leds::Green => { - main_messaging::user_le_ds_pattern::UserRgbLedPattern::AllGreen - } - Leds::Blue => { - main_messaging::user_le_ds_pattern::UserRgbLedPattern::AllBlue - } - Leds::White => { - main_messaging::user_le_ds_pattern::UserRgbLedPattern::AllWhite - } - _ => { - error!("Invalid rgb color"); - return Err(eyre!("Invalid LEDs")); - } - }; + Ok(e) => { + return Err(eyre!("Error setting white/booster LEDs brightness: ack {:?}", e)); + } + Err(e) => { + return Err(eyre!("Error setting white/booster LEDs brightness: {:?}", e)); + } + } + // Turn off after 3 seconds if keep_on is false + if !keep_on && brightness > 0 { + info!("LEDs will turn off in 3 seconds... (use --keep-on to keep them on)"); + tokio::time::sleep(Duration::from_millis(3000)).await; + match self .isotp_iface .send(McuPayload::ToMain( - main_messaging::jetson_to_mcu::Payload::UserLedsPattern( - main_messaging::UserLeDsPattern { - pattern: pattern as i32, - custom_color: None, - start_angle: 0, - angle_length: 360, - pulsing_scale: 0.0, - pulsing_period_ms: 0, - }, + main_messaging::jetson_to_mcu::Payload::WhiteLedsBrightness( + main_messaging::WhiteLeDsBrightness { brightness: 0 }, ), )) .await { Ok(CommonAckError::Success) => { - info!("🚦 {:?} enabled", pattern); + info!("White/booster LEDs turned off"); } Ok(e) => { - return Err(eyre!("Error enabling green LEDs: ack {:?}", e)); + return Err(eyre!("Error turning off white/booster LEDs: ack {:?}", e)); } Err(e) => { - return Err(eyre!("Error enabling green LEDs: {:?}", e)); + return Err(eyre!("Error turning off white/booster LEDs: {:?}", e)); } } } + Ok(()) + } + + pub async fn front_leds(&mut self, leds: Leds) -> Result<()> { + let pattern = match leds { + Leds::Red => { + main_messaging::user_le_ds_pattern::UserRgbLedPattern::AllRed + } + Leds::Green => { + main_messaging::user_le_ds_pattern::UserRgbLedPattern::AllGreen + } + Leds::Blue => { + main_messaging::user_le_ds_pattern::UserRgbLedPattern::AllBlue + } + Leds::White => { + main_messaging::user_le_ds_pattern::UserRgbLedPattern::AllWhite + } + }; + + match self + .isotp_iface + .send(McuPayload::ToMain( + main_messaging::jetson_to_mcu::Payload::UserLedsPattern( + main_messaging::UserLeDsPattern { + pattern: pattern as i32, + custom_color: None, + start_angle: 0, + angle_length: 360, + pulsing_scale: 0.0, + pulsing_period_ms: 0, + }, + ), + )) + .await + { + Ok(CommonAckError::Success) => { + info!("🚦 RGB LEDs {:?} enabled", pattern); + } + Ok(e) => { + return Err(eyre!("Error enabling RGB LEDs: ack {:?}", e)); + } + Err(e) => { + return Err(eyre!("Error enabling RGB LEDs: {:?}", e)); + } + } + // turn off all LEDs after 3 seconds tokio::time::sleep(Duration::from_millis(3000)).await; - if let Leds::Booster = leds { - match self - .isotp_iface - .send(McuPayload::ToMain( - main_messaging::jetson_to_mcu::Payload::WhiteLedsBrightness( - main_messaging::WhiteLeDsBrightness { brightness: 0 }, - ), - )) - .await - { - Ok(CommonAckError::Success) => { - info!("LEDs disabled"); - } - Ok(e) => { - return Err(eyre!("Error disabling booster LEDs: ack {:?}", e)); - } - Err(e) => { - return Err(eyre!("Error disabling booster LEDs: {:?}", e)); - } + match self + .isotp_iface + .send(McuPayload::ToMain( + main_messaging::jetson_to_mcu::Payload::UserLedsPattern( + main_messaging::UserLeDsPattern { + pattern: + main_messaging::user_le_ds_pattern::UserRgbLedPattern::Off + as i32, + custom_color: None, + start_angle: 0, + angle_length: 360, + pulsing_scale: 0.0, + pulsing_period_ms: 0, + }, + ), + )) + .await + { + Ok(CommonAckError::Success) => { + info!("RGB LEDs disabled"); } - } else { - match self - .isotp_iface - .send(McuPayload::ToMain( - main_messaging::jetson_to_mcu::Payload::UserLedsPattern( - main_messaging::UserLeDsPattern { - pattern: - main_messaging::user_le_ds_pattern::UserRgbLedPattern::Off - as i32, - custom_color: None, - start_angle: 0, - angle_length: 360, - pulsing_scale: 0.0, - pulsing_period_ms: 0, - }, - ), - )) - .await - { - Ok(CommonAckError::Success) => { - info!("LEDs disabled"); - } - Ok(e) => { - return Err(eyre!("Error disabling RGB LEDs: ack {:?}", e)); - } - Err(e) => { - return Err(eyre!("Error disabling RGB LEDs: {:?}", e)); - } + Ok(e) => { + return Err(eyre!("Error disabling RGB LEDs: ack {:?}", e)); + } + Err(e) => { + return Err(eyre!("Error disabling RGB LEDs: {:?}", e)); } } From bed9a7643f4ed9199d3e03d18bd31278c869ca7f Mon Sep 17 00:00:00 2001 From: Aleksandr Karavaev Date: Thu, 17 Apr 2025 23:39:54 +0200 Subject: [PATCH 2/2] format --- mcu-util/src/main.rs | 5 ++++- mcu-util/src/orb/main_board.rs | 27 +++++++++++++++++---------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/mcu-util/src/main.rs b/mcu-util/src/main.rs index 484ab7f1..cdb49068 100644 --- a/mcu-util/src/main.rs +++ b/mcu-util/src/main.rs @@ -313,7 +313,10 @@ async fn execute(args: Args) -> Result<()> { }, SubCommand::Ui(opts) => match opts { UiOpts::RgbLed(leds) => orb.main_board_mut().front_leds(leds).await?, - UiOpts::Booster { brightness, keep_on } => orb.main_board_mut().white_leds(brightness, keep_on).await?, + UiOpts::Booster { + brightness, + keep_on, + } => orb.main_board_mut().white_leds(brightness, keep_on).await?, }, } diff --git a/mcu-util/src/orb/main_board.rs b/mcu-util/src/orb/main_board.rs index 7c7dd45c..5e70b117 100644 --- a/mcu-util/src/orb/main_board.rs +++ b/mcu-util/src/orb/main_board.rs @@ -286,7 +286,7 @@ impl MainBoard { pub async fn white_leds(&mut self, brightness: u32, keep_on: bool) -> Result<()> { // Cap brightness at 1000 let brightness = std::cmp::min(brightness, 1000); - + // Send the command to set white LED brightness match self .isotp_iface @@ -305,10 +305,16 @@ impl MainBoard { } } Ok(e) => { - return Err(eyre!("Error setting white/booster LEDs brightness: ack {:?}", e)); + return Err(eyre!( + "Error setting white/booster LEDs brightness: ack {:?}", + e + )); } Err(e) => { - return Err(eyre!("Error setting white/booster LEDs brightness: {:?}", e)); + return Err(eyre!( + "Error setting white/booster LEDs brightness: {:?}", + e + )); } } @@ -316,7 +322,7 @@ impl MainBoard { if !keep_on && brightness > 0 { info!("LEDs will turn off in 3 seconds... (use --keep-on to keep them on)"); tokio::time::sleep(Duration::from_millis(3000)).await; - + match self .isotp_iface .send(McuPayload::ToMain( @@ -330,7 +336,10 @@ impl MainBoard { info!("White/booster LEDs turned off"); } Ok(e) => { - return Err(eyre!("Error turning off white/booster LEDs: ack {:?}", e)); + return Err(eyre!( + "Error turning off white/booster LEDs: ack {:?}", + e + )); } Err(e) => { return Err(eyre!("Error turning off white/booster LEDs: {:?}", e)); @@ -343,9 +352,7 @@ impl MainBoard { pub async fn front_leds(&mut self, leds: Leds) -> Result<()> { let pattern = match leds { - Leds::Red => { - main_messaging::user_le_ds_pattern::UserRgbLedPattern::AllRed - } + Leds::Red => main_messaging::user_le_ds_pattern::UserRgbLedPattern::AllRed, Leds::Green => { main_messaging::user_le_ds_pattern::UserRgbLedPattern::AllGreen } @@ -393,8 +400,8 @@ impl MainBoard { main_messaging::jetson_to_mcu::Payload::UserLedsPattern( main_messaging::UserLeDsPattern { pattern: - main_messaging::user_le_ds_pattern::UserRgbLedPattern::Off - as i32, + main_messaging::user_le_ds_pattern::UserRgbLedPattern::Off + as i32, custom_color: None, start_angle: 0, angle_length: 360,