cosmos 3.8.0 → 3.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/autohotkey/tools/packet_viewer.ahk +4 -0
  3. data/cosmos.gemspec +1 -1
  4. data/data/crc.txt +277 -277
  5. data/demo/Gemfile +2 -2
  6. data/demo/config/data/crc.txt +176 -176
  7. data/demo/config/targets/INST/cmd_tlm/_ccsds_cmd.txt +2 -2
  8. data/demo/config/targets/INST/cmd_tlm/inst_cmds.txt +4 -4
  9. data/demo/procedures/example_test.rb +4 -0
  10. data/install/Gemfile +1 -1
  11. data/install/config/data/crc.txt +112 -112
  12. data/lib/cosmos/config/config_parser.rb +35 -1
  13. data/lib/cosmos/core_ext/string.rb +21 -17
  14. data/lib/cosmos/core_ext/time.rb +6 -2
  15. data/lib/cosmos/gui/opengl/gl_viewer.rb +4 -4
  16. data/lib/cosmos/gui/opengl/stl_shape.rb +5 -1
  17. data/lib/cosmos/gui/qt.rb +0 -26
  18. data/lib/cosmos/io/io_multiplexer.rb +27 -45
  19. data/lib/cosmos/packets/packet.rb +64 -24
  20. data/lib/cosmos/packets/packet_config.rb +254 -54
  21. data/lib/cosmos/packets/packet_item.rb +39 -10
  22. data/lib/cosmos/packets/parsers/packet_item_parser.rb +7 -2
  23. data/lib/cosmos/script/commands.rb +5 -0
  24. data/lib/cosmos/script/scripting.rb +5 -5
  25. data/lib/cosmos/script/telemetry.rb +5 -0
  26. data/lib/cosmos/tools/cmd_tlm_server/api.rb +22 -0
  27. data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +38 -10
  28. data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +48 -9
  29. data/lib/cosmos/tools/test_runner/test_runner.rb +76 -14
  30. data/lib/cosmos/tools/tlm_viewer/widgets/linegraph_widget.rb +11 -2
  31. data/lib/cosmos/tools/tlm_viewer/widgets/timegraph_widget.rb +15 -12
  32. data/lib/cosmos/top_level.rb +29 -32
  33. data/lib/cosmos/version.rb +4 -4
  34. data/spec/config/config_parser_spec.rb +8 -15
  35. data/spec/core_ext/socket_spec.rb +2 -2
  36. data/spec/core_ext/string_spec.rb +10 -0
  37. data/spec/core_ext/time_spec.rb +12 -4
  38. data/spec/io/io_multiplexer_spec.rb +11 -3
  39. data/spec/packets/packet_spec.rb +30 -0
  40. data/spec/script/commands_spec.rb +2 -1
  41. data/spec/script/scripting_spec.rb +22 -0
  42. data/spec/script/telemetry_spec.rb +2 -1
  43. data/spec/spec_helper.rb +2 -2
  44. data/spec/tools/cmd_tlm_server/router_thread_spec.rb +2 -2
  45. data/spec/top_level/top_level_spec.rb +4 -2
  46. metadata +5 -5
@@ -366,7 +366,7 @@ module Cosmos
366
366
  end
367
367
 
368
368
  def to_xtce_type(param_or_arg, xml)
369
- # TODO: Arrays, Spline Conversions
369
+ # TODO: Spline Conversions
370
370
  case self.data_type
371
371
  when :INT, :UINT
372
372
  attrs = { :name => (self.name + '_Type') }
@@ -383,12 +383,13 @@ module Cosmos
383
383
  encoding = 'unsigned'
384
384
  end
385
385
  if @states
386
- xml['xtce'].send('Enumerated' + param_or_arg + 'Type', attrs) do
386
+ xml['xtce'].send('Enumerated' + param_or_arg + 'Type', attrs) do
387
+ to_xtce_endianness(xml)
387
388
  to_xtce_units(xml)
388
389
  xml['xtce'].IntegerDataEncoding(:sizeInBits => self.bit_size, :encoding => encoding)
