extface 0.7.1 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6ac009d832ffa37b301bb919347d453ccbbe5a6ffc39320693132bdae2a39e30
4
- data.tar.gz: 22af9b02d3cbe48d96e558e80861ad8d75a5ba3fb662ae254473ff75c866de8e
3
+ metadata.gz: 8efd853272c69b139418f39bb6da6668ff26421b3306bb19362b297766b8dd1c
4
+ data.tar.gz: 5e1b4d8944463cad340a6a9cf595abb9809cd83c4a7921b597046a54228bbda0
5
5
  SHA512:
6
- metadata.gz: 94b2aab08c3471736845866598540912d312f9b856500a7a31671e6174f13a4b86a8db97bea15d23b04781f7035d86699dddf6072fecedce1b5fe3dde4cd95d3
7
- data.tar.gz: 14be7adba1c7bd42f727f5a7a2414904338156ee568ed82aa88458faeb9786e81af9a114d5d4ab93f8b8da78a0a1b3d45e70bb2dbc70c2fccd092878e084fcf6
6
+ metadata.gz: abc4767ce19343e70426c08ad4f05ea6b0bfd752864d62f3ee7ac27ec649edbc53f5925f2b92549cec95ac2843b2259473962f4136ba27f0cd8889289e99f606
7
+ data.tar.gz: 87e86cb335fcd01d503e638334943bd7d27653f84ec0a96a8f7435f8d615e388282edaf9f51671c32e94319c6b0ea5435fb27c13d46a9f8c6343a2c38cb0b2a7
@@ -0,0 +1,359 @@
1
+ ### http://www.datecs.bg/en/downloads/pdf?id=PM_XXXXXX_-BUL-FPprotocol_v2_04.pdf
2
+ module Extface
3
+ class Driver::Datecs::DpX5New < Extface::Driver::Base::Fiscal
4
+ NAME = 'Datecs DPX5 New'.freeze
5
+
6
+ RESPONSE_TIMEOUT = 3 #seconds
7
+ INVALID_FRAME_RETRIES = 6 #count (bad length, bad checksum)
8
+ ACKS_MAX_WAIT = 60 #count / nothing is forever
9
+ NAKS_MAX_COUNT = 3 #count
10
+ BAD_SEQ_MAX_COUNT = 3
11
+ NO_RESP_MAX_COUNT = 3
12
+
13
+ TAX_GROUPS_MAP = {
14
+ 1 => "\xc0",
15
+ 2 => "\xc1",
16
+ 3 => "\xc2",
17
+ 4 => "\xc3",
18
+ 5 => "\xc4",
19
+ 6 => "\xc5",
20
+ 7 => "\xc6",
21
+ 8 => "\xc7"
22
+ }
23
+
24
+ PAYMENT_TYPE_MAP = {
25
+ 1 => "P",
26
+ 2 => "N",
27
+ 3 => "C",
28
+ 4 => "D",
29
+ 5 => "B"
30
+ }
31
+
32
+ include Extface::Driver::Datecs::CommandsV1
33
+
34
+ def handle(buffer)
35
+ #if i = buffer.index(/[\x03\x16\x15]/) # find position of frame possible delimiter
36
+ if i = buffer.index("\x03") || buffer.index("\x16") || buffer.index("\x15")
37
+ rpush buffer[0..i] # this will make data available for #pull(timeout) method
38
+ return i+1 # return number of bytes processed
39
+ end
40
+ end
41
+
42
+ #tests
43
+ def non_fiscal_test
44
+ device.session("Non Fiscal Text") do |s|
45
+ s.notify "Printing Non Fiscal Text"
46
+ s.open_non_fiscal_doc
47
+ s.print "********************************"
48
+ s.print "Extface Print Test".center(32)
49
+ s.print "********************************"
50
+ s.fsend Printer::PAPER_MOVE, "1"
51
+ s.print "Driver: " + "#{self.class::NAME}".truncate(24)
52
+ s.close_non_fiscal_doc
53
+ s.notify "Printing finished"
54
+ end
55
+ end
56
+
57
+ def fiscal_test
58
+ sale_and_pay_items_session([
59
+ SaleItem.new( price: 0.01, text1: "Extface Test" )
60
+ ])
61
+ end
62
+
63
+ #reports
64
+ def z_report_session
65
+ device.session("Z Report") do |s|
66
+ s.notify "Z Report Start"
67
+ s.fsend Closure::DAY_FIN_REPORT, "0"
68
+ s.notify "Z Report End"
69
+ end
70
+ end
71
+
72
+ def x_report_session
73
+ device.session("X Report") do |s|
74
+ s.notify "X Report Start"
75
+ s.fsend Closure::DAY_FIN_REPORT, "2"
76
+ s.notify "X Report End"
77
+ end
78
+ end
79
+
80
+ def period_report_session(from, to, detailed = true)
81
+ device.session("Period Report #{ '(detailed)' if detailed }") do |s|
82
+ s.notify "Period Report Start #{ '(detailed)' if detailed }"
83
+ s.fsend detailed ? Reports::REPORT_FP_BY_DATE : Reports::COMPACT_REPORT_FP_BY_DATE, "#{from.strftime('%d%m%y')},#{to.strftime('%d%m%y')}"
84
+ s.notify "Period Report End"
85
+ end
86
+ end
87
+
88
+ #print
89
+ def open_non_fiscal_doc
90
+ fsend Sales::START_NON_FISCAL_DOC
91
+ @print_session = true
92
+ end
93
+
94
+ def print(text) #up to 38 sybols, TODO check
95
+ raise "Not in print session" unless @print_session
96
+ fsend Sales::PRINT_NON_FISCAL_TEXT, text
97
+ end
98
+
99
+ def close_non_fiscal_doc
100
+ fsend Sales::END_NON_FISCAL_DOC
101
+ @print_session = false
102
+ end
103
+
104
+ def check_status
105
+ flush #clear receive buffer
106
+ fsend(Info::GET_STATUS, 'X') # get 6 bytes status
107
+ errors.empty?
108
+ end
109
+
110
+ #fiscal
111
+ def open_fiscal_doc(operator = "1", password = "1")
112
+ fsend Sales::START_FISCAL_DOC, "#{operator.presence || "1"},#{password.presence || "1"},,1"
113
+ @fiscal_session = true
114
+ end
115
+
116
+ def close_fiscal_doc
117
+ raise "Not in fiscal session" unless @fiscal_session
118
+ fsend Sales::END_FISCAL_DOC
119
+ @fiscal_session = false
120
+ end
121
+
122
+ def add_sale(sale_item)
123
+ raise "Not in fiscal session" unless @fiscal_session
124
+ fsend Sales::SALE_AND_SHOW, build_sale_data(sale_item)
125
+ end
126
+
127
+ def add_comment(text)
128
+ raise "Not in fiscal session" unless @fiscal_session
129
+ end
130
+
131
+ def add_payment(value = nil, type_num = nil)
132
+ raise "Not in fiscal session" unless @fiscal_session
133
+ payment_data = "".tap() do |data|
134
+ data << "\t"
135
+ data << PAYMENT_TYPE_MAP[type_num || 1]
136
+ data << ("%.2f" % value) unless value.blank?
137
+ end
138
+ fsend(Sales::TOTAL, payment_data)
139
+ end
140
+
141
+ def total_payment
142
+ raise "Not in fiscal session" unless @fiscal_session
143
+ fsend(Sales::TOTAL, "\t")
144
+ end
145
+
146
+ #basket
147
+ def sale_and_pay_items_session(items = [], operator = "1", password = "1")
148
+ device.session("Fiscal Doc") do |s|
149
+ s.notify "Fiscal Doc Start"
150
+ s.open_fiscal_doc
151
+ s.notify "Register Sale"
152
+ items.each do |item|
153
+ s.add_sale(item)
154
+ end
155
+ s.notify "Register Payment"
156
+ s.total_payment
157
+ s.notify "Close Fiscal Receipt"
158
+ s.close_fiscal_doc
159
+ s.notify "Fiscal Doc End"
160
+ end
161
+ end
162
+
163
+ def cancel_doc_session
164
+ device.session("Doc cancel") do |s|
165
+ s.notify "Doc Cancel Start"
166
+ s.fsend Sales::CANCEL_FISCAL_DOC
167
+ s.paper_cut
168
+ s.notify "Doc Cancel End"
169
+ end
170
+ end
171
+
172
+ #common
173
+ def fsend(cmd, data = "") #return data or nil
174
+ packet_data = build_packet(cmd, data) #store packet to be able to re-transmit it with the same sequence number
175
+ result = false
176
+ invalid_frames = 0 #counter for bad responses
177
+ nak_messages = 0 #counter for rejected packets (should re-transmit the packet)
178
+ no_resp = 0
179
+ flush #prevent double packet response issue like daisy driver
180
+ push packet_data #send packet
181
+ ACKS_MAX_WAIT.times do |retries|
182
+ errors.clear
183
+ if resp = frecv(RESPONSE_TIMEOUT)
184
+ if resp.valid?
185
+ human_status_errors(resp.status)
186
+ if errors.empty?
187
+ result = resp.data
188
+ break
189
+ else
190
+ raise errors.full_messages.join(',')
191
+ end
192
+ else #ack, nak or bad
193
+ if resp.nak?
194
+ nak_messages += 1
195
+ if nak_messages > NAKS_MAX_COUNT
196
+ errors.add :base, "#{NAKS_MAX_COUNT} NAKs Received. Abort!"
197
+ break
198
+ end
199
+ elsif !resp.ack?
200
+ invalid_frames += 1
201
+ if invalid_frames > INVALID_FRAME_RETRIES
202
+ errors.add :base, "#{INVALID_FRAME_RETRIES} Broken Packets Received. Abort!"
203
+ break
204
+ end
205
+ end
206
+ push packet_data unless resp.ack?
207
+ end
208
+ else
209
+ no_resp += 1
210
+ if no_resp > NO_RESP_MAX_COUNT
211
+ p "No reply in #{NO_RESP_MAX_COUNT * RESPONSE_TIMEOUT} seconds. Abort!"
212
+ errors.add :base, "No reply in #{NO_RESP_MAX_COUNT * RESPONSE_TIMEOUT} seconds. Abort!"
213
+ return result
214
+ end
215
+ end
216
+ errors.add :base, "#{ACKS_MAX_WAIT} ACKs Received. Abort!"
217
+ end
218
+ return result
219
+ end
220
+
221
+ def frecv(timeout) # return Frame or nil
222
+ rframe = nil
223
+ BAD_SEQ_MAX_COUNT.times do
224
+ errors.clear
225
+ if frame_bytes = pull(timeout)
226
+ rframe = Frame.new(frame_bytes.b)
227
+ if rframe.seq.nil? || rframe.seq.ord == sequence_number(false) #accept only current sequence number as reply
228
+ break
229
+ else
230
+ errors.add :base, "Sequence mismatch"
231
+ p "Invalid sequence (expected: #{sequence_number(false).to_s(16)}, got: #{rframe.seq.ord.to_s(16)})"
232
+ rframe = nil #invalidate mismatch sequence frame for the last retry
233
+ end
234
+ else
235
+ errors.add :base, "No data received from device"
236
+ break
237
+ end
238
+ end
239
+ return rframe
240
+ end
241
+
242
+ def build_packet(cmd, data = "")
243
+ "".b.tap() do |packet|
244
+ packet << STX #Preamble. 1 byte long. Value: 01H.
245
+ packet << 0x20 + 4 + data.b.length #Number of bytes from <01> preamble (excluded) to <05> (included) plus the fixed offset of 20H
246
+ packet << sequence_number #Sequence number of the frame. Length : 1 byte. Value: 20H – FFH.
247
+ packet << cmd #Length: 1 byte. Value: 20H - 7FH.
248
+ packet << data.b #Length: 0 - 218 bytes for Host to printer
249
+ packet << PA1 #Post-amble. Length: 1 byte. Value: 05H.
250
+ packet << Frame.bcc(packet[1..-1])#Control sum (0000H-FFFFH). Length: 4 bytes. Value of each byte: 30H-3FH
251
+ packet << ETX #Terminator. Length: 1 byte. Value: 03H.
252
+ end
253
+ end
254
+
255
+ def paper_cut
256
+ device.session('Paper Cut') do |s|
257
+ s.push build_packet(Printer::PAPER_CUT)
258
+ end
259
+ end
260
+
261
+ def human_status_errors(status) #6 bytes status
262
+ status_0 = status[0].ord
263
+ errors.add :base, "Fiscal Device General Error" unless (status_0 & 0x20).zero?
264
+ errors.add :base, "Invalid Command" unless (status_0 & 0x02).zero?
265
+ errors.add :base, "Date & Time Not Set" unless (status_0 & 0x04).zero?
266
+ errors.add :base, "Syntax Error" unless (status_0 & 0x01).zero?
267
+ status_1 = status[1].ord
268
+ errors.add :base, "Unpermitted Command In This Mode" unless (status_1 & 0x02).zero?
269
+ errors.add :base, "Field Overflow" unless (status_1 & 0x01).zero?
270
+ end
271
+
272
+ private
273
+ def build_sale_data(item)
274
+ encoded_text1 = device.encoding.present? ? item.text1.encode(device.encoding).b : item.text1
275
+ encoded_text1 = encoded_text1.mb_chars.slice!(0..19).to_s.b + '...' if encoded_text1 && encoded_text1.b.length > 22
276
+
277
+ encoded_text2 = device.encoding.present? ? item.text2.encode(device.encoding).b : item.text2
278
+ encoded_text2 = encoded_text2.mb_chars.slice!(0..19).to_s.b + '...' if encoded_text2 && encoded_text2.b.length > 22
279
+
280
+ "".b.tap() do |data|
281
+ data << encoded_text1 unless encoded_text1.blank?
282
+ data << "\x0a#{encoded_text2}" unless encoded_text2.blank?
283
+ data << "\t"
284
+ data << TAX_GROUPS_MAP[item.tax_group || 2].b
285
+ data << ("%.2f" % item.price)
286
+ data << "*#{'%.3f' % item.qty}" unless item.qty.blank?
287
+ data << ",#{item.percent}" unless item.percent.blank?
288
+ data << ",;#{'%.2f' % item.neto}" unless item.neto.blank?
289
+ end
290
+ end
291
+
292
+ def sequence_number(increment = true)
293
+ @seq ||= 0x1f
294
+ @seq += 1 if increment
295
+ @seq = 0x1f if @seq == 0x7f
296
+ @seq
297
+ end
298
+
299
+ class Frame
300
+ include ActiveModel::Validations
301
+ attr_reader :frame, :len, :seq, :cmd, :data, :status, :bcc
302
+
303
+ validates_presence_of :frame#, unless: :unpacked?
304
+ validate :bcc_validation
305
+ validate :len_validation
306
+
307
+ def initialize(buffer)
308
+ if match = buffer.match(/\x01(.{1})(.{1})(.{1})(.*)\x04(.{6})\x05(.{4})\x03/nm)
309
+ @frame = match.to_a.first
310
+ @len, @seq, @cmd, @data, @status, @bcc = match.captures
311
+ else
312
+ if buffer[/^\x16+$/] # only ACKs
313
+ @ack = true
314
+ elsif buffer.index("\x15")
315
+ @nak = true
316
+ end
317
+ end
318
+ end
319
+
320
+ def ack?; !!@ack; end #should wait, response is yet to come
321
+
322
+ def nak?; !!@nak; end #should retry command with same seq
323
+
324
+ private
325
+
326
+ def unpacked? # is it packed or unpacked message?
327
+ @ack || @nak
328
+ end
329
+
330
+ def bcc_validation
331
+ unless unpacked? || frame.blank?
332
+ calc_bcc = self.class.bcc frame[1..-6]
333
+ errors.add(:bcc, I18n.t('errors.messages.invalid')) if bcc != calc_bcc
334
+ end
335
+ end
336
+
337
+ def len_validation
338
+ unless unpacked? || frame.blank?
339
+ errors.add(:len, I18n.t('errors.messages.invalid')) if frame.nil? || len.ord != (frame[1..-6].length + 0x20)
340
+ end
341
+ end
342
+
343
+ class << self
344
+ def bcc(buffer)
345
+ sum = 0
346
+ buffer.each_byte do |byte|
347
+ sum += byte
348
+ end
349
+ "".tap() do |bcc|
350
+ 4.times do |halfbyte|
351
+ bcc.insert 0, (0x30 + ((sum >> (halfbyte*4)) & 0x0f)).chr
352
+ end
353
+ end
354
+ end
355
+ end
356
+ end
357
+
358
+ end
359
+ end
@@ -0,0 +1,12 @@
1
+
2
+ <%= button_to 'Paper Cut', fiscal_device_path(@device), remote: true, name: :paper_cut, value: true, class: 'btn btn-warning' %>
3
+
4
+ <%= button_to 'Non Fiscal Test', fiscal_device_path(@device), remote: true, name: :non_fiscal_test, value: true, class: 'btn btn-warning' %>
5
+
6
+ <%= button_to 'Fiscal Test', fiscal_device_path(@device), remote: true, name: :fiscal_test, value: true, class: 'btn btn-warning' %>
7
+
8
+ <%= button_to 'X Report', fiscal_device_path(@device), remote: true, name: :x_report, value: true, class: 'btn btn-warning' %>
9
+ <%= button_to 'Z Report', fiscal_device_path(@device), remote: true, name: :z_report, value: true, class: 'btn btn-warning' %>
10
+
11
+ <%= button_to 'Cancel Fiscal Doc', fiscal_device_path(@device), remote: true, name: :cancel_fiscal_doc, value: true, class: 'btn btn-danger' %>
12
+
@@ -1,3 +1,3 @@
1
1
  module Extface
