cosmos 4.4.0 → 4.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +5 -5
  2. data/.dockerignore +2 -0
  3. data/.gitignore +1 -0
  4. data/.travis.yml +6 -6
  5. data/Dockerfile +65 -0
  6. data/Manifest.txt +12 -2
  7. data/README.md +5 -0
  8. data/Rakefile +52 -0
  9. data/appveyor.yml +18 -8
  10. data/autohotkey/config/tools/cmd_sequence/cmd_sequence.txt +2 -0
  11. data/autohotkey/lib/cmd_sequence_exporter.rb +52 -0
  12. data/autohotkey/procedures/collect.rb +2 -2
  13. data/autohotkey/procedures/collect_util.rb +1 -1
  14. data/autohotkey/procedures/script_test.rb +1 -1
  15. data/autohotkey/tools/CmdSenderAHK2 +18 -0
  16. data/autohotkey/tools/cmd_sender.ahk +34 -6
  17. data/autohotkey/tools/cmd_sender2.ahk +4 -0
  18. data/autohotkey/tools/cmd_sequence.ahk +21 -8
  19. data/autohotkey/tools/config_editor.ahk +4 -4
  20. data/bin/cstol_converter +1 -1
  21. data/cosmos.gemspec +1 -1
  22. data/data/config/command_modifiers.yaml +16 -1
  23. data/data/config/param_item_modifiers.yaml +5 -0
  24. data/data/config/system.yaml +31 -1
  25. data/data/config/telemetry_modifiers.yaml +16 -1
  26. data/data/crc.txt +415 -410
  27. data/demo/config/dart/Gemfile +1 -6
  28. data/demo/config/data/crc.txt +244 -243
  29. data/demo/config/system/system.txt +3 -0
  30. data/demo/config/system/system2.txt +3 -0
  31. data/demo/config/system/system_alt_ports.txt +3 -0
  32. data/demo/config/targets/INST/cmd_tlm/inst_cmds.txt +3 -3
  33. data/demo/config/targets/INST/cmd_tlm/inst_tlm.txt +4 -0
  34. data/demo/config/targets/INST/cmd_tlm/inst_tlm_override.txt +12 -0
  35. data/demo/config/targets/INST/lib/sim_inst.rb +2 -2
  36. data/demo/config/targets/INST/target.txt +1 -0
  37. data/demo/procedures/cosmos_api_test.rb +8 -8
  38. data/install/config/dart/Gemfile +2 -7
  39. data/install/config/data/crc.txt +143 -143
  40. data/install/config/system/system.txt +3 -0
  41. data/lib/cosmos/dart/config/boot.rb +1 -1
  42. data/lib/cosmos/dart/config/database.yml +2 -0
  43. data/lib/cosmos/dart/lib/dart_common.rb +11 -4
  44. data/lib/cosmos/dart/lib/dart_constants.rb +15 -0
  45. data/lib/cosmos/dart/lib/dart_decom_query.rb +5 -6
  46. data/lib/cosmos/dart/lib/dart_decommutator.rb +66 -56
  47. data/lib/cosmos/dart/lib/dart_master_query.rb +71 -0
  48. data/lib/cosmos/dart/lib/dart_reducer_worker_thread.rb +165 -134
  49. data/lib/cosmos/dart/processes/dart.rb +4 -2
  50. data/lib/cosmos/dart/processes/dart_decom_server.rb +2 -2
  51. data/lib/cosmos/dart/processes/dart_ingester.rb +38 -1
  52. data/lib/cosmos/dart/processes/dart_master.rb +44 -0
  53. data/lib/cosmos/dart/processes/dart_util.rb +115 -0
  54. data/lib/cosmos/gui/widgets/dart_meta_frame.rb +21 -2
  55. data/lib/cosmos/interfaces/protocols/length_protocol.rb +5 -0
  56. data/lib/cosmos/io/json_drb.rb +3 -3
  57. data/lib/cosmos/io/posix_serial_driver.rb +1 -1
  58. data/lib/cosmos/io/win32_serial_driver.rb +23 -2
  59. data/lib/cosmos/packet_logs/packet_log_reader.rb +2 -2
  60. data/lib/cosmos/packets/packet.rb +1 -1
  61. data/lib/cosmos/packets/packet_config.rb +26 -8
  62. data/lib/cosmos/packets/structure.rb +17 -0
  63. data/lib/cosmos/packets/structure_item.rb +5 -1
  64. data/lib/cosmos/packets/telemetry.rb +7 -1
  65. data/lib/cosmos/system/system.rb +115 -48
  66. data/lib/cosmos/tools/cmd_sender/cmd_params.rb +360 -0
  67. data/lib/cosmos/tools/cmd_sender/cmd_sender.rb +23 -319
  68. data/lib/cosmos/tools/cmd_sequence/cmd_sequence.rb +14 -17
  69. data/lib/cosmos/tools/cmd_sequence/sequence_item.rb +43 -331
  70. data/lib/cosmos/tools/cmd_sequence/sequence_list.rb +16 -11
  71. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +1 -0
  72. data/lib/cosmos/tools/config_editor/config_editor.rb +33 -2
  73. data/lib/cosmos/tools/config_editor/config_editor_frame.rb +8 -9
  74. data/lib/cosmos/tools/config_editor/system_config_dialog.rb +158 -0
  75. data/lib/cosmos/tools/script_runner/script_runner_frame.rb +2 -2
  76. data/lib/cosmos/tools/test_runner/test.rb +5 -2
  77. data/lib/cosmos/tools/test_runner/test_runner.rb +2 -2
  78. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_processor.rb +17 -13
  79. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_dart_thread.rb +20 -16
  80. data/lib/cosmos/tools/tlm_grapher/tlm_grapher.rb +18 -11
  81. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +16 -5
  82. data/lib/cosmos/utilities/ruby_lex_utils.rb +34 -30
  83. data/lib/cosmos/version.rb +4 -4
  84. data/lib/cosmos/win32/excel.rb +23 -17
  85. data/run_gui_tests.bat +1 -0
  86. data/spec/core_ext/socket_spec.rb +1 -1
  87. data/spec/install/yaml_docs_spec.rb +26 -6
  88. data/spec/interfaces/protocols/length_protocol_spec.rb +39 -0
  89. data/spec/io/json_drb_spec.rb +14 -0
  90. data/spec/io/win32_serial_driver_spec.rb +16 -2
  91. data/spec/packet_logs/packet_log_reader_spec.rb +2 -2
  92. data/spec/packets/structure_spec.rb +52 -2
  93. data/spec/packets/telemetry_spec.rb +29 -1
  94. data/spec/system/system_spec.rb +2 -2
  95. data/spec/utilities/message_log_spec.rb +6 -3
  96. data/tasks/gemfile_stats.rake +22 -13
  97. metadata +17 -7
  98. data/lib/cosmos/dart/Gemfile +0 -69
