rsmp 0.37.0 → 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 (106) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/devcontainer.json +22 -0
  3. data/.github/workflows/rubocop.yaml +17 -0
  4. data/.gitignore +5 -6
  5. data/.rubocop.yml +80 -0
  6. data/Gemfile +13 -1
  7. data/Gemfile.lock +34 -1
  8. data/Rakefile +3 -3
  9. data/lib/rsmp/cli.rb +147 -124
  10. data/lib/rsmp/collect/ack_collector.rb +8 -7
  11. data/lib/rsmp/collect/aggregated_status_collector.rb +4 -4
  12. data/lib/rsmp/collect/alarm_collector.rb +31 -23
  13. data/lib/rsmp/collect/alarm_matcher.rb +3 -3
  14. data/lib/rsmp/collect/collector/logging.rb +17 -0
  15. data/lib/rsmp/collect/collector/reporting.rb +44 -0
  16. data/lib/rsmp/collect/collector/status.rb +34 -0
  17. data/lib/rsmp/collect/collector.rb +69 -150
  18. data/lib/rsmp/collect/command_matcher.rb +19 -6
  19. data/lib/rsmp/collect/command_response_collector.rb +7 -7
  20. data/lib/rsmp/collect/distributor.rb +14 -11
  21. data/lib/rsmp/collect/filter.rb +31 -15
  22. data/lib/rsmp/collect/matcher.rb +7 -11
  23. data/lib/rsmp/collect/queue.rb +4 -4
  24. data/lib/rsmp/collect/receiver.rb +10 -12
  25. data/lib/rsmp/collect/state_collector.rb +116 -77
  26. data/lib/rsmp/collect/status_collector.rb +6 -6
  27. data/lib/rsmp/collect/status_matcher.rb +17 -7
  28. data/lib/rsmp/{alarm_state.rb → component/alarm_state.rb} +76 -37
  29. data/lib/rsmp/{component.rb → component/component.rb} +15 -15
  30. data/lib/rsmp/component/component_base.rb +89 -0
  31. data/lib/rsmp/component/component_proxy.rb +75 -0
  32. data/lib/rsmp/component/components.rb +63 -0
  33. data/lib/rsmp/convert/export/json_schema.rb +116 -110
  34. data/lib/rsmp/convert/import/yaml.rb +21 -18
  35. data/lib/rsmp/{rsmp.rb → helpers/clock.rb} +5 -6
  36. data/lib/rsmp/{deep_merge.rb → helpers/deep_merge.rb} +2 -1
  37. data/lib/rsmp/helpers/error.rb +71 -0
  38. data/lib/rsmp/{inspect.rb → helpers/inspect.rb} +6 -10
  39. data/lib/rsmp/log/archive.rb +98 -0
  40. data/lib/rsmp/log/colorization.rb +41 -0
  41. data/lib/rsmp/log/filtering.rb +54 -0
  42. data/lib/rsmp/log/logger.rb +206 -0
  43. data/lib/rsmp/{logging.rb → log/logging.rb} +5 -7
  44. data/lib/rsmp/message.rb +159 -148
  45. data/lib/rsmp/{node.rb → node/node.rb} +19 -17
  46. data/lib/rsmp/{protocol.rb → node/protocol.rb} +5 -3
  47. data/lib/rsmp/node/site/site.rb +195 -0
  48. data/lib/rsmp/node/supervisor/modules/configuration.rb +59 -0
  49. data/lib/rsmp/node/supervisor/modules/connection.rb +140 -0
  50. data/lib/rsmp/node/supervisor/modules/sites.rb +64 -0
  51. data/lib/rsmp/node/supervisor/supervisor.rb +72 -0
  52. data/lib/rsmp/{task.rb → node/task.rb} +12 -14
  53. data/lib/rsmp/proxy/modules/acknowledgements.rb +144 -0
  54. data/lib/rsmp/proxy/modules/receive.rb +119 -0
  55. data/lib/rsmp/proxy/modules/send.rb +76 -0
  56. data/lib/rsmp/proxy/modules/state.rb +25 -0
  57. data/lib/rsmp/proxy/modules/tasks.rb +105 -0
  58. data/lib/rsmp/proxy/modules/versions.rb +69 -0
  59. data/lib/rsmp/proxy/modules/watchdogs.rb +66 -0
  60. data/lib/rsmp/proxy/proxy.rb +199 -0
  61. data/lib/rsmp/proxy/site/modules/aggregated_status.rb +52 -0
  62. data/lib/rsmp/proxy/site/modules/alarms.rb +27 -0
  63. data/lib/rsmp/proxy/site/modules/commands.rb +31 -0
  64. data/lib/rsmp/proxy/site/modules/status.rb +110 -0
  65. data/lib/rsmp/proxy/site/site_proxy.rb +205 -0
  66. data/lib/rsmp/proxy/supervisor/modules/aggregated_status.rb +47 -0
  67. data/lib/rsmp/proxy/supervisor/modules/alarms.rb +73 -0
  68. data/lib/rsmp/proxy/supervisor/modules/commands.rb +53 -0
  69. data/lib/rsmp/proxy/supervisor/modules/status.rb +204 -0
  70. data/lib/rsmp/proxy/supervisor/supervisor_proxy.rb +178 -0
  71. data/lib/rsmp/tlc/detector_logic.rb +18 -34
  72. data/lib/rsmp/tlc/input_states.rb +126 -0
  73. data/lib/rsmp/tlc/modules/detector_logics.rb +50 -0
  74. data/lib/rsmp/tlc/modules/display.rb +78 -0
  75. data/lib/rsmp/tlc/modules/helpers.rb +41 -0
  76. data/lib/rsmp/tlc/modules/inputs.rb +173 -0
  77. data/lib/rsmp/tlc/modules/modes.rb +253 -0
  78. data/lib/rsmp/tlc/modules/outputs.rb +30 -0
  79. data/lib/rsmp/tlc/modules/plans.rb +218 -0
  80. data/lib/rsmp/tlc/modules/signal_groups.rb +109 -0
  81. data/lib/rsmp/tlc/modules/startup_sequence.rb +22 -0
  82. data/lib/rsmp/tlc/modules/system.rb +140 -0
  83. data/lib/rsmp/tlc/modules/traffic_data.rb +49 -0
  84. data/lib/rsmp/tlc/signal_group.rb +37 -41
  85. data/lib/rsmp/tlc/signal_plan.rb +14 -11
  86. data/lib/rsmp/tlc/signal_priority.rb +39 -35
  87. data/lib/rsmp/tlc/startup_sequence.rb +59 -0
  88. data/lib/rsmp/tlc/traffic_controller.rb +38 -1010
  89. data/lib/rsmp/tlc/traffic_controller_site.rb +58 -57
  90. data/lib/rsmp/version.rb +1 -1
  91. data/lib/rsmp.rb +82 -48
  92. data/rsmp.gemspec +24 -31
  93. metadata +79 -139
  94. data/lib/rsmp/archive.rb +0 -76
  95. data/lib/rsmp/collect/message_matchers.rb +0 -0
  96. data/lib/rsmp/component_base.rb +0 -87
  97. data/lib/rsmp/component_proxy.rb +0 -57
  98. data/lib/rsmp/components.rb +0 -65
  99. data/lib/rsmp/error.rb +0 -71
  100. data/lib/rsmp/logger.rb +0 -216
  101. data/lib/rsmp/proxy.rb +0 -693
  102. data/lib/rsmp/site.rb +0 -188
  103. data/lib/rsmp/site_proxy.rb +0 -389
  104. data/lib/rsmp/supervisor.rb +0 -302
  105. data/lib/rsmp/supervisor_proxy.rb +0 -510
  106. data/lib/rsmp/tlc/inputs.rb +0 -134
