rsmp 0.1.17 → 0.1.30

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: 1b583271d38fc35e2badabf94b0a8a764f07a8e36025c2902922d926adbf320b
4
- data.tar.gz: 9e37dd8939d68a19e1cf16580c558c813e8a5d6214a733cc8dce08fe4957be59
3
+ metadata.gz: 78085a76c3c6c8d5b504f614f72137e9d540e884e5cb08c37fbea304d397a183
4
+ data.tar.gz: 9b2c223b8f9f4f1e221f72ee1c80b61dc365089a0bfa56ff343c5ff2a08efdf9
5
5
  SHA512:
6
- metadata.gz: 1af3ecb44fc6c9e9fa0735b524c1561eafd91ef05775c0be325c8093635354e535d9d8f024d05cbc256859319a13795dfff34233165b8b57c53ac82fb76dbbd5
7
- data.tar.gz: aeaa068f63614bcd8e3af873400e5af54810c51e7a1941d62834c1bd2d94a3ff4ae62e59d89ad3242749fff54126aa3ccabf3bf3ac672f29c9cac9611ebddd47
6
+ metadata.gz: 362fac56d0554fff5b48b53d317b70bd4bbf88efa56e7a097ac7a5b71231e474399cb6039f55f0cbb11789f861d31c9f9c93b4fbd32e5e6cf8b92f2159c98468
7
+ data.tar.gz: 49edc4941f8b23f45fbbb6e2d344254b3ce3a5ff309cbcd965f069822c3cf31683d75889762490077944300551406738e385901bf78469f5e29d8264664a668e
data/.gitignore CHANGED
@@ -12,5 +12,6 @@ log
12
12
  /spec/reports/
13
13
  /tmp/
14
14
  /lib/rsmp_schema/
15
+ /config/private/
15
16
 
16
17
 
data/.gitmodules CHANGED
@@ -1,4 +0,0 @@
1
- [submodule "rsmp_schema"]
2
- path = lib/rsmp_schema
3
- url = git@github.com:rsmp-nordic/rsmp_schema.git
4
-
data/Gemfile.lock CHANGED
@@ -1,11 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rsmp (0.1.17)
5
- async (~> 1.23.0)
6
- async-io (~> 1.27.4)
4
+ rsmp (0.1.30)
5
+ async (~> 1.28.7)
6
+ async-io (~> 1.30.2)
7
7
  colorize (~> 0.8.1)
8
- json_schemer (~> 0.2.11)
8
+ rsmp_schemer (~> 0.2.0)
9
9
  thor (~> 1.0.1)
10
10
 
11
11
  GEM
@@ -18,17 +18,18 @@ GEM
18
18
  ffi (~> 1.9)
19
19
  rspec-expectations (~> 3.4)
20
20
  thor (~> 1.0)
21
- async (1.23.0)
22
- console (~> 1.0)
21
+ async (1.28.9)
22
+ console (~> 1.10)
23
23
  nio4r (~> 2.3)
24
24
  timers (~> 4.1)
25
- async-io (1.27.5)
25
+ async-io (1.30.2)
26
26
  async (~> 1.14)
27
27
  backports (3.17.0)
28
28
  builder (3.2.4)
29
29
  childprocess (3.0.0)
30
30
  colorize (0.8.1)
31
- console (1.8.2)
31
+ console (1.12.0)
32
+ fiber-local
32
33
  contracts (0.16.0)
33
34
  cucumber (3.1.2)
34
35
  builder (>= 2.1.2)
@@ -47,21 +48,24 @@ GEM
47
48
  cucumber-tag_expressions (1.1.1)
48
49
  cucumber-wire (0.0.1)
49
50
  diff-lcs (1.3)
50
- ecma-re-validator (0.2.0)
51
- regexp_parser (~> 1.2)
51
+ ecma-re-validator (0.3.0)
52
+ regexp_parser (~> 2.0)
52
53
  ffi (1.12.2)
54
+ fiber-local (1.0.0)
53
55
  gherkin (5.1.0)
54
- hana (1.3.5)
55
- json_schemer (0.2.11)
56
- ecma-re-validator (~> 0.2)
56
+ hana (1.3.7)
57
+ json_schemer (0.2.18)
58
+ ecma-re-validator (~> 0.3)
57
59
  hana (~> 1.3)
