Jump to content
The simFlight Network Forums

Paul Henty

Members
  • Posts

    1,652
  • Joined

  • Days Won

    74

Everything posted by Paul Henty

  1. You need to call Start() sometime after Init(). Sorry, I completely left that out of the other post. I'll go and fix it now. If you're using LVars as well then you'll also need to call RefreshData() periodically to get the latest values. Paul
  2. Hi Matt, The new beta version of my DLL is now available with support for LVars and HVars in MSFS via John's WASM Module. It's on NuGet (3.2.1-Beta) (remember to tick the box to 'include pre-release'.) Documentation is here: Paul
  3. Hi, The beta is now available on NuGet (3.2.1-Beta) (remember to tick the box to 'include pre-release'. Documentation is here: https://forum.simflight.com/topic/92372-added-support-for-lvarshvars-access-in-msfs-via-john-dowsons-wasm-module/ Paul
  4. MSFSVariableServices Background A new class called MSFSVariableServices has been added to the FSUIPCClient dll from Version 3.2.1-Beta. This module allows direct access to LVars and HVars for MSFS. Other Flight Sims (e.g. P3D) are NOT supported. It uses John Dowson's WASM module for MSFS which must be installed in your MSFS and will also need to be installed in your users' MSFS. This module is installed by the FSUIPC7 installer. This facility is completely independent of FSUIPC. When using this feature in the FSUIPCClient dll you will not need a connection to FSUIPC. It works separately. Note that the FSUIPCConnection.ReadLVar() and WriteLVar() methods still use the legacy LVAR access provided by Offset 0x0D70. You can still use these, however this method of LVAR access has historically been slow (read one variable per Process()) and will continue to be. The new MSFSVariableServices offers significant performance advantages. Requirements As the developer you will also need John's FSUIPC_WAPID.dll. This can be found in latest the WASM package which can be downloaded from the "Additional Free Software" section of the FSUIPC website: (Look for "FSUIPC WASM Module x.x.x") http://www.fsuipc.com/ Inside the Zip file, the DLL can be found in \FSUIPC_WAPI\dll This dll must be distributed with your application and should be located in the same folder as your .exe and FSUIPCClient.dll. In Visual Studio you can add this DLL to your project as a normal project item and set the property "Copy to Output Directory" to "Copy if Newer". You CANNOT add this dll as a reference to your project as it's an unmanged C-style DLL. 64Bit Only The WAPI DLL is 64 bit so you must run your .NET application as 64-bit. This means the 'Platform Target' must be x64, not x86. You can also target 'Any CPU' but you must untick the box that says "Prefer 32-bit". These options can be found in the project properties page on the Build tab. (Right-Click the project in the solution explorer and select Properties). Example Code: An example project (C# and VB.NET) can be downloaded from the FSUIPCClient DLL website: http://fsuipc.paulhenty.com/#downloads How to Use: The MSFSVaraibleServices is a static class in the FSUIPC namespace. You need to add a using statement for the namespace: using FSUIPC; If you don't want to use the full class name you can optionally add an alias: using VS = FSUIPC.MSFSVariableServices; The rest of the code examples here use this alias. Events: This module is purely event-driven. The following events should be handled: OnValuesChanged will notify you when any of the LVar values in the sim change. VS.OnValuesChanged += VS_OnValuesChanged; private void VS_OnValuesChanged(object sender, EventArgs e) { // At least one LVar value has changed. // Do work with new values. For examples see later in this post } OnVariableListChanged will notify you when the WASM module has discovered new LVars and HVars. VS.OnVariableListChanged += VS_VariableListChanged ; private void VS_VariableListChanged (object sender, EventArgs e) { // Variables have been discovered or changed } OnLogEntryReceived. This event will notify you of log entries being produced by the WASM module. This will give you status updates, errors etc. What you do with the messages is up to you. In the example below I'm writing the log entries to a listbox, but you could show them in the Debug output window or write to your own log. VS.OnLogEntryReceived += VS_OnLogEntryReceived; private void VS_OnLogEntryReceived(object sender, LogEventArgs e) { this.lstLog.Items.Add(e.LogEntry); } Initialisation: After setting up your events, you need to call Init(). This will attempt a connection to the flight sim via SimConnect. The result of this will be returned as a log entry. You need to pass in the handle of the main window in your application: e.g: Assuming the code is in the code behind the main form/window: WinForms: VS.Init(this.Handle); WPF: VS.Init(new WindowInteropHelper(this).Handle); Configuration: There are a number of properties to control how the module behaves. The default values for these properties are good for most cases. VS.LogLevel Defines what kinds of events (if any) are logged via the logging system. Values can be: DISABLE_LOG LOG_LEVEL_INFO LOG_LEVEL_BUFFER LOG_LEVEL_DEBUG LOG_LEVEL_TRACE ENABLE_LOG VS.SimConfigConnection By default the MSFSVariableServices will connect to the local instance of SimConnect. If you have other instances configured on your machine (e.g. connections to remote PCs running MSFS) you can change this property to use them. Starting the module: After initializing and setting your configuration, you must then call Start() to tell the WASM module to start receiving data. VS.Start(); NOTE: After calling Start() it will take the WASM module a few seconds to collect the data from the flight sim and do its housekeeping. This means that LVars and HVars may not be instantly available. It's best to wait until the OnVariableListChanged event has fired before reading LVars. If you ever want to pause the data transfer you can call VS.Stop(); No more data updates will be received by the WASM module until you call Start() again. Accessing LVars: The module automatically discovers the loaded LVars. These are located in the LVars property and are stored as a collection of FsLVar objects. You can access the individual FsLVar objects like this: 1. Iterate through all of them: foreach (FsLVar lvar in VS.LVars) { // Do something with each LVar... e.g. CheckLVar(lvar); } 2. Get a specific LVar by name: FsLVar myLVar = VS.LVars["B747_8_MFD_Range"]; Getting names of all LVars You can find a List<string> of all known LVar names at: VS.LVars.Names Checking if LVars exist To find if an LVar exists by Name use: if (VS.LVars.Exists("B747_8_MFD_Range")) { // Exists } Counting number of LVars You can get the number of LVars with: VA.LVars.Count Accessing HVars HVars are stored as a collection in the property VS.HVars This collection works in exactly the same way as LVars above. Using the LVar values: Each FsLVar object has a Value property. This is a double type as all LVars are stored as doubles within the Flight Sim. e.g. To get the value for B747_8_MFD_Range use: double range = VS.LVars["B747_8_MFD_Range"].Value; Advanced use: You can also keep a reference to the LVar FsLVar mfdRange = VS.LVars["B747_8_MFD_Range"]; double range = mfdRange.Value; Updating the LVar values: To write a new value for an LVar call the SetValue() method. This will sent the new value to be written to the Flight Sim. e.g. VS.LVars["B747_8_MFD_Range"].SetValue(2); NOTE: This will NOT update the local Value property of the FsLVar. It only sends a request to the Sim to change the value. The local Value property will be updated when the Sim sends back the new value. The OnValueChanged event will also fire at this time. Setting HVars: To set an HVar, call the Set() method of the FsHVar object: VS.HVars["AS1000_PFD_NAV_Switch"].Set(); This will cause the new HVar to be set in the Flight Sim immediately. Checking for changes in LVars: There are a number of ways to know if LVar values have changed: 1. Check the ValueChanged property of the FsLVar object: if (VS.LVars["B747_8_MFD_Range"].ValueChanged) { // do something with new range value } 2. Get a collection of all the changed LVars from the LVarsChanged property: foreach (FsLVar lvar in VS.LVarsChanged) { // Do something with each changed LVar... e.g. NotifyChangesTo(lvar); } Note that the LVarChanged collection works the same way as the normal LVars collection. 3. You can handle the OnValueChanged event of an FsLVar: e.g. to be notified of changed to B747_8_MFD_Range: VS.LVars["B747_8_MFD_Range"].OnValueChanged += MFDRange_OnValueChanged; private void MFDRange_OnValueChanged(object sender, LVarEvent e) { double newSetting = e.LVar.Value; MessageBox.Show("MFD Range Changed to " + newSetting.ToString()); } Logging LVars and HVars: List of LVars and HVars can sent to the log by calling: VS.LogLVars(); VS.LogHVars(); Creating a new LVar: Call CreateNewLVar passing in the name of the new LVar and its initial value. VS.CreateLVar("My_New_LVar", 1.25); Executing Calculator Code: VS.ExecuteCalculatorCode(myCode); where myCode is a string containing the code to execute. Paul
  5. I've had a quick look at John's WASM C DLL and have successfully connected to it from my .net DLL. Over the next few days I will add a proper module to my dll that will (hopefully) allow fast access to LVars and HVars. The only potential problem is that I don't have MSFS so I can't test or debug anything here. I'll post here again when a beta is ready for testing. Paul
  6. Hi, The basic use of the airports database is covered in the example code application. The examples below for the ILS info assume you already have an FsAirport object. I've used EGLL: // Get airport info for EGLL FsAirport egll = db.Airports["EGLL"]; Example 1: Getting all runways at the airport with ILS info and displaying the ILS details in a listbox: // Clear any ILS info in the listbox this.lstILS.Items.Clear(); // Go through each runway and find those with ILS info foreach (FsRunway rw in egll.Runways) { if (rw.ILSInfo != null) { // This runway has ILS Data - Show it in the list box string ilsInfo = "Runway " + rw.ID + " | Freq: " + rw.ILSInfo.Frequency + " | Hdg: " + rw.ILSInfo.Heading.ToString("F0"); this.lstILS.Items.Add(ilsInfo); } } Example 2: Getting ILS info for a specific runway at the airport: string runwayID = "27L"; FsRunway rw = egll.Runways[runwayID]; if (rw != null) { if (rw.ILSInfo != null) { string ilsInfo = "Runway " + runwayID + " | Freq: " + rw.ILSInfo.Frequency + " | Hdg: " + rw.ILSInfo.Heading.ToString("F0"); MessageBox.Show(ilsInfo); } else { MessageBox.Show("Runway " + runwayID + " has no ILS"); } } The FsILSInfo class has a few other properties: http://fsuipc.paulhenty.com/Reference/html/classFSUIPC_1_1FsILSInfo.html Paul
  7. Hi Peter, Correct. It's only for the local PC. If you want it running over WideFS then getting the info from the ini or (as Pete suggested) the log file would be better. You'll need the user to setup windows file sharing though. They aren't no.. Lua is just a programming language and you're just using a Lua library to talk to your HID devices. There are .NET libraries available for talking to hid devices. I've never done this myself so I can't recommend any, or tell you how easy/difficult it is. One other thought comes to mind... You already have Lua plugins that handle the Joystick/LED stuff. Are you trying to replace these with your C# program, or do you intend having a Lua component to your application? If you're going to have both, then you could set up communication between your Lua plugin and your C# program. The easiest way would be via the user offsets. This would then run over WideFS without problems as the Joystick/HID code is all on the FS PC (in LUA). You could have the LUA plugin give information to the C# program and have the C# program tell the LUA program to light LEDs etc. (Your users would need a registered version of the FSUIPC to run the LUA part). If you're intending to replace the Lua code with C# then you'll need to replicate everything you do in Lua in C#. My DLL will only handle reading/writing offsets and LVars. For everything else you'll need to find other .NET libraries that handle the particular task. Paul
  8. Hi Peter, Unfortunately the DLL does not have that feature. There's no way to get the joystick names from the IPC interface. Two ideas you can look into: 1. Have your program read the user's FSUIPCx.ini file. There are lines there detailing what the joystick numbers are: e.g. [JoyNames] AutoAssignLetters=No 0=Controller (Xbox One For Windows) 0.GUID={363210E0-98B7-11EB-8001-444553540000} 2. Use a .net library that lets you talk to the Windows Direct Input API to enumerate the plugged-in joysticks on the user's computer. I'm pretty sure that's how FSUIPC gets the joystick numbers. This is an example using the SharpDX.DirectInput library, available as a NuGet package: private void button1_Click(object sender, EventArgs e) { this.listBox1.Items.Clear(); DirectInput di = new DirectInput(); IList<DeviceInstance> devices = di.GetDevices(DeviceClass.GameControl, DeviceEnumerationFlags.AttachedOnly); for (int i = 0; i < devices.Count; i++) { DeviceInstance device = devices[i]; this.listBox1.Items.Add(i.ToString() + " = " + device.InstanceName + " | GUID=" + device.InstanceGuid.ToString()); } } Paul
  9. Hi, Most of these feature are not simulated by P3D. This means there are no offsets for them. I can suggest trying the following however: Instruments switch - usually the 'Master Avionics' at 0x2E80 Master Ignition Switch - Maybe 0x3B00 General Engine 1 Starter , or, 0x0892 Engine 1 Magneto Switch Position The features you listed are being simulated within the aircraft's code. They might be available to you in two ways: 1. The author of the plane might be using custom controls, or redundant controls (e.g. helicopter/turboprop controls). 2. The author might be storing the values for these features in local panel variables (LVARs). There is no guarantee that the author has used these two methods. They might be completely inaccessible to you. Here is how you can find out what is available: Events/Controls These can be found by using the logging facilities in FSUIPC. Select the Logging tab in FSUIPC and check the box for Events (non-axis controls). Also check the box to "Send to console window". Then operate the control in the aircraft (e.g. Inverter Switch). If it uses an event its number will be logged in the console window. You can use via the DLL (FSUIPCConnection.SendControlToFS()), but only for control - you can't 'listen' for these events. LVARS (Local Panel Variables) Many aircraft store data in local panel variables. To see what it available for your aircraft: Go to FSUIPC and assign a key press or joystick button to the control "List Local Panel Vars". Make sure the console logging is enabled (see above), go back to the aircraft and press the button/key you just mapped. A list of LVAR names will be listed in the console. If any look useful you can use these from the DLL. (See FSUIPCConnection.ReadLVAR() and FSUIPCConnection.WriteLVAR() ) Paul
  10. Just an update - John posted today that he's got LVARs working in FSUIPC7: Paul
  11. Hi Neil, It's FSUIPC unfortunately. The LVAR support only has a single offset where you can request an LVAR (0x0D70), so that's where the limitation comes from. Internally, FSUIPC6 and previous versions, call into the Flight Sim Panels dll which would be very fast at getting and setting LVARs. I suspect SPAD is doing the same thing. C++ programmers can use this tequnique via SimConnect, but it doubt it can be done from managed code. Sticking with FSUIPC6 and previous, it's possible to read/write LVARs values in LUA plugins. This would be fast as this doesn't need to go through the IPC (offsets) interface. The LUA plugin would then copy the values into user offsets and then your program would read the values from the offsets. For large numbers of LVARs this would be much faster. BUT there are some disadvantages to this method: You or your users would need to maintain the LUA plugin LUA Plugins only work on the registered version of FSUIPC In FSUIPC7 (MSFS 2020) things are slightly different. John has written a plugin for MSFS that allows users to read/write LVARS outside of FSUIPC. At the moment though it's only available to C++ users. I'm hoping John and I can get it working from managed code but there's no guarantee at the moment. Paul
  12. Compared to reading offsets, yes. Every LVAR read or write takes one Process() call. Usually around of 10ms. Whereas you can read many offsets in a single process call. There's no problem with a few LVARs per second. Depending on the PC, and what else is running using SimConnect/FSUIPC, I would think you can easily read about 50 per second without problems or running out of time. That's strange. I don't have P3D so I can't test that here. I might be worth asking the John Dowson about this in the main support forum. Yes there are two offsets you can look at: 0x3364: Ready to Fly. (1 Byte). Look for it to be Zero when the sim has finished loading and the flight has started. 0x3365: In Menu or Dialog. (1 byte). Again, look for this to Zero when not in a menu. These offsets work a little differently in each type of sim (FSX/P3D etc.) so you might need to experiment a bit. Paul
  13. The problem is probably with MSFS or the way the A320 is programmed. Even though you have set standard pressure, the code in the aircraft doesn't light the indicator. The RPN script seems to be using local panel variables (LVARs) to force the indicator on. I can't understand the syntax of the script but it seems like L:XMLVAR_Baro1_ForcedToSTD is being used to light the indicator. Unfortunately LVARs are not yet available in FSUIPC when using MSFS (both are still in development). When they are implemented you will likely be able to light the indicator by writing the correct value to the LVARs. Use FSUIPCConnection.ReadLVAR() and FSUIPCConnection.WriteLVAR(). Paul
  14. That was easier than I thought it would be. Version 3.2.0 BETA is now on Nuget. (Tick the box for 'Include Prerelease' to see it. The Nuget package now contains two version, one for .NET 5 (net50-windows) and one for .NET 4.0 Framework as normal. They are both compiled from the same source code, so they will be functionally identical. The package manager in Visual Studio will install the correct version for your project. I've given it a good test under .NET 5 with my Example Code Application and all seems well. Paul
  15. The radar altimeter is in offset 0x31E4. It does have a height limit, above which it stops working. If you need higher altitudes AGL you'll need to stick with the formula that you are currently using. Paul
  16. Ahh, I understand now. I've had a look and I've no plans to do this at the moment. John says he's going to build this into FSUIPC7. When he does I'll see what that means. If LVars become accessible via the normal IPC interface then I won't need to do anything. If this provides a faster way to access LVars than the current IPC method (one LVAR per Process()) then I'll look at adding support for it then. Paul
  17. What kind of support are you thinking about? If you mean referencing the DLL from a WASM application and having it run on the browser then I don't think that's possible. Communication with FSUIPC is done via Windows messaging using the Win32 API. I'm pretty sure that can't be accessed from code running in a browser. You can use the DLL on the server side with an ASP.NET application. Not sure about the new Blazor server apps. Let me know if you had something else in mind. If you want real-time access to FSUIPC data from Javascript or WASM applications you can use my WebSocket server. This runs on the FlightSim computer and allows the browser to request and receive real-time updates over a WebSocket. http://fsuipcwebsockets.paulhenty.com/ Paul
  18. Hi Neil, It looks to be possible. I've got the DLL compiling here against net5.0-windows. It does use some WinForms classes to make some of the helper objects (e.g. Airports) show up in the PropertyGrid properly, so I can't build it against the basic net5.0 without removing those features. (Same goes for Standard). I think this is okay as FSUIPC only runs on Windows anyway, so there's no real point in forcing the DLL to be cross-platform. I'll need to give it a good test and then sort out the NuGet package to include both the net40 and net5.0 versions. If all goes well, I expect to release it by next weekend. Paul
  19. Hi Nach, You can just the the helper method below. This uses offset 0x3110 behind the scenes but is easier to use: FSUIPCConnection.SendControlToFS(c,p) where c is the control number and p is the parameter value you want to write to that control. If the control doesn't need a parameter just pass 0. Paul
  20. Dim points As FsLatLonPoint() = { New FsLatLonPoint(51.828207, -2.669643), New FsLatLonPoint(51.823186, -2.654353), New FsLatLonPoint(51.827549, -2.646808), New FsLatLonPoint(51.836629, -2.638694), New FsLatLonPoint(51.796211, -2.663467), New FsLatLonPoint(51.801533, -2.68468), New FsLatLonPoint(51.812531, -2.68296), New FsLatLonPoint(51.828207, -2.669643) } Dim myPolygon As FsLatLonPolygon = New FsLatLonPolygon(points) Paul
  21. The constructor takes in an array of FsLatLonPoint that define the points (vertices) of a closed polygon. There can be any number of points. The polygon can be convex, concave or complex (having self-intersecting sides). Here is an example I used to test the class. I just supply hard-coded points of the outline of London: (I've removed lots of points in the middle for this example): FsLatLonPoint[] points = new FsLatLonPoint[] { new FsLatLonPoint(51.828207,-2.669643), new FsLatLonPoint(51.823186,-2.654353), new FsLatLonPoint(51.827549,-2.646808), new FsLatLonPoint(51.836629,-2.638694), // Points removed new FsLatLonPoint(51.796211,-2.663467), new FsLatLonPoint(51.801533,-2.68468), new FsLatLonPoint(51.812531,-2.68296), new FsLatLonPoint(51.828207,-2.669643) }; FsLatLonPolygon myPolygon = new FsLatLonPolygon(points); Normally you would get the points from a database or mapping service, so you would need to read the points and create the array of FsLatLonPoint[] in code. If you need more specific help, let me know how you're getting the polygon point data and what format the data is in. I can then explain how to convert them to the point array. Paul
  22. Hi James, The FsFrequency classes are helpers to use the legacy frequency offsets stored in binary-coded decimal format (FSUIPC3/4). These only needed 2 decimals so that's all they can return. The offsets starting at 0x05C4 store the frequency as a normal 32bit int value and therefore will report the 8.33hz spacing properly. As these offsets use normal values there is no need to use the FsFrequency helper classes. Paul
  23. Hi Alex, With the PMDG aircraft (and maybe Aerosoft as well), the developers keep track of the fuel in their own code. This is to more accurately simulate fuel flow. They are constantly overwriting the FSX fuel levels with the levels produced from their own fuel simulation. Therefore whatever you write into the fuel offsets gets overwritten. This also happens if you use the FSX fuel menu. Unfortunately, there is no way around this that I know of. Paul
  24. You can just cast it to an int. It'll be the same bit pattern as the uint when it gets to FSUIPC: Declared as uint... private readonly uint MOUSE_FLAG_RIGHTSINGLE = 0x80000000; Cast to int for the SendControlToFS method... FSUIPCConnection.SendControlToFS(PMDG_737_NGX_Control.EVT_MCP_CMD_A_SWITCH, (int)MOUSE_FLAG_RIGHTSINGLE); Paul
  25. Hi, Sorry I missed your questions. If you find you need delays between the keypresses then Thread.Sleep is the only way I can think of. If you're running this on the main User Interface thread (e.g. inside your main form) then it will cause your application to stop responding while it's sleeping. If that's a problem you can run the keypress code on a background thread. Your code will still pause, but the User Interface will not lock up. The easiest way to do this is to use Tasks: 1. Put your key press code in its own method: private void SelectGSXMenu() { FSUIPCConnection.SendKeyToFS(Keys.F12, SendModifierKeys.Control, null); Thread.Sleep(500); FSUIPCConnection.SendKeyToFS(Keys.F1, SendModifierKeys.None, null); Thread.Sleep(500); FSUIPCConnection.SendKeyToFS(Keys.F1, SendModifierKeys.None, null); Thread.Sleep(500); } 2. Mark your Timer method with the async keyword: e.g.: private async void timer1_Tick(object sender, EventArgs e) 3. When you need to make the menu selection inside the timer use this syntax to call the new method on a background thread: await Task.Run(() => SelectGSXMenu()); It will still take 1.5 seconds to do the keypresses, but your application will not lock up. If your program logic doesn't need to wait for the menu selection to complete, you can remove the async and await keywords. The menu selection will then be done in the background while your main timer continues. Paul
×
×
  • 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.