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 primatives 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



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

def initialize(config)
  @config = config
end

Instance Attribute Details

#configObject

Returns the value of attribute config.



34
35
36
# File 'lib/openc3/packets/commands.rb', line 34

def config
  @config
end

Instance Method Details

#allObject



321
322
323
# File 'lib/openc3/packets/commands.rb', line 321

def all
  @config.commands
end

#all_packet_strings(include_hidden = false, splash = nil) ⇒ Object

Returns an array with a “TARGET_NAME PACKET_NAME” string for every command in the system (PACKET_NAME == command name)



298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
# File 'lib/openc3/packets/commands.rb', line 298

def all_packet_strings(include_hidden = false, splash = nil)
  strings = []
  tnames = target_names()
  total = tnames.length.to_f
  tnames.each_with_index do |target_name, index|
    if splash
      splash.message = "Processing #{target_name} command"
      splash.progress = index / total
    end

    # TODO: This wasn't being used ... should it be
    # ignored_items = System.targets[target_name].ignored_items

    packets(target_name).each do |command_name, packet|
      # We don't audit against hidden or disabled packets/commands
      next if !include_hidden and (packet.hidden || packet.disabled)

      strings << "#{target_name} #{command_name}"
    end
  end
  strings
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 initialzed to the given params values.

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



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/openc3/packets/commands.rb', line 158

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)
  pkt.received_count += 1
  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



199
200
201
202
203
204
205
206
207
208
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
# File 'lib/openc3/packets/commands.rb', line 199

def build_cmd_output_string(target_name, cmd_name, cmd_params, raw = false)
  if raw
    output_string = 'cmd_raw("'
  else
    output_string = 'cmd("'
  end
  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

#clear_countersObject



289
290
291
292
293
294
295
# File 'lib/openc3/packets/commands.rb', line 289

def clear_counters
  @config.commands.each do |target_name, target_packets|
    target_packets.each do |packet_name, packet|
      packet.received_count = 0
    end
  end
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)


283
284
285
286
287
# File 'lib/openc3/packets/commands.rb', line 283

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)


256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/openc3/packets/commands.rb', line 256

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

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

Formatted version of a command



187
188
189
190
191
192
193
194
195
196
197
# File 'lib/openc3/packets/commands.rb', line 187

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.



97
98
99
100
101
102
103
104
105
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
# File 'lib/openc3/packets/commands.rb', line 97

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.received_count += 1
      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



70
71
72
73
74
75
76
# File 'lib/openc3/packets/commands.rb', line 70

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



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

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



81
82
83
# File 'lib/openc3/packets/commands.rb', line 81

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)



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

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.



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

def warnings
  return @config.warnings
end