rsmp 0.3.0 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/rsmp/collector.rb +15 -6
- data/lib/rsmp/components.rb +10 -0
- data/lib/rsmp/matcher.rb +27 -15
- data/lib/rsmp/proxy.rb +14 -3
- data/lib/rsmp/site.rb +8 -2
- data/lib/rsmp/site_proxy.rb +3 -3
- data/lib/rsmp/supervisor.rb +1 -1
- data/lib/rsmp/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f529bfbfcdd5fc6b0854c294e2412c5e7da10e2595a6a20ab0f6c65b7eb28964
|
4
|
+
data.tar.gz: c8fb86566e623a27ec78784e3d0299f16d082edc87ad9438f2335a0c33657b39
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 58c5d44cb5d8a1f87b77d91823eaa76adfd437df955412ba42950e359d1b08b47acec78034f42524b72d474a6c7870e2e22f418973d634fc938650b13f95fc47
|
7
|
+
data.tar.gz: 6006f41562af7ce3419c50895040fc0682026fa3c5b0db113875645fdd1de5286e25b73edc22f1d547a1daac50059532e7c4061cc5e3789d3a92c18c5e502aca
|
data/Gemfile.lock
CHANGED
data/lib/rsmp/collector.rb
CHANGED
@@ -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
|
56
|
-
@messages.first @options[:num]
|
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
|
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
|
data/lib/rsmp/components.rb
CHANGED
@@ -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
|
-
#
|
59
|
+
# Get items from results
|
59
60
|
def items
|
60
61
|
@queries.map { |query,result| result[:item] }.uniq
|
61
62
|
end
|
62
63
|
|
63
|
-
#
|
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
|
79
|
-
#
|
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|
|
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
|
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
|
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
|
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
|
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
|
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
|
-
|
177
|
-
|
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
|
-
|
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
|
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
|
-
'
|
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']
|
data/lib/rsmp/site_proxy.rb
CHANGED
@@ -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 =
|
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
|
-
|
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
|
372
|
+
def collect_aggregated_status task, options
|
373
373
|
AggregatedStatusMatcher.new(self, options).collect task
|
374
374
|
end
|
375
375
|
end
|
data/lib/rsmp/supervisor.rb
CHANGED
@@ -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
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.
|
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-
|
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.
|
258
|
+
rubygems_version: 3.2.15
|
259
259
|
signing_key:
|
260
260
|
specification_version: 4
|
261
261
|
summary: RoadSide Message Protocol (RSMP) library.
|