extface 0.1.9 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fc59569d61b550e245d115c0542d9803bc9ded4c
4
- data.tar.gz: 16607248a89cc5776e47a9145eed8a4a68389509
3
+ metadata.gz: ffc7be7748574fcff49cfea02aab44e7f4f97760
4
+ data.tar.gz: 426759fdcff98ca0979ef600877c42674f9b4733
5
5
  SHA512:
6
- metadata.gz: 981cd2238ba9611ea66f5375af2e34d4f33272bdc303109910e8407c979c59946881a17c234150b2275ad878e0b77df4104a6abf52b3ca6a4722870e9af3b700
7
- data.tar.gz: a11e17b3b21d4600915fc7181898258a0eb28961da58d5c0bffaeb8b0d571e0819fca358037a90f573e61bbe5e0e03a6d26e3aa3f135dbd578896646e07fd538
6
+ metadata.gz: 4cf1335ec7f7cf50da17e1816213b740a675e5d0b6223f13b9d4145ff14a14d50c6411b4ec29808568b9d39f456b1d657f160122c64da8596f5dfb0439d86ad9
7
+ data.tar.gz: 6821ca4e6a6e1078740eebc9c7d30a4dd899e204eb1c979eca3dd695080b35141c7eaff4bf036969151031c830dd4a2483b124396c357264e348391bd597361d
@@ -1,4 +1,4 @@
1
- Copyright 2014 YOURNAME
1
+ Copyright 2014 Alex Vangelov
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -269,7 +269,7 @@ module Extface
269
269
  def initialize(buffer)
270
270
  # test Extface::Driver::DaisyFx1200::RespFrame.new("\x16\x16\x01\x2c\x20\x2dP\x04SSSSSS\x05\BBBB\x03")
271
271
  # LEN SEQ CMD DATA STATUS BCC
272
- if match = buffer.match(/\x01(.{1})(.{1})(.{1})(.*)\x04(.{6})\x05(.{4})\x03/n)
272
+ if match = buffer.match(/\x01(.{1})(.{1})(.{1})(.*)\x04(.{6})\x05(.{4})\x03/nm)
273
273
  @frame = match.to_a.first
274
274
  @len, @seq, @cmd, @data, @status, @bcc = match.captures
275
275
  else
