cosmos 4.4.2 → 4.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Dockerfile +6 -2
- data/Manifest.txt +25 -0
- data/README.md +4 -0
- data/Rakefile +3 -8
- data/bin/rubysloc +73 -28
- data/cosmos.gemspec +1 -1
- data/data/config/interface_modifiers.yaml +3 -2
- data/data/config/system.yaml +81 -24
- data/data/crc.txt +426 -426
- data/demo/config/data/crc.txt +233 -233
- data/demo/config/system/system.txt +15 -7
- data/demo/config/system/system2.txt +15 -7
- data/demo/config/system/system_alt_ports.txt +15 -7
- data/demo/config/targets/INST/cmd_tlm/inst_cmds.txt +1 -1
- data/extensions/vscode/.gitignore +4 -0
- data/extensions/vscode/.vscode/launch.json +32 -0
- data/extensions/vscode/.vscode/settings.json +13 -0
- data/extensions/vscode/.vscode/tasks.json +79 -0
- data/extensions/vscode/License.txt +879 -0
- data/extensions/vscode/README.md +9 -0
- data/extensions/vscode/client/License.txt +879 -0
- data/extensions/vscode/client/README.md +39 -0
- data/extensions/vscode/client/cosmos.configuration.json +23 -0
- data/extensions/vscode/client/images/icon.png +0 -0
- data/extensions/vscode/client/package-lock.json +414 -0
- data/extensions/vscode/client/package.json +105 -0
- data/extensions/vscode/client/src/extension.ts +132 -0
- data/extensions/vscode/client/src/screen_preview.rb +25 -0
- data/extensions/vscode/client/syntaxes/cosmos.tmLanguage.json +219 -0
- data/extensions/vscode/client/tsconfig.json +17 -0
- data/extensions/vscode/package-lock.json +26 -0
- data/extensions/vscode/package.json +35 -0
- data/extensions/vscode/server/License.txt +879 -0
- data/extensions/vscode/server/package-lock.json +236 -0
- data/extensions/vscode/server/package.json +29 -0
- data/extensions/vscode/server/src/server.ts +59 -0
- data/extensions/vscode/server/tsconfig.json +16 -0
- data/install/config/data/crc.txt +132 -132
- data/install/config/system/system.txt +15 -7
- data/lib/cosmos/core_ext/time.rb +3 -1
- data/lib/cosmos/dart/examples/dart_decom_client.rb +1 -1
- data/lib/cosmos/dart/lib/dart_decommutator.rb +4 -4
- data/lib/cosmos/dart/processes/dart_decom_server.rb +1 -1
- data/lib/cosmos/dart/processes/dart_master.rb +1 -1
- data/lib/cosmos/gui/qt_tool.rb +10 -12
- data/lib/cosmos/gui/widgets/dart_meta_frame.rb +1 -1
- data/lib/cosmos/interfaces/dart_status_interface.rb +1 -1
- data/lib/cosmos/interfaces/serial_interface.rb +7 -1
- data/lib/cosmos/io/json_drb.rb +2 -2
- data/lib/cosmos/io/json_drb_object.rb +7 -2
- data/lib/cosmos/io/json_drb_rack.rb +25 -5
- data/lib/cosmos/io/json_rpc.rb +1 -1
- data/lib/cosmos/io/posix_serial_driver.rb +60 -22
- data/lib/cosmos/io/serial_driver.rb +11 -8
- data/lib/cosmos/io/win32_serial_driver.rb +8 -1
- data/lib/cosmos/packets/structure.rb +11 -2
- data/lib/cosmos/script/api_shared.rb +8 -1
- data/lib/cosmos/script/script.rb +2 -9
- data/lib/cosmos/streams/serial_stream.rb +11 -6
- data/lib/cosmos/system/system.rb +43 -12
- data/lib/cosmos/tools/cmd_sender/cmd_param_table_item_delegate.rb +15 -0
- data/lib/cosmos/tools/cmd_sender/cmd_params.rb +25 -3
- data/lib/cosmos/tools/cmd_sender/cmd_sender.rb +7 -0
- data/lib/cosmos/tools/cmd_sequence/sequence_item.rb +0 -5
- data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +2 -2
- data/lib/cosmos/tools/cmd_tlm_server/router_thread.rb +5 -0
- data/lib/cosmos/tools/config_editor/config_editor.rb +1 -1
- data/lib/cosmos/tools/handbook_creator/handbook_creator_config.rb +1 -1
- data/lib/cosmos/tools/tlm_extractor/tlm_extractor_config.rb +1 -4
- data/lib/cosmos/tools/tlm_extractor/tlm_extractor_processor.rb +3 -3
- data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_dart_thread.rb +1 -1
- data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +2 -2
- data/lib/cosmos/version.rb +5 -5
- data/spec/core_ext/time_spec.rb +4 -0
- data/spec/io/json_drb_rack_spec.rb +166 -0
- data/spec/io/json_rpc_spec.rb +4 -5
- data/spec/io/posix_serial_driver_spec.rb +81 -0
- data/spec/io/win32_serial_driver_spec.rb +17 -1
- data/spec/system/system_spec.rb +108 -0
- data/spec/tools/cmd_tlm_server/router_thread_spec.rb +2 -3
- metadata +31 -6
@@ -5,16 +5,17 @@ AUTO_DECLARE_TARGETS
|
|
5
5
|
# DECLARE_TARGET SYSTEM
|
6
6
|
|
7
7
|
# Listen Hosts - Ip addresses or hostnames to listen on when running the tools
|
8
|
+
# Set these to 0.0.0.0 if you need external connections from other computers
|
8
9
|
LISTEN_HOST CTS_API 127.0.0.1
|
9
10
|
LISTEN_HOST TLMVIEWER_API 127.0.0.1
|
10
|
-
LISTEN_HOST CTS_PREIDENTIFIED
|
11
|
-
LISTEN_HOST CTS_CMD_ROUTER
|
11
|
+
LISTEN_HOST CTS_PREIDENTIFIED 127.0.0.1
|
12
|
+
LISTEN_HOST CTS_CMD_ROUTER 127.0.0.1
|
12
13
|
LISTEN_HOST REPLAY_API 127.0.0.1
|
13
|
-
LISTEN_HOST REPLAY_PREIDENTIFIED
|
14
|
-
LISTEN_HOST REPLAY_CMD_ROUTER
|
15
|
-
LISTEN_HOST DART_STREAM
|
16
|
-
LISTEN_HOST DART_DECOM
|
17
|
-
LISTEN_HOST DART_MASTER
|
14
|
+
LISTEN_HOST REPLAY_PREIDENTIFIED 127.0.0.1
|
15
|
+
LISTEN_HOST REPLAY_CMD_ROUTER 127.0.0.1
|
16
|
+
LISTEN_HOST DART_STREAM 127.0.0.1
|
17
|
+
LISTEN_HOST DART_DECOM 127.0.0.1
|
18
|
+
LISTEN_HOST DART_MASTER 127.0.0.1
|
18
19
|
|
19
20
|
# Connect Hosts - Ip addresses or hostnames to connect to when running the tools
|
20
21
|
CONNECT_HOST CTS_API 127.0.0.1
|
@@ -65,3 +66,10 @@ ALLOW_ACCESS ALL
|
|
65
66
|
# META_INIT config/data/meta_init.txt
|
66
67
|
|
67
68
|
# ADD_HASH_FILE lib/user_version.rb
|
69
|
+
|
70
|
+
# ALLOW_ROUTER_COMMANDING # Enable this to chain servers with commanding
|
71
|
+
# ALLOW_HOST localhost:7777 # This is provided by default. Add with HostIP:7777 for chaining
|
72
|
+
# ALLOW_ORIGIN 1.2.3.4:8080 # Add this if you have a webserver that should be able to access the COSMOS API
|
73
|
+
|
74
|
+
# *** IMPORTANT *** Change this value to a unique value for each project
|
75
|
+
X_CSRF_TOKEN SuperSecret # Secret used to secure requests - Change for each project
|
data/lib/cosmos/core_ext/time.rb
CHANGED
@@ -389,7 +389,9 @@ class Time
|
|
389
389
|
# @return [Float] The number of seconds from the given epoch to the given
|
390
390
|
# CCSDS day, milliseconds, and microseconds.
|
391
391
|
def self.ccsds2sec(day, ms, us, sec_epoch_jd = JULIAN_DATE_OF_CCSDS_EPOCH)
|
392
|
-
|
392
|
+
# NOTE: We don't call ccsds2julian to avoid loss of precision
|
393
|
+
(day + JULIAN_DATE_OF_CCSDS_EPOCH - sec_epoch_jd +
|
394
|
+
((ms.to_f + (us / 1000.0)) / MSEC_PER_DAY_FLOAT)) * SEC_PER_DAY_FLOAT
|
393
395
|
end
|
394
396
|
|
395
397
|
# @param sec [Float] Number of seconds to convert
|
@@ -31,7 +31,7 @@ request['value_type'] = 'RAW_AVG'
|
|
31
31
|
request['meta_filters'] = ["OPERATOR_NAME == 'Unspecified'"]
|
32
32
|
|
33
33
|
puts "Connecting to Dart Decom Server..."
|
34
|
-
server = Cosmos::JsonDRbObject.new(Cosmos::System.connect_hosts['DART_DECOM'], Cosmos::System.ports['DART_DECOM'])
|
34
|
+
server = Cosmos::JsonDRbObject.new(Cosmos::System.connect_hosts['DART_DECOM'], Cosmos::System.ports['DART_DECOM'], 1.0, Cosmos::System.x_csrf_token)
|
35
35
|
puts "Getting SYSTEM META fields"
|
36
36
|
result = server.item_names("SYSTEM", "META")
|
37
37
|
puts result.inspect(10000)
|
@@ -36,16 +36,16 @@ class DartDecommutator
|
|
36
36
|
|
37
37
|
# Wait 60s before giving up on the PacketConfig becoming ready
|
38
38
|
PACKET_CONFIG_READY_TIMEOUT = 60
|
39
|
-
|
39
|
+
|
40
40
|
# Delay between updating the DART status packet. Simply throttles this rarely viewed status
|
41
41
|
STATUS_UPDATE_PERIOD_SECONDS = 60.seconds
|
42
|
-
|
42
|
+
|
43
43
|
def initialize(worker_id = 0, num_workers = 1)
|
44
44
|
sync_targets_and_packets()
|
45
45
|
@worker_id = worker_id
|
46
46
|
@num_workers = num_workers
|
47
47
|
@status = DartDecommutatorStatus.new
|
48
|
-
@master = Cosmos::JsonDRbObject.new(Cosmos::System.connect_hosts['DART_MASTER'], Cosmos::System.ports['DART_MASTER'])
|
48
|
+
@master = Cosmos::JsonDRbObject.new(Cosmos::System.connect_hosts['DART_MASTER'], Cosmos::System.ports['DART_MASTER'], 1.0, Cosmos::System.x_csrf_token)
|
49
49
|
end
|
50
50
|
|
51
51
|
def timeit(message, &block)
|
@@ -84,7 +84,7 @@ class DartDecommutator
|
|
84
84
|
# If we timeout this code will simply exit the application
|
85
85
|
wait_for_ready_packet_config(packet_config)
|
86
86
|
decom_packet(ple, packet, packet_config)
|
87
|
-
|
87
|
+
|
88
88
|
# Update status
|
89
89
|
if Time.now > status_time
|
90
90
|
status_time = Time.now + 60.seconds
|
@@ -25,7 +25,7 @@ Cosmos.catch_fatal_exception do
|
|
25
25
|
json_drb.method_whitelist = ['query', 'item_names', 'dart_status', 'clear_errors']
|
26
26
|
begin
|
27
27
|
json_drb.start_service(Cosmos::System.listen_hosts['DART_DECOM'],
|
28
|
-
Cosmos::System.ports['DART_DECOM'], DartDecomQuery.new)
|
28
|
+
Cosmos::System.ports['DART_DECOM'], DartDecomQuery.new, 1000, Cosmos::System)
|
29
29
|
rescue Exception => error
|
30
30
|
raise Cosmos::FatalError.new("Error starting JsonDRb on port #{Cosmos::System.ports['DART_DECOM']}.\nPerhaps another DART Decom Server is already running?\n#{error.formatted}")
|
31
31
|
end
|
@@ -29,7 +29,7 @@ Cosmos.catch_fatal_exception do
|
|
29
29
|
json_drb.method_whitelist = ['get_decom_ple_ids']
|
30
30
|
begin
|
31
31
|
json_drb.start_service(Cosmos::System.listen_hosts['DART_MASTER'],
|
32
|
-
Cosmos::System.ports['DART_MASTER'], DartMasterQuery.new(ples_per_request))
|
32
|
+
Cosmos::System.ports['DART_MASTER'], DartMasterQuery.new(ples_per_request), 1000, Cosmos::System)
|
33
33
|
rescue Exception => error
|
34
34
|
raise Cosmos::FatalError.new("Error starting JsonDRb on port #{Cosmos::System.ports['DART_MASTER']}.\nPerhaps another DART Master is already running?\n#{error.formatted}")
|
35
35
|
end
|
data/lib/cosmos/gui/qt_tool.rb
CHANGED
@@ -82,7 +82,7 @@ module Cosmos
|
|
82
82
|
else
|
83
83
|
options.config_file = nil
|
84
84
|
options.stylesheet = nil
|
85
|
-
end
|
85
|
+
end
|
86
86
|
end
|
87
87
|
|
88
88
|
# Creates a path to a configuration file. If the file is given it is
|
@@ -209,28 +209,26 @@ module Cosmos
|
|
209
209
|
|
210
210
|
# Handle manually positioning the window
|
211
211
|
unless @options.auto_position
|
212
|
-
# Get the desktop's geometry
|
213
|
-
desktop = Qt::Application.desktop
|
214
|
-
|
215
|
-
# Handle position relative to right edge
|
216
|
-
@options.x = desktop.width - frameGeometry().width + @options.x + 1 if @options.x < 0
|
217
|
-
|
218
|
-
# Handle position relative to bottom edge
|
219
|
-
@options.y = desktop.height - frameGeometry().height + @options.y + 1 if @options.y < 0
|
220
|
-
|
221
212
|
# Move to the desired position
|
222
213
|
move(@options.x, @options.y)
|
223
214
|
end
|
224
215
|
|
225
216
|
if @options.remember_geometry and !@options.command_line_geometry
|
217
|
+
# Get the desktop's geometry
|
218
|
+
desktop = Qt::Application.desktop
|
219
|
+
screen = desktop.screen
|
226
220
|
settings = Qt::Settings.new('Ball Aerospace', self.class.to_s)
|
227
221
|
if settings.contains('size') and @options.restore_size and @options.startup_state != :DEFAULT
|
228
222
|
size = settings.value('size').toSize
|
229
|
-
|
223
|
+
if size.height > 0 and size.height < screen.height and size.width > 0 and size.width < screen.width
|
224
|
+
resize(size)
|
225
|
+
end
|
230
226
|
end
|
231
227
|
if settings.contains('position') and @options.restore_position
|
232
228
|
position = settings.value('position').toPoint
|
233
|
-
|
229
|
+
if position.x > 0 and position.y > 0 and position.x < screen.width and position.y < screen.height
|
230
|
+
move(position)
|
231
|
+
end
|
234
232
|
end
|
235
233
|
end
|
236
234
|
|
@@ -114,7 +114,7 @@ module Cosmos
|
|
114
114
|
if !@got_meta_item_names and !@update_thread
|
115
115
|
@update_thread = Thread.new do
|
116
116
|
begin
|
117
|
-
server = JsonDRbObject.new(System.connect_hosts['DART_DECOM'], System.ports['DART_DECOM'])
|
117
|
+
server = JsonDRbObject.new(System.connect_hosts['DART_DECOM'], System.ports['DART_DECOM'], 1.0, Cosmos::System.x_csrf_token)
|
118
118
|
item_names = server.item_names("SYSTEM", "META")
|
119
119
|
Qt.execute_in_main_thread do
|
120
120
|
unless self.disposed?
|
@@ -36,7 +36,7 @@ module Cosmos
|
|
36
36
|
@status_packet.write('PACKET_ID', 1)
|
37
37
|
@clear_errors_command = System.commands.packet('DART', 'CLEAR_ERRORS')
|
38
38
|
@sleeper = Sleeper.new
|
39
|
-
@dart = JsonDRbObject.new(System.connect_hosts['DART_DECOM'], System.ports['DART_DECOM'])
|
39
|
+
@dart = JsonDRbObject.new(System.connect_hosts['DART_DECOM'], System.ports['DART_DECOM'], 1.0, Cosmos::System.x_csrf_token)
|
40
40
|
end
|
41
41
|
|
42
42
|
# Indicates if the interface is connected to its target(s) or not. Must be
|
@@ -52,6 +52,7 @@ module Cosmos
|
|
52
52
|
@read_allowed = false unless @read_port_name
|
53
53
|
@flow_control = :NONE
|
54
54
|
@data_bits = 8
|
55
|
+
@struct = []
|
55
56
|
end
|
56
57
|
|
57
58
|
# Creates a new {SerialStream} using the parameters passed in the constructor
|
@@ -65,13 +66,16 @@ module Cosmos
|
|
65
66
|
@write_timeout,
|
66
67
|
@read_timeout,
|
67
68
|
@flow_control,
|
68
|
-
@data_bits
|
69
|
+
@data_bits,
|
70
|
+
@struct
|
69
71
|
)
|
70
72
|
super()
|
71
73
|
end
|
72
74
|
|
73
75
|
# Supported Options
|
74
76
|
# FLOW_CONTROL - Flow control method NONE or RTSCTS. Defaults to NONE
|
77
|
+
# DATA_BITS - How many data bits to use
|
78
|
+
# STRUCT - Directly set fields in the Win32 DCB or POSIX termios structure
|
75
79
|
def set_option(option_name, option_values)
|
76
80
|
super(option_name, option_values)
|
77
81
|
case option_name.upcase
|
@@ -79,6 +83,8 @@ module Cosmos
|
|
79
83
|
@flow_control = option_values[0]
|
80
84
|
when 'DATA_BITS'
|
81
85
|
@data_bits = option_values[0].to_i
|
86
|
+
when 'STRUCT'
|
87
|
+
@struct << option_values
|
82
88
|
end
|
83
89
|
end
|
84
90
|
end
|
data/lib/cosmos/io/json_drb.rb
CHANGED
@@ -123,7 +123,7 @@ module Cosmos
|
|
123
123
|
# @param object [Object] The object to send the DRb requests to. This
|
124
124
|
# object must either include the Cosmos::Script module or be the
|
125
125
|
# CmdTlmServer.
|
126
|
-
def start_service(hostname = nil, port = nil, object = nil, max_threads = 1000)
|
126
|
+
def start_service(hostname = nil, port = nil, object = nil, max_threads = 1000, system = nil)
|
127
127
|
server_started = false
|
128
128
|
@server_mutex.synchronize do
|
129
129
|
server_started = true if @server
|
@@ -147,7 +147,7 @@ module Cosmos
|
|
147
147
|
}
|
148
148
|
|
149
149
|
# The run call will block until the server is stopped.
|
150
|
-
Rack::Handler::Puma.run(JsonDrbRack.new(self), server_config) do |server|
|
150
|
+
Rack::Handler::Puma.run(JsonDrbRack.new(self, system), server_config) do |server|
|
151
151
|
@server_mutex.synchronize do
|
152
152
|
@server = server
|
153
153
|
end
|
@@ -38,7 +38,7 @@ module Cosmos
|
|
38
38
|
# @param hostname [String] The name of the machine which has started
|
39
39
|
# the JSON service
|
40
40
|
# @param port [Integer] The port number of the JSON service
|
41
|
-
def initialize(hostname, port, connect_timeout = 1.0)
|
41
|
+
def initialize(hostname, port, connect_timeout = 1.0, x_csrf_token = nil)
|
42
42
|
hostname = '127.0.0.1' if (hostname.to_s.upcase == 'LOCALHOST')
|
43
43
|
begin
|
44
44
|
Socket.pack_sockaddr_in(port, hostname)
|
@@ -61,6 +61,7 @@ module Cosmos
|
|
61
61
|
@connect_timeout = connect_timeout
|
62
62
|
@connect_timeout = @connect_timeout.to_f if @connect_timeout
|
63
63
|
@shutdown = false
|
64
|
+
@x_csrf_token = x_csrf_token
|
64
65
|
end
|
65
66
|
|
66
67
|
# Disconnects from http server
|
@@ -127,7 +128,11 @@ module Cosmos
|
|
127
128
|
STDOUT.puts "\nRequest:\n" if JsonDRb.debug?
|
128
129
|
STDOUT.puts @request_data if JsonDRb.debug?
|
129
130
|
@request_in_progress = true
|
130
|
-
|
131
|
+
if @x_csrf_token
|
132
|
+
headers = {'Content-Type' => 'application/json-rpc', 'X-Csrf-Token' => @x_csrf_token}
|
133
|
+
else
|
134
|
+
headers = {'Content-Type' => 'application/json-rpc'}
|
135
|
+
end
|
131
136
|
res = @http.post(@uri,
|
132
137
|
:body => @request_data,
|
133
138
|
:header => headers)
|
@@ -17,8 +17,9 @@ module Cosmos
|
|
17
17
|
class JsonDrbRack
|
18
18
|
# @param drb [JsonDRb] - An instance of the JsonDRb class that'll be used
|
19
19
|
# to process the JSON request and generate a response
|
20
|
-
def initialize(drb)
|
20
|
+
def initialize(drb, system = nil)
|
21
21
|
@drb = drb
|
22
|
+
@system = system
|
22
23
|
end
|
23
24
|
|
24
25
|
# Handles a request.
|
@@ -32,22 +33,41 @@ module Cosmos
|
|
32
33
|
# ACL allow_addr? function takes address in the form returned by
|
33
34
|
# IPSocket.peeraddr.
|
34
35
|
req_addr = ["AF_INET", request.port, request.host.to_s, request.ip.to_s]
|
36
|
+
status = nil
|
35
37
|
|
36
38
|
if @drb.acl and !@drb.acl.allow_addr?(req_addr)
|
37
39
|
status = 403
|
38
40
|
content_type = "text/plain"
|
39
41
|
body = "Forbidden"
|
40
42
|
elsif request.post?
|
41
|
-
|
43
|
+
if @system
|
44
|
+
if @system.x_csrf_token and (request.env['HTTP_X_CSRF_TOKEN'] != @system.x_csrf_token)
|
45
|
+
status = 403
|
46
|
+
content_type = "text/plain"
|
47
|
+
body = "Forbidden: Bad X-Csrf-Token: #{request.env['HTTP_X_CSRF_TOKEN']}"
|
48
|
+
end
|
49
|
+
if !@system.allowed_hosts.include?(request.env['HTTP_HOST'])
|
50
|
+
status = 403
|
51
|
+
content_type = "text/plain"
|
52
|
+
body = "Forbidden: #{request.env['HTTP_HOST']} not in allowed hosts"
|
53
|
+
end
|
54
|
+
if request.env['HTTP_ORIGIN'] and !@system.allowed_origins.include?(request.env['HTTP_ORIGIN'])
|
55
|
+
status = 403
|
56
|
+
content_type = "text/plain"
|
57
|
+
body = "Forbidden: #{request.env['HTTP_ORIGIN']} not in allowed origins"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
status, content_type, body = handle_post(request) unless status
|
42
62
|
else
|
43
63
|
status = 405
|
44
64
|
content_type = "text/plain"
|
45
65
|
body = "Request not allowed"
|
46
66
|
end
|
47
|
-
|
67
|
+
|
48
68
|
return status, {'Content-Type' => content_type}, [body]
|
49
69
|
end
|
50
|
-
|
70
|
+
|
51
71
|
# Handles an http post.
|
52
72
|
#
|
53
73
|
# @param request [Rack::Request] - A rack post request
|
@@ -57,7 +77,7 @@ module Cosmos
|
|
57
77
|
request_data = request.body.read
|
58
78
|
start_time = Time.now.sys
|
59
79
|
response_data, error_code = @drb.process_request(request_data, start_time)
|
60
|
-
|
80
|
+
|
61
81
|
# Convert json error code into html status code
|
62
82
|
# see http://www.jsonrpc.org/historical/json-rpc-over-http.html#errors
|
63
83
|
if error_code
|
data/lib/cosmos/io/json_rpc.rb
CHANGED
@@ -269,7 +269,7 @@ module Cosmos
|
|
269
269
|
# @param response_data [String] JSON encoded string representing the response
|
270
270
|
# @return [JsonRpcResponse]
|
271
271
|
def self.from_json(response_data)
|
272
|
-
msg = "Invalid JSON-RPC 2.0 Response"
|
272
|
+
msg = "Invalid JSON-RPC 2.0 Response: #{response_data.inspect}"
|
273
273
|
begin
|
274
274
|
hash = JSON.parse(response_data, :allow_nan => true, :create_additions => true)
|
275
275
|
rescue
|
@@ -25,19 +25,20 @@ module Cosmos
|
|
25
25
|
write_timeout = 10.0,
|
26
26
|
read_timeout = nil,
|
27
27
|
flow_control = :NONE,
|
28
|
-
data_bits = 8
|
28
|
+
data_bits = 8,
|
29
|
+
struct = [])
|
29
30
|
|
30
31
|
# Convert Baud Rate into Termios constant
|
31
32
|
begin
|
32
33
|
baud_rate = Object.const_get("Termios::B#{baud_rate}")
|
33
34
|
rescue NameError
|
34
|
-
raise(ArgumentError, "Invalid
|
35
|
+
raise(ArgumentError, "Invalid baud rate: #{baud_rate}")
|
35
36
|
end
|
36
37
|
|
37
38
|
# Verify Parameters
|
38
|
-
raise(ArgumentError, "Invalid
|
39
|
+
raise(ArgumentError, "Invalid data bits: #{data_bits}") unless [5,6,7,8].include?(data_bits)
|
39
40
|
raise(ArgumentError, "Invalid parity: #{parity}") if parity and !SerialDriver::VALID_PARITY.include?(parity)
|
40
|
-
raise(ArgumentError, "Invalid
|
41
|
+
raise(ArgumentError, "Invalid stop bits: #{stop_bits}") unless [1,2].include?(stop_bits)
|
41
42
|
@write_timeout = write_timeout
|
42
43
|
@read_timeout = read_timeout
|
43
44
|
|
@@ -51,22 +52,61 @@ module Cosmos
|
|
51
52
|
|
52
53
|
# Configure the serial Port
|
53
54
|
tio = Termios::new_termios()
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
tio.cflag = cflags
|
67
|
-
tio.lflag = 0
|
55
|
+
iflag = 0
|
56
|
+
iflag |= Termios::IGNPAR unless parity
|
57
|
+
oflag = 0
|
58
|
+
cflag = 0
|
59
|
+
cflag |= Termios::CREAD # Enable receiver
|
60
|
+
cflag |= Termios.const_get("CS#{data_bits}") # data bits
|
61
|
+
cflag |= Termios::CLOCAL # Ignore Modem Control Lines
|
62
|
+
cflag |= Termios::CSTOPB if stop_bits == 2
|
63
|
+
cflag |= Termios::PARENB if parity
|
64
|
+
cflag |= Termios::PARODD if parity == :ODD
|
65
|
+
cflag |= Termios::CRTSCTS if flow_control == :RTSCTS
|
66
|
+
lflag = 0
|
68
67
|
tio.cc[Termios::VTIME] = 0
|
69
68
|
tio.cc[Termios::VMIN] = 1
|
69
|
+
unless struct.empty?
|
70
|
+
struct.each do |field, key, value|
|
71
|
+
case field
|
72
|
+
when 'iflag'
|
73
|
+
if value == "0"
|
74
|
+
iflag &= ~Termios.const_get(key)
|
75
|
+
else
|
76
|
+
iflag |= Termios.const_get(key)
|
77
|
+
end
|
78
|
+
when 'oflag'
|
79
|
+
if value == "0"
|
80
|
+
oflag &= ~Termios.const_get(key)
|
81
|
+
else
|
82
|
+
oflag |= Termios.const_get(key)
|
83
|
+
end
|
84
|
+
when 'cflag'
|
85
|
+
if value == "0"
|
86
|
+
cflag &= ~Termios.const_get(key)
|
87
|
+
else
|
88
|
+
cflag |= Termios.const_get(key)
|
89
|
+
end
|
90
|
+
when 'lflag'
|
91
|
+
if value == "0"
|
92
|
+
lflag &= ~Termios.const_get(key)
|
93
|
+
else
|
94
|
+
lflag |= Termios.const_get(key)
|
95
|
+
end
|
96
|
+
when 'cc'
|
97
|
+
begin
|
98
|
+
value = Integer(value) # Try to convert to int
|
99
|
+
rescue ArgumentError
|
100
|
+
# Ignore this error and use the string
|
101
|
+
end
|
102
|
+
tio.cc[Termios.const_get(key)] = value
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
tio.iflag = iflag
|
107
|
+
tio.oflag = oflag
|
108
|
+
tio.cflag = cflag
|
109
|
+
tio.lflag = lflag
|
70
110
|
tio.ispeed = baud_rate
|
71
111
|
tio.ospeed = baud_rate
|
72
112
|
@handle.tcflush(Termios::TCIOFLUSH)
|
@@ -143,7 +183,5 @@ module Cosmos
|
|
143
183
|
|
144
184
|
data
|
145
185
|
end
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
end # module Cosmos
|
186
|
+
end
|
187
|
+
end
|
@@ -32,8 +32,10 @@ module Cosmos
|
|
32
32
|
# complete or nil to block
|
33
33
|
# @param read_timeout [Float|nil] Number of seconds to wait for the read to
|
34
34
|
# complete or nil to block
|
35
|
-
# @param flow_control [Symbol] Currently supported :NONE
|
35
|
+
# @param flow_control [Symbol] Currently supported :NONE, :RTSCTS (default :NONE)
|
36
36
|
# @param data_bits [Integer] Number of data bits (default 8)
|
37
|
+
# @param struct [Array] Array of arrays of fields and values to set in the
|
38
|
+
# Windows DCB or POSIX structure
|
37
39
|
def initialize(port_name,
|
38
40
|
baud_rate,
|
39
41
|
parity = :NONE,
|
@@ -41,7 +43,8 @@ module Cosmos
|
|
41
43
|
write_timeout = 10.0,
|
42
44
|
read_timeout = nil,
|
43
45
|
flow_control = :NONE,
|
44
|
-
data_bits = 8
|
46
|
+
data_bits = 8,
|
47
|
+
struct = [])
|
45
48
|
raise(ArgumentError, "Invalid parity: #{parity}") unless VALID_PARITY.include? parity
|
46
49
|
if Kernel.is_windows?
|
47
50
|
@driver = Win32SerialDriver.new(port_name,
|
@@ -53,7 +56,8 @@ module Cosmos
|
|
53
56
|
0.01,
|
54
57
|
1000,
|
55
58
|
flow_control,
|
56
|
-
data_bits
|
59
|
+
data_bits,
|
60
|
+
struct)
|
57
61
|
elsif RUBY_ENGINE == 'ruby'
|
58
62
|
@driver = PosixSerialDriver.new(port_name,
|
59
63
|
baud_rate,
|
@@ -62,7 +66,8 @@ module Cosmos
|
|
62
66
|
write_timeout,
|
63
67
|
read_timeout,
|
64
68
|
flow_control,
|
65
|
-
data_bits
|
69
|
+
data_bits,
|
70
|
+
struct)
|
66
71
|
else
|
67
72
|
@driver = nil # JRuby Serial on Linux not currently supported
|
68
73
|
end
|
@@ -92,7 +97,5 @@ module Cosmos
|
|
92
97
|
def read_nonblock
|
93
98
|
@driver.read_nonblock
|
94
99
|
end
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
end # module Cosmos
|
100
|
+
end
|
101
|
+
end
|