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();
        }
Exemplo n.º 2
0
        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();
        }