rsmp 0.3.0 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9a3b1b8a67bdc7a3c8887ea606d3539d934121d99597f1a77f697d8259daba97
4
- data.tar.gz: 03f420b48a4eff2f3b6978eed5053a838a87da4f507eb2ddb2f0c15cb0e3e7b4
3
+ metadata.gz: f529bfbfcdd5fc6b0854c294e2412c5e7da10e2595a6a20ab0f6c65b7eb28964
4
+ data.tar.gz: c8fb86566e623a27ec78784e3d0299f16d082edc87ad9438f2335a0c33657b39
5
5
  SHA512:
6
- metadata.gz: 9fef0b5ea4b2e5481d3be7992e76c7cddb1d20db49df06c86d9b90faa37b56d458fde9cba36e14ea085e96e67f61dbe67f1a82a49401d360cb48900c6138b27d
7
- data.tar.gz: a14a735fccf39e8584e3d9ab43a1fdb727c279f395c138d9c7c50f7a8d491265c0aeb3aa67ee071642195bd7a15e0339de4785b5230bbed624965ef3619a231e
6
+ metadata.gz: 58c5d44cb5d8a1f87b77d91823eaa76adfd437df955412ba42950e359d1b08b47acec78034f42524b72d474a6c7870e2e22f418973d634fc938650b13f95fc47
7
+ data.tar.gz: 6006f41562af7ce3419c50895040fc0682026fa3c5b0db113875645fdd1de5286e25b73edc22f1d547a1daac50059532e7c4061cc5e3789d3a92c18c5e502aca
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rsmp (0.3.0)
4
+ rsmp (0.3.3)
5
5
  async (~> 1.29.1)
6
6
  async-io (~> 1.32.1)
7
7
  colorize (~> 0.8.1)
@@ -13,6 +13,7 @@ module RSMP
13
13
  @condition = Async::Notification.new
14
14
  @title = options[:title] || [@options[:type]].flatten.join('/')
15
15
  @options[:timeout] ||= 1
16
+ @options[:num] ||= 1
16
17
  reset
17
18
  end
18
19
 
@@ -51,21 +52,21 @@ module RSMP
51
52
  raise RSMP::TimeoutError.new str
52
53
  end
53
54
 
55
+ # Get the collected messages.
56
+ # If one message was requested, return it as a plain object instead of array
54
57
  def result
55
- return @messages.first if @options[:num] == 1 # if one message was requested, return it instead of array
56
- @messages.first @options[:num] # return array, but ensure we never return more than requested
58
+ return @messages.first if @options[:num] == 1
59
+ @messages.first @options[:num]
57
60
  end
58
61
 
62
+ # Clear all query results
59
63
  def reset
60
64
  @messages = []
61
65
  @error = nil
62
66
  @done = false
63
67
  end
64
68
 
65
- # Check for MessageNotAck
66
- # If the original request identified by @m_id is rejected, set the result to an exception,
67
- # which will be returned by the async task and stored as the task result.
68
- # When the parent task call wait() on the task, the exception will be raised in the parent task.
69
+ # Check if we receive a NotAck related to initiating request, identified by @m_id.
69
70
  def check_not_ack message
70
71
  return unless @options[:m_id]
71
72
  if message.is_a?(MessageNotAck)
@@ -81,6 +82,7 @@ module RSMP
81
82
  # Handle message. and return true when we're done collecting
82
83
  def notify message
83
84
  raise ArgumentError unless message
85
+ raise RuntimeError.new("can't process message when already done") if @done
84
86
  check_not_ack(message)
85
87
  return true if @done
86
88
  check_match message
@@ -98,24 +100,31 @@ module RSMP
98
100
  end
99
101
  end
100
102
 
103
+ # Have we collected the required number of messages?
101
104
  def done?
102
105
  @options[:num] && @messages.size >= @options[:num]
103
106
  end
104
107
 
108
+ # Called when we're done collecting. Remove ourself as a listener,
109
+ # se we don't receive message notifications anymore
105
110
  def complete
106
111
  @done = true
107
112
  @proxy.remove_listener self
108
113
  @condition.signal
109
114
  end
110
115
 
116
+ # Store a message in the result array
111
117
  def keep message
112
118
  @messages << message
113
119
  end
114
120
 
121
+ # Remove a message from the result array
115
122
  def forget message
116
123
  @messages.delete message
117
124
  end
118
125
 
126
+ # Check a message against our match criteria
127
+ # Return true if there's a match
119
128
  def match? message
120
129
  raise ArgumentError unless message
121
130
  return if message.direction == :in && @ingoing == false
@@ -13,6 +13,7 @@ module RSMP
13
13
 
14
14
  def setup_components settings
15
15
  return unless settings
16
+ check_main_component settings
16
17
  settings.each_pair do |type,components_by_type|
