Skip to content

Commit 2bd91cf

Browse files
authored
New version (#16)
- New parser - Modify response message types - Fix errors
2 parents 642ca70 + 2253410 commit 2bd91cf

6 files changed

Lines changed: 226 additions & 45 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "xcontroller"
3-
version = "0.1.0"
3+
version = "0.1.1"
44
edition = "2021"
55

66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

src/commands.rs

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,36 @@ pub fn g_command(cmd: &str) -> Result<&str, Error> {
1717
| "M09" | "M10" | "M11" | "M16" | "M17" | "M18" | "M19" | "M20" | "M21" | "M22" | "M23"
1818
| "M24" | "M25" | "M26" | "M27" | "M28" | "M29" | "M30" | "M31" | "M32" | "M33" | "M34"
1919
| "M42" | "M43" | "M48" | "M73" | "M75" | "M76" | "M77" | "M78" | "M80" | "M81" | "M82"
20-
| "M83" | "M84" |"M85" | "M86" | "M87" | "M92" | "M100" | "M102" | "M104" | "M105" | "M106"
21-
| "M107" | "M108" | "M109" | "M110" | "M111" | "M112" | "M113" | "M114" | "M115"
22-
| "M117" | "M118" | "M119" | "M120" | "M121" | "M122" | "M123" | "M125" | "M126"
23-
| "M127" | "M128" | "M129" | "M140" | "M141" | "M143" | "M145" | "M149" | "M150"
24-
| "M154" | "M155" | "M163" | "M164" | "M165" | "M166" | "M190" | "M191" | "M192"
25-
| "M193" | "M200" | "M201" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208"
26-
| "M209" | "M211" | "M217" | "M218" | "M220" | "M221" | "M226" | "M240" | "M250"
27-
| "M255" | "M256" | "M260" | "M261" | "M282" | "M290" | "M300" | "M301" | "M302"
28-
| "M303" | "M304" | "M305" | "M306" | "M350" | "M351" | "M355" | "M360" | "M361"
29-
| "M362" | "M363" | "M364" | "M380" | "M381" | "M400" | "M401" | "M402" | "M403"
30-
| "M404" | "M405" | "M406" | "M407" | "M410" | "M412" | "M413" | "M420" | "M421"
31-
| "M422" | "M423" | "M425" | "M428" | "M430" | "M486" | "M493" | "M500" | "M501"
32-
| "M502" | "M503" | "M504" | "M510" | "M511" | "M512" | "M524" | "M540" | "M569"
33-
| "M575" | "M592" | "M593" | "M600" | "M603" | "M605" | "M665" | "M666" | "M672"
34-
| "M701" | "M702" | "M710" | "M808" | "M810" | "M811" | "M812" | "M813" | "M814"
35-
| "M815" | "M816" | "M817" | "M818" | "M819" | "M851" | "M852" | "M860" | "M861"
36-
| "M862" | "M863" | "M864" | "M865" | "M866" | "M867" | "M868" | "M869" | "M871"
37-
| "M876" | "M900" | "M906" | "M907" | "M908" | "M909" | "M910" | "M911" | "M912"
38-
| "M913" | "M914" | "M915" | "M916" | "M917" | "M918" | "M919" | "M928" | "M951"
39-
| "M993" | "M994" | "M995" | "M997" | "M999" | "M7219" | "T00" | "T0" | "T01" | "T1"
40-
| "T02" | "T2" | "T03" | "T3" | "T04" | "T4" | "T05" | "T5" | "T06" | "T6" | "T07"
41-
| "T7" | "T08" | "T8" | "T09" | "T9" | "T?" | "Tc" | "Tx" | "S00" | "S0" | "S01" | "S1"
42-
| "S02" | "S2" | "S03" | "S3" | "S04" | "S4" | "S05" | "S5" | "S06" | "S6" | "S07"
43-
| "S7" | "S08" | "S8" | "S09" | "S9" | "F00" | "F0" | "F01" | "F1" | "F02" | "F2"
44-
| "F03" | "F3" | "F04" | "F4" | "F05" | "F5" | "F06" | "F6" | "F07" | "F7" | "F08"
45-
| "F8" | "F09" | "F9" | "H00" | "H0" | "H01" | "H1" | "H02" | "H2" | "H03" | "H3"
46-
| "H04" | "H4" | "H05" | "H5" | "H06" | "H6" | "H07" | "H7" | "H08" | "H8" | "H09"
47-
| "H9" | "D00" | "D0" | "D01" | "D1" | "D02" | "D2" | "D03" | "D3" | "D04" | "D4"
48-
| "D05" | "D5" | "D06" | "D6" | "D07" | "D7" | "D08" | "D8" | "D09" | "D9" => Ok(cmd),
20+
| "M83" | "M84" | "M85" | "M86" | "M87" | "M92" | "M100" | "M102" | "M104" | "M105"
21+
| "M106" | "M107" | "M108" | "M109" | "M110" | "M111" | "M112" | "M113" | "M114"
22+
| "M115" | "M117" | "M118" | "M119" | "M120" | "M121" | "M122" | "M123" | "M125"
23+
| "M126" | "M127" | "M128" | "M129" | "M140" | "M141" | "M143" | "M145" | "M149"
24+
| "M150" | "M154" | "M155" | "M163" | "M164" | "M165" | "M166" | "M190" | "M191"
25+
| "M192" | "M193" | "M200" | "M201" | "M203" | "M204" | "M205" | "M206" | "M207"
26+
| "M208" | "M209" | "M211" | "M217" | "M218" | "M220" | "M221" | "M226" | "M240"
27+
| "M250" | "M255" | "M256" | "M260" | "M261" | "M282" | "M290" | "M300" | "M301"
28+
| "M302" | "M303" | "M304" | "M305" | "M306" | "M350" | "M351" | "M355" | "M360"
29+
| "M361" | "M362" | "M363" | "M364" | "M380" | "M381" | "M400" | "M401" | "M402"
30+
| "M403" | "M404" | "M405" | "M406" | "M407" | "M410" | "M412" | "M413" | "M420"
31+
| "M421" | "M422" | "M423" | "M425" | "M428" | "M430" | "M486" | "M493" | "M500"
32+
| "M501" | "M502" | "M503" | "M504" | "M510" | "M511" | "M512" | "M524" | "M540"
33+
| "M569" | "M575" | "M592" | "M593" | "M600" | "M603" | "M605" | "M665" | "M666"
34+
| "M672" | "M701" | "M702" | "M710" | "M808" | "M810" | "M811" | "M812" | "M813"
35+
| "M814" | "M815" | "M816" | "M817" | "M818" | "M819" | "M851" | "M852" | "M860"
36+
| "M861" | "M862" | "M863" | "M864" | "M865" | "M866" | "M867" | "M868" | "M869"
37+
| "M871" | "M876" | "M900" | "M906" | "M907" | "M908" | "M909" | "M910" | "M911"
38+
| "M912" | "M913" | "M914" | "M915" | "M916" | "M917" | "M918" | "M919" | "M928"
39+
| "M951" | "M993" | "M994" | "M995" | "M997" | "M999" | "M7219" | "T00" | "T0" | "T01"
40+
| "T1" | "T02" | "T2" | "T03" | "T3" | "T04" | "T4" | "T05" | "T5" | "T06" | "T6"
41+
| "T07" | "T7" | "T08" | "T8" | "T09" | "T9" | "T?" | "Tc" | "Tx" | "S00" | "S0"
42+
| "S01" | "S1" | "S02" | "S2" | "S03" | "S3" | "S04" | "S4" | "S05" | "S5" | "S06"
43+
| "S6" | "S07" | "S7" | "S08" | "S8" | "S09" | "S9" | "F00" | "F0" | "F01" | "F1"
44+
| "F02" | "F2" | "F03" | "F3" | "F04" | "F4" | "F05" | "F5" | "F06" | "F6" | "F07"
45+
| "F7" | "F08" | "F8" | "F09" | "F9" | "H00" | "H0" | "H01" | "H1" | "H02" | "H2"
46+
| "H03" | "H3" | "H04" | "H4" | "H05" | "H5" | "H06" | "H6" | "H07" | "H7" | "H08"
47+
| "H8" | "H09" | "H9" | "D00" | "D0" | "D01" | "D1" | "D02" | "D2" | "D03" | "D3"
48+
| "D04" | "D4" | "D05" | "D5" | "D06" | "D6" | "D07" | "D7" | "D08" | "D8" | "D09"
49+
| "D9" => Ok(cmd),
4950
_ => Err(Error::new(ErrorKind::Other, "Invalid command")),
5051
}
5152
}

