smartware 0.2.7 → 0.2.8

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.
@@ -5,6 +5,13 @@ interfaces:
5
5
  - name: Modem
6
6
  uri: druby://localhost:6002
7
7
  driver: Dummy
8
+ - name: Watchdog
9
+ uri: druby://localhost:6003
10
+ driver: Dummy
11
+ - name: CardReader
12
+ uri: druby://localhost:6004
13
+ driver: Dummy
8
14
  - name: Printer
9
15
  uri: druby://localhost:6005
10
16
  driver: Dummy
17
+ connection_timeout: 60
@@ -0,0 +1,60 @@
1
+ require 'drb'
2
+
3
+ module Smartware
4
+ module Client
5
+
6
+ module CardReader
7
+
8
+ DRb.start_service
9
+ @device = DRbObject.new_with_uri('druby://localhost:6004')
10
+
11
+ def self.open(limit_min = nil, limit_max = nil)
12
+ @device.open_session(limit_min, limit_max)
13
+ end
14
+
15
+ def self.close
16
+ @device.close_session
17
+ end
18
+
19
+ def self.status
20
+ @device.status
21
+ end
22
+
23
+ def self.error
24
+ @device.error
25
+ end
26
+
27
+ def self.model
28
+ @device.model
29
+ end
30
+
31
+ def self.version
32
+ @device.version
33
+ end
34
+
35
+ def self.card_inserted?
36
+ @device.card_inserted?
37
+ end
38
+
39
+ def self.start_accepting
40
+ @device.start_accepting
41
+ end
42
+
43
+ def self.stop_accepting
44
+ @device.stop_accepting
45
+ end
46
+
47
+ def self.eject
48
+ @device.eject
49
+ end
50
+
51
+ def self.capture
52
+ @device.capture
53
+ end
54
+
55
+ def self.read_magstrip
56
+ @device.read_magstrip
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,71 @@
1
+ module Smartware
2
+ module Driver
3
+ module CardReader
4
+ class Dummy
5
+ def initialize(config)
6
+ @accepting = false
7
+ @state = nil
8
+ end
9
+
10
+ def model
11
+ "Dummy card reader"
12
+ end
13
+
14
+ def version
15
+ ""
16
+ end
17
+
18
+ def ready?
19
+ true
20
+ end
21
+
22
+ def accepting?
23
+ @accepting
24
+ end
25
+
26
+ def accepting=(accepting)
27
+ @state = :accepting if accepting
28
+ @accepting = accepting
29
+ end
30
+
31
+ def eject
32
+ @state = :eject
33
+
34
+ self
35
+ end
36
+
37
+ def capture
38
+ @state = :eject
39
+ self
40
+ end
41
+
42
+ def status
43
+ case @state
44
+ when nil
45
+ :ready
46
+
47
+ when :accepting
48
+ @state = :inserted
49
+ :card_at_gate
50
+
51
+ when :inserted
52
+ :card_inserted
53
+
54
+ when :eject
55
+ @state = nil
56
+ :card_at_gate
57
+ end
58
+ end
59
+
60
+ def read_magstrip
61
+ [
62
+ "B4154000000000000^IVANOV/IVAN^1501101000",
63
+ "4154000000000000=1501101000",
64
+ nil,
65
+ nil
66
+ ]
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,466 @@
1
+ require "serialport"
2
+ require "digest/crc16_ccitt"
3
+
4
+ module Smartware
5
+
6
+ module Driver
7
+ module CardReader
8
+ class ICT3K5
9
+ ERRORS = {
10
+ 0x00 => Interface::CardReader::COMMUNICATION_ERROR, # A given command code is unidentified
11
+ 0x01 => Interface::CardReader::COMMUNICATION_ERROR, # Parameter is not correct
12
+ 0x02 => Interface::CardReader::COMMUNICATION_ERROR, # Command execution is impossible
13
+ 0x03 => Interface::CardReader::COMMUNICATION_ERROR, # Function is not implemented
14
+ 0x04 => Interface::CardReader::COMMUNICATION_ERROR, # Command data error
15
+ 0x06 => Interface::CardReader::COMMUNICATION_ERROR, # Key for decrypting is not received
16
+ 0x10 => Interface::CardReader::CARD_JAM_ERROR,
17
+ 0x11 => Interface::CardReader::CARD_ERROR, # Shutter error
18
+ 0x13 => Interface::CardReader::CARD_ERROR, # Long card
19
+ 0x14 => Interface::CardReader::CARD_ERROR, # Short card
20
+ 0x15 => Interface::CardReader::HARDWARE_ERROR, # Flash Memory Parameter Area CRC error
21
+ 0x16 => Interface::CardReader::CARD_ERROR, # Card position move
22
+ 0x17 => Interface::CardReader::CARD_JAM_ERROR, # Jam error at retrieve
23
+ 0x18 => Interface::CardReader::CARD_ERROR, # Two card error
24
+ 0x20 => Interface::CardReader::MAG_READ_ERROR, # Parity error
25
+ 0x21 => Interface::CardReader::MAG_READ_ERROR, # Sentinel error
26
+ 0x23 => Interface::CardReader::MAG_READ_ERROR, # No data contents
27
+ 0x24 => Interface::CardReader::MAG_READ_ERROR, # No stripe
28
+ 0x30 => Interface::CardReader::HARDWARE_ERROR, # Power loss
29
+ 0x31 => Interface::CardReader::COMMUNICATION_ERROR, # DTR low
30
+ 0x39 => Interface::CardReader::HARDWARE_ERROR, # Fan failure
31
+ 0x40 => Interface::CardReader::CARD_ERROR, # Pull out error
32
+ 0x43 => Interface::CardReader::CARD_ERROR, # IC positioning error
33
+ 0x50 => Interface::CardReader::HARDWARE_ERROR, # Capture counter overflow
34
+ 0x60 => Interface::CardReader::ICC_ERROR, # Abnormal VCC condition
35
+ 0x61 => Interface::CardReader::ICC_ERROR, # ATR error
36
+ 0x62 => Interface::CardReader::ICC_ERROR, # Invalid ATR error
37
+ 0x63 => Interface::CardReader::ICC_ERROR, # No response
38
+ 0x64 => Interface::CardReader::ICC_ERROR, # Communication error
39
+ 0x65 => Interface::CardReader::ICC_ERROR, # Not activated
40
+ 0x66 => Interface::CardReader::ICC_ERROR, # Unsupported card
41
+ 0x69 => Interface::CardReader::ICC_ERROR, # Unsupported card
42
+ 0x73 => Interface::CardReader::HARDWARE_ERROR, # EEPROM error
43
+ 0xB0 => Interface::CardReader::COMMUNICATION_ERROR # Not received initialize
44
+ }
45
+
46
+ class CRC < Digest::CRC16CCITT
47
+ INIT_CRC = 0x0000
48
+ end
49
+
50
+ class CommandResponse
51
+ def initialize(response)
52
+ @response = response
53
+ end
54
+
55
+ def error?
56
+ @response.nil? || (@response[0] != "P" && @response[0] != "N")
57
+ end
58
+
59
+ def positive?
60
+ @response[0] == "P"
61
+ end
62
+
63
+ def negative?
64
+ @response[0] == "N"
65
+ end
66
+
67
+ def response
68
+ @response[1..-1]
69
+ end
70
+ end
71
+
72
+ STX = 0xF2
73
+ ACK = 0x06
74
+ NAK = 0x15
75
+
76
+ def initialize(config)
77
+ @config = config
78
+
79
+ @port = SerialPort.new(config["port"], 115200, 8, 1, SerialPort::EVEN)
80
+
81
+ @state = :not_ready
82
+ @event_read, @event_write = IO.pipe
83
+ @read_buf = ""
84
+ @write_buf = ""
85
+ @command_queue = Queue.new
86
+ @status_mutex = Mutex.new
87
+ @active_command = nil
88
+ @active_block = nil
89
+ @start_time = nil
90
+ @retries = nil
91
+ @ready = false
92
+ @accepting = false
93
+
94
+ Thread.new &method(:dispatch)
95
+ end
96
+
97
+ def model
98
+ "ICT3K5"
99
+ end
100
+
101
+ def version
102
+ ""
103
+ end
104
+
105
+ def ready?
106
+ @status_mutex.synchronize { @ready }
107
+ end
108
+
109
+ def accepting?
110
+ @status_mutex.synchronize { @accepting }
111
+ end
112
+
113
+ def accepting=(accepting)
114
+ if accepting
115
+ set_led :green
116
+ resp = command 0x3A, 0x30
117
+ else
118
+ set_led :red
119
+ resp = command 0x3A, 0x31
120
+ end
121
+
122
+ translate_response resp
123
+
124
+ @status_mutex.synchronize { @accepting = accepting }
125
+ end
126
+
127
+ def eject
128
+ resp = command 0x33, 0x30
129
+ translate_response resp
130
+
131
+ self
132
+ end
133
+
134
+ def capture
135
+ resp = command 0x33, 0x31
136
+ translate_response resp
137
+
138
+ self
139
+ end
140
+
141
+ def status
142
+ return :not_ready if !ready?
143
+
144
+ resp = command 0x31, 0x30
145
+ translate_response resp
146
+
147
+ case resp.response[2..3]
148
+ when "00"
149
+ :ready
150
+
151
+ when "01"
152
+ :card_at_gate
153
+
154
+ when "02"
155
+ :card_inserted
156
+
157
+ else
158
+ :not_ready
159
+ end
160
+ end
161
+
162
+ def read_magstrip
163
+ [ 0x31, 0x32, 0x33, 0x34 ].map! do |track|
164
+ resp = command 0x36, track
165
+ translate_response resp if resp.error?
166
+
167
+ if resp.positive?
168
+ resp.response[4..-1]
169
+ else
170
+ nil
171
+ end
172
+ end
173
+ end
174
+
175
+ private
176
+
177
+ def command(*args, &block)
178
+ if block_given?
179
+ @command_queue.push [ args, block ]
180
+ @event_write.write "\x01"
181
+ else
182
+ queue = Queue.new
183
+ command(*args) { |response| queue.push response }
184
+ queue.pop
185
+ end
186
+ end
187
+
188
+ def translate_response(response)
189
+ if response.error?
190
+ raise Interface::CardReader::CardReaderError.new(
191
+ "communication error",
192
+ Interface::CardReader::COMMUNICATION_ERROR
193
+ )
194
+ elsif response.negative?
195
+ error = response.response[0..1].to_i(16)
196
+ if ERRORS.include? error
197
+ translated_error = ERRORS[error]
198
+ else
199
+ translated_error = Interface::CardReader::HARDWARE_ERROR
200
+ end
201
+
202
+ raise Interface::CardReader::CardReaderError.new(
203
+ "command failed: #{error}",
204
+ translated_error
205
+ )
206
+ end
207
+ end
208
+
209
+ def set_led(color)
210
+ code = nil
211
+
212
+ case color
213
+ when :off
214
+ code = 0x30
215
+
216
+ when :green
217
+ code = 0x31
218
+
219
+ when :red
220
+ code = 0x32
221
+
222
+ when :orange
223
+ code = 0x33
224
+ end
225
+
226
+ command(0x35, code) do |resp|
227
+
228
+ end
229
+ end
230
+
231
+ def complete_init(response)
232
+ if response.error?
233
+ Smartware::Logging.logger.info "ICT3K5: initialization error"
234
+ elsif response.negative?
235
+ Smartware::Logging.logger.info "ICT3K5: initialization negative: #{response.response}"
236
+ else
237
+ Smartware::Logging.logger.info "ICT3K5: initialization: #{response.response}"
238
+ @status_mutex.synchronize { @ready = true }
239
+ set_led :red
240
+ end
241
+ end
242
+
243
+ def run_periodic
244
+ if @start_time.nil?
245
+ elapsed = nil
246
+ else
247
+ elapsed = Time.now - @start_time
248
+ end
249
+
250
+ case @state
251
+ when :not_ready
252
+ if @port.dsr == 1
253
+
254
+ Smartware::Logging.logger.info "ICT3K5: DSR active, initializing"
255
+
256
+ @state = :accepting
257
+
258
+ flushed = []
259
+
260
+ command 0x30, # Initialize
261
+ 0x30, # Eject card,
262
+ 0x33, 0x32, 0x34, 0x31, 0x30, # Compatibility nonsense
263
+ 0x30, # Power down card
264
+ 0x31, # Identify reader
265
+ 0x30, # Eject card on DTR low
266
+ 0x30, # Turn off capture counter
267
+ &method(:complete_init)
268
+
269
+ flushed.each do |(command, block)|
270
+ block.call CommandResponse.new(error: "timeout")
271
+ end
272
+ end
273
+
274
+ when :waiting_ack
275
+ if elapsed > 0.3
276
+ Smartware::Logging.logger.info "ICT3K5: ACK timeout"
277
+ retry_or_fail
278
+ end
279
+
280
+ when :reading_response
281
+ if elapsed > 20
282
+ Smartware::Logging.logger.info "ICT3K5: command timeout"
283
+ retry_or_fail
284
+ end
285
+ end
286
+
287
+ if @port.dsr == 0
288
+ @status_mutex.synchronize do
289
+ @ready = false
290
+ @accepting = false
291
+ end
292
+
293
+ if !@active_command.nil?
294
+ Smartware::Logging.logger.info "ICT3K5: DSR fall"
295
+
296
+ fail_command
297
+ end
298
+
299
+ until @command_queue.empty?
300
+ unpacked, block = @command_queue.pop(true)
301
+
302
+ block.call CommandResponse.new(nil)
303
+ end
304
+ end
305
+ end
306
+
307
+ def start_execution
308
+ @event_read.readbyte
309
+
310
+ unpacked, @active_block = @command_queue.pop
311
+ @active_command = frame_command(unpacked)
312
+
313
+ @write_buf << @active_command
314
+ @start_time = Time.now
315
+ @state = :waiting_ack
316
+ @retries = 8
317
+ end
318
+
319
+ def complete_command(response)
320
+ block = @active_block
321
+
322
+ @state = :accepting
323
+ @active_command = nil
324
+ @active_block = nil
325
+
326
+ Smartware::Logging.logger.info "ICT3K5: completing command"
327
+
328
+ block.call CommandResponse.new(response)
329
+ end
330
+
331
+ def fail_command
332
+ block = @active_block
333
+
334
+ @state = :accepting
335
+ @active_command = nil
336
+ @active_block = nil
337
+
338
+ Smartware::Logging.logger.info "ICT3K5: failing command"
339
+
340
+ block.call CommandResponse.new(nil)
341
+ end
342
+
343
+ def retry_or_fail
344
+ if @retries == 0
345
+ fail_command
346
+ else
347
+ @retries -= 1
348
+ @start_time = Time.now
349
+ @state = :waiting_ack
350
+ @write_buf << @active_command
351
+ end
352
+ end
353
+
354
+ def frame_command(bytes)
355
+ data = [ STX, bytes.length + 1 ].pack("Cn")
356
+ data << "C"
357
+ data << bytes.pack("C*")
358
+
359
+ crc = CRC.new
360
+ crc << data
361
+ data << [ crc.checksum ].pack("n")
362
+
363
+ data
364
+ end
365
+
366
+ def read_chunk
367
+ @read_buf << @port.read_nonblock(8192)
368
+ rescue IO::WaitReadable
369
+ end
370
+
371
+ def write_chunk
372
+ bytes = @port.write_nonblock @write_buf
373
+ @write_buf.slice! 0, bytes
374
+
375
+ rescue IO::WaitWritable
376
+ end
377
+
378
+ def handle_input
379
+ until @read_buf.empty? do
380
+ case @state
381
+ when :waiting_ack
382
+ initial_byte = @read_buf.slice!(0, 1).ord
383
+
384
+ case initial_byte
385
+ when ACK
386
+ Smartware::Logging.logger.info "ICT3K5: ACK"
387
+
388
+ @state = :reading_response
389
+ @start_time = Time.now
390
+
391
+ when NAK
392
+ Smartware::Logging.logger.info "ICT3K5: NAK"
393
+
394
+ retry_or_fail
395
+
396
+ else
397
+ Smartware::Logging.logger.info "ICT3K5: garbage on line: #{initial_byte}"
398
+ end
399
+
400
+ when :reading_response
401
+ break if @read_buf.length < 5
402
+
403
+ leading_byte, length = @read_buf[0..2].unpack("Cn")
404
+ if leading_byte != STX
405
+ Smartware::Logging.logger.info "ICT3K5: garbage on line: #{leading_byte}"
406
+
407
+ @read_buf.slice! 0, 1
408
+ next
409
+ end
410
+
411
+ full_length = 5 + length
412
+
413
+ break if @read_buf.length < full_length
414
+
415
+ message = @read_buf.slice! 0, full_length
416
+ sum, = message.slice!(full_length - 2, 2).unpack("n")
417
+ crc = CRC.new
418
+ crc << message
419
+ if sum == crc.checksum
420
+ Smartware::Logging.logger.info "ICT3K5: message checksum ok, ACK and process"
421
+ @write_buf << ACK.chr
422
+ complete_command message[3..-1]
423
+ else
424
+ Smartware::Logging.logger.info "ICT3K5: message checksum invalid, NAK"
425
+ @write_buf << NAK.chr
426
+ end
427
+
428
+ else
429
+ break
430
+ end
431
+ end
432
+ end
433
+
434
+ def dispatch
435
+ loop do
436
+ begin
437
+ run_periodic
438
+
439
+ read_set = [ @port ]
440
+ write_set = []
441
+
442
+ read_set << @event_read if @state == :accepting
443
+ write_set << @port unless @write_buf.empty?
444
+
445
+ read_set, write_set, = IO.select read_set, write_set, [], 1
446
+
447
+ unless read_set.nil?
448
+ start_execution if read_set.include? @event_read
449
+ read_chunk if read_set.include? @port
450
+ write_chunk if write_set.include? @port
451
+ end
452
+
453
+ handle_input
454
+ rescue => e
455
+ Smartware::Logging.logger.error "Error in ICT3K5 dispatch:"
456
+ Smartware::Logging.logger.error e.to_s
457
+ e.backtrace.each do |line|
458
+ Smartware::Logging.logger.error line
459
+ end
460
+ end
461
+ end
462
+ end
463
+ end
464
+ end
465
+ end
466
+ end
@@ -9,7 +9,14 @@ module Smartware
9
9
  attr_reader :error, :model, :balance, :version