@@ -0,0 +1,78 @@
1
+ #Source: ELTRADE COMMUNICATION PROTOCOL for Fiscal Printers (ver 4.0.2.12)
2
+
3
+ module Extface
4
+ module Driver::Eltrade::CommandsFp4
5
+ STRT = "\xAA\x55"
6
+
7
+ module Info
8
+ GET_SERIAL_NUMBER = 0x10
9
+ GET_HEADING_ROWS_1_6 = 0x11
10
+ GET_FISC_MEM_NUMBER = 0x14
11
+ GET_TAX_NUMBER = 0x15
12
+ GET_HEADING_ROWS_7_10 = 0x17
13
+ GET_TAX_GROUPS = 0x19
14
+ GET_OPERATOR = 0x1A
15
+ GET_PAYMENTS = 0x1B
16
+ GET_PRINTER_STATUS = 0x2C
17
+ GET_FISCAL_STATUS = 0x30
18
+ GET_FISCAL_TYPE = 0x3C
19
+ GET_DATE_TIME = 0x3E
20
+ REQUEST_HARDWARE_STAT = 0x46
21
+ GET_HARDWARE_STATUS = 0x47
22
+ GET_STATUS = 0x70
23
+ end
24
+ module Receipt
25
+ OPEN_RECEIPT = 0x2D
26
+ PRINT_RECEIPT = 0x2E
27
+ module Variant
28
+ COMMENT = "\x01"
29
+ PLU = "\x02"
30
+ START_INVOICE_RECEIPT = "\x0D"
31
+ START_COMMENT_RECEIPT = "\x0F"
32
+ end
33
+ CLOSE_RECEIPT = 0x2F
34
+ LAST_DOC_COPY = 0x31
35
+ SET_INVOICE_NUMBER = 0x34
36
+ PRINT_RECEIPT_HEADER = 0x38
37
+ end
38
+ module Reports
39
+ SILENT0_PLU = 0x22
40
+ SILENT_PRINTER = 0x23
41
+ PLU_REPORT = 0x32
42
+ DAILY_REPORT = 0x33
43
+ end
44
+ module Init
45
+ GRAPHIC_LOGO_PRINTING = 0x13
46
+ SET_OPERATOR_INFO = 0x2A
47
+ SET_PAYMENT_TYPES = 0x2B
48
+ SET_FISCAL_DEV_NUM = 0x35
49
+ FISCAL_PARAMS_REC = 0x36
50
+ SET_PRINT_PLU_NUMBER = 0x3A
51
+ SET_SERIAL_NUMBER = 0x3B
52
+ SET_DATE_TIME = 0x3D
53
+ end
54
+ module Other
55
+ EXEC_PRINTER_TEST = 0x24
56
+ FISC_MEM_READ_TEST = 0x25
57
+ FISC_MEM_WRITE_TEST = 0x26
58
+ PAYED_RECV_ACCOUNT = 0x28 # ?
59
+ GET_DATE_TIME = 0x3E
60
+ SET_DATE_TIME = 0x3D
61
+ OPEN_CASH_DRAWER = 0x4B
62
+ end
63
+
64
+ def build_packet(cmd, fields = [])
65
+ String.new.tap() do |frame|
66
+ frame << STX
67
+ frame << sequence_number
68
+ frame << cmd
69
+ fields.each do |field|
70
+ frame << SEP
71
+ frame << field
72
+ end
73
+ frame << ETX
74
+ frame << bcc(frame)
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,359 @@
1
+
2
+ # 1 2 3 4 5 6 6+n
3
+ #STRT ADDR SEQ CMD LEN DATA CS
4
+ # 1 1 1 1 1 1 4 1
5
+ #AAh 55h 0–FFh 0–FFh 10h–70h 0-FFh 30h–3Fh 0-FFh
6
+
7
+ module Extface
8
+ class Driver::EltradeTmU220 < Extface::Driver
9
+ NAME = 'Eltrade TM-U220 (Serial)'.freeze
10
+ GROUP = Extface::FISCAL_DRIVER
11
+
12
+ DEVELOPMENT = true #driver is not ready for production (not passing all tests or has major bugs)
13
+
14
+ # Select driver features
15
+ RAW = true #responds to #push(data) and #pull
16
+ PRINT = false #POS, slip printers
17
+ FISCAL = true #cash registers, fiscal printers
18
+ REPORT = false #only transmit data that must be parsed by handler, CDR, report devices
19
+
20
+ RESPONSE_TIMEOUT = 3 #seconds
21
+ INVALID_FRAME_RETRIES = 6 #seconds
22
+
23
+ FLAG_TRUE = "\xff\xff"
24
+ FLAG_FALSE = "\x00\x00"
25
+
26
+ has_serial_config
27
+
28
+ include Extface::Driver::Eltrade::CommandsFp4
29
+
30
+ def handle(buffer)
31
+ bytes_processed = 0
32
+ if frame_match = buffer.match(/\xAA\x55.{3}(.{1}).*/nm) #m Treat \x0a as a character matched by .
33
+ len = frame_match.captures.first.ord
34
+ skip = frame_match.pre_match.length
35
+ bytes_processed = skip + 7 + len # 6 pre + 1 check sum
36
+ rpush buffer[skip..bytes_processed]
37
+ end
38
+ return bytes_processed
39
+ end
40
+
41
+ def open_receipt(variant = nil)
42
+ fsend Receipt::OPEN_RECEIPT
43
+ status = printer_status!
44
+ unless variant.blank?
45
+ fsend Receipt::PRINT_RECEIPT, variant
46
+ status = printer_status!
47
+ end
48
+ end
49
+
50
+ def close_receipt
51
+ fsend Receipt::CLOSE_RECEIPT
52
+ status = printer_status!
53
+ end
54
+
55
+ def send_comment(text)
56
+ fsend Receipt::PRINT_RECEIPT, Receipt::Variant::COMMENT + text
57
+ status = printer_status!
58
+ end
59
+
60
+ def send_plu(plu_data)
61
+ fsend Receipt::PRINT_RECEIPT, Receipt::Variant::PLU + plu_data
62
+ status = printer_status!
63
+ end
64
+
65
+ def send_payment(type_num = 0, value = nil) # 0, 1, 2, 3
66
+ value_bytes = "\x00\x00\x00\x00" # recalculate
67
+ unless value.nil?
68
+ value_units = (value * 100).to_i # !FIXME
69
+ value_bytes = "".b
70
+ 4.times{ |shift| value_bytes.insert 0, ((value_units >> shift*8) & 0xff).chr }
71
+ end
72
+ fsend Receipt::PRINT_RECEIPT, "" << (9 + type_num).chr << value_bytes
73
+ end
74
+
75
+ def non_fiscal_test
76
+ device.session("Non Fiscal Text") do |s|
77
+ s.notify "Printing Non Fiscal Text"
78
+ s.open_receipt Receipt::Variant::START_COMMENT_RECEIPT
79
+ s.send_comment "********************************"
80
+ s.send_comment "Extface Print Test".center(32)
81
+ s.send_comment "********************************"
82
+ s.send_comment ""
83
+ s.send_comment "Driver: " + "#{self.class::NAME}".truncate(24)
84
+ s.close_receipt
85
+ s.notify "Printing finished"
86
+ end
87
+ end
88
+
89
+ def fiscal_test
90
+ sale_and_pay_items_session([
91
+ { price: 0.01, text1: "Extface Test" }
92
+ ])
93
+ end
94
+
95
+ def build_sale_data(price, text1 = "", text2 = nil, tax_group = 2, qty = 1, percent = nil, neto = nil, number = nil)
96
+ "".b.tap() do |data|
97
+ price_units = (price * 100).to_i # !FIXME
98
+ price_bytes = "".b
99
+ 4.times{ |shift| price_bytes.insert 0, ((price_units >> shift*8) & 0xff).chr }
100
+ data << price_bytes
101
+ qty_units = ((qty || 1) * 1000).to_i # !FIXME
102
+ qty_bytes = "".b
103
+ 4.times{ |shift| qty_bytes.insert 0, ((qty_units >> shift*8) & 0xff).chr }
104
+ data << qty_bytes
105
+ data << "\x00".b #number len FIXME
106
+ data << "\xAA\xAA\xAA\xAA\xAA\xAA".b #number FIXME
107
+ text = text1.truncate(20)
108
+ data << text.length.chr
109
+ data << text.ljust(20, " ").b
110
+ data << (tax_group || 2).chr
111
+ end
112
+ end
113
+
114
+ def sale_and_pay_items_session(items = [], operator = "1", password = "1")
115
+ device.session("Fiscal Doc") do |s|
116
+ s.notify "Fiscal Doc Start"
117
+ s.open_receipt
118
+ items.each do |item|
119
+ s.send_plu build_sale_data(item[:price], item[:text1], nil, item[:tax_group], item[:qty], nil, nil, item[:number])
120
+ s.send_comment(item[:text2]) unless item[:text2].blank?
121
+ end
122
+ s.send_payment
123
+ s.close_receipt
124
+ s.notify "Fiscal Doc End"
125
+ end
126
+ end
127
+
128
+ def z_report_session
129
+ device.session("Z Report") do |s|
130
+ s.notify "Z Report Start"
131
+ s.fsend Reports::DAILY_REPORT, FLAG_TRUE
132
+ status = s.printer_status!
133
+ s.notify "Z Report End"
134
+ end
135
+ end
136
+
137
+ def x_report_session
138
+ device.session("Z Report") do |s|
139
+ s.notify "Z Report Start"
140
+ s.fsend Reports::DAILY_REPORT, FLAG_FALSE
141
+ status = s.printer_status!
142
+ s.notify "Z Report End"
143
+ end
144
+ end
145
+
146
+ def cancel_doc_session
147
+ device.session("Doc cancel") do |s|
148
+ s.notify "Doc Cancel Start"
149
+ #s.fsend Sales::CANCEL_DOC
150
+ s.notify "Doc Cancel End"
151
+ end
152
+ end
153
+
154
+
155
+ def printer_status!
156
+ fsend Info::GET_STATUS
157
+ raise errors.full_messages.join(", ") if errors.any?
158
+ status = PrinterStatus.new(fsend(Info::GET_PRINTER_STATUS))
159
+ raise errors.full_messages.join(", ") if errors.any?
160
+ status
161
+ end
162
+
163
+ def check_status
164
+ flush
165
+ fsend(Info::GET_STATUS)
166
+ errors.empty?
167
+ end
168
+
169
+ def build_packet(cmd, data = "")
170
+ "".tap() do |packet|
171
+ packet << STRT.b
172
+ packet << 0x00 #address
173
+ packet << sequence_number
174
+ packet << cmd
175
+ packet << data.length
176
+ packet << data.b
177
+ packet << check_sum(packet[2..-1])
178
+ end
179
+ end
180
+
181
+ def fsend(cmd, data = "") #return data or nil
182
+ packet_data = build_packet(cmd, data)
183
+ result = false
184
+ INVALID_FRAME_RETRIES.times do |retries|
185
+ errors.clear
186
+ push packet_data
187
+ if resp = frecv(RESPONSE_TIMEOUT)
188
+ if resp.valid?
189
+ result = resp.data
190
+ break
191
+ else
192
+ resp.errors.full_messages.each do |msg|
193
+ errors.add :base, msg
194
+ end
195
+ end
196
+ end
197
+ errors.add :base, "#{INVALID_FRAME_RETRIES} Broken Packets Received. Abort!"
198
+ end
199
+ return result
200
+ end
201
+
202
+ def frecv(timeout) # return RespFrame or nil
203
+ if frame_bytes = pull(timeout)
204
+ return Frame.new(frame_bytes.b)
205
+ else
206
+ errors.add :base, "No data received from device"
207
+ return nil
208
+ end
209
+ end
210
+
211
+ def check_sum(buffer)
212
+ sum = 0
213
+ buffer.each_byte do |byte|
214
+ sum -= byte
215
+ end
216
+ sum & 0xff
217
+ end
218
+
219
+ private
220
+ def sequence_number(increment = true)
221
+ @seq ||= 0
222
+ @seq += 1 if increment
223
+ @seq = 0 if @seq == 0xff
224
+ @seq
225
+ end
226
+
227
+ class Frame
228
+ include ActiveModel::Validations
229
+ attr_reader :frame, :addr, :seq, :cmd, :len, :data, :check_sum
230
+
231
+ validates_presence_of :frame
232
+ validate :check_sum_validation
233
+ validate :len_validation
234
+ validate :response_code_validation
235
+
236
+ def initialize(buffer)
237
+ if match = buffer.match(/\xAA\x55(.{1})(.{1})(.{1})(.{1})(.*)(.{1})$/nm)
238
+ @frame = match.to_a.first
239
+ @addr, @seq, @cmd, @len, @data, @check_sum = match.captures
240
+ end
241
+ end
242
+
243
+ def ready?
244
+ @ready || true
245
+ end
246
+
247
+ private
248
+ def check_sum_validation
249
+ sum = 0
250
+ frame[2..-1].each_byte do |byte|
251
+ sum += byte
252
+ end
253
+ errors.add(:check_sum, I18n.t('errors.messages.invalid')) if (sum & 0xff) != 0
254
+ end
255
+
256
+ def len_validation
257
+ errors.add(:len, I18n.t('errors.messages.invalid')) if len.ord != data.length
258
+ end
259
+
260
+ def response_code_validation
261
+ case cmd.ord
262
+ when 0x2c then
263
+ case data[0] # printer error code
264
+ when 1 then errors.add :base, "Opening of the cash register document is not requested"
265
+ when 2 then errors.add :base, "Transaction code recognized (refer to command 0x2E)"
266
+ when 3 then errors.add :base, "Transaction buffer overflow"
267
+ when 4 then errors.add :base, "Transaction sequence error"
268
+ when 5 then errors.add :base, "Multiplication overflow"
269
+ when 6 then errors.add :base, "Cash register document overflow"
270
+ when 7 then errors.add :base, "'0' length of code name"
271
+ when 8 then errors.add :base, "Negative result"
272
+ when 9 then errors.add :base, "Cash register document surcharge"
273
+ when 10 then errors.add :base, "Out of range parameter"
274
+ when 11 then errors.add :base, "Cash register document not paid"
275
+ when 12 then errors.add :base, "'0' result"
276
+ when 13 then errors.add :base, "Memory overflow because of too many PLUs"
277
+ when 14 then errors.add :base, "Daily report overflow"
278
+ end
279
+ when 0x6F then
280
+ case data[1]
281
+ when 1 then errors.add :base, "End of paper"
282
+ when 2 then errors.add :base, "Printing error"
283
+ when 16 then errors.add :base, "Fiscal error 0: Error at writing in FM"
284
+ when 17 then errors.add :base, "Fiscal error 1: Attempt for writing in overflowing FM"
285
+ when 18 then errors.add :base, "Fiscal error 2: Incorrect structure in fiscal part 1"
286
+ when 19 then errors.add :base, "Fiscal error 3: Control sum error"
287
+ when 20 then errors.add :base, "Fiscal error 4: Incorrect structure in fiscal part 2"
288
+ when 21 then errors.add :base, "Fiscal error 5: No connection with the fiscal memory"
289
+ when 22 then errors.add :base, "Fiscal error 6: Incorrect record structure"
290
+ when 23 then errors.add :base, "Fiscal error 7: Fiscal memory overflow"
291
+
292
+ when 32 then errors.add :base, "No connection with terminal"
293
+ when 33 then errors.add :base, "No valid registration (IMSI on the SIM is different than the one recorded in fiscal memory"
294
+ when 34 then errors.add :base, "Not used"
295
+ when 35 then errors.add :base, "3 Daily reports with zeroing and no connection with NRA’s server"
296
+ when 36 then errors.add :base, "Missing or invalid SIM card"
297
+ when 37 then errors.add :base, "GSM module data reading error"
298
+ when 38 then errors.add :base, "Terminal data memory error"
299
+ when 39 then errors.add :base, "Terminal data memory damaged"
300
+ when 40 then errors.add :base, "GSM module error (registration not possible, wrong PIN, damaged GSM module)"
301
+ when 41 then errors.add :base, "KLEN SD card is not valid"
302
+ when 42 then errors.add :base, "KLEN SD card is missing"
303
+ when 43 then errors.add :base, "KLEN SD card data error"
304
+ when 44 then errors.add :base, "New KLEN SD card is put in a terminal with sales registration in RAM memory (daily report with zeroing must be done before changing the KLEN SD cards)"
305
+ when 45 then errors.add :base, "New KLEN SD card is not registered because some fiscal parameters cannot be changed"
306
+ when 46 then errors.add :base, "New KLEN SD card is put and fiscalization must be done"
307
+ when 47 then errors.add :base, "Recognized a KLEN SD card from a different device – only reports are available"
308
+ end
309
+ when 0x70 then @ready = true
310
+ when 0x71 then @ready = false
311
+ when 0x7E then errors.add :base, "Failed RAM"
312
+ when 0x7F then errors.add :base, "Wrong command"
313
+ end
314
+ end
315
+ end
316
+
317
+ class PrinterStatus
318
+
319
+ def initialize(status)
320
+ end
321
+
322
+ def start_bon_flag?
323
+ end
324
+
325
+ def end_bon_flag?
326
+ end
327
+
328
+ def last_transaction
329
+ end
330
+
331
+ def transaction_count
332
+ end
333
+
334
+ def last_transaction_sum
335
+ end
336
+
337
+ def all_transaction_sum
338
+ end
339
+
340
+ def total_sum
341
+ end
342
+
343
+ def stl_discount_flag?
344
+ end
345
+
346
+ def last_recept_number
347
+ end
348
+
349
+ def last_invoice_number
350
+ end
351
+
352
+ def available_invoice_numbers
353
+ end
354
+
355
+ def plu_count_in_memory
356
+ end
357
+ end
358
+ end
359
+ end
@@ -1,3 +1,3 @@
1
1
  module Extface
