openc3 5.2.0 → 5.4.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of openc3 might be problematic. Click here for more details.

Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/bin/openc3cli +108 -105
  3. data/data/config/interface_modifiers.yaml +22 -4
  4. data/data/config/item_modifiers.yaml +4 -2
  5. data/data/config/microservice.yaml +18 -0
  6. data/data/config/table_manager.yaml +2 -2
  7. data/data/config/tool.yaml +1 -1
  8. data/ext/openc3/ext/config_parser/config_parser.c +17 -2
  9. data/lib/openc3/api/api.rb +1 -0
  10. data/lib/openc3/api/interface_api.rb +12 -0
  11. data/lib/openc3/api/metrics_api.rb +97 -0
  12. data/lib/openc3/api/router_api.rb +14 -2
  13. data/lib/openc3/api/target_api.rb +24 -3
  14. data/lib/openc3/api/tlm_api.rb +5 -4
  15. data/lib/openc3/config/config_parser.rb +29 -4
  16. data/lib/openc3/core_ext/time.rb +6 -1
  17. data/lib/openc3/interfaces/interface.rb +27 -26
  18. data/lib/openc3/interfaces/mqtt_interface.rb +240 -0
  19. data/lib/openc3/interfaces/protocols/override_protocol.rb +2 -61
  20. data/lib/openc3/interfaces/protocols/protocol.rb +6 -1
  21. data/lib/openc3/interfaces/simulated_target_interface.rb +1 -3
  22. data/lib/openc3/interfaces/tcpip_server_interface.rb +0 -11
  23. data/lib/openc3/interfaces.rb +2 -3
  24. data/lib/openc3/logs/buffered_packet_log_reader.rb +2 -2
  25. data/lib/openc3/microservices/cleanup_microservice.rb +17 -1
  26. data/lib/openc3/microservices/decom_microservice.rb +12 -9
  27. data/lib/openc3/microservices/interface_microservice.rb +93 -9
  28. data/lib/openc3/microservices/log_microservice.rb +11 -5
  29. data/lib/openc3/microservices/microservice.rb +10 -9
  30. data/lib/openc3/microservices/periodic_microservice.rb +7 -0
  31. data/lib/openc3/microservices/reaction_microservice.rb +0 -33
  32. data/lib/openc3/microservices/reducer_microservice.rb +14 -10
  33. data/lib/openc3/microservices/text_log_microservice.rb +12 -3
  34. data/lib/openc3/microservices/timeline_microservice.rb +0 -6
  35. data/lib/openc3/microservices/trigger_group_microservice.rb +0 -20
  36. data/lib/openc3/models/cvt_model.rb +103 -47
  37. data/lib/openc3/models/interface_model.rb +23 -0
  38. data/lib/openc3/models/metric_model.rb +53 -6
  39. data/lib/openc3/models/microservice_model.rb +15 -1
  40. data/lib/openc3/models/model.rb +1 -1
  41. data/lib/openc3/models/plugin_model.rb +6 -1
  42. data/lib/openc3/models/secret_model.rb +53 -0
  43. data/lib/openc3/models/target_model.rb +2 -2
  44. data/lib/openc3/models/tool_model.rb +17 -8
  45. data/lib/openc3/operators/microservice_operator.rb +25 -0
  46. data/lib/openc3/operators/operator.rb +5 -1
  47. data/lib/openc3/packets/packet.rb +21 -7
  48. data/lib/openc3/packets/packet_item.rb +3 -2
  49. data/lib/openc3/script/api_shared.rb +18 -2
  50. data/lib/openc3/script/script.rb +8 -0
  51. data/lib/openc3/script/script_runner.rb +1 -2
  52. data/lib/openc3/script/storage.rb +2 -1
  53. data/lib/openc3/script/suite.rb +15 -11
  54. data/lib/openc3/system/system.rb +6 -3
  55. data/lib/openc3/topics/interface_topic.rb +17 -1
  56. data/lib/openc3/topics/router_topic.rb +17 -1
  57. data/lib/openc3/utilities/aws_bucket.rb +20 -3
  58. data/lib/openc3/utilities/bucket.rb +1 -1
  59. data/lib/openc3/utilities/bucket_file_cache.rb +1 -1
  60. data/lib/openc3/utilities/bucket_utilities.rb +1 -1
  61. data/lib/openc3/utilities/local_mode.rb +1 -0
  62. data/lib/openc3/utilities/metric.rb +77 -101
  63. data/lib/openc3/utilities/redis_secrets.rb +46 -0
  64. data/lib/openc3/utilities/s3_autoload.rb +19 -9
  65. data/lib/openc3/utilities/secrets.rb +63 -0
  66. data/lib/openc3/utilities/target_file.rb +3 -1
  67. data/lib/openc3/version.rb +5 -5
  68. data/templates/plugin-template/LICENSE.txt +7 -0
  69. data/templates/plugin-template/README.md +4 -3
  70. data/templates/plugin-template/plugin.gemspec +4 -4
  71. metadata +22 -3
  72. data/data/config/_interfaces.yaml.err +0 -1017
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aff3df27d8a9cde6fb3e45403131ff0a29fbb5abb2e204e398e33d79c2bb7ead
4
- data.tar.gz: ae3041bbd1868d8f3c5627dd5a6ebc381397deae7d27d997e7dfee009683175c
3
+ metadata.gz: 6c51fd2722cde933052c2bf5941c3a111a14ae995de868bb6371faf9f32f708e
4
+ data.tar.gz: 0a1684b608df0335f485e59b29e55e66a1307cb62c7ab76586989a4566096946
5
5
  SHA512:
