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.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/devcontainer.json +22 -0
  3. data/.github/copilot-instructions.md +33 -0
  4. data/.github/workflows/copilot-setup-steps.yml +35 -0
  5. data/.github/workflows/rspec.yaml +2 -1
  6. data/.github/workflows/rubocop.yaml +17 -0
  7. data/.gitignore +7 -7
  8. data/.rubocop.yml +80 -0
  9. data/Gemfile +13 -1
  10. data/Gemfile.lock +73 -35
  11. data/Rakefile +3 -3
  12. data/bin/console +2 -4
  13. data/documentation/tasks.md +4 -4
  14. data/lib/rsmp/cli.rb +147 -124
  15. data/lib/rsmp/collect/ack_collector.rb +8 -7
  16. data/lib/rsmp/collect/aggregated_status_collector.rb +4 -4
  17. data/lib/rsmp/collect/alarm_collector.rb +31 -23
  18. data/lib/rsmp/collect/alarm_matcher.rb +3 -3
  19. data/lib/rsmp/collect/collector/logging.rb +17 -0
  20. data/lib/rsmp/collect/collector/reporting.rb +44 -0
  21. data/lib/rsmp/collect/collector/status.rb +34 -0
  22. data/lib/rsmp/collect/collector.rb +69 -150
  23. data/lib/rsmp/collect/command_matcher.rb +19 -6
  24. data/lib/rsmp/collect/command_response_collector.rb +7 -7
  25. data/lib/rsmp/collect/distributor.rb +14 -11
  26. data/lib/rsmp/collect/filter.rb +31 -15
  27. data/lib/rsmp/collect/matcher.rb +7 -11
  28. data/lib/rsmp/collect/queue.rb +4 -4
  29. data/lib/rsmp/collect/receiver.rb +10 -12
  30. data/lib/rsmp/collect/state_collector.rb +116 -77
  31. data/lib/rsmp/collect/status_collector.rb +6 -6
  32. data/lib/rsmp/collect/status_matcher.rb +17 -7
  33. data/lib/rsmp/{alarm_state.rb → component/alarm_state.rb} +76 -37
  34. data/lib/rsmp/{component.rb → component/component.rb} +15 -15
  35. data/lib/rsmp/component/component_base.rb +89 -0
  36. data/lib/rsmp/component/component_proxy.rb +75 -0
  37. data/lib/rsmp/component/components.rb +63 -0
  38. data/lib/rsmp/convert/export/json_schema.rb +116 -110
  39. data/lib/rsmp/convert/import/yaml.rb +21 -18
  40. data/lib/rsmp/{rsmp.rb → helpers/clock.rb} +5 -6
  41. data/lib/rsmp/{deep_merge.rb → helpers/deep_merge.rb} +2 -1
  42. data/lib/rsmp/helpers/error.rb +71 -0
  43. data/lib/rsmp/{inspect.rb → helpers/inspect.rb} +6 -10
  44. data/lib/rsmp/log/archive.rb +98 -0
  45. data/lib/rsmp/log/colorization.rb +41 -0
  46. data/lib/rsmp/log/filtering.rb +54 -0
  47. data/lib/rsmp/log/logger.rb +206 -0
  48. data/lib/rsmp/{logging.rb → log/logging.rb} +5 -7
  49. data/lib/rsmp/message.rb +159 -148
  50. data/lib/rsmp/{node.rb → node/node.rb} +19 -17
  51. data/lib/rsmp/node/protocol.rb +37 -0
  52. data/lib/rsmp/node/site/site.rb +195 -0
  53. data/lib/rsmp/node/supervisor/modules/configuration.rb +59 -0
  54. data/lib/rsmp/node/supervisor/modules/connection.rb +140 -0
  55. data/lib/rsmp/node/supervisor/modules/sites.rb +64 -0
  56. data/lib/rsmp/node/supervisor/supervisor.rb +72 -0
  57. data/lib/rsmp/{task.rb → node/task.rb} +29 -19
  58. data/lib/rsmp/proxy/modules/acknowledgements.rb +144 -0
  59. data/lib/rsmp/proxy/modules/receive.rb +119 -0
  60. data/lib/rsmp/proxy/modules/send.rb +76 -0
  61. data/lib/rsmp/proxy/modules/state.rb +25 -0
  62. data/lib/rsmp/proxy/modules/tasks.rb +105 -0
  63. data/lib/rsmp/proxy/modules/versions.rb +69 -0
  64. data/lib/rsmp/proxy/modules/watchdogs.rb +66 -0
  65. data/lib/rsmp/proxy/proxy.rb +199 -0
  66. data/lib/rsmp/proxy/site/modules/aggregated_status.rb +52 -0
  67. data/lib/rsmp/proxy/site/modules/alarms.rb +27 -0
  68. data/lib/rsmp/proxy/site/modules/commands.rb +31 -0
  69. data/lib/rsmp/proxy/site/modules/status.rb +110 -0
  70. data/lib/rsmp/proxy/site/site_proxy.rb +205 -0
  71. data/lib/rsmp/proxy/supervisor/modules/aggregated_status.rb +47 -0
  72. data/lib/rsmp/proxy/supervisor/modules/alarms.rb +73 -0
  73. data/lib/rsmp/proxy/supervisor/modules/commands.rb +53 -0
  74. data/lib/rsmp/proxy/supervisor/modules/status.rb +204 -0
  75. data/lib/rsmp/proxy/supervisor/supervisor_proxy.rb +178 -0
  76. data/lib/rsmp/tlc/detector_logic.rb +18 -34
  77. data/lib/rsmp/tlc/input_states.rb +126 -0
  78. data/lib/rsmp/tlc/modules/detector_logics.rb +50 -0
  79. data/lib/rsmp/tlc/modules/display.rb +78 -0
  80. data/lib/rsmp/tlc/modules/helpers.rb +41 -0
  81. data/lib/rsmp/tlc/modules/inputs.rb +173 -0
  82. data/lib/rsmp/tlc/modules/modes.rb +253 -0
  83. data/lib/rsmp/tlc/modules/outputs.rb +30 -0
  84. data/lib/rsmp/tlc/modules/plans.rb +218 -0
  85. data/lib/rsmp/tlc/modules/signal_groups.rb +109 -0
  86. data/lib/rsmp/tlc/modules/startup_sequence.rb +22 -0
  87. data/lib/rsmp/tlc/modules/system.rb +140 -0
  88. data/lib/rsmp/tlc/modules/traffic_data.rb +49 -0
  89. data/lib/rsmp/tlc/signal_group.rb +37 -41
  90. data/lib/rsmp/tlc/signal_plan.rb +14 -11
  91. data/lib/rsmp/tlc/signal_priority.rb +39 -35
  92. data/lib/rsmp/tlc/startup_sequence.rb +59 -0
  93. data/lib/rsmp/tlc/traffic_controller.rb +39 -1006
  94. data/lib/rsmp/tlc/traffic_controller_site.rb +58 -57
  95. data/lib/rsmp/version.rb +1 -1
  96. data/lib/rsmp.rb +86 -49
  97. data/rsmp.gemspec +24 -30
  98. metadata +87 -130
  99. data/lib/rsmp/archive.rb +0 -76
  100. data/lib/rsmp/collect/message_matchers.rb +0 -0
  101. data/lib/rsmp/component_base.rb +0 -87
  102. data/lib/rsmp/component_proxy.rb +0 -57
  103. data/lib/rsmp/components.rb +0 -65
  104. data/lib/rsmp/error.rb +0 -71
  105. data/lib/rsmp/logger.rb +0 -216
  106. data/lib/rsmp/proxy.rb +0 -695
  107. data/lib/rsmp/site.rb +0 -188
  108. data/lib/rsmp/site_proxy.rb +0 -389
  109. data/lib/rsmp/supervisor.rb +0 -287
  110. data/lib/rsmp/supervisor_proxy.rb +0 -516
  111. data/lib/rsmp/tlc/inputs.rb +0 -134
data/lib/rsmp/cli.rb CHANGED
@@ -1,186 +1,208 @@
1
1
  require 'thor'
2
- require 'rsmp'
2
+ require_relative '../rsmp'
3
3
 
4
4
  module RSMP
5
5
  class CLI < Thor
6
- desc "version", "Show version"
6
+ desc 'version', 'Show version'
7
7
  def version
8
8
  puts RSMP::VERSION
9
9
  end
10
10
 
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", banner: 'ip:port,... list of supervisor to connect to'
15
- method_option :core, :string => :string, banner: "Core version: [#{RSMP::Schema.core_versions.join(' ')}]", enum: RSMP::Schema.core_versions
16
- method_option :type, :type => :string, :aliases => "-t", banner: 'Type of site: [tlc]', enum: ['tlc'], default: 'tlc'
17
- method_option :log, :type => :string, :aliases => "-l", banner: 'Path to log file'
18
- method_option :json, :type => :boolean, :aliases => "-j", banner: 'Show JSON messages in log'
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 = { 'active' => true }
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
- if options[:id]
34
- settings['site_id'] = options[:id]
73
+ [settings, log_settings]
35
74
  end
75
+ end
36
76
 
37
- if options[:supervisors]
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
- if options[:core]
48
- settings['core_version'] = options[:core]
49
- end
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
- site_class = RSMP::Site
52
- site_type = options[:type] || settings['type']
53
- case site_type
54
- when 'tlc'
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
- if options[:log]
62
- log_settings['path'] = options[:log]
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
- if options[:json]
66
- log_settings['json'] = options[:json]
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
- begin
73
- site = site_class.new(site_settings: settings, log_settings: log_settings)
74
- site.start
75
- site.wait
76
- rescue Psych::SyntaxError => e
77
- puts "Cannot read config file #{e}"
78
- break
79
- rescue RSMP::Schema::UnknownSchemaTypeError => e
80
- puts "Cannot start site: #{e}"
81
- break
82
- rescue RSMP::Schema::UnknownSchemaVersionError => e
83
- puts "Cannot start site: #{e}"
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
- desc "supervisor", "Run RSMP supervisor"
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
- if options[:config]
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[:id]
123
- settings['site_id'] = options[:id]
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
- if options[:ip]
127
- settings['ip'] = options[:ip]
128
- end
145
+ [settings, log_settings]
146
+ end
129
147
 