2
- VERSION = "0.1.9"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: extface
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Vangelov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-21 00:00:00.000000000 Z
11
+ date: 2014-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '>='
18
18
  - !ruby/object:Gem::Version
19
- version: 4.0.1
19
+ version: 4.0.5
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '>='
25
25
  - !ruby/object:Gem::Version
26
- version: 4.0.1
26
+ version: 4.0.5
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: redis
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -98,9 +98,8 @@ files:
98
98
  - app/models/extface/driver.rb
99
99
  - app/models/extface/driver/daisy/commands_fx1200.rb
100
100
  - app/models/extface/driver/daisy_fx1200.rb
101
- - app/models/extface/driver/epson/esc_pos.rb
102
- - app/models/extface/driver/epson/fiscal.rb
103
- - app/models/extface/driver/epson_tm_u220.rb
101
+ - app/models/extface/driver/eltrade/commands_fp4.rb
102
+ - app/models/extface/driver/eltrade_tm_u220.rb
104
103
  - app/models/extface/driver/generic_pos.rb
105
104
  - app/models/extface/driver/star_scp700.rb
106
105
  - app/models/extface/driver/star_tsp200.rb
@@ -111,7 +110,7 @@ files:
111
110
  - app/views/extface/devices/index.html.erb
112
111
  - app/views/extface/devices/show.html.erb
