Class: RSMP::StateCollector
- Defined in:
- lib/rsmp/collect/state_collector.rb
Overview
Base class for waiting for specific status or command responses, specified by a list of matchers. Matchers are defined as an array of hashes, e.g [
{"cCI"=>"M0104", "cO"=>"setDate", "n"=>"securityCode", "v"=>"1111"},
{"cCI"=>"M0104", "cO"=>"setDate", "n"=>"year", "v"=>"2020"},
{"cCI"=>"M0104", "cO"=>"setDate", "n"=>"month", "v"=>/\d+/}
]
Note that matchers can contain regex patterns for values, like /d+/ in the example above.
When an input messages is received it typically contains several items, eg: [
{"cCI"=>"M0104", "n"=>"month", "v"=>"9", "age"=>"recent"},
{"cCI"=>"M0104", "n"=>"day", "v"=>"29", "age"=>"recent"},
{"cCI"=>"M0104", "n"=>"hour", "v"=>"17", "age"=>"recent"}
]
Each input item is matched against each of the matchers. If a match is found, it’s stored in the @results hash, with the matcher as the key, and a mesage and status as the key. In the example above, this matcher:
“cO”=>“setDate”, “n”=>“month”, “v”=>/d+/
matches this input:
“n”=>“month”, “v”=>“9”, “age”=>“recent”
And the result is stored as:
{"cCI"=>"M0104", "cO"=>"setDate", "n"=>"month", "v"=>/\d+/ =>
{ <StatusResponse >, "cO"=>"setDate", "n"=>"month", "v"=>"9" }
}
Direct Known Subclasses
Instance Attribute Summary collapse
-
#matchers ⇒ Object
readonly
Returns the value of attribute matchers.
Attributes inherited from Collector
#condition, #error, #m_id, #status, #task
Attributes included from Logging
Instance Method Summary collapse
- #add_command_result(hash, want, got) ⇒ Object
- #add_command_want_to_hash(hash, item) ⇒ Object
- #add_status_result(hash, want, got) ⇒ Object
- #add_status_want_to_hash(hash, item) ⇒ Object
-
#build_matcher(want) ⇒ Object
Build a matcher object.
- #describe ⇒ Object
-
#describe_matcher ⇒ Object
return a string that describes the attributes that we’re looking for.
-
#describe_progress ⇒ Object
return a string that describe how many many messages have been collected.
-
#done? ⇒ Boolean
Are there matchers left to type_match?.
- #handle_match_result(matched, matcher, message, item) ⇒ Object
-
#initialize(proxy, want, options = {}) ⇒ StateCollector
constructor
Initialize with a list of wanted statuses.
-
#keep(message) ⇒ Object
don’t collect anything.
-
#log_complete ⇒ Object
log when we end collecting.
- #log_match_result(message, matched, matcher, item) ⇒ Object
- #matcher_got_hash ⇒ Object
-
#matcher_result(want) ⇒ Object
Get a results.
-
#matcher_status ⇒ Object
Get a simplified hash of matchers, with values set to either true or false, indicating which matchers have been matched.
- #matcher_want_hash ⇒ Object
-
#messages ⇒ Object
Get messages from results.
- #perform_match(message) ⇒ Object
-
#progress ⇒ Object
Return progress as completes matchers vs.
-
#progress_hash ⇒ Object
return a hash that describe the status of all matchers.
-
#reached ⇒ Object
Get an array of the last item received for each matcher.
-
#summary ⇒ Object
Get a simply array of bools, showing which matchers have been matched.
Methods inherited from Collector
#acceptable?, #cancel, #collect, #collect!, #complete, #do_stop, #incomplete, #inspect, #make_title, #ok!, #receive, #receive_disconnect, #receive_error, #receive_schema_error, #reject_not_ack, #reset, #start, #use_task, #wait, #wait!
Methods included from Logging
#author, #initialize_logging, #log
Methods included from Collector::Reporting
#describe_num_and_type, #describe_types, #identifier
Methods included from Collector::Status
#cancelled?, #collecting?, #ingoing?, #ok?, #outgoing?, #ready?, #timeout?
Methods included from Receiver
#accept_message?, #handle_message, #initialize_receiver, #receive, #receive_error, #reject_message?, #start_receiving, #stop_receiving
Methods included from Inspect
Constructor Details
#initialize(proxy, want, options = {}) ⇒ StateCollector
Initialize with a list of wanted statuses
38 39 40 41 42 43 |
# File 'lib/rsmp/collect/state_collector.rb', line 38 def initialize(proxy, want, = {}) raise ArgumentError, 'num option cannot be used' if [:num] super(proxy, ) @matchers = want.map { |item| build_matcher item } end |
Instance Attribute Details
#matchers ⇒ Object (readonly)
Returns the value of attribute matchers.
35 36 37 |
# File 'lib/rsmp/collect/state_collector.rb', line 35 def matchers @matchers end |
Instance Method Details
#add_command_result(hash, want, got) ⇒ Object
215 216 217 218 219 220 221 222 223 |
# File 'lib/rsmp/collect/state_collector.rb', line 215 def add_command_result(hash, want, got) cci = want['cCI'] hash[cci] ||= {} co = want['cO'] hash[cci][co] ||= {} n = want['n'] v = got ? got['v'] : nil hash[cci][co][n] = v end |
#add_command_want_to_hash(hash, item) ⇒ Object
197 198 199 200 201 202 203 204 205 |
# File 'lib/rsmp/collect/state_collector.rb', line 197 def add_command_want_to_hash(hash, item) cci = item['cCI'] hash[cci] ||= {} co = item['cO'] hash[cci][co] ||= {} n = item['n'] v = item['v'] hash[cci][co][n] = v || :any end |
#add_status_result(hash, want, got) ⇒ Object
225 226 227 228 229 230 231 |
# File 'lib/rsmp/collect/state_collector.rb', line 225 def add_status_result(hash, want, got) sci = want['sCI'] hash[sci] ||= {} n = want['n'] s = got ? got['s'] : nil hash[sci][n] = s end |
#add_status_want_to_hash(hash, item) ⇒ Object
207 208 209 210 211 212 213 |
# File 'lib/rsmp/collect/state_collector.rb', line 207 def add_status_want_to_hash(hash, item) sci = item['sCI'] hash[sci] ||= {} n = item['n'] s = item['s'] hash[sci][n] = s || :any end |
#build_matcher(want) ⇒ Object
Build a matcher object. Sub-classes should override to use their own matcher classes.
47 48 49 |
# File 'lib/rsmp/collect/state_collector.rb', line 47 def build_matcher(want) Matcher.new want end |
#describe ⇒ Object
128 129 130 |
# File 'lib/rsmp/collect/state_collector.rb', line 128 def describe @matchers.map { |q| q.want.to_s } end |
#describe_matcher ⇒ Object
return a string that describes the attributes that we’re looking for
133 134 135 |
# File 'lib/rsmp/collect/state_collector.rb', line 133 def describe_matcher "#{super} matching #{matcher_want_hash}" end |
#describe_progress ⇒ Object
return a string that describe how many many messages have been collected
178 179 180 181 182 |
# File 'lib/rsmp/collect/state_collector.rb', line 178 def describe_progress num_matchers = @matchers.size num_matched = @matchers.count(&:done?) ".. Matched #{num_matched}/#{num_matchers} with #{progress_hash}" end |
#done? ⇒ Boolean
Are there matchers left to type_match?
77 78 79 |
# File 'lib/rsmp/collect/state_collector.rb', line 77 def done? @matchers.all?(&:done?) end |
#handle_match_result(matched, matcher, message, item) ⇒ Object
98 99 100 101 102 103 104 105 106 107 |
# File 'lib/rsmp/collect/state_collector.rb', line 98 def handle_match_result(matched, matcher, , item) return if matched.nil? log_match_result(, matched, matcher, item) if matched == true matcher.keep , item elsif matched == false matcher.forget end end |
#keep(message) ⇒ Object
don’t collect anything. Matcher will collect them instead
126 |
# File 'lib/rsmp/collect/state_collector.rb', line 126 def keep(); end |
#log_complete ⇒ Object
log when we end collecting
248 249 250 |
# File 'lib/rsmp/collect/state_collector.rb', line 248 def log_complete @distributor.log "#{identifier}: Completed with #{matcher_got_hash}", level: :collect end |
#log_match_result(message, matched, matcher, item) ⇒ Object
92 93 94 95 96 |
# File 'lib/rsmp/collect/state_collector.rb', line 92 def log_match_result(, matched, matcher, item) type = { true => 'match', false => 'mismatch' }[matched] @distributor.log "#{@title.capitalize} #{message.m_id_short} collect #{type} #{matcher.want}, item #{item}", level: :debug end |
#matcher_got_hash ⇒ Object
233 234 235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/rsmp/collect/state_collector.rb', line 233 def matcher_got_hash h = {} @matchers.each do |matcher| want = matcher.want got = matcher.got if want['cCI'] add_command_result(h, want, got) elsif want['sCI'] add_status_result(h, want, got) end end h end |
#matcher_result(want) ⇒ Object
Get a results
52 53 54 55 56 57 |
# File 'lib/rsmp/collect/state_collector.rb', line 52 def matcher_result(want) matcher = @matchers.find { |q| q.want == want } raise unless matcher matcher.got end |
#matcher_status ⇒ Object
Get a simplified hash of matchers, with values set to either true or false, indicating which matchers have been matched.
83 84 85 |
# File 'lib/rsmp/collect/state_collector.rb', line 83 def matcher_status @matchers.to_h { |matcher| [matcher.want, matcher.done?] } end |
#matcher_want_hash ⇒ Object
184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/rsmp/collect/state_collector.rb', line 184 def matcher_want_hash h = {} @matchers.each do |matcher| item = matcher.want if item['cCI'] add_command_want_to_hash(h, item) elsif item['sCI'] add_status_want_to_hash(h, item) end end h end |
#messages ⇒ Object
Get messages from results
65 66 67 |
# File 'lib/rsmp/collect/state_collector.rb', line 65 def @matchers.map(&:message).uniq.compact end |
#perform_match(message) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/rsmp/collect/state_collector.rb', line 109 def perform_match() return false if super == false return unless collecting? @matchers.each do |matcher| break unless collecting? get_items().each do |item| matched = matcher.perform_match(item, , @block) break unless collecting? handle_match_result(matched, matcher, , item) end end end |
#progress ⇒ Object
Return progress as completes matchers vs. total number of matchers
70 71 72 73 74 |
# File 'lib/rsmp/collect/state_collector.rb', line 70 def progress need = @matchers.size reached = @matchers.count(&:done?) { need: need, reached: reached } end |
#progress_hash ⇒ Object
return a hash that describe the status of all matchers
138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/rsmp/collect/state_collector.rb', line 138 def progress_hash h = {} @matchers.each do |matcher| want = matcher.want if want['cCI'] process_command_matcher(h, matcher, want) elsif want['sCI'] process_status_matcher(h, matcher, want) end end h end |
#reached ⇒ Object
Get an array of the last item received for each matcher
60 61 62 |
# File 'lib/rsmp/collect/state_collector.rb', line 60 def reached @matchers.map(&:got).compact end |
#summary ⇒ Object
Get a simply array of bools, showing which matchers have been matched.
88 89 90 |
# File 'lib/rsmp/collect/state_collector.rb', line 88 def summary @matchers.map(&:done?) end |