rsmp 0.1.13 → 0.1.17

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d2c272fba5c28e4b5746aa03efac286b646d635cb23ae8c68d3c6cb08ba657ae
4
- data.tar.gz: 1051548b65417edbbf31550f4a6a02ae4df7c98aba190682e5c4a5faed3af116
3
+ metadata.gz: 1b583271d38fc35e2badabf94b0a8a764f07a8e36025c2902922d926adbf320b
4
+ data.tar.gz: 9e37dd8939d68a19e1cf16580c558c813e8a5d6214a733cc8dce08fe4957be59
5
5
  SHA512:
6
- metadata.gz: 33b1fb0ad681f71b58571e31a3ef59415ad45ee7ec4a5b947eb494f0474e9a46b85e25e25f977d88da28e4d91011f92b35dc2c1b49c6630d3c7eb5b14ec170a3
7
- data.tar.gz: b0614210f4db03d2aba012f07f7df76aefaae0b96db5779558f46c5ca5433c1b0df1ae3f41e828936f45593fdd7e69723df84895510ba798e64964213c0c4cee
6
+ metadata.gz: 1af3ecb44fc6c9e9fa0735b524c1561eafd91ef05775c0be325c8093635354e535d9d8f024d05cbc256859319a13795dfff34233165b8b57c53ac82fb76dbbd5
7
+ data.tar.gz: aeaa068f63614bcd8e3af873400e5af54810c51e7a1941d62834c1bd2d94a3ff4ae62e59d89ad3242749fff54126aa3ccabf3bf3ac672f29c9cac9611ebddd47
@@ -1,35 +1,34 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rsmp (0.1.13)
4
+ rsmp (0.1.17)
5
5
  async (~> 1.23.0)
6
- async-io (~> 1.27.1)
6
+ async-io (~> 1.27.4)
7
7
  colorize (~> 0.8.1)
8
- json_schemer (~> 0.2.8)
9
- thor (~> 0.20.3)
8
+ json_schemer (~> 0.2.11)
9
+ thor (~> 1.0.1)
10
10
 
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
- aruba (0.14.11)
15
- childprocess (>= 0.6.3, < 3.0.0)
16
- contracts (~> 0.9)
17
- cucumber (>= 1.3.19)
14
+ aruba (1.0.0)
15
+ childprocess (~> 3.0)
16
+ contracts (~> 0.16.0)
17
+ cucumber (>= 2.4, < 4.0)
18
18
  ffi (~> 1.9)
19
- rspec-expectations (>= 2.99)
20
- thor (~> 0.19)
19
+ rspec-expectations (~> 3.4)
20
+ thor (~> 1.0)
21
21
  async (1.23.0)
22
22
  console (~> 1.0)
23
23
  nio4r (~> 2.3)
24
24
  timers (~> 4.1)
25
- async-io (1.27.1)
25
+ async-io (1.27.5)
26
26
  async (~> 1.14)
27
- backports (3.15.0)
28
- builder (3.2.3)
29
- childprocess (2.0.0)
30
- rake (< 13.0)
27
+ backports (3.17.0)
28
+ builder (3.2.4)
29
+ childprocess (3.0.0)
31
30
  colorize (0.8.1)
32
- console (1.7.0)
31
+ console (1.8.2)
33
32
  contracts (0.16.0)
34
33
  cucumber (3.1.2)
35
34
  builder (>= 2.1.2)
@@ -50,35 +49,33 @@ GEM
50
49
  diff-lcs (1.3)
51
50
  ecma-re-validator (0.2.0)
52
51
  regexp_parser (~> 1.2)
53
- ffi (1.11.1)
52
+ ffi (1.12.2)
54
53
  gherkin (5.1.0)
55
54
  hana (1.3.5)
56
- json_schemer (0.2.8)
55
+ json_schemer (0.2.11)
57
56
  ecma-re-validator (~> 0.2)
58
57
  hana (~> 1.3)
59
58
  regexp_parser (~> 1.5)
60
59
  uri_template (~> 0.7)
61
- multi_json (1.13.1)
60
+ multi_json (1.14.1)
62
61
  multi_test (0.1.2)
63
62
  nio4r (2.5.2)
64
- rake (10.5.0)
65
- regexp_parser (1.6.0)
66
- rspec (3.8.0)
67
- rspec-core (~> 3.8.0)
68
- rspec-expectations (~> 3.8.0)
69
- rspec-mocks (~> 3.8.0)
70
- rspec-core (3.8.2)
71
- rspec-support (~> 3.8.0)
72
- rspec-expectations (3.8.4)
63
+ rake (13.0.1)
64
+ regexp_parser (1.7.0)
65
+ rspec (3.9.0)
66
+ rspec-core (~> 3.9.0)
67
+ rspec-expectations (~> 3.9.0)
68
+ rspec-mocks (~> 3.9.0)
69
+ rspec-core (3.9.1)
70
+ rspec-support (~> 3.9.1)
71
+ rspec-expectations (3.9.1)
73
72
  diff-lcs (>= 1.2.0, < 2.0)
74
- rspec-support (~> 3.8.0)
75
- rspec-mocks (3.8.1)
73
+ rspec-support (~> 3.9.0)
74
+ rspec-mocks (3.9.1)
76
75
  diff-lcs (>= 1.2.0, < 2.0)
77
- rspec-support (~> 3.8.0)
78
- rspec-support (3.8.2)
79
- rspec-with_params (0.2.0)
80
- rspec (~> 3.0)
81
- thor (0.20.3)
76
+ rspec-support (~> 3.9.0)
77
+ rspec-support (3.9.2)
78
+ thor (1.0.1)
82
79
  timecop (0.9.1)
83
80
  timers (4.3.0)
84
81
  uri_template (0.7.0)
