Class: OpenC3::Commands

Inherits:
Object show all
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

Constructor Details

#initialize(config) ⇒ Commands

Returns a new instance of Commands.

Parameters:

  • config (PacketConfig)

    Packet configuration to use to access the commands



46
47
48
# File 'lib/openc3/packets/commands.rb', line 46

def initialize(config)
  @config = config
end

Instance Attribute Details

#configObject

Returns the value of attribute config.



40
41
42
# File 'lib/openc3/packets/commands.rb', line 40

def config
  @config
end

Instance Method Details

#allObject



301
302
303
# File 'lib/openc3/packets/commands.rb', line 301

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'.



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

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) ⇒ Object



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/openc3/packets/commands.rb', line 209

def build_cmd_output_string(target_name, cmd_name, cmd_params, raw = false)
  if raw
    output_string = 'cmd_raw("'
  else
    output_string = 'cmd("'
  end
  target_name = 'UNKNOWN' unless target_name
  cmd_name = 'UNKNOWN' unless cmd_name
  output_string << (target_name + ' ' + cmd_name)
  if cmd_params.nil? or cmd_params.empty?
    output_string << '")'
  else
    begin
      command_items = packet(target_name, cmd_name).items
    rescue
    end

    params = []
    cmd_params.each do |key, value|
      next if Packet::RESERVED_ITEM_NAMES.include?(key)

      begin
        item_type = command_items[key].data_type
      rescue
        item_type = nil
      end

      if value.is_a?(String)
        value = value.dup
        if item_type == :BLOCK or item_type == :STRING
          if !value.is_printable?
            value = "0x" + value.simple_formatted
          else
            value = value.inspect
          end
        else
          value = value.convert_to_value.to_s
        end
        if value.length > 256
          value = value[0..255] + "...'"
        end
        value.tr!('"', "'")
      elsif value.is_a?(Array)
        value = "[#{value.join(", ")}]"
      end
      params << "#{key} #{value}"
    end
    params = params.join(", ")
    output_string << (' with ' + params + '")')
  end
  return output_string
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)


295
296
297
298
299
# File 'lib/openc3/packets/commands.rb', line 295

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)


268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/openc3/packets/commands.rb', line 268

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



305
306
307
# File 'lib/openc3/packets/commands.rb', line 305

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



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

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)
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.



106
107
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
# File 'lib/openc3/packets/commands.rb', line 106

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



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

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



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

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



87
88
89
# File 'lib/openc3/packets/commands.rb', line 87

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)



56
57
58
59
60
# File 'lib/openc3/packets/commands.rb', line 56

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.



51
52
53
# File 'lib/openc3/packets/commands.rb', line 51

def warnings
  return @config.warnings
end