cosmos 4.4.2 → 4.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +6 -2
  3. data/Manifest.txt +25 -0
  4. data/README.md +4 -0
  5. data/Rakefile +3 -8
  6. data/bin/rubysloc +73 -28
  7. data/cosmos.gemspec +1 -1
  8. data/data/config/interface_modifiers.yaml +3 -2
  9. data/data/config/system.yaml +81 -24
  10. data/data/crc.txt +426 -426
  11. data/demo/config/data/crc.txt +233 -233
  12. data/demo/config/system/system.txt +15 -7
  13. data/demo/config/system/system2.txt +15 -7
  14. data/demo/config/system/system_alt_ports.txt +15 -7
  15. data/demo/config/targets/INST/cmd_tlm/inst_cmds.txt +1 -1
  16. data/extensions/vscode/.gitignore +4 -0
  17. data/extensions/vscode/.vscode/launch.json +32 -0
  18. data/extensions/vscode/.vscode/settings.json +13 -0
  19. data/extensions/vscode/.vscode/tasks.json +79 -0
  20. data/extensions/vscode/License.txt +879 -0
  21. data/extensions/vscode/README.md +9 -0
  22. data/extensions/vscode/client/License.txt +879 -0
  23. data/extensions/vscode/client/README.md +39 -0
  24. data/extensions/vscode/client/cosmos.configuration.json +23 -0
  25. data/extensions/vscode/client/images/icon.png +0 -0
  26. data/extensions/vscode/client/package-lock.json +414 -0
  27. data/extensions/vscode/client/package.json +105 -0
  28. data/extensions/vscode/client/src/extension.ts +132 -0
  29. data/extensions/vscode/client/src/screen_preview.rb +25 -0
  30. data/extensions/vscode/client/syntaxes/cosmos.tmLanguage.json +219 -0
  31. data/extensions/vscode/client/tsconfig.json +17 -0
  32. data/extensions/vscode/package-lock.json +26 -0
  33. data/extensions/vscode/package.json +35 -0
  34. data/extensions/vscode/server/License.txt +879 -0
  35. data/extensions/vscode/server/package-lock.json +236 -0
  36. data/extensions/vscode/server/package.json +29 -0
  37. data/extensions/vscode/server/src/server.ts +59 -0
  38. data/extensions/vscode/server/tsconfig.json +16 -0
  39. data/install/config/data/crc.txt +132 -132
  40. data/install/config/system/system.txt +15 -7
  41. data/lib/cosmos/core_ext/time.rb +3 -1
  42. data/lib/cosmos/dart/examples/dart_decom_client.rb +1 -1
  43. data/lib/cosmos/dart/lib/dart_decommutator.rb +4 -4
  44. data/lib/cosmos/dart/processes/dart_decom_server.rb +1 -1
  45. data/lib/cosmos/dart/processes/dart_master.rb +1 -1
  46. data/lib/cosmos/gui/qt_tool.rb +10 -12
  47. data/lib/cosmos/gui/widgets/dart_meta_frame.rb +1 -1
  48. data/lib/cosmos/interfaces/dart_status_interface.rb +1 -1
  49. data/lib/cosmos/interfaces/serial_interface.rb +7 -1
  50. data/lib/cosmos/io/json_drb.rb +2 -2
  51. data/lib/cosmos/io/json_drb_object.rb +7 -2
  52. data/lib/cosmos/io/json_drb_rack.rb +25 -5
  53. data/lib/cosmos/io/json_rpc.rb +1 -1
  54. data/lib/cosmos/io/posix_serial_driver.rb +60 -22
  55. data/lib/cosmos/io/serial_driver.rb +11 -8
  56. data/lib/cosmos/io/win32_serial_driver.rb +8 -1
  57. data/lib/cosmos/packets/structure.rb +11 -2
  58. data/lib/cosmos/script/api_shared.rb +8 -1
  59. data/lib/cosmos/script/script.rb +2 -9
  60. data/lib/cosmos/streams/serial_stream.rb +11 -6
  61. data/lib/cosmos/system/system.rb +43 -12
  62. data/lib/cosmos/tools/cmd_sender/cmd_param_table_item_delegate.rb +15 -0
  63. data/lib/cosmos/tools/cmd_sender/cmd_params.rb +25 -3
  64. data/lib/cosmos/tools/cmd_sender/cmd_sender.rb +7 -0
  65. data/lib/cosmos/tools/cmd_sequence/sequence_item.rb +0 -5
  66. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +2 -2
  67. data/lib/cosmos/tools/cmd_tlm_server/router_thread.rb +5 -0
  68. data/lib/cosmos/tools/config_editor/config_editor.rb +1 -1
  69. data/lib/cosmos/tools/handbook_creator/handbook_creator_config.rb +1 -1
  70. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_config.rb +1 -4
  71. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_processor.rb +3 -3
  72. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_dart_thread.rb +1 -1
  73. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +2 -2
  74. data/lib/cosmos/version.rb +5 -5
  75. data/spec/core_ext/time_spec.rb +4 -0
  76. data/spec/io/json_drb_rack_spec.rb +166 -0
  77. data/spec/io/json_rpc_spec.rb +4 -5
  78. data/spec/io/posix_serial_driver_spec.rb +81 -0
  79. data/spec/io/win32_serial_driver_spec.rb +17 -1
  80. data/spec/system/system_spec.rb +108 -0
  81. data/spec/tools/cmd_tlm_server/router_thread_spec.rb +2 -3
  82. metadata +31 -6
