openc3 5.19.0 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -7
  3. data/bin/openc3cli +12 -120
  4. data/bin/pipinstall +5 -3
  5. data/data/config/command_modifiers.yaml +17 -1
  6. data/data/config/interface_modifiers.yaml +21 -4
  7. data/data/config/item_modifiers.yaml +1 -1
  8. data/data/config/microservice.yaml +15 -2
  9. data/data/config/param_item_modifiers.yaml +1 -1
  10. data/data/config/parameter_modifiers.yaml +1 -1
  11. data/data/config/table_manager.yaml +2 -2
  12. data/data/config/target.yaml +11 -0
  13. data/data/config/telemetry_modifiers.yaml +17 -1
  14. data/data/config/tool.yaml +12 -0
  15. data/data/config/widgets.yaml +41 -17
  16. data/ext/openc3/ext/packet/packet.c +3 -0
  17. data/lib/openc3/accessors/form_accessor.rb +4 -3
  18. data/lib/openc3/accessors/html_accessor.rb +3 -3
  19. data/lib/openc3/accessors/http_accessor.rb +13 -13
  20. data/lib/openc3/accessors/xml_accessor.rb +16 -4
  21. data/lib/openc3/api/cmd_api.rb +4 -5
  22. data/lib/openc3/api/limits_api.rb +3 -3
  23. data/lib/openc3/api/target_api.rb +0 -30
  24. data/lib/openc3/api/tlm_api.rb +2 -1
  25. data/lib/openc3/bridge/bridge_config.rb +1 -2
  26. data/lib/openc3/ccsds/ccsds_parser.rb +12 -8
  27. data/lib/openc3/config/config_parser.rb +10 -3
  28. data/lib/openc3/conversions/bit_reverse_conversion.rb +1 -0
  29. data/lib/openc3/conversions/conversion.rb +5 -1
  30. data/lib/openc3/conversions/generic_conversion.rb +3 -8
  31. data/lib/openc3/conversions/object_read_conversion.rb +1 -8
  32. data/lib/openc3/conversions/polynomial_conversion.rb +3 -8
  33. data/lib/openc3/conversions/processor_conversion.rb +13 -11
  34. data/lib/openc3/conversions/segmented_polynomial_conversion.rb +3 -11
  35. data/lib/openc3/conversions/unix_time_conversion.rb +4 -7
  36. data/lib/openc3/conversions/unix_time_formatted_conversion.rb +4 -3
  37. data/lib/openc3/conversions/unix_time_seconds_conversion.rb +4 -3
  38. data/lib/openc3/core_ext/array.rb +0 -16
  39. data/lib/openc3/core_ext.rb +0 -1
  40. data/lib/openc3/interfaces/file_interface.rb +198 -0
  41. data/lib/openc3/interfaces/http_client_interface.rb +71 -39
  42. data/lib/openc3/interfaces/http_server_interface.rb +1 -9
  43. data/lib/openc3/interfaces/interface.rb +3 -2
  44. data/lib/openc3/interfaces/mqtt_interface.rb +32 -15
  45. data/lib/openc3/interfaces/mqtt_stream_interface.rb +19 -4
  46. data/lib/openc3/interfaces/protocols/crc_protocol.rb +7 -0
  47. data/lib/openc3/interfaces/serial_interface.rb +1 -0
  48. data/lib/openc3/interfaces/tcpip_server_interface.rb +1 -2
  49. data/lib/openc3/interfaces/udp_interface.rb +5 -3
  50. data/lib/openc3/interfaces.rb +2 -4
  51. data/lib/openc3/io/json_drb.rb +5 -0
  52. data/lib/openc3/io/json_rpc.rb +10 -9
  53. data/lib/openc3/io/udp_sockets.rb +7 -5
  54. data/lib/openc3/microservices/decom_microservice.rb +24 -7
  55. data/lib/openc3/microservices/interface_microservice.rb +65 -7
  56. data/lib/openc3/microservices/microservice.rb +1 -2
  57. data/lib/openc3/microservices/multi_microservice.rb +3 -3
  58. data/lib/openc3/migrations/20241208080000_no_critical_cmd.rb +31 -0
  59. data/lib/openc3/migrations/20241208080001_no_trigger_group.rb +46 -0
  60. data/lib/openc3/models/activity_model.rb +7 -3
  61. data/lib/openc3/models/cvt_model.rb +7 -1
  62. data/lib/openc3/models/interface_model.rb +9 -3
  63. data/lib/openc3/models/microservice_model.rb +8 -1
  64. data/lib/openc3/models/model.rb +1 -0
  65. data/lib/openc3/models/plugin_model.rb +11 -6
  66. data/lib/openc3/models/python_package_model.rb +10 -3
  67. data/lib/openc3/models/reaction_model.rb +14 -10
  68. data/lib/openc3/models/scope_model.rb +87 -25
  69. data/lib/openc3/models/target_model.rb +17 -1
  70. data/lib/openc3/models/timeline_model.rb +17 -5
  71. data/lib/openc3/models/tool_model.rb +15 -3
  72. data/lib/openc3/models/trigger_group_model.rb +6 -3
  73. data/lib/openc3/operators/microservice_operator.rb +10 -3
  74. data/lib/openc3/packets/commands.rb +17 -6
  75. data/lib/openc3/packets/limits.rb +0 -12
  76. data/lib/openc3/packets/packet.rb +10 -1
  77. data/lib/openc3/packets/packet_config.rb +34 -1
  78. data/lib/openc3/packets/packet_item.rb +30 -32
  79. data/lib/openc3/packets/structure_item.rb +2 -2
  80. data/lib/openc3/script/calendar.rb +1 -6
  81. data/lib/openc3/script/commands.rb +19 -13
  82. data/lib/openc3/script/critical_cmd.rb +91 -0
  83. data/lib/openc3/script/screen.rb +2 -2
  84. data/lib/openc3/script/script.rb +17 -10
  85. data/lib/openc3/script/web_socket_api.rb +5 -5
  86. data/lib/openc3/streams/mqtt_stream.rb +41 -33
  87. data/lib/openc3/streams/serial_stream.rb +27 -27
  88. data/lib/openc3/streams/stream.rb +17 -17
  89. data/lib/openc3/streams/tcpip_client_stream.rb +1 -1
  90. data/lib/openc3/streams/tcpip_socket_stream.rb +19 -19
  91. data/lib/openc3/system/system.rb +1 -1
  92. data/lib/openc3/system.rb +2 -3
  93. data/lib/openc3/tools/table_manager/table.rb +2 -2
  94. data/lib/openc3/tools/table_manager/table_parser.rb +1 -1
  95. data/lib/openc3/top_level.rb +9 -5
  96. data/lib/openc3/topics/command_decom_topic.rb +0 -7
  97. data/lib/openc3/topics/command_topic.rb +16 -0
  98. data/lib/openc3/topics/interface_topic.rb +2 -0
  99. data/lib/openc3/utilities/authentication.rb +7 -3
  100. data/lib/openc3/utilities/bucket_utilities.rb +1 -1
  101. data/lib/openc3/utilities/cli_generator.rb +0 -1
  102. data/lib/openc3/utilities/logger.rb +1 -0
  103. data/lib/openc3/utilities/store_queued.rb +1 -0
  104. data/lib/openc3/version.rb +6 -6
  105. data/templates/conversion/conversion.rb +2 -0
  106. data/templates/plugin/README.md +1 -1
  107. data/templates/target/targets/TARGET/lib/target.rb +1 -1
  108. data/templates/tool_angular/package.json +9 -9
  109. data/templates/tool_angular/src/app/app.component.html +4 -13
  110. data/templates/tool_angular/src/app/app.component.scss +5 -13
  111. data/templates/tool_angular/src/app/app.component.ts +5 -4
  112. data/templates/tool_angular/src/app/custom-overlay-container.ts +2 -2
  113. data/templates/tool_angular/src/app/openc3-api.d.ts +1 -1
  114. data/templates/tool_angular/src/main.single-spa.ts +1 -1
  115. data/templates/tool_react/package.json +1 -0
  116. data/templates/tool_react/src/root.component.js +1 -1
  117. data/templates/tool_svelte/build/smui.css +1 -1
  118. data/templates/tool_svelte/package.json +11 -9
  119. data/templates/tool_svelte/rollup.config.js +2 -0
  120. data/templates/tool_svelte/src/App.svelte +2 -2
  121. data/templates/tool_vue/eslint.config.mjs +68 -0
  122. data/templates/tool_vue/jsconfig.json +1 -1
  123. data/templates/tool_vue/package.json +26 -43
  124. data/templates/tool_vue/src/App.vue +3 -5
  125. data/templates/tool_vue/src/main.js +12 -23
  126. data/templates/tool_vue/src/router.js +19 -18
  127. data/templates/tool_vue/src/tools/tool_name/tool_name.vue +2 -2
  128. data/templates/tool_vue/vite.config.js +52 -0
  129. data/templates/widget/package.json +19 -26
  130. data/templates/widget/src/Widget.vue +13 -15
  131. data/templates/widget/vite.config.js +26 -0
  132. metadata +25 -39
  133. data/lib/openc3/core_ext/hash.rb +0 -40
  134. data/lib/openc3/core_ext/httpclient.rb +0 -11
  135. data/lib/openc3/interfaces/linc_interface.rb +0 -480
  136. data/lib/openc3/interfaces/protocols/override_protocol.rb +0 -4
  137. data/lib/openc3/microservices/reaction_microservice.rb +0 -607
  138. data/lib/openc3/microservices/timeline_microservice.rb +0 -400
  139. data/lib/openc3/microservices/trigger_group_microservice.rb +0 -698
  140. data/lib/openc3/migrations/20230615000000_autonomic.rb +0 -86
  141. data/lib/openc3/migrations/20240915000000_activity_uuid.rb +0 -28
  142. data/lib/openc3/system/system_config.rb +0 -413
  143. data/templates/tool_svelte/src/services/api.js +0 -92
  144. data/templates/tool_svelte/src/services/axios.js +0 -85
  145. data/templates/tool_svelte/src/services/cable.js +0 -65
  146. data/templates/tool_svelte/src/services/config-parser.js +0 -198
  147. data/templates/tool_svelte/src/services/openc3-api.js +0 -606
  148. data/templates/tool_vue/.eslintrc.js +0 -43
  149. data/templates/tool_vue/babel.config.json +0 -11
  150. data/templates/tool_vue/vue.config.js +0 -38
  151. data/templates/widget/.eslintrc.js +0 -43
  152. data/templates/widget/babel.config.json +0 -11
  153. data/templates/widget/vue.config.js +0 -28
  154. /data/templates/tool_vue/{.prettierrc.js → .prettierrc.cjs} +0 -0
  155. /data/templates/widget/{.prettierrc.js → .prettierrc.cjs} +0 -0
