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
@@ -39,7 +39,7 @@ module Cosmos
39
39
  end
40
40
 
41
41
  def convert_microservice_to_process_definition(microservice_name, microservice_config)
42
- process_definition = ["ruby", "plugin_microservice.rb", microservice_name]
42
+ process_definition = ["ruby", "plugin_microservice.rb"]
43
43
  work_dir = "/cosmos/lib/cosmos/microservices"
44
44
  env = microservice_config["env"].dup
45
45
  if microservice_config["needs_dependencies"]
@@ -47,6 +47,7 @@ module Cosmos
47
47
  else
48
48
  env['GEM_HOME'] = nil
49
49
  end
50
+ env['COSMOS_MICROSERVICE_NAME'] = microservice_name
50
51
  container = microservice_config["container"]
51
52
  scope = microservice_name.split("__")[0]
52
53
  return process_definition, work_dir, env, scope, container
@@ -98,7 +98,7 @@ module Cosmos
98
98
  # @param buffer [String] String buffer to hold the packet data
99
99
  # @param item_class [Class] Class used to instantiate items (Must be a
100
100
  # subclass of PacketItem)
101
- def initialize(target_name, packet_name, default_endianness = :BIG_ENDIAN, description = nil, buffer = '', item_class = PacketItem)
101
+ def initialize(target_name, packet_name, default_endianness = :BIG_ENDIAN, description = nil, buffer = nil, item_class = PacketItem)
102
102
  super(default_endianness, buffer, item_class)
103
103
  # Explictly call the defined setter methods
104
104
  self.target_name = target_name
@@ -445,6 +445,11 @@ module Cosmos
445
445
  @meta ||= {}
446
446
  end
447
447
 
448
+ # Sets packet specific metadata
449
+ def meta=(meta)
450
+ @meta = meta
451
+ end
452
+
448
453
  # Indicates if the packet has been identified
449
454
  # @return [TrueClass or FalseClass]
450
455
  def identified?
@@ -1009,6 +1014,24 @@ module Cosmos
1009
1014
  config
1010
1015
  end
1011
1016
 
1017
+ def self.from_json(hash)
1018
+ endianness = hash['endianness'] ? hash['endianness'].intern : nil # Convert to symbol
1019
+ packet = Packet.new(hash['target_name'], hash['packet_name'], endianness, hash['description'])
1020
+ packet.short_buffer_allowed = hash['short_buffer_allowed']
1021
+ packet.hazardous = hash['hazardous']
1022
+ packet.hazardous_description = hash['hazardous_description']
1023
+ packet.messages_disabled = hash['messages_disabled']
1024
+ packet.disabled = hash['disabled']
1025
+ packet.hidden = hash['hidden']
1026
+ # packet.stale is read only
1027
+ packet.meta = hash['meta']
1028
+ # Can't convert processors
1029
+ hash['items'].each do |item|
1030
+ packet.define(PacketItem.from_json(item))
1031
+ end
1032
+ packet
1033
+ end
1034
+
1012
1035
  protected
1013
1036
 
1014
1037
  # Performs packet specific processing on the packet.
@@ -463,8 +463,8 @@ module Cosmos
463
463
  when 'POLY_READ_CONVERSION', 'POLY_WRITE_CONVERSION'
464
464
  usage = "#{keyword} <C0> <C1> <C2> ..."
465
465
  parser.verify_num_parameters(1, nil, usage)
466
- @current_item.read_conversion = PolynomialConversion.new(params) if keyword.include? "READ"
467
- @current_item.write_conversion = PolynomialConversion.new(params) if keyword.include? "WRITE"
466
+ @current_item.read_conversion = PolynomialConversion.new(*params) if keyword.include? "READ"
467
+ @current_item.write_conversion = PolynomialConversion.new(*params) if keyword.include? "WRITE"
468
468
 
469
469
  # Apply a segmented polynomial conversion to the current item
470
470
  # after it is read from the telemetry packet
@@ -486,6 +486,63 @@ module Cosmos
486
486
  config
487
487
  end
488
488
 
