escpos_rust/printer/printer_profile.rs
1use std::collections::HashMap;
2use crate::{
3 Error,
4 command::Font
5};
6
7/// Available connections with the printer
8///
9/// Determines the kind of connection that will be sustained with the printer. At the moment, only Usb and Terminal are implemented. Try not to use this enum directly, use the builder pattern instead (using the [usb_builder](PrinterProfile::usb_builder) or [usb_builder](PrinterProfile::terminal_builder) methods. `network_builder` soon to be available).
10#[derive(Clone, Debug)]
11pub enum PrinterConnectionData {
12 /// Usb connection
13 Usb {
14 /// Vendor id for the printer
15 vendor_id: u16,
16 /// product id for the printer
17 product_id: u16,
18 /// Endpoint where the usb data is meant to be written to
19 endpoint: Option<u8>,
20 /// Timeout for bulk write operations
21 timeout: std::time::Duration
22 },
23 /// Network connection (not implemented yet)
24 Network {
25 _host: String,
26 _port: u16
27 },
28 /// Terminal printer, used for really simple previews.
29 Terminal
30}
31
32/// Details required to connect and print
33///
34/// In order to use the full functionality of the library, some information should be provided regarding the printer. The bare minimum information needed is the product id and the vendor id.
35#[derive(Clone, Debug)]
36pub struct PrinterProfile {
37 /// Existing connection to the printer
38 pub (crate) printer_connection_data: PrinterConnectionData,
39 /// Paper width, in characters, for the printer
40 pub (crate) columns_per_font: HashMap<Font, u8>,
41 /// Total printer width in pixels, for image printing
42 pub (crate) width: u16
43}
44
45impl PrinterProfile {
46 /// Create custom printing details
47 ///
48 /// Not recommended to use, as it contains a lot of arguments. See one of the builders instead (at the moment, only [usb_builder](PrinterProfile::usb_builder) and [terminal_builder](PrinterProfile::terminal_builder) available).
49 pub fn new(printer_connection_data: PrinterConnectionData, columns_per_font: HashMap<Font, u8>, width: u16) -> PrinterProfile {
50 PrinterProfile {
51 printer_connection_data,
52 columns_per_font,
53 width
54 }
55 }
56
57 /// Creates a [PrinterProfileBuilder](crate::PrinterProfileBuilder) set for usb printing.
58 ///
59 /// Equivalent to a call to [PrinterProfileBuilder](crate::PrinterProfileBuilder)'s [new_usb](crate::PrinterProfileBuilder::new_usb) function.
60 /// ```rust
61 /// use escpos_rs::PrinterProfile;
62 /// // Creates a minimum data structure to connect to a printer
63 /// let printer_profile = PrinterProfile::usb_builder(0x0001, 0x0001).build();
64 /// ```
65 pub fn usb_builder(vendor_id: u16, product_id: u16) -> PrinterProfileBuilder {
66 PrinterProfileBuilder::new_usb(vendor_id, product_id)
67 }
68
69 /// Creates a [PrinterProfileBuilder](crate::PrinterProfileBuilder) set for terminal printing
70 ///
71 /// Equivalent to a call to [PrinterProfileBuilder](crate::PrinterProfileBuilder)'s [new_terminal](crate::PrinterProfileBuilder::new_terminal) function.
72 /// ```rust
73 /// use escpos_rs::PrinterProfile;
74 /// // Creates a minimum data structure to connect to a printer
75 /// let printer_profile = PrinterProfile::terminal_builder().build();
76 /// ```
77 pub fn terminal_builder() -> PrinterProfileBuilder {
78 PrinterProfileBuilder::new_terminal()
79 }
80}
81
82/// Helper structure to create a [PrinterProfile](crate::PrinterProfile)
83///
84/// Builder pattern for the [PrinterProfile](crate::PrinterProfile) structure.
85pub struct PrinterProfileBuilder {
86 /// The connection to the printer
87 printer_connection_data: PrinterConnectionData,
88 /// Columns that each font spans at maximum
89 columns_per_font: HashMap<Font, u8>,
90 /// Widtth, in dots, of the printer
91 width: u16
92}
93
94impl PrinterProfileBuilder {
95 /// Creates a new [PrinterProfileBuilder](crate::PrinterProfileBuilder) set for usb printing
96 ///
97 /// ```rust
98 /// use escpos_rs::PrinterProfileBuilder;
99 /// // Creates a minimum data structure to connect to a printer
100 /// let printer_profile_builder = PrinterProfileBuilder::new_usb(0x0001, 0x0001);
101 /// ```
102 ///
103 /// The data structure will be properly built just with the vendor id and the product id. The [Printer](crate::Printer)'s [new](crate::Printer::new) method will try to locate a bulk write endpoint, but it might fail to do so. See [with_endpoint](PrinterProfileBuilder::with_endpoint) for manual setup.
104 ///
105 /// By default, a width of 384 dots and the `FontA` with 32 columns of width will be loaded with the profile.
106 pub fn new_usb(vendor_id: u16, product_id: u16) -> PrinterProfileBuilder {
107 PrinterProfileBuilder {
108 printer_connection_data: PrinterConnectionData::Usb {
109 vendor_id,
110 product_id,
111 endpoint: None,
112 timeout: std::time::Duration::from_secs(2)
113 },
114 columns_per_font: vec![(Font::FontA, 32)].into_iter().collect(),
115 width: 384
116 }
117 }
118
119 /// Creates a new [PrinterProfileBuilder](crate::PrinterProfileBuilder) set for terminal printing
120 ///
121 /// ```rust
122 /// use escpos_rs::PrinterProfileBuilder;
123 /// // Creates a minimum (probably non-working) data structure to connect to a printer
124 /// let printer_profile_builder = PrinterProfileBuilder::new_terminal();
125 /// ```
126 ///
127 /// The printer will have a 32-char width for printing text, and a default with of 384 (but it cannot be used, as pictures can't be printed to the terminal).
128 pub fn new_terminal() -> PrinterProfileBuilder {
129 PrinterProfileBuilder {
130 printer_connection_data: PrinterConnectionData::Terminal,
131 columns_per_font: vec![(Font::FontA, 32)].into_iter().collect(),
132 width: 384
133 }
134 }
135
136 /// Sets the usb endpoint to which the data will be written.
137 ///
138 /// ```rust
139 /// use escpos_rs::PrinterProfileBuilder;
140 /// // Creates the printer details with the endpoint 0x02
141 /// let printer_profile = PrinterProfileBuilder::new_usb(0x0001, 0x0001)
142 /// .with_endpoint(0x02).unwrap()
143 /// .build();
144 /// ```
145 pub fn with_endpoint(mut self, endpoint: u8) -> Result<PrinterProfileBuilder, Error> {
146 match &mut self.printer_connection_data {
147 PrinterConnectionData::Usb{endpoint: self_endpoint, ..} => {
148 *self_endpoint = Some(endpoint);
149 Ok(self)
150 },
151 _other => Err(Error::UnsupportedForPrinterConnection)
152 }
153 }
154
155 /// Adds a specific pixel width for the printer (required for printing images)
156 ///
157 /// Defaults to 384, usually for 58mm printers.
158 /// ```rust
159 /// use escpos_rs::PrinterProfileBuilder;
160 /// let printer_profile = PrinterProfileBuilder::new_usb(0x0001, 0x0001)
161 /// .with_width(384)
162 /// .build();
163 /// ```
164 pub fn with_width(mut self, width: u16) -> PrinterProfileBuilder {
165 self.width = width;
166 self
167 }
168
169 /// Adds a specific width per font
170 ///
171 /// This allows the justification, and proper word splitting to work. If you feel insecure about what value to use, the default font (FontA) usually has 32 characters of width for 58mm paper printers, and 48 for 80mm paper. You can also look for the specsheet, or do trial and error.
172 /// ```rust
173 /// use escpos_rs::{PrinterProfileBuilder, command::Font};
174 /// let printer_profile = PrinterProfileBuilder::new_usb(0x0001, 0x0001)
175 /// .with_font_width(Font::FontA, 32)
176 /// .build();
177 /// ```
178 pub fn with_font_width(mut self, font: Font, width: u8) -> PrinterProfileBuilder {
179 self.columns_per_font.insert(font, width);
180 self
181 }
182
183 /// Adds a bulk write timeout (usb only)
184 ///
185 /// USB devices might fail to write to the bulk endpoint. In such a case, a timeout must be provided to know when to stop waiting for the buffer to flush to the printer. The default value is 2 seconds.
186 /// ```rust
187 /// use escpos_rs::PrinterProfileBuilder;
188 /// let printer_profile = PrinterProfileBuilder::new_usb(0x0001, 0x0001)
189 /// .with_timeout(std::time::Duration::from_secs(3)).unwrap()
190 /// .build();
191 /// ```
192 pub fn with_timeout(mut self, timeout: std::time::Duration) -> Result<PrinterProfileBuilder, Error> {
193 match &mut self.printer_connection_data {
194 PrinterConnectionData::Usb{timeout: self_timeout, ..} => {
195 *self_timeout = timeout;
196 Ok(self)
197 },
198 _other => Err(Error::UnsupportedForPrinterConnection)
199 }
200 }
201
202 /// Build the `PrinterProfile` that lies beneath the builder
203 ///
204 /// ```rust
205 /// # use escpos_rs::PrinterProfileBuilder;
206 /// let printer_profile = PrinterProfileBuilder::new_usb(0x0001, 0x0001).build();
207 /// ```
208 pub fn build(self) -> PrinterProfile {
209 PrinterProfile {
210 printer_connection_data: self.printer_connection_data,
211 columns_per_font: self.columns_per_font,
212 width: self.width
213 }
214 }
215}