Jump to content
The simFlight Network Forums

FSUIPC Client DLL for .NET - Version 2.0


Recommended Posts

  • 2 weeks later...

It would be nice if the next release of FSUIPC.NET Client came with both an x86 DLL as well as an Any CPU dll. I develop in Windows 7 Ultimate x64 usually with Any CPU but when I try to compile my flight sim projects I get a warning about the MSIL mismatch :(

For now I had to switch all my flight sim projects to x86 but would be nice to also have an "Any CPU" dll I can link to.

Link to comment
Share on other sites

It would be nice if the next release of FSUIPC.NET Client came with both an x86 DLL as well as an Any CPU dll.

I'm not sure this is possible. The .NET Client DLL must be x86 or it will not be able to communicate with FSUIPC. The communication process uses windows messages and shared memory.

Because FSUIPC is running inside Flight Sim which is a 32-bit process, my understanding is that only another 32-bit process can send windows messages to it and access the same memory. This makes sense because 32-bit software is running inside a virtual machine on the 64-bit windows so it has it's own separate virtual memory.

I think the only communication possible would be those than can cross machine boundaries like DCOM and TCP/IP etc. But FSUIPC doesn't use these.

Paul

Link to comment
Share on other sites

Is there any way to know the Maximum Landing Weight (MLW) of the aircraft using FSUIPC? I seem to recall an XML gauge in FS 2004 (freeware addon) that gave you a red indication when your current weight (0x30C0) exceeded the MLW.

I am unable to see any MLW in the FSUIPC offsets document I have (v4.70)

Link to comment
Share on other sites

I am using your DLL in a project of mine that uses WCF, all my assemblies in the project are .NET 4.5 with runtime 4.0 and target platform x86. So on my part I checked that all my references are for 4.0 including System.dll

The problem is when I run the WCF service under the service host I get an error indicating that one of the assemblies could not be loaded, a BadImageException. In the Microsoft forums they told me to check the version of System.DLL referenced by the assemblies. So as I said, all my projects reference the 4.0.0.0 runtime version of System.dll. The only one I can't verify is your FSUIPCDotNetClient DLL. Could you tell me for which .NET platform it was compiled AND which System.dll version it is referencing?

Link to comment
Share on other sites

Could you tell me for which .NET platform it was compiled AND which System.dll version it is referencing?

The normal one available at the start of this thread targets the .NET 2 framework.

In December 2011 I sent you a DLL (version 2.2) via PM that targets the .NET 4.0 framework. I don't know which one you are using.

I can make you another for .NET 4 if you like (will be 2.3). Looking at my system, the version info for the System.DLL will be:

Version = 4.0.0.0

Runtime Version = v4.0.30319

Specific Version = False

Paul

Link to comment
Share on other sites

Just checked, I have v2.3Beta which I downloaded from this thread but in VS.2012 the FSUIPCClient.dll from 2.3 shows runtime v2.0.50727

Yeah that would be for .NET 2.

Attached is 2.3 but compiled for the .Net 4 runtime.

Let me know if this doesn't work and I'll see if I can tweak anything.

Paul

FSUIPCClientBeta2.3_Net4.zip

Link to comment
Share on other sites

  • 3 weeks later...

Is there an update in the documentation? I have noticed a couple of new classes like FsFuelTank & FsPayloadStation or something like that but they are neither static classes, nor have a constructor so they can't be used :(

I haven't updated the documentation yet, which is why the official version is still 2.0. The new stuff is 2.3 what put in for a few users that needed/requested them. There are:

1. Payload reading/writing facilities (includes fuel tanks)

2. Responding to user input in Flight Sim (keystrokes, joystick buttons and menu items - includes adding the menu item to FS).

The only documentation I have is the supplied intellisense and some sample code in VB:

Payload and Fuel data

===================

The payload and fuel data is accessed from a new property on the FSUIPCConnection class called 'PayloadServices'.

It's a good idea to assign this to a local variable to save typing FSUIPCConnection.PayloadServices all the time...

' Get a reference to save so much typing...
Dim ps As PayloadServices = FSUIPCConnection.PayloadServices

Whenever you want to get the latest payload and fuel data you just need to call RefreshData() on the PayloadServices object...

' Get the latest data from FSUIPC
ps.RefreshData()

Once you have done that there are lots of properties on the PayloadServices class that will give you weight and fuel data for the aircraft overall. For example:

ps.PayloadWeightLbs
ps.AircraftWeightLbs

Most are self-explanatory and there is Intellisense on everything.

You also have access to the individual payload stations and fuel tanks. Here is an example of iterating through each payload station.

 ' Go through each station and get the name and weight
For Each (payloadStation As FsPayloadStation In ps.PayloadStations)
   Dim name As String = payloadStation.Name
   Dim weight As Double = payloadStation.WeightLbs
Next payloadStation

You can also write new values to individual payload stations or fuel tanks.

To change the value of payload station, just change one of the weight properties for that station (Lbs, Kg etc).

When you've made all the changes you want call WriteChanges() on your PayloadServices object. This will send all the changed values to FSUIPC.

Fuel tanks are the same except, in addition to changing the weight, you can also change them by setting a new % full level or a volume in Gallons or Litres.

Note that WriteChanges() send both Payload and Fuel changes in one go.

User Input - Menus

=================

1. First, declare a UserInputServices object using the WithEvents modifier

' Declare a UserInputServices object so we can use it in the code
Private WithEvents userInput As UserInputServices

2. After opening the FSUIPC connection you need to set the variable above and add your menu items:

 ' Open the connection to FSUIPC
FSUIPCConnection.Open()
' Set our userInput object to the UserInputServices
userInput = FSUIPCConnection.UserInputServices
' Add our menu items (2 examples)
' First parameter is the ID we use to identify this menu item
' Second parameter is the Text for the menu item (Max 30 chars)
' use & before a letter to make it the shortcut key
' Third parameter specifies whether or not to pause FS when
' the menu item is selected.
userInput.AddMenuItem("Menu1", "Menu Item &One", False)
userInput.AddMenuItem("Menu2", "Menu Item &Two (Pauses FS)", True)

Note that if you use a pausing menu item it will be your application's responsibility to unpause FS by writing to offset 0626 at the appropriate time.

3. You need add a new method to handle the MenuSelected event. This will be called when the user selects one of your menu items:

 Private Sub menuItemSelected(ByVal sender As Object, ByVal e As UserInputMenuEventArgs) Handles userInput.MenuSelected
   ' This sub gets called when a menu item is selected
   ' Use the e object to see which one (Check the ID)
   Select Case e.ID
      Case "Menu1"
         MessageBox.Show("Menu item 1 selected")
      Case "Menu2"
         MessageBox.Show("Menu item 2 selected")
   End Select
End Sub

4. You need to call CheckForInput() regularly to check if the user has selected any menu items. If they have the above method above will automatically be called for you. Add this code in one of your timers.

 ' Check for input. Recommended every 200ms
userInput.CheckForInput()

5. FSUIPC will delete your menu items after about 14 seconds. To prevent this you must tell FSUIPC that your application is still running and stills needs the menu items. You must call KeepMenuItemsAlive() regularly. Pete suggests every 8 seconds. So on an 8 second timer call:

userInput.KeepMenuItemsAlive()

6. Before your application exits, call the RemoveAll() method to clean up your menu items.

 ' Remove our menu items
userInput.RemoveAll()

User Input - Buttons and Keys

==========================

Similar to above except you use AddKeyPress() and AddJoystickButtonPress() to register the buttons/keys.

You then sink the KeyPressed or ButtonPressed events to detect the user pressing the button/key.

You still need to call the CheckForInput() regularly but KeepMenuItemsAlive() is obviously not required for buttons/keys.

If you need any more help with the new features just ask.

Paul

  • Upvote 1
Link to comment
Share on other sites

Thank you VERY much Paul, that is superb. Will experiment with that soon, in the meantime I already added the code but am short of time for playing.

Just one more question with regards to that.... Say I had a connection and my menu items were declared, registered and refreshed periodically. Then all of a sudden I lost the connection with FSUIPC, takes some time before I reconnect, say more than the 14 seconds and FSUIPC removes my menu items, then, since I don't know for sure (maybe it took less than 14 seconds) if my menu items are gone, say they are and I call KeepMenuItemsAlive() or CheckForInput() now that my menu items are gone, will that throw an exception? what would be the FSUIPCError? I don't see any error code relating to that.

Would in that case be a way that I can know whether I have to rebuild the menu? I don't see anything in UserInputServices that would let me check if my menu items have been zapped, otherwise they are gone, my app doesn't know and it will cease operating correctly.

Anyway, great feature, thanks!

Link to comment
Share on other sites

The losing of the connection isn't really an issue, the important thing is if Flight Sim was unloaded or not during that time. If not then everything will carry on as normal. If it was then all the registered buttons/menus etc will be lost. They are stored in the FSUIPC dll which runs in the Flight Sim process.

Calling CheckForInput or KeepAlive() will not throw any errors if nothing is registered, or if the registered buttons etc have been cleared (because FS was unloaded).

These will throw errors if the connection is broken however - the same ones as process().

The safest way to handle things would be:

1. Detect the loss of connection.

2. Wait until it reconnects.

3. Call UserInputServices.RemoveAll()

4. Reregister all the buttons/menus

5. Carry on as normal.

That way you don't need to worry about testing if FS was unloaded or not.

Step 3 is important because it will clear the registrations from my DLL as well as FSUIPC. If nothing was registered it will just do nothing, it won't throw an error.

Paul

Link to comment
Share on other sites

  • 2 months later...

Paul,

need your advice for a (small) problem. The following example declarion works fine in VB.net 2010:

Dim Newoffset="&H" & textbox1.text

Dim readoffset As Offset(Of UShort) = New FSUIPC.Offset(Of UShort)(Newoffset)

With overloading by a GroupName VB2010 gives me an error, example:

Dim Newoffset="&H" & textbox1.text

Dim readoffset As Offset(Of UShort) = New FSUIPC.Offset(Of UShort)("TestGroup", Newoffset)

The following example works:

Dim readoffset As Offset(Of UShort) = New FSUIPC.Offset(Of UShort)("TestGroup", &H57A6)

Thanks for your help!

Ruediger

visit: http://www.flying-the-winglets.de

Link to comment
Share on other sites

Hi Ruediger,

...The following example declarion works fine in VB.net 2010:

Dim Newoffset="&H" & textbox1.text
Dim readoffset As Offset(Of UShort) = New FSUIPC.Offset(Of UShort)(Newoffset)

It does work, but in my view the compiler is being far too generous! It's converting the hex string into an integer for you behind the scenes.

With overloading by a GroupName VB2010 gives me an error, example:

Dim Newoffset="&H" & textbox1.text
Dim readoffset As Offset(Of UShort) = New FSUIPC.Offset(Of UShort)("TestGroup", Newoffset)

This time, the compiler cannot to the conversion for you because there is more than one overload with two parameters. It doesn't know which one it should use.

To get this to work you need to explicitly convert the string to an Integer using the Integer.Parse method. I recommend you always use this method, even if it does work the other way. I've separated the conversion here to make it easier to read, but you can of course put the conversion directly in the FSUIPC.Offset constructor parameters.

Dim Newoffset = TextBox1.Text ' No &H is required.
Dim IntNewoffset as Integer
IntNewOffset = Integer.Parse(Newoffset, Globalization.NumberStyles.AllowHexSpecifier)
Dim readoffset As Offset(Of UShort) = New FSUIPC.Offset(Of UShort)("Group1", IntNewoffset)

Note that the Integer.Parse() conversion does not allow the string to include the "&H" prefix.

Paul

Link to comment
Share on other sites

  • 5 weeks later...

Hey Paul (and all the other readers here),

since a few weeks I am working on a fuel & CG planner and I got everything I should get. My application saves the "passenger" load into the aircraft.cfg, however the fuel is the only thing which cannot be saved that simple. I tried a lot of things with SimConnect but this made me mad. I searched for alternatives and finally I found one with your DLL. For this now already a big THANK YOU! Makes life much easier :)

