Jump to content
The simFlight Network Forums

Paul Henty

  • Content count

  • Joined

  • Last visited

  • Days Won


Paul Henty last won the day on May 6

Paul Henty had the most liked content!

Community Reputation

46 Excellent


About Paul Henty

  • Rank
    Advanced Member
  • Birthday 01/01/1970

Profile Information

  • Gender
  • Location
    Bristol, UK

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Paul Henty

    Hep with EVENTs

    No, that's not how the events work. When the event.timer() line is reached the script does not start the timer and wait until it stops. The timer is started and then the script continues to execute. So your current script does this: 1. Creates a function in memory called checkAlive(). 2. Starts a timer that calls that function every 500ms. 3. Creates a function called checkIAS() 4. Reprograms the timer to call checkIAS() every 500ms. 5. Creates a function called checkRALT() 6. Reprograms the timer to call checkRALT() every 500ms Note that all of this happens in a few milliseconds, before the timer has ticked for the first time. Because there is only 1 timer per script. The script does stop at each timer line. It carries on and overwrites the previous timer settings. Yes because the function (e.g. checkAlive()) is called every 500ms and the conditions that play the sound still exist 500ms later. In that case of checkAlive you are looking for IAS >= 25 kts. You play the sound at 25kts, but 500ms later the IAS is still >= 25kts so it plays it again. It will play every 500ms until the IAS comes below 25kts. Stopping the timer was a good way of preventing this when you were only doing one thing with the timer. Now you want to do many things with the timer you can't just stop the timer after the first thing happens. You need to keep track of this yourself. You need to setup some boolean variables (true/false) so that you know what checklist items have been done and which haven't. I show this later... doChecks() was just an example name off the top of my head. The idea is this: 1. Create a single function that you can call with your timer. I came up with the name doChecks(). 2. That function will check every item in your list that hasn't already been done. 3. You could put all the code in the one function but it might get very long. It's better to break them out into a function for each check (as you have now) and have doCheck() call each one in turn. (If it needs calling). 4. You must keep track of what's been done and what hasn't. Here is some code that would be the sort of thing you would do. I don't use LUA so this might not be 100% working, correct LUA, but it shows the basic plan. I've included the three checks you've given but you can hopefully see the logic and how you would expand this basic structure to add other items. local airspeedAliveCalled = false local rotateCalled = false local gearUpCalled = false function checkAlive() ias = ipc.readUD(0X02BC)/128 ipc.lineDisplay("Airspeed="..ias) if ias >= 25 then sound.play("F:\\FSX\\Sound\\wavefiles\\senecaII\\Airspeed alive.wav") ipc.lineDisplay("Airspeed alive") airspeedAliveCalled = true end end function checkIAS() ias = ipc.readUD(0X02BC)/128 ipc.lineDisplay("Airspeed= "..ias) if ias >= 60 then sound.play("F:\\FSX\\Sound\\wavefiles\\senecaII\\70 knots rotate.wav") ipc.lineDisplay("Rotate") rotateCalled = true end end function checkRALT() radio_alt = (3.281/65536)*ipc.readUD (0x31E4) radio_alt = math.floor(radio_alt + 0.5) ipc.lineDisplay("AGL= "..radio_alt) if radio_alt >= 200 then sound.play("F:\\FSX\\Sound\\wavefiles\\senecaII\\Positive climb rate gear up.wav") ipc.lineDisplay("Positive climb rate") gearUpCalled = true end end function doChecks() if not airspeedAliveCalled then checkAlive() elseif not rotateCalled then checkIAS() elseif not gearUpCalled then checkRALT() end end -- Only 1 timer! event.timer(500, "doChecks") Paul
  2. Paul Henty

    Hep with EVENTs

    From the lua docs on event.timer: So you must either: 1. Break these out into three separate plugins or 2. setup one timer to call a single function e.g. "doChecks()" and either put all the checks in there, or have it call each of your functions in turn. For 2 however, you can't just cancel the event when the action is done. You'll need to setup variables (true/false) to know when each action has completed, has check those each time. Paul
  3. Paul Henty

    ERROR #15

    Yes there was. One of the internal offsets wasn't getting removed. Thanks for the report. I've just uploaded 3.1.5 to NuGet which should fix this. Paul
  4. Paul Henty

    Object placing by code in sim

    It's not possible with FSUIPC and so it's not possible with my DLL either. It might be possible using SimConnect but I don't know much about that. It might also depend on the sim you are using. e.g. P3D has many more SimConnect features than FSX. You mentioned VB which is not the best language to use for SimConnect. There are wrappers for .NET but all the documentation is in C# and even that is very poor. If you don't get any other responses here, you could try asking in SimConnect forums or P3D developer forums, or maybe Scenery Developer forums. People there will have more knowledge of what is possible for scenery objects. Paul
  5. Paul Henty

    Offset pmdg

    You're welcome. Looks great!
  6. Paul Henty

    Offset pmdg

    The new version is now live on NuGet. It's 3.1.4-beta so you'll need to make sure you have "Include Prerelease" checked. To access the screen data for a CDU, declare an instance of PMDG_NGX_CDU_Screen: ' Declare a PMDG_NGX_CDU_Screen variable for the CDU ' Pass the base offset address to the contructor Private cdu0 As PMDG_NGX_CDU_Screen = New PMDG_NGX_CDU_Screen(&H5400) This example code shows a number of different ways to access the text and other info: Private Sub CDUExampleCode() ' Call RefreshData to get the latest screen contents ' (Connection must already be open) cdu0.RefreshData() ' Use Powered property to know if CDU is on If (cdu0.Powered) Then ' Use the ToString() method to get a string of the whole screen. ' Use the optional overload to pass a dilimiter for the rows. ' E.g. Here we pass CRLF so we can display the screen in a text box: ' (Use a fixed size font like 'Consolas' or 'Courier New') Me.txtCDU.Text = cdu0.ToString(vbCrLf) Else Me.txtCDU.Text = "No Power" End If ' To get a single row of text use the Rows array: ' e.g. Row 3 (Index 2 - Arrays are 0 based) Dim row3Text As String = cdu0.Rows(2).ToString() ' To get a the data in single cell of the CDU use the Cells array on the row ' e.g. Row 3 (Index 2), First Character (Index 0): Dim R3C1Char As Char = cdu0.Rows(2).Cells(0).Symbol ' Or as a string: Dim R3C1String As String = cdu0.Rows(2).Cells(0).ToString() ' You can also find other data about the cell: Dim R3C1Colour As PMDG_NGX_CDU_COLOR = cdu0.Rows(2).Cells(0).Color Dim R3C1Flags As PMDG_NGX_CDU_FLAG = cdu0.Rows(2).Cells(0).Flags ' To avoid accessing the row everytime, you can hold a reference to the row: Dim row3 As PMDG_NGX_CDU_Row = cdu0.Rows(2) ' The same for cells: Dim R3C1Cell As PMDG_NGX_CDU_Cell = cdu0.Rows(2).Cells(0) ' Example of iterating through all rows: For Each row As PMDG_NGX_CDU_Row In cdu0.Rows Dim rowText As String = row.ToString() ' do more work Next ' Example of iterating through all cells in a row: For Each cell As PMDG_NGX_CDU_Cell In row3.Cells Dim cellChar As Char = cell.Symbol ' do more work Next End Sub Let me know if you need any more help with this, or if there are any problems. Paul
  7. Paul Henty

    Offset pmdg

    Are you using version 3 of the DLL with NuGet? If so, I'm adding support for the PMDG CDUs in the DLL. They are a bit complicated to use because of the way the the data is stored (3 bytes per character). The dll will simplify things and give you a nice .net array for the cells. I'll let you know when it's released (probably late tonight or tomorrow), but you'll need to be getting the dll from NuGet. Paul
  8. Paul Henty

    FSUIPCConnection.Process() Error

    Hi Dirk, Thanks for reporting this. It's now fixed. Please use Nuget to update to the latest version of the DLL (3.1.3). Paul
  9. Paul Henty

    Axis For Throttle Etc

    Hi Padraig, The basic process is that you need to read the pot position (value) and then write to one of the FSUIPC offsets that controls an axis. For example the axis for throttle 1 is offset 0x088C (as described in the FSUIPC documentation). This particular offset expects the values from –4096 (full reverse) to +16384 (full throttle) with 0 being idle. You'll need to translate the values from your pot to cover the range required by FSUIPC. For example assuming there is no reverse and 107 is idle and 198 is full then you'd need: value for fsuipc = (value from pot - 107) / (198-107) * 16384 If you are new to using my DLL in VB.NET there is a beginner's guide video linked on the website (in the help section). This will tell you everything you need to know to get started including where to find the documentation you'll need. Please also look at the Example Code Application as that will show you the basics of how to read and write to FSUIPC offsets. http://fsuipc.paulhenty.com Feel free to post back here if you need any more help with this. Paul
  10. You can also set/get the FSUIPCConnection.LocalDateTime property. This is the local time according to the location of the plane in the SIM, not where the user's PC is located. This might be of use to you if you're working with local times. Paul
  11. Hi Dirk, Are you sure that writing to 0248 changes the season in p3D? It doesn't in FSX and is marked as read-only in the FSUIPC Offsets List. The MoveAircraft() method uses offset 0558, which uses a special feature of SimConnect to move the aircraft. This feature doesn't include the season or date time so there's no way I can include it. I have experimented with this in FSX (I don't have p3d) and found that writing a new datetime and then calling MoveAircraft() only does one scenery refresh. Normally either of these would reload the scenery. But calling them one after the other doesn't do two loads. It seems to abort the first load when starting the second. Here is the code I used: (I used the snapshot overload but it uses the same code. I had to change the season by setting a new date as 0248 is read-only (at least in FSX): FSUIPCConnection.UTCDateTime = dateTimeSave; FSUIPCConnection.MoveAircraft(posSave, false); So I think you can achieve what you want by using this method. Alternatively if you want to use this code (assuming it works in P3D): //set the time/season this.hour.Value = Convert.ToByte(iHour); this.season.Value = 0; sendControl.Value = REFRESH_SCENERY; FSUIPCConnection.Process(); ... you can try not refreshing the scenery here. Just call MoveAircraft() after this and let that reload the scenery. e.g.: //set the time/season this.hour.Value = Convert.ToByte(iHour); this.season.Value = 0; FSUIPCConnection.MoveAircraft(.......); Let me know if these ideas don't work, or don't do what you want, and I'll look into it some more. Paul
  12. Paul Henty

    Runtime Offsets with type

    Hi Brad, In C#, the <T> syntax is information for the compiler at compile-time. This means you can't use variables for 'T' because the compiler won't know what the type is. So, the only way to use this syntax is a switch statement with the correct type 'hard-coded': Here's a simple example using a string to hold the type: (Could also be an enum you have created) string variableType = "Int32"; switch (variableType) { case "Int32": int valueInt = myOffset.GetValue<int>(); break; case "Double": double valueDbl = myOffset.GetValue<double>(); break; } Note that the return types are strongly typed. If you need to process these values later, you might consider casting all the values up to 'double's for easier use. (i.e. all the values will be of one type (double)). But this will depend on what your application does with the values. There is another syntax that does take a variable to specify the type: Type variableType = typeof(int); object myValue = myOffset.GetValue(variableType); However, at some point you'll need a switch with this method to generate the real type from the enum or string that you use to hold the offset type. Also note that this method returns an object so you'll also need a switch to cast to the underlying type (unless you're just going to call ToString() on the values). Which method is best comes down to your personal preference and how your application uses the offset values. But I think it's likely that you'll need a switch statement somewhere. It's just down to C# being a type-safe language. Paul
  13. Paul Henty

    Problem with LVARS

    Hi George, I don't know of any issues with the LVAR read/write functionality. I've just tried it here with the example app connected to FSX:SE and it works fine. It read the throttle position and I was able to control the range and mode. What version/type of flight sim are you using? When you say it fails to read them, do you mean the values are 0 or is there an error of some kind? Make sure you have the latest FSUIPC installed (see the downloads section on Pete's main forum), and the latest version of my DLL (3.1.1). Paul
  14. 10 seconds is a long time to read that file. If you are using my .NET Client DLL see the latest version (3.1) post in my sub forum. If you use the new AirportsDatabase feature it will save you a lot of coding and loading the database into memory takes about 2 seconds. The database it just a collection in memory, so if you need to get it into a dataset you'll have to transfer the data from the AirportsDatabase with your own code. If you're not using my DLL, here's the testing I did for the different ways of reading the runways.xml File: XMLTextReader: 24490 Airports in 674 ms XDocument: 24490 Airports in 1,254 ms XMLDocument: 24490 Airports in 16,275 ms Manual Read: 24490 Airports in 937 ms If you only need to read the file from top to bottom then XMLTextReader is about twice as fast as XDocument. But even using XDocument only takes just over a second for me. XMLTextReader will require writing a lot more code though. I also added code to create rows in a data table and that didn't add any significant time. XMLTextReader + Create Table Rows: 24490 Airports in 727 ms This test code just finds all the airports from the file, so this is just the time taken to read through the file. There's no other processing. In my DLL I read a lot of the data into an in-memory collection and it takes about 2 seconds with all the string parsing to numbers etc. Paul
  15. Paul Henty

    Hold PMDG Offsets

    Process() always brings back the current value. If you only want to do something when a value changes then you need to store the old value in a variable. The variable would need to be declared at the form or module level. Then after you Process(), you need to compare the current value with the old to see if it's different. Paul

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.