389
- xml['xtce'].EnumerationList do
390
+ xml['xtce'].EnumerationList do
390
391
  @states.each do |state_name, state_value|
391
- xml['xtce'].Enumeration(:value => state_value, :label => state_name)
392
+ xml['xtce'].Enumeration(:value => state_value, :label => state_name)
392
393
  end
393
394
  end
394
395
  end
@@ -400,6 +401,7 @@ module Cosmos
400
401
  attrs[:signed] = signed
401
402
  end
402
403
  xml['xtce'].send(type_string, attrs) do
404
+ to_xtce_endianness(xml)
403
405
  to_xtce_units(xml)
404
406
  if (self.read_conversion and self.read_conversion.class == PolynomialConversion) or (self.write_conversion and self.write_conversion.class == PolynomialConversion)
405
407
  xml['xtce'].IntegerDataEncoding(:sizeInBits => self.bit_size, :encoding => encoding) do
@@ -432,6 +434,7 @@ module Cosmos
432
434
  attrs[:initialValue] = self.default if self.default and !self.array_size
433
435
  attrs[:shortDescription] = self.description if self.description
434
436
  xml['xtce'].send('Float' + param_or_arg + 'Type', attrs) do
437
+ to_xtce_endianness(xml)
435
438
  to_xtce_units(xml)
436
439
  if (self.read_conversion and self.read_conversion.class == PolynomialConversion) or (self.write_conversion and self.write_conversion.class == PolynomialConversion)
437
440
  xml['xtce'].FloatDataEncoding(:sizeInBits => self.bit_size, :encoding => 'IEEE754_1985') do
@@ -467,9 +470,10 @@ module Cosmos
467
470
  attrs[:initialValue] = self.default if self.default and !self.array_size
468
471
  attrs[:shortDescription] = self.description if self.description
469
472
  xml['xtce'].send('String' + param_or_arg + 'Type', attrs) do
473
+ to_xtce_endianness(xml)
470
474
  to_xtce_units(xml)
471
475
  xml['xtce'].StringDataEncoding(:encoding => 'UTF-8') do
472
- xml['xtce'].SizeInBits do
476
+ xml['xtce'].SizeInBits do
473
477
  xml['xtce'].Fixed do
474
478
  xml['xtce'].FixedValue(self.bit_size.to_s)
475
479
  end
@@ -483,9 +487,10 @@ module Cosmos
483
487
  attrs[:shortDescription] = self.description if self.description
484
488
  #attrs[:initialValue] = self.default if self.default and !self.array_size
485
489
  xml['xtce'].send('Binary' + param_or_arg + 'Type', attrs) do
490
+ to_xtce_endianness(xml)
486
491
  to_xtce_units(xml)
487
492
  xml['xtce'].BinaryDataEncoding do
488
- xml['xtce'].SizeInBits do
493
+ xml['xtce'].SizeInBits do
489
494
  xml['xtce'].FixedValue(self.bit_size.to_s)
490
495
  end
491
496
  end
@@ -493,10 +498,24 @@ module Cosmos
493
498
  when :DERIVED
494
499
  raise "DERIVED data type not supported in XTCE"
495
500
  end
501
+
502
+ # Handle arrays
503
+ if self.array_size
504
+ # The above will have created the type for the array entries. Now we create the type for the actual array.
505
+ attrs = { :name => (self.name + '_ArrayType') }
506
+ attrs[:shortDescription] = self.description if self.description
507
+ attrs[:arrayTypeRef] = (self.name + '_Type')
508
+ attrs[:numberOfDimensions] = '1' # COSMOS Only supports one-dimensional arrays
509
+ xml['xtce'].send('Array' + param_or_arg + 'Type', attrs)
510
+ end
496
511
  end
497
512
 
498
513
  def to_xtce_item(param_or_arg, xml)
499
- xml['xtce'].send(param_or_arg, :name => self.name, "#{param_or_arg.downcase}TypeRef" => self.name + '_Type')
514
+ if self.array_size
515
+ xml['xtce'].send(param_or_arg, :name => self.name, "#{param_or_arg.downcase}TypeRef" => self.name + '_ArrayType')
516
+ else
517
+ xml['xtce'].send(param_or_arg, :name => self.name, "#{param_or_arg.downcase}TypeRef" => self.name + '_Type')
518
+ end
500
519
  end