489
+ def self.from_json(hash)
490
+ # Convert strings to symbols
491
+ endianness = hash['endianness'] ? hash['endianness'].intern : nil
492
+ data_type = hash['data_type'] ? hash['data_type'].intern : nil
493
+ overflow = hash['overflow'] ? hash['overflow'].intern : nil
494
+ item = PacketItem.new(hash['name'], hash['bit_offset'], hash['bit_size'],
495
+ data_type, endianness, hash['array_size'], overflow)
496
+ item.description = hash['description']
497
+ item.id_value = hash['id_value']
498
+ item.default = hash['default']
499
+ item.range = (hash['minimum']..hash['maximum']) if hash['minimum'] && hash['maximum']
500
+ item.required = hash['required']
501
+ item.format_string = hash['format_string']
502
+ item.units = hash['units']
503
+ item.units_full = hash['units_full']
504
+ if hash['states']
505
+ item.states = {}
506
+ item.hazardous = {}
507
+ item.state_colors = {}
508
+ hash['states'].each do |state_name, state|
509
+ item.states[state_name] = state['value']
510
+ item.hazardous[state_name] = state['hazardous']
511
+ item.state_colors[state_name] = state['color'].to_sym if state['color']
512
+ end
513
+ end
514
+ # Recreate COSMOS built-in conversions
515
+ if hash['read_conversion']
516
+ begin
517
+ item.read_conversion = Cosmos::const_get(hash['read_conversion']['class']).new(*hash['read_conversion']['params'])
518
+ rescue => error
519
+ Logger.instance.error "#{item.name} read_conversion of #{hash['read_conversion']} could not be instantiated due to #{error}"
520
+ end
521
+ end
522
+ if hash['write_conversion']
523
+ begin
524
+ item.write_conversion = Cosmos::const_get(hash['write_conversion']['class']).new(*hash['write_conversion']['params'])
525
+ rescue => error
526
+ Logger.instance.error "#{item.name} write_conversion of #{hash['write_conversion']} could not be instantiated due to #{error}"
527
+ end
528
+ end
529
+
530
+ if hash['limits']
531
+ item.limits = PacketItemLimits.new
532
+ # Delete these keys so the only ones left are limits sets
533
+ item.limits.persistence_setting = hash['limits'].delete('persistence_setting')
534
+ item.limits.enabled = true if hash['limits'].delete('enabled')
535
+ values = {}
536
+ hash['limits'].each do |set, items|
537
+ values[set.to_sym] = [items['red_low'], items['yellow_low'], items['yellow_high'], items['red_high']]
538
+ values[set.to_sym].concat([items['green_low'], items['green_high']]) if items['green_low'] && items['green_high']
539
+ end
540
+ item.limits.values = values
541
+ end
542
+ item.meta = hash['meta']
543
+ item
544
+ end
545
+
489
546
  protected
490
547
 
491
548
  def parameter_config
@@ -132,7 +132,7 @@ module Cosmos
132
132
  end
133
133
  alias dup clone
134
134
 
135
- def to_hash
135
+ def as_json
136
136
  hash = {}
137
137
  hash['values'] = self.values
138
138
  hash['enabled'] = self.enabled
@@ -146,5 +146,17 @@ module Cosmos
146
146
  hash['persistence_count'] = self.persistence_count
147
147
  hash
148
148
  end
149
+
150
+ def self.from_json(hash)
151
+ limits = PacketItemLimits.new
152
+ limits.values = hash['values'].transform_keys(&:to_sym) if hash['values']
153
+ limits.enabled = hash['enabled']
154
+ limits.state = hash['state'] ? hash['state'].to_sym : nil
155
+ # Can't recreate a LimitsResponse class
156
+ # limits.response = hash['response']
157
+ limits.persistence_setting = hash['persistence_setting'] if hash['persistence_setting']
158
+ limits.persistence_count = hash['persistence_count'] if hash['persistence_count']
159
+ limits
160
+ end
149
161
  end
150
- end # module Cosmos
162
+ end
@@ -56,7 +56,7 @@ module Cosmos
56
56
  max_options = @usage.count("<")
57
57
  # The last two options (description and endianness) are optional