@@ -30,7 +30,8 @@ class Dart
30
30
  # streamed from the packet log binary file
31
31
  # 4. Decom Server - JSON DRB server which handles requests for decommutated
32
32
  # or reduced data from the database
33
- # 5..n Worker - Decommutates data from the packet log binary file into the DB
33
+ # 5. Master - Hands out packets to be decommutated by workers
34
+ # 6..n Worker - Decommutates data from the packet log binary file into the DB
34
35
  def run
35
36
  Cosmos::Logger.level = Cosmos::Logger::INFO
36
37
  dart_logging = DartLogging.new('dart')
@@ -53,7 +54,8 @@ class Dart
53
54
  [ruby_process_name, File.join(__dir__, 'dart_ingester.rb')],
54
55
  [ruby_process_name, File.join(__dir__, 'dart_reducer.rb')],
55
56
  [ruby_process_name, File.join(__dir__, 'dart_stream_server.rb')],
56
- [ruby_process_name, File.join(__dir__, 'dart_decom_server.rb')]
57
+ [ruby_process_name, File.join(__dir__, 'dart_decom_server.rb')],
58
+ [ruby_process_name, File.join(__dir__, 'dart_master.rb')]
57
59
  ]
58
60
 
59
61
  num_workers.times do |index|
@@ -26,8 +26,8 @@ Cosmos.catch_fatal_exception do
26
26
  begin
27
27
  json_drb.start_service(Cosmos::System.listen_hosts['DART_DECOM'],
28
28
  Cosmos::System.ports['DART_DECOM'], DartDecomQuery.new)
29
- rescue Exception
30
- raise Cosmos::FatalError.new("Error starting JsonDRb on port #{Cosmos::System.ports['DART_DECOM']}.\nPerhaps another DART Decom Server is already running?")
29
+ rescue Exception => error
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
32
32
  ["TERM", "INT"].each {|sig| Signal.trap(sig) {exit}}
33
33
  Cosmos::Logger.info("Dart Decom Server Started...")
@@ -16,20 +16,57 @@ require 'dart_logging'
16
16
  # Handles packets by writing them to the dart log file. New SYSTEM META packets