501
520
 
502
521
  protected
@@ -511,6 +530,16 @@ module Cosmos
511
530
  end
512
531
  end
513
532
 
533
+ def to_xtce_endianness(xml)
534
+ if self.endianness == :LITTLE_ENDIAN and self.bit_size > 8
535
+ xml['xtce'].ByteOrderList do
536
+ (((self.bit_size - 1)/ 8) + 1).times do |byte_significance|
537
+ xml['xtce'].Byte(:byteSignificance => byte_significance)
538
+ end
539
+ end
540
+ end
541
+ end
542
+
514
543
  def to_xtce_conversion(xml)
515
544
  if self.read_conversion
516
545
  conversion = self.read_conversion
@@ -519,11 +548,11 @@ module Cosmos
519
548
  end
520
549
  if conversion and conversion.class == PolynomialConversion
521
550
  xml['xtce'].DefaultCalibrator do
522
- xml['xtce'].PolynomialCalibrator do
551
+ xml['xtce'].PolynomialCalibrator do
523
552
  conversion.coeffs.each_with_index do |coeff, index|
524
- xml['xtce'].Term(:coefficient => coeff, :exponent => index)
553
+ xml['xtce'].Term(:coefficient => coeff, :exponent => index)
525
554
  end
526
- end
555
+ end
527
556
  end
528
557
  end
529
558
  end
@@ -119,7 +119,11 @@ module Cosmos
119
119
  return nil if data_type == :STRING or data_type == :BLOCK
120
120
 
121
121
  index = append? ? 3 : 4
122
- (ConfigParser.handle_defined_constants(@parser.parameters[index].convert_to_value))..(ConfigParser.handle_defined_constants(@parser.parameters[index+1].convert_to_value))
122
+ min = ConfigParser.handle_defined_constants(
123
+ @parser.parameters[index].convert_to_value, get_data_type(), get_bit_size())
124
+ max = ConfigParser.handle_defined_constants(
125
+ @parser.parameters[index+1].convert_to_value, get_data_type(), get_bit_size())
126
+ min..max
123
127
  end
124
128
 
125
129
  def get_default
@@ -130,7 +134,8 @@ module Cosmos
130
134
  if data_type == :STRING or data_type == :BLOCK
131
135
  return @parser.parameters[index]
132
136
  else
133
- return ConfigParser.handle_defined_constants(@parser.parameters[index+2].convert_to_value)
137
+ return ConfigParser.handle_defined_constants(
138
+ @parser.parameters[index+2].convert_to_value, get_data_type(), get_bit_size())
134
139
  end
135
140
  end
136
141
 
@@ -178,6 +178,11 @@ module Cosmos
178
178
  results
179
179
  end
180
180
 
181
+ # Returns the buffer from the most recent specified command
182
+ def get_cmd_buffer(target_name, command_name)
183
+ return $cmd_tlm_server.get_cmd_buffer(target_name, command_name)
184
+ end
185
+
181
186
  end # module Script
182
187
 
183
188
  end # module Cosmos
@@ -596,13 +596,13 @@ module Cosmos
596
596
  when 3
597
597
  target_name, packet_name, item_name = extract_fields_from_tlm_text(args[0])
598
598
  expected_value = args[1]
599
- tolerance = args[2]
599
+ tolerance = args[2].abs
600
600
  when 5
601
601
  target_name = args[0]
602
602
  packet_name = args[1]
603
603
  item_name = args[2]
604
604
  expected_value = args[3]
605
- tolerance = args[4]
605
+ tolerance = args[4].abs
606
606
  else
607
607
  # Invalid number of arguments
608
608
  raise "ERROR: Invalid number of arguments (#{args.length}) passed to #{function_name}()"
@@ -676,7 +676,7 @@ module Cosmos
676
676
  when 4, 5
677
677
  target_name, packet_name, item_name = extract_fields_from_tlm_text(args[0])
678
678
  expected_value = args[1]
679
- tolerance = args[2]
679
+ tolerance = args[2].abs
680
680
  timeout = args[3]
681
681
  if args.length == 5
682
682
  polling_rate = args[4]
@@ -688,7 +688,7 @@ module Cosmos
688
688
  packet_name = args[1]
689
689
  item_name = args[2]
690
690
  expected_value = args[3]
691
- tolerance = args[4]
691
+ tolerance = args[4].abs
692
692
  timeout = args[5]
693
693
  if args.length == 7
694
694
  polling_rate = args[6]
@@ -799,7 +799,7 @@ module Cosmos
799
799
 
800
800
  def cosmos_script_wait_implementation_tolerance(target_name, packet_name, item_name, value_type, expected_value, tolerance, timeout, polling_rate = DEFAULT_TLM_POLLING_RATE)
801
801
  _cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, timeout, polling_rate) do
802
- "((#{expected_value} - #{tolerance})..(#{expected_value} + #{tolerance})).include? value"
802
+ "((#{expected_value} - #{tolerance.abs})..(#{expected_value} + #{tolerance.abs})).include? value"
803
803
  end
804
804
  end
805
805
 
@@ -122,6 +122,11 @@ module Cosmos
122
122
  $cmd_tlm_server.get_tlm_details(items)
123
123
  end
124
124
 
125
+ # Returns the buffer from the telemetry packet.
126
+ def get_tlm_buffer(target_name, packet_name)
127
+ return $cmd_tlm_server.get_tlm_buffer(target_name, packet_name)
128
+ end
129
+
125
130
  # Subscribe to one or more telemetry packets. The queue ID is returned for
126
131
  # use in get_packet_data and unsubscribe_packet_data.
127
132
  # Usage:
@@ -28,6 +28,7 @@ module Cosmos
28
28
  'cmd_raw_no_hazardous_check',
29
29
  'cmd_raw_no_checks',
30
30
  'send_raw',
31
+ 'get_cmd_buffer',
31
32
  'get_cmd_list',
32
33
  'get_cmd_param_list',
33
34
  'get_cmd_hazardous',
@@ -40,6 +41,7 @@ module Cosmos
40
41
  'tlm_variable',
41
42
  'set_tlm',
42
43
  'set_tlm_raw',
44
+ 'get_tlm_buffer',
43
45
  'get_tlm_packet',
44
46
  'get_tlm_values',
45
47
  'get_tlm_list',
@@ -226,6 +228,16 @@ module Cosmos
226
228
  nil
227
229
  end
228
230
 
231
+ # Returns the raw buffer from the most recent specified command packet.
232
+ #
233
+ # @param target_name [String] Target name of the command
234
+ # @param command_name [String] Packet name of the command
235
+ # @return [String] last command buffer packet
236
+ def get_cmd_buffer(target_name, command_name)
237
+ packet = System.commands.packet(target_name, command_name)
238
+ return packet.buffer
239
+ end
240
+
229
241
  # Returns the list of all the command names and their descriptions from the
230
242
  # given target.
231
243
  #
@@ -480,6 +492,16 @@ module Cosmos
480
492
  nil
481
493
  end
482
494
 
495
+ # Returns the raw buffer for a telemetry packet.
496
+ #
497
+ # @param target_name [String] Name of the target
498
+ # @param packet_name [String] Name of the packet
499
+ # @return [String] last telemetry packet buffer
500
+ def get_tlm_buffer(target_name, packet_name)
501
+ packet = System.telemetry.packet(target_name, packet_name)
502
+ return packet.buffer
503
+ end
504
+
483
505
  # Returns all the values (along with their limits state) for a packet.
484
506
  #
485
507
  # @param target_name [String] Name of the target
@@ -58,6 +58,12 @@ module Cosmos
58
58
  attr_reader :ignored
59
59
  # @return [Boolean] Whether the limits items have been fetched from the server
60
60
  attr_reader :initialized