58
- regexp_parser (~> 1.5)
60
+ regexp_parser (~> 2.0)
59
61
  uri_template (~> 0.7)
60
62
  multi_json (1.14.1)
61
63
  multi_test (0.1.2)
62
- nio4r (2.5.2)
64
+ nio4r (2.5.7)
63
65
  rake (13.0.1)
64
- regexp_parser (1.7.0)
66
+ regexp_parser (2.1.1)
67
+ rsmp_schemer (0.2.0)
68
+ json_schemer (~> 0.2.18)
65
69
  rspec (3.9.0)
66
70
  rspec-core (~> 3.9.0)
67
71
  rspec-expectations (~> 3.9.0)
@@ -77,7 +81,7 @@ GEM
77
81
  rspec-support (3.9.2)
78
82
  thor (1.0.1)
79
83
  timecop (0.9.1)
80
- timers (4.3.0)
84
+ timers (4.3.3)
81
85
  uri_template (0.7.0)
82
86
 
83
87
  PLATFORMS
@@ -85,7 +89,7 @@ PLATFORMS
85
89
 
86
90
  DEPENDENCIES
87
91
  aruba (~> 1.0.0)
88
- bundler (~> 2.1.4)
92
+ bundler (~> 2.2.3)
89
93
  cucumber (~> 3.1.2)
90
94
  rake (~> 13.0.1)
91
95
  rsmp!
@@ -94,4 +98,4 @@ DEPENDENCIES
94
98
  timecop (~> 0.9.1)
95
99
 
96
100
  BUNDLED WITH
97
- 2.1.4
101
+ 2.2.3
data/README.md CHANGED
@@ -178,7 +178,7 @@ Use ```--config <path>``` to point to a .yaml config file, controlling things li
178
178
  ### RSpec
179
179
  RSpec tests are located in spec/. The tests will start supervisor and sites to test communication, but will do so on port 13111, rather than the usual port 12111, to avoid inferference with other RMSP processes running locally.
180
180
 
181
- Note that these tests are NOT intented for testing external equipment or systems. The tests are for validating the code in this repository. To test external equipment or systems.
181
+ Note that these tests are NOT intented for testing external equipment or systems. The tests are for validating the code in this repository. To test external equipment or systems use the rsmp_validator tool.
182
182
 