6
- metadata.gz: 967885d19c2ccf945765d355346ffde2aca982e65993630f4a4c4fe36a7f04c425176f50b9a8e4c639a21a5cc673f87928513047c84fccc3d12a8d59762fe44e
7
- data.tar.gz: 2d11de60af3e15328db350cd278dc4ec79a848bb8bfbcb5f6f1a819f052f93f37397f2f23e1a1ebc1868b002f9568262599e05aa9c33f960f8fef31fe25e221b
6
+ metadata.gz: c36db608db41b6f0c1edc8ae6b83293d71eb37984e115d86a9ca9ff1e6aa4f124c3e0d645b1ac01b329d3fd490ef6a3b281ddc2754344bbdc1c78a702258522c
7
+ data.tar.gz: 754bc2ce9f0fd0066e47731bc5b50279ac5ce166f20752bb5be42d2ce4ab09698212ee82abcfd1ab353aa1e85029f47e5b766b4bfdba60823682c23148754837
data/bin/openc3cli CHANGED
@@ -322,14 +322,14 @@ ensure
322
322
  exit(result)
323
323
  end
324
324
 
325
- def update_plugin(plugin_file_path, plugin_name, variables: nil, plugin_txt_lines: nil, scope:, existing_plugin_name:)
325
+ def update_plugin(plugin_file_path, plugin_name, variables: nil, plugin_txt_lines: nil, scope:, existing_plugin_name:, force: false)
326
326
  new_gem = File.basename(plugin_file_path)
327
327
  old_gem = existing_plugin_name.split("__")[0]
328
328
  puts "Updating existing plugin: #{existing_plugin_name} with #{File.basename(plugin_file_path)}"
329
329
  plugin_model = OpenC3::PluginModel.get_model(name: existing_plugin_name, scope: scope)
330
330
  begin
331
331
  # Only update if something has changed
332
- if (new_gem != old_gem) or (variables and variables != plugin_model.variables) or (plugin_txt_lines and plugin_txt_lines != plugin_model.plugin_txt_lines)
332
+ if force or (new_gem != old_gem) or (variables and variables != plugin_model.variables) or (plugin_txt_lines and plugin_txt_lines != plugin_model.plugin_txt_lines)
333
333
  puts "Gem version change detected - New: #{new_gem}, Old: #{old_gem}" if new_gem != old_gem
334
334
  if variables and variables != plugin_model.variables
335
335
  pp_variables = ""
@@ -360,7 +360,7 @@ end
360
360
  # This code is used from the command line and is the same code that gets called if you
361
361
  # edit/upgrade or install a new plugin from the Admin interface
362
362
  #
363
- # Usage: cli load gemfile_path [scope] [plugin_hash_file_path]
363
+ # Usage: cli load gemfile_path [scope] [plugin_hash_file_path] [force]
364
364
  #
365
365
  # With just gemfile_path and/or scope: Will do nothing if any plugin
366
366
  # with the same gem file already exists
@@ -370,7 +370,10 @@ end
370
370
  # Otherwise, it will be assumed that the plugin is intentionally being installed for a second
371
371
  # time
372
372
  #
373
- def load_plugin(plugin_file_path, scope:, plugin_hash_file: nil)
373
+ # Pass true as the last argument to force install even if a plugin with
374
+ # the same version number exists
375
+ #
376
+ def load_plugin(plugin_file_path, scope:, plugin_hash_file: nil, force: false)
374
377
  scope ||= 'DEFAULT'
375
378
  # Only create the scope if it doesn't already exist