@@ -64,9 +64,9 @@ module OpenC3
64
64
  end
65
65
  end
66
66
 
67
- attr_reader :name, :scope, :updated_at
67
+ attr_reader :name, :scope, :shard, :updated_at
68
68
 
69
- def initialize(name:, scope:, updated_at: nil)
69
+ def initialize(name:, scope:, shard: 0, updated_at: nil)
70
70
  unless name.is_a?(String)
71
71
  raise TriggerGroupInputError.new "invalid group name: '#{name}'"
72
72
  end
@@ -75,6 +75,7 @@ module OpenC3
75
75
  end
76
76
  super("#{scope}#{PRIMARY_KEY}", name: name, scope: scope)
77
77
  @microservice_name = "#{scope}__TRIGGER_GROUP__#{name}"
78
+ @shard = shard.to_i # to_i to handle nil
78
79
  @updated_at = updated_at
79
80
  end
80
81
 
@@ -93,6 +94,7 @@ module OpenC3
93
94
  return {
94
95
  'name' => @name,
95
96
  'scope' => @scope,
97
+ 'shard' => @shard,
96
98
  'updated_at' => @updated_at,
97
99
  }
98
100
  end
@@ -122,11 +124,12 @@ module OpenC3
122
124
  name: @microservice_name,
123
125
  folder_name: nil,