130
- if options[:port]
131
- settings['port'] = options[:port]
132
- end
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
- if options[:core]
135
- settings['guest'] = {}
136
- settings['guest']['core_version'] = options[:core]
137
- end
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
- if options[:log]
140
- log_settings['path'] = options[:log]
141
- end
160
+ def apply_core_version_option(settings)
161
+ return unless options[:core]
142
162
 
143
- if options[:json]
144
- log_settings['json'] = options[:json]
145
- end
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 => e
155
- puts "Cannot start supervisor: #{e}"
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
- desc "convert", "Convert SXL from YAML to JSON Schema"
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 "Error: Input option missing"
188
+ puts 'Error: Input option missing'
171
189
  exit
172
190
  end
173
191
 
174
- unless options[:out]
175
- puts "Error: Output option missing"
176
- exit
177
- end
192
+ return if options[:out]
178
193
 
179
- unless File.exist? options[:in]
180
- puts "Error: Input path file #{options[:in]} not found"
181
- exit
182
- end
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 proxy, options={}
5
- raise ArgumentError.new("m_id must be provided") unless options[:m_id]
6
- super proxy, options.merge(
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? message
15
- super(message) && message.attribute('oMId') == @m_id
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 proxy, options={}
5
- super proxy, options.merge(
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 proxy,options={}
4
+ def initialize(proxy, options = {})
5
5
  @matcher = options[:matcher] || {}
6
- super proxy, options.merge(
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
- # match alarm attributes
13
- def acceptable? message
14
- return false if super(message) == 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
- # match fixed attributes
17
- %w{cId aCId aSp ack aS sS cat pri}.each do |key|
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
- # match rvs items
29
- if @matcher['rvs']
30
- matcher_rvs = @matcher['rvs']
31
- message_rvs = message.attributes['rvs']
32
- return false unless message_rvs
33
- return false unless matcher_rvs.all? do |matcher_item|
34
- return false unless message_rvs.any? do |message_item|
35
- next message_item['n'] == matcher_item['n'] && message_item['v'] == matcher_item['v']
36
- end
37
- next true
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} #{ {component: @options[:component]}.merge(@matcher).compact }"
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
- # Match an alarm value against a matcher
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