1.1 --- a/Server/FormMain.cs Wed Sep 28 22:31:27 2016 +0200
1.2 +++ b/Server/FormMain.cs Wed Oct 05 15:02:09 2016 +0200
1.3 @@ -1033,7 +1033,12 @@
1.4
1.5 }
1.6
1.7 - //This is our timer tick responsible to perform our render
1.8 + /// <summary>
1.9 + /// This is our timer tick responsible to perform our render
1.10 + /// TODO: Use a threading timer instead of a Windows form timer.
1.11 + /// </summary>
1.12 + /// <param name="sender"></param>
1.13 + /// <param name="e"></param>
1.14 private void timer_Tick(object sender, EventArgs e)
1.15 {
1.16 //Update our animations
1.17 @@ -1095,7 +1100,7 @@
1.18
1.19 //Compute instant FPS
1.20 toolStripStatusLabelFps.Text = (1.0/NewTickTime.Subtract(LastTickTime).TotalSeconds).ToString("F0") + " / " +
1.21 - (1000/timer.Interval).ToString() + " FPS";
1.22 + (1000/iTimerDisplay.Interval).ToString() + " FPS";
1.23
1.24 LastTickTime = NewTickTime;
1.25
1.26 @@ -1257,7 +1262,7 @@
1.27 maskedTextBoxMinFontSize.Text = cds.MinFontSize.ToString();
1.28 maskedTextBoxScrollingSpeed.Text = cds.ScrollingSpeedInPixelsPerSecond.ToString();
1.29 comboBoxDisplayType.SelectedIndex = cds.DisplayType;
1.30 - timer.Interval = cds.TimerInterval;
1.31 + iTimerDisplay.Interval = cds.TimerInterval;
1.32 maskedTextBoxTimerInterval.Text = cds.TimerInterval.ToString();
1.33 textBoxScrollLoopSeparator.Text = cds.Separator;
1.34 //
1.35 @@ -1563,27 +1568,27 @@
1.36 private void StartTimer()
1.37 {
1.38 LastTickTime = DateTime.Now; //Reset timer to prevent jump
1.39 - timer.Enabled = true;
1.40 + iTimerDisplay.Enabled = true;
1.41 UpdateSuspendButton();
1.42 }
1.43
1.44 private void StopTimer()
1.45 {
1.46 LastTickTime = DateTime.Now; //Reset timer to prevent jump
1.47 - timer.Enabled = false;
1.48 + iTimerDisplay.Enabled = false;
1.49 UpdateSuspendButton();
1.50 }
1.51
1.52 private void ToggleTimer()
1.53 {
1.54 LastTickTime = DateTime.Now; //Reset timer to prevent jump
1.55 - timer.Enabled = !timer.Enabled;
1.56 + iTimerDisplay.Enabled = !iTimerDisplay.Enabled;
1.57 UpdateSuspendButton();
1.58 }
1.59
1.60 private void UpdateSuspendButton()
1.61 {
1.62 - if (!timer.Enabled)
1.63 + if (!iTimerDisplay.Enabled)
1.64 {
1.65 buttonSuspend.Text = "Run";
1.66 }
1.67 @@ -2301,8 +2306,8 @@
1.68
1.69 if (interval > 0)
1.70 {
1.71 - timer.Interval = interval;
1.72 - cds.TimerInterval = timer.Interval;
1.73 + iTimerDisplay.Interval = interval;
1.74 + cds.TimerInterval = iTimerDisplay.Interval;
1.75 Properties.Settings.Default.Save();
1.76 }
1.77 }
1.78 @@ -3062,6 +3067,11 @@
1.79 #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
1.80 }
1.81
1.82 +
1.83 +
1.84 + int iHarmonyReconnectTries = 0;
1.85 + const int KHarmonyMaxReconnectTries = 10;
1.86 +
1.87 /// <summary>
1.88 ///
1.89 /// </summary>
1.90 @@ -3073,9 +3083,12 @@
1.91 await Program.HarmonyClient.CloseAsync();
1.92 }
1.93
1.94 + bool success = false;
1.95 +
1.96 //Reset Harmony client & config
1.97 Program.HarmonyClient = null;
1.98 Program.HarmonyConfig = null;
1.99 + iTreeViewHarmony.Nodes.Clear();
1.100
1.101 Trace.WriteLine("Harmony: Connecting... ");
1.102 //First create our client and login
1.103 @@ -3087,13 +3100,17 @@
1.104 if (!string.IsNullOrEmpty(authToken) && !aForceAuth)
1.105 {
1.106 Trace.WriteLine("Harmony: Reusing token: {0}", authToken);
1.107 - await Program.HarmonyClient.TryOpenAsync(authToken);
1.108 + success = await Program.HarmonyClient.TryOpenAsync(authToken);
1.109 }
1.110
1.111 - if (!Program.HarmonyClient.IsReady)
1.112 + if (!Program.HarmonyClient.IsReady || !success
1.113 + // Only first failure triggers new Harmony server AUTH
1.114 + // That's to avoid calling upon Logitech servers too often
1.115 + && iHarmonyReconnectTries == 0 )
1.116 {
1.117 //We failed to connect using our token
1.118 //Delete it then
1.119 + Trace.WriteLine("Harmony: Reseting authentication token!");
1.120 Properties.Settings.Default.LogitechAuthToken = "";
1.121 Properties.Settings.Default.Save();
1.122
1.123 @@ -3105,18 +3122,65 @@
1.124 }
1.125
1.126 Trace.WriteLine("Harmony: Authenticating with Logitech servers...");
1.127 - await Program.HarmonyClient.TryOpenAsync(iTextBoxLogitechUserName.Text, iTextBoxLogitechPassword.Text);
1.128 + success = await Program.HarmonyClient.TryOpenAsync(iTextBoxLogitechUserName.Text, iTextBoxLogitechPassword.Text);
1.129 //Persist our authentication token in our setting
1.130 - Properties.Settings.Default.LogitechAuthToken = Program.HarmonyClient.Token;
1.131 - Properties.Settings.Default.Save();
1.132 + if (success)
1.133 + {
1.134 + Trace.WriteLine("Harmony: Saving authentication token.");
1.135 + Properties.Settings.Default.LogitechAuthToken = Program.HarmonyClient.Token;
1.136 + Properties.Settings.Default.Save();
1.137 + }
1.138 }
1.139 -
1.140 - //Fetch our config
1.141 - Program.HarmonyConfig = await Program.HarmonyClient.GetConfigAsync();
1.142 - PopulateTreeViewHarmony(Program.HarmonyConfig);
1.143 -
1.144 - //Make sure harmony command actions are showing device name instead of device id
1.145 - PopulateTreeViewEvents(CurrentEarObject());
1.146 +
1.147 + // I've seen this failing with "Policy lookup failed on server".
1.148 + Program.HarmonyConfig = await Program.HarmonyClient.TryGetConfigAsync();
1.149 + if (Program.HarmonyConfig == null)
1.150 + {
1.151 + success = false;
1.152 + }
1.153 + else
1.154 + {
1.155 + // So we now have our Harmony Configuration
1.156 + PopulateTreeViewHarmony(Program.HarmonyConfig);
1.157 + // Make sure harmony command actions are showing device name instead of device id
1.158 + PopulateTreeViewEvents(CurrentEarObject());
1.159 + }
1.160 +
1.161 + // TODO: Consider putting the retry logic one level higher in ResetHarmonyAsync
1.162 + if (!success)
1.163 + {
1.164 + // See if we need to keep trying
1.165 + if (iHarmonyReconnectTries < KHarmonyMaxReconnectTries)
1.166 + {
1.167 + iHarmonyReconnectTries++;
1.168 + Trace.WriteLine("Harmony: Failed to connect, try again: " + iHarmonyReconnectTries);
1.169 + await ConnectHarmonyAsync();
1.170 + }
1.171 + else
1.172 + {
1.173 + Trace.WriteLine("Harmony: Failed to connect, giving up!");
1.174 + iHarmonyReconnectTries = 0;
1.175 + // TODO: Could use a data member as timer rather than a new instance.
1.176 + // Try that again in 5 minutes then.
1.177 + // Using Windows Form timer to make sure we run in the UI thread.
1.178 + System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
1.179 + timer.Tick += async delegate (object sender, EventArgs e)
1.180 + {
1.181 + // Stop our timer first as we won't need it anymore
1.182 + (sender as System.Windows.Forms.Timer).Stop();
1.183 + // Then try to connect again
1.184 + await ConnectHarmonyAsync();
1.185 + };
1.186 + timer.Interval = 300000;
1.187 + timer.Start();
1.188 + }
1.189 + }
1.190 + else
1.191 + {
1.192 + // We are connected with a valid Harmony Configuration
1.193 + // Reset our tries counter then
1.194 + iHarmonyReconnectTries = 0;
1.195 + }
1.196 }
1.197
1.198 /// <summary>