17
17
  # cause a new log file to be started.
18
18
  class DartInterfaceThread < Cosmos::InterfaceThread
19
+ include DartCommon
20
+
19
21
  attr_writer :packet_log_writer
20
22
  attr_writer :log_type
21
-
23
+
22
24
  def handle_packet(packet)
23
25
  if packet.target_name == 'SYSTEM'.freeze and packet.packet_name == 'META'.freeze
24
26
  Cosmos::Logger.info("#{@log_type}: #{packet.target_name} #{packet.packet_name}")
27
+
28
+ # Manually read the configuration from the buffer because the packet might not be identified if
29
+ # identify_and_define is false
30
+ buffer = packet.buffer(false)
31
+ if buffer.length >= 33
32
+ system_config_name = Cosmos::BinaryAccessor.read(8, 256, :STRING, buffer, :BIG_ENDIAN)
33
+ # Switch to this system_config
34
+ begin
35
+ switch_and_get_system_config(system_config_name)
36
+ rescue Exception => e
37
+ Cosmos::Logger.error(e.formatted)
38
+ Cosmos::Logger.error("Could not load system_config: #{system_config_name}")
39
+ end
40
+ end
41
+
25
42
  # Update Current Value Table Used By Packet Log Writer
26
43
  cvt_packet = Cosmos::System.telemetry.update!(packet.target_name, packet.packet_name, packet.buffer)
27
44
  cvt_packet.received_time = packet.received_time
28
45
  cvt_packet.stored = packet.stored
29
46
  cvt_packet.extra = packet.extra
47
+
30
48
  @packet_log_writer.start
31
49
  @packet_log_writer.write(cvt_packet)
32
50
  else
51
+ # Define the packet so that packet_time will work correctly
52
+ begin
53
+ packet_data = packet.buffer(false)
54
+ received_time = packet.received_time
55
+ stored = packet.stored
56
+ extra = packet.extra
57
+ if @log_type == :TLM
58
+ packet = Cosmos::System.telemetry.packet(packet.target_name, packet.packet_name)
59
+ else
60
+ packet = Cosmos::System.commands.packet(packet.target_name, packet.packet_name)
61
+ end
62
+ packet.buffer = packet_data
63
+ packet.received_time = received_time
64
+ packet.stored = stored
65
+ packet.extra = extra
66
+ rescue Exception => error
67
+ # Could not find a definition for this packet
68
+ Cosmos::Logger.error "Unknown packet #{target_name} #{packet_name}"
69
+ end
33
70
  @packet_log_writer.write(packet)
34
71
  end
35
72
  end
@@ -0,0 +1,44 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2018 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+
11
+ ENV['RAILS_ENV'] = 'production'
12
+ require File.expand_path('../../config/environment', __FILE__)
13
+ require 'dart_common'
14
+ require 'dart_master_query'
15
+
16
+ ples_per_request = ENV['DART_PLE_REQ_SIZE']
17
+ ples_per_request ||= 5
18
+ ples_per_request = ples_per_request.to_i
19
+
20
+ Cosmos.catch_fatal_exception do
21
+ DartCommon.handle_argv
22
+
23
+ Cosmos::Logger.level = Cosmos::Logger::INFO
24
+ dart_logging = DartLogging.new('dart_master')
25
+
26
+ json_drb = Cosmos::JsonDRb.new
27
+ json_drb.acl = Cosmos::System.acl if Cosmos::System.acl
28
+ begin
29
+ json_drb.method_whitelist = ['get_decom_ple_ids']
30
+ begin
31
+ json_drb.start_service(Cosmos::System.listen_hosts['DART_MASTER'],
32
+ Cosmos::System.ports['DART_MASTER'], DartMasterQuery.new(ples_per_request))
33
+ rescue Exception => error
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
+ end
36
+ ["TERM", "INT"].each {|sig| Signal.trap(sig) {exit}}
37
+ Cosmos::Logger.info("Dart Master Started...")
38
+ sleep(1) while true
39
+ rescue Interrupt
40
+ Cosmos::Logger.info("Dart Master Closing...")
41
+ json_drb.stop_service
42
+ dart_logging.stop
43
+ end
44
+ end
@@ -56,6 +56,8 @@ ENV['RAILS_ENV'] = 'production'
56
56
  require File.expand_path('../../config/environment', __FILE__)
57
57
  require 'dart_database_cleaner'
58
58
 
59
+ include DartCommon
60
+
59
61
  Cosmos.catch_fatal_exception do
60
62
  case action.downcase
61
63
  when 'showpleerrors'
