
Paul Henty
Members-
Posts
1,724 -
Joined
-
Days Won
77
Content Type
Profiles
Forums
Events
Gallery
Downloads
Everything posted by Paul Henty
-
Applications detecting FSUIPC?
Paul Henty replied to rfresh's topic in FSUIPC Support Pete Dowson Modules
The usual way to handle this is to attempt the connection and catch the error thrown if FSUIPC is not running. This could be because the user doesn't have it installed or because FSX isn't loaded yet. Either way, you can display a message or a status in your application to let the user know that your application cannot connect to FSUIPC. If you have a look at my C# Example Application there is code in there that attempts a connection and if it doesn't find one it will keep trying. Meanwhile, the connection status is displayed on the form. If the connection is ever lost it goes back to the looking state and the main functionality is suspended until the connection comes back. Paul -
I've reread your post where you did the logging. I think I misread it earlier. It seems to me now that line I quoted was not sent by PMDG but by your code. What you need to do is turn on the event logging in FSUIPC and press the keys on the CDU with your mouse and see what controls and parameters PMDG is sending. That will help us replicate the correct messages. Paul
-
I've really no idea how you would use the mouse flags. Controls do have parameters, so my first thought was that the mouse flags could be send as the parameter to the control. However, looking at your log from FSUIPC it clearly shows the menu control being sent by PMDG without any parameter (it's 0). If you want to try sending the mouse flag you can but I don't have much expectation that it will work: To do this you need another offset. This one MUST be declared before the sendControl offset, or it won't work properly (you can set the values in any order you like). // Order is important! private Offset<int> controlParameter = new Offset<int>("SendControl", 0x3114, true); // Both in the SendControl group, not a typo! private Offset<int> sendControl = new Offset<int>("SendControl", 0x3110, true); private readonly int MOUSE_FLAG_LEFTSINGLE = 0x20000000; // Press MENU button sendControl.Value = THIRD_PARTY_EVENT_ID_MIN + 551; controlParameter.Value = MOUSE_FLAG_LEFTSINGLE; FSUIPCConnection.Process("SendControl"); If that doesn't work then you really need to ask PMDG directly or on their support forums how these CDU controls are meant to be used. Paul
-
Hi Ralph, Here is the updated version of the DLL (Version 3.0 beta) containing the sub menu functionality. To update, either overwrite your existing DLL and XML file with the new ones, or you can put them in a new folder and redo the reference in the C# project. The sub menu functionality is the same as the main menu except you have to specify the parent menu: Here's some sample code which should be self-explanatory. In all other respects (e.g. responding to the user clicking them) the sub menus are exactly the same as the normal menu. I refer you back to the main 2.4 thread. ui = FSUIPCConnection.UserInputServices; // Add our main menu items // The first parameter is the key and can be whatever you want. // Second is the text to display // Third is whether to pause FS on selection ui.AddMenuItem("MenuA", "Menu A", false); ui.AddMenuItem("MenuB", "Menu B", false); ui.AddMenuItem("MenuC", "Menu C", false); // Adding sub menus to menu B // First is the ID of this sub menu // Second is the ID of the parent menu // Third is the test to display ui.AddSubMenuItem("SubMenuB1", "MenuB", "Sub B1"); ui.AddSubMenuItem("SubMenuB2", "MenuB", "Sub B2"); As an aside, I've improved the way the payload stations and fuel tanks work as you can now hold on to a reference to a particular tank or payload station between calls to RefreshData(). Before it was recreating new tank and payload objects forcing users to get new copies from PayloadServices after RefreshData(). It is still the case that you need to call RefreshData() at least once before any fuel tanks are available. I couldn't see an elegant way around that. Paul FSUIPCClient3.0_BETA.zip
-
Thanks very much for the donation, it's much appreciated. I can't see anything wrong with your code. I can't test it properly because I don't have the PMDG 737. I've tested sending a normal 'fsx' control (parking brakes toggle) and it's working okay. Maybe you can adding this to the end of your controls and see if this one reacts. sendControl.Value = 65752; // parking brakes FSUIPCConnection.Process("SendControl"); If this doesn't work on the 737NGX then try on a stock FS aircraft, just to prove the code/dll/fsuipc is working okay. If it's just the 737NGX CDU events that aren't working, try enabling the event (non axis) logging in FSUIPC. You can show the log in a separate console window to get real time feedback. Then press the buttons on the CDU and see what events are being triggered. Make sure they are the ones you are expecting. You can also run your code and compare the events fired manually with the ones your code it firing. Paul
-
Thanks for that Pete, I didn't know about those control for sending Key Presses. Ralph - here's an example of sending the key presses for your sequence: First you need to declare the offset to send the control to (0x3110). Here i've put it in it's own group and made it write only. Also I've declared the constant for the THIRD_PARTY_EVENT_ID_MIN value to make things easier. private Offset<int> sendControl = new Offset<int>("SendControl", 0x3110, true); private readonly int THIRD_PARTY_EVENT_ID_MIN = 0x00011000; // equal to 69632 Then to send the sequence you need this: // Press MENU button sendControl.Value = THIRD_PARTY_EVENT_ID_MIN + 551; FSUIPCConnection.Process("SendControl"); // Press FS ACTIONS> LSK5R sendControl.Value = THIRD_PARTY_EVENT_ID_MIN + 544; FSUIPCConnection.Process("SendControl"); // Press <FUEL LSK1L sendControl.Value = THIRD_PARTY_EVENT_ID_MIN + 534; FSUIPCConnection.Process("SendControl"); // Press digit 3 sendControl.Value = THIRD_PARTY_EVENT_ID_MIN + 563; FSUIPCConnection.Process("SendControl"); // Press digit 4 sendControl.Value = THIRD_PARTY_EVENT_ID_MIN + 564; FSUIPCConnection.Process("SendControl"); Etc... You could go to the trouble of declaring all the constants as well as the 'min' constant. You can then use those variable names instead of using the '+' syntax all the time. e.g. private readonly int EVT_CDU_L_4 = THIRD_PARTY_EVENT_ID_MIN + 564; then you can just use this to set the control value. It will make the code much more readable. sendControl.Value = EVT_CDU_L_4; Paul
-
The DLL has nothing specific, but FSUIPC has a key send facility at offset 0x3200. It seems to be a 'front' for a normal Win32 SendMessage() however, so unless you're familiar with the Win32 API and working with bits and bytes it might be a bit of a challenge. The documentation for the key down message is here: (You'll need this to know what to set as the Iparam and Wparam). http://msdn.microsoft.com/en-us/library/windows/desktop/ms646280%28v=vs.85%29.aspx You'll also need to manage each key up as well. I wonder if the PMDG interface has a more direct way of simulating key presses for the CDU through a flight sim 'control' (aka 'events')? It's worth looking in the PMDG SDK for the control list (I think it's in the form of a C header file). This would be much easier than sending actual keyboard presses into the Flight Sim windows process.. If it does exist then report back and we'll go from there. If they don't have such a control then I could put a feature in the DLL to send real key presses to FSX so that you don't have to deal directly with the Win32 API parameters. It will make it much simpler. Paul
-
new Offset<string>("info", 0x3D00, 24); Yes, the 24 is the number of bytes to read. This is only required for certain offset types where the length cannot be determined from the type itself. So with 'int' for example you don't need to specify the length because an 'int' is always 4 bytes. For strings and arrays the dll needs some extra info as strings don't have a fixed length. The "info" part is an example of the grouping feature. You don't have to use grouping, but it can make sense when you don't want to read some offsets as often as others. Typically in applications there is data that needs to be updated frequently (e.g. aircraft position, airspeed etc) and other data that may only be required infrequently or just once. To avoid reading more data than is required you can place offsets in named groups. The names can be anything you like. You can then choose when to Process() the different groups by passing the name to the Process() method as you've seen. You can also process multiple groups at once, see the user guide for how to do that. You could declare the offset like this: private Offset<string> aircraftName = new Offset<string>(0x3D00, 24); and then it will work with the normal Process(). It's really up to you how, or if, you use the grouping. Paul
-
You need to call ps.RefreshData() before you try to get any tank objects back. I'm not happy with how that works so I look at improving this, but for now you need to call RefreshData() at least once to create the fuel tanks in the dll. Paul
-
Seems this was a new feature for FSUIPC4. I don't know why I didn't include this feature in the DLL, but I'll fix this and get you a new version by the end of the week. Thanks for spotting this. Paul
-
I have to apologise - I've read the FSUIPC documentation completely wrong. You can indeed do sub menu items. Let me look into it some more. Paul
-
Nested menus are not possible via FSUIPC. The SimConnect interface (which is how FSUIPC mainly talks to FSX) only allows 16 items directly under the Add-ons menus. Paul
-
Thanks for the information. I've just run your code here and the reason you're not reading back the new fuel level is that the refresh is too soon. It seems that FSX or FSUIPC needs a bit of time to adjust to the new values in the fuel tank. If you put a pause between them then it works as expected. // Get a reference to save so much typing later... PayloadServices ps = FSUIPCConnection.PayloadServices; // Get the latest data from FSUIPC ps.RefreshData(); // Display centre tank percentage string str1 = ps.GetFuelTank(FSFuelTanks.Centre_Main).WeightLbs.ToString("F0"); ps.GetFuelTank(FSFuelTanks.Centre_Main).WeightLbs = 16000; ps.WriteChanges(); Thread.Sleep(2000); // Wait 2 seconds for everything to catch up ps.RefreshData(); string str2 = ps.GetFuelTank(FSFuelTanks.Centre_Main).WeightLbs.ToString("F0"); this.Text = str1 + " " + str2; You probably don't need to wait a full 2 seconds, that's just what I used to test this. The 'get' part is getting the fuel tank object. Once you have got the fuel tank object you set the WeightLbs property on that object. If I break it into two steps you can see it makes more sense. FsFuelTank leftTank = ps.GetFuelTank(FSFuelTanks.Left_Main); leftTank.WeightLbs = 8000; Putting it all in one line just saves typing and creating a variable. You might want to break it out though if you need to do more work on the single tank. This will save running the GetFuelTank method over and over. So imagine some code like this: FsFuelTank leftTank = ps.GetFuelTank(FSFuelTanks.Left_Main); if (leftTank.WeightLbs < 1000 && automaticRefuelActive) { leftTank.LevelPercentage = 100; ps.WriteChanges(); } This makes more sense than calling GetFuelTank twice and also makes the code cleaner and easier to read. So now to the main problem of the PDMG737 not respecting the fuel level changes. What's probably happening is that the PMDG code is constantly updating the fuel levels in the FSX tanks, So when you write your level it's soon overwritten again by the PMDG code. The reason for this is so they can more accurately simulate fuel consumption and feeding fuel betweens tanks. There are special offsets in FSUIPC for the PMDG 737ngx which allow access to areas of the aircraft that are modelled outside of FSX. These would normally not be available to FSUIPC but Pete has integrated FSUIPC with PDMG's SDK. For details of how to enable this interface and the extra offsets available see the document called "Offset Mapping for PMDG 737NGX.pdf" in the FSUIPC Documents folder under your FSX modules folder. This will not help with your fuel however as they are all read-only. The document does however mention that certain aspects of the 737NGX can be changed by sending 'controls' via FSUIPC. These are listed in the PMDG 737 SDK documentation. I don't have this aircraft so I can't look myself, but there might be controls to set fuel levels. Another place you can look for help is the 'User Contributions' forum under Pete's main support forum. Someone may have already solved this problem. Also if PMDG have forums then you could also try asking there. Paul
-
If you write fuel tank levels with WriteChanges() then these should show up instantly in the sim. To really make sure the new level is being written, do another ps.RefreshData() after the WriteChanges() and then get the value again. At the moment your check is just reading the local (pending) value you've set as it's before the WriteChanges() call. If that comes back okay then here are some other thoughts: 1. If you just read the centre tank without changing it, does it match the gauge on the 737? 2. Is the change from your program reflected in the FSX Fuel dialog from the Aircraft menu? 3. Have you tried the code with the default 737? It may be that PDMG don't use the FSX fuel tanks at all, but use their own code. This sort of thing is common with complex add-on aircraft. 4. Maybe they are using one of the other centre tanks - try Centre_2 and Centre_3. I'm not sure about the nested menus - I'll look in to that tomorrow. Paul
-
The documentation hasn't been updated since 2.0. The documentation for the new 2.4 features (which includes the payload services) is in the thread I linked you to. Please see the section in the user guide pdf called 'licence' (page 3) for details about donations. Paul
-
Firstly you're declaring an offset in the method. This is not good practice as you run the risk of creating duplicate offsets. I recommend you always create the offsets at class (form) level. See the C# sample application (the top of the main form code) to see the correct place to put all the offset declarations. Turning to the main problem.... the centerFuelTankLevel is a variable representing the Offset<int> class. That's why ToString() is giving you that class name back. To get the value from the offset you need to use the Value property: this.Text = centerFuelTankLevel.Value.ToString(); Now, this will give you a large number which won't mean much. In the documentation Pete says the value here is scaled like this: So you need to reverse this scaling to get a value that's useful to you. double centerFuelPercent = (double)centerFuelTankLevel.Value / 128d / 65536d * 100d; this.Text = centerFuel.ToString("F0") + "%"; The (double) is a cast to convert the integer to a double so we can do floating point maths on it. The 'd' after the literal numbers is to define these as doubles instead of integers. The "F0" in the ToString() method is to format the number with 0 decimal places. Having said all of that, there is much easier way of working with payloads and fuel in my DLL. You need version 2.4 if you've not already got that. You can get it from the link below. At the bottom of the same thread is example code in C# of reading the fuel tanks with the "PayloadServices". With this method everything is converted to the various units for you (lbs, kg, percentages etc) and you don't need to worry about any conversions or scaling. http://forum.simflight.com/topic/74848-fsuipc-client-dll-for-net-version-24/ You code would become: try { FSUIPCConnection.Open(); } catch (Exception ex) { MessageBox.Show(ex.Message, "FSUIPC Connetion Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } // Get a reference to save so much typing later... PayloadServices ps = FSUIPCConnection.PayloadServices; // Get the latest data from FSUIPC ps.RefreshData(); // Display centre tank percentage this.Text = ps.GetFuelTank(FSFuelTanks.Centre_Main).LevelPercentage.ToString("F0") + "%"; If you need any more help with this let me know. Paul
-
Sorry, posted before it was ready... Correct post below.
-
I've just seen your replies in the main support forum with your PC specs. As you can see they are way better than mine, so there must be something else going on as you've got plenty of horse power and memory. I have no other suggestions though, sorry. Paul
-
Hi Ralph, 1) FSUIPC should be loaded by FSX. If the FSUIPC menu is in the 'Addons' menu in FSX then it's running and the DLL should connect. If you continue to have problems connecting then the text in the message box might help diagnose the problem. 2) Yes, FSX (or WideClient.exe) needs to be running on the same machine. 3) If your PC/Laptop is fast enough and has enough memory it shouldn't be a problem running VS and FSX at the same time. My development laptop is an i7 running at 1.6 ghz and has 8gb of memory and runs both at the same time with no problem (although I have set FSX to low settings - see next paragraph). If your computer doesn't have much memory or has a slow processor then that could be the cause of your problems. You can try to improve things by turning down all the scenery options in FSX to very low settings and avoiding third-party scenery and aircraft. Also running in a very small sized window might help. I see you've got the PMDG 737 in your signature - that will not be helping matters if you have that loaded. Of course if this is essential for your application then there's not much you can do. If you have another PC on your home network that can run Visual Studio then you could invest in Pete's WideFS program. You'll need to buy a licence for WideFS (make sure it's version 7) and register it on the FSX PC. Then on the Visual Studio PC you can run WideClient.exe which is tiny in comparison to FSX. This will act like FSUIPC on the VS pc and will talk to the FSX PC over the network to get all your values, but it hardly uses any resources. So, yes, it sounds like you're doing everything right, it's just that your PC doesn't sound like it's up to the job of running two large programs like FSX and VS2013. Paul
-
You could check the Ground Speed at offset 0x02B4. See the "FSUIPC4 Offset Status.pdf" for details. Paul
-
Hi Tom, Your post appeared eventually - I think it's because new users need their first posts need to be reviewed by a moderator. Even though we dealt with this on PM I'm including my reply here in case anyone else comes across this post who has a similar problem. When using Hexadecimal notation in VB you need to add &H at the start of the number so the compiler knows that you want to use Hex. So in the brackets you need: (&H23A) Note that you can type (&H023A) but the code editor will probably remove the leading 0 to give the above. FSUIPC offsets are always given in Hex, so even if the offset address contains only numbers you still need to prefix with &H. If you don't, it will compile okay but you'll be getting a completely different offset. I notice from your code that you've declared (Dim'ed) the offset inside the Form load event. You should always declare the offsets at the class (form) level. This means they will be accessible from anywhere in the form and will prevent the offsets being created more than once. So your code should look more like this: Imports FSUIPC Public Class Form1 Dim secondfstime as Offset(Of Byte) = New FSUIPC.Offset(Of Byte)(&H23A) ' Other offsets go here Public Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load FSUIPCConnection.Open() End Sub End Class Paul
-
Hi Lukas, It's not enough to run the .exe located in the FSX folder, you also need to set the 'start' folder for your new process to the FSX folder. How you do that will be specific to your programming language and method of running an external program. There will be some parameter or property that you can set. If you can't find out how to do this I would suggest mentioning the programming language you are using or posting the code that doesn't work. Someone who knows that language will then be able to help further. Pete will pick up your other question on his return. Paul
-
Hi Manfred, The METAR strings are returned directly from the SimConnect interface (via FSUIPC). These contain extended data used by SimConnect in addition to the standard METAR codes. The extensions tend to start with &. &D920NG means the (D)epth (height) of the wind layer is 920 metres, the turbulence is (N)one, and wind shear is (G)radual. The &A is for winds above the surface layer and specifies the altitude in metres (in your example 1539m), The official specification of the SimConnect METAR string can be found here: http://msdn.microsoft.com/en-gb/library/cc526983.aspx#Metar_Data_Format If you want a clean, standard METAR string then you can either build one from the SimConnect METAR, or create your own from the information in the FsWeather object e.g.: FsWeather weather = ws.GetWeatherAtLocation(IACO); Paul
-
Converting nm to FS Format
Paul Henty replied to xxallrounderxx's topic in FSUIPC Support Pete Dowson Modules
The runway heading you used (161) seems to be the Magnetic heading. You need to use True headings when working with Lon/Lat positions. The True heading of this runway is about 164. If you don't have the true headings for the runways you can derive them from the magnetic headings by adding the magnetic variation. This can be found is offset 02A0, but only gives the value for the current position of the player. Paul -
Converting nm to FS Format
Paul Henty replied to xxallrounderxx's topic in FSUIPC Support Pete Dowson Modules
Pete's away at the moment so I'll tell you how I did this in my .NET Client DLL for FSUIPC. It has a helper class for calculating the very thing you describe. I assume you're not using .NET and so can't use these facilities, so here's what's 'under the hood': What I suggest is not converting the NM distances into FS Units, but rather use them to calculate new Lon/Lat positions, then convert these to FS Units in the normal way. Converting Lon/Lat to FS Units for 0560 and 0568 is well documented and fairly easy. Trying to convert NM distances into these units is not documented and more difficult. Adding/subtracting NM distances to Lon/Lat coordinates is easy for Latitude and a bit more cumbersome for Longitude. The following calculations all assume the Lon/Lat is in pure degrees and fractions of a degree (e.g. you're working with a value of 50.5 degrees representing 50 Degrees 30 Minutes) Latitude: 1 Nautical Mile = 1/60th of 1 degree of Latitude, or 1 Degree of Latitude = 60 NM. Therefore the number of degrees (or fraction of degrees) to add for distance d in NM = d / 60. e.g. Adding 30NM to latitude 50.454: 50.454 + (30 / 60) = 50.954 Longitude: A bit more tricky because the length of 1 degree of longitude varies depending on the latitude because the circles of longitude are smaller towards the pole than at the equator. The first step is to figure out the length of a degree of longitude at the latitude of the point. This is given by: cosine(latitude) * circumference of FS equator / 360 The circumference of the FS Equator is 40,075km = 21,638.7689 NM So at 49.882 degrees latitude, one degree of longitude (in FS at least) is: cos(49.882) * 21638.7689 / 360 = 38.73 NM (Assume the cos function above takes degrees to keep this simple. Most programming languages have trig functions that take radians). The next step is to calculate the number of degrees of longitude to add for the given distance (same as latitude but using the value from step 1 instead of the fixed 60 value) e.g. Adding 30mn to 2.33 degrees longitude at latitude 49.882: 2.33 + (30 / 38.73) = 3.10 Once you have the new Lon/Lat you can just do the normal conversion to FS units to write to the offsets you mentioned. Paul Nothing in this post should be used for real-world navigation :smile: