rsmp 0.1.21 → 0.1.32
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 +13 -11
- data/config/supervisor.yaml +9 -15
- data/config/tlc.yaml +9 -8
- data/documentation/message_distribution.md +8 -8
- data/lib/rsmp.rb +5 -0
- data/lib/rsmp/archive.rb +7 -4
- data/lib/rsmp/cli.rb +133 -102
- data/lib/rsmp/collector.rb +42 -30
- data/lib/rsmp/component.rb +2 -0
- data/lib/rsmp/components.rb +1 -1
- 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 +4 -14
- data/lib/rsmp/logger.rb +3 -1
- data/lib/rsmp/logging.rb +1 -1
- data/lib/rsmp/message.rb +22 -31
- data/lib/rsmp/node.rb +11 -1
- data/lib/rsmp/notifier.rb +7 -2
- data/lib/rsmp/proxy.rb +95 -39
- data/lib/rsmp/rsmp.rb +34 -23
- data/lib/rsmp/site.rb +30 -32
- data/lib/rsmp/site_proxy.rb +103 -22
- data/lib/rsmp/site_proxy_wait.rb +63 -38
- data/lib/rsmp/supervisor.rb +82 -47
- data/lib/rsmp/supervisor_proxy.rb +21 -13
- data/lib/rsmp/tlc.rb +61 -35
- data/lib/rsmp/version.rb +1 -1
- data/rsmp.gemspec +3 -14
- metadata +13 -113
- data/config/site.yaml +0 -40
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,18 +122,37 @@ 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
|
-
settings = @supervisor_settings['sites'][info[:ip]] || @supervisor_settings['sites'][:any]
|
121
150
|
proxy = build_proxy({
|
122
151
|
supervisor: self,
|
152
|
+
ip: info[:ip],
|
153
|
+
port: info[:port],
|
123
154
|
task: @task,
|
124
|
-
settings:
|
155
|
+
settings: {'collect'=>@supervisor_settings['collect']},
|
125
156
|
socket: socket,
|
126
157
|
info: info,
|
127
158
|
logger: @logger,
|
@@ -133,7 +164,7 @@ module RSMP
|
|
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
|
@@ -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
|
@@ -49,12 +49,12 @@ module RSMP
|
|
49
49
|
@endpoint = Async::IO::Endpoint.tcp(@ip, @port)
|
50
50
|
@socket = @endpoint.connect
|
51
51
|
@stream = Async::IO::Stream.new(@socket)
|
52
|
-
@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
|
53
53
|
end
|
54
54
|
|
55
55
|
def connection_complete
|
56
56
|
super
|
57
|
-
log "Connection to supervisor established", level: :info
|
57
|
+
log "Connection to supervisor established, using core #{@rsmp_version}, #{sxl} #{sxl_version}", level: :info
|
58
58
|
start_watchdog
|
59
59
|
end
|
60
60
|
|
@@ -65,6 +65,8 @@ module RSMP
|
|
65
65
|
when StatusUpdate
|
66
66
|
when AggregatedStatus
|
67
67
|
will_not_handle message
|
68
|
+
when AggregatedStatusRequest
|
69
|
+
process_aggregated_status_request message
|
68
70
|
when CommandRequest
|
69
71
|
process_command_request message
|
70
72
|
when CommandResponse
|
@@ -108,7 +110,7 @@ module RSMP
|
|
108
110
|
end
|
109
111
|
|
110
112
|
def reconnect_delay
|
111
|
-
interval = @site_settings[
|
113
|
+
interval = @site_settings['intervals']['reconnect']
|
112
114
|
log "Waiting #{interval} seconds before trying to reconnect", level: :info
|
113
115
|
@task.sleep interval
|
114
116
|
end
|
@@ -123,7 +125,7 @@ module RSMP
|
|
123
125
|
|
124
126
|
def send_aggregated_status component
|
125
127
|
message = AggregatedStatus.new({
|
126
|
-
"aSTS" =>
|
128
|
+
"aSTS" => clock.to_s,
|
127
129
|
"cId" => component.c_id,
|
128
130
|
"fP" => 'NormalControl',
|
129
131
|
"fS" => nil,
|
@@ -161,6 +163,14 @@ module RSMP
|
|
161
163
|
sorted
|
162
164
|
end
|
163
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
|
+
|
164
174
|
def process_command_request message
|
165
175
|
log "Received #{message.type}", message: message, level: :log
|
166
176
|
component_id = message.attributes["cId"]
|
@@ -177,7 +187,7 @@ module RSMP
|
|
177
187
|
end
|
178
188
|
response = CommandResponse.new({
|
179
189
|
"cId"=>component_id,
|
180
|
-
"cTS"=>
|
190
|
+
"cTS"=>clock.to_s,
|
181
191
|
"rvs"=>rvs
|
182
192
|
})
|
183
193
|
acknowledge message
|
@@ -194,7 +204,7 @@ module RSMP
|
|
194
204
|
end
|
195
205
|
response = StatusResponse.new({
|
196
206
|
"cId"=>component_id,
|
197
|
-
"sTs"=>
|
207
|
+
"sTs"=>clock.to_s,
|
198
208
|
"sS"=>sS,
|
199
209
|
"mId" => options[:m_id]
|
200
210
|
})
|
@@ -221,7 +231,7 @@ module RSMP
|
|
221
231
|
update_list[component] ||= {}
|
222
232
|
|
223
233
|
subs = @status_subscriptions[component]
|
224
|
-
now =
|
234
|
+
now = Time.now # internal timestamp
|
225
235
|
|
226
236
|
message.attributes["sS"].each do |arg|
|
227
237
|
sCI = arg["sCI"]
|
@@ -310,12 +320,10 @@ module RSMP
|
|
310
320
|
end
|
311
321
|
end
|
312
322
|
send_status_updates update_list
|
313
|
-
rescue StandardError => e
|
314
|
-
log ["Status update exception: #{e}",e.backtrace].flatten.join("\n"), level: :error
|
315
323
|
end
|
316
324
|
|
317
325
|
def send_status_updates update_list
|
318
|
-
now =
|
326
|
+
now = clock.to_s
|
319
327
|
update_list.each_pair do |component_id,by_code|
|
320
328
|
component = @site.find_component component_id
|
321
329
|
sS = []
|
@@ -343,7 +351,7 @@ module RSMP
|
|
343
351
|
|
344
352
|
def send_alarm
|
345
353
|
message = Alarm.new({
|
346
|
-
"aSTS"=>
|
354
|
+
"aSTS"=>clock.to_s,
|
347
355
|
"fP"=>nil,
|
348
356
|
"fS"=>nil,
|
349
357
|
"se"=>@site.aggregated_status_bools
|
data/lib/rsmp/tlc.rb
CHANGED
@@ -13,7 +13,6 @@ module RSMP
|
|
13
13
|
@cycle_time = cycle_time
|
14
14
|
@num_traffic_situations = 1
|
15
15
|
@num_inputs = 8
|
16
|
-
|
17
16
|
reset
|
18
17
|
end
|
19
18
|
|
@@ -41,6 +40,11 @@ module RSMP
|
|
41
40
|
@input_results = '0'*@num_inputs
|
42
41
|
end
|
43
42
|
|
43
|
+
def clock
|
44
|
+
node.clock
|
45
|
+
end
|
46
|
+
|
47
|
+
|
44
48
|
def add_signal_group group
|
45
49
|
@signal_groups << group
|
46
50
|
end
|
@@ -48,8 +52,12 @@ module RSMP
|
|
48
52
|
def add_detector_logic logic
|
49
53
|
@detector_logics << logic
|
50
54
|
end
|
55
|
+
|
51
56
|
def timer now
|
52
|
-
|
57
|
+
# TODO
|
58
|
+
# We should use a monotone timer, to avoid jumps
|
59
|
+
# in case the user sets the system time
|
60
|
+
pos = Time.now.to_i % @cycle_time
|
53
61
|
if pos != @pos
|
54
62
|
@pos = pos
|
55
63
|
move pos
|
@@ -80,7 +88,11 @@ module RSMP
|
|
80
88
|
end
|
81
89
|
|
82
90
|
def format_signal_group_status
|
83
|
-
@
|
91
|
+
if @yellow_flash
|
92
|
+
'c' * @signal_groups.size
|
93
|
+
else
|
94
|
+
@signal_groups.map { |group| group.state }.join
|
95
|
+
end
|
84
96
|
end
|
85
97
|
|
86
98
|
def handle_command command_code, arg
|
@@ -202,6 +214,17 @@ module RSMP
|
|
202
214
|
|
203
215
|
def handle_m0104 arg
|
204
216
|
@node.verify_security_code 1, arg['securityCode']
|
217
|
+
time = Time.new(
|
218
|
+
arg['year'],
|
219
|
+
arg['month'],
|
220
|
+
arg['day'],
|
221
|
+
arg['hour'],
|
222
|
+
arg['minute'],
|
223
|
+
arg['second'],
|
224
|
+
'UTC'
|
225
|
+
)
|
226
|
+
@node.clock.set time
|
227
|
+
log "Clock set to #{time}, (adjustment is #{@node.clock.adjustment}s)", level: :info
|
205
228
|
end
|
206
229
|
|
207
230
|
def set_input i, value
|
@@ -518,35 +541,37 @@ module RSMP
|
|
518
541
|
end
|
519
542
|
|
520
543
|
def handle_s0096 status_code, status_name=nil
|
544
|
+
now = clock.now
|
521
545
|
case status_name
|
522
546
|
when 'year'
|
523
|
-
RSMP::Tlc.make_status
|
547
|
+
RSMP::Tlc.make_status now.year.to_s.rjust(4, "0")
|
524
548
|
when 'month'
|
525
|
-
RSMP::Tlc.make_status
|
549
|
+
RSMP::Tlc.make_status now.month.to_s.rjust(2, "0")
|
526
550
|
when 'day'
|
527
|
-
RSMP::Tlc.make_status
|
551
|
+
RSMP::Tlc.make_status now.day.to_s.rjust(2, "0")
|
528
552
|
when 'hour'
|
529
|
-
RSMP::Tlc.make_status
|
553
|
+
RSMP::Tlc.make_status now.hour.to_s.rjust(2, "0")
|
530
554
|
when 'minute'
|
531
|
-
RSMP::Tlc.make_status
|
555
|
+
RSMP::Tlc.make_status now.min.to_s.rjust(2, "0")
|
532
556
|
when 'second'
|
533
|
-
RSMP::Tlc.make_status
|
557
|
+
RSMP::Tlc.make_status now.sec.to_s.rjust(2, "0")
|
534
558
|
end
|
535
559
|
end
|
536
560
|
|
537
561
|
def handle_s0097 status_code, status_name=nil
|
538
562
|
case status_name
|
539
|
-
when '
|
540
|
-
RSMP::Tlc.make_status '1'
|
541
|
-
when 'hash'
|
563
|
+
when 'checksum'
|
542
564
|
RSMP::Tlc.make_status '1'
|
565
|
+
when 'timestamp'
|
566
|
+
now = @node.clock.to_s
|
567
|
+
RSMP::Tlc.make_status now
|
543
568
|
end
|
544
569
|
end
|
545
570
|
|
546
571
|
def handle_s0205 status_code, status_name=nil
|
547
572
|
case status_name
|
548
573
|
when 'start'
|
549
|
-
RSMP::Tlc.make_status
|
574
|
+
RSMP::Tlc.make_status clock.to_s
|
550
575
|
when 'vehicles'
|
551
576
|
RSMP::Tlc.make_status 0
|
552
577
|
end
|
@@ -555,7 +580,7 @@ module RSMP
|
|
555
580
|
def handle_s0206 status_code, status_name=nil
|
556
581
|
case status_name
|
557
582
|
when 'start'
|
558
|
-
RSMP::Tlc.make_status
|
583
|
+
RSMP::Tlc.make_status clock.to_s
|
559
584
|
when 'speed'
|
560
585
|
RSMP::Tlc.make_status 0
|
561
586
|
end
|
@@ -564,7 +589,7 @@ module RSMP
|
|
564
589
|
def handle_s0207 status_code, status_name=nil
|
565
590
|
case status_name
|
566
591
|
when 'start'
|
567
|
-
RSMP::Tlc.make_status
|
592
|
+
RSMP::Tlc.make_status clock.to_s
|
568
593
|
when 'occupancy'
|
569
594
|
RSMP::Tlc.make_status 0
|
570
595
|
end
|
@@ -573,7 +598,7 @@ module RSMP
|
|
573
598
|
def handle_s0208 status_code, status_name=nil
|
574
599
|
case status_name
|
575
600
|
when 'start'
|
576
|
-
RSMP::Tlc.make_status
|
601
|
+
RSMP::Tlc.make_status clock.to_s
|
577
602
|
when 'P'
|
578
603
|
RSMP::Tlc.make_status 0
|
579
604
|
when 'PS'
|
@@ -653,21 +678,22 @@ module RSMP
|
|
653
678
|
end
|
654
679
|
|
655
680
|
def handle_s0025 status_code, status_name=nil
|
681
|
+
now = @node.clock.to_s
|
656
682
|
case status_name
|
657
683
|
when 'minToGEstimate'
|
658
|
-
RSMP::Tlc.make_status
|
684
|
+
RSMP::Tlc.make_status now
|
659
685
|
when 'maxToGEstimate'
|
660
|
-
RSMP::Tlc.make_status
|
686
|
+
RSMP::Tlc.make_status now
|
661
687
|
when 'likelyToGEstimate'
|
662
|
-
RSMP::Tlc.make_status
|
688
|
+
RSMP::Tlc.make_status now
|
663
689
|
when 'ToGConfidence'
|
664
690
|
RSMP::Tlc.make_status 0
|
665
691
|
when 'minToREstimate'
|
666
|
-
RSMP::Tlc.make_status
|
692
|
+
RSMP::Tlc.make_status now
|
667
693
|
when 'maxToREstimate'
|
668
|
-
RSMP::Tlc.make_status
|
694
|
+
RSMP::Tlc.make_status now
|
669
695
|
when 'likelyToREstimate'
|
670
|
-
RSMP::Tlc.make_status
|
696
|
+
RSMP::Tlc.make_status now
|
671
697
|
when 'ToRConfidence'
|
672
698
|
RSMP::Tlc.make_status 0
|
673
699
|
end
|
@@ -695,7 +721,7 @@ module RSMP
|
|
695
721
|
def handle_s0201 status_code, status_name=nil
|
696
722
|
case status_name
|
697
723
|
when 'starttime'
|
698
|
-
RSMP::Tlc.make_status
|
724
|
+
RSMP::Tlc.make_status @node.clock.to_s
|
699
725
|
when 'vehicles'
|
700
726
|
RSMP::Tlc.make_status 0
|
701
727
|
end
|
@@ -704,7 +730,7 @@ module RSMP
|
|
704
730
|
def handle_s0202 status_code, status_name=nil
|
705
731
|
case status_name
|
706
732
|
when 'starttime'
|
707
|
-
RSMP::Tlc.make_status
|
733
|
+
RSMP::Tlc.make_status @node.clock.to_s
|
708
734
|
when 'speed'
|
709
735
|
RSMP::Tlc.make_status 0
|
710
736
|
end
|
@@ -713,7 +739,7 @@ module RSMP
|
|
713
739
|
def handle_s0203 status_code, status_name=nil
|
714
740
|
case status_name
|
715
741
|
when 'starttime'
|
716
|
-
RSMP::Tlc.make_status
|
742
|
+
RSMP::Tlc.make_status @node.clock.to_s
|
717
743
|
when 'occupancy'
|
718
744
|
RSMP::Tlc.make_status 0
|
719
745
|
end
|
@@ -722,7 +748,7 @@ module RSMP
|
|
722
748
|
def handle_s0204 status_code, status_name=nil
|
723
749
|
case status_name
|
724
750
|
when 'starttime'
|
725
|
-
RSMP::Tlc.make_status
|
751
|
+
RSMP::Tlc.make_status @node.clock.to_s
|
726
752
|
when 'P'
|
727
753
|
RSMP::Tlc.make_status 0
|
728
754
|
when 'PS'
|
@@ -767,11 +793,12 @@ module RSMP
|
|
767
793
|
end
|
768
794
|
|
769
795
|
class Tlc < Site
|
796
|
+
attr_accessor :main
|
770
797
|
def initialize options={}
|
771
798
|
super options
|
772
799
|
@sxl = 'traffic_light_controller'
|
773
800
|
@security_codes = options[:site_settings]['security_codes']
|
774
|
-
@interval = options[:site_settings]['
|
801
|
+
@interval = options[:site_settings]['intervals']['timer'] || 1
|
775
802
|
unless @main
|
776
803
|
raise ConfigurationError.new "TLC must have a main component"
|
777
804
|
end
|
@@ -806,22 +833,21 @@ module RSMP
|
|
806
833
|
next_time = Time.now.to_f
|
807
834
|
loop do
|
808
835
|
begin
|
809
|
-
now
|
810
|
-
timer(now)
|
836
|
+
timer(@clock.now)
|
811
837
|
rescue EOFError => e
|
812
|
-
log "
|
838
|
+
log "Connection closed: #{e}", level: :warning
|
813
839
|
rescue IOError => e
|
814
|
-
log "
|
840
|
+
log "IOError", level: :warning
|
815
841
|
rescue Errno::ECONNRESET
|
816
|
-
log "
|
842
|
+
log "Connection reset by peer", level: :warning
|
817
843
|
rescue Errno::EPIPE => e
|
818
|
-
log "
|
844
|
+
log "Broken pipe", level: :warning
|
819
845
|
rescue StandardError => e
|
820
|
-
|
846
|
+
notify_error e, level: :internal
|
821
847
|
ensure
|
822
848
|
# adjust sleep duration to avoid drift. so wake up always happens on the
|
823
849
|
# same fractional second.
|
824
|
-
# note that Time.now is not monotonic. If the clock
|
850
|
+
# note that Time.now is not monotonic. If the clock is changed,
|
825
851
|
# either manaully or via NTP, the sleep interval might jump.
|
826
852
|
# an alternative is to use ::Process.clock_gettime(::Process::CLOCK_MONOTONIC),
|
827
853
|
# to get the current time. this ensures a constant interval, but
|