fix: Macro list/save uses binary protocol (LIST_MACROS 0x30)

Firmware v2 doesn't respond to text "MACROS?" query.
Now uses binary LIST_MACROS (0x30) for refresh, with proper
parse_macros_binary() for the response payload.
Save still uses text MACROSEQ, then binary refresh after 100ms.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mae PUGIN 2026-04-07 12:34:40 +02:00
parent 0813e8531f
commit b4ab9af18b

View file

@ -20,7 +20,8 @@ enum BgMsg {
TextLines(String, Vec<String>), // tag, lines TextLines(String, Vec<String>), // tag, lines
HeatmapData(Vec<Vec<u32>>, u32), // counts, max HeatmapData(Vec<Vec<u32>>, u32), // counts, max
BigramLines(Vec<String>), BigramLines(Vec<String>),
LayoutJson(Vec<KeycapPos>), // physical key positions from firmware LayoutJson(Vec<KeycapPos>),
MacroList(Vec<logic::parsers::MacroEntry>),
FlashProgress(f32, String), // progress 0-1, status message FlashProgress(f32, String), // progress 0-1, status message
FlashDone(Result<(), String>), FlashDone(Result<(), String>),
} }
@ -1170,8 +1171,16 @@ fn main() {
let tx = tx.clone(); let tx = tx.clone();
std::thread::spawn(move || { std::thread::spawn(move || {
let mut ser = serial.lock().unwrap_or_else(|e| e.into_inner()); let mut ser = serial.lock().unwrap_or_else(|e| e.into_inner());
let lines = ser.query_command("MACROS?").unwrap_or_default(); if ser.v2 {
let _ = tx.send(BgMsg::TextLines("macros".into(), lines)); if let Ok(resp) = ser.send_binary(logic::binary_protocol::cmd::LIST_MACROS, &[]) {
let macros = logic::parsers::parse_macros_binary(&resp.payload);
let _ = tx.send(BgMsg::MacroList(macros));
}
} else {
let lines = ser.query_command("MACROS?").unwrap_or_default();
let macros = logic::parsers::parse_macro_lines(&lines);
let _ = tx.send(BgMsg::MacroList(macros));
}
}); });
}); });
} }
@ -1236,8 +1245,11 @@ fn main() {
std::thread::spawn(move || { std::thread::spawn(move || {
let mut ser = serial.lock().unwrap_or_else(|e| e.into_inner()); let mut ser = serial.lock().unwrap_or_else(|e| e.into_inner());
let _ = ser.send_command(&cmd); let _ = ser.send_command(&cmd);
let lines = ser.query_command("MACROS?").unwrap_or_default(); std::thread::sleep(std::time::Duration::from_millis(100));
let _ = tx.send(BgMsg::TextLines("macros".into(), lines)); if let Ok(resp) = ser.send_binary(logic::binary_protocol::cmd::LIST_MACROS, &[]) {
let macros = logic::parsers::parse_macros_binary(&resp.payload);
let _ = tx.send(BgMsg::MacroList(macros));
}
}); });
w.global::<AppState>().set_status_text( w.global::<AppState>().set_status_text(
SharedString::from(format!("Saving macro #{}...", slot_num)) SharedString::from(format!("Saving macro #{}...", slot_num))
@ -1664,6 +1676,22 @@ fn main() {
_ => {} _ => {}
} }
} }
BgMsg::MacroList(macros) => {
let model: Vec<MacroData> = macros.iter().map(|m| {
let steps_str: Vec<String> = m.steps.iter().map(|s| {
if s.is_delay() { format!("T({})", s.delay_ms()) }
else { format!("{}", keycode::hid_key_name(s.keycode)) }
}).collect();
MacroData {
slot: m.slot as i32,
name: SharedString::from(&m.name),
steps: SharedString::from(steps_str.join(" ")),
}
}).collect();
window.global::<MacroBridge>().set_macros(
ModelRc::from(Rc::new(VecModel::from(model)))
);
}
} }
} }
}, },