@@ -24,7 +24,8 @@ module Cosmos
24
24
  read_polling_period = 0.01,
25
25
  read_max_length = 1000,
26
26
  flow_control = :NONE,
27
- data_bits = 8)
27
+ data_bits = 8,
28
+ struct = [])
28
29
 
29
30
  # Verify Parameters
30
31
  port_name = '\\\\.\\' + port_name if port_name =~ /^COM[0-9]{2,3}$/
@@ -78,6 +79,12 @@ module Cosmos
78
79
  # 0x03 - RTS_CONTROL_TOGGLE - Specifies that the RTS line will be high if bytes are available for transmission. After all buffered bytes have been sent, the RTS line will be low.
79
80
  dcb.write('fRtsControl', 0x03)
80
81
  end
82
+ # Allow the end user to write arbitrary values into the Windows DCB structure
83
+ unless struct.empty?
84
+ struct.each do |key, value|
85
+ dcb.write(key, value.to_i)
86
+ end
87
+ end
81
88
  Win32.set_comm_state(@handle, dcb)
82
89
 
83
90
  # Configure Timeouts, the WinAPI structure is COMMTIMEOUTS:
@@ -464,9 +464,18 @@ module Cosmos
464
464
 
465
465
  protected
466
466
 
467
+ MUTEX = Mutex.new
468
+
469
+ def setup_mutex
470
+ return if @mutex
471
+ MUTEX.synchronize do
472
+ @mutex ||= Mutex.new
473
+ end
474
+ end
475
+
467
476
  # Take the structure mutex to ensure the buffer does not change while you perform activities
468
477
  def synchronize
469
- @mutex ||= Mutex.new
478
+ setup_mutex()
470
479
  @mutex.synchronize {|| yield}
471
480
  end
472
481
 
@@ -476,7 +485,7 @@ module Cosmos
476
485
  # lower level calls to go forward without getting the mutex
477
486
  def synchronize_allow_reads(top = false)
478
487
  @mutex_allow_reads ||= false
479
- @mutex ||= Mutex.new
488
+ setup_mutex()
480
489
  if top
481
490
  @mutex.synchronize do
482
491
  @mutex_allow_reads = Thread.current
@@ -9,6 +9,13 @@
9
9
  # attribution addendums as found in the LICENSE.txt
10
10
 
11
11
  module Cosmos
12
+ # Error raised by the API when a check fails
13
+ class CheckError < RuntimeError; end
14
+ # Error raised when a Script should be stopped
15
+ class StopScript < StandardError; end
16
+ # Error raised when a TestCase should be skipped by TestRunner
17
+ class SkipTestCase < StandardError; end
18
+
12
19
  module ApiShared
13
20
  DEFAULT_TLM_POLLING_RATE = 0.25
14
21
 
@@ -942,7 +949,7 @@ module Cosmos
942
949
  end
943
950
 
944
951
  def run_tlm_viewer(action, display_name = '')
