cosmos 5.0.2 → 5.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/bin/cosmos +183 -42
  3. data/data/config/microservice.yaml +47 -35
  4. data/data/config/plugins.yaml +10 -147
  5. data/data/config/target.yaml +70 -0
  6. data/data/config/tool.yaml +37 -31
  7. data/ext/cosmos/ext/cosmos_io/cosmos_io.c +14 -14
  8. data/ext/cosmos/ext/packet/packet.c +3 -3
  9. data/ext/cosmos/ext/structure/structure.c +31 -31
  10. data/lib/cosmos/api/api.rb +1 -25
  11. data/lib/cosmos/api/cmd_api.rb +17 -6
  12. data/lib/cosmos/api/config_api.rb +10 -4
  13. data/lib/cosmos/api/limits_api.rb +1 -1
  14. data/lib/cosmos/api/settings_api.rb +19 -7
  15. data/lib/cosmos/api/target_api.rb +2 -2
  16. data/lib/cosmos/api/tlm_api.rb +65 -41
  17. data/lib/cosmos/config/config_parser.rb +19 -22
  18. data/lib/cosmos/config/meta_config_parser.rb +1 -1
  19. data/lib/cosmos/conversions/generic_conversion.rb +2 -2
  20. data/lib/cosmos/conversions/polynomial_conversion.rb +5 -8
  21. data/lib/cosmos/conversions/segmented_polynomial_conversion.rb +26 -9
  22. data/lib/cosmos/io/json_drb.rb +5 -1
  23. data/lib/cosmos/logs/log_writer.rb +78 -29
  24. data/lib/cosmos/microservices/cleanup_microservice.rb +28 -29
  25. data/lib/cosmos/microservices/decom_microservice.rb +1 -1
  26. data/lib/cosmos/microservices/interface_microservice.rb +0 -16
  27. data/lib/cosmos/microservices/microservice.rb +3 -3
  28. data/lib/cosmos/microservices/reducer_microservice.rb +12 -10
  29. data/lib/cosmos/models/cvt_model.rb +6 -6
  30. data/lib/cosmos/models/gem_model.rb +9 -3
  31. data/lib/cosmos/models/info_model.rb +1 -1
  32. data/lib/cosmos/models/interface_model.rb +16 -7
  33. data/lib/cosmos/models/interface_status_model.rb +1 -1
  34. data/lib/cosmos/models/metadata_model.rb +69 -219
  35. data/lib/cosmos/models/metric_model.rb +2 -2
  36. data/lib/cosmos/models/microservice_model.rb +7 -4
  37. data/lib/cosmos/models/microservice_status_model.rb +1 -1
  38. data/lib/cosmos/models/model.rb +23 -16
  39. data/lib/cosmos/models/note_model.rb +122 -0
  40. data/lib/cosmos/models/ping_model.rb +2 -1
  41. data/lib/cosmos/models/plugin_model.rb +108 -48
  42. data/lib/cosmos/models/process_status_model.rb +1 -1
  43. data/lib/cosmos/models/scope_model.rb +10 -25
  44. data/lib/cosmos/models/settings_model.rb +55 -0
  45. data/lib/cosmos/models/sorted_model.rb +167 -0
  46. data/lib/cosmos/models/target_model.rb +143 -27
  47. data/lib/cosmos/models/tool_config_model.rb +38 -0
  48. data/lib/cosmos/models/tool_model.rb +9 -9
  49. data/lib/cosmos/models/widget_model.rb +11 -11
  50. data/lib/cosmos/operators/microservice_operator.rb +2 -1
  51. data/lib/cosmos/packets/packet.rb +24 -1
  52. data/lib/cosmos/packets/packet_config.rb +2 -2
  53. data/lib/cosmos/packets/packet_item.rb +57 -0
  54. data/lib/cosmos/packets/packet_item_limits.rb +14 -2
  55. data/lib/cosmos/packets/parsers/packet_item_parser.rb +1 -1
  56. data/lib/cosmos/packets/parsers/packet_parser.rb +1 -1
  57. data/lib/cosmos/packets/parsers/xtce_parser.rb +1 -1
  58. data/lib/cosmos/packets/structure.rb +30 -33
  59. data/lib/cosmos/packets/structure_item.rb +10 -1
  60. data/lib/cosmos/script/api_shared.rb +30 -25
  61. data/lib/cosmos/script/calendar.rb +37 -15
  62. data/lib/cosmos/script/commands.rb +5 -7
  63. data/lib/cosmos/script/script.rb +19 -39
  64. data/lib/cosmos/script/storage.rb +92 -105
  65. data/lib/cosmos/system/system.rb +2 -1
  66. data/lib/cosmos/tools/table_manager/table_config.rb +16 -1
  67. data/lib/cosmos/tools/table_manager/table_item.rb +1 -1
  68. data/lib/cosmos/tools/table_manager/table_manager_core.rb +213 -309
  69. data/lib/cosmos/top_level.rb +5 -1
  70. data/lib/cosmos/topics/autonomic_topic.rb +2 -2
  71. data/lib/cosmos/topics/calendar_topic.rb +1 -1
  72. data/lib/cosmos/topics/command_decom_topic.rb +35 -1
  73. data/lib/cosmos/topics/command_topic.rb +6 -4
  74. data/lib/cosmos/topics/config_topic.rb +68 -0
  75. data/lib/cosmos/topics/interface_topic.rb +8 -8
  76. data/lib/cosmos/topics/limits_event_topic.rb +5 -3
  77. data/lib/cosmos/topics/notifications_topic.rb +1 -1
  78. data/lib/cosmos/topics/router_topic.rb +9 -9
  79. data/lib/cosmos/topics/telemetry_decom_topic.rb +5 -1
  80. data/lib/cosmos/topics/telemetry_topic.rb +1 -1
  81. data/lib/cosmos/topics/timeline_topic.rb +1 -1
  82. data/lib/cosmos/topics/topic.rb +23 -8
  83. data/lib/cosmos/utilities/logger.rb +4 -3
  84. data/lib/cosmos/utilities/metric.rb +32 -26
  85. data/lib/cosmos/utilities/s3.rb +61 -0
  86. data/lib/cosmos/utilities/s3_file_cache.rb +12 -6
  87. data/lib/cosmos/utilities/store.rb +1 -0
  88. data/lib/cosmos/utilities/store_autoload.rb +25 -134
  89. data/lib/cosmos/version.rb +5 -4
  90. data/templates/plugin-template/plugin.gemspec +0 -2
  91. metadata +12 -10
  92. data/bin/xtce_converter +0 -92
  93. data/lib/cosmos/models/narrative_model.rb +0 -280