17
18
  components_by_type.each_pair do |id,settings|
18
19
  @components[id] = build_component(id:id, type:type, settings:settings)
@@ -20,6 +21,15 @@ module RSMP
20
21
  end
21
22
  end
22
23
 
24
+ def check_main_component settings
25
+ unless settings['main'] && settings['main'].size >= 1
26
+ raise ConfigurationError.new("main component must be defined")
27
+ end
28
+ if settings['main'].size > 1
29
+ raise ConfigurationError.new("only one main component can be defined, found #{settings['main'].keys.join(', ')}")
30
+ end
31
+ end
32
+
23
33
  def add_component component
24
34
  @components[component.c_id] = component
25
35
  end
data/lib/rsmp/matcher.rb CHANGED
@@ -35,6 +35,7 @@ module RSMP
35
35
  #
36
36
  #
37
37
  class Matcher < Collector
38
+ attr_reader :queries
38
39
 
39
40
  # Initialize with a list a wanted statuses
40
41
  def initialize proxy, want, options={}
@@ -55,16 +56,27 @@ module RSMP
55
56
  @queries.map { |query,result| result[:message] }.uniq
56
57
  end
57
58
 
58
- # get items from results
59
+ # Get items from results
59
60
  def items
60
61
  @queries.map { |query,result| result[:item] }.uniq
61
62
  end
62
63
 
63
- # Queries left to match?
64
+ # Are there queries left to match?
64
65
  def done?
65
66
  @queries.values.all? { |result| result != nil }
66
67
  end
67
68
 
69
+ # Get a simplified hash of queries, with values set to either true or false,
70
+ # indicating which queries have been matched.
71
+ def status
72
+ @queries.transform_values{ |v| v != nil }
73
+ end
74
+
75
+ # Get a simply array of bools, showing which queries ahve been matched.
76
+ def summary
77
+ @queries.values.map { |v| v != nil }
78
+ end
79
+
68
80
  # Mark a query as matched, by linking it to the matched item and message
69
81
  def keep query, message, item
70
82
  @queries[query] = { message:message, item:item }
@@ -75,11 +87,12 @@ module RSMP
75
87
  @queries[query] = nil
76
88
  end
77
89
 
78
- # Check if a messages is wanted.
79
- # Returns true when we found all that we want.
90
+ # Check if a messages matches our criteria.
91
+ # We iterate through each of the status items or return values in the message
92
+ # Breaks as soon as where done matching all queries
80
93
  def check_match message
81
94
  return unless match?(message)
82
- @queries.keys.each do |query| # look through queries
95
+ @queries.keys.each do |query| # look through queries
83
96
  get_items(message).each do |item| # look through status items in message
84
97
  break if check_item_match message, query, item
85
98
  end
@@ -104,15 +117,16 @@ module RSMP
104
117
  def initialize proxy, want, options={}
105
118
  super proxy, want, options.merge(
106
119
  type: ['CommandResponse','MessageNotAck'],
107
- title:'command request'
120
+ title:'command response'
108
121
  )
109
122
  end
110
123
 
124
+ # Get items, in our case the return values
111
125
  def get_items message
112
126
  message.attributes['rvs']
113
127
  end
114
128
 
115
- # Match an item against a query
129
+ # Match a return value item against a query
116
130
  def match_item? query, item
117
131
  return nil if query['cCI'] && query['cCI'] != item['cCI']
118
132
  return nil if query['n'] && query['n'] != item['n']
@@ -131,11 +145,12 @@ module RSMP
131
145
  super proxy, want, options.merge
132
146
  end
133
147
 
148
+ # Get items, in our case status values
134
149
  def get_items message
135
150
  message.attributes['sS']
136
151
  end
137
152
 
138
- # Match an item against a query
153
+ # Match a status value against a query
139
154
  def match_item? query, item
140
155
  return nil if query['sCI'] && query['sCI'] != item['sCI']
141
156
  return nil if query['cO'] && query['cO'] != item['cO']
@@ -155,7 +170,7 @@ module RSMP
155
170
  def initialize proxy, want, options={}
156
171
  super proxy, want, options.merge(
157
172
  type: ['StatusResponse','MessageNotAck'],
158
- title: 'status request'
173
+ title: 'status response'
159
174
  )
160
175
  end
161
176
  end
@@ -165,7 +180,7 @@ module RSMP
165
180
  def initialize proxy, want, options={}
166
181
  super proxy, want, options.merge(
167
182
  type: ['StatusUpdate','MessageNotAck'],
168
- title:'status subscription'
183
+ title:'status update'
169
184
  )
170
185
  end
171
186
  end
@@ -173,11 +188,8 @@ module RSMP
173
188
  # Class for waiting for an aggregated status response