10
10
 
11
11
  def initialize(config)
12
- @config = config
12
+ @port = config["port"]
13
+ @balance_ussd = config["balance_ussd"]
14
+ @status_channel_id = config["status_channel"].to_i
15
+ @ppp_channel_id = config["ppp_channel"].to_i
16
+ @poll_interval = config["poll_interval"].to_i
17
+ @balance_interval = config["balance_interval"].to_i
18
+ @apn = config["apn"]
19
+
13
20
  @state = :closed
14
21
  @error = Interface::Modem::MODEM_NOT_AVAILABLE
15
22
  @mux = nil
@@ -18,7 +25,7 @@ module Smartware
18
25
  @model = "GSM modem"
19
26
  @version = ""
20
27
  @signal = "+CSQ: 99,99"
21
- @ussd_interval = 0
28
+ @balance_timer = 0
22
29
  @balance = nil
23
30
  @ppp_state = :stopped
24
31
  @ppp_pid = nil
@@ -70,13 +77,13 @@ module Smartware
70
77
  Smartware::Logging.logger.info "trying to open modem"
71
78
 
72
79
  begin
73
- @mux = CMUX::MUX.new @config["port"]
80
+ @mux = CMUX::MUX.new @port
74
81
  @state = :open
75
- @status_channel = @mux.allocate(@config["status_channel"]).open
82
+ @status_channel = @mux.allocate(@status_channel_id).open
76
83
  @chatter = CMUX::ModemChatter.new @status_channel
