rsmp 0.6.1 → 0.6.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/README.md +2 -2
- data/config/supervisor.yaml +1 -7
- data/config/tlc.yaml +17 -11
- data/lib/rsmp/archive.rb +1 -1
- data/lib/rsmp/cli.rb +1 -1
- data/lib/rsmp/component.rb +11 -10
- data/lib/rsmp/components.rb +2 -1
- data/lib/rsmp/error.rb +3 -0
- data/lib/rsmp/logger.rb +8 -7
- data/lib/rsmp/logging.rb +1 -1
- data/lib/rsmp/message.rb +1 -1
- data/lib/rsmp/proxy.rb +8 -5
- data/lib/rsmp/supervisor_proxy.rb +11 -4
- data/lib/rsmp/tlc/detector_logic.rb +101 -0
- data/lib/rsmp/tlc/signal_group.rb +85 -0
- data/lib/rsmp/tlc/signal_plan.rb +29 -0
- data/lib/rsmp/tlc/traffic_controller.rb +652 -0
- data/lib/rsmp/tlc/traffic_controller_site.rb +136 -0
- data/lib/rsmp/version.rb +1 -1
- data/lib/rsmp.rb +5 -1
- metadata +8 -4
- data/lib/rsmp/tlc.rb +0 -920
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ffe9f097053c9814ad119cbd6a01192cd20c02d3ca1fffa6269dbdf534f419b
|
4
|
+
data.tar.gz: 9848398d419a76f16fa8eb1f527d4c6b055b17886a5ee689b7607c891103d5a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d974b915cbc32bee428cc7f39a1e26134c6db34f72590ad9bd67400ad71ce831037a82341601369aa6582c1e4b5ecf8d4e6f8c3249a4375716bc877ca1cc7cec
|
7
|
+
data.tar.gz: 301eb51aecb05c57fc3395f3a06df33846e24fdd863db2ff65e81e9fc1b7c23c4e6b40e508b15a3ec0c92e87595ce78317773cfca6e13ec72ca9609d037cb1f1
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rsmp (0.6.
|
4
|
+
rsmp (0.6.5)
|
5
5
|
async (~> 1.29.1)
|
6
6
|
async-io (~> 1.32.1)
|
7
7
|
colorize (~> 0.8.1)
|
@@ -96,7 +96,7 @@ GEM
|
|
96
96
|
thread_safe
|
97
97
|
rake (13.0.3)
|
98
98
|
regexp_parser (2.1.1)
|
99
|
-
rsmp_schemer (0.3.
|
99
|
+
rsmp_schemer (0.3.2)
|
100
100
|
json_schemer (~> 0.2.18)
|
101
101
|
rspec (3.10.0)
|
102
102
|
rspec-core (~> 3.10.0)
|
data/README.md
CHANGED
@@ -125,7 +125,7 @@ This will output messages form both the site and the supervisor, ordered chronol
|
|
125
125
|
```console
|
126
126
|
RN+SU0001 Starting supervisor RN+SU0001 on port 12111
|
127
127
|
RN+SI0001 Starting site RN+SI0001
|
128
|
-
RN+SI0001 Connecting to
|
128
|
+
RN+SI0001 Connecting to supervisor at 127.0.0.1:12111
|
129
129
|
RN+SI0001 <-- f8c7 Sent Version
|
130
130
|
RN+SU0001 Site connected from 127.0.0.1:53500
|
131
131
|
RN+SU0001 RN+SI0001 --> f8c7 Received Version message for sites [RN+SI0001] using RSMP 3.1.4
|
@@ -156,7 +156,7 @@ The ```site``` command will start an RSMP site, which will try to connect to one
|
|
156
156
|
```console
|
157
157
|
% rsmp site
|
158
158
|
2019-11-11 12:22:00 UTC Starting site RN+SI0001
|
159
|
-
2019-11-11 12:22:00 UTC Connecting to
|
159
|
+
2019-11-11 12:22:00 UTC Connecting to supervisor at 127.0.0.1:12111
|
160
160
|
2019-11-11 12:22:00 UTC <-- 792f Sent Version
|
161
161
|
2019-11-11 12:22:00 UTC RN+SU0001 --> e70e Received Version message, using RSMP 3.1.4
|
162
162
|
2019-11-11 12:22:00 UTC RN+SU0001 Connection to supervisor established
|
data/config/supervisor.yaml
CHANGED
@@ -8,15 +8,9 @@ guest:
|
|
8
8
|
watchdog: 0.2
|
9
9
|
acknowledgement: 0.2
|
10
10
|
log:
|
11
|
-
active: true
|
12
|
-
color: true
|
13
|
-
timestamp: true
|
14
|
-
component: true
|
15
|
-
ip: false
|
16
11
|
port: true
|
17
12
|
site_id: 9
|
18
|
-
|
19
|
-
text: true
|
13
|
+
component: 2
|
20
14
|
direction: false
|
21
15
|
level: false
|
22
16
|
debug: true
|
data/config/tlc.yaml
CHANGED
@@ -10,15 +10,27 @@ components:
|
|
10
10
|
cycle_time: 6
|
11
11
|
signal_group:
|
12
12
|
A1:
|
13
|
-
plan: '11NBBB'
|
14
13
|
A2:
|
15
|
-
plan: '1NBBBB'
|
16
14
|
B1:
|
17
|
-
plan: 'BBB11N'
|
18
15
|
B2:
|
19
|
-
plan: 'BBB1NB'
|
20
16
|
detector_logic:
|
21
17
|
DL1:
|
18
|
+
signal_plans:
|
19
|
+
1:
|
20
|
+
dynamic_bands:
|
21
|
+
1: 0
|
22
|
+
2: 5
|
23
|
+
states:
|
24
|
+
A1: '11NBBB'
|
25
|
+
A2: '1NBBBB'
|
26
|
+
B1: 'BBB11N'
|
27
|
+
B2: 'BBB1NB'
|
28
|
+
2:
|
29
|
+
states:
|
30
|
+
A1: '111NBB'
|
31
|
+
A2: '11NBBB'
|
32
|
+
B1: 'BBB11N'
|
33
|
+
B2: 'BBB1NB'
|
22
34
|
intervals:
|
23
35
|
timer: 0.1
|
24
36
|
watchdog: 0.1
|
@@ -30,17 +42,11 @@ security_codes:
|
|
30
42
|
1: '1111'
|
31
43
|
2: '2222'
|
32
44
|
log:
|
33
|
-
active: true
|
34
|
-
color: true
|
35
|
-
timestamp: true
|
36
|
-
component_id: true
|
37
45
|
ip: false
|
38
46
|
site_id: 9
|
39
|
-
component:
|
47
|
+
component: 2
|
40
48
|
level: false
|
41
49
|
debug: true
|
42
|
-
text: true
|
43
|
-
direction: false
|
44
50
|
json: true
|
45
51
|
acknowledgements: false
|
46
52
|
watchdogs: false
|
data/lib/rsmp/archive.rb
CHANGED
@@ -21,7 +21,7 @@ module RSMP
|
|
21
21
|
def self.prepare_item item
|
22
22
|
raise ArgumentError unless item.is_a? Hash
|
23
23
|
|
24
|
-
cleaned = item.select { |k,v| [:author,:level,:ip,:port,:site_id,:component,:
|
24
|
+
cleaned = item.select { |k,v| [:author,:level,:ip,:port,:site_id,:component,:text,:message,:exception].include? k }
|
25
25
|
cleaned[:timestamp] = Clock.now
|
26
26
|
if item[:message]
|
27
27
|
cleaned[:direction] = item[:message].direction
|
data/lib/rsmp/cli.rb
CHANGED
data/lib/rsmp/component.rb
CHANGED
@@ -65,7 +65,8 @@ module RSMP
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def log str, options
|
68
|
-
|
68
|
+
default = { component: c_id}
|
69
|
+
@node.log str, default.merge(options)
|
69
70
|
end
|
70
71
|
|
71
72
|
def handle_command command_code, arg
|
@@ -78,16 +79,17 @@ module RSMP
|
|
78
79
|
|
79
80
|
def handle_alarm message
|
80
81
|
code = message.attribute('aCId')
|
81
|
-
|
82
|
-
if
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
82
|
+
previous = @alarms[code]
|
83
|
+
if previous
|
84
|
+
unless message.differ?(previous)
|
85
|
+
raise RepeatedAlarmError.new("no changes from previous alarm #{previous.m_id_short}")
|
86
|
+
end
|
87
|
+
if Time.parse(message.attribute('aTs')) < Time.parse(previous.attribute('aTs'))
|
88
|
+
raise RepeatedAlarmError.new("timestamp is earlier than previous alarm #{previous.m_id_short}")
|
87
89
|
end
|
88
|
-
else
|
89
|
-
@alarms[code] = message
|
90
90
|
end
|
91
|
+
ensure
|
92
|
+
@alarms[code] = message
|
91
93
|
end
|
92
94
|
|
93
95
|
# Handle an incoming status respone, by storing the values
|
@@ -118,7 +120,6 @@ module RSMP
|
|
118
120
|
@statuses[sCI][n] ||= {}
|
119
121
|
@statuses[sCI][n][:initial] = true
|
120
122
|
end
|
121
|
-
#pp @subscribes
|
122
123
|
end
|
123
124
|
|
124
125
|
# Our proxy unsubscribed to status updates.
|
data/lib/rsmp/components.rb
CHANGED
@@ -52,7 +52,8 @@ module RSMP
|
|
52
52
|
component = inferred.new node: self, id: component_id
|
53
53
|
@components[ component_id] = component
|
54
54
|
class_name = component.class.name.split('::').last
|
55
|
-
|
55
|
+
class_name << " compoent" unless class_name == 'Component'
|
56
|
+
log "Inferred #{class_name} #{component_id}", level: :debug
|
56
57
|
component
|
57
58
|
else
|
58
59
|
raise UnknownComponent.new("Component #{component_id} not found") unless component
|
data/lib/rsmp/error.rb
CHANGED
data/lib/rsmp/logger.rb
CHANGED
@@ -5,7 +5,7 @@ module RSMP
|
|
5
5
|
|
6
6
|
def initialize settings={}
|
7
7
|
defaults = {
|
8
|
-
'active'=>
|
8
|
+
'active'=>true,
|
9
9
|
'path'=>nil,
|
10
10
|
'stream'=>nil,
|
11
11
|
'color'=>true,
|
@@ -13,6 +13,7 @@ module RSMP
|
|
13
13
|
'statistics'=>false,
|
14
14
|
'hide_ip_and_port' => false,
|
15
15
|
'acknowledgements' => false,
|
16
|
+
'watchdogs' => false,
|
16
17
|
'json'=>false,
|
17
18
|
'tabs'=>'-',
|
18
19
|
|
@@ -27,7 +28,7 @@ module RSMP
|
|
27
28
|
'direction'=>false,
|
28
29
|
'level'=>false,
|
29
30
|
'id'=>true,
|
30
|
-
'
|
31
|
+
'text'=>true,
|
31
32
|
}
|
32
33
|
|
33
34
|
default_lengths = {
|
@@ -38,7 +39,7 @@ module RSMP
|
|
38
39
|
'port'=>5,
|
39
40
|
'site_id'=>19,
|
40
41
|
'component'=>19,
|
41
|
-
'direction'=>
|
42
|
+
'direction'=>3,
|
42
43
|
'level'=>7,
|
43
44
|
'id'=>4,
|
44
45
|
}
|
@@ -189,15 +190,15 @@ module RSMP
|
|
189
190
|
build_part( parts, item, :ip )
|
190
191
|
build_part( parts, item, :port )
|
191
192
|
build_part( parts, item, :site_id )
|
192
|
-
build_part( parts, item, :
|
193
|
-
build_part( parts, item, :direction ) { |part| {in:"
|
193
|
+
build_part( parts, item, :component )
|
194
|
+
build_part( parts, item, :direction ) { |part| {in:"In",out:"Out"}[part] }
|
194
195
|
build_part( parts, item, :level ) { |part| part.capitalize }
|
195
196
|
build_part( parts, item, :id ) { Logger.shorten_message_id(item[:message].m_id,4) if item[:message] }
|
196
|
-
build_part( parts, item, :
|
197
|
+
build_part( parts, item, :text )
|
197
198
|
build_part( parts, item, :json ) { item[:message].json if item[:message] }
|
198
199
|
build_part( parts, item, :exception ) { |e| [e.class,e.backtrace].flatten.join("\n") }
|
199
200
|
|
200
|
-
parts.join(' ').chomp(@settings['tabs']).rstrip
|
201
|
+
parts.join(' ').chomp(@settings['tabs'].to_s).rstrip
|
201
202
|
end
|
202
203
|
end
|
203
204
|
end
|
data/lib/rsmp/logging.rb
CHANGED
@@ -15,7 +15,7 @@ module RSMP
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def log str, options={}
|
18
|
-
default = {
|
18
|
+
default = { text:str, level: :log, author: author, ip: @ip, port: @port }
|
19
19
|
prepared = RSMP::Archive.prepare_item default.merge(options)
|
20
20
|
@archive.add prepared
|
21
21
|
@logger.log prepared
|
data/lib/rsmp/message.rb
CHANGED
@@ -126,7 +126,7 @@ module RSMP
|
|
126
126
|
end
|
127
127
|
|
128
128
|
def initialize attributes = {}
|
129
|
-
@timestamp = Time.now # this timestamp is for internal use, and does not the clock
|
129
|
+
@timestamp = Time.now # this timestamp is for internal use, and does not use the clock
|
130
130
|
# in the node, which can be set by an rsmp supervisor
|
131
131
|
|
132
132
|
@attributes = { "mType"=> "rSMsg" }.merge attributes
|
data/lib/rsmp/proxy.rb
CHANGED
@@ -348,20 +348,23 @@ module RSMP
|
|
348
348
|
# cannot send NotAcknowledged for a malformed message since we can't read it, just ignore it
|
349
349
|
nil
|
350
350
|
rescue SchemaError, RSMP::Schemer::Error => e
|
351
|
-
|
351
|
+
reason = "schema errors: #{e.message}"
|
352
|
+
str = "Received invalid #{message.type}, #{reason}"
|
352
353
|
log str, message: message, level: :warning
|
353
354
|
notify_error e.exception(str), message: message
|
354
|
-
dont_acknowledge message, str
|
355
|
+
dont_acknowledge message, str, reason
|
355
356
|
message
|
356
357
|
rescue InvalidMessage => e
|
357
|
-
|
358
|
+
reason = "#{e.message}"
|
359
|
+
str = "Received invalid #{message.type},"
|
358
360
|
notify_error e.exception("#{str} #{message.json}"), message: message
|
359
|
-
dont_acknowledge message, str
|
361
|
+
dont_acknowledge message, str, reason
|
360
362
|
message
|
361
363
|
rescue FatalError => e
|
364
|
+
reason = e.message
|
362
365
|
str = "Rejected #{message.type},"
|
363
366
|
notify_error e.exception(str), message: message
|
364
|
-
dont_acknowledge message, str,
|
367
|
+
dont_acknowledge message, str, reason
|
365
368
|
stop
|
366
369
|
message
|
367
370
|
ensure
|
@@ -23,15 +23,22 @@ module RSMP
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def start
|
26
|
-
log "Connecting to
|
26
|
+
log "Connecting to supervisor at #{@ip}:#{@port}", level: :info
|
27
27
|
super
|
28
28
|
connect
|
29
29
|
@logger.unmute @ip, @port
|
30
|
-
log "Connected to
|
30
|
+
log "Connected to supervisor at #{@ip}:#{@port}", level: :info
|
31
31
|
start_reader
|
32
32
|
send_version @site_settings['site_id'], @site_settings["rsmp_versions"]
|
33
|
-
rescue
|
34
|
-
log "
|
33
|
+
rescue SystemCallError => e
|
34
|
+
log "Could not connect to supervisor at #{@ip}:#{@port}: Errno #{e.errno} #{e}", level: :error
|
35
|
+
retry_notice
|
36
|
+
rescue StandardError => e
|
37
|
+
log "Error while connecting to supervisor at #{@ip}:#{@port}: #{e}", level: :error
|
38
|
+
retry_notice
|
39
|
+
end
|
40
|
+
|
41
|
+
def retry_notice
|
35
42
|
unless @site.site_settings['intervals']['reconnect'] == :no
|
36
43
|
log "Will try to reconnect again every #{@site.site_settings['intervals']['reconnect']} seconds..", level: :info
|
37
44
|
@logger.mute @ip, @port
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module RSMP
|
2
|
+
module TLC
|
3
|
+
class DetectorLogic < Component
|
4
|
+
attr_reader :forced, :value
|
5
|
+
|
6
|
+
def initialize node:, id:
|
7
|
+
super node: node, id: id, grouped: false
|
8
|
+
@forced = 0
|
9
|
+
@value = 0
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_status code, name=nil
|
13
|
+
case code
|
14
|
+
when 'S0201', 'S0202', 'S0203', 'S0204'
|
15
|
+
return send("handle_#{code.downcase}", code, name)
|
16
|
+
else
|
17
|
+
raise InvalidMessage.new "unknown status code #{code}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def handle_s0201 status_code, status_name=nil
|
22
|
+
case status_name
|
23
|
+
when 'starttime'
|
24
|
+
TrafficControllerSite.make_status @node.clock.to_s
|
25
|
+
when 'vehicles'
|
26
|
+
TrafficControllerSite.make_status 0
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def handle_s0202 status_code, status_name=nil
|
31
|
+
case status_name
|
32
|
+
when 'starttime'
|
33
|
+
TrafficControllerSite.make_status @node.clock.to_s
|
34
|
+
when 'speed'
|
35
|
+
TrafficControllerSite.make_status 0
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def handle_s0203 status_code, status_name=nil
|
40
|
+
case status_name
|
41
|
+
when 'starttime'
|
42
|
+
TrafficControllerSite.make_status @node.clock.to_s
|
43
|
+
when 'occupancy'
|
44
|
+
TrafficControllerSite.make_status 0
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def handle_s0204 status_code, status_name=nil
|
49
|
+
case status_name
|
50
|
+
when 'starttime'
|
51
|
+
TrafficControllerSite.make_status @node.clock.to_s
|
52
|
+
when 'P'
|
53
|
+
TrafficControllerSite.make_status 0
|
54
|
+
when 'PS'
|
55
|
+
TrafficControllerSite.make_status 0
|
56
|
+
when 'L'
|
57
|
+
TrafficControllerSite.make_status 0
|
58
|
+
when 'LS'
|
59
|
+
TrafficControllerSite.make_status 0
|
60
|
+
when 'B'
|
61
|
+
TrafficControllerSite.make_status 0
|
62
|
+
when 'SP'
|
63
|
+
TrafficControllerSite.make_status 0
|
64
|
+
when 'MC'
|
65
|
+
TrafficControllerSite.make_status 0
|
66
|
+
when 'C'
|
67
|
+
TrafficControllerSite.make_status 0
|
68
|
+
when 'F'
|
69
|
+
TrafficControllerSite.make_status 0
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def handle_command command_code, arg
|
74
|
+
case command_code
|
75
|
+
when 'M0008'
|
76
|
+
handle_m0008 arg
|
77
|
+
else
|
78
|
+
raise UnknownCommand.new "Unknown command #{command_code}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def handle_m0008 arg
|
83
|
+
@node.verify_security_code 2, arg['securityCode']
|
84
|
+
status = arg['status']=='True'
|
85
|
+
mode = arg['mode']=='True'
|
86
|
+
force_detector_logic status, mode
|
87
|
+
arg
|
88
|
+
end
|
89
|
+
|
90
|
+
def force_detector_logic forced, value
|
91
|
+
@forced = forced
|
92
|
+
@value = value
|
93
|
+
if @forced
|
94
|
+
log "Forcing to #{value}", level: :info
|
95
|
+
else
|
96
|
+
log "Releasing", level: :info
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module RSMP
|
2
|
+
module TLC
|
3
|
+
class SignalGroup < Component
|
4
|
+
attr_reader :plan, :state
|
5
|
+
|
6
|
+
# plan is a string, with each character representing a signal phase at a particular second in the cycle
|
7
|
+
def initialize node:, id:
|
8
|
+
super node: node, id: id, grouped: false
|
9
|
+
move 0
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_state pos
|
13
|
+
default = 'a' # phase a means disabled/dark
|
14
|
+
plan = node.main.current_plan
|
15
|
+
return default unless plan
|
16
|
+
return default unless plan.states
|
17
|
+
states = plan.states[c_id]
|
18
|
+
return default unless states
|
19
|
+
state =states[pos]
|
20
|
+
return default unless state =~ /[a-hA-G0-9N-P]/ # valid signal group states
|
21
|
+
state
|
22
|
+
end
|
23
|
+
|
24
|
+
def move pos
|
25
|
+
@state = get_state pos
|
26
|
+
end
|
27
|
+
|
28
|
+
def handle_command command_code, arg
|
29
|
+
case command_code
|
30
|
+
when 'M0010', 'M0011'
|
31
|
+
return send("handle_#{command_code.downcase}", arg)
|
32
|
+
else
|
33
|
+
raise UnknownCommand.new "Unknown command #{command_code}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Start of signal group. Orders a signal group to green
|
38
|
+
def handle_m0010 arg
|
39
|
+
@node.verify_security_code 2, arg['securityCode']
|
40
|
+
if TrafficControllerSite.from_rsmp_bool arg['status']
|
41
|
+
log "Start signal group #{c_id}, go to green", level: :info
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Stop of signal group. Orders a signal group to red
|
46
|
+
def handle_m0011 arg
|
47
|
+
@node.verify_security_code 2, arg['securityCode']
|
48
|
+
if TrafficControllerSite.from_rsmp_bool arg['status']
|
49
|
+
log "Stop signal group #{c_id}, go to red", level: :info
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_status code, name=nil
|
54
|
+
case code
|
55
|
+
when 'S0025'
|
56
|
+
return send("handle_#{code.downcase}", code, name)
|
57
|
+
else
|
58
|
+
raise InvalidMessage.new "unknown status code #{code}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def handle_s0025 status_code, status_name=nil
|
63
|
+
now = @node.clock.to_s
|
64
|
+
case status_name
|
65
|
+
when 'minToGEstimate'
|
66
|
+
TrafficControllerSite.make_status now
|
67
|
+
when 'maxToGEstimate'
|
68
|
+
TrafficControllerSite.make_status now
|
69
|
+
when 'likelyToGEstimate'
|
70
|
+
TrafficControllerSite.make_status now
|
71
|
+
when 'ToGConfidence'
|
72
|
+
TrafficControllerSite.make_status 0
|
73
|
+
when 'minToREstimate'
|
74
|
+
TrafficControllerSite.make_status now
|
75
|
+
when 'maxToREstimate'
|
76
|
+
TrafficControllerSite.make_status now
|
77
|
+
when 'likelyToREstimate'
|
78
|
+
TrafficControllerSite.make_status now
|
79
|
+
when 'ToRConfidence'
|
80
|
+
TrafficControllerSite.make_status 0
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module RSMP
|
2
|
+
module TLC
|
3
|
+
# A Traffic Light Controller Signal Plan.
|
4
|
+
# A signal plan is a description of how all signal groups should change
|
5
|
+
# state over time.
|
6
|
+
class SignalPlan
|
7
|
+
attr_reader :nr, :states, :dynamic_bands
|
8
|
+
def initialize nr:, states:, dynamic_bands:
|
9
|
+
@nr = nr
|
10
|
+
@states = states
|
11
|
+
@dynamic_bands = dynamic_bands || {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def dynamic_bands_string
|
15
|
+
str = @dynamic_bands.map { |band,value| "#{nr}-#{band}-#{value}" }.join(',')
|
16
|
+
return nil if str == ''
|
17
|
+
str
|
18
|
+
end
|
19
|
+
|
20
|
+
def set_band band, value
|
21
|
+
@dynamic_bands[ band.to_i ] = value.to_i
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_band band
|
25
|
+
@dynamic_bands[ band.to_i ]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|