escper 1.2.1 → 1.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/README.md +24 -24
- data/escper.gemspec +2 -2
- data/lib/escper.rb +1 -1
- data/lib/escper/image.rb +5 -8
- data/lib/escper/log.rb +2 -2
- data/lib/escper/printer.rb +149 -46
- data/lib/escper/version.rb +1 -1
- metadata +8 -8
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -9,15 +9,15 @@ Installation
|
|
9
9
|
Introduction
|
10
10
|
------------
|
11
11
|
|
12
|
-
Escper is a collection of
|
12
|
+
Escper is a collection of tools that make printing of plain text and images to one or several serial thermal printers easy. USB, serial (RS232) and TCP/IP based printers are supported. Escper is useful for Ruby-based Point of Sale (POS) systems that want to print receipts, tickets or labels.
|
13
13
|
|
14
|
-
While the actual printing is just writing a
|
14
|
+
While the actual printing is just writing a bytearray to a device node located inside of `/dev`, there is some preprocessing necessary. Thermal printers usually have a narrow and custom character set, do not support UTF-8, only ASCII-8BIT. However, Escper makes it possible to conveniently pass an UTF-8 string to the printing method, and it does all the conversion work under the hood. For special characters, Escper will map UTF-8 characters to the ASCII-8BIT codes that are actually supported by the currently enabled codepage on the printer (have a look at the user manual of your printer). The file `lib/escper/codepages.yml` is an example for matching UTF-8 codes to ASCII codes of the standard codepage of the commonly available Espon and Metapace printers.
|
15
15
|
|
16
16
|
Another tricky usecase is where text is mixed with images. Images are transformed into ESCPOS compatible printing data, which is supported by the majority of thermal printers. When mixing text and images in one print 'document', Escper will still transform special UTF-8 characters according to the above mentioned codepages.yml file, but leave the image data raw i.e. unchanged.
|
17
17
|
|
18
|
-
Escper only supports printers which support plain data
|
18
|
+
Escper only supports printers which support plain data-copy to their device node living under `/dev` or via a TCP socket. Printers for which the Linux Kernel does not create a device node that can be opened as a file or as a Serial Port, or non-plain-TCP printers are not supported. Escper does not care about the formatting of the text; it is up to the user to pass those formatting commands as part of the printing string. An exception are images; those are converted to ESCPOS code always.
|
19
19
|
|
20
|
-
Some Point of Sale systems, especially those for restaurants, have to send tickets to several printers at the same time (e.g. kitchen, bar, etc.). Escper makes this easy. Have a look at the usage examples below.
|
20
|
+
Some Point of Sale systems, especially those for restaurants, have to send tickets to several printers/locations at the same time (e.g. kitchen, bar, etc.). Escper makes this easy. Have a look at the usage examples below.
|
21
21
|
|
22
22
|
Usecase: Convert image to ESCPOS code
|
23
23
|
------------
|
@@ -30,11 +30,11 @@ The source of the image can be a file:
|
|
30
30
|
|
31
31
|
escpos_code = Escper::Img.new('/path/to/test.png', :file).to_s
|
32
32
|
|
33
|
-
The source of the image can also be data which is uploaded
|
33
|
+
The source of the image can also be data which is uploaded via a HTML form. Here, the variable `data` is a variable containing the image data of a multipart HTML form. The following code would work in Ruby on Rails:
|
34
34
|
|
35
35
|
escpos_code = Escper::Img.new(data.read, :blob).to_s
|
36
36
|
|
37
|
-
Alternatively, the image source can also be
|
37
|
+
Alternatively, the image source can also be a dynamically created ImageMagick canvas:
|
38
38
|
|
39
39
|
canvas = Magick::Image.new(512, 128)
|
40
40
|
gc = Magick::Draw.new
|
@@ -52,21 +52,21 @@ Alternatively, the image source can also be an ImageMagick canvas:
|
|
52
52
|
|
53
53
|
For optimal visual results, when using a file or a blob, the image should previously be converted to an indexed, black and white 1-bit palette image. In Gimp, click on "Image -> Mode -> Indexed..." and select "Use black and white (1-bit) palette". For dithering, choose "Floyd-Steinberg (reduced color bleeding)". The image size depends on the resolution of the printer.
|
54
54
|
|
55
|
-
To
|
55
|
+
To print an image directly on a thermal receipt printer, in just one line:
|
56
56
|
|
57
|
-
File.open('/dev/usb/lp0','w') { |f| f.write Escper::Img.new('/path/to/image.png').to_s }
|
57
|
+
File.open('/dev/usb/lp0','w') { |f| f.write Escper::Img.new('/path/to/image.png', :file).to_s }
|
58
58
|
|
59
59
|
|
60
60
|
Usecase: Print UTF-8 text to several printers at the same time
|
61
61
|
------------
|
62
62
|
|
63
|
-
First, create `VendorPrinter`
|
63
|
+
First, in Ruby, create objects of the class named `VendorPrinter` which are simply containers for configuration data about the printer. If you develop your application in a framework like Ruby on Rails, you also can use the models from the Rails application instead of creating them from within Escper. The only requirements are that the objects respond to the methods `id`, `name`, `path`, `copies`, `codepage` and `baudrate`. Here we are creating 3 printers of the types USB, RS232 and TCP/IP:
|
64
64
|
|
65
65
|
vp1 = Escper::VendorPrinter.new :id => 1, :name => 'Printer 1 USB', :path => '/dev/usb/lp0', :copies => 1
|
66
|
-
vp2 = Escper::VendorPrinter.new :id => 2, :name => 'Printer 2
|
67
|
-
vp3 = Escper::VendorPrinter.new :id => 3, :name => 'Printer 3
|
66
|
+
vp2 = Escper::VendorPrinter.new :id => 2, :name => 'Printer 2 RS232', :path => '/dev/ttyUSB0', :copies => 1
|
67
|
+
vp3 = Escper::VendorPrinter.new :id => 3, :name => 'Printer 3 TCP/IP', :path => '192.168.0.201:9100', :copies => 1
|
68
68
|
|
69
|
-
`id` must be unique integers which will be needed later during printing. `name` is an arbitrary string which is only used for logging. `path` is the path to a regular file
|
69
|
+
`id` must be unique integers which will be needed later during printing. `name` is an arbitrary string which is only used for logging. `path` is the path to a regular file, serial device node or `IP:port` of the thermal printer (with a colon). Device nodes can be of the type USB, serial port (RS232) or TCP/IP. `copies` are the number of duplications of pages that the printer should print. Optionally, you can pass in the key `codepage` which is a number that must correspond to one of the YAML keys in the file `codepages.yml`. By making the `codepage` a parameter of the printer model, it is possible to use several different printers from different manufacturers with different character sets at the same time. `baudrate` is an optional integer to set the speed of the transmission (the default is 9600, this setting is only effective when using RS232 communication).
|
70
70
|
|
71
71
|
Next, initialize the printing engine of Escper by passing it an array of the VendorPrinter instances. It is also possible to pass a single VendorPrinter instance instead of an Array. As mentioned earlier, you also can pass instances or Arrays of instances of a class that is named differently (e.g. ActiveRecord queries), as longs as it responds to the afore mentioned attributes:
|
72
72
|
|
@@ -76,32 +76,32 @@ Now, open all device nodes as specified in `new`:
|
|
76
76
|
|
77
77
|
print_engine.open
|
78
78
|
|
79
|
-
|
79
|
+
After this, you can finally print text and images. Text must be UTF-8 encoded. The fist parameter is the `id` of the printer object that should be printed to. The second parameter is the actual text:
|
80
80
|
|
81
81
|
print_engine.print 1, 'print text to printer 1'
|
82
82
|
print_engine.print 2, 'print text to printer 2'
|
83
83
|
print_engine.print 3, 'print text to printer 3'
|
84
84
|
|
85
85
|
The `print` method will return an array which contains the number of bytes actually written to the device node, as well as the raw text that was written to the device node.
|
86
|
-
|
86
|
+
|
87
87
|
After printing is finished, don't forget to close the device nodes which were openened during the `open` call:
|
88
88
|
|
89
89
|
print_engine.close
|
90
90
|
|
91
91
|
|
92
|
-
Usecase: Print
|
92
|
+
Usecase: Print UTF-8 text mixed with binary images
|
93
93
|
------------
|
94
94
|
|
95
95
|
Create a printer object:
|
96
96
|
|
97
97
|
vp1 = Escper::VendorPrinter.new :id => 1, :name => 'Printer 1 USB', :path => '/dev/usb/lp0', :copies => 1
|
98
98
|
|
99
|
-
Render images into ESCPOS, stored in variables:
|
99
|
+
Render images into ESCPOS code, stored in variables:
|
100
100
|
|
101
101
|
image_escpos1 = Escper::Img.new('/path/to/test1.png', :file).to_s
|
102
102
|
image_escpos2 = Escper::Img.new('/path/to/test2.png', :file).to_s
|
103
103
|
|
104
|
-
This raw image data now must be stored in a hash, whith a unique key that gives the image a unique name
|
104
|
+
This raw image data now must be stored in a hash, whith a unique key that gives the image a unique name. This is necessary so that the image code will not be distorted by the codepage transformation.
|
105
105
|
|
106
106
|
raw_images = {:image1 => image_escpos1, :image2 => image_escpos2}
|
107
107
|
|
@@ -115,9 +115,9 @@ Open the printer device nodes:
|
|
115
115
|
|
116
116
|
Print text and image at the same time:
|
117
117
|
|
118
|
-
print_engine.print 1,
|
118
|
+
print_engine.print 1, "print text and image1 {::escper}image1{:/} and image 2 {::escper}image1{:/} to printer 1", raw_images
|
119
119
|
|
120
|
-
Note that the
|
120
|
+
Note that the special tag `{::escper}image_key{:/}` will be replaced with the image that is stored in the hash `raw_images` with the key `image_key`.
|
121
121
|
|
122
122
|
After printing is done, close the device nodes again:
|
123
123
|
|
@@ -127,7 +127,7 @@ After printing is done, close the device nodes again:
|
|
127
127
|
Fallback mode
|
128
128
|
----------------------
|
129
129
|
|
130
|
-
If a device node is busy or not writable, Escper will create fallback files instead and append the print data to that file. The fallback files will have the name of the printers and will by default be saved in `/tmp`, or, when you include Escper from Rails, in the `tmp` folder of the Rails app source.
|
130
|
+
If a device node is busy or not writable, Escper will create fallback files instead and append the print data to that file. The fallback files will have the name of the printers and will by default be saved in `/tmp`, or, when you include Escper from Rails, in the `tmp` folder of the Rails app source. A connection to an IP address (a TCP socket) must succeed within 2 seconds, otherwise the fallback mode becomes enabled.
|
131
131
|
|
132
132
|
Configuration
|
133
133
|
----------------------
|
@@ -142,7 +142,7 @@ You can configure Escper by calling in your project:
|
|
142
142
|
|
143
143
|
`codepage_file` specifies the path to `codepages.yml`. (for an explanation see above). If not specified, the file `codepages.yml` that is part of this gem distribution will be used.
|
144
144
|
|
145
|
-
`use_safe_device_path` can be set to `true` when you are running Escper on a remote server and no actual writes to physical printers should occur. In this case, all print data will be stored in regular files in the path `safe_device_path` with safe/escaped file names, which can be further processed or served by other programs.
|
145
|
+
`use_safe_device_path` can be set to `true` for security reasons when you are running Escper on a remote server and no actual writes to physical printers should occur. In this case, all print data will always be stored in regular files in the path `safe_device_path` with safe/escaped file names, which can be further processed or served by other programs.
|
146
146
|
|
147
147
|
Additional Features
|
148
148
|
----------------------
|
@@ -171,15 +171,15 @@ Ask for support or additional features!
|
|
171
171
|
|
172
172
|
Red (E) Tools Ltd.
|
173
173
|
|
174
|
-
office@
|
174
|
+
office@thebigrede.net
|
175
175
|
|
176
|
-
www.
|
176
|
+
www.thebigrede.net
|
177
177
|
|
178
178
|
|
179
179
|
Licence
|
180
180
|
----------------------
|
181
181
|
|
182
|
-
Copyright (C) 2011-2013 Red (E) Tools Ltd. <office@
|
182
|
+
Copyright (C) 2011-2013 Red (E) Tools Ltd. <office@thebigrede.net>
|
183
183
|
|
184
184
|
Permission is hereby granted, free of charge, to any person obtaining
|
185
185
|
a copy of this software and associated documentation files (the
|
data/escper.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.authors = ["Red (E) Tools Ltd."]
|
10
10
|
s.email = ["office@red-e.eu"]
|
11
11
|
s.homepage = "http://red-e.eu"
|
12
|
-
s.summary = %q{Collection of
|
13
|
-
s.description = %q{Collection of
|
12
|
+
s.summary = %q{Collection of tools that make printing of plain text and images to one or many serial thermal printers easy.}
|
13
|
+
s.description = %q{Collection of tools that make printing of plain text and images to one or many serial thermal printers easy. USB, serial (RS232) and TCP/IP printers are supported. Escper is useful for Ruby based Point of Sale systems that want to print receipts or tickets, but also suitable for stand-alone applications.}
|
14
14
|
|
15
15
|
#s.rubyforge_project = "escper"
|
16
16
|
|
data/lib/escper.rb
CHANGED
data/lib/escper/image.rb
CHANGED
@@ -54,16 +54,13 @@ module Escper
|
|
54
54
|
temp = 0
|
55
55
|
end
|
56
56
|
end
|
57
|
-
result = bits.
|
57
|
+
result = bits.pack("C*")
|
58
|
+
p_cmd = "\x1D\x76\x30\x00"
|
59
|
+
hdr = [@x, (@y*8)].pack("SS")
|
58
60
|
escpos = ''
|
59
61
|
escpos.encode! 'ASCII-8BIT'
|
60
|
-
escpos +=
|
61
|
-
@x.chr +
|
62
|
-
"\x00" +
|
63
|
-
(@y*8).chr +
|
64
|
-
"\x00" +
|
65
|
-
result
|
62
|
+
escpos += p_cmd + hdr + result
|
66
63
|
return escpos
|
67
64
|
end
|
68
65
|
end
|
69
|
-
end
|
66
|
+
end
|
data/lib/escper/log.rb
CHANGED
data/lib/escper/printer.rb
CHANGED
@@ -1,54 +1,78 @@
|
|
1
1
|
module Escper
|
2
2
|
class Printer
|
3
|
-
|
4
|
-
#
|
5
|
-
|
3
|
+
|
4
|
+
# Creates a new Printer object.
|
5
|
+
# +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.
|
6
|
+
# +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+, +copies+ and +codepage+.
|
7
|
+
# +subdirectory+:: If the Escper module variable +use_safe_device_path+ is other than nil, it will not be printed to the path gived by the +path+ attribute of the printers, but +subdirectory+ will 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
|
+
def initialize(mode="local", vendor_printers=nil, subdirectory=nil)
|
6
9
|
@mode = mode
|
7
10
|
@subdirectory = subdirectory
|
8
|
-
@open_printers =
|
11
|
+
@open_printers = {}
|
9
12
|
@codepages_lookup = YAML::load(File.read(Escper.codepage_file))
|
10
13
|
@file_mode = 'wb'
|
14
|
+
|
11
15
|
if defined?(Rails)
|
12
16
|
@fallback_root_path = Rails.root
|
13
17
|
else
|
14
18
|
@fallback_root_path = '/'
|
15
19
|
end
|
20
|
+
|
16
21
|
if vendor_printers.kind_of?(Array) or (defined?(ActiveRecord) == 'constant' and vendor_printers.kind_of?(ActiveRecord::Relation))
|
17
22
|
@vendor_printers = vendor_printers
|
18
23
|
elsif vendor_printers.kind_of?(VendorPrinter) or vendor_printers.kind_of?(::VendorPrinter)
|
19
24
|
@vendor_printers = [vendor_printers]
|
20
25
|
else
|
21
26
|
# If no available VendorPrinters are initialized, create a set of temporary VendorPrinters with usual device paths.
|
22
|
-
Escper.log "No VendorPrinters specified. Creating a set of temporary printers with common device paths"
|
23
|
-
paths = ['/dev/ttyUSB0', '/dev/ttyUSB1', '/dev/ttyUSB2', '/dev/usb/lp0', '/dev/usb/lp1', '/dev/usb/lp2'
|
27
|
+
Escper.log "[initialize] No VendorPrinters specified. Creating a set of temporary printers with common device paths"
|
28
|
+
paths = ['/dev/ttyUSB0', '/dev/ttyUSB1', '/dev/ttyUSB2', '/dev/usb/lp0', '/dev/usb/lp1', '/dev/usb/lp2']
|
24
29
|
@vendor_printers = Array.new
|
25
30
|
paths.size.times do |i|
|
26
|
-
|
31
|
+
vp = VendorPrinter.new
|
32
|
+
vp.name = paths[i].gsub(/^.*\//,'')
|
33
|
+
vp.path = paths[i]
|
34
|
+
vp.copies = 1
|
35
|
+
vp.codepage = 0
|
27
36
|
end
|
28
37
|
end
|
29
38
|
end
|
30
39
|
|
40
|
+
# Outputs text to the printing device (File, SerialPort or TCPSocket)
|
41
|
+
# +printer_id+:: The id of the printer which was passed to +new()+
|
42
|
+
# +text+:: UTF-8 encoded string. UTF-8 will be converted to ASCII-8BIT encoding according to the +codepage+ attribute of a specified printer. Codepage lookup tables are in the file +codepages.yml+, included in this gem. +text+ may include tags in the format {::escper}my_tag{:/}.For example, this tag "my_tag" will be replaced by the value of the key "my_tag" in the +raw_text_insertations+ hash. No character conversion will be done for these insertations.
|
43
|
+
# +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.
|
31
44
|
def print(printer_id, text, raw_text_insertations={})
|
32
|
-
|
33
|
-
|
34
|
-
|
45
|
+
if @open_printers == {}
|
46
|
+
Escper.log "[print] No printers have been opened. Not printing anything"
|
47
|
+
return 0, ""
|
48
|
+
end
|
49
|
+
|
35
50
|
printer = @open_printers[printer_id]
|
36
|
-
|
51
|
+
if printer.nil?
|
52
|
+
Escper.log "[print] No printer with id #{ printer_id } has been opened."
|
53
|
+
return 0, ""
|
54
|
+
end
|
37
55
|
|
38
56
|
codepage = printer[:codepage]
|
39
57
|
codepage ||= 0
|
58
|
+
|
40
59
|
output_text = Printer.merge_texts(text, raw_text_insertations, codepage)
|
41
60
|
|
42
|
-
Escper.log "[
|
61
|
+
Escper.log "[print] Printing on #{ printer[:name] } @ #{ printer[:device].inspect }."
|
62
|
+
|
43
63
|
bytes_written = nil
|
44
64
|
printer[:copies].times do |i|
|
45
|
-
# The method .write works
|
65
|
+
# The method .write works for SerialPort, File and TCPSocket, so we don't have to distinguish here.
|
46
66
|
bytes_written = @open_printers[printer_id][:device].write output_text
|
47
|
-
|
67
|
+
if output_text.length != bytes_written
|
68
|
+
Escper.log "[print] WARN: Byte count mismatch: sent #{text.length} bytes, actually written #{bytes_written} bytes"
|
69
|
+
end
|
48
70
|
end
|
49
|
-
|
71
|
+
|
72
|
+
# 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.
|
50
73
|
@open_printers[printer_id][:device].flush
|
51
|
-
|
74
|
+
|
75
|
+
Escper.log "[print] Written text: #{ output_text[0..60] }"
|
52
76
|
return bytes_written, output_text
|
53
77
|
end
|
54
78
|
|
@@ -62,13 +86,15 @@ module Escper
|
|
62
86
|
return asciified_text
|
63
87
|
end
|
64
88
|
|
89
|
+
# Open a set of usual printer device paths, print example text, then close the printers.
|
90
|
+
# +chartest+:: Can be +true+ or +nil+. 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.
|
65
91
|
def identify(chartest=nil)
|
66
|
-
Escper.log "[
|
67
|
-
|
68
|
-
open
|
92
|
+
Escper.log "[identify] ============"
|
93
|
+
self.open
|
69
94
|
@open_printers.each do |id, value|
|
70
95
|
init = "\e@"
|
71
96
|
cut = "\n\n\n\n\n\n" + "\x1D\x56\x00"
|
97
|
+
|
72
98
|
testtext =
|
73
99
|
"\e!\x38" + # double tall, double wide, bold
|
74
100
|
"#{ I18n.t :printing_test }\r\n" +
|
@@ -76,20 +102,21 @@ module Escper
|
|
76
102
|
"#{ value[:name] }\r\n" +
|
77
103
|
"#{ value[:device].inspect }"
|
78
104
|
|
79
|
-
Escper.log "[PRINTING] Testing #{value[:device].inspect }"
|
80
105
|
if chartest
|
106
|
+
Escper.log "[identify] Printing all possible characters"
|
81
107
|
print(id, init + Escper::Asciifier.all_chars + cut)
|
82
108
|
else
|
109
|
+
Escper.log "[identify] Printing infos about this printer"
|
83
110
|
ascifiier = Escper::Asciifier.new(value[:codepage])
|
84
111
|
print(id, init + ascifiier.process(testtext) + cut)
|
85
112
|
end
|
86
113
|
end
|
87
|
-
close
|
114
|
+
self.close
|
88
115
|
end
|
89
116
|
|
117
|
+
# Opens all printers as passed to +new+
|
90
118
|
def open
|
91
|
-
Escper.log "[
|
92
|
-
Escper.log "[PRINTING]OPEN Printers..."
|
119
|
+
Escper.log "[open] ============"
|
93
120
|
@vendor_printers.size.times do |i|
|
94
121
|
p = @vendor_printers[i]
|
95
122
|
name = p.name
|
@@ -104,60 +131,136 @@ module Escper
|
|
104
131
|
@file_mode = 'ab'
|
105
132
|
end
|
106
133
|
|
107
|
-
Escper.log "[
|
108
|
-
pid = p.id ? p.id : i
|
134
|
+
Escper.log "[open] Trying to open #{ name }@#{ path }@#{ baudrate }bps ..."
|
135
|
+
pid = p.id ? p.id : i # assign incrementing id if none given
|
136
|
+
|
137
|
+
# ================ TCPSOCKET PRINTERS =============================
|
138
|
+
if @mode == "local"
|
139
|
+
# Writing to IP Addresses is only supported in local mode
|
140
|
+
if /\d+\.\d+\.\d+\.\d+:\d+/.match(path)
|
141
|
+
ip_addr = /(\d+\.\d+\.\d+\.\d+)/.match(path)[1]
|
142
|
+
port = /\d+\.\d+\.\d+\.\d+:(\d+)/.match(path)[1]
|
143
|
+
Escper.log "[open] Parsed IP #{ ip_addr} on port #{ port }"
|
144
|
+
|
145
|
+
begin
|
146
|
+
printer = nil
|
147
|
+
Escper.log "[open] Attempting to open TCPSocket at #{ ip_addr} on port #{ port } ... "
|
148
|
+
Timeout.timeout(2) do
|
149
|
+
printer = TCPSocket.new ip_addr, port
|
150
|
+
end
|
151
|
+
Escper.log "[open] Success for TCPSocket: #{ printer.inspect }"
|
152
|
+
@open_printers.merge! pid => {
|
153
|
+
:name => name,
|
154
|
+
:path => path,
|
155
|
+
:copies => p.copies,
|
156
|
+
:device => printer,
|
157
|
+
:codepage => codepage
|
158
|
+
}
|
159
|
+
next
|
160
|
+
rescue Errno::ECONNREFUSED
|
161
|
+
Escper.log "[open] TCPSocket ERROR: Connection refused at IP #{ ip_addr} on port #{ port }. Skipping this printer."
|
162
|
+
next
|
163
|
+
rescue Timeout::Error
|
164
|
+
Escper.log "[open] TCPSocket ERROR: Timeout #{ ip_addr} on port #{ port }. Skipping this printer."
|
165
|
+
next
|
166
|
+
rescue => e
|
167
|
+
Escper.log "[open] TCPSocket ERROR: Failed to open: #{ e.inspect }"
|
168
|
+
next
|
169
|
+
end
|
170
|
+
else
|
171
|
+
Escper.log "[open] Path #{ path } is not in IP:port format. Not trying to open printer as TCPSocket."
|
172
|
+
end
|
173
|
+
else
|
174
|
+
Escper.log "[open] Mode is #{ @mode }. Not trying to open printer as TCPSocket."
|
175
|
+
end
|
176
|
+
|
177
|
+
# ================ SERIALPORT PRINTERS =============================
|
109
178
|
begin
|
110
179
|
printer = SerialPort.new path, baudrate
|
111
|
-
@open_printers.merge! pid => {
|
112
|
-
|
180
|
+
@open_printers.merge! pid => {
|
181
|
+
:name => name,
|
182
|
+
:path => path,
|
183
|
+
:copies => p.copies,
|
184
|
+
:device => printer,
|
185
|
+
:codepage => codepage
|
186
|
+
}
|
187
|
+
Escper.log "[open] Success for SerialPort: #{ printer.inspect }"
|
113
188
|
next
|
114
|
-
rescue
|
115
|
-
Escper.log "[
|
189
|
+
rescue => e
|
190
|
+
Escper.log "[open] Failed to open as SerialPort: #{ e.inspect }"
|
116
191
|
end
|
117
192
|
|
193
|
+
|
194
|
+
# ================ FILE PRINTERS =============================
|
118
195
|
begin
|
119
196
|
printer = File.open path, @file_mode
|
120
|
-
@open_printers.merge! pid => {
|
121
|
-
|
197
|
+
@open_printers.merge! pid => {
|
198
|
+
:name => name,
|
199
|
+
:path => path,
|
200
|
+
:copies => p.copies,
|
201
|
+
:device => printer,
|
202
|
+
:codepage => codepage
|
203
|
+
}
|
204
|
+
Escper.log "[open] Success for File: #{ printer.inspect }"
|
122
205
|
next
|
123
206
|
rescue Errno::EBUSY
|
124
|
-
|
125
|
-
Escper.log "[
|
207
|
+
# This happens when there are 2 printes with the same path
|
208
|
+
Escper.log "[open] The File #{ path } is already open."
|
209
|
+
Escper.log "[open] Trying to reuse already opened printers."
|
126
210
|
previously_opened_printers = @open_printers.clone
|
127
211
|
previously_opened_printers.each do |key, val|
|
128
|
-
Escper.log "[
|
212
|
+
Escper.log "[open] Trying to reuse already opened File #{ key }: #{ val.inspect }"
|
129
213
|
if val[:path] == p[:path] and val[:device].class == File
|
130
|
-
Escper.log "[
|
131
|
-
@open_printers.merge! pid => {
|
214
|
+
Escper.log "[open] Reused."
|
215
|
+
@open_printers.merge! pid => {
|
216
|
+
:name => name,
|
217
|
+
:path => path,
|
218
|
+
:copies => p.copies,
|
219
|
+
:device => val[:device],
|
220
|
+
:codepage => codepage
|
221
|
+
}
|
132
222
|
break
|
133
223
|
end
|
134
224
|
end
|
135
225
|
unless @open_printers.has_key? p.id
|
136
226
|
path = File.join(@fallback_root_path, 'tmp')
|
137
227
|
printer = File.open(File.join(path, "#{ p.id }-#{ name }-fallback-busy.salor"), @file_mode)
|
138
|
-
@open_printers.merge! pid => {
|
139
|
-
|
228
|
+
@open_printers.merge! pid => {
|
229
|
+
:name => name,
|
230
|
+
:path => path,
|
231
|
+
:copies => p.copies,
|
232
|
+
:device => printer,
|
233
|
+
:codepage => codepage
|
234
|
+
}
|
235
|
+
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."
|
140
236
|
end
|
141
237
|
next
|
142
|
-
rescue
|
238
|
+
rescue => e
|
143
239
|
path = File.join(@fallback_root_path, 'tmp')
|
144
240
|
printer = File.open(File.join(path, "#{ p.id }-#{ name }-fallback-notbusy.salor"), @file_mode)
|
145
|
-
@open_printers.merge! pid => {
|
146
|
-
|
241
|
+
@open_printers.merge! pid => {
|
242
|
+
:name => name,
|
243
|
+
:path => path,
|
244
|
+
:copies => p.copies,
|
245
|
+
:device => printer,
|
246
|
+
:codepage => codepage
|
247
|
+
}
|
248
|
+
Escper.log "[open] Failed to open as either SerialPort or USB File and resource is NOT busy. Created #{ printer.inspect } instead."
|
147
249
|
end
|
148
250
|
end
|
149
251
|
end
|
150
252
|
|
253
|
+
# Closes all opened printers
|
151
254
|
def close
|
152
|
-
Escper.log "[
|
153
|
-
Escper.log "[PRINTING]CLOSING Printers..."
|
255
|
+
Escper.log "[close] ============"
|
154
256
|
@open_printers.each do |key, value|
|
155
257
|
begin
|
258
|
+
# File, SerialPort, and TCPSocket all have the close method
|
156
259
|
value[:device].close
|
157
|
-
Escper.log "[
|
260
|
+
Escper.log "[close] Closing #{ value[:name] } @ #{ value[:device].inspect }"
|
158
261
|
@open_printers.delete(key)
|
159
|
-
rescue
|
160
|
-
Escper.log "[
|
262
|
+
rescue => e
|
263
|
+
Escper.log "[close] Error during closing of #{ value[:device] }: #{ e.inspect }"
|
161
264
|
end
|
162
265
|
end
|
163
266
|
end
|
data/lib/escper/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: escper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2014-05-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rmagick
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
|
-
description: Collection of
|
47
|
-
|
48
|
-
|
49
|
-
|
46
|
+
description: Collection of tools that make printing of plain text and images to one
|
47
|
+
or many serial thermal printers easy. USB, serial (RS232) and TCP/IP printers are
|
48
|
+
supported. Escper is useful for Ruby based Point of Sale systems that want to print
|
49
|
+
receipts or tickets, but also suitable for stand-alone applications.
|
50
50
|
email:
|
51
51
|
- office@red-e.eu
|
52
52
|
executables: []
|
@@ -90,6 +90,6 @@ rubyforge_project:
|
|
90
90
|
rubygems_version: 1.8.23
|
91
91
|
signing_key:
|
92
92
|
specification_version: 3
|
93
|
-
summary: Collection of
|
94
|
-
|
93
|
+
summary: Collection of tools that make printing of plain text and images to one or
|
94
|
+
many serial thermal printers easy.
|
95
95
|
test_files: []
|