945
- tlm_viewer = JsonDRbObject.new System.connect_hosts['TLMVIEWER_API'], System.ports['TLMVIEWER_API']
952
+ tlm_viewer = JsonDRbObject.new System.connect_hosts['TLMVIEWER_API'], System.ports['TLMVIEWER_API'], 1.0, Cosmos::System.x_csrf_token
946
953
  begin
947
954
  yield tlm_viewer
948
955
  tlm_viewer.disconnect
@@ -25,13 +25,6 @@ $disconnect_all_targets = false
25
25
  $cmd_tlm_replay_mode = false
26
26
 
27
27
  module Cosmos
28
- # Error raised by the API when a check fails
29
- class CheckError < RuntimeError; end
30
- # Error raised when a Script should be stopped
31
- class StopScript < StandardError; end
32
- # Error raised when a TestCase should be skipped by TestRunner
33
- class SkipTestCase < StandardError; end
34
-
35
28
  # Provides a proxy to both a disconnected CmdTlmServer instance and the real
36
29
  # JsonDRbObject which communicates with the real CmdTlmServer. If targets
37
30
  # are disconnected their method calls are forwarded to the disconnected
@@ -49,9 +42,9 @@ module Cosmos
49
42
  end
50
43
  # Start a Json connect to the real server
51
44
  if $cmd_tlm_replay_mode
52
- @cmd_tlm_server = JsonDRbObject.new(System.connect_hosts['REPLAY_API'], System.ports['REPLAY_API'])
45
+ @cmd_tlm_server = JsonDRbObject.new(System.connect_hosts['REPLAY_API'], System.ports['REPLAY_API'], 1.0, Cosmos::System.x_csrf_token)
53
46
  else
54
- @cmd_tlm_server = JsonDRbObject.new(System.connect_hosts['CTS_API'], System.ports['CTS_API'])
47
+ @cmd_tlm_server = JsonDRbObject.new(System.connect_hosts['CTS_API'], System.ports['CTS_API'], 1.0, Cosmos::System.x_csrf_token)
55
48
  end
56
49
  end
57
50
 
@@ -35,8 +35,10 @@ module Cosmos
35
35
  # complete. Pass nil to create no timeout. The {SerialDriver} will
36
36
  # continously try to read data until it has received data or an error
37
37
  # occurs.
38
- # @param flow_control [Symbol] Currently supported :NONE and :RTSCTS (default :NONE)
38
+ # @param flow_control [Symbol] Currently supported :NONE, :RTSCTS (default :NONE)
39
39
  # @param data_bits [Integer] Number of data bits (default 8)
40
+ # @param struct [Array] Array of arrays of fields and values to set in the
41
+ # Windows DCB or POSIX structure
40
42
  def initialize(write_port_name,
41
43
  read_port_name,
42
44
  baud_rate,
@@ -45,7 +47,8 @@ module Cosmos
45
47
  write_timeout,
46
48
  read_timeout,
47
49
  flow_control = :NONE,
48
- data_bits = 8)
50
+ data_bits = 8,
51
+ struct = [])
49
52
  super()
50
53
 
51
54
  # The SerialDriver class will validate the parameters
@@ -69,7 +72,8 @@ module Cosmos
69
72
  @write_timeout,
70
73
  @read_timeout,
71
74
  @flow_control,
72
- @data_bits)
75
+ @data_bits,
76
+ struct)
73
77
  else
74
78
  @write_serial_port = nil
75
79
  end
@@ -84,7 +88,8 @@ module Cosmos
84
88
  @write_timeout,
85
89
  @read_timeout,
86
90
  @flow_control,
87
- @data_bits)
91
+ @data_bits,
92
+ struct)
88
93
  end
89
94
  else
90
95
  @read_serial_port = nil
@@ -151,5 +156,5 @@ module Cosmos
151
156
  @connected = false
152
157
  end
153
158
  end
154
- end # class SerialStream
155
- end # module Cosmos
159
+ end
160
+ end
@@ -76,9 +76,18 @@ module Cosmos
76
76
  instance_attr_reader :classificiation_banner
77
77
  # @return [String] Which hashing algorithm is in use
78
78
  instance_attr_reader :hashing_algorithm
