openc3 5.5.2 → 5.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/bin/openc3cli +167 -69
  3. data/data/config/_interfaces.yaml +1 -6
  4. data/data/config/interface_modifiers.yaml +55 -4
  5. data/data/config/microservice.yaml +30 -3
  6. data/ext/openc3/ext/crc/crc.c +82 -1
  7. data/lib/openc3/api/cmd_api.rb +19 -7
  8. data/lib/openc3/api/tlm_api.rb +13 -12
  9. data/lib/openc3/bridge/bridge_config.rb +4 -4
  10. data/lib/openc3/config/config_parser.rb +1 -0
  11. data/lib/openc3/conversions/unix_time_conversion.rb +3 -1
  12. data/lib/openc3/ext/.keep +0 -0
  13. data/lib/openc3/interfaces/interface.rb +54 -26
  14. data/lib/openc3/interfaces/serial_interface.rb +4 -5
  15. data/lib/openc3/interfaces/simulated_target_interface.rb +4 -4
  16. data/lib/openc3/interfaces/stream_interface.rb +2 -2
  17. data/lib/openc3/interfaces/tcpip_client_interface.rb +4 -3
  18. data/lib/openc3/interfaces/tcpip_server_interface.rb +18 -19
  19. data/lib/openc3/interfaces/udp_interface.rb +10 -4
  20. data/lib/openc3/io/json_api.rb +72 -0
  21. data/lib/openc3/io/serial_driver.rb +4 -5
  22. data/lib/openc3/logs/buffered_packet_log_writer.rb +2 -4
  23. data/lib/openc3/logs/log_writer.rb +9 -8
  24. data/lib/openc3/logs/packet_log_reader.rb +8 -1
  25. data/lib/openc3/logs/packet_log_writer.rb +3 -4
  26. data/lib/openc3/logs/stream_log.rb +116 -0
  27. data/lib/openc3/logs/stream_log_pair.rb +70 -0
  28. data/lib/openc3/microservices/cleanup_microservice.rb +1 -1
  29. data/lib/openc3/microservices/decom_microservice.rb +17 -2
  30. data/lib/openc3/microservices/interface_decom_common.rb +42 -0
  31. data/lib/openc3/microservices/interface_microservice.rb +24 -17
  32. data/lib/openc3/microservices/router_microservice.rb +46 -4
  33. data/lib/openc3/migrations/20221202214600_add_target_names.rb +1 -1
  34. data/lib/openc3/migrations/20230319154100_log_stream.rb +40 -0
  35. data/lib/openc3/migrations/20230413101100_remove_log.rb +30 -0
  36. data/lib/openc3/models/gem_model.rb +2 -2
  37. data/lib/openc3/models/interface_model.rb +13 -14
  38. data/lib/openc3/models/metadata_model.rb +1 -1
  39. data/lib/openc3/models/note_model.rb +1 -1
  40. data/lib/openc3/models/plugin_model.rb +3 -2
  41. data/lib/openc3/operators/operator.rb +2 -0
  42. data/lib/openc3/packets/commands.rb +2 -0
  43. data/lib/openc3/packets/packet_config.rb +3 -2
  44. data/lib/openc3/packets/parsers/xtce_converter.rb +2 -1
  45. data/lib/openc3/script/gems.rb +125 -0
  46. data/lib/openc3/script/plugins.rb +186 -0
  47. data/lib/openc3/script/screen.rb +119 -0
  48. data/lib/openc3/script/script.rb +3 -0
  49. data/lib/openc3/script/script_runner.rb +19 -8
  50. data/lib/openc3/script/suite_results.rb +2 -2
  51. data/lib/openc3/script/web_socket_api.rb +5 -1
  52. data/lib/openc3/streams/serial_stream.rb +14 -11
  53. data/lib/openc3/streams/tcpip_client_stream.rb +5 -2
  54. data/lib/openc3/streams/tcpip_socket_stream.rb +37 -71
  55. data/lib/openc3/streams/web_socket_client_stream.rb +5 -3
  56. data/lib/openc3/system/system.rb +2 -0
  57. data/lib/openc3/topics/interface_topic.rb +13 -4
  58. data/lib/openc3/topics/router_topic.rb +6 -6
  59. data/lib/openc3/topics/telemetry_decom_topic.rb +10 -1
  60. data/lib/openc3/utilities/bucket_utilities.rb +12 -5
  61. data/lib/openc3/utilities/cli_generator.rb +56 -4
  62. data/lib/openc3/utilities/crc.rb +42 -7
  63. data/lib/openc3/utilities/process_manager.rb +3 -1
  64. data/lib/openc3/utilities/ruby_lex_utils.rb +265 -504
  65. data/lib/openc3/version.rb +6 -6
  66. data/templates/conversion/conversion.rb +10 -2
  67. data/templates/microservice/microservices/TEMPLATE/microservice.rb +1 -1
  68. data/templates/plugin/Rakefile +8 -1
  69. data/templates/widget/.browserslistrc +16 -0
  70. data/templates/widget/.eslintrc.js +43 -0
  71. data/templates/widget/.nycrc +3 -0
  72. data/templates/widget/.prettierrc.js +5 -0
  73. data/templates/widget/LICENSE.txt +20 -0
  74. data/templates/widget/Rakefile +24 -0
  75. data/templates/widget/babel.config.json +11 -0
  76. data/templates/widget/package.json +35 -0
  77. data/templates/widget/src/Widget.vue +46 -0
  78. data/templates/widget/vue.config.js +25 -0
  79. data/templates/widget/yarn.lock +8938 -0
  80. metadata +23 -4
  81. data/lib/openc3/io/raw_logger.rb +0 -170
  82. data/lib/openc3/io/raw_logger_pair.rb +0 -80
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6ff99b8c3ca332659e787d054c96ed43f617a4e53ba3aea706c4ed799d024f9d
4
- data.tar.gz: 72b7fe317faf9e6902a797de6ebfbd8069b51967c0adb54e9367f13ed74b4f15
3
+ metadata.gz: 9de820bd93122cc0e11533c3d875e3d6babce9247128f9a63fe3ad6e75b6d196
4
+ data.tar.gz: 293cf85c989666a805a3dec9125ba35692548c27910a09aff871f3c4c523fe7b
5
5
  SHA512:
6
- metadata.gz: 73ca222afa29f68ad9c3dcdbe697a90eebb9d656db43e5f69dcc3e0fb7e5bb6f5dd0e774a80c4282a26a623a9d63ee0d8a8b8ad6f743e9bc6cad5cca876bc395
7
- data.tar.gz: a33e0239e3c688968587154945b426a5f3f2f6f73d9ea0270868235b8ccef74c19f4a823ea2d9665c07f15a3441de577da79b46ac8c4fc0877959a0d4552ee02
6
+ metadata.gz: 26a29caa9cd9a211959587b54c76c389dbb70390d573587972a52938c9a3c8ccfcbd702d52f942b37f89133bf76048018ef569a9dcd6ff1990b9030ba62d9208
7
+ data.tar.gz: c8dce98075822016cfe3c10624b2e54f174d32b87fda748eb04d43031a89535538d8746f1da0945201f9a8b614499c961bcf3bc61fd03973999dfccae122ceb3
data/bin/openc3cli CHANGED
@@ -79,6 +79,28 @@ def print_usage
79
79
  puts ""
80
80
  end
81
81
 
82
+ def check_environment
83
+ hostname = ENV['OPENC3_API_HOSTNAME'] || (ENV['OPENC3_DEVEL'] ? '127.0.0.1' : 'openc3-cosmos-cmd-tlm-api')
84
+ begin
85
+ Resolv.getaddress(hostname)
86
+ rescue Resolv::ResolvError
87
+ abort "Unable to resolv api hostname: #{hostname}"
88
+ end
89
+
90
+ if hostname =~ /openc3-cosmos-cmd-tlm-api/
91
+ $openc3_in_cluster = true
92
+ else
93
+ $openc3_in_cluster = false
94
+ end
95
+
96
+ unless $openc3_in_cluster
97
+ # Make sure the user has all the required environment variables set
98
+ abort "OPENC3_API_HOSTNAME environment variable is required" unless ENV['OPENC3_API_HOSTNAME']
99
+ abort "OPENC3_API_PORT environment variable is required" unless ENV['OPENC3_API_PORT']
100
+ abort "OPENC3_API_PASSWORD environment variable is required" unless ENV['OPENC3_API_PASSWORD']
101
+ end
102
+ end
103
+
82
104
  def migrate(args)
83
105
  MIGRATE_PARSER.parse!(args)
84
106
  abort(MIGRATE_PARSER.to_s) if args.length == 0
@@ -101,9 +123,7 @@ def migrate(args)
101
123
  # NOTE: generate does a chdir to be inside the plugin directory
102
124
  ###############################################################
103
125
  plugin = args.shift
104
- target_name = OpenC3::CliGenerator.generate(['plugin', plugin])
105
- # Delete target contents from the plugin framework (but keep directory)
106
- FileUtils.rm_rf Dir.glob("targets/#{target_name}/*")
126
+ OpenC3::CliGenerator.generate(['plugin', plugin])
107
127
 
108
128
  if MIGRATE_OPTIONS.all
109
129
  # Grab all target directories to match the command line input