61
+ # @return [Boolean] Whether to display an item with a colorblind option
62
+ attr_accessor :colorblind
63
+ # @return [Boolean] Whether to display an item with operational limits while it's
64
+ # currently green. If false, items are not displayed until they go yellow
65
+ # or red. If true, items are displayed when transitioning from blue to green.
66
+ attr_accessor :monitor_operational
61
67
 
62
68
  UNKNOWN_ARRAY = ['UNKNOWN', 'UNKNOWN', nil]
63
69
 
@@ -73,6 +79,8 @@ module Cosmos
73
79
  @out_of_limits = []
74
80
  @queue_id = nil
75
81
  @limits_set = :DEFAULT
82
+ @colorblind = false
83
+ @monitor_operational = true
76
84
  request_reset()
77
85
  end
78
86
 
@@ -237,6 +245,10 @@ module Cosmos
237
245
  @ignored << ([params[0], params[1], params[2]])
238
246
  when 'IGNORE_PACKET'
239
247
  @ignored << ([params[0], params[1], nil])
248
+ when 'COLOR_BLIND'
249
+ @colorblind = true
250
+ when 'IGNORE_OPERATIONAL_LIMITS'
251
+ @monitor_operational = false
240
252
  end
241
253
  end
242
254
  result = "#{filename} loaded. "
@@ -256,6 +268,12 @@ module Cosmos
256
268
  def save_config(filename)
257
269
  begin
258
270
  File.open(filename, "w") do |file|
271
+ if @colorblind
272
+ file.puts("COLOR_BLIND")
273
+ end
274
+ unless @monitor_operational
275
+ file.puts("IGNORE_OPERATIONAL_LIMITS")
276
+ end
259
277
  @ignored.each do |target, pkt_name, item_name|
260
278
  if item_name
261
279
  file.puts("IGNORE_ITEM #{target} #{pkt_name} #{item_name}")
@@ -311,7 +329,11 @@ module Cosmos
311
329
  message << "ERROR: "
312
330
  color = :RED
313
331
  out_of_limit(item)
314
- when :GREEN, :GREEN_HIGH, :GREEN_LOW
332
+ when :GREEN_HIGH, :GREEN_LOW
333
+ message << "INFO: "
334
+ color = :GREEN
335
+ out_of_limit(item) if @monitor_operational
336
+ when :GREEN
315
337
  message << "INFO: "
316
338
  color = :GREEN
317
339
  when :BLUE
@@ -343,6 +365,8 @@ module Cosmos
343
365
  # encountered by the COSMOS server. It provides the ability to ignore and
344
366
  # restore limits as well as logs all limits events.
345
367
  class LimitsMonitor < QtTool
368
+ attr_reader :limits_items
369
+
346
370
  # LimitsWidget displays either a stale packet using the Label widget
347
371
  # or more commonly an out of limits item using the Labelvaluelimitsbar
348
372
  # Widget.
@@ -364,7 +388,7 @@ module Cosmos
364
388
  item = [target_name, packet_name, item_name]
365
389
  if item_name
366
390
  @value = LabelvaluelimitsbarWidget.new(@layout, target_name, packet_name, item_name)
367
- @value.set_setting('COLORBLIND', [@colorblind])
391
+ @value.set_setting('COLORBLIND', [parent.limits_items.colorblind])
368
392
  @value.process_settings
369
393
  else
370
394
  @value = LabelWidget.new(layout, "#{target_name} #{packet_name} is STALE")
@@ -530,7 +554,9 @@ module Cosmos
530
554
  dialog.setWindowTitle('Options')
531
555
 
532
556
  colorblind_box = Qt::CheckBox.new('Colorblind Mode Enabled', self)
533
- colorblind_box.setCheckState(Qt::Checked) if @colorblind
557
+ colorblind_box.setCheckState(Qt::Checked) if @limits_items.colorblind
558
+ operational_limit_box = Qt::CheckBox.new('Monitor Operational Limits', self)
559
+ operational_limit_box.setCheckState(Qt::Checked) if @limits_items.monitor_operational
534
560
 
535
561
  ok = Qt::PushButton.new('Ok') do
536
562
  connect(SIGNAL('clicked()')) { dialog.accept }
