rsmp 0.37.0 → 0.38.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.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/devcontainer.json +22 -0
  3. data/.github/workflows/rubocop.yaml +17 -0
  4. data/.gitignore +5 -6
  5. data/.rubocop.yml +80 -0
  6. data/Gemfile +13 -1
  7. data/Gemfile.lock +34 -1
  8. data/Rakefile +3 -3
  9. data/lib/rsmp/cli.rb +147 -124
  10. data/lib/rsmp/collect/ack_collector.rb +8 -7
  11. data/lib/rsmp/collect/aggregated_status_collector.rb +4 -4
  12. data/lib/rsmp/collect/alarm_collector.rb +31 -23
  13. data/lib/rsmp/collect/alarm_matcher.rb +3 -3
  14. data/lib/rsmp/collect/collector/logging.rb +17 -0
  15. data/lib/rsmp/collect/collector/reporting.rb +44 -0
  16. data/lib/rsmp/collect/collector/status.rb +34 -0
  17. data/lib/rsmp/collect/collector.rb +69 -150
  18. data/lib/rsmp/collect/command_matcher.rb +19 -6
  19. data/lib/rsmp/collect/command_response_collector.rb +7 -7
  20. data/lib/rsmp/collect/distributor.rb +14 -11
  21. data/lib/rsmp/collect/filter.rb +31 -15
  22. data/lib/rsmp/collect/matcher.rb +7 -11
  23. data/lib/rsmp/collect/queue.rb +4 -4
  24. data/lib/rsmp/collect/receiver.rb +10 -12
  25. data/lib/rsmp/collect/state_collector.rb +116 -77
  26. data/lib/rsmp/collect/status_collector.rb +6 -6
  27. data/lib/rsmp/collect/status_matcher.rb +17 -7
  28. data/lib/rsmp/{alarm_state.rb → component/alarm_state.rb} +76 -37
  29. data/lib/rsmp/{component.rb → component/component.rb} +15 -15
  30. data/lib/rsmp/component/component_base.rb +89 -0
  31. data/lib/rsmp/component/component_proxy.rb +75 -0
  32. data/lib/rsmp/component/components.rb +63 -0
  33. data/lib/rsmp/convert/export/json_schema.rb +116 -110
  34. data/lib/rsmp/convert/import/yaml.rb +21 -18
  35. data/lib/rsmp/{rsmp.rb → helpers/clock.rb} +5 -6
  36. data/lib/rsmp/{deep_merge.rb → helpers/deep_merge.rb} +2 -1
  37. data/lib/rsmp/helpers/error.rb +71 -0
  38. data/lib/rsmp/{inspect.rb → helpers/inspect.rb} +6 -10
  39. data/lib/rsmp/log/archive.rb +98 -0
  40. data/lib/rsmp/log/colorization.rb +41 -0
  41. data/lib/rsmp/log/filtering.rb +54 -0
  42. data/lib/rsmp/log/logger.rb +206 -0
  43. data/lib/rsmp/{logging.rb → log/logging.rb} +5 -7
  44. data/lib/rsmp/message.rb +159 -148
  45. data/lib/rsmp/{node.rb → node/node.rb} +19 -17
  46. data/lib/rsmp/{protocol.rb → node/protocol.rb} +5 -3
  47. data/lib/rsmp/node/site/site.rb +195 -0
  48. data/lib/rsmp/node/supervisor/modules/configuration.rb +59 -0
  49. data/lib/rsmp/node/supervisor/modules/connection.rb +140 -0
  50. data/lib/rsmp/node/supervisor/modules/sites.rb +64 -0
  51. data/lib/rsmp/node/supervisor/supervisor.rb +72 -0
  52. data/lib/rsmp/{task.rb → node/task.rb} +12 -14
  53. data/lib/rsmp/proxy/modules/acknowledgements.rb +144 -0
  54. data/lib/rsmp/proxy/modules/receive.rb +119 -0
  55. data/lib/rsmp/proxy/modules/send.rb +76 -0
  56. data/lib/rsmp/proxy/modules/state.rb +25 -0
  57. data/lib/rsmp/proxy/modules/tasks.rb +105 -0
  58. data/lib/rsmp/proxy/modules/versions.rb +69 -0
  59. data/lib/rsmp/proxy/modules/watchdogs.rb +66 -0
  60. data/lib/rsmp/proxy/proxy.rb +199 -0
  61. data/lib/rsmp/proxy/site/modules/aggregated_status.rb +52 -0
  62. data/lib/rsmp/proxy/site/modules/alarms.rb +27 -0
  63. data/lib/rsmp/proxy/site/modules/commands.rb +31 -0
  64. data/lib/rsmp/proxy/site/modules/status.rb +110 -0
  65. data/lib/rsmp/proxy/site/site_proxy.rb +205 -0
  66. data/lib/rsmp/proxy/supervisor/modules/aggregated_status.rb +47 -0
  67. data/lib/rsmp/proxy/supervisor/modules/alarms.rb +73 -0
  68. data/lib/rsmp/proxy/supervisor/modules/commands.rb +53 -0
  69. data/lib/rsmp/proxy/supervisor/modules/status.rb +204 -0
  70. data/lib/rsmp/proxy/supervisor/supervisor_proxy.rb +178 -0
  71. data/lib/rsmp/tlc/detector_logic.rb +18 -34
  72. data/lib/rsmp/tlc/input_states.rb +126 -0
  73. data/lib/rsmp/tlc/modules/detector_logics.rb +50 -0
  74. data/lib/rsmp/tlc/modules/display.rb +78 -0
  75. data/lib/rsmp/tlc/modules/helpers.rb +41 -0
  76. data/lib/rsmp/tlc/modules/inputs.rb +173 -0
  77. data/lib/rsmp/tlc/modules/modes.rb +253 -0
  78. data/lib/rsmp/tlc/modules/outputs.rb +30 -0
  79. data/lib/rsmp/tlc/modules/plans.rb +218 -0
  80. data/lib/rsmp/tlc/modules/signal_groups.rb +109 -0
  81. data/lib/rsmp/tlc/modules/startup_sequence.rb +22 -0
  82. data/lib/rsmp/tlc/modules/system.rb +140 -0
  83. data/lib/rsmp/tlc/modules/traffic_data.rb +49 -0
  84. data/lib/rsmp/tlc/signal_group.rb +37 -41
  85. data/lib/rsmp/tlc/signal_plan.rb +14 -11
  86. data/lib/rsmp/tlc/signal_priority.rb +39 -35
  87. data/lib/rsmp/tlc/startup_sequence.rb +59 -0
  88. data/lib/rsmp/tlc/traffic_controller.rb +38 -1010
  89. data/lib/rsmp/tlc/traffic_controller_site.rb +58 -57
  90. data/lib/rsmp/version.rb +1 -1
  91. data/lib/rsmp.rb +82 -48
  92. data/rsmp.gemspec +24 -31
  93. metadata +79 -139
  94. data/lib/rsmp/archive.rb +0 -76
  95. data/lib/rsmp/collect/message_matchers.rb +0 -0
  96. data/lib/rsmp/component_base.rb +0 -87
  97. data/lib/rsmp/component_proxy.rb +0 -57
  98. data/lib/rsmp/components.rb +0 -65
  99. data/lib/rsmp/error.rb +0 -71
  100. data/lib/rsmp/logger.rb +0 -216
  101. data/lib/rsmp/proxy.rb +0 -693
  102. data/lib/rsmp/site.rb +0 -188
  103. data/lib/rsmp/site_proxy.rb +0 -389
  104. data/lib/rsmp/supervisor.rb +0 -302
  105. data/lib/rsmp/supervisor_proxy.rb +0 -510
  106. data/lib/rsmp/tlc/inputs.rb +0 -134
