summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerguey Parkhomovsky <xindigo@gmail.com>2026-03-21 17:33:46 -0700
committerSerguey Parkhomovsky <xindigo@gmail.com>2026-03-21 17:33:46 -0700
commite008298187c3dc57f37e9511763e9e35d7dca80b (patch)
tree359ad1081a285cd94dad1709fcc341d468000107
parent12fe7e6d05e7fdcb0d9925e55a5f0fed17718341 (diff)
Separate some fields into prusa and bambu structs
-rw-r--r--TODO.md12
-rw-r--r--src/lib.rs58
2 files changed, 50 insertions, 20 deletions
diff --git a/TODO.md b/TODO.md
index 4640904..5a213c7 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1 +1,13 @@
# TODO
+
+Example requests:
+
+2026-03-21T23:55:38.281622Z DEBUG printstats: Received Bambu payload payload=b"{\"print\":{\"upgrade_state\":{\"sequence_id\":0,\"progress\":\"\",\"status\":\"IDLE\",\"consistency_request\":false,\"dis_state\":0,\"err_code\":0,\"force_upgrade\":false,\"message\":\"0%, 0B/s\",\"module\":\"\",\"new_version_state\":0,\"cur_state_code\":1,\"idx2\":2259839987,\"new_ver_list\":[]},\"ipcam\":{\"ipcam_dev\":\"1\",\"ipcam_record\":\"enable\",\"timelapse\":\"enable\",\"resolution\":\"\",\"tutk_server\":\"disable\",\"mode_bits\":3},\"upload\":{\"status\":\"idle\",\"progress\":0,\"message\":\"\"},\"net\":{\"conf\":0,\"info\":[{\"ip\":1090627776,\"mask\":16777215}]},\"nozzle_temper\":109.125,\"nozzle_target_temper\":80,\"bed_temper\":65.03125,\"bed_target_temper\":65,\"chamber_temper\":5,\"mc_print_stage\":\"3\",\"heatbreak_fan_speed\":\"15\",\"cooling_fan_speed\":\"15\",\"big_fan1_speed\":\"12\",\"big_fan2_speed\":\"8\",\"mc_percent\":45,\"mc_remaining_time\":24,\"ams_status\":768,\"ams_rfid_status\":0,\"hw_switch_state\":0,\"spd_mag\":50,\"spd_lvl\":1,\"print_error\":50364420,\"lifecycle\":\"product\",\"wifi_signal\":\"-90dBm\",\"gcode_state\":\"PAUSE\",\"gcode_file_prepare_percent\":\"0\",\"queue_number\":0,\"queue_total\":0,\"queue_est\":0,\"queue_sts\":0,\"project_id\":\"0\",\"profile_id\":\"0\",\"task_id\":\"0\",\"subtask_id\":\"0\",\"subtask_name\":\"calicat\",\"gcode_file\":\"calicat.gcode.3mf\",\"stg\":[2,14,1],\"stg_cur\":0,\"print_type\":\"local\",\"home_flag\":6505751,\"mc_print_line_number\":\"0\",\"mc_print_sub_stage\":0,\"sdcard\":true,\"force_upgrade\":false,\"mess_production_state\":\"active\",\"layer_num\":33,\"total_layer_num\":173,\"s_obj\":[],\"filam_bak\":[],\"fan_gear\":9885695,\"nozzle_diameter\":\"0.4\",\"nozzle_type\":\"hardened_steel\",\"cali_version\":0,\"k\":\"0.0200\",\"flag3\":8843,\"hms\":[],\"online\":{\"ahb\":false,\"rfid\":false,\"version\":1459095491},\"ams\":{\"ams\":[],\"ams_exist_bits\":\"0\",\"tray_exist_bits\":\"0\",\"tray_is_bbl_bits\":\"0\",\"tray_tar\":\"254\",\"tray_now\":\"255\",\"tray_pre\":\"255\",\"tray_read_done_bits\":\"0\",\"tray_reading_bits\":\"0\",\"version\":2,\"insert_flag\":true,\"power_on_flag\":false},\"vt_tray\":{\"id\":\"254\",\"tag_uid\":\"0000000000000000\",\"tray_id_name\":\"\",\"tray_info_idx\":\"GFL99\",\"tray_type\":\"PLA\",\"tray_sub_brands\":\"\",\"tray_color\":\"F98C36FF\",\"tray_weight\":\"0\",\"tray_diameter\":\"0.00\",\"tray_temp\":\"0\",\"tray_time\":\"0\",\"bed_temp_type\":\"0\",\"bed_temp\":\"0\",\"nozzle_temp_max\":\"240\",\"nozzle_temp_min\":\"190\",\"xcam_info\":\"000000000000000000000000\",\"tray_uuid\":\"00000000000000000000000000000000\",\"remain\":0,\"k\":0.019999999552965164,\"n\":1,\"cali_idx\":-1},\"lights_report\":[{\"node\":\"chamber_light\",\"mode\":\"on\"}],\"command\":\"push_status\",\"msg\":0,\"sequence_id\":\"3768\"}}"
+
+{"job":{"id":1063,"progress":4.00,"time_remaining":0,"time_printing":213},"storage":{"path":"/usb/","name":"usb","read_only":false},"printer":{"state":"PRINTING","temp_bed":60.0,"target_bed":60.0,"temp_nozzle":232.5,"target_nozzle":230.0,"axis_z":15.0,"flow":100,"speed":100,"fan_hotend":3255,"fan_print":0}}
+
+{"id":1064,"state":"PRINTING","progress":17.00,"time_remaining":2520,"time_printing":530,"file":{"refs":{"icon":"/thumb/s/usb/theo/3DBENC~1.GCO","thumbnail":"/thumb/l/usb/theo/3DBENC~1.GCO","download":"/usb/theo/3DBENC~1.GCO"},"name":"3DBENC~1.GCO","display_name":"3DBenchy_0.2mm_PLA_Prusa MK4_51m1s.gcode","path":"/usb/theo","size":4027041,"m_timestamp":1774137908}}
+
+- [ ] Prusa outputs time in seconds, while bambu outputs time in minutes
+- [ ] Grab the job information for Prusa from job endpoint
+- [ ] Grab job info for Bambu too
diff --git a/src/lib.rs b/src/lib.rs
index ce2d40a..b704849 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -20,22 +20,32 @@ pub trait UpdateFrom<T> {
}
#[derive(Debug, Default, Serialize, Clone)]
+pub struct BambuPrinterState {
+ pub layer_num: u32,
+ pub total_layer_num: u32,
+ pub print_speed: Option<String>,
+}
+
+#[derive(Debug, Default, Serialize, Clone)]
+pub struct PrusaPrinterState {
+ pub flow: u32,
+ pub speed: u32,
+ pub fan_hotend: u32,
+ pub fan_print: u32,
+ pub time_printing: u32,
+}
+
+#[derive(Debug, Default, Serialize, Clone)]
pub struct PrinterState {
pub status: PrintStatus,
pub bed_temp: f32,
pub target_bed_temp: f32,
pub nozzle_temp: f32,
pub target_nozzle_temp: f32,
- pub flow: u32,
- pub speed: u32,
- pub fan_hotend: u32,
- pub fan_print: u32,
pub progress: f32,
pub time_remaining: u32,
- pub time_printing: u32,
- pub layer_num: u32,
- pub total_layer_num: u32,
- pub print_speed: Option<String>,
+ pub prusa: Option<PrusaPrinterState>,
+ pub bambu: Option<BambuPrinterState>,
}
#[derive(Debug, Deserialize)]
@@ -105,14 +115,16 @@ impl UpdateFrom<PrusaStatus> for PrinterState {
self.target_bed_temp = p.target_bed;
self.nozzle_temp = p.temp_nozzle;
self.target_nozzle_temp = p.target_nozzle;
- self.flow = p.flow;
- self.speed = p.speed;
- self.fan_hotend = p.fan_hotend;
- self.fan_print = p.fan_print;
+ self.prusa = Some(PrusaPrinterState {
+ flow: p.flow,
+ speed: p.speed,
+ fan_hotend: p.fan_hotend,
+ fan_print: p.fan_print,
+ time_printing: status.job.as_ref().map_or(0, |j| j.time_printing),
+ });
if let Some(job) = &status.job {
self.progress = job.progress;
self.time_remaining = job.time_remaining;
- self.time_printing = job.time_printing;
}
}
}
@@ -155,15 +167,21 @@ impl UpdateFrom<BambuStatus> for PrinterState {
self.progress = v as f32;
}
if let Some(v) = print.mc_remaining_time {
- self.time_remaining = v;
- }
- if let Some(v) = print.layer_num {
- self.layer_num = v;
+ // Bambu remaining time is in minutes
+ self.time_remaining = v * 60;
}
- if let Some(v) = print.total_layer_num {
- self.total_layer_num = v;
+ if print.layer_num.is_some() || print.total_layer_num.is_some() || print.print_speed.is_some() {
+ let bambu = self.bambu.get_or_insert_with(BambuPrinterState::default);
+ if let Some(v) = print.layer_num {
+ bambu.layer_num = v;
+ }
+ if let Some(v) = print.total_layer_num {
+ bambu.total_layer_num = v;
+ }
+ if print.print_speed.is_some() {
+ bambu.print_speed = print.print_speed.clone();
+ }
}
- self.print_speed = print.print_speed.clone();
if let Some(gcode_state) = &print.gcode_state {
self.status = match gcode_state {
BambuState::Prepare => PrintStatus::Prepare,