124
126
  cmd: ['ruby', "trigger_group_microservice.rb", @microservice_name],
125
- work_dir: '/openc3/lib/openc3/microservices',
127
+ work_dir: '/openc3-enterprise/lib/openc3-enterprise/microservices',
126
128
  options: [],
127
129
  topics: topics,
128
130
  target_names: [],
129
131
  plugin: nil,
132
+ shard: @shard,
130
133
  scope: @scope
131
134
  )
132
135
  microservice.create
@@ -42,6 +42,8 @@ module OpenC3
42
42
  @new_microservices = {}
43
43
  @changed_microservices = {}
44
44
  @removed_microservices = {}
45
+ @shard = ENV['OPENC3_SHARD'] || 0
46
+ @shard = @shard.to_i
45
47
  end
46
48
 
47
49
  def convert_microservice_to_process_definition(microservice_name, microservice_config)
@@ -65,10 +67,9 @@ module OpenC3
65
67
  secrets.each do |type, secret_name, env_name_or_path, secret_store|
66
68
  secret_value = @secrets.get(secret_name, secret_store: secret_store, scope: scope)
67
69
  if secret_value
68
- case type
69
- when 'ENV'
70
+ if type == 'ENV'
70
71
  env[env_name_or_path] = secret_value
71
- when 'FILE'
72
+ elsif type == 'FILE'
72
73
  FileUtils.mkdir_p(File.dirname(env_name_or_path))
73
74
  File.open(env_name_or_path, 'wb') do |file|
74
75
  file.write(secret_value)
@@ -88,6 +89,12 @@ module OpenC3
88
89
  # Get all the microservice configuration
89
90
  @microservices = MicroserviceModel.all
90
91
 
92
+ # Filter to just this shard
93
+ @microservices = @microservices.select do |microservice_name, microservice_config|
94
+ microservice_shard = microservice_config['shard'] || 0
95
+ microservice_shard == @shard
96
+ end
97
+
91
98
  # Detect new and changed microservices
92
99
  @new_microservices = {}
93
100
  @changed_microservices = {}
@@ -14,7 +14,7 @@
14
14
  # GNU Affero General Public License for more details.
15
15
 
16
16
  # Modified by OpenC3, Inc.
17
- # All changes Copyright 2022, OpenC3, Inc.
17
+ # All changes Copyright 2024, OpenC3, Inc.
18
18
  # All Rights Reserved
19
19
  #