@@ -0,0 +1,73 @@
1
+ module RSMP
2
+ class SupervisorProxy < Proxy
3
+ module Modules
4
+ # Alarm handling
5
+ module Alarms
6
+ def send_alarm(_component, alarm, options = {})
7
+ send_and_optionally_collect alarm, options do |collect_options|
8
+ Collector.new self, collect_options.merge(task: @task, type: 'MessageAck')
9
+ end
10
+ end
11
+
12
+ def send_active_alarms
13
+ @site.components.each_pair do |_c_id, component|
14
+ component.alarms.each_pair do |_alarm_code, alarm_state|
15
+ if alarm_state.active
16
+ alarm = AlarmIssue.new(alarm_state.to_hash.merge('aSp' => 'Issue'))
17
+ send_message alarm
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ def process_alarm(message)
24
+ case message
25
+ when AlarmAcknowledge
26
+ handle_alarm_acknowledge message
27
+ when AlarmSuspend
28
+ handle_alarm_suspend message
29
+ when AlarmResume
30
+ handle_alarm_resume message
31
+ when AlarmRequest
32
+ handle_alarm_request message
33
+ else
34
+ dont_acknowledge message, 'Invalid alarm message type'
35
+ end
36
+ end
37
+
38
+ def handle_alarm_acknowledge(message)
39
+ component_id = message.attributes['cId']
40
+ component = @site.find_component component_id
41
+ alarm_code = message.attribute('aCId')
42
+ log "Received #{message.type} #{alarm_code} acknowledgement", message: message, level: :log
43
+ acknowledge message
44
+ component.acknowledge_alarm alarm_code
45
+ end
46
+
47
+ def handle_alarm_suspend(message)
48
+ component_id = message.attributes['cId']
49
+ component = @site.find_component component_id
50
+ alarm_code = message.attribute('aCId')
51
+ log "Received #{message.type} #{alarm_code} suspend", message: message, level: :log
52
+ acknowledge message
53
+ component.suspend_alarm alarm_code
54
+ end
55
+
56
+ def handle_alarm_resume(message)
57
+ component_id = message.attributes['cId']
58
+ component = @site.find_component component_id
59
+ alarm_code = message.attribute('aCId')
60
+ log "Received #{message.type} #{alarm_code} resume", message: message, level: :log
61
+ acknowledge message
62
+ component.resume_alarm alarm_code
63
+ end
64
+
65
+ def handle_alarm_request(message)
66
+ log "Received #{message.type}", message: message, level: :log
67
+ acknowledge message
68
+ send_active_alarms
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,53 @@
1
+ module RSMP
2
+ class SupervisorProxy < Proxy
3
+ module Modules
4
+ # Command request handling
5
+ module Commands
6
+ def simplify_command_requests(arg)
7
+ sorted = {}
8
+ arg.each do |item|
9
+ sorted[item['cCI']] ||= {}
10
+ sorted[item['cCI']][item['n']] = item['v']
11
+ end
12
+ sorted
13
+ end
14
+
15
+ def build_command_rvs(args)
16
+ args.map do |item|
17
+ item = item.dup.merge('age' => 'recent')
18
+ item.delete 'cO'
19
+ item
20
+ end
21
+ end
22
+
23
+ def execute_commands(message, component_id, rvs)
24
+ component = @site.find_component component_id
25
+ commands = simplify_command_requests message.attributes['arg']
26
+ commands.each_pair do |command_code, arg|
27
+ component.handle_command command_code, arg
28
+ end
29
+ log "Received #{message.type}", message: message, level: :log
30
+ rescue UnknownComponent
31
+ log "Received #{message.type} with unknown component id '#{component_id}' and cannot infer type",
32
+ message: message, level: :warning
33
+ rvs.map { |item| item['age'] = 'undefined' }
34
+ end
35
+
36
+ def process_command_request(message)
37
+ component_id = message.attributes['cId']
38
+ rvs = build_command_rvs(message.attributes['arg'])
39
+ execute_commands(message, component_id, rvs)
40
+
41
+ response = CommandResponse.new({
42
+ 'cId' => component_id,
43
+ 'cTS' => clock.to_s,
44
+ 'rvs' => rvs
45
+ })
46
+ apply_nts_message_attributes response
47
+ acknowledge message
48
+ send_message response
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,204 @@
1
+ module RSMP
2
+ class SupervisorProxy < Proxy
3
+ module Modules
4
+ # Status request and subscription handling
5
+ module Status
6
+ def rsmpify_value(value, quality)
7
+ if value.is_a?(Array) || value.is_a?(Set)
8
+ value
9
+ elsif %w[undefined unknown].include?(quality.to_s)
10
+ nil
11
+ else
12
+ value.to_s
13
+ end
14
+ end
15
+
16
+ def fetch_status_values(component, args)
17
+ args.map do |arg|
18
+ value, quality = component.get_status arg['sCI'], arg['n'], { sxl_version: sxl_version }
19
+ { 's' => rsmpify_value(value, quality), 'q' => quality.to_s }.merge arg
20
+ end
21
+ end
22
+
23
+ def build_undefined_statuses(args)
24
+ args.map { |arg| arg.dup.merge('q' => 'undefined', 's' => nil) }
25
+ end
26
+
27
+ def process_status_request(message, options = {})
28
+ component_id = message.attributes['cId']
29
+ args = message.attributes['sS']
30
+
31
+ begin
32
+ component = @site.find_component component_id
33
+ ss = fetch_status_values(component, args)
34
+ log "Received #{message.type}", message: message, level: :log
35
+ rescue UnknownComponent
36
+ log "Received #{message.type} with unknown component id '#{component_id}' and cannot infer type",
37
+ message: message, level: :warning
38
+ ss = build_undefined_statuses(args)
39
+ end
40
+
41
+ response = StatusResponse.new({
42
+ 'cId' => component_id,
43
+ 'sTs' => clock.to_s,
44
+ 'sS' => ss,
45
+ 'mId' => options[:m_id]
46
+ })
47
+
48
+ apply_nts_message_attributes response
49
+ acknowledge message
50
+ send_message response
51
+ end
52
+
53
+ def add_status_subscription(component_id, subs, update_list, arg, now)
54
+ sci = arg['sCI']
55
+ name = arg['n']
56
+ subcription = { interval: arg['uRt'].to_i, last_sent_at: now }
57
+ subs[sci] ||= {}
58
+ subs[sci][name] = subcription
59
+ update_list[component_id][sci] ||= []
60
+ update_list[component_id][sci] << name
61
+ end
62
+
63
+ def process_status_subcribe(message)
64
+ log "Received #{message.type}", message: message, level: :log
65
+
66
+ update_list = {}
67
+ component_id = message.attributes['cId']
68
+ @status_subscriptions[component_id] ||= {}
69
+ update_list[component_id] ||= {}
70
+ now = Time.now
71
+ subs = @status_subscriptions[component_id]
72
+
73
+ message.attributes['sS'].each do |arg|
74
+ add_status_subscription(component_id, subs, update_list, arg, now)
75
+ end
76
+ acknowledge message
77
+ send_status_updates update_list
78
+ end
79
+
80
+ def get_status_subscribe_interval(component_id, sci, name)
81
+ @status_subscriptions.dig component_id, sci, name
82
+ end
83
+
84
+ def remove_status_subscription(subs, arg)
85
+ sci = arg['sCI']
86
+ return unless subs[sci]
87
+
88
+ subs[sci].delete arg['n']
89
+ subs.delete(sci) if subs[sci].empty?
90
+ end
91
+
92
+ def process_status_unsubcribe(message)
93
+ log "Received #{message.type}", message: message, level: :log
94
+ component = message.attributes['cId']
95
+
96
+ subs = @status_subscriptions[component]
97
+ if subs
98
+ message.attributes['sS'].each { |arg| remove_status_subscription(subs, arg) }
99
+ @status_subscriptions.delete(component) if subs.empty?
100
+ end
101
+ acknowledge message
102
+ end
103
+
104
+ def fetch_last_sent_status(component, code, name)
105
+ @last_status_sent&.dig component, code, name
106
+ end
107
+
108
+ def store_last_sent_status(message)
109
+ component_id = message.attribute('cId')
110
+ @last_status_sent ||= {}
111
+ @last_status_sent[component_id] ||= {}
112
+ message.attribute('sS').each do |item|
113
+ sci = item['sCI']
114
+ n = item['n']
115
+ s = item['s']
116
+ @last_status_sent[component_id][sci] ||= {}
117
+ @last_status_sent[component_id][sci][n] = s
118
+ end
119
+ end
120
+
121
+ def check_on_change_update(subscription, component, code, name)
122
+ return [nil, false] unless subscription[:interval].zero?
123
+
124
+ current = nil
125
+ if component
126
+ current, quality = *(component.get_status code, name)
127
+ current = rsmpify_value(current, quality)
128
+ end
129
+ last_sent = fetch_last_sent_status component.c_id, code, name
130
+ [current, current != last_sent]
131
+ end
132
+
133
+ def interval_update_due?(subscription, now)
134
+ return true if subscription[:last_sent_at].nil?
135
+
136
+ (now - subscription[:last_sent_at]) >= subscription[:interval]
137
+ end
138
+
139
+ def check_status_subscription(subscription, component, code, name, now)
140
+ current, should_send = check_on_change_update(subscription, component, code, name)
141
+ should_send ||= interval_update_due?(subscription, now)
142
+ return [nil, false] unless should_send
143
+
144
+ subscription[:last_sent_at] = now
145
+ [current, true]
146
+ end
147
+
148
+ def status_update_timer(now)
149
+ update_list = {}
150
+
151
+ @status_subscriptions.each_pair do |component_id, by_code|
152
+ component = @site.find_component component_id
153
+ by_code.each_pair do |code, by_name|
154
+ by_name.each_pair do |name, subscription|
155
+ current, should_send = check_status_subscription(subscription, component, code, name, now)
156
+ next unless should_send
157
+
158
+ update_list[component_id] ||= {}
159
+ update_list[component_id][code] ||= {}
160
+ update_list[component_id][code][name] = current
161
+ end
162
+ end
163
+ end
164
+ send_status_updates update_list
165
+ end
166
+
167
+ def build_status_list(component, by_code)
168
+ ss = []
169
+ by_code.each_pair do |code, names|
170
+ names.map do |status_name, value|
171
+ if value
172
+ quality = 'recent'
173
+ else
174
+ value, quality = component.get_status code, status_name
175
+ end
176
+ ss << { 'sCI' => code,
177
+ 'n' => status_name,
178
+ 's' => rsmpify_value(value, quality),
179
+ 'q' => quality }
180
+ end
181
+ end
182
+ ss
183
+ end
184
+
185
+ def send_status_updates(update_list)
186
+ now = clock.to_s
187
+ update_list.each_pair do |component_id, by_code|
188
+ component = @site.find_component component_id
189
+ ss = build_status_list(component, by_code)
190
+ update = StatusUpdate.new({
191
+ 'cId' => component_id,
192
+ 'sTs' => now,
193
+ 'sS' => ss
194
+ })
195
+ apply_nts_message_attributes update
196
+ send_message update
197
+ store_last_sent_status update
198
+ component.status_updates_sent
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,178 @@
1
+ # Handles a site connection to a remote supervisor
2
+
3
+ require 'digest'
4
+
5
+ module RSMP
6
+ class SupervisorProxy < Proxy
7
+ include Modules::Status
8
+ include Modules::Commands
9
+ include Modules::Alarms
10
+ include Modules::AggregatedStatus
11
+
12
+ attr_reader :supervisor_id, :site
13
+
14
+ def initialize(options)
15
+ super(options.merge(node: options[:site]))
16
+ @site = options[:site]
17
+ @site_settings = @site.site_settings.clone
18
+ @ip = options[:ip]
19
+ @port = options[:port]
20
+ @status_subscriptions = {}
21
+ @sxl = @site_settings['sxl']
22
+ @synthetic_id = Supervisor.build_id_from_ip_port @ip, @port
23
+ end
24
+
25
+ # handle communication
26
+ # if disconnected, then try to reconnect
27
+ def run
28
+ loop do
29
+ connect
30
+ start_reader
31
+ start_handshake
32
+ wait_for_reader # run until disconnected
33
+ break unless reconnect_delay?
34
+ rescue Restart
35
+ @logger.mute @ip, @port
36
+ raise
37
+ rescue RSMP::ConnectionError => e
38
+ log e, level: :error
39
+ break unless reconnect_delay?
40
+ rescue StandardError => e
41
+ distribute_error e, level: :internal
42
+ break unless reconnect_delay?
43
+ ensure
44
+ close
45
+ stop_subtasks
46
+ end
47
+ end
48
+
49
+ def start_handshake
50
+ send_version @site_settings['site_id'], core_versions
51
+ end
52
+
53
+ # connect to the supervisor and initiate handshake supervisor
54
+ def connect
55
+ log "Connecting to supervisor at #{@ip}:#{@port}", level: :info
56
+ self.state = :connecting
57
+ connect_tcp
58
+ @logger.unmute @ip, @port
59
+ log "Connected to supervisor at #{@ip}:#{@port}", level: :info
60
+ rescue SystemCallError => e
61
+ raise ConnectionError, "Could not connect to supervisor at #{@ip}:#{@port}: Errno #{e.errno} #{e}"
62
+ rescue StandardError => e
63
+ raise ConnectionError, "Error while connecting to supervisor at #{@ip}:#{@port}: #{e}"
64
+ end
65
+
66
+ def stop_task
67
+ super
68
+ @last_status_sent = nil
69
+ end
70
+
71
+ def connect_tcp
72
+ @endpoint = IO::Endpoint.tcp(@ip, @port)
73
+
74
+ # this timeout is a workaround for connect hanging on windows if the other side is not present yet
75
+ timeout = @site_settings.dig('timeouts', 'connect') || 1.1
76
+ task.with_timeout timeout do
77
+ @socket = @endpoint.connect
78
+ end
79
+ delay = @site_settings.dig('intervals', 'after_connect')
80
+ task.sleep delay if delay
81
+
82
+ @stream = IO::Stream::Buffered.new(@socket)
83
+ @protocol = RSMP::Protocol.new(@stream) # rsmp messages are json terminated with a form-feed
84
+ self.state = :connected
85
+ rescue Errno::ECONNREFUSED => e # rescue to avoid log output
86
+ log 'Connection refused', level: :warning
87
+ raise e
88
+ end
89
+
90
+ def handshake_complete
91
+ sanitized_sxl_version = RSMP::Schema.sanitize_version(sxl_version)
92
+ log "Connection to supervisor established, using core #{@core_version}, #{sxl} #{sanitized_sxl_version}",
93
+ level: :info
94
+ self.state = :ready
95
+ start_watchdog
96
+ if @site_settings['send_after_connect']
97
+ send_all_aggregated_status
98
+ send_active_alarms
99
+ end
100
+ super
101
+ end
102
+
103
+ def process_message(message)
104
+ case message
105
+ when StatusResponse, StatusUpdate, AggregatedStatus, AlarmIssue
106
+ will_not_handle message
107
+ when AggregatedStatusRequest
108
+ process_aggregated_status_request message
109
+ when CommandRequest
110
+ process_command_request message
111
+ when CommandResponse
112
+ process_command_response message
113
+ when StatusRequest
114
+ process_status_request message
115
+ when StatusSubscribe
116
+ process_status_subcribe message
117
+ when StatusUnsubscribe
118
+ process_status_unsubcribe message
119
+ when Alarm, AlarmAcknowledged, AlarmSuspend, AlarmResume, AlarmRequest
120
+ process_alarm message
121
+ else
122
+ super
123
+ end
124
+ rescue UnknownComponent, UnknownCommand, UnknownStatus,
125
+ MessageRejected, MissingAttribute => e
126
+ dont_acknowledge message, '', e.to_s
127
+ end
128
+
129
+ def acknowledged_first_ingoing(message)
130
+ case message.type
131
+ when 'Watchdog'
132
+ handshake_complete
133
+ end
134
+ end
135
+
136
+ def reconnect_delay?
137
+ return false if @site_settings['intervals']['reconnect'] == :no
138
+
139
+ interval = @site_settings['intervals']['reconnect']
140
+ log "Will try to reconnect again every #{interval} seconds...", level: :info
141
+ @logger.mute @ip, @port
142
+ @task.sleep interval
143
+ true
144
+ end
145
+
146
+ def version_accepted(message)
147
+ log "Received Version message, using RSMP #{@core_version}", message: message, level: :log
148
+ start_timer
149
+ acknowledge message
150
+ @version_determined = true
151
+ send_watchdog
152
+ end
153
+
154
+ def timer(now)
155
+ super
156
+ status_update_timer now if ready?
157
+ end
158
+
159
+ def sxl_version
160
+ @site_settings['sxl_version'].to_s
161
+ end
162
+
163
+ def process_version(message)
164
+ return extraneous_version message if @version_determined
165
+
166
+ check_core_version message
167
+ check_sxl_version message
168
+ @site_id = Supervisor.build_id_from_ip_port @ip, @port
169
+ version_accepted message
170
+ end
171
+
172
+ def check_sxl_version(message); end
173
+
174
+ def main
175
+ @site.main
176
+ end
177
+ end
178
+ end
@@ -3,22 +3,22 @@ module RSMP
3
3
  class DetectorLogic < Component