77
84
  @chatter.subscribe "CUSD", self
78
85
  @error = nil
79
- @ussd_interval = 0
86
+ @balance_timer = 0
80
87
  Smartware::Logging.logger.info "modem ready"
81
88
  rescue => e
82
89
  close_modem "unable to open modem: #{e}"
@@ -103,15 +110,15 @@ module Smartware
103
110
  end
104
111
 
105
112
  if modem_works
106
- if @config.include?("balance_ussd") && @ussd_interval == 0
107
- @ussd_interval = @config["balance_interval"]
113
+ if !@balance_ussd.nil? && @balance_timer == 0
114
+ @balance_timer = @balance_interval
108
115
  begin
109
- @chatter.command("+CUSD=1,\"#{@config["balance_ussd"]}\",15", 1)
116
+ @chatter.command("+CUSD=1,\"#{@balance_ussd}\",15", 1)
110
117
  rescue => e
111
118
  close_modem "USSD request failed: #{e}"
112
119
  end
113
120
  else
114
- @ussd_interval -= 1
121
+ @balance_timer -= 1
115
122
  end
116
123
  else
117
124
  close_modem "modem is not responding"
@@ -125,11 +132,11 @@ module Smartware
125
132
  if @state == :open
126
133
  Smartware::Logging.logger.info "trying to start pppd"
127
134
  begin
128
- @ppp_channel = @mux.allocate @config["ppp_channel"]
135
+ @ppp_channel = @mux.allocate @ppp_channel_id
129
136
 
130
137
  @ppp_pid = Process.spawn "smartware-ppp-helper",
131
138
  @ppp_channel.device,
132
- @config["apn"]
139
+ @apn
133
140
  @ppp_state = :running
134
141
 
135
142
  Smartware::Logging.logger.info "started pppd, PID #{@ppp_pid}"
@@ -171,12 +178,12 @@ module Smartware
171
178
  def wait_for_event
172
179
  if @state == :open
173
180
  begin
174
- CMUX::ModemChatter.poll [ @chatter ], @config["poll_interval"]
181
+ CMUX::ModemChatter.poll [ @chatter ], @poll_interval
175
182
  rescue => e
176
183
  close_modem "modem poll failed: #{e}"
177
184
  end
178
185
  else
179
- sleep @config["poll_interval"]
186
+ sleep @poll_interval
180
187
  end
181
188
 
182
189
  end
@@ -25,6 +25,13 @@ module Smartware
25
25
  end
26
26
 
27
27
  def print(data)
28
+ name = "smartwareprint_#{Time.now.strftime("%Y-%m-%d-%H:%M:%S")}.txt"
29
+ pathname = File.join(Dir.home, name)
30
+
31
+ File.open(pathname, 'w') { |io| io.write data }
32
+
33
+ Logging.logger.info "Created #{pathname}"
34
+
28
35
  true