174
189
  class AggregatedStatusMatcher < Collector
175
190
  def initialize proxy, options={}
176
- super proxy, options.merge(
177
- num: 1,
178
- type: ['AggregatedStatus','MessageNotAck'],
179
- title: 'aggregated status request'
180
- )
191
+ required = { type: ['AggregatedStatus','MessageNotAck'], title: 'aggregated status' }
192
+ super proxy, options.merge(required)
181
193
  end
182
194
  end
183
195
  end
data/lib/rsmp/proxy.rb CHANGED
@@ -124,7 +124,11 @@ module RSMP
124
124
  message = process_packet json
125
125
  duration = Time.now - beginning
126
126
  ms = (duration*1000).round(4)
127
- per_second = (1.0 / duration).round
127
+ if duration > 0
128
+ per_second = (1.0 / duration).round
129
+ else
130
+ per_second = Float::INFINITY
131
+ end
128
132
  if message
129
133
  type = message.type
130
134
  m_id = Logger.shorten_message_id(message.m_id)
@@ -203,7 +207,6 @@ module RSMP
203
207
  def watchdog_send_timer now
204
208
  return unless @watchdog_started
205
209
  return if @site_settings['intervals']['watchdog'] == :never
206
-
207
210
  if @latest_watchdog_send_at == nil
208
211
  send_watchdog now
209
212
  else
@@ -299,10 +302,18 @@ module RSMP
299
302
  end
300
303
  end
301
304
 
305
+ def should_validate_ingoing_message? message
306
+ return false unless @site_settings
307
+ skip = @site_settings.dig('skip_validation')
308
+ return false unless skip
309
+ klass = message.class.name.split('::').last
310
+ !skip.include?(klass)
311
+ end
312
+
302
313
  def process_packet json
303
314
  attributes = Message.parse_attributes json
304
315
  message = Message.build attributes, json
305
- message.validate get_schemas
316
+ message.validate(get_schemas) if should_validate_ingoing_message?(message)
306
317
  notify message
307
318
  expect_version_message(message) unless @version_determined
308
319
  process_message message
data/lib/rsmp/site.rb CHANGED
@@ -41,10 +41,16 @@ module RSMP
41
41
  },
42
42
  'send_after_connect' => true,
43
43
  'components' => {
44
- 'C1' => {}
44
+ 'main' => {
45
+ 'C1' => {}
46
+ }
45
47
  }
46
48
  }
47
-
49
+ # only one main component can be defined, so replace the default if options define one
50
+ if options.dig(:site_settings,'components','main')
51
+ defaults['components']['main'] = options[:site_settings]['components']['main']
52
+ end
53
+
48
54
  @site_settings = defaults.deep_merge options[:site_settings]
49
55
  check_sxl_version
50
56
  setup_components @site_settings['components']
@@ -11,7 +11,7 @@ module RSMP
11
11
  initialize_components
12
12
  @supervisor = options[:supervisor]
13
13
  @settings = @supervisor.supervisor_settings.clone
14
- @site_id = nil
14
+ @site_id = options[:site_id]
15
15
  end
16
16
 
17
17
  def revive options
@@ -103,7 +103,7 @@ module RSMP
103
103
  })
104
104
  if options[:collect]
105
105
  task = @task.async do |task|
106
- wait_for_aggregated_status task, options[:collect].merge(m_id: m_id)
106
+ collect_aggregated_status task, options[:collect].merge(m_id: m_id)
107
107
  end
108
108
  send_message message, validate: options[:validate]
109
109
  return message, task.wait
@@ -369,7 +369,7 @@ module RSMP
369
369
  CommandResponseMatcher.new(self, command_list, options).collect task
370
370
  end
371
371
 
372
- def wait_for_aggregated_status task, options
372
+ def collect_aggregated_status task, options
373
373
  AggregatedStatusMatcher.new(self, options).collect task
374
374
  end
375
375
  end
@@ -175,7 +175,7 @@ module RSMP
175
175
  proxy.revive settings
176
176
  else
177
177
  check_max_sites
178
- proxy = build_proxy settings
178
+ proxy = build_proxy settings.merge(site_id:id) # keep the id learned by peeking above
179
179
  @proxies.push proxy
180
180
  end
181
181
  proxy.run # will run until the site disconnects
data/lib/rsmp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module RSMP
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.4"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rsmp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Emil Tin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-10-14 00:00:00.000000000 Z
11
+ date: 2021-10-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -255,7 +255,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
255
255
  - !ruby/object:Gem::Version
256
256
  version: '0'
257
257
  requirements: []
258
- rubygems_version: 3.2.26
258
+ rubygems_version: 3.2.15
259
259
  signing_key:
260
260
  specification_version: 4
261
261
  summary: RoadSide Message Protocol (RSMP) library.