Class: OpenC3::Commands

Inherits:
Object show all
Includes:
CmdLog
Defined in:
lib/openc3/packets/commands.rb

Overview

Commands uses PacketConfig to parse the command and telemetry configuration files. It contains all the knowledge of which command packets exist in the system and how to access them. This class is the API layer which other classes use to access commands.

This should not be confused with the Api module which implements the JSON API that is used by tools when accessing the Server. The Api module always provides Ruby primitives where the PacketConfig class can return actual Packet or PacketItem objects. While there are some overlapping methods between the two, these are separate interfaces into the system.

Constant Summary collapse

LATEST_PACKET_NAME =
'LATEST'.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from CmdLog

#_build_cmd_output_string

Constructor Details

#initialize(config) ⇒ Commands

Returns a new instance of Commands.

Parameters:

  • config (PacketConfig)

    Packet configuration to use to access the commands



48
49
50
# File 'lib/openc3/packets/commands.rb', line 48

def initialize(config)
  @config = config
end

Instance Attribute Details

#configObject

Returns the value of attribute config.



42
43
44
# File 'lib/openc3/packets/commands.rb', line 42

def config
  @config
end

Instance Method Details

#allObject



259
260
261
# File 'lib/openc3/packets/commands.rb', line 259

def all
  @config.commands
end

#build_cmd(target_name, packet_name, params = {}, range_checking = true, raw = false, check_required_params = true) ⇒ Object

Returns a copy of the specified command packet with the parameters initialized to the given params values.

Note: this method does not increment received_count and it should be incremented externally if needed.

Parameters:

  • params (Hash<param_name=>param_value>) (defaults to: {})

    Parameter items to override in the given command.

  • range_checking (Boolean) (defaults to: true)

    Whether to perform range checking on the passed in parameters.

  • raw (Boolean) (defaults to: false)

    Indicates whether or not to run conversions on command parameters

  • check_required_params (Boolean) (defaults to: true)

    Indicates whether or not to check that the required command parameters are present

  • target_name (String)

    The target name

  • packet_name (String)

    The packet name. Must be a defined packet name and not 'LATEST'.



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/openc3/packets/commands.rb', line 171

def build_cmd(target_name, packet_name, params = {}, range_checking = true, raw = false, check_required_params = true)
  target_upcase = target_name.to_s.upcase
  packet_upcase = packet_name.to_s.upcase

  # Lookup the command and create a light weight copy
  pkt = packet(target_upcase, packet_upcase)
  command = pkt.clone

  # Restore the command's buffer to a zeroed string of defined length
  # This will undo any side effects from earlier commands that may have altered the size
  # of the buffer
  command.buffer = "\x00" * command.defined_length

  # Set time, parameters, and restore defaults
  command.received_time = Time.now.sys
  command.stored = false
  command.extra = nil
  command.given_values = params
  command.restore_defaults(command.buffer(false), params.keys)
  command.raw = raw

  given_item_names = set_parameters(command, params, range_checking)
  check_required_params(command, given_item_names) if check_required_params

  return command
end

#build_cmd_output_string(target_name, cmd_name, cmd_params, raw = false, packet) ⇒ Object



211
212
213
214
215
216
217
218
# File 'lib/openc3/packets/commands.rb', line 211

def build_cmd_output_string(target_name, cmd_name, cmd_params, raw = false, packet)
  method_name = raw ? "cmd_raw" : "cmd"
  target_name = 'UNKNOWN' unless target_name
  cmd_name = 'UNKNOWN' unless cmd_name
  packet_hash = packet ? packet.as_json : {}

  _build_cmd_output_string(method_name, target_name, cmd_name, cmd_params, packet_hash)
end

#cmd_hazardous?(target_name, packet_name, params = {}) ⇒ Boolean

Returns whether the given command is hazardous. Commands are hazardous if they are marked hazardous overall or if any of their hardardous states are set. Thus any given parameter values are first applied to the command and then checked for hazardous states.

Parameters:

  • target_name (String)

    The target name

  • packet_name (String)

    The packet name. Must be a defined packet name and not 'LATEST'.

  • params (Hash<param_name=>param_value>) (defaults to: {})

    Parameter items to override in the given command.

Returns:

  • (Boolean)


253
254
255
256
257
# File 'lib/openc3/packets/commands.rb', line 253

def cmd_hazardous?(target_name, packet_name, params = {})
  # Build a command without range checking, perform conversions, and don't
  # check required parameters since we're not actually using the command.
  cmd_pkt_hazardous?(build_cmd(target_name, packet_name, params, false, false, false))
end

#cmd_pkt_hazardous?(command) ⇒ Boolean

Returns whether the given command is hazardous. Commands are hazardous if they are marked hazardous overall or if any of their hardardous states are set. Thus any given parameter values are first applied to the command and then checked for hazardous states.

Parameters:

  • command (Packet)

    The command to check for hazardous

Returns:

  • (Boolean)


226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/openc3/packets/commands.rb', line 226

def cmd_pkt_hazardous?(command)
  return [true, command.hazardous_description] if command.hazardous

  # Check each item for hazardous states
  item_defs = command.items
  item_defs.each do |item_name, item_def|
    if item_def.hazardous
      state_name = command.read(item_name)
      # Nominally the command.read will return a valid state_name
      # If it doesn't, the if check will fail and we'll fall through to
      # the bottom where we return [false, nil] which means this
      # command is not hazardous.
      return [true, item_def.hazardous[state_name]] if item_def.hazardous[state_name]
    end
  end

  return [false, nil]
