Class: OpenC3::InterfaceThread

Inherits:
Object
  • Object
show all
Defined in:
lib/openc3/tools/cmd_tlm_server/interface_thread.rb

Overview

Encapsulates an Interface in a Ruby thread. When the thread is started by the #start method, it loops trying to connect. It then continously reads from the interface while handling the packets it receives.

Direct Known Subclasses

BridgeInterfaceThread, BridgeRouterThread

Constant Summary collapse

UNKNOWN_BYTES_TO_PRINT =

The number of bytes to print when an UNKNOWN packet is received

36

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(interface) ⇒ InterfaceThread

Returns a new instance of InterfaceThread.

Parameters:

  • interface (Interface)

    The interface to create a thread for



48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/openc3/tools/cmd_tlm_server/interface_thread.rb', line 48

def initialize(interface)
  @interface = interface
  @connection_success_callback = nil
  @connection_failed_callback = nil
  @connection_lost_callback = nil
  @identified_packet_callback = nil
  @fatal_exception_callback = nil
  @thread = nil
  @thread_sleeper = Sleeper.new
  @connection_failed_messages = []
  @connection_lost_messages = []
  @mutex = Mutex.new
end

Instance Attribute Details

#connection_failed_callback#call(Exception)

Returns Callback which is called if the OpenC3::Interface#connect method throws an exception.

Returns:



36
37
38
# File 'lib/openc3/tools/cmd_tlm_server/interface_thread.rb', line 36

def connection_failed_callback
  @connection_failed_callback
end

#connection_lost_callback#call(Exception|nil)

Returns Callback which is called if the interface connection is lost.

Returns:

  • (#call(Exception|nil))

    Callback which is called if the interface connection is lost.



39
40
41
# File 'lib/openc3/tools/cmd_tlm_server/interface_thread.rb', line 39

def connection_lost_callback
  @connection_lost_callback
end

#connection_success_callback#call()

Returns Callback which is called if the #OpenC3::Interface#connect method succeeds.

Returns:



33
34
35
# File 'lib/openc3/tools/cmd_tlm_server/interface_thread.rb', line 33

def connection_success_callback
  @connection_success_callback
end

#fatal_exception_callback#call(Exception)

Returns Callback which is called if the InterfaceThread dies for any reason.

Returns:

  • (#call(Exception))

    Callback which is called if the InterfaceThread dies for any reason.



45
46
47
# File 'lib/openc3/tools/cmd_tlm_server/interface_thread.rb', line 45

def fatal_exception_callback
  @fatal_exception_callback
end

#identified_packet_callback#call(Packet)

Returns Callback which is called when a packet has been received from the interface and identified.

Returns:

  • (#call(Packet))

    Callback which is called when a packet has been received from the interface and identified.



42
43
44
# File 'lib/openc3/tools/cmd_tlm_server/interface_thread.rb', line 42

def identified_packet_callback
  @identified_packet_callback
end

Instance Method Details

#graceful_killObject



147
148
149
# File 'lib/openc3/tools/cmd_tlm_server/interface_thread.rb', line 147

def graceful_kill
  # Just to avoid warning
end

#startObject

Create and start the Ruby thread that will encapsulate the interface. Creates a while loop that waits for OpenC3::Interface#connect to succeed. Then calls OpenC3::Interface#read and handles all the incoming packets.



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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
# File 'lib/openc3/tools/cmd_tlm_server/interface_thread.rb', line 65

def start
  @thread_sleeper = Sleeper.new
  @thread = Thread.new do
    @cancel_thread = false
    begin
      if @interface.read_allowed?
        Logger.info "Starting packet reading for #{@interface.name}"
      else
        Logger.info "Starting connection maintenance for #{@interface.name}"
      end
      while true
        break if @cancel_thread

        unless @interface.connected?
          begin
            @mutex.synchronize do
              # We need to make sure connect is not called after stop() has been called
              connect() unless @cancel_thread
            end
            break if @cancel_thread
          rescue Exception => connect_error
            handle_connection_failed(connect_error)
            if @cancel_thread
              break
            else
              next
            end
          end
        end

        if @interface.read_allowed?
          begin
            packet = @interface.read
            unless packet
              Logger.info "Clean disconnect from #{@interface.name} (returned nil)"
              handle_connection_lost(nil)
              if @cancel_thread
                break
              else
                next
              end
            end
            packet.received_time = Time.now.sys unless packet.received_time
          rescue Exception => err
            handle_connection_lost(err)
            if @cancel_thread
              break
            else
              next
            end
          end

          handle_packet(packet)
        else
          @thread_sleeper.sleep(1)
          handle_connection_lost(nil) if !@interface.connected?
        end
      end # loop
    rescue Exception => error
      if @fatal_exception_callback
        @fatal_exception_callback.call(error)
      else
        Logger.error "Packet reading thread unexpectedly died for #{@interface.name}"
        OpenC3.handle_fatal_exception(error)
      end
    end
    Logger.info "Stopped packet reading for #{@interface.name}"
  end # Thread.new
end

#stopObject

Disconnect from the interface and stop the thread



136
137
138
139
140
141
142
143
144
145
# File 'lib/openc3/tools/cmd_tlm_server/interface_thread.rb', line 136

def stop
  @mutex.synchronize do
    # Need to make sure that @cancel_thread is set and the interface disconnected within
    # mutex to ensure that connect() is not called when we want to stop()
    @cancel_thread = true
    @thread_sleeper.cancel
    @interface.disconnect
  end
  OpenC3.kill_thread(self, @thread) if @thread and @thread != Thread.current
end