Class: RSMP::Matcher

Inherits:
Collector show all
Defined in:
lib/rsmp/collect/matcher.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" }

}

Instance Attribute Summary collapse

Attributes inherited from Collector

#condition, #error, #status

Instance Method Summary collapse

Methods inherited from Collector

#cancel, #collect, #collect!, #complete, #describe_progress, #do_stop, #ingoing?, #inspect, #keep, #notify, #notify_disconnect, #notify_error, #notify_schema_error, #outgoing?, #reject_not_ack, #reset, #start, #type_match?, #wait, #wait!

Methods inherited from Listener

#change_notifier, #listen, #notify, #notify_error

Methods included from Inspect

#inspect, #inspector

Constructor Details

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

Initialize with a list of wanted statuses

Raises:

  • (ArgumentError)


39
40
41
42
43
# File 'lib/rsmp/collect/matcher.rb', line 39

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.



36
37
38
# File 'lib/rsmp/collect/matcher.rb', line 36

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.



47
48
49
# File 'lib/rsmp/collect/matcher.rb', line 47

def build_query want
  Query.new want
end

#done?Boolean

Are there queries left to type_match?

Returns:

  • (Boolean)


76
77
78
# File 'lib/rsmp/collect/matcher.rb', line 76

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

#messagesObject

Get messages from results



64
65
66
# File 'lib/rsmp/collect/matcher.rb', line 64

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

#perform_match(message) ⇒ Object

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



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

def perform_match message
  return unless type_match?(message)
  @queries.each do |query|       # look through queries
    get_items(message).each do |item|  # look through items in message
      matched = query.perform_match(item,message)
      if matched == true
        matched = @block.call(message,item) if @block
      end
      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
        break
      end
    end
  end
  complete if done?
  @notifier.log "#{@title.capitalize} collect reached #{summary}", level: :debug
end

#progressObject

Return progress as completes queries vs. total number of queries



69
70
71
72
73
# File 'lib/rsmp/collect/matcher.rb', line 69

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

#query_result(want) ⇒ Object

Get a results



52
53
54
55
56
# File 'lib/rsmp/collect/matcher.rb', line 52

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.



82
83
84
# File 'lib/rsmp/collect/matcher.rb', line 82

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

#reachedObject

Get an array of the last item received for each query



59
60
61
# File 'lib/rsmp/collect/matcher.rb', line 59

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

#summaryObject

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



87
88
89
# File 'lib/rsmp/collect/matcher.rb', line 87

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