rsmp 0.1.27 → 0.1.33
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/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
|
-
|