79
+ # @return [Boolean] Allow router commanding - defaults to false
80
+ instance_attr_reader :allow_router_commanding
81
+ # @return [String] API access secret using X-Csrf-Token - defaults to SuperSecret
82
+ instance_attr_reader :x_csrf_token
83
+ # @return [Array<String>] Allowed origins in http origin header - defaults to no origin header only
84
+ instance_attr_reader :allowed_origins
85
+ # @return [Array<String>] Allowed hosts in http host header - defaults to '127.0.0.1:7777' only
86
+ instance_attr_reader :allowed_hosts
79
87
 
80
88
  # Known COSMOS ports
81
89
  KNOWN_PORTS = ['CTS_API', 'TLMVIEWER_API', 'CTS_PREIDENTIFIED', 'CTS_CMD_ROUTER', 'REPLAY_API', 'REPLAY_PREIDENTIFIED', 'REPLAY_CMD_ROUTER', 'DART_STREAM', 'DART_DECOM', 'DART_MASTER']
90
+ API_PORTS = ['CTS_API', 'TLMVIEWER_API', 'REPLAY_API', 'DART_DECOM', 'DART_MASTER']
82
91
  # Known COSMOS hosts
83
92
  KNOWN_HOSTS = ['CTS_API', 'TLMVIEWER_API', 'CTS_PREIDENTIFIED', 'CTS_CMD_ROUTER', 'REPLAY_API', 'REPLAY_PREIDENTIFIED', 'REPLAY_CMD_ROUTER', 'DART_STREAM', 'DART_DECOM', 'DART_MASTER']
84
93
  # Known COSMOS paths
@@ -88,6 +97,7 @@ module Cosmos
88
97
 
89
98
  @@instance = nil
90
99
  @@instance_mutex = Mutex.new
100
+ @@instance_filename = nil
91
101
 
92
102
  # Create a new System object. Note, this should not be called directly but
93
103
  # you should instead use System.instance and treat this class as a
@@ -97,6 +107,7 @@ module Cosmos
97
107
  # read. Be default this is <Cosmos::USERPATH>/config/system/system.txt
98
108
  def initialize(filename = nil)
99
109
  raise "Cosmos::System created twice" unless @@instance.nil?
110
+ @@instance_filename = filename
100
111
  reset_variables(filename)
101
112
  @@instance = self
102
113
  end
@@ -217,6 +228,7 @@ module Cosmos
217
228
  parser.verify_num_parameters(2, 2, usage)
218
229
  port_name = parameters[0].to_s.upcase
219
230
  @ports[port_name] = Integer(parameters[1])
231
+ @allowed_hosts << "127.0.0.1:#{parameters[1]}" if API_PORTS.include?(port_name)
220
232
  Logger.warn("Unknown port name given: #{port_name}") unless KNOWN_PORTS.include?(port_name)
221
233
 
222
234
  when 'LISTEN_HOST', 'CONNECT_HOST'
@@ -373,6 +385,22 @@ module Cosmos
373
385
  @classificiation_banner = {'display_text' => parameters[0],
374
386
  'color' => color}
375
387
 
388
+ when 'ALLOW_ROUTER_COMMANDING'
389
+ parser.verify_num_parameters(0, 0, "#{keyword}")
390
+ @allow_router_commanding = true
391
+
392
+ when 'X_CSRF_TOKEN'
393
+ parser.verify_num_parameters(1, 1, "#{keyword} <Token>")
394
+ @x_csrf_token = ConfigParser.handle_nil(parameters[0])
395
+
396
+ when 'ALLOW_ORIGIN'
397
+ parser.verify_num_parameters(1, 1, "#{keyword} <Origin>")
398
+ @allowed_origins << parameters[0]
399
+
400
+ when 'ALLOW_HOST'
401
+ parser.verify_num_parameters(1, 1, "#{keyword} <Host:Port>")
402
+ @allowed_hosts << parameters[0]
403
+
376
404
  else
377
405
  # blank lines will have a nil keyword and should not raise an exception
378
406
  raise parser.error("Unknown keyword '#{keyword}'") if keyword
@@ -521,7 +549,7 @@ module Cosmos
521
549
  # Zip file configuration so unzip and reset configuration path
522
550
  configuration = unzip(configuration)
523
551
  end
524
-
552
+
525
553
  Logger.info "Switching to configuration: #{name}"
526
554
  process_file(File.join(configuration, 'system.txt'), configuration)
527
555
  load_packets(name, false)
