public override bool Notify(ref PluginNotification notifyData) { bool result = true; switch (notifyData.Reason) { case Reason.DatabaseLoaded: // if database is loaded if (controller != null) { // disconnect from TWS and reset all data controller.Disconnect(); ((IDisposable)controller).Dispose(); controller = null; } Workspace = notifyData.Workspace; DatabasePath = notifyData.DatabasePath; MainWindowHandle = notifyData.MainWnd; AllowMixedEODIntra = Workspace.AllowMixedEODIntra != 0; // start logging the opening of the database LogAndMessage.Log(MessageType.Info, "Database: " + DatabasePath); LogAndMessage.Log(MessageType.Info, "Mixed EOD/Intra: " + (Workspace.AllowMixedEODIntra != 0)); LogAndMessage.Log(MessageType.Info, "Number of bars: " + Workspace.NumBars); LogAndMessage.Log(MessageType.Info, "Database config: " + Settings); // create the config object IBConfiguration = FTConfiguration.GetConfigObject(Settings); LogAndMessage.VerboseLog = IBConfiguration.VerboseLog; RthOnly = IBConfiguration.RthOnly; CalcNextAutoRefreshTime(); // create new controller connectionRetryTime = DateTime.Now.AddSeconds(ConnectionRetryInterval); prevPluginState = IBPluginState.Disconnected; firstConnection = true; controller = new FTController(); // connect database to tws controller.Connect(false); if (rtWindowTickersBck.Count > 0) { for (int i = 0; i < rtWindowTickersBck.Count; i++) { controller.GetRecentInfo(rtWindowTickersBck[i]); } } break; // user changed the db case Reason.DatabaseUnloaded: // disconnect from TWS if (controller != null) { controller.Disconnect(); ((IDisposable)controller).Dispose(); controller = null; } // clean up Workspace = new Workspace(); DatabasePath = null; MainWindowHandle = IntPtr.Zero; searchForm = null; break; // seams to be obsolete case Reason.SettingsChanged: break; // user right clicks data plugin area in AB case Reason.RightMouseClick: if (controller != null) { currentSI = notifyData.CurrentSI; if (currentSI != null) { currentTicker = currentSI.ShortName; if (currentTicker.Length > 10) { currentTickerShortend = currentTicker.Substring(0, 7) + "..."; } else { currentTickerShortend = currentTicker; } } else { currentTicker = null; currentTickerShortend = null; } } SetContextMenuState(); ShowContextMenu(mContextMenu); break; default: result = false; break; } return(result); }
/// <summary> /// Timer event handler /// </summary> /// <param name="sender"></param> /// <remarks> /// If connection is broken, it tries to reconnect in every 30 secs. /// If it reconnects, it starts a backfill of all tickers /// If status is ready and autorefresh is configured, it starts the scheduled refresh /// </remarks> private void timer_Tick(object sender) { if (controller == null) { return; } // check and indicate thread entry if (Interlocked.CompareExchange(ref inTimerTick, 1, 0) != 0) { return; } IBPluginState currPluginState = IBPluginState.Disconnected; try { currPluginState = controller.GetIBPluginState(); if (currPluginState != prevPluginState) { LogAndMessage.Log(MessageType.Info, "Plugin status: " + currPluginState); } // if no connection between the data plugin and the TWS client if (currPluginState == IBPluginState.Disconnected) { // if not manually disconnected, try to reconnect if (manuallyDisconnected == false) { // if retry period has elapsed if (connectionRetryTime < DateTime.Now) { // if connection has just got broken (prevent repeated log entries) if (prevPluginState != IBPluginState.Disconnected) { LogAndMessage.LogAndQueue(MessageType.Warning, "Data plugin has been disconnected from TWS. Trying to reconnect in every " + ConnectionRetryInterval + " sec."); } // set new retry time and increase interval up to 30 secs connectionRetryTime = DateTime.Now.AddSeconds(ConnectionRetryInterval); // try to reconnect controller.Connect(true); } } } // data plugin is connected to TWS else { // reset connection retrying connectionRetryTime = DateTime.MinValue; // if an existing connection was disconnected if (prevPluginState == IBPluginState.Disconnected && !firstConnection || controller.RestartStreaming) { LogAndMessage.LogAndQueue(MessageType.Warning, "TWS has been reconnected. Starting database refresh."); // request refresh of all tickers, restart subscriptions, etc. controller.RestartAfterReconnect(lastUptodateTime); return; } // clear flag of first connection firstConnection = false; // check if it's time to run AutoRefresh if (prevPluginState == IBPluginState.Ready) // Plugin works with up to date data { lastUptodateTime = DateTime.Now; if (IBConfiguration != null && IBConfiguration.AutoRefreshEnabled && // Auto refresh is enabled nextAutoRefreshTime < DateTime.Now) // The time of auto refresh has passed { DateTime refreshStartDate = DateTime.Now.Date.AddDays(-IBConfiguration.AutoRefreshDays); LogAndMessage.LogAndQueue(MessageType.Warning, "Starting automatic database refresh (" + refreshStartDate.ToShortDateString() + ")."); controller.RefreshAllUsed(refreshStartDate); CalcNextAutoRefreshTime(); } } } } catch (Exception ex) { LogAndMessage.Log(MessageType.Error, "Error in data source timer event handler: " + ex); } finally { // update plugin state prevPluginState = currPluginState; // indicate thread exit Interlocked.Exchange(ref inTimerTick, 0); } }
public override PluginStatus GetStatus() { PluginStatus status = new PluginStatus(); IBPluginState ibPluginState = IBPluginState.Disconnected; if (controller != null) { ibPluginState = controller.GetIBPluginState(); } switch (ibPluginState) { case IBPluginState.Disconnected: status.Status = StatusCode.SevereError; status.Color = System.Drawing.Color.IndianRed; status.ShortMessage = "Off-line"; break; case IBPluginState.Busy: status.Status = StatusCode.OK; status.Color = System.Drawing.Color.Yellow; status.ShortMessage = "Busy"; break; case IBPluginState.Ready: status.Status = StatusCode.OK; status.Color = System.Drawing.Color.ForestGreen; status.ShortMessage = "Ready"; break; } status.LongMessage = LogAndMessage.GetMessages(); // collect and display data issues string failedTickers = controller.GetFailedTickers(); bool dataError = !string.IsNullOrEmpty(failedTickers); if (dataError && ibPluginState != IBPluginState.Disconnected) // if disconnected, data issues are meaningless... { status.ShortMessage += " !"; status.Status = StatusCode.Warning; if (string.IsNullOrEmpty(status.LongMessage)) { status.LongMessage = "Failed tickers: " + failedTickers; } } // if there is no message, we show the short message (Busy, Ok, etc) if (string.IsNullOrEmpty(status.LongMessage)) { status.LongMessage = status.ShortMessage; // save as last shown message to avoid status popup lastLongMessageText = status.ShortMessage; } // if new message we use a new lastLongMessageTime value to cause status popup if (lastLongMessageText != status.LongMessage) { lastLongMessageText = status.LongMessage; lastLongMessageTime = (int)DateTime.Now.TimeOfDay.TotalMilliseconds; } // set status and "timestamp" status.Status = (StatusCode)((int)status.Status + lastLongMessageTime); return(status); }