@@ -87,15 +84,14 @@ PLATFORMS
87
84
  ruby
88
85
 
89
86
  DEPENDENCIES
90
- aruba (~> 0.14.11)
91
- bundler (~> 2.0)
87
+ aruba (~> 1.0.0)
88
+ bundler (~> 2.1.4)
92
89
  cucumber (~> 3.1.2)
93
- rake (~> 10.0)
90
+ rake (~> 13.0.1)
94
91
  rsmp!
95
- rspec (~> 3.0)
96
- rspec-expectations (~> 3.8.3)
97
- rspec-with_params (~> 0.2.0)
92
+ rspec (~> 3.9.0)
93
+ rspec-expectations (~> 3.9.1)
98
94
  timecop (~> 0.9.1)
99
95
 
100
96
  BUNDLED WITH
101
- 2.1.0.pre.2
97
+ 2.1.4
data/README.md CHANGED
@@ -163,6 +163,12 @@ The ```site``` command will start an RSMP site, which will try to connect to one
163
163
  2019-11-11 12:22:00 UTC RN+SU0001 C1 <-- 8280 Sent AggregatedStatus
164
164
  ```
165
165
 
166
+
167
+ Use the the --type switch to select a specific type of site. Messages will be validated against the corresponding SXL JSON schema. Without any type specified, messages will be validated against the core RSMP schema only.
168
+
169
+ Use the ```tlc``` site type to run an emulation of a traffic light controller. This type of site implements enough of functionality to pass all the rsmp_validator tests. You can setup signal group components, in the config file.
170
+
171
+
166
172
  ### CLI help and options.
167
173
  Use ```--help <command>``` to get a list of available options.
168
174
 
@@ -12,8 +12,8 @@ rsmp_versions:
12
12
  - 3.1.4
13
13
 
14
14
  components:
15
- C1:
16
- type: main
15
+ main:
16
+ C1:
17
17
 
18
18
  watchdog_interval: 1
19
19
  watchdog_timeout: 2
@@ -3,25 +3,21 @@ supervisors:
3
3
  - ip: 127.0.0.1
4
4
  port: 12111
5
5
 
6
- sxl: traffic_light_controller
7
-
8
- rsmp_versions:
9
- - 3.1.1
10
- - 3.1.2
11
- - 3.1.3
12
- - 3.1.4
13
-
14
6
  components:
15
- TC:
16
- type: main
17
- cycle_time: 6
18
- A1:
19
- type: signal_group
20
- plan: 'GGyrrr'
21
- B1:
22
- type: signal_group
23
- plan: 'rrrGGy'
24
-
7
+ main:
8
+ TC:
9
+ cycle_time: 6
10
+ signal_group:
11
+ A1:
12
+ plan: '11NBBB'
13
+ A2:
14
+ plan: '1NBBBB'
15
+ B1:
16
+ plan: 'BBB11N'
17
+ B2:
18
+ plan: 'BBB1NB'
19
+ detector_logic:
20
+ DL1:
25
21
  watchdog_interval: 1
26
22
  watchdog_timeout: 2
27
23
  acknowledgement_timeout: 1
@@ -18,7 +18,7 @@ module RSMP
18
18
  if options[:config]
19
19
  if File.exist? options[:config]
20
20
  settings = YAML.load_file options[:config]
21
- log_settings = settings.delete 'log'
21
+ log_settings = settings.delete('log') || {}
22
22
  else
23
23
  puts "Error: Config #{options[:config]} not found"
24
24
  exit
@@ -29,9 +29,9 @@ module RSMP
29
29
  settings['site_id'] = options[:id]
30
30
  end
31
31
 
32
- if options[:supervisors]
33
- options[:supervisors].split(',').each do |supervisor|
34
- settings[:supervisors] ||= []
32
+ if options[:supervisors]
33
+ options[:supervisors].split(',').each do |supervisor|
34
+ settings[:supervisors] ||= []
35
35
  ip, port = supervisor.split ':'
36
36
  ip = '127.0.0.1' if ip.empty?
37
37
  port = '12111' if port.empty?
@@ -1,6 +1,6 @@
1
1
  module RSMP
2
2
  class Component
3
- attr_reader :c_id, :alarms, :statuses, :aggregated_status, :aggregated_status_bools, :grouped
3
+ attr_reader :c_id, :node, :alarms, :statuses, :aggregated_status, :aggregated_status_bools, :grouped
4
4
 
5
5
  AGGREGATED_STATUS_KEYS = [ :local_control,
6
6
  :communication_distruption,
@@ -58,11 +58,17 @@ module RSMP
58
58
  def alarm code:, status:
59
59
  end
60
60
 
61
- def status code:, value:
62
- end
63
-
64
61
  def log str, options
65
62
  @node.log str, options
66
63
  end
64
+
65
+ def handle_command command_code, arg
66
+ raise UnknownCommand.new "Command #{command_code} not implemented by #{self.class}"
67
+ end
68
+
69
+ def get_status status_code, status_name=nil
70
+ raise UnknownStatus.new "Status #{status_code}/#{status_name} not implemented by #{self.class}"
71
+ end
72
+
67
73
  end
68
74
  end
@@ -141,14 +141,5 @@ module RSMP
141
141
  proxy.stop
142
142
  end
143
143
  end
144
-
145
- def handle_command command_code, arg
146
- raise UnknownCommand.new "Command #{command_code} not implemented"
147
- end
148
-
149
- def get_status status_code, status_name=nil
150
- raise UnknownStatus.new "Status #{status_code}/#{status_name} not implemented"
151
- end
152
-
153
144
  end
154
145
  end
@@ -13,8 +13,10 @@ module RSMP
13
13
 
14
14
  def setup_components settings
15
15
  return unless settings
16
- settings.each_pair do |id,settings|
17
- @components[id] = build_component(id,settings)
16
+ settings.each_pair do |type,components_by_type|
17
+ components_by_type.each_pair do |id,settings|
18
+ @components[id] = build_component(id:id, type:type, settings:settings)
19
+ end
18
20
  end
19
21
  end
20
22
 
@@ -22,8 +24,8 @@ module RSMP
22
24
  @components[component.c_id] = component
23
25
  end
24
26
 
25
- def build_component id, settings={}
26
- Component.new id: id, node: self, grouped: true
27
+ def build_component id:, type:, settings:{}
28
+ Component.new id:id, node: self, grouped: true
27
29
  end
28
30
 
29
31
  def find_component component_id
@@ -81,7 +81,7 @@ module RSMP
81
81
  component = @components[c_id]
82
82
  if component == nil
83
83
  if @site_settings == nil || @site_settings['components'] == nil
84
- component = build_component c_id
84
+ component = build_component(id:c_id, type:nil)
85
85
  @components[c_id] = component
86
86
  log "Adding component #{c_id} to site #{@site_id}", level: :info
87
87
  else
@@ -196,7 +196,11 @@ module RSMP
196
196
  next if options[:sCI] && options[:sCI] != status['sCI']
197
197
  next if options[:n] && options[:n] != status['n']
198
198
  next if options[:q] && options[:q] != status['q']
199
- next if options[:s] && options[:s] != status['s']
199
+ if options[:s].is_a? Regexp
200
+ next if options[:s] && status['s'] !~ options[:s]
201
+ else
202
+ next if options[:s] && options[:s] != status['s']
203
+ end
200
204
  matching_status = status
201
205
  break
202
206
  end
@@ -207,6 +211,24 @@ module RSMP
207
211
  end
208
212
  end
209
213
 
214
+ def wait_for_alarm options={}
215
+ raise ArgumentError unless options[:component]
216
+ matching_alarm = nil
217
+ item = @archive.capture(@task,options.merge(type: "Alarm", with_message: true, num: 1)) do |item|
218
+ # TODO check components
219
+ matching_alarm = nil
220
+ alarm = item[:message]
221
+ next if options[:aCId] && options[:aCId] != alarm.attribute("aCId")
222
+ next if options[:aSp] && options[:aSp] != alarm.attribute("aSp")
223
+ next if options[:aS] && options[:aS] != alarm.attribute("aS")
224
+ matching_alarm = alarm
225
+ break
226
+ end
227
+ if item
228
+ { message: item[:message], status: matching_alarm }
229
+ end
230
+ end
231
+
210
232
  def send_command component, args
211
233
  raise NotReady unless @state == :ready
212
234
  message = RSMP::CommandRequest.new({
@@ -266,4 +288,4 @@ module RSMP
266
288
 
267
289
 
268
290
  end
269
- end
291
+ end
@@ -155,10 +155,12 @@ module RSMP
155
155
  end
156
156
 
157
157
  def process_command_request message
158
- log "Received #{message.type}", message: message, level: :log
158
+ log "Received #{message.type}", message: message, level: :log
159
+ component_id = message.attributes["cId"]
160
+ component = @site.find_component component_id
159
161
  commands = simplify_command_requests message.attributes["arg"]
160
162
  commands.each_pair do |command_code,arg|
161
- @site.handle_command(command_code,arg).merge('cCI'=>command_code)
163
+ component.handle_command command_code,arg
162
164
  end
163
165
 
164
166
  rvs = message.attributes["arg"].map do |item|
@@ -167,7 +169,7 @@ module RSMP
167
169
  item
168
170
  end
169
171
  response = CommandResponse.new({
170
- "cId"=>message.attributes["cId"],
172
+ "cId"=>component_id,
171
173
  "cTS"=>RSMP.now_string,
172
174
  "rvs"=>rvs
173
175
  })
@@ -180,8 +182,8 @@ module RSMP
180
182
  component = @site.find_component component_id
181
183
  log "Received #{message.type}", message: message, level: :log
182
184
  sS = message.attributes["sS"].map do |arg|
183
- value, quality = @site.get_status arg['sCI'], arg['n']
184
- { "s" => value, "q" => quality }.merge arg
185
+ value, quality = component.get_status arg['sCI'], arg['n']
186
+ { "s" => value.to_s, "q" => quality.to_s }.merge arg
185
187
  end
186
188
  response = StatusResponse.new({
187
189
  "cId"=>component_id,
@@ -283,11 +285,12 @@ module RSMP
283
285
 
284
286
  def send_status_updates update_list
285
287
  now = RSMP.now_string
286
- update_list.each_pair do |component,by_code|
288
+ update_list.each_pair do |component_id,by_code|
289
+ component = @site.find_component component_id
287
290
  sS = []
288
291
  by_code.each_pair do |code,names|
289
292
  names.map do |status_name|
290
- value,quality = @site.get_status code, status_name
293
+ value,quality = component.get_status code, status_name
291
294
  sS << { "sCI" => code,
292
295
  "n" => status_name,
293
296
  "s" => value.to_s,
@@ -295,7 +298,7 @@ module RSMP
295
298
  end
296
299
  end
297
300
  update = StatusUpdate.new({
298
- "cId"=>component,
301
+ "cId"=>component_id,
299
302
  "sTs"=>now,
300
303
  "sS"=>sS
301
304
  })
@@ -6,20 +6,42 @@ module RSMP
6
6
  attr_reader :pos, :cycle_time
7
7
  def initialize node:, id:, cycle_time:
8
8
  super node: node, id: id, grouped: true
9
+ @signal_groups = []
10
+ @detector_logics = []
11
+ @plans = []
9
12
  @pos = 0
10
13
  @cycle_time = cycle_time
11
- @signal_groups = []
12
14
  @plan = 0
13
- @dark_mode = 'False'
14
- @yellow_flash = 'False'
15
- @booting = 'False'
15
+ @dark_mode = false
16
+ @yellow_flash = false
17
+ @booting = false
18
+ @control_mode = 'control'
16
19
  @police_key = 0
20
+ @intersection = 0
21
+ @is_starting = false
22
+ @emergency_route = false
23
+ @emergency_route_number = 0
24
+ @traffic_situation = 0
25
+ @num_traffic_situations = 1
26
+ @manual_control = false
27
+ @fixed_time_control = false
28
+ @isolated_control = false
29
+ @yellow_flash = false
30
+ @all_red = false
31
+
32
+ @num_inputs = 8
33
+ @inputs = '0'*@num_inputs
34
+ @input_activations = '0'*@num_inputs
35
+ @input_results = '0'*@num_inputs
17
36
  end
18
37
 
19
38
  def add_signal_group group
20
39
  @signal_groups << group
21
40
  end
22
41
 
42
+ def add_detector_logic logic
43
+ @detector_logics << logic
44
+ end
23
45
  def timer now
24
46
  pos = now.to_i % @cycle_time
25
47
  if pos != @pos
@@ -32,19 +54,27 @@ module RSMP
32
54
  @signal_groups.each do |group|
33
55
  group.move pos
34
56
  end
35
- output_states
36
-
37
57
  if pos == 0
38
58
  aggrated_status_changed
39
59
  end
40
60
  end
41
61
 
42
62
  def output_states
43
- #print "\t#{pos.to_s.ljust(3)} #{format_signal_group_status}\r"
63
+ str = @signal_groups.map do |group|
64
+ s = "#{group.c_id}:#{group.state}"
65
+ if group.state =~ /^[1-9]$/
66
+ s.colorize(:green)
67
+ elsif group.state =~ /^[NOP]$/
68
+ s.colorize(:yellow)
69
+ else
70
+ s.colorize(:red)
71
+ end
72
+ end.join ' '
73
+ print "\t#{pos.to_s.ljust(3)} #{str}\r"
44
74
  end
45
75
 
46
76
  def format_signal_group_status
47
- @signal_groups.map { |group|group.state }.join
77
+ @signal_groups.map { |group| group.state }.join
48
78
  end
49
79
 
50
80
  def handle_command command_code, arg
@@ -53,6 +83,14 @@ module RSMP
53
83
  handle_m0001 arg
54
84
  when 'M0002'
55
85
  handle_m0002 arg
86
+ when 'M0003'
87
+ handle_m0003 arg
88
+ when 'M0004'
89
+ handle_m0004 arg
90
+ when 'M0005'
91
+ handle_m0005 arg
92
+ when 'M0006'
93
+ handle_m0006 arg
56
94
  when 'M0007'
57
95
  handle_m0007 arg
58
96
  else
@@ -61,25 +99,56 @@ module RSMP
61
99
  end
62
100
 
63
101
  def handle_m0001 arg
64
- verify_security_code arg['securityCode']
102
+ @node.verify_security_code arg['securityCode']
65
103
  switch_mode arg['status']
66
- arg
67
104
  end
68
105
 
69
106
  def handle_m0002 arg
70
- verify_security_code arg['securityCode']
71
- if arg['status'] = 'True'
107
+ @node.verify_security_code arg['securityCode']
108
+ if RSMP::Tlc.from_rsmp_bool(arg['status'])
72
109
  switch_plan arg['timeplan']
73
110
  else
74
111
  switch_plan 0 # TODO use clock/calender
75
112
  end
76
- arg
77
113
  end
78
114
 
115
+ def handle_m0003 arg
116
+ @node.verify_security_code arg['securityCode']
117
+ @traffic_situation = arg['traficsituation'].to_i
118
+ end
119
+
120
+ def handle_m0004 arg
121
+ @node.verify_security_code arg['securityCode']
122
+ # restarting the node means we will disconnect and reconnect.
123
+ # note that this will happen immediately, and no
124
+ # command response will therefore be sent
125
+ log "Restarting TLC", level: :info
126
+ @node.restart
127
+ end
128
+
129
+ def handle_m0005 arg
130
+ @node.verify_security_code arg['securityCode']
131
+ @emergency_route = arg['status'] == 'True'
132
+ @emergency_route_number = arg['emergencyroute'].to_i
133
+ end
134
+
135
+ def handle_m0006 arg
136
+ @node.verify_security_code arg['securityCode']
137
+ input = arg['input'].to_i
138
+ return unless input>=0 && input<@num_inputs
139
+ @input_activations[input] = (arg['status']=='True' ? '1' : '0')
140
+ result = @input_activations[input]=='1' || @inputs[input]=='1'
141
+ @input_results[input] = (result ? '1' : '0')
142
+ end
143
+
144
+ def set_input i, value
145
+ return unless i>=0 && i<@num_inputs
146
+ @inputs[i] = (arg['value'] ? '1' : '0')
147
+ end
148
+
79
149
  def handle_m0007 arg
80
- verify_security_code arg['securityCode']
150
+ @node.verify_security_code arg['securityCode']
81
151
  set_fixed_time_control arg['status']
82
- arg
83
152
  end
84
153
 
85
154
  def set_fixed_time_control status
@@ -89,51 +158,355 @@ module RSMP
89
158
  def switch_plan plan
90
159
  log "Switching to plan #{plan}", level: :info
91
160
  @plan = plan.to_i
92
- plan
93
161
  end
94
162
 
95
- def switch_mode mode
163
+ def switch_mode mode
96
164
  log "Switching to mode #{mode}", level: :info
97
165
  case mode
98
166
  when 'NormalControl'
99
- @yellow_flash = 'False'
100
- @dark_mode = 'False'
167
+ @yellow_flash = false
168
+ @dark_mode = false
101
169
  when 'YellowFlash'
102
- @yellow_flash = 'True'
103
- @dark_mode = 'False'
170
+ @yellow_flash = true
171
+ @dark_mode = false
104
172
  when 'Dark'
105
- @yellow_flash = 'False'
106
- @dark_mode = 'True'
173
+ @yellow_flash = false
174
+ @dark_mode = true
107
175
  end
108
176
  mode
109
177
  end
110
178
 
111
- def get_status status_code, status_name=nil
112
- case status_code
113
- when 'S0001'
114
- return format_signal_group_status, "recent"
115
- when 'S0005'
116
- return @booting, "recent"
117
- when 'S0007'
118
- if @dark_mode == 'True'
119
- return 'False', "recent"
120
- else
121
- return 'True', "recent"
122
- end
123
- when 'S0009'
124
- return @fixed_time_control.to_s, "recent"
125
- when 'S0013'
126
- return @police_key.to_s, "recent"
127
- when 'S0014'
128
- return @plan.to_s, "recent"
129
- when 'S0011'
130
- return @yellow_flash, "recent"
179
+ def get_status code, name=nil
180
+ case code
181
+ when 'S0001', 'S0002', 'S0003', 'S0004', 'S0005', 'S0006', 'S0007',
182
+ 'S0008', 'S0009', 'S0010', 'S0011', 'S0012', 'S0013', 'S0014',
183
+ 'S0015', 'S0016', 'S0017', 'S0018', 'S0019', 'S0020', 'S0021',
184
+ 'S0022', 'S0023', 'S0024', 'S0026', 'S0027', 'S0028',
185
+ 'S0029',
186
+ 'S0091', 'S0092', 'S0095', 'S0096',
187
+ 'S0205', 'S0206', 'S0207', 'S0208'
188
+ return send("handle_#{code.downcase}", code, name)
131
189
  else
132
- raise InvalidMessage.new "unknown status code #{status_code}"
190
+ raise InvalidMessage.new "unknown status code #{code}"
133
191
  end
134
192
  end
135
193
 
136
- def verify_security_code code
194
+ def handle_s0001 status_code, status_name=nil
195
+ case status_name
196
+ when 'signalgroupstatus'
197
+ return RSMP::Tlc.make_status format_signal_group_status
198
+ when 'cyclecounter'
199
+ RSMP::Tlc.make_status @pos.to_s
200
+ when 'basecyclecounter'
201
+ RSMP::Tlc.make_status @pos.to_s
202
+ when 'stage'
203
+ RSMP::Tlc.make_status 0.to_s
204
+ end
205
+ end
206
+
207
+ def handle_s0002 status_code, status_name=nil
208
+ case status_name
209
+ when 'detectorlogicstatus'
210
+ RSMP::Tlc.make_status @detector_logics.map { |dl| dl.forced ? '1' : '0' }.join
211
+ end
212
+ end
213
+
214
+ def handle_s0003 status_code, status_name=nil
215
+ case status_name
216
+ when 'inputstatus'
217
+ RSMP::Tlc.make_status @input_results
218
+ when 'extendedinputstatus'
219
+ RSMP::Tlc.make_status 0.to_s
220
+ end
221
+ end
222
+
223
+ def handle_s0004 status_code, status_name=nil
224
+ case status_name
225
+ when 'outputstatus'
226
+ RSMP::Tlc.make_status 0
227
+ when 'extendedoutputstatus'
228
+ RSMP::Tlc.make_status 0
229
+ end
230
+ end
231
+
232
+ def handle_s0005 status_code, status_name=nil
233
+ case status_name
234
+ when 'status'
235
+ RSMP::Tlc.make_status @is_starting
236
+ end
237
+ end
238
+
239
+ def handle_s0006 status_code, status_name=nil
240
+ case status_name
241
+ when 'status'
242
+ RSMP::Tlc.make_status @emergency_route
243
+ when 'emergencystage'
244
+ RSMP::Tlc.make_status @emergency_route_number
245
+ end
246
+ end
247
+
248
+ def handle_s0007 status_code, status_name=nil
249
+ case status_name
250
+ when 'intersection'
251
+ RSMP::Tlc.make_status @intersection
252
+ when 'status'
253
+ RSMP::Tlc.make_status !@dark_mode
254
+ end
255
+ end
256
+
257
+ def handle_s0008 status_code, status_name=nil
258
+ case status_name
259
+ when 'intersection'
260
+ RSMP::Tlc.make_status @intersection
261
+ when 'status'
262
+ RSMP::Tlc.make_status @manual_control
263
+ end
264
+ end
265
+
266
+ def handle_s0009 status_code, status_name=nil
267
+ case status_name
268
+ when 'intersection'
269
+ RSMP::Tlc.make_status @intersection
270
+ when 'status'
271
+ RSMP::Tlc.make_status @fixed_time_control
272
+ end
273
+ end
274
+
275
+ def handle_s0010 status_code, status_name=nil
276
+ case status_name
277
+ when 'intersection'
278
+ RSMP::Tlc.make_status @intersection
279
+ when 'status'
280
+ RSMP::Tlc.make_status @isolated_control
281
+ end
282
+ end
283
+
284
+ def handle_s0011 status_code, status_name=nil
285
+ case status_name
286
+ when 'intersection'
287
+ RSMP::Tlc.make_status @intersection
288
+ when 'status'
289
+ RSMP::Tlc.make_status @yellow_flash
290
+ end
291
+ end
292
+
293
+ def handle_s0012 status_code, status_name=nil
294
+ case status_name
295
+ when 'intersection'
296
+ RSMP::Tlc.make_status @intersection
297
+ when 'status'
298
+ RSMP::Tlc.make_status @all_red
299
+ end
300
+ end
301
+
302
+ def handle_s0013 status_code, status_name=nil
303
+ case status_name
304
+ when 'intersection'
305
+ RSMP::Tlc.make_status @intersection
306
+ when 'status'
307
+ RSMP::Tlc.make_status @police_key
308
+ end
309
+ end
310
+
311
+ def handle_s0014 status_code, status_name=nil
312
+ case status_name
313
+ when 'status'
314
+ RSMP::Tlc.make_status @plan
315
+ end
316
+ end
317
+
318
+ def handle_s0015 status_code, status_name=nil
319
+ case status_name
320
+ when 'status'
321
+ RSMP::Tlc.make_status @traffic_situation
322
+ end
323
+ end
324
+
325
+ def handle_s0016 status_code, status_name=nil
326
+ case status_name
327
+ when 'number'
328
+ RSMP::Tlc.make_status @detector_logics.size
329
+ end
330
+ end
331
+
332
+ def handle_s0017 status_code, status_name=nil
333
+ case status_name
334
+ when 'number'
335
+ RSMP::Tlc.make_status @signal_groups.size
336
+ end
337
+ end
338
+
339
+ def handle_s0018 status_code, status_name=nil
340
+ case status_name
341
+ when 'number'
342
+ RSMP::Tlc.make_status @plans.size
343
+ end
344
+ end
345
+
346
+ def handle_s0019 status_code, status_name=nil
347
+ case status_name
348
+ when 'number'
349
+ RSMP::Tlc.make_status @num_traffic_situations
350
+ end
351
+ end
352
+
353
+ def handle_s0020 status_code, status_name=nil
354
+ case status_name
355
+ when 'intersection'
356
+ RSMP::Tlc.make_status @intersection
357
+ when 'controlmode'
358
+ RSMP::Tlc.make_status @control_mode
359
+ end
360
+ end
361
+
362
+ def handle_s0021 status_code, status_name=nil
363
+ case status_name
364
+ when 'detectorlogics'
365
+ RSMP::Tlc.make_status @detector_logics.map { |logic| logic.forced=='True' ? '1' : '0'}.join
366
+ end
367
+ end
368
+
369
+ def handle_s0022 status_code, status_name=nil
370
+ case status_name
371
+ when 'status'
372
+ RSMP::Tlc.make_status '1'
373
+ end
374
+ end
375
+
376
+ def handle_s0023 status_code, status_name=nil
377
+ case status_name
378
+ when 'status'
379
+ RSMP::Tlc.make_status '1-1-0'
380
+ end
381
+ end
382
+
383
+ def handle_s0024 status_code, status_name=nil
384
+ case status_name
385
+ when 'status'
386
+ RSMP::Tlc.make_status '1-0'
387
+ end
388
+ end
389
+
390
+ def handle_s0026 status_code, status_name=nil
391
+ case status_name
392
+ when 'status'
393
+ RSMP::Tlc.make_status '0-00'
394
+ end
395
+ end
396
+
397
+ def handle_s0027 status_code, status_name=nil
398
+ case status_name
399
+ when 'status'
400
+ RSMP::Tlc.make_status '00-00-00-00'
401
+ end
402
+ end
403
+
404
+ def handle_s0028 status_code, status_name=nil
405
+ case status_name
406
+ when 'status'
407
+ RSMP::Tlc.make_status '00-00'
408
+ end
409
+ end
410
+
411
+ def handle_s0029 status_code, status_name=nil
412
+ case status_name
413
+ when 'status'
414
+ RSMP::Tlc.make_status ''
415
+ end
416
+ end
417
+
418
+ def handle_s0091 status_code, status_name=nil
419
+ case status_name
420
+ when 'user'
421
+ RSMP::Tlc.make_status 'nobody'
422
+ when 'status'
423
+ RSMP::Tlc.make_status 'logout'
424
+ end
425
+ end
426
+
427
+ def handle_s0092 status_code, status_name=nil
428
+ case status_name
429
+ when 'user'
430
+ RSMP::Tlc.make_status 'nobody'
431
+ when 'status'
432
+ RSMP::Tlc.make_status 'logout'
433
+ end
434
+ end
435
+
436
+ def handle_s0095 status_code, status_name=nil
437
+ case status_name
438
+ when 'status'
439
+ RSMP::Tlc.make_status RSMP::VERSION
440
+ end
441
+ end
442
+
443
+ def handle_s0096 status_code, status_name=nil
444
+ case status_name
445
+ when 'year'
446
+ RSMP::Tlc.make_status RSMP.now_object.year.to_s.rjust(4, "0")
447
+ when 'month'
448
+ RSMP::Tlc.make_status RSMP.now_object.month.to_s.rjust(2, "0")
449
+ when 'day'
450
+ RSMP::Tlc.make_status RSMP.now_object.day.to_s.rjust(2, "0")
451
+ when 'hour'
452
+ RSMP::Tlc.make_status RSMP.now_object.hour.to_s.rjust(2, "0")
453
+ when 'minute'
454
+ RSMP::Tlc.make_status RSMP.now_object.min.to_s.rjust(2, "0")
455
+ when 'second'
456
+ RSMP::Tlc.make_status RSMP.now_object.sec.to_s.rjust(2, "0")
457
+ end
458
+ end
459
+
460
+ def handle_s0205 status_code, status_name=nil
461
+ case status_name
462
+ when 'start'
463
+ RSMP::Tlc.make_status RSMP.now_string
464
+ when 'vehicles'
465
+ RSMP::Tlc.make_status 0
466
+ end
467
+ end
468
+
469
+ def handle_s0206 status_code, status_name=nil
470
+ case status_name
471
+ when 'start'
472
+ RSMP::Tlc.make_status RSMP.now_string
473
+ when 'speed'
474
+ RSMP::Tlc.make_status 0
475
+ end
476
+ end
477
+
478
+ def handle_s0207 status_code, status_name=nil
479
+ case status_name
480
+ when 'start'
481
+ RSMP::Tlc.make_status RSMP.now_string
482
+ when 'occupancy'
483
+ RSMP::Tlc.make_status 0
484
+ end
485
+ end
486
+
487
+ def handle_s0208 status_code, status_name=nil
488
+ case status_name
489
+ when 'start'
490
+ RSMP::Tlc.make_status RSMP.now_string
491
+ when 'P'
492
+ RSMP::Tlc.make_status 0
493
+ when 'PS'
494
+ RSMP::Tlc.make_status 0
495
+ when 'L'
496
+ RSMP::Tlc.make_status 0
497
+ when 'LS'
498
+ RSMP::Tlc.make_status 0
499
+ when 'B'
500
+ RSMP::Tlc.make_status 0
501
+ when 'SP'
502
+ RSMP::Tlc.make_status 0
503
+ when 'MC'
504
+ RSMP::Tlc.make_status 0
505
+ when 'C'
506
+ RSMP::Tlc.make_status 0
507
+ when 'F'
508
+ RSMP::Tlc.make_status 0
509
+ end
137
510
  end
138
511
 
139
512
  end
@@ -158,6 +531,128 @@ module RSMP
158
531
  def move pos
159
532
  @state = get_state pos
160
533
  end
534
+
535
+ def get_status code, name=nil
536
+ case code
537
+ when 'S0025'
538
+ return send("handle_#{code.downcase}", code, name)
539
+ else
540
+ raise InvalidMessage.new "unknown status code #{code}"
541
+ end
542
+ end
543
+
544
+ def handle_s0025 status_code, status_name=nil
545
+ case status_name
546
+ when 'minToGEstimate'
547
+ RSMP::Tlc.make_status RSMP.now_string
548
+ when 'maxToGEstimate'
549
+ RSMP::Tlc.make_status RSMP.now_string
550
+ when 'likelyToGEstimate'
551
+ RSMP::Tlc.make_status RSMP.now_string
552
+ when 'ToGConfidence'
553
+ RSMP::Tlc.make_status 0
554
+ when 'minToREstimate'
555
+ RSMP::Tlc.make_status RSMP.now_string
556
+ when 'maxToREstimate'
557
+ RSMP::Tlc.make_status RSMP.now_string
558
+ when 'likelyToREstimate'
559
+ RSMP::Tlc.make_status RSMP.now_string
560
+ when 'ToRConfidence'
561
+ RSMP::Tlc.make_status 0
562
+ end
563
+ end
564
+ end
565
+
566
+ class DetectorLogic < Component
567
+ attr_reader :status, :forced, :value
568
+
569
+ def initialize node:, id:
570
+ super node: node, id: id, grouped: false
571
+ @forced = 0
572
+ @value = 0
573
+ end
574
+
575
+ def get_status code, name=nil
576
+ case code
577
+ when 'S0201', 'S0202', 'S0203', 'S0204'
578
+ return send("handle_#{code.downcase}", code, name)
579
+ else
580
+ raise InvalidMessage.new "unknown status code #{code}"
581
+ end
582
+ end
583
+
584
+ def handle_s0201 status_code, status_name=nil
585
+ case status_name
586
+ when 'starttime'
587
+ RSMP::Tlc.make_status RSMP.now_string
588
+ when 'vehicles'
589
+ RSMP::Tlc.make_status 0
590
+ end
591
+ end
592
+
593
+ def handle_s0202 status_code, status_name=nil
594
+ case status_name
595
+ when 'starttime'
596
+ RSMP::Tlc.make_status RSMP.now_string
597
+ when 'speed'
598
+ RSMP::Tlc.make_status 0
599
+ end
600
+ end
601
+
602
+ def handle_s0203 status_code, status_name=nil
603
+ case status_name
604
+ when 'starttime'
605
+ RSMP::Tlc.make_status RSMP.now_string
606
+ when 'occupancy'
607
+ RSMP::Tlc.make_status 0
608
+ end
609
+ end
610
+
611
+ def handle_s0204 status_code, status_name=nil
612
+ case status_name
613
+ when 'starttime'
614
+ RSMP::Tlc.make_status RSMP.now_string
615
+ when 'P'
616
+ RSMP::Tlc.make_status 0
617
+ when 'PS'
618
+ RSMP::Tlc.make_status 0
619
+ when 'L'
620
+ RSMP::Tlc.make_status 0
621
+ when 'LS'
622
+ RSMP::Tlc.make_status 0
623
+ when 'B'
624
+ RSMP::Tlc.make_status 0
625
+ when 'SP'
626
+ RSMP::Tlc.make_status 0
627
+ when 'MC'
628
+ RSMP::Tlc.make_status 0
629
+ when 'C'
630
+ RSMP::Tlc.make_status 0
631
+ when 'F'
632
+ RSMP::Tlc.make_status 0
633
+ end
634
+ end
635
+
636
+ def handle_command command_code, arg
637
+ case command_code
638
+ when 'M0008'
639
+ handle_m0008 arg
640
+ else
641
+ raise UnknownCommand.new "Unknown command #{command_code}"
642
+ end
643
+ end
644
+
645
+ def handle_m0008 arg
646
+ @node.verify_security_code arg['securityCode']
647
+ force_detector_logic arg['status']=='True', arg['value']='True'
648
+ arg
649
+ end
650
+
651
+ def force_detector_logic status, value
652
+ @forced = status
653
+ @value = value
654
+ end
655
+
161
656
  end
162
657
 
163
658
  class Tlc < Site
@@ -171,14 +666,18 @@ module RSMP
171
666
  end
172
667
  end
173
668
 
174
- def build_component id, settings={}
175
- component = case settings['type']
669
+ def build_component id:, type:, settings:{}
670
+ component = case type
176
671
  when 'main'
177
672
  @main = TrafficController.new node: self, id: id, cycle_time: settings['cycle_time']
178
673
  when 'signal_group'
179
674
  group = SignalGroup.new node: self, id: id, plan: settings['plan']
180
675
  @main.add_signal_group group
181
676
  group
677
+ when 'detector_logic'
678
+ logic = DetectorLogic.new node: self, id: id
679
+ @main.add_detector_logic logic
680
+ logic
182
681
  end
183
682
  end
184
683
 
@@ -222,14 +721,28 @@ module RSMP
222
721
  @main.timer now
223
722
  end
224
723
 
225
- def handle_command command_code, arg
226
- return unless @main
227
- @main.handle_command command_code, arg
724
+ def verify_security_code code
228
725
  end
229
726
 
230
- def get_status status_code, status_name=nil
231
- return unless @main
232
- @main.get_status status_code, status_name
727
+ def self.to_rmsp_bool bool
728
+ if bool
729
+ 'True'
730
+ else
731
+ 'False'
732
+ end
733
+ end
734
+
735
+ def self.from_rsmp_bool str
736
+ str == 'True'
737
+ end
738
+
739
+ def self.make_status value, q='recent'
740
+ case value
741
+ when true, false
742
+ return to_rmsp_bool(value), q
743
+ else
744
+ return value, q
745
+ end
233
746
  end
234
747
 
235
748
  end
@@ -1,3 +1,3 @@
1
1
  module RSMP
2
- VERSION = "0.1.13"
2
+ VERSION = "0.1.17"
3
3
  end
@@ -42,17 +42,16 @@ Gem::Specification.new do |spec|
42
42
  spec.require_paths = ["lib"]
43
43
 
44
44
  spec.add_dependency "async", "~> 1.23.0"
45
- spec.add_dependency "async-io", "~> 1.27.1"
45
+ spec.add_dependency "async-io", "~> 1.27.4"
46
46
  spec.add_dependency "colorize", "~> 0.8.1"
47
- spec.add_dependency "thor", "~> 0.20.3"
48
- spec.add_dependency "json_schemer", "~> 0.2.8"
49
-
50
- spec.add_development_dependency "bundler", "~> 2.0"
51
- spec.add_development_dependency "rake", "~> 10.0"
52
- spec.add_development_dependency "rspec", "~> 3.0"
53
- spec.add_development_dependency "rspec-expectations", "~> 3.8.3"
54
- spec.add_development_dependency "rspec-with_params", "~> 0.2.0"
47
+ spec.add_dependency "thor", "~> 1.0.1"
48
+ spec.add_dependency "json_schemer", "~> 0.2.11"
49
+
50
+ spec.add_development_dependency "bundler", "~> 2.1.4"
51
+ spec.add_development_dependency "rake", "~> 13.0.1"
52
+ spec.add_development_dependency "rspec", "~> 3.9.0"
53
+ spec.add_development_dependency "rspec-expectations", "~> 3.9.1"
55
54
  spec.add_development_dependency "timecop", "~> 0.9.1"
56
55
  spec.add_development_dependency "cucumber", "~> 3.1.2"
57
- spec.add_development_dependency "aruba", "~> 0.14.11"
56
+ spec.add_development_dependency "aruba", "~> 1.0.0"
58
57
  end
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.1.13
4
+ version: 0.1.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Emil Tin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-01-09 00:00:00.000000000 Z
11
+ date: 2020-03-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.27.1
33
+ version: 1.27.4
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 1.27.1
40
+ version: 1.27.4
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: colorize
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -58,98 +58,84 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.20.3
61
+ version: 1.0.1
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 0.20.3
68
+ version: 1.0.1
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: json_schemer
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 0.2.8
75
+ version: 0.2.11
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 0.2.8
82
+ version: 0.2.11
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: bundler
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '2.0'
89
+ version: 2.1.4
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '2.0'
96
+ version: 2.1.4
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rake
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '10.0'
103
+ version: 13.0.1
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '10.0'
110
+ version: 13.0.1
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: rspec
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '3.0'
117
+ version: 3.9.0
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '3.0'
124
+ version: 3.9.0
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: rspec-expectations
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: 3.8.3
131
+ version: 3.9.1
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: 3.8.3
139
- - !ruby/object:Gem::Dependency
140
- name: rspec-with_params
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: 0.2.0
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: 0.2.0
138
+ version: 3.9.1
153
139
  - !ruby/object:Gem::Dependency
154
140
  name: timecop
155
141
  requirement: !ruby/object:Gem::Requirement
@@ -184,14 +170,14 @@ dependencies:
184
170
  requirements:
185
171
  - - "~>"
186
172
  - !ruby/object:Gem::Version
187
- version: 0.14.11
173
+ version: 1.0.0
188
174
  type: :development
189
175
  prerelease: false
190
176
  version_requirements: !ruby/object:Gem::Requirement
191
177
  requirements:
192
178
  - - "~>"
193
179
  - !ruby/object:Gem::Version
194
- version: 0.14.11
180
+ version: 1.0.0
195
181
  description: Easy RSMP site and supervisor communication.
196
182
  email:
197
183
  - zf0f@kk.dk
@@ -359,7 +345,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
359
345
  - !ruby/object:Gem::Version
360
346
  version: '0'
361
347
  requirements: []
362
- rubygems_version: 3.0.3
348
+ rubygems_version: 3.1.2
363
349
  signing_key:
364
350
  specification_version: 4
365
351
  summary: RoadSide Message Protocol (RSMP) library.