rsmp 0.9.7 → 0.9.10

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: 9634c9a0b4e843d2f9d53f85023a51584a4686bea45aeb4cc74dbca7d63a117b
4
- data.tar.gz: 598c15d07dc9dd22bda5e4901e2537b902b675af9a88281c2dae9b494d41a52f
3
+ metadata.gz: f9afdedb545513c5574db59a28f07515866dbd34d8908767813275518ee590cd
4
+ data.tar.gz: e6fa96a531f450ce114601a57f91045ade415bb9317c5155a57a05054acf6481
5
5
  SHA512:
6
- metadata.gz: 990b18990bc24622bdceb84c9f19a247fb3c6e6cca82fb0a4019e1aa1da7f33503f182ebd4d7789ab890c4d9d51c83062f7f6ff8ab96681bc8cd98cc626418e8
7
- data.tar.gz: 20d4a23d38c6cce0ce46fe7def72d90a822627f51800a82d90c06f433e7104d3336a1c300ba6462038c641d08378980ceb794dc0ec54a91d36a17b21d1bf589a
6
+ metadata.gz: c3a2fbb33b4789e0cc0200156f759014eab17b51a23f78e486fd8fa67e54da1ac241bdd1c1b6c77ce0b0534d8447607b8806105433920ef7d00733183c2e67de
7
+ data.tar.gz: c6cf57cc0b98b54c541293283b7810de1ce218a3c22454d925db5727706b1d29793493d2cc0bff6f96e932c8dc6e9f5dffab005ebba79785617f9292c056575c
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rsmp (0.9.7)
4
+ rsmp (0.9.10)
5
5
  async (~> 1.29.1)
6
6
  async-io (~> 1.32.2)
7
7
  colorize (~> 0.8.1)
@@ -72,7 +72,7 @@ module RSMP
72
72
  else
73
73
  super message
74
74
  end
75
- rescue RSMP::RepeatedAlarmError, RSMP::RepeatedStatusError => e
75
+ rescue RSMP::RepeatedAlarmError, RSMP::RepeatedStatusError, RSMP::TimestampError => e
76
76
  str = "Rejected #{message.type} message,"
77
77
  dont_acknowledge message, str, "#{e}"
78
78
  notify_error e.exception("#{str}#{e.message} #{message.json}")
@@ -0,0 +1,134 @@
1
+ module RSMP
2
+ module TLC
3
+ # class that maintains the state of TLC inputs
4
+ # indexing is 1-based since that's how the RSMP messages are specified
5
+ class Inputs
6
+ attr_reader :size
7
+
8
+ def initialize size
9
+ @size = size
10
+ reset
11
+ end
12
+
13
+ def reset
14
+ string_size = @size+1
15
+ @value = '0'*string_size
16
+ @forced = '0'*string_size
17
+ @forced_value = '0'*string_size
18
+ @actual = '0'*string_size
19
+ end
20
+
21
+ def set input, value
22
+ check_input input
23
+ report_change(input) do
24
+ @value[input] = to_digit value
25
+ update_actual input
26
+ end
27
+ end
28
+
29
+ def set_forcing input, force=true, forced_value=true
30
+ check_input input
31
+ report_change(input) do
32
+ @forced[input] = to_digit force
33
+ @forced_value[input] = to_digit forced_value
34
+ update_actual input
35
+ end
36
+ end
37
+
38
+ def force input, forced_value=true
39
+ report_change(input) do
40
+ set_forcing input, true, forced_value
41
+ end
42
+ end
43
+
44
+ def release input
45
+ report_change(input) do
46
+ set_forcing input, false, false
47
+ end
48
+ end
49
+
50
+ def value input
51
+ check_input input
52
+ from_digit @value[input]
53
+ end
54
+
55
+ def forced? input
56
+ check_input input
57
+ from_digit @forced[input]
58
+ end
59
+
60
+ def forced_value input
61
+ check_input input
62
+ from_digit @forced_value[input]
63
+ end
64
+
65
+ def actual input
66
+ check_input input
67
+ from_digit @actual[input]
68
+ end
69
+
70
+ def report input
71
+ {
72
+ value: value(input),
73
+ forced: forced?(input),
74
+ forced_value: forced_value(input),
75
+ actual:actual(input)
76
+ }
77
+ end
78
+
79
+ def value_string
80
+ @value[1..-1]
81
+ end
82
+
83
+ def value_string
84
+ @value[1..-1]
85
+ end
86
+
87
+ def forced_string
88
+ @forced[1..-1]
89
+ end
90
+
91
+ def forced_value_string
92
+ @forced[1..-1]
93
+ end
94
+
95
+ def actual_string
96
+ @actual[1..-1]
97
+ end
98
+
99
+ protected
100
+
101
+ def check_input input
102
+ raise ArgumentError.new("Input index #{input} must be in the range 1-#{@size}") if input<1 || input>@size
103
+ end
104
+
105
+ def from_digit input
106
+ input == '1'
107
+ end
108
+
109
+ def to_digit input
110
+ input ? '1' : '0'
111
+ end
112
+
113
+ def update_actual input
114
+ if from_digit @forced[input]
115
+ @actual[input] = @forced_value[input]
116
+ else
117
+ @actual[input] = @value[input]
118
+ end
119
+ end
120
+
121
+ def report_change input, &block
122
+ before = @actual[input]
123
+ yield
124
+ if @actual[input] != before
125
+ from_digit @actual[input]
126
+ else
127
+ nil
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+
@@ -10,15 +10,22 @@ module RSMP
10
10
  :startup_sequence_active, :startup_sequence, :startup_sequence_pos