29
36
  end
30
37
 
@@ -33,10 +40,23 @@ module Smartware
33
40
  end
34
41
 
35
42
  def new_render
36
- Redcarpet::Render::HTML.new
43
+ DummyRender.new
37
44
  end
38
45
  end
39
46
 
47
+ class DummyRender < Redcarpet::Render::Base
48
+ def linebreak
49
+ "\n"
50
+ end
51
+
52
+ def normal_text(text, keep_newlines = false)
53
+ unless keep_newlines
54
+ text.gsub! "\n", " "
55
+ end
56
+
57
+ text
58
+ end
59
+ end
40
60
  end
41
61
  end
42
62
  end
@@ -0,0 +1,83 @@
1
+ module Smartware
2
+ module Interface
3
+ class CardReader < Interface
4
+ COMMUNICATION_ERROR = 1
5
+ HARDWARE_ERROR = 2
6
+ CARD_JAM_ERROR = 3
7
+ CARD_ERROR = 4
8
+ MAG_READ_ERROR = 5
9
+ ICC_ERROR = 6
10
+
11
+ class CardReaderError < RuntimeError
12
+ attr_reader :code
13
+
14
+ def initialize(message, code)
15
+ super(message)
16
+
17
+ @code = code
18
+ end
19
+ end
20
+
21
+ def initialize(config)
22
+ super
23
+
24
+ @status[:model] = @device.model
25
+ @status[:version] = @device.version
26
+ end
27
+
28
+ def card_inserted?
29
+ @device.status == :card_inserted
30
+ rescue CardReaderError => e
31
+ @status[:error] = e.code
32
+ nil
33
+ end
34
+
35
+ def start_accepting
36
+ @device.accepting = true
37
+ @status[:error] = nil
38
+ true
39
+ rescue CardReaderError => e
40
+ @status[:error] = e.code
41
+ false
42
+ end
43
+
44
+ def stop_accepting
45
+ @device.accepting = false
46
+ @status[:error] = nil
47
+ true
48
+ rescue CardReaderError => e
49
+ @status[:error] = e.code
50
+ false
51
+ end
52
+
53
+ def eject
54
+ @device.eject
55
+
56
+ sleep 0.5 while @device.status == :card_at_gate
57
+
58
+ @status[:error] = nil
59
+ true
60
+ rescue CardReaderError => e
61
+ @status[:error] = e.code
62
+ false
63
+ end
64
+
65
+ def capture
66
+ @device.capture
67
+ @status[:error] = nil
68
+ true
69
+ rescue CardReaderError => e
70
+ @status[:error] = e.code
71
+ false
72
+ end
73
+
74
+ def read_magstrip
75
+ @device.read_magstrip
76
+
77
+ rescue CardReaderError => e
78
+ @status[:error] = e.code
79
+ nil
80
+ end
81
+ end
82
+ end
83
+ end
@@ -17,7 +17,7 @@ module Smartware
17
17
  unless @config["connection_timeout"].nil?
