rsmp 0.1.27 → 0.1.33
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/config/supervisor.yaml +8 -20
- data/config/tlc.yaml +7 -14
- data/lib/rsmp.rb +1 -0
- data/lib/rsmp/cli.rb +4 -2
- data/lib/rsmp/component.rb +4 -4
- data/lib/rsmp/components.rb +1 -1
- data/lib/rsmp/deep_merge.rb +11 -0
- data/lib/rsmp/proxy.rb +50 -23
- data/lib/rsmp/site.rb +35 -28
- data/lib/rsmp/site_proxy.rb +30 -15
- data/lib/rsmp/site_proxy_wait.rb +0 -35
- data/lib/rsmp/supervisor.rb +50 -44
- data/lib/rsmp/supervisor_proxy.rb +19 -6
- data/lib/rsmp/tlc.rb +6 -2
- data/lib/rsmp/version.rb +1 -1
- metadata +3 -3
- data/config/site.yaml +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ea326578bffa5b75bcd86c0829215d0111b3ba52c88bba7110cca3b9cc0f9fa9
|
4
|
+
data.tar.gz: b7d197a3430be8922429ce5ac5ce3512900d85b4b9d276d5d283f150082a3303
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '09ad5202d5feb194cdd9e54177f86910631ac260cd94e5afccdf1a386260de91063b438e5e6dc8675703fdaae8112036f6940793f7d3a266e84827ed38d465c1'
|
7
|
+
data.tar.gz: c37dcaac65b0c1a692ef95507ad25f1fa0e78bdfa089758b8511af331e2f47b1bb497cf1452442ad7f9fbf34f8860c9408eeb1674cb3084337ce4fd3b4f552eb
|
data/Gemfile.lock
CHANGED
data/config/supervisor.yaml
CHANGED
@@ -1,23 +1,12 @@
|
|
1
1
|
port: 12111
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
:any:
|
11
|
-
sxl: tlc
|
12
|
-
|
13
|
-
watchdog_interval: 0.1
|
14
|
-
watchdog_timeout: 0.2
|
15
|
-
acknowledgement_timeout: 0.2
|
16
|
-
store_messages: false
|
17
|
-
command_response_timeout: 0.1
|
18
|
-
status_response_timeout: 0.1
|
19
|
-
status_update_timeout: 0.1
|
20
|
-
|
2
|
+
guest:
|
3
|
+
sxl: tlc
|
4
|
+
intervals:
|
5
|
+
timer: 0.1
|
6
|
+
watchdog: 0.1
|
7
|
+
timeouts:
|
8
|
+
watchdog: 0.2
|
9
|
+
acknowledgement: 0.2
|
21
10
|
log:
|
22
11
|
active: true
|
23
12
|
color: true
|
@@ -33,4 +22,3 @@ log:
|
|
33
22
|
json: true
|
34
23
|
acknowledgements: false
|
35
24
|
watchdogs: false
|
36
|
-
|
data/config/tlc.yaml
CHANGED
@@ -2,15 +2,8 @@ site_id: RN+SI0001
|
|
2
2
|
supervisors:
|
3
3
|
- ip: 127.0.0.1
|
4
4
|
port: 12111
|
5
|
-
|
6
|
-
# if you leave it out, all know version will be allowed
|
7
|
-
#rsmp_versions:
|
8
|
-
# - 3.1.4
|
9
|
-
# - 3.1.5
|
10
|
-
|
11
5
|
sxl: tlc
|
12
6
|
sxl_version: 1.0.15
|
13
|
-
|
14
7
|
components:
|
15
8
|
main:
|
16
9
|
TC:
|
@@ -26,15 +19,16 @@ components:
|
|
26
19
|
plan: 'BBB1NB'
|
27
20
|
detector_logic:
|
28
21
|
DL1:
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
22
|
+
intervals:
|
23
|
+
timer: 0.1
|
24
|
+
watchdog: 0.1
|
25
|
+
reconnect: 0.1
|
26
|
+
timeouts:
|
27
|
+
watchdog: 0.2
|
28
|
+
acknowledgement: 0.2
|
34
29
|
security_codes:
|
35
30
|
1: '1111'
|
36
31
|
2: '2222'
|
37
|
-
|
38
32
|
log:
|
39
33
|
active: true
|
40
34
|
color: true
|
@@ -49,4 +43,3 @@ log:
|
|
49
43
|
json: true
|
50
44
|
acknowledgements: false
|
51
45
|
watchdogs: false
|
52
|
-
|
data/lib/rsmp.rb
CHANGED
data/lib/rsmp/cli.rb
CHANGED
@@ -30,12 +30,12 @@ module RSMP
|
|
30
30
|
end
|
31
31
|
|
32
32
|
if options[:supervisors]
|
33
|
+
settings['supervisors'] = []
|
33
34
|
options[:supervisors].split(',').each do |supervisor|
|
34
|
-
settings[:supervisors] ||= []
|
35
35
|
ip, port = supervisor.split ':'
|
36
36
|
ip = '127.0.0.1' if ip.empty?
|
37
37
|
port = '12111' if port.empty?
|
38
|
-
settings[
|
38
|
+
settings['supervisors'] << {"ip"=>ip, "port"=>port}
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
@@ -61,6 +61,8 @@ module RSMP
|
|
61
61
|
puts "Cannot start site: #{e}"
|
62
62
|
rescue RSMP::Schemer::UnknownSchemaVersionError => e
|
63
63
|
puts "Cannot start site: #{e}"
|
64
|
+
rescue Psych::SyntaxError => e
|
65
|
+
puts "Cannot read config file #{e}"
|
64
66
|
end
|
65
67
|
|
66
68
|
desc "supervisor", "Run RSMP supervisor"
|
data/lib/rsmp/component.rb
CHANGED
@@ -28,7 +28,7 @@ module RSMP
|
|
28
28
|
@aggregated_status_bools[5] = true
|
29
29
|
end
|
30
30
|
|
31
|
-
def set_aggregated_status status
|
31
|
+
def set_aggregated_status status, options={}
|
32
32
|
status = [status] if status.is_a? Symbol
|
33
33
|
raise InvalidArgument unless status.is_a? Array
|
34
34
|
input = status & AGGREGATED_STATUS_KEYS
|
@@ -36,7 +36,7 @@ module RSMP
|
|
36
36
|
AGGREGATED_STATUS_KEYS.each_with_index do |key,index|
|
37
37
|
@aggregated_status_bools[index] = status.include?(key)
|
38
38
|
end
|
39
|
-
aggrated_status_changed
|
39
|
+
aggrated_status_changed options
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -54,8 +54,8 @@ module RSMP
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
-
def aggrated_status_changed
|
58
|
-
@node.aggrated_status_changed self
|
57
|
+
def aggrated_status_changed options={}
|
58
|
+
@node.aggrated_status_changed self, options
|
59
59
|
end
|
60
60
|
|
61
61
|
def alarm code:, status:
|
data/lib/rsmp/components.rb
CHANGED
data/lib/rsmp/proxy.rb
CHANGED
@@ -22,10 +22,10 @@ module RSMP
|
|
22
22
|
@port = options[:port]
|
23
23
|
@connection_info = options[:info]
|
24
24
|
@sxl = nil
|
25
|
+
@site_settings = nil # can't pick until we know the site id
|
25
26
|
initialize_distributor
|
26
27
|
|
27
|
-
prepare_collection
|
28
|
-
|
28
|
+
prepare_collection @settings['collect']
|
29
29
|
clear
|
30
30
|
end
|
31
31
|
|
@@ -144,14 +144,14 @@ module RSMP
|
|
144
144
|
end
|
145
145
|
|
146
146
|
def start_watchdog
|
147
|
-
log "Starting watchdog with interval #{@
|
147
|
+
log "Starting watchdog with interval #{@site_settings['intervals']['watchdog']} seconds", level: :debug
|
148
148
|
send_watchdog
|
149
149
|
@watchdog_started = true
|
150
150
|
end
|
151
151
|
|
152
152
|
def start_timer
|
153
153
|
name = "timer"
|
154
|
-
interval = @
|
154
|
+
interval = @site_settings['intervals']['timer'] || 1
|
155
155
|
log "Starting #{name} with interval #{interval} seconds", level: :debug
|
156
156
|
@latest_watchdog_received = Clock.now
|
157
157
|
|
@@ -189,7 +189,7 @@ module RSMP
|
|
189
189
|
|
190
190
|
def watchdog_send_timer now
|
191
191
|
return unless @watchdog_started
|
192
|
-
return if @
|
192
|
+
return if @site_settings['intervals']['watchdog'] == :never
|
193
193
|
|
194
194
|
if @latest_watchdog_send_at == nil
|
195
195
|
send_watchdog now
|
@@ -197,7 +197,7 @@ module RSMP
|
|
197
197
|
# we add half the timer interval to pick the timer
|
198
198
|
# event closes to the wanted wathcdog interval
|
199
199
|
diff = now - @latest_watchdog_send_at
|
200
|
-
if (diff + 0.5*@
|
200
|
+
if (diff + 0.5*@site_settings['intervals']['timer']) >= (@site_settings['intervals']['watchdog'])
|
201
201
|
send_watchdog now
|
202
202
|
end
|
203
203
|
end
|
@@ -210,7 +210,7 @@ module RSMP
|
|
210
210
|
end
|
211
211
|
|
212
212
|
def check_ack_timeout now
|
213
|
-
timeout = @
|
213
|
+
timeout = @site_settings['timeouts']['acknowledgement']
|
214
214
|
# hash cannot be modify during iteration, so clone it
|
215
215
|
@awaiting_acknowledgement.clone.each_pair do |m_id, message|
|
216
216
|
latest = message.timestamp + timeout
|
@@ -222,7 +222,7 @@ module RSMP
|
|
222
222
|
end
|
223
223
|
|
224
224
|
def check_watchdog_timeout now
|
225
|
-
timeout = @
|
225
|
+
timeout = @site_settings['timeouts']['watchdog']
|
226
226
|
latest = @latest_watchdog_received + timeout
|
227
227
|
left = latest - now
|
228
228
|
if left < 0
|
@@ -360,13 +360,20 @@ module RSMP
|
|
360
360
|
dont_acknowledge message, "Received", "extraneous Version message"
|
361
361
|
end
|
362
362
|
|
363
|
+
def rsmp_versions
|
364
|
+
return ['3.1.5'] if @site_settings["rsmp_versions"] == 'latest'
|
365
|
+
return ['3.1.1','3.1.2','3.1.3','3.1.4','3.1.5'] if @site_settings["rsmp_versions"] == 'all'
|
366
|
+
@site_settings["rsmp_versions"]
|
367
|
+
end
|
368
|
+
|
363
369
|
def check_rsmp_version message
|
370
|
+
versions = rsmp_versions
|
364
371
|
# find versions that both we and the client support
|
365
|
-
candidates = message.versions &
|
372
|
+
candidates = message.versions & versions
|
366
373
|
if candidates.any?
|
367
374
|
@rsmp_version = candidates.sort_by { |v| Gem::Version.new(v) }.last # pick latest version
|
368
375
|
else
|
369
|
-
raise FatalError.new "RSMP versions [#{message.versions.join(',')}] requested, but only [#{
|
376
|
+
raise FatalError.new "RSMP versions [#{message.versions.join(',')}] requested, but only [#{versions.join(',')}] supported."
|
370
377
|
end
|
371
378
|
end
|
372
379
|
|
@@ -410,7 +417,15 @@ module RSMP
|
|
410
417
|
end
|
411
418
|
|
412
419
|
def send_version site_id, rsmp_versions
|
413
|
-
|
420
|
+
if rsmp_versions=='latest'
|
421
|
+
versions = ['3.1.5']
|
422
|
+
elsif rsmp_versions=='all'
|
423
|
+
versions = ['3.1.1','3.1.2','3.1.3','3.1.4','3.1.5']
|
424
|
+
else
|
425
|
+
versions = [rsmp_versions].flatten
|
426
|
+
end
|
427
|
+
versions_array = versions.map {|v| {"vers" => v} }
|
428
|
+
|
414
429
|
site_id_array = [site_id].flatten.map {|id| {"sId" => id} }
|
415
430
|
|
416
431
|
version_response = Version.new({
|
@@ -513,18 +528,6 @@ module RSMP
|
|
513
528
|
def version_acknowledged
|
514
529
|
end
|
515
530
|
|
516
|
-
def wait_for_acknowledgement original, timeout
|
517
|
-
raise ArgumentError unless original
|
518
|
-
wait_for(@acknowledgement_condition,timeout) do |message|
|
519
|
-
if message.is_a?(MessageNotAck) && message.attributes["oMId"] == original.m_id
|
520
|
-
raise RSMP::MessageRejected.new(message.attributes['rea'])
|
521
|
-
end
|
522
|
-
message.is_a?(MessageAck) && message.attributes["oMId"] == original.m_id
|
523
|
-
end
|
524
|
-
rescue Async::TimeoutError
|
525
|
-
raise RSMP::TimeoutError.new("Acknowledgement for #{original.type} #{original.m_id} not received within #{timeout}s")
|
526
|
-
end
|
527
|
-
|
528
531
|
def node
|
529
532
|
raise 'Must be overridden'
|
530
533
|
end
|
@@ -532,5 +535,29 @@ module RSMP
|
|
532
535
|
def author
|
533
536
|
node.site_id
|
534
537
|
end
|
538
|
+
|
539
|
+
def wait_for_acknowledgement parent_task, options={}, m_id
|
540
|
+
collect(parent_task,options.merge({
|
541
|
+
type: ['MessageAck','MessageNotAck'],
|
542
|
+
num: 1
|
543
|
+
})) do |message|
|
544
|
+
if message.is_a?(MessageNotAck)
|
545
|
+
if message.attribute('oMId') == m_id
|
546
|
+
# set result to an exception, but don't raise it.
|
547
|
+
# this will be returned by the task and stored as the task result
|
548
|
+
# when the parent task call wait() on the task, the exception
|
549
|
+
# will be raised in the parent task, and caught by rspec.
|
550
|
+
# rspec will then show the error and record the test as failed
|
551
|
+
m_id_short = RSMP::Message.shorten_m_id m_id, 8
|
552
|
+
result = RSMP::MessageRejected.new "Aggregated status request #{m_id_short} was rejected: #{message.attribute('rea')}"
|
553
|
+
next true # done, no more messages wanted
|
554
|
+
end
|
555
|
+
elsif message.is_a?(MessageAck)
|
556
|
+
next true if message.attribute('oMId') == m_id
|
557
|
+
end
|
558
|
+
false
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
535
562
|
end
|
536
563
|
end
|
data/lib/rsmp/site.rb
CHANGED
@@ -14,48 +14,39 @@ module RSMP
|
|
14
14
|
super options
|
15
15
|
@proxies = []
|
16
16
|
@sleep_condition = Async::Notification.new
|
17
|
+
@proxies_condition = Async::Notification.new
|
17
18
|
end
|
18
19
|
|
19
20
|
def site_id
|
20
21
|
@site_settings['site_id']
|
21
22
|
end
|
22
23
|
|
23
|
-
def handle_site_settings options
|
24
|
-
|
24
|
+
def handle_site_settings options={}
|
25
|
+
defaults = {
|
25
26
|
'site_id' => 'RN+SI0001',
|
26
27
|
'supervisors' => [
|
27
28
|
{ 'ip' => '127.0.0.1', 'port' => 12111 }
|
28
29
|
],
|
29
|
-
'rsmp_versions' =>
|
30
|
+
'rsmp_versions' => 'all',
|
30
31
|
'sxl' => 'tlc',
|
31
32
|
'sxl_version' => '1.0.15',
|
32
|
-
'
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
'
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
'reconnect_interval' => 0.1,
|
33
|
+
'intervals' => {
|
34
|
+
'timer' => 0.1,
|
35
|
+
'watchdog' => 1,
|
36
|
+
'reconnect' => 0.1
|
37
|
+
},
|
38
|
+
'timeouts' => {
|
39
|
+
'watchdog' => 2,
|
40
|
+
'acknowledgement' => 2
|
41
|
+
},
|
42
42
|
'send_after_connect' => true,
|
43
43
|
'components' => {
|
44
44
|
'C1' => {}
|
45
45
|
}
|
46
46
|
}
|
47
|
-
|
48
|
-
|
49
|
-
converted.compact!
|
50
|
-
@site_settings.merge! converted
|
51
|
-
end
|
52
|
-
|
53
|
-
required = [:supervisors,:rsmp_versions,:site_id,:watchdog_interval,:watchdog_timeout,
|
54
|
-
:acknowledgement_timeout,:command_response_timeout]
|
55
|
-
check_required_settings @site_settings, required
|
56
|
-
|
47
|
+
|
48
|
+
@site_settings = defaults.deep_merge options[:site_settings]
|
57
49
|
check_sxl_version
|
58
|
-
|
59
50
|
setup_components @site_settings['components']
|
60
51
|
end
|
61
52
|
|
@@ -84,9 +75,9 @@ module RSMP
|
|
84
75
|
SupervisorProxy.new settings
|
85
76
|
end
|
86
77
|
|
87
|
-
def aggrated_status_changed component
|
78
|
+
def aggrated_status_changed component, options={}
|
88
79
|
@proxies.each do |proxy|
|
89
|
-
proxy.send_aggregated_status component
|
80
|
+
proxy.send_aggregated_status component, options
|
90
81
|
end
|
91
82
|
end
|
92
83
|
|
@@ -101,9 +92,11 @@ module RSMP
|
|
101
92
|
archive: @archive
|
102
93
|
})
|
103
94
|
@proxies << proxy
|
95
|
+
@proxies_condition.signal
|
104
96
|
run_site_proxy task, proxy
|
105
97
|
ensure
|
106
98
|
@proxies.delete proxy
|
99
|
+
@proxies_condition.signal
|
107
100
|
end
|
108
101
|
|
109
102
|
def run_site_proxy task, proxy
|
@@ -115,10 +108,10 @@ module RSMP
|
|
115
108
|
notify_error e, level: :internal
|
116
109
|
ensure
|
117
110
|
begin
|
118
|
-
if @site_settings[
|
111
|
+
if @site_settings['intervals']['watchdog'] != :no
|
119
112
|
# sleep until waken by reconnect() or the reconnect interval passed
|
120
113
|
proxy.set_state :wait_for_reconnect
|
121
|
-
task.with_timeout(@site_settings[
|
114
|
+
task.with_timeout(@site_settings['intervals']['watchdog']) do
|
122
115
|
@sleep_condition.wait
|
123
116
|
end
|
124
117
|
else
|
@@ -152,5 +145,19 @@ module RSMP
|
|
152
145
|
end
|
153
146
|
end
|
154
147
|
|
148
|
+
def wait_for_supervisor ip, timeout
|
149
|
+
supervisor = find_supervisor ip
|
150
|
+
return supervisor if supervisor
|
151
|
+
wait_for(@proxy_condition,timeout) { find_supervisor ip }
|
152
|
+
rescue Async::TimeoutError
|
153
|
+
raise RSMP::TimeoutError.new "Supervisor '#{ip}' did not connect within #{timeout}s"
|
154
|
+
end
|
155
|
+
|
156
|
+
def find_supervisor ip
|
157
|
+
@proxies.each do |supervisor|
|
158
|
+
return supervisor if ip == :any || supervisor.ip == ip
|
159
|
+
end
|
160
|
+
nil
|
161
|
+
end
|
155
162
|
end
|
156
163
|
end
|
data/lib/rsmp/site_proxy.rb
CHANGED
@@ -36,7 +36,7 @@ module RSMP
|
|
36
36
|
|
37
37
|
def connection_complete
|
38
38
|
super
|
39
|
-
log "Connection to site #{@site_id} established, using core #{@rsmp_version},
|
39
|
+
log "Connection to site #{@site_id} established, using core #{@rsmp_version}, #{@sxl} #{@site_sxl_version}", level: :info
|
40
40
|
end
|
41
41
|
|
42
42
|
def process_message message
|
@@ -73,21 +73,10 @@ module RSMP
|
|
73
73
|
end
|
74
74
|
|
75
75
|
def version_accepted message
|
76
|
-
if @settings['sites']
|
77
|
-
@site_settings = @settings['sites'][@site_id]
|
78
|
-
@site_settings = @settings['sites'][:any] unless @site_settings
|
79
|
-
if @site_settings
|
80
|
-
@sxl = @site_settings['sxl']
|
81
|
-
setup_components @site_settings['components']
|
82
|
-
else
|
83
|
-
dont_acknowledge message, 'Rejected', "No config found for site #{@site_id}"
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
76
|
log "Received Version message for site #{@site_id}", message: message, level: :log
|
88
77
|
start_timer
|
89
78
|
acknowledge message
|
90
|
-
send_version @site_id,
|
79
|
+
send_version @site_id, rsmp_versions
|
91
80
|
@version_determined = true
|
92
81
|
|
93
82
|
end
|
@@ -145,7 +134,7 @@ module RSMP
|
|
145
134
|
acknowledge message
|
146
135
|
end
|
147
136
|
|
148
|
-
def aggrated_status_changed component
|
137
|
+
def aggrated_status_changed component, options={}
|
149
138
|
@supervisor.aggregated_status_changed self, component
|
150
139
|
end
|
151
140
|
|
@@ -309,7 +298,7 @@ module RSMP
|
|
309
298
|
end
|
310
299
|
|
311
300
|
def set_watchdog_interval interval
|
312
|
-
@settings[
|
301
|
+
@settings['intervals']['watchdog'] = interval
|
313
302
|
end
|
314
303
|
|
315
304
|
def check_sxl_version message
|
@@ -347,9 +336,35 @@ module RSMP
|
|
347
336
|
site_id = message.attribute("siteId").map { |item| item["sId"] }.first
|
348
337
|
@supervisor.check_site_id site_id
|
349
338
|
@site_id = site_id
|
339
|
+
setup_site_settings
|
350
340
|
site_ids_changed
|
351
341
|
end
|
352
342
|
|
343
|
+
def find_site_settings site_id
|
344
|
+
if @settings['sites'] && @settings['sites'][@site_id]
|
345
|
+
log "Using site settings for site id #{@site_id}", level: :debug
|
346
|
+
return @settings['sites'][@site_id]
|
347
|
+
end
|
348
|
+
|
349
|
+
settings = @settings['guest']
|
350
|
+
if @settings['guest']
|
351
|
+
log "Using site settings for guest", level: :debug
|
352
|
+
return @settings['guest']
|
353
|
+
end
|
354
|
+
|
355
|
+
nil
|
356
|
+
end
|
357
|
+
|
358
|
+
def setup_site_settings
|
359
|
+
@site_settings = find_site_settings @site_id
|
360
|
+
if @site_settings
|
361
|
+
@sxl = @site_settings['sxl']
|
362
|
+
setup_components @site_settings['components']
|
363
|
+
else
|
364
|
+
dont_acknowledge message, 'Rejected', "No config found for site #{@site_id}"
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
353
368
|
def notify_error e, options={}
|
354
369
|
@supervisor.notify_error e, options if @supervisor
|
355
370
|
end
|
data/lib/rsmp/site_proxy_wait.rb
CHANGED
@@ -2,24 +2,6 @@
|
|
2
2
|
module RSMP
|
3
3
|
module SiteProxyWait
|
4
4
|
|
5
|
-
def wait_for_status_updates parent_task, options={}, &send_block
|
6
|
-
send_while_collecting parent_task, send_block do |task, m_id|
|
7
|
-
collect_status_updates_or_responses task, 'StatusUpdate', options, m_id
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
def wait_for_status_responses parent_task, options={}, &send_block
|
12
|
-
send_while_collecting parent_task, send_block do |task, m_id|
|
13
|
-
collect_status_updates_or_responses task, 'StatusResponse', options, m_id
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def wait_for_command_responses parent_task, options={}, &send_block
|
18
|
-
send_while_collecting parent_task, send_block do |task, m_id|
|
19
|
-
collect_command_responses task, options, m_id
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
5
|
def wait_for_alarm parent_task, options={}
|
24
6
|
matching_alarm = nil
|
25
7
|
message = collect(parent_task,options.merge(type: "Alarm", with_message: true, num: 1)) do |message|
|
@@ -161,23 +143,6 @@ module RSMP
|
|
161
143
|
true
|
162
144
|
end
|
163
145
|
|
164
|
-
def send_while_collecting parent_task, send_block, &collect_block
|
165
|
-
m_id = RSMP::Message.make_m_id # make message id so we can start waiting for it
|
166
|
-
|
167
|
-
# wait for command responses in an async task
|
168
|
-
task = parent_task.async do |task|
|
169
|
-
collect_block.call task, m_id
|
170
|
-
rescue StandardError => e
|
171
|
-
notify_error e, level: :internal
|
172
|
-
end
|
173
|
-
|
174
|
-
# call block, it should send command request using the given m_id
|
175
|
-
send_block.call m_id
|
176
|
-
|
177
|
-
# wait for the response and return it, raise exception if NotAck received, it it timed out
|
178
|
-
task.wait
|
179
|
-
end
|
180
|
-
|
181
146
|
def wait_for_aggregated_status parent_task, options={}
|
182
147
|
collect(parent_task,options.merge({
|
183
148
|
type: ['AggregatedStatus','MessageNotAck'],
|
data/lib/rsmp/supervisor.rb
CHANGED
@@ -17,55 +17,45 @@ module RSMP
|
|
17
17
|
@supervisor_settings['site_id']
|
18
18
|
end
|
19
19
|
|
20
|
-
def handle_supervisor_settings options
|
21
|
-
|
20
|
+
def handle_supervisor_settings options={}
|
21
|
+
defaults = {
|
22
22
|
'port' => 12111,
|
23
|
-
'
|
24
|
-
'
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
'sites' => {
|
35
|
-
:any => {
|
36
|
-
'sxl' => 'tlc'
|
23
|
+
'ips' => 'all',
|
24
|
+
'guest' => {
|
25
|
+
'rsmp_versions' => 'all',
|
26
|
+
'sxl' => 'tlc',
|
27
|
+
'intervals' => {
|
28
|
+
'timer' => 1,
|
29
|
+
'watchdog' => 1
|
30
|
+
},
|
31
|
+
'timeouts' => {
|
32
|
+
'watchdog' => 2,
|
33
|
+
'acknowledgement' => 2
|
37
34
|
}
|
38
35
|
}
|
39
36
|
}
|
40
|
-
|
41
|
-
if options[:supervisor_settings]
|
42
|
-
converted = options[:supervisor_settings].map { |k,v| [k.to_s,v] }.to_h #convert symbol keys to string keys
|
43
|
-
converted.compact!
|
44
|
-
@supervisor_settings.merge! converted
|
45
|
-
end
|
46
|
-
|
47
|
-
required = [:port, :rsmp_versions, :watchdog_interval, :watchdog_timeout,
|
48
|
-
:acknowledgement_timeout, :command_response_timeout]
|
49
|
-
check_required_settings @supervisor_settings, required
|
50
37
|
|
38
|
+
# merge options into defaults
|
39
|
+
@supervisor_settings = defaults.deep_merge(options[:supervisor_settings] || {})
|
51
40
|
@rsmp_versions = @supervisor_settings["rsmp_versions"]
|
52
|
-
|
53
41
|
check_site_sxl_types
|
54
42
|
end
|
55
43
|
|
56
44
|
def check_site_sxl_types
|
57
|
-
@supervisor_settings['sites'].
|
45
|
+
sites = @supervisor_settings['sites'].clone || {}
|
46
|
+
sites['guest'] = @supervisor_settings['guest']
|
47
|
+
sites.each do |site_id,settings|
|
58
48
|
unless settings
|
59
|
-
raise RSMP::ConfigurationError.new("Configuration for site '#{
|
49
|
+
raise RSMP::ConfigurationError.new("Configuration for site '#{site_id}' is empty")
|
60
50
|
end
|
61
51
|
sxl = settings['sxl']
|
62
52
|
sxl = 'tlc' unless sxl # temporary fix until configs are updated
|
63
53
|
unless sxl
|
64
|
-
raise RSMP::ConfigurationError.new("Configuration error for site '#{
|
54
|
+
raise RSMP::ConfigurationError.new("Configuration error for site '#{site_id}': No SXL specified")
|
65
55
|
end
|
66
56
|
RSMP::Schemer.find_schemas! sxl if sxl
|
67
57
|
rescue RSMP::Schemer::UnknownSchemaError => e
|
68
|
-
raise RSMP::ConfigurationError.new("Configuration error for site '#{
|
58
|
+
raise RSMP::ConfigurationError.new("Configuration error for site '#{site_id}': #{e}")
|
69
59
|
end
|
70
60
|
end
|
71
61
|
|
@@ -101,7 +91,8 @@ module RSMP
|
|
101
91
|
reject socket, info
|
102
92
|
end
|
103
93
|
rescue ConnectionError => e
|
104
|
-
log "Rejected connection from #{remote_ip}, #{e.to_s}", level: :
|
94
|
+
log "Rejected connection from #{remote_ip}:#{remote_port}, #{e.to_s}", level: :warning
|
95
|
+
notify_error e
|
105
96
|
rescue StandardError => e
|
106
97
|
log "Connection: #{e.to_s}", exception: e, level: :error
|
107
98
|
notify_error e, level: :internal
|
@@ -131,6 +122,21 @@ module RSMP
|
|
131
122
|
end
|
132
123
|
end
|
133
124
|
|
125
|
+
def authorize_ip ip
|
126
|
+
return if @supervisor_settings['ips'] == 'all'
|
127
|
+
return if @supervisor_settings['ips'].include? ip
|
128
|
+
raise ConnectionError.new('guest ip not allowed')
|
129
|
+
end
|
130
|
+
|
131
|
+
def check_max_sites
|
132
|
+
max = @supervisor_settings['max_sites']
|
133
|
+
if max
|
134
|
+
if @proxies.size >= max
|
135
|
+
raise ConnectionError.new("maximum of #{max} sites already connected")
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
134
140
|
def connect socket, info
|
135
141
|
log "Site connected from #{format_ip_and_port(info)}",
|
136
142
|
ip: info[:ip],
|
@@ -138,15 +144,15 @@ module RSMP
|
|
138
144
|
level: :info,
|
139
145
|
timestamp: Clock.now
|
140
146
|
|
141
|
-
|
142
|
-
|
147
|
+
authorize_ip info[:ip]
|
148
|
+
check_max_sites
|
143
149
|
|
144
150
|
proxy = build_proxy({
|
145
151
|
supervisor: self,
|
146
152
|
ip: info[:ip],
|
147
153
|
port: info[:port],
|
148
154
|
task: @task,
|
149
|
-
settings:
|
155
|
+
settings: {'collect'=>@supervisor_settings['collect']},
|
150
156
|
socket: socket,
|
151
157
|
info: info,
|
152
158
|
logger: @logger,
|
@@ -158,7 +164,7 @@ module RSMP
|
|
158
164
|
@proxies.delete proxy
|
159
165
|
site_ids_changed
|
160
166
|
|
161
|
-
stop if @supervisor_settings['
|
167
|
+
stop if @supervisor_settings['one_shot']
|
162
168
|
end
|
163
169
|
|
164
170
|
def site_ids_changed
|
@@ -195,36 +201,36 @@ module RSMP
|
|
195
201
|
return site if site
|
196
202
|
wait_for(@site_id_condition,timeout) { find_site site_id }
|
197
203
|
rescue Async::TimeoutError
|
198
|
-
raise RSMP::TimeoutError.new "Site '#{site_id}'
|
204
|
+
raise RSMP::TimeoutError.new "Site '#{site_id}' did not connect within #{timeout}s"
|
199
205
|
end
|
200
206
|
|
201
207
|
def wait_for_site_disconnect site_id, timeout
|
202
208
|
wait_for(@site_id_condition,timeout) { true unless find_site site_id }
|
203
209
|
rescue Async::TimeoutError
|
204
|
-
raise RSMP::TimeoutError.new "Site '#{site_id}'
|
210
|
+
raise RSMP::TimeoutError.new "Site '#{site_id}' did not disconnect within #{timeout}s"
|
205
211
|
end
|
206
212
|
|
207
213
|
def check_site_id site_id
|
208
214
|
check_site_already_connected site_id
|
209
|
-
return
|
215
|
+
return site_id_to_site_setting site_id
|
210
216
|
end
|
211
217
|
|
212
218
|
def check_site_already_connected site_id
|
213
|
-
raise FatalError.new "Site '#{site_id}'
|
219
|
+
raise FatalError.new "Site '#{site_id}' already connected" if find_site(site_id)
|
214
220
|
end
|
215
221
|
|
216
|
-
def
|
222
|
+
def site_id_to_site_setting site_id
|
217
223
|
return {} unless @supervisor_settings['sites']
|
218
224
|
@supervisor_settings['sites'].each_pair do |id,settings|
|
219
|
-
if id ==
|
225
|
+
if id == 'guest' || id == site_id
|
220
226
|
return settings
|
221
227
|
end
|
222
228
|
end
|
223
|
-
raise FatalError.new "site id #{site_id}
|
229
|
+
raise FatalError.new "site id #{site_id} unknown"
|
224
230
|
end
|
225
231
|
|
226
232
|
def ip_to_site_settings ip
|
227
|
-
@supervisor_settings['sites'][ip] || @supervisor_settings['sites'][
|
233
|
+
@supervisor_settings['sites'][ip] || @supervisor_settings['sites']['guest']
|
228
234
|
end
|
229
235
|
|
230
236
|
def aggregated_status_changed site_proxy, component
|
@@ -32,8 +32,8 @@ module RSMP
|
|
32
32
|
send_version @site_settings['site_id'], @site_settings["rsmp_versions"]
|
33
33
|
rescue Errno::ECONNREFUSED
|
34
34
|
log "No connection to supervisor at #{@ip}:#{@port}", level: :error
|
35
|
-
unless @site.site_settings[
|
36
|
-
log "Will try to reconnect again every #{@site.site_settings[
|
35
|
+
unless @site.site_settings['intervals']['reconnect'] == :no
|
36
|
+
log "Will try to reconnect again every #{@site.site_settings['intervals']['reconnect']} seconds..", level: :info
|
37
37
|
@logger.mute @ip, @port
|
38
38
|
end
|
39
39
|
end
|
@@ -110,7 +110,7 @@ module RSMP
|
|
110
110
|
end
|
111
111
|
|
112
112
|
def reconnect_delay
|
113
|
-
interval = @site_settings[
|
113
|
+
interval = @site_settings['intervals']['reconnect']
|
114
114
|
log "Waiting #{interval} seconds before trying to reconnect", level: :info
|
115
115
|
@task.sleep interval
|
116
116
|
end
|
@@ -123,15 +123,28 @@ module RSMP
|
|
123
123
|
@version_determined = true
|
124
124
|
end
|
125
125
|
|
126
|
-
def send_aggregated_status component
|
126
|
+
def send_aggregated_status component, options={}
|
127
|
+
m_id = options[:m_id] || RSMP::Message.make_m_id
|
127
128
|
message = AggregatedStatus.new({
|
128
129
|
"aSTS" => clock.to_s,
|
129
130
|
"cId" => component.c_id,
|
130
131
|
"fP" => 'NormalControl',
|
131
132
|
"fS" => nil,
|
132
|
-
"se" => component.aggregated_status_bools
|
133
|
+
"se" => component.aggregated_status_bools,
|
134
|
+
"mId" => m_id
|
133
135
|
})
|
134
|
-
|
136
|
+
|
137
|
+
if options[:collect]
|
138
|
+
result = nil
|
139
|
+
task = @task.async do |task|
|
140
|
+
wait_for_acknowledgement task, options[:collect], m_id
|
141
|
+
end
|
142
|
+
send_message message, validate: options[:validate]
|
143
|
+
return message, task.wait
|
144
|
+
else
|
145
|
+
send_message message, validate: options[:validate]
|
146
|
+
message
|
147
|
+
end
|
135
148
|
end
|
136
149
|
|
137
150
|
def process_aggregated_status message
|
data/lib/rsmp/tlc.rb
CHANGED
@@ -88,7 +88,11 @@ module RSMP
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def format_signal_group_status
|
91
|
-
@
|
91
|
+
if @yellow_flash
|
92
|
+
'c' * @signal_groups.size
|
93
|
+
else
|
94
|
+
@signal_groups.map { |group| group.state }.join
|
95
|
+
end
|
92
96
|
end
|
93
97
|
|
94
98
|
def handle_command command_code, arg
|
@@ -794,7 +798,7 @@ module RSMP
|
|
794
798
|
super options
|
795
799
|
@sxl = 'traffic_light_controller'
|
796
800
|
@security_codes = options[:site_settings]['security_codes']
|
797
|
-
@interval = options[:site_settings]['
|
801
|
+
@interval = options[:site_settings]['intervals']['timer'] || 1
|
798
802
|
unless @main
|
799
803
|
raise ConfigurationError.new "TLC must have a main component"
|
800
804
|
end
|
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.1.
|
4
|
+
version: 0.1.33
|
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-
|
11
|
+
date: 2021-06-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async
|
@@ -197,7 +197,6 @@ files:
|
|
197
197
|
- Rakefile
|
198
198
|
- bin/console
|
199
199
|
- bin/setup
|
200
|
-
- config/site.yaml
|
201
200
|
- config/supervisor.yaml
|
202
201
|
- config/tlc.yaml
|
203
202
|
- documentation/classes_and_modules.md
|
@@ -212,6 +211,7 @@ files:
|
|
212
211
|
- lib/rsmp/components.rb
|
213
212
|
- lib/rsmp/convert/export/json_schema.rb
|
214
213
|
- lib/rsmp/convert/import/yaml.rb
|
214
|
+
- lib/rsmp/deep_merge.rb
|
215
215
|
- lib/rsmp/error.rb
|
216
216
|
- lib/rsmp/inspect.rb
|
217
217
|
- lib/rsmp/listener.rb
|
data/config/site.yaml
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
site_id: RN+SI0001
|
2
|
-
supervisors:
|
3
|
-
- ip: 127.0.0.1
|
4
|
-
port: 12111
|
5
|
-
|
6
|
-
sxl: traffic_light_controller
|
7
|
-
|
8
|
-
rsmp_versions:
|
9
|
-
- 3.1.1
|
10
|
-
- 3.1.2
|
11
|
-
- 3.1.3
|
12
|
-
- 3.1.4
|
13
|
-
|
14
|
-
components:
|
15
|
-
main:
|
16
|
-
C1:
|
17
|
-
|
18
|
-
watchdog_interval: 1
|
19
|
-
watchdog_timeout: 2
|
20
|
-
acknowledgement_timeout: 1
|
21
|
-
command_response_timeout: 1
|
22
|
-
status_response_timeout: 1
|
23
|
-
status_update_timeout: 1
|
24
|
-
reconnect_interval: 0.1
|
25
|
-
|
26
|
-
log:
|
27
|
-
active: true
|
28
|
-
color: true
|
29
|
-
timestamp: true
|
30
|
-
id: true
|
31
|
-
component: true
|
32
|
-
ip: false
|
33
|
-
site_id: true
|
34
|
-
level: false
|
35
|
-
text: true
|
36
|
-
direction: true
|
37
|
-
json: true
|
38
|
-
acknowledgements: false
|
39
|
-
watchdogs: false
|
40
|
-
|