smartware 0.1.30 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,29 @@
1
+ module Smartware
2
+ module Driver
3
+ module Watchdog
4
+
5
+ class Dummy
6
+
7
+ def initialize(config)
8
+
9
+ end
10
+
11
+ def model
12
+ "Dummy watchdog"
13
+ end
14
+
15
+ def version
16
+ ""
17
+ end
18
+
19
+ def reboot_modem
20
+
21
+ end
22
+
23
+ def error
24
+ nil
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,40 @@
1
+ module Smartware
2
+ module Driver
3
+ module Watchdog
4
+
5
+ class WatchdogDaemon
6
+
7
+ attr_reader :error
8
+
9
+ def initialize(config)
10
+ @error = nil
11
+ @config = config
12
+ end
13
+
14
+ def model
15
+ "watchdogd-controlled watchdog"
16
+ end
17
+
18
+ def version
19
+ ""
20
+ end
21
+
22
+ def reboot_modem
23
+ begin
24
+ File.open(@config["pidfile"], "r") do |io|
25
+ pid = io.read.to_i
26
+
27
+ Process.kill :USR1, pid
28
+ end
29
+
30
+ @error = nil
31
+ rescue => e
32
+ Smartware::Logging.logger.warn "Watchdog communication error: #{e}"
33
+
34
+ @error = Interface::Watchdog::WATCHDOG_NOT_AVAILABLE
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,142 +1,187 @@
1
- require 'drb'
2
-
3
1
  module Smartware
4
2
  module Interface
3
+ class CashAcceptor < Interface
4
+
5
+ DROP_CASETTE_FULL = 1
6
+ DROP_CASETTE_OUT_OF_POSITION = 2
7
+ VALIDATOR_JAMMED = 3
8
+ DROP_CASETTE_JAMMED = 4
9
+ CHEATED = 5
10
+ PAUSE = 6
11
+ BILL_VALIDATOR_FAILURE = 7
12
+ STACK_MOTOR_FAILURE = 8
13
+ TRANSPORT_MOTOR_SPEED_FAILURE = 9
14
+ TRANSPORT_MOTOR_FAILURE = 10
15
+ ALIGNING_MOTOR_FAILURE = 11
16
+ INITIAL_CASETTE_STATUS_FAILURE = 12
17
+ OPTIC_CANAL_FAILURE = 13
18
+ MAGNETIC_CANAL_FAILURE = 14
19
+ CAPACITANCE_CANAL_FAILURE = 15
20
+ COMMUNICATION_ERROR = 16
21
+
22
+ def initialize(config)
23
+ super
24
+
25
+ @limit = nil
26
+ @banknotes = {}
27
+ @banknotes.default = 0
5
28
 
6
- module CashAcceptor
7
-
8
- #
9
- # Init vars
10
- #
11
- @configured = false
12
- @no_limit = true
13
- @banknotes = {}
14
- @commands = %w(monitor)
15
- @status = { :cassette => true }
16
-
17
- #
18
- # (re)configure device
19
- #
20
- def self.configure!(port=nil, driver=nil)
21
- @device = Smartware::Driver::CashAcceptor.const_get(
22
- Smartware::Service.config['cash_acceptor_driver']).new(
23
- Smartware::Service.config['cash_acceptor_port'])
24
- @session.kill if @session and @session.alive?
25
- @commands = %w(monitor)
26
- @device.cancel_accept
27
- @session = self.start_poll!
29
+ update_status do
30
+ @status[:casette] = true
31
+ end
32
+
33
+ @accepting = false
34
+ @commands = Queue.new
35
+ @commands.push :close
36
+
37
+ Thread.new &method(:dispatch_commands)
38
+ Thread.new &method(:periodic)
28
39
  Smartware::Logging.logger.info "Cash acceptor monitor started"
29
- @configured = true
30
- rescue => e
31
- @configured = false
32
- Smartware::Logging.logger.error e.message
33
- Smartware::Logging.logger.error e.backtrace.join("\n")
34
40
  end
35
41
 
36
- def self.open_session(limit_min, limit_max)
37
- @commands << 'open'
38
- @banknotes = {}
39
- if !limit_min.nil? && !limit_max.nil?
40
- @no_limit = false
41
- @limit_min = limit_min
42
- @limit_max = limit_max
42
+ def open_session(limit_min, limit_max)
43
+ @banknotes.clear
44
+
45
+ if limit_min.nil? || limit_max.nil?
46
+ @limit = nil
47
+
48
+ Smartware::Logging.logger.info "Session open, unlimited"
43
49
  else
44
- @no_limit = true
50
+ @limit = limit_min..limit_max
51
+
52
+ Smartware::Logging.logger.info "Session open, limit: #{@limit}"
45
53
  end
54
+
55
+ @commands.push :open
56
+ @commands.push :get_money
46
57
  end
47
58
 
48
- def self.close_session
49
- @commands << 'close'
50
- @limit_min = nil
51
- @limit_max = nil
52
- @no_limit = true
59
+ def close_session
60
+ Smartware::Logging.logger.info "Session closed"
61
+
62
+ @commands.push :close
63
+ @limit = nil
53
64
  end
