cosmos 4.4.2 → 4.5.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/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
|