58
58
  @parser.verify_num_parameters(max_options - 2, max_options, @usage)
59
- @parser.verify_parameters_underscores(1) # Item name is the 1st parameter
59
+ @parser.verify_parameter_naming(1) # Item name is the 1st parameter
60
60
  end
61
61
 
62
62
  def create_packet_item(packet, cmd_or_tlm)
@@ -72,7 +72,7 @@ module Cosmos
72
72
  def verify_parameters
73
73
  @usage = "#{@parser.keyword} <TARGET NAME> <PACKET NAME> <ENDIANNESS: BIG_ENDIAN/LITTLE_ENDIAN> <DESCRIPTION (Optional)>"
74
74
  @parser.verify_num_parameters(3, 4, @usage)
75
- @parser.verify_parameters_underscores(2) # Packet name is the 2nd parameter
75
+ @parser.verify_parameter_naming(2) # Packet name is the 2nd parameter
76
76
  end
77
77
 
78
78
  def create_command(target_name, commands, warnings)
@@ -293,7 +293,7 @@ module Cosmos
293
293
  xtce_recurse_element(element) do |block_element|
294
294
  if block_element.name == 'Term'
295
295
  exponent = Float(block_element['exponent']).to_i
296
- @current_type.conversion ||= PolynomialConversion.new([])
296
+ @current_type.conversion ||= PolynomialConversion.new()
297
297
  @current_type.conversion.coeffs[exponent] = Float(block_element['coefficient'])
298
298
  @current_type.conversion.coeffs.each_with_index do |value, index|
299
299
  @current_type.conversion.coeffs[index] = 0.0 if value.nil?
@@ -66,7 +66,7 @@ module Cosmos
66
66
  # @param buffer [String] Buffer used to store the structure
67
67
  # @param item_class [Class] Class used to instantiate new structure items.
68
68
  # Must be StructureItem or one of its subclasses.
69
- def initialize(default_endianness = BinaryAccessor::HOST_ENDIANNESS, buffer = '', item_class = StructureItem)
69
+ def initialize(default_endianness = BinaryAccessor::HOST_ENDIANNESS, buffer = nil, item_class = StructureItem)
70
70
  if (default_endianness == :BIG_ENDIAN) || (default_endianness == :LITTLE_ENDIAN)
71
71
  @default_endianness = default_endianness
72
72
  if buffer
@@ -102,14 +102,11 @@ module Cosmos
102
102
  def read_item(item, value_type = :RAW, buffer = @buffer)
103
103
  return nil if item.data_type == :DERIVED
104
104
 
105
- if buffer
106
- if item.array_size
107
- return BinaryAccessor.read_array(item.bit_offset, item.bit_size, item.data_type, item.array_size, buffer, item.endianness)
108
- else
109
- return BinaryAccessor.read(item.bit_offset, item.bit_size, item.data_type, buffer, item.endianness)
110
- end
105
+ buffer = allocate_buffer_if_needed() unless buffer
106
+ if item.array_size
107
+ return BinaryAccessor.read_array(item.bit_offset, item.bit_size, item.data_type, item.array_size, buffer, item.endianness)
111
108
  else
112
- raise "No buffer given to read_item"
109
+ return BinaryAccessor.read(item.bit_offset, item.bit_size, item.data_type, buffer, item.endianness)
113
110
  end
114
111
  end
115
112
 
@@ -117,9 +114,8 @@ module Cosmos
117
114
  #
118
115
  # @return [Integer] Size of the buffer in bytes
119
116
  def length
120
- return @buffer.length if @buffer
121
-
122
- return 0
117
+ allocate_buffer_if_needed()
118
+ return @buffer.length
123
119
  end
124
120
 
125
121
  # Resize the buffer at least the defined length of the structure
@@ -129,12 +125,23 @@ module Cosmos
129
125
  if @buffer.length < @defined_length
130
126
  @buffer << (ZERO_STRING * (@defined_length - @buffer.length))
131
127
  end
128
+ else
129
+ allocate_buffer_if_needed()
132
130
  end
133
131
 
134
132
  return self
135
133
  end
136
134
  end
137
135
 