Although I am digging in this, my application seems to have a problem. I am programming in VB.net but it seems I am too dumb to find my mistake. I debugged it and all my values are calculated correctly (at least I think so) but when it comes to send it to FSX I just get instead of a loaded fuel tank an empty one. I just did the case to fill my left tank with 50 gallons of fuel (just to get the thing running..) however as said instead that I get 50 gallons in my tank I always get 0 gallons after the process is finished.

Here my code:


Private Sub ButtonSend_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Open a connection to FSUIPC on FSX
Try
FSUIPCConnection.Open(FlightSim.FSX)
Dim FuelLeftCapacity As Offset(Of Integer) = New Offset(Of Integer)(&HB80)
Dim FuelLeftTankLevel As Offset(Of Integer) = New Offset(Of Integer)(&HB7C, True)
Dim FuelRightCapacity As Offset(Of Integer) = New Offset(Of Integer)(&HB98)
Dim FuelRightTankLevel As Offset(Of Integer) = New Offset(Of Integer)(&HB94, True)

'Let the application load once the data
FSUIPCConnection.Process()

'Calculate now the values to have finally 50 gallons fuel in my left tank
Dim LeftTankLevelGallons As Double = 50
Dim LeftTankLevel As Double = (LeftTankLevelGallons / FuelLeftCapacity.Value) * 128D * 65535D
Dim LeftTankLevelPercentage As Double = LeftTankLevel / 128D / 65535D * 100D
FuelLeftTankLevel.Value = LeftTankLevelPercentage