376
379
  unless OpenC3::ScopeModel.names.include?(scope)
@@ -403,7 +406,7 @@ def load_plugin(plugin_file_path, scope:, plugin_hash_file: nil)
403
406
  found = true
404
407
  # Upgrade if version changed else do nothing
405
408
  if file_full_name != full_name
406
- update_plugin(plugin_file_path, plugin_name, scope: scope, existing_plugin_name: plugin_name)
409
+ update_plugin(plugin_file_path, plugin_name, scope: scope, existing_plugin_name: plugin_name, force: force)
407
410
  else
408
411
  puts "No version change detected for: #{plugin_name}"
409
412
  end
@@ -430,15 +433,16 @@ def load_plugin(plugin_file_path, scope:, plugin_hash_file: nil)
430
433
 
431
434
  if existing_plugin_hash
432
435
  # Upgrade or Edit
433
- update_plugin(plugin_file_path, plugin_hash['name'], variables: plugin_hash['variables'], plugin_txt_lines: plugin_hash['plugin_txt_lines'], scope: scope, existing_plugin_name: existing_plugin_hash['name'])
436
+ update_plugin(plugin_file_path, plugin_hash['name'], variables: plugin_hash['variables'], scope: scope,
437
+ plugin_txt_lines: plugin_hash['plugin_txt_lines'], existing_plugin_name: existing_plugin_hash['name'], force: force)
434
438
  else
435
439
  # New Install
436
440
  puts "Loading new plugin: #{plugin_file_path}\n#{plugin_hash}"
437
441
  plugin_hash = OpenC3::PluginModel.install_phase2(plugin_hash, scope: scope)
438
442
  OpenC3::LocalMode.update_local_plugin(plugin_file_path, plugin_hash, scope: scope)
439
443
  end
440
- rescue => err
441
- abort("Error installing plugin: #{scope}: #{plugin_file_path}: #{err.formatted}")
444
+ rescue => error
445
+ abort("Error installing plugin: #{scope}: #{plugin_file_path}\n#{error.message}")
442
446
  end
443
447
  end
444
448
 
@@ -517,129 +521,128 @@ def run_migrations(folder)
517
521
  end
518
522
  end
519
523
 
520
- if __FILE__ == $0
521
- if not ARGV[0].nil? # argument(s) given
524
+ if not ARGV[0].nil? # argument(s) given
522
525
 
523
- # Handle each task
524
- case ARGV[0].downcase
526
+ # Handle each task
527
+ case ARGV[0].downcase
525
528
 
526
- when 'rake'
527
- puts `rake #{ARGV[1..-1].join(' ')}`
529
+ when 'rake'
530
+ puts `rake #{ARGV[1..-1].join(' ')}`
528
531
 
529
- when 'validate'
530
- validate_plugin(ARGV[1], scope: ARGV[2], variables_file: ARGV[3])
532
+ when 'validate'
533
+ validate_plugin(ARGV[1], scope: ARGV[2], variables_file: ARGV[3])
531
534
 
532
- when 'load'
533
- load_plugin(ARGV[1], scope: ARGV[2], plugin_hash_file: ARGV[3])
535
+ when 'load'
536
+ # force is a boolean so if they pass 'force' it is true
537
+ # See plugins_controller.rb install for usage
538
+ load_plugin(ARGV[1], scope: ARGV[2], plugin_hash_file: ARGV[3], force: ARGV[4] == 'force')
534
539
 
535
- when 'unload'
536
- unload_plugin(ARGV[1], scope: ARGV[2])
540
+ when 'unload'
541
+ unload_plugin(ARGV[1], scope: ARGV[2])
537
542
 
538
- when 'geminstall'
539
- gem_install(ARGV[1], scope: ARGV[2])
543
+ when 'geminstall'
544
+ gem_install(ARGV[1], scope: ARGV[2])
540
545
 
541
- when 'generate'
542
- generate(ARGV[1..-1])
546
+ when 'generate'
547
+ generate(ARGV[1..-1])
543
548
 
544
- when 'migrate'
545
- migrate(ARGV[1..-1])
549
+ when 'migrate'
550
+ migrate(ARGV[1..-1])
546
551
 
547
- when 'rubysloc'
548
- puts `ruby /openc3/bin/rubysloc #{ARGV[1..-1].join(' ')}`
552
+ when 'rubysloc'
553
+ puts `ruby /openc3/bin/rubysloc #{ARGV[1..-1].join(' ')}`
549
554
 