183
183
  ```console
184
184
  $ rspec
@@ -1,18 +1,12 @@
1
1
  port: 12111
2
- rsmp_versions:
3
- - 3.1.1
4
- - 3.1.2
5
- - 3.1.3
6
- - 3.1.4
7
-
8
- watchdog_interval: 1
9
- watchdog_timeout: 2
10
- acknowledgement_timeout: 2
11
- store_messages: false
12
- command_response_timeout: 1
13
- status_response_timeout: 1
14
- status_update_timeout: 1
15
-
2
+ guest:
3
+ sxl: tlc
4
+ intervals:
5
+ timer: 0.1
6
+ watchdog: 0.1
7
+ timeouts:
8
+ watchdog: 0.2
9
+ acknowledgement: 0.2
16
10
  log:
17
11
  active: true
18
12
  color: true
@@ -20,6 +14,7 @@ log:
20
14
  id: true
21
15
  component: true
22
16
  ip: false
17
+ port: true
23
18
  site_id: true
24
19
  text: true
25
20
  direction: true
@@ -27,4 +22,3 @@ log:
27
22
  json: true
28
23
  acknowledgements: false
29
24
  watchdogs: false
30
-
data/config/tlc.yaml CHANGED
@@ -2,7 +2,8 @@ site_id: RN+SI0001
2
2
  supervisors:
3
3
  - ip: 127.0.0.1
4
4
  port: 12111
5
-
5
+ sxl: tlc
6
+ sxl_version: 1.0.15
6
7
  components:
7
8
  main:
8
9
  TC:
@@ -18,14 +19,16 @@ components:
18
19
  plan: 'BBB1NB'
19
20
  detector_logic:
20
21
  DL1:
21
- watchdog_interval: 1
22
- watchdog_timeout: 2
23
- acknowledgement_timeout: 1
24
- command_response_timeout: 1
25
- status_response_timeout: 1
26
- status_update_timeout: 1
27
- reconnect_interval: 0.1
28
-
22
+ intervals:
23
+ timer: 0.1
24
+ watchdog: 0.1
25
+ reconnect: 0.1
26
+ timeouts:
27
+ watchdog: 0.2
28
+ acknowledgement: 0.2
29
+ security_codes:
30
+ 1: '1111'
31
+ 2: '2222'
29
32
  log:
30
33
  active: true
31
34
  color: true
@@ -40,4 +43,3 @@ log:
40
43
  json: true
41
44
  acknowledgements: false
42
45
  watchdogs: false
43
-
@@ -0,0 +1,65 @@
1
+ # Classes and Modules
2
+
3
+ ## Overview
4
+ ```
5
+ Node - - include Logging, Wait
6
+ / \
7
+ Super Site - - include Components
8
+
9
+
10
+ Proxy - - include Logging, Wait
11
+ / \
12
+ SupervisorProxy SiteProxy - - include Components, SiteProxyWait
13
+ ```
14
+
15
+ ## Modules
16
+ ### Logging
17
+ Handle logging.
18
+
19
+ ### Wait
20
+ Handles waiting for an async condition and block.
21
+
22
+ ### SiteProxyWait
23
+ Handles waiting for different types of messages and responses from a remote site.
24
+
25
+ ### Components
26
+ Component handling.
27
+
28
+ ## Classes
29
+ ### Node
30
+ A Node has an async task. A node can be started and stopped.
31
+
32
+ Node has two child classes: Site and Supervisor.
33
+
34
+ ### Site
35
+ A Site represents an RSMP site, typically a traffic light, variable message sign, or other type of field equipment. An RSMP site can connect to one or more supervisors.
36
+
37
+ A Site has one or more SupervisorProxies (connections to supervisor).
38
+
39
+ A site has one of more components.
40
+
41
+ ### Supervisor
42
+ A Supervisor represents an RSMP supervisor, typically a central supervisor system. An RSMP supervisor can handle connections one or more sites.
43
+
44
+ A Supervisor has one or more SiteProxies (connections to sites).
45
+
46
+ ### Proxy
47
+ A Proxy represents a connection to a remove Site or Supervisor and handles the RSMP interface.
48
+
49
+ A proxy has an async task listening for messages on an TCP/IP socket. Incoming RSMP messages are parsing and appropriate handles are called.
50
+
51
+ A proxy also has a repaating async timer task for handling watchdog and acknowledgement timeouts.
52
+
53
+ Proxy has to child classes: SiteProxy and SupervisorProxy.
54
+
55
+ ### SiteProxy
56
+ A connection to a remote Site.
57
+
58
+ Handles RSMP messaging specific to a supervisor, including methods for requesting status, sending commands, etc.
59
+
60
+ A SiteProxy has one or more components, representing the components in the remote site.
61
+
62
+ ### SupervisorProxy
63
+ A connection to a remote Site. Handles RSMP messaging specific to a site, including sending aggregated status, handling status requests, status subscription and command requests.
64
+
65
+ Status and command requests are delegated to the appropriate components.
@@ -0,0 +1,23 @@
1
+ # Message distribution
2
+
3
+ Proxy - - Notifier --> Listeners
4
+
5
+ A proxy distributes messages to listeners, when they are installed.
6
+
7
+ Collectors are special listenerws that waits for specific message, and are used to implement methods for waiting for RMSP responses, statuses, alarms, etc.
8
+
9
+ Note that Archive is not a listener, and does not receive messages via the Notifier. Instead the Archive gets and stores messages via the log() interface in the Logging module. The reason is that the items that the Archive and the Logger contain other data as well as the message, like error messages, warnings, text descriptions, colors codes, etc. The Distributor and Receiver handles only Message objects.
10
+
11
+ ## Notifier
12
+ A module that handles distributing messages to receivers.
13
+
14
+ ## Listener
15
+ Receives messages as long as it's installed into a distributor.
16
+
17
+ ## Collector
18
+ A subclass of Receiver that wait for specific messages. Once received
19
+ the client receives the collection.
20
+
21
+ ## Proxy
22
+ A proxy includes the Notifier module and distributes each message to listerens after processing it.
23
+
data/lib/rsmp.rb CHANGED
@@ -10,21 +10,30 @@ require 'json_schemer'
10
10
  require 'async/queue'
11
11
 
12
12
  require 'rsmp/rsmp'
13
- require 'rsmp/base'
13
+ require 'rsmp/deep_merge'
14
+ require 'rsmp/inspect'
15
+ require 'rsmp/logging'
14
16
  require 'rsmp/wait'
15
- require 'rsmp/version'
16
17
  require 'rsmp/node'
17
18
  require 'rsmp/supervisor'
19
+ require 'rsmp/components'
20
+ require 'rsmp/notifier'
21
+
22
+ require 'rsmp/listener'
23
+ require 'rsmp/collector'
18
24
  require 'rsmp/component'
19
- require 'rsmp/site_base'
20
25
  require 'rsmp/site'
21
26
  require 'rsmp/proxy'
22
27
  require 'rsmp/supervisor_proxy'
28
+ require 'rsmp/site_proxy_wait'
23
29
  require 'rsmp/site_proxy'
24
30
  require 'rsmp/error'
25
- require 'rsmp/probe'
26
- require 'rsmp/probe_collection'
27
31
  require 'rsmp/message'
28
32
  require 'rsmp/logger'
29
33
  require 'rsmp/archive'
30
34
  require 'rsmp/tlc'
35
+
36
+ require 'rsmp/convert/import/yaml'
37
+ require 'rsmp/convert/export/json_schema'
38
+
39
+ require 'rsmp/version'
data/lib/rsmp/archive.rb CHANGED
@@ -3,22 +3,26 @@
3
3
 
4
4
  module RSMP
5
5
  class Archive
6
+ include Inspect
7
+
6
8
  attr_reader :items
7
- attr_accessor :probes
8
9
 
9
- def initialize
10
+ @@index = 0
11
+
12
+ def initialize max=100
10
13
  @items = []
11
- @probes = ProbeCollection.new
14
+ @max = max
15
+ end
16
+
17
+ def inspect
18
+ "#<#{self.class.name}:#{self.object_id}, #{inspector(:@items)}>"
12
19
  end
13
20
 
14
21
  def self.prepare_item item
15
22
  raise ArgumentError unless item.is_a? Hash
16
23
 
17
- now_obj = RSMP.now_object
18
- now_str = RSMP.now_string(now_obj)
19
-
20
24
  cleaned = item.select { |k,v| [:author,:level,:ip,:port,:site_id,:component_id,:str,:message,:exception].include? k }
21
- cleaned[:timestamp] = now_obj
25
+ cleaned[:timestamp] = Clock.now
22
26
  if item[:message]
23
27
  cleaned[:direction] = item[:message].direction
24
28
  cleaned[:component_id] = item[:message].attributes['cId']
@@ -27,6 +31,14 @@ module RSMP
27
31
  cleaned
28
32
  end
29
33
 
34
+ def self.increase_index
35
+ @@index += 1
36
+ end
37
+
38
+ def self.current_index
39
+ @@index
40
+ end
41
+
30
42
  def by_level levels
31
43
  items.select { |item| levels.include? item[:level] }
32
44
  end
@@ -35,27 +47,16 @@ module RSMP
35
47
  items.map { |item| item[:str] }
36
48
  end
37
49
 
38
- def current_index
39
- @items.size
40
- end
41
-
42
50
  def add item
43
- item[:index] = @items.size
51
+ item[:index] = RSMP::Archive.increase_index
44
52
  @items << item
45
- probe item
46
- end
47
-
48
- def capture task, options, &block
49
- probe = RSMP::Probe.new self
50
- probe.capture task, options, &block
53
+ if @items.size > @max
54
+ @items.shift
55
+ end
51
56
  end
52
57
 
53
58
  private
54
59
 
55
- def probe item
56
- @probes.process item
57
- end
58
-
59
60
  def find options, &block
60
61
  # search backwards from newest to older, stopping once messages
61
62
  # are older that options[:earliest]
data/lib/rsmp/cli.rb CHANGED
@@ -2,106 +2,137 @@ require 'thor'
2
2
  require 'rsmp'
3
3
 
4
4
  module RSMP
5
- class CLI < Thor
6
-
7
- desc "site", "Run RSMP site"
8
- method_option :config, :type => :string, :aliases => "-c", banner: 'Path to .yaml config file'
9
- method_option :id, :type => :string, :aliases => "-i", banner: 'RSMP site id'
10
- method_option :supervisors, :type => :string, :aliases => "-s", banner: 'ip:port,... list of supervisor to connect to'
11
- method_option :log, :type => :string, :aliases => "-l", banner: 'Path to log file'
12
- method_option :json, :type => :boolean, :aliases => "-j", banner: 'Show JSON messages in log'
13
- method_option :type, :type => :string, :aliases => "-t", banner: 'Type of site: [tlc]'
14
- def site
15
- settings = {}
16
- log_settings = { 'active' => true }
17
-
18
- if options[:config]
19
- if File.exist? options[:config]
20
- settings = YAML.load_file options[:config]
21
- log_settings = settings.delete('log') || {}
22
- else
23
- puts "Error: Config #{options[:config]} not found"
24
- exit
25
- end
26
- end
27
-
28
- if options[:id]
29
- settings['site_id'] = options[:id]
30
- end
31
-
32
- if options[:supervisors]
33
- options[:supervisors].split(',').each do |supervisor|
34
- settings[:supervisors] ||= []
35
- ip, port = supervisor.split ':'
36
- ip = '127.0.0.1' if ip.empty?
37
- port = '12111' if port.empty?
38
- settings[:supervisors] << {"ip"=>ip, "port"=>port}
39
- end
40
- end
41
-
42
- if options[:log]
43
- log_settings['path'] = options[:log]
44
- end
45
-
46
- if options[:json]
47
- log_settings['json'] = options[:json]
48
- end
49
-
50
- site_class = RSMP::Site
51
- if options[:type]
52
- case options[:type]
53
- when 'tlc'
54
- site_class = RSMP::Tlc
55
- else
56
- site_class = RSMP::Site
57
- end
58
- end
59
- site_class.new(site_settings:settings, log_settings: log_settings).start
60
- end
61
-
62
- desc "supervisor", "Run RSMP supervisor"
63
- method_option :config, :type => :string, :aliases => "-c", banner: 'Path to .yaml config file'
64
- method_option :id, :type => :string, :aliases => "-i", banner: 'RSMP site id'
65
- method_option :ip, :type => :numeric, banner: 'IP address to listen on'
66
- method_option :port, :type => :string, :aliases => "-p", banner: 'Port to listen on'
67
- method_option :log, :type => :string, :aliases => "-l", banner: 'Path to log file'
68
- method_option :json, :type => :boolean, :aliases => "-j", banner: 'Show JSON messages in log'
69
- def supervisor
70
- settings = {}
71
- log_settings = { 'active' => true }
72
-
73
- if options[:config]
74
- if File.exist? options[:config]
75
- settings = YAML.load_file options[:config]
76
- log_settings = settings.delete 'log'
77
- else
78
- puts "Error: Config #{options[:config]} not found"
79
- exit
80
- end
81
- end
82
-
83
- if options[:id]
84
- settings['site_id'] = options[:id]
85
- end
86
-
87
- if options[:ip]
88
- settings['ip'] = options[:ip]
89
- end
90
-
91
- if options[:port]
92
- settings['port'] = options[:port]
93
- end
94
-
95
- if options[:log]
96
- log_settings['path'] = options[:log]
97
- end
98
-
99
- if options[:json]
100
- log_settings['json'] = options[:json]
101
- end
102
-
103
- RSMP::Supervisor.new(supervisor_settings:settings,log_settings:log_settings).start
104
- end
105
-
106
- end
5
+ class CLI < Thor
6
+
7
+ desc "site", "Run RSMP site"
8
+ method_option :config, :type => :string, :aliases => "-c", banner: 'Path to .yaml config file'
9
+ method_option :id, :type => :string, :aliases => "-i", banner: 'RSMP site id'
10
+ method_option :supervisors, :type => :string, :aliases => "-s", banner: 'ip:port,... list of supervisor to connect to'
11
+ method_option :log, :type => :string, :aliases => "-l", banner: 'Path to log file'
12
+ method_option :json, :type => :boolean, :aliases => "-j", banner: 'Show JSON messages in log'
13
+ method_option :type, :type => :string, :aliases => "-t", banner: 'Type of site: [tlc]'
14
+ def site
15
+ settings = {}
16
+ log_settings = { 'active' => true }
17
+
18
+ if options[:config]
19
+ if File.exist? options[:config]
20
+ settings = YAML.load_file options[:config]
21
+ log_settings = settings.delete('log') || {}
22
+ else
23
+ puts "Error: Config #{options[:config]} not found"
24
+ exit
25
+ end
26
+ end
27
+
28
+ if options[:id]
29
+ settings['site_id'] = options[:id]
30
+ end
31
+
32
+ if options[:supervisors]
33
+ options[:supervisors].split(',').each do |supervisor|
34
+ settings['supervisors'] ||= []
35
+ ip, port = supervisor.split ':'
36
+ ip = '127.0.0.1' if ip.empty?
37
+ port = '12111' if port.empty?
38
+ settings['supervisors'] << {"ip"=>ip, "port"=>port}
39
+ end
40
+ end
41
+
42
+ if options[:log]
43
+ log_settings['path'] = options[:log]
44
+ end
45
+
46
+ if options[:json]
47
+ log_settings['json'] = options[:json]
48
+ end
49
+
50
+ site_class = RSMP::Site
51
+ if options[:type]
52
+ case options[:type]
53
+ when 'tlc'
54
+ site_class = RSMP::Tlc
55
+ else
56
+ site_class = RSMP::Site
57
+ end
58
+ end
59
+ site_class.new(site_settings:settings, log_settings: log_settings).start
60
+ rescue RSMP::Schemer::UnknownSchemaTypeError => e
61
+ puts "Cannot start site: #{e}"
62
+ rescue RSMP::Schemer::UnknownSchemaVersionError => e
63
+ puts "Cannot start site: #{e}"
64
+ rescue Psych::SyntaxError => e
65
+ puts "Cannot read config file #{e}"
66
+ end
67
+
68
+ desc "supervisor", "Run RSMP supervisor"
69
+ method_option :config, :type => :string, :aliases => "-c", banner: 'Path to .yaml config file'
70
+ method_option :id, :type => :string, :aliases => "-i", banner: 'RSMP site id'
71
+ method_option :ip, :type => :numeric, banner: 'IP address to listen on'
72
+ method_option :port, :type => :string, :aliases => "-p", banner: 'Port to listen on'
73
+ method_option :log, :type => :string, :aliases => "-l", banner: 'Path to log file'
74
+ method_option :json, :type => :boolean, :aliases => "-j", banner: 'Show JSON messages in log'
75
+ def supervisor
76
+ settings = {}
77
+ log_settings = { 'active' => true }
78
+
79
+ if options[:config]
80
+ if File.exist? options[:config]
81
+ settings = YAML.load_file options[:config]
82
+ log_settings = settings.delete 'log'
83
+ else
84
+ puts "Error: Config #{options[:config]} not found"
85
+ exit
86
+ end
87
+ end
88
+
89
+ if options[:id]
90
+ settings['site_id'] = options[:id]
91
+ end
92
+
93
+ if options[:ip]
94
+ settings['ip'] = options[:ip]
95
+ end
96
+
97
+ if options[:port]
98
+ settings['port'] = options[:port]
99
+ end
100
+
101
+ if options[:log]
102
+ log_settings['path'] = options[:log]
103
+ end
104
+
105
+ if options[:json]
106
+ log_settings['json'] = options[:json]
107
+ end
108
+
109
+ RSMP::Supervisor.new(supervisor_settings:settings,log_settings:log_settings).start
110
+ rescue RSMP::ConfigurationError => e
111
+ puts "Cannot start supervisor: #{e}"
112
+ end
113
+
114
+ desc "convert", "Convert SXL from YAML to JSON Schema"
115
+ method_option :in, :type => :string, :aliases => "-i", banner: 'Path to YAML input file'
116
+ method_option :out, :type => :string, :aliases => "-o", banner: 'Path to JSON Schema output file'
117
+ def convert
118
+ unless options[:in]
119
+ puts "Error: Input option missing"
120
+ exit
121
+ end
122
+
123
+ unless options[:out]
124
+ puts "Error: Output option missing"
125
+ exit
126
+ end
127
+
128
+ unless File.exist? options[:in]
129
+ puts "Error: Input path file #{options[:in]} not found"
130
+ exit
131
+ end
132
+
133
+ sxl = RSMP::Convert::Import::YAML.read options[:in]
134
+ RSMP::Convert::Export::JSONSchema.write sxl, options[:out]
135
+ end
136
+
137
+ end
107
138
  end