@@ -77,6 +79,119 @@ Cosmos.catch_fatal_exception do
77
79
  Cosmos::Logger.level = Cosmos::Logger::INFO
78
80
  DartDatabaseCleaner.new.remove_packet_log(ARGV[1])
79
81
 
82
+ when 'showdatabase'
83
+ puts "Status:"
84
+ status = Status.last
85
+ puts " Updated At: #{status.updated_at.formatted}"
86
+ puts " Decom Count: #{status.decom_count}"
87
+ puts " Decom Error Count: #{status.decom_error_count}"
88
+ puts " Decom Message: #{status.decom_message}"
89
+ puts " Decom Message Time: #{status.decom_message_time.formatted}"
90
+ puts " Reduction Count: #{status.reduction_count}"
91
+ puts " Reduction Error Count: #{status.reduction_error_count}"
92
+ puts " Reduction Message: #{status.reduction_message}"
93
+ puts " Reduction Message Time: #{status.reduction_message_time}"
94
+ puts ""
95
+
96
+ puts "System Configs:"
97
+ SystemConfig.all.each do |system_config|
98
+ puts " #{sprintf("%6d", system_config.id)} #{system_config.name}"
99
+ end
100
+ puts ""
101
+
102
+ puts "Targets:"
103
+ Target.all.each do |target|
104
+ puts " #{sprintf("%6d", target.id)} #{target.name}"
105
+ end
106
+ puts ""
107
+
108
+ puts "Packets:"
109
+ Packet.all.each do |packet|
110
+ target = Target.find(packet.target_id)
111
+ puts " #{sprintf("%6d", packet.id)} #{target.name} #{packet.name} (#{packet.is_tlm ? "TLM" : "CMD"})"
112
+ end
113
+ puts ""
114
+
115
+ puts "Items:"
116
+ Item.find_each do |item|
117
+ packet = Packet.find(item.packet_id)
118
+ target = Target.find(packet.target_id)
119
+ puts " #{sprintf("%6d", item.id)} #{target.name} #{packet.name} #{item.name}"
120
+ end
121
+ puts ""
122
+
123
+ puts "Packet Logs:"
124
+ PacketLog.all.each do |packet_log|
125
+ puts " #{sprintf("%6d", packet_log.id)} #{packet_log.filename} (#{packet_log.is_tlm ? "TLM" : "CMD"}) #{packet_log.created_at.formatted}"
126
+ end
127
+ puts ""
128
+
129
+ puts "Packet Log Entry Count: #{PacketLogEntry.count}"
130
+ puts ""
131
+
132
+ puts "Packet Configs:"
133
+ PacketConfig.all.each do |packet_config|
134
+ packet = Packet.find(packet_config.packet_id)
135
+ target = Target.find(packet.target_id)
136
+ puts " #{sprintf("%6d", packet_config.id)} #{target.name} #{packet.name} (#{packet_config.name}) sysconfig:#{packet_config.first_system_config_id} maxindex:#{packet_config.max_table_index} ready:#{packet_config.ready} start:#{packet_config.start_time.formatted} end:#{packet_config.end_time.formatted}"
137
+ end
138
+ puts ""
139
+
140
+ value_type_lookup = {0 => "RAW", 1 => "CONVERTED", 2 => "RAW_CON"}
141
+ puts "Item to Decom Table Mappings:"
142
+ ItemToDecomTableMapping.find_each do |itdtm|
143
+ item = Item.find(itdtm.item_id)
144
+ packet = Packet.find(item.packet_id)
145
+ target = Target.find(packet.target_id)
146
+ puts " #{sprintf("%6d", itdtm.id)} #{target.name} #{packet.name} #{item.name} #{value_type_lookup[itdtm.value_type]} packet_config:#{itdtm.packet_config_id} item_index:#{itdtm.item_index} table_index:#{itdtm.table_index} reduced:#{itdtm.reduced}"
147
+ end
148
+ puts ""
149
+
150
+ puts "Decom and Reduced Tables:"
151
+ each_decom_and_reduced_table do |packet_config_id, table_index, decom_model, minute_model, hour_model, day_model|
152
+ puts " t#{decom_model.name.split("::")[1][1..-1]}: (#{decom_model.count} entries)"
153
+ ItemToDecomTableMapping.where("packet_config_id = ? and table_index = ?", packet_config_id, table_index).order("item_index ASC").each do |itdtm|
154
+ item = Item.find(itdtm.item_id)
155
+ packet = Packet.find(item.packet_id)
156
+ target = Target.find(packet.target_id)
157
+ puts " i#{itdtm.item_index} #{target.name} #{packet.name} #{item.name} #{value_type_lookup[itdtm.value_type]}"
158
+ end
159
+ puts ""
160
+ puts " t#{minute_model.name.split("::")[1][1..-1]}: (#{minute_model.count} entries)"
161
+ ItemToDecomTableMapping.where("packet_config_id = ? and table_index = ? and reduced = true", packet_config_id, table_index).order("item_index ASC").each do |itdtm|
162
+ item = Item.find(itdtm.item_id)
163
+ packet = Packet.find(item.packet_id)
164
+ target = Target.find(packet.target_id)
165
+ puts " i#{itdtm.item_index}max #{target.name} #{packet.name} #{item.name} #{value_type_lookup[itdtm.value_type]}"
166
+ puts " i#{itdtm.item_index}min #{target.name} #{packet.name} #{item.name} #{value_type_lookup[itdtm.value_type]}"
167
+ puts " i#{itdtm.item_index}avg #{target.name} #{packet.name} #{item.name} #{value_type_lookup[itdtm.value_type]}"
168
+ puts " i#{itdtm.item_index}stddev #{target.name} #{packet.name} #{item.name} #{value_type_lookup[itdtm.value_type]}"
169
+ end
170
+ puts ""
171
+ puts " t#{hour_model.name.split("::")[1][1..-1]}: (#{hour_model.count} entries)"
172
+ ItemToDecomTableMapping.where("packet_config_id = ? and table_index = ? and reduced = true", packet_config_id, table_index).order("item_index ASC").each do |itdtm|
173
+ item = Item.find(itdtm.item_id)
174
+ packet = Packet.find(item.packet_id)
175
+ target = Target.find(packet.target_id)
176
+ puts " i#{itdtm.item_index}max #{target.name} #{packet.name} #{item.name} #{value_type_lookup[itdtm.value_type]}"
177
+ puts " i#{itdtm.item_index}min #{target.name} #{packet.name} #{item.name} #{value_type_lookup[itdtm.value_type]}"
178
+ puts " i#{itdtm.item_index}avg #{target.name} #{packet.name} #{item.name} #{value_type_lookup[itdtm.value_type]}"
179
+ puts " i#{itdtm.item_index}stddev #{target.name} #{packet.name} #{item.name} #{value_type_lookup[itdtm.value_type]}"
180
+ end
181
+ puts ""
182
+ puts " t#{day_model.name.split("::")[1][1..-1]}: (#{day_model.count} entries)"
183
+ ItemToDecomTableMapping.where("packet_config_id = ? and table_index = ? and reduced = true", packet_config_id, table_index).order("item_index ASC").each do |itdtm|
184
+ item = Item.find(itdtm.item_id)
185
+ packet = Packet.find(item.packet_id)
186
+ target = Target.find(packet.target_id)
187
+ puts " i#{itdtm.item_index}max #{target.name} #{packet.name} #{item.name} #{value_type_lookup[itdtm.value_type]}"
188
+ puts " i#{itdtm.item_index}min #{target.name} #{packet.name} #{item.name} #{value_type_lookup[itdtm.value_type]}"
189
+ puts " i#{itdtm.item_index}avg #{target.name} #{packet.name} #{item.name} #{value_type_lookup[itdtm.value_type]}"
190
+ puts " i#{itdtm.item_index}stddev #{target.name} #{packet.name} #{item.name} #{value_type_lookup[itdtm.value_type]}"
191
+ end
192
+ puts ""
193
+ end
194
+
80
195
  when 'showpacketlogs'