550
- when 'cstol_converter'
551
- puts `ruby /openc3/bin/cstol_converter #{ARGV[1..-1].join(' ')}`
555
+ when 'cstol_converter'
556
+ puts `ruby /openc3/bin/cstol_converter #{ARGV[1..-1].join(' ')}`
552
557
 
553
- when 'xtce_converter'
554
- xtce_converter(ARGV[1..-1])
558
+ when 'xtce_converter'
559
+ xtce_converter(ARGV[1..-1])
555
560
 
556
- when 'bridge'
557
- ENV['OPENC3_NO_STORE'] = '1'
558
- filename = ARGV[1]
559
- filename = 'bridge.txt' unless filename
560
- bridge = OpenC3::Bridge.new(filename)
561
- begin
562
- while true
563
- sleep(1)
564
- end
565
- rescue Interrupt
566
- exit(0)
561
+ when 'bridge'
562
+ ENV['OPENC3_NO_STORE'] = '1'
563
+ filename = ARGV[1]
564
+ filename = 'bridge.txt' unless filename
565
+ bridge = OpenC3::Bridge.new(filename)
566
+ begin
567
+ while true
568
+ sleep(1)
567
569
  end
570
+ rescue Interrupt
571
+ exit(0)
572
+ end
568
573
 
569
- when 'bridgesetup'
570
- ENV['OPENC3_NO_STORE'] = '1'
571
- filename = ARGV[1]
572
- filename = 'bridge.txt' unless filename
573
- unless File.exist?(filename)
574
- OpenC3::BridgeConfig.generate_default(filename)
575
- end
574
+ when 'bridgesetup'
575
+ ENV['OPENC3_NO_STORE'] = '1'
576
+ filename = ARGV[1]
577
+ filename = 'bridge.txt' unless filename
578
+ unless File.exist?(filename)
579
+ OpenC3::BridgeConfig.generate_default(filename)
580
+ end
576
581
 
577
- when 'help'
578
- print_usage()
579
-
580
- when 'redis'
581
- case (ARGV[1])
582
- when 'keys'
583
- get_redis_keys()
584
- when 'hget'
585
- redis = Redis.new(url: $redis_url, username: ENV['OPENC3_REDIS_USERNAME'], password: ENV['OPENC3_REDIS_PASSWORD'])
586
- puts JSON.parse(redis.hget(ARGV[2], ARGV[3]), :allow_nan => true, :create_additions => true)
587
- else
588
- puts "Unknown redis task: #{ARGV[1]}\n"
589
- puts "Valid redis tasks: keys, hget"
590
- end
582
+ when 'help'
583
+ print_usage()
591
584
 
592
- when 'removebase'
593
- # Used to remove tool base to better support enterprise upgrade
594
- scopes = OpenC3::ScopeModel.all
595
- scopes.each do |scope_name, scope|
596
- plugins = OpenC3::PluginModel.all(scope: scope_name)
597
- plugins.each do |plugin_name, plugin|
598
- if plugin["name"] =~ /tool-base/ and plugin["name"] !~ /enterprise/
599
- unload_plugin(plugin_name, scope: scope_name)
600
- end
601
- if plugin["name"] =~ /tool-admin/ and plugin["name"] !~ /enterprise/
602
- unload_plugin(plugin_name, scope: scope_name)
603
- end
585
+ when 'redis'
586
+ case (ARGV[1])
587
+ when 'keys'
588
+ get_redis_keys()
589
+ when 'hget'
590
+ redis = Redis.new(url: $redis_url, username: ENV['OPENC3_REDIS_USERNAME'], password: ENV['OPENC3_REDIS_PASSWORD'])
591
+ puts JSON.parse(redis.hget(ARGV[2], ARGV[3]), :allow_nan => true, :create_additions => true)
592
+ else
593
+ puts "Unknown redis task: #{ARGV[1]}\n"
594
+ puts "Valid redis tasks: keys, hget"
595
+ end
596
+
597
+ when 'removebase'
598
+ # Used to remove tool base to better support enterprise upgrade
599
+ scopes = OpenC3::ScopeModel.all
600
+ scopes.each do |scope_name, scope|
601
+ plugins = OpenC3::PluginModel.all(scope: scope_name)
602
+ plugins.each do |plugin_name, plugin|
603
+ if plugin["name"] =~ /tool-base/ and plugin["name"] !~ /enterprise/
604
+ unload_plugin(plugin_name, scope: scope_name)
605
+ end
606
+ if plugin["name"] =~ /tool-admin/ and plugin["name"] !~ /enterprise/
607
+ unload_plugin(plugin_name, scope: scope_name)
604
608
  end
605
609
  end
610
+ end
606
611
 