'Send data to FSX
FSUIPCConnection.Process()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
FSUIPCConnection.Close()
End Sub
[/CODE]

Can anybody help me here please?

Link to comment
Share on other sites

'Calculate now the values to have finally 50 gallons fuel in my left tank

Dim LeftTankLevelGallons As Double = 50

Dim LeftTankLevel As Double = (LeftTankLevelGallons / FuelLeftCapacity.Value) * 128D * 65535D

Dim LeftTankLevelPercentage As Double = LeftTankLevel / 128D / 65535D * 100D

FuelLeftTankLevel.Value = LeftTankLevelPercentage

I don't know VB.NET I'm afraid,so for definitive answers I'll have to leave that to Paul, but it seems there are some odditities here.

The most striking one seems to be that you define FuelLeftTankLevel as inmteger but assign to it a double. Does VB.NET do a conversion for you automatically, truncating the floating point value to an integer.

The other things which seem odd are:

a ) the derivation of LeftTankLevel from the ratio multiplied by 128 * 65535 when it is defined as a * 128 * 65536. Why 65535 instead?

b ) if you fix that, the result you then have in LeftTankLevel is the value you need. Why are you then doing that / 128 / 65535 * 100 business? You already converted it into the correct units in the line before.

Please try using FSInterrogate so you can see what the values actually look like and how they are derived. Use a calculator to see what you'd get. In the above case, for the FSX 738, value for 50 gallons would work like this:

LeftTankLevel = (50 / 1288) * 128 * 65536 = 325644

That's the Integer value which would need to be written. But your further conversion does this:

LeftTankLevelPercentage = 325644 / 128 / 65536 * 100 = 3 (as an integer).

The value 3 there amounts to 0.0000004 % full, or 0.0004606 Gallons, which will certainly read out as 0.

You'd be able to spot this sort of error using FSInterrogate to check and compare. I know FS uses the term "percentage" incorrectly. Almost every tme it really means "ratio", so 100% full = 1, and in units of 128 * 65536 that it would be, well 128 * 65536.

Regards

Pete

Link to comment
Share on other sites

Hi ScKevin,

First, if that is your real application code, then it's best not to keep opening and closing the connection. Just open once when your application starts and close before it unloads.

Similarly only DIM the offsets once at the form (or class) level. Offsets are not garbage-collected when they go out of scope so your application will be requesting more and more data from FSUIPC with each press of the button.

But maybe this is just test code to show the problem you are having...

So turning to your fuel problem you have two conversions wrong as Pete has already explained above. Should be as follows:


Dim LeftTankLevel As Double = LeftTankLevelGallons / FuelLeftCapacity.Value * 128D * 65536D
FuelLeftTankLevel.Value = LeftTankLevel
[/CODE]

As an alternative to using the raw fuel offsets you could instead use the payload services in my DLL (Version 2.3)

