Jump to content
The simFlight Network Forums

Quick Query Lat/Long


rheitzman

Recommended Posts

Great tool! My BeattlesBlog connection stopped working after I installed P3D and I started looking around for solutions - this one is great!

 

I think I did look at it ages ago via the old FSUIPC VB.Net demo but I think it required treading which is a huge pain. This tool (is there a short name?) seems to do the trick w/o any serious hoop jumping.

 

In the VB.Net code below (VS2013 Express, .Net 4.0, FSX) is a minimal proof of concept of opening a connection on demand and getting the curretn lat/long and closing the connection - seems to work OK.

 

How about garbage collection? This code would run in a "moving map" type tool that would stay open. The app has a button to "Center on the a/c" that gets clicked every once in awhile - it does not try to track the a/c. Can I call GetLatLongString() using the garabge collection code shown - or is it overkill, or?

 

Also - for the latlong class - how to I get a decimal string instead of DDHHMMSS?

 

Thanks!

 

Option Explicit On
Imports FSUIPC
Public Class frmACLocation
    Dim ofsLatitude As Offset(Of Long) = New Offset(Of Long)(&H560)
    Dim ofsLongitude As Offset(Of Long) = New Offset(Of Long)(&H568)
    Dim mlat As FsLatitude
    Dim mlon As FsLongitude
    Dim mlatlon As New FsLatLonPoint

    Private Sub btnGetLatLong_Click(sender As Object, e As EventArgs) Handles btnGetLatLong.Click
        Try
            MsgBox(GetLatLongString)
        Catch ex As Exception
            MsgBox(ex.Message, , "btnGetLatLong_Click")
        End Try
    End Sub

    Function GetLatLongString() As String
        Try
            FSUIPCConnection.Open()
            FSUIPCConnection.Process()
            mlat = New FsLatitude(ofsLatitude.Value)
            mlon = New FsLongitude(ofsLongitude.Value)
            mlatlon = New FsLatLonPoint(mlat, mlon)
            Return mlatlon.ToString ' how to get decimal lat/lon?
            FSUIPCConnection.Close()
        Catch ex As Exception
            ' Badness occurred - show the error message
            MsgBox(ex.Message, , "OpenFSUIPC")
            Return "error"
        Finally
            ' cleanup required?
        '    ofsLatitude = Nothing
         '   ofsLongitude = Nothing
            mlat = Nothing
            mlon = Nothing
            mlatlon = Nothing
        End Try
    End Function
End Class

Link to comment
Share on other sites

Hi,

 

You don't need to worry about garbage collection, the .NET framework will take care of everything for you. Your current 'finally' block is overkill and not required.

 

You could improve things a little by declaring mlat, mlon and mlatlon in the method rather than at the class level as they only seem to be used in that method. They only take a up a few bytes however which is insignificant on modern PCs with gigabytes of memory.

 

The only improvement I would advise is to call FSUIPCConnection.Close() at the end of your Catch block. If you don't do this then you might find you'll never be able to open a connection again if you ever get an exception (e.g. if FSX is not running at the time).

 