@@ -301,6 +321,29 @@ def update_plugin(plugin_file_path, plugin_name, variables: nil, plugin_txt_line
301
321
  end
302
322
  end
303
323
 
324
+ def wait_process_complete(process_name)
325
+ STDOUT.flush
326
+ state = 'Running'
327
+ status = nil
328
+ while state == 'Running'
329
+ status = plugin_status(process_name)
330
+ state = status['state']
331
+ sleep(5)
332
+ print '.'
333
+ STDOUT.flush
334
+ end
335
+ puts "\nFinished: #{state}"
336
+ puts "Output:\n"
337
+ puts status['output']
338
+ if state == 'Complete'
339
+ puts "Success!"
340
+ exit 0
341
+ else
342
+ puts "Failed!"
343
+ exit 1
344
+ end
345
+ end
346
+
304
347
  # Loads a plugin into the OpenC3 system
305
348
  # This code is used from the command line and is the same code that gets called if you
306
349
  # edit/upgrade or install a new plugin from the Admin interface
@@ -320,90 +363,142 @@ end
320
363
  #
321
364
  def load_plugin(plugin_file_path, scope:, plugin_hash_file: nil, force: false)
322
365
  scope ||= 'DEFAULT'
323
- # Only create the scope if it doesn't already exist
324
- unless OpenC3::ScopeModel.names.include?(scope)
325
- begin
326
- puts "Creating scope: #{scope}"
327
- scope_model = OpenC3::ScopeModel.new(name: scope, scope: scope)
328
- scope_model.create
329
- scope_model.deploy(".", {})
330
- rescue => err
331
- abort("Error creating scope: #{scope}: #{err.formatted}")
366
+ check_environment()
367
+ if $openc3_in_cluster
368
+ # In Cluster
369
+
370
+ # Only create the scope if it doesn't already exist
371
+ unless OpenC3::ScopeModel.names.include?(scope)
372
+ begin
373
+ puts "Creating scope: #{scope}"
374
+ scope_model = OpenC3::ScopeModel.new(name: scope, scope: scope)
375
+ scope_model.create
376
+ scope_model.deploy(".", {})
377
+ rescue => err
378
+ abort("Error creating scope: #{scope}: #{err.formatted}")
379
+ end
332
380
  end
333
- end
334
381
 
335
- begin
336
- if plugin_hash_file
337
- # Admin Create / Edit / or Upgrade Plugin
338
- OpenC3::PluginModel.install_phase1(plugin_file_path, scope: scope)
339
- plugin_hash = JSON.parse(File.read(plugin_hash_file), :allow_nan => true, :create_additions => true)
340
- else
341
- # Init or Command Line openc3cli load with no plugin_hash_file
342
- file_full_name = File.basename(plugin_file_path, ".gem")
343
- file_gem_name = file_full_name.split('-')[0..-2].join('-')
344
- found = false
345
- plugin_names = OpenC3::PluginModel.names(scope: scope)
346
- plugin_names.each do |plugin_name|
347
- gem_name = plugin_name.split("__")[0]
348
- full_name = File.basename(gem_name, ".gem")
349
- gem_name = full_name.split('-')[0..-2].join('-')
350
- if file_gem_name == gem_name
351
- found = true
352
- # Upgrade if version changed else do nothing
353
- if file_full_name != full_name
354
- update_plugin(plugin_file_path, plugin_name, scope: scope, existing_plugin_name: plugin_name, force: force)
355
- else
356
- puts "No version change detected for: #{plugin_name}"
382
+ begin
383
+ if plugin_hash_file
384
+ # Admin Create / Edit / or Upgrade Plugin
385
+ OpenC3::PluginModel.install_phase1(plugin_file_path, scope: scope)
386
+ plugin_hash = JSON.parse(File.read(plugin_hash_file), :allow_nan => true, :create_additions => true)
387
+ else
388
+ # Init or Command Line openc3cli load with no plugin_hash_file
389
+ file_full_name = File.basename(plugin_file_path, ".gem")
390
+ file_gem_name = file_full_name.split('-')[0..-2].join('-')
391
+ found = false
392
+ plugin_names = OpenC3::PluginModel.names(scope: scope)
393
+ plugin_names.each do |plugin_name|
394
+ gem_name = plugin_name.split("__")[0]
395
+ full_name = File.basename(gem_name, ".gem")
396
+ gem_name = full_name.split('-')[0..-2].join('-')
397
+ if file_gem_name == gem_name
398
+ found = true
399
+ # Upgrade if version changed else do nothing
400
+ if file_full_name != full_name
401
+ update_plugin(plugin_file_path, plugin_name, scope: scope, existing_plugin_name: plugin_name, force: force)
402
+ else
403
+ puts "No version change detected for: #{plugin_name}"
404
+ end
357
405
  end
358
406
  end
407
+ return if found
408
+
409
+ plugin_hash = OpenC3::PluginModel.install_phase1(plugin_file_path, scope: scope)
359
410
  end
360
- return if found
361
411
 
362
- plugin_hash = OpenC3::PluginModel.install_phase1(plugin_file_path, scope: scope)
363
- end
412
+ # Determine if plugin named in plugin_hash exists
413
+ existing_plugin_hash = OpenC3::PluginModel.get(name: plugin_hash['name'], scope: scope)
414
+
415
+ # Existing plugin hash will be present if plugin is being edited or upgraded
416
+ # However, a missing existing could also be that a plugin was updated in local mode directly from across installations
417
+ # changing the plugin name without really meaning to create a new instance of the plugin
418
+ # ie.
419
+ # User on machine 1 checks in a changed plugin_instance.json with a different name - There is still only one plugin desired and committed
420
+ # User on machine 2 starts up with the new configuration, OpenC3::PluginModel.get will return nil because the exact name is different
421
+ # In this case, the plugin should be updated without installing a second instance. analyze_local_mode figures this out.
422
+ unless existing_plugin_hash
423
+ existing_plugin_hash = OpenC3::LocalMode.analyze_local_mode(plugin_name: plugin_hash['name'], scope: scope)
424
+ end
364
425
 
365
- # Determine if plugin named in plugin_hash exists
366
- existing_plugin_hash = OpenC3::PluginModel.get(name: plugin_hash['name'], scope: scope)
367
-
368
- # Existing plugin hash will be present if plugin is being edited or upgraded
369
- # However, a missing existing could also be that a plugin was updated in local mode directly from across installations
370
- # changing the plugin name without really meaning to create a new instance of the plugin
371
- # ie.
372
- # User on machine 1 checks in a changed plugin_instance.json with a different name - There is still only one plugin desired and committed
373
- # User on machine 2 starts up with the new configuration, OpenC3::PluginModel.get will return nil because the exact name is different
374
- # In this case, the plugin should be updated without installing a second instance. analyze_local_mode figures this out.
375
- unless existing_plugin_hash
376
- existing_plugin_hash = OpenC3::LocalMode.analyze_local_mode(plugin_name: plugin_hash['name'], scope: scope)
426
+ if existing_plugin_hash
427
+ # Upgrade or Edit
428
+ update_plugin(plugin_file_path, plugin_hash['name'], variables: plugin_hash['variables'], scope: scope,
429
+ plugin_txt_lines: plugin_hash['plugin_txt_lines'], existing_plugin_name: existing_plugin_hash['name'], force: force)
430
+ else
431
+ # New Install
432
+ puts "Loading new plugin: #{plugin_file_path}\n#{plugin_hash}"
433
+ plugin_hash = OpenC3::PluginModel.install_phase2(plugin_hash, scope: scope)
434
+ OpenC3::LocalMode.update_local_plugin(plugin_file_path, plugin_hash, scope: scope)
435
+ end
436
+ rescue => error
437
+ abort("Error installing plugin: #{scope}: #{plugin_file_path}\n#{error.message}")
377
438
  end
439
+ else
440
+ # Outside Cluster
441
+ require 'openc3/script'
378
442
 
379
- if existing_plugin_hash
380
- # Upgrade or Edit
381
- update_plugin(plugin_file_path, plugin_hash['name'], variables: plugin_hash['variables'], scope: scope,
382
- plugin_txt_lines: plugin_hash['plugin_txt_lines'], existing_plugin_name: existing_plugin_hash['name'], force: force)
443
+ if plugin_hash_file
444
+ plugin_hash = JSON.parse(File.read(plugin_hash_file), :allow_nan => true, :create_additions => true)
383
445
  else
384
- # New Install
385
- puts "Loading new plugin: #{plugin_file_path}\n#{plugin_hash}"
386
- plugin_hash = OpenC3::PluginModel.install_phase2(plugin_hash, scope: scope)
387
- OpenC3::LocalMode.update_local_plugin(plugin_file_path, plugin_hash, scope: scope)
446
+ plugin_hash = plugin_install_phase1(plugin_file_path, scope: scope)
388
447
  end
389
- rescue => error
390
- abort("Error installing plugin: #{scope}: #{plugin_file_path}\n#{error.message}")
448
+
449
+ process_name = plugin_install_phase2(plugin_hash, scope: scope)
450
+
451
+ print "Installing..."
452
+ wait_process_complete(process_name)
391
453
  end
392
454
  end
393
455
 
394
456
  def unload_plugin(plugin_name, scope:)
395
457
  scope ||= 'DEFAULT'
396
- begin
397
- OpenC3::PluginModel.new(name: plugin_name, scope: scope).destroy
398
- OpenC3::LocalMode.remove_local_plugin(plugin_name, scope: scope)
399
- OpenC3::Logger.info("PluginModel destroyed: #{plugin_name}", scope: scope)
400
- rescue => err
401
- abort("Error uninstalling plugin: #{scope}: #{plugin_name}: #{err.formatted}")
458
+ check_environment()
459
+ if $openc3_in_cluster
460
+ begin
461
+ plugin_model = OpenC3::PluginModel.get_model(name: plugin_name, scope: scope)
462
+ plugin_model.destroy
463
+ OpenC3::LocalMode.remove_local_plugin(plugin_name, scope: scope)
464
+ OpenC3::Logger.info("PluginModel destroyed: #{plugin_name}", scope: scope)
465
+ rescue => err
466
+ abort("Error uninstalling plugin: #{scope}: #{plugin_name}: #{err.formatted}")
467
+ end
468
+ else
469
+ # Outside Cluster
470
+ require 'openc3/script'
471
+ process_name = plugin_uninstall(plugin_name, scope: scope)
472
+ print "Uninstalling..."
473
+ wait_process_complete(process_name)
474
+ end
475
+ end
476
+
477
+ def cli_gem_install(gem_filename, scope:)
478
+ scope ||= 'DEFAULT'
479
+ check_environment()
480
+ if $openc3_in_cluster
481
+ OpenC3::GemModel.install(gem_filename, scope: scope)
482
+ else
483
+ # Outside Cluster
484
+ require 'openc3/script'
485
+ process_name = gem_install(gem_filename, scope: scope)
486
+ print "Installing..."
487
+ wait_process_complete(process_name)
402
488
  end
403
489
  end
404
490
 
405
- def gem_install(gem_filename, scope:)
406
- OpenC3::GemModel.install(gem_filename, scope: scope)
491
+ def cli_gem_uninstall(gem_filename, scope:)
492
+ scope ||= 'DEFAULT'
493
+ check_environment()
494
+ if $openc3_in_cluster
495
+ OpenC3::GemModel.destroy(gem_filename)
496
+ else
497
+ # Outside Cluster
498
+ require 'openc3/script'
499
+ gem_uninstall(gem_filename, scope: scope)
500
+ puts "Success!"
501
+ end
407
502
  end
408
503
 
409
504
  def get_redis_keys
@@ -510,7 +605,10 @@ if not ARGV[0].nil? # argument(s) given
510
605
  unload_plugin(ARGV[1], scope: ARGV[2])
511
606
 
512
607
  when 'geminstall'
513
- gem_install(ARGV[1], scope: ARGV[2])
608
+ cli_gem_install(ARGV[1], scope: ARGV[2])
609
+
610
+ when 'gemuninstall'
611
+ cli_gem_uninstall(ARGV[1], scope: ARGV[2])
514
612
 
515
613
  when 'generate'
516
614
  OpenC3::CliGenerator.generate(ARGV[1..-1])
@@ -17,7 +17,6 @@ tcpip_client_interface.rb:
17
17
  - name: Write Timeout
18
18
  required: true
19
19
  description: Number of seconds to wait before aborting the write.
20
- Pass 'nil' to block on write.
21
20
  values: .+
22
21
  - name: Read Timeout
23
22
  required: true
@@ -43,7 +42,6 @@ tcpip_server_interface.rb:
43
42
  - name: Write Timeout
44
43
  required: true
45
44
  description: Number of seconds to wait before aborting the write.
46
- Pass 'nil' to block on write.
47
45
  values: .+
48
46
  - name: Read Timeout
49
47
  required: true
@@ -90,9 +88,7 @@ udp_interface.rb:
90
88
  values: .+
91
89
  - name: Write Timeout
92
90
  required: false
93
- description:
94
- Number of seconds to wait before aborting the write. Default is
95
- 'nil' (block on write).
91
+ description: Number of seconds to wait before aborting the write
96
92
  values: .+
97
93
  - name: Read Timeout
98
94
  required: false
@@ -134,7 +130,6 @@ serial_interface.rb:
134
130
  - name: Write Timeout
135
131
  required: true
136
132
  description: Number of seconds to wait before aborting the write.
137
- Pass 'nil' to block on write.
138
133
  values: .+
139
134
  - name: Read Timeout
140
135
  required: true
@@ -6,6 +6,9 @@ MAP_TARGET:
6
6
  required: true
7
7
  description: Target name to map to this interface
8
8
  values: .+
9
+ example: |
10
+ INTERFACE DATA_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST
11
+ MAP_TARGET DATA
9
12
  MAP_CMD_TARGET:
10
13
  summary: Maps a target name to an interface for commands only
11
14
  since: 5.2.0
@@ -14,6 +17,9 @@ MAP_CMD_TARGET:
14
17
  required: true
15
18
  description: Command target name to map to this interface
16
19
  values: .+
20
+ example: |
21
+ INTERFACE CMD_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST
22
+ MAP_CMD_TARGET DATA # Only DATA commands go on the CMD_INT interface
17
23
  MAP_TLM_TARGET:
18
24
  summary: Maps a target name to an interface for telemetry only
19
25
  since: 5.2.0
@@ -22,6 +28,9 @@ MAP_TLM_TARGET:
22
28
  required: true
23
29
  description: Telemetry target name to map to this interface
24
30
  values: .+
31
+ example: |
32
+ INTERFACE TLM_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST
33
+ MAP_TLM_TARGET DATA # Only DATA telemetry received on TLM_INT interface
25
34
  DONT_CONNECT:
26
35
  summary: Server will not automatically try to connect to the interface at startup
27
36
  DONT_RECONNECT:
@@ -43,14 +52,41 @@ DISABLE_DISCONNECT:
43
52
  Use this keyword to prevent the user from disconnecting from the interface.
44
53
  This is typically used in a 'production' environment where you would not want
45
54
  the user to inadvertantly disconnect from a target.
46
- DONT_LOG:
47
- summary: Disable logging commands and telemetry on this interface
48
55
  LOG_RAW:
56
+ summary: Deprecated, use LOG_STREAM
57
+ LOG_STREAM:
49
58
  summary: Log all data on the interface exactly as it is sent and received
50
59
  description:
51
- LOG_RAW does not add any OpenC3 headers and thus can not be read by OpenC3 tools.
60
+ LOG_STREAM does not add any OpenC3 headers and thus can not be read by OpenC3 tools.
52
61
  It is primarily useful for low level debugging of an interface. You will have to
53
62
  manually parse these logs yourself using a hex editor or other application.
63
+ since: 5.5.2
64
+ parameters:
65
+ - name: Cycle Time
66
+ required: false
67
+ description:
68
+ Amount of time to wait before cycling the log file. Default is 10 min.
69
+ If nil refer to Cycle Hour and Cycle Minute.
70
+ values: .*
71
+ - name: Cycle Size
72
+ required: false
73
+ description: Amount of data to write before cycling the log file. Default is 50MB.
74
+ values: .*
75
+ - name: Cycle Hour
76
+ required: false
77
+ description:
78
+ The time at which to cycle the log. Combined with Cycle Minute to cycle
79
+ the log daily at the specified time. If nil, the log will be cycled hourly at the specified Cycle Minute.
80
+ Only applies if Cycle Time is nil.
81
+ values: .*
82
+ - name: Cycle Minute
83
+ required: false
84
+ description: See Cycle Hour.
85
+ values: .*
86
+ example: |
87
+ INTERFACE EXAMPLE example_interface.rb
88
+ # Override the default log time of 600
89
+ LOG_STREAM 60
54
90
  PROTOCOL:
55
91
  summary: Protocols modify the interface by processing the data
56
92
  description:
@@ -71,6 +107,14 @@ PROTOCOL:
71
107
  - name: Protocol specific parameters
72
108
  required: false
73
109
  description: Additional parameters used by the protocol
110
+ example: |
111
+ INTERFACE DATA_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil nil
112
+ MAP_TARGET DATA
113
+ # Rather than defining the LENGTH protocol on the INTERFACE line we define it here
114
+ PROTOCOL READ LengthProtocol 0 16 0 1 BIG_ENDIAN 4 0xBA5EBA11
115
+ INTERFACE DATA_INT tcpip_client_interface.rb host.docker.internal 8080 8081 10.0 nil BURST
116
+ MAP_TARGET DATA
117
+ PROTOCOL READ IgnorePacketProtocol INST IMAGE # Drop all INST IMAGE packets
74
118
  OPTION:
75
119
  summary: Set a parameter on an interface
76
120
  description:
@@ -90,6 +134,10 @@ OPTION:
90
134
  required: false
91
135
  description: Parameters to pass to the option
92
136
  values: .*
137
+ example: |
138
+ INTERFACE SERIAL_INT serial_interface.rb COM1 COM1 115200 NONE 1 10.0 nil
139
+ OPTION FLOW_CONTROL RTSCTS
140
+ OPTION DATA_BITS 8
93
141
  SECRET:
94
142
  summary: Define a secret needed by this interface
95
143
  description: Defines a secret for this interface and optionally assigns its value to an option
@@ -105,7 +153,7 @@ SECRET:
105
153
  required: true
106
154
  description: The name of the secret to retrieve
107
155
  values: .*
108
- - name: Environment Variable of File Path
156
+ - name: Environment Variable or File Path
109
157
  required: true
110
158
  description: Environment variable name or file path to store secret
111
159
  values: .*
@@ -117,3 +165,6 @@ SECRET:
117
165
  required: false
118
166
  description: Name of the secret store for stores with multipart keys
119
167
  values: .*
168
+ example: |
169
+ SECRET ENV USERNAME ENV_USERNAME USERNAME
170
+ SECRET FILE KEY "/tmp/DATA/cert" KEY
@@ -1,7 +1,6 @@
1
1
  ---
2
2
  MICROSERVICE:
3
3
  summary: Defines a new microservice
4
- example: MICROSERVICE EXAMPLE example-microservice
5
4
  description: Defines a microservice that the plugin adds to the OpenC3 system. Microservices are background software processes that perform persistent processing.
6
5
  parameters:
7
6
  - name: Microservice Folder Name
@@ -12,6 +11,7 @@ MICROSERVICE:
12
11
  description: The specific name of this instance of the microservice in the OpenC3 system
13
12
  required: true
14
13
  values: .+
14
+ example: MICROSERVICE EXAMPLE openc3-example
15
15
  modifiers:
16
16
  ENV:
17
17
  summary: Sets an environment variable in the microservice.
@@ -24,6 +24,9 @@ MICROSERVICE:
24
24
  required: true
25
25
  description: Environment variable value
26
26
  values: .+
27
+ example: |
28
+ MICROSERVICE EXAMPLE openc3-example
29
+ ENV COMPANY OpenC3
27
30
  WORK_DIR:
28
31
  summary: Set the working directory
29
32
  description: Working directory to run the microservice CMD in. Can be a path relative to the microservice folder in the plugin, or an absolute path in the container the microservice runs in.
@@ -32,6 +35,9 @@ MICROSERVICE:
32
35
  required: true
33
36
  description: Working directory to run the microservice CMD in. Can be a path relative to the microservice folder in the plugin, or an absolute path in the container the microservice runs in.
34
37
  values: .+
38
+ example: |
39
+ MICROSERVICE EXAMPLE openc3-example
40
+ WORK_DIR .
35
41
  PORT:
36
42
  summary: Open port for the microservice
37
43
  description: Kubernetes needs a Service to be applied to open a port so this is required for Kubernetes support
@@ -45,6 +51,9 @@ MICROSERVICE:
45
51
  required: false
46
52
  description: Port protocol. Default is TCP.
47
53
  values: .+
54
+ example: |
55
+ MICROSERVICE EXAMPLE openc3-example
56
+ PORT 7272
48
57
  TOPIC:
49
58
  summary: Associate a Redis topic
50
59
  description: Redis topic to associate with this microservice. Standard OpenC3 microservices such as decom_microservice use this information to know what packet streams to subscribe to. The TOPIC keyword can be used as many times as necessary to associate all needed topics.
@@ -53,6 +62,12 @@ MICROSERVICE:
53
62
  required: true
54
63
  description: Redis Topic to associate with the microservice
55
64
  values: .+
65
+ example: |
66
+ MICROSERVICE EXAMPLE openc3-example
67
+ # Manually assigning topics is an advanced topic and requires
68
+ # intimate knowledge of the internal COSMOS data structures.
69
+ TOPIC DEFAULT__openc3_log_messages
70
+ TOPIC DEFAULT__TELEMETRY__EXAMPLE__STATUS
56
71
  TARGET_NAME:
57
72
  summary: Associate a OpenC3 target
58
73
  description: OpenC3 target to associate with the microservice. For standard OpenC3 microservices such as decom_microservice this causes the target configuration to get loaded into the container for the microservice.
@@ -61,6 +76,9 @@ MICROSERVICE:
61
76
  required: true
62
77
  description: OpenC3 target to associate with the microservice
63
78
  values: .+
79
+ example: |
80
+ MICROSERVICE EXAMPLE openc3-example
81
+ TARGET_NAME EXAMPLE
64
82
  CMD:
65
83
  summary: Command line to execute to run the microservice.
66
84
  description: Command line to execute to run the microservice.
@@ -69,6 +87,9 @@ MICROSERVICE:
69
87
  required: true
70
88
  description: One or more arguments to exec to run the microservice.
71
89
  values: .+
90
+ example: |
91
+ MICROSERVICE EXAMPLE openc3-example
92
+ CMD ruby example_target.rb
72
93
  OPTION:
73
94
  summary: Pass an option to the microservice
74
95
  description: Generic key/value(s) options to pass to the microservice. These take the form of KEYWORD/PARAMS like a line in a OpenC3 configuration file. Multiple OPTION keywords can be used to pass multiple options to the microservice.
@@ -82,8 +103,8 @@ MICROSERVICE:
82
103
  description: One or more values to associate with the option
83
104
  values: .+
84
105
  CONTAINER:
85
- summary: Docker Container.
86
- description: Container to execute and run the microservice in.
106
+ summary: Docker Container
107
+ description: Container to execute and run the microservice in. Only used in COSMOS Enterprise Edition.
87
108
  parameters:
88
109
  - name: Args
89
110
  required: false
@@ -112,6 +133,9 @@ MICROSERVICE:
112
133
  required: false
113
134
  description: Name of the secret store for stores with multipart keys
114
135
  values: .*
136
+ example: |
137
+ SECRET ENV USERNAME ENV_USERNAME
138
+ SECRET FILE KEY "/tmp/DATA/cert"
115
139
  ROUTE_PREFIX:
116
140
  summary: Prefix of route
117
141
  description: Prefix of route to the microservice to expose externally with Traefik
@@ -121,3 +145,6 @@ MICROSERVICE:
121
145
  required: true
122
146
  description: Route prefix. Must be unique across all scopes. Something like /myprefix
123
147
  values: .*
148
+ example: |
149
+ MICROSERVICE CFDP CFDP
150
+ ROUTE_PREFIX /cfdp
@@ -18,7 +18,7 @@
18
18
  # All changes Copyright 2022, OpenC3, Inc.
19
19
  # All Rights Reserved
20
20
  #
21
- # This file may also be used under the terms of a commercial license
21
+ # This file may also be used under the terms of a commercial license
22
22
  # if purchased from OpenC3, Inc.
23
23
  */
24
24
 
@@ -27,6 +27,7 @@
27
27
 
28
28
  VALUE mOpenC3;
29
29
  VALUE cCrc;
30
+ VALUE cCrc8;
30
31
  VALUE cCrc16;
31
32
  VALUE cCrc32;
32
33
  VALUE cCrc64;
@@ -98,6 +99,83 @@ static unsigned long long bit_reverse_64(unsigned long long value)
98
99
  ((unsigned long long)BIT_REVERSE_TABLE[(value >> 56) & 0x00000000000000ffULL]);
99
100
  }