607
- when 'removeenterprise'
608
- # Used to remove enterprise plugins to better support downgrade
609
- scopes = OpenC3::ScopeModel.all
610
- scopes.each do |scope_name, scope|
611
- plugins = OpenC3::PluginModel.all(scope: scope_name)
612
- plugins.each do |plugin_name, plugin|
613
- if plugin["name"] =~ /enterprise/
614
- unload_plugin(plugin_name, scope: scope_name)
615
- end
612
+ when 'removeenterprise'
613
+ # Used to remove enterprise plugins to better support downgrade
614
+ scopes = OpenC3::ScopeModel.all
615
+ scopes.each do |scope_name, scope|
616
+ plugins = OpenC3::PluginModel.all(scope: scope_name)
617
+ plugins.each do |plugin_name, plugin|
618
+ if plugin["name"] =~ /enterprise/
619
+ unload_plugin(plugin_name, scope: scope_name)
616
620
  end
617
621
  end
622
+ end
618
623
 
619
- when 'destroyscope'
620
- scope = OpenC3::ScopeModel.get_model(name: ARGV[1])
621
- scope.destroy
624
+ when 'destroyscope'
625
+ scope = OpenC3::ScopeModel.get_model(name: ARGV[1])
626
+ scope.destroy
622
627
 
623
- when 'localinit'
624
- OpenC3::LocalMode.local_init()
628
+ when 'localinit'
629
+ OpenC3::LocalMode.local_init()
625
630
 
626
- when 'initbuckets'
627
- client = OpenC3::Bucket.getClient()
628
- client.create(ENV['OPENC3_CONFIG_BUCKET'])
629
- client.create(ENV['OPENC3_LOGS_BUCKET'])
630
- client.create(ENV['OPENC3_TOOLS_BUCKET'])
631
- client.ensure_public(ENV['OPENC3_TOOLS_BUCKET'])
631
+ when 'initbuckets'
632
+ client = OpenC3::Bucket.getClient()
633
+ client.create(ENV['OPENC3_CONFIG_BUCKET'])
634
+ client.create(ENV['OPENC3_LOGS_BUCKET'])
635
+ client.create(ENV['OPENC3_TOOLS_BUCKET'])
636
+ client.ensure_public(ENV['OPENC3_TOOLS_BUCKET'])
632
637
 
633
- when 'runmigrations'
634
- run_migrations(ARGV[1])
638
+ when 'runmigrations'
639
+ run_migrations(ARGV[1])
635
640
 
636
- else # Unknown task
637
- print_usage()
638
- abort("Unknown task: #{ARGV[0]}")
639
- end
640
-
641
- else # No arguments given
641
+ else # Unknown task
642
642
  print_usage()
643
+ abort("Unknown task: #{ARGV[0]}")
643
644
  end
644
645
 
645
- end
646
+ else # No arguments given
647
+ print_usage()
648
+ end
@@ -78,10 +78,6 @@ PROTOCOL:
78
78
  Protocols can be either READ, WRITE, or READ_WRITE. READ protocols act on the data
79
79
  received by the interface while write acts on the data before it is sent out. READ_WRITE applies
80
80
  the protocol to both reading and writing.<br/><br/>
81
- There is only one built in protocol implemented by override_protocol.rb.
82
- This protocol allows for Scripts to use the override_tlm() and normalize_tlm() methods to permanently
83
- change a telemetry value. Note, this differs from set_tlm() as set_tlm() is over-written by new
84
- incoming telemetry.<br/><br/>
85
81
  For information on creating your own custom protocol please see <a href="https://openc3.com/docs/v5/protocols">https://openc3.com/docs/v5/protocols</a>
86
82
  since: 4.0.0
87
83
  parameters:
@@ -116,3 +112,25 @@ OPTION:
116
112
  required: false
117
113
  description: Parameters to pass to the option
118
114
  values: .*
115
+ SECRET:
116
+ summary: Define a secret needed by this interface
117
+ description: Defines a secret for this interface and optionally assigns its value to an option
118
+ parameters:
119
+ - name: Type
120
+ required: true
121
+ description:
122
+ ENV or FILE. ENV will mount the secret into an environment variable.
123
+ FILE mounts the secret into a file.
124
+ values: .*
125
+ - name: Secret Name
126
+ required: true
127
+ description: The name of the secret to retrieve
128
+ values: .*
129
+ - name: Environment Variable of File Path
130
+ required: true
131
+ description: Environment variable name or file path to store secret
132
+ values: .*
133
+ - name: Option Name
134
+ required: false
135
+ description: Interface option to pass the secret value
136
+ values: .*
@@ -5,11 +5,13 @@ STATE:
5
5
  description: Key value pairs allow for user friendly strings. For example,
