Class: RSMP::StateCollector

Inherits:
Collector show all
Defined in:
lib/rsmp/collect/state_collector.rb

Overview

Base class for waiting for specific status or command responses, specified by a list of queries. Queries 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 queries 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 queries. If a match is found, it's stored in the @results hash, with the query as the key, and a mesage and status as the key. In the example above, this query:

“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 message>, "cO"=>"setDate", "n"=>"month", "v"=>"9" }

}

Direct Known Subclasses

CommandResponseCollector, StatusCollector

Instance Attribute Summary collapse

Attributes inherited from Collector

#condition, #error, #status, #task

Instance Method Summary collapse

Methods inherited from Collector

#cancel, #cancelled?, #collect, #collect!, #collecting?, #complete, #describe_num_and_type, #describe_types, #do_stop, #identifier, #incomplete, #ingoing?, #inspect, #log_incomplete, #log_start, #notify, #notify_disconnect, #notify_error, #notify_schema_error, #ok!, #ok?, #outgoing?, #ready?, #reject_not_ack, #reset, #start, #timeout?, #type_match?, #use_task, #wait, #wait!

Methods inherited from Listener

#change_notifier, #notify, #notify_error

Methods included from Inspect

#inspect, #inspector

Constructor Details

#initialize(proxy, want, options = {}) ⇒ StateCollector

Initialize with a list of wanted statuses

Raises:

  • (ArgumentError)


38
39
40
41
42
# File 'lib/rsmp/collect/state_collector.rb', line 38

def initialize proxy, want, options={}
  raise ArgumentError.new("num option cannot be used") if options[:num]
  super proxy, options.merge( ingoing: true, outgoing: false)
  @queries = want.map { |item| build_query item }
end

Instance Attribute Details

#queriesObject (readonly)

Returns the value of attribute queries.



35
36
37
# File 'lib/rsmp/collect/state_collector.rb', line 35

def queries
  @queries
end

Instance Method Details

#build_query(want) ⇒ Object

Build a query object. Sub-classes should override to use their own query classes.



46
47
48
# File 'lib/rsmp/collect/state_collector.rb', line 46

def build_query want
  Query.new want
end

#describeObject



116
117
118
# File 'lib/rsmp/collect/state_collector.rb', line 116

def describe
  @queries.map {|q| q.want.to_s }
end

#describe_progressObject

return a string that describe how many many messages have been collected



154
155
156
157
158
# File 'lib/rsmp/collect/state_collector.rb', line 154

def describe_progress
  num_queries = @queries.size
  num_matched =  @queries.count { |query| query.done? }
  ".. Matched #{num_matched}/#{num_queries} with #{progress_hash.to_s}"
end

#describe_queryObject

return a string that describes the attributes that we're looking for



121
122
123
# File 'lib/rsmp/collect/state_collector.rb', line 121

def describe_query
  "#{super} matching #{query_want_hash.to_s}"
end

#done?Boolean

Are there queries left to type_match?

Returns:

  • (Boolean)


75
76
77
# File 'lib/rsmp/collect/state_collector.rb', line 75

def done?
  @queries.all? { |query| query.done? }
end

#keep(message) ⇒ Object

don't collect anything. Query will collect them instead



113
114
# File 'lib/rsmp/collect/state_collector.rb', line 113

def keep message
end

#log_completeObject

log when we end collecting



209
210
211
# File 'lib/rsmp/collect/state_collector.rb', line 209

def log_complete
  @notifier.log "#{identifier}: Completed with #{query_got_hash.to_s}", level: :collect
end

#messagesObject

Get messages from results



63
64
65
# File 'lib/rsmp/collect/state_collector.rb', line 63

def messages
  @queries.map { |query| query.message }.uniq.compact
end

#perform_match(message) ⇒ Object

Check if a messages matches our criteria. Match each query against each item in the message



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/rsmp/collect/state_collector.rb', line 92

def perform_match message
  return false if super(message) == false
  return unless collecting?
  @queries.each do |query|       # look through queries
    get_items(message).each do |item|  # look through items in message
      matched = query.perform_match(item,message,@block)
      return unless collecting?
      if matched != nil
        #type = {true=>'match',false=>'mismatch'}[matched]
        #@notifier.log "#{@title.capitalize} #{message.m_id_short} collect #{type} #{query.want}, item #{item}", level: :debug
        if matched == true
          query.keep message, item
        elsif matched == false
          query.forget
        end
      end
    end
  end
end

#progressObject

Return progress as completes queries vs. total number of queries



68
69
70
71
72
# File 'lib/rsmp/collect/state_collector.rb', line 68

def progress
  need = @queries.size
  reached =  @queries.count { |query| query.done? }
  { need: need, reached: reached }
end

#progress_hashObject

return a hash that describe the status of all queries



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/rsmp/collect/state_collector.rb', line 126

def progress_hash
  h = {}
  @queries.each do |query|
    want = query.want
    if want['cCI']
      cCI = want['cCI']
      h[cCI] ||= {}
      cO = h['cO']
      n = h['n']
      v = h['v']
      h[cCI][cO] ||= {}
      h[cCI][cO][n] = v
    elsif want['sCI']
      sCI = want['sCI']
      h[sCI] ||= {}
      n = want['n']
      s = want['s']
      if query.got && query.got['s']
        h[sCI][n] = { {s=>query.got['s']} => query.done? }
      else
        h[sCI][n] = { s=>nil }
      end
    end
  end
  h
end

#query_got_hashObject

return a hash that describe the end result



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/rsmp/collect/state_collector.rb', line 184

def query_got_hash
  h = {}
  @queries.each do |query|
    want = query.want
    got = query.got
    if got['cCI']
      cCI = want['cCI']
      h[cCI] ||= {}
      cO = want['cO']
      h[cCI][cO] ||= {}
      n = want['n']
      v = got['v']
      h[cCI][cO][n] = v
    elsif want['sCI']
      sCI = want['sCI']
      h[sCI] ||= {}
      n = want['n']
      s = got['s']
      h[sCI][n] = s
    end
  end
  h
end

#query_result(want) ⇒ Object

Get a results



51
52
53
54
55
# File 'lib/rsmp/collect/state_collector.rb', line 51

def query_result want
  query = @queries.find { |q| q.want == want}
  raise unless query
  query.got
end

#query_statusObject

Get a simplified hash of queries, with values set to either true or false, indicating which queries have been matched.



81
82
83
# File 'lib/rsmp/collect/state_collector.rb', line 81

def query_status
  @queries.map { |query| [query.want, query.done?] }.to_h
end

#query_want_hashObject



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/rsmp/collect/state_collector.rb', line 160

def query_want_hash
  h = {}
  @queries.each do |query|
    item = query.want
    if item['cCI']
      cCI = item['cCI']
      h[cCI] ||= {}
      cO = item['cO']
      h[cCI][cO] ||= {}
      n = item['n']
      v = item['v']
      h[cCI][cO][n] = v || :any
    elsif item['sCI']
      sCI = item['sCI']
      h[sCI] ||= {}
      n = item['n']
      s = item['s']
      h[sCI][n] = s || :any
    end
  end
  h
end

#reachedObject

Get an array of the last item received for each query



58
59
60
# File 'lib/rsmp/collect/state_collector.rb', line 58

def reached
  @queries.map { |query| query.got }.compact
end

#summaryObject

Get a simply array of bools, showing which queries have been matched.



86
87
88
# File 'lib/rsmp/collect/state_collector.rb', line 86

def summary
  @queries.map { |query| query.done? }
end