136
+ # Allocate a buffer if not available
137
+ def allocate_buffer_if_needed
138
+ unless @buffer
139
+ @buffer = ZERO_STRING * @defined_length
140
+ @buffer.force_encoding(ASCII_8BIT_STRING)
141
+ end
142
+ return @buffer
143
+ end
144
+
138
145
  # Indicates if any items have been defined for this structure
139
146
  # @return [TrueClass or FalseClass]
140
147
  def defined?
@@ -340,14 +347,11 @@ module Cosmos
340
347
  # parameter to check whether to perform conversions on the item.
341
348
  # @param buffer [String] The binary buffer to write the value to
342
349
  def write_item(item, value, value_type = :RAW, buffer = @buffer)
343
- if buffer
344
- if item.array_size
345
- BinaryAccessor.write_array(value, item.bit_offset, item.bit_size, item.data_type, item.array_size, buffer, item.endianness, item.overflow)
346
- else
347
- BinaryAccessor.write(value, item.bit_offset, item.bit_size, item.data_type, buffer, item.endianness, item.overflow)
348
- end
350
+ buffer = allocate_buffer_if_needed() unless buffer
351
+ if item.array_size
352
+ BinaryAccessor.write_array(value, item.bit_offset, item.bit_size, item.data_type, item.array_size, buffer, item.endianness, item.overflow)
349
353
  else
350
- raise "No buffer given to write_item"
354
+ BinaryAccessor.write(value, item.bit_offset, item.bit_size, item.data_type, buffer, item.endianness, item.overflow)
351
355
  end
352
356
  end
353
357
 
@@ -432,14 +436,11 @@ module Cosmos
432
436
  # @param copy [TrueClass/FalseClass] Whether to copy the buffer
433
437
  # @return [String] Data buffer backing the structure
434
438
  def buffer(copy = true)
435
- if @buffer
436
- if copy
437
- return @buffer.dup
438
- else
439
- return @buffer
440
- end
439
+ local_buffer = allocate_buffer_if_needed()
440
+ if copy
441
+ return local_buffer.dup
441
442
  else
442
- return nil
443
+ return local_buffer
443
444
  end
444
445
  end
445
446
 
@@ -525,15 +526,11 @@ module Cosmos
525
526
  module MethodMissing
526
527
  # Method missing provides reading/writing item values as if they were methods to the class
527
528
  def method_missing(name, value = nil)
528
- if @buffer
529
- if value
530
- # Strip off the equals sign before looking up the item
531
- return write(name.to_s[0..-2], value)
532
- else
533
- return read(name.to_s)
534
- end
529
+ if value
530
+ # Strip off the equals sign before looking up the item
531
+ return write(name.to_s[0..-2], value)
535
532
  else
536
- raise "No buffer available for method_missing"
533
+ return read(name.to_s)
537
534
  end
538
535
  end
539
536
  end
@@ -292,7 +292,16 @@ module Cosmos
292
292
  end
293
293
  alias dup clone
294
294
 
295
- def to_hash
295
+ def self.from_json(hash)
296
+ # Convert strings to symbols
297
+ endianness = hash['endianness'] ? hash['endianness'].intern : nil
298
+ data_type = hash['data_type'] ? hash['data_type'].intern : nil
299
+ overflow = hash['overflow'] ? hash['overflow'].intern : nil
300
+ StructureItem.new(hash['name'], hash['bit_offset'], hash['bit_size'], data_type,
301
+ endianness, hash['array_size'], overflow)
302
+ end
303
+
304
+ def as_json
296
305
  hash = {}
297
306
  hash['name'] = self.name
298
307
  hash['bit_offset'] = self.bit_offset
@@ -300,10 +300,10 @@ module Cosmos
300
300
  #
301
301
  # @param args [String|Array<String>] See the description for calling style
302
302
  # @param type [Symbol] Telemetry type, :RAW, :CONVERTED (default), :FORMATTED, or :WITH_UNITS
303
- def wait_check(*args, type: :CONVERTED, scope: $cosmos_scope, token: $cosmos_token)
303
+ def wait_check(*args, type: :CONVERTED, scope: $cosmos_scope, token: $cosmos_token, &block)
304
304
  target_name, packet_name, item_name, comparison_to_eval, timeout, polling_rate = _wait_check_process_args(args, scope: scope, token: token)
305
305
  start_time = Time.now.sys
306
- success, value = cosmos_script_wait_implementation(target_name, packet_name, item_name, type, comparison_to_eval, timeout, polling_rate, scope: scope, token: token)
306
+ success, value = cosmos_script_wait_implementation(target_name, packet_name, item_name, type, comparison_to_eval, timeout, polling_rate, scope: scope, token: token, &block)
307
307
  time = Time.now.sys - start_time
308
308
  check_str = "CHECK: #{_upcase(target_name, packet_name, item_name)} #{comparison_to_eval}"
309
309
  with_value_str = "with value == #{value} after waiting #{time} seconds"
@@ -321,8 +321,8 @@ module Cosmos
321
321
  end
322
322
 
323
323
  # @deprecated use wait_check with type: :RAW
324
- def wait_check_raw(*args, scope: $cosmos_scope, token: $cosmos_token)
325
- wait_check(*args, type: :RAW, scope: scope, token: token)
324
+ def wait_check_raw(*args, scope: $cosmos_scope, token: $cosmos_token, &block)
325
+ wait_check(*args, type: :RAW, scope: scope, token: token, &block)
326
326
  end
327
327
 
328
328
  # Wait for the value of a telmetry item to be within a tolerance of a value
@@ -334,7 +334,7 @@ module Cosmos
334
334
  #
335
335
  # @param args [String|Array<String>] See the description for calling style
336
336
  # @param type [Symbol] Telemetry type, :RAW or :CONVERTED (default)
337
- def wait_check_tolerance(*args, type: :CONVERTED, scope: $cosmos_scope, token: $cosmos_token)
337
+ def wait_check_tolerance(*args, type: :CONVERTED, scope: $cosmos_scope, token: $cosmos_token, &block)
338
338
  raise "Invalid type '#{type}' for wait_check_tolerance" unless %i(RAW CONVERTED).include?(type)
339
339
 
340
340
  target_name, packet_name, item_name, expected_value, tolerance, timeout, polling_rate = _wait_tolerance_process_args(args, scope: scope, token: token)
@@ -343,7 +343,7 @@ module Cosmos
343
343
  if value.is_a?(Array)
344
344
  expected_value, tolerance = array_tolerance_process_args(value.size, expected_value, tolerance, 'wait_check_tolerance', scope: scope, token: token)
345
345
 
346
- success, value = cosmos_script_wait_implementation_array_tolerance(value.size, target_name, packet_name, item_name, type, expected_value, tolerance, timeout, polling_rate, scope: scope, token: token)
346
+ success, value = cosmos_script_wait_implementation_array_tolerance(value.size, target_name, packet_name, item_name, type, expected_value, tolerance, timeout, polling_rate, scope: scope, token: token, &block)
347
347
  time = Time.now.sys - start_time
348
348
 
349
349
  message = ""
@@ -388,8 +388,8 @@ module Cosmos
388
388
  end
389
389
 
390
390
  # @deprecated Use wait_check_tolerance with type: :RAW
391
- def wait_check_tolerance_raw(*args, scope: $cosmos_scope, token: $cosmos_token)
392
- wait_check_tolerance(*args, type: :RAW, scope: scope, token: token)
391
+ def wait_check_tolerance_raw(*args, scope: $cosmos_scope, token: $cosmos_token, &block)
392
+ wait_check_tolerance(*args, type: :RAW, scope: scope, token: token, &block)
393
393
  end
394
394
 
395
395
  # Wait on an expression to be true. On a timeout, the script will pause.
@@ -397,12 +397,12 @@ module Cosmos
397
397
  timeout,
398
398
  polling_rate = DEFAULT_TLM_POLLING_RATE,
399
399
  context = nil,
400
- scope: $cosmos_scope, token: $cosmos_token)
400
+ scope: $cosmos_scope, token: $cosmos_token, &block)
401
401
  start_time = Time.now.sys