The code to set 50 Gallons in the left fuel tank would look like this: (Requires an already open connection)

[CODE]Dim ps As PayloadServices = FSUIPCConnection.PayloadServices
ps.RefreshData()
ps.GetFuelTank(FSFuelTanks.Left_Main).LevelUSGallons = 50
ps.WriteChanges()[/CODE]

The payload services allows you to read/write fuel tank and payload stations. There are also some properties that are derived and not available directly from FSUIPC.

I'll put a post under this in a few minutes with version 2.3 of the DLL plus some sample code for the new features. I don't have the proper documentation done yet.

Paul

Edited by Paul Henty
Link to comment
Share on other sites

Attached is version 2.3 of the DLL which includes some new features:

1. Read/write fuel and payload data

2. Allows you application to respond to keypresses, joystick buttons and menu items added to the FS menu by your application.

There are two Zips. They contain the same DLL except for the version of the .NET framework they target. You can choose between the 2.0 Framework (NET2) or the 4.0 Framework Client Profile (NET4). If you don't know which one you need get the NET2 version.

Reading Payload and Fuel data

=============================

The payload and fuel data is accessed from a new property on the FSUIPCConnection class called 'PayloadServices'.

It's a good idea to assign this to a local variable to save typing FSUIPCConnection.PayloadServices all the time...

' Get a reference to save so much typing...
Dim ps As PayloadServices = FSUIPCConnection.PayloadServices

Whenever you want to get the latest payload and fuel data you just need to call RefreshData() on the PayloadServices object...

' Get the latest data from FSUIPC
ps.RefreshData()

Once you have done that there are lots of properties on the PayloadServices class that will give you weight and fuel data for the aircraft overall. For example:

ps.PayloadWeightLbs
ps.AircraftWeightLbs
ps.FuelWeightLbs
ps.FuelCapacityUSGallons

Most are self-explanatory and there is Intellisense on everything.

You also have access to the individual payload stations and fuel tanks. Here is an example of iterating through each payload station.

 ' Go through each station and get the name and weight
For Each (payloadStation As FsPayloadStation In ps.PayloadStations)
Dim name As String = payloadStation.Name
Dim weight As Double = payloadStation.WeightLbs
Next payloadStation

You can do the same thing with the FuelTanks collection. This holds a FsFuelTank object for each possible tank. Some might not be in use for the current aircraft though.

To access properties on a specific fuel tank you can use the following syntax: (This gets the current level of the Centre_Main tank in US Gallons. Other properties and tanks are available.)

ps.GetFuelTank(FSFuelTanks.Centre_Main).LevelUSGallons

Changing Payload and Fuel

=========================

You can also write new values to individual payload stations or fuel tanks.

To change the value of payload station, just change one of the weight properties for that station (Lbs, Kg etc).

When you've made all the changes you want call WriteChanges() on your PayloadServices object. This will send all the changed values to FSUIPC.

Fuel tanks are the same except, in addition to changing the weight, you can also change them by setting a new % full level or a volume in Gallons or Litres.

Note that WriteChanges() send both Payload and Fuel changes in one go.

User Input - Menus

===================

1. First, declare a UserInputServices object using the WithEvents modifier

' Declare a UserInputServices object so we can use it in the code
Private WithEvents userInput As UserInputServices

2. After opening the FSUIPC connection you need to set the variable above and add your menu items:

 ' Open the connection to FSUIPC
FSUIPCConnection.Open()
' Set our userInput object to the UserInputServices
userInput = FSUIPCConnection.UserInputServices
' Add our menu items (2 examples)
' First parameter is the ID we use to identify this menu item
' Second parameter is the Text for the menu item (Max 30 chars)
' use & before a letter to make it the shortcut key
' Third parameter specifies whether or not to pause FS when
' the menu item is selected.
userInput.AddMenuItem("Menu1", "Menu Item &One", False)
userInput.AddMenuItem("Menu2", "Menu Item &Two (Pauses FS)", True)

Note that if you use a pausing menu item it will be your application's responsibility to unpause FS by writing to offset 0626 at the appropriate time.