113
112
  - app/views/extface/driver/daisy_fx1200/_settings.html.erb
114
- - app/views/extface/driver/epson_tm_u220/_settings.html.erb
113
+ - app/views/extface/driver/eltrade_tm_u220/_settings.html.erb
115
114
  - app/views/extface/driver/generic_pos/_settings.html.erb
116
115
  - app/views/extface/driver/star_scp700/_settings.html.erb
117
116
  - app/views/extface/driver/star_tsp200/_settings.html.erb
@@ -1,12 +0,0 @@
1
- require 'active_support/concern'
2
- module Extface
3
- module Driver::Epson::EscPos
4
-
5
- def autocut(partial = true) # (Function B)
6
- # <GS> 'V' 0x65 x - Full-cut command
7
- # <GS> 'V' 0x66 x - Partial-cut command
8
- push partial ? "\x1D\x56\x65\x03" : "\x1D\x56\x66\x03"
9
- end
10
-
11
- end
12
- end
@@ -1,99 +0,0 @@
1
- module Extface
2
- module Driver::Epson::Fiscal
3
- STX = 0x02
4
- ETX = 0x03
5
- SEP = 0x1c
6
- DC2 = 0x12
7
- DC4 = 0x14
8
- NAK = 0x15
9
-
10
- module Control
11
- STATUS_IF = 0x38
12
- X_Z_REPORTS = 0x39
13
- FISC_MEM_REPORT_DATE = 0x3a
14
- FISC_MEM_REPORT = 0x3b
15
- end
16
- module Vouchers
17
- OPEN_FISCAL_VOUCHER = 0x40
18
- PRINT_FISCAL_TEXT = 0x41
19
- PRINT_FISCAL_ARTICLE = 0x42
20
- SUBTOTAL_FISCAL = 0x43
21
- FISCAL_VOUCHER = 0x44 # pay / cancel / discount in
22
- CLOSE_FISCAL_VOUCHER = 0x45
23
- end
24
- module NonFiscal
25
- OPEN_NON_FISCAL_DOC = 0x48
26
- PRINT_NON_FISCAL_TEXT = 0x49
27
- CLOSE_NON_FISCAL_DOC = 0x4a
28
- end
29
- module Printer
30
- CUT_PAPER = 0x4b
31
- ADVANCE_PAPER = 0x50
32
- ACTIVATE_SLIP = 0xa0 #TMU950, TMU675
33
- DISABLE_SLIP = 0xa1
34
- FORMAT_CHECKS = 0xaa
35
- FORMAT_ENDOSEMENT = 0xab
36
- end
37
- module General
38
- SET_DATE_HOUR = 0x58
39
- GET_DATE_HOUR = 0x59
40
- HEADED = 0x5d
41
- FOOT_OF_PAGE = 0x5e
42
- OPEN_DRAWER_1 = 0x7b
43
- OPEN_DRAWER_2 = 0x7c
44
- end
45
-
46
- def handle(buffer)
47
- bytes_processed = 0
48
- if frame_match = buffer.match(/\x02.*\x03.{4}/n)
49
- frame_data = frame_match.to_s
50
- rpush frame_data
51
- bytes_processed = frame_match.pre_match.length + frame_data.length
52
- end
53
- return bytes_processed
54
- end
55
-
56
- def build_packet(cmd, fields = [])
57
- String.new.tap() do |frame|
58
- frame << STX
59
- frame << sequence_number
60
- frame << cmd
61
- fields.each do |field|
62
- frame << SEP
63
- frame << field
64
- end
65
- frame << ETX
66
- frame << bcc(frame)
67
- end
68
- end
69
-
70
- private
71
- def bcc(buffer)
72
- sum = 0
73
- buffer.each_byte do |b|
74
- sum += b
75
- end
76
- sum.to_s(16).rjust(4, '0')
77
- end
78
-
79
- def sequence_number(increment = true)
80
- @seq ||= 0x20
81
- @seq += 1 if increment
82
- @seq = 0x20 if @seq == 0x7f
83
- @seq
84
- end
85
-
86
- class Frame
87
- include ActiveModel::Validations
88
- attr_reader :frame, :seq, :cmd, :fields_data, :fields, :bcc
89
-
90
- def initialize(buffer)
91
- if match = buffer.match(/\x02([\x20-\x7F])([\x30-\xaf])\x1c(.*)\x03(.{4})/n)
92
- @frame = match.to_a.first
93
- @seq, @cmd, @fileds_data, @bcc = match.captures
94
- @fields = @fields_data.split("\x1c")
95
- end
96
- end
97
- end
98
- end
99
- end
@@ -1,21 +0,0 @@
1
- require 'extface/driver/epson/esc_pos'
2
- require 'extface/driver/epson/fiscal'
3
- module Extface
4
- class Driver::EpsonTmU220 < Driver::GenericPos
5
- NAME = 'Epson TM-U220 (Serial)'.freeze
6
- GROUP = Extface::FISCAL_DRIVER
7
-
8
- DEVELOPMENT = true #driver is not ready for production (not passing all tests or has major bugs)
9
-
10
- # Select driver features
11
- RAW = true #responds to #push(data) and #pull
12
- PRINT = true #POS, slip printers
13
- FISCAL = true #cash registers, fiscal printers
14
- REPORT = false #only transmit data that must be parsed by handler, CDR, report devices
15
-
16
- has_serial_config
17
-
18
- include Extface::Driver::Epson::EscPos
19
- include Extface::Driver::Epson::Fiscal
20
- end
21
- end