20
20
  # This file may also be used under the terms of a commercial license
@@ -308,12 +308,23 @@ module OpenC3
308
308
  item = command.get_item(item_upcase)
309
309
  range_check_value = value
310
310
 
311
- # Convert from state to value if possible
312
- if item.states and item.states[value.to_s.upcase]
313
- range_check_value = item.states[value.to_s.upcase]
314
- end
315
-
316
311
  if range_checking
312
+ if item.states
313
+ if item.states[value.to_s.upcase]
314
+ range_check_value = item.states[value.to_s.upcase]
315
+ else
316
+ unless item.states.values.include?(value)
317
+ if command.raw
318
+ # Raw commands report missing value maps
319
+ raise "Command parameter '#{command.target_name} #{command.packet_name} #{item_upcase}' = #{value.to_s.upcase} not one of #{item.states.values.join(', ')}"
320
+ else
321
+ # Normal commands report missing state maps
322
+ raise "Command parameter '#{command.target_name} #{command.packet_name} #{item_upcase}' = #{value.to_s.upcase} not one of #{item.states.keys.join(', ')}"
323
+ end
324
+ end
325
+ end
326
+ end
327
+
317
328
  range = item.range
318
329
  if range
319
330
  # Perform Range Check on command parameter
@@ -50,18 +50,6 @@ module OpenC3
50
50
  return @config.limits_sets
51
51
  end
52
52
 
53
- # (see OpenC3::Packet#out_of_limits)
54
- def out_of_limits
55
- items = []
56
- @config.telemetry.each do |target_name, target_packets|
57
- target_packets.each do |packet_name, packet|
58
- new_items = packet.out_of_limits
59
- items.concat(new_items)
60
- end
61
- end
62
- return items
63
- end
64
-
65
53
  # @return [Hash(String, Array)] The defined limits groups
66
54
  def groups
67
55
  return @config.limits_groups
@@ -110,6 +110,9 @@ module OpenC3
110
110
  # @return [Boolean] If this packet should be used for identification
111
111
  attr_reader :virtual
112
112
 
113
+ # @return [Boolean] If this packet is marked as restricted use
114
+ attr_accessor :restricted
115
+
113
116
  # Valid format types
114
117
  VALUE_TYPES = [:RAW, :CONVERTED, :FORMATTED, :WITH_UNITS]
115
118
 
@@ -151,6 +154,7 @@ module OpenC3
151
154
  @packet_time = nil
152
155
  @ignore_overlap = false
153
156
  @virtual = false
157
+ @restricted = false
154
158
  @validator = nil
155
159
  end
156
160
 
@@ -752,7 +756,7 @@ module OpenC3
752
756
  super(item, value, :RAW, buffer)
753
757
  rescue ArgumentError => e
754
758
  if item.states and String === value and e.message =~ /invalid value for/
755
- raise "Unknown state #{value} for #{item.name}"
759
+ raise "Unknown state #{value} for #{item.name}, must be one of #{item.states.keys.join(', ')}"
756
760
  else
757
761
  raise e
758
762
  end
@@ -1085,6 +1089,9 @@ module OpenC3
1085
1089
  elsif @hidden
1086
1090
  config << " HIDDEN\n"
1087
1091
  end
1092
+ if @restricted
1093
+ config << " RESTRICTED\n"
1094
+ end
1088
1095
 
1089
1096
  if @processors
1090
1097
  @processors.each do |_processor_name, processor|
@@ -1145,6 +1152,7 @@ module OpenC3
1145
1152
  config['disabled'] = true if @disabled
1146
1153
  config['hidden'] = true if @hidden
1147
1154
  config['virtual'] = true if @virtual
1155
+ config['restricted'] = true if @restricted
1148
1156
  config['accessor'] = @accessor.class.to_s
1149
1157
  config['accessor_args'] = @accessor.args
1150
1158
  config['validator'] = @validator.class.to_s if @validator
@@ -1201,6 +1209,7 @@ module OpenC3
1201
1209
  packet.disabled = hash['disabled']
1202
1210
  packet.hidden = hash['hidden']
1203
1211
  packet.virtual = hash['virtual']
1212
+ packet.restricted = hash['restricted']
1204
1213
  if hash['accessor']
1205
1214
  begin
1206
1215
  accessor = OpenC3::const_get(hash['accessor'])
@@ -34,9 +34,11 @@ require 'openc3/packets/parsers/xtce_converter'
34
34
  require 'openc3/utilities/python_proxy'
35
35
  require 'openc3/conversions'
36
36
  require 'openc3/processors'
37
+ require 'openc3/accessors'
37
38
  require 'nokogiri'
38
39
  require 'ostruct'
39
40
  require 'fileutils'
41
+ require 'tempfile'
40
42
 
41
43
  module OpenC3
42
44
  # Reads a command or telemetry configuration file and builds a hash of packets.