6
6
  you might define states for ON = 1 and OFF = 0. This allows the word ON to be
7
7
  used rather than the number 1 when sending the telemetry item and allows
8
- for much greater clarity and less chance for user error.
8
+ for much greater clarity and less chance for user error. A catch all value
9
+ of ANY applies to all other values not already defined as state values.
9
10
  example: |
10
11
  APPEND_ITEM ENABLE 32 UINT "Enable setting"
11
12
  STATE FALSE 0
12
13
  STATE TRUE 1
14
+ STATE ERROR ANY # Match all other values to ERROR
13
15
  APPEND_ITEM STRING 1024 STRING "String"
14
16
  STATE "NOOP" "NOOP" GREEN
15
17
  STATE "ARM LASER" "ARM LASER" YELLOW
@@ -21,7 +23,7 @@ STATE:
21
23
  values: .*
22
24
  - name: Value
23
25
  required: true
24
- description: The numerical state value
26
+ description: The numerical state value or ANY to apply the state to all other values
25
27
  values: .*
26
28
  - name: Color
27
29
  required: false
@@ -88,3 +88,21 @@ MICROSERVICE:
88
88
  required: false
89
89
  description: Name of the container
90
90
  values: .+
91
+ SECRET:
92
+ summary: Define a secret needed by this microservice
93
+ description: Defines a secret for this microservice
94
+ parameters:
95
+ - name: Type
96
+ required: true
97
+ description:
98
+ ENV or FILE. ENV will mount the secret into an environment variable.
99
+ FILE mounts the secret into a file.
100
+ values: .*
101
+ - name: Secret Name
102
+ required: true
103
+ description: The name of the secret to retrieve
104
+ values: .*
105
+ - name: Environment Variable of File Path
106
+ required: true
107
+ description: Environment variable name or file path to store secret
108
+ values: .*
@@ -80,8 +80,8 @@ SELECT_TABLE:
80
80
  description: The name of the existin table
81
81
  values: .*
82
82
  DEFAULT:
83
- summary: Specify default values for a SINGLE row in a multi-column table.
84
- If you have multiple rows you need a DEFAULT line for each row.
83
+ summary: Specify default values for a SINGLE row in a multi-column table
84
+ description: If you have multiple rows you need a DEFAULT line for each row.
85
85
  If all your rows are identical consider using ERB as shown in the OpenC3 demo.
86
86
  parameters:
87
87
  - name: Default values
@@ -47,7 +47,7 @@ TOOL:
47
47
  values: .+
48
48
  CATEGORY:
49
49
  summary: Category for the tool
50
- description: Associates the tool with a category. In a future release this will be able to organize tools into submenus in the Navigation menu.
50
+ description: Associates the tool with a category which becomes a submenu in the Navigation menu.
51
51
  parameters:
52
52
  - name: Category Name
53
53
  required: true
@@ -41,6 +41,7 @@ static ID id_method_scan = 0;
41
41
  static ID id_method_strip = 0;
42
42
  static ID id_method_to_s = 0;
43
43
  static ID id_method_upcase = 0;
44
+ static ID id_method_parse_errors = 0;
44
45
 