402
402
  success = cosmos_script_wait_implementation_expression(exp_to_eval,
403
403
  timeout,
404
404
  polling_rate,
405
- context, scope: scope, token: token)
405
+ context, scope: scope, token: token, &block)
406
406
  time = Time.now.sys - start_time
407
407
  if success
408
408
  Logger.info "CHECK: #{exp_to_eval} is TRUE after waiting #{time} seconds"
@@ -691,15 +691,20 @@ module Cosmos
691
691
  return [target_name, packet_name, item_name, comparison_to_eval, timeout, polling_rate]
692
692
  end
693
693
 
694
- def _cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, timeout, polling_rate, scope: $cosmos_scope, token: $cosmos_token)
694
+ def _cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, timeout, polling_rate, exp_to_eval, scope: $cosmos_scope, token: $cosmos_token, &block)
695
695
  end_time = Time.now.sys + timeout
696
- exp_to_eval = yield
697
696
 
698
697
  while true
699
698
  work_start = Time.now.sys
700
699
  value = tlm(target_name, packet_name, item_name, type: value_type, scope: scope, token: token)
701
- if eval(exp_to_eval)
702
- return true, value
700
+ if not block.nil?
701
+ if block.call(value)
702
+ return true, value
703
+ end
704
+ else
705
+ if eval(exp_to_eval)
706
+ return true, value
707
+ end
703
708
  end
704
709
  break if Time.now.sys >= end_time
705
710
 
@@ -724,25 +729,25 @@ module Cosmos
724
729
  end
725
730
 
726
731
  # Wait for a converted telemetry item to pass a comparison
727
- def cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, comparison_to_eval, timeout, polling_rate = DEFAULT_TLM_POLLING_RATE, scope: $cosmos_scope, token: $cosmos_token)
728
- _cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, timeout, polling_rate, scope: scope, token: token) do
729
- "value " + comparison_to_eval
732
+ def cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, comparison_to_eval, timeout, polling_rate = DEFAULT_TLM_POLLING_RATE, scope: $cosmos_scope, token: $cosmos_token, &block)
733
+ if comparison_to_eval
734
+ exp_to_eval = "value " + comparison_to_eval
735
+ else
736
+ exp_to_eval = nil
730
737
  end
738
+ _cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, timeout, polling_rate, exp_to_eval, scope: scope, token: token, &block)
731
739
  end
732
740
 
733
- def cosmos_script_wait_implementation_tolerance(target_name, packet_name, item_name, value_type, expected_value, tolerance, timeout, polling_rate = DEFAULT_TLM_POLLING_RATE, scope: $cosmos_scope, token: $cosmos_token)
734
- _cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, timeout, polling_rate, scope: scope, token: token) do
735
- "((#{expected_value} - #{tolerance})..(#{expected_value} + #{tolerance})).include? value"
736
- end
741
+ def cosmos_script_wait_implementation_tolerance(target_name, packet_name, item_name, value_type, expected_value, tolerance, timeout, polling_rate = DEFAULT_TLM_POLLING_RATE, scope: $cosmos_scope, token: $cosmos_token, &block)
742
+ exp_to_eval = "((#{expected_value} - #{tolerance})..(#{expected_value} + #{tolerance})).include? value"
743
+ _cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, timeout, polling_rate, exp_to_eval, scope: scope, token: token, &block)
737
744
  end
738
745
 
739
- def cosmos_script_wait_implementation_array_tolerance(array_size, target_name, packet_name, item_name, value_type, expected_value, tolerance, timeout, polling_rate = DEFAULT_TLM_POLLING_RATE, scope: $cosmos_scope, token: $cosmos_token)
746
+ def cosmos_script_wait_implementation_array_tolerance(array_size, target_name, packet_name, item_name, value_type, expected_value, tolerance, timeout, polling_rate = DEFAULT_TLM_POLLING_RATE, scope: $cosmos_scope, token: $cosmos_token, &block)
740
747
  statements = []
741
748
  array_size.times { |i| statements << "(((#{expected_value[i]} - #{tolerance[i]})..(#{expected_value[i]} + #{tolerance[i]})).include? value[#{i}])" }
