rsmp 0.1.19 → 0.1.31
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitmodules +0 -4
- data/Gemfile.lock +16 -14
- data/config/supervisor.yaml +9 -15
- data/config/tlc.yaml +9 -8
- data/documentation/{classes.md → classes_and_modules.md} +25 -22
- data/documentation/message_distribution.md +23 -0
- data/lib/rsmp.rb +14 -5
- data/lib/rsmp/archive.rb +12 -17
- data/lib/rsmp/cli.rb +133 -102
- data/lib/rsmp/collector.rb +102 -0
- data/lib/rsmp/component.rb +2 -0
- data/lib/rsmp/{site_base.rb → components.rb} +3 -3
- data/lib/rsmp/convert/export/json_schema.rb +204 -0
- data/lib/rsmp/convert/import/yaml.rb +38 -0
- data/lib/rsmp/deep_merge.rb +11 -0
- data/lib/rsmp/inspect.rb +46 -0
- data/lib/rsmp/listener.rb +23 -0
- data/lib/rsmp/logger.rb +6 -4
- data/lib/rsmp/{base.rb → logging.rb} +3 -3
- data/lib/rsmp/message.rb +22 -31
- data/lib/rsmp/node.rb +15 -7
- data/lib/rsmp/notifier.rb +29 -0
- data/lib/rsmp/proxy.rb +114 -38
- data/lib/rsmp/rsmp.rb +34 -23
- data/lib/rsmp/site.rb +32 -34
- data/lib/rsmp/site_proxy.rb +160 -97
- data/lib/rsmp/site_proxy_wait.rb +206 -0
- data/lib/rsmp/supervisor.rb +82 -47
- data/lib/rsmp/supervisor_proxy.rb +21 -14
- data/lib/rsmp/tlc.rb +80 -38
- data/lib/rsmp/version.rb +1 -1
- data/lib/rsmp/wait.rb +4 -151
- data/rsmp.gemspec +4 -15
- metadata +27 -124
- data/config/site.yaml +0 -40
- data/lib/rsmp/probe.rb +0 -101
- data/lib/rsmp/probe_collection.rb +0 -28
@@ -0,0 +1,206 @@
|
|
1
|
+
# waiting for various types of messages and reponses from remote sites
|
2
|
+
module RSMP
|
3
|
+
module SiteProxyWait
|
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
|
+
def wait_for_alarm parent_task, options={}
|
24
|
+
matching_alarm = nil
|
25
|
+
message = collect(parent_task,options.merge(type: "Alarm", with_message: true, num: 1)) do |message|
|
26
|
+
# TODO check components
|
27
|
+
matching_alarm = nil
|
28
|
+
alarm = message
|
29
|
+
next if options[:aCId] && options[:aCId] != alarm.attribute("aCId")
|
30
|
+
next if options[:aSp] && options[:aSp] != alarm.attribute("aSp")
|
31
|
+
next if options[:aS] && options[:aS] != alarm.attribute("aS")
|
32
|
+
matching_alarm = alarm
|
33
|
+
break
|
34
|
+
end
|
35
|
+
if item
|
36
|
+
{ message: message, status: matching_alarm }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def collect_status_updates task, options, m_id
|
41
|
+
collect_status_updates_or_responses task, 'StatusUpdate', options, m_id
|
42
|
+
end
|
43
|
+
|
44
|
+
def collect_status_responses task, options, m_id
|
45
|
+
collect_status_updates_or_responses task, 'StatusResponse', options, m_id
|
46
|
+
end
|
47
|
+
|
48
|
+
def collect_command_responses parent_task, options, m_id
|
49
|
+
task.annotate "wait for command response"
|
50
|
+
want = options[:command_list].clone
|
51
|
+
result = {}
|
52
|
+
messages = []
|
53
|
+
collect(parent_task,options.merge({
|
54
|
+
type: ['CommandResponse','MessageNotAck'],
|
55
|
+
num: 1
|
56
|
+
})) do |message|
|
57
|
+
if message.is_a?(MessageNotAck)
|
58
|
+
if message.attribute('oMId') == m_id
|
59
|
+
# set result to an exception, but don't raise it.
|
60
|
+
# this will be returned by the task and stored as the task result
|
61
|
+
# when the parent task call wait() on the task, the exception
|
62
|
+
# will be raised in the parent task, and caught by rspec.
|
63
|
+
# rspec will then show the error and record the test as failed
|
64
|
+
m_id_short = RSMP::Message.shorten_m_id m_id, 8
|
65
|
+
result = RSMP::MessageRejected.new "Command request #{m_id_short} was rejected: #{message.attribute('rea')}"
|
66
|
+
next true # done, no more messages wanted
|
67
|
+
else
|
68
|
+
false
|
69
|
+
end
|
70
|
+
else
|
71
|
+
add = false
|
72
|
+
# look through querues
|
73
|
+
want.each_with_index do |query,i|
|
74
|
+
# look through items in message
|
75
|
+
message.attributes['rvs'].each do |input|
|
76
|
+
matching = command_match? query, input
|
77
|
+
if matching == true
|
78
|
+
result[query] = input
|
79
|
+
add = true
|
80
|
+
elsif matching == false
|
81
|
+
result.delete query
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
messages << message if add
|
86
|
+
result.size == want.size # any queries left to match?
|
87
|
+
end
|
88
|
+
end
|
89
|
+
return result, messages
|
90
|
+
rescue Async::TimeoutError
|
91
|
+
raise RSMP::TimeoutError.new "Did not receive correct command response to #{m_id} within #{options[:timeout]}s"
|
92
|
+
end
|
93
|
+
|
94
|
+
def collect_status_updates_or_responses task, type, options, m_id
|
95
|
+
want = options[:status_list].clone
|
96
|
+
result = {}
|
97
|
+
messages = []
|
98
|
+
# wait for a status update
|
99
|
+
collect(task,options.merge({
|
100
|
+
type: [type,'MessageNotAck'],
|
101
|
+
num: 1
|
102
|
+
})) do |message|
|
103
|
+
if message.is_a?(MessageNotAck)
|
104
|
+
if message.attribute('oMId') == m_id
|
105
|
+
# set result to an exception, but don't raise it.
|
106
|
+
# this will be returned by the task and stored as the task result
|
107
|
+
# when the parent task call wait() on the task, the exception
|
108
|
+
# will be raised in the parent task, and caught by rspec.
|
109
|
+
# rspec will then show the error and record the test as failed
|
110
|
+
m_id_short = RSMP::Message.shorten_m_id m_id, 8
|
111
|
+
result = RSMP::MessageRejected.new "Status request #{m_id_short} was rejected: #{message.attribute('rea')}"
|
112
|
+
next true # done, no more messages wanted
|
113
|
+
end
|
114
|
+
false
|
115
|
+
else
|
116
|
+
found = []
|
117
|
+
add = false
|
118
|
+
# look through querues
|
119
|
+
want.each_with_index do |query,i|
|
120
|
+
# look through status items in message
|
121
|
+
message.attributes['sS'].each do |input|
|
122
|
+
matching = status_match? query, input
|
123
|
+
if matching == true
|
124
|
+
result[query] = input
|
125
|
+
add = true
|
126
|
+
elsif matching == false
|
127
|
+
result.delete query
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
messages << message if add
|
132
|
+
result.size == want.size # any queries left to match?
|
133
|
+
end
|
134
|
+
end
|
135
|
+
return result, messages
|
136
|
+
rescue Async::TimeoutError
|
137
|
+
type_str = {'StatusUpdate'=>'update', 'StatusResponse'=>'response'}[type]
|
138
|
+
raise RSMP::TimeoutError.new "Did not received correct status #{type_str} in reply to #{m_id} within #{options[:timeout]}s"
|
139
|
+
end
|
140
|
+
|
141
|
+
def status_match? query, item
|
142
|
+
return nil if query['sCI'] && query['sCI'] != item['sCI']
|
143
|
+
return nil if query['n'] && query['n'] != item['n']
|
144
|
+
return false if query['q'] && query['q'] != item['q']
|
145
|
+
if query['s'].is_a? Regexp
|
146
|
+
return false if query['s'] && item['s'] !~ query['s']
|
147
|
+
else
|
148
|
+
return false if query['s'] && item['s'] != query['s']
|
149
|
+
end
|
150
|
+
true
|
151
|
+
end
|
152
|
+
|
153
|
+
def command_match? query, item
|
154
|
+
return nil if query['cCI'] && query['cCI'] != item['cCI']
|
155
|
+
return nil if query['n'] && query['n'] != item['n']
|
156
|
+
if query['v'].is_a? Regexp
|
157
|
+
return false if query['v'] && item['v'] !~ query['v']
|
158
|
+
else
|
159
|
+
return false if query['v'] && item['v'] != query['v']
|
160
|
+
end
|
161
|
+
true
|
162
|
+
end
|
163
|
+
|
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
|
+
def wait_for_aggregated_status parent_task, options={}
|
182
|
+
collect(parent_task,options.merge({
|
183
|
+
type: ['AggregatedStatus','MessageNotAck'],
|
184
|
+
num: 1
|
185
|
+
})) do |message|
|
186
|
+
if message.is_a?(MessageNotAck)
|
187
|
+
if message.attribute('oMId') == m_id
|
188
|
+
# set result to an exception, but don't raise it.
|
189
|
+
# this will be returned by the task and stored as the task result
|
190
|
+
# when the parent task call wait() on the task, the exception
|
191
|
+
# will be raised in the parent task, and caught by rspec.
|
192
|
+
# rspec will then show the error and record the test as failed
|
193
|
+
m_id_short = RSMP::Message.shorten_m_id m_id, 8
|
194
|
+
result = RSMP::MessageRejected.new "Aggregated status request #{m_id_short} was rejected: #{message.attribute('rea')}"
|
195
|
+
next true # done, no more messages wanted
|
196
|
+
else
|
197
|
+
false
|
198
|
+
end
|
199
|
+
else
|
200
|
+
true
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
end
|
data/lib/rsmp/supervisor.rb
CHANGED
@@ -17,47 +17,57 @@ 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
|
-
|
35
|
-
:any => {}
|
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
|
34
|
+
}
|
36
35
|
}
|
37
36
|
}
|
38
|
-
|
39
|
-
if options[:supervisor_settings]
|
40
|
-
converted = options[:supervisor_settings].map { |k,v| [k.to_s,v] }.to_h #convert symbol keys to string keys
|
41
|
-
converted.compact!
|
42
|
-
@supervisor_settings.merge! converted
|
43
|
-
end
|
44
|
-
|
45
|
-
required = [:port, :rsmp_versions, :watchdog_interval, :watchdog_timeout,
|
46
|
-
:acknowledgement_timeout, :command_response_timeout]
|
47
|
-
check_required_settings @supervisor_settings, required
|
48
37
|
|
38
|
+
# merge options into defaults
|
39
|
+
@supervisor_settings = defaults.deep_merge(options[:supervisor_settings] || {})
|
49
40
|
@rsmp_versions = @supervisor_settings["rsmp_versions"]
|
41
|
+
check_site_sxl_types
|
42
|
+
end
|
43
|
+
|
44
|
+
def check_site_sxl_types
|
45
|
+
sites = @supervisor_settings['sites'].clone || {}
|
46
|
+
sites['guest'] = @supervisor_settings['guest']
|
47
|
+
sites.each do |site_id,settings|
|
48
|
+
unless settings
|
49
|
+
raise RSMP::ConfigurationError.new("Configuration for site '#{site_id}' is empty")
|
50
|
+
end
|
51
|
+
sxl = settings['sxl']
|
52
|
+
sxl = 'tlc' unless sxl # temporary fix until configs are updated
|
53
|
+
unless sxl
|
54
|
+
raise RSMP::ConfigurationError.new("Configuration error for site '#{site_id}': No SXL specified")
|
55
|
+
end
|
56
|
+
RSMP::Schemer.find_schemas! sxl if sxl
|
57
|
+
rescue RSMP::Schemer::UnknownSchemaError => e
|
58
|
+
raise RSMP::ConfigurationError.new("Configuration error for site '#{site_id}': #{e}")
|
59
|
+
end
|
50
60
|
end
|
51
61
|
|
52
62
|
def start_action
|
53
63
|
@endpoint = Async::IO::Endpoint.tcp('0.0.0.0', @supervisor_settings["port"])
|
54
|
-
@endpoint.accept do |socket|
|
64
|
+
@endpoint.accept do |socket| # creates async tasks
|
55
65
|
handle_connection(socket)
|
66
|
+
rescue StandardError => e
|
67
|
+
notify_error e, level: :internal
|
56
68
|
end
|
57
|
-
rescue SystemCallError => e # all ERRNO errors
|
58
|
-
log "Exception: #{e.to_s}", level: :error
|
59
69
|
rescue StandardError => e
|
60
|
-
|
70
|
+
notify_error e, level: :internal
|
61
71
|
end
|
62
72
|
|
63
73
|
def stop
|
@@ -74,16 +84,18 @@ module RSMP
|
|
74
84
|
remote_hostname = socket.remote_address.ip_address
|
75
85
|
remote_ip = socket.remote_address.ip_address
|
76
86
|
|
77
|
-
info = {ip:remote_ip, port:remote_port, hostname:remote_hostname, now:
|
87
|
+
info = {ip:remote_ip, port:remote_port, hostname:remote_hostname, now:Clock.now}
|
78
88
|
if accept? socket, info
|
79
89
|
connect socket, info
|
80
90
|
else
|
81
91
|
reject socket, info
|
82
92
|
end
|
83
|
-
rescue
|
84
|
-
log "
|
93
|
+
rescue ConnectionError => e
|
94
|
+
log "Rejected connection from #{remote_ip}:#{remote_port}, #{e.to_s}", level: :warning
|
95
|
+
notify_error e
|
85
96
|
rescue StandardError => e
|
86
|
-
log "
|
97
|
+
log "Connection: #{e.to_s}", exception: e, level: :error
|
98
|
+
notify_error e, level: :internal
|
87
99
|
ensure
|
88
100
|
close socket, info
|
89
101
|
end
|
@@ -91,7 +103,7 @@ module RSMP
|
|
91
103
|
def starting
|
92
104
|
log "Starting supervisor on port #{@supervisor_settings["port"]}",
|
93
105
|
level: :info,
|
94
|
-
timestamp:
|
106
|
+
timestamp: @clock.now
|
95
107
|
end
|
96
108
|
|
97
109
|
def accept? socket, info
|
@@ -110,30 +122,49 @@ module RSMP
|
|
110
122
|
end
|
111
123
|
end
|
112
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
|
+
|
113
140
|
def connect socket, info
|
114
141
|
log "Site connected from #{format_ip_and_port(info)}",
|
115
142
|
ip: info[:ip],
|
116
143
|
port: info[:port],
|
117
144
|
level: :info,
|
118
|
-
timestamp:
|
145
|
+
timestamp: Clock.now
|
146
|
+
|
147
|
+
authorize_ip info[:ip]
|
148
|
+
check_max_sites
|
119
149
|
|
120
150
|
proxy = build_proxy({
|
121
151
|
supervisor: self,
|
152
|
+
ip: info[:ip],
|
153
|
+
port: info[:port],
|
122
154
|
task: @task,
|
123
|
-
settings:
|
155
|
+
settings: {'collect'=>@supervisor_settings['collect']},
|
124
156
|
socket: socket,
|
125
157
|
info: info,
|
126
158
|
logger: @logger,
|
127
159
|
archive: @archive
|
128
160
|
})
|
129
161
|
@proxies.push proxy
|
130
|
-
|
131
162
|
proxy.run # will run until the site disconnects
|
132
163
|
ensure
|
133
164
|
@proxies.delete proxy
|
134
165
|
site_ids_changed
|
135
166
|
|
136
|
-
stop if @supervisor_settings['
|
167
|
+
stop if @supervisor_settings['one_shot']
|
137
168
|
end
|
138
169
|
|
139
170
|
def site_ids_changed
|
@@ -146,9 +177,9 @@ module RSMP
|
|
146
177
|
|
147
178
|
def close socket, info
|
148
179
|
if info
|
149
|
-
log "Connection to #{format_ip_and_port(info)} closed", ip: info[:ip], level: :info, timestamp:
|
180
|
+
log "Connection to #{format_ip_and_port(info)} closed", ip: info[:ip], level: :info, timestamp: Clock.now
|
150
181
|
else
|
151
|
-
log "Connection closed", level: :info, timestamp:
|
182
|
+
log "Connection closed", level: :info, timestamp: Clock.now
|
152
183
|
end
|
153
184
|
|
154
185
|
socket.close
|
@@ -170,32 +201,36 @@ module RSMP
|
|
170
201
|
return site if site
|
171
202
|
wait_for(@site_id_condition,timeout) { find_site site_id }
|
172
203
|
rescue Async::TimeoutError
|
173
|
-
|
204
|
+
raise RSMP::TimeoutError.new "Site '#{site_id}' did not connect within #{timeout}s"
|
174
205
|
end
|
175
206
|
|
176
207
|
def wait_for_site_disconnect site_id, timeout
|
177
208
|
wait_for(@site_id_condition,timeout) { true unless find_site site_id }
|
178
209
|
rescue Async::TimeoutError
|
179
|
-
|
210
|
+
raise RSMP::TimeoutError.new "Site '#{site_id}' did not disconnect within #{timeout}s"
|
180
211
|
end
|
181
212
|
|
182
213
|
def check_site_id site_id
|
183
214
|
check_site_already_connected site_id
|
184
|
-
return
|
215
|
+
return site_id_to_site_setting site_id
|
185
216
|
end
|
186
217
|
|
187
218
|
def check_site_already_connected site_id
|
188
|
-
raise FatalError.new "Site #{site_id} already connected" if find_site(site_id)
|
219
|
+
raise FatalError.new "Site '#{site_id}' already connected" if find_site(site_id)
|
189
220
|
end
|
190
221
|
|
191
|
-
def
|
222
|
+
def site_id_to_site_setting site_id
|
192
223
|
return {} unless @supervisor_settings['sites']
|
193
224
|
@supervisor_settings['sites'].each_pair do |id,settings|
|
194
|
-
if id ==
|
225
|
+
if id == 'guest' || id == site_id
|
195
226
|
return settings
|
196
227
|
end
|
197
228
|
end
|
198
|
-
raise FatalError.new "site id #{site_id}
|
229
|
+
raise FatalError.new "site id #{site_id} unknown"
|
230
|
+
end
|
231
|
+
|
232
|
+
def ip_to_site_settings ip
|
233
|
+
@supervisor_settings['sites'][ip] || @supervisor_settings['sites']['guest']
|
199
234
|
end
|
200
235
|
|
201
236
|
def aggregated_status_changed site_proxy, component
|
@@ -14,7 +14,6 @@ module RSMP
|
|
14
14
|
@ip = options[:ip]
|
15
15
|
@port = options[:port]
|
16
16
|
@status_subscriptions = {}
|
17
|
-
@status_subscriptions_mutex = Mutex.new
|
18
17
|
@sxl = @site_settings['sxl']
|
19
18
|
@synthetic_id = Supervisor.build_id_from_ip_port @ip, @port
|
20
19
|
end
|
@@ -33,8 +32,8 @@ module RSMP
|
|
33
32
|
send_version @site_settings['site_id'], @site_settings["rsmp_versions"]
|
34
33
|
rescue Errno::ECONNREFUSED
|
35
34
|
log "No connection to supervisor at #{@ip}:#{@port}", level: :error
|
36
|
-
unless @site.site_settings[
|
37
|
-
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
|
38
37
|
@logger.mute @ip, @port
|
39
38
|
end
|
40
39
|
end
|
@@ -50,12 +49,12 @@ module RSMP
|
|
50
49
|
@endpoint = Async::IO::Endpoint.tcp(@ip, @port)
|
51
50
|
@socket = @endpoint.connect
|
52
51
|
@stream = Async::IO::Stream.new(@socket)
|
53
|
-
@protocol = Async::IO::Protocol::Line.new(@stream,
|
52
|
+
@protocol = Async::IO::Protocol::Line.new(@stream,WRAPPING_DELIMITER) # rsmp messages are json terminated with a form-feed
|
54
53
|
end
|
55
54
|
|
56
55
|
def connection_complete
|
57
56
|
super
|
58
|
-
log "Connection to supervisor established", level: :info
|
57
|
+
log "Connection to supervisor established, using core #{@rsmp_version}, #{sxl} #{sxl_version}", level: :info
|
59
58
|
start_watchdog
|
60
59
|
end
|
61
60
|
|
@@ -66,6 +65,8 @@ module RSMP
|
|
66
65
|
when StatusUpdate
|
67
66
|
when AggregatedStatus
|
68
67
|
will_not_handle message
|
68
|
+
when AggregatedStatusRequest
|
69
|
+
process_aggregated_status_request message
|
69
70
|
when CommandRequest
|
70
71
|
process_command_request message
|
71
72
|
when CommandResponse
|
@@ -109,7 +110,7 @@ module RSMP
|
|
109
110
|
end
|
110
111
|
|
111
112
|
def reconnect_delay
|
112
|
-
interval = @site_settings[
|
113
|
+
interval = @site_settings['intervals']['reconnect']
|
113
114
|
log "Waiting #{interval} seconds before trying to reconnect", level: :info
|
114
115
|
@task.sleep interval
|
115
116
|
end
|
@@ -124,7 +125,7 @@ module RSMP
|
|
124
125
|
|
125
126
|
def send_aggregated_status component
|
126
127
|
message = AggregatedStatus.new({
|
127
|
-
"aSTS" =>
|
128
|
+
"aSTS" => clock.to_s,
|
128
129
|
"cId" => component.c_id,
|
129
130
|
"fP" => 'NormalControl',
|
130
131
|
"fS" => nil,
|
@@ -162,6 +163,14 @@ module RSMP
|
|
162
163
|
sorted
|
163
164
|
end
|
164
165
|
|
166
|
+
def process_aggregated_status_request message
|
167
|
+
log "Received #{message.type}", message: message, level: :log
|
168
|
+
component_id = message.attributes["cId"]
|
169
|
+
component = @site.find_component component_id
|
170
|
+
acknowledge message
|
171
|
+
send_aggregated_status component
|
172
|
+
end
|
173
|
+
|
165
174
|
def process_command_request message
|
166
175
|
log "Received #{message.type}", message: message, level: :log
|
167
176
|
component_id = message.attributes["cId"]
|
@@ -178,7 +187,7 @@ module RSMP
|
|
178
187
|
end
|
179
188
|
response = CommandResponse.new({
|
180
189
|
"cId"=>component_id,
|
181
|
-
"cTS"=>
|
190
|
+
"cTS"=>clock.to_s,
|
182
191
|
"rvs"=>rvs
|
183
192
|
})
|
184
193
|
acknowledge message
|
@@ -195,7 +204,7 @@ module RSMP
|
|
195
204
|
end
|
196
205
|
response = StatusResponse.new({
|
197
206
|
"cId"=>component_id,
|
198
|
-
"sTs"=>
|
207
|
+
"sTs"=>clock.to_s,
|
199
208
|
"sS"=>sS,
|
200
209
|
"mId" => options[:m_id]
|
201
210
|
})
|
@@ -222,7 +231,7 @@ module RSMP
|
|
222
231
|
update_list[component] ||= {}
|
223
232
|
|
224
233
|
subs = @status_subscriptions[component]
|
225
|
-
now =
|
234
|
+
now = Time.now # internal timestamp
|
226
235
|
|
227
236
|
message.attributes["sS"].each do |arg|
|
228
237
|
sCI = arg["sCI"]
|
@@ -311,12 +320,10 @@ module RSMP
|
|
311
320
|
end
|
312
321
|
end
|
313
322
|
send_status_updates update_list
|
314
|
-
rescue StandardError => e
|
315
|
-
log ["Status update exception: #{e}",e.backtrace].flatten.join("\n"), level: :error
|
316
323
|
end
|
317
324
|
|
318
325
|
def send_status_updates update_list
|
319
|
-
now =
|
326
|
+
now = clock.to_s
|
320
327
|
update_list.each_pair do |component_id,by_code|
|
321
328
|
component = @site.find_component component_id
|
322
329
|
sS = []
|
@@ -344,7 +351,7 @@ module RSMP
|
|
344
351
|
|
345
352
|
def send_alarm
|
346
353
|
message = Alarm.new({
|
347
|
-
"aSTS"=>
|
354
|
+
"aSTS"=>clock.to_s,
|
348
355
|
"fP"=>nil,
|
349
356
|
"fS"=>nil,
|
350
357
|
"se"=>@site.aggregated_status_bools
|