rsmp 0.6.2 → 0.7.0
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 +2 -2
- data/README.md +2 -2
- data/config/supervisor.yaml +1 -9
- data/config/tlc.yaml +17 -13
- 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 +26 -10
- 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 +7 -3
- 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: c9a318474a865aca223c43e6bfe2bb2bf55a1e0a4584a7d28c80fc87295bc1f9
|
4
|
+
data.tar.gz: 64e892b4fe5b4dbd4aa910542634d82e9120f6c698eb57920c718657be200c1d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c9cada8fb00a82666968a656e6896f35942ef480d0ee0e5a442be38b25cc20b89460c6317e13b3087a2c2e7b70432bd8dd69d33a010cca13685f100fc4c0aed
|
7
|
+
data.tar.gz: 305d823c21f5de5f32fc143fdc5d7ad0e2c7947940fd4b261e6dd94b222c58657173cacf14c7a4aae59b263eebb1d5d7060d1b0645a99cd414a76cc8d65d55e0
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rsmp (0.
|
4
|
+
rsmp (0.7.0)
|
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,18 +8,10 @@ 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
|
23
17
|
json: true
|
24
|
-
acknowledgements: false
|
25
|
-
watchdogs: false
|
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,9 @@ 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
|
-
acknowledgements: false
|
46
|
-
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,8 @@ module RSMP
|
|
13
13
|
'statistics'=>false,
|
14
14
|
'hide_ip_and_port' => false,
|
15
15
|
'acknowledgements' => false,
|
16
|
+
'watchdogs' => false,
|
17
|
+
'alarms' => true,
|
16
18
|
'json'=>false,
|
17
19
|
'tabs'=>'-',
|
18
20
|
|
@@ -27,7 +29,7 @@ module RSMP
|
|
27
29
|
'direction'=>false,
|
28
30
|
'level'=>false,
|
29
31
|
'id'=>true,
|
30
|
-
'
|
32
|
+
'text'=>true,
|
31
33
|
}
|
32
34
|
|
33
35
|
default_lengths = {
|
@@ -38,11 +40,20 @@ module RSMP
|
|
38
40
|
'port'=>5,
|
39
41
|
'site_id'=>19,
|
40
42
|
'component'=>19,
|
41
|
-
'direction'=>
|
43
|
+
'direction'=>3,
|
42
44
|
'level'=>7,
|
43
45
|
'id'=>4,
|
44
46
|
}
|
45
47
|
|
48
|
+
@ignorable = {
|
49
|
+
'versions' => ['Version'],
|
50
|
+
'statuses' => ['StatusRequest','StatusSubscribe','StatusUnsubscribe','StatusResponse','StatusUpdate'],
|
51
|
+
'commands' => ['CommandRequest','CommandResponse'],
|
52
|
+
'watchdogs' => 'Watchdog',
|
53
|
+
'alarms' => ['Alarm','AlarmRequest'],
|
54
|
+
'aggregated_status' => ['AggregatedStatus','AggregatedStatusRequest']
|
55
|
+
}
|
56
|
+
|
46
57
|
if settings
|
47
58
|
@settings = defaults.merge settings
|
48
59
|
else
|
@@ -95,10 +106,15 @@ module RSMP
|
|
95
106
|
if item[:message]
|
96
107
|
type = item[:message].type
|
97
108
|
ack = type == "MessageAck" || type == "MessageNotAck"
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
109
|
+
@ignorable.each_pair do |key,types|
|
110
|
+
next unless types
|
111
|
+
ignore = [types].flatten
|
112
|
+
if @settings[key] == false
|
113
|
+
#p [type,ignore_type, [ignore_type].flatten.include?(type)]
|
114
|
+
return false if ignore.include?(type)
|
115
|
+
if ack
|
116
|
+
return false if item[:message].original && ignore.include?(item[:message].original.type)
|
117
|
+
end
|
102
118
|
end
|
103
119
|
end
|
104
120
|
return false if ack && @settings["acknowledgements"] == false &&
|
@@ -190,14 +206,14 @@ module RSMP
|
|
190
206
|
build_part( parts, item, :port )
|
191
207
|
build_part( parts, item, :site_id )
|
192
208
|
build_part( parts, item, :component )
|
193
|
-
build_part( parts, item, :direction ) { |part| {in:"
|
209
|
+
build_part( parts, item, :direction ) { |part| {in:"In",out:"Out"}[part] }
|
194
210
|
build_part( parts, item, :level ) { |part| part.capitalize }
|
195
211
|
build_part( parts, item, :id ) { Logger.shorten_message_id(item[:message].m_id,4) if item[:message] }
|
196
|
-
build_part( parts, item, :
|
212
|
+
build_part( parts, item, :text )
|
197
213
|
build_part( parts, item, :json ) { item[:message].json if item[:message] }
|
198
214
|
build_part( parts, item, :exception ) { |e| [e.class,e.backtrace].flatten.join("\n") }
|
199
215
|
|
200
|
-
parts.join(' ').chomp(@settings['tabs']).rstrip
|
216
|
+
parts.join(' ').chomp(@settings['tabs'].to_s).rstrip
|
201
217
|
end
|
202
218
|
end
|
203
219
|
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
|