@@ -31,50 +31,111 @@ module Cosmos
31
31
  class MismatchError < CoreError
32
32
  end
33
33
 
34
- # Raised when there is no current table configuration
35
- class NoConfigError < CoreError
36
- # @return [String] Error message
37
- def message
38
- 'No current table configuration'
39
- end
34
+ def self.binary(binary, definition_filename, table_name)
35
+ config = TableConfig.process_file(definition_filename)
36
+ load_binary(config, binary)
37
+ return config.table(table_name).buffer
40
38
  end
41
39
 
42
- # Raised when there is no table in the current configuration
43
- class NoTableError < CoreError
44
- # @return [String] Error message
45
- def message
46
- 'Table does not exist in current configuration'
47
- end
40
+ def self.definition(definition_filename, table_name)
41
+ config = TableConfig.process_file(definition_filename)
42
+ return config.definition(table_name) # This returns an array: [filename, contents]
48
43
  end
49
44
 
50
- # @return [TableConfig] Configuration instance
51
- attr_reader :config
45
+ def self.report(binary, definition_filename, requested_table_name = nil)
46
+ report = StringIO.new
47
+ config = TableConfig.process_file(definition_filename)
48
+ begin
49
+ load_binary(config, binary)
50
+ rescue CoreError => err
51
+ report.puts "Error: #{err.message}\n"
52
+ end
53
+
54
+ config.tables.each do |table_name, table|
55
+ next if requested_table_name && table_name != requested_table_name
56
+ items = table.sorted_items
57
+ report.puts(table.table_name)
52
58
 
