smartware 0.1.16 → 0.1.17

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.
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.1.16
4
+ version: 0.1.17
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: 2012-12-28 00:00:00.000000000 Z
13
+ date: 2013-01-02 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: serialport
@@ -48,34 +48,10 @@ description: Smartware is the Smartkiosk hardware control daemon
48
48
  email:
49
49
  - e.sudarchikov@roundlake.ru
50
50
  - boris@roundlake.ru
51
- executables:
52
- - smartware
51
+ executables: []
53
52
  extensions: []
54
53
  extra_rdoc_files: []
55
- files:
56
- - .gitignore
57
- - Gemfile
58
- - LICENSE.txt
59
- - README.md
60
- - Rakefile
61
- - bin/smartware
62
- - lib/smartware.rb
63
- - lib/smartware/clients/cash_acceptor.rb
64
- - lib/smartware/clients/modem.rb
65
- - lib/smartware/clients/printer.rb
66
- - lib/smartware/drivers/cash_acceptor/ccnet.rb
67
- - lib/smartware/drivers/cash_acceptor/dummy.rb
68
- - lib/smartware/drivers/modem/dummy.rb
69
- - lib/smartware/drivers/modem/standard.rb
70
- - lib/smartware/drivers/printer/dummy.rb
71
- - lib/smartware/drivers/printer/tg24xx.rb
72
- - lib/smartware/interfaces/cash_acceptor.rb
73
- - lib/smartware/interfaces/modem.rb
74
- - lib/smartware/interfaces/printer.rb
75
- - lib/smartware/logging.rb
76
- - lib/smartware/service.rb
77
- - lib/smartware/version.rb
78
- - smartware.gemspec
54
+ files: []
79
55
  homepage: https://github.com/roundlake/smartware
80
56
  licenses: []
81
57
  post_install_message:
data/.gitignore DELETED
@@ -1,18 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- .idea
7
- Gemfile.lock
8
- InstalledFiles
9
- _yardoc
10
- coverage
11
- doc/
12
- lib/bundler/man
13
- pkg
14
- rdoc
15
- spec/reports
16
- test/tmp
17
- test/version_tmp
18
- tmp
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in smartware.gemspec
4
- gemspec
data/LICENSE.txt DELETED
@@ -1,22 +0,0 @@
1
- Copyright (c) 2012 ya.jeks
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md DELETED
@@ -1,29 +0,0 @@
1
- # Smartware
2
-
3
- TODO: Write a gem description
4
-
5
- ## Installation
6
-
7
- Add this line to your application's Gemfile:
8
-
9
- gem 'smartware'
10
-
11
- And then execute:
12
-
13
- $ bundle
14
-
15
- Or install it yourself as:
16
-
17
- $ gem install smartware
18
-
19
- ## Usage
20
-
21
- TODO: Write usage instructions here
22
-
23
- ## Contributing
24
-
25
- 1. Fork it
26
- 2. Create your feature branch (`git checkout -b my-new-feature`)
27
- 3. Commit your changes (`git commit -am 'Add some feature'`)
28
- 4. Push to the branch (`git push origin my-new-feature`)
29
- 5. Create new Pull Request
data/Rakefile DELETED
@@ -1 +0,0 @@
1
- require "bundler/gem_tasks"
data/bin/smartware DELETED
@@ -1,35 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- trap 'TTIN' do
4
- Thread.list.each do |thread|
5
- if thread.backtrace
6
- puts thread.backtrace.join("\n")
7
- else
8
- puts "<no backtrace available>"
9
- end
10
- end
11
- end
12
-
13
- require 'smartware/service'
14
- require 'dante'
15
-
16
- runner = Dante::Runner.new('smartware')
17
- runner.description = "Smartkiosk hardware control daemon"
18
- runner.with_options do |opts|
19
- opts.on("-c", "--config-file FILE", String, "Hardware config file to use. Sample: --config-file=/path/to/smartware.yml") do |x|
20
- options[:config] = x
21
- end
22
- end
23
-
24
- runner.execute do |opts|
25
- abort "You should specify hardware configuration file path(--config-file=/path/to/smartware.yml)" if opts[:config].nil?
26
-
27
- begin
28
- Smartware::Service.start(opts[:config])
29
- rescue => e
30
- raise e if $DEBUG
31
- STDERR.puts e.message
32
- STDERR.puts e.backtrace.join("\n")
33
- exit 1
34
- end
35
- end
@@ -1,37 +0,0 @@
1
- require 'drb'
2
-
3
- module Smartware
4
- module Client
5
-
6
- module CashAcceptor
7
-
8
- DRb.start_service
9
- @device = DRbObject.new_with_uri('druby://localhost:6001')
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.model
24
- @device.model
25
- end
26
-
27
- def self.banknotes
28
- @device.banknotes
29
- end
30
-
31
- def self.sum
32
- @device.cashsum
33
- end
34
-
35
- end
36
- end
37
- end
@@ -1,29 +0,0 @@
1
- require 'drb'
2
-
3
- module Smartware
4
- module Client
5
-
6
- module Modem
7
-
8
- DRb.start_service
9
- @device = DRbObject.new_with_uri('druby://localhost:6002')
10
-
11
- def self.error
12
- @device.error
13
- end
14
-
15
- def self.model
16
- @device.model
17
- end
18
-
19
- def self.balance
20
- @device.balance
21
- end
22
-
23
- def self.signal_level
24
- @device.signal_level
25
- end
26
-
27
- end
28
- end
29
- end
@@ -1,37 +0,0 @@
1
- require 'drb'
2
-
3
- module Smartware
4
- module Client
5
-
6
- module Printer
7
-
8
- DRb.start_service
9
- @device = DRbObject.new_with_uri('druby://localhost:6005')
10
-
11
- def self.error
12
- @device.error
13
- rescue => e
14
- 'No device'
15
- end
16
-
17
- def self.model
18
- @device.model
19
- rescue => e
20
- 'No device'
21
- end
22
-
23
- def self.test
24
- @device.test
25
- rescue => e
26
- 'No device'
27
- end
28
-
29
- def self.print(filepath)
30
- @device.print filepath
31
- rescue => e
32
- 'No device'
33
- end
34
-
35
- end
36
- end
37
- end
@@ -1,202 +0,0 @@
1
- # coding: utf-8
2
- #
3
- # CCNET protocol driver for CashCode bill validator
4
- #
5
- require 'serialport'
6
-
7
- module Smartware
8
- module Driver
9
- module CashAcceptor
10
-
11
- class CCNET
12
-
13
- RESET = 0x30
14
- GET_STATUS = 0x31
15
- SET_SECURITY = 0x32
16
- POLL = 0x33
17
- ENABLE_BILL_TYPES = 0x34
18
- STACK = 0x35
19
- RETURN = 0x36
20
- IDENTIFICATION = 0x37
21
- HOLD = 0x38
22
- SET_BARCODE_PARAMETERS = 0x39
23
- EXTRACT_BARCODE_DATA = 0x3A
24
- GET_BILL_TABLE = 0x41
25
- GET_CRC32_OF_THE_CODE = 0x51
26
- DOWNLOAD = 0x50
27
- REQUEST_STATISTICS = 0x60
28
- ACK = 0x00
29
- DISPENCE = 0x3C
30
-
31
- STATUSES = {
32
- "10" => "10", # 'Power up',
33
- "11" => "11", # 'Power Up with Bill in Validator',
34
- "12" => "12", # 'Power Up with Bill in Stacker',
35
- "13" => "13", # 'Initialize',
36
- "14" => "14", # 'Idling',
37
- "15" => "15", # 'Accepting',
38
- "17" => "16", # 'Stacking',
39
- "18" => "17", # 'Returning',
40
- "19" => "18", # 'Unit Disabled',
41
- "1a" => "19", # 'Holding',
42
- "1b" => "20", # 'Device Busy',
43
- "1c" => "21", # 'Rejecting',
44
- "82" => "22" # 'Bill returned'
45
- }
46
-
47
- ERRORS = {
48
- "41" => "23", # 'Drop Cassette Full',
49
- "42" => "24", # 'Drop Cassette out of position. The Bill Validator has detected the drop cassette to be open or removed.',
50
- "43" => "25", # 'Validator Jammed. A bill(s) has jammed in the acceptance path.',
51
- "44" => "26", # 'Drop Cassette Jammed. A bill has jammed in drop cassette.',
52
- "45" => "27", # 'Cheated. Intentions of the user to deceive the Bill Validator are detected',
53
- "46" => "28", # 'Pause. Bill Validator stops motion of the second bill until the second bill is removed.',
54
- "47" => "29", # 'Bill validator failure',
55
- "50" => "30", # 'Stack Motor Failure',
56
- "51" => "31", # 'Transport Motor Speed Failure',
57
- "52" => "32", # 'Transport Motor Failure',
58
- "53" => "33", # 'Aligning Motor Failure',
59
- "54" => "34", # 'Initial Cassette Status Failure',
60
- "55" => "35", # 'Optic Canal Failure',
61
- "56" => "36", # 'Magnetic Canal Failure',
62
- "5f" => "37" # 'Capacitance Canal Failure'
63
- }
64
-
65
- NOMINALS = { "2" => 10, "3" => 50, "4" => 100, "5" => 500, "6" => 1000, "7" => 5000 }
66
-
67
- def initialize(port)
68
- @port = port
69
- end
70
-
71
- def cassette?
72
- return false if error == "24"
73
- true
74
- end
75
-
76
- def model
77
- if answer = send([IDENTIFICATION], false)
78
- answer = answer[2..answer.length]
79
- return "#{answer[0..15]} #{answer[16..27]} #{answer[28..34].unpack("C*")}"
80
- else
81
- return "Unknown device answer"
82
- end
83
- rescue
84
- -1
85
- end
86
-
87
- def error
88
- res = poll
89
- ack
90
- return false if res != nil and CCNET::STATUSES.keys.include?(res[3])
91
- return false if res == nil
92
-
93
- result = check_error(res)
94
- rescue
95
- -1
96
- end
97
-
98
- def current_banknote
99
- poll
100
- ack
101
- hold
102
- res = poll
103
- ack
104
-
105
- result = check_error(res)
106
- if res != nil and res[2] == "7" and res[3] == "80" and CCNET::NOMINALS.keys.include?(res[4]) # has money?
107
- result = CCNET::NOMINALS[res[4]]
108
- end
109
- result
110
- end
111
-
112
- def get_status
113
- send([GET_STATUS])
114
- end
115
-
116
- def reset
117
- send([RESET])
118
- end
119
-
120
- def ack
121
- send([ACK])
122
- end
123
-
124
- def stack
125
- send([STACK])
126
- end
127
-
128
- def return
129
- send([RETURN])
130
- end
131
-
132
- def hold
133
- send([])
134
- end
135
-
136
- def poll
137
- send([POLL])
138
- end
139
-
140
- def accept
141
- send([ENABLE_BILL_TYPES,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF])
142
- end
143
-
144
- def cancel_accept
145
- send([ENABLE_BILL_TYPES,0x00,0x00,0x00,0x00,0x00,0x00])
146
- get_status
147
- end
148
-
149
- private
150
- def check_error(res)
151
- if CCNET::ERRORS.keys.include? res[3]
152
- res[3] == "47" ? CCNET::ERRORS[res[4]] : CCNET::ERRORS[res[3]] # More details for 47 error
153
- else
154
- false
155
- end
156
- end
157
-
158
- def crc_for(msg)
159
- polynom = 0x8408.to_i
160
- msg = msg.collect{|o| o.to_i}
161
- res = 0
162
- tmpcrc = 0
163
- 0.upto(msg.length-1){|i|
164
- tmpcrc = res ^ msg[i]
165
- 0.upto(7){
166
- if tmpcrc & 1 != 0
167
- tmpcrc = tmpcrc >> 1
168
- tmpcrc = tmpcrc ^ polynom
169
- else
170
- tmpcrc = tmpcrc >> 1
171
- end
172
- }
173
- res = tmpcrc
174
- }
175
- crc = tmpcrc
176
- crc = ("%02x" % crc).rjust(4,"0")
177
- crc = [Integer("0x"+crc[2..3]), Integer("0x"+crc[0..1])]
178
- end
179
-
180
- def send(msg, parse_answer = true)
181
- sp = SerialPort.new(@port, 9600, 8, 1, SerialPort::NONE)
182
- sp.read_timeout = 100
183
- message = [0x02, 0x03, 5 + msg.length]
184
- message += msg
185
- crc = crc_for(message)
186
- message += crc
187
- message = message.pack("C*")
188
- sp.write message
189
- ans = sp.gets
190
- if ans
191
- parse_answer ? res = ans.unpack("C*").map{|e| e.to_s(16) } : res = ans
192
- else
193
- res = nil
194
- end
195
- sp.close
196
- res
197
- end
198
- end
199
-
200
- end
201
- end
202
- end
@@ -1,52 +0,0 @@
1
- # coding: utf-8
2
- module Smartware
3
- module Driver
4
- module CashAcceptor
5
-
6
- class Dummy
7
-
8
- def initialize(port)
9
- @port = port
10
- end
11
-
12
- def model
13
- "Dummy cash acceptor v1.0"
14
- end
15
-
16
- def cassette?
17
- true
18
- end
19
-
20
- def error
21
- false
22
- end
23
-
24
- def current_banknote
25
- return false if ( rand(9) < 6 )
26
- [20, 40, 60, 80].sample
27
- end
28
-
29
- def accept
30
-
31
- end
32
-
33
- def cancel_accept
34
-
35
- end
36
-
37
- def stack
38
-
39
- end
40
-
41
- def return
42
-
43
- end
44
-
45
- def reset
46
-
47
- end
48
- end
49
-
50
- end
51
- end
52
- end
@@ -1,39 +0,0 @@
1
- # coding: utf-8
2
- module Smartware
3
- module Driver
4
- module Modem
5
-
6
- class Dummy
7
-
8
- def initialize(port)
9
- @port = port
10
- end
11
-
12
- def model
13
- 'Dummy modem v1.0'
14
- end
15
-
16
- def error
17
- false
18
- end
19
-
20
- def signal_level
21
- "-#{rand(90)*10+rand(9)} dbm"
22
- end
23
-
24
- #
25
- # Method send ussd to operator and return only valid answer body
26
- # Don`t call with method synchronously from app, method waits USSD answer 3 sec,
27
- # Use some scheduler and buffer for balance value
28
- #
29
- def ussd(code="*100#")
30
- sleep 3
31
- "#{rand(90)*100+rand(9)} " + %w(руб. dollars тэньге).sample
32
- end
33
-
34
- end
35
-
36
- end
37
- end
38
- end
39
-
@@ -1,84 +0,0 @@
1
- # coding: utf-8
2
- require 'serialport'
3
-
4
- module Smartware
5
- module Driver
6
- module Modem
7
-
8
- class Standard
9
-
10
- ERRORS = {
11
- "-1" => -1, # invalid device answer
12
- "10" => 10, # invalid ussd answer
13
- "11" => 11, # invalid ussd answer size
14
- "12" => 12, # invalid ussd body answer size
15
- "20" => 20, # invalid modem model
16
- "21" => 21, # invalid modem signal level
17
- }
18
-
19
- def initialize(port)
20
- @sp = SerialPort.new(port, 115200, 8, 1, SerialPort::NONE)
21
- end
22
-
23
- def error
24
- @error ||= false
25
- end
26
-
27
- def model
28
- res = send 'ATI'
29
- res.shift
30
- res.pop
31
- res.join(' ')
32
- rescue
33
- @error = ERRORS["20"]
34
- end
35
-
36
- #
37
- # Returns signal level in dbm
38
- #
39
- def signal_level
40
- res = send 'AT+CSQ'
41
- value = res[1].gsub("+CSQ: ",'').split(',')[0].to_i
42
- "#{(-113 + value * 2)} dbm"
43
- rescue
44
- @error = ERRORS["21"]
45
- end
46
-
47
- #
48
- # Method send ussd to operator and return only valid answer body
49
- # Returns modem balance by default, it works for MTS and Megafon, use *102# for Beeline
50
- # Do not call with method synchronously from app, method waits USSD answer some time,
51
- # Use some scheduler and buffer for balance value
52
- #
53
- # Valid ussd answer sample: ["", "+CUSD: 2,\"003100310035002C003000300440002E00320031002E00330031002004310430043B002E0020\",72", "OK"]
54
- #
55
- def ussd(code="*100#")
56
- res = self.send "AT+CUSD=1,\"#{code}\",15"
57
- unless res[1][0..4] == "+CUSD"
58
- @error = ERRORS["11"]
59
- return false
60
- end
61
-
62
- ussd_body = res[1].split(",")[1].gsub('"','') # Parse USSD message body
63
- ussd_body.scan(/\w{4}/).map{|i| [i.hex].pack("U") }.join.strip # Encode USSD message from broken ucs2 to utf-8
64
- rescue
65
- @error = ERRORS["10"]
66
- return false
67
- end
68
-
69
- def send(cmd, read_timeout = 0.25)
70
- @sp.write "#{ cmd }\r\n"
71
- answer = ''
72
- while IO.select [@sp], [], [], read_timeout
73
- chr = @sp.getc.chr
74
- answer << chr
75
- end
76
- res = answer.split(/[\r\n]+/)
77
- return ERRORS["-1"] unless res.last == "OK"
78
- res
79
- end
80
- end
81
-
82
- end
83
- end
84
- end
@@ -1,25 +0,0 @@
1
- # coding: utf-8
2
- module Smartware
3
- module Driver
4
- module Printer
5
-
6
- class Dummy
7
-
8
- def initialize(port)
9
-
10
- end
11
-
12
- def error
13
- false
14
- end
15
-
16
- def model
17
- 'Dummy printer'
18
- end
19
-
20
- end
21
-
22
- end
23
- end
24
- end
25
-
@@ -1,61 +0,0 @@
1
- # coding: utf-8
2
- #
3
- # Custom tg2480h printer functions
4
- #
5
-
6
- require 'serialport'
7
-
8
- module Smartware
9
- module Driver
10
- module Printer
11
-
12
- class TG24XX
13
-
14
- def initialize(port)
15
- @sp = SerialPort.new(port, 115200, 8, 1, SerialPort::NONE)
16
- @sp.read_timeout = 100
17
- end
18
-
19
- def error
20
- res = send "\x1Dr1"
21
- return "1" unless res # No answer
22
- return "" if res == "0" # No error
23
- return "2" if res == "f" # Paper not present
24
- return "3" if res == "3" # Paper near end
25
- rescue
26
- -1
27
- end
28
-
29
- def model
30
- model_code = send "\x1DI1"
31
- rom_version = send "\x1DI3", false
32
- model_name = case model_code
33
- when "a7" then 'Custom TG2460H'
34
- when "a8" then 'Custom TG2480H'
35
- when "ac" then 'Custom TL80'
36
- when "ad" then 'Custom TL60'
37
- else 'Unknown printer'
38
- end
39
- "#{model_name}, ROM v#{rom_version}"
40
- rescue
41
- -1
42
- end
43
-
44
- private
45
- def send(message, parse_answer = true)
46
- @sp.write message
47
- ans = @sp.gets
48
- if ans
49
- parse_answer ? res = ans.unpack("C*").map{|e| e.to_s(16) } : res = ans
50
- else
51
- res = nil
52
- end
53
- res.is_a?(Array) ? res[0] : res
54
- end
55
-
56
- end
57
-
58
- end
59
- end
60
- end
61
-
@@ -1,135 +0,0 @@
1
- require 'drb'
2
- require 'smartware/drivers/cash_acceptor/ccnet'
3
- require 'smartware/drivers/cash_acceptor/dummy'
4
-
5
- module Smartware
6
- module Interface
7
-
8
- module CashAcceptor
9
-
10
- #
11
- # Init vars
12
- #
13
- @configured = false
14
- @no_limit = true
15
- @banknotes = {}
16
- @commands = %w(monitor)
17
- @status = { :cassette => true }
18
-
19
- #
20
- # (re)configure device
21
- #
22
- def self.configure!(port=nil, driver=nil)
23
- @device = Smartware::Driver::CashAcceptor.const_get(
24
- Smartware::Service.config['cash_acceptor_driver']).new(
25
- Smartware::Service.config['cash_acceptor_port'])
26
- @session.kill if @session and @session.alive?
27
- @commands = %w(monitor)
28
- @device.cancel_accept
29
- @session = self.start_poll!
30
- Smartware::Logging.logger.info "Cash acceptor monitor started"
31
- @configured = true
32
- rescue => e
33
- @configured = false
34
- Smartware::Logging.logger.error e.message
35
- Smartware::Logging.logger.error e.backtrace.join("\n")
36
- end
37
-
38
- def self.open_session(limit_min, limit_max)
39
- @commands << 'open'
40
- @banknotes = {}
41
- if !limit_min.nil? && !limit_max.nil?
42
- @no_limit = false
43
- @limit_min = limit_min
44
- @limit_max = limit_max
45
- else
46
- @no_limit = true
47
- end
48
- end
49
-
50
- def self.close_session
51
- @commands << 'close'
52
- @limit_min = nil
53
- @limit_max = nil
54
- @no_limit = true
55
- end
56
-
57
- def self.configured?
58
- @configured
59
- end
60
-
61
- def self.status
62
- @status
63
- end
64
-
65
- def self.model
66
- @status[:model]
67
- end
68
-
69
- def self.cashsum
70
- @banknotes.inject(0){ |result, (key, value)| result + key.to_i*value.to_i }
71
- end
72
-
73
- def self.banknotes
74
- @banknotes
75
- end
76
-
77
- #
78
- # Session private method
79
- #
80
- private
81
- def self.start_poll!
82
- t = Thread.new do
83
- loop do
84
- case @commands[0]
85
- when 'open'
86
- @device.reset
87
- @device.accept
88
- Smartware::Logging.logger.info "Cash acceptor open: #{@commands}"
89
-
90
- @commands.shift
91
- @commands << 'get_money'
92
- when 'get_money'
93
- res = @device.current_banknote
94
- if res.is_a? Integer # Have a banknote
95
- if @no_limit or (@limit_min..@limit_max).include?(self.cashsum + res)
96
- @device.stack
97
- @banknotes[res] = (@banknotes[res]||0) + 1
98
- Smartware::Logging.logger.info "Cash acceptor bill stacked, #{res}"
99
- else
100
- @device.return
101
- Smartware::Logging.logger.info "Cash acceptor limit violation, return #{res}"
102
- end
103
- elsif res.is_a? String # Have a error, errors always as String
104
- Smartware::Logging.logger.error "Cash acceptor error #{res}"
105
- @status[:error] = res
106
- end
107
- @device.cancel_accept if !@no_limit && (@limit_max == self.cashsum and @limit_max > 0) # Close cash acceptor if current cashsum equal max-limit
108
-
109
- @commands.shift
110
- @commands << 'get_money' if @commands.empty?
111
- when 'close'
112
- @device.cancel_accept
113
- Smartware::Logging.logger.info "Cash acceptor close: #{@commands}"
114
-
115
- @commands.shift
116
- when 'monitor'
117
- @status[:error] = @device.error || ''
118
- @status[:model] = @device.model
119
- @status[:cassette] = @device.cassette?
120
- @commands.shift
121
- else
122
- @commands << 'monitor'
123
- end
124
- sleep 0.5
125
- end
126
- end
127
- end
128
-
129
- self.configure!
130
- end
131
- end
132
- end
133
-
134
- DRb.start_service('druby://localhost:6001', Smartware::Interface::CashAcceptor)
135
- DRb.thread.join
@@ -1,68 +0,0 @@
1
- require 'drb'
2
- require 'smartware/drivers/modem/standard'
3
- require 'smartware/drivers/modem/dummy'
4
-
5
- module Smartware
6
- module Interface
7
-
8
- module Modem
9
-
10
- @configured = false
11
- @status = {}
12
-
13
- def self.configure!(port=nil, driver=nil)
14
- @device = Smartware::Driver::Modem.const_get(
15
- Smartware::Service.config['modem_driver']).new(
16
- Smartware::Service.config['modem_port'])
17
- @session.kill if @session
18
- @session = self.poll_status!
19
- @configured = true
20
- Smartware::Logging.logger.info 'Modem monitor started'
21
- @status = {}
22
- rescue => e
23
- Smartware::Logging.logger.error e.message
24
- Smartware::Logging.logger.error e.backtrace.join("\n")
25
- @configured = false
26
- end
27
-
28
- def self.configured?
29
- @configured
30
- end
31
-
32
- def self.error
33
- @status[:error] || ''
34
- end
35
-
36
- def self.model
37
- @status[:model]
38
- end
39
-
40
- def self.balance
41
- @status[:balance]
42
- end
43
-
44
- def self.signal_level
45
- @status[:signal_level]
46
- end
47
-
48
- private
49
- def self.poll_status!
50
- t = Thread.new do
51
- loop do
52
- @status[:signal_level] = @device.signal_level
53
- @status[:model] = @device.model
54
- @status[:error] = @device.error
55
- @status[:balance] = balance if balance = @device.ussd("*100#")
56
- sleep 30
57
- end
58
- end
59
- end
60
-
61
- self.configure!
62
- end
63
- end
64
- end
65
-
66
- DRb.start_service('druby://localhost:6002', Smartware::Interface::Modem)
67
- DRb.thread.join
68
-
@@ -1,76 +0,0 @@
1
- require 'drb'
2
- require 'smartware/drivers/printer/dummy'
3
- require 'smartware/drivers/printer/tg24xx'
4
-
5
- module Smartware
6
- module Interface
7
-
8
- module Printer
9
-
10
- @configured = false
11
- @status = {:error => ''}
12
- @queue = []
13
-
14
- def self.configure!(port=nil, driver=nil)
15
- @device = Smartware::Driver::Printer.const_get(
16
- Smartware::Service.config['printer_driver']).new(
17
- Smartware::Service.config['printer_port'])
18
- @session.kill if @session and @session.alive?
19
- @session = self.start_monitor!
20
- Smartware::Logging.logger.info 'Printer monitor started'
21
- @configured = true
22
- rescue => e
23
- @configured = false
24
- end
25
-
26
- def self.configured?
27
- @configured
28
- end
29
-
30
- def self.error
31
- @status[:error]
32
- end
33
-
34
- def self.model
35
- @status[:model]
36
- end
37
-
38
- def self.print(filepath)
39
- @queue << filepath unless filepath.nil?
40
- end
41
-
42
- def self.test
43
- @queue << '/usr/share/cups/data/testprint'
44
- end
45
-
46
- private
47
- def self.start_monitor!
48
- t = Thread.new do
49
- loop do
50
- if @queue.empty?
51
- @status[:error] = @device.error || ''
52
- @status[:model] = @device.model
53
- else
54
- begin
55
- `lpr #{@queue[0]}`
56
- Smartware::Logging.logger.info "Printed #{@queue[0]}"
57
- @queue.shift
58
- sleep 5
59
- rescue => e
60
- Smartware::Logging.logger.error e.message
61
- Smartware::Logging.logger.error e.backtrace.join("\n")
62
- end
63
- end
64
- sleep 0.2
65
- end
66
- end
67
- end
68
-
69
- self.configure!
70
- end
71
- end
72
- end
73
-
74
- DRb.start_service('druby://localhost:6005', Smartware::Interface::Printer)
75
- DRb.thread.join
76
-
@@ -1,31 +0,0 @@
1
- require 'logger'
2
-
3
- module Smartware
4
- module Logging
5
-
6
- def self.logdir=(dir)
7
- @logdir = dir
8
- end
9
-
10
- def self.logger
11
- @logger ||= begin
12
- log = Logger.new(STDOUT)
13
- log.level = Logger::INFO
14
- log
15
- end
16
- end
17
-
18
- def self.logger=(val)
19
- @logger = (val ? val : Logger.new('/dev/null'))
20
- end
21
-
22
- def self.logfile=(val)
23
- @logfile = val
24
- end
25
-
26
- def self.logfile
27
- @logfile
28
- end
29
-
30
- end
31
- end
@@ -1,38 +0,0 @@
1
- require 'thread'
2
- require 'yaml'
3
- require 'smartware/logging'
4
-
5
- module Smartware
6
- module Service
7
-
8
- def self.config
9
- @config
10
- end
11
-
12
- def self.start(config_file)
13
- $stdout.sync = true
14
-
15
- @config = YAML.load File.read(File.expand_path(config_file))
16
-
17
- Smartware::Logging.logger = Logger.new($stdout)
18
- Smartware::Logging.logger.info "Smartware started at #{Time.now}"
19
-
20
- @threads = %w(smartware/interfaces/cash_acceptor
21
- smartware/interfaces/printer
22
- smartware/interfaces/modem).inject([]){|arr, iface| arr << Thread.new{ require iface } }
23
-
24
- @threads.map(&:join)
25
- rescue => e
26
- Smartware::Logging.logger.fatal e.message
27
- Smartware::Logging.logger.fatal e.backtrace.join("\n")
28
- end
29
-
30
- def self.stop
31
- @threads.map(&:kill)
32
- Smartware::Logging.logger.info "Smartware shutdown at #{Time.now}"
33
- exit 0
34
- end
35
-
36
- end
37
- end
38
-
@@ -1,3 +0,0 @@
1
- module Smartware
2
- VERSION = "0.1.16"
3
- end
data/lib/smartware.rb DELETED
@@ -1,25 +0,0 @@
1
- require 'smartware/clients/cash_acceptor'
2
- require 'smartware/clients/printer'
3
- require 'smartware/clients/modem'
4
-
5
- module Smartware
6
-
7
- def self.devices
8
- yield self
9
- end
10
-
11
- def self.cash_acceptor
12
- Smartware::Client::CashAcceptor
13
- end
14
-
15
- def self.printer
16
- Smartware::Client::Printer
17
- end
18
-
19
- def self.modem
20
- Smartware::Client::Modem
21
- end
22
-
23
- end
24
-
25
-
data/smartware.gemspec DELETED
@@ -1,23 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'smartware/version'
5
-
6
- Gem::Specification.new do |gem|
7
- gem.name = "smartware"
8
- gem.version = Smartware::VERSION
9
- gem.authors = ["Evgeni Sudarchikov", "Boris Staal"]
10
- gem.email = ["e.sudarchikov@roundlake.ru", "boris@roundlake.ru"]
11
- gem.description = %q{Smartware is the Smartkiosk hardware control daemon}
12
- gem.summary = gem.description
13
- gem.homepage = "https://github.com/roundlake/smartware"
14
-
15
- gem.files = `git ls-files`.split($/)
16
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
- gem.require_paths = ["lib"]
19
-
20
- gem.add_dependency 'serialport'
21
- gem.add_dependency 'dante'
22
-
23
- end