extface 0.7.1 → 0.7.2

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
  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