rsmp 0.43.2 → 0.45.1
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/.github/workflows/rubocop.yaml +1 -1
- data/.github/workflows/sus.yaml +1 -1
- data/.gitignore +0 -1
- data/CHANGELOG.md +12 -1
- data/Gemfile +0 -2
- data/Gemfile.lock +10 -88
- data/README.md +30 -35
- data/Rakefile +2 -2
- data/config/supervisor.yaml +2 -1
- data/config/tlc.yaml +2 -2
- data/documentation/configuration.md +12 -11
- data/documentation/message_distribution.md +1 -2
- data/documentation/tasks.md +1 -2
- data/exe/rsmp +1 -2
- data/lib/rsmp/cli.rb +62 -8
- 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 +19 -0
- data/lib/rsmp/convert/export/json_schema/values.rb +7 -5
- data/lib/rsmp/convert/export/json_schema.rb +15 -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/core_sxl_resolution.rb +69 -0
- data/lib/rsmp/schema/message_resolution.rb +104 -0
- data/lib/rsmp/schema/validation.rb +57 -0
- data/lib/rsmp/schema.rb +87 -32
- 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.0.10/rsmp.json +2 -1
- data/schemas/tlc/1.0.10/sxl.yaml +1 -0
- data/schemas/tlc/1.0.10/sxl_index.json +356 -0
- data/schemas/tlc/1.0.13/rsmp.json +2 -1
- data/schemas/tlc/1.0.13/sxl.yaml +1 -0
- data/schemas/tlc/1.0.13/sxl_index.json +436 -0
- data/schemas/tlc/1.0.14/rsmp.json +2 -1
- data/schemas/tlc/1.0.14/sxl.yaml +1 -0
- data/schemas/tlc/1.0.14/sxl_index.json +468 -0
- data/schemas/tlc/1.0.15/rsmp.json +2 -1
- data/schemas/tlc/1.0.15/sxl.yaml +1 -0
- data/schemas/tlc/1.0.15/sxl_index.json +508 -0
- data/schemas/tlc/1.0.7/rsmp.json +2 -1
- data/schemas/tlc/1.0.7/sxl.yaml +1 -0
- data/schemas/tlc/1.0.7/sxl_index.json +356 -0
- data/schemas/tlc/1.0.8/rsmp.json +2 -1
- data/schemas/tlc/1.0.8/sxl.yaml +1 -0
- data/schemas/tlc/1.0.8/sxl_index.json +356 -0
- data/schemas/tlc/1.0.9/rsmp.json +2 -1
- data/schemas/tlc/1.0.9/sxl.yaml +1 -0
- data/schemas/tlc/1.0.9/sxl_index.json +356 -0
- data/schemas/tlc/1.1.0/rsmp.json +2 -1
- data/schemas/tlc/1.1.0/sxl.yaml +1 -0
- data/schemas/tlc/1.1.0/sxl_index.json +572 -0
- data/schemas/tlc/1.2.0/rsmp.json +2 -1
- data/schemas/tlc/1.2.0/sxl.yaml +1 -0
- data/schemas/tlc/1.2.0/sxl_index.json +571 -0
- data/schemas/tlc/1.2.1/rsmp.json +2 -1
- data/schemas/tlc/1.2.1/sxl.yaml +1 -0
- data/schemas/tlc/1.2.1/sxl_index.json +571 -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 +133 -0
- data/schemas/tlc/1.3.0/defs/guards.json +24 -0
- data/schemas/tlc/1.3.0/rsmp.json +75 -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 +37 -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 +2297 -0
- data/schemas/tlc/1.3.0/sxl_index.json +578 -0
- metadata +157 -15
- data/.github/copilot-instructions.md +0 -33
- data/.rspec +0 -1
- data/cucumber.yml +0 -1
|
@@ -15,6 +15,27 @@ module RSMP
|
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
+
def core_3_3?
|
|
19
|
+
core_version && version_meets_requirement?(core_version, '>=3.3.0')
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def configured_sxls
|
|
23
|
+
(@site_settings['sxls'] || []).map { |item| item.transform_keys(&:to_s) }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def primary_configured_sxl
|
|
27
|
+
configured_sxls.first
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def sxl_request_items
|
|
31
|
+
configured_sxls.map do |sxl|
|
|
32
|
+
item = { 'name' => sxl['name'], 'version' => sxl['version'].to_s }
|
|
33
|
+
prefix = RSMP::Schema.sxl_prefix(sxl['name'], sxl['version'], lenient: true)
|
|
34
|
+
item['prefix'] = prefix if prefix
|
|
35
|
+
item
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
18
39
|
def check_core_version(message)
|
|
19
40
|
versions = core_versions
|
|
20
41
|
# find versions that both we and the client support
|
|
@@ -36,33 +57,87 @@ module RSMP
|
|
|
36
57
|
end
|
|
37
58
|
|
|
38
59
|
def send_version(site_id, core_versions)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
60
|
+
send_version_message(site_id, core_versions, step: nil)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def send_version_request(site_id, core_versions)
|
|
64
|
+
send_version_message(site_id, core_versions, step: 'Request')
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def send_version_response(site_id, core_versions)
|
|
68
|
+
if core_3_3?
|
|
69
|
+
send_message Version.new({
|
|
70
|
+
'step' => 'Response',
|
|
71
|
+
'RSMP' => [{ 'vers' => core_version }],
|
|
72
|
+
'supervisorId' => site_id,
|
|
73
|
+
'SXLS' => version_response_sxls,
|
|
74
|
+
'receiveAlarms' => @site_settings['receive_alarms'] != false
|
|
75
|
+
}), validate: false
|
|
76
|
+
else
|
|
77
|
+
send_version_message(site_id, core_versions, step: nil)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def send_version_message(site_id, core_versions, step:)
|
|
82
|
+
attributes = version_message_attributes(site_id, core_versions)
|
|
83
|
+
attributes.merge!(version_request_attributes) if step == 'Request'
|
|
84
|
+
send_message Version.new(attributes), validate: false
|
|
85
|
+
end
|
|
47
86
|
|
|
48
|
-
|
|
87
|
+
def version_message_attributes(site_id, core_versions)
|
|
88
|
+
primary = primary_configured_sxl
|
|
89
|
+
attributes = {
|
|
90
|
+
'RSMP' => version_items(core_versions),
|
|
91
|
+
'siteId' => site_id_items(site_id)
|
|
92
|
+
}
|
|
93
|
+
attributes['SXL'] = primary['version'].to_s if primary
|
|
94
|
+
attributes
|
|
95
|
+
end
|
|
49
96
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
97
|
+
def version_items(core_versions)
|
|
98
|
+
normalized_core_versions(core_versions).map { |version| { 'vers' => version } }
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def normalized_core_versions(core_versions)
|
|
102
|
+
case core_versions
|
|
103
|
+
when 'latest'
|
|
104
|
+
[RSMP::Schema.latest_core_version]
|
|
105
|
+
when 'all'
|
|
106
|
+
RSMP::Schema.core_versions
|
|
107
|
+
else
|
|
108
|
+
[core_versions].flatten
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def site_id_items(site_id)
|
|
113
|
+
[site_id].flatten.map { |id| { 'sId' => id } }
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def version_request_attributes
|
|
117
|
+
{
|
|
118
|
+
'step' => 'Request',
|
|
119
|
+
'SXLS' => sxl_request_items
|
|
120
|
+
}
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def version_response_sxls
|
|
124
|
+
accepted_sxls + rejected_sxls
|
|
56
125
|
end
|
|
57
126
|
|
|
58
127
|
def version_acknowledged; end
|
|
59
128
|
|
|
129
|
+
def component_list_acknowledged; end
|
|
130
|
+
|
|
60
131
|
# Use Gem class to check version requirement
|
|
61
132
|
# Requirement must be a string like '1.1', '>=1.0.3' or '<2.1.4',
|
|
62
133
|
# or list of strings, like ['<=1.4','<1.5']
|
|
63
134
|
def self.version_meets_requirement?(version, requirement)
|
|
64
135
|
Gem::Requirement.new(requirement).satisfied_by?(Gem::Version.new(version))
|
|
65
136
|
end
|
|
137
|
+
|
|
138
|
+
def version_meets_requirement?(version, requirement)
|
|
139
|
+
RSMP::Proxy::Modules::Versions.version_meets_requirement?(version, requirement)
|
|
140
|
+
end
|
|
66
141
|
end
|
|
67
142
|
end
|
|
68
143
|
end
|
data/lib/rsmp/proxy/proxy.rb
CHANGED
|
@@ -17,7 +17,9 @@ module RSMP
|
|
|
17
17
|
include Modules::Versions
|
|
18
18
|
include Modules::Tasks
|
|
19
19
|
|
|
20
|
-
attr_reader :state, :archive, :connection_info, :
|
|
20
|
+
attr_reader :state, :archive, :connection_info, :sxls, :accepted_sxls, :rejected_sxls,
|
|
21
|
+
:collector, :ip, :port, :node, :core_version, :sxl_interfaces,
|
|
22
|
+
:site_settings
|
|
21
23
|
|
|
22
24
|
def initialize(options)
|
|
23
25
|
@node = options[:node]
|
|
@@ -136,6 +138,9 @@ module RSMP
|
|
|
136
138
|
@ingoing_acknowledged = {}
|
|
137
139
|
@outgoing_acknowledged = {}
|
|
138
140
|
@latest_watchdog_send_at = nil
|
|
141
|
+
@component_list_received = false
|
|
142
|
+
@outgoing_watchdog_acknowledged = false
|
|
143
|
+
@sxl_interfaces = {}
|
|
139
144
|
|
|
140
145
|
@acknowledgements = {}
|
|
141
146
|
@acknowledgement_condition = Async::Notification.new
|
|
@@ -154,7 +159,10 @@ module RSMP
|
|
|
154
159
|
@ip = options[:ip]
|
|
155
160
|
@port = options[:port]
|
|
156
161
|
@connection_info = options[:info]
|
|
157
|
-
@
|
|
162
|
+
@sxls = []
|
|
163
|
+
@accepted_sxls = []
|
|
164
|
+
@rejected_sxls = []
|
|
165
|
+
@receive_alarms = true
|
|
158
166
|
@site_settings = nil # can't pick until we know the site id
|
|
159
167
|
return unless options[:collect]
|
|
160
168
|
|
|
@@ -177,14 +185,55 @@ module RSMP
|
|
|
177
185
|
def schemas
|
|
178
186
|
schemas = { core: RSMP::Schema.latest_core_version } # use latest core
|
|
179
187
|
schemas[:core] = core_version if core_version
|
|
180
|
-
|
|
188
|
+
accepted_sxls.each do |sxl|
|
|
189
|
+
schemas[sxl['name'].to_sym] = RSMP::Schema.sanitize_version(sxl['version'].to_s)
|
|
190
|
+
end
|
|
181
191
|
schemas
|
|
182
192
|
end
|
|
183
193
|
|
|
194
|
+
def receive_alarms?
|
|
195
|
+
@receive_alarms != false
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def primary_sxl
|
|
199
|
+
accepted_sxls.first || sxls.first
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def sxl
|
|
203
|
+
primary_sxl && primary_sxl['name']
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def sxl_version
|
|
207
|
+
primary_sxl && primary_sxl['version']
|
|
208
|
+
end
|
|
209
|
+
|
|
184
210
|
def author
|
|
185
211
|
@node.site_id
|
|
186
212
|
end
|
|
187
213
|
|
|
214
|
+
def build_sxl_interfaces
|
|
215
|
+
@sxl_interfaces = accepted_sxls.to_h do |sxl|
|
|
216
|
+
[sxl['name'], RSMP::SXL::Registry.build_for(self, sxl)]
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def sxl_interface(name)
|
|
221
|
+
sxl_interfaces.fetch(name.to_s) do
|
|
222
|
+
raise RSMP::Schema::UnknownSchemaTypeError, "SXL #{name} is not accepted on this connection"
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def tlc
|
|
227
|
+
sxl_interface 'tlc'
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def sxl_interface_for(message)
|
|
231
|
+
resolved = RSMP::Schema.resolve_sxl(message.attributes, schemas: schemas)
|
|
232
|
+
return unless resolved
|
|
233
|
+
|
|
234
|
+
sxl_interface resolved.first
|
|
235
|
+
end
|
|
236
|
+
|
|
188
237
|
# Use Gem class to check version requirement
|
|
189
238
|
# Requirement must be a string like '1.1', '>=1.0.3' or '<2.1.4',
|
|
190
239
|
# or list of strings, like ['<=1.4','<1.5']
|
|
@@ -125,14 +125,13 @@ module RSMP
|
|
|
125
125
|
end
|
|
126
126
|
|
|
127
127
|
def unsubscribe_to_status(status_list, component: nil, validate: nil)
|
|
128
|
+
validate_ready 'unsubscribe to status'
|
|
128
129
|
component ||= main.c_id
|
|
129
130
|
|
|
130
131
|
status_list.each do |item|
|
|
131
132
|
remove_subscription_item(component, item['sCI'], item['n'])
|
|
132
133
|
end
|
|
133
134
|
|
|
134
|
-
return unless ready? # if the connection is don't we skip sending
|
|
135
|
-
|
|
136
135
|
message = RSMP::StatusUnsubscribe.new({
|
|
137
136
|
'cId' => component,
|
|
138
137
|
'sS' => status_list
|
|
@@ -145,7 +144,10 @@ module RSMP
|
|
|
145
144
|
# unsubscribes to all statuses (with all attributes) defined in the used SXL
|
|
146
145
|
def unsubscribe_from_all(component: nil)
|
|
147
146
|
component ||= main.c_id
|
|
148
|
-
catalogue =
|
|
147
|
+
catalogue = accepted_sxls.each_with_object({}) do |sxl, memo|
|
|
148
|
+
version = RSMP::Schema.sanitize_version(sxl['version'].to_s)
|
|
149
|
+
memo.merge! RSMP::Schema.status_catalogue(sxl['name'], version)
|
|
150
|
+
end
|
|
149
151
|
status_list = catalogue.flat_map do |status_code_id, names|
|
|
150
152
|
names.map { |name| { 'sCI' => status_code_id.to_s, 'n' => name.to_s } }
|
|
151
153
|
end
|
|
@@ -6,6 +6,7 @@ module RSMP
|
|
|
6
6
|
include Modules::AggregatedStatus
|
|
7
7
|
include Modules::Alarms
|
|
8
8
|
include Modules::Commands
|
|
9
|
+
include SiteSxlSelection
|
|
9
10
|
|
|
10
11
|
attr_reader :supervisor, :site_id
|
|
11
12
|
|
|
@@ -44,7 +45,8 @@ module RSMP
|
|
|
44
45
|
|
|
45
46
|
def handshake_complete
|
|
46
47
|
super
|
|
47
|
-
|
|
48
|
+
sxl_summary = accepted_sxls.map { |item| "#{item['name']} #{item['version']}" }.join(', ')
|
|
49
|
+
log "Connection to site #{@site_id} established, using core #{@core_version}, SXLs [#{sxl_summary}]",
|
|
48
50
|
level: :info
|
|
49
51
|
start_watchdog
|
|
50
52
|
end
|
|
@@ -55,16 +57,13 @@ module RSMP
|
|
|
55
57
|
case message
|
|
56
58
|
when StatusUnsubscribe, AggregatedStatusRequest
|
|
57
59
|
will_not_handle message
|
|
60
|
+
when ComponentList
|
|
61
|
+
process_component_list message
|
|
58
62
|
when AggregatedStatus
|
|
59
63
|
process_aggregated_status message
|
|
60
|
-
when AlarmIssue, AlarmSuspended, AlarmResumed, AlarmAcknowledged
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
process_command_response message
|
|
64
|
-
when StatusResponse
|
|
65
|
-
process_status_response message
|
|
66
|
-
when StatusUpdate
|
|
67
|
-
process_status_update message
|
|
64
|
+
when AlarmIssue, AlarmSuspended, AlarmResumed, AlarmAcknowledged,
|
|
65
|
+
CommandResponse, StatusResponse, StatusUpdate
|
|
66
|
+
handle_interface_message message
|
|
68
67
|
else
|
|
69
68
|
super
|
|
70
69
|
end
|
|
@@ -78,11 +77,32 @@ module RSMP
|
|
|
78
77
|
message.is_a?(CommandRequest) || message.is_a?(StatusRequest) || message.is_a?(StatusSubscribe)
|
|
79
78
|
end
|
|
80
79
|
|
|
80
|
+
def handle_interface_message(message)
|
|
81
|
+
interface = sxl_interface_for message
|
|
82
|
+
interface.validate_message! message
|
|
83
|
+
record_interface_message message
|
|
84
|
+
interface.process_message message
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def record_interface_message(message)
|
|
88
|
+
case message
|
|
89
|
+
when AlarmIssue, AlarmSuspended, AlarmResumed, AlarmAcknowledged
|
|
90
|
+
process_alarm message
|
|
91
|
+
when CommandResponse
|
|
92
|
+
process_command_response message
|
|
93
|
+
when StatusResponse
|
|
94
|
+
process_status_response message
|
|
95
|
+
when StatusUpdate
|
|
96
|
+
process_status_update message
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
81
100
|
def version_accepted(message)
|
|
82
101
|
log "Received Version message for site #{@site_id}", message: message, level: :log
|
|
83
102
|
start_timer
|
|
84
103
|
acknowledge message
|
|
85
|
-
|
|
104
|
+
response_id = core_3_3? ? (@supervisor.site_id || @site_id) : @site_id
|
|
105
|
+
send_version_response response_id, core_versions
|
|
86
106
|
@version_determined = true
|
|
87
107
|
end
|
|
88
108
|
|
|
@@ -96,7 +116,12 @@ module RSMP
|
|
|
96
116
|
def acknowledged_first_outgoing(message)
|
|
97
117
|
case message.type
|
|
98
118
|
when 'Watchdog'
|
|
99
|
-
|
|
119
|
+
if core_3_3?
|
|
120
|
+
@outgoing_watchdog_acknowledged = true
|
|
121
|
+
handshake_complete if @component_list_received
|
|
122
|
+
else
|
|
123
|
+
handshake_complete
|
|
124
|
+
end
|
|
100
125
|
end
|
|
101
126
|
end
|
|
102
127
|
|
|
@@ -106,6 +131,33 @@ module RSMP
|
|
|
106
131
|
|
|
107
132
|
def version_acknowledged; end
|
|
108
133
|
|
|
134
|
+
def process_component_list(message)
|
|
135
|
+
log "Received #{message.type}", message: message, level: :log
|
|
136
|
+
rebuild_components_from_list message.attributes['components']
|
|
137
|
+
build_sxl_interfaces
|
|
138
|
+
acknowledge message
|
|
139
|
+
@component_list_received = true
|
|
140
|
+
handshake_complete if @outgoing_watchdog_acknowledged
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def rebuild_components_from_list(items)
|
|
144
|
+
main_id = @site_settings.dig('components', 'main')&.keys&.first
|
|
145
|
+
@components = {}
|
|
146
|
+
@main = nil
|
|
147
|
+
items.each do |item|
|
|
148
|
+
grouped = item['id'] == main_id
|
|
149
|
+
component = ComponentProxy.new(
|
|
150
|
+
id: item['id'],
|
|
151
|
+
node: self,
|
|
152
|
+
type: item['type'],
|
|
153
|
+
name: item['name'],
|
|
154
|
+
grouped: grouped
|
|
155
|
+
)
|
|
156
|
+
@components[component.c_id] = component
|
|
157
|
+
@main = component if grouped
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
109
161
|
def site_ids_changed
|
|
110
162
|
@supervisor.site_ids_changed
|
|
111
163
|
end
|
|
@@ -114,27 +166,6 @@ module RSMP
|
|
|
114
166
|
@settings['intervals']['watchdog'] = interval
|
|
115
167
|
end
|
|
116
168
|
|
|
117
|
-
def check_sxl_version(message)
|
|
118
|
-
# check that we have a schema for specified sxl type and version
|
|
119
|
-
# note that the type comes from the site config, while the version
|
|
120
|
-
# comes from the Version message send by the site
|
|
121
|
-
type = @site_settings['sxl']
|
|
122
|
-
sanitized_version = RSMP::Schema.sanitize_version(message.attribute('SXL'))
|
|
123
|
-
RSMP::Schema.find_schema! type, sanitized_version
|
|
124
|
-
|
|
125
|
-
# store raw sxl version from site (may be 2-part like "1.2"), so we echo it back unchanged
|
|
126
|
-
# TODO should check agaist site settings
|
|
127
|
-
@site_sxl_version = message.attribute('SXL')
|
|
128
|
-
rescue RSMP::Schema::UnknownSchemaError => e
|
|
129
|
-
dont_acknowledge message, "Rejected #{message.type} message,", e.to_s
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
def sxl_version
|
|
133
|
-
# a supervisor does not maintain it's own sxl version
|
|
134
|
-
# instead we use what the site requests
|
|
135
|
-
@site_sxl_version
|
|
136
|
-
end
|
|
137
|
-
|
|
138
169
|
def process_version(message)
|
|
139
170
|
return extraneous_version message if @version_determined
|
|
140
171
|
|
|
@@ -173,7 +204,9 @@ module RSMP
|
|
|
173
204
|
def setup_site_settings
|
|
174
205
|
@site_settings = find_site_settings @site_id
|
|
175
206
|
if @site_settings
|
|
176
|
-
@
|
|
207
|
+
@sxls = configured_sxls
|
|
208
|
+
@accepted_sxls = @sxls.dup
|
|
209
|
+
build_sxl_interfaces
|
|
177
210
|
setup_components @site_settings['components']
|
|
178
211
|
else
|
|
179
212
|
dont_acknowledge message, 'Rejected', "No config found for site #{@site_id}"
|
|
@@ -188,10 +221,10 @@ module RSMP
|
|
|
188
221
|
def build_component(id:, type:, settings: {})
|
|
189
222
|
settings ||= {}
|
|
190
223
|
if type == 'main'
|
|
191
|
-
ComponentProxy.new id: id, node: self, grouped: true,
|
|
224
|
+
ComponentProxy.new id: id, node: self, type: type, name: settings['name'], grouped: true,
|
|
192
225
|
ntsoid: settings['ntsOId'], xnid: settings['xNId']
|
|
193
226
|
else
|
|
194
|
-
ComponentProxy.new id: id, node: self, grouped: false
|
|
227
|
+
ComponentProxy.new id: id, node: self, type: type, name: settings['name'], grouped: false
|
|
195
228
|
end
|
|
196
229
|
end
|
|
197
230
|
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module RSMP
|
|
2
|
+
# Selects the SXL versions accepted by a supervisor-side site proxy.
|
|
3
|
+
module SiteSxlSelection
|
|
4
|
+
def check_sxl_version(message)
|
|
5
|
+
if core_3_3?
|
|
6
|
+
select_sxls message
|
|
7
|
+
else
|
|
8
|
+
select_legacy_sxl message
|
|
9
|
+
end
|
|
10
|
+
rescue RSMP::Schema::UnknownSchemaError => e
|
|
11
|
+
dont_acknowledge message, "Rejected #{message.type} message,", e.to_s
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def select_legacy_sxl(message)
|
|
15
|
+
primary = configured_sxls.first
|
|
16
|
+
unless primary
|
|
17
|
+
reason = 'Legacy Version message received, but no SXL is configured'
|
|
18
|
+
dont_acknowledge message, "Rejected #{message.type} message,", reason
|
|
19
|
+
raise HandshakeError, reason
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
sanitized_version = RSMP::Schema.sanitize_version(message.attribute('SXL'))
|
|
23
|
+
RSMP::Schema.find_schema! primary['name'], sanitized_version
|
|
24
|
+
@accepted_sxls = [{ 'name' => primary['name'], 'version' => message.attribute('SXL') }]
|
|
25
|
+
@rejected_sxls = []
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def select_sxls(message)
|
|
29
|
+
selected_sxls = message.sxls.map { |requested| select_sxl(requested) }
|
|
30
|
+
@accepted_sxls, @rejected_sxls = selected_sxls.partition { |item| item['rejected'].nil? }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def select_sxl(requested)
|
|
34
|
+
configured = configured_sxls.find { |item| item['name'] == requested['name'] }
|
|
35
|
+
return rejected_sxl(requested, 1, 'SXL not supported') unless configured
|
|
36
|
+
|
|
37
|
+
if configured['version'].to_s == requested['version'].to_s
|
|
38
|
+
RSMP::Schema.find_schema! requested['name'], requested['version'], lenient: true
|
|
39
|
+
requested.slice('name', 'version', 'prefix')
|
|
40
|
+
else
|
|
41
|
+
rejected_sxl(requested, 2, "Supervisor only supports #{configured['version']}")
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def rejected_sxl(requested, code, reason)
|
|
46
|
+
{
|
|
47
|
+
'name' => requested['name'],
|
|
48
|
+
'version' => requested['version'],
|
|
49
|
+
'rejected' => code,
|
|
50
|
+
'reason' => reason
|
|
51
|
+
}.compact
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -17,7 +17,9 @@ module RSMP
|
|
|
17
17
|
@ip = options[:ip]
|
|
18
18
|
@port = options[:port]
|
|
19
19
|
@status_subscriptions = {}
|
|
20
|
-
@
|
|
20
|
+
@sxls = configured_sxls
|
|
21
|
+
@accepted_sxls = @sxls.dup
|
|
22
|
+
@rejected_sxls = []
|
|
21
23
|
@synthetic_id = Supervisor.build_id_from_ip_port @ip, @port
|
|
22
24
|
end
|
|
23
25
|
|
|
@@ -46,7 +48,7 @@ module RSMP
|
|
|
46
48
|
end
|
|
47
49
|
|
|
48
50
|
def start_handshake
|
|
49
|
-
|
|
51
|
+
send_version_request @site_settings['site_id'], core_versions
|
|
50
52
|
end
|
|
51
53
|
|
|
52
54
|
# connect to the supervisor and initiate handshake supervisor
|
|
@@ -87,14 +89,14 @@ module RSMP
|
|
|
87
89
|
end
|
|
88
90
|
|
|
89
91
|
def handshake_complete
|
|
90
|
-
|
|
91
|
-
log "Connection to supervisor established, using core #{@core_version},
|
|
92
|
+
sxl_summary = accepted_sxls.map { |item| "#{item['name']} #{item['version']}" }.join(', ')
|
|
93
|
+
log "Connection to supervisor established, using core #{@core_version}, SXLs [#{sxl_summary}]",
|
|
92
94
|
level: :info
|
|
93
95
|
self.state = :ready
|
|
94
96
|
start_watchdog
|
|
95
97
|
if @site_settings['send_after_connect']
|
|
96
98
|
send_all_aggregated_status
|
|
97
|
-
send_active_alarms
|
|
99
|
+
send_active_alarms if receive_alarms?
|
|
98
100
|
end
|
|
99
101
|
super
|
|
100
102
|
end
|
|
@@ -105,10 +107,29 @@ module RSMP
|
|
|
105
107
|
will_not_handle message
|
|
106
108
|
when AggregatedStatusRequest
|
|
107
109
|
process_aggregated_status_request message
|
|
108
|
-
when CommandRequest
|
|
109
|
-
process_command_request message
|
|
110
110
|
when CommandResponse
|
|
111
111
|
process_command_response message
|
|
112
|
+
when CommandRequest, StatusRequest, StatusSubscribe, StatusUnsubscribe,
|
|
113
|
+
Alarm, AlarmAcknowledged, AlarmSuspend, AlarmResume, AlarmRequest
|
|
114
|
+
handle_interface_request message
|
|
115
|
+
else
|
|
116
|
+
super
|
|
117
|
+
end
|
|
118
|
+
rescue UnknownComponent, UnknownCommand, UnknownStatus,
|
|
119
|
+
MessageRejected, MissingAttribute => e
|
|
120
|
+
dont_acknowledge message, '', e.to_s
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def handle_interface_request(message)
|
|
124
|
+
interface = sxl_interface_for message
|
|
125
|
+
interface.validate_message! message
|
|
126
|
+
interface.process_message message
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def process_sxl_request(message)
|
|
130
|
+
case message
|
|
131
|
+
when CommandRequest
|
|
132
|
+
process_command_request message
|
|
112
133
|
when StatusRequest
|
|
113
134
|
process_status_request message
|
|
114
135
|
when StatusSubscribe
|
|
@@ -117,18 +138,17 @@ module RSMP
|
|
|
117
138
|
process_status_unsubcribe message
|
|
118
139
|
when Alarm, AlarmAcknowledged, AlarmSuspend, AlarmResume, AlarmRequest
|
|
119
140
|
process_alarm message
|
|
120
|
-
else
|
|
121
|
-
super
|
|
122
141
|
end
|
|
123
|
-
rescue UnknownComponent, UnknownCommand, UnknownStatus,
|
|
124
|
-
MessageRejected, MissingAttribute => e
|
|
125
|
-
dont_acknowledge message, '', e.to_s
|
|
126
142
|
end
|
|
127
143
|
|
|
128
144
|
def acknowledged_first_ingoing(message)
|
|
129
145
|
case message.type
|
|
130
146
|
when 'Watchdog'
|
|
131
|
-
|
|
147
|
+
if core_3_3?
|
|
148
|
+
send_component_list
|
|
149
|
+
else
|
|
150
|
+
handshake_complete
|
|
151
|
+
end
|
|
132
152
|
end
|
|
133
153
|
end
|
|
134
154
|
|
|
@@ -155,10 +175,6 @@ module RSMP
|
|
|
155
175
|
status_update_timer now if ready?
|
|
156
176
|
end
|
|
157
177
|
|
|
158
|
-
def sxl_version
|
|
159
|
-
@site_settings['sxl_version'].to_s
|
|
160
|
-
end
|
|
161
|
-
|
|
162
178
|
def process_version(message)
|
|
163
179
|
return extraneous_version message if @version_determined
|
|
164
180
|
|
|
@@ -168,7 +184,27 @@ module RSMP
|
|
|
168
184
|
version_accepted message
|
|
169
185
|
end
|
|
170
186
|
|
|
171
|
-
def check_sxl_version(message)
|
|
187
|
+
def check_sxl_version(message)
|
|
188
|
+
if core_3_3?
|
|
189
|
+
@rejected_sxls, @accepted_sxls = message.sxls.partition { |item| item['rejected'] }
|
|
190
|
+
@receive_alarms = message.attributes.fetch('receiveAlarms', true)
|
|
191
|
+
else
|
|
192
|
+
primary = primary_configured_sxl
|
|
193
|
+
raise HandshakeError, 'Legacy Version response received, but no SXL is configured' unless primary
|
|
194
|
+
|
|
195
|
+
@accepted_sxls = [primary]
|
|
196
|
+
@rejected_sxls = []
|
|
197
|
+
end
|
|
198
|
+
build_sxl_interfaces
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def send_component_list
|
|
202
|
+
send_message ComponentList.new('components' => @site.component_list)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def component_list_acknowledged
|
|
206
|
+
handshake_complete
|
|
207
|
+
end
|
|
172
208
|
|
|
173
209
|
def main
|
|
174
210
|
@site.main
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
module RSMP
|
|
2
|
+
# Provides JSON Schema validation for RSMP messages across core and SXL versions.
|
|
3
|
+
module Schema
|
|
4
|
+
def self.clear_core_sxl_schemas(type = nil, version = nil)
|
|
5
|
+
@core_sxl_schemas ||= {}
|
|
6
|
+
return @core_sxl_schemas.clear unless type
|
|
7
|
+
|
|
8
|
+
type = type.to_sym
|
|
9
|
+
@core_sxl_schemas.delete_if do |(cached_type, cached_version, _core_version), _schema|
|
|
10
|
+
cached_type == type && (!version || cached_version == version.to_s)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.schema_core_version(schemas)
|
|
15
|
+
schemas[:core] || schemas['core']
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.validate_resolved_sxl(message, resolved, schemas, options)
|
|
19
|
+
type, version = resolved
|
|
20
|
+
schema = find_core_sxl_schema! type, version, schema_core_version(schemas), options
|
|
21
|
+
validate_using_schema(message, schema)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.find_core_sxl_schema!(type, version, core_version, options = {})
|
|
25
|
+
raise ArgumentError, 'core version missing' unless core_version
|
|
26
|
+
|
|
27
|
+
version = sanitize_version(version.to_s) if options[:lenient]
|
|
28
|
+
core_version = sanitize_version(core_version.to_s) if options[:lenient]
|
|
29
|
+
find_schema! type, version
|
|
30
|
+
find_schema! :core, core_version
|
|
31
|
+
|
|
32
|
+
key = [type.to_sym, version.to_s, core_version.to_s]
|
|
33
|
+
@core_sxl_schemas ||= {}
|
|
34
|
+
@core_sxl_schemas[key] ||= build_core_sxl_schema(type, version, core_version)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.build_core_sxl_schema(type, version, core_version)
|
|
38
|
+
schema_path = @schema_paths&.dig(type.to_sym, version.to_s)
|
|
39
|
+
raise UnknownSchemaVersionError, "Unknown schema version #{type} #{version}" unless schema_path
|
|
40
|
+
|
|
41
|
+
file_path = File.join(schema_path, 'rsmp.json')
|
|
42
|
+
JSONSchemer.schema(
|
|
43
|
+
Pathname.new(file_path),
|
|
44
|
+
ref_resolver: core_sxl_ref_resolver(core_version)
|
|
45
|
+
)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.core_sxl_ref_resolver(core_version)
|
|
49
|
+
proc do |uri|
|
|
50
|
+
if sxl_definitions_ref?(uri)
|
|
51
|
+
JSON.parse(File.read(core_definitions_path(core_version), encoding: 'UTF-8'))
|
|
52
|
+
else
|
|
53
|
+
JSONSchemer::FILE_URI_REF_RESOLVER.call(uri)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def self.sxl_definitions_ref?(uri)
|
|
59
|
+
uri.scheme == 'file' && uri.path.end_with?('/defs/definitions.json')
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def self.core_definitions_path(core_version)
|
|
63
|
+
path = File.join(schema_root_path, 'core', core_version.to_s, 'definitions.json')
|
|
64
|
+
return path if File.exist?(path)
|
|
65
|
+
|
|
66
|
+
raise UnknownSchemaVersionError, "Missing core definitions for RSMP #{core_version}"
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|