11
11
 
12
12
  def initialize node:, id:, cycle_time: 10, signal_plans:,
13
- startup_sequence:, live_output:nil, inputs:
13
+ startup_sequence:, live_output:nil, inputs:{}
14
14
  super node: node, id: id, grouped: true
15
15
  @signal_groups = []
16
16
  @detector_logics = []
17
17
  @plans = signal_plans
18
18
  @cycle_time = cycle_time
19
19
  @num_traffic_situations = 1
20
- @num_inputs = inputs['total']
21
- @input_programming = inputs['programming']
20
+
21
+ if inputs
22
+ num_inputs = inputs['total']
23
+ @input_programming = inputs['programming']
24
+ else
25
+ @input_programming = nil
26
+ end
27
+ @inputs = TLC::Inputs.new num_inputs || 8
28
+
22
29
  @startup_sequence = startup_sequence
23
30
  @live_output = live_output
24
31
  reset
@@ -41,25 +48,18 @@ module RSMP
41
48
 
42
49
  def reset
43
50
  reset_modes
44
-
45
51
  @cycle_counter = 0
46
52
  @plan = 1
47
53
  @intersection = 0
48
54
  @emergency_route = false
49
55
  @emergency_route_number = 0
50
56
  @traffic_situation = 0
51
-
52
- @inputs = '0'*@num_inputs
53
- @input_activations = '0'*@num_inputs
54
- @input_forced = '0'*@num_inputs
55
- @input_forced_values = '0'*@num_inputs
56
- @input_results = '0'*@num_inputs
57
-
58
57
  @day_time_table = {}
59
58
  @startup_sequence_active = false
60
59
  @startup_sequence_initiated_at = nil
61
60
  @startup_sequence_pos = 0
62
61
  @time_int = nil
62
+ @inputs.reset
63
63
  end
64
64
 
65
65
  def dark?
@@ -256,43 +256,34 @@ module RSMP
256
256
  end
257
257
  end
258
258
 
259
- def recompute_input idx
260
- if @input_forced[idx] == '1'
261
- @input_results[idx] = @input_forced_values[idx]
262
- elsif @input_activations[idx]=='1'
263
- @input_results[idx] = '1'
264
- else
265
- @input_results[idx] = bool_to_digit( @inputs[idx]=='1' )
259
+ def input_logic input, change
260
+ return unless @input_programming && change != nil
261
+ actions = @input_programming[input]
262
+ return unless actions
263
+ if actions['raise']
264
+ alarm_code = actions['raise']
265
+ if change
266
+ log "Activating alarm #{alarm_code}, because input #{input} was activated", level: :info
267
+ else
268
+ log "Deactivating alarm #{alarm_code}, because input #{input} was deactivated", level: :info
269
+ end
266
270
  end
267
271
  end
268
272
 
269
273
  def handle_m0006 arg
270
274
  @node.verify_security_code 2, arg['securityCode']
271
275
  input = arg['input'].to_i
272
- unless input>0 && input<=@num_inputs
273
- raise MessageRejected.new("Input #{idx} is invalid, must be in the range 1-#{@num_inputs}")
274
- end
275
- idx = input - 1
276
- @input_activations[idx] = bool_string_to_digit arg['status']
277
- recompute_input idx
278
- activate = @input_activations[idx] == '1'
279
- if activate
276
+ status = string_to_bool arg['status']
277
+ unless input>=1 && input<=@inputs.size
278
+ raise MessageRejected.new("Input must be in the range 1-#{@inputs.size}")
279
+ end
280
+ if status
280
281
  log "Activating input #{input}", level: :info
281
282
  else
282
283
  log "Deactivating input #{input}", level: :info