2
- VERSION = "0.7.1"
2
+ VERSION = "0.7.2"
3
3
  end
Binary file
@@ -18746,3 +18746,20 @@ Completed 200 OK in 10004ms (ActiveRecord: 3.2ms)
18746
18746
  ActiveRecord::InternalMetadata Load (0.2ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? LIMIT ? [["key", "environment"], ["LIMIT", 1]]
18747
18747
   (0.1ms) begin transaction
18748
18748
   (0.0ms) commit transaction
18749
+  (0.2ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
18750
+  (87.7ms) DROP TABLE IF EXISTS "extface_devices"
18751
+  (0.3ms) SELECT sqlite_version(*)
18752
+  (105.1ms) CREATE TABLE "extface_devices" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" varchar, "name" varchar, "extfaceable_id" integer, "extfaceable_type" varchar, "driver_id" integer, "created_at" datetime, "updated_at" datetime, "encoding" varchar)
18753
+  (114.7ms) DROP TABLE IF EXISTS "extface_drivers"
18754
+  (115.2ms) CREATE TABLE "extface_drivers" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "type" varchar, "settings" text, "created_at" datetime, "updated_at" datetime)
18755
+  (105.2ms) DROP TABLE IF EXISTS "extface_jobs"
18756
+  (94.8ms) CREATE TABLE "extface_jobs" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "device_id" integer, "created_at" datetime, "updated_at" datetime, "description" varchar, "error" varchar, "failed_at" datetime, "completed_at" datetime, "connected_at" datetime, "started_at" datetime)
18757
+  (199.7ms) CREATE INDEX "index_extface_jobs_on_device_id" ON "extface_jobs" ("device_id")
18758
+  (123.0ms) DROP TABLE IF EXISTS "extface_serial_configs"
18759
+  (122.5ms) CREATE TABLE "extface_serial_configs" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "driver_id" integer, "serial_boud_rate" integer, "serial_data_length" integer, "serial_parity_check" integer, "serial_stop_bits" integer, "serial_handshake" integer, "created_at" datetime, "updated_at" datetime)
18760
+  (97.9ms) DROP TABLE IF EXISTS "shops"
18761
+  (114.9ms) CREATE TABLE "shops" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "created_at" datetime, "updated_at" datetime)
18762
+  (0.3ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
18763
+ ActiveRecord::InternalMetadata Load (0.2ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? LIMIT ? [["key", "environment"], ["LIMIT", 1]]
18764
+  (0.1ms) begin transaction
18765
+  (0.1ms) commit transaction
@@ -24,6 +24,12 @@ datecs_dp25:
24
24
  extfaceable: one(Shop)
25
25
  driver: datecs_dp25
26
26
 
27
+ datecs_dpX5_new:
28
+ uuid: datecs_dpX5new
29
+ name: Datect DPX5 New
30
+ extfaceable: one(Shop)
31
+ driver: datecs_dpX5_new
32
+
27
33
  datecs_dp35:
28
34
  uuid: datecs_dp35
29
35
  name: Datect DP35
@@ -15,6 +15,9 @@ datecs_fp550:
15
15
  datecs_dp25:
16
16
  type: Extface::Driver::Datecs::Dp25
17
17
 
18
+ datecs_dpX5_new:
19
+ type: Extface::Driver::Datecs::DpX5New
20
+
18
21
  datecs_dp35:
19
22
  type: Extface::Driver::Datecs::Dp35
20
23
 
@@ -0,0 +1,63 @@
1
+ require 'test_helper'
2
+
3
+ module Extface
4
+ class Driver::Datecs::Dp25Test < ActiveSupport::TestCase
5
+ setup do
6
+ @driver = extface_drivers(:datecs_dpX5_new)
7
+ @driver.flush # clear receive buffer
8
+ end
9
+
10
+ test "handle" do
11
+ assert_equal nil, @driver.handle('bad packet')
12
+ assert_equal 6, @driver.handle("\x01data\x03data"), "Frame not match"
13
+ assert_equal 9, @driver.handle("pre\x01data\x03data"), "Frame with preamble not match"
14
+ assert_equal 8, @driver.handle("\x16\x16\x01data\x03data"), "Frame with ACK preamble not match"
15
+ assert_equal 4, @driver.handle("pre\x15"), "NAK not match"
16
+ end
17
+
18
+ xtest "build packet" do
19
+ assert_equal "\x01\x24\x20\x4a\x05\x30\x30\x39\x33\x03".b, @driver.build_packet(0x4a), "packet without data"
20
+ assert_equal "\x01\x25\x21\x4a\x58\x05\x30\x30\x3e\x3d\x03".b, @driver.build_packet(0x4a, 'X'), "packet with data"
21
+ end
22
+
23
+ xtest "response frame" do
24
+ frame_class = @driver.class::Frame
25
+ assert frame_class.new("\x15").nak?, "NAK message failed"
26
+ assert frame_class.new("\x16\x16").ack?, "ACK message failed"
27
+ assert_nothing_raised do
28
+ assert_equal false, frame_class.new("bad data\x01\x25\x21\x4asome broken packet\x58\x05\x30\x30\x3e\x3d\x03".b).valid?
29
+ end
30
+ frame = frame_class.new("\x16\x01\x2C\x2F\x2D\x50\x04\x88\x80\xC0\x80\x80\xB0\x05\x30\x34\x35\x39\x03".b)
31
+ assert frame.valid?, "Vailid frame not recognized"
32
+ assert_equal "\x01\x2C\x2F\x2D\x50\x04\x88\x80\xC0\x80\x80\xB0\x05\x30\x34\x35\x39\x03".b, frame.frame
33
+ assert_equal "\x2c".b, frame.len
34
+ assert_equal "\x2f".b, frame.seq
35
+ assert_equal "\x2d".b, frame.cmd
36
+ assert_equal "\x50".b, frame.data
37
+ assert_equal "\x88\x80\xC0\x80\x80\xB0".b, frame.status
38
+ assert_equal "\x30\x34\x35\x39".b, frame.bcc
39
+ #bad check sum
40
+ frame = frame_class.new("\x01\x2C\x2F\x2D\x50\x04\x88\x80\xC0\x80\x80\xB0\x05\x30\x34\x35\x38\x03".b)
41
+ assert_equal false, frame.valid?
42
+ assert frame.errors.messages[:bcc]
43
+ #bad length
44
+ frame = frame_class.new("\x01\x2b\x2F\x2D\x50\x04\x88\x80\xC0\x80\x80\xB0\x05\x30\x34\x35\x38\x03".b)
45
+ assert_equal false, frame.valid?
46
+ assert frame.errors.messages[:len]
47
+ end
48
+
49
+ xtest "fsend" do
50
+ job = extface_jobs(:one)
51
+ job_thread = Thread.new do
52
+ @driver.set_job(job)
53
+ result = @driver.fsend(0x2C) # paper move command
54
+ end
55
+ simulate_device_pull(job)
56
+ @driver.handle("\x01\x31\x20\x4A\x88\x80\xC0\x80\x80\xB8\x04\x88\x80\xC0\x80\x80\xB8\x05\x30\x37\x3A\x34\x03".b)
57
+ simulate_device_pull(job)
58
+ @driver.handle("\x01\x38\x21\x30\x30\x30\x30\x30\x35\x30\x2C\x30\x30\x30\x30\x34\x39\x04\x80\x80\x88\x80\x80\xB8\x05\x30\x36\x35\x30\x03".b)
59
+ job_thread.join
60
+ assert @driver.errors.empty?
61
+ end
62
+ end
63
+ 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.7.1
4
+ version: 0.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Vangelov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-02 00:00:00.000000000 Z
11
+ date: 2019-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -106,6 +106,7 @@ files:
106
106
  - app/models/extface/driver/datecs/commands_v1.rb
107
107
  - app/models/extface/driver/datecs/dp25.rb
108
108
  - app/models/extface/driver/datecs/dp35.rb
109
+ - app/models/extface/driver/datecs/dp_x5_new.rb
109
110
  - app/models/extface/driver/datecs/fp550.rb
110
111
  - app/models/extface/driver/eltrade/commands_fp4.rb
111
112
  - app/models/extface/driver/eltrade_tm_u220.rb
@@ -132,6 +133,8 @@ files:
132
133
  - app/views/extface/driver/datecs/dp25/_settings.html.erb
133
134
  - app/views/extface/driver/datecs/dp35/_control.html.erb
134
135
  - app/views/extface/driver/datecs/dp35/_settings.html.erb
136
+ - app/views/extface/driver/datecs/dp_x5_new/_control.html.erb
137
+ - app/views/extface/driver/datecs/dp_x5_new/_settings.html.erb
135
138
  - app/views/extface/driver/datecs/fp550/_control.html.erb
136
139
  - app/views/extface/driver/datecs/fp550/_settings.html.erb
137
140
  - app/views/extface/driver/eltrade_tm_u220/_control_.html.erb
@@ -263,6 +266,7 @@ files:
263
266
  - test/models/extface/driver/daisy_fx1200_test.rb
264
267
  - test/models/extface/driver/datecs/dp25_test.rb
265
268
  - test/models/extface/driver/datecs/dp35_test.rb
269
+ - test/models/extface/driver/datecs/dp_x5_new_test.rb
266
270
  - test/models/extface/driver/datecs/fp550_test.rb
267
271
  - test/models/extface/driver/generic_pos_test.rb
268
272
  - test/models/extface/driver/posiflex/aura80_test.rb
@@ -391,6 +395,7 @@ test_files:
391
395
  - test/models/extface/driver/posiflex/aura80_test.rb
392
396
  - test/models/extface/driver/daisy_fx1200_test.rb
393
397
  - test/models/extface/driver/star_tsp200_test.rb
398
+ - test/models/extface/driver/datecs/dp_x5_new_test.rb
394
399
  - test/models/extface/driver/datecs/dp35_test.rb
395
400
  - test/models/extface/driver/datecs/fp550_test.rb
396
401
  - test/models/extface/driver/datecs/dp25_test.rb