@@ -544,18 +570,24 @@ module Cosmos
544
570
  end
545
571
  dialog.layout = Qt::VBoxLayout.new do
546
572
  addWidget(colorblind_box)
573
+ addWidget(operational_limit_box)
547
574
  addLayout(buttons)
548
575
  end
549
576
 
550
577
  case dialog.exec
551
578
  when Qt::Dialog::Accepted
579
+ if (operational_limit_box.checkState() == Qt::Checked)
580
+ @limits_items.monitor_operational = true
581
+ else
582
+ @limits_items.monitor_operational = false
583
+ end
552
584
  if (colorblind_box.checkState() == Qt::Checked)
553
- @colorblind = true
585
+ @limits_items.colorblind = true
554
586
  else
555
- @colorblind = false
587
+ @limits_items.colorblind = false
556
588
  end
557
589
  (0...@scroll_layout.count).each do |index|
558
- @scroll_layout.itemAt(index).widget.set_colorblind(@colorblind)
590
+ @scroll_layout.itemAt(index).widget.set_colorblind(@limits_items.colorblind)
559
591
  end
560
592
  end
561
593
  dialog.dispose
@@ -784,10 +816,6 @@ module Cosmos
784
816
  palette = Cosmos.getPalette(Cosmos.getColor(0, 0, 0), Cosmos.getColor(255,0,0))
785
817
  @monitored_state_text_field.setPalette(palette)
786
818
  text = 'Red'
787
- when :BLUE
788
- palette = Cosmos.getPalette(Cosmos.getColor(0, 0, 0), Cosmos.getColor(0,0,255))
789
- @monitored_state_text_field.setPalette(palette)
790
- text = 'Blue'
791
819
  end
792
820
  text << ' - Some Items Ignored' if @limits_items.ignored_items?
793
821
  @monitored_state_text_field.text = text
@@ -116,6 +116,14 @@ module Cosmos
116
116
  end
117
117
  end
118
118
 
119
+ @derived_last_action = Qt::Action.new(tr('&Display Derived Last'), self)
120
+ @derived_last_keyseq = Qt::KeySequence.new(tr('Ctrl+D'))
121
+ @derived_last_action.shortcut = @derived_last_keyseq
122
+ @derived_last_action.statusTip = tr('Display derived telemetry items last')
123
+ @derived_last_action.setCheckable(true)
124
+ @derived_last_action.setChecked(false)
125
+ @derived_last_action.connect(SIGNAL('triggered()')) { update_tlm_items() }
126
+
119
127
  @formatted_tlm_units_action = Qt::Action.new(tr('Formatted Telemetry With &Units'), self)
120
128
  @formatted_tlm_units_keyseq = Qt::KeySequence.new(tr('Ctrl+U'))
121
129
  @formatted_tlm_units_action.shortcut = @formatted_tlm_units_keyseq
@@ -177,6 +185,7 @@ module Cosmos
177
185
  view_menu = menuBar.addMenu(tr('&View'))
178
186
  view_menu.addAction(@color_blind_action)
179
187
  view_menu.addAction(@hide_ignored_action)
188
+ view_menu.addAction(@derived_last_action)
180
189
  view_menu.addSeparator.setText(tr('Formatting'));
181
190
  view_menu.addAction(@formatted_tlm_units_action)
182
191
  view_menu.addAction(@formatted_tlm_action)
@@ -253,7 +262,8 @@ module Cosmos
253
262
  end
254
263
 
255
264
  def file_options
256
- @polling_rate = Qt::InputDialog.getDouble(self, tr("Options"), tr("Polling Rate (sec):"), @polling_rate, 0, 1000, 1, nil)
265
+ @polling_rate = Qt::InputDialog.getDouble(self, tr("Options"), tr("Polling Rate (sec):"),
266
+ @polling_rate, 0, 1000, 1, nil)
257
267
  end
258
268
 
259
269
  def update_all
@@ -330,8 +340,22 @@ module Cosmos
330
340
  # Update Telemetry Items
331
341
  tlm_items = []
332
342
  begin
