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_progress, #do_stop, #ingoing?, #inspect, #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



118
119
120
# File 'lib/rsmp/collect/state_collector.rb', line 118

def describe
  @queries.map {|q| q.want.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



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

def keep message
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
111
112
# 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
  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