4
4
  attr_reader :forced, :value
5
5
 
6
- def initialize node:, id:
7
- super node: node, id: id, grouped: false
6
+ def initialize(node:, id:)
7
+ super(node: node, id: id, grouped: false)
8
8
  @forced = 0
9
9
  @value = 0
10
10
  end
11
11
 
12
- def get_status code, name=nil, options={}
12
+ def get_status(code, name = nil, _options = {})
13
13
  case code
14
14
  when 'S0201', 'S0202', 'S0203', 'S0204'
15
- return send("handle_#{code.downcase}", code, name)
15
+ send("handle_#{code.downcase}", code, name)
16
16
  else
17
- raise InvalidMessage.new "unknown status code #{code}"
17
+ raise InvalidMessage, "unknown status code #{code}"
18
18
  end
19
19
  end
20
20
 
21
- def handle_s0201 status_code, status_name=nil, options={}
21
+ def handle_s0201(_status_code, status_name = nil, _options = {})
22
22
  case status_name
23
23
  when 'starttime'
24
24
  TrafficControllerSite.make_status @node.clock.to_s
@@ -27,7 +27,7 @@ module RSMP
27
27
  end
28
28
  end
29
29
 
30
- def handle_s0202 status_code, status_name=nil, options={}
30
+ def handle_s0202(_status_code, status_name = nil, _options = {})
31
31
  case status_name