333
- System.telemetry.items(target_name, packet_name).each do |item|
334
- tlm_items << [item.name, item.states, item.description]
343
+ @derived_row = 0
344
+ if @derived_last_action.isChecked
345
+ derived = []
346
+ System.telemetry.items(target_name, packet_name).each do |item|
347
+ if item.data_type == :DERIVED
348
+ derived << [item.name, item.states, item.description]
349
+ else
350
+ tlm_items << [item.name, item.states, item.description]
351
+ @derived_row += 1
352
+ end
353
+ end
354
+ tlm_items.concat(derived) # Tack the derived onto the end
355
+ else
356
+ System.telemetry.items(target_name, packet_name).each do |item|
357
+ tlm_items << [item.name, item.states, item.description]
358
+ end
335
359
  end
336
360
  rescue
337
361
  # Unknown packet
@@ -371,9 +395,11 @@ module Cosmos
371
395
 
372
396
  # Handle Table Clicks
373
397
  @table.setMouseTracking(true)
374
- connect(@table, SIGNAL('cellEntered(int, int)'), self, SLOT('mouse_over(int, int)'))
398
+ connect(@table, SIGNAL('cellEntered(int, int)'),
399
+ self, SLOT('mouse_over(int, int)'))
375
400
  @table.setContextMenuPolicy(Qt::CustomContextMenu)
376
- connect(@table, SIGNAL('customContextMenuRequested(const QPoint&)'), self, SLOT('context_menu(const QPoint&)'))
401
+ connect(@table, SIGNAL('customContextMenuRequested(const QPoint&)'),
402
+ self, SLOT('context_menu(const QPoint&)'))
377
403
 
378
404
  # Start Update Thread
379
405
  update_needed = false
@@ -403,15 +429,23 @@ module Cosmos
403
429
 
404
430
  Qt.execute_in_main_thread(true) do
405
431
  # If we need an update (which indicates we've reconnected to the server)
406
- # Then we call update_all which will update all the telemetry items and kill and respawn this thread
432
+ # Then we call update_all which will update all the telemetry items
433
+ # and kill and respawn this thread
407
434
  if update_needed
408
435
  update_all()
409
436
  end
410
437
 
411
438
  if tlm_items
412
- row = 0
439
+ # Start with wherever the first derived item is
440
+ # See above where we populate tlm_items
441
+ row = @derived_row
413
442
  tlm_items.each do |name, value, limits_state|
414
443
  text = value.to_s
444
+ # If derived is last we need to reset the row to 0
445
+ # to start populating the real items at the top
446
+ if row == (tlm_items.length)
447
+ row = 0
448
+ end
415
449
 
416
450
  case limits_state
417
451
  when :GREEN, :GREEN_HIGH
@@ -527,7 +561,8 @@ module Cosmos
527
561
  options.height = 200
528
562
  options.title = 'Packet Viewer : Formatted Telemetry with Units'
529
563
  option_parser.separator "Packet Viewer Specific Options:"
530
- option_parser.on("-p", "--packet 'TARGET_NAME PACKET_NAME'", "Start viewing the specified packet") do |arg|
564
+ option_parser.on("-p", "--packet 'TARGET_NAME PACKET_NAME'",
565
+ "Start viewing the specified packet") do |arg|
531
566
  split = arg.split
532
567
  if split.length != 2
533
568
  puts "Packet must be specified as 'TARGET_NAME PACKET_NAME' in quotes"
@@ -535,7 +570,10 @@ module Cosmos
535
570
  end
536
571
  options.packet = split
537
572
  end
538
- option_parser.on("-r", "--rate PERIOD", "Set the polling rate to PERIOD (unit seconds)") { |arg| options.rate = Float(arg) }
573
+ option_parser.on("-r", "--rate PERIOD",
574
+ "Set the polling rate to PERIOD (unit seconds)") do |arg|
575
+ options.rate = Float(arg)
576
+ end
539
577
  end
540
578
 
541
579
  super(option_parser, options)
@@ -545,3 +583,4 @@ module Cosmos
545
583
  end # class PacketViewer
546
584
 
547
585
  end # module Cosmos
586
+