Jump to content
The simFlight Network Forums

Paul Henty

Members
  • Posts

    1,728
  • Joined

  • Days Won

    78

Everything posted by Paul Henty

  1. Your ini file [Auto] section looks wrong which means the sndloop lua is never loaded (as confirmed in your latest log) You have: 1.Lua=Sndloop It should be: 1=Lua Sndloop Paul
  2. Here is how I would approach this: 1. Create a class to hold score items. These are going to be all the things you want to check for that calculate the overall score. I suggest you put this at the form/class level (at the same level as the offsets declarations). However, if you prefer you can put this in it's own class file and make it public. private class scoreItem { public string description; public int scoreValue; public bool failed = false; public scoreItem(string Description, int ScoreValue) { this.description = Description; this.scoreValue = ScoreValue; } } 2. Declare the offsets you need for the scoring. For this example you'll need these offsets: (To use the BitArray you may need to add 'using using System.Collections;' at the top of the form. private Offset<ushort> onGround = new Offset<ushort>(0x0366); private Offset<int> ias = new Offset<int>(0x02BC); private Offset<BitArray> lights = new Offset<BitArray>(0x0D0C, 2); private Offset<ushort> pause = new Offset<ushort>(0x0264); 3. Create a dictionary to hold all the scores. (Under the offsets). private Dictionary<string, scoreItem> scores; 4. Create a method to populate all the score items. For this example I only have two items: One is to lose points if you pause. The other is to lose points if you don't have the landing light on before take off. You can use the score value to 'weight' the items. So here pausing (10) is twice as bad as forgetting the landing lights (5). private void createScoreItems() { this.scores = new Dictionary<string, scoreItem>(); // Added two possible penalties for demonstration // 1. Pausing the sim scoreItem pausing = new scoreItem("Fly the route without pausing the flight sim.", 10); this.scores.Add("pausing", pausing); // 2. Forgetting landing lights on takeoff scoreItem noLightsTakeOff = new scoreItem("Turn on the landing lights for take-off.", 5); this.scores.Add("noLightsTakeoff", noLightsTakeOff); // Add more here } 5. Create a method to work out the score: (I've done it here as a percentage) private double calculatePercentageScore() { int totalPossible = this.scores.Sum(s => s.Value.scoreValue); int notFailed = this.scores.Sum(s => s.Value.failed ? 0 : s.Value.scoreValue); return (double)notFailed / (double)totalPossible * 100d; } 6. Create a method to show the score: Here I print the percentage score in a text box, and put all the score items in to two lists. One is items passed so far, the other is items failed so far: private void showScore() { // display the actual score this.txtScore.Text = calculatePercentageScore().ToString("F0") + "%"; // show the passed and failed scores in the list this.lstFailed.Items.Clear(); this.lstFailed.ForeColor = Color.Red; this.lstPassed.Items.Clear(); foreach (scoreItem si in this.scores.Values) { if (si.failed) { this.lstFailed.Items.Add(si.description); } else { this.lstPassed.Items.Add(si.description); } } } 7. After you open the connection (or somewhere at the start of your application) call the methods to initialise the scores and show the starting scores: try { // Attempt to open a connection to FSUIPC (running on any version of Flight Sim) FSUIPCConnection.Open(); // Opened OK FSUIPCConnection.Process(); createScoreItems(); showScore(); // start the timer timer1.Interval = 250; timer1.Start(); } catch (Exception ex) { // Badness occurred - show the error message MessageBox.Show(ex.Message, AppTitle, MessageBoxButtons.OK, MessageBoxIcon.Error); } 8. In the timer tick, check the conditions for each score. If they have failed, mark the relevant score item as failed and show the new score. FSUIPCConnection.Process(); // Check the pause score item if (pause.Value == 1) { // sim paused - fail the pause item this.scores["pausing"].failed = true; showScore(); } // check the noLandingLightsTakeoff score item // If we're still on the ground and the IAS is over 60 and the lights are off then fail double iasKnots = (double)ias.Value / 128d; if (onGround.Value == 1 && iasKnots > 60 && !lights.Value[2]) { this.scores["noLightsTakeoff"].failed = true; showScore(); } All of that will give you a working scoring system in real-time with the two example score items. These conditions are fairly simple, you'll likely need more complicated checks involving keeping track of the flight phase (e.g. Before Taxi, Taxi, After take off, Top of climb, decent, approach etc). Paul
  3. Which part of this specifically are you having a problem with? Your description above seems to describe exactly how to do this. Paul
  4. To log events when offsets change you need to keep a copy of the previous values. Then test against the current values. If they are different you can write the new value to the log. After every 'tick' you must update the last values with the current values. Below is some code that shows logging 'pause/un-pause' and when the gear is put up and down. 1. Create variables to store the last values. These can be the same type as the raw 'value' of the offset (that's what I've used), or they could be the real-world values after conversion. These are at the form/class level, the same as the offsets. private Offset<ushort> pause = new Offset<ushort>(0x0264); private Offset<int> gearPositionNose = new Offset<int>(0x0BEC); private ushort lastPause; private int lastGearPositionNose; 2. Create a method to set these values from the current values of the offsets: private void setLastValues() { this.lastGearPositionNose = this.gearPositionNose.Value; this.lastPause = this.pause.Value; } 3. Call this method after open to set the initial values: try { // Attempt to open a connection to FSUIPC (running on any version of Flight Sim) FSUIPCConnection.Open(); // Opened OK FSUIPCConnection.Process(); setLastValues(); // start the timer timer1.Interval = 250; timer1.Start(); } catch (Exception ex) { // Badness occurred - show the error message MessageBox.Show(ex.Message, AppTitle, MessageBoxButtons.OK, MessageBoxIcon.Error); } 4. In the TIck, test the current values of the relevant offsets and log if they are changed. Finally call the method to update the last values with the current ones (ready for the next tick). private void timer1_Tick(object sender, EventArgs e) { // Pause // If pause changed write it to the log FSUIPCConnection.Process(); if (this.pause.Value != this.lastPause) { log("Sim was " + (pause.Value == 1 ? "PAUSED" : "UN-PAUSED")); } // Gear if (gearPositionNose.Value == 0) { this.textBox4.Text = "Gear Up"; if (this.lastGearPositionNose != 0) { log("Gear UP"); } } else if (gearPositionNose.Value == 16383) { this.textBox4.Text = "Gear Down"; if (this.lastGearPositionNose != 16383) { log("Gear DOWN"); } } else { this.textBox4.Text = "Gear In Transit"; } setLastValues(); } 5. For this demonstration, my 'log' method just adds an item to a ListBox on the form. private void log(string message) { string logLine = DateTime.Now.ToString() + ": " + message; this.listBox1.Items.Add(logLine); } Paul
  5. There is an example application in the main download package that has real-time updates. If you haven't got this please download it from the following link. The zip also contains a user manual. http://forum.simflight.com/topic/74848-fsuipc-client-dll-for-net-version-24/ About your code: 1. You must declare all the offsets at the class (form) level. Not in methods. Every time you declare an offset you are making a new copy of it. Eventually your program will run out of FSUIPC memory space. 2. To get realtime updates you need to do the following: 2.1 Drag a timer onto your form. (For the examples we assume it's called 'timer1' 2.2 Set the timer running after you open the connection to FSUIPC. Stop the timer before you close the connection. 2.3 In the form designer, go to the timer and create an event method for the 'Tick' event. This 'tick' method will run at the specified Interval. In this method you need to process() the offsets and then update your text boxes. The whole thing should be something like this: public partial class Form1 : MetroForm public string AppTitle { get; set; } private Offset<int> airspeed = new Offset<int>(0x02BC); private Offset<int> GroundSpeed = new Offset<int>(0x02B4); private Offset<int> ZeroFuelWeight = new Offset<int>(0x3BFC); private Offset<int> verticalSpeed = new Offset<int>(0x02C8); private Offset<int> gearPositionNose = new Offset<int>(0x0BEC); private Offset<int> Flapscontrol = new Offset<int>(0x0BDC); private Offset<double> agl = new Offset<double>(0x0020); public Form1() { InitializeComponent(); } private void metroButton1_Click(object sender, EventArgs e) { try { // Attempt to open a connection to FSUIPC (running on any version of Flight Sim) FSUIPCConnection.Open(); // start the timer timer1.Interval = 250; // in milliseconds (i.e. 4 times per second.) Adjust for your needs. timer1.Start(); // Opened OK } catch (Exception ex) { // Badness occurred - show the error message MessageBox.Show(ex.Message, AppTitle, MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void metroButton2_Click(object sender, EventArgs e) { // stop the timer timer1.Stop(); FSUIPCConnection.Close(); } private void timer1_Tick(object sender, EventArgs e) { // get data from FSUIPC FSUIPCConnection.Process(); // show data in the text boxes // Airspeed double airpeedKnots = (double)airspeed.Value / 128d; this.textBox1.Text = airpeedKnots.ToString("f0"); // Ground speed double GroundSpeedKnots = (double)GroundSpeed.Value / 65536d; this.textBox5.Text = GroundSpeedKnots.ToString("f0"); // altitude string altitude = agl.Value.ToString(); // ZFW double ZeroFuelWeightlbs = (double)ZeroFuelWeight.Value / 256; this.textBox12.Text = ZeroFuelWeightlbs.ToString("f0"); // VS double verticalSpeed_FeetPerMinute = (double)verticalSpeed.Value * 60d * 3.28084d / 256d; this.textBox2.Text = verticalSpeed_FeetPerMinute.ToString(""); // Gear if (gearPositionNose.Value == 0) { this.textBox4.Text = "Gear Up"; } else if (gearPositionNose.Value == 16383) { this.textBox4.Text = "Gear Down"; } else { this.textBox4.Text = "Gear In Transit"; } } } Paul
  6. Yes you need an open connection. Paul
  7. You need to have FSX running on the same PC. Or, if you have a WideFS licence, you can run WideClient.exe instead. This will connect to the FSX computer and is a tiny program compared to FSX. You cannot get a payload station by name because Flight Sim allows duplicate names for payload stations. For example the stock Cessna C172 has two payload stations called 'Rear Passenger'. If you want to load (update) all the payload stations at once, use a 'select' statement. This example loads the station weights from text boxes on the form. I've only shown two stations to keep it short. Dim ps As PayloadServices = FSUIPCConnection.PayloadServices ps.RefreshData() For Each payloadStation As FsPayloadStation In ps.PayloadStations Select Case payloadStation.Name Case "Cabin 0A" payloadStation.WeightKgs = txtCabinA.Text Case "Crew1" payloadStation.WeightKgs = txtCrew1.Text End Select Dim weight As Double = payloadStation.WeightLbs Next payloadStation ps.WriteChanges() If you want to access payload stations individually then you use the index, not the name. This example updates the Crew1 station - the index of this station is 10: station_load.10 ="0, 28.5715924813225, 0.0, 0.0, Crew1" ps.RefreshData() ps.PayloadStations(10).WeightKgs = txtCrew1.Text ps.WriteChanges() Process() is on the FSUIPCConnection class. This will read or write the data in all the offsets you have declared in your application. It does nothing for PayloadServices. WriteChanges() is on the PayloadServices() class. This will write any changed to payload information you have made. It does not write any offsets you have declared. When you use PayloadServices you don't need to use Process(). Paul
  8. transponder.Length.ToString will not work. Ah yes. I did not see that there is another variable being declared call transponder: Dim transponder As String = DateTime.UtcNow.ToString("[HH:mm]") & Chr(32) & "Transponder set to " & txtTransponder.Text & vbCrLf This is bad because it's the same name as the offset called transponder. If you change the name of this new variable then it will work. I changed it to transponderMsg: Private Sub tmrtrans_Tick(sender As Object, e As EventArgs) Handles tmrtrans.Tick If transponder.Value <> lastTransponder Then Dim transponderMsg As String = DateTime.UtcNow.ToString("[HH:mm]") & Chr(32) & "Transponder set to " & txtTransponder.Text & vbCrLf My.Computer.FileSystem.WriteAllText(logname, transponderMsg, True) Dim xml As String = DateTime.UtcNow.ToString("[HH:mm]") & Chr(32) & "Transponder set to " & txtTransponder.Text & "*" My.Computer.FileSystem.WriteAllText(reportname, xml, True) lastTransponder = transponder.Value End If tmrtrans.Stop() End Sub This should do the same thing without timers. I renamed the timer tick event and removed the timers start/stop calls. Private Sub logTransponder() If transponder.Value <> lastTransponder Then Dim transponderMSg As String = DateTime.UtcNow.ToString("[HH:mm]") & Chr(32) & "Transponder set to " & txtTransponder.Text & vbCrLf My.Computer.FileSystem.WriteAllText(logname, transponderMSg, True) Dim xml As String = DateTime.UtcNow.ToString("[HH:mm]") & Chr(32) & "Transponder set to " & txtTransponder.Text & "*" My.Computer.FileSystem.WriteAllText(reportname, xml, True) lastTransponder = transponder.Value End If End Sub Private Sub txtTransponder_TextChanged(sender As Object, e As EventArgs) Handles txtTransponder.TextChanged If txtTransponder.Text.Length = 1 Then txtTransponder.Text = "000" & txtTransponder.Text End If If txtTransponder.Text.Length = 2 Then txtTransponder.Text = "00" & txtTransponder.Text End If If txtTransponder.Text.Length = 3 Then txtTransponder.Text = "0" & txtTransponder.Text End If logTransponder() End Sub
  9. I think FSUIPC4 should work with any version or P3D up to 2.5. I'm running 4.939t here without any problems. You don't say if you're using 2.4 of my DLL or one of the many 3.0 Beta builds that are posted in various threads. You could try using the latest 3.0 build. I've attached it here. If that doesn't work then it sounds like you have something wrong with the FSUIPC installation and it's returning 0 for all offsets (therefore failing the version test because it's reporting version 0). Can you try using another FSUIPC application to see if that works, for example FSInterrogator (available in the FSUIPC SDK), If that works then it's something to do with my dll. If it doesn't work either then something is wrong with your FSUIPC installation or registration. Paul FSUIPCClient3.0_BETA.zip
  10. The timers don't make any sense to me. They seem to be started, run one tick and then stop again. I don't know if you want to sort that out. It could lead to more problems. Yes they all have the same problem. They all compare the value with the text. It's the same solution: store the last value and compare against that. Paul
  11. Hi Fred, This line in tmrtrans_tick() is wrong: If transponder.Value = txtTransponder.Text Then It's trying to catch the same value so the log line does not appear. But, it's testing the integer value against the converted hex string. They will never be the same. The easiest way to fix this with the code you have is: 1. Create a form level private variable to hold the last value written: (Make it the same type as the offset (i.e. Integer)) Private lastTransponder as Integer 2. Change the tmrtrans_tick() to test against this value. When you write a new value, update the 'lastTransponder' variable: (I also rewrote the 'If = then else' as 'if <> then') Private Sub tmrtrans_Tick(sender As Object, e As EventArgs) Handles tmrtrans.Tick If transponder.Value <> lastTransponder Then Dim transponder As String = DateTime.UtcNow.ToString("[HH:mm]") & Chr(32) & "Transponder set to " & txtTransponder.Text & vbCrLf My.Computer.FileSystem.WriteAllText(logname, transponder, True) Dim xml As String = DateTime.UtcNow.ToString("[HH:mm]") & Chr(32) & "Transponder set to " & txtTransponder.Text & "*" My.Computer.FileSystem.WriteAllText(reportname, xml, True) lastTransponder = transponder.Value End If tmrtrans.Stop() End Sub Try that. Paul
  12. I forgot to say that you probably don't need to do the 'luakill' control on the button release. The script will automatically die when it's finished executing (i.e. it gets to the bottom).
  13. The parameter set in the FSUIPC dialog comes through in lua as a variable called ipcPARAM. You just set up some if statements to test the value... You can use any numbering scheme you want. Maybe you'll want to match the parameter number with the number in your filenames. I've just used 1 to 3 here. sound.path("C:\\") if ipcPARAM == 1 then sound.play("5-0firebell.wav") elseif ipcPARAM == 2 then sound.play("5-4safety_brief") elseif ipcPARAM == 3 then sound.play("5-5another_file") end Just stack as many elseif blocks as you need. Paul
  14. No, it gets sent immediately. The process() is done by the dll internally. Paul
  15. There are no Lua errors reported in the log and your screenshot of the GUI also looks okay. I can only offer two suggestions now... 1. You have a few sound devices listed. You could try specifying the number of the device you are using as the second parameter. Without this you are leaving up to windows to decide on the 'primary' device. For example if you are using the 5.1 speaker output then use: sound.play("firebell.wav", 4) 2. Try using one of the sounds that comes with flight sim in case your firebell.wav is in an unsupported bit-depth or sample rate. I used sound.play("INNERMK.WAV") but I have FSX, so check this is in FS9 or chose another one. Pete is back on Thursday if you have no luck with these. Paul
  16. Have a look in the FSUIPC.log file (in the modules folder). It might have a error message that will explain why it's not working. Paste the contents here if you want me to take a look. Paul
  17. Two problems I can see: 1. sound should start with a lower case s sound.play() 2. The parameter should be the name of the sound file, not a path. The default path according to the documentation is the 'sound' folder under the main FS folder. If you want to play sounds from a different folder, you can call sound.path() with the new folder. Try this: sound.path("D:\\")sound.play("firebell.wav") Paul
  18. Yes, this works if the plane is using the built-in FS autopilot. This may not work on Third-party payware where they have coded their own autopilot. You can also send the Autopilot off control as follows (Must be using Version 3.0 of my DLL. It's attached to a previous reply in this thread.) FSUIPCConnection.SendControlToFS(FsControl.AUTOPILOT_OFF, 0) Yes it's 0x2F80. Again, this will not work where aircraft developers have coded their own autobrake system. Paul
  19. Hi Fred, Offset 0x0330 is only 2 bytes. You've declared the offset as 'Integer' which is a 4 bytes in VB. The type tells the DLL how many bytes to read. A 2-Byte integer is a Short. This value is also unsigned so it's best to use UShort like this: Public qnh As Offset(Of UShort) = New FSUIPC.Offset(Of UShort)(&H330) My userguide.pdf explains which VB types to use. See the table on page 7. Regards, Paul
  20. Hi Philipp, I don't have P3D so I can't test anything here. To receive key presses, FSX or P3D must have focus. When you send keys with FSUIPCConnection.SendKeyToFS, the DLL brings the sim into focus using an FSUIPC control called 'Key focus restore'. It may be that this doesn't work for P3D. Can you just try this out for me and report back? All you need to do is run this line of code from a button or similar: FSUIPCConnection.SendControlToFS(FSUIPCControl.Key_focus_restore, 0) If it's working then your application will lose focus and FSX/P3D will get the focus. Depending on the results I'll see if there's anything that can be done. Regards, Paul
  21. 1. The number of passengers on board is not recorded in FS. Each plane, depending on how it's written, has a different number of payload stations. For example, the default 737 has playload stations representing rows of seats: e.g. First Class, Coach 3-10. All you can do is read and write the total weight for all these passengers. Some complex payware aircraft have a payload station per seat. 1a. The Max Takeoff Weight is not available in FS. You can get the Max Gross Weight which is usually close. I've added this to the PayloadServices (new DLL attached). Either use the Max Gross Weight or you can just hold the real-world information in a table in your application. Dim ps As PayloadServices = FSUIPCConnection.PayloadServices ps.RefreshData() MsgBox(ps.MaxGrossWeightKgs.ToString("F0") & "Kg") 2. You can get back a weather structure from the weather services. You can then construct your string from the various properties. There is full Intellisense documentation to help with this. For example, making a temperature string: Dim ws As WeatherServices = FSUIPCConnection.WeatherServices Dim weather As FsWeather = ws.GetWeatherAtAircraft() Dim message As String = "Temperature " & weather.TemperatureLayers(0).DayCelsius & "°C" MsgBox(message) 3. The QNH can be set at offset 0x0330. The altitude above ground can be calculated by subtracting the height of the terrain (0x0020) from the altitude above sea level (0x6020). 4. Dual autopilots are not supported in FS. The main autopilot switch is at 0x07BC. Some payware aircraft may have dual autopilots, but you'll need to find out if/how you can access this information. Each aircraft will be different. 5. See offsets 0x0C48 and 0x0C49 to get the position of the ILS/Glideslope indicators. 6. Offset 0x0D06, bit 6. See this thread on how to use a bitarray to make it easier. http://forum.simflight.com/topic/79536-little-understanding-problem-reading-from-project-magenta-offset/ 7. Offset 0x31F4 controls the pushback. I cannot see anywhere in your application that this is declared or used. Looks like to need to add this. Paul FSUIPCClient3.0_BETA.zip
  22. I don't think so. Lua is the only way I know of accessing L:VARs. If Aerosoft have an SDK you might be able to access that directly from your program. However, this may be difficult with VB as most SDKs are intended for C. Paul
  23. No. Users of FSUIPC can change the text to white using the tick box for 'non-scrolling FS msgs to be in white' on the 'miscellaneous' tab. But I don't believe the colour cannot be set via code. Paul
  24. Problem 1 - Message not disappearing after 5 seconds This code is in a sub called 'mess()' which is called from drivestarttmr(). drivestarttmr() runs every 0.5 seconds, called from TmrGetDataFromFs_Tick(). So the problem is the message is being displayed every 0.5 seconds. Every time it is called the message timer gets reset. It will never reach 5 seconds. Solution: Move the mess() call from drivestarttmr() to a more suitable place so it's only called once after the connection is made. Problem 2 - Losing Connection This is because you are declaring offsets in the main sub: Dim msgcontrol As Offset(Of Short) = New FSUIPC.Offset(Of Short)("msg", &H32FA) '<---- Very bad Dim msg As Offset(Of String) = New FSUIPC.Offset(Of String)("msg", &H3380, 128) '<---- Very bad msg.Value = "SKYDreamTracker is Connected to SIM !!! Have a nice flight;)" msgcontrol.Value = 5 FSUIPCConnection.Process("msg") Each time this code runs (2 times a second) you create two new offsets in the 'msg' group. Eventually there are too many for FSUIPC to handle. Solution: You must move these two lines to the top of the class (FSUIPCData.vb) with all the other offset declarations. Paul
  25. The easiest way is to set the type as a BitArray: (You also need to add the offset length as the second parameter.) Public LED As Offset(Of BitArray) = New FSUIPC.Offset(Of BitArray)(&H4F0, 2) To read the state of a particular light just use an array index with the bit number you need. For example this is how you know if the LNAV light is on or off: FSUIPCConnection.Process() Dim lnav As Boolean = LED.Value(6) 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.