@@ -219,7 +221,7 @@ module OpenC3
219
221
  'PARAMETER', 'ID_ITEM', 'ID_PARAMETER', 'ARRAY_ITEM', 'ARRAY_PARAMETER', 'APPEND_ITEM',\
220
222
  'APPEND_PARAMETER', 'APPEND_ID_ITEM', 'APPEND_ID_PARAMETER', 'APPEND_ARRAY_ITEM',\
221
223
  'APPEND_ARRAY_PARAMETER', 'ALLOW_SHORT', 'HAZARDOUS', 'PROCESSOR', 'META',\
222
- 'DISABLE_MESSAGES', 'HIDDEN', 'DISABLED', 'VIRTUAL', 'ACCESSOR', 'TEMPLATE', 'TEMPLATE_FILE',\
224
+ 'DISABLE_MESSAGES', 'HIDDEN', 'DISABLED', 'VIRTUAL', 'RESTRICTED', 'ACCESSOR', 'TEMPLATE', 'TEMPLATE_FILE',\
223
225
  'RESPONSE', 'ERROR_RESPONSE', 'SCREEN', 'RELATED_ITEM', 'IGNORE_OVERLAP', 'VALIDATOR'
224
226
  raise parser.error("No current packet for #{keyword}") unless @current_packet
225
227
 
@@ -367,6 +369,32 @@ module OpenC3
367
369
  end
368
370
  end
369
371
 
372
+ # This method provides way to quickly test packet configs
373
+ #
374
+ # require 'openc3/packets/packet_config'
375
+ #
376
+ # config = <<END
377
+ # ...
378
+ # END
379
+ #
380
+ # pc = PacketConfig.from_config(config, "MYTARGET")
381
+ # c = pc.commands['CMDADCS']['SET_POINTING_CMD']
382
+ # c.restore_defaults()
383
+ # c.write("MYITEM", 5)
384
+ # puts c.buffer.formatted
385
+ def self.from_config(config, process_target_name, language = 'ruby')
386
+ pc = self.new
387
+ tf = Tempfile.new("pc.txt")
388
+ tf.write(config)
389
+ tf.close
390
+ begin
391
+ pc.process_file(tf.path, process_target_name, language)
392
+ ensure
393
+ tf.unlink
394
+ end
395
+ return pc
396
+ end
397
+
370
398
  protected
371
399
 
372
400
  def update_id_value_hash(packet, hash)
@@ -480,6 +508,11 @@ module OpenC3
480
508
  @current_packet.disabled = true
481
509
  @current_packet.virtual = true
482
510
 
511
+ when 'RESTRICTED'
512
+ usage = "#{keyword}"
513
+ parser.verify_num_parameters(0, 0, usage)
514
+ @current_packet.restricted = true
515
+
483
516
  when 'ACCESSOR', 'VALIDATOR'
484
517
  usage = "#{keyword} <Class name> <Optional parameters> ..."
485
518
  parser.verify_num_parameters(1, nil, usage)
@@ -112,8 +112,6 @@ module OpenC3
112
112
  @messages_disabled = nil
113
113
  @state_colors = nil
114
114
  @limits = PacketItemLimits.new
115
- @persistence_setting = 1
116
- @persistence_count = 0
117
115
  @meta = nil
118
116
  end
119
117
 
@@ -426,15 +424,13 @@ module OpenC3
426
424
  config << self.read_conversion.to_config(:READ) if self.read_conversion
427
425
  config << self.write_conversion.to_config(:WRITE) if self.write_conversion
428
426
 
429
- if self.limits
430
- if self.limits.values
431
- self.limits.values.each do |limits_set, limits_values|
432
- config << " LIMITS #{limits_set} #{self.limits.persistence_setting} #{self.limits.enabled ? 'ENABLED' : 'DISABLED'} #{limits_values[0]} #{limits_values[1]} #{limits_values[2]} #{limits_values[3]}"
433
- if limits_values[4] && limits_values[5]
434
- config << " #{limits_values[4]} #{limits_values[5]}\n"
435
- else
436
- config << "\n"
437
- end
427
+ if self.limits.values
428
+ self.limits.values.each do |limits_set, limits_values|
429
+ config << " LIMITS #{limits_set} #{self.limits.persistence_setting} #{self.limits.enabled ? 'ENABLED' : 'DISABLED'} #{limits_values[0]} #{limits_values[1]} #{limits_values[2]} #{limits_values[3]}"
430
+ if limits_values[4] && limits_values[5]
431
+ config << " #{limits_values[4]} #{limits_values[5]}\n"
432
+ else
433
+ config << "\n"
438
434
  end
439
435
  end
440
436
  config << self.limits.response.to_config if self.limits.response
@@ -489,31 +485,33 @@ module OpenC3
489
485
  config['read_conversion'] = self.read_conversion.as_json(*a) if self.read_conversion
490
486
  config['write_conversion'] = self.write_conversion.as_json(*a) if self.write_conversion
491
487
 