45
46
  /*
46
47
  * Removes quotes from the given string if present.
@@ -103,6 +104,7 @@ static VALUE parse_loop(VALUE self, VALUE io, VALUE yield_non_keyword_lines, VAL
103
104
  volatile VALUE ivar_keyword = Qnil;
104
105
  volatile VALUE ivar_parameters = rb_ary_new();
105
106
  volatile VALUE ivar_line = rb_str_new2("");
107
+ volatile VALUE errors = rb_ary_new();
106
108
 
107
109
  rb_ivar_set(self, id_ivar_line_number, INT2FIX(0));
108
110
  rb_ivar_set(self, id_ivar_keyword, ivar_keyword);
@@ -205,7 +207,12 @@ static VALUE parse_loop(VALUE self, VALUE io, VALUE yield_non_keyword_lines, VAL
205
207
  rb_ary_clear(array);
206
208
  rb_ary_push(array, ivar_keyword);
207
209
  rb_ary_push(array, ivar_parameters);
208
- rb_yield(array);
210
+ line = rb_protect(rb_yield, array, &result);
211
+ if (result)
212
+ {
213
+ rb_ary_push(errors, rb_errinfo());
214
+ rb_set_errinfo(Qnil);
215
+ }
209
216
  }
210
217
  ivar_line = rb_str_new2("");
211
218
  rb_ivar_set(self, id_ivar_line, ivar_line);
@@ -247,11 +254,18 @@ static VALUE parse_loop(VALUE self, VALUE io, VALUE yield_non_keyword_lines, VAL
247
254
  rb_ary_clear(array);
248
255
  rb_ary_push(array, ivar_keyword);
249
256
  rb_ary_push(array, ivar_parameters);
250
- rb_yield(array);
257
+ line = rb_protect(rb_yield, array, &result);
258
+ if (result)
259
+ {
260
+ rb_ary_push(errors, rb_errinfo());
261
+ rb_set_errinfo(Qnil);
262
+ }
251
263
  ivar_line = rb_str_new2("");
252
264
  rb_ivar_set(self, id_ivar_line, ivar_line);
253
265
  }
254
266
 
267
+ rb_funcall(self, id_method_parse_errors, 1, errors);
268
+
255
269
  if (RTEST(progress_callback))
256
270
  {
257
271
  rb_funcall(progress_callback, id_method_call, 1, rb_float_new(1.0));
@@ -278,6 +292,7 @@ void Init_config_parser(void)
278
292
  id_method_strip = rb_intern("strip");
279
293
  id_method_to_s = rb_intern("to_s");
280
294
  id_method_upcase = rb_intern("upcase");
295
+ id_method_parse_errors = rb_intern("parse_errors");
281
296
 
282
297
  mOpenC3 = rb_define_module("OpenC3");
283
298
 
@@ -26,6 +26,7 @@ require 'openc3/api/cmd_api'
26
26
  require 'openc3/api/config_api'
27
27
  require 'openc3/api/interface_api'
28
28
  require 'openc3/api/limits_api'
29
+ require 'openc3/api/metrics_api'
29
30
  require 'openc3/api/offline_access_api'
30
31
  require 'openc3/api/router_api'
31
32
  require 'openc3/api/settings_api'
@@ -36,6 +36,8 @@ module OpenC3
36
36
  'stop_raw_logging_interface',
37
37
  'get_all_interface_info',
38
38
  'map_target_to_interface',
39
+ 'interface_cmd',
40
+ 'interface_protocol_cmd'
39
41
  ])
40
42
 
41
43
  # Get information about an interface
@@ -139,5 +141,15 @@ module OpenC3
139
141
  end
140
142
  nil
141
143
  end
144
+
145
+ def interface_cmd(interface_name, cmd_name, *cmd_params, scope: $openc3_scope, token: $openc3_token)
146
+ authorize(permission: 'system_set', interface_name: interface_name, scope: scope, token: token)
147
+ InterfaceTopic.interface_cmd(interface_name, cmd_name, *cmd_params, scope: scope)
148
+ end
149
+
150
+ def interface_protocol_cmd(interface_name, cmd_name, *cmd_params, read_write: :READ_WRITE, index: -1, scope: $openc3_scope, token: $openc3_token)
151
+ authorize(permission: 'system_set', interface_name: interface_name, scope: scope, token: token)
152
+ InterfaceTopic.protocol_cmd(interface_name, cmd_name, *cmd_params, read_write: read_write, index: index, scope: scope)
153
+ end
142
154
  end
143
155
  end
@@ -0,0 +1,97 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2023 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
+ require 'openc3/models/metric_model'
20
+ require 'openc3/utilities/authentication'
21
+ require 'openc3/utilities/store'
22
+
23
+ module OpenC3
24
+ module Api
25
+ WHITELIST ||= []
26
+ WHITELIST.concat([
27
+ 'get_metrics',
28
+ ])
29
+
30
+ DELAY_METRICS = {}
31
+ DELAY_METRICS['decom_topic_delta_seconds'] = 0.0
32
+ DELAY_METRICS['interface_topic_delta_seconds'] = 0.0
33
+ DELAY_METRICS['log_topic_delta_seconds'] = 0.0
34
+ DELAY_METRICS['router_topic_delta_seconds'] = 0.0
35
+ DELAY_METRICS['text_log_topic_delta_seconds'] = 0.0
36
+
37
+ DURATION_METRICS = {}
38
+ DURATION_METRICS['decom_duration_seconds'] = 0.0
39
+ DURATION_METRICS['reducer_minute_processing_seconds'] = 0
40
+ DURATION_METRICS['reducer_hour_processing_seconds'] = 0
41
+ DURATION_METRICS['reducer_day_processing_seconds'] = 0
42
+
43
+ SUM_METRICS = {}
44
+ SUM_METRICS['cleanup_total'] = 0
45
+ SUM_METRICS['cleanup_delete_total'] = 0
46
+ SUM_METRICS['decom_total'] = 0
47
+ SUM_METRICS['decom_error_total'] = 0
48
+ SUM_METRICS['interface_cmd_total'] = 0
49
+ SUM_METRICS['interface_tlm_total'] = 0
50
+ SUM_METRICS['interface_directive_total'] = 0
51
+ SUM_METRICS['log_total'] = 0
52
+ SUM_METRICS['log_error_total'] = 0
53
+ SUM_METRICS['periodic_total'] = 0
54
+ SUM_METRICS['reducer_total'] = 0
55
+ SUM_METRICS['reducer_error_total'] = 0
56
+ SUM_METRICS['router_cmd_total'] = 0
57
+ SUM_METRICS['router_tlm_total'] = 0
58
+ SUM_METRICS['router_directive_total'] = 0
59
+ SUM_METRICS['text_log_total'] = 0
60
+ SUM_METRICS['text_log_error_total'] = 0
61
+
62
+ def get_metrics(scope: $openc3_scope, token: $openc3_token)
63
+ authorize(permission: 'system', scope: scope, token: token)
64
+
65
+ sum_metrics = SUM_METRICS.dup
66
+ duration_metrics = DURATION_METRICS.dup
67
+ delay_metrics = DELAY_METRICS.dup
68
+
69
+ metrics = MetricModel.all(scope: scope)
70
+ metrics.each do |microservice_name, metrics|
71
+ next unless metrics and metrics['values']
72
+ metrics['values'].each do |metric_name, data|
73
+ value = data['value']
74
+ if sum_metrics[metric_name]
75
+ sum_metrics[metric_name] += value
76
+ elsif duration_metrics[metric_name]
77
+ previous = duration_metrics[metric_name]
78
+ duration_metrics[metric_name] = value if value > previous
79
+ elsif delay_metrics.include?(metric_name)
80
+ previous = delay_metrics[metric_name]
81
+ delay_metrics[metric_name] = value if value > previous
82
+ else
83
+ # Ignore other metrics for now
84
+ end
85
+ end
86
+ end
87
+
88
+ result = delay_metrics
89
+ result.merge!(duration_metrics)
90
+ result.merge!(sum_metrics)
91
+
92
+ result.merge!(MetricModel.redis_metrics)
93
+
94
+ return result
95
+ end
96
+ end
97
+ end
@@ -35,6 +35,8 @@ module OpenC3
35
35
  'start_raw_logging_router',
36
36
  'stop_raw_logging_router',
37
37
  'get_all_router_info',
38
+ 'router_cmd',
39
+ 'router_protocol_cmd'
38
40
  ])
39
41
 
40
42
  # Get information about a router
@@ -74,7 +76,7 @@ module OpenC3
74
76
 
75
77
  # Starts raw logging for a router
76
78
  #
77
- # @param router_name [String] The name of the interface
79
+ # @param router_name [String] The name of the router
78
80
  def start_raw_logging_router(router_name = 'ALL', scope: $openc3_scope, token: $openc3_token)
79
81
  authorize(permission: 'system_set', router_name: router_name, scope: scope, token: token)
80
82
  if router_name == 'ALL'
@@ -88,7 +90,7 @@ module OpenC3
88
90
 
89
91
  # Stop raw logging for a router
90
92
  #
91
- # @param router_name [String] The name of the interface
93
+ # @param router_name [String] The name of the router
92
94
  def stop_raw_logging_router(router_name = 'ALL', scope: $openc3_scope, token: $openc3_token)
93
95
  authorize(permission: 'system_set', router_name: router_name, scope: scope, token: token)
94
96
  if router_name == 'ALL'
@@ -116,5 +118,15 @@ module OpenC3
116
118
  info.sort! { |a, b| a[0] <=> b[0] }
117
119
  info
118
120
  end
121
+
122
+ def router_cmd(router_name, cmd_name, *cmd_params, scope: $openc3_scope, token: $openc3_token)
123
+ authorize(permission: 'system_set', router_name: router_name, scope: scope, token: token)
124
+ RouterTopic.router_cmd(router_name, cmd_name, *cmd_params, scope: scope)
125
+ end
126
+
127
+ def router_protocol_cmd(router_name, cmd_name, *cmd_params, read_write: :READ_WRITE, index: -1, scope: $openc3_scope, token: $openc3_token)
128
+ authorize(permission: 'system_set', router_name: router_name, scope: scope, token: token)
129
+ RouterTopic.protocol_cmd(router_name, cmd_name, *cmd_params, read_write: read_write, index: index, scope: scope)
130
+ end
119
131
  end
120
132
  end