nom_reprap_response/
echo.rs

1use nom::{
2    IResult,
3    character::streaming::*,
4    bytes::streaming::*,
5};
6use nom::branch::*;
7use nom::combinator::*;
8use nom::sequence::*;
9// use nom::multi::*;
10
11use crate::Busy;
12
13use super::{
14    Response,
15    SDCard,
16    Feedback,
17    StartSDWrite,
18    u32_str,
19};
20
21pub fn echo<'r>(input: &'r str) ->  IResult<&'r str, Response> {
22    preceded(
23        pair(
24            tag_no_case("echo:"),
25            space0,
26        ),
27        alt((
28            busy,
29            m21_sd_card_ok,
30            m23_m28_fresh_file,
31            normal_echo_content,
32        )),
33    )(input)
34}
35
36fn normal_echo_content<'r>(input: &'r str) ->  IResult<&'r str, Response> {
37    map(
38        not_line_ending,
39        |s: &str| Response::Echo(s.to_string()),
40    )(input)
41}
42
43// TX "N63 M21*37\n"
44// RX "echo:SD card ok\n"
45// RX "Init power off infomation.\n"
46// RX "size: \n"
47// 123
48fn m21_sd_card_ok<'r>(input: &'r str) ->  IResult<&'r str, Response> {
49    map(
50        preceded(
51            tuple((
52                tag("SD card ok"),
53                space0,
54                line_ending,
55                take_until("\nsize:"),
56                space0,
57                line_ending,
58            )),
59            u32_str(),
60        ),
61        |size: u32| {
62            let sd_card = SDCard {
63                enabled: true,
64                size: Some(size),
65            };
66            Response::Ok(Some(Feedback::SDCard(sd_card)))
67        },
68    )(input)
69}
70
71// TX "N389 M28 file.txt *75\n"
72// RX "echo:Now fresh file: file.txt\n"
73// RX "Writing to file: file.txt\n"
74// OR
75// TX "N125 M28 teg.gcode*13\n"
76// RX "echo:Now fresh file: teg.gcod\n"
77// RX "open failed, File: teg.gcod.\n"
78fn m23_m28_fresh_file<'r>(input: &'r str) ->  IResult<&'r str, Response> {
79    preceded(
80        tuple((
81            tag_no_case("Now fresh file:"),
82            not_line_ending,
83            line_ending,
84        )),
85        alt((
86            // RX "Writing to file: file.txt\n"
87            map(
88                preceded(
89                    pair(
90                        tag_no_case("Writing to file:"),
91                        space0,
92                    ),
93                    not_line_ending,
94                ),
95                |filename: &str| {
96                    let start_streaming = Feedback::StartSDWrite(StartSDWrite {
97                        filename: filename.to_string(),
98                    });
99
100                    Response::Ok(Some(start_streaming))
101                },
102            ),
103            // RX "File opened: file.tx Size: 17\n"
104            // RX "File selected\n"
105            map(
106                recognize(tuple((
107                    tag("File opened:"),
108                    not_line_ending,
109                    line_ending,
110                    tag("File selected"),
111                ))),
112                |s: &str| Response::Debug(s.to_string())
113            ),
114            // RX "open failed, File: teg.gcod.\n"
115            map(
116                preceded(
117                    tag_no_case("open failed, File:"),
118                    not_line_ending,
119                ),
120                |_| {
121                    Response::Error("\
122                        Failed to open sd card file. \
123                        Check that SD card is inserted and enabled in firmware.\
124                    ".to_string())
125                },
126            ),
127        )),
128    )(input)
129}
130
131// On a PrintMill:
132// Heating the extruder, removing the filament from the runout sensor and sending an `M75`:
133//
134// TX "N100 M75*16\n"
135// RX "ok\n"
136//
137// After a delay of a few (2?) seconds:
138// RX "echo:busy: processing\n"
139//
140// Repeats the processing message several times at 2(?) second intervals
141//
142// Then it sends a more specific echo but only once:
143// RX "echo:Insert filament and press button\n"
144//
145// And finally it begins repeating:
146// RX "echo:busy: paused for user\n"
147fn busy<'r>(input: &'r str) ->  IResult<&'r str, Response> {
148    preceded(
149        pair(
150            tag_no_case("busy:"),
151            space0,
152        ),
153        alt((
154            value(
155                Response::Feedback(Feedback::Busy(Busy::Processing)),
156                tag_no_case("processing"),
157            ),
158            value(
159                Response::Feedback(Feedback::Busy(Busy::PausedForUser)),
160                tag_no_case("paused for user"),
161            ),
162            map(
163                not_line_ending,
164                |s: &str| Response::Feedback(Feedback::Busy(Busy::Other(s.to_string()))),
165            ),
166        ))
167    )(input)
168}