Class: Tamashii::Agent::Connection
- Inherits:
-
Component
show all
- Includes:
- AASM
- Defined in:
- lib/tamashii/agent/connection.rb,
lib/tamashii/agent/connection/request_observer.rb
Defined Under Namespace
Classes: RequestObserver, RequestTimeoutError
Instance Attribute Summary collapse
Instance Method Summary
collapse
-
#create_request_async(id, ev_type, ev_body) ⇒ Object
-
#create_request_scheduler_task(id, ev_type, ev_body) ⇒ Object
-
#handle_card_result(result) ⇒ Object
-
#handle_remote_response(ev_type, wrapped_ev_body) ⇒ Object
-
#initialize(master) ⇒ Connection
constructor
A new instance of Connection.
-
#new_remote_request(id, ev_type, ev_body) ⇒ Object
-
#on_request_timeout(ev_type, ev_body) ⇒ Object
-
#process_event(event) ⇒ Object
-
#process_packet(pkt) ⇒ Object
-
#schedule_next_task(interval, id, ev_type, ev_body, start_time, times) ⇒ Object
-
#schedule_task_runner(id, ev_type, ev_body, start_time, times) ⇒ Object
-
#send_auth_request ⇒ Object
-
#setup_callbacks ⇒ Object
-
#setup_resolver ⇒ Object
-
#stop_threads ⇒ Object
-
#try_send_request(ev_type, ev_body) ⇒ Object
Methods inherited from Component
#check_new_event, #clean_up, #handle_new_event, #restart_current_component_async, #run, #run!, #run_worker_loop, #send_event, #stop, #worker_loop
#logger, #progname
Constructor Details
#initialize(master) ⇒ Connection
Returns a new instance of Connection.
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
# File 'lib/tamashii/agent/connection.rb', line 46
def initialize(master)
super
self.reset
@client = Tamashii::Client::Base.new
@tag = 0
@future_ivar_pool = Concurrent::Map.new
@last_error_report_time = Time.now
setup_callbacks
setup_resolver
end
|
Instance Attribute Details
#master ⇒ Object
Returns the value of attribute master.
44
45
46
|
# File 'lib/tamashii/agent/connection.rb', line 44
def master
@master
end
|
#url ⇒ Object
Returns the value of attribute url.
43
44
45
|
# File 'lib/tamashii/agent/connection.rb', line 43
def url
@url
end
|
Instance Method Details
#create_request_async(id, ev_type, ev_body) ⇒ Object
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
|
# File 'lib/tamashii/agent/connection.rb', line 204
def create_request_async(id, ev_type, ev_body)
req = Concurrent::Future.new do
ivar = Concurrent::IVar.new
@future_ivar_pool[id] = ivar
create_request_scheduler_task(id, ev_type, ev_body)
if result = ivar.value(Config.connection_timeout)
result
else
logger.error "Timeout when getting IVar for #{id}"
@future_ivar_pool.delete(id)
raise RequestTimeoutError, "Request Timeout"
end
end
req.add_observer(RequestObserver.new(self, id, ev_type, ev_body, req))
req.execute
req
end
|
#create_request_scheduler_task(id, ev_type, ev_body) ⇒ Object
200
201
202
|
# File 'lib/tamashii/agent/connection.rb', line 200
def create_request_scheduler_task(id, ev_type, ev_body)
schedule_next_task(0, id, ev_type, ev_body, Time.now, 0)
end
|
#handle_card_result(result) ⇒ Object
79
80
81
82
83
84
85
86
87
88
|
# File 'lib/tamashii/agent/connection.rb', line 79
def handle_card_result(result)
if result["auth"]
@master.send_event(Event.new(Event::BEEP, "ok"))
else
@master.send_event(Event.new(Event::BEEP, "no"))
end
if result["message"]
@master.send_event(Event.new(Event::LCD_MESSAGE, result["message"]))
end
end
|
#handle_remote_response(ev_type, wrapped_ev_body) ⇒ Object
239
240
241
242
243
244
245
246
247
248
249
250
|
# File 'lib/tamashii/agent/connection.rb', line 239
def handle_remote_response(ev_type, wrapped_ev_body)
logger.debug "Remote packet back: #{ev_type} #{wrapped_ev_body}"
result = JSON.parse(wrapped_ev_body)
id = result["id"]
ev_body = result["ev_body"]
if ivar = @future_ivar_pool.delete(id)
ivar.set(ev_type: ev_type, ev_body: ev_body)
else
logger.warn "IVar #{id} not in pool"
end
end
|
#new_remote_request(id, ev_type, ev_body) ⇒ Object
228
229
230
231
232
233
234
235
236
|
# File 'lib/tamashii/agent/connection.rb', line 228
def new_remote_request(id, ev_type, ev_body)
if !@future_ivar_pool[id]
create_request_async(id, ev_type, ev_body)
logger.debug "Request created: #{id}"
else
logger.warn "Duplicated id: #{id}, ignored"
end
end
|
#on_request_timeout(ev_type, ev_body) ⇒ Object
75
76
77
|
# File 'lib/tamashii/agent/connection.rb', line 75
def on_request_timeout(ev_type, ev_body)
@master.send_event(Event.new(Event::CONNECTION_NOT_READY, "Connection not ready for #{ev_type}:#{ev_body}"))
end
|
#process_event(event) ⇒ Object
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
|
# File 'lib/tamashii/agent/connection.rb', line 163
def process_event(event)
case event.type
when Event::CARD_DATA
if self.ready?
id = event.body
wrapped_body = {
id: id,
ev_body: event.body
}.to_json
new_remote_request(id, Type::RFID_NUMBER, wrapped_body)
else
@master.send_event(Event.new(Event::CONNECTION_NOT_READY, "Connection not ready for #{event.type}:#{event.body}"))
end
end
end
|
#process_packet(pkt) ⇒ Object
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
# File 'lib/tamashii/agent/connection.rb', line 139
def process_packet(pkt)
if self.auth_pending?
if pkt.type == Type::AUTH_RESPONSE
if pkt.body == Packet::STRING_TRUE
@tag = pkt.tag
self.auth_success
else
logger.error "Authentication failed. Delay for 3 seconds"
@master.send_event(Event.new(Event::LCD_MESSAGE, "Fatal Error\nAuth Failed"))
sleep 3
end
else
logger.error "Authentication error: Not an authentication result packet"
end
else
if pkt.tag == @tag || pkt.tag == 0
Resolver.resolve(pkt)
else
logger.debug "Tag mismatch packet: tag: #{pkt.tag}, type: #{pkt.type}"
end
end
end
|
#schedule_next_task(interval, id, ev_type, ev_body, start_time, times) ⇒ Object
196
197
198
|
# File 'lib/tamashii/agent/connection.rb', line 196
def schedule_next_task(interval, id, ev_type, ev_body, start_time, times)
Concurrent::ScheduledTask.execute(interval, args: [id, ev_type, ev_body, start_time, times], &method(:schedule_task_runner))
end
|
#schedule_task_runner(id, ev_type, ev_body, start_time, times) ⇒ Object
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
# File 'lib/tamashii/agent/connection.rb', line 179
def schedule_task_runner(id, ev_type, ev_body, start_time, times)
logger.debug "Schedule send attemp #{id} : #{times + 1} time(s)"
if try_send_request(ev_type, ev_body)
logger.debug "Request sent for id = #{id}"
else
if Time.now - start_time < Config.connection_timeout
logger.warn "Reschedule #{id} after 1 sec"
schedule_next_task(1, id, ev_type, ev_body, start_time, times + 1)
else
logger.warn "Abort scheduling #{id}"
end
end
end
|
#send_auth_request ⇒ Object
105
106
107
108
109
110
111
112
|
# File 'lib/tamashii/agent/connection.rb', line 105
def send_auth_request
if @client.transmit(Packet.new(Type::AUTH_TOKEN, 0, [Type::CLIENT[:agent], @master.serial_number,Config.token].join(",")).dump)
logger.debug "Auth sent!"
else
logger.error "Cannot sent auth request!"
end
end
|
#setup_callbacks ⇒ Object
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
# File 'lib/tamashii/agent/connection.rb', line 114
def setup_callbacks
@client.on :open, proc {
logger.info "Server opened"
self.auth_request
send_auth_request
}
@client.on :close, proc {
logger.info "Server closed normally"
}
@client.on :socket_closed, proc {
logger.info "Server socket closed"
self.reset
}
@client.on :message, proc { |data|
pkt = Packet.load(data)
process_packet(pkt) if pkt
}
@client.on :error, proc { |e|
logger.error("#{e.message}")
}
end
|
#setup_resolver ⇒ Object
61
62
63
64
65
66
67
68
69
70
71
72
73
|
# File 'lib/tamashii/agent/connection.rb', line 61
def setup_resolver
env_data = {connection: self}
Resolver.config do
[Type::REBOOT, Type::POWEROFF, Type::RESTART, Type::UPDATE].each do |type|
handle type, Handler::System, env_data
end
[Type::LCD_MESSAGE, Type::LCD_SET_IDLE_TEXT].each do |type|
handle type, Handler::LCD, env_data
end
handle Type::BUZZER_SOUND, Handler::Buzzer, env_data
handle Type::RFID_RESPONSE_JSON, Handler::RemoteResponse, env_data
end
end
|
#stop_threads ⇒ Object
99
100
101
102
|
# File 'lib/tamashii/agent/connection.rb', line 99
def stop_threads
super
@client.close
end
|
#try_send_request(ev_type, ev_body) ⇒ Object
90
91
92
93
94
95
96
97
|
# File 'lib/tamashii/agent/connection.rb', line 90
def try_send_request(ev_type, ev_body)
if self.ready?
@client.transmit(Packet.new(ev_type, @tag, ev_body).dump)
true
else
false
end
end
|