54
65
 
55
- def self.configured?
56
- @configured
66
+ def banknotes
67
+ update_status { @banknotes }
57
68
  end
58
69
 
59
- def self.error
60
- @status[:error] || ''
70
+ def cashsum
71
+ self.banknotes.inject(0) do |result, (key, value)|
72
+ result + key.to_i * value.to_i
73
+ end
61
74
  end
62
75
 
63
- def self.status
64
- @status
76
+ private
77
+
78
+ def limit_satisfied(sum)
79
+ @limit.nil? or @limit.include? sum
65
80
  end
66
81
 
67
- def self.model
68
- @status[:model]
82
+ def execute_open
83
+ @device.reset
84
+ @device.accept
85
+ Smartware::Logging.logger.info "Cash acceptor open"
86
+
87
+ @accepting = true
69
88
  end
70
89
 
71
- def self.version
72
- @status[:version]
90
+ def execute_get_money
91
+ res = @device.current_banknote
92
+
93
+ case res
94
+ when Integer
95
+ if limit_satisfied(self.cashsum + res)
96
+ @device.stack
97
+ update_status do
98
+ @banknotes[res] += 1
99
+ end
100
+ Smartware::Logging.logger.info "Cash acceptor bill stacked, #{res}"
101
+ else
102
+ @device.return
103
+ Smartware::Logging.logger.info "Cash acceptor limit violation, return #{res}"
104
+ end
105
+
106
+ when String
107
+ Smartware::Logging.logger.error "Cash acceptor error #{res}"
108
+
109
+ update_status do
110
+ @status[:error] = res
111
+ end
112
+ end
113
+
114
+ if !@limit.nil? && @limit.end > 0 && @limit.end == self.cashsum
115
+ # Close cash acceptor if current cashsum equal max-limit
116
+
117
+ execute_close
118
+ end
73
119
  end
74
120
 
75
- def self.cashsum
76
- @banknotes.inject(0){ |result, (key, value)| result + key.to_i*value.to_i }
121
+ def execute_close
122
+ @device.cancel_accept
123
+ Smartware::Logging.logger.info "Cash acceptor close"
124
+
125
+ @accepting = false
77
126
  end
78
127
 
79
- def self.banknotes
80
- @banknotes
128
+ def execute_monitor
129
+
130
+ error = @device.error || ''
131
+ model = @device.model
132
+ version = @device.version
133
+ cassette = @device.cassette?
134
+
135
+ update_status do
136
+ @status[:error] = error
137
+ @status[:model] = model
138
+ @status[:version] = version
139
+ @status[:cassette] = cassette
140
+ end
81
141
  end
82
142
 
83
- #
84
- # Session private method
85
- #
86
- private
87
- def self.start_poll!
88
- t = Thread.new do
89
- loop do
90
- case @commands[0]
91
- when 'open'
92
- @device.reset
93
- @device.accept
94
- Smartware::Logging.logger.info "Cash acceptor open: #{@commands}"
95
-
96
- @commands.shift
97
- @commands << 'get_money'
98
- when 'get_money'
99
- res = @device.current_banknote
100
- if res.is_a? Integer # Have a banknote
101
- if @no_limit or (@limit_min..@limit_max).include?(self.cashsum + res)
102
- @device.stack
103
- @banknotes[res] = (@banknotes[res]||0) + 1
104
- Smartware::Logging.logger.info "Cash acceptor bill stacked, #{res}"
105
- else
106
- @device.return
107
- Smartware::Logging.logger.info "Cash acceptor limit violation, return #{res}"
108
- end
109
- elsif res.is_a? String # Have a error, errors always as String
110
- Smartware::Logging.logger.error "Cash acceptor error #{res}"
111
- @status[:error] = res
112
- end
113
- @device.cancel_accept if !@no_limit && (@limit_max == self.cashsum and @limit_max > 0) # Close cash acceptor if current cashsum equal max-limit
114
-
115
- @commands.shift
116
- @commands << 'get_money' if @commands.empty?
117
- when 'close'
118
- @device.cancel_accept
119
- Smartware::Logging.logger.info "Cash acceptor close: #{@commands}"
120
-
121
- @commands.shift
122
- when 'monitor'
123
- @status[:error] = @device.error || ''
124
- @status[:model] = @device.model
125
- @status[:version] = @device.version
126
- @status[:cassette] = @device.cassette?
127
- @commands.shift
128
- else
129
- @commands << 'monitor'
130
- end
131
- sleep 0.5
143
+ def dispatch_commands
144
+ loop do
145
+ command = @commands.pop
146
+
147
+ begin
148
+ start = Time.now
149
+
150
+ send :"execute_#{command}"
151
+
152
+ complete = Time.now
153
+ if complete - start > 1
154
+ Smartware::Logging.logger.warn "#{command} has been running for #{complete - start} seconds."
155
+ end
156
+
157
+ rescue => e
158
+ Smartware::Logging.logger.error "Execution of #{command} failed:"
159
+ Smartware::Logging.logger.error e.to_s
160
+ e.backtrace.each do |line|
161
+ Smartware::Logging.logger.error line
132
162
  end
133
163
  end
