rsmp 0.14.6 → 0.15.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 +4 -4
- data/Gemfile.lock +4 -4
- data/config/tlc.yaml +1 -1
- data/lib/rsmp/collect/ack_collector.rb +16 -0
- data/lib/rsmp/component.rb +1 -1
- data/lib/rsmp/components.rb +2 -2
- data/lib/rsmp/proxy.rb +19 -1
- data/lib/rsmp/site.rb +2 -1
- data/lib/rsmp/site_proxy.rb +1 -1
- data/lib/rsmp/supervisor_proxy.rb +9 -4
- data/lib/rsmp/tlc/detector_logic.rb +7 -7
- data/lib/rsmp/tlc/signal_group.rb +6 -6
- data/lib/rsmp/tlc/signal_priority.rb +28 -0
- data/lib/rsmp/tlc/traffic_controller.rb +161 -69
- data/lib/rsmp/version.rb +1 -1
- data/lib/rsmp.rb +2 -0
- data/rsmp.gemspec +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0cd9ae260f3226f42fd5d0e2aafbd2daefaebebe7a13863ac9a809609cf78935
|
4
|
+
data.tar.gz: 772ad76e47e4470b15d1245634e9dc6c477b20e41d746f258855a48230340f10
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f9c480ba0ba82548ca0aa639281f7a44a7489ed096087505a1887f328bf818e83e4549b7fbe0099e83a731cc316d736d64b63b925ad993ac428ad3346990fab
|
7
|
+
data.tar.gz: 892f11941e75f9517b975e1d16202a48046c902febbc89d1c4463c98abe1dccb0416d2425b11af2fa771d967ce173933b476410430da22d405abd35af96031fb
|
data/Gemfile.lock
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rsmp (0.
|
4
|
+
rsmp (0.15.2)
|
5
5
|
async (~> 1.30.3)
|
6
6
|
async-io (~> 1.33.0)
|
7
7
|
colorize (~> 0.8.1)
|
8
|
-
rsmp_schema (~> 0.
|
8
|
+
rsmp_schema (~> 0.3.1)
|
9
9
|
thor (~> 1.2.1)
|
10
10
|
|
11
11
|
GEM
|
@@ -80,7 +80,7 @@ GEM
|
|
80
80
|
nio4r (2.5.8)
|
81
81
|
rake (13.0.6)
|
82
82
|
regexp_parser (2.5.0)
|
83
|
-
rsmp_schema (0.
|
83
|
+
rsmp_schema (0.3.1)
|
84
84
|
json_schemer (~> 0.2.21)
|
85
85
|
thor (~> 1.2.1)
|
86
86
|
rspec (3.10.0)
|
@@ -100,7 +100,7 @@ GEM
|
|
100
100
|
ffi (~> 1.1)
|
101
101
|
thor (1.2.1)
|
102
102
|
timecop (0.9.5)
|
103
|
-
timers (4.3.
|
103
|
+
timers (4.3.4)
|
104
104
|
uri_template (0.7.0)
|
105
105
|
|
106
106
|
PLATFORMS
|
data/config/tlc.yaml
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
module RSMP
|
2
|
+
# Class for waiting for a message acknowledgement
|
3
|
+
class AckCollector < Collector
|
4
|
+
def initialize proxy, options={}
|
5
|
+
raise ArgumentError.new("m_id must be provided") unless options[:m_id]
|
6
|
+
required = { type: 'MessageAck', num: 1, title: 'message acknowledgement' }
|
7
|
+
super proxy, options.merge(required)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Check if we the MessageAck related to initiating request, identified by @m_id.
|
11
|
+
def type_match? message
|
12
|
+
return false if super(message) == false
|
13
|
+
return message.attribute('oMId') == @options[:m_id]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/rsmp/component.rb
CHANGED
@@ -9,7 +9,7 @@ module RSMP
|
|
9
9
|
raise UnknownCommand.new "Command #{command_code} not implemented by #{self.class}"
|
10
10
|
end
|
11
11
|
|
12
|
-
def get_status status_code, status_name=nil
|
12
|
+
def get_status status_code, status_name=nil, options={}
|
13
13
|
raise UnknownStatus.new "Status #{status_code}/#{status_name} not implemented by #{self.class}"
|
14
14
|
end
|
15
15
|
|
data/lib/rsmp/components.rb
CHANGED
@@ -17,8 +17,8 @@ module RSMP
|
|
17
17
|
check_main_component settings
|
18
18
|
settings.each_pair do |type,components_by_type|
|
19
19
|
if components_by_type
|
20
|
-
components_by_type.each_pair do |id,
|
21
|
-
@components[id] = build_component(id:id, type:type, settings:
|
20
|
+
components_by_type.each_pair do |id,component_settings|
|
21
|
+
@components[id] = build_component(id:id, type:type, settings:component_settings)
|
22
22
|
@main = @components[id] if type=='main'
|
23
23
|
end
|
24
24
|
end
|
data/lib/rsmp/proxy.rb
CHANGED
@@ -560,8 +560,11 @@ module RSMP
|
|
560
560
|
message.original = original
|
561
561
|
log_acknowledgement_for_original message, original
|
562
562
|
|
563
|
-
|
563
|
+
case original.type
|
564
|
+
when "Version"
|
564
565
|
version_acknowledged
|
566
|
+
when "StatusSubscribe"
|
567
|
+
status_subscribe_acknowledged original
|
565
568
|
end
|
566
569
|
|
567
570
|
check_outgoing_acknowledged original
|
@@ -647,5 +650,20 @@ module RSMP
|
|
647
650
|
message.attributes['ntsOId'] = (main && main.ntsOId) ? main.ntsOId : ''
|
648
651
|
message.attributes['xNId'] = (main && main.xNId) ? main.xNId : ''
|
649
652
|
end
|
653
|
+
|
654
|
+
# use Gem class to check version requirement
|
655
|
+
def self.version_requirement_met? requirement, version
|
656
|
+
Gem::Requirement.new(requirement).satisfied_by?(Gem::Version.new(version))
|
657
|
+
end
|
658
|
+
|
659
|
+
def status_subscribe_acknowledged original
|
660
|
+
component = find_component original.attribute('cId')
|
661
|
+
return unless component
|
662
|
+
short = Message.shorten_m_id original.m_id
|
663
|
+
subscribe_list = original.attributes['sS']
|
664
|
+
log "StatusSubscribe #{short} acknowledged, allowing repeated status values for #{subscribe_list}", level: :info
|
665
|
+
component.allow_repeat_updates subscribe_list
|
666
|
+
end
|
667
|
+
|
650
668
|
end
|
651
669
|
end
|
data/lib/rsmp/site.rb
CHANGED
@@ -145,7 +145,8 @@ module RSMP
|
|
145
145
|
nil
|
146
146
|
end
|
147
147
|
|
148
|
-
def build_component id:, type:, settings:
|
148
|
+
def build_component id:, type:, settings:
|
149
|
+
settings ||= {}
|
149
150
|
if type == 'main'
|
150
151
|
Component.new id:id, node: self, grouped: true,
|
151
152
|
ntsOId: settings['ntsOId'], xNId: settings['xNId']
|
data/lib/rsmp/site_proxy.rb
CHANGED
@@ -228,7 +228,6 @@ module RSMP
|
|
228
228
|
end
|
229
229
|
|
230
230
|
component = find_component component_id
|
231
|
-
component.allow_repeat_updates subscribe_list
|
232
231
|
|
233
232
|
message = RSMP::StatusSubscribe.new({
|
234
233
|
"cId" => component_id,
|
@@ -236,6 +235,7 @@ module RSMP
|
|
236
235
|
'mId' => m_id
|
237
236
|
})
|
238
237
|
set_nts_message_attributes message
|
238
|
+
|
239
239
|
send_and_optionally_collect message, options do |collect_options|
|
240
240
|
StatusCollector.new(
|
241
241
|
self,
|
@@ -270,13 +270,18 @@ module RSMP
|
|
270
270
|
send_message response
|
271
271
|
end
|
272
272
|
|
273
|
+
def rsmpify_value v
|
274
|
+
return v if v.is_a? Array
|
275
|
+
v.to_s
|
276
|
+
end
|
277
|
+
|
273
278
|
def process_status_request message, options={}
|
274
279
|
component_id = message.attributes["cId"]
|
275
280
|
component = @site.find_component component_id
|
276
281
|
log "Received #{message.type}", message: message, level: :log
|
277
282
|
sS = message.attributes["sS"].map do |arg|
|
278
|
-
value, quality = component.get_status arg['sCI'], arg['n']
|
279
|
-
{ "s" => value
|
283
|
+
value, quality = component.get_status arg['sCI'], arg['n'], {sxl_version: sxl_version}
|
284
|
+
{ "s" => rsmpify_value(value), "q" => quality.to_s }.merge arg
|
280
285
|
end
|
281
286
|
response = StatusResponse.new({
|
282
287
|
"cId"=>component_id,
|
@@ -375,7 +380,7 @@ module RSMP
|
|
375
380
|
# send as soon as the data changes
|
376
381
|
if component_object
|
377
382
|
current, age = *(component_object.get_status code, name)
|
378
|
-
current = current
|
383
|
+
current = rsmpify_value(current)
|
379
384
|
end
|
380
385
|
last_sent = fetch_last_sent_status component, code, name
|
381
386
|
if current != last_sent
|
@@ -413,7 +418,7 @@ module RSMP
|
|
413
418
|
end
|
414
419
|
sS << { "sCI" => code,
|
415
420
|
"n" => status_name,
|
416
|
-
"s" => value
|
421
|
+
"s" => rsmpify_value(value),
|
417
422
|
"q" => quality }
|
418
423
|
end
|
419
424
|
end
|
@@ -9,7 +9,7 @@ module RSMP
|
|
9
9
|
@value = 0
|
10
10
|
end
|
11
11
|
|
12
|
-
def get_status code, name=nil
|
12
|
+
def get_status code, name=nil, options={}
|
13
13
|
case code
|
14
14
|
when 'S0201', 'S0202', 'S0203', 'S0204'
|
15
15
|
return send("handle_#{code.downcase}", code, name)
|
@@ -18,7 +18,7 @@ module RSMP
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
def handle_s0201 status_code, status_name=nil
|
21
|
+
def handle_s0201 status_code, status_name=nil, options={}
|
22
22
|
case status_name
|
23
23
|
when 'starttime'
|
24
24
|
TrafficControllerSite.make_status @node.clock.to_s
|
@@ -27,7 +27,7 @@ module RSMP
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
def handle_s0202 status_code, status_name=nil
|
30
|
+
def handle_s0202 status_code, status_name=nil, options={}
|
31
31
|
case status_name
|
32
32
|
when 'starttime'
|
33
33
|
TrafficControllerSite.make_status @node.clock.to_s
|
@@ -36,7 +36,7 @@ module RSMP
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
def handle_s0203 status_code, status_name=nil
|
39
|
+
def handle_s0203 status_code, status_name=nil, options={}
|
40
40
|
case status_name
|
41
41
|
when 'starttime'
|
42
42
|
TrafficControllerSite.make_status @node.clock.to_s
|
@@ -45,7 +45,7 @@ module RSMP
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
def handle_s0204 status_code, status_name=nil
|
48
|
+
def handle_s0204 status_code, status_name=nil, options={}
|
49
49
|
case status_name
|
50
50
|
when 'starttime'
|
51
51
|
TrafficControllerSite.make_status @node.clock.to_s
|
@@ -70,7 +70,7 @@ module RSMP
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
-
def handle_command command_code, arg
|
73
|
+
def handle_command command_code, arg, options={}
|
74
74
|
case command_code
|
75
75
|
when 'M0008'
|
76
76
|
handle_m0008 arg
|
@@ -79,7 +79,7 @@ module RSMP
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
-
def handle_m0008 arg
|
82
|
+
def handle_m0008 arg, options={}
|
83
83
|
@node.verify_security_code 2, arg['securityCode']
|
84
84
|
status = arg['status']=='True'
|
85
85
|
mode = arg['mode']=='True'
|
@@ -35,17 +35,17 @@ module RSMP
|
|
35
35
|
state
|
36
36
|
end
|
37
37
|
|
38
|
-
def handle_command command_code, arg
|
38
|
+
def handle_command command_code, arg, options={}
|
39
39
|
case command_code
|
40
40
|
when 'M0010', 'M0011'
|
41
|
-
return send("handle_#{command_code.downcase}", arg)
|
41
|
+
return send("handle_#{command_code.downcase}", arg, options)
|
42
42
|
else
|
43
43
|
raise UnknownCommand.new "Unknown command #{command_code}"
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
47
|
# Start of signal group. Orders a signal group to green
|
48
|
-
def handle_m0010 arg
|
48
|
+
def handle_m0010 arg, options={}
|
49
49
|
@node.verify_security_code 2, arg['securityCode']
|
50
50
|
if TrafficControllerSite.from_rsmp_bool arg['status']
|
51
51
|
log "Start signal group #{c_id}, go to green", level: :info
|
@@ -53,14 +53,14 @@ module RSMP
|
|
53
53
|
end
|
54
54
|
|
55
55
|
# Stop of signal group. Orders a signal group to red
|
56
|
-
def handle_m0011 arg
|
56
|
+
def handle_m0011 arg, options={}
|
57
57
|
@node.verify_security_code 2, arg['securityCode']
|
58
58
|
if TrafficControllerSite.from_rsmp_bool arg['status']
|
59
59
|
log "Stop signal group #{c_id}, go to red", level: :info
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
def get_status code, name=nil
|
63
|
+
def get_status code, name=nil, options={}
|
64
64
|
case code
|
65
65
|
when 'S0025'
|
66
66
|
return send("handle_#{code.downcase}", code, name)
|
@@ -69,7 +69,7 @@ module RSMP
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
def handle_s0025 status_code, status_name=nil
|
72
|
+
def handle_s0025 status_code, status_name=nil, options={}
|
73
73
|
now = @node.clock.to_s
|
74
74
|
case status_name
|
75
75
|
when 'minToGEstimate'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class RSMP::TLC::SignalPriority
|
2
|
+
attr_reader :state, :node, :id, :level, :eta, :vehicleType, :age, :updated
|
3
|
+
|
4
|
+
def initialize node:, id:, level:, eta:, vehicleType:
|
5
|
+
@node = node
|
6
|
+
@id = id
|
7
|
+
@level = level
|
8
|
+
@eta = eta
|
9
|
+
@vehicleType = vehicleType
|
10
|
+
set_state 'received'
|
11
|
+
end
|
12
|
+
|
13
|
+
def set_state state
|
14
|
+
@state = state
|
15
|
+
@updated = node.clock.now
|
16
|
+
node.signal_priority_changed self, @state
|
17
|
+
end
|
18
|
+
|
19
|
+
def timer
|
20
|
+
@age = @node.clock.now - @updated
|
21
|
+
case @state
|
22
|
+
when 'received'
|
23
|
+
set_state 'activated' if @age >= 0.5
|
24
|
+
when 'activated'
|
25
|
+
set_state 'completed' if @age >= 0.5
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -60,6 +60,7 @@ module RSMP
|
|
60
60
|
@startup_sequence_pos = 0
|
61
61
|
@time_int = nil
|
62
62
|
@inputs.reset
|
63
|
+
@signal_priorities = []
|
63
64
|
end
|
64
65
|
|
65
66
|
def dark?
|
@@ -105,8 +106,30 @@ module RSMP
|
|
105
106
|
move_startup_sequence if @startup_sequence_active
|
106
107
|
|
107
108
|
@signal_groups.each { |group| group.timer }
|
109
|
+
@signal_priorities.each {|priority| priority.timer }
|
108
110
|
|
109
111
|
output_states
|
112
|
+
prune_priorities
|
113
|
+
end
|
114
|
+
|
115
|
+
def signal_priority_changed priority, state
|
116
|
+
#puts "priority #{priority.id} -> #{state}"
|
117
|
+
end
|
118
|
+
|
119
|
+
def prune_priorities
|
120
|
+
# TODO spec states that update must be send one time when it reaches the state 'completed',
|
121
|
+
# and then be removed. so we need to know when it has been sent
|
122
|
+
@signal_priorities.delete_if {|priority| priority.state=='completed' && priority.age >= 1.5 }
|
123
|
+
end
|
124
|
+
|
125
|
+
def get_priority_list
|
126
|
+
@signal_priorities.map do |priority|
|
127
|
+
{
|
128
|
+
"r" => priority.id,
|
129
|
+
"t" => RSMP::Clock.to_s(priority.updated),
|
130
|
+
"s" => priority.state
|
131
|
+
}
|
132
|
+
end
|
110
133
|
end
|
111
134
|
|
112
135
|
def move_cycle_counter
|
@@ -204,25 +227,25 @@ module RSMP
|
|
204
227
|
@signal_groups.map { |group| group.state }.join
|
205
228
|
end
|
206
229
|
|
207
|
-
def handle_command command_code, arg
|
230
|
+
def handle_command command_code, arg, options={}
|
208
231
|
case command_code
|
209
232
|
when 'M0001', 'M0002', 'M0003', 'M0004', 'M0005', 'M0006', 'M0007',
|
210
233
|
'M0012', 'M0013', 'M0014', 'M0015', 'M0016', 'M0017', 'M0018',
|
211
234
|
'M0019', 'M0020', 'M0021', 'M0022',
|
212
235
|
'M0103', 'M0104'
|
213
236
|
|
214
|
-
return send("handle_#{command_code.downcase}", arg)
|
237
|
+
return send("handle_#{command_code.downcase}", arg, options)
|
215
238
|
else
|
216
239
|
raise UnknownCommand.new "Unknown command #{command_code}"
|
217
240
|
end
|
218
241
|
end
|
219
242
|
|
220
|
-
def handle_m0001 arg
|
243
|
+
def handle_m0001 arg, options={}
|
221
244
|
@node.verify_security_code 2, arg['securityCode']
|
222
245
|
switch_functional_position arg['status'], timeout: arg['timeout'].to_i*60
|
223
246
|
end
|
224
247
|
|
225
|
-
def handle_m0002 arg
|
248
|
+
def handle_m0002 arg, options={}
|
226
249
|
@node.verify_security_code 2, arg['securityCode']
|
227
250
|
if TrafficControllerSite.from_rsmp_bool(arg['status'])
|
228
251
|
switch_plan arg['timeplan']
|
@@ -231,12 +254,12 @@ module RSMP
|
|
231
254
|
end
|
232
255
|
end
|
233
256
|
|
234
|
-
def handle_m0003 arg
|
257
|
+
def handle_m0003 arg, options={}
|
235
258
|
@node.verify_security_code 2, arg['securityCode']
|
236
259
|
@traffic_situation = arg['traficsituation'].to_i
|
237
260
|
end
|
238
261
|
|
239
|
-
def handle_m0004 arg
|
262
|
+
def handle_m0004 arg, options={}
|
240
263
|
@node.verify_security_code 2, arg['securityCode']
|
241
264
|
# don't restart immeediately, since we need to first send command response
|
242
265
|
# instead, defer an action, which will be handled by the TLC site
|
@@ -244,7 +267,7 @@ module RSMP
|
|
244
267
|
@node.defer :restart
|
245
268
|
end
|
246
269
|
|
247
|
-
def handle_m0005 arg
|
270
|
+
def handle_m0005 arg, options={}
|
248
271
|
@node.verify_security_code 2, arg['securityCode']
|
249
272
|
@emergency_route = (arg['status'] == 'True')
|
250
273
|
@emergency_route_number = arg['emergencyroute'].to_i
|
@@ -272,7 +295,7 @@ module RSMP
|
|
272
295
|
end
|
273
296
|
end
|
274
297
|
|
275
|
-
def handle_m0006 arg
|
298
|
+
def handle_m0006 arg, options={}
|
276
299
|
@node.verify_security_code 2, arg['securityCode']
|
277
300
|
input = arg['input'].to_i
|
278
301
|
status = string_to_bool arg['status']
|
@@ -288,16 +311,16 @@ module RSMP
|
|
288
311
|
input_logic input, change if change != nil
|
289
312
|
end
|
290
313
|
|
291
|
-
def handle_m0007 arg
|
314
|
+
def handle_m0007 arg, options={}
|
292
315
|
@node.verify_security_code 2, arg['securityCode']
|
293
316
|
set_fixed_time_control arg['status']
|
294
317
|
end
|
295
318
|
|
296
|
-
def handle_m0012 arg
|
319
|
+
def handle_m0012 arg, options={}
|
297
320
|
@node.verify_security_code 2, arg['securityCode']
|
298
321
|
end
|
299
322
|
|
300
|
-
def handle_m0013 arg
|
323
|
+
def handle_m0013 arg, options={}
|
301
324
|
@node.verify_security_code 2, arg['securityCode']
|
302
325
|
end
|
303
326
|
|
@@ -307,7 +330,7 @@ module RSMP
|
|
307
330
|
plan
|
308
331
|
end
|
309
332
|
|
310
|
-
def handle_m0014 arg
|
333
|
+
def handle_m0014 arg, options={}
|
311
334
|
@node.verify_security_code 2, arg['securityCode']
|
312
335
|
plan = find_plan arg['plan']
|
313
336
|
arg['status'].split(',').each do |item|
|
@@ -319,15 +342,15 @@ module RSMP
|
|
319
342
|
end
|
320
343
|
end
|
321
344
|
|
322
|
-
def handle_m0015 arg
|
345
|
+
def handle_m0015 arg, options={}
|
323
346
|
@node.verify_security_code 2, arg['securityCode']
|
324
347
|
end
|
325
348
|
|
326
|
-
def handle_m0016 arg
|
349
|
+
def handle_m0016 arg, options={}
|
327
350
|
@node.verify_security_code 2, arg['securityCode']
|
328
351
|
end
|
329
352
|
|
330
|
-
def handle_m0017 arg
|
353
|
+
def handle_m0017 arg, options={}
|
331
354
|
@node.verify_security_code 2, arg['securityCode']
|
332
355
|
arg['status'].split(',').each do |item|
|
333
356
|
elems = item.split('-')
|
@@ -343,7 +366,7 @@ module RSMP
|
|
343
366
|
end
|
344
367
|
end
|
345
368
|
|
346
|
-
def handle_m0018 arg
|
369
|
+
def handle_m0018 arg, options={}
|
347
370
|
@node.verify_security_code 2, arg['securityCode']
|
348
371
|
end
|
349
372
|
|
@@ -373,7 +396,7 @@ module RSMP
|
|
373
396
|
bool ? '1' : '0'
|
374
397
|
end
|
375
398
|
|
376
|
-
def handle_m0019 arg
|
399
|
+
def handle_m0019 arg, options={}
|
377
400
|
@node.verify_security_code 2, arg['securityCode']
|
378
401
|
input = arg['input'].to_i
|
379
402
|
force = string_to_bool arg['status']
|
@@ -390,20 +413,57 @@ module RSMP
|
|
390
413
|
input_logic input, change if change != nil
|
391
414
|
end
|
392
415
|
|
393
|
-
def handle_m0020 arg
|
416
|
+
def handle_m0020 arg, options={}
|
394
417
|
@node.verify_security_code 2, arg['securityCode']
|
395
418
|
end
|
396
419
|
|
397
|
-
def handle_m0021 arg
|
420
|
+
def handle_m0021 arg, options={}
|
398
421
|
@node.verify_security_code 2, arg['securityCode']
|
399
422
|
end
|
400
423
|
|
401
|
-
def
|
424
|
+
def handle_m0022 arg, options={}
|
425
|
+
id = arg['requestId']
|
426
|
+
type = arg['type']
|
427
|
+
priority = @signal_priorities.find { |priority| priority.id == id }
|
428
|
+
case type
|
429
|
+
when 'new'
|
430
|
+
if priority
|
431
|
+
raise MessageRejected.new("Priority Request #{id} already exists")
|
432
|
+
else
|
433
|
+
#ref = arg.slice('signalGroupId','inputId','connectionId','approachId','laneInId','laneOutId')
|
434
|
+
if arg['signalGroupId']
|
435
|
+
signal_group = node.find_component arg['signalGroupId']
|
436
|
+
end
|
437
|
+
|
438
|
+
level = arg['level']
|
439
|
+
eta = arg['eta']
|
440
|
+
vehicleType = arg['vehicleType']
|
441
|
+
@signal_priorities << SignalPriority.new(node:self, id:id, level:level, eta:eta, vehicleType:vehicleType)
|
442
|
+
log "Priority request for signal group #{signal_group.c_id} received with id #{id}", level: :info
|
443
|
+
end
|
444
|
+
when 'update'
|
445
|
+
if priority
|
446
|
+
log "Priority Request #{id} updated", level: :info
|
447
|
+
else
|
448
|
+
raise MessageRejected.new("Cannot update priority request #{id}, not found")
|
449
|
+
end
|
450
|
+
when 'cancel'
|
451
|
+
if priority
|
452
|
+
@signal_priorities.delete priority
|
453
|
+
else
|
454
|
+
raise MessageRejected.new("Cannot cancel priority request #{id}, not found")
|
455
|
+
end
|
456
|
+
else
|
457
|
+
raise MessageRejected.new("Unknown type #{type}")
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
461
|
+
def handle_m0103 arg, options={}
|
402
462
|
level = {'Level1'=>1,'Level2'=>2}[arg['status']]
|
403
463
|
@node.change_security_code level, arg['oldSecurityCode'], arg['newSecurityCode']
|
404
464
|
end
|
405
465
|
|
406
|
-
def handle_m0104 arg
|
466
|
+
def handle_m0104 arg, options={}
|
407
467
|
@node.verify_security_code 1, arg['securityCode']
|
408
468
|
time = Time.new(
|
409
469
|
arg['year'],
|
@@ -459,22 +519,22 @@ module RSMP
|
|
459
519
|
mode
|
460
520
|
end
|
461
521
|
|
462
|
-
def get_status code, name=nil
|
522
|
+
def get_status code, name=nil, options={}
|
463
523
|
case code
|
464
524
|
when 'S0001', 'S0002', 'S0003', 'S0004', 'S0005', 'S0006', 'S0007',
|
465
525
|
'S0008', 'S0009', 'S0010', 'S0011', 'S0012', 'S0013', 'S0014',
|
466
526
|
'S0015', 'S0016', 'S0017', 'S0018', 'S0019', 'S0020', 'S0021',
|
467
527
|
'S0022', 'S0023', 'S0024', 'S0026', 'S0027', 'S0028',
|
468
|
-
'S0029', 'S0030', 'S0031',
|
528
|
+
'S0029', 'S0030', 'S0031', 'S0032', 'S0033',
|
469
529
|
'S0091', 'S0092', 'S0095', 'S0096', 'S0097',
|
470
530
|
'S0205', 'S0206', 'S0207', 'S0208'
|
471
|
-
return send("handle_#{code.downcase}", code, name)
|
531
|
+
return send("handle_#{code.downcase}", code, name, options)
|
472
532
|
else
|
473
533
|
raise InvalidMessage.new "unknown status code #{code}"
|
474
534
|
end
|
475
535
|
end
|
476
536
|
|
477
|
-
def handle_s0001 status_code, status_name=nil
|
537
|
+
def handle_s0001 status_code, status_name=nil, options={}
|
478
538
|
case status_name
|
479
539
|
when 'signalgroupstatus'
|
480
540
|
TrafficControllerSite.make_status format_signal_group_status
|
@@ -487,14 +547,14 @@ module RSMP
|
|
487
547
|
end
|
488
548
|
end
|
489
549
|
|
490
|
-
def handle_s0002 status_code, status_name=nil
|
550
|
+
def handle_s0002 status_code, status_name=nil, options={}
|
491
551
|
case status_name
|
492
552
|
when 'detectorlogicstatus'
|
493
553
|
TrafficControllerSite.make_status @detector_logics.map { |dl| bool_to_digit(dl.value) }.join
|
494
554
|
end
|
495
555
|
end
|
496
556
|
|
497
|
-
def handle_s0003 status_code, status_name=nil
|
557
|
+
def handle_s0003 status_code, status_name=nil, options={}
|
498
558
|
case status_name
|
499
559
|
when 'inputstatus'
|
500
560
|
TrafficControllerSite.make_status @inputs.actual_string
|
@@ -503,7 +563,7 @@ module RSMP
|
|
503
563
|
end
|
504
564
|
end
|
505
565
|
|
506
|
-
def handle_s0004 status_code, status_name=nil
|
566
|
+
def handle_s0004 status_code, status_name=nil, options={}
|
507
567
|
case status_name
|
508
568
|
when 'outputstatus'
|
509
569
|
TrafficControllerSite.make_status 0
|
@@ -512,14 +572,14 @@ module RSMP
|
|
512
572
|
end
|
513
573
|
end
|
514
574
|
|
515
|
-
def handle_s0005 status_code, status_name=nil
|
575
|
+
def handle_s0005 status_code, status_name=nil, options={}
|
516
576
|
case status_name
|
517
577
|
when 'status'
|
518
578
|
TrafficControllerSite.make_status @is_starting
|
519
579
|
end
|
520
580
|
end
|
521
581
|
|
522
|
-
def handle_s0006 status_code, status_name=nil
|
582
|
+
def handle_s0006 status_code, status_name=nil, options={}
|
523
583
|
case status_name
|
524
584
|
when 'status'
|
525
585
|
TrafficControllerSite.make_status @emergency_route
|
@@ -528,7 +588,7 @@ module RSMP
|
|
528
588
|
end
|
529
589
|
end
|
530
590
|
|
531
|
-
def handle_s0007 status_code, status_name=nil
|
591
|
+
def handle_s0007 status_code, status_name=nil, options={}
|
532
592
|
case status_name
|
533
593
|
when 'intersection'
|
534
594
|
TrafficControllerSite.make_status @intersection
|
@@ -537,7 +597,7 @@ module RSMP
|
|
537
597
|
end
|
538
598
|
end
|
539
599
|
|
540
|
-
def handle_s0008 status_code, status_name=nil
|
600
|
+
def handle_s0008 status_code, status_name=nil, options={}
|
541
601
|
case status_name
|
542
602
|
when 'intersection'
|
543
603
|
TrafficControllerSite.make_status @intersection
|
@@ -546,7 +606,7 @@ module RSMP
|
|
546
606
|
end
|
547
607
|
end
|
548
608
|
|
549
|
-
def handle_s0009 status_code, status_name=nil
|
609
|
+
def handle_s0009 status_code, status_name=nil, options={}
|
550
610
|
case status_name
|
551
611
|
when 'intersection'
|
552
612
|
TrafficControllerSite.make_status @intersection
|
@@ -555,7 +615,7 @@ module RSMP
|
|
555
615
|
end
|
556
616
|
end
|
557
617
|
|
558
|
-
def handle_s0010 status_code, status_name=nil
|
618
|
+
def handle_s0010 status_code, status_name=nil, options={}
|
559
619
|
case status_name
|
560
620
|
when 'intersection'
|
561
621
|
TrafficControllerSite.make_status @intersection
|
@@ -564,7 +624,7 @@ module RSMP
|
|
564
624
|
end
|
565
625
|
end
|
566
626
|
|
567
|
-
def handle_s0011 status_code, status_name=nil
|
627
|
+
def handle_s0011 status_code, status_name=nil, options={}
|
568
628
|
case status_name
|
569
629
|
when 'intersection'
|
570
630
|
TrafficControllerSite.make_status @intersection
|
@@ -573,7 +633,7 @@ module RSMP
|
|
573
633
|
end
|
574
634
|
end
|
575
635
|
|
576
|
-
def handle_s0012 status_code, status_name=nil
|
636
|
+
def handle_s0012 status_code, status_name=nil, options={}
|
577
637
|
case status_name
|
578
638
|
when 'intersection'
|
579
639
|
TrafficControllerSite.make_status @intersection
|
@@ -582,7 +642,7 @@ module RSMP
|
|
582
642
|
end
|
583
643
|
end
|
584
644
|
|
585
|
-
def handle_s0013 status_code, status_name=nil
|
645
|
+
def handle_s0013 status_code, status_name=nil, options={}
|
586
646
|
case status_name
|
587
647
|
when 'intersection'
|
588
648
|
TrafficControllerSite.make_status @intersection
|
@@ -591,49 +651,49 @@ module RSMP
|
|
591
651
|
end
|
592
652
|
end
|
593
653
|
|
594
|
-
def handle_s0014 status_code, status_name=nil
|
654
|
+
def handle_s0014 status_code, status_name=nil, options={}
|
595
655
|
case status_name
|
596
656
|
when 'status'
|
597
657
|
TrafficControllerSite.make_status @plan
|
598
658
|
end
|
599
659
|
end
|
600
660
|
|
601
|
-
def handle_s0015 status_code, status_name=nil
|
661
|
+
def handle_s0015 status_code, status_name=nil, options={}
|
602
662
|
case status_name
|
603
663
|
when 'status'
|
604
664
|
TrafficControllerSite.make_status @traffic_situation
|
605
665
|
end
|
606
666
|
end
|
607
667
|
|
608
|
-
def handle_s0016 status_code, status_name=nil
|
668
|
+
def handle_s0016 status_code, status_name=nil, options={}
|
609
669
|
case status_name
|
610
670
|
when 'number'
|
611
671
|
TrafficControllerSite.make_status @detector_logics.size
|
612
672
|
end
|
613
673
|
end
|
614
674
|
|
615
|
-
def handle_s0017 status_code, status_name=nil
|
675
|
+
def handle_s0017 status_code, status_name=nil, options={}
|
616
676
|
case status_name
|
617
677
|
when 'number'
|
618
678
|
TrafficControllerSite.make_status @signal_groups.size
|
619
679
|
end
|
620
680
|
end
|
621
681
|
|
622
|
-
def handle_s0018 status_code, status_name=nil
|
682
|
+
def handle_s0018 status_code, status_name=nil, options={}
|
623
683
|
case status_name
|
624
684
|
when 'number'
|
625
685
|
TrafficControllerSite.make_status @plans.size
|
626
686
|
end
|
627
687
|
end
|
628
688
|
|
629
|
-
def handle_s0019 status_code, status_name=nil
|
689
|
+
def handle_s0019 status_code, status_name=nil, options={}
|
630
690
|
case status_name
|
631
691
|
when 'number'
|
632
692
|
TrafficControllerSite.make_status @num_traffic_situations
|
633
693
|
end
|
634
694
|
end
|
635
695
|
|
636
|
-
def handle_s0020 status_code, status_name=nil
|
696
|
+
def handle_s0020 status_code, status_name=nil, options={}
|
637
697
|
case status_name
|
638
698
|
when 'intersection'
|
639
699
|
TrafficControllerSite.make_status @intersection
|
@@ -642,21 +702,21 @@ module RSMP
|
|
642
702
|
end
|
643
703
|
end
|
644
704
|
|
645
|
-
def handle_s0021 status_code, status_name=nil
|
705
|
+
def handle_s0021 status_code, status_name=nil, options={}
|
646
706
|
case status_name
|
647
707
|
when 'detectorlogics'
|
648
708
|
TrafficControllerSite.make_status @detector_logics.map { |logic| bool_to_digit(logic.forced)}.join
|
649
709
|
end
|
650
710
|
end
|
651
711
|
|
652
|
-
def handle_s0022 status_code, status_name=nil
|
712
|
+
def handle_s0022 status_code, status_name=nil, options={}
|
653
713
|
case status_name
|
654
714
|
when 'status'
|
655
715
|
TrafficControllerSite.make_status @plans.keys.join(',')
|
656
716
|
end
|
657
717
|
end
|
658
718
|
|
659
|
-
def handle_s0023 status_code, status_name=nil
|
719
|
+
def handle_s0023 status_code, status_name=nil, options={}
|
660
720
|
case status_name
|
661
721
|
when 'status'
|
662
722
|
dynamic_bands = @plans.map { |nr,plan| plan.dynamic_bands_string }
|
@@ -665,21 +725,21 @@ module RSMP
|
|
665
725
|
end
|
666
726
|
end
|
667
727
|
|
668
|
-
def handle_s0024 status_code, status_name=nil
|
728
|
+
def handle_s0024 status_code, status_name=nil, options={}
|
669
729
|
case status_name
|
670
730
|
when 'status'
|
671
731
|
TrafficControllerSite.make_status '1-0'
|
672
732
|
end
|
673
733
|
end
|
674
734
|
|
675
|
-
def handle_s0026 status_code, status_name=nil
|
735
|
+
def handle_s0026 status_code, status_name=nil, options={}
|
676
736
|
case status_name
|
677
737
|
when 'status'
|
678
738
|
TrafficControllerSite.make_status '0-00'
|
679
739
|
end
|
680
740
|
end
|
681
741
|
|
682
|
-
def handle_s0027 status_code, status_name=nil
|
742
|
+
def handle_s0027 status_code, status_name=nil, options={}
|
683
743
|
case status_name
|
684
744
|
when 'status'
|
685
745
|
status = @day_time_table.map do |i,item|
|
@@ -689,60 +749,92 @@ module RSMP
|
|
689
749
|
end
|
690
750
|
end
|
691
751
|
|
692
|
-
def handle_s0028 status_code, status_name=nil
|
752
|
+
def handle_s0028 status_code, status_name=nil, options={}
|
693
753
|
case status_name
|
694
754
|
when 'status'
|
695
755
|
TrafficControllerSite.make_status '00-00'
|
696
756
|
end
|
697
757
|
end
|
698
758
|
|
699
|
-
def handle_s0029 status_code, status_name=nil
|
759
|
+
def handle_s0029 status_code, status_name=nil, options={}
|
700
760
|
case status_name
|
701
761
|
when 'status'
|
702
762
|
TrafficControllerSite.make_status @inputs.forced_string
|
703
763
|
end
|
704
764
|
end
|
705
765
|
|
706
|
-
def handle_s0030 status_code, status_name=nil
|
766
|
+
def handle_s0030 status_code, status_name=nil, options={}
|
707
767
|
case status_name
|
708
768
|
when 'status'
|
709
769
|
TrafficControllerSite.make_status ''
|
710
770
|
end
|
711
771
|
end
|
712
772
|
|
713
|
-
def handle_s0031 status_code, status_name=nil
|
773
|
+
def handle_s0031 status_code, status_name=nil, options={}
|
714
774
|
case status_name
|
715
775
|
when 'status'
|
716
776
|
TrafficControllerSite.make_status ''
|
717
777
|
end
|
718
778
|
end
|
719
779
|
|
720
|
-
def
|
780
|
+
def handle_s0032 status_code, status_name=nil, options={}
|
721
781
|
case status_name
|
722
|
-
when '
|
723
|
-
TrafficControllerSite.make_status
|
782
|
+
when 'intersection'
|
783
|
+
TrafficControllerSite.make_status @intersection
|
724
784
|
when 'status'
|
725
|
-
TrafficControllerSite.make_status '
|
785
|
+
TrafficControllerSite.make_status 'local'
|
786
|
+
when 'source'
|
787
|
+
TrafficControllerSite.make_status 'startup'
|
726
788
|
end
|
727
789
|
end
|
728
790
|
|
729
|
-
def
|
791
|
+
def handle_s0033 status_code, status_name=nil, options={}
|
730
792
|
case status_name
|
731
|
-
when 'user'
|
732
|
-
TrafficControllerSite.make_status 'nobody'
|
733
793
|
when 'status'
|
734
|
-
TrafficControllerSite.make_status
|
794
|
+
TrafficControllerSite.make_status get_priority_list
|
795
|
+
end
|
796
|
+
end
|
797
|
+
|
798
|
+
def handle_s0091 status_code, status_name=nil, options={}
|
799
|
+
if Proxy.version_requirement_met? '>=1.1',options[:sxl_version]
|
800
|
+
case status_name
|
801
|
+
when 'user'
|
802
|
+
TrafficControllerSite.make_status 0
|
803
|
+
end
|
804
|
+
else
|
805
|
+
case status_name
|
806
|
+
when 'user'
|
807
|
+
TrafficControllerSite.make_status 'nobody'
|
808
|
+
when 'status'
|
809
|
+
TrafficControllerSite.make_status 'logout'
|
810
|
+
end
|
811
|
+
end
|
812
|
+
end
|
813
|
+
|
814
|
+
def handle_s0092 status_code, status_name=nil, options={}
|
815
|
+
if Proxy.version_requirement_met? '>=1.1',options[:sxl_version]
|
816
|
+
case status_name
|
817
|
+
when 'user'
|
818
|
+
TrafficControllerSite.make_status 0
|
819
|
+
end
|
820
|
+
else
|
821
|
+
case status_name
|
822
|
+
when 'user'
|
823
|
+
TrafficControllerSite.make_status 'nobody'
|
824
|
+
when 'status'
|
825
|
+
TrafficControllerSite.make_status 'logout'
|
826
|
+
end
|
735
827
|
end
|
736
828
|
end
|
737
829
|
|
738
|
-
def handle_s0095 status_code, status_name=nil
|
830
|
+
def handle_s0095 status_code, status_name=nil, options={}
|
739
831
|
case status_name
|
740
832
|
when 'status'
|
741
833
|
TrafficControllerSite.make_status RSMP::VERSION
|
742
834
|
end
|
743
835
|
end
|
744
836
|
|
745
|
-
def handle_s0096 status_code, status_name=nil
|
837
|
+
def handle_s0096 status_code, status_name=nil, options={}
|
746
838
|
now = clock.now
|
747
839
|
case status_name
|
748
840
|
when 'year'
|
@@ -760,7 +852,7 @@ module RSMP
|
|
760
852
|
end
|
761
853
|
end
|
762
854
|
|
763
|
-
def handle_s0097 status_code, status_name=nil
|
855
|
+
def handle_s0097 status_code, status_name=nil, options={}
|
764
856
|
case status_name
|
765
857
|
when 'checksum'
|
766
858
|
TrafficControllerSite.make_status '1'
|
@@ -770,7 +862,7 @@ module RSMP
|
|
770
862
|
end
|
771
863
|
end
|
772
864
|
|
773
|
-
def handle_s0205 status_code, status_name=nil
|
865
|
+
def handle_s0205 status_code, status_name=nil, options={}
|
774
866
|
case status_name
|
775
867
|
when 'start'
|
776
868
|
TrafficControllerSite.make_status clock.to_s
|
@@ -779,7 +871,7 @@ module RSMP
|
|
779
871
|
end
|
780
872
|
end
|
781
873
|
|
782
|
-
def handle_s0206 status_code, status_name=nil
|
874
|
+
def handle_s0206 status_code, status_name=nil, options={}
|
783
875
|
case status_name
|
784
876
|
when 'start'
|
785
877
|
TrafficControllerSite.make_status clock.to_s
|
@@ -788,7 +880,7 @@ module RSMP
|
|
788
880
|
end
|
789
881
|
end
|
790
882
|
|
791
|
-
def handle_s0207 status_code, status_name=nil
|
883
|
+
def handle_s0207 status_code, status_name=nil, options={}
|
792
884
|
case status_name
|
793
885
|
when 'start'
|
794
886
|
TrafficControllerSite.make_status clock.to_s
|
@@ -797,7 +889,7 @@ module RSMP
|
|
797
889
|
end
|
798
890
|
end
|
799
891
|
|
800
|
-
def handle_s0208 status_code, status_name=nil
|
892
|
+
def handle_s0208 status_code, status_name=nil, options={}
|
801
893
|
case status_name
|
802
894
|
when 'start'
|
803
895
|
TrafficControllerSite.make_status clock.to_s
|
data/lib/rsmp/version.rb
CHANGED
data/lib/rsmp.rb
CHANGED
@@ -30,6 +30,7 @@ require 'rsmp/collect/status_collector'
|
|
30
30
|
require 'rsmp/collect/command_response_collector'
|
31
31
|
require 'rsmp/collect/aggregated_status_collector'
|
32
32
|
require 'rsmp/collect/alarm_collector'
|
33
|
+
require 'rsmp/collect/ack_collector'
|
33
34
|
require 'rsmp/alarm_state'
|
34
35
|
require 'rsmp/component_base'
|
35
36
|
require 'rsmp/component'
|
@@ -48,6 +49,7 @@ require 'rsmp/tlc/detector_logic'
|
|
48
49
|
require 'rsmp/tlc/signal_group'
|
49
50
|
require 'rsmp/tlc/signal_plan'
|
50
51
|
require 'rsmp/tlc/inputs'
|
52
|
+
require 'rsmp/tlc/signal_priority'
|
51
53
|
|
52
54
|
require 'rsmp/convert/import/yaml'
|
53
55
|
require 'rsmp/convert/export/json_schema'
|
data/rsmp.gemspec
CHANGED
@@ -34,7 +34,7 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.add_dependency "async-io", "~> 1.33.0"
|
35
35
|
spec.add_dependency "colorize", "~> 0.8.1"
|
36
36
|
spec.add_dependency "thor", "~> 1.2.1"
|
37
|
-
spec.add_dependency "rsmp_schema", "~> 0.
|
37
|
+
spec.add_dependency "rsmp_schema", "~> 0.3.1"
|
38
38
|
|
39
39
|
spec.add_development_dependency "bundler", "~> 2.3.7"
|
40
40
|
spec.add_development_dependency "rake", "~> 13.0.6"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rsmp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.15.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Emil Tin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async
|
@@ -72,14 +72,14 @@ dependencies:
|
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 0.
|
75
|
+
version: 0.3.1
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 0.
|
82
|
+
version: 0.3.1
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: bundler
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -211,6 +211,7 @@ files:
|
|
211
211
|
- lib/rsmp/alarm_state.rb
|
212
212
|
- lib/rsmp/archive.rb
|
213
213
|
- lib/rsmp/cli.rb
|
214
|
+
- lib/rsmp/collect/ack_collector.rb
|
214
215
|
- lib/rsmp/collect/aggregated_status_collector.rb
|
215
216
|
- lib/rsmp/collect/alarm_collector.rb
|
216
217
|
- lib/rsmp/collect/alarm_query.rb
|
@@ -249,6 +250,7 @@ files:
|
|
249
250
|
- lib/rsmp/tlc/inputs.rb
|
250
251
|
- lib/rsmp/tlc/signal_group.rb
|
251
252
|
- lib/rsmp/tlc/signal_plan.rb
|
253
|
+
- lib/rsmp/tlc/signal_priority.rb
|
252
254
|
- lib/rsmp/tlc/traffic_controller.rb
|
253
255
|
- lib/rsmp/tlc/traffic_controller_site.rb
|
254
256
|
- lib/rsmp/version.rb
|