rsmp 0.43.2 → 0.45.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 +11 -11
- data/README.md +19 -3
- data/Rakefile +2 -2
- data/config/supervisor.yaml +2 -1
- data/config/tlc.yaml +2 -2
- data/lib/rsmp/cli.rb +29 -5
- data/lib/rsmp/component/component.rb +0 -4
- data/lib/rsmp/component/component_base.rb +15 -2
- data/lib/rsmp/component/component_proxy.rb +1 -1
- data/lib/rsmp/component/components.rb +22 -1
- data/lib/rsmp/convert/export/json_schema/outputs.rb +1 -0
- data/lib/rsmp/convert/export/json_schema/values.rb +6 -4
- data/lib/rsmp/convert/export/json_schema.rb +7 -3
- data/lib/rsmp/helpers/deep_merge.rb +2 -2
- data/lib/rsmp/message.rb +32 -0
- data/lib/rsmp/node/site/site.rb +34 -10
- data/lib/rsmp/node/supervisor/modules/configuration.rb +32 -5
- data/lib/rsmp/node/supervisor/modules/connection.rb +0 -2
- data/lib/rsmp/node/supervisor/supervisor.rb +0 -7
- data/lib/rsmp/options/options.rb +55 -6
- data/lib/rsmp/options/schemas/site.json +6 -3
- data/lib/rsmp/options/schemas/supervisor.json +5 -2
- data/lib/rsmp/options/schemas/supervisor_site.json +5 -2
- data/lib/rsmp/options/site_options.rb +3 -2
- data/lib/rsmp/options/supervisor_options.rb +3 -1
- data/lib/rsmp/proxy/modules/acknowledgements.rb +2 -0
- data/lib/rsmp/proxy/modules/receive.rb +5 -2
- data/lib/rsmp/proxy/modules/state.rb +1 -0
- data/lib/rsmp/proxy/modules/versions.rb +90 -15
- data/lib/rsmp/proxy/proxy.rb +52 -3
- data/lib/rsmp/proxy/site/modules/status.rb +5 -3
- data/lib/rsmp/proxy/site/site_proxy.rb +68 -35
- data/lib/rsmp/proxy/site/sxl_selection.rb +54 -0
- data/lib/rsmp/proxy/supervisor/supervisor_proxy.rb +54 -18
- data/lib/rsmp/schema/message_resolution.rb +104 -0
- data/lib/rsmp/schema.rb +104 -22
- data/lib/rsmp/schema_error.rb +7 -1
- data/lib/rsmp/sxl/interface.rb +48 -0
- data/lib/rsmp/sxl/registry.rb +55 -0
- data/lib/rsmp/sxl/site_interface.rb +10 -0
- data/lib/rsmp/sxl/supervisor_interface.rb +21 -0
- data/lib/rsmp/tlc/detector_logic.rb +2 -2
- data/lib/rsmp/tlc/signal_group.rb +2 -2
- data/lib/rsmp/tlc/site_interface.rb +10 -0
- data/lib/rsmp/tlc/{traffic_controller_proxy.rb → supervisor_interface.rb} +19 -34
- data/lib/rsmp/tlc/traffic_controller.rb +10 -2
- data/lib/rsmp/tlc/traffic_controller_site.rb +4 -2
- data/lib/rsmp/tlc.rb +10 -0
- data/lib/rsmp/version.rb +1 -1
- data/lib/rsmp.rb +8 -1
- data/rsmp.gemspec +5 -5
- data/schemas/core/3.3.0/aggregated_status.json +25 -0
- data/schemas/core/3.3.0/aggregated_status_request.json +9 -0
- data/schemas/core/3.3.0/alarm.json +71 -0
- data/schemas/core/3.3.0/alarm_acknowledge.json +11 -0
- data/schemas/core/3.3.0/alarm_issue.json +44 -0
- data/schemas/core/3.3.0/alarm_request.json +3 -0
- data/schemas/core/3.3.0/alarm_suspend_resume.json +3 -0
- data/schemas/core/3.3.0/alarm_suspended_resumed.json +44 -0
- data/schemas/core/3.3.0/command_request.json +24 -0
- data/schemas/core/3.3.0/command_response.json +35 -0
- data/schemas/core/3.3.0/component_list.json +24 -0
- data/schemas/core/3.3.0/core.json +40 -0
- data/schemas/core/3.3.0/definitions.json +133 -0
- data/schemas/core/3.3.0/message_ack.json +11 -0
- data/schemas/core/3.3.0/message_not_ack.json +15 -0
- data/schemas/core/3.3.0/rsmp.json +142 -0
- data/schemas/core/3.3.0/status.json +21 -0
- data/schemas/core/3.3.0/status_request.json +5 -0
- data/schemas/core/3.3.0/status_response.json +41 -0
- data/schemas/core/3.3.0/status_subscribe.json +31 -0
- data/schemas/core/3.3.0/status_unsubscribe.json +5 -0
- data/schemas/core/3.3.0/status_update.json +41 -0
- data/schemas/core/3.3.0/version.json +144 -0
- data/schemas/core/3.3.0/watchdog.json +9 -0
- data/schemas/tlc/1.3.0/alarms/A0001.json +4 -0
- data/schemas/tlc/1.3.0/alarms/A0002.json +4 -0
- data/schemas/tlc/1.3.0/alarms/A0003.json +4 -0
- data/schemas/tlc/1.3.0/alarms/A0004.json +4 -0
- data/schemas/tlc/1.3.0/alarms/A0005.json +4 -0
- data/schemas/tlc/1.3.0/alarms/A0006.json +4 -0
- data/schemas/tlc/1.3.0/alarms/A0007.json +34 -0
- data/schemas/tlc/1.3.0/alarms/A0008.json +30 -0
- data/schemas/tlc/1.3.0/alarms/A0009.json +4 -0
- data/schemas/tlc/1.3.0/alarms/A0010.json +4 -0
- data/schemas/tlc/1.3.0/alarms/A0101.json +4 -0
- data/schemas/tlc/1.3.0/alarms/A0201.json +35 -0
- data/schemas/tlc/1.3.0/alarms/A0202.json +35 -0
- data/schemas/tlc/1.3.0/alarms/A0301.json +92 -0
- data/schemas/tlc/1.3.0/alarms/A0302.json +115 -0
- data/schemas/tlc/1.3.0/alarms/A0303.json +92 -0
- data/schemas/tlc/1.3.0/alarms/A0304.json +115 -0
- data/schemas/tlc/1.3.0/alarms/alarms.json +287 -0
- data/schemas/tlc/1.3.0/commands/M0001.json +92 -0
- data/schemas/tlc/1.3.0/commands/M0002.json +69 -0
- data/schemas/tlc/1.3.0/commands/M0003.json +69 -0
- data/schemas/tlc/1.3.0/commands/M0004.json +51 -0
- data/schemas/tlc/1.3.0/commands/M0005.json +69 -0
- data/schemas/tlc/1.3.0/commands/M0006.json +69 -0
- data/schemas/tlc/1.3.0/commands/M0007.json +51 -0
- data/schemas/tlc/1.3.0/commands/M0008.json +87 -0
- data/schemas/tlc/1.3.0/commands/M0010.json +51 -0
- data/schemas/tlc/1.3.0/commands/M0011.json +51 -0
- data/schemas/tlc/1.3.0/commands/M0012.json +51 -0
- data/schemas/tlc/1.3.0/commands/M0013.json +51 -0
- data/schemas/tlc/1.3.0/commands/M0014.json +69 -0
- data/schemas/tlc/1.3.0/commands/M0015.json +69 -0
- data/schemas/tlc/1.3.0/commands/M0016.json +51 -0
- data/schemas/tlc/1.3.0/commands/M0017.json +51 -0
- data/schemas/tlc/1.3.0/commands/M0018.json +69 -0
- data/schemas/tlc/1.3.0/commands/M0019.json +87 -0
- data/schemas/tlc/1.3.0/commands/M0020.json +87 -0
- data/schemas/tlc/1.3.0/commands/M0021.json +51 -0
- data/schemas/tlc/1.3.0/commands/M0022.json +249 -0
- data/schemas/tlc/1.3.0/commands/M0023.json +51 -0
- data/schemas/tlc/1.3.0/commands/M0024.json +33 -0
- data/schemas/tlc/1.3.0/commands/M0103.json +72 -0
- data/schemas/tlc/1.3.0/commands/M0104.json +141 -0
- data/schemas/tlc/1.3.0/commands/command_requests.json +8 -0
- data/schemas/tlc/1.3.0/commands/command_responses.json +8 -0
- data/schemas/tlc/1.3.0/commands/commands.json +415 -0
- data/schemas/tlc/1.3.0/defs/definitions.json +72 -0
- data/schemas/tlc/1.3.0/defs/guards.json +24 -0
- data/schemas/tlc/1.3.0/rsmp.json +74 -0
- data/schemas/tlc/1.3.0/statuses/S0001.json +109 -0
- data/schemas/tlc/1.3.0/statuses/S0002.json +36 -0
- data/schemas/tlc/1.3.0/statuses/S0003.json +36 -0
- data/schemas/tlc/1.3.0/statuses/S0004.json +36 -0
- data/schemas/tlc/1.3.0/statuses/S0005.json +72 -0
- data/schemas/tlc/1.3.0/statuses/S0006.json +54 -0
- data/schemas/tlc/1.3.0/statuses/S0007.json +73 -0
- data/schemas/tlc/1.3.0/statuses/S0008.json +73 -0
- data/schemas/tlc/1.3.0/statuses/S0009.json +73 -0
- data/schemas/tlc/1.3.0/statuses/S0010.json +73 -0
- data/schemas/tlc/1.3.0/statuses/S0011.json +73 -0
- data/schemas/tlc/1.3.0/statuses/S0012.json +73 -0
- data/schemas/tlc/1.3.0/statuses/S0013.json +54 -0
- data/schemas/tlc/1.3.0/statuses/S0014.json +55 -0
- data/schemas/tlc/1.3.0/statuses/S0015.json +55 -0
- data/schemas/tlc/1.3.0/statuses/S0016.json +36 -0
- data/schemas/tlc/1.3.0/statuses/S0017.json +36 -0
- data/schemas/tlc/1.3.0/statuses/S0018.json +61 -0
- data/schemas/tlc/1.3.0/statuses/S0019.json +36 -0
- data/schemas/tlc/1.3.0/statuses/S0020.json +54 -0
- data/schemas/tlc/1.3.0/statuses/S0021.json +37 -0
- data/schemas/tlc/1.3.0/statuses/S0022.json +36 -0
- data/schemas/tlc/1.3.0/statuses/S0023.json +37 -0
- data/schemas/tlc/1.3.0/statuses/S0024.json +36 -0
- data/schemas/tlc/1.3.0/statuses/S0025.json +162 -0
- data/schemas/tlc/1.3.0/statuses/S0026.json +36 -0
- data/schemas/tlc/1.3.0/statuses/S0027.json +36 -0
- data/schemas/tlc/1.3.0/statuses/S0028.json +36 -0
- data/schemas/tlc/1.3.0/statuses/S0029.json +36 -0
- data/schemas/tlc/1.3.0/statuses/S0030.json +36 -0
- data/schemas/tlc/1.3.0/statuses/S0031.json +36 -0
- data/schemas/tlc/1.3.0/statuses/S0032.json +73 -0
- data/schemas/tlc/1.3.0/statuses/S0033.json +77 -0
- data/schemas/tlc/1.3.0/statuses/S0034.json +36 -0
- data/schemas/tlc/1.3.0/statuses/S0035.json +49 -0
- data/schemas/tlc/1.3.0/statuses/S0091.json +40 -0
- data/schemas/tlc/1.3.0/statuses/S0092.json +40 -0
- data/schemas/tlc/1.3.0/statuses/S0095.json +36 -0
- data/schemas/tlc/1.3.0/statuses/S0096.json +126 -0
- data/schemas/tlc/1.3.0/statuses/S0097.json +54 -0
- data/schemas/tlc/1.3.0/statuses/S0098.json +72 -0
- data/schemas/tlc/1.3.0/statuses/S0201.json +54 -0
- data/schemas/tlc/1.3.0/statuses/S0202.json +54 -0
- data/schemas/tlc/1.3.0/statuses/S0203.json +54 -0
- data/schemas/tlc/1.3.0/statuses/S0204.json +198 -0
- data/schemas/tlc/1.3.0/statuses/S0205.json +54 -0
- data/schemas/tlc/1.3.0/statuses/S0206.json +54 -0
- data/schemas/tlc/1.3.0/statuses/S0207.json +54 -0
- data/schemas/tlc/1.3.0/statuses/S0208.json +198 -0
- data/schemas/tlc/1.3.0/statuses/statuses.json +787 -0
- data/schemas/tlc/1.3.0/sxl.yaml +2296 -0
- metadata +144 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9c85b2875cd3f63dfb4d146d1a3d4718f666444d4773eb6a2b8feb21bd309030
|
|
4
|
+
data.tar.gz: f7492b775476f78362c8317bb76f4a76eefd8720afc8657c705bb23991e24fec
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4cf58cbf2d93df79e9accef572eb767dcac614499c8aec296369d9e63e57dffe0f387c28906d537bc60d1008dda823e58ab132f9c65c06d2e7e0fb069d3c687a
|
|
7
|
+
data.tar.gz: '096b1798a92696a5d1db4859d90cdee8b3fd9a3ac3c75028988ed4deb698c7f18b1d1d368f85173ae1c9093f45652c45ba9a800536dfa760dbd4eb7ce67427c5'
|
data/Gemfile.lock
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
rsmp (0.
|
|
5
|
-
async (~> 2.
|
|
4
|
+
rsmp (0.45.0)
|
|
5
|
+
async (~> 2.39)
|
|
6
6
|
colorize (~> 1.1)
|
|
7
|
-
io-endpoint (~> 0.
|
|
8
|
-
io-stream (~> 0.
|
|
7
|
+
io-endpoint (~> 0.17)
|
|
8
|
+
io-stream (~> 0.13)
|
|
9
9
|
json_schemer (~> 2.5)
|
|
10
|
-
logger (~> 1.
|
|
10
|
+
logger (~> 1.7)
|
|
11
11
|
ostruct (~> 0.6)
|
|
12
12
|
thor (~> 1.5)
|
|
13
13
|
|
|
@@ -31,7 +31,7 @@ GEM
|
|
|
31
31
|
bigdecimal (4.1.2)
|
|
32
32
|
builder (3.3.0)
|
|
33
33
|
colorize (1.1.0)
|
|
34
|
-
console (1.
|
|
34
|
+
console (1.36.0)
|
|
35
35
|
fiber-annotation
|
|
36
36
|
fiber-local (~> 1.1)
|
|
37
37
|
json
|
|
@@ -82,7 +82,7 @@ GEM
|
|
|
82
82
|
prism (>= 1.3.0)
|
|
83
83
|
rdoc (>= 4.0.0)
|
|
84
84
|
reline (>= 0.4.2)
|
|
85
|
-
json (2.19.
|
|
85
|
+
json (2.19.8)
|
|
86
86
|
json_schemer (2.5.0)
|
|
87
87
|
bigdecimal
|
|
88
88
|
hana (~> 1.3)
|
|
@@ -104,7 +104,7 @@ GEM
|
|
|
104
104
|
prettyprint
|
|
105
105
|
prettyprint (0.2.0)
|
|
106
106
|
prism (1.9.0)
|
|
107
|
-
psych (5.
|
|
107
|
+
psych (5.4.0)
|
|
108
108
|
date
|
|
109
109
|
stringio
|
|
110
110
|
racc (1.8.1)
|
|
@@ -121,7 +121,7 @@ GEM
|
|
|
121
121
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
122
122
|
rspec-support (~> 3.13.0)
|
|
123
123
|
rspec-support (3.13.7)
|
|
124
|
-
rubocop (1.
|
|
124
|
+
rubocop (1.87.0)
|
|
125
125
|
json (~> 2.3)
|
|
126
126
|
language_server-protocol (~> 3.17.0.2)
|
|
127
127
|
lint_roller (~> 1.1.0)
|
|
@@ -141,7 +141,7 @@ GEM
|
|
|
141
141
|
ruby-progressbar (1.13.0)
|
|
142
142
|
simpleidn (0.2.3)
|
|
143
143
|
stringio (3.2.0)
|
|
144
|
-
sus (0.
|
|
144
|
+
sus (0.37.0)
|
|
145
145
|
sus-fixtures-async (0.2.0)
|
|
146
146
|
async
|
|
147
147
|
sus (~> 0.10)
|
|
@@ -181,4 +181,4 @@ DEPENDENCIES
|
|
|
181
181
|
timecop (~> 0.9)
|
|
182
182
|
|
|
183
183
|
BUNDLED WITH
|
|
184
|
-
4.0.
|
|
184
|
+
4.0.13
|
data/README.md
CHANGED
|
@@ -4,7 +4,7 @@ This is a Ruby implementation of the RSMP protocol, including:
|
|
|
4
4
|
- Command-line tools for quickly running RSMP supervisors or sites and view messages exchanged
|
|
5
5
|
|
|
6
6
|
## Installation
|
|
7
|
-
You need a recent version of Ruby intalled.
|
|
7
|
+
You need a recent version of Ruby intalled. 4.0.5 or later is recommended.
|
|
8
8
|
|
|
9
9
|
Install required gems:
|
|
10
10
|
|
|
@@ -124,7 +124,24 @@ RN+SU0001 RN+SI0001 --> f8c7 Received Version message for sites [RN+SI
|
|
|
124
124
|
```
|
|
125
125
|
|
|
126
126
|
### JSON Schema validation
|
|
127
|
-
All messages sent and received
|
|
127
|
+
All messages sent and received are validated against the copied RSMP JSON Schemas maintained in
|
|
128
|
+
`rsmp_core`.
|
|
129
|
+
|
|
130
|
+
Core and SXL schemas are selected with a flat map:
|
|
131
|
+
|
|
132
|
+
```ruby
|
|
133
|
+
RSMP::Schema.validate(message, {
|
|
134
|
+
core: '3.3.0',
|
|
135
|
+
tlc: '1.3.0'
|
|
136
|
+
})
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Sites and supervisors configure one or more SXLs with `sxls`:
|
|
140
|
+
|
|
141
|
+
```yaml
|
|
142
|
+
sxls:
|
|
143
|
+
tlc: '1.3.0'
|
|
144
|
+
```
|
|
128
145
|
|
|
129
146
|
## Command-line tool
|
|
130
147
|
Tools for easily running RSMP supervisors and sites. The binary is called ```rsmp```.
|
|
@@ -198,4 +215,3 @@ Feature: Run site
|
|
|
198
215
|
28 steps (28 passed)
|
|
199
216
|
0m7.036s
|
|
200
217
|
```
|
|
201
|
-
|
data/Rakefile
CHANGED
|
@@ -4,8 +4,8 @@ task :test do
|
|
|
4
4
|
sh 'bundle exec sus'
|
|
5
5
|
end
|
|
6
6
|
|
|
7
|
-
CORE_VERSIONS = %w[3.1.2 3.1.3 3.1.4 3.1.5 3.2.0 3.2.1 3.2.2].freeze
|
|
8
|
-
TLC_VERSIONS = %w[1.0.7 1.0.8 1.0.9 1.0.10 1.0.13 1.0.14 1.0.15 1.1.0 1.2.0 1.2.1].freeze
|
|
7
|
+
CORE_VERSIONS = %w[3.1.2 3.1.3 3.1.4 3.1.5 3.2.0 3.2.1 3.2.2 3.3.0].freeze
|
|
8
|
+
TLC_VERSIONS = %w[1.0.7 1.0.8 1.0.9 1.0.10 1.0.13 1.0.14 1.0.15 1.1.0 1.2.0 1.2.1 1.3.0].freeze
|
|
9
9
|
|
|
10
10
|
# Update vendored schemas from source repos.
|
|
11
11
|
# Usage: rake schemas:update[/path/to/rsmp_core,/path/to/rsmp_sxl_traffic_lights]
|
data/config/supervisor.yaml
CHANGED
data/config/tlc.yaml
CHANGED
data/lib/rsmp/cli.rb
CHANGED
|
@@ -75,7 +75,7 @@ module RSMP
|
|
|
75
75
|
return [settings, log_settings] unless options[:config]
|
|
76
76
|
|
|
77
77
|
begin
|
|
78
|
-
options_object =
|
|
78
|
+
options_object = site_options_class.load_file(options[:config])
|
|
79
79
|
settings = options_object.to_h
|
|
80
80
|
log_settings = log_settings.deep_merge(options_object.log_settings)
|
|
81
81
|
rescue RSMP::ConfigurationError => e
|
|
@@ -89,6 +89,15 @@ module RSMP
|
|
|
89
89
|
|
|
90
90
|
private
|
|
91
91
|
|
|
92
|
+
def site_options_class
|
|
93
|
+
case site_type
|
|
94
|
+
when 'tlc'
|
|
95
|
+
RSMP::TLC::TrafficControllerSite::Options
|
|
96
|
+
else
|
|
97
|
+
RSMP::Site::Options
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
92
101
|
def apply_site_options(settings, log_settings)
|
|
93
102
|
apply_basic_site_options(settings)
|
|
94
103
|
parse_supervisors(settings) if options[:supervisors]
|
|
@@ -98,7 +107,19 @@ module RSMP
|
|
|
98
107
|
def apply_basic_site_options(settings)
|
|
99
108
|
settings['site_id'] = options[:id] if options[:id]
|
|
100
109
|
settings['core_version'] = options[:core] || ENV['CORE_VERSION'] if options[:core] || ENV['CORE_VERSION']
|
|
101
|
-
settings['
|
|
110
|
+
settings['sxls'] = parse_sxls(ENV['SXLS']) if ENV['SXLS']
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def parse_sxls(value)
|
|
114
|
+
value.split(',').each_with_object({}) do |item, memo|
|
|
115
|
+
parts = item.split(':')
|
|
116
|
+
unless parts.length == 2
|
|
117
|
+
raise RSMP::ConfigurationError, "Invalid SXLS item #{item.inspect}, expected name:version"
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
name, version = parts
|
|
121
|
+
memo[name] = version
|
|
122
|
+
end
|
|
102
123
|
end
|
|
103
124
|
|
|
104
125
|
def parse_supervisors(settings)
|
|
@@ -112,16 +133,19 @@ module RSMP
|
|
|
112
133
|
end
|
|
113
134
|
|
|
114
135
|
def determine_site_class(settings)
|
|
115
|
-
site_type
|
|
116
|
-
case site_type
|
|
136
|
+
case site_type(settings)
|
|
117
137
|
when 'tlc'
|
|
118
138
|
RSMP::TLC::TrafficControllerSite
|
|
119
139
|
else
|
|
120
|
-
puts "Error: Unknown site type #{site_type}"
|
|
140
|
+
puts "Error: Unknown site type #{site_type(settings)}"
|
|
121
141
|
exit
|
|
122
142
|
end
|
|
123
143
|
end
|
|
124
144
|
|
|
145
|
+
def site_type(settings = nil)
|
|
146
|
+
options[:type] || settings&.fetch('type', nil)
|
|
147
|
+
end
|
|
148
|
+
|
|
125
149
|
def run_site(site_class, settings, log_settings)
|
|
126
150
|
Async do |task|
|
|
127
151
|
task.annotate 'cli'
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
module RSMP
|
|
2
2
|
# RSMP component
|
|
3
3
|
class Component < ComponentBase
|
|
4
|
-
def initialize(node:, id:, ntsoid: nil, xnid: nil, grouped: false)
|
|
5
|
-
super
|
|
6
|
-
end
|
|
7
|
-
|
|
8
4
|
def handle_command(command_code, _arg)
|
|
9
5
|
raise UnknownCommand, "Command #{command_code} not implemented by #{self.class}"
|
|
10
6
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module RSMP
|
|
2
2
|
# RSMP component base class.
|
|
3
3
|
class ComponentBase
|
|
4
|
-
attr_reader :c_id, :ntsoid, :xnid, :node, :alarms, :statuses,
|
|
4
|
+
attr_reader :c_id, :component_type, :name, :ntsoid, :xnid, :node, :alarms, :statuses,
|
|
5
5
|
:aggregated_status, :aggregated_status_bools, :grouped
|
|
6
6
|
|
|
7
7
|
AGGREGATED_STATUS_KEYS = %i[local_control
|
|
@@ -13,13 +13,21 @@ module RSMP
|
|
|
13
13
|
rest
|
|
14
14
|
not_connected].freeze
|
|
15
15
|
|
|
16
|
-
def initialize(node:, id:,
|
|
16
|
+
def initialize(node:, id:, **attributes)
|
|
17
|
+
type = attributes[:type]
|
|
18
|
+
name = attributes[:name]
|
|
19
|
+
ntsoid = attributes[:ntsoid]
|
|
20
|
+
xnid = attributes[:xnid]
|
|
21
|
+
grouped = attributes.fetch(:grouped, false)
|
|
22
|
+
|
|
17
23
|
if grouped == false && (ntsoid || xnid)
|
|
18
24
|
raise RSMP::ConfigurationError,
|
|
19
25
|
'ntsoid and xnid are only allowed for grouped objects'
|
|
20
26
|
end
|
|
21
27
|
|
|
22
28
|
@c_id = id
|
|
29
|
+
@component_type = type
|
|
30
|
+
@name = name || id
|
|
23
31
|
@ntsoid = ntsoid
|
|
24
32
|
@xnid = xnid
|
|
25
33
|
@node = node
|
|
@@ -32,6 +40,11 @@ module RSMP
|
|
|
32
40
|
"#<#{self.class.name}:#{object_id}:#{object_id} c_id:#{@c_id}>"
|
|
33
41
|
end
|
|
34
42
|
|
|
43
|
+
def update_metadata(type: nil, name: nil)
|
|
44
|
+
@component_type = type if type
|
|
45
|
+
@name = name if name
|
|
46
|
+
end
|
|
47
|
+
|
|
35
48
|
def now
|
|
36
49
|
node.now
|
|
37
50
|
end
|
|
@@ -19,7 +19,12 @@ module RSMP
|
|
|
19
19
|
|
|
20
20
|
components_by_type.each_pair do |id, component_settings|
|
|
21
21
|
component_settings ||= {}
|
|
22
|
-
|
|
22
|
+
component = build_component(id: id, type: type, settings: component_settings)
|
|
23
|
+
component.update_metadata(
|
|
24
|
+
type: component_settings['type'] || type,
|
|
25
|
+
name: component_settings['name'] || id
|
|
26
|
+
)
|
|
27
|
+
@components[id] = component
|
|
23
28
|
@main = @components[id] if type == 'main'
|
|
24
29
|
end
|
|
25
30
|
end
|
|
@@ -36,6 +41,22 @@ module RSMP
|
|
|
36
41
|
@components[component.c_id] = component
|
|
37
42
|
end
|
|
38
43
|
|
|
44
|
+
def natural_sort_key(value)
|
|
45
|
+
value.to_s.split(/(\d+)/).map do |part|
|
|
46
|
+
part.match?(/\A\d+\z/) ? part.to_i : part
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def component_list
|
|
51
|
+
@components.values.sort_by { |component| natural_sort_key(component.c_id) }.map do |component|
|
|
52
|
+
{
|
|
53
|
+
'id' => component.c_id,
|
|
54
|
+
'type' => component.component_type || 'component',
|
|
55
|
+
'name' => component.name || component.c_id
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
39
60
|
def infer_component_type(component_id)
|
|
40
61
|
raise UnknownComponent, "Component #{component_id} mising and cannot infer type"
|
|
41
62
|
end
|
|
@@ -7,7 +7,7 @@ module RSMP
|
|
|
7
7
|
def self.build_value(item)
|
|
8
8
|
out = {}
|
|
9
9
|
out['description'] = item['description'] if item['description']
|
|
10
|
-
if item['type'] =~ /_list
|
|
10
|
+
if item['type'] =~ /_list(_as_string)?$/
|
|
11
11
|
handle_string_list item, out
|
|
12
12
|
else
|
|
13
13
|
handle_types item, out
|
|
@@ -59,11 +59,13 @@ module RSMP
|
|
|
59
59
|
# convert a yaml item with list: true to json schema
|
|
60
60
|
def self.handle_string_list(item, out)
|
|
61
61
|
case item['type']
|
|
62
|
-
when 'boolean_list'
|
|
62
|
+
when 'boolean_list', 'boolean_list_as_string'
|
|
63
63
|
out['$ref'] = '../defs/definitions.json#/boolean_list'
|
|
64
|
-
when 'integer_list'
|
|
64
|
+
when 'integer_list', 'integer_list_as_string'
|
|
65
65
|
out['$ref'] = '../defs/definitions.json#/integer_list'
|
|
66
|
-
when '
|
|
66
|
+
when 'number_list', 'number_list_as_string'
|
|
67
|
+
out['$ref'] = '../defs/definitions.json#/number_list'
|
|
68
|
+
when 'string_list', 'string_list_as_string'
|
|
67
69
|
out['$ref'] = '../defs/definitions.json#/string_list'
|
|
68
70
|
else
|
|
69
71
|
raise "Error: List of #{item['type']} is not supported: #{item.inspect}"
|
|
@@ -26,8 +26,11 @@ module RSMP
|
|
|
26
26
|
JSON.generate(item, JSON_OPTIONS)
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
#
|
|
30
|
-
|
|
29
|
+
# Path to definitions.json for the latest bundled core schema version
|
|
30
|
+
def self.definitions_source
|
|
31
|
+
version = RSMP::Schema.latest_core_version
|
|
32
|
+
File.expand_path("../../../../schemas/core/#{version}/definitions.json", __dir__)
|
|
33
|
+
end
|
|
31
34
|
|
|
32
35
|
# generate the json schema from a string containing yaml
|
|
33
36
|
def self.generate(sxl)
|
|
@@ -50,7 +53,8 @@ module RSMP
|
|
|
50
53
|
# Copy definitions.json so each version folder is self-contained
|
|
51
54
|
defs_dest = File.join(folder, 'defs', 'definitions.json')
|
|
52
55
|
FileUtils.mkdir_p File.dirname(defs_dest)
|
|
53
|
-
|
|
56
|
+
source = definitions_source
|
|
57
|
+
FileUtils.cp source, defs_dest if File.exist?(source)
|
|
54
58
|
end
|
|
55
59
|
end
|
|
56
60
|
end
|
|
@@ -3,8 +3,8 @@ class Hash
|
|
|
3
3
|
def deep_merge(other_hash)
|
|
4
4
|
return self unless other_hash
|
|
5
5
|
|
|
6
|
-
merge(other_hash) do |
|
|
7
|
-
if old.is_a?(Hash) && fresh.is_a?(Hash)
|
|
6
|
+
merge(other_hash) do |key, old, fresh|
|
|
7
|
+
if key != 'sxls' && old.is_a?(Hash) && fresh.is_a?(Hash)
|
|
8
8
|
old.deep_merge(fresh)
|
|
9
9
|
else
|
|
10
10
|
fresh
|
data/lib/rsmp/message.rb
CHANGED
|
@@ -30,6 +30,7 @@ module RSMP
|
|
|
30
30
|
'MessageAck' => MessageAck,
|
|
31
31
|
'MessageNotAck' => MessageNotAck,
|
|
32
32
|
'Version' => Version,
|
|
33
|
+
'ComponentList' => ComponentList,
|
|
33
34
|
'AggregatedStatus' => AggregatedStatus,
|
|
34
35
|
'AggregatedStatusRequest' => AggregatedStatusRequest,
|
|
35
36
|
'Watchdog' => Watchdog,
|
|
@@ -216,6 +217,37 @@ module RSMP
|
|
|
216
217
|
def versions
|
|
217
218
|
attribute('RSMP').map { |item| item['vers'] }
|
|
218
219
|
end
|
|
220
|
+
|
|
221
|
+
def step
|
|
222
|
+
@attributes['step']
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def request?
|
|
226
|
+
step == 'Request'
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def response?
|
|
230
|
+
step == 'Response'
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def sxls
|
|
234
|
+
(@attributes['SXLS'] || []).map do |item|
|
|
235
|
+
item.transform_keys(&:to_s)
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def site_ids
|
|
240
|
+
attribute('siteId').map { |item| item['sId'] }
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# ComponentList message, lists site components and their component types.
|
|
245
|
+
class ComponentList < Message
|
|
246
|
+
def initialize(attributes = {})
|
|
247
|
+
super({
|
|
248
|
+
'type' => 'ComponentList'
|
|
249
|
+
}.merge attributes)
|
|
250
|
+
end
|
|
219
251
|
end
|
|
220
252
|
|
|
221
253
|
# Unknown message type wrapper.
|
data/lib/rsmp/node/site/site.rb
CHANGED
|
@@ -19,8 +19,16 @@ module RSMP
|
|
|
19
19
|
build_proxies
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
+
def sxls
|
|
23
|
+
@site_settings['sxls']
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def primary_sxl
|
|
27
|
+
sxls.first
|
|
28
|
+
end
|
|
29
|
+
|
|
22
30
|
def sxl_version
|
|
23
|
-
|
|
31
|
+
primary_sxl && primary_sxl['version']
|
|
24
32
|
end
|
|
25
33
|
|
|
26
34
|
def site_id
|
|
@@ -30,18 +38,34 @@ module RSMP
|
|
|
30
38
|
def handle_site_settings(options = {})
|
|
31
39
|
options_class = self.class.options_class
|
|
32
40
|
settings = options[:site_settings] || {}
|
|
41
|
+
settings = denormalize_sxls(settings)
|
|
33
42
|
@site_options = options_class.new(settings)
|
|
34
43
|
@site_settings = @site_options.to_h
|
|
35
44
|
|
|
36
|
-
|
|
45
|
+
check_sxls
|
|
37
46
|
check_core_versions
|
|
38
47
|
setup_components @site_settings['components']
|
|
39
48
|
end
|
|
40
49
|
|
|
41
|
-
def
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
50
|
+
def denormalize_sxls(settings)
|
|
51
|
+
sxls = settings['sxls']
|
|
52
|
+
return settings unless sxls.is_a?(Array)
|
|
53
|
+
|
|
54
|
+
settings.merge(
|
|
55
|
+
'sxls' => sxls.to_h { |sxl| [sxl['name'], sxl['version']] }
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def check_sxls
|
|
60
|
+
raise RSMP::ConfigurationError, 'No SXLs specified' unless sxls
|
|
61
|
+
|
|
62
|
+
sxls.each do |sxl|
|
|
63
|
+
name = sxl['name']
|
|
64
|
+
version = sxl['version'].to_s
|
|
65
|
+
raise RSMP::ConfigurationError, 'SXL name cannot be core' if name.to_s == 'core'
|
|
66
|
+
|
|
67
|
+
RSMP::Schema.find_schema! name, version, lenient: true
|
|
68
|
+
end
|
|
45
69
|
end
|
|
46
70
|
|
|
47
71
|
def check_core_versions
|
|
@@ -60,7 +84,7 @@ module RSMP
|
|
|
60
84
|
|
|
61
85
|
def log_site_starting
|
|
62
86
|
log "Starting #{site_type_name} #{@site_settings['site_id']}", level: :info, timestamp: @clock.now
|
|
63
|
-
sxl = "Using #{
|
|
87
|
+
sxl = "Using SXLs #{sxls.map { |item| "#{item['name']} #{item['version']}" }.join(', ')}"
|
|
64
88
|
version = @site_settings['core_version']
|
|
65
89
|
core = if version
|
|
66
90
|
"accepting only core version #{version}"
|
|
@@ -113,7 +137,7 @@ module RSMP
|
|
|
113
137
|
|
|
114
138
|
def send_alarm(alarm)
|
|
115
139
|
@proxies.each do |proxy|
|
|
116
|
-
proxy.send_message alarm if proxy.ready?
|
|
140
|
+
proxy.send_message alarm if proxy.ready? && proxy.receive_alarms?
|
|
117
141
|
end
|
|
118
142
|
end
|
|
119
143
|
|
|
@@ -158,10 +182,10 @@ module RSMP
|
|
|
158
182
|
def build_component(id:, type:, settings:)
|
|
159
183
|
settings ||= {}
|
|
160
184
|
if type == 'main'
|
|
161
|
-
Component.new id: id, node: self, grouped: true,
|
|
185
|
+
Component.new id: id, node: self, type: type, name: settings['name'], grouped: true,
|
|
162
186
|
ntsoid: settings['ntsOId'], xnid: settings['xNId']
|
|
163
187
|
else
|
|
164
|
-
Component.new id: id, node: self, grouped: false
|
|
188
|
+
Component.new id: id, node: self, type: type, name: settings['name'], grouped: false
|
|
165
189
|
end
|
|
166
190
|
end
|
|
167
191
|
end
|
|
@@ -4,22 +4,49 @@ module RSMP
|
|
|
4
4
|
# Handles supervisor configuration and site settings
|
|
5
5
|
module Configuration
|
|
6
6
|
def handle_supervisor_settings(supervisor_settings)
|
|
7
|
+
supervisor_settings = denormalize_supervisor_sxls(supervisor_settings || {})
|
|
7
8
|
options = RSMP::Supervisor::Options.new(supervisor_settings || {})
|
|
8
9
|
@supervisor_settings = options.to_h
|
|
9
10
|
@core_version = @supervisor_settings.dig('default', 'core_version')
|
|
10
|
-
|
|
11
|
+
check_site_sxls
|
|
11
12
|
end
|
|
12
13
|
|
|
13
|
-
def
|
|
14
|
+
def denormalize_supervisor_sxls(settings)
|
|
15
|
+
settings = settings.merge('default' => denormalize_site_sxls(settings['default'])) if settings['default']
|
|
16
|
+
return settings unless settings['sites']
|
|
17
|
+
|
|
18
|
+
settings.merge(
|
|
19
|
+
'sites' => settings['sites'].transform_values { |site_settings| denormalize_site_sxls(site_settings) }
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def denormalize_site_sxls(settings)
|
|
24
|
+
sxls = settings['sxls']
|
|
25
|
+
return settings unless sxls.is_a?(Array)
|
|
26
|
+
|
|
27
|
+
settings.merge(
|
|
28
|
+
'sxls' => sxls.to_h { |sxl| [sxl['name'], sxl['version']] }
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def check_site_sxls
|
|
14
33
|
sites = @supervisor_settings['sites'].clone || {}
|
|
15
34
|
sites['default'] = @supervisor_settings['default']
|
|
16
35
|
sites.each do |site_id, settings|
|
|
17
36
|
raise RSMP::ConfigurationError, "Configuration for site '#{site_id}' is empty" unless settings
|
|
18
37
|
|
|
19
|
-
|
|
20
|
-
raise RSMP::ConfigurationError, "Configuration error for site '#{site_id}': No
|
|
38
|
+
sxls = settings['sxls']
|
|
39
|
+
raise RSMP::ConfigurationError, "Configuration error for site '#{site_id}': No SXLs specified" unless sxls
|
|
40
|
+
|
|
41
|
+
sxls.each do |sxl|
|
|
42
|
+
name = sxl['name']
|
|
43
|
+
if name.to_s == 'core'
|
|
44
|
+
raise RSMP::ConfigurationError,
|
|
45
|
+
"Configuration error for site '#{site_id}': SXL name cannot be core"
|
|
46
|
+
end
|
|
21
47
|
|
|
22
|
-
|
|
48
|
+
RSMP::Schema.find_schema! name, sxl['version'], lenient: true
|
|
49
|
+
end
|
|
23
50
|
rescue RSMP::Schema::UnknownSchemaError => e
|
|
24
51
|
raise RSMP::ConfigurationError, "Configuration error for site '#{site_id}': #{e}"
|
|
25
52
|
end
|
|
@@ -128,8 +128,6 @@ module RSMP
|
|
|
128
128
|
stop if @supervisor_settings['one_shot']
|
|
129
129
|
end
|
|
130
130
|
|
|
131
|
-
# Proxy type is now derived from `site_settings['sxl']` in Supervisor#build_proxy.
|
|
132
|
-
|
|
133
131
|
def reject_connection(_socket, info)
|
|
134
132
|
log 'Site rejected', ip: info[:ip], level: :info
|
|
135
133
|
end
|
|
@@ -59,13 +59,6 @@ module RSMP
|
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
def build_proxy(settings)
|
|
62
|
-
# Determine proxy type from site settings (SXL). Fall back to supervisor
|
|
63
|
-
# default settings when site-specific settings are not present.
|
|
64
|
-
site_settings = settings[:site_settings] || @supervisor_settings['default']
|
|
65
|
-
sxl_type = site_settings && site_settings['sxl']
|
|
66
|
-
|
|
67
|
-
return RSMP::TLC::TrafficControllerProxy.new(settings) if sxl_type == 'tlc'
|
|
68
|
-
|
|
69
62
|
SiteProxy.new settings
|
|
70
63
|
end
|
|
71
64
|
|