To show the lat/lon in decimal format, use the ToString() overload that takes the formatting parameters. See the intellisense for details. (If you're not getting the intellisense make sure you have the FSUIPCClient.xml file in the same folder as your FSUIPCClient.dll.) I suggest the following would be what you want but it's quite flexible so you can tweak it to your exact requirements.

mlatlon.ToString(False, "d", 6)

Here's your code with the suggested changes:

Option Explicit On
Imports FSUIPC
Public Class frmACLocation

   Dim ofsLatitude As Offset(Of Long) = New Offset(Of Long)(&H560)
    Dim ofsLongitude As Offset(Of Long) = New Offset(Of Long)(&H568)
    
    Private Sub btnGetLatLong_Click(sender As Object, e As EventArgs) Handles btnGetLatLong.Click
        Try
            MsgBox(GetLatLongString)
        Catch ex As Exception
            MsgBox(ex.Message, , "btnGetLatLong_Click")
        End Try
    End Sub

    Function GetLatLongString() As String
        Try
            FSUIPCConnection.Open()
            FSUIPCConnection.Process()
            Dim mlat As FsLatitude = New FsLatitude(ofsLatitude.Value)
            Dim mlon As FsLongitude = New FsLongitude(ofsLongitude.Value)
            Dim mlatlon As New FsLatLonPoint = New FsLatLonPoint(mlat, mlon)
            Return mlatlon.ToString(False, "d", 6)
            FSUIPCConnection.Close()
        Catch ex As Exception
            ' Badness occurred - show the error message
            MsgBox(ex.Message, , "OpenFSUIPC")
            FSUIPCConnection.Close()
            Return "error"
        End Try
    End Function
End Class

Paul

 

 

 

 

 

Link to comment
Share on other sites

Thanks - here is my modified code.

 

This is a simple one button form that gets the lat/lon from the a/c and offers to open a chart web site.

 

I used your format string but it had some non-numeric'ness to the returned string. I resorted to the deprciated, but handy, Val() to clean it up. The code is verbose, I didn't want to string a bunch of operations together for the post.

 

Is there an elegant way to check to see if Open() was called and we're still connected?

 

What's the check that the a/c is "ready?" (loaded by FSX/P3D and ready to respond)

 

In the code sample I Open() once then error out on other calls. I close the conenction when the form closes. Bad technique?  If the form made other calls to other offsets would things get balled up? GetLatLongString() below should probably have some busy logic to avoid a second call from wherever.

 

I couldn't find a good list of offsets - is FSUIPC4 Offsets Status.pdf the best available?

Option Explicit On
Imports FSUIPC 
' Project Reference to FSUIPCClient.dll
Public Class frmACLocation
    Private Sub btnGetLatLong_Click(sender As Object, e As EventArgs) Handles btnGetLatLong.Click
        Try
            Dim sLatLon As String = GetLatLongString()
            If sLatLon <> "error" Then
                If MsgBox("a/c Lat/Lon: " & sLatLon & vbCrLf & "Open Chart?", MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then 
                     Process.Start("http:\\skyvector.com/?ll=" & sLatLon & "&zoom=3")
                End If
            End If
        Catch ex As Exception
            MsgBox(ex.Message, , "btnGetLatLong_Click")
        End Try
    End Sub
    Function GetLatLongString() As String
        Dim ofsLatitude As Offset(Of Long) = New Offset(Of Long)(&H560)
        Dim ofsLongitude As Offset(Of Long) = New Offset(Of Long)(&H568)
        Dim mlat As FsLatitude
        Dim mlon As FsLongitude
        Dim sLat As String = ""
        Dim sLon As String = ""
        Try             
            Try 
                ' is there a better test to see if Open() has happened and we're connected
                FSUIPCConnection.Open()
            Catch ex As Exception
                ' assume already Open
                ' next call with throw an error if that was not the case
            End Try
            FSUIPCConnection.Process()
            mlat = New FsLatitude(ofsLatitude.Value)
            mlon = New FsLongitude(ofsLongitude.Value)
            sLat = mlat.ToString(False, "d", 6)
            sLon = mlon.ToString(False, "d", 6)
            sLat = Val(sLat) ' strip off leading zeros and * symbol
            sLon = Val(sLon)
            Return sLat & "," & sLon
        Catch ex As Exception
            ' Badness occurred - show the error message
            MsgBox(ex.Message, , "GetLatLongString")
            Return "error"
        End Try
    End Function
    Private Sub frmACLocation_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
        Try
            FSUIPCConnection.Close()
        Catch ex As Exception

        End Try
    End Sub
End Class
Link to comment
Share on other sites

I used your format string but it had some non-numeric'ness to the returned string. I resorted to the deprciated, but handy, Val() to clean it up. The code is verbose, I didn't want to string a bunch of operations together for the post.

 

You can use the DecimalDegrees property then (as this is a pure number (double)) and use ToString("F6") to turn it into a string with 6 decimal places.

 

In the code sample I Open() once then error out on other calls. I close the conenction when the form closes. Bad technique? 

 

 

 

Yes, bad technique, If you want to maintain the connection for the lifetime of the application then you should just open it once when the application starts. Usually you would do this on a timer until the open is successful. If the connection ever drops then you restart the timer to attempt reconnection.

 

Is there an elegant way to check to see if Open() was called and we're still connected?

 

 

 

You have to maintain a connected flag yourself and track the Open() and subsequent Process() failures. Although FSUIPC uses the language of 'connections' being 'open' and 'closed' in reality there is nothing like a connection behind the scenes. The only way you know if the Flight Sim has been unloaded is when a Process() or Open() fails. You need to track those exceptions and maintain your own 'connected' flag.

 

All of this is shown in the sample application that I provide with the DLL.

 

If the form made other calls to other offsets would things get balled up? GetLatLongString() below should probably have some busy logic to avoid a second call from wherever.

 

 

 

No you don't need any such checks and there is no way anything gets 'balled up'. The only concern would be if you had multiple threads calling GetLatLonString() but there's no way that would happen on such a simple form as you have. Even then, the DLL is thread safe and would just deal with one thread at a time, blocking the others.

 

What's the check that the a/c is "ready?" (loaded by FSX/P3D and ready to respond)

 

 

 

You can check offset 0x3364.  When it's 0 the sim is 'ready to fly'.

 

I couldn't find a good list of offsets - is FSUIPC4 Offsets Status.pdf the best available?

 

 

 

It's the best available because it's the only official and complete list. It's the only source of information about offsets you should use.

 

You have made a mistake in your new code:

Dim ofsLatitude As Offset(Of Long) = New Offset(Of Long)(&H560)
Dim ofsLongitude As Offset(Of Long) = New Offset(Of Long)(&H568)

These offsets are now declared in your GetLatLongString method. I did not advise this. Offsets should only be declared once in the lifetime of your application.The easiest way to make sure this is the case is to declare them in at the form (or class) level, like you had them before.

 

I've amended your code with the suggestions above. I've also added an example timer mechanism, 'open' connection tracking and the use of the ready to fly offset. You'll need to add a timer to your form called 'tmrConnection' and a label 'lblConnection' to show the status of the connection.

Option Explicit On
Imports FSUIPC

Public Class frmACLocation
    Dim ofsLatitude As Offset(Of Long) = New Offset(Of Long)(&H560)
    Dim ofsLongitude As Offset(Of Long) = New Offset(Of Long)(&H568)
    Dim ofsReadyToFly As Offset(Of Byte) = New Offset(Of Byte)(&H3364)

    Dim bolConnected As Boolean = False

    Private Sub btnGetLatLong_Click(sender As Object, e As EventArgs) Handles btnGetLatLong.Click
        Try
            Dim sLatLon As String = GetLatLongString()
            If sLatLon <> "error" Then
                If MsgBox("a/c Lat/Lon: " & sLatLon & vbCrLf & "Open Chart?", MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
                    Process.Start("http:\\skyvector.com/?ll=" & sLatLon & "&zoom=3")
                End If
            End If
        Catch ex As Exception
            MsgBox(ex.Message, , "btnGetLatLong_Click")
        End Try
    End Sub

    Function GetLatLongString() As String
        Dim mlat As FsLatitude
        Dim mlon As FsLongitude
        Dim sLat As String = ""
        Dim sLon As String = ""
        Try
            FSUIPCConnection.Process()
            If (ofsReadyToFly.Value = 0) Then
                mlat = New FsLatitude(ofsLatitude.Value)
                mlon = New FsLongitude(ofsLongitude.Value)
                sLat = mlat.DecimalDegrees.ToString("F6")
                sLon = mlon.DecimalDegrees.ToString("F6")
                Return sLat & "," & sLon
            Else
                MsgBox("Flight Sim is not ready to fly", , "GetLatLongString")
                Return "error"
            End If
        Catch ex As Exception
            'Badness occurred - show the error message
            MsgBox(ex.Message, , "GetLatLongString")
            Me.tmrConnection.Start() 'start the timer again to reconnect
            Return "error"
        End Try
    End Function

    Private Sub frmACLocation_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
        Try
            FSUIPCConnection.Close()
        Catch ex As Exception

        End Try
    End Sub

    Private Sub frmACLocation_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        configureScreen()
        Me.tmrConnection.Interval = 1000 ' try connection every second
        Me.tmrConnection.Start() ' Start looking for flight sim
    End Sub

    Private Sub tmrConnection_Tick(sender As Object, e As EventArgs) Handles tmrConnection.Tick
        Me.bolConnected = False
        Try
            FSUIPCConnection.Open()
            ' Open sucessful
            Me.bolConnected = True
            Me.tmrConnection.Stop() ' Stop looking for a connection
        Catch ex As Exception
            ' Connection failed
            FSUIPCConnection.Close() ' Close ready for next retry
        Finally
            configureScreen()
        End Try
    End Sub

    Private Sub configureScreen()
        If Me.bolConnected Then
            Me.lblConnection.Text = "Connected to " & FSUIPCConnection.FlightSimVersionConnected.ToString()
            Me.lblConnection.ForeColor = Color.Green
            Me.btnGetLatLong.Enabled = True
        Else
            Me.lblConnection.Text = "Connecting to Flight Sim..."
            Me.lblConnection.ForeColor = Color.Red
            Me.btnGetLatLong.Enabled = False
        End If
    End Sub
End Class

Paul

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use. Guidelines Privacy Policy We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.