@@ -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
@@ -1,18 +1,21 @@
1
1
  module RSMP
2
-
3
2
  # Collects messages from a distributor.
4
3
  # Can filter by message type, componet and direction.
5
4
  # Wakes up the once the desired number of messages has been collected.
6
5
  class Collector
7
6
  include Receiver
7
+ include Status
8
+ include Reporting
9
+ include Logging
10
+
8
11
  attr_reader :condition, :messages, :status, :error, :task, :m_id
9
12
 
10
- def initialize distributor, options={}
13
+ def initialize(distributor, options = {})
11
14
  initialize_receiver distributor, filter: options[:filter]
12
15
  @options = {
13
16
  cancel: {
14
17
  schema_error: true,
15
- disconnect: false,
18
+ disconnect: false
16
19
  }
17
20
  }.deep_merge options
18
21
  @timeout = options[:timeout]
@@ -20,34 +23,31 @@ module RSMP
20
23
  @m_id = options[:m_id]
21
24
  @condition = Async::Notification.new
22
25
  make_title options[:title]
23
-
26
+
24
27
  if task
25
28
  @task = task
26
- else
27
- # if distributor is a Proxy, or some other object that implements task(),
28
- # then try to get the task that way
29
- if distributor.respond_to? 'task'
30
- @task = distributor.task
31
- end
29
+ elsif distributor.respond_to? 'task'
30
+ # if distributor is a Proxy, or some other object that implements task(),
31
+ # then try to get the task that way
32
+ @task = distributor.task
32
33
  end
