rsmp 0.48.3 → 0.51.0
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/CHANGELOG.md +6 -0
- data/Gemfile.lock +19 -20
- data/README.md +27 -3
- data/Rakefile +3 -1
- data/documentation/cli.md +79 -4
- data/documentation/collecting_message.md +90 -170
- data/documentation/message_distribution.md +17 -3
- data/documentation/tasks.md +65 -117
- data/lib/rsmp/cli.rb +93 -5
- data/lib/rsmp/collect/collector.rb +117 -134
- data/lib/rsmp/collect/distributor.rb +16 -3
- data/lib/rsmp/collect/queue.rb +14 -6
- data/lib/rsmp/collect/receiver.rb +1 -1
- data/lib/rsmp/collect/state_collector.rb +11 -2
- data/lib/rsmp/collection.rb +12 -0
- data/lib/rsmp/completion.rb +49 -0
- data/lib/rsmp/component/component_base.rb +3 -3
- data/lib/rsmp/convert/export/json_schema/index.rb +8 -3
- data/lib/rsmp/convert/import/yaml.rb +12 -8
- data/lib/rsmp/delivery.rb +18 -0
- data/lib/rsmp/event.rb +19 -0
- data/lib/rsmp/event_source.rb +36 -0
- data/lib/rsmp/exchange.rb +10 -0
- data/lib/rsmp/failure.rb +23 -0
- data/lib/rsmp/helpers/error.rb +14 -23
- data/lib/rsmp/message.rb +9 -7
- data/lib/rsmp/node/node.rb +3 -21
- data/lib/rsmp/node/site/connections.rb +4 -9
- data/lib/rsmp/node/site/site.rb +31 -16
- data/lib/rsmp/node/supervisor/modules/connection.rb +19 -5
- data/lib/rsmp/node/supervisor/modules/sites.rb +16 -5
- data/lib/rsmp/node/supervisor/supervisor.rb +13 -14
- data/lib/rsmp/node/task.rb +59 -53
- data/lib/rsmp/proxy/modules/acknowledgements.rb +22 -9
- data/lib/rsmp/proxy/modules/lifecycle.rb +134 -0
- data/lib/rsmp/proxy/modules/receive.rb +109 -66
- data/lib/rsmp/proxy/modules/send.rb +109 -51
- data/lib/rsmp/proxy/modules/state.rb +15 -5
- data/lib/rsmp/proxy/modules/tasks.rb +96 -70
- data/lib/rsmp/proxy/modules/versions.rb +8 -8
- data/lib/rsmp/proxy/modules/watchdogs.rb +15 -2
- data/lib/rsmp/proxy/proxy.rb +4 -66
- data/lib/rsmp/proxy/site/connection.rb +27 -22
- data/lib/rsmp/proxy/site/modules/aggregated_status.rb +18 -8
- data/lib/rsmp/proxy/site/modules/alarms.rb +45 -38
- data/lib/rsmp/proxy/site/modules/commands.rb +18 -8
- data/lib/rsmp/proxy/site/modules/status.rb +44 -19
- data/lib/rsmp/proxy/site/site_proxy.rb +12 -10
- data/lib/rsmp/proxy/supervisor/modules/aggregated_status.rb +1 -1
- data/lib/rsmp/proxy/supervisor/modules/alarms.rb +1 -1
- data/lib/rsmp/proxy/supervisor/modules/commands.rb +1 -1
- data/lib/rsmp/proxy/supervisor/modules/message_buffer.rb +8 -9
- data/lib/rsmp/proxy/supervisor/modules/status.rb +1 -1
- data/lib/rsmp/proxy/supervisor/modules/status_updates.rb +1 -1
- data/lib/rsmp/proxy/supervisor/supervisor_proxy.rb +34 -30
- data/lib/rsmp/result.rb +95 -0
- data/lib/rsmp/schema/validation.rb +5 -3
- data/lib/rsmp/sxl/interface.rb +8 -1
- data/lib/rsmp/sxl/processing/catalogue.rb +61 -0
- data/lib/rsmp/sxl/processing/conflict_checker.rb +30 -0
- data/lib/rsmp/sxl/processing/dependency_graph.rb +37 -0
- data/lib/rsmp/sxl/processing/document.rb +158 -0
- data/lib/rsmp/sxl/processing/error.rb +8 -0
- data/lib/rsmp/sxl/processing/manifest.rb +144 -0
- data/lib/rsmp/sxl/processing/natural_sort.rb +22 -0
- data/lib/rsmp/sxl/processing/resolver.rb +94 -0
- data/lib/rsmp/sxl/processing/version_requirement.rb +86 -0
- data/lib/rsmp/sxl/processing.rb +18 -0
- data/lib/rsmp/sxl/supervisor_interface.rb +8 -1
- data/lib/rsmp/termination.rb +10 -0
- data/lib/rsmp/tlc/modules/plans.rb +0 -2
- data/lib/rsmp/tlc/proxy/control.rb +50 -16
- data/lib/rsmp/tlc/proxy/detectors.rb +15 -4
- data/lib/rsmp/tlc/proxy/io.rb +46 -31
- data/lib/rsmp/tlc/proxy/plans.rb +36 -19
- data/lib/rsmp/tlc/proxy/plans_bang.rb +44 -0
- data/lib/rsmp/tlc/proxy/status.rb +47 -23
- data/lib/rsmp/tlc/proxy/system.rb +16 -4
- data/lib/rsmp/tlc/supervisor_interface.rb +7 -1
- data/lib/rsmp/tlc/traffic_controller_site.rb +6 -9
- data/lib/rsmp/validation.rb +22 -0
- data/lib/rsmp/version.rb +1 -1
- data/lib/rsmp.rb +19 -4
- data/rsmp.gemspec +1 -1
- data/schemas/tlc/1.0.10/commands/M0001.json +3 -3
- data/schemas/tlc/1.0.10/source/sxl.yaml +3 -3
- data/schemas/tlc/1.0.10/sxl_index.json +3 -3
- data/schemas/tlc/1.0.13/commands/M0001.json +3 -3
- data/schemas/tlc/1.0.13/source/sxl.yaml +3 -3
- data/schemas/tlc/1.0.13/sxl_index.json +3 -3
- data/schemas/tlc/1.0.14/commands/M0001.json +3 -3
- data/schemas/tlc/1.0.14/source/sxl.yaml +3 -3
- data/schemas/tlc/1.0.14/sxl_index.json +3 -3
- data/schemas/tlc/1.0.15/commands/M0001.json +3 -3
- data/schemas/tlc/1.0.15/source/sxl.yaml +3 -3
- data/schemas/tlc/1.0.15/sxl_index.json +3 -3
- data/schemas/tlc/1.0.7/commands/M0001.json +3 -3
- data/schemas/tlc/1.0.7/source/sxl.yaml +3 -3
- data/schemas/tlc/1.0.7/sxl_index.json +3 -3
- data/schemas/tlc/1.0.8/commands/M0001.json +3 -3
- data/schemas/tlc/1.0.8/source/sxl.yaml +3 -3
- data/schemas/tlc/1.0.8/sxl_index.json +3 -3
- data/schemas/tlc/1.0.9/commands/M0001.json +3 -3
- data/schemas/tlc/1.0.9/source/sxl.yaml +3 -3
- data/schemas/tlc/1.0.9/sxl_index.json +3 -3
- metadata +25 -4
- data/lib/rsmp/collect/collector/status.rb +0 -34
|
@@ -6,20 +6,29 @@ module RSMP
|
|
|
6
6
|
module Control
|
|
7
7
|
# M0001 - Set functional position (NormalControl, YellowFlash, Dark).
|
|
8
8
|
def set_functional_position(status, within:, timeout_minutes: 0)
|
|
9
|
-
validate_ready 'set functional position'
|
|
9
|
+
readiness = validate_ready 'set functional position'
|
|
10
|
+
return readiness if readiness.failure?
|
|
11
|
+
|
|
10
12
|
raise 'TLC main component not found' unless main
|
|
11
13
|
|
|
12
14
|
command_list = functional_position_command_list(status, timeout_minutes)
|
|
13
15
|
confirm_status = functional_position_confirm_status(status)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
send_command_and_collect(command_list, within: within).and_then do |exchange|
|
|
17
|
+
next Result.success(exchange) if confirm_status.empty?
|
|
18
|
+
|
|
19
|
+
wait_for_status("functional position #{status}", confirm_status, timeout: within).map { exchange }
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def set_functional_position!(...)
|
|
24
|
+
set_functional_position(...).value!
|
|
18
25
|
end
|
|
19
26
|
|
|
20
27
|
# M0005 - Set or clear an emergency route.
|
|
21
28
|
def set_emergency_route(route:, active:, within:)
|
|
22
|
-
validate_ready 'set emergency route'
|
|
29
|
+
readiness = validate_ready 'set emergency route'
|
|
30
|
+
return readiness if readiness.failure?
|
|
31
|
+
|
|
23
32
|
raise 'TLC main component not found' unless main
|
|
24
33
|
|
|
25
34
|
security_code = security_code_for(2)
|
|
@@ -41,12 +50,18 @@ module RSMP
|
|
|
41
50
|
'v' => command_value('M0005', 'emergencyroute', route)
|
|
42
51
|
}]
|
|
43
52
|
|
|
44
|
-
send_command_and_collect(command_list, within: within)
|
|
53
|
+
send_command_and_collect(command_list, within: within)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def set_emergency_route!(...)
|
|
57
|
+
set_emergency_route(...).value!
|
|
45
58
|
end
|
|
46
59
|
|
|
47
60
|
# M0007 - Enable or disable fixed-time control.
|
|
48
61
|
def set_fixed_time(status, within:)
|
|
49
|
-
validate_ready 'set fixed time'
|
|
62
|
+
readiness = validate_ready 'set fixed time'
|
|
63
|
+
return readiness if readiness.failure?
|
|
64
|
+
|
|
50
65
|
raise 'TLC main component not found' unless main
|
|
51
66
|
|
|
52
67
|
security_code = security_code_for(2)
|
|
@@ -64,13 +79,20 @@ module RSMP
|
|
|
64
79
|
}]
|
|
65
80
|
|
|
66
81
|
confirm_status = [{ 'sCI' => 'S0009', 'n' => 'status', 's' => [boolean_value(status)] }]
|
|
67
|
-
send_command_and_collect(command_list, within: within).
|
|
68
|
-
|
|
82
|
+
send_command_and_collect(command_list, within: within).and_then do |exchange|
|
|
83
|
+
wait_for_status("fixed time #{status}", confirm_status, timeout: within).map { exchange }
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def set_fixed_time!(...)
|
|
88
|
+
set_fixed_time(...).value!
|
|
69
89
|
end
|
|
70
90
|
|
|
71
91
|
# M0003 - Set traffic situation (activate a specific situation number).
|
|
72
92
|
def set_traffic_situation(situation, within:)
|
|
73
|
-
validate_ready 'set traffic situation'
|
|
93
|
+
readiness = validate_ready 'set traffic situation'
|
|
94
|
+
return readiness if readiness.failure?
|
|
95
|
+
|
|
74
96
|
raise 'TLC main component not found' unless main
|
|
75
97
|
|
|
76
98
|
security_code = security_code_for(2)
|
|
@@ -93,13 +115,20 @@ module RSMP
|
|
|
93
115
|
}]
|
|
94
116
|
|
|
95
117
|
confirm_status = [{ 'sCI' => 'S0015', 'n' => 'status', 's' => integer_value(situation) }]
|
|
96
|
-
send_command_and_collect(command_list, within: within).
|
|
97
|
-
|
|
118
|
+
send_command_and_collect(command_list, within: within).and_then do |exchange|
|
|
119
|
+
wait_for_status("traffic situation #{situation}", confirm_status, timeout: within).map { exchange }
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def set_traffic_situation!(...)
|
|
124
|
+
set_traffic_situation(...).value!
|
|
98
125
|
end
|
|
99
126
|
|
|
100
127
|
# M0003 - Clear the active traffic situation.
|
|
101
128
|
def unset_traffic_situation(within:)
|
|
102
|
-
validate_ready 'unset traffic situation'
|
|
129
|
+
readiness = validate_ready 'unset traffic situation'
|
|
130
|
+
return readiness if readiness.failure?
|
|
131
|
+
|
|
103
132
|
raise 'TLC main component not found' unless main
|
|
104
133
|
|
|
105
134
|
security_code = security_code_for(2)
|
|
@@ -122,8 +151,13 @@ module RSMP
|
|
|
122
151
|
}]
|
|
123
152
|
|
|
124
153
|
confirm_status = [{ 'sCI' => 'S0015', 'n' => 'status', 's' => 1 }]
|
|
125
|
-
send_command_and_collect(command_list, within: within).
|
|
126
|
-
|
|
154
|
+
send_command_and_collect(command_list, within: within).and_then do |exchange|
|
|
155
|
+
wait_for_status('traffic situation unset', confirm_status, timeout: within).map { exchange }
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def unset_traffic_situation!(...)
|
|
160
|
+
unset_traffic_situation(...).value!
|
|
127
161
|
end
|
|
128
162
|
|
|
129
163
|
private
|
|
@@ -7,7 +7,8 @@ module RSMP
|
|
|
7
7
|
# M0008 - Force detector logic to a given mode and status.
|
|
8
8
|
# component_id must refer to the detector logic component, not main.
|
|
9
9
|
def force_detector_logic(component_id, status:, mode:, within:)
|
|
10
|
-
validate_ready 'force detector logic'
|
|
10
|
+
readiness = validate_ready 'force detector logic'
|
|
11
|
+
return readiness if readiness.failure?
|
|
11
12
|
|
|
12
13
|
security_code = security_code_for(2)
|
|
13
14
|
|
|
@@ -27,12 +28,18 @@ module RSMP
|
|
|
27
28
|
'n' => 'mode',
|
|
28
29
|
'v' => command_value('M0008', 'mode', mode)
|
|
29
30
|
}]
|
|
30
|
-
send_command_and_collect(command_list, component: component_id, within: within)
|
|
31
|
+
send_command_and_collect(command_list, component: component_id, within: within)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def force_detector_logic!(...)
|
|
35
|
+
force_detector_logic(...).value!
|
|
31
36
|
end
|
|
32
37
|
|
|
33
38
|
# M0021 - Set the trigger level for traffic counting.
|
|
34
39
|
def set_trigger_level(status, within:)
|
|
35
|
-
validate_ready 'set trigger level'
|
|
40
|
+
readiness = validate_ready 'set trigger level'
|
|
41
|
+
return readiness if readiness.failure?
|
|
42
|
+
|
|
36
43
|
raise 'TLC main component not found' unless main
|
|
37
44
|
|
|
38
45
|
security_code = security_code_for(2)
|
|
@@ -48,7 +55,11 @@ module RSMP
|
|
|
48
55
|
'n' => 'securityCode',
|
|
49
56
|
'v' => security_code.to_s
|
|
50
57
|
}]
|
|
51
|
-
send_command_and_collect(command_list, within: within)
|
|
58
|
+
send_command_and_collect(command_list, within: within)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def set_trigger_level!(...)
|
|
62
|
+
set_trigger_level(...).value!
|
|
52
63
|
end
|
|
53
64
|
end
|
|
54
65
|
end
|
data/lib/rsmp/tlc/proxy/io.rb
CHANGED
|
@@ -6,7 +6,9 @@ module RSMP
|
|
|
6
6
|
module IO
|
|
7
7
|
# M0006 - Set a single input to a given status.
|
|
8
8
|
def set_input(input:, status:, within:)
|
|
9
|
-
validate_ready 'set input'
|
|
9
|
+
readiness = validate_ready 'set input'
|
|
10
|
+
return readiness if readiness.failure?
|
|
11
|
+
|
|
10
12
|
raise 'TLC main component not found' unless main
|
|
11
13
|
|
|
12
14
|
security_code = security_code_for(2)
|
|
@@ -27,12 +29,18 @@ module RSMP
|
|
|
27
29
|
'n' => 'input',
|
|
28
30
|
'v' => command_value('M0006', 'input', input)
|
|
29
31
|
}]
|
|
30
|
-
send_command_and_collect(command_list, within: within)
|
|
32
|
+
send_command_and_collect(command_list, within: within)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def set_input!(...)
|
|
36
|
+
set_input(...).value!
|
|
31
37
|
end
|
|
32
38
|
|
|
33
39
|
# M0013 - Set all inputs via a bit-pattern string.
|
|
34
40
|
def set_inputs(status, within:)
|
|
35
|
-
validate_ready 'set inputs'
|
|
41
|
+
readiness = validate_ready 'set inputs'
|
|
42
|
+
return readiness if readiness.failure?
|
|
43
|
+
|
|
36
44
|
raise 'TLC main component not found' unless main
|
|
37
45
|
|
|
38
46
|
security_code = security_code_for(2)
|
|
@@ -48,53 +56,60 @@ module RSMP
|
|
|
48
56
|
'n' => 'securityCode',
|
|
49
57
|
'v' => security_code.to_s
|
|
50
58
|
}]
|
|
51
|
-
send_command_and_collect(command_list, within: within)
|
|
59
|
+
send_command_and_collect(command_list, within: within)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def set_inputs!(...)
|
|
63
|
+
set_inputs(...).value!
|
|
52
64
|
end
|
|
53
65
|
|
|
54
66
|
# M0019 - Force an input to a given value.
|
|
55
67
|
def force_input(input:, status:, value:, within:)
|
|
56
|
-
validate_ready 'force input'
|
|
68
|
+
readiness = validate_ready 'force input'
|
|
69
|
+
return readiness if readiness.failure?
|
|
70
|
+
|
|
57
71
|
raise 'TLC main component not found' unless main
|
|
58
72
|
|
|
59
73
|
command_list = force_input_command_list(input, status, value)
|
|
60
74
|
confirm_status = force_input_confirm_status(input, status, value)
|
|
61
|
-
send_command_and_collect(command_list, within: within).
|
|
62
|
-
|
|
75
|
+
send_command_and_collect(command_list, within: within).and_then do |exchange|
|
|
76
|
+
wait_for_status("force input #{input}", confirm_status, timeout: within).map { exchange }
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def force_input!(...)
|
|
81
|
+
force_input(...).value!
|
|
63
82
|
end
|
|
64
83
|
|
|
65
84
|
# M0020 - Force an output to a given value.
|
|
66
85
|
def force_output(output:, status:, value:, within:)
|
|
67
|
-
validate_ready 'force output'
|
|
86
|
+
readiness = validate_ready 'force output'
|
|
87
|
+
return readiness if readiness.failure?
|
|
88
|
+
|
|
68
89
|
raise 'TLC main component not found' unless main
|
|
69
90
|
|
|
70
|
-
|
|
91
|
+
send_command_and_collect(force_output_command_list(output, status, value), within: within)
|
|
92
|
+
end
|
|
71
93
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
'cO' => 'setOutput',
|
|
75
|
-
'n' => 'status',
|
|
76
|
-
'v' => command_value('M0020', 'status', status)
|
|
77
|
-
}, {
|
|
78
|
-
'cCI' => 'M0020',
|
|
79
|
-
'cO' => 'setOutput',
|
|
80
|
-
'n' => 'securityCode',
|
|
81
|
-
'v' => security_code.to_s
|
|
82
|
-
}, {
|
|
83
|
-
'cCI' => 'M0020',
|
|
84
|
-
'cO' => 'setOutput',
|
|
85
|
-
'n' => 'output',
|
|
86
|
-
'v' => command_value('M0020', 'output', output)
|
|
87
|
-
}, {
|
|
88
|
-
'cCI' => 'M0020',
|
|
89
|
-
'cO' => 'setOutput',
|
|
90
|
-
'n' => 'outputValue',
|
|
91
|
-
'v' => command_value('M0020', 'outputValue', value)
|
|
92
|
-
}]
|
|
93
|
-
send_command_and_collect(command_list, within: within).ok!
|
|
94
|
+
def force_output!(...)
|
|
95
|
+
force_output(...).value!
|
|
94
96
|
end
|
|
95
97
|
|
|
96
98
|
private
|
|
97
99
|
|
|
100
|
+
def force_output_command_list(output, status, value)
|
|
101
|
+
security_code = security_code_for(2)
|
|
102
|
+
values = { 'status' => status, 'output' => output, 'outputValue' => value }
|
|
103
|
+
values.map do |name, item|
|
|
104
|
+
{ 'cCI' => 'M0020', 'cO' => 'setOutput', 'n' => name, 'v' => command_value('M0020', name, item) }
|
|
105
|
+
end.insert(1, {
|
|
106
|
+
'cCI' => 'M0020',
|
|
107
|
+
'cO' => 'setOutput',
|
|
108
|
+
'n' => 'securityCode',
|
|
109
|
+
'v' => security_code.to_s
|
|
110
|
+
})
|
|
111
|
+
end
|
|
112
|
+
|
|
98
113
|
def force_input_command_list(input, status, value)
|
|
99
114
|
security_code = security_code_for(2)
|
|
100
115
|
[
|
data/lib/rsmp/tlc/proxy/plans.rb
CHANGED
|
@@ -6,7 +6,9 @@ module RSMP
|
|
|
6
6
|
module Plans
|
|
7
7
|
# M0014 - Set dynamic bands for a signal plan.
|
|
8
8
|
def set_dynamic_bands(plan:, status:, within:)
|
|
9
|
-
validate_ready 'set dynamic bands'
|
|
9
|
+
readiness = validate_ready 'set dynamic bands'
|
|
10
|
+
return readiness if readiness.failure?
|
|
11
|
+
|
|
10
12
|
raise 'TLC main component not found' unless main
|
|
11
13
|
|
|
12
14
|
security_code = security_code_for(2)
|
|
@@ -27,12 +29,14 @@ module RSMP
|
|
|
27
29
|
'n' => 'plan',
|
|
28
30
|
'v' => command_value('M0014', 'plan', plan)
|
|
29
31
|
}]
|
|
30
|
-
send_command_and_collect(command_list, within: within)
|
|
32
|
+
send_command_and_collect(command_list, within: within)
|
|
31
33
|
end
|
|
32
34
|
|
|
33
35
|
# M0023 - Set timeout for dynamic bands.
|
|
34
36
|
def set_dynamic_bands_timeout(status, within:)
|
|
35
|
-
validate_ready 'set dynamic bands timeout'
|
|
37
|
+
readiness = validate_ready 'set dynamic bands timeout'
|
|
38
|
+
return readiness if readiness.failure?
|
|
39
|
+
|
|
36
40
|
raise 'TLC main component not found' unless main
|
|
37
41
|
|
|
38
42
|
security_code = security_code_for(2)
|
|
@@ -48,12 +52,14 @@ module RSMP
|
|
|
48
52
|
'n' => 'securityCode',
|
|
49
53
|
'v' => security_code.to_s
|
|
50
54
|
}]
|
|
51
|
-
send_command_and_collect(command_list, within: within)
|
|
55
|
+
send_command_and_collect(command_list, within: within)
|
|
52
56
|
end
|
|
53
57
|
|
|
54
58
|
# M0015 - Set offset for a signal plan.
|
|
55
59
|
def set_offset(plan:, offset:, within:)
|
|
56
|
-
validate_ready 'set offset'
|
|
60
|
+
readiness = validate_ready 'set offset'
|
|
61
|
+
return readiness if readiness.failure?
|
|
62
|
+
|
|
57
63
|
raise 'TLC main component not found' unless main
|
|
58
64
|
|
|
59
65
|
security_code = security_code_for(2)
|
|
@@ -74,12 +80,14 @@ module RSMP
|
|
|
74
80
|
'n' => 'plan',
|
|
75
81
|
'v' => command_value('M0015', 'plan', plan)
|
|
76
82
|
}]
|
|
77
|
-
send_command_and_collect(command_list, within: within)
|
|
83
|
+
send_command_and_collect(command_list, within: within)
|
|
78
84
|
end
|
|
79
85
|
|
|
80
86
|
# Set the timeplan (signal plan) on the remote TLC.
|
|
81
87
|
def set_timeplan(plan_nr, within:)
|
|
82
|
-
validate_ready 'set timeplan'
|
|
88
|
+
readiness = validate_ready 'set timeplan'
|
|
89
|
+
return readiness if readiness.failure?
|
|
90
|
+
|
|
83
91
|
raise 'TLC main component not found' unless main
|
|
84
92
|
|
|
85
93
|
security_code = security_code_for(2)
|
|
@@ -101,13 +109,16 @@ module RSMP
|
|
|
101
109
|
'v' => command_value('M0002', 'timeplan', plan_nr)
|
|
102
110
|
}]
|
|
103
111
|
confirm_status = [{ 'sCI' => 'S0014', 'n' => 'status', 's' => integer_value(plan_nr) }]
|
|
104
|
-
send_command_and_collect(command_list, within: within).
|
|
105
|
-
|
|
112
|
+
send_command_and_collect(command_list, within: within).and_then do |exchange|
|
|
113
|
+
wait_for_status("timeplan #{plan_nr}", confirm_status, timeout: within).map { exchange }
|
|
114
|
+
end
|
|
106
115
|
end
|
|
107
116
|
|
|
108
117
|
# M0016 - Set week table (mapping week days to traffic situations).
|
|
109
118
|
def set_week_table(status, within:)
|
|
110
|
-
validate_ready 'set week table'
|
|
119
|
+
readiness = validate_ready 'set week table'
|
|
120
|
+
return readiness if readiness.failure?
|
|
121
|
+
|
|
111
122
|
raise 'TLC main component not found' unless main
|
|
112
123
|
|
|
113
124
|
security_code = security_code_for(2)
|
|
@@ -123,12 +134,14 @@ module RSMP
|
|
|
123
134
|
'n' => 'securityCode',
|
|
124
135
|
'v' => security_code.to_s
|
|
125
136
|
}]
|
|
126
|
-
send_command_and_collect(command_list, within:)
|
|
137
|
+
send_command_and_collect(command_list, within:)
|
|
127
138
|
end
|
|
128
139
|
|
|
129
140
|
# M0017 - Set day table (mapping time periods to signal plans).
|
|
130
141
|
def set_day_table(status, within:)
|
|
131
|
-
validate_ready 'set day table'
|
|
142
|
+
readiness = validate_ready 'set day table'
|
|
143
|
+
return readiness if readiness.failure?
|
|
144
|
+
|
|
132
145
|
raise 'TLC main component not found' unless main
|
|
133
146
|
|
|
134
147
|
security_code = security_code_for(2)
|
|
@@ -144,12 +157,14 @@ module RSMP
|
|
|
144
157
|
'n' => 'securityCode',
|
|
145
158
|
'v' => security_code.to_s
|
|
146
159
|
}]
|
|
147
|
-
send_command_and_collect(command_list, within:)
|
|
160
|
+
send_command_and_collect(command_list, within:)
|
|
148
161
|
end
|
|
149
162
|
|
|
150
163
|
# M0018 - Set cycle time for a signal plan.
|
|
151
164
|
def set_cycle_time(plan:, cycle_time:, within:)
|
|
152
|
-
validate_ready 'set cycle time'
|
|
165
|
+
readiness = validate_ready 'set cycle time'
|
|
166
|
+
return readiness if readiness.failure?
|
|
167
|
+
|
|
153
168
|
raise 'TLC main component not found' unless main
|
|
154
169
|
|
|
155
170
|
security_code = security_code_for(2)
|
|
@@ -170,12 +185,13 @@ module RSMP
|
|
|
170
185
|
'n' => 'plan',
|
|
171
186
|
'v' => command_value('M0018', 'plan', plan)
|
|
172
187
|
}]
|
|
173
|
-
send_command_and_collect(command_list, within:)
|
|
188
|
+
send_command_and_collect(command_list, within:)
|
|
174
189
|
end
|
|
175
190
|
|
|
176
191
|
# M0010 - Order signal start for a signal group component.
|
|
177
192
|
def order_signal_start(component_id, within:)
|
|
178
|
-
validate_ready 'order signal start'
|
|
193
|
+
readiness = validate_ready 'order signal start'
|
|
194
|
+
return readiness if readiness.failure?
|
|
179
195
|
|
|
180
196
|
security_code = security_code_for(2)
|
|
181
197
|
|
|
@@ -190,12 +206,13 @@ module RSMP
|
|
|
190
206
|
'n' => 'securityCode',
|
|
191
207
|
'v' => security_code.to_s
|
|
192
208
|
}]
|
|
193
|
-
send_command_and_collect(command_list, component: component_id, within:)
|
|
209
|
+
send_command_and_collect(command_list, component: component_id, within:)
|
|
194
210
|
end
|
|
195
211
|
|
|
196
212
|
# M0011 - Order signal stop for a signal group component.
|
|
197
213
|
def order_signal_stop(component_id, within:)
|
|
198
|
-
validate_ready 'order signal stop'
|
|
214
|
+
readiness = validate_ready 'order signal stop'
|
|
215
|
+
return readiness if readiness.failure?
|
|
199
216
|
|
|
200
217
|
security_code = security_code_for(2)
|
|
201
218
|
|
|
@@ -210,7 +227,7 @@ module RSMP
|
|
|
210
227
|
'n' => 'securityCode',
|
|
211
228
|
'v' => security_code.to_s
|
|
212
229
|
}]
|
|
213
|
-
send_command_and_collect(command_list, component: component_id, within:)
|
|
230
|
+
send_command_and_collect(command_list, component: component_id, within:)
|
|
214
231
|
end
|
|
215
232
|
end
|
|
216
233
|
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module RSMP
|
|
2
|
+
module TLC
|
|
3
|
+
module Proxy
|
|
4
|
+
# Explicit exception-raising variants of finite plan operations.
|
|
5
|
+
module PlansBang
|
|
6
|
+
def set_dynamic_bands!(...)
|
|
7
|
+
set_dynamic_bands(...).value!
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def set_dynamic_bands_timeout!(...)
|
|
11
|
+
set_dynamic_bands_timeout(...).value!
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def set_offset!(...)
|
|
15
|
+
set_offset(...).value!
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def set_timeplan!(...)
|
|
19
|
+
set_timeplan(...).value!
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def set_week_table!(...)
|
|
23
|
+
set_week_table(...).value!
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def set_day_table!(...)
|
|
27
|
+
set_day_table(...).value!
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def set_cycle_time!(...)
|
|
31
|
+
set_cycle_time(...).value!
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def order_signal_start!(...)
|
|
35
|
+
order_signal_start(...).value!
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def order_signal_stop!(...)
|
|
39
|
+
order_signal_stop(...).value!
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -4,25 +4,28 @@ module RSMP
|
|
|
4
4
|
# Status reading and waiting methods for a remote TLC.
|
|
5
5
|
# Covers status subscriptions, group waits, and plan/band reading.
|
|
6
6
|
module Status
|
|
7
|
-
# Fetch the current signal plan from the remote TLC.
|
|
7
|
+
# Fetch the current signal plan from the remote TLC. Returns Result<Hash>.
|
|
8
8
|
def fetch_signal_plan(options: {})
|
|
9
|
-
validate_ready 'fetch signal plan'
|
|
10
9
|
timeout = options[:timeout] || @timeouts['status_response']
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
request_status_and_collect({ S0014: %i[status source] }, within: timeout).map do |exchange|
|
|
11
|
+
exchange.collection.messages.last.attributes['sS'].to_h do |item|
|
|
12
|
+
[item['n'], item['s']]
|
|
13
|
+
end
|
|
15
14
|
end
|
|
16
15
|
end
|
|
17
16
|
|
|
17
|
+
def fetch_signal_plan!(...)
|
|
18
|
+
fetch_signal_plan(...).value!
|
|
19
|
+
end
|
|
20
|
+
|
|
18
21
|
# Subscribe to one or more statuses and wait until they match the expected values.
|
|
19
|
-
# Raises RSMP::TimeoutError if the values don't match within the timeout.
|
|
20
|
-
#
|
|
21
22
|
# status_list items: { 'sCI' => ..., 'n' => ..., 's' => <expected value or Regexp> }
|
|
22
23
|
# component_id defaults to the main TLC component.
|
|
23
24
|
# timeout defaults to @timeouts['command'].
|
|
24
25
|
def wait_for_status(description, status_list, update_rate: 0, timeout: nil, component_id: nil)
|
|
25
|
-
validate_ready 'wait for status'
|
|
26
|
+
readiness = validate_ready 'wait for status'
|
|
27
|
+
return readiness if readiness.failure?
|
|
28
|
+
|
|
26
29
|
component_id ||= main.c_id
|
|
27
30
|
timeout ||= @timeouts['command']
|
|
28
31
|
|
|
@@ -35,13 +38,17 @@ module RSMP
|
|
|
35
38
|
log "Wait for #{description}", level: :debug
|
|
36
39
|
|
|
37
40
|
begin
|
|
38
|
-
subscribe_to_status_and_collect(subscribe_list, component: component_id, within: timeout)
|
|
41
|
+
subscribe_to_status_and_collect(subscribe_list, component: component_id, within: timeout)
|
|
39
42
|
ensure
|
|
40
43
|
unsubscribe_list = status_list.map { |item| item.slice('sCI', 'n') }
|
|
41
44
|
unsubscribe_to_status unsubscribe_list, component: component_id
|
|
42
45
|
end
|
|
43
46
|
end
|
|
44
47
|
|
|
48
|
+
def wait_for_status!(...)
|
|
49
|
+
wait_for_status(...).value!
|
|
50
|
+
end
|
|
51
|
+
|
|
45
52
|
# Wait for all signal groups to match state (as regex string, e.g. 'c' for yellow flash).
|
|
46
53
|
def wait_for_groups(state, timeout:)
|
|
47
54
|
regex = /^#{state}+$/
|
|
@@ -52,6 +59,10 @@ module RSMP
|
|
|
52
59
|
)
|
|
53
60
|
end
|
|
54
61
|
|
|
62
|
+
def wait_for_groups!(...)
|
|
63
|
+
wait_for_groups(...).value!
|
|
64
|
+
end
|
|
65
|
+
|
|
55
66
|
# Wait for the TLC to return to normal control mode (functional position NormalControl,
|
|
56
67
|
# yellow flash off, startup mode off).
|
|
57
68
|
def wait_for_normal_control(timeout: nil)
|
|
@@ -66,36 +77,49 @@ module RSMP
|
|
|
66
77
|
)
|
|
67
78
|
end
|
|
68
79
|
|
|
80
|
+
def wait_for_normal_control!(...)
|
|
81
|
+
wait_for_normal_control(...).value!
|
|
82
|
+
end
|
|
83
|
+
|
|
69
84
|
# Read cycle times for all plans via S0028.
|
|
70
85
|
# Returns a hash of plan_nr (Integer) => cycle_time (Integer, seconds).
|
|
71
86
|
def read_cycle_times(options: {})
|
|
72
|
-
validate_ready 'read cycle times'
|
|
73
87
|
timeout = options[:timeout] || @timeouts['status_response']
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
88
|
+
request_status_and_collect({ S0028: [:status] }, within: timeout).map do |exchange|
|
|
89
|
+
status_items(exchange.collection.messages.first.attributes['sS'].first['s']).to_h do |item|
|
|
90
|
+
item.split('-').map(&:to_i)
|
|
91
|
+
end
|
|
78
92
|
end
|
|
79
93
|
end
|
|
80
94
|
|
|
95
|
+
def read_cycle_times!(...)
|
|
96
|
+
read_cycle_times(...).value!
|
|
97
|
+
end
|
|
98
|
+
|
|
81
99
|
# Read the current signal plan number via S0014.
|
|
82
100
|
# Returns the plan number as an Integer.
|
|
83
101
|
def read_current_plan(options: {})
|
|
84
|
-
validate_ready 'read current plan'
|
|
85
102
|
timeout = options[:timeout] || @timeouts['status_response']
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
103
|
+
request_status_and_collect({ S0014: [:status] }, within: timeout).map do |exchange|
|
|
104
|
+
exchange.collection.messages.first.attributes['sS'].first['s'].to_i
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def read_current_plan!(...)
|
|
109
|
+
read_current_plan(...).value!
|
|
89
110
|
end
|
|
90
111
|
|
|
91
112
|
# Read the value of a single dynamic band for a given plan and band index via S0023.
|
|
92
113
|
# Returns the band value as an Integer, or nil if not found.
|
|
93
114
|
def read_dynamic_band(plan:, band:, options: {})
|
|
94
|
-
validate_ready 'read dynamic band'
|
|
95
115
|
timeout = options[:timeout] || @timeouts['status_response']
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
116
|
+
request_status_and_collect({ S0023: [:status] }, within: timeout).map do |exchange|
|
|
117
|
+
extract_band_value(exchange.collection, plan, band)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def read_dynamic_band!(...)
|
|
122
|
+
read_dynamic_band(...).value!
|
|
99
123
|
end
|
|
100
124
|
|
|
101
125
|
private
|
|
@@ -7,7 +7,9 @@ module RSMP
|
|
|
7
7
|
# M0103 - Change security code for a given level.
|
|
8
8
|
# Does not use security_code_for since the codes are passed explicitly.
|
|
9
9
|
def set_security_code(level:, old_code:, new_code:, within:)
|
|
10
|
-
validate_ready 'set security code'
|
|
10
|
+
readiness = validate_ready 'set security code'
|
|
11
|
+
return readiness if readiness.failure?
|
|
12
|
+
|
|
11
13
|
raise 'TLC main component not found' unless main
|
|
12
14
|
|
|
13
15
|
command_list = [{
|
|
@@ -26,15 +28,25 @@ module RSMP
|
|
|
26
28
|
'n' => 'newSecurityCode',
|
|
27
29
|
'v' => new_code.to_s
|
|
28
30
|
}]
|
|
29
|
-
send_command_and_collect(command_list, within: within)
|
|
31
|
+
send_command_and_collect(command_list, within: within)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def set_security_code!(...)
|
|
35
|
+
set_security_code(...).value!
|
|
30
36
|
end
|
|
31
37
|
|
|
32
38
|
# M0104 - Set the clock on the remote TLC. clock must respond to year/month/day/hour/min/sec.
|
|
33
39
|
def set_clock(clock, within:)
|
|
34
|
-
validate_ready 'set clock'
|
|
40
|
+
readiness = validate_ready 'set clock'
|
|
41
|
+
return readiness if readiness.failure?
|
|
42
|
+
|
|
35
43
|
raise 'TLC main component not found' unless main
|
|
36
44
|
|
|
37
|
-
send_command_and_collect(clock_command_list(clock), within: within)
|
|
45
|
+
send_command_and_collect(clock_command_list(clock), within: within)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def set_clock!(...)
|
|
49
|
+
set_clock(...).value!
|
|
38
50
|
end
|
|
39
51
|
|
|
40
52
|
private
|