src/parser.rs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,61 @@ pub fn m20(message: String) -> Vec<String> {
2525
files
2626
}
2727

28+
/**
29+
* Get SD printing status
30+
* @param message: String, return message from firmware
31+
* @return String, percentage of the print or "not-printing"
32+
*/
33+
pub fn m27(message: String) -> String {
34+
if message.contains("Not SD printing") {
35+
return "not-printing".to_string();
36+
}
37+
38+
if message.contains("SD printing byte") {
39+
let re = Regex::new(r"SD printing byte\s+(\d+)/(\d+)").unwrap();
40+
41+
if let Some(captures) = re.captures(&message) {
42+
let current_str = captures.get(1).map_or("0", |m| m.as_str());
43+
let total_str = captures.get(2).map_or("1", |m| m.as_str());
44+
45+
if let (Ok(current), Ok(total)) = (current_str.parse::<f64>(), total_str.parse::<f64>())
46+
{
47+
if total > 0.0 {
48+
let percentage = (current / total) * 100.0;
49+
return format!("{:.1}", percentage);
50+
}
51+
} else {
52+
debug!("Failed to parse printing progress values");
53+
}
54+
} else {
55+
debug!("Failed to find printing progress values");
56+
}
57+
}
58+
59+
"not-printing".to_string()
60+
}
61+
62+
/**
63+
* Get print time from completed print
64+
* @param message: String, return message from firmware
65+
* @return String, print time or "not-printing" if no print or 0s print time
66+
*/
67+
pub fn m31(message: String) -> String {
68+
let re = Regex::new(r"Print time:\s+([0-9]+[hm]?\s+[0-9]+[ms]|[0-9]+[s])").unwrap();
69+
70+
if let Some(captures) = re.captures(&message) {
71+
let print_time = captures.get(1).map_or("", |m| m.as_str()).trim();
72+
73+
if print_time == "0s" {
74+
return "not-printing".to_string();
75+
}
76+
77+
return print_time.to_string();
78+
}
79+
80+
"not-printing".to_string()
81+
}
82+
2883
/**
2984
* Get long path of a single file
3085
* @param message: String, return message from firmware
@@ -285,4 +340,69 @@ mod tests {
285340
assert_eq!(status.y_min, "open");
286341
assert_eq!(status.z_min, "open");
287342
}
343+
344+
#[test]
345+
fn test_m27_not_printing() {
346+
let sample_response = "Not SD printing ok".to_string();
347+
let status = m27(sample_response);
348+
assert_eq!(status, "not-printing");
349+
}
350+
351+
#[test]
352+
fn test_m27_printing() {
353+
let sample_response = "SD printing byte 2812/1798968 ok".to_string();
354+
let status = m27(sample_response);
355+
356+
assert_eq!(status, "0.2"); // Rounded to one decimal place
357+
}
358+
359+
#[test]
360+
fn test_m27_printing_complete() {
361+
let sample_response = "SD printing byte 1798968/1798968 ok".to_string();
362+
let status = m27(sample_response);
363+
assert_eq!(status, "100.0");
364+
}
365+
366+
#[test]
367+
fn test_m27_printing_start() {
368+
let sample_response = "SD printing byte 0/1798968 ok".to_string();
369+
let status = m27(sample_response);
370+
assert_eq!(status, "0.0");
371+
}
372+
373+
#[test]
374+
fn test_m31_no_print_time() {
375+
let sample_response = "ok".to_string();
376+
let print_time = m31(sample_response);
377+
assert_eq!(print_time, "not-printing");
378+
}
379+
380+
#[test]
381+
fn test_m31_zero_seconds() {
382+
let sample_response = "echo:Print time: 0s ok".to_string();
383+
let print_time = m31(sample_response);
384+
assert_eq!(print_time, "not-printing");
385+
}
386+
387+
#[test]
388+
fn test_m31_with_time() {
389+
let sample_response = "echo:Print time: 9m 33s ok".to_string();
390+
let print_time = m31(sample_response);
391+
assert_eq!(print_time, "9m 33s");
392+
}
393+
394+
#[test]
395+
fn test_m31_with_temperatures() {
396+
let sample_response =
397+
"ok T:198.61 /200.00 B:49.98 /50.00 @:106 B@:27 echo:Print time: 9m 33s ok".to_string();
398+
let print_time = m31(sample_response);
399+
assert_eq!(print_time, "9m 33s");
400+
}
401+
402+
#[test]
403+
fn test_m31_hours_minutes() {
404+
let sample_response = "echo:Print time: 2h 45m ok".to_string();
405+
let print_time = m31(sample_response);
406+
assert_eq!(print_time, "2h 45m");
407+
}
288408
}

src/structs.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub enum MessageType {
66
GCommand,
77
SerialConfig,
88
Unsafe,
9+
Terminal,
910
}
1011

1112
/// Used for received messages

src/wscom.rs

Lines changed: 73 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use tungstenite::Message;
1212
use crate::commands::g_command;
1313
use crate::serialcom::create_serialcom;
1414

15-
use crate::parser::{m105, m114, m115, m119, m20, m33};
15+
use crate::parser::{m105, m114, m115, m119, m20, m27, m31, m33};
1616
use crate::structs::MessageSender;
1717
use crate::Config;
1818
use crate::MessageType;
@@ -73,7 +73,7 @@ async fn handle_connection(
7373
>,
7474
) -> Result<()> {
7575
let json_str =
76-
serde_json::to_string(&message).expect("Failed to serialize messge into JSON");
76+
serde_json::to_string(&message).expect("Failed to serialize message into JSON");
7777
let resp_message = Message::Text(json_str);
7878

7979
if let Err(e) = ws_write.send(resp_message).await {
@@ -122,7 +122,7 @@ async fn handle_connection(
122122

123123
// Define response message
124124
let mut message_sender = MessageSender {
125-
message_type: "MessageSender".to_string(),
125+
message_type: cmd.to_string(),
126126
message: "".to_string(),
127127
raw_message: response.clone(),
128128
timestamp,
@@ -133,38 +133,54 @@ async fn handle_connection(
133133
"M20" => {
134134
let response = m20(response);
135135
serde_json::to_string(&response).expect(
136-
"Failed to serialize messge into JSON",
136+
"Failed to serialize message into JSON",
137+
)
138+
}
139+
"M27" => {
140+
let response = m27(response);
141+
serde_json::to_string(&response).expect(
142+
"Failed to serialize message into JSON",
143+
)
144+
}
145+
"M31" => {
146+
let response = m31(response);
147+
serde_json::to_string(&response).expect(
148+
"Failed to serialize message into JSON",
149+
)
150+
}
151+
"M33" => {
152+
let response = m33(response);
153+
serde_json::to_string(&response).expect(
154+
"Failed to serialize message into JSON",
137155
)
138156
}
139-
"M33" => m33(response),
140157
"M105" => {
141158
let response = m105(response);
142159
serde_json::to_string(&response).expect(
143-
"Failed to serialize messge into JSON",
160+
"Failed to serialize message into JSON",
144161
)
145162
}
146163
"M114" => {
147164
let response = m114(response);
148165
serde_json::to_string(&response).expect(
149-
"Failed to serialize messge into JSON",
166+
"Failed to serialize message into JSON",
150167
)
151168
}
152169
"M115" => {
153170
let response = m115(response);
154171
serde_json::to_string(&response).expect(
155-
"Failed to serialize messge into JSON",
172+
"Failed to serialize message into JSON",
156173
)
157174
}
158175
"M119" => {
159176
let response = m119(response);
160177
serde_json::to_string(&response).expect(
161-
"Failed to serialize messge into JSON",
178+
"Failed to serialize message into JSON",
162179
)
163180
}
164181
_ => response.to_string(),
165182
};
166183
}
167-
// Return response to WS clients
168184
send_message_back(message_sender, &mut ws_write)
169185
.await?;
170186
}
@@ -179,10 +195,53 @@ async fn handle_connection(
179195
}
180196
}
181197
MessageType::SerialConfig => {
198+
// Not yet implemented, changes to the config loading is required
182199
debug!("SerialConfig: {}", message.message);
183-
// Test GCode for printer info
184-
// cmd = "M115";
185-
//Expects message.message to be ex: /dev/USBtty01;119200
200+
}
201+
MessageType::Terminal => {
202+
let cmd = message.message;
203+
match create_serialcom(
204+
cmd,
205+
configuration.serial_port.to_string(),
206+
configuration.baud_rate,
207+
) {
208+
Ok(response) => {
209+
debug!("{:?}", response);
210+
211+
// Get timestamp
212+
let since_epoch = now
213+
.duration_since(UNIX_EPOCH)
214+
.expect("Time went backwards");
215+
let timestamp = since_epoch.as_secs();
216+
217+
let message_sender = MessageSender {
218+
message_type: "terminal".to_string(),
219+
message: response.to_string().clone(),
220+
raw_message: response,
221+
timestamp,
222+
};
223+
224+
send_message_back(message_sender, &mut ws_write).await?;
225+
}
226+
Err(e) => {
227+
error!("{:?}", e);
228+
229+
let since_epoch = now
230+
.duration_since(UNIX_EPOCH)
231+
.expect("Time went backwards");
232+
let timestamp = since_epoch.as_secs();
233+
234+
// Define response message
235+
let message_sender = MessageSender {
236+
message_type: "MessageSenderError".to_string(),
237+
message: "Error executing command".to_string(),
238+
raw_message: "Error executing command".to_string(),
239+
timestamp,
240+
};
241+
242+
send_message_back(message_sender, &mut ws_write).await?;
243+
}
244+
}
186245
}
187246
MessageType::Unsafe => {
188247
let cmd = message.message;
@@ -201,7 +260,7 @@ async fn handle_connection(
201260
let timestamp = since_epoch.as_secs();
202261

203262
let message_sender = MessageSender {
204-
message_type: "MessageSender".to_string(),
263+
message_type: "Unsafe".to_string(),
205264
message: response.to_string().clone(),
206265
raw_message: response,
207266
timestamp,

0 commit comments

Comments
 (0)