33
34
  reset
34
35
  end
35
36
 
36
- def make_title title
37
- if title
38
- @title = title
39
- elsif @filter
40
- @title = [@filter.type].flatten.join('/')
41
- else
42
- @title = ""
43
- end
37
+ def make_title(title)
38
+ @title = if title
39
+ title
40
+ elsif @filter
41
+ [@filter.type].flatten.join('/')
42
+ else
43
+ ''
44
+ end
44
45
  end
45
46
 
46
- def use_task task
47
+ def use_task(task)
47
48
  @task = task
48
49
  end
49
50
 
50
- # Clear all matcher results
51
51
  def reset
52
52
  @messages = []
53
53
  @error = nil
@@ -56,65 +56,31 @@ module RSMP
56
56
 
57
57
  # Inspect formatter that shows the message we have collected
58
58
  def inspect
59
- "#<#{self.class.name}:#{self.object_id}, #{inspector(:@messages)}>"
60
- end
61
-
62
- # Is collection active?
63
- def collecting?
64
- @status == :collecting
65
- end
66
-
67
- # Is collection complete?
68
- def ok?
69
- @status == :ok
70
- end
71
-
72
- # Has collection timed out?
73
- def timeout?
74
- @status == :timeout
75
- end
76
-
77
- # Is collection ready to start?
78
- def ready?
79
- @status == :ready
80
- end
81
-
82
- # Has collection been cancelled?
83
- def cancelled?
84
- @status == :cancelled
85
- end
86
-
87
- # Want ingoing messages?
88
- def ingoing?
89
- @ingoing == true
90
- end
91
-
92
- # Want outgoing messages?
93
- def outgoing?
94
- @outgoing == true
59
+ "#<#{self.class.name}:#{object_id}, #{inspector(:@messages)}>"
95
60
  end
96
61
 
97
62
  # if an errors caused collection to abort, then raise it
98
63
  # return self, so this can be tucked on to calls that return a collector
99
64
  def ok!
100
65
  raise @error if @error
66
+
101
67
  self
102
68
  end
103
69
 
104
70
  # Collect message
105
71
  # Will return once all messages have been collected, or timeout is reached
106
- def collect &block
107
- start &block
72
+ def collect(&)
73
+ start(&)
108
74
  wait
109
75
  @status
110
76
  ensure
111
- @distributor.remove_receiver self if @distributor
77
+ @distributor&.remove_receiver self
112
78
  end
113
79
 
114
80
  # Collect message
115
81
  # Returns the collected messages, or raise an exception in case of a time out.
116
- def collect! &block
117
- collect(&block)
82
+ def collect!(&)
83
+ collect(&)
118
84
  ok!
119
85
  @messages
