Skip to main content

esc_pos_lib/
printer.rs

1use super::constants;
2use super::network;
3use super::qr;
4use std::fs::File;
5use std::io::Write;
6
7pub struct Printer {
8    message: Vec<u8>,
9}
10
11
12impl Printer {
13    ///Call this function to create a new printer object.
14    ///It will start with the initial values ESC and @ which initializes the printer.
15    ///This is done in order to reset the printer to initial state
16    pub fn new() -> Printer {
17        let mut p = Printer {
18            message: Vec::new(),
19        };
20        p.message.push(constants::ESC);
21        p.message.push(constants::AT);
22        p
23    }
24
25
26    ///Add a list of u8 characters to be printed. 
27    ///This is intended to mainly be used to print plaintext.
28    ///It could however be used for commands as well.
29    pub fn add(&mut self, text: Vec<u8>) {
30        for i in text {
31            self.message.push(i);
32        }
33    }
34
35
36    ///Prints the given qr code. 
37    ///The qr code is to be constructed with the qr submodule..
38    pub fn add_qr(&mut self, qr: qr::Qr) {
39        self.add(qr.export());
40    }
41
42    ///Add a list of str to be printed. 
43    ///keep in mind that the printer only works on ASCII characters.
44    ///So it's the responsibility of the callee to make sure that the string is ASCII.
45    ///If not then it will most likely be malformed.
46    pub fn add_str(&mut self, text: &str) {
47        for i in text.bytes() {
48            self.message.push(i);
49        }
50    }
51
52
53    ///This function will turn on or off double strike mode
54    ///This is done by giving either the value constants::ON or constants::OFF
55    pub fn set_double_strike(&mut self, value: u8) {
56        self.message.push(constants::ESC);
57        self.message.push(b'G');
58        if value == constants::ON {
59            self.message.push(constants::ON);
60        } else {
61            self.message.push(constants::OFF);
62        }
63    }
64
65    ///Call this to either turn on or off emphisized text.
66    ///This is done by giving either the value constants::ON or constants::OFF
67    pub fn set_emph(&mut self, value: u8) {
68        self.message.push(constants::ESC);
69        self.message.push(b'E');
70        if value == constants::ON {
71            self.message.push(constants::ON);
72        } else {
73            self.message.push(constants::OFF);
74        }
75    }
76
77    ///Call this to turn smoothing on or off
78    ///This is done by giving either the value constants::ON or constants::OFF
79    pub fn set_smoothing(&mut self, value: u8) {
80        self.message.push(constants::GS);
81        self.message.push(0x62);
82        if value == constants::ON {
83            self.message.push(constants::ON);
84        } else {
85            self.message.push(constants::OFF);
86        }
87    }
88
89
90    fn _barcode_mode_a(&mut self, text:&str, barcode_type: u8) {
91        self.message.push(constants::GS);
92        self.message.push(0x6b);
93        self.message.push(barcode_type);
94        for i in text.bytes() {
95            self.message.push(i);
96        }
97        self.message.push(0x00);
98    }
99
100    fn _barcode_mode_b(&mut self, text:&str, barcode_type: u8) {
101        self.message.push(constants::GS);
102        self.message.push(0x6b);
103        self.message.push(barcode_type + 65);
104        self.message.push(text.len() as u8);
105        for i in text.bytes() {
106            self.message.push(i);
107        }
108    }
109
110
111    ///This function will set the height of the barcode.
112    ///The actual height depends on the printer, try and find what works for you.
113    ///Can be given values between 0-255
114    pub fn set_barcode_height(&mut self, height: u8) {
115        self.message.push(constants::GS);
116        self.message.push(0x68);
117        self.message.push(height);
118    }
119
120    ///This function will set the width of the barcode
121    ///The actual width depends on the printer, try and find what works for you.
122    ///Can be given values between 2-6
123    ///Not sure why this is the case, but it is. 
124    ///Will set to either highest or lowest if out of range.
125    pub fn set_barcode_width(&mut self, mut width: u8) {
126        if width >6 {
127            width = 6;
128        }
129        else if width < 2 {
130            width = 2;
131        }
132        self.message.push(constants::GS);
133        self.message.push(0x77);
134        self.message.push(width);
135    }
136
137    ///Prints a given barcode
138    ///The barcode to print is given as a str
139    ///There can be different types of barcodes. Check which you want to print https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id=128
140    ///There are two kinds of ways to print barcode, either constant::MODE_A or constant::MODE_B
141    ///You have to know which mode is right for you.
142    pub fn add_barcode(&mut self, text: &str, barcode_type: u8, mode: u8) {
143        
144        if mode == constants::MODE_A {
145            self._barcode_mode_a(text, barcode_type);
146        }
147        else {
148            self._barcode_mode_b( text, barcode_type);
149        }
150    }
151
152    ///Call this to reverse feed paper.
153    ///This is done by giving the number of lines to reverse feed.
154    ///The maximum number of lines is 255.
155    ///WARNING: I don't think this works on most printers
156    pub fn reverse_feed(&mut self, lines: u8) {
157        self.message.push(constants::ESC);
158        self.message.push(0x4b);
159        self.message.push(lines);
160    }
161
162    ///Call this to either turn on or off upside down text
163    ///This is done by giving either the value constants::ON or constants::OFF
164    pub fn set_upside_down(&mut self, value: u8) {
165        self.message.push(constants::ESC);
166        self.message.push(b'{');
167        if value == constants::ON {
168            self.message.push(constants::ON);
169        } else {
170            self.message.push(constants::OFF);
171        }
172    }
173
174    ///Call this to either set underline text on or off
175    ///This is done by giving either the value constants::SINGLE, constant::DOUBLE or constants::OFF
176    pub fn set_underline(&mut self, value: u8) {
177        self.message.push(constants::ESC);
178        self.message.push(0x2D);
179        self.message.push(value);
180    }
181    
182    ///Call this to change the spacing between lines
183    ///This is done by giving a value between 0 and 255
184    pub fn set_line_spacing(&mut self, value: u8) {
185        self.message.push(constants::ESC);
186        self.message.push(0x33);
187        self.message.push(value);
188    }
189
190    ///Call this to set back to the default line spacing
191    pub fn set_default_line_spacing(&mut self) {
192        self.message.push(constants::ESC);
193        self.message.push(0x32);
194    }
195
196    pub fn cut(&mut self) {
197        self.message.push(constants::LF);
198        self.message.push(constants::GS);
199        self.message.push(0x56);
200        self.message.push(0x41);
201        self.message.push(0x08);
202        self.message.push(constants::LF);
203    }
204
205    ///Prints the message straight to stdout
206    pub fn print_stdout(&self) {
207        for i in &self.message {
208            print!("{}", *i as char);
209        }
210    }
211
212
213    ///Prints the message to a file
214    ///The path is given as a str
215    pub fn print_file(&self, path: &str) {
216        let mut file = File::create(path).unwrap();
217        for i in &self.message {
218            file.write(&[*i]).unwrap();
219        }
220    }
221
222    ///Sends a printjob to the correct address and port.
223    ///This requires that other functions adding actions have been called before this.
224    pub fn print(&self, address: String, port: u32) -> Result<(), String> {
225        if self.message.len() == 2 {
226            return Err("No message to print".to_string());
227        }
228        network::send_message(&self.message, address, port)
229    }
230
231}
232