81
196
  total_size = 0
82
197
  packet_logs = PacketLog.all
@@ -16,6 +16,13 @@ module Cosmos
16
16
  class DartMetaFrame < Qt::Widget
17
17
  @@meta_filters = []
18
18
 
19
+ class LabelPopup < Qt::Label
20
+ attr_accessor :text
21
+ def mousePressEvent(event)
22
+ Qt::MessageBox.critical(self.parent, 'Error', @text)
23
+ end
24
+ end
25
+
19
26
  def initialize(parent)
20
27
  super(parent)
21
28
 
@@ -27,6 +34,7 @@ module Cosmos
27
34
  @groupbox = Qt::GroupBox.new("Meta Filter Selection")
28
35
  @vbox = Qt::VBoxLayout.new(@groupbox)
29
36
  @hbox1 = Qt::HBoxLayout.new
37
+
30
38
  @label = Qt::Label.new("Meta Filters: ")
31
39
  @hbox1.addWidget(@label)
32
40
  @meta_filters_text = Qt::LineEdit.new
@@ -43,6 +51,10 @@ module Cosmos
43
51
  @vbox.addLayout(@hbox1)
44
52
 
45
53
  @hbox2 = Qt::HBoxLayout.new
54
+ @error = LabelPopup.new
55
+ @error.setPixmap(Qt::Application.style.standardIcon(Qt::Style::SP_MessageBoxCritical).pixmap(20, 20))
56
+ @error.hide
57
+ @hbox2.addWidget(@error)
46
58
  @meta_item_name = Qt::ComboBox.new
47
59
  @meta_item_name.setMinimumWidth(200)
48
60
  @meta_item_name.setMaxVisibleItems(6)
@@ -113,8 +125,15 @@ module Cosmos
113
125
  end
114
126
  end
115
127
  @got_meta_item_names = true
116
- rescue Exception
117
- # We tried...
128
+ Qt.execute_in_main_thread { @error.hide }
129
+ rescue Exception => e
130
+ case e.message
131
+ when /execution expired/
132
+ @error.text = "Could not connect to the DART Decom Server. Is it running?"
133
+ else
134
+ @error.text = e.message
135
+ end
136
+ Qt.execute_in_main_thread { @error.show }
118
137
  ensure
119
138
  @update_thread = nil
120
139
  server.disconnect if defined? server
@@ -135,6 +135,11 @@ module Cosmos
135
135
  @length_endianness)
136
136
  raise "Length value received larger than max_length: #{length} > #{@max_length}" if @max_length and length > @max_length
137
137
  packet_length = (length * @length_bytes_per_count) + @length_value_offset
138
+ # Ensure the calculated packet length is long enough to support the location of the length field
139
+ # without overlap into the next packet
140
+ if (packet_length * 8) < (@length_bit_offset + @length_bit_size)
141
+ raise "Calculated packet length of #{packet_length * 8} bits < (offset:#{@length_bit_offset} + size:#{@length_bit_size})"
142
+ end
138
143
 
139
144
  # Make sure we have enough data for the packet
140
145
  return :STOP if @data.length < packet_length
@@ -259,10 +259,10 @@ module Cosmos
259
259
  error_code = nil
260
260
  response_data = nil
261
261
 
262
- if (@method_whitelist and @method_whitelist.include?(request.method)) or
263
- (!@method_whitelist and !JsonRpcRequest::DANGEROUS_METHODS.include?(request.method))
262
+ if (@method_whitelist and @method_whitelist.include?(request.method.downcase())) or
263
+ (!@method_whitelist and !JsonRpcRequest::DANGEROUS_METHODS.include?(request.method.downcase()))
264
264
  begin
265
- result = @object.send(request.method.intern, *request.params)
265
+ result = @object.send(request.method.downcase().intern, *request.params)
266
266
  if request.id
267
267
  response = JsonRpcSuccessResponse.new(result, request.id)
268
268
  end
@@ -59,7 +59,7 @@ module Cosmos
59
59
  cflags |= Termios::CLOCAL # Ignore Modem Control Lines
60
60
  cflags |= Termios::CSTOPB if stop_bits == 2
61
61
  cflags |= Termios::PARENB if parity
62
- cflags |= Termios::PADODD if parity == :ODD
62
+ cflags |= Termios::PARODD if parity == :ODD
63
63
  cflags |= Termios::CRTSCTS if flow_control == :RTSCTS
64
64
  tio.iflag = iflags
65
65
  tio.oflag = 0
@@ -80,8 +80,29 @@ module Cosmos
80
80
  end
81
81
  Win32.set_comm_state(@handle, dcb)
82
82
 
83
- # Configure Timeouts
84
- Win32.set_comm_timeouts(@handle, 4294967295, 0, 0, 0, 0)
83
+ # Configure Timeouts, the WinAPI structure is COMMTIMEOUTS:
84
+ # DWORD ReadIntervalTimeout;
85
+ # DWORD ReadTotalTimeoutMultiplier;
86
+ # DWORD ReadTotalTimeoutConstant;
87
+ # DWORD WriteTotalTimeoutMultiplier;
88
+ # DWORD WriteTotalTimeoutConstant;
89
+ # 0xFFFFFFFF, 0, 0 specifies that the read operation is to return immediately
90
+ # with the bytes that have already been received, even if no bytes have been received.
91
+ # The WriteTotalTimeoutMultiplier is multiplied by the number of bytes to be written
92
+ # and the WriteTotalTimeoutConstant is added to that total (both are in milliseconds).
93
+ bits_per_symbol = data_bits + 1 # 1 start bit
94
+ case stop_bits
95
+ when Win32::ONESTOPBIT
96
+ bits_per_symbol += 1
97
+ when Win32::TWOSTOPBITS
98
+ bits_per_symbol += 2
99
+ end
100
+ case parity
101
+ when Win32::ODDPARITY, Win32::EVENPARITY
102
+ bits_per_symbol += 1
103
+ end
104
+ delay = (1000.0 / (baud_rate / bits_per_symbol.to_f)).ceil
105
+ Win32.set_comm_timeouts(@handle, 0xFFFFFFFF, 0, 0, delay, 1000)
85
106
  end