32
32
  when 'starttime'
33
33
  TrafficControllerSite.make_status @node.clock.to_s
@@ -36,7 +36,7 @@ module RSMP
36
36
  end
37
37
  end
38
38
 
39
- def handle_s0203 status_code, status_name=nil, options={}
39
+ def handle_s0203(_status_code, status_name = nil, _options = {})
40
40
  case status_name
41
41
  when 'starttime'
42
42
  TrafficControllerSite.make_status @node.clock.to_s
@@ -45,57 +45,41 @@ module RSMP
45
45
  end
46
46
  end
47
47
 
48
- def handle_s0204 status_code, status_name=nil, options={}
48
+ def handle_s0204(_status_code, status_name = nil, _options = {})
49
49
  case status_name
50
50
  when 'starttime'
51
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'
52
+ when 'P', 'PS', 'L', 'LS', 'B', 'SP', 'MC', 'C', 'F'
69
53
  TrafficControllerSite.make_status 0
70
54
  end
71
55
  end
72
56
 
73
- def handle_command command_code, arg, options={}
57
+ def handle_command(command_code, arg, _options = {})
74
58
  case command_code
75
59
  when 'M0008'
76
60
  handle_m0008 arg
77
61
  else
78
- raise UnknownCommand.new "Unknown command #{command_code}"
62
+ raise UnknownCommand, "Unknown command #{command_code}"
79
63
  end
80
64
  end
81
65
 
82
- def handle_m0008 arg, options={}
66
+ def handle_m0008(arg, _options = {})
83
67
  @node.verify_security_code 2, arg['securityCode']
84
- status = arg['status']=='True'
85
- mode = arg['mode']=='True'
68
+ status = arg['status'] == 'True'
69
+ mode = arg['mode'] == 'True'
86
70
  force_detector_logic status, mode
87
71
  arg
88
72
  end
89
73
 
90
- def force_detector_logic forced, value
74
+ def force_detector_logic(forced, value)
91
75
  @forced = forced
92
76
  @value = value
93
77
  if @forced
94
78
  log "Forcing to #{value}", level: :info
95
79
  else
96
- log "Releasing", level: :info
80
+ log 'Releasing', level: :info
97
81
  end
98
82
  end
99
83
  end
100
84
  end
101
- end
85
+ end