3. You need add a new method to handle the MenuSelected event. This will be called when the user selects one of your menu items:

 Private Sub menuItemSelected(ByVal sender As Object, ByVal e As UserInputMenuEventArgs) Handles userInput.MenuSelected
' This sub gets called when a menu item is selected
' Use the e object to see which one (Check the ID)
Select Case e.ID
Case "Menu1"
	 MessageBox.Show("Menu item 1 selected")
Case "Menu2"
	 MessageBox.Show("Menu item 2 selected")
End Select
End Sub

4. You need to call CheckForInput() regularly to check if the user has selected any menu items. If they have the above method above will automatically be called for you. Add this code in one of your timers.

 ' Check for input. Recommended every 200ms
userInput.CheckForInput()

5. FSUIPC will delete your menu items after about 14 seconds. To prevent this you must tell FSUIPC that your application is still running and stills needs the menu items. You must call KeepMenuItemsAlive() regularly. Pete suggests every 8 seconds. So on an 8 second timer call:

userInput.KeepMenuItemsAlive()

6. Before your application exits, call the RemoveAll() method to clean up your menu items.

 ' Remove our menu items
userInput.RemoveAll()

User Input - Buttons and Keys

===============================

Similar to above except you use AddKeyPress() and AddJoystickButtonPress() to register the buttons/keys.

You then sink the KeyPressed or ButtonPressed events to detect the user pressing the button/key.

You still need to call the CheckForInput() regularly but KeepMenuItemsAlive() is obviously not required for buttons/keys.

FSUIPCClient2.3_NET2.zip

FSUIPCClient2.3_NET4.zip

Link to comment
Share on other sites

First of all thanks Paul for a new version of your amazing .dll!

Then I used the way you gave me the example with this code:


Try
FSUIPCConnection.Open(FlightSim.FSX)
Dim ps As PayloadServices = FSUIPCConnection.PayloadServices
ps.FuelTanks(FSFuelTanks.Left_Main).LevelUSGallons = 50
ps.WriteChanges()
MsgBox("Done")
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
[/CODE]

And I always get an error saying the following:

"Index is out of bounds. He shouldn't be negative und be below the list. Parametername: Index"

(Since my PC is a German one, I get the German message of it: "Der Index lag außerhalb des Bereichs. Er muss nicht negativ und kleiner als die Auflistung sein.Parametername: index" and I translated it into English as best as I can)

That makes me mad. My aircraft.cfg says the following under fuel:

[CODE]
LeftMain = X.X, X.X, X.X, 158.0, 3.6 //Longitudinal (feet), Lateral (feet), Vertical (feet), Usable(gallons), Unusable (gallons)
RightMain = X.X, X.X, X.X, 158.0, 3.6 //Longitudinal (feet), Lateral (feet), Vertical (feet), Usable(gallons), Unusable (gallons)
[/CODE]

I cannot find again my mistake since FSX is running and the airplane is loaded. This also happens with different airplanes like Majestic Q400, so basically it is wrong or?

thanks for your help

Link to comment
Share on other sites

Then I used the way you gave me the example with this code:

And I always get an error saying the following:

"Index is out of bounds. He shouldn't be negative und be below the list. Parametername: Index"

Oh I think this could just be a problem with the code I gave you. I think you might need to call RefreshData() first to 'create' the fuel tanks so you can change them.

Try this:


Try
FSUIPCConnection.Open(FlightSim.FSX)
Dim ps As PayloadServices = FSUIPCConnection.PayloadServices
ps.RefreshData()
ps.FuelTanks(FSFuelTanks.Left_Main).LevelUSGallons = 50
ps.WriteChanges()
MsgBox("Done")
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
[/CODE]

Link to comment
Share on other sites

Ok I copied it now exactly like this into my application:


Try
FSUIPCConnection.Open(FlightSim.FSX)
Dim ps As PayloadServices = FSUIPCConnection.PayloadServices
ps.RefreshData()
ps.FuelTanks(FSFuelTanks.Left_Main).LevelUSGallons = 50
ps.WriteChanges()
MsgBox("Done")
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
[/CODE]

but nothig changes. My fuel tank is still fuel. I am missing surely one thing here or?

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • 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.