492
- if self.limits
493
- config['limits'] ||= {}
494
- config['limits']['enabled'] = true if self.limits.enabled
495
- if self.limits.values
496
- config['limits'] ||= {}
497
- config['limits']['persistence_setting'] = self.limits.persistence_setting
498
- config['limits']['response'] = self.limits.response.to_s if self.limits.response
499
- self.limits.values.each do |limits_set, limits_values|
500
- limits = {}
501
- limits['red_low'] = limits_values[0]
502
- limits['yellow_low'] = limits_values[1]
503
- limits['yellow_high'] = limits_values[2]
504
- limits['red_high'] = limits_values[3]
505
- limits['green_low'] = limits_values[4] if limits_values[4]
506
- limits['green_high'] = limits_values[5] if limits_values[5]
507
- config['limits'][limits_set] = limits
508
- end
488
+ config['limits'] ||= {}
489
+ if self.limits.enabled
490
+ config['limits']['enabled'] = true
491
+ elsif self.limits.values || (self.state_colors && self.state_colors.length > 0)
492
+ # Only set to false if there are limits or state colors
493
+ # to avoid items without limits acting like they can be enabled
494
+ config['limits']['enabled'] = false
495
+ end
496
+ if self.limits.values
497
+ # Only set these if there are limits.values because persistence_setting has a default
498
+ # and we don't want keys on the 'limits' hash if there aren't any limits
499
+ config['limits']['persistence_setting'] = self.limits.persistence_setting if self.limits.persistence_setting
500
+ config['limits']['response'] = self.limits.response.to_s if self.limits.response
501
+ self.limits.values.each do |limits_set, limits_values|
502
+ limits = {}
503
+ limits['red_low'] = limits_values[0]
504
+ limits['yellow_low'] = limits_values[1]
505
+ limits['yellow_high'] = limits_values[2]
506
+ limits['red_high'] = limits_values[3]
507
+ limits['green_low'] = limits_values[4] if limits_values[4]
508
+ limits['green_high'] = limits_values[5] if limits_values[5]
509
+ config['limits'][limits_set] = limits
509
510
  end
510
- config['limits_response'] = self.limits.response.as_json(*a) if self.limits.response
511
511
  end
512
512
 
513
513
  config['meta'] = @meta if @meta
514
- if @variable_bit_size
515
- config['variable_bit_size'] = @variable_bit_size
516
- end
514
+ config['variable_bit_size'] = @variable_bit_size if @variable_bit_size
517
515
  config
518
516
  end
519
517
 
@@ -14,7 +14,7 @@
14
14
  # GNU Affero General Public License for more details.
15
15
 
16
16
  # Modified by OpenC3, Inc.
17
- # All changes Copyright 2022, OpenC3, Inc.
17
+ # All changes Copyright 2024, OpenC3, Inc.
18
18
  # All Rights Reserved
19
19
  #
20
20
  # This file may also be used under the terms of a commercial license
@@ -141,7 +141,7 @@ module OpenC3
141
141
  end
142
142
 
143
143
  def key=(key)
144
- raise ArgumentError, "key must be a String but is a #{name.class}" unless String === key
144
+ raise ArgumentError, "key must be a String but is a #{key.class}" unless String === key
145
145
  raise ArgumentError, "key must contain at least one character" if key.empty?
146
146
 
147
147
  @key = key
@@ -98,12 +98,7 @@ module OpenC3
98
98
  result = JSON.parse(response.body, :allow_nan => true, :create_additions => true)
99
99
  raise "#{error_message} due to #{result['message']}"
100
100
  end
101
- # TODO: Not sure why the response body is empty (on delete) but check for that
102
- if response.body.nil? or response.body.empty?
103
- return nil
104
- else
105
- return JSON.parse(response.body, :allow_nan => true, :create_additions => true)
106
- end
101
+ return JSON.parse(response.body, :allow_nan => true, :create_additions => true)
107
102
  end
108
103
  end
109
104
  end
@@ -46,12 +46,10 @@ module OpenC3
46
46
  next if Packet::RESERVED_ITEM_NAMES.include?(key)
47
47
 
48
48
  if value.is_a?(String)
49
- value = value.convert_to_value.to_s
50
- if value.length > 256
51
- value = value[0..255] + "...'"
52
- end
53
49
  if !value.is_printable?
54
50
  value = "BINARY"
51
+ elsif value.length > 256
52
+ value = value[0..255] + "...'"
55
53
  end
56
54
  value.tr!('"', "'")
57
55
  elsif value.is_a?(Array)
@@ -120,17 +118,25 @@ module OpenC3
120
118
  _cmd_disconnect(cmd, raw, no_range, no_hazardous, *args, scope: scope)
121
119
  else
122
120
  begin
