rsmp 0.8.3 → 0.8.4
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 +3 -3
- data/config/tlc.yaml +8 -6
- data/lib/rsmp/site.rb +1 -1
- data/lib/rsmp/tlc/signal_group.rb +15 -7
- data/lib/rsmp/tlc/traffic_controller.rb +92 -28
- data/lib/rsmp/tlc/traffic_controller_site.rb +10 -1
- data/lib/rsmp/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d6e0bddb9443fd704586251f92785f5ec4d703431d587047f8a2e835fcb48b9f
|
4
|
+
data.tar.gz: 81b56b1687ad356177b6277d58f6db4ed4d3f8fa8e59aa0fc626a90fcc03bb86
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8ba189a5602f9ec1bc7f09e821231c2f5135dd163da82ffae48b9a9f62ac79ec8d4beb114e6112d41902fc1ca06ccff2a208863d00f05e51c9a83cafb68e33c
|
7
|
+
data.tar.gz: 4fd8b04217edb49b3c1b929ac3d585c60194207cdb8380be7693ee00b448a28fce90cc6e55621b6cee601d773f80c6780c0d7a3a31ee8606f62f23cfce0718f8
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rsmp (0.8.
|
4
|
+
rsmp (0.8.4)
|
5
5
|
async (~> 1.29.1)
|
6
6
|
async-io (~> 1.32.1)
|
7
7
|
colorize (~> 0.8.1)
|
@@ -70,8 +70,8 @@ GEM
|
|
70
70
|
cucumber-cucumber-expressions (~> 12.1, >= 12.1.1)
|
71
71
|
cucumber-messages (~> 15.0, >= 15.0.0)
|
72
72
|
diff-lcs (1.4.4)
|
73
|
-
ecma-re-validator (0.
|
74
|
-
regexp_parser (~> 2.
|
73
|
+
ecma-re-validator (0.4.0)
|
74
|
+
regexp_parser (~> 2.2)
|
75
75
|
ffi (1.15.3)
|
76
76
|
fiber-local (1.0.0)
|
77
77
|
hana (1.3.7)
|
data/config/tlc.yaml
CHANGED
@@ -20,17 +20,18 @@ signal_plans:
|
|
20
20
|
dynamic_bands:
|
21
21
|
1: 0
|
22
22
|
2: 5
|
23
|
-
states:
|
24
|
-
A1: '123efg'
|
25
|
-
A2: '123efg'
|
26
|
-
B1: '123efg'
|
27
|
-
B2: '123efg'
|
28
|
-
2:
|
29
23
|
states:
|
30
24
|
A1: '111NBB'
|
31
25
|
A2: '11NBBB'
|
32
26
|
B1: 'BBB11N'
|
33
27
|
B2: 'BBB1NB'
|
28
|
+
2:
|
29
|
+
states:
|
30
|
+
A1: 'NNNNBB'
|
31
|
+
A2: 'NNNNBN'
|
32
|
+
B1: 'BBNNNN'
|
33
|
+
B2: 'BNNNNN'
|
34
|
+
startup_sequence: 'efg'
|
34
35
|
intervals:
|
35
36
|
timer: 0.1
|
36
37
|
watchdog: 0.1
|
@@ -48,3 +49,4 @@ log:
|
|
48
49
|
level: false
|
49
50
|
debug: true
|
50
51
|
json: true
|
52
|
+
live_output: tmp/tlc.state
|
data/lib/rsmp/site.rb
CHANGED
@@ -9,9 +9,9 @@ module RSMP
|
|
9
9
|
attr_reader :rsmp_versions, :site_settings, :logger, :proxies
|
10
10
|
|
11
11
|
def initialize options={}
|
12
|
+
super options
|
12
13
|
initialize_components
|
13
14
|
handle_site_settings options
|
14
|
-
super options
|
15
15
|
@proxies = []
|
16
16
|
@sleep_condition = Async::Notification.new
|
17
17
|
@proxies_condition = Async::Notification.new
|
@@ -6,25 +6,33 @@ module RSMP
|
|
6
6
|
# plan is a string, with each character representing a signal phase at a particular second in the cycle
|
7
7
|
def initialize node:, id:
|
8
8
|
super node: node, id: id, grouped: false
|
9
|
-
move 0
|
10
9
|
end
|
11
10
|
|
12
|
-
def
|
11
|
+
def timer
|
12
|
+
@state = get_state
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_state
|
16
|
+
return 'a' if node.main.dark_mode
|
17
|
+
return 'c' if node.main.yellow_flash
|
18
|
+
|
19
|
+
cycle_counter = node.main.cycle_counter
|
20
|
+
|
21
|
+
if node.main.startup_sequence_active
|
22
|
+
@state = node.main.startup_state || 'a'
|
23
|
+
end
|
24
|
+
|
13
25
|
default = 'a' # phase a means disabled/dark
|
14
26
|
plan = node.main.current_plan
|
15
27
|
return default unless plan
|
16
28
|
return default unless plan.states
|
17
29
|
states = plan.states[c_id]
|
18
30
|
return default unless states
|
19
|
-
state = states[
|
31
|
+
state = states[cycle_counter]
|
20
32
|
return default unless state =~ /[a-hA-G0-9N-P]/ # valid signal group states
|
21
33
|
state
|
22
34
|
end
|
23
35
|
|
24
|
-
def move pos
|
25
|
-
@state = get_state pos
|
26
|
-
end
|
27
|
-
|
28
36
|
def handle_command command_code, arg
|
29
37
|
case command_code
|
30
38
|
when 'M0010', 'M0011'
|
@@ -5,9 +5,12 @@ module RSMP
|
|
5
5
|
# and keeps track of signal plans, detector logics, inputs, etc. which do
|
6
6
|
# not have dedicated components.
|
7
7
|
class TrafficController < Component
|
8
|
-
attr_reader :pos, :cycle_time, :plan
|
8
|
+
attr_reader :pos, :cycle_time, :plan, :cycle_counter,
|
9
|
+
:yellow_flash, :dark_mode,
|
10
|
+
:startup_sequence_active, :startup_sequence, :startup_sequence_pos
|
9
11
|
|
10
|
-
def initialize node:, id:, cycle_time: 10, signal_plans
|
12
|
+
def initialize node:, id:, cycle_time: 10, signal_plans:,
|
13
|
+
startup_sequence:, live_output:nil
|
11
14
|
super node: node, id: id, grouped: true
|
12
15
|
@signal_groups = []
|
13
16
|
@detector_logics = []
|
@@ -15,13 +18,15 @@ module RSMP
|
|
15
18
|
@cycle_time = cycle_time
|
16
19
|
@num_traffic_situations = 1
|
17
20
|
@num_inputs = 8
|
21
|
+
@startup_sequence = startup_sequence
|
22
|
+
@live_output = live_output
|
18
23
|
reset
|
19
24
|
end
|
20
25
|
|
21
26
|
def reset
|
22
|
-
@
|
23
|
-
@plan =
|
24
|
-
@dark_mode =
|
27
|
+
@cycle_counter = 0
|
28
|
+
@plan = 1
|
29
|
+
@dark_mode = true
|
25
30
|
@yellow_flash = false
|
26
31
|
@booting = false
|
27
32
|
@control_mode = 'control'
|
@@ -40,6 +45,12 @@ module RSMP
|
|
40
45
|
@inputs = '0'*@num_inputs
|
41
46
|
@input_activations = '0'*@num_inputs
|
42
47
|
@input_results = '0'*@num_inputs
|
48
|
+
|
49
|
+
@day_time_table = {}
|
50
|
+
@startup_sequence_active = false
|
51
|
+
@startup_sequence_initiated_at = nil
|
52
|
+
@startup_sequence_pos = 0
|
53
|
+
@time_int = nil
|
43
54
|
end
|
44
55
|
|
45
56
|
def clock
|
@@ -64,46 +75,83 @@ module RSMP
|
|
64
75
|
end
|
65
76
|
|
66
77
|
def timer now
|
67
|
-
# TODO
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
78
|
+
# TODO use monotone timer, to avoid jumps in case the user sets the system time
|
79
|
+
@signal_groups.each { |group| group.timer }
|
80
|
+
time = Time.now.to_i
|
81
|
+
return if time == @time_int
|
82
|
+
@time_int = time
|
83
|
+
move_cycle_counter
|
84
|
+
move_startup_sequence if @startup_sequence_active
|
85
|
+
output_states
|
86
|
+
end
|
87
|
+
|
88
|
+
def move_cycle_counter
|
89
|
+
counter = Time.now.to_i % @cycle_time
|
90
|
+
@cycle_counter = counter
|
91
|
+
end
|
92
|
+
|
93
|
+
def startup_state
|
94
|
+
return unless @startup_sequence_active
|
95
|
+
return unless @startup_sequence_pos
|
96
|
+
@startup_sequence[ @startup_sequence_pos ]
|
75
97
|
end
|
76
98
|
|
77
|
-
def
|
78
|
-
|
79
|
-
|
99
|
+
def initiate_startup_sequence
|
100
|
+
log "Initiating startup sequence", level: :info
|
101
|
+
@startup_sequence_active = true
|
102
|
+
@startup_sequence_initiated_at = nil
|
103
|
+
@startup_sequence_pos = nil
|
104
|
+
end
|
105
|
+
|
106
|
+
def end_startup_sequence
|
107
|
+
@startup_sequence_active = false
|
108
|
+
@startup_sequence_initiated_at = nil
|
109
|
+
@startup_sequence_pos = nil
|
110
|
+
|
111
|
+
@yellow_flash = false
|
112
|
+
@dark_mode = false
|
113
|
+
end
|
114
|
+
|
115
|
+
def move_startup_sequence
|
116
|
+
was = @startup_sequence_pos
|
117
|
+
if @startup_sequence_initiated_at == nil
|
118
|
+
@startup_sequence_initiated_at = Time.now.to_i + 1
|
119
|
+
@startup_sequence_pos = 0
|
120
|
+
else
|
121
|
+
@startup_sequence_pos = Time.now.to_i - @startup_sequence_initiated_at
|
122
|
+
end
|
123
|
+
if @startup_sequence_pos >= @startup_sequence.size
|
124
|
+
end_startup_sequence
|
80
125
|
end
|
81
|
-
#output_states
|
82
126
|
end
|
83
127
|
|
84
128
|
def output_states
|
129
|
+
return unless @live_output
|
85
130
|
str = @signal_groups.map do |group|
|
86
131
|
s = "#{group.c_id}:#{group.state}"
|
87
132
|
if group.state =~ /^[1-9]$/
|
88
133
|
s.colorize(:green)
|
89
134
|
elsif group.state =~ /^[NOP]$/
|
90
135
|
s.colorize(:yellow)
|
91
|
-
elsif group.state =~ /^[
|
92
|
-
s.colorize(
|
136
|
+
elsif group.state =~ /^[ae]$/
|
137
|
+
s.colorize(:black)
|
138
|
+
elsif group.state =~ /^[f]$/
|
139
|
+
s.colorize(:yellow)
|
140
|
+
elsif group.state =~ /^[g]$/
|
141
|
+
s.colorize(:red)
|
93
142
|
else
|
94
143
|
s.colorize(:red)
|
95
144
|
end
|
96
145
|
end.join ' '
|
97
146
|
plan = "P#{@plan}"
|
98
|
-
|
147
|
+
|
148
|
+
File.open @live_output, 'w' do |file|
|
149
|
+
file.puts "#{plan.rjust(4)} #{pos.to_s.rjust(4)} #{str}\r"
|
150
|
+
end
|
99
151
|
end
|
100
152
|
|
101
153
|
def format_signal_group_status
|
102
|
-
|
103
|
-
'c' * @signal_groups.size
|
104
|
-
else
|
105
|
-
@signal_groups.map { |group| group.state }.join
|
106
|
-
end
|
154
|
+
@signal_groups.map { |group| group.state }.join
|
107
155
|
end
|
108
156
|
|
109
157
|
def handle_command command_code, arg
|
@@ -214,6 +262,18 @@ module RSMP
|
|
214
262
|
|
215
263
|
def handle_m0017 arg
|
216
264
|
@node.verify_security_code 2, arg['securityCode']
|
265
|
+
arg['status'].split(',').each do |item|
|
266
|
+
elems = item.split('-')
|
267
|
+
nr = elems[0].to_i
|
268
|
+
plan = elems[1].to_i
|
269
|
+
hour = elems[2].to_i
|
270
|
+
min = elems[3].to_i
|
271
|
+
if nr<0 || nr>12
|
272
|
+
raise InvalidMessage.new "time table id must be between 0 and 12, got #{nr}"
|
273
|
+
end
|
274
|
+
#p "nr: #{nr}, plan #{plan} at #{hour}:#{min}"
|
275
|
+
@day_time_table[nr] = {plan: plan, hour: hour, min:min}
|
276
|
+
end
|
217
277
|
end
|
218
278
|
|
219
279
|
def handle_m0018 arg
|
@@ -276,6 +336,7 @@ module RSMP
|
|
276
336
|
log "Switching to mode #{mode}", level: :info
|
277
337
|
case mode
|
278
338
|
when 'NormalControl'
|
339
|
+
initiate_startup_sequence if @yellow_flash || @dark_mode
|
279
340
|
@yellow_flash = false
|
280
341
|
@dark_mode = false
|
281
342
|
when 'YellowFlash'
|
@@ -308,9 +369,9 @@ module RSMP
|
|
308
369
|
when 'signalgroupstatus'
|
309
370
|
TrafficControllerSite.make_status format_signal_group_status
|
310
371
|
when 'cyclecounter'
|
311
|
-
TrafficControllerSite.make_status @
|
372
|
+
TrafficControllerSite.make_status @cycle_counter.to_s
|
312
373
|
when 'basecyclecounter'
|
313
|
-
TrafficControllerSite.make_status @
|
374
|
+
TrafficControllerSite.make_status @cycle_counter.to_s
|
314
375
|
when 'stage'
|
315
376
|
TrafficControllerSite.make_status 0.to_s
|
316
377
|
end
|
@@ -511,7 +572,10 @@ module RSMP
|
|
511
572
|
def handle_s0027 status_code, status_name=nil
|
512
573
|
case status_name
|
513
574
|
when 'status'
|
514
|
-
|
575
|
+
status = @day_time_table.map do |i,item|
|
576
|
+
"#{i}-#{item[:plan]}-#{item[:hour]}-#{item[:min]}"
|
577
|
+
end.join(',')
|
578
|
+
TrafficControllerSite.make_status status
|
515
579
|
end
|
516
580
|
end
|
517
581
|
|
@@ -5,11 +5,16 @@ module RSMP
|
|
5
5
|
attr_accessor :main, :signal_plans
|
6
6
|
|
7
7
|
def initialize options={}
|
8
|
+
# setup options before calling super initializer,
|
9
|
+
# since build of components depend on options
|
8
10
|
@sxl = 'traffic_light_controller'
|
9
11
|
@security_codes = options[:site_settings]['security_codes']
|
10
12
|
@interval = options[:site_settings].dig('intervals','timer') || 1
|
13
|
+
@startup_sequence = options[:site_settings]['startup_sequence'] || 'efg'
|
11
14
|
build_plans options[:site_settings].dig('signal_plans')
|
15
|
+
|
12
16
|
super options
|
17
|
+
|
13
18
|
unless @main
|
14
19
|
raise ConfigurationError.new "TLC must have a main component"
|
15
20
|
end
|
@@ -37,7 +42,9 @@ module RSMP
|
|
37
42
|
when 'main'
|
38
43
|
@main = TrafficController.new node: self, id: id,
|
39
44
|
cycle_time: settings['cycle_time'],
|
40
|
-
|
45
|
+
startup_sequence: @startup_sequence,
|
46
|
+
signal_plans: @signal_plans,
|
47
|
+
live_output: @site_settings['live_output']
|
41
48
|
when 'signal_group'
|
42
49
|
group = SignalGroup.new node: self, id: id
|
43
50
|
@main.add_signal_group group
|
@@ -52,6 +59,7 @@ module RSMP
|
|
52
59
|
def start_action
|
53
60
|
super
|
54
61
|
start_timer
|
62
|
+
@main.initiate_startup_sequence
|
55
63
|
end
|
56
64
|
|
57
65
|
def start_timer
|
@@ -134,6 +142,7 @@ module RSMP
|
|
134
142
|
when :restart
|
135
143
|
log "Restarting TLC", level: :info
|
136
144
|
restart
|
145
|
+
initiate_startup_sequence
|
137
146
|
end
|
138
147
|
end
|
139
148
|
end
|
data/lib/rsmp/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rsmp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Emil Tin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-01-
|
11
|
+
date: 2022-01-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async
|