18
18
  Thread.new do
19
19
  begin
20
- monitor = ConnectionMonitor.new @config["connection_timeout"]
20
+ monitor = ConnectionMonitor.new @config["connection_timeout"].to_i
21
21
 
22
22
  monitor.run
23
23
  rescue => e
@@ -1,3 +1,3 @@
1
1
  module Smartware
2
- VERSION = "0.2.7"
2
+ VERSION = "0.2.8"
3
3
  end
data/lib/smartware.rb CHANGED
@@ -3,6 +3,7 @@ require 'yaml'
3
3
  require 'active_support/core_ext/string/inflections'
4
4
  require 'drb'
5
5
  require 'redcarpet'
6
+ require 'stringio'
6
7
 
7
8
  require 'smartkiosk/common'
8
9
 
@@ -14,11 +15,13 @@ require 'smartware/clients/cash_acceptor'
14
15
  require 'smartware/clients/printer'
15
16
  require 'smartware/clients/modem'
16
17
  require 'smartware/clients/watchdog'
18
+ require 'smartware/clients/card_reader'
17
19
  require 'smartware/interfaces/interface'
18
20
  require 'smartware/interfaces/cash_acceptor'
19
21
  require 'smartware/interfaces/modem'
20
22
  require 'smartware/interfaces/printer'