120
86
  end
@@ -141,40 +107,44 @@ module RSMP
141
107
  def wait!
142
108
  wait
143
109
  raise @error if timeout?
110
+
144
111
  @messages
145
112
  end
146
113
 
147
114
  # Start collection and return immediately
148
115
  # You can later use wait() to wait for completion
149
- def start &block
150
- raise RuntimeError.new("Can't start collectimng unless ready (currently #{@status})") unless ready?
116
+ def start(&block)
117
+ raise "Can't start collectimng unless ready (currently #{@status})" unless ready?
118
+
151
119
  @block = block
152
- raise ArgumentError.new("Num, timeout or block must be provided") unless @num || @timeout || @block
120
+ raise ArgumentError, 'Num, timeout or block must be provided' unless @num || @timeout || @block
121
+
153
122
  reset
154
123
  @status = :collecting
155
124
  log_start
156
- @distributor.add_receiver self if @distributor
125
+ @distributor&.add_receiver self
157
126
  end
158
127
 
159
128
  # Check if we receive a NotAck related to initiating request, identified by @m_id.
160
- def reject_not_ack message
129
+ def reject_not_ack(message)
161
130
  return unless @m_id
162
- if message.is_a?(MessageNotAck)
163
- if message.attribute('oMId') == @m_id
164
- m_id_short = RSMP::Message.shorten_m_id @m_id, 8
165
- cancel RSMP::MessageRejected.new("#{@title} #{m_id_short} was rejected with '#{message.attribute('rea')}'")
166
- @distributor.log "#{identifier}: cancelled due to a NotAck", level: :debug
167
- true
168
- end
169
- end
131
+
132
+ return unless message.is_a?(MessageNotAck)
133
+ return unless message.attribute('oMId') == @m_id
134
+
135
+ m_id_short = RSMP::Message.shorten_m_id @m_id, 8
136
+ cancel RSMP::MessageRejected.new("#{@title} #{m_id_short} was rejected with '#{message.attribute('rea')}'")
137
+ @distributor.log "#{identifier}: cancelled due to a NotAck", level: :debug
138
+ true
170
139
  end
171
140
 
172
- # Handle message. and return true when we're done collecting
173
- def receive message
141
+ # Handle message and return true if we're done collecting
142
+ def receive(message)
174
143
  raise ArgumentError unless message
175
144
  unless ready? || collecting?
176
- raise RuntimeError.new("can't process message when status is :#{@status}, title: #{@title}, desc: #{describe}")
145
+ raise "can't process message when status is :#{@status}, title: #{@title}, desc: #{describe}"
177
146
  end
147
+
178
148
  if perform_match message
179
149
  if done?
180
150
  complete
@@ -185,17 +155,17 @@ module RSMP
185
155
  @status
186
156
  end
187
157
 
188
- def describe
189
- end
158
+ def describe; end
190
159
 
191
160
  # Match message against our collection criteria
192
- def perform_match message
161
+ def perform_match(message)
193
162
  return false if reject_not_ack(message)
194
163
  return false unless acceptable?(message)
195
- #@distributor.log "#{identifier}: Looking at #{message.type} #{message.m_id_short}", level: :collect
164
+
196
165
  if @block
197
166
  status = [@block.call(message)].flatten
198
167
  return unless collecting?
168
+
199
169
  keep message if status.include?(:keep)
200
170
  else
201
171
  keep message
@@ -227,9 +197,8 @@ module RSMP
227
197
  @condition.signal
228
198
  end
229
199
 
230
- # An error occured upstream.
231
- # Check if we should cancel.
232
- def receive_error error, options={}
200
+ # Handle upstream error
201
+ def receive_error(error, options = {})
233
202
  case error
234
203
  when RSMP::SchemaError
235
204
  receive_schema_error error, options
@@ -239,93 +208,43 @@ module RSMP
239
208
  end
240
209
 
241
210
  # Cancel if we received e schema error for a message type we're collecting