53
- # Create the instance
54
- def initialize
55
- reset
59
+ # Write the column headers
60
+ if table.type == :ROW_COLUMN
61
+ columns = ['Item']
62
+
63
+ # Remove the '0' from the 'itemname0'
64
+ table.num_columns.times.each do |x|
65
+ columns << items[x].name[0...-1]
66
+ end
67
+ report.puts columns.join(', ')
68
+ else
69
+ report.puts 'Label, Value'
70
+ end
71
+
72
+ # Write the table item values
73
+ (0...table.num_rows).each do |r|
74
+ if table.type == :ROW_COLUMN
75
+ rowtext = "#{r + 1}"
76
+ else
77
+ rowtext = items[r].name
78
+ end
79
+
80
+ report.write "#{rowtext}, "
81
+ (0...table.num_columns).each do |c|
82
+ if table.type == :ROW_COLUMN
83
+ table_item = items[c + r * table.num_columns]
84
+ else
85
+ table_item = items[r]
86
+ end
87
+ value = table.read(table_item.name, :FORMATTED)
88
+ if value.is_printable?
89
+ report.write "#{value}, "
90
+ else
91
+ report.write "#{value.simple_formatted}, "
92
+ end
93
+ end
94
+ report.write("\n") # newline after each row
95
+ end
96
+ report.write("\n") # newline after each table
97
+ end
98
+ report.string
56
99
  end
57
100
 
58
- # Clears the configuration
59
- def reset
60
- @config = nil
101
+ def self.generate(definition_filename)
102
+ config = TableConfig.process_file(definition_filename)
103
+ binary = ''
104
+ config.tables.each do |table_name, table|
105
+ table.restore_defaults
106
+ binary += table.buffer
107
+ end
108
+ binary
61
109
  end
62
110
 
63
- # @param filename [String] Create a new TableConfig instance and process the filename
64
- def process_definition(filename)
65
- @config = TableConfig.new
66
- @config.process_file(filename)
111
+ def self.save(definition_filename, tables)
112
+ config = TableConfig.process_file(definition_filename)
113
+ tables.each do |table|
114
+ table_def = config.tables[table['name']]
115
+ table['rows'].each do |row|
116
+ row.each do |item|
117
+ # TODO: I don't know how the frontend could edit an item like this:
118
+ # item:{"name"=>"BINARY", "value"=>{"json_class"=>"String", "raw"=>[222, 173, 190, 239]} }
119
+ next if item['value'].is_a? Hash
120
+ table_def.write(item['name'], item['value'])
121
+ end
122
+ end
123
+ end
124
+ binary = ''
125
+ config.tables.each { |table_name, table| binary += table.buffer }
126
+ binary
67
127
  end
68
128
 
69
- def generate_json(bin_path, def_path)
129
+ def self.build_json(binary, definition_filename)
130
+ config = TableConfig.process_file(definition_filename)
70
131
  tables = []
71
132
  json = { tables: tables }
72
133
  begin
73
- file_open(bin_path, def_path)
134
+ load_binary(config, binary)
74
135
  rescue CoreError => err
75
136
  json['errors'] = err.message
76
137
  end
77
- @config.tables.each do |table_name, table|
138
+ config.tables.each do |table_name, table|
78
139
  tables << {
79
140
  name: table_name,
80
141
  numRows: table.num_rows,
@@ -129,301 +190,144 @@ module Cosmos
129
190
  json.to_json
130
191
  end
131
192
 
132
- def save_tables(bin_path, def_path, tables)
133
- file_open(bin_path, def_path)
134
- tables.each do |table|
135
- table_def = @config.tables[table['name']]
136
- table['rows'].each do |row|
137
- row.each do |item|
138
- # TODO: I don't know how the frontend could edit an item like this:
139
- # item:{"name"=>"BINARY", "value"=>{"json_class"=>"String", "raw"=>[222, 173, 190, 239]} }
140
- next if item['value'].is_a? Hash
141
- table_def.write(item['name'], item['value'])
142
- end
143
- end
144
- end
145
- file_save(bin_path)
146
- bin_path
147
- end
148
-
149
- # @param def_path [String] Definition file to process
150
- # @param output_dir [String] Output directory to create the new file
151
- # @return [String] Binary file path
152
- def file_new(def_path, output_dir)
153
- process_definition(def_path)
154
- @config.table_names.each do |table_name|
155
- set_binary_data_to_default(table_name)
156
- end
157
- bin_path = File.join(output_dir, def_to_bin_filename(def_path))
158
- file_save(bin_path)
159
- bin_path
160
- end
161
-
162
- # @param bin_path [String] Binary file to open
163
- # @param def_path [String] Definition file to use when opening
164
- def file_open(bin_path, def_path)
165
- process_definition(def_path)
166
- open_and_load_binary_file(bin_path)
167
- end
168
-
169
- # Saves the current tables in the config instance to the given filename.
170
- #
171
- # @param filename [String] Filename to write, overwritten if it exists.
172
- def file_save(filename)
173
- raise NoConfigError unless @config
174
- file_check
175
- File.open(filename, 'wb') do |file|
176
- @config.tables.each { |table_name, table| file.write(table.buffer) }
177
- end
178
- # file_report(filename, @config.filename)
179
- end
180
-
181
- # @return [String] Success string if parameters all check. Raises
182
- # a CoreError if errors are found.
183
- def file_check
184
- raise NoConfigError unless @config
185
- result = ''
186
- @config.table_names.each do |name|
187
- table_result = table_check(name)
188
- unless table_result.empty?
189
- result << "Errors in #{name}:\n" + table_result
190
- end
191
- end
192
- raise CoreError, result unless result.empty?
193
- 'All parameters are within their constraints.'
194
- end
195
-
196
- # Create a CSV report file based on the file contents.
197
- #
198
- # @param bin_path [String] Binary filename currently open. Used to generate the
199
- # report name such that it matches the binary filename.
200
- # @param def_path [String] Definition filename currently open
201
- # @return [String] Report filename path
202
- def file_report(bin_path, def_path)
203
- raise NoConfigError unless @config
204
- file_check
205
-
206
- basename = File.basename(bin_path, '.bin')
207
- report_path = File.join(File.dirname(bin_path), "#{basename}.csv")
208
- File.open(report_path, 'w+') do |file|
209
- file.write("File Definition, #{def_path}\n")
210
- file.write("File Binary, #{bin_path}\n\n")
211
- @config.tables.values.each do |table|
212
- items = table.sorted_items
213
- file.puts(table.table_name)
214
-
215
- # Write the column headers
216
- if table.type == :ROW_COLUMN
217
- columns = ['Item']
218
-
219
- # Remove the '0' from the 'itemname0'
220
- table.num_columns.times.each do |x|
221
- columns << items[x].name[0...-1]
222
- end
223
- file.puts columns.join(', ')
224
- else
225
- file.puts 'Label, Value'
226
- end
227
-
228
- # Write the table item values
229
- (0...table.num_rows).each do |r|
230
- if table.type == :ROW_COLUMN
231
- rowtext = "#{r + 1}"
232
- else
233
- rowtext = items[r].name
234
- end
235
-
236
- file.write "#{rowtext}, "
237
- (0...table.num_columns).each do |c|
238
- if table.type == :ROW_COLUMN
239
- table_item = items[c + r * table.num_columns]
240
- else
241
- table_item = items[r]
242
- end
243
-
244
- file.write "#{table.read(table_item.name, :FORMATTED).to_s}, "
245
- end
246
- file.write("\n") # newline after each row
247
- end
248
- file.write("\n") # newline after each table
249
- end
250
- end
251
- report_path
252
- end
253
-
254
- # Create a hex formatted string of all the file data
255
- def file_hex
256
- raise NoConfigError unless @config
257
- data = ''
258
- @config.tables.values.each { |table| data << table.buffer }
259
- "#{data.formatted}\n\nTotal Bytes Read: #{data.length}"
260
- end
261
-
262
- # @param table_name [String] Name of the table to check for out of range values
263
- def table_check(table_name)
264
- raise NoConfigError unless @config
265
- table = @config.table(table_name)
266
- raise NoTableError unless table
267
-
268
- result = ''
269
- table_items = table.sorted_items
270
-
271
- # Check the ranges and constraints for each item in the table
272
- # We go through it this way (by row and columns) so we can grab the actual
273
- # user input when we display any errors found
274
- (0...table.num_rows).each do |r|
275
- (0...table.num_columns).each do |c|
276
- # get the table item definition so we know how to save it
277
- table_item = table_items[r * table.num_columns + c]
278
-
279
- value = table.read(table_item.name)
280
- unless table_item.range.nil?
281
- # If the item has states which include the value, then convert
282
- # the state back to the numeric value for range checking
283
- if table_item.states && table_item.states.include?(value)
284
- value = table_item.states[value]
285
- end
286
-
287
- # check to see if the value lies within its valid range
288
- unless table_item.range.include?(value)
289
- if table_item.format_string
290
- value = table.read(table_item.name, :FORMATTED)
291
- range_first =
292
- sprintf(table_item.format_string, table_item.range.first)
293
- range_last =
294
- sprintf(table_item.format_string, table_item.range.last)
295
- else
296
- range_first = table_item.range.first
297
- range_last = table_item.range.last
298
- end
299
- result <<
300
- " #{table_item.name}: #{value} outside valid range of #{range_first}..#{range_last}\n"
301
- end
302
- end
303
- end # end each column
304
- end # end each row
305
- result
306
- end
307
-
308
- # @param table_name [String] Name of the table to revert all values to default
309
- def table_default(table_name)
310
- raise NoConfigError unless @config
311
- set_binary_data_to_default(table_name)
312
- end
313
-
314
- # @param table_name [String] Create a hex formatted string of the given table data
315
- def table_hex(table_name)
316
- raise NoConfigError unless @config
317
- table = @config.table(table_name)
318
- raise NoTableError unless table
319
- "#{table.buffer.formatted}\n\nTotal Bytes Read: #{table.buffer.length}"
320
- end
321
-
322
- # @param table_name [String] Table name to write as a stand alone file
323
- # @param filename [String] Filename to write the table data to. Existing
324
- # files will be overwritten.
325
- def table_save(table_name, filename)
326
- raise NoConfigError unless @config
327
- result = table_check(table_name)
328
- unless result.empty?
329
- raise CoreError, "Errors in #{table_name}:\n#{result}"
330
- end
331
- File.open(filename, 'wb') do |file|
332
- file.write(@config.table(table_name).buffer)
333
- end
334
- end
335
-
336
- # Commit a table from the current configuration into a new binary
337
- #
338
- # @param table_name [String] Table name to commit to an existing binary
339
- # @param bin_file [String] Binary file to open
340
- # @param def_file [String] Definition file to use when opening
341
- def table_commit(table_name, bin_file, def_file)
342
- raise NoConfigError unless @config
343
- save_table = @config.table(table_name)
344
- raise NoTableError unless save_table
345
-
346
- result = table_check(table_name)
347
- unless result.empty?
348
- raise CoreError, "Errors in #{table_name}:\n#{result}"
349
- end
350
-
351
- config = TableConfig.new
352
- begin
353
- config.process_file(def_file)
354
- rescue => err
355
- raise CoreError,
356
- "The table definition file:#{def_file} has the following errors:\n#{err}"
357
- end
358
-
359
- if !config.table_names.include?(table_name.upcase)
360
- raise NoTableError,
361
- "#{table_name} not found in #{def_file} table definition file."
362
- end
363
-
364
- saved_config = @config
365
- @config = config
366
- open_and_load_binary_file(bin_file)
367
-
368
- # Store the saved table data in the new table definition
369
- table = config.table(save_table.table_name)
370
- table.buffer = save_table.buffer[0...table.length]
371
- file_save(bin_file)
372
- @config = saved_config
373
- end
374
-
375
- protected
376
-
377
- # Set all the binary data in the table to the default values
378
- def set_binary_data_to_default(table_name)
379
- table = @config.table(table_name)
380
- raise NoTableError unless table
381
- table.restore_defaults
382
- end
383
-
384
- # Get the binary filename equivalent for the given definition filename
385
- def def_to_bin_filename(def_path)
386
- if File.basename(def_path) =~ /_def\.txt$/
387
- # Remove _def.txt if present (should be)
388
- basename = File.basename(def_path)[0...-8]
389
- else
390
- # Remove any extension if present
391
- basename = File.basename(def_path, File.extname(def_path))
392
- end
393
- "#{basename}.bin"
394
- end
395
-
396
- # Opens the given binary file and populates the table definition.
397
- # The filename parameter should be a properly formatted file path.
398
- def open_and_load_binary_file(filename)
399
- begin
400
- data = nil
401
-
402
- # read the binary file and store it into an array
403
- File.open(filename, 'rb') { |file| data = file.read }
404
- rescue => err
405
- raise "Unable to open and load #{filename} due to #{err}."
406
- end
407
-
193
+ def self.load_binary(config, data)
408
194
  binary_data_index = 0
409
195
  total_table_length = 0
410
- @config.tables.each do |table_name, table|
196
+ config.tables.each do |table_name, table|
411
197
  total_table_length += table.length
412
198
  end
413
- @config.tables.each do |table_name, table|
199
+ config.tables.each do |table_name, table|
414
200
  if binary_data_index + table.length > data.length
415
201
  table.buffer = data[binary_data_index..-1]
416
202
  raise MismatchError,
417
- "Binary size of #{data.length} not large enough to fully represent table definition of length #{total_table_length}. The remaining table definition (starting with byte #{data.length - binary_data_index} in #{table.table_name}) will be filled with 0."
203
+ "Binary size of #{data.length} not large enough to fully represent table definition of length #{total_table_length}. "+
204
+ "The remaining table definition (starting with byte #{data.length - binary_data_index} in #{table.table_name}) will be filled with 0."
418
205
  end
419
- table.buffer =
420
- data[binary_data_index...binary_data_index + table.length]
206
+ table.buffer = data[binary_data_index...binary_data_index + table.length]
421
207
  binary_data_index += table.length
422
208
  end
423
209
  if binary_data_index < data.length
424
210
  raise MismatchError,
425
- "Binary size of #{data.length} larger than table definition of length #{total_table_length}. Discarding the remaing #{data.length - binary_data_index} bytes."
211
+ "Binary size of #{data.length} larger than table definition of length #{total_table_length}. "+
212
+ "Discarding the remaing #{data.length - binary_data_index} bytes."
426
213
  end
427
214
  end
215
+
216
+ # TODO: Potentially useful methods?
217
+ # # @return [String] Success string if parameters all check. Raises
218
+ # # a CoreError if errors are found.
219
+ # def file_check
220
+ # raise NoConfigError unless @config
221
+ # result = ''
222
+ # @config.table_names.each do |name|
223
+ # table_result = table_check(name)
224
+ # unless table_result.empty?
225
+ # result << "Errors in #{name}:\n" + table_result
226
+ # end
227
+ # end
228
+ # raise CoreError, result unless result.empty?
229
+ # 'All parameters are within their constraints.'
230
+ # end
231
+
232
+ # # Create a hex formatted string of all the file data
233
+ # def file_hex
234
+ # raise NoConfigError unless @config
235
+ # data = ''
236
+ # @config.tables.values.each { |table| data << table.buffer }
237
+ # "#{data.formatted}\n\nTotal Bytes Read: #{data.length}"
238
+ # end
239
+
240
+ # # @param table_name [String] Name of the table to check for out of range values
241
+ # def table_check(table_name)
242
+ # raise NoConfigError unless @config
243
+ # table = @config.table(table_name)
244
+ # raise NoTableError unless table
245
+
246
+ # result = ''
247
+ # table_items = table.sorted_items
248
+
249
+ # # Check the ranges and constraints for each item in the table
250
+ # # We go through it this way (by row and columns) so we can grab the actual
251
+ # # user input when we display any errors found
252
+ # (0...table.num_rows).each do |r|
253
+ # (0...table.num_columns).each do |c|
254
+ # # get the table item definition so we know how to save it
255
+ # table_item = table_items[r * table.num_columns + c]
256
+
257
+ # value = table.read(table_item.name)
258
+ # unless table_item.range.nil?
259
+ # # If the item has states which include the value, then convert
260
+ # # the state back to the numeric value for range checking
261
+ # if table_item.states && table_item.states.include?(value)
262
+ # value = table_item.states[value]
263
+ # end
264
+
265
+ # # check to see if the value lies within its valid range
266
+ # unless table_item.range.include?(value)
267
+ # if table_item.format_string
268
+ # value = table.read(table_item.name, :FORMATTED)
269
+ # range_first =
270
+ # sprintf(table_item.format_string, table_item.range.first)
271
+ # range_last =
272
+ # sprintf(table_item.format_string, table_item.range.last)
273
+ # else
274
+ # range_first = table_item.range.first
275
+ # range_last = table_item.range.last
276
+ # end
277
+ # result <<
278
+ # " #{table_item.name}: #{value} outside valid range of #{range_first}..#{range_last}\n"
279
+ # end
280
+ # end
281
+ # end # end each column
282
+ # end # end each row
283
+ # result
284
+ # end
285
+
286
+ # # @param table_name [String] Create a hex formatted string of the given table data
287
+ # def table_hex(table_name)
288
+ # raise NoConfigError unless @config
289
+ # table = @config.table(table_name)
290
+ # raise NoTableError unless table
291
+ # "#{table.buffer.formatted}\n\nTotal Bytes Read: #{table.buffer.length}"
292
+ # end
293
+
294
+ # # Commit a table from the current configuration into a new binary
295
+ # #
296
+ # # @param table_name [String] Table name to commit to an existing binary
297
+ # # @param bin_file [String] Binary file to open
298
+ # # @param def_file [String] Definition file to use when opening
299
+ # def table_commit(table_name, bin_file, def_file)
300
+ # raise NoConfigError unless @config
301
+ # save_table = @config.table(table_name)
302
+ # raise NoTableError unless save_table
303
+
304
+ # result = table_check(table_name)
305
+ # unless result.empty?
306
+ # raise CoreError, "Errors in #{table_name}:\n#{result}"
307
+ # end
308
+
309
+ # config = TableConfig.new
310
+ # begin
311
+ # config.process_file(def_file)
312
+ # rescue => err
313
+ # raise CoreError,
314
+ # "The table definition file:#{def_file} has the following errors:\n#{err}"
315
+ # end
316
+
317
+ # if !config.table_names.include?(table_name.upcase)
318
+ # raise NoTableError,
319
+ # "#{table_name} not found in #{def_file} table definition file."
320
+ # end
321
+
322
+ # saved_config = @config
323
+ # @config = config
324
+ # open_and_load_binary_file(bin_file)
325
+
326
+ # # Store the saved table data in the new table definition
327
+ # table = config.table(save_table.table_name)
328
+ # table.buffer = save_table.buffer[0...table.length]
329
+ # file_save(bin_file)
330
+ # @config = saved_config
331
+ # end
428
332
  end
429
333
  end
@@ -37,9 +37,13 @@ class HazardousError < StandardError
37
37
  attr_accessor :cmd_name
38
38
  attr_accessor :cmd_params
39
39
  attr_accessor :hazardous_description
40
+ attr_accessor :formatted # formatted command for use in resending original
40
41
 
41
42
  def to_s
42
- "#{target_name} #{cmd_name} with #{cmd_params} is Hazardous due to #{hazardous_description}"
43
+ string = "#{target_name} #{cmd_name} with #{cmd_params} is Hazardous"
44
+ string << "due to '#{hazardous_description}'" if hazardous_description
45
+ # Pass along the original formatted command so it can be resent
46
+ string << ".\n#{formatted}"
43
47
  end
44
48
  end
45
49
 
@@ -26,7 +26,7 @@ module Cosmos
26
26
  # Notify to the topic
27
27
  #
28
28
  # ```json
29
- # {
29
+ # {
30
30
  # "kind" => "created",
31
31
  # "type" => "trigger",
32
32
  # "data" => {
@@ -46,7 +46,7 @@ module Cosmos
46
46
  # }
47
47
  # ```
48
48
  def self.write_notification(notification, scope:)
49
- Store.write_topic("#{scope}#{PRIMARY_KEY}", notification, '*', 1000)
49
+ Topic.write_topic("#{scope}#{PRIMARY_KEY}", notification, '*', 1000)
50
50
  end
51
51
  end
52
52
  end
@@ -38,7 +38,7 @@ module Cosmos
38
38
  # }
39
39
  # ```
40
40
  def self.write_entry(entry, scope:)
41
- Store.write_topic("#{scope}#{PRIMARY_KEY}", entry, '*', 1000)
41
+ Topic.write_topic("#{scope}#{PRIMARY_KEY}", entry, '*', 1000)
42
42
  end
43
43
  end
44
44
  end
@@ -21,6 +21,10 @@ require 'cosmos/topics/topic'
21
21
 
22
22
  module Cosmos
23
23
  class CommandDecomTopic < Topic
24
+ def self.topics(scope:)
25
+ super(scope, 'DECOMCMD')
26
+ end
27
+
24
28
  def self.write_packet(packet, scope:)
25
29
  topic = "#{scope}__DECOMCMD__{#{packet.target_name}}__#{packet.packet_name}"
26
30
  msg_hash = { time: packet.received_time.to_nsec_from_epoch,
@@ -36,7 +40,37 @@ module Cosmos
36
40
  json_hash[item.name + "__U"] = packet.read_item(item, :WITH_UNITS) if item.units
37
41
  end
38
42
  msg_hash['json_data'] = JSON.generate(json_hash.as_json)
39
- Store.write_topic(topic, msg_hash)
43
+ Topic.write_topic(topic, msg_hash)
44
+ end
45
+
46
+ def self.get_cmd_item(target_name, packet_name, param_name, type: :WITH_UNITS, scope: $cosmos_scope)
47
+ msg_id, msg_hash = Topic.get_newest_message("#{scope}__DECOMCMD__{#{target_name}}__#{packet_name}")
48
+ if msg_id
49
+ # TODO: We now have these reserved items directly on command packets
50
+ # Do we still calculate from msg_hash['time'] or use the times directly?
51
+ #
52
+ # if param_name == 'RECEIVED_TIMESECONDS' || param_name == 'PACKET_TIMESECONDS'
53
+ # Time.from_nsec_from_epoch(msg_hash['time'].to_i).to_f
54
+ # elsif param_name == 'RECEIVED_TIMEFORMATTED' || param_name == 'PACKET_TIMEFORMATTED'
55
+ # Time.from_nsec_from_epoch(msg_hash['time'].to_i).formatted
56
+ if param_name == 'RECEIVED_COUNT'
57
+ msg_hash['received_count'].to_i
58
+ else
59
+ json = msg_hash['json_data']
60
+ hash = JSON.parse(json)
61
+ # Start from the most complex down to the basic raw value
62
+ value = hash["#{param_name}__U"]
63
+ return value if value && type == :WITH_UNITS
64
+
65
+ value = hash["#{param_name}__F"]
66
+ return value if value && (type == :WITH_UNITS || type == :FORMATTED)
67
+
68
+ value = hash["#{param_name}__C"]
69
+ return value if value && (type == :WITH_UNITS || type == :FORMATTED || type == :CONVERTED)
70
+
71
+ return hash[param_name]
72
+ end
73
+ end
40
74
  end
41
75
  end
42
76
  end