Class: Escper::Printer
- Inherits:
-
Object
- Object
- Escper::Printer
- Defined in:
- lib/escper/printer.rb
Class Method Summary collapse
Instance Method Summary collapse
-
#close ⇒ Object
Closes all opened printers.
-
#identify(chartest = nil) ⇒ Object
Open a set of usual printer device paths, print example text, then close the printers.
-
#initialize(mode = "local", vendor_printers = nil, subdirectory = nil) ⇒ Printer
constructor
Creates a new Printer object.
-
#open ⇒ Object
Opens all printers as passed to
new. -
#print(printer_id, text, raw_text_insertations = {}) ⇒ Object
- Outputs text to the printing device (File, SerialPort or TCPSocket)
printer_id - The id of the printer which was passed to new()
text -
UTF-8 encoded string.
- The id of the printer which was passed to new()
- Outputs text to the printing device (File, SerialPort or TCPSocket)
Constructor Details
#initialize(mode = "local", vendor_printers = nil, subdirectory = nil) ⇒ Printer
Creates a new Printer object.
mode-
can be either “local” or any other string. Currently only “local” is recognized. If set to anything else than “local”, printing to TCP/IP based printers will be disabled.
vendor_printers-
can either be a single object of class VendorPrinter, or an Array of objects of class VendorPrinter, or an ActiveRecord Relation containing objects which respond to the methods
id,path,name,copiesandcodepage. subdirectory-
If the Escper module variable
use_safe_device_pathis other than nil, it will not be printed to the path gived by thepathattribute of the printers, butsubdirectorywill be the prefix for the path. This way, printing data are saved to regular files in a regular directory. This is useful if this printing data is processed and served by a webserver rather than being sent to a real printer immmediately.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/escper/printer.rb', line 8 def initialize(mode="local", vendor_printers=nil, subdirectory=nil) @mode = mode @subdirectory = subdirectory @open_printers = {} @codepages_lookup = YAML::load(File.read(Escper.codepage_file)) @file_mode = 'wb' if defined?(Rails) @fallback_root_path = Rails.root else @fallback_root_path = '/' end if vendor_printers.kind_of?(Array) or (defined?(ActiveRecord) == 'constant' and vendor_printers.kind_of?(ActiveRecord::Relation)) @vendor_printers = vendor_printers elsif vendor_printers.kind_of?(VendorPrinter) or vendor_printers.kind_of?(::VendorPrinter) @vendor_printers = [vendor_printers] else # If no available VendorPrinters are initialized, create a set of temporary VendorPrinters with usual device paths. Escper.log "[initialize] No VendorPrinters specified. Creating a set of temporary printers with common device paths" paths = ['/dev/ttyUSB0', '/dev/ttyUSB1', '/dev/ttyUSB2', '/dev/usb/lp0', '/dev/usb/lp1', '/dev/usb/lp2'] @vendor_printers = Array.new paths.size.times do |i| vp = VendorPrinter.new vp.name = paths[i].gsub(/^.*\//,'') vp.path = paths[i] vp.copies = 1 vp.codepage = 0 end end end |
Class Method Details
.merge_texts(text, raw_text_insertations, codepage = 0) ⇒ Object
79 80 81 82 83 84 85 86 87 |
# File 'lib/escper/printer.rb', line 79 def self.merge_texts(text, raw_text_insertations, codepage = 0) asciifier = Escper::Asciifier.new(codepage) asciified_text = asciifier.process(text) raw_text_insertations.each do |key, value| markup = "{::escper}#{key.to_s}{:/}".encode('ASCII-8BIT') asciified_text.gsub!(markup, value) end return asciified_text end |
Instance Method Details
#close ⇒ Object
Closes all opened printers
254 255 256 257 258 259 260 261 262 263 264 265 266 |
# File 'lib/escper/printer.rb', line 254 def close Escper.log "[close] ============" @open_printers.each do |key, value| begin # File, SerialPort, and TCPSocket all have the close method value[:device].close Escper.log "[close] Closing #{ value[:name] } @ #{ value[:device].inspect }" @open_printers.delete(key) rescue => e Escper.log "[close] Error during closing of #{ value[:device] }: #{ e.inspect }" end end end |
#identify(chartest = nil) ⇒ Object
Open a set of usual printer device paths, print example text, then close the printers.
chartest-
Can be
trueornil. If true, a character test will be sent to the printer. If false, a test page containing the printer name and printer path will be sent to the printer.
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/escper/printer.rb', line 91 def identify(chartest=nil) Escper.log "[identify] ============" self.open @open_printers.each do |id, value| init = "\e@" cut = "\n\n\n\n\n\n" + "\x1D\x56\x00" testtext = "\e!\x38" + # double tall, double wide, bold "#{ I18n.t :printing_test }\r\n" + "\e!\x00" + # Font A "#{ value[:name] }\r\n" + "#{ value[:device].inspect }" if chartest Escper.log "[identify] Printing all possible characters" print(id, init + Escper::Asciifier.all_chars + cut) else Escper.log "[identify] Printing infos about this printer" ascifiier = Escper::Asciifier.new(value[:codepage]) print(id, init + ascifiier.process(testtext) + cut) end end self.close end |
#open ⇒ Object
Opens all printers as passed to new
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'lib/escper/printer.rb', line 118 def open Escper.log "[open] ============" @vendor_printers.size.times do |i| p = @vendor_printers[i] name = p.name path = p.path codepage = p.codepage baudrate = p.baudrate if Escper.use_safe_device_path == true sanitized_path = path.gsub(/[\/\s'"\&\^\$\#\!;\*]/,'_').gsub(/[^\w\/\.\-@]/,'') path = File.join(Escper.safe_device_path, @subdirectory, "escpos", "#{sanitized_path}.bill") FileUtils.mkdir_p(File.dirname(path)) unless File.exists?(File.dirname(path)) @file_mode = 'ab' end Escper.log "[open] Trying to open #{ name }@#{ path }@#{ baudrate }bps ..." pid = p.id ? p.id : i # assign incrementing id if none given # ================ TCPSOCKET PRINTERS ============================= if @mode == "local" # Writing to IP Addresses is only supported in local mode if /\d+\.\d+\.\d+\.\d+:\d+/.match(path) ip_addr = /(\d+\.\d+\.\d+\.\d+)/.match(path)[1] port = /\d+\.\d+\.\d+\.\d+:(\d+)/.match(path)[1] Escper.log "[open] Parsed IP #{ ip_addr} on port #{ port }" begin printer = nil Escper.log "[open] Attempting to open TCPSocket at #{ ip_addr} on port #{ port } ... " Timeout.timeout(2) do printer = TCPSocket.new ip_addr, port end Escper.log "[open] Success for TCPSocket: #{ printer.inspect }" @open_printers.merge! pid => { :name => name, :path => path, :copies => p.copies, :device => printer, :codepage => codepage } next rescue Errno::ECONNREFUSED Escper.log "[open] TCPSocket ERROR: Connection refused at IP #{ ip_addr} on port #{ port }. Skipping this printer." next rescue Timeout::Error Escper.log "[open] TCPSocket ERROR: Timeout #{ ip_addr} on port #{ port }. Skipping this printer." next rescue => e Escper.log "[open] TCPSocket ERROR: Failed to open: #{ e.inspect }" next end else Escper.log "[open] Path #{ path } is not in IP:port format. Not trying to open printer as TCPSocket." end else Escper.log "[open] Mode is #{ @mode }. Not trying to open printer as TCPSocket." end # ================ SERIALPORT PRINTERS ============================= begin printer = SerialPort.new path, baudrate @open_printers.merge! pid => { :name => name, :path => path, :copies => p.copies, :device => printer, :codepage => codepage } Escper.log "[open] Success for SerialPort: #{ printer.inspect }" next rescue => e Escper.log "[open] Failed to open as SerialPort: #{ e.inspect }" end # ================ FILE PRINTERS ============================= begin printer = File.open path, @file_mode @open_printers.merge! pid => { :name => name, :path => path, :copies => p.copies, :device => printer, :codepage => codepage } Escper.log "[open] Success for File: #{ printer.inspect }" next rescue Errno::EBUSY # This happens when there are 2 printes with the same path Escper.log "[open] The File #{ path } is already open." Escper.log "[open] Trying to reuse already opened printers." previously_opened_printers = @open_printers.clone previously_opened_printers.each do |key, val| Escper.log "[open] Trying to reuse already opened File #{ key }: #{ val.inspect }" if val[:path] == p[:path] and val[:device].class == File Escper.log "[open] Reused." @open_printers.merge! pid => { :name => name, :path => path, :copies => p.copies, :device => val[:device], :codepage => codepage } break end end unless @open_printers.has_key? p.id path = File.join(@fallback_root_path, 'tmp') printer = File.open(File.join(path, "#{ p.id }-#{ name }-fallback-busy.salor"), @file_mode) @open_printers.merge! pid => { :name => name, :path => path, :copies => p.copies, :device => printer, :codepage => codepage } Escper.log "[open] Failed to open as either SerialPort or USB File and resource IS busy. This should not have happened. Created #{ printer.inspect } instead." end next rescue => e path = File.join(@fallback_root_path, 'tmp') printer = File.open(File.join(path, "#{ p.id }-#{ name }-fallback-notbusy.salor"), @file_mode) @open_printers.merge! pid => { :name => name, :path => path, :copies => p.copies, :device => printer, :codepage => codepage } Escper.log "[open] Failed to open as either SerialPort or USB File and resource is NOT busy. Created #{ printer.inspect } instead." end end end |
#print(printer_id, text, raw_text_insertations = {}) ⇒ Object
Outputs text to the printing device (File, SerialPort or TCPSocket)
printer_id-
The id of the printer which was passed to new()
text-
UTF-8 encoded string. UTF-8 will be converted to ASCII-8BIT encoding according to the
codepageattribute of a specified printer. Codepage lookup tables are in the filecodepages.yml, included in this gem.textmay include tags in the format escpermy_tag:/.For example, this tag “my_tag” will be replaced by the value of the key “my_tag” in theraw_text_insertationshash. No character conversion will be done for these insertations. raw_text_insertations-
A hash specifying ASCII-8BIT encoded text for the keys given in the escper:/ tags. This is useful to send binary data to the printer (e.g. ESCPOS-encoded bitmaps), without being ‘damaged’ by the UTF-8 to ASCII-8BIT conversion.
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/escper/printer.rb', line 44 def print(printer_id, text, raw_text_insertations={}) if @open_printers == {} Escper.log "[print] No printers have been opened. Not printing anything" return 0, "" end printer = @open_printers[printer_id] if printer.nil? Escper.log "[print] No printer with id #{ printer_id } has been opened." return 0, "" end codepage = printer[:codepage] codepage ||= 0 output_text = Printer.merge_texts(text, raw_text_insertations, codepage) Escper.log "[print] Printing on #{ printer[:name] } @ #{ printer[:device].inspect }." bytes_written = nil printer[:copies].times do |i| # The method .write works for SerialPort, File and TCPSocket, so we don't have to distinguish here. bytes_written = @open_printers[printer_id][:device].write output_text if output_text.length != bytes_written Escper.log "[print] WARN: Byte count mismatch: sent #{text.length} bytes, actually written #{bytes_written} bytes" end end # The method .flush works for SerialPort, File and TCPSocket, so we don't have to distinguish here. It is not really neccessary, since the close method will theoretically flush also. @open_printers[printer_id][:device].flush Escper.log "[print] Written text: #{ output_text[0..60] }" return bytes_written, output_text end |