86
107
 
87
108
  # (see SerialDriver#close)
@@ -152,7 +152,7 @@ module Cosmos
152
152
 
153
153
  # Read Packet Data
154
154
  packet_data = @file.read_length_bytes(4, @max_read_size)
155
- return nil unless packet_data and packet_data.length > 0
155
+ return nil unless packet_data and packet_data.length >= 0
156
156
 
157
157
  if identify_and_define
158
158
  packet = identify_and_define_packet_data(target_name, packet_name, received_time, packet_data)
@@ -275,7 +275,7 @@ module Cosmos
275
275
  end
276
276
  packet.buffer = packet_data
277
277
  packet.set_received_time_fast(received_time)
278
- rescue
278
+ rescue Exception => error
279
279
  # Could not find a definition for this packet
280
280
  Logger.instance.error "Unknown packet #{target_name} #{packet_name}"
281
281
  packet = Packet.new(target_name, packet_name, :BIG_ENDIAN, nil, packet_data)
@@ -341,7 +341,7 @@ module Cosmos
341
341
  previous_item = nil
342
342
  warnings = []
343
343
  @sorted_items.each do |item|
344
- if expected_next_offset and item.bit_offset < expected_next_offset
344
+ if expected_next_offset and (item.bit_offset < expected_next_offset) and !item.overlap
345
345
  msg = "Bit definition overlap at bit offset #{item.bit_offset} for packet #{@target_name} #{@packet_name} items #{item.name} and #{previous_item.name}"
346
346
  Logger.instance.warn(msg)
347
347
  warnings << msg
@@ -198,14 +198,22 @@ module Cosmos
198
198
  #######################################################################
199
199
  # All the following keywords must have a current packet defined
200
200
  #######################################################################
201
- when 'SELECT_ITEM', 'SELECT_PARAMETER', 'ITEM', 'PARAMETER', 'ID_ITEM', 'ID_PARAMETER', 'ARRAY_ITEM', 'ARRAY_PARAMETER', 'APPEND_ITEM', 'APPEND_PARAMETER', 'APPEND_ID_ITEM', 'APPEND_ID_PARAMETER', 'APPEND_ARRAY_ITEM', 'APPEND_ARRAY_PARAMETER', 'MACRO_APPEND_START', 'MACRO_APPEND_END', 'ALLOW_SHORT', 'HAZARDOUS', 'PROCESSOR', 'META', 'DISABLE_MESSAGES', 'HIDDEN', 'DISABLED'
201
+ when 'SELECT_ITEM', 'SELECT_PARAMETER', 'DELETE_ITEM', 'DELETE_PARAMETER', 'ITEM',\
202
+ 'PARAMETER', 'ID_ITEM', 'ID_PARAMETER', 'ARRAY_ITEM', 'ARRAY_PARAMETER', 'APPEND_ITEM',\
203
+ 'APPEND_PARAMETER', 'APPEND_ID_ITEM', 'APPEND_ID_PARAMETER', 'APPEND_ARRAY_ITEM',\
204
+ 'APPEND_ARRAY_PARAMETER', 'MACRO_APPEND_START', 'MACRO_APPEND_END', 'ALLOW_SHORT',\
205
+ 'HAZARDOUS', 'PROCESSOR', 'META', 'DISABLE_MESSAGES', 'HIDDEN', 'DISABLED'
202
206
  raise parser.error("No current packet for #{keyword}") unless @current_packet
203
207
  process_current_packet(parser, keyword, params)
204
208
 
205
209
  #######################################################################
206
210
  # All the following keywords must have a current item defined
207
211
  #######################################################################