134
164
  end
165
+ end
166
+
167
+ def periodic
168
+ loop do
169
+ begin
170
+ if @commands.empty?
171
+ @commands.push :monitor
172
+ @commands.push :get_money if @accepting
173
+ end
135
174
 
136
- self.configure!
175
+ sleep 0.5
176
+ rescue => e
177
+ Smartware::Logging.logger.error "Error in periodic failed:"
178
+ Smartware::Logging.logger.error e.to_s
179
+ e.backtrace.each do |line|
180
+ Smartware::Logging.logger.error line
181
+ end
182
+ end
183
+ end
184
+ end
137
185
  end
138
186
  end
139
187
  end
140
-
141
- DRb.start_service('druby://localhost:6001', Smartware::Interface::CashAcceptor)
142
- DRb.thread.join
@@ -0,0 +1,47 @@
1
+ module Smartware
2
+ module Interface
3
+ class Interface
4
+ attr_reader :config
5
+
6
+ def initialize(config)
7
+ @config = config
8
+ @status_mutex = Mutex.new
9
+ @status = {
10
+ model: '',
11
+ version: ''
12
+ }
13
+
14
+ iface = @config["name"]
15
+ driver = @config["driver"]
16
+
17
+ require "smartware/drivers/#{iface.underscore}/#{driver.underscore}"
18
+
19
+ @device = Smartware::Driver.const_get(iface.to_s)
20
+ .const_get(driver.to_s)
21
+ .new(config)
22
+ end
23
+
24
+ def error
25
+ self.status[:error]
26
+ end
27
+
28
+ def model
29
+ self.status[:model]
30
+ end
31
+
32
+ def version
33
+ self.status[:version]
34
+ end
35
+
36
+ def status
37
+ @status_mutex.synchronize { @status }
38
+ end
39
+
40
+ protected
41
+
42
+ def update_status(&block)
43
+ @status_mutex.synchronize &block
44
+ end
45
+ end
46
+ end
47
+ end
@@ -1,78 +1,49 @@
1
- require 'drb'
2
-
3
1
  module Smartware
4
2
  module Interface
3
+ class Modem < Interface
4
+ MODEM_NOT_AVAILABLE = 1
5
5
 
6
- module Modem
7
- @configured = false
8
- @status = {}
9
-
10
- def self.configure!
11
- Smartware::Logging.logger.debug "Creating modem"
12
- @device = Smartware::Driver::Modem.const_get(
13
- Smartware::Service.config['modem_driver']).new(
14
- Smartware::Service.config['modem_config'])
15
- Smartware::Logging.logger.debug "Starting modem"
16
- @session.kill if @session
17
- @session = self.poll_status!
18
- @configured = true
19
- Smartware::Logging.logger.info 'Modem monitor started'
20
- @status = {}
21
- rescue => e
22
- Smartware::Logging.logger.error e.message
23
- Smartware::Logging.logger.error e.backtrace.join("\n")
24
- @configured = false
25
- end
26
-
27
- def self.configured?
28
- @configured
29
- end
30
-
31
- def self.error
32
- @status[:error]
33
- end
6
+ def initialize(config)
7
+ super
34
8
 
35
- def self.model
36
- @status[:model]
37
- end
9
+ update_status do
10
+ @status[:balance] = ''
11
+ @status[:signal_level] = ''
12
+ end
38
13
 
39
- def self.version
40
- @status[:version]
14
+ @session = Thread.new &method(:poll)
15
+ Smartware::Logging.logger.info 'Modem monitor started'
41
16
  end
42
17
 
43
- def self.balance
44
- @status[:balance]
18
+ def balance
19
+ self.status[:balance]
45
20
  end
46
21
 
47
- def self.signal_level
48
- @status[:signal_level]
22
+ def signal_level
23
+ self.status[:signal_level]
49
24
  end
50
25
 
51
26
  private
52
- def self.poll_status!
53
- t = Thread.new do
54
- begin
55
- loop do
56
- @device.tick
57
27
 
58
- @status[:signal_level] = @device.signal_level
59
- @status[:model] = @device.model
60
- @status[:version] = @device.version
61
- @status[:error] = @device.error || ''
62
- @status[:balance] = @device.balance
63
- end
64
- rescue => e
65
- Smartware::Logging.logger.error e.message
66
- Smartware::Logging.logger.error e.backtrace.join("\n")
28
+ def poll
29
+ begin
30
+ loop do
31
+ @device.tick
32
+
33
+ update_status do
34
+ @status[:signal_level] = @device.signal_level
35
+ @status[:model] = @device.model
36
+ @status[:version] = @device.version
37
+ @status[:error] = @device.error || ''
38
+ @status[:balance] = @device.balance
67
39
  end
68
40
  end
41
+ rescue => e
42
+ Smartware::Logging.logger.error e.message
43
+ Smartware::Logging.logger.error e.backtrace.join("\n")
69
44
  end
70
-
71
- self.configure!
45
+ end
72
46
  end
73
47
  end
74
48
  end
75
49
 
76
- DRb.start_service('druby://localhost:6002', Smartware::Interface::Modem)
77
- DRb.thread.join
78
-