rsmp 0.35.2 → 0.38.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/.devcontainer/devcontainer.json +22 -0
- data/.github/copilot-instructions.md +33 -0
- data/.github/workflows/copilot-setup-steps.yml +35 -0
- data/.github/workflows/rspec.yaml +2 -1
- data/.github/workflows/rubocop.yaml +17 -0
- data/.gitignore +7 -7
- data/.rubocop.yml +80 -0
- data/Gemfile +13 -1
- data/Gemfile.lock +73 -35
- data/Rakefile +3 -3
- data/bin/console +2 -4
- data/documentation/tasks.md +4 -4
- data/lib/rsmp/cli.rb +147 -124
- data/lib/rsmp/collect/ack_collector.rb +8 -7
- data/lib/rsmp/collect/aggregated_status_collector.rb +4 -4
- data/lib/rsmp/collect/alarm_collector.rb +31 -23
- data/lib/rsmp/collect/alarm_matcher.rb +3 -3
- data/lib/rsmp/collect/collector/logging.rb +17 -0
- data/lib/rsmp/collect/collector/reporting.rb +44 -0
- data/lib/rsmp/collect/collector/status.rb +34 -0
- data/lib/rsmp/collect/collector.rb +69 -150
- data/lib/rsmp/collect/command_matcher.rb +19 -6
- data/lib/rsmp/collect/command_response_collector.rb +7 -7
- data/lib/rsmp/collect/distributor.rb +14 -11
- data/lib/rsmp/collect/filter.rb +31 -15
- data/lib/rsmp/collect/matcher.rb +7 -11
- data/lib/rsmp/collect/queue.rb +4 -4
- data/lib/rsmp/collect/receiver.rb +10 -12
- data/lib/rsmp/collect/state_collector.rb +116 -77
- data/lib/rsmp/collect/status_collector.rb +6 -6
- data/lib/rsmp/collect/status_matcher.rb +17 -7
- data/lib/rsmp/{alarm_state.rb → component/alarm_state.rb} +76 -37
- data/lib/rsmp/{component.rb → component/component.rb} +15 -15
- data/lib/rsmp/component/component_base.rb +89 -0
- data/lib/rsmp/component/component_proxy.rb +75 -0
- data/lib/rsmp/component/components.rb +63 -0
- data/lib/rsmp/convert/export/json_schema.rb +116 -110
- data/lib/rsmp/convert/import/yaml.rb +21 -18
- data/lib/rsmp/{rsmp.rb → helpers/clock.rb} +5 -6
- data/lib/rsmp/{deep_merge.rb → helpers/deep_merge.rb} +2 -1
- data/lib/rsmp/helpers/error.rb +71 -0
- data/lib/rsmp/{inspect.rb → helpers/inspect.rb} +6 -10
- data/lib/rsmp/log/archive.rb +98 -0
- data/lib/rsmp/log/colorization.rb +41 -0
- data/lib/rsmp/log/filtering.rb +54 -0
- data/lib/rsmp/log/logger.rb +206 -0
- data/lib/rsmp/{logging.rb → log/logging.rb} +5 -7
- data/lib/rsmp/message.rb +159 -148
- data/lib/rsmp/{node.rb → node/node.rb} +19 -17
- data/lib/rsmp/node/protocol.rb +37 -0
- data/lib/rsmp/node/site/site.rb +195 -0
- data/lib/rsmp/node/supervisor/modules/configuration.rb +59 -0
- data/lib/rsmp/node/supervisor/modules/connection.rb +140 -0
- data/lib/rsmp/node/supervisor/modules/sites.rb +64 -0
- data/lib/rsmp/node/supervisor/supervisor.rb +72 -0
- data/lib/rsmp/{task.rb → node/task.rb} +29 -19
- data/lib/rsmp/proxy/modules/acknowledgements.rb +144 -0
- data/lib/rsmp/proxy/modules/receive.rb +119 -0
- data/lib/rsmp/proxy/modules/send.rb +76 -0
- data/lib/rsmp/proxy/modules/state.rb +25 -0
- data/lib/rsmp/proxy/modules/tasks.rb +105 -0
- data/lib/rsmp/proxy/modules/versions.rb +69 -0
- data/lib/rsmp/proxy/modules/watchdogs.rb +66 -0
- data/lib/rsmp/proxy/proxy.rb +199 -0
- data/lib/rsmp/proxy/site/modules/aggregated_status.rb +52 -0
- data/lib/rsmp/proxy/site/modules/alarms.rb +27 -0
- data/lib/rsmp/proxy/site/modules/commands.rb +31 -0
- data/lib/rsmp/proxy/site/modules/status.rb +110 -0
- data/lib/rsmp/proxy/site/site_proxy.rb +205 -0
- data/lib/rsmp/proxy/supervisor/modules/aggregated_status.rb +47 -0
- data/lib/rsmp/proxy/supervisor/modules/alarms.rb +73 -0
- data/lib/rsmp/proxy/supervisor/modules/commands.rb +53 -0
- data/lib/rsmp/proxy/supervisor/modules/status.rb +204 -0
- data/lib/rsmp/proxy/supervisor/supervisor_proxy.rb +178 -0
- data/lib/rsmp/tlc/detector_logic.rb +18 -34
- data/lib/rsmp/tlc/input_states.rb +126 -0
- data/lib/rsmp/tlc/modules/detector_logics.rb +50 -0
- data/lib/rsmp/tlc/modules/display.rb +78 -0
- data/lib/rsmp/tlc/modules/helpers.rb +41 -0
- data/lib/rsmp/tlc/modules/inputs.rb +173 -0
- data/lib/rsmp/tlc/modules/modes.rb +253 -0
- data/lib/rsmp/tlc/modules/outputs.rb +30 -0
- data/lib/rsmp/tlc/modules/plans.rb +218 -0
- data/lib/rsmp/tlc/modules/signal_groups.rb +109 -0
- data/lib/rsmp/tlc/modules/startup_sequence.rb +22 -0
- data/lib/rsmp/tlc/modules/system.rb +140 -0
- data/lib/rsmp/tlc/modules/traffic_data.rb +49 -0
- data/lib/rsmp/tlc/signal_group.rb +37 -41
- data/lib/rsmp/tlc/signal_plan.rb +14 -11
- data/lib/rsmp/tlc/signal_priority.rb +39 -35
- data/lib/rsmp/tlc/startup_sequence.rb +59 -0
- data/lib/rsmp/tlc/traffic_controller.rb +39 -1006
- data/lib/rsmp/tlc/traffic_controller_site.rb +58 -57
- data/lib/rsmp/version.rb +1 -1
- data/lib/rsmp.rb +86 -49
- data/rsmp.gemspec +24 -30
- metadata +87 -130
- data/lib/rsmp/archive.rb +0 -76
- data/lib/rsmp/collect/message_matchers.rb +0 -0
- data/lib/rsmp/component_base.rb +0 -87
- data/lib/rsmp/component_proxy.rb +0 -57
- data/lib/rsmp/components.rb +0 -65
- data/lib/rsmp/error.rb +0 -71
- data/lib/rsmp/logger.rb +0 -216
- data/lib/rsmp/proxy.rb +0 -695
- data/lib/rsmp/site.rb +0 -188
- data/lib/rsmp/site_proxy.rb +0 -389
- data/lib/rsmp/supervisor.rb +0 -287
- data/lib/rsmp/supervisor_proxy.rb +0 -516
- data/lib/rsmp/tlc/inputs.rb +0 -134
data/lib/rsmp/cli.rb
CHANGED
|
@@ -1,186 +1,208 @@
|
|
|
1
1
|
require 'thor'
|
|
2
|
-
|
|
2
|
+
require_relative '../rsmp'
|
|
3
3
|
|
|
4
4
|
module RSMP
|
|
5
5
|
class CLI < Thor
|
|
6
|
-
desc
|
|
6
|
+
desc 'version', 'Show version'
|
|
7
7
|
def version
|
|
8
8
|
puts RSMP::VERSION
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
desc
|
|
12
|
-
method_option :config, :
|
|
13
|
-
method_option :id, :
|
|
14
|
-
method_option :supervisors, :
|
|
15
|
-
|
|
16
|
-
method_option :
|
|
17
|
-
method_option :
|
|
18
|
-
|
|
11
|
+
desc 'site', 'Run RSMP site'
|
|
12
|
+
method_option :config, type: :string, aliases: '-c', banner: 'Path to .yaml config file'
|
|
13
|
+
method_option :id, type: :string, aliases: '-i', banner: 'RSMP site id'
|
|
14
|
+
method_option :supervisors, type: :string, aliases: '-s',
|
|
15
|
+
banner: 'ip:port,... list of supervisor to connect to'
|
|
16
|
+
method_option :core, type: :string, banner: "Core version: [#{RSMP::Schema.core_versions.join(' ')}]", enum: RSMP::Schema.core_versions
|
|
17
|
+
method_option :type, type: :string, aliases: '-t', banner: 'Type of site: [tlc]', enum: ['tlc'],
|
|
18
|
+
default: 'tlc'
|
|
19
|
+
method_option :log, type: :string, aliases: '-l', banner: 'Path to log file'
|
|
20
|
+
method_option :json, type: :boolean, aliases: '-j', banner: 'Show JSON messages in log'
|
|
19
21
|
def site
|
|
20
|
-
settings =
|
|
21
|
-
log_settings
|
|
22
|
+
settings, log_settings = load_site_configuration
|
|
23
|
+
apply_site_options(settings, log_settings)
|
|
24
|
+
site_class = determine_site_class(settings)
|
|
25
|
+
run_site(site_class, settings, log_settings)
|
|
26
|
+
rescue Interrupt
|
|
27
|
+
# ctrl-c
|
|
28
|
+
rescue StandardError => e
|
|
29
|
+
puts "Uncaught error: #{e}"
|
|
30
|
+
puts caller.join("\n")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
desc 'supervisor', 'Run RSMP supervisor'
|
|
34
|
+
method_option :config, type: :string, aliases: '-c', banner: 'Path to .yaml config file'
|
|
35
|
+
method_option :id, type: :string, aliases: '-i', banner: 'RSMP site id'
|
|
36
|
+
method_option :ip, type: :string, banner: 'IP address to listen on'
|
|
37
|
+
method_option :port, type: :string, aliases: '-p', banner: 'Port to listen on'
|
|
38
|
+
method_option :core, type: :string, banner: "Core version: [#{RSMP::Schema.core_versions.join(' ')}]", enum: RSMP::Schema.core_versions
|
|
39
|
+
method_option :log, type: :string, aliases: '-l', banner: 'Path to log file'
|
|
40
|
+
method_option :json, type: :boolean, aliases: '-j', banner: 'Show JSON messages in log'
|
|
41
|
+
def supervisor
|
|
42
|
+
settings, log_settings = load_supervisor_configuration
|
|
43
|
+
apply_supervisor_options(settings, log_settings)
|
|
44
|
+
run_supervisor(settings, log_settings)
|
|
45
|
+
rescue Interrupt
|
|
46
|
+
# ctrl-c
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
desc 'convert', 'Convert SXL from YAML to JSON Schema'
|
|
50
|
+
method_option :in, type: :string, aliases: '-i', banner: 'Path to YAML input file'
|
|
51
|
+
method_option :out, type: :string, aliases: '-o', banner: 'Path to JSON Schema output file'
|
|
52
|
+
def convert
|
|
53
|
+
validate_convert_options
|
|
54
|
+
validate_input_file_exists
|
|
55
|
+
perform_conversion
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
no_commands do
|
|
59
|
+
def load_site_configuration
|
|
60
|
+
settings = {}
|
|
61
|
+
log_settings = { 'active' => true }
|
|
62
|
+
|
|
63
|
+
return [settings, log_settings] unless options[:config]
|
|
22
64
|
|
|
23
|
-
if options[:config]
|
|
24
65
|
if File.exist? options[:config]
|
|
25
66
|
settings = YAML.load_file options[:config]
|
|
26
|
-
log_settings = settings.delete('log') ||
|
|
67
|
+
log_settings = settings.delete('log') || log_settings
|
|
27
68
|
else
|
|
28
69
|
puts "Error: Config #{options[:config]} not found"
|
|
29
70
|
exit
|
|
30
71
|
end
|
|
31
|
-
end
|
|
32
72
|
|
|
33
|
-
|
|
34
|
-
settings['site_id'] = options[:id]
|
|
73
|
+
[settings, log_settings]
|
|
35
74
|
end
|
|
75
|
+
end
|
|
36
76
|
|
|
37
|
-
|
|
38
|
-
settings['supervisors'] = []
|
|
39
|
-
options[:supervisors].split(',').each do |supervisor|
|
|
40
|
-
ip, port = supervisor.split ':'
|
|
41
|
-
ip = '127.0.0.1' if ip.empty?
|
|
42
|
-
port = '12111' if port.empty?
|
|
43
|
-
settings['supervisors'] << {"ip"=>ip, "port"=>port}
|
|
44
|
-
end
|
|
45
|
-
end
|
|
77
|
+
private
|
|
46
78
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
79
|
+
def apply_site_options(settings, log_settings)
|
|
80
|
+
apply_basic_site_options(settings)
|
|
81
|
+
parse_supervisors(settings) if options[:supervisors]
|
|
82
|
+
apply_log_options(log_settings)
|
|
83
|
+
end
|
|
50
84
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
site_class = RSMP::TLC::TrafficControllerSite
|
|
56
|
-
else
|
|
57
|
-
puts "Error: Unknown site type #{site_type}"
|
|
58
|
-
exit
|
|
59
|
-
end
|
|
85
|
+
def apply_basic_site_options(settings)
|
|
86
|
+
settings['site_id'] = options[:id] if options[:id]
|
|
87
|
+
settings['core_version'] = options[:core] if options[:core]
|
|
88
|
+
end
|
|
60
89
|
|
|
61
|
-
|
|
62
|
-
|
|
90
|
+
def parse_supervisors(settings)
|
|
91
|
+
settings['supervisors'] = []
|
|
92
|
+
options[:supervisors].split(',').each do |supervisor|
|
|
93
|
+
ip, port = supervisor.split ':'
|
|
94
|
+
ip = '127.0.0.1' if ip.empty?
|
|
95
|
+
port = '12111' if port.empty?
|
|
96
|
+
settings['supervisors'] << { 'ip' => ip, 'port' => port }
|
|
63
97
|
end
|
|
98
|
+
end
|
|
64
99
|
|
|
65
|
-
|
|
66
|
-
|
|
100
|
+
def determine_site_class(settings)
|
|
101
|
+
site_type = options[:type] || settings['type']
|
|
102
|
+
case site_type
|
|
103
|
+
when 'tlc'
|
|
104
|
+
RSMP::TLC::TrafficControllerSite
|
|
105
|
+
else
|
|
106
|
+
puts "Error: Unknown site type #{site_type}"
|
|
107
|
+
exit
|
|
67
108
|
end
|
|
109
|
+
end
|
|
68
110
|
|
|
111
|
+
def run_site(site_class, settings, log_settings)
|
|
69
112
|
Async do |task|
|
|
70
113
|
task.annotate 'cli'
|
|
71
114
|
loop do
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
break
|
|
85
|
-
rescue RSMP::ConfigurationError => e
|
|
86
|
-
puts "Cannot start site: #{e}"
|
|
87
|
-
break
|
|
88
|
-
rescue RSMP::Restart
|
|
89
|
-
site.stop
|
|
90
|
-
end
|
|
115
|
+
site = site_class.new(site_settings: settings, log_settings: log_settings)
|
|
116
|
+
site.start
|
|
117
|
+
site.wait
|
|
118
|
+
rescue Psych::SyntaxError => e
|
|
119
|
+
puts "Cannot read config file #{e}"
|
|
120
|
+
break
|
|
121
|
+
rescue RSMP::Schema::UnknownSchemaTypeError, RSMP::Schema::UnknownSchemaVersionError,
|
|
122
|
+
RSMP::ConfigurationError => e
|
|
123
|
+
puts "Cannot start site: #{e}"
|
|
124
|
+
break
|
|
125
|
+
rescue RSMP::Restart
|
|
126
|
+
site.stop
|
|
91
127
|
end
|
|
92
128
|
end
|
|
93
|
-
rescue Interrupt
|
|
94
|
-
# cntr-c
|
|
95
|
-
rescue Exception => e
|
|
96
|
-
puts "Uncaught error: #{e}"
|
|
97
|
-
puts caller.join("\n")
|
|
98
129
|
end
|
|
99
130
|
|
|
100
|
-
|
|
101
|
-
method_option :config, :type => :string, :aliases => "-c", banner: 'Path to .yaml config file'
|
|
102
|
-
method_option :id, :type => :string, :aliases => "-i", banner: 'RSMP site id'
|
|
103
|
-
method_option :ip, :type => :numeric, banner: 'IP address to listen on'
|
|
104
|
-
method_option :port, :type => :string, :aliases => "-p", banner: 'Port to listen on'
|
|
105
|
-
method_option :core, :string => :string, banner: "Core version: [#{RSMP::Schema.core_versions.join(' ')}]", enum: RSMP::Schema.core_versions
|
|
106
|
-
method_option :log, :type => :string, :aliases => "-l", banner: 'Path to log file'
|
|
107
|
-
method_option :json, :type => :boolean, :aliases => "-j", banner: 'Show JSON messages in log'
|
|
108
|
-
def supervisor
|
|
131
|
+
def load_supervisor_configuration
|
|
109
132
|
settings = {}
|
|
110
133
|
log_settings = { 'active' => true }
|
|
111
134
|
|
|
112
|
-
|
|
113
|
-
if File.exist? options[:config]
|
|
114
|
-
settings = YAML.load_file options[:config]
|
|
115
|
-
log_settings = settings.delete 'log'
|
|
116
|
-
else
|
|
117
|
-
puts "Error: Config #{options[:config]} not found"
|
|
118
|
-
exit
|
|
119
|
-
end
|
|
120
|
-
end
|
|
135
|
+
return [settings, log_settings] unless options[:config]
|
|
121
136
|
|
|
122
|
-
if options[:
|
|
123
|
-
settings
|
|
137
|
+
if File.exist? options[:config]
|
|
138
|
+
settings = YAML.load_file options[:config]
|
|
139
|
+
log_settings = settings.delete('log') || log_settings
|
|
140
|
+
else
|
|
141
|
+
puts "Error: Config #{options[:config]} not found"
|
|
142
|
+
exit
|
|
124
143
|
end
|
|
125
144
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
end
|
|
145
|
+
[settings, log_settings]
|
|
146
|
+
end
|
|
129
147
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
148
|
+
def apply_supervisor_options(settings, log_settings)
|
|
149
|
+
apply_basic_supervisor_options(settings)
|
|
150
|
+
apply_core_version_option(settings)
|
|
151
|
+
apply_log_options(log_settings)
|
|
152
|
+
end
|
|
133
153
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
154
|
+
def apply_basic_supervisor_options(settings)
|
|
155
|
+
settings['site_id'] = options[:id] if options[:id]
|
|
156
|
+
settings['ip'] = options[:ip] if options[:ip]
|
|
157
|
+
settings['port'] = options[:port] if options[:port]
|
|
158
|
+
end
|
|
138
159
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
end
|
|
160
|
+
def apply_core_version_option(settings)
|
|
161
|
+
return unless options[:core]
|
|
142
162
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
163
|
+
settings['guest'] ||= {}
|
|
164
|
+
settings['guest']['core_version'] = options[:core]
|
|
165
|
+
end
|
|
146
166
|
|
|
167
|
+
def apply_log_options(log_settings)
|
|
168
|
+
log_settings['path'] = options[:log] if options[:log]
|
|
169
|
+
log_settings['json'] = options[:json] if options[:json]
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def run_supervisor(settings, log_settings)
|
|
147
173
|
Async do |task|
|
|
148
174
|
task.annotate 'cli'
|
|
149
|
-
supervisor = RSMP::Supervisor.new(supervisor_settings:settings,log_settings:log_settings)
|
|
175
|
+
supervisor = RSMP::Supervisor.new(supervisor_settings: settings, log_settings: log_settings)
|
|
150
176
|
supervisor.start
|
|
151
177
|
supervisor.wait
|
|
152
178
|
rescue Psych::SyntaxError => e
|
|
153
179
|
puts "Cannot read config file #{e}"
|
|
154
|
-
rescue RSMP::Schema::UnknownSchemaTypeError
|
|
155
|
-
|
|
156
|
-
rescue RSMP::Schema::UnknownSchemaVersionError => e
|
|
157
|
-
puts "Cannot start supervisor: #{e}"
|
|
158
|
-
rescue RSMP::ConfigurationError => e
|
|
180
|
+
rescue RSMP::Schema::UnknownSchemaTypeError, RSMP::Schema::UnknownSchemaVersionError,
|
|
181
|
+
RSMP::ConfigurationError => e
|
|
159
182
|
puts "Cannot start supervisor: #{e}"
|
|
160
183
|
end
|
|
161
|
-
rescue Interrupt
|
|
162
|
-
# ctrl-c
|
|
163
184
|
end
|
|
164
185
|
|
|
165
|
-
|
|
166
|
-
method_option :in, :type => :string, :aliases => "-i", banner: 'Path to YAML input file'
|
|
167
|
-
method_option :out, :type => :string, :aliases => "-o", banner: 'Path to JSON Schema output file'
|
|
168
|
-
def convert
|
|
186
|
+
def validate_convert_options
|
|
169
187
|
unless options[:in]
|
|
170
|
-
puts
|
|
188
|
+
puts 'Error: Input option missing'
|
|
171
189
|
exit
|
|
172
190
|
end
|
|
173
191
|
|
|
174
|
-
|
|
175
|
-
puts "Error: Output option missing"
|
|
176
|
-
exit
|
|
177
|
-
end
|
|
192
|
+
return if options[:out]
|
|
178
193
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
194
|
+
puts 'Error: Output option missing'
|
|
195
|
+
exit
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def validate_input_file_exists
|
|
199
|
+
return if File.exist? options[:in]
|
|
200
|
+
|
|
201
|
+
puts "Error: Input path file #{options[:in]} not found"
|
|
202
|
+
exit
|
|
203
|
+
end
|
|
183
204
|
|
|
205
|
+
def perform_conversion
|
|
184
206
|
sxl = RSMP::Convert::Import::YAML.read options[:in]
|
|
185
207
|
RSMP::Convert::Export::JSONSchema.write sxl, options[:out]
|
|
186
208
|
end
|
|
@@ -190,5 +212,6 @@ module RSMP
|
|
|
190
212
|
def self.exit_on_failure?
|
|
191
213
|
true
|
|
192
214
|
end
|
|
215
|
+
private_class_method :exit_on_failure?
|
|
193
216
|
end
|
|
194
|
-
end
|
|
217
|
+
end
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
module RSMP
|
|
2
2
|
# Class for waiting for a message acknowledgement
|
|
3
3
|
class AckCollector < Collector
|
|
4
|
-
def initialize
|
|
5
|
-
raise ArgumentError
|
|
6
|
-
|
|
4
|
+
def initialize(proxy, options = {})
|
|
5
|
+
raise ArgumentError, 'm_id must be provided' unless options[:m_id]
|
|
6
|
+
|
|
7
|
+
super(proxy, options.merge(
|
|
7
8
|
filter: RSMP::Filter.new(ingoing: true, outgoing: false, type: 'MessageAck'),
|
|
8
9
|
num: 1,
|
|
9
10
|
title: 'message acknowledgement'
|
|
10
|
-
)
|
|
11
|
+
))
|
|
11
12
|
end
|
|
12
13
|
|
|
13
14
|
# Check if we the MessageAck related to initiating request, identified by @m_id.
|
|
14
|
-
def acceptable?
|
|
15
|
-
super
|
|
15
|
+
def acceptable?(message)
|
|
16
|
+
super && message.attribute('oMId') == @m_id
|
|
16
17
|
end
|
|
17
18
|
end
|
|
18
|
-
end
|
|
19
|
+
end
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
module RSMP
|
|
2
2
|
# Class for waiting for an aggregated status response
|
|
3
3
|
class AggregatedStatusCollector < Collector
|
|
4
|
-
def initialize
|
|
5
|
-
super
|
|
4
|
+
def initialize(proxy, options = {})
|
|
5
|
+
super(proxy, options.merge(
|
|
6
6
|
filter: RSMP::Filter.new(ingoing: true, outgoing: false, type: 'AggregatedStatus'),
|
|
7
7
|
title: 'aggregated status'
|
|
8
|
-
)
|
|
8
|
+
))
|
|
9
9
|
end
|
|
10
10
|
end
|
|
11
|
-
end
|
|
11
|
+
end
|
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
module RSMP
|
|
2
2
|
# Class for waiting for specific command responses
|
|
3
3
|
class AlarmCollector < Collector
|
|
4
|
-
def initialize
|
|
4
|
+
def initialize(proxy, options = {})
|
|
5
5
|
@matcher = options[:matcher] || {}
|
|
6
|
-
super
|
|
6
|
+
super(proxy, options.merge(
|
|
7
7
|
filter: RSMP::Filter.new(ingoing: true, outgoing: false, type: 'Alarm'),
|
|
8
|
-
title:'alarm'
|
|
9
|
-
)
|
|
8
|
+
title: 'alarm'
|
|
9
|
+
))
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return false
|
|
12
|
+
def acceptable?(message)
|
|
13
|
+
return false if super == false
|
|
14
|
+
return false unless fixed_attributes_match?(message)
|
|
15
|
+
return false unless rvs_attributes_match?(message)
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
true
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def fixed_attributes_match?(message)
|
|
23
|
+
%w[cId aCId aSp ack aS sS cat pri].each do |key|
|
|
18
24
|
want = @matcher[key]
|
|
19
25
|
got = message.attribute(key)
|
|
20
26
|
case want
|
|
@@ -24,26 +30,28 @@ module RSMP
|
|
|
24
30
|
return false if got != want
|
|
25
31
|
end
|
|
26
32
|
end
|
|
33
|
+
true
|
|
34
|
+
end
|
|
27
35
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
def rvs_attributes_match?(message)
|
|
37
|
+
return true unless @matcher['rvs']
|
|
38
|
+
|
|
39
|
+
matcher_rvs = @matcher['rvs']
|
|
40
|
+
message_rvs = message.attributes['rvs']
|
|
41
|
+
return false unless message_rvs
|
|
42
|
+
|
|
43
|
+
matcher_rvs.all? do |matcher_item|
|
|
44
|
+
message_rvs.any? do |message_item|
|
|
45
|
+
message_item['n'] == matcher_item['n'] && message_item['v'] == matcher_item['v']
|
|
38
46
|
end
|
|
39
47
|
end
|
|
40
|
-
true
|
|
41
48
|
end
|
|
42
49
|
|
|
50
|
+
public
|
|
51
|
+
|
|
43
52
|
# return a string that describes what we're collecting
|
|
44
53
|
def describe_matcher
|
|
45
|
-
"#{describe_num_and_type} #{
|
|
54
|
+
"#{describe_num_and_type} #{{ component: @options[:component] }.merge(@matcher).compact}"
|
|
46
55
|
end
|
|
47
|
-
|
|
48
56
|
end
|
|
49
|
-
end
|
|
57
|
+
end
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
module RSMP
|
|
2
2
|
# Match a specific alarm
|
|
3
3
|
class AlarmMatcher < Matcher
|
|
4
|
-
|
|
5
|
-
def match? item
|
|
4
|
+
def match?(item)
|
|
6
5
|
return false if @want['n'] && @want['n'] != item['n']
|
|
6
|
+
|
|
7
7
|
if @want['v'].is_a? Regexp
|
|
8
8
|
return false if item['v'] !~ @want['v']
|
|
9
9
|
elsif @want['v']
|
|
@@ -12,4 +12,4 @@ module RSMP
|
|
|
12
12
|
true
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
|
-
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module RSMP
|
|
2
|
+
class Collector
|
|
3
|
+
module Logging
|
|
4
|
+
def log_start
|
|
5
|
+
@distributor.log "#{identifier}: Waiting for #{describe_matcher}".strip, level: :collect
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def log_incomplete
|
|
9
|
+
@distributor.log "#{identifier}: #{describe_progress}", level: :collect
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def log_complete
|
|
13
|
+
@distributor.log "#{identifier}: Done", level: :collect
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module RSMP
|
|
2
|
+
class Collector
|
|
3
|
+
# Progress reporting and description methods for collectors
|
|
4
|
+
module Reporting
|
|
5
|
+
# return a string describing the types of messages we're collecting
|
|
6
|
+
def describe_types
|
|
7
|
+
[@filter&.type].flatten.join('/')
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# return a string that describes whe number of messages, and type of message we're collecting
|
|
11
|
+
def describe_num_and_type
|
|
12
|
+
if @num && @num > 1
|
|
13
|
+
"#{@num} #{describe_types}s"
|
|
14
|
+
else
|
|
15
|
+
describe_types
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# return a string that describes the attributes that we're looking for
|
|
20
|
+
def describe_matcher
|
|
21
|
+
h = { component: @filter&.component }.compact
|
|
22
|
+
if h.empty?
|
|
23
|
+
describe_num_and_type
|
|
24
|
+
else
|
|
25
|
+
"#{describe_num_and_type} #{h}"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Build a string describing how far progress reached before timeout
|
|
30
|
+
def describe_progress
|
|
31
|
+
str = "#{@title.capitalize} #{identifier} "
|
|
32
|
+
str << "in response to #{@m_id} " if @m_id
|
|
33
|
+
str << "timed out after #{@timeout}s, "
|
|
34
|
+
str << "reaching #{@messages.size}/#{@num}"
|
|
35
|
+
str
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# get a short id in hex format, identifying ourself
|
|
39
|
+
def identifier
|
|
40
|
+
"Collect #{object_id.to_s(16)}"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module RSMP
|
|
2
|
+
class Collector
|
|
3
|
+
# Status predicate methods for collectors
|
|
4
|
+
module Status
|
|
5
|
+
def collecting?
|
|
6
|
+
@status == :collecting
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def ok?
|
|
10
|
+
@status == :ok
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def timeout?
|
|
14
|
+
@status == :timeout
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def ready?
|
|
18
|
+
@status == :ready
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def cancelled?
|
|
22
|
+
@status == :cancelled
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def ingoing?
|
|
26
|
+
@ingoing == true
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def outgoing?
|
|
30
|
+
@outgoing == true
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|