242
- def receive_schema_error error, options
243
- return unless @options.dig(:cancel,:schema_error)
211
+ def receive_schema_error(error, options)
212
+ return unless @options.dig(:cancel, :schema_error)
213
+
244
214
  message = options[:message]
245
215
  return unless message
216
+
246
217
  klass = message.class.name.split('::').last
247
- return unless @filter&.type == nil || [@filter&.type].flatten.include?(klass)
218
+ return unless @filter&.type.nil? || [@filter&.type].flatten.include?(klass)
219
+
248
220
  @distributor.log "#{identifier}: cancelled due to schema error in #{klass} #{message.m_id_short}", level: :debug
249
221
  cancel error
250
222
  end
251
223
 
252
- # Cancel if we received e notificaiton about a disconnect
253
- def receive_disconnect error, options
254
- return unless @options.dig(:cancel,:disconnect)
255
- @distributor.log "#{identifier}: cancelled due to a connection error: #{error.to_s}", level: :debug
224
+ # Cancel if we received e notifiction about a disconnect
225
+ def receive_disconnect(error, _options)
226
+ return unless @options.dig(:cancel, :disconnect)
227
+
228
+ @distributor.log "#{identifier}: cancelled due to a connection error: #{error}", level: :debug
256
229
  cancel error
257
230
  end
258
231
 
259
232
  # Abort collection
260
- def cancel error=nil
233
+ def cancel(error = nil)
261
234
  @error = error
262
235
  @status = :cancelled
263
236
  do_stop
264
237
  end
265
238
 
266
239
  # Store a message in the result array
267
- def keep message
240
+ def keep(message)
268
241
  @messages << message
269
242
  end
270
243
 
271
244
  # Check a message against our match criteria
272
245
  # Return true if there's a match, false if not
273
- def acceptable? message
274
- @filter == nil || @filter.accept?(message)
246
+ def acceptable?(message)
247
+ @filter.nil? || @filter.accept?(message)
275
248
  end
276
-
277
- # return a string describing the types of messages we're collecting
278
- def describe_types
279
- [@filter&.type].flatten.join('/')
280
- end
281
-
282
- # return a string that describes whe number of messages, and type of message we're collecting
283
- def describe_num_and_type
284
- if @num && @num > 1
285
- "#{@num} #{describe_types}s"
286
- else
287
- describe_types
288
- end
289
- end
290
-
291
- # return a string that describes the attributes that we're looking for
292
- def describe_matcher
293
- h = {component: @filter&.component}.compact
294
- if h.empty?
295
- describe_num_and_type
296
- else
297
- "#{describe_num_and_type} #{h}"
298
- end
299
- end
300
-
301
- # Build a string describing how how progress reached before timeout
302
- def describe_progress
303
- str = "#{@title.capitalize} #{identifier} "
304
- str << "in response to #{@m_id} " if @m_id
305
- str << "timed out after #{@timeout}s, "
306
- str << "reaching #{@messages.size}/#{@num}"
307
- str
308
- end
309
-
310
- # log when we start collecting
311
- def log_start
312
- @distributor.log "#{identifier}: Waiting for #{describe_matcher}".strip, level: :collect
313
- end
314
-
315
- # log current progress
316
- def log_incomplete
317
- @distributor.log "#{identifier}: #{describe_progress}", level: :collect
318
- end
319
-
320
- # log when we end collecting
321
- def log_complete
322
- @distributor.log "#{identifier}: Done", level: :collect
323
- end
324
-
325
- # get a short id in hex format, identifying ourself
326
- def identifier
327
- "Collect #{self.object_id.to_s(16)}"
328
- end
329
-
330
249
  end
331
- end
250
+ end
@@ -1,16 +1,29 @@
1
1
  module RSMP
2
- # Match a specific command responses
2
+ # Class for matching a command
3
3
  class CommandMatcher < Matcher
4
- # Match a return value item against a matcher
5
- def match? item
4
+ def match_code?(item)
6
5
  return nil if @want['cCI'] && @want['cCI'] != item['cCI']
7
6
  return nil if @want['n'] && @want['n'] != item['n']
