extface 0.1.9 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/MIT-LICENSE +1 -1
- data/app/models/extface/driver/daisy_fx1200.rb +1 -1
- data/app/models/extface/driver/eltrade/commands_fp4.rb +78 -0
- data/app/models/extface/driver/eltrade_tm_u220.rb +359 -0
- data/app/views/extface/driver/{epson_tm_u220 → eltrade_tm_u220}/_settings.html.erb +0 -0
- data/lib/extface/version.rb +1 -1
- metadata +7 -8
- data/app/models/extface/driver/epson/esc_pos.rb +0 -12
- data/app/models/extface/driver/epson/fiscal.rb +0 -99
- data/app/models/extface/driver/epson_tm_u220.rb +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ffc7be7748574fcff49cfea02aab44e7f4f97760
|
4
|
+
data.tar.gz: 426759fdcff98ca0979ef600877c42674f9b4733
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4cf1335ec7f7cf50da17e1816213b740a675e5d0b6223f13b9d4145ff14a14d50c6411b4ec29808568b9d39f456b1d657f160122c64da8596f5dfb0439d86ad9
|
7
|
+
data.tar.gz: 6821ca4e6a6e1078740eebc9c7d30a4dd899e204eb1c979eca3dd695080b35141c7eaff4bf036969151031c830dd4a2483b124396c357264e348391bd597361d
|
data/MIT-LICENSE
CHANGED
@@ -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/
|
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
|
File without changes
|
data/lib/extface/version.rb
CHANGED
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.
|
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-
|
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.
|
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.
|
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/
|
102
|
-
- app/models/extface/driver/
|
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/
|
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
|