@@ -547,7 +575,7 @@ module Cosmos
547
575
  Logger.info "Switching to initial configuration: #{@initial_config.name}"
548
576
  update_config(@initial_config)
549
577
  end
550
-
578
+
551
579
  return @config.name, nil
552
580
  end
553
581
  end
@@ -596,16 +624,14 @@ module Cosmos
596
624
  @listen_hosts = {}
597
625
  @listen_hosts['CTS_API'] = '127.0.0.1'
598
626
  @listen_hosts['TLMVIEWER_API'] = '127.0.0.1'
599
- # Localhost would be more secure but historically these are open to allow for chaining servers by default
600
- @listen_hosts['CTS_PREIDENTIFIED'] = '0.0.0.0'
601
- @listen_hosts['CTS_CMD_ROUTER'] = '0.0.0.0'
627
+ @listen_hosts['CTS_PREIDENTIFIED'] = '127.0.0.1'
628
+ @listen_hosts['CTS_CMD_ROUTER'] = '127.0.0.1'
602
629
  @listen_hosts['REPLAY_API'] = '127.0.0.1'
603
- # Localhost would be more secure but historically these are open to allow for chaining servers by default
604
- @listen_hosts['REPLAY_PREIDENTIFIED'] = '0.0.0.0'
605
- @listen_hosts['REPLAY_CMD_ROUTER'] = '0.0.0.0'
606
- @listen_hosts['DART_STREAM'] = '0.0.0.0'
607
- @listen_hosts['DART_DECOM'] = '0.0.0.0'
608
- @listen_hosts['DART_MASTER'] = '0.0.0.0'
630
+ @listen_hosts['REPLAY_PREIDENTIFIED'] = '127.0.0.1'
631
+ @listen_hosts['REPLAY_CMD_ROUTER'] = '127.0.0.1'
632
+ @listen_hosts['DART_STREAM'] = '127.0.0.1'
633
+ @listen_hosts['DART_DECOM'] = '127.0.0.1'
634
+ @listen_hosts['DART_MASTER'] = '127.0.0.1'
609
635
 
610
636
  @connect_hosts = {}
611
637
  @connect_hosts['CTS_API'] = '127.0.0.1'
@@ -630,6 +656,11 @@ module Cosmos
630
656
  @paths['DART_DATA'] = File.join(USERPATH, 'outputs', 'dart', 'data')
631
657
  @paths['DART_LOGS'] = File.join(USERPATH, 'outputs', 'dart', 'logs')
632
658
 
659
+ @allow_router_commanding = false
660
+ @x_csrf_token = 'SuperSecret'
661
+ @allowed_origins = []
662
+ @allowed_hosts = ['127.0.0.1:7777', '127.0.0.1:7778', '127.0.0.1:7877', '127.0.0.1:8779', '127.0.0.1:8780']
663
+
633
664
  unless filename
634
665
  system_arg = false
635
666
  ARGV.each do |arg|
@@ -650,7 +681,7 @@ module Cosmos
650
681
  end
651
682
 
652
683
  # Reset variables and load packets
653
- def reset(filename = nil)
684
+ def reset(filename = @@instance_filename)
654
685
  reset_variables(filename)
655
686
  load_packets()
656
687
  end
@@ -42,6 +42,9 @@ module Cosmos
42
42
  def paint(painter, option, index)
43
43
  packet_item, _, _ = @widgets[index.row]
44
44
  if index.column == 1 and packet_item and packet_item.states
45
+ painter.save
46
+ option = Qt::StyleOptionViewItemV4.new(option)
47
+ initStyleOption(option, index)
45
48
  # This code simply draws the current combo box text inside a button to
46
49
  # give the user an idea that they have to click it to activate it
47
50
  opt = Qt::StyleOptionButton.new
@@ -49,6 +52,18 @@ module Cosmos
49
52
  opt.text = @table.item(index.row, index.column).text.to_s
50
53
  Qt::Application.style.drawControl(Qt::Style::CE_PushButton, opt, painter)
51
54
  opt.dispose