100
101
 
102
+ /*
103
+ * Calculate a 8-bit CRC
104
+ */
105
+ static VALUE crc8_calculate(int argc, VALUE *argv, VALUE self)
106
+ {
107
+ volatile VALUE param_data = Qnil;
108
+ volatile VALUE param_seed = Qnil;
109
+ unsigned char *data = NULL;
110
+ unsigned char *table = NULL;
111
+ int i = 0;
112
+ long length = 0;
113
+ unsigned char crc = 0;
114
+
115
+ switch (argc)
116
+ {
117
+ case 1:
118
+ Check_Type(argv[0], T_STRING);
119
+ param_data = argv[0];
120
+ param_seed = rb_ivar_get(self, id_ivar_seed);
121
+ break;
122
+ case 2:
123
+ Check_Type(argv[0], T_STRING);
124
+ param_data = argv[0];
125
+ if (argv[1] == Qnil)
126
+ {
127
+ param_seed = rb_ivar_get(self, id_ivar_seed);
128
+ }
129
+ else
130
+ {
131
+ param_seed = argv[1];
132
+ }
133
+ break;
134
+ default:
135
+ /* Invalid number of arguments given */
136
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc);
137
+ break;
138
+ };
139
+
140
+ crc = NUM2UINT(param_seed);
141
+ data = (unsigned char *)RSTRING_PTR(param_data);
142
+ length = RSTRING_LEN(param_data);
143
+ table = (unsigned char *)RSTRING_PTR(rb_ivar_get(self, id_ivar_table));
144
+
145
+ if (RTEST(rb_ivar_get(self, id_ivar_reflect)))
146
+ {
147
+ for (i = 0; i < length; i++)
148
+ {
149
+ crc = (crc << 8) ^ table[(crc) ^ bit_reverse_8(data[i])];
150
+ }
151
+
152
+ if (RTEST(rb_ivar_get(self, id_ivar_xor)))
153
+ {
154
+ return UINT2NUM(bit_reverse_8(crc ^ 0xFF));
155
+ }
156
+ else
157
+ {
158
+ return UINT2NUM(bit_reverse_8(crc));
159
+ }
160
+ }
161
+ else
162
+ {
163
+ for (i = 0; i < length; i++)
164
+ {
165
+ crc = (crc << 8) ^ table[(crc) ^ data[i]];
166
+ }
167
+
168
+ if (RTEST(rb_ivar_get(self, id_ivar_xor)))
169
+ {
170
+ return UINT2NUM(crc ^ 0xFF);
171
+ }
172
+ else
173
+ {
174
+ return UINT2NUM(crc);
175
+ }
176
+ }
177
+ }
178
+
101
179
  /*
102
180
  * Calculate a 16-bit CRC
103
181
  */
@@ -343,6 +421,9 @@ void Init_crc()
343
421
 
344
422
  cCrc = rb_define_class_under(mOpenC3, "Crc", rb_cObject);
345
423
 
424
+ cCrc8 = rb_define_class_under(mOpenC3, "Crc8", cCrc);
425
+ rb_define_method(cCrc8, "calc", crc8_calculate, -1);
426
+
346
427
  cCrc16 = rb_define_class_under(mOpenC3, "Crc16", cCrc);
347
428
  rb_define_method(cCrc16, "calc", crc16_calculate, -1);
348
429