21
23
  require 'smartware/interfaces/watchdog'
24
+ require 'smartware/interfaces/card_reader'
22
25
  require 'smartware/connection_monitor'
23
26
 
24
27
  module Smartware
data/smartware.gemspec CHANGED
@@ -23,4 +23,5 @@ Gem::Specification.new do |gem|
23
23
  gem.add_dependency 'trollop'
24
24
  gem.add_dependency 'activesupport'
25
25
  gem.add_dependency 'redcarpet'
26
+ gem.add_dependency 'digest-crc'
26
27
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smartware
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.7
4
+ version: 0.2.8
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-01-21 00:00:00.000000000 Z
13
+ date: 2013-01-24 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: smartkiosk-common
@@ -108,6 +108,22 @@ dependencies:
108
108
  - - ! '>='
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: digest-crc
113
+ requirement: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ! '>='
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :runtime
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ! '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
111
127
  description: Smartware is the Smartkiosk hardware control daemon
112
128
  email:
113
129
  - e.sudarchikov@roundlake.ru
@@ -127,11 +143,14 @@ files:
127
143
  - bin/smartware-ppp-helper
128
144
  - config/smartware.yml.sample
129
145
  - lib/smartware.rb
146
+ - lib/smartware/clients/card_reader.rb
130
147
  - lib/smartware/clients/cash_acceptor.rb
131
148
  - lib/smartware/clients/modem.rb
132
149
  - lib/smartware/clients/printer.rb
133
150
  - lib/smartware/clients/watchdog.rb
134
151
  - lib/smartware/connection_monitor.rb
152
+ - lib/smartware/drivers/card_reader/dummy.rb
153
+ - lib/smartware/drivers/card_reader/ict3_k5.rb
135
154
  - lib/smartware/drivers/cash_acceptor/ccnet.rb
136
155
  - lib/smartware/drivers/cash_acceptor/dummy.rb
137
156
  - lib/smartware/drivers/modem/dummy.rb
@@ -140,6 +159,7 @@ files:
140
159
  - lib/smartware/drivers/printer/esc_pos.rb
141
160
  - lib/smartware/drivers/watchdog/dummy.rb
142
161
  - lib/smartware/drivers/watchdog/watchdog_daemon.rb
162
+ - lib/smartware/interfaces/card_reader.rb
143
163
  - lib/smartware/interfaces/cash_acceptor.rb
144
164
  - lib/smartware/interfaces/interface.rb
145
165
  - lib/smartware/interfaces/modem.rb