208
- when 'STATE', 'READ_CONVERSION', 'WRITE_CONVERSION', 'POLY_READ_CONVERSION', 'POLY_WRITE_CONVERSION', 'SEG_POLY_READ_CONVERSION', 'SEG_POLY_WRITE_CONVERSION', 'GENERIC_READ_CONVERSION_START', 'GENERIC_WRITE_CONVERSION_START', 'REQUIRED', 'LIMITS', 'LIMITS_RESPONSE', 'UNITS', 'FORMAT_STRING', 'DESCRIPTION', 'MINIMUM_VALUE', 'MAXIMUM_VALUE', 'DEFAULT_VALUE', 'OVERFLOW'
212
+ when 'STATE', 'READ_CONVERSION', 'WRITE_CONVERSION', 'POLY_READ_CONVERSION',\
213
+ 'POLY_WRITE_CONVERSION', 'SEG_POLY_READ_CONVERSION', 'SEG_POLY_WRITE_CONVERSION',\
214
+ 'GENERIC_READ_CONVERSION_START', 'GENERIC_WRITE_CONVERSION_START', 'REQUIRED',\
215
+ 'LIMITS', 'LIMITS_RESPONSE', 'UNITS', 'FORMAT_STRING', 'DESCRIPTION',\
216
+ 'MINIMUM_VALUE', 'MAXIMUM_VALUE', 'DEFAULT_VALUE', 'OVERFLOW', 'OVERLAP'
209
217
  raise parser.error("No current item for #{keyword}") unless @current_item
210
218
  process_current_item(parser, keyword, params)
211
219
 
@@ -327,25 +335,31 @@ module Cosmos
327
335
  def process_current_packet(parser, keyword, params)
328
336
  case keyword
329
337
 
330
- # Select an item in the current telemetry packet for editing
331
- when 'SELECT_PARAMETER', 'SELECT_ITEM'
338
+ # Select or delete an item in the current packet
339
+ when 'SELECT_PARAMETER', 'SELECT_ITEM', 'DELETE_PARAMETER', 'DELETE_ITEM'
332
340
  if (@current_cmd_or_tlm == COMMAND) && (keyword.split('_')[1] == 'ITEM')
333
- raise parser.error("SELECT_ITEM only applies to telemetry packets")
341
+ raise parser.error("#{keyword} only applies to telemetry packets")
334
342
  end
335
343
  if (@current_cmd_or_tlm == TELEMETRY) && (keyword.split('_')[1] == 'PARAMETER')
336
- raise parser.error("SELECT_PARAMETER only applies to command packets")
344
+ raise parser.error("#{keyword} only applies to command packets")
337
345
  end
338
346
  usage = "#{keyword} <#{keyword.split('_')[1]} NAME>"
339
347
  finish_item()
340
348
  parser.verify_num_parameters(1, 1, usage)
341
349
  begin
342
- @current_item = @current_packet.get_item(params[0])
350
+ if keyword.include?("SELECT")
351
+ @current_item = @current_packet.get_item(params[0])
352
+ else # DELETE
353
+ @current_packet.delete_item(params[0])
354
+ end
343
355
  rescue # Rescue the default execption to provide a nicer error message
344
356
  raise parser.error("#{params[0]} not found in #{@current_cmd_or_tlm.downcase} packet #{@current_packet.target_name} #{@current_packet.packet_name}", usage)
345
357
  end
346
358
 
347
359
  # Start a new telemetry item in the current packet
348
- when 'ITEM', 'PARAMETER', 'ID_ITEM', 'ID_PARAMETER', 'ARRAY_ITEM', 'ARRAY_PARAMETER', 'APPEND_ITEM', 'APPEND_PARAMETER', 'APPEND_ID_ITEM', 'APPEND_ID_PARAMETER', 'APPEND_ARRAY_ITEM', 'APPEND_ARRAY_PARAMETER'
360
+ when 'ITEM', 'PARAMETER', 'ID_ITEM', 'ID_PARAMETER', 'ARRAY_ITEM', 'ARRAY_PARAMETER',\
361
+ 'APPEND_ITEM', 'APPEND_PARAMETER', 'APPEND_ID_ITEM', 'APPEND_ID_PARAMETER',\
362
+ 'APPEND_ARRAY_ITEM', 'APPEND_ARRAY_PARAMETER'
349
363
  start_item(parser)
350
364
 
351
365
  # Start the creation of a macro-expanded list of items
@@ -570,6 +584,10 @@ module Cosmos
570
584
  parser.verify_num_parameters(1, 1, usage)
571
585
  @current_item.overflow = params[0].to_s.upcase.intern
572
586
 
587
+ when 'OVERLAP'
588
+ parser.verify_num_parameters(0, 0, 'OVERLAP')
589
+ @current_item.overlap = true
590
+
573
591
  end
574
592
  end
575
593