55
+ painter.restore
56
+ # Not sure why but once we re-implement paint() the word wrapping
57
+ # doesn't work when we simply call super(painter, option, index)
58
+ # Thus we implement this to support word wrapping on the description
59
+ elsif index.column == 4
60
+ painter.save
61
+ option = Qt::StyleOptionViewItemV4.new(option)
62
+ initStyleOption(option, index)
63
+ option.text = index.data().toString()
64
+ option.features = Qt::StyleOptionViewItemV2::WrapText
65
+ self.parent().style().drawControl(Qt::Style.CE_ItemViewItem, option, painter)
66
+ painter.restore
52
67
  else
53
68
  super(painter, option, index)
54
69
  end
@@ -67,7 +67,7 @@ module Cosmos
67
67
  # @return [Hash] Hash keyed by parameter name with String formatted value
68
68
  def params_text(raw = false)
69
69
  params = {}
70
- Qt.execute_in_main_thread do
70
+ Qt.execute_in_main_thread do
71
71
  @param_widgets.each do |packet_item, value_item, state_value_item|
72
72
  text = value_item.text
73
73
  text = state_value_item.text if state_value_item && (text == MANUALLY or raw)
@@ -197,7 +197,7 @@ module Cosmos
197
197
  end
198
198
  end
199
199
 
200
- private
200
+ private
201
201
 
202
202
  def get_params(show_ignored)
203
203
  params = {}
@@ -322,7 +322,7 @@ module Cosmos
322
322
  value_text = "0x" + value_text.simple_formatted
323
323
  # Add quotes around STRING or BLOCK defaults so they are interpreted correctly
324
324
  elsif (packet_item.data_type == :STRING or packet_item.data_type == :BLOCK)
325
- value_text = "'#{packet_item.default}'"
325
+ value_text = "'#{value_text}'"
326
326
  end
327
327
  value_item = Qt::TableWidgetItem.new(value_text)
328
328
  value_item.setTextAlignment(Qt::AlignRight | Qt::AlignVCenter)
@@ -338,6 +338,14 @@ module Cosmos
338
338
  if item.column == 1
339
339
  if packet_item.states
340
340
  value = packet_item.states[value_item.text]
341
+ if packet_item.hazardous && packet_item.hazardous.key?(value_item.text)
342
+ desc = packet_item.hazardous[value]
343
+ # Hazardous states aren't required to have a description so use the item description
344
+ desc = packet_item.description unless desc
345
+ @table.item(item.row, 4).setText("(Hazardous) #{desc}")
346
+ else
347
+ @table.item(item.row, 4).setText(packet_item.description)
348
+ end
341
349
  @table.blockSignals(true)
342
350
  if CmdParams.states_in_hex && value.kind_of?(Integer)
343
351
  state_value_item.setText(sprintf("0x%X", value))
@@ -351,10 +359,24 @@ module Cosmos
351
359
  @table.item(item.row, 1).setText(MANUALLY)
352
360
  @table.blockSignals(false)
353
361
  end
362
+ calculate_height()
354
363
  emit modified()
355
364
  end
365
+ calculate_height()
366
+ end
367
+
368
+ def calculate_height
356
369
  @table.resizeColumnsToContents()
357
370
  @table.resizeRowsToContents()
371
+ height = @table.horizontalHeader.height + 2 # 2 = Header frame?
372
+ @table.rowCount.times do |i|
373
+ # TODO: rowHeight does not reflect word wrapping ... it's always 37
374
+ height += @table.rowHeight(i)
375
+ # NOTE: Checking the fontMetrics boundingRect also does not refect word wrapping
376
+ # e.g. Cosmos.getFontMetrics(@table.font).boundingRect(@table.item(x,y).text).height
377
+ end
378
+ @table.setMaximumHeight(height)
379
+ @table.setMinimumHeight(height)
358
380
  end
359
381
  end
360
382
  end
@@ -491,6 +491,13 @@ module Cosmos
491
491
  packet_name = @cmd_select.text
492
492
  if target_name && packet_name
493
493
  packet = System.commands.packet(target_name, packet_name)
494
+ # Directly update packet description ... safe because always in GUI thread
495
+ hazardous, _ = System.commands.cmd_hazardous?(target_name, packet_name)
496
+ if hazardous
497
+ @description.text = "(Hazardous) #{packet.description}"
498
+ else
499
+ @description.text = packet.description
500
+ end
494
501
  table = @cmd_params.update_cmd_params(packet, show_ignored: checked)
495
502
  @table_layout.addWidget(table, 500) if table