123
- target_name, cmd_name, cmd_params = $api_server.method_missing(cmd, *args, timeout: timeout, log_message: log_message, validate: validate, scope: scope, token: token)
124
- if log_message.nil? or log_message
125
- _log_cmd(target_name, cmd_name, cmd_params, raw, no_range, no_hazardous)
121
+ begin
122
+ target_name, cmd_name, cmd_params = $api_server.method_missing(cmd, *args, timeout: timeout, log_message: log_message, validate: validate, scope: scope, token: token)
123
+ if log_message.nil? or log_message
124
+ _log_cmd(target_name, cmd_name, cmd_params, raw, no_range, no_hazardous)
125
+ end
126
+ rescue HazardousError => e
127
+ # This opens a prompt at which point they can cancel and stop the script
128
+ # or say Yes and send the command. Thus we don't care about the return value.
129
+ prompt_for_hazardous(e.target_name, e.cmd_name, e.hazardous_description)
130
+ target_name, cmd_name, cmd_params = $api_server.method_missing(cmd_no_hazardous, *args, timeout: timeout, log_message: log_message, validate: validate, scope: scope, token: token)
131
+ if log_message.nil? or log_message
132
+ _log_cmd(target_name, cmd_name, cmd_params, raw, no_range, no_hazardous)
133
+ end
126
134
  end
127
- rescue HazardousError => e
128
- # This opens a prompt at which point they can cancel and stop the script
129
- # or say Yes and send the command. Thus we don't care about the return value.
130
- prompt_for_hazardous(e.target_name, e.cmd_name, e.hazardous_description)
131
- target_name, cmd_name, cmd_params = $api_server.method_missing(cmd_no_hazardous, *args, timeout: timeout, log_message: log_message, validate: validate, scope: scope, token: token)
135
+ rescue CriticalCmdError => e
136
+ # This should not return until the critical command has been approved
137
+ prompt_for_critical_cmd(e.uuid, e.username, e.target_name, e.cmd_name, e.cmd_params, e.cmd_string)
132
138
  if log_message.nil? or log_message
133
- _log_cmd(target_name, cmd_name, cmd_params, raw, no_range, no_hazardous)
139
+ _log_cmd(e.target_name, e.cmd_name, e.cmd_params, raw, no_range, no_hazardous)
134
140
  end
135
141
  end
136
142
  end
@@ -0,0 +1,91 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2024 OpenC3, Inc.
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 Affero 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
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # This file may also be used under the terms of a commercial license
17
+ # if purchased from OpenC3, Inc.
18
+
19
+ module OpenC3
20
+ module Script
21
+ private
22
+
23
+ def critical_cmd_status(uuid, scope: $openc3_scope)
24
+ begin
25
+ endpoint = "/openc3-api/criticalcmd/status/#{uuid}"
26
+ response = $api_server.request('get', endpoint, scope: scope)
27
+ if response.nil? || response.status != 200
28
+ raise "Unexpected response to critical_cmd_status: #{response.inspect}"
29
+ end
30
+ result = JSON.parse(response.body)
31
+ return result['status']
32
+ rescue => error
33
+ raise "critical_cmd_status failed due to #{error.formatted}"
34
+ end
35
+ end
36
+
37
+ def critical_cmd_approve(uuid, scope: $openc3_scope)
38
+ begin
39
+ endpoint = "/openc3-api/criticalcmd/approve/#{uuid}"
40
+ response = $api_server.request('post', endpoint, :json => true, scope: scope)
41
+ if response.nil? || response.status != 200
42
+ if response
43
+ parsed = JSON.parse(response.body)
44
+ raise "critical_cmd_approve error: #{parsed['error']}"
45
+ else
46
+ raise "critical_cmd_approve failed"
47
+ end
48
+ end
49
+ return
50
+ rescue => error
51
+ raise "critical_cmd_approve failed due to #{error.formatted}"
52
+ end
53
+ end
54
+
55
+ def critical_cmd_reject(uuid, scope: $openc3_scope)
56
+ begin
57
+ endpoint = "/openc3-api/criticalcmd/reject/#{uuid}"
58
+ response = $api_server.request('post', endpoint, :json => true, scope: scope)
59
+ if response.nil? || response.status != 200
60
+ if response
61
+ parsed = JSON.parse(response.body)
62
+ raise "critical_cmd_reject error: #{parsed['error']}"
63
+ else
64
+ raise "critical_cmd_reject failed"
65
+ end
66
+ end
67
+ return
68
+ rescue => error
69
+ raise "critical_cmd_reject failed due to #{error.formatted}"
70
+ end
71
+ end
72
+
73
+ def critical_cmd_can_approve(uuid, scope: $openc3_scope)
74
+ begin
75
+ endpoint = "/openc3-api/criticalcmd/canapprove/#{uuid}"
76
+ response = $api_server.request('get', endpoint, scope: scope)
77
+ if response.nil? || response.status != 200
78
+ raise "Unexpected response to critical_cmd_can_approve: #{response.inspect}"
79
+ end
80
+ result = JSON.parse(response.body)
81
+ if result['status'] == 'ok'
82
+ return true
83
+ else
84
+ return false
85
+ end
86
+ rescue => error
87
+ raise "critical_cmd_can_approve failed due to #{error.formatted}"
88
+ end
89
+ end
90
+ end
91
+ end
@@ -70,7 +70,7 @@ module OpenC3
70
70
  response = $api_server.request('post', endpoint, :data => data, :json => true, scope: scope)
71
71
  if response.nil? || response.status != 200
72
72
  if response
73
- parsed = JSON.parse(response)
73
+ parsed = JSON.parse(response.body)
74
74
  raise "create_screen error: #{parsed['error']}"
75
75
  else
76
76
  raise "create_screen failed"
@@ -88,7 +88,7 @@ module OpenC3
88
88
  response = $api_server.request('delete', endpoint, scope: scope)
89
89
  if response.nil? || response.status != 200
90
90
  if response
91
- parsed = JSON.parse(response)
91
+ parsed = JSON.parse(response.body)
92
92
  raise "delete_screen error: #{parsed['error']}"
93
93
  else
94
94
  raise "delete_screen failed"
@@ -36,6 +36,7 @@ require 'openc3/script/storage'
36
36
  require 'openc3/script/web_socket_api'
37
37
  require 'openc3/script/packages'
38
38
  require 'openc3/script/plugins'
39
+ require 'openc3/script/critical_cmd'
39
40
  require 'openc3/utilities/authentication'
40
41
 
41
42
  $api_server = nil
@@ -108,6 +109,22 @@ module OpenC3
108
109
  end
109
110
  end
110
111
 
112
+ def prompt_for_critical_cmd(uuid, _username, _target_name, _cmd_name, _cmd_params, cmd_string)
113
+ puts "Waiting for critical command approval:"
114
+ puts " #{cmd_string}"
115
+ puts " UUID: #{uuid}"
116
+ loop do
117
+ status = critical_cmd_status(uuid)
118
+ if status == 'APPROVED'
119
+ return
120
+ elsif status == 'REJECTED'
121
+ raise "Critical command rejected"
122
+ end
123
+ # Else still waiting
124
+ wait(0.1)
125
+ end
126
+ end
127
+
111
128
  ###########################################################################
112
129
  # START PUBLIC API
113
130
  ###########################################################################
@@ -116,16 +133,6 @@ module OpenC3
116
133
  $disconnect = true
117
134
  end
118
135
 
119
- # DEPRECATED
120
- def play_wav_file(wav_filename)
121
- # NOOP
122
- end
123
-
124
- # DEPRECATED
125
- def status_bar(message)
126
- # NOOP
127
- end
128
-
129
136
  def ask_string(question, blank_or_default = false, password = false)
130
137
  answer = ''
131
138
  default = ''
@@ -126,7 +126,7 @@ module OpenC3
126
126
  # Connect to the websocket with authorization in query params
127
127
  def connect
128
128
  disconnect()
129
- final_url = @url + "?scope=#{@scope}&authorization=#{@authentication.token}"
129
+ final_url = @url + "?scope=#{@scope}&authorization=#{@authentication.token(include_bearer: false)}"
130
130
  @stream = WebSocketClientStream.new(final_url, @write_timeout, @read_timeout, @connect_timeout)
131
131
  @stream.headers = {
132
132
  'Sec-WebSocket-Protocol' => 'actioncable-v1-json, actioncable-unsupported',
@@ -240,7 +240,7 @@ module OpenC3
240
240
  end
241
241
  end
242
242
 
243
- # Autonomic Events WebSocket
243
+ # Autonomic Events WebSocket (Enterprise Only)
244
244
  class AutonomicEventsWebSocketApi < CmdTlmWebSocketApi
245
245
  def initialize(history_count: 0, url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
246
246
  @identifier = {
@@ -251,7 +251,7 @@ module OpenC3
251
251
  end
252
252
  end
253
253
 
254
- # Calendar Events WebSocket
254
+ # Calendar Events WebSocket (Enterprise Only)
255
255
  class CalendarEventsWebSocketApi < CmdTlmWebSocketApi
256
256
  def initialize(history_count: 0, url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
257
257
  @identifier = {
@@ -355,7 +355,7 @@ module OpenC3
355
355
  data_hash['items'] = items if items
356
356
  data_hash['packets'] = packets if packets
357
357
  data_hash['scope'] = scope
358
- data_hash['token'] = @authentication.token
358
+ data_hash['token'] = @authentication.token(include_bearer: false)
359
359
  write_action(data_hash)
360
360
  end
361
361
 
@@ -384,7 +384,7 @@ module OpenC3
384
384
  data_hash['items'] = items if items
385
385
  data_hash['packets'] = packets if packets
386
386
  data_hash['scope'] = scope
387
- data_hash['token'] = @authentication.token
387
+ data_hash['token'] = @authentication.token(include_bearer: false)
388
388
  write_action(data_hash)
389
389
  end
390
390