Class IB::IB
In: ib.rb
Parent: Object

Methods

close   dispatch   new   open   reader   server_version   subscribe   to_s  

Constants

Tws_client_version = 27

Public Class methods

[Source]

    # File ib.rb, line 65
65:     def initialize(options_in = {})
66:       @options = {
67:         :ip => "127.0.0.1",
68:         :port => "7496",
69:       }.merge(options_in)
70: 
71:       @connected = false
72:       @server = Hash.new # information about server and server connection state
73: 
74:       # Message listeners.
75:       # Key is the message class to listen for.
76:       # Value is an Array of Procs. The proc will be called with the populated message instance as its argument when
77:       # a message of that type is received.
78:       @listeners = Hash.new { |hash, key|
79:         hash[key] = Array.new
80:       }
81: 
82: 
83:       IBLogger.debug("IB#init: Initializing...")
84: 
85:       self.open(@options)
86: 
87:     end

Public Instance methods

[Source]

     # File ib.rb, line 140
140:     def close
141:       @server[:reader_thread].kill # Thread uses blocking I/O, so join is useless.
142:       @server[:socket].close()
143:       @server = Hash.new
144:       @@server_version = nil
145:       @connected = false
146:       IBLogger.debug("Disconnected.")
147:     end

Send an outgoing message.

[Source]

     # File ib.rb, line 167
167:     def dispatch(message)
168:       raise Exception.new("dispatch() must be given an OutgoingMessages::AbstractMessage subclass") unless message.is_a? OutgoingMessage::AbstractMessage
169:       message.send(@server)
170:     end

[Source]

     # File ib.rb, line 94
 94:     def open(options_in = {})
 95:       raise Exception.new("Already connected!") if @connected
 96: 
 97:       opts = {
 98:         :ip => "127.0.0.1",
 99:         :port => "7496"      
100:       }.merge(options_in)
101: 
102:       @server[:socket] = IBSocket.open(@options[:ip], @options[:port])
103:       IBLogger.debug("* open(): Socket connected to #{@options[:ip]}:#{@options[:port]}.")
104: 
105:       # Sekrit handshake.
106:       IBLogger.debug("\tSending client version #{Tws_client_version}..")
107: 
108:       @server[:socket].send(Tws_client_version)
109:       @server[:version] = @server[:socket].read_int
110:       @@server_version = @server[:version]
111:       @server[:local_connect_time] = Time.now()
112: 
113:       IBLogger.debug("\tGot server version: #{@server[:version]}.")
114: 
115:       # Server version >= 20 sends the server time back.
116:       if @server[:version] >= 20
117:         @server[:remote_connect_time] = @server[:socket].read_string
118:         IBLogger.debug("\tServer connect time: #{@server[:remote_connect_time]}.")
119:       end
120:       
121:       # Server version >= 3 wants an arbitrary client ID at this point. This can be used
122:       # to identify subsequent communications.
123:       if @server[:version] >= 3
124:         @server[:client_id] = SHA1.digest(Time.now.to_s + $$.to_s).unpack("C*").join.to_i % 999999999
125:         @server[:socket].send(@server[:client_id])
126:         IBLogger.debug("\tSent client id # #{@server[:client_id]}.")
127:       end
128: 
129:       IBLogger.debug("Starting reader thread..")
130:       Thread.abort_on_exception = true
131:       @server[:reader_thread] = Thread.new {
132:         self.reader
133:       }
134: 
135:       @connected = true
136:     end

[Source]

    # File ib.rb, line 89
89:     def server_version
90:       @server[:version]
91:     end

Subscribe to incoming message events of type messageClass. code is a Proc that will be called with the message instance as its argument.

[Source]

     # File ib.rb, line 159
159:     def subscribe(messageClass, code)
160:       raise(Exception.new("Invalid argument type (#{messageClass.class}, #{code.class}) - must be (IncomingMessages::AbstractMessage, Proc)")) unless messageClass.is_a?(IncomingMessages::AbstractMessage) && code.is_a?(Proc)
161:       @listeners[messageClass].push(code)
162:     end

[Source]

     # File ib.rb, line 151
151:     def to_s
152:       "IB Connector: #{ @connected ? "connected." : "disconnected."}"
153:     end

Protected Instance methods

[Source]

     # File ib.rb, line 176
176:     def reader
177:       IBLogger.debug("Reader started.")
178: 
179:       while true
180:         msg_id = @server[:socket].read_int # this blocks, so Thread#join is useless.
181:         IBLogger.debug("Reader: got message id #{msg_id}.")
182:         
183:         # create a new instance of the appropriate message type, and have it read the message.
184:         msg = IncomingMessages::Table[msg_id].new(@server[:socket], @server[:version])
185: 
186:         @listeners[msg].each { |listener|
187:           listener.call(msg)
188:         }
189: 
190:         # IBLogger.debug("Reader done with message id #{msg_id}.")
191:         
192: 
193:       end # while
194: 
195:       IBLogger.debug("Reader done.")
196:     end

[Validate]