496
503
  end
@@ -56,11 +56,6 @@ module Cosmos
56
56
 
57
57
  def add_table(table)
58
58
  return unless table
59
- table.setSizePolicy(Qt::SizePolicy.Minimum, Qt::SizePolicy.Minimum)
60
- table.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff)
61
- table.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff)
62
- table.setFixedSize(table.horizontalHeader.length + table.verticalHeader.width,
63
- 2 + table.verticalHeader.length + table.horizontalHeader.height)
64
59
  @table_layout.addWidget(table)
65
60
  end
66
61
 
@@ -201,9 +201,9 @@ module Cosmos
201
201
  @json_drb.method_whitelist = @api_whitelist
202
202
  begin
203
203
  if @mode == :CMD_TLM_SERVER
204
- @json_drb.start_service(System.listen_hosts['CTS_API'], System.ports['CTS_API'], self)
204
+ @json_drb.start_service(System.listen_hosts['CTS_API'], System.ports['CTS_API'], self, 1000, System)
205
205
  else
206
- @json_drb.start_service(System.listen_hosts['REPLAY_API'], System.ports['REPLAY_API'], self)
206
+ @json_drb.start_service(System.listen_hosts['REPLAY_API'], System.ports['REPLAY_API'], self, 1000, System)
207
207
  end
208
208
  rescue Exception
209
209
  # Call packet_logging shutdown here to explicitly kill the logging
@@ -19,6 +19,11 @@ module Cosmos
19
19
  protected
20
20
 
21
21
  def handle_packet(packet)
22
+ unless System.allow_router_commanding
23
+ Logger.error "Router received command with router commanding disabled"
24
+ return
25
+ end
26
+
22
27
  # Start out assuming we will route to all associated interfaces
23
28
  interfaces = @interface.interfaces
24
29
 
@@ -653,7 +653,7 @@ module Cosmos
653
653
  end
654
654
  File.open(File.join(target_folder, 'procedures', "#{target.downcase}_noop.rb"), 'w') do |file|
655
655
  file.puts "require 'cosmos'"
656
- file.puts "require '#{File.basename(lib_filename)}'"
656
+ file.puts "load_utility '#{File.basename(lib_filename)}'"
657
657
  file.puts "\n"
658
658
  file.puts "#{target.downcase} = #{lib_filename.filename_to_class_name}.new"
659
659
  file.puts "#{target.downcase}.noop"
@@ -115,7 +115,7 @@ module Cosmos
115
115
  cover, cover_file = make_pdf_detail('cover', @pdf_cover_filename, @pdf_cover_title, target_name)
116
116
  header, header_file = make_pdf_detail('--header-spacing 3 --header-html', @pdf_header_filename, @pdf_header_title, target_name)
117
117
  footer, footer_file = make_pdf_detail('--footer-spacing 3 --footer-html', @pdf_footer_filename, @pdf_footer_title, target_name)
118
- system_call = "wkhtmltopdf -L #{@pdf_side_margin} -R #{@pdf_side_margin} -T #{@pdf_top_margin} -B #{@pdf_bottom_margin} -s Letter #{header} #{footer} #{cover} #{@pdf_toc} \"#{tmp_html_file.path}\" \"#{File.dirname(filename)}/#{File.basename(filename, '.*')}.pdf\""
118
+ system_call = "wkhtmltopdf --enable-local-file-access -L #{@pdf_side_margin} -R #{@pdf_side_margin} -T #{@pdf_top_margin} -B #{@pdf_bottom_margin} -s Letter #{header} #{footer} #{cover} #{@pdf_toc} \"#{tmp_html_file.path}\" \"#{File.dirname(filename)}/#{File.basename(filename, '.*')}.pdf\""
119
119
  status = nil
120
120
  begin
121
121
  Cosmos.set_working_dir(System.paths['HANDBOOKS']) do
@@ -385,10 +385,7 @@ module Cosmos
385
385
 
386
386
  # Print column headings to output file
387
387
  @output_file.print "%" if @matlab_header
388
- column_names().each do |column_name|
389
- @output_file.print column_name
390
- @output_file.print @delimiter
391
- end
388
+ @output_file.print column_names.join(@delimiter)
392
389
  @output_file.puts ""
393
390
  @row_index += 1
394
391
  end