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



43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/openc3/tools/cmd_tlm_server/interface_thread.rb', line 43

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:



31
32
33
# File 'lib/openc3/tools/cmd_tlm_server/interface_thread.rb', line 31

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.



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

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:



28
29
30
# File 'lib/openc3/tools/cmd_tlm_server/interface_thread.rb', line 28

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.



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

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.



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

def identified_packet_callback
  @identified_packet_callback
end

Instance Method Details

#graceful_killObject



142
143
144
# File 'lib/openc3/tools/cmd_tlm_server/interface_thread.rb', line 142

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.



60
61
62
63
64
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
# File 'lib/openc3/tools/cmd_tlm_server/interface_thread.rb', line 60

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 => e
            handle_connection_failed(e)
            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 => e
            handle_connection_lost(e)
            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 => e
      if @fatal_exception_callback
        @fatal_exception_callback.call(e)
      else
        Logger.error "Packet reading thread unexpectedly died for #{@interface.name}"
        OpenC3.handle_fatal_exception(e)
      end
    end
    Logger.info "Stopped packet reading for #{@interface.name}"
  end # Thread.new
end

#stopObject

Disconnect from the interface and stop the thread



131
132
133
134
135
136
137
138
139
140
# File 'lib/openc3/tools/cmd_tlm_server/interface_thread.rb', line 131

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