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" }

}

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_progress, #do_stop, #ingoing?, #inspect, #keep, #notify, #notify_disconnect, #notify_error, #notify_schema_error, #ok?, #outgoing?, #ready?, #reject_not_ack, #reset, #start, #timeout?, #type_match?, #use_task, #wait, #wait!

Methods inherited from Listener

#change_notifier, #listen, #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

#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

#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
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
# File 'lib/rsmp/collect/state_collector.rb', line 92

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



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

#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

#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