283
284
  end
284
-
285
- if @input_programming
286
- actions = @input_programming[input]
287
- if actions && actions['raise']
288
- alarm_code = actions['raise']
289
- if activate
290
- log "Activating alarm #{alarm_code}, due to input #{input} programming", level: :info
291
- else
292
- log "Deactivating alarm #{alarm_code}, due to input #{input} programming", level: :info
293
- end
294
- end
295
- end
285
+ change = @inputs.set input, status
286
+ input_logic input, change if change != nil
296
287
  end
297
288
 
298
289
  def handle_m0007 arg
@@ -354,6 +345,17 @@ module RSMP
354
345
  @node.verify_security_code 2, arg['securityCode']
355
346
  end
356
347
 
348
+ def string_to_bool bool_str
349
+ case bool_str
350
+ when 'True'
351
+ true
352
+ when 'False'
353
+ false
354
+ else
355
+ raise RSMP::MessageRejected.new "Invalid boolean '#{bool}', must be 'True' or 'False'"
356
+ end
357
+ end
358
+
357
359
  def bool_string_to_digit bool
358
360
  case bool
359
361
  when 'True'
@@ -372,21 +374,18 @@ module RSMP
372
374
  def handle_m0019 arg
373
375
  @node.verify_security_code 2, arg['securityCode']
374
376
  input = arg['input'].to_i
375
- idx = input - 1
376
- unless idx>=0 && input<@num_inputs # TODO should NotAck
377
- log "Can't force input #{idx+1}, only have #{@num_inputs} inputs", level: :warning
378
- return
379
- end
380
- @input_forced[idx] = bool_string_to_digit arg['status']
381
- if @input_forced[idx]
382
- @input_forced_values[idx] = bool_string_to_digit arg['inputValue']
383
- end
384
- recompute_input idx
385
- if @input_forced[idx]
386
- log "Forcing input #{idx+1} to #{@input_forced_values[idx]}, #{@input_results}", level: :info
377
+ force = string_to_bool arg['status']
378
+ forced_value = string_to_bool arg['inputValue']
379
+ unless input>=1 && input<=@inputs.size
380
+ raise MessageRejected.new("Input must be in the range 1-#{@inputs.size}")
381
+ end
382
+ if force
383
+ log "Forcing input #{input} to #{forced_value}", level: :info
387
384
  else
388
- log "Releasing input #{idx+1}", level: :info
385
+ log "Releasing input #{input}", level: :info
389
386
  end
387
+ change = @inputs.set_forcing input, force, forced_value
388
+ input_logic input, change if change != nil
390
389
  end
391
390
 
392
391
  def handle_m0020 arg
@@ -496,7 +495,7 @@ module RSMP
496
495
  def handle_s0003 status_code, status_name=nil
497
496
  case status_name
498
497
  when 'inputstatus'
499
- TrafficControllerSite.make_status @input_results
498
+ TrafficControllerSite.make_status @inputs.actual_string
500
499
  when 'extendedinputstatus'
501
500
  TrafficControllerSite.make_status 0.to_s
502
501
  end
@@ -698,7 +697,7 @@ module RSMP
698
697
  def handle_s0029 status_code, status_name=nil
699
698
  case status_name
700
699
  when 'status'
701
- TrafficControllerSite.make_status @input_forced
700
+ TrafficControllerSite.make_status @inputs.forced_string
702
701
  end
703
702
  end
704
703
 
data/lib/rsmp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module RSMP
2
- VERSION = "0.9.7"
2
+ VERSION = "0.9.10"
3
3
  end
data/lib/rsmp.rb CHANGED
@@ -44,6 +44,7 @@ require 'rsmp/tlc/traffic_controller'
44
44
  require 'rsmp/tlc/detector_logic'
45
45
  require 'rsmp/tlc/signal_group'
46
46
  require 'rsmp/tlc/signal_plan'
47
+ require 'rsmp/tlc/inputs'
47
48
 
48
49
  require 'rsmp/convert/import/yaml'
49
50
  require 'rsmp/convert/export/json_schema'
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.9.7
4
+ version: 0.9.10
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-03-10 00:00:00.000000000 Z
11
+ date: 2022-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -243,6 +243,7 @@ files:
243
243
  - lib/rsmp/supervisor_proxy.rb
244
244
  - lib/rsmp/task.rb
245
245
  - lib/rsmp/tlc/detector_logic.rb
246
+ - lib/rsmp/tlc/inputs.rb
246
247
  - lib/rsmp/tlc/signal_group.rb
247
248
  - lib/rsmp/tlc/signal_plan.rb
248
249
  - lib/rsmp/tlc/traffic_controller.rb