Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions _openc3
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ _openc3_cli() {
'conversion:generate a conversion (requires TARGET NAME)'
'processor:generate a processor (requires TARGET NAME)'
'limits_response:generate a limits response (requires TARGET NAME)'
'command_validator:generate a command validator (requires TARGET NAME)'
'tool:generate a tool (requires "Tool Name")'
'tool_vue:generate a Vue tool (requires "Tool Name")'
'tool_angular:generate an Angular tool (requires "Tool Name")'
Expand All @@ -124,7 +125,7 @@ _openc3_cli() {
elif (( CURRENT == 3 )); then
# Different generators have different requirements
case $gen_type in
conversion|processor|limits_response)
conversion|processor|limits_response|command_validator)
# These require TARGET as first arg
_message -r 'TARGET (required)'
return 0
Expand All @@ -137,7 +138,7 @@ _openc3_cli() {
esac
elif (( CURRENT == 4 )); then
case $gen_type in
conversion|processor|limits_response)
conversion|processor|limits_response|command_validator)
# After TARGET, need NAME
_message -r 'NAME (required)'
return 0
Expand Down
31 changes: 30 additions & 1 deletion openc3/lib/openc3/utilities/cli_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

module OpenC3
class CliGenerator
GENERATORS = %w(plugin target microservice widget conversion processor limits_response tool tool_vue tool_angular tool_react tool_svelte)
GENERATORS = %w(plugin target microservice widget conversion processor limits_response tool tool_vue tool_angular tool_react tool_svelte command_validator)
TEMPLATES_DIR = "#{File.dirname(__FILE__)}/../../../templates"

# Called by openc3cli with ARGV[1..-1]
Expand Down Expand Up @@ -385,5 +385,34 @@ def self.generate_limits_response(args)
puts " LIMITS_RESPONSE #{response_basename}"
return response_name
end

def self.generate_command_validator(args)
if args.length < 3 or args.length > 4
abort("Usage: cli generate command_validator <TARGET> <NAME> (--ruby or --python)")
end

# Create the local variables
target_name = args[1].upcase
unless File.exist?("targets/#{target_name}")
abort("Target '#{target_name}' does not exist! Command validators must be created for existing targets.")
end
validator_name = "#{args[2].upcase.gsub(/_+|-+/, '_')}_COMMAND_VALIDATOR"
validator_basename = "#{validator_name.downcase}.#{@@language}"
validator_class = validator_basename.filename_to_class_name # NOSONAR
validator_filename = "targets/#{target_name}/lib/#{validator_basename}"
if File.exist?(validator_filename)
abort("Command validator #{validator_filename} already exists!")
end

process_template("#{TEMPLATES_DIR}/command_validator", binding) do |filename|
filename.sub!("command_validator.#{@@language}", validator_filename)
false
end

puts "Command validator #{validator_filename} successfully generated!"
puts "To use the command validator add the following to a command:"
puts " VALIDATOR #{validator_basename}"
return validator_name
end
end
end
48 changes: 48 additions & 0 deletions openc3/templates/command_validator/command_validator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from openc3.packets.command_validator import CommandValidator
# Using the OpenC3 API requires the following imports:
# from openc3.api import wait_check

# Custom command validator class
# See https://docs.openc3.com/docs/configuration/command
class <%= validator_class %>(CommandValidator):
def __init__(self, *args):
super().__init__()
self.args = args

# Called before a command is sent
# @param command [dict] The command dictionary containing all the command details
# @return [list] First element is True/False/None for success/failure/unknown,
# second element is an optional message string
def pre_check(self, command):
# Add your pre-command validation logic here
# Example:
# target_name = command['target_name']
# command_name = command['cmd_name']
# params = command['cmd_params']
# self.count = tlm("TARGET PACKET COUNT")
#
# if some_condition:
# return [False, "Command validation failed: reason"]

# Return True to indicate Success, False to indicate Failure,
# and None to indicate Unknown. The second value is the optional message.
return [True, None]

# Called after a command is sent
# @param command [dict] The command dictionary containing all the command details
# @return [list] First element is True/False/None for success/failure/unknown,
# second element is an optional message string
def post_check(self, command):
# Add your post-command validation logic here
# Example:
# Use the OpenC3 API to check telemetry or wait for responses
# wait_check(f"TARGET PACKET COUNT > {self.count}", 5) # Wait up to 5 seconds
#
# if some_condition:
# return [False, "Post-command validation failed: reason"]
#
# Wait for telemetry

# Return True to indicate Success, False to indicate Failure,
# and None to indicate Unknown. The second value is the optional message.
return [True, None]
53 changes: 53 additions & 0 deletions openc3/templates/command_validator/command_validator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# encoding: ascii-8bit
require 'openc3/packets/command_validator'

module OpenC3
# Custom command validator class
# See https://docs.openc3.com/docs/configuration/command
class <%= validator_class %> < CommandValidator
def initialize(*args)
super()
@args = args
end

# Called before a command is sent
# @param command [Hash] The command hash containing all the command details
# @return [Array<Boolean, String>] First element is true/false/nil for success/failure/unknown,
# second element is an optional message string
def pre_check(command)
# Add your pre-command validation logic here
# Example:
# target_name = command['target_name']
# command_name = command['cmd_name']
# params = command['cmd_params']
# @count = tlm("TARGET PACKET COUNT")
#
# if some_condition
# return [false, "Command validation failed: reason"]
# end

# Return true to indicate Success, false to indicate Failure,
# and nil to indicate Unknown. The second value is the optional message.
return [true, nil]
end

# Called after a command is sent
# @param command [Hash] The command hash containing all the command details
# @return [Array<Boolean, String>] First element is true/false/nil for success/failure/unknown,
# second element is an optional message string
def post_check(command)
# Add your post-command validation logic here
# Example:
# Use the OpenC3 API to check telemetry or wait for responses
# wait_check("TARGET PACKET COUNT > #{@count}", 5) # Wait up to 5 seconds
#
# if some_condition
# return [false, "Post-command validation failed: reason"]
# end

# Return true to indicate Success, false to indicate Failure,
# and nil to indicate Unknown. The second value is the optional message.
return [true, nil]
end
end
end
Loading