7
+
8
+ true
9
+ end
10
+
11
+ def match_value?(item)
12
+ return true unless @want['v']
13
+
8
14
  if @want['v'].is_a? Regexp
9
- return false if @want['v'] && item['v'] !~ @want['v']
10
- else
11
- return false if @want['v'] && item['v'] != @want['v']
15
+ return false if item['v'] !~ @want['v']
16
+ elsif item['v'] != @want['v']
17
+ return false
12
18
  end
13
19
  true
14
20
  end
21
+
22
+ def match?(item)
23
+ code_match = match_code?(item)
24
+ return code_match if code_match.nil?
25
+
26
+ match_value?(item)
27
+ end
15
28
  end
16
29
  end
@@ -1,20 +1,20 @@
1
1
  module RSMP
2
2
  # Class for waiting for specific command responses
3
3
  class CommandResponseCollector < StateCollector
4
- def initialize proxy, want, options={}
5
- super proxy, want, options.merge(
4
+ def initialize(proxy, want, options = {})
5
+ super(proxy, want, options.merge(
6
6
  filter: RSMP::Filter.new(ingoing: true, outgoing: false, type: 'CommandResponse'),
7
- title:'command response'
8
- )
7
+ title: 'command response'
8
+ ))
9
9
  end
10
10
 
11
- def build_matcher want
11
+ def build_matcher(want)
12
12
  CommandMatcher.new want
13
13
  end
14
14
 
15
15
  # Get items, in our case the return values
16
- def get_items message
16
+ def get_items(message)
17
17
  message.attributes['rvs'] || []
18
18
  end
19
19
  end
20
- end
20
+ end
@@ -1,13 +1,12 @@
1
- # Distributes messages to receivers
2
-
3
1
  module RSMP
2
+ # Class which distributes messages to receivers
4
3
  module Distributor
5
4
  attr_reader :receivers
6
5
 
7
6
  include Inspect
8
7
 
9
8
  def inspect
10
- "#<#{self.class.name}:#{self.object_id}, #{inspector(:@receivers)}>"
9
+ "#<#{self.class.name}:#{object_id}, #{inspector(:@receivers)}>"
11
10
  end
12
11
 
13
12
  def initialize_distributor
@@ -16,12 +15,13 @@ module RSMP
16
15
  @deferred_messages = []
17
16
  end
18
17
 
19
- def clear_deferred_distribution &block
18
+ def clear_deferred_distribution
20
19
  @deferred_messages = []
21
20
  end
22
21
 
23
- def with_deferred_distribution &block
24
- was, @defer_distribution = @defer_distribution, true
22
+ def with_deferred_distribution
23
+ was = @defer_distribution
24
+ @defer_distribution = true
25
25
  yield
26
26
  distribute_queued
27
27
  ensure
@@ -35,18 +35,21 @@ module RSMP
35
35
  @deferred_messages = []
36
36
  end
37
37
 
38
- def add_receiver receiver
38
+ def add_receiver(receiver)
39
39
  raise ArgumentError unless receiver
40
+
40
41
  @receivers << receiver unless @receivers.include? receiver
41
42
  end
42
43
 
43
- def remove_receiver receiver
44
+ def remove_receiver(receiver)
44
45
  raise ArgumentError unless receiver
46
+
45
47
  @receivers.delete receiver
46
48
  end
47
49
 
48
- def distribute message
50
+ def distribute(message)
49
51
  raise ArgumentError unless message
52
+
50
53
  if @defer_distribution
51
54
  @deferred_messages << message
52
55
  else
@@ -54,11 +57,11 @@ module RSMP
54
57
  end
55
58
  end
56
59
 
57
- def distribute_immediately message
60
+ def distribute_immediately(message)
58
61
  @receivers.each { |receiver| receiver.receive message }
59
62
  end
60
63
 
61
- def distribute_error error, options={}
64
+ def distribute_error(error, options = {})
62
65
  @receivers.each { |receiver| receiver.receive_error error, options }
63
66
  end
64
67
  end