Class: OpenC3::CommandTopic

Inherits:
Topic show all
Defined in:
lib/openc3/topics/command_topic.rb

Constant Summary collapse

COMMAND_ACK_TIMEOUT_S =

TODO: This is in several places, should maybe be a parameter in settings?

30

Class Method Summary collapse

Methods inherited from Topic

clear_topics, get_cnt, method_missing

Class Method Details

.raise_critical_cmd_error(msg_hash, command) ⇒ Object



98
99
100
101
102
103
104
105
106
# File 'lib/openc3/topics/command_topic.rb', line 98

def self.raise_critical_cmd_error(msg_hash, command)
  _, uuid = msg_hash["result"].split("\n")
  # Create and populate a new CriticalCmdError and raise it up
  # The _cmd method in script/commands.rb rescues this and calls prompt_for_critical_cmd
  error = CriticalCmdError.new
  error.uuid = uuid
  error.command = command
  raise error
end

.raise_hazardous_error(msg_hash, command) ⇒ Object

PRIVATE implementation details



83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/openc3/topics/command_topic.rb', line 83

def self.raise_hazardous_error(msg_hash, command)
  _, description, formatted = msg_hash["result"].split("\n")
  # Create and populate a new HazardousError and raise it up
  # The _cmd method in script/commands.rb rescues this and calls prompt_for_hazardous
  error = HazardousError.new
  error.target_name = command["target_name"]
  error.cmd_name = command["cmd_name"]
  error.cmd_params = command["cmd_params"]
  error.hazardous_description = description
  error.formatted = formatted

  # No Logger.info because the error is already logged by the Logger.info "Ack Received ...
  raise error
end

.send_command(command, timeout: COMMAND_ACK_TIMEOUT_S, scope:, obfuscated_items: []) ⇒ Object

Parameters:

  • command (Hash)

    Command hash structure read to be written to a topic

  • timeout (Float) (defaults to: COMMAND_ACK_TIMEOUT_S)

    Timeout in seconds. Set to 0 or negative for fire-and-forget mode (no ACK waiting).



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/openc3/topics/command_topic.rb', line 41

def self.send_command(command, timeout: COMMAND_ACK_TIMEOUT_S, scope:, obfuscated_items: [])
  timeout = COMMAND_ACK_TIMEOUT_S unless timeout
  # Save the existing cmd_params Hash and JSON generate before writing to the topic
  cmd_params = command['cmd_params']
  command['cmd_params'] = JSON.generate(command['cmd_params'].as_json, allow_nan: true)
  OpenC3.inject_context(command)

  # Fire-and-forget mode: skip ACK waiting when timeout <= 0
  if timeout <= 0
    Topic.write_topic("{#{scope}__CMD}TARGET__#{command['target_name']}", command, '*', 100)
    command["cmd_params"] = cmd_params # Restore the original cmd_params Hash
    return command
  end

  ack_topic = "{#{scope}__ACKCMD}TARGET__#{command['target_name']}"
  Topic.update_topic_offsets([ack_topic])
  cmd_id = Topic.write_topic("{#{scope}__CMD}TARGET__#{command['target_name']}", command, '*', 100)
  command["cmd_params"] = cmd_params # Restore the original cmd_params Hash
  time = Time.now
  while (Time.now - time) < timeout
    Topic.read_topics([ack_topic]) do |_topic, _msg_id, msg_hash, _redis|
      if msg_hash["id"] == cmd_id
        if msg_hash["result"] == "SUCCESS"
          return command
        # Check for HazardousError which is a special case
        elsif msg_hash["result"].include?("HazardousError")
          raise_hazardous_error(msg_hash, command)
        elsif msg_hash["result"].include?("CriticalCmdError")
          raise_critical_cmd_error(msg_hash, command)
        else
          raise msg_hash["result"]
        end
      end
    end
  end
  raise "Timeout of #{timeout}s waiting for cmd ack"
end

.write_packet(packet, scope:) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
# File 'lib/openc3/topics/command_topic.rb', line 27

def self.write_packet(packet, scope:)
  topic = "#{scope}__COMMAND__{#{packet.target_name}}__#{packet.packet_name}"
  msg_hash = { time: packet.packet_time.to_nsec_from_epoch,
               received_time: packet.received_time.to_nsec_from_epoch,
               target_name: packet.target_name,
               packet_name: packet.packet_name,
               received_count: packet.received_count,
               stored: packet.stored.to_s,
               buffer: packet.buffer(false) }
  EphemeralStoreQueued.write_topic(topic, msg_hash)
end