end

#dynamic_add_packet(packet, affect_ids: false) ⇒ Object



263
264
265
# File 'lib/openc3/packets/commands.rb', line 263

def dynamic_add_packet(packet, affect_ids: false)
  @config.dynamic_add_packet(packet, :COMMAND, affect_ids: affect_ids)
end

#format(packet, ignored_parameters = []) ⇒ Object

Formatted version of a command



199
200
201
202
203
204
205
206
207
208
209
# File 'lib/openc3/packets/commands.rb', line 199

def format(packet, ignored_parameters = [])
  if packet.raw
    items = packet.read_all(:RAW)
    raw = true
  else
    items = packet.read_all(:FORMATTED)
    raw = false
  end
  items.delete_if { |item_name, _item_value| ignored_parameters.include?(item_name) }
  return build_cmd_output_string(packet.target_name, packet.packet_name, items, raw, packet)
end

#identify(packet_data, target_names = nil) ⇒ Object

Identifies an unknown buffer of data as a defined command and sets the commands’s data to the given buffer. Identifying a command uses the fields marked as ID_PARAMETER to identify if the buffer passed represents the command defined. Incorrectly sized buffers are still processed but an error is logged.

Note: Subsequent requests for the command (using packet) will return an uninitialized copy of the command. Thus you must use the return value of this method.

Note: this method does not increment received_count and it should be incremented externally if needed.



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/openc3/packets/commands.rb', line 108

def identify(packet_data, target_names = nil)
  identified_packet = nil

  target_names = target_names() unless target_names

  target_names.each do |target_name|
    target_name = target_name.to_s.upcase
    target_packets = nil
    begin
      target_packets = packets(target_name)
    rescue RuntimeError
      # No commands for this target
      next
    end

    target = System.targets[target_name]
    if target and target.cmd_unique_id_mode
      # Iterate through the packets and see if any represent the buffer
      target_packets.each do |_packet_name, packet|
        if packet.identify?(packet_data)
          identified_packet = packet
          break
        end
      end
    else
      # Do a hash lookup to quickly identify the packet
      if target_packets.length > 0
        packet = target_packets.first[1]
        key = packet.read_id_values(packet_data)
        hash = @config.cmd_id_value_hash[target_name]
        identified_packet = hash[key]
        identified_packet = hash['CATCHALL'.freeze] unless identified_packet
      end
    end

    if identified_packet
      identified_packet = identified_packet.clone
      identified_packet.received_time = nil
      identified_packet.stored = false
      identified_packet.extra = nil
      identified_packet.buffer = packet_data
      break
    end
  end

  return identified_packet
end

#packet(target_name, packet_name) ⇒ Packet

Returns The command packet for the given target and packet name.

Parameters:

  • target_name (String)

    The target name

  • packet_name (String)

    The packet name. Must be a defined packet name and not 'LATEST'.

Returns:

  • (Packet)

    The command packet for the given target and packet name



78
79
80
81
82
83
84
# File 'lib/openc3/packets/commands.rb', line 78

def packet(target_name, packet_name)
  target_packets = packets(target_name)
  packet = target_packets[packet_name.to_s.upcase]
  raise "Command packet '#{target_name.to_s.upcase} #{packet_name.to_s.upcase}' does not exist" unless packet

  packet
end

#packets(target_name) ⇒ Hash<packet_name=>Packet>

Returns Hash of the command packets for the given target name keyed by the packet name.

Parameters:

  • target_name (String)

    The target name

Returns:

  • (Hash<packet_name=>Packet>)

    Hash of the command packets for the given target name keyed by the packet name



67
68
69
70
71
72
# File 'lib/openc3/packets/commands.rb', line 67

def packets(target_name)
  target_packets = @config.commands[target_name.to_s.upcase]
  raise "Command target '#{target_name.to_s.upcase}' does not exist" unless target_packets

  target_packets
end

#params(target_name, packet_name) ⇒ Array<PacketItem>

Returns The command parameters for the given target and packet name.

Parameters:

  • target_name (String)

    The target name

  • packet_name (String)

    The packet name. Must be a defined packet name and not 'LATEST'.

Returns:

  • (Array<PacketItem>)

    The command parameters for the given target and packet name



89
90
91
# File 'lib/openc3/packets/commands.rb', line 89

def params(target_name, packet_name)
  return packet(target_name, packet_name).sorted_items
end

#target_namesArray<String>

Returns The command target names (excluding UNKNOWN).

Returns:

  • (Array<String>)

    The command target names (excluding UNKNOWN)



58
59
60
61
62
# File 'lib/openc3/packets/commands.rb', line 58

def target_names
  result = @config.commands.keys.sort
  result.delete('UNKNOWN'.freeze)
  return result
end

#warningsArray<String>

Returns Array of strings listing all the warnings that were created while parsing the configuration file.

Returns:

  • (Array<String>)

    Array of strings listing all the warnings that were created while parsing the configuration file.



53
54
55
# File 'lib/openc3/packets/commands.rb', line 53

def warnings
  return @config.warnings
end