rsmp 0.1.19 → 0.1.31
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/.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
|