rsmp 0.41.0 → 0.42.1
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/.github/workflows/{rspec.yaml → sus.yaml} +4 -4
- data/.rubocop.yml +10 -14
- data/Gemfile +3 -4
- data/Gemfile.lock +32 -37
- data/Rakefile +4 -3
- data/config/sus.rb +14 -0
- data/documentation/collecting_message.md +56 -41
- data/lib/rsmp/cli.rb +2 -1
- data/lib/rsmp/collect/collector.rb +3 -2
- data/lib/rsmp/command_list.rb +42 -0
- data/lib/rsmp/node/site/site.rb +2 -2
- data/lib/rsmp/proxy/modules/send.rb +8 -16
- data/lib/rsmp/proxy/site/modules/aggregated_status.rb +19 -8
- data/lib/rsmp/proxy/site/modules/commands.rb +22 -9
- data/lib/rsmp/proxy/site/modules/status.rb +74 -29
- data/lib/rsmp/proxy/supervisor/modules/aggregated_status.rb +3 -5
- data/lib/rsmp/proxy/supervisor/modules/alarms.rb +0 -6
- data/lib/rsmp/status_list.rb +44 -0
- data/lib/rsmp/tlc/modules/modes.rb +2 -2
- data/lib/rsmp/tlc/modules/system.rb +26 -12
- data/lib/rsmp/tlc/proxy/control.rb +16 -12
- data/lib/rsmp/tlc/proxy/detectors.rb +4 -6
- data/lib/rsmp/tlc/proxy/io.rb +18 -16
- data/lib/rsmp/tlc/proxy/plans.rb +21 -29
- data/lib/rsmp/tlc/proxy/status.rb +19 -26
- data/lib/rsmp/tlc/proxy/system.rb +4 -5
- data/lib/rsmp/tlc/traffic_controller_proxy.rb +2 -31
- data/lib/rsmp/version.rb +1 -1
- data/lib/rsmp.rb +2 -0
- metadata +5 -2
|
@@ -3,13 +3,17 @@ module RSMP
|
|
|
3
3
|
module Modules
|
|
4
4
|
# Handles status requests, responses, subscriptions and updates
|
|
5
5
|
module Status
|
|
6
|
-
|
|
6
|
+
# Build and send a StatusRequest. Returns { sent: message }.
|
|
7
|
+
def request_status(status_list, component: nil, m_id: nil, validate: true)
|
|
7
8
|
validate_ready 'request status'
|
|
8
|
-
|
|
9
|
+
component ||= main.c_id
|
|
10
|
+
m_id ||= RSMP::Message.make_m_id
|
|
11
|
+
|
|
12
|
+
list = RSMP::StatusList.new(status_list)
|
|
9
13
|
|
|
10
14
|
# additional items can be used when verifying the response,
|
|
11
15
|
# but must be removed from the request
|
|
12
|
-
request_list =
|
|
16
|
+
request_list = list.map { |item| item.slice('sCI', 'n') }
|
|
13
17
|
|
|
14
18
|
message = RSMP::StatusRequest.new({
|
|
15
19
|
'cId' => component,
|
|
@@ -17,13 +21,31 @@ module RSMP
|
|
|
17
21
|
'mId' => m_id
|
|
18
22
|
})
|
|
19
23
|
apply_nts_message_attributes message
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
send_message message, validate: validate
|
|
25
|
+
{ sent: message }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Build, send a StatusRequest and collect the StatusResponse. Returns the collector.
|
|
29
|
+
# Call .ok! on the result to raise on NotAck or timeout.
|
|
30
|
+
def request_status_and_collect(status_list, within:, component: nil, m_id: nil, validate: true)
|
|
31
|
+
validate_ready 'request status'
|
|
32
|
+
component ||= main.c_id
|
|
33
|
+
m_id ||= RSMP::Message.make_m_id
|
|
34
|
+
|
|
35
|
+
list = RSMP::StatusList.new(status_list)
|
|
36
|
+
|
|
37
|
+
# additional items can be used when verifying the response,
|
|
38
|
+
# but must be removed from the request
|
|
39
|
+
request_list = list.map { |item| item.slice('sCI', 'n') }
|
|
40
|
+
|
|
41
|
+
message = RSMP::StatusRequest.new({
|
|
42
|
+
'cId' => component,
|
|
43
|
+
'sS' => request_list,
|
|
44
|
+
'mId' => m_id
|
|
45
|
+
})
|
|
46
|
+
apply_nts_message_attributes message
|
|
47
|
+
collector = StatusCollector.new(self, list.to_a, timeout: within, m_id: m_id)
|
|
48
|
+
send_message_and_collect(message, collector, validate: validate)[:collector]
|
|
27
49
|
end
|
|
28
50
|
|
|
29
51
|
def process_status_response(message)
|
|
@@ -49,28 +71,49 @@ module RSMP
|
|
|
49
71
|
end
|
|
50
72
|
end
|
|
51
73
|
|
|
52
|
-
|
|
74
|
+
# Build and send a StatusSubscribe. Returns { sent: message }.
|
|
75
|
+
def subscribe_to_status(status_list, component: nil, m_id: nil, validate: true)
|
|
53
76
|
validate_ready 'subscribe to status'
|
|
54
|
-
|
|
55
|
-
|
|
77
|
+
component ||= main.c_id
|
|
78
|
+
m_id ||= RSMP::Message.make_m_id
|
|
56
79
|
|
|
57
|
-
|
|
58
|
-
|
|
80
|
+
list = RSMP::StatusList.new(status_list)
|
|
81
|
+
subscribe_list = list.map { |item| item.slice('sCI', 'n', 'uRt', 'sOc') }
|
|
82
|
+
|
|
83
|
+
update_subscription(component, subscribe_list)
|
|
84
|
+
find_component component
|
|
59
85
|
|
|
60
86
|
message = RSMP::StatusSubscribe.new({
|
|
61
|
-
'cId' =>
|
|
87
|
+
'cId' => component,
|
|
62
88
|
'sS' => subscribe_list,
|
|
63
89
|
'mId' => m_id
|
|
64
90
|
})
|
|
65
91
|
apply_nts_message_attributes message
|
|
92
|
+
send_message message, validate: validate
|
|
93
|
+
{ sent: message }
|
|
94
|
+
end
|
|
66
95
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
96
|
+
# Build, send a StatusSubscribe and collect the first matching status update. Returns the collector.
|
|
97
|
+
# Call .ok! on the result to raise on NotAck or timeout.
|
|
98
|
+
def subscribe_to_status_and_collect(status_list, within:, component: nil, m_id: nil, validate: true)
|
|
99
|
+
validate_ready 'subscribe to status'
|
|
100
|
+
component ||= main.c_id
|
|
101
|
+
m_id ||= RSMP::Message.make_m_id
|
|
102
|
+
|
|
103
|
+
list = RSMP::StatusList.new(status_list)
|
|
104
|
+
subscribe_list = list.map { |item| item.slice('sCI', 'n', 'uRt', 'sOc') }
|
|
105
|
+
|
|
106
|
+
update_subscription(component, subscribe_list)
|
|
107
|
+
find_component component
|
|
108
|
+
|
|
109
|
+
message = RSMP::StatusSubscribe.new({
|
|
110
|
+
'cId' => component,
|
|
111
|
+
'sS' => subscribe_list,
|
|
112
|
+
'mId' => m_id
|
|
113
|
+
})
|
|
114
|
+
apply_nts_message_attributes message
|
|
115
|
+
collector = StatusCollector.new(self, list.to_a, timeout: within, m_id: m_id)
|
|
116
|
+
send_message_and_collect(message, collector, validate: validate)[:collector]
|
|
74
117
|
end
|
|
75
118
|
|
|
76
119
|
def remove_subscription_item(component_id, code, name)
|
|
@@ -81,29 +124,31 @@ module RSMP
|
|
|
81
124
|
@status_subscriptions.delete(component_id) if @status_subscriptions[component_id].empty?
|
|
82
125
|
end
|
|
83
126
|
|
|
84
|
-
def unsubscribe_to_status(
|
|
127
|
+
def unsubscribe_to_status(status_list, component: nil, validate: nil)
|
|
85
128
|
validate_ready 'unsubscribe to status'
|
|
129
|
+
component ||= main.c_id
|
|
86
130
|
|
|
87
131
|
status_list.each do |item|
|
|
88
|
-
remove_subscription_item(
|
|
132
|
+
remove_subscription_item(component, item['sCI'], item['n'])
|
|
89
133
|
end
|
|
90
134
|
|
|
91
135
|
message = RSMP::StatusUnsubscribe.new({
|
|
92
|
-
'cId' =>
|
|
136
|
+
'cId' => component,
|
|
93
137
|
'sS' => status_list
|
|
94
138
|
})
|
|
95
139
|
apply_nts_message_attributes message
|
|
96
|
-
send_message message, validate:
|
|
140
|
+
send_message message, validate: validate
|
|
97
141
|
message
|
|
98
142
|
end
|
|
99
143
|
|
|
100
144
|
# unsubscribes to all statuses (with all attributes) defined in the used SXL
|
|
101
|
-
def unsubscribe_from_all(
|
|
145
|
+
def unsubscribe_from_all(component: nil)
|
|
146
|
+
component ||= main.c_id
|
|
102
147
|
catalogue = RSMP::Schema.status_catalogue(@sxl, sxl_version)
|
|
103
148
|
status_list = catalogue.flat_map do |status_code_id, names|
|
|
104
149
|
names.map { |name| { 'sCI' => status_code_id.to_s, 'n' => name.to_s } }
|
|
105
150
|
end
|
|
106
|
-
unsubscribe_to_status
|
|
151
|
+
unsubscribe_to_status status_list, component: component
|
|
107
152
|
end
|
|
108
153
|
|
|
109
154
|
def process_status_update(message)
|
|
@@ -10,8 +10,8 @@ module RSMP
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
# Send aggregated status for a component
|
|
13
|
-
def send_aggregated_status(component,
|
|
14
|
-
m_id
|
|
13
|
+
def send_aggregated_status(component, m_id: nil)
|
|
14
|
+
m_id ||= RSMP::Message.make_m_id
|
|
15
15
|
|
|
16
16
|
se = if Proxy.version_meets_requirement?(core_version, '<=3.1.2')
|
|
17
17
|
component.aggregated_status_bools.map { |bool| bool ? 'true' : 'false' }
|
|
@@ -29,9 +29,7 @@ module RSMP
|
|
|
29
29
|
})
|
|
30
30
|
|
|
31
31
|
apply_nts_message_attributes message
|
|
32
|
-
|
|
33
|
-
Collector.new self, collect_options.merge(task: @task, type: 'MessageAck')
|
|
34
|
-
end
|
|
32
|
+
send_message message
|
|
35
33
|
end
|
|
36
34
|
|
|
37
35
|
def process_aggregated_status_request(message)
|
|
@@ -3,12 +3,6 @@ module RSMP
|
|
|
3
3
|
module Modules
|
|
4
4
|
# Alarm handling
|
|
5
5
|
module Alarms
|
|
6
|
-
def send_alarm(_component, alarm, options = {})
|
|
7
|
-
send_and_optionally_collect alarm, options do |collect_options|
|
|
8
|
-
Collector.new self, collect_options.merge(task: @task, type: 'MessageAck')
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
|
|
12
6
|
def send_active_alarms
|
|
13
7
|
@site.components.each_pair do |_c_id, component|
|
|
14
8
|
component.alarms.each_pair do |_alarm_code, alarm_state|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module RSMP
|
|
2
|
+
# Represents an RSMP status list and converts between the two common formats:
|
|
3
|
+
#
|
|
4
|
+
# Compact Hash (symbol or string keys):
|
|
5
|
+
# { S0014: [:status, :source] }
|
|
6
|
+
# { 'S0014' => ['status', 'source'] }
|
|
7
|
+
#
|
|
8
|
+
# Raw wire Array (used in RSMP messages):
|
|
9
|
+
# [{ 'sCI' => 'S0014', 'n' => 'status' }, { 'sCI' => 'S0014', 'n' => 'source' }]
|
|
10
|
+
class StatusList
|
|
11
|
+
include Enumerable
|
|
12
|
+
|
|
13
|
+
def initialize(input)
|
|
14
|
+
@list = case input
|
|
15
|
+
when StatusList
|
|
16
|
+
input.to_a
|
|
17
|
+
when Array
|
|
18
|
+
input
|
|
19
|
+
when Hash
|
|
20
|
+
input.flat_map do |code, names|
|
|
21
|
+
names.map { |name| { 'sCI' => code.to_s, 'n' => name.to_s } }
|
|
22
|
+
end
|
|
23
|
+
else
|
|
24
|
+
raise ArgumentError, "StatusList requires an Array, Hash, or StatusList, got #{input.class}"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def each(&)
|
|
29
|
+
@list.each(&)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def to_a
|
|
33
|
+
@list
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def to_h
|
|
37
|
+
@list.each_with_object({}) do |item, hash|
|
|
38
|
+
code = item['sCI']
|
|
39
|
+
name = item['n']
|
|
40
|
+
(hash[code] ||= []) << name
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -196,8 +196,8 @@ module RSMP
|
|
|
196
196
|
|
|
197
197
|
# S0006 - Emergency route status (deprecated, use S0035)
|
|
198
198
|
def handle_s0006(_status_code, status_name = nil, options = {})
|
|
199
|
-
if Proxy.version_meets_requirement? options[:sxl_version],
|
|
200
|
-
|
|
199
|
+
if RSMP::Proxy.version_meets_requirement? options[:sxl_version],
|
|
200
|
+
'>=1.2.0'
|
|
201
201
|
log 'S0006 is depreciated, use S0035 instead.',
|
|
202
202
|
level: :warning
|
|
203
203
|
end
|
|
@@ -63,22 +63,36 @@ module RSMP
|
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
# S0091 - Operator logged in/out OP-panel
|
|
66
|
-
def handle_s0091(_status_code, status_name = nil,
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
def handle_s0091(_status_code, status_name = nil, options = {})
|
|
67
|
+
if RSMP::Proxy.version_meets_requirement?(options[:sxl_version], '>=1.1')
|
|
68
|
+
case status_name
|
|
69
|
+
when 'user'
|
|
70
|
+
TrafficControllerSite.make_status 0
|
|
71
|
+
end
|
|
72
|
+
else
|
|
73
|
+
case status_name
|
|
74
|
+
when 'user'
|
|
75
|
+
TrafficControllerSite.make_status 'nobody'
|
|
76
|
+
when 'status'
|
|
77
|
+
TrafficControllerSite.make_status 'logout'
|
|
78
|
+
end
|
|
72
79
|
end
|
|
73
80
|
end
|
|
74
81
|
|
|
75
82
|
# S0092 - Operator logged in/out web-interface
|
|
76
|
-
def handle_s0092(_status_code, status_name = nil,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
83
|
+
def handle_s0092(_status_code, status_name = nil, options = {})
|
|
84
|
+
if RSMP::Proxy.version_meets_requirement?(options[:sxl_version], '>=1.1')
|
|
85
|
+
case status_name
|
|
86
|
+
when 'user'
|
|
87
|
+
TrafficControllerSite.make_status 0
|
|
88
|
+
end
|
|
89
|
+
else
|
|
90
|
+
case status_name
|
|
91
|
+
when 'user'
|
|
92
|
+
TrafficControllerSite.make_status 'nobody'
|
|
93
|
+
when 'status'
|
|
94
|
+
TrafficControllerSite.make_status 'logout'
|
|
95
|
+
end
|
|
82
96
|
end
|
|
83
97
|
end
|
|
84
98
|
|
|
@@ -5,17 +5,20 @@ module RSMP
|
|
|
5
5
|
# Covers functional position, emergency routes, I/O modes, signal group orders, and system settings.
|
|
6
6
|
module Control
|
|
7
7
|
# M0001 — Set functional position (NormalControl, YellowFlash, Dark).
|
|
8
|
-
def set_functional_position(status, timeout_minutes: 0
|
|
8
|
+
def set_functional_position(status, within:, timeout_minutes: 0)
|
|
9
9
|
validate_ready 'set functional position'
|
|
10
10
|
raise 'TLC main component not found' unless main
|
|
11
11
|
|
|
12
12
|
command_list = functional_position_command_list(status, timeout_minutes)
|
|
13
13
|
confirm_status = functional_position_confirm_status(status)
|
|
14
|
-
|
|
14
|
+
collector = send_command_and_collect(command_list, within: within)
|
|
15
|
+
collector.ok!
|
|
16
|
+
wait_for_status "functional position #{status}", confirm_status, timeout: within unless confirm_status.empty?
|
|
17
|
+
{ collector: collector }
|
|
15
18
|
end
|
|
16
19
|
|
|
17
20
|
# M0005 — Set or clear an emergency route.
|
|
18
|
-
def set_emergency_route(route:, active:,
|
|
21
|
+
def set_emergency_route(route:, active:, within:)
|
|
19
22
|
validate_ready 'set emergency route'
|
|
20
23
|
raise 'TLC main component not found' unless main
|
|
21
24
|
|
|
@@ -39,13 +42,11 @@ module RSMP
|
|
|
39
42
|
'v' => route.to_s
|
|
40
43
|
}]
|
|
41
44
|
|
|
42
|
-
|
|
43
|
-
send_command_with_confirm main.c_id, command_list, options,
|
|
44
|
-
"emergency route #{route} #{active ? 'active' : 'inactive'}", confirm_status
|
|
45
|
+
send_command_and_collect(command_list, within: within).ok!
|
|
45
46
|
end
|
|
46
47
|
|
|
47
48
|
# M0007 — Enable or disable fixed-time control.
|
|
48
|
-
def set_fixed_time(status,
|
|
49
|
+
def set_fixed_time(status, within:)
|
|
49
50
|
validate_ready 'set fixed time'
|
|
50
51
|
raise 'TLC main component not found' unless main
|
|
51
52
|
|
|
@@ -65,11 +66,12 @@ module RSMP
|
|
|
65
66
|
|
|
66
67
|
confirm_status = [{ 'sCI' => 'S0009', 'n' => 'status',
|
|
67
68
|
's' => /^#{Regexp.escape(status.to_s)}(,#{Regexp.escape(status.to_s)})*$/ }]
|
|
68
|
-
|
|
69
|
+
send_command_and_collect(command_list, within: within).ok!
|
|
70
|
+
wait_for_status "fixed time #{status}", confirm_status, timeout: within
|
|
69
71
|
end
|
|
70
72
|
|
|
71
73
|
# M0003 — Set traffic situation (activate a specific situation number).
|
|
72
|
-
def set_traffic_situation(situation,
|
|
74
|
+
def set_traffic_situation(situation, within:)
|
|
73
75
|
validate_ready 'set traffic situation'
|
|
74
76
|
raise 'TLC main component not found' unless main
|
|
75
77
|
|
|
@@ -93,11 +95,12 @@ module RSMP
|
|
|
93
95
|
}]
|
|
94
96
|
|
|
95
97
|
confirm_status = [{ 'sCI' => 'S0015', 'n' => 'status', 's' => situation.to_s }]
|
|
96
|
-
|
|
98
|
+
send_command_and_collect(command_list, within: within).ok!
|
|
99
|
+
wait_for_status "traffic situation #{situation}", confirm_status, timeout: within
|
|
97
100
|
end
|
|
98
101
|
|
|
99
102
|
# M0003 — Clear the active traffic situation.
|
|
100
|
-
def unset_traffic_situation(
|
|
103
|
+
def unset_traffic_situation(within:)
|
|
101
104
|
validate_ready 'unset traffic situation'
|
|
102
105
|
raise 'TLC main component not found' unless main
|
|
103
106
|
|
|
@@ -121,7 +124,8 @@ module RSMP
|
|
|
121
124
|
}]
|
|
122
125
|
|
|
123
126
|
confirm_status = [{ 'sCI' => 'S0015', 'n' => 'status', 's' => '1' }]
|
|
124
|
-
|
|
127
|
+
send_command_and_collect(command_list, within: within).ok!
|
|
128
|
+
wait_for_status 'traffic situation unset', confirm_status, timeout: within
|
|
125
129
|
end
|
|
126
130
|
|
|
127
131
|
private
|
|
@@ -6,7 +6,7 @@ module RSMP
|
|
|
6
6
|
module Detectors
|
|
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
|
-
def force_detector_logic(component_id, status:, mode:,
|
|
9
|
+
def force_detector_logic(component_id, status:, mode:, within:)
|
|
10
10
|
validate_ready 'force detector logic'
|
|
11
11
|
|
|
12
12
|
security_code = security_code_for(2)
|
|
@@ -27,12 +27,11 @@ module RSMP
|
|
|
27
27
|
'n' => 'mode',
|
|
28
28
|
'v' => mode.to_s
|
|
29
29
|
}]
|
|
30
|
-
|
|
31
|
-
send_command_with_confirm component_id, command_list, options, "force detector logic #{component_id}", nil
|
|
30
|
+
send_command_and_collect(command_list, component: component_id, within: within).ok!
|
|
32
31
|
end
|
|
33
32
|
|
|
34
33
|
# M0021 — Set the trigger level for traffic counting.
|
|
35
|
-
def set_trigger_level(status,
|
|
34
|
+
def set_trigger_level(status, within:)
|
|
36
35
|
validate_ready 'set trigger level'
|
|
37
36
|
raise 'TLC main component not found' unless main
|
|
38
37
|
|
|
@@ -49,8 +48,7 @@ module RSMP
|
|
|
49
48
|
'n' => 'securityCode',
|
|
50
49
|
'v' => security_code.to_s
|
|
51
50
|
}]
|
|
52
|
-
|
|
53
|
-
send_command_with_confirm main.c_id, command_list, options, "trigger level #{status}", nil
|
|
51
|
+
send_command_and_collect(command_list, within: within).ok!
|
|
54
52
|
end
|
|
55
53
|
end
|
|
56
54
|
end
|
data/lib/rsmp/tlc/proxy/io.rb
CHANGED
|
@@ -5,7 +5,7 @@ module RSMP
|
|
|
5
5
|
# Covers detector logic, input/output forcing and setting.
|
|
6
6
|
module IO
|
|
7
7
|
# M0006 — Set a single input to a given status.
|
|
8
|
-
def set_input(input:, status:,
|
|
8
|
+
def set_input(input:, status:, within:)
|
|
9
9
|
validate_ready 'set input'
|
|
10
10
|
raise 'TLC main component not found' unless main
|
|
11
11
|
|
|
@@ -27,12 +27,11 @@ module RSMP
|
|
|
27
27
|
'n' => 'input',
|
|
28
28
|
'v' => input.to_s
|
|
29
29
|
}]
|
|
30
|
-
|
|
31
|
-
send_command_with_confirm main.c_id, command_list, options, "input #{input} set to #{status}", nil
|
|
30
|
+
send_command_and_collect(command_list, within: within).ok!
|
|
32
31
|
end
|
|
33
32
|
|
|
34
33
|
# M0013 — Set all inputs via a bit-pattern string.
|
|
35
|
-
def set_inputs(status,
|
|
34
|
+
def set_inputs(status, within:)
|
|
36
35
|
validate_ready 'set inputs'
|
|
37
36
|
raise 'TLC main component not found' unless main
|
|
38
37
|
|
|
@@ -40,31 +39,31 @@ module RSMP
|
|
|
40
39
|
|
|
41
40
|
command_list = [{
|
|
42
41
|
'cCI' => 'M0013',
|
|
43
|
-
'cO' => '
|
|
42
|
+
'cO' => 'setInput',
|
|
44
43
|
'n' => 'status',
|
|
45
44
|
'v' => status.to_s
|
|
46
45
|
}, {
|
|
47
46
|
'cCI' => 'M0013',
|
|
48
|
-
'cO' => '
|
|
47
|
+
'cO' => 'setInput',
|
|
49
48
|
'n' => 'securityCode',
|
|
50
49
|
'v' => security_code.to_s
|
|
51
50
|
}]
|
|
52
|
-
|
|
53
|
-
send_command_with_confirm main.c_id, command_list, options, "inputs #{status}", nil
|
|
51
|
+
send_command_and_collect(command_list, within: within).ok!
|
|
54
52
|
end
|
|
55
53
|
|
|
56
54
|
# M0019 — Force an input to a given value.
|
|
57
|
-
def force_input(input:, status:, value:,
|
|
55
|
+
def force_input(input:, status:, value:, within:)
|
|
58
56
|
validate_ready 'force input'
|
|
59
57
|
raise 'TLC main component not found' unless main
|
|
60
58
|
|
|
61
59
|
command_list = force_input_command_list(input, status, value)
|
|
62
60
|
confirm_status = force_input_confirm_status(input, status, value)
|
|
63
|
-
|
|
61
|
+
send_command_and_collect(command_list, within: within).ok!
|
|
62
|
+
wait_for_status "force input #{input}", confirm_status, timeout: within
|
|
64
63
|
end
|
|
65
64
|
|
|
66
65
|
# M0020 — Force an output to a given value.
|
|
67
|
-
def force_output(output:, status:, value:,
|
|
66
|
+
def force_output(output:, status:, value:, within:)
|
|
68
67
|
validate_ready 'force output'
|
|
69
68
|
raise 'TLC main component not found' unless main
|
|
70
69
|
|
|
@@ -91,8 +90,7 @@ module RSMP
|
|
|
91
90
|
'n' => 'outputValue',
|
|
92
91
|
'v' => value.to_s
|
|
93
92
|
}]
|
|
94
|
-
|
|
95
|
-
send_command_with_confirm main.c_id, command_list, options, "force output #{output}", nil
|
|
93
|
+
send_command_and_collect(command_list, within: within).ok!
|
|
96
94
|
end
|
|
97
95
|
|
|
98
96
|
private
|
|
@@ -108,10 +106,14 @@ module RSMP
|
|
|
108
106
|
end
|
|
109
107
|
|
|
110
108
|
def force_input_confirm_status(input, status, value)
|
|
111
|
-
[
|
|
112
|
-
{ 'sCI' => 'S0029', 'n' => 'status', 's' => /^.{#{input.to_i - 1}}#{status == 'True' ? '1' : '0'}/ }
|
|
113
|
-
{ 'sCI' => 'S0003', 'n' => 'inputstatus', 's' => /^.{#{input.to_i - 1}}#{value == 'True' ? '1' : '0'}/ }
|
|
109
|
+
result = [
|
|
110
|
+
{ 'sCI' => 'S0029', 'n' => 'status', 's' => /^.{#{input.to_i - 1}}#{status == 'True' ? '1' : '0'}/ }
|
|
114
111
|
]
|
|
112
|
+
if status == 'True'
|
|
113
|
+
result << { 'sCI' => 'S0003', 'n' => 'inputstatus',
|
|
114
|
+
's' => /^.{#{input.to_i - 1}}#{value == 'True' ? '1' : '0'}/ }
|
|
115
|
+
end
|
|
116
|
+
result
|
|
115
117
|
end
|
|
116
118
|
end
|
|
117
119
|
end
|
data/lib/rsmp/tlc/proxy/plans.rb
CHANGED
|
@@ -5,7 +5,7 @@ module RSMP
|
|
|
5
5
|
# Covers time plans, week/day tables, bands, offsets, and cycle times.
|
|
6
6
|
module Plans
|
|
7
7
|
# M0014 — Set dynamic bands for a signal plan.
|
|
8
|
-
def set_dynamic_bands(plan:, status:,
|
|
8
|
+
def set_dynamic_bands(plan:, status:, within:)
|
|
9
9
|
validate_ready 'set dynamic bands'
|
|
10
10
|
raise 'TLC main component not found' unless main
|
|
11
11
|
|
|
@@ -27,12 +27,11 @@ module RSMP
|
|
|
27
27
|
'n' => 'plan',
|
|
28
28
|
'v' => plan.to_s
|
|
29
29
|
}]
|
|
30
|
-
|
|
31
|
-
send_command_with_confirm main.c_id, command_list, options, "dynamic bands plan #{plan}", nil
|
|
30
|
+
send_command_and_collect(command_list, within: within).ok!
|
|
32
31
|
end
|
|
33
32
|
|
|
34
33
|
# M0023 — Set timeout for dynamic bands.
|
|
35
|
-
def set_dynamic_bands_timeout(status,
|
|
34
|
+
def set_dynamic_bands_timeout(status, within:)
|
|
36
35
|
validate_ready 'set dynamic bands timeout'
|
|
37
36
|
raise 'TLC main component not found' unless main
|
|
38
37
|
|
|
@@ -49,12 +48,11 @@ module RSMP
|
|
|
49
48
|
'n' => 'securityCode',
|
|
50
49
|
'v' => security_code.to_s
|
|
51
50
|
}]
|
|
52
|
-
|
|
53
|
-
send_command_with_confirm main.c_id, command_list, options, "dynamic bands timeout #{status}", nil
|
|
51
|
+
send_command_and_collect(command_list, within: within).ok!
|
|
54
52
|
end
|
|
55
53
|
|
|
56
54
|
# M0015 — Set offset for a signal plan.
|
|
57
|
-
def set_offset(plan:, offset:,
|
|
55
|
+
def set_offset(plan:, offset:, within:)
|
|
58
56
|
validate_ready 'set offset'
|
|
59
57
|
raise 'TLC main component not found' unless main
|
|
60
58
|
|
|
@@ -76,12 +74,11 @@ module RSMP
|
|
|
76
74
|
'n' => 'plan',
|
|
77
75
|
'v' => plan.to_s
|
|
78
76
|
}]
|
|
79
|
-
|
|
80
|
-
send_command_with_confirm main.c_id, command_list, options, "offset plan #{plan} to #{offset}", nil
|
|
77
|
+
send_command_and_collect(command_list, within: within).ok!
|
|
81
78
|
end
|
|
82
79
|
|
|
83
80
|
# Set the timeplan (signal plan) on the remote TLC.
|
|
84
|
-
def set_timeplan(plan_nr,
|
|
81
|
+
def set_timeplan(plan_nr, within:)
|
|
85
82
|
validate_ready 'set timeplan'
|
|
86
83
|
raise 'TLC main component not found' unless main
|
|
87
84
|
|
|
@@ -103,13 +100,13 @@ module RSMP
|
|
|
103
100
|
'n' => 'timeplan',
|
|
104
101
|
'v' => plan_nr.to_s
|
|
105
102
|
}]
|
|
106
|
-
|
|
107
103
|
confirm_status = [{ 'sCI' => 'S0014', 'n' => 'status', 's' => plan_nr.to_s }]
|
|
108
|
-
|
|
104
|
+
send_command_and_collect(command_list, within: within).ok!
|
|
105
|
+
wait_for_status("timeplan #{plan_nr}", confirm_status, timeout: within)
|
|
109
106
|
end
|
|
110
107
|
|
|
111
108
|
# M0016 — Set week table (mapping week days to traffic situations).
|
|
112
|
-
def set_week_table(status,
|
|
109
|
+
def set_week_table(status, within:)
|
|
113
110
|
validate_ready 'set week table'
|
|
114
111
|
raise 'TLC main component not found' unless main
|
|
115
112
|
|
|
@@ -126,12 +123,11 @@ module RSMP
|
|
|
126
123
|
'n' => 'securityCode',
|
|
127
124
|
'v' => security_code.to_s
|
|
128
125
|
}]
|
|
129
|
-
|
|
130
|
-
send_command_with_confirm main.c_id, command_list, options, 'week table', nil
|
|
126
|
+
send_command_and_collect(command_list, within:).ok!
|
|
131
127
|
end
|
|
132
128
|
|
|
133
129
|
# M0017 — Set day table (mapping time periods to signal plans).
|
|
134
|
-
def set_day_table(status,
|
|
130
|
+
def set_day_table(status, within:)
|
|
135
131
|
validate_ready 'set day table'
|
|
136
132
|
raise 'TLC main component not found' unless main
|
|
137
133
|
|
|
@@ -139,21 +135,20 @@ module RSMP
|
|
|
139
135
|
|
|
140
136
|
command_list = [{
|
|
141
137
|
'cCI' => 'M0017',
|
|
142
|
-
'cO' => '
|
|
138
|
+
'cO' => 'setTimeTable',
|
|
143
139
|
'n' => 'status',
|
|
144
140
|
'v' => status.to_s
|
|
145
141
|
}, {
|
|
146
142
|
'cCI' => 'M0017',
|
|
147
|
-
'cO' => '
|
|
143
|
+
'cO' => 'setTimeTable',
|
|
148
144
|
'n' => 'securityCode',
|
|
149
145
|
'v' => security_code.to_s
|
|
150
146
|
}]
|
|
151
|
-
|
|
152
|
-
send_command_with_confirm main.c_id, command_list, options, 'day table', nil
|
|
147
|
+
send_command_and_collect(command_list, within:).ok!
|
|
153
148
|
end
|
|
154
149
|
|
|
155
150
|
# M0018 — Set cycle time for a signal plan.
|
|
156
|
-
def set_cycle_time(plan:, cycle_time:,
|
|
151
|
+
def set_cycle_time(plan:, cycle_time:, within:)
|
|
157
152
|
validate_ready 'set cycle time'
|
|
158
153
|
raise 'TLC main component not found' unless main
|
|
159
154
|
|
|
@@ -175,12 +170,11 @@ module RSMP
|
|
|
175
170
|
'n' => 'plan',
|
|
176
171
|
'v' => plan.to_s
|
|
177
172
|
}]
|
|
178
|
-
|
|
179
|
-
send_command_with_confirm main.c_id, command_list, options, "cycle time plan #{plan} to #{cycle_time}", nil
|
|
173
|
+
send_command_and_collect(command_list, within:).ok!
|
|
180
174
|
end
|
|
181
175
|
|
|
182
176
|
# M0010 — Order signal start for a signal group component.
|
|
183
|
-
def order_signal_start(component_id,
|
|
177
|
+
def order_signal_start(component_id, within:)
|
|
184
178
|
validate_ready 'order signal start'
|
|
185
179
|
|
|
186
180
|
security_code = security_code_for(2)
|
|
@@ -196,12 +190,11 @@ module RSMP
|
|
|
196
190
|
'n' => 'securityCode',
|
|
197
191
|
'v' => security_code.to_s
|
|
198
192
|
}]
|
|
199
|
-
|
|
200
|
-
send_command_with_confirm component_id, command_list, options, "signal start #{component_id}", nil
|
|
193
|
+
send_command_and_collect(command_list, component: component_id, within:).ok!
|
|
201
194
|
end
|
|
202
195
|
|
|
203
196
|
# M0011 — Order signal stop for a signal group component.
|
|
204
|
-
def order_signal_stop(component_id,
|
|
197
|
+
def order_signal_stop(component_id, within:)
|
|
205
198
|
validate_ready 'order signal stop'
|
|
206
199
|
|
|
207
200
|
security_code = security_code_for(2)
|
|
@@ -217,8 +210,7 @@ module RSMP
|
|
|
217
210
|
'n' => 'securityCode',
|
|
218
211
|
'v' => security_code.to_s
|
|
219
212
|
}]
|
|
220
|
-
|
|
221
|
-
send_command_with_confirm component_id, command_list, options, "signal stop #{component_id}", nil
|
|
213
|
+
send_command_and_collect(command_list, component: component_id, within:).ok!
|
|
222
214
|
end
|
|
223
215
|
end
|
|
224
216
|
end
|