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



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

def initialize(config)
  @config = config
end

Instance Attribute Details

#configObject

Returns the value of attribute config.



37
38
39
# File 'lib/openc3/packets/commands.rb', line 37

def config
  @config
end

Instance Method Details

#allObject



294
295
296
# File 'lib/openc3/packets/commands.rb', line 294

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.

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



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

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



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
249
250
251
252
253
# File 'lib/openc3/packets/commands.rb', line 202

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)


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

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)


261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/openc3/packets/commands.rb', line 261

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



298
299
300
# File 'lib/openc3/packets/commands.rb', line 298

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



190
191
192
193
194
195
196
197
198
199
200
# File 'lib/openc3/packets/commands.rb', line 190

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.



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
145
146
147
# File 'lib/openc3/packets/commands.rb', line 100

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



73
74
75
76
77
78
79
# File 'lib/openc3/packets/commands.rb', line 73

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



62
63
64
65
66
67
# File 'lib/openc3/packets/commands.rb', line 62

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



84
85
86
# File 'lib/openc3/packets/commands.rb', line 84

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)



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

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.



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

def warnings
  return @config.warnings
end