private async void ProcessStateMachine(object sender, EventArgs e) { stateTimer.Stop(); switch (CurrentStep) { case Steps.WaitForBaudrate: break; case Steps.WaitForConnection: break; case Steps.CheckHardware: { var connectResult = await _mountViewModel.ConnectToOat(SelectedDevice + "@" + SelectedBaudRate); ShowGPSStatus = false; GPSStatus = string.Empty; if (!connectResult.Item1) { ShowGPSStatus = true; GPSStatus = connectResult.Item2; CurrentStep = Steps.WaitForConnection; return; } if (_mountViewModel.IsAddonSupported("GYRO")) { CurrentStep = Steps.WaitForLevel; // Turn on the Digital Level var doneEvent = new AutoResetEvent(false); _sendCommand(":XL1#,#", (a) => { doneEvent.Set(); }); doneEvent.WaitOne(); doneEvent.Reset(); // Get the reference angles from the level. _sendCommand(":XLGR#,#", (a) => { if (a.Success) { string referenceAngles = a.Data; var angles = referenceAngles.Split(",".ToCharArray()); float.TryParse(angles[0], NumberStyles.Float, _oatCulture, out float _pitchReference); float.TryParse(angles[1], NumberStyles.Float, _oatCulture, out float _rollReference); } doneEvent.Set(); }); doneEvent.WaitOne(); ShowLevelDisplay = true; } else if (_mountViewModel.IsAddonSupported("GPS")) { CurrentStep = Steps.WaitForGPS; ShowGPSStatus = true; _startedGPSWaitAt = DateTime.UtcNow; } else { ShowManualLocation = true; CurrentStep = Steps.ConfirmLocation; // Let's get teh coordinate stored on the OAT var locDoneEvent = new AutoResetEvent(false); bool gotLoc = false; float lat = 0, lng = 0; _sendCommand(":Gt#,#", (a) => { gotLoc = a.Success && TryParseLatLong(a.Data, ref lat); }); _sendCommand(":Gg#,#", (a) => { gotLoc = gotLoc && a.Success && TryParseLatLong(a.Data, ref lng); locDoneEvent.Set(); }); locDoneEvent.WaitOne(); if (gotLoc) { Latitude = lat; Longitude = 180.0f - lng; } break; } } break; case Steps.WaitForLevel: { var doneEvent = new AsyncAutoResetEvent(); // Get the current digital level angles. _sendCommand(":XLGC#,#", (a) => { string currentAngles = a.Data; if (a.Success && !currentAngles.Contains("NAN")) { var angles = currentAngles.Split(",".ToCharArray()); float.TryParse(angles[0], NumberStyles.Float, _oatCulture, out float currentPitch); float.TryParse(angles[1], NumberStyles.Float, _oatCulture, out float currentRoll); // Keep a rolling average of the last 3 values. if (_rollOffsetHistory.Count > 2) { _rollOffsetHistory.RemoveAt(0); } if (_pitchOffsetHistory.Count > 2) { _pitchOffsetHistory.RemoveAt(0); } _rollOffsetHistory.Add(currentRoll - _rollReference); _pitchOffsetHistory.Add(currentPitch - _pitchReference); } doneEvent.Set(); }); await doneEvent.WaitAsync(); if (_rollOffsetHistory.Any()) { RollOffset = _rollOffsetHistory.Average(); } if (_pitchOffsetHistory.Any()) { PitchOffset = _pitchOffsetHistory.Average(); } } break; case Steps.WaitForGPS: { TimeSpan elapsed; elapsed = DateTime.UtcNow - _startedGPSWaitAt; if (elapsed.TotalSeconds >= MaxWaitForGPS) { GPSStatus = "GPS could not get a location lock. Please enter location manually:"; ShowManualLocation = true; CurrentStep = Steps.ConfirmLocation; break; } GPSStatus = $"Waiting {MaxWaitForGPS - elapsed.TotalSeconds:0}s for GPS to find satellites and sync..."; await Task.Delay(150); bool gpsIsSyncd = false; var doneEvent = new AutoResetEvent(false); _sendCommand(":gT100#,n", async(result) => { if (result.Data == "1") { gpsIsSyncd = true; } else { await Task.Delay(500); } doneEvent.Set(); }); doneEvent.WaitOne(2500); if (gpsIsSyncd) { GPSStatus = "Sync'd! Retrieving current location..."; float latitude = 0; float longitude = 0; bool gotLoc = false; var doneEventLatLong = new AutoResetEvent(false); _sendCommand(":Gt#,#", (a) => { gotLoc = a.Success && TryParseLatLong(a.Data, ref latitude); }); _sendCommand(":Gg#,#", (a) => { gotLoc = gotLoc && a.Success && TryParseLatLong(a.Data, ref longitude); doneEventLatLong.Set(); }); doneEventLatLong.WaitOne(); if (gotLoc) { longitude = 180 - longitude; GPSStatus = "Sync'd! Setting OAT location..."; await _mountViewModel.SetSiteLatitude(latitude); await _mountViewModel.SetSiteLongitude(longitude); await Task.Delay(400); } Settings.Default.SiteLatitude = latitude; Settings.Default.SiteLongitude = longitude; Settings.Default.Save(); CurrentStep = Steps.Completed; } } break; case Steps.ConfirmLocation: break; case Steps.Completed: this.Result = true; this.Close(); return; default: break; } stateTimer.Start(); }
private async void ProcessStateMachine(object sender, EventArgs e) { stateTimer.Stop(); switch (CurrentStep) { case Steps.WaitForConnect: break; case Steps.CheckHardware: var connectResult = await _mountViewModel.ConnectToOat(SelectedDevice); ShowGPSStatus = false; GPSStatus = string.Empty; if (!connectResult) { this.Result = null; this.Close(); CurrentStep = Steps.WaitForConnect; return; } if (_mountViewModel.IsAddonSupported("GYRO")) { CurrentStep = Steps.WaitForLevel; // Turn on the Digital Level await _sendCommand(":XL1#,#"); // Get the reference angles from the level. string referenceAngles = await _sendCommand(":XLGR#,#"); var angles = referenceAngles.Split(",".ToCharArray()); _pitchReference = float.Parse(angles[0]); _rollReference = float.Parse(angles[1]); ShowLevelDisplay = true; } else if (_mountViewModel.IsAddonSupported("GPS")) { CurrentStep = Steps.WaitForGPS; ShowGPSStatus = true; _startedGPSWaitAt = DateTime.UtcNow; } else { ShowManualLocation = true; CurrentStep = Steps.ConfirmLocation; } break; case Steps.WaitForLevel: // Get the current digital level angles. string currentAngles = await _sendCommand(":XLGC#,#"); if (!currentAngles.Contains("NAN")) { var angles = currentAngles.Split(",".ToCharArray()); float currentPitch = float.Parse(angles[0]); float currentRoll = float.Parse(angles[1]); // Keep a rolling average of the last 6 values. if (_rollOffsetHistory.Count > 5) { _rollOffsetHistory.RemoveAt(0); } if (_pitchOffsetHistory.Count > 5) { _pitchOffsetHistory.RemoveAt(0); } _rollOffsetHistory.Add(currentRoll - _rollReference); RollOffset = _rollOffsetHistory.Average(); _pitchOffsetHistory.Add(currentPitch - _pitchReference); PitchOffset = _pitchOffsetHistory.Average(); } break; case Steps.WaitForGPS: TimeSpan elapsed; elapsed = DateTime.UtcNow - _startedGPSWaitAt; if (elapsed.TotalSeconds >= MaxWaitForGPS) { GPSStatus = string.Format("GPS could not get a location lock. Please enter location manually:"); ShowManualLocation = true; CurrentStep = Steps.ConfirmLocation; break; } GPSStatus = string.Format("Waiting {0:0}s for GPS to find satellites and sync...", MaxWaitForGPS - elapsed.TotalSeconds); await Task.Delay(150); var result = await _sendCommand(":gT100#,n"); if (result == "1") { GPSStatus = "Sync'd! Retrieving current location..."; result = await _sendCommand(":Gt#,#"); float latitude = float.Parse(result.Substring(0, 3)) + (float.Parse(result.Substring(4)) / 60.0f); await Task.Delay(250); result = await _sendCommand(":Gg#,#"); float longitude = float.Parse(result.Substring(0, 3)) + (float.Parse(result.Substring(4)) / 60.0f); if (longitude > 180) { longitude -= 360; } await Task.Delay(250); GPSStatus = "Sync'd! Setting OAT location..."; await _mountViewModel.SetSiteLatitude(latitude); await _mountViewModel.SetSiteLongitude(longitude); await Task.Delay(250); Settings.Default.SiteLatitude = latitude; Settings.Default.SiteLongitude = longitude; Settings.Default.Save(); CurrentStep = Steps.Completed; } break; case Steps.ConfirmLocation: break; case Steps.Completed: this.Result = true; this.Close(); return; default: break; } stateTimer.Start(); }