charge controller page#54
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new “Charge Controller” workspace widget and expands the theming system (including a OneDark theme) to provide semantic colors that widgets can reuse across the UI.
Changes:
- Introduces a
ChargeControllerwidget (spawnable from the sidebar / command palette) with CAN-driven status/fault display and command sending. - Extends theming with a OneDark TOML and adds semantic theme colors stored in egui context for global access.
- Adjusts CAN extended-ID handling and UDP ID parsing to better preserve extended-vs-standard identity.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| themes/onedark.toml | Adds OneDark theme color definitions (including semantic colors). |
| src/workspace.rs | Tracks Charge Controller open-state and clears it when the tab is closed. |
| src/widgets.rs | Registers the new ChargeController widget and routes show/message handling. |
| src/ui/sidebar.rs | Adds “Add Charge Controller” button; uses theme semantic colors for connection status. |
| src/ui/mod.rs | Exposes the new charge_controller module. |
| src/ui/charge_controller.rs | Implements the Charge Controller UI, CAN parsing, and command send/stop behavior. |
| src/theme.rs | Adds OneDark selection, semantic colors, and egui-context storage/getters for theme colors. |
| src/can/thread.rs | Restores an extended-ID flag on received extended CAN IDs before DBC decode. |
| src/can/driver.rs | Enables UDP socket nonblocking mode; uses explicit isExtID bit when parsing UDP identity. |
| src/app.rs | Prevents multiple Charge Controller widgets; stores theme colors globally each frame. |
| src/action.rs | Adds WidgetType::ChargeController to spawn actions / command palette list. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
LelsersLasers
left a comment
There was a problem hiding this comment.
Reviewing on my phone so some comments may be dumb
b245ed7 to
0dcd7da
Compare
LelsersLasers
left a comment
There was a problem hiding this comment.
If it works it looks good to me 🔋 📈
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 9 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…id flag and the 29 bit version
9b64bd4 to
2013c65
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let crm_id = util::msg_id::can_dbc_to_u32_with_extid_flag( | ||
| &crm.as_ref().expect("Charge request message not found").id, | ||
| ); | ||
|
|
||
| self.active_msg_id = Some(crm_id); | ||
|
|
||
| let is_extended = matches!( | ||
| &crm.as_ref().expect("Charge request message not found").id, | ||
| can_dbc::MessageId::Extended(_) | ||
| ); | ||
|
|
||
| let signal_values: std::collections::HashMap<String, f64> = vec![ | ||
| ( | ||
| "charge_voltage".to_string(), | ||
| (self.max_charge_voltage as f64), | ||
| ), | ||
| ( | ||
| "charge_current".to_string(), | ||
| (self.max_charge_current as f64), | ||
| ), | ||
| ("charge_enable".to_string(), self.charge_enable as u8 as f64), | ||
| ( | ||
| "balance_enable".to_string(), | ||
| self.balance_enable as u8 as f64, | ||
| ), | ||
| ] | ||
| .into_iter() | ||
| .collect(); | ||
|
|
||
| let Some(msg_bytes) = parser.parser.encode_msg(crm_id, &signal_values) else { | ||
| log::error!("Failed to encode charge_request"); | ||
| return; | ||
| }; | ||
|
|
||
| ui_to_can_tx | ||
| .send(messages::MsgFromUi::AddSendMessage( | ||
| messages::AddSendMessage { | ||
| amount: messages::SendAmount::Infinite { | ||
| period: self.request_msg_period, | ||
| }, | ||
| msg_id: crm_id, | ||
| is_msg_id_extended: is_extended, | ||
| msg_bytes, |
| fn stop_charge_request( | ||
| &self, | ||
| ui_to_can_tx: &std::sync::mpsc::Sender<messages::MsgFromUi>, | ||
| parser: &app::ParserInfo, | ||
| ) { | ||
| // find charge_request message definition | ||
| let crm = parser | ||
| .parser | ||
| .msg_defs() | ||
| .into_iter() | ||
| .find(|m| m.name == "charge_request"); | ||
|
|
||
| let crm_id = util::msg_id::can_dbc_to_u32_with_extid_flag( | ||
| &crm.as_ref().expect("Charge request message not found").id, | ||
| ); | ||
| ui_to_can_tx | ||
| .send(messages::MsgFromUi::DeleteSendMessage { msg_id: crm_id }) | ||
| .expect("Failed to send DeleteSendMessage"); |
| } | ||
| "charge_current" => { | ||
| if let can_decode::DecodedSignalValue::Numeric(v) = &signal.value { | ||
| self.charge_current_raw = *v as u16; |
| pub fn new( | ||
| can_to_ui_rx: std::sync::mpsc::Receiver<messages::MsgFromCan>, | ||
| ui_to_can_tx: std::sync::mpsc::Sender<messages::MsgFromUi>, | ||
| settings: settings::Settings, | ||
| _cc: &eframe::CreationContext, | ||
| ) -> Self { | ||
| let theme_selection = settings.theme; | ||
| let theme_style = theme_selection.get_style(); | ||
| let theme_colors = theme_selection.get_colors(); | ||
|
|
||
| Self { | ||
| connection_status: ConnectionStatus::Disconnected, | ||
| is_sidebar_open: true, | ||
| command_palette: ui::command_palette::CommandPalette::new(), | ||
| tile_tree: egui_tiles::Tree::empty("workspace_tree"), | ||
| next_can_viewer_num: 1, | ||
| next_can_list_num: 1, | ||
| next_bootloader_num: 1, | ||
| next_scope_num: 1, | ||
| next_log_parser_num: 1, | ||
| next_send_ui_num: 1, | ||
| next_bus_load_num: 1, | ||
| is_charge_controller_open: false, | ||
| next_battery_viewer_num: 1, | ||
| can_to_ui_rx, | ||
| ui_to_can_tx, | ||
| action_queue: Vec::new(), | ||
| selected_source: settings.selected_source, | ||
| theme: theme_style, | ||
| theme_selection, | ||
| pixels_per_point: settings.pixels_per_point, | ||
| serial_ports: util::get_available_serial_ports(), | ||
| parser: ParserInfo::new_maybe(settings.dbc_path), | ||
| udp_port: settings.udp_port, | ||
| can_messages: Vec::new(), | ||
| theme_colors, | ||
| } | ||
| } |
| if let Some(egui_tiles::Tile::Pane(_)) = self.tile_tree.tiles.get(tile_id) { | ||
| if let Some(egui_tiles::Tile::Pane(widget)) = self.tile_tree.tiles.get(tile_id) { | ||
| if matches!(widget, widgets::Widget::ChargeController(_)) { | ||
| log::info!("Closing Charge Controlller"); |
| socket.set_nonblocking(true).map_err(|e| { | ||
| DriverError::ConnectionFailed(format!("Unable to set nonblocking mode: {}", e)) | ||
| })?; |
Uh oh!
There was an error while loading. Please reload this page.