742
749
  exp_to_eval = statements.join(" && ")
743
- _cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, timeout, polling_rate, scope: scope, token: token) do
744
- exp_to_eval
745
- end
750
+ _cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, timeout, polling_rate, exp_to_eval, scope: scope, token: token, &block)
746
751
  end
747
752
 
748
753
  # Wait on an expression to be true.
@@ -18,6 +18,7 @@
18
18
  # copyright holder
19
19
 
20
20
  require 'cosmos/script/extract'
21
+ require 'time'
21
22
 
22
23
  module Cosmos
23
24
  module Script
@@ -25,38 +26,59 @@ module Cosmos
25
26
 
26
27
  private
27
28
 
28
- # Sets the metadata value for a target
29
+ # Gets the current metadata
29
30
  #
30
- # @param target [String] Target to set metadata on
31
31
  # @return The result of the method call.
32
- def get_metadata(target)
33
- endpoint = "/cosmos-api/metadata/_get/#{target}"
34
- response = $api_server.request('get', endpoint)
32
+ def get_metadata()
33
+ response = $api_server.request('get', "/cosmos-api/metadata/latest")
35
34
  return nil if response.nil? || response.code != 200
36
35
  return JSON.parse(response.body)
37
36
  end
38
37
 
39
- # Sets the metadata value for a target
38
+ # Sets the metadata
40
39
  #
41
- # @param target [String] Target to set metadata on
42
40
  # @param metadata [Hash<Symbol, Variable>] A hash of metadata
43
- # @param color [String] Events color to show on Calendar tool
44
- # @param start (optional) [String] Metadata time value if nil will default to current time
41
+ # @param color [String] Events color to show on Calendar tool, if nil will be blue
42
+ # @param start [Time] Metadata time value, if nil will be current time
45
43
  # @return The result of the method call.
46
- def set_metadata(target, metadata, color: nil, start: nil)
44
+ def set_metadata(metadata, color: nil, start: nil)
45
+ unless metadata.is_a?(Hash)
46
+ raise "metadata must be a Hash: #{metadata} is a #{metadata.class}"
47
+ end
47
48
  color = color.nil? ? '#003784' : color
48
- data = {:color => color, :metadata => metadata, :target => target}
49
- data[:start] = start unless start.nil?
49
+ data = { color: color, metadata: metadata }
50
+ data[:start] = start.iso8601 unless start.nil?
50
51
  response = $api_server.request('post', '/cosmos-api/metadata', data: data, json: true)
51
52
  return nil if response.nil? || response.code != 201
52
53
  return JSON.parse(response.body)
53
54
  end
54
55
 
55
- # Requests the metadata from the user for a target
56
+ # Updates the metadata
56
57
  #
57
- def input_metadata(*args, **kwargs)
58
- rasie StandardError "can only be used in script-runner"
58
+ # @param metadata [Hash<Symbol, Variable>] A hash of metadata
59
+ # @param color [String] Events color to show on Calendar tool, if nil will be blue
60
+ # @param start [Integer] Metadata time value as integer seconds from epoch
61
+ # @return The result of the method call.
62
+ def update_metadata(metadata, color: nil, start: nil)
63
+ unless metadata.is_a?(Hash)
64
+ raise "metadata must be a Hash: #{metadata} is a #{metadata.class}"
65
+ end
66
+ color = color.nil? ? '#003784' : color
67
+ if start == nil
68
+ existing = get_metadata()
69
+ start = existing['start']
70
+ metadata = existing['metadata'].merge(metadata)
71
+ end
72
+ data = { :color => color, :metadata => metadata }
73
+ data[:start] = Time.at(start).iso8601
74
+ response = $api_server.request('put', "/cosmos-api/metadata/#{start}", data: data, json: true)
75
+ return nil if response.nil? || response.code != 201
76
+ return JSON.parse(response.body)
59
77
  end
60
78
 
79
+ # Requests the metadata from the user for a target
80
+ def input_metadata(*args, **kwargs)
81
+ raise StandardError "can only be used in Script Runner"
82
+ end
61
83
  end
62
84
  end
@@ -112,13 +112,11 @@ module Cosmos
112
112
  target_name, cmd_name, cmd_params = $api_server.method_missing(cmd, *args)
113
113
  _log_cmd(target_name, cmd_name, cmd_params, raw, no_range, no_hazardous)
114
114
  rescue HazardousError => e
115
- ok_to_proceed = prompt_for_hazardous(e.target_name, e.cmd_name, e.hazardous_description)
116
- if ok_to_proceed
117
- target_name, cmd_name, cmd_params = $api_server.method_missing(cmd_no_hazardous, *args)
118
- _log_cmd(target_name, cmd_name, cmd_params, raw, no_range, no_hazardous)
119
- else
120
- retry unless prompt_for_script_abort()
121
- end
115
+ # This opens a prompt at which point they can cancel and stop the script
116
+ # or say Yes and send the command. Thus we don't care about the return value.
117
+ prompt_for_hazardous(e.target_name, e.cmd_name, e.hazardous_description)
118
+ target_name, cmd_name, cmd_params = $api_server.method_missing(cmd_no_hazardous, *args)
119
+ _log_cmd(target_name, cmd_name, cmd_params, raw, no_range, no_hazardous)
122
120
  end
123
121
  end
124
122
  end
@@ -129,58 +129,38 @@ module Cosmos
129
129
  message_box(string, *items, **options)
130
130
  end
131
131
 
132
- def _file_dialog(message, directory, filter, select_files = true)
132
+ def _file_dialog(title, message, filter:)
133
133
  answer = ''
134
- files = Dir["#{directory}/#{filter}"]
135
- if select_files
136
- files.select! { |f| !File.directory? f }
137
- else
138
- files.select! { |f| File.directory? f }
139
- end
134
+ path = "./*"
135
+ path += filter if filter
136
+ files = Dir[path]
137
+ files.select! { |f| !File.directory? f }
140
138
  while answer.empty?
141
- print message + "\n" + files.join("\n") + "\n<Type file name>:"
139
+ print "#{title}\n#{message}\n#{files.join("\n")}\n<Type file name>:"
142
140
  answer = gets
143
141
  answer.chomp!
144
142
  end
145
143
  return answer
146
144
  end
147
145
 
148
- def save_file_dialog(directory, message = "Save File", filter = "*")
149
- _file_dialog(message, directory, filter)
150
- end
151
-
152
- def open_file_dialog(directory, message = "Open File", filter = "*")
153
- _file_dialog(message, directory, filter)
154
- end
155
-
156
- def open_files_dialog(directory, message = "Open File(s)", filter = "*")
157
- _file_dialog(message, directory, filter)
146
+ def open_file_dialog(title, message = "Open File", filter:)
147
+ _file_dialog(title, message, filter)
158
148
  end
159
149
 
160
- def open_directory_dialog(directory, message = "Open Directory")
161
- _file_dialog(message, directory, "*", false)
150
+ def open_files_dialog(title, message = "Open File(s)", filter:)
151
+ _file_dialog(title, message, filter)
162
152
  end
163
153
 
164
154
  def prompt_for_hazardous(target_name, cmd_name, hazardous_description)
165
- message = "Warning: Command #{target_name} #{cmd_name} is Hazardous. "
166
- message << "\n#{hazardous_description}\n" if hazardous_description
167
- message << "Send? (y,n): "
168
- print message
169
- answer = gets.chomp
170
- if answer.downcase == 'y'
171
- return true
172
- else
173
- return false
174
- end
175
- end
176
-
177
- def prompt_for_script_abort
178
- print "Stop running script? (y,n): "
179
- answer = gets.chomp
180
- if answer.downcase == 'y'
181
- exit
182
- else
183
- return false # Not aborted - Retry
155
+ loop do
156
+ message = "Warning: Command #{target_name} #{cmd_name} is Hazardous. "
157
+ message << "\n#{hazardous_description}\n" if hazardous_description
158
+ message << "Send? (y): "
159
+ print message
160
+ answer = gets.chomp
161
+ if answer.downcase == 'y'
162
+ return true
163
+ end
184
164
  end
185
165
  end
186
166