Jump to content
The simFlight Network Forums

Paul Henty

Members
  • Posts

    1,724
  • Joined

  • Days Won

    77

Everything posted by Paul Henty

  1. No, I haven't built in any events for offset value changes. I've often thought about it because it's more in line with the normal way of .NET programming, but I can't see a good way of doing it. e.g. Would you want to subscribe to each offset's updated event separately? Or maybe one event that gets called every time any offset changes. If it's one event, should it be called once for each offset that has changed, or just once with an array of all offsets that have changed? Would you want to still control the Process() calls yourself or have the DLL do this automatically given a polling interval? If you're using multiple groups then you may need to specify different time intervals between the automatic Process() calls for each group separately. FSUIPC doesn't work by events, so the DLL will need to Process() and then detect changes in the Offset values. It can be done, but the more I think about it the more complicated it gets. If you have any ideas on how it should work from your point of view, or answers to the questions raised then I'll have another think about it. Paul
  2. The easiest way would be to use a ProgressBar control. Set the min value to 0, the max value to 4096 and the Style to 'continuous' or 'blocks' depending on your preference. The memory used is just 4096 - memory free in Mb (VASMb variable in the example code). In the configureScreen method, set the Value property of ProgressBar to the memoryUsed, Then set the colour of the bar (Forecolor property) depending on the value of the memory used. For example, if it's > 3072 then Red, else if > 2048 then Orange, else Green. Set the levels to your preference. There are plenty of websites and YouTube videos that cover how to use ProgressBars in VB.NET and C#. Paul
  3. Here is the C# version. Other than the language it's identical to the VB version above. NOTE: You will need to change the 'namespace'. Before pasting the code, make a note of what the namespace is for your project (Look at the code behind the Form1 and see what the namespace line says). Then after pasting the code, change the namespace from VASOffsetCSharp back to whatever yours was. To get this working use the same procedure as above. Make a new C# windows forms project, add the controls to the form and paste the entire code behind, then change the namespace. NOTE2: Is c# make sure the timer is called 'timer1' (lowercase t) and not 'Timer1' as in VB. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using FSUIPC; namespace VASOffsetCSharp { public partial class Form1 : Form { // Declare offsets here private Offset<int> VAS = new Offset<int>(0x024C); public Form1() { InitializeComponent(); this.Load += Form1_Load; this.FormClosing += Form1_FormClosing; this.timer1.Tick += timer1_Tick; this.btnConnect.Click += btnConnect_Click; this.btnDisconnect.Click += btnDisconnect_Click; } private void Form1_Load(object sender, EventArgs e) { // set the timer to tick every second. (Change this if you need more rapid updates) this.timer1.Interval = 1000; configureScreen(); } private void btnConnect_Click(object sender, EventArgs e) { // Try to connect to FS try { FSUIPCConnection.Open(); // Open was sucessful, start the timer this.timer1.Start(); } catch (FSUIPCException exFSUIPC) { MessageBox.Show(exFSUIPC.Message); } catch (Exception ex) { MessageBox.Show("Error when connecting: " + ex.Message); } } private void timer1_Tick(object sender, EventArgs e) { try { // Process the offsets FSUIPCConnection.Process(); } catch (Exception ex) { // Connection lost // Stop the timer this.timer1.Stop(); MessageBox.Show("Error reading data from Flight Sim: " + ex.Message); } finally { configureScreen(); } } private void configureScreen() { // Configure the screen // Test if connection is open or not if (FSUIPCConnection.IsConnectionOpen()) { this.lblConnectionStatus.Text = "Connected to " + FSUIPCConnection.FlightSimVersionConnected.ToString(); this.btnConnect.Enabled = false; this.btnDisconnect.Enabled = true; // VAS readout double VASMb = this.VAS.Value / 1024d; // Convert from Kb to Mb this.lblVAS.Text = "Memory remaining: " + VASMb.ToString("N0") + "Mb"; // Show Mb with no decimal places } else { this.lblConnectionStatus.Text = "Not connected"; this.btnConnect.Enabled = true; this.btnDisconnect.Enabled = false; this.lblVAS.Text = "Memory remaining: ?Mb"; } } private void btnDisconnect_Click(object sender, EventArgs e) { // Stop the timer this.timer1.Stop(); // Close the connection FSUIPCConnection.Close(); configureScreen(); } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { FSUIPCConnection.Close(); } } } Paul
  4. Here is the VB version: You need to make a new Windows Forms project in VB.NET Then add a reference to the FSUIPCClient.DLL (I've attached the latest version). Then on Form1 you need to add: A button called "btnConnect" A button called "btnDisconnect" A Timer called "Timer1" A Label called "lblConnectionStatus" A Label called "lblVAS" Then paste the whole code below into the code behind the form: Imports FSUIPC Public Class Form1 ' Declare offsets here Private VAS As Offset(Of Integer) = New Offset(Of Integer)(&H24C) Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load ' set the timer to tick every second. (Change this if you need more rapid updates) Me.Timer1.Interval = 1000 configureScreen() End Sub Private Sub btnConnect_Click(sender As Object, e As EventArgs) Handles btnConnect.Click ' Try to connect to FS Try FSUIPCConnection.Open() ' Open was sucessful, start the timer Me.Timer1.Start() Catch exFSUIPC As FSUIPCException MessageBox.Show(exFSUIPC.Message) Catch ex As Exception MessageBox.Show("Error when connecting: " & ex.Message) End Try End Sub Private Sub timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick ' Process the offsets Try FSUIPCConnection.Process() Catch ex As Exception ' Connection lost ' Stop the timer Me.Timer1.Stop() MessageBox.Show("Error reading data from Flight Sim: " & ex.Message) Finally configureScreen() End Try End Sub Private Sub configureScreen() ' Configure the screen ' Test if connection is open or not If (FSUIPCConnection.IsConnectionOpen()) Then Me.lblConnectionStatus.Text = "Connected to " & FSUIPCConnection.FlightSimVersionConnected.ToString() Me.btnConnect.Enabled = False Me.btnDisconnect.Enabled = True ' VAS readout Dim VASMb As Double = Me.VAS.Value / 1024D ' Convert from Kb to Mb Me.lblVAS.Text = "Memory remaining: " & VASMb.ToString("N0") & "Mb" ' Show Mb with no decimal places Else Me.lblConnectionStatus.Text = "Not connected" Me.btnConnect.Enabled = True Me.btnDisconnect.Enabled = False Me.lblVAS.Text = "Memory remaining: ?Mb" End If End Sub Private Sub btnDisconnect_Click(sender As Object, e As EventArgs) Handles btnDisconnect.Click ' Stop the timer Me.Timer1.Stop() ' Close the connection FSUIPCConnection.Close() configureScreen() End Sub Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing FSUIPCConnection.Close() End Sub End Class How it works: There is a timer (Timer1) that is set to tick every 1 second. (You can change this if your application needs more frequent updates). When the user presses the connect button, we try to connect to FSUIPC. If a problem occurs we tell the user. If the connection is good we start the timer ticking. We then call configure screen which will always draw the screen properly, depending on if we're connected etc. If we are connected it: lights the 'diconnect' button tells the user they are connection (and to what sim - FSX/P3D etc) disables the 'connect' button displays the current VAS value If we're not connected it: disabled the 'diconnect' button tells the user they are not connected enables the 'connect' button displays the ? for the current VAS value Once the timer is ticking, on every tick we call Process() to get the the current offset data. If all goes well we call configureScreen() to update the screen. If there is a problem (connection lost) then we stop the timer and tell the user there was a problem. I'll post the C# version below in a bit... FSUIPCClient3.0_RC2.zip
  5. Sure, which language C# or VB.NET? Sorry, Just seen in your original post you're asking for VB. Paul
  6. 1. The VAS Value (Memory available to FS in Kb) is in offset 0x024C. It's an Integer (4 Bytes), 2. I can't help with writing a full ACARS system unfortunately. Hopefully someone else is looking for a new project. Paul
  7. Okay - Try this. It reports you're at a gate when you are inside the radius of that gate. Public Function getgate(ByVal icaocode As String) As String ' Returns the current gate or "" is not parked at any gate. Using MyReader As New FileIO.TextFieldParser(Form1.fullFSpath.Value & "g5.csv") MyReader.TextFieldType = FileIO.FieldType.Delimited MyReader.SetDelimiters(",") Dim gatename As String Dim gatenumber As String Dim gatereturn As String = "" Dim currentRow As String() While Not MyReader.EndOfData Try currentRow = MyReader.ReadFields() If currentRow(0) = icaocode Then gatename = currentRow(1) gatenumber = currentRow(2) Dim aaa As String = currentRow(3) Dim bbb As String = currentRow(4) Dim aaaa As Double = Double.Parse(aaa, CultureInfo.InvariantCulture) Dim bbbb As Double = Double.Parse(bbb, CultureInfo.InvariantCulture) Dim gateRadius As String = currentRow(5) Dim gateRadiusKm As Double = Double.Parse(gateRadius, CultureInfo.InvariantCulture) / 1000D ' *** Distance now returned in Km *** Dim distance As Double = Form1.distance(Functions.getAircraftLatFS(), Functions.getAircraftLonFS(), aaaa, bbbb, "K") If distance <= gateRadiusKm Then gatereturn = gatename + " " + gatenumber MyReader.Close() MyReader.Dispose() Return gatereturn End If End If Catch ex As FileIO.MalformedLineException 'MsgBox("Line " & ex.Message & "is not valid and will be skipped.") End Try End While MyReader.Close() MyReader.Dispose() Return "" ' Not near any gate End Using End Function Paul
  8. Thanks. I can fix this up to work properly. Just one thing I need to know: Do you want to always get back the closest gate even if you're a long way from it (e.g. at the end of the runway). Or do you only want to report being at a gate when you're parked at it (e.g. within 20 metres or so?). Paul
  9. Hi Scott, I looks like you're trying to process() the default group without any offsets having been declared. It's a bit difficult to tell without seeing any of your code however. I've attached the latest version of the DLL for you to try in case there is a bug in the version you have. This is compiled against the .NET 4.0 Runtime. Can you post some of the code here so I can take a look? Thanks, Paul FSUIPCClient3.0_RC2.zip
  10. Assuming that your distance function is correct, you need something like this: I don't know how you are loop though each gate so I've just put a placeholder for that. Also I don't know what units your distance function returns so I've assumed Metres. If it's different just adjust the values. Dim currentGate as String = "" Dim minDistanceToGate as Double = 20 'Need to be within 20 metres of the gate. (Adjust to your preference). [Loop for each gate] Dim distance As Double = distance(acLat, acLon, gateLat, gateLon, "M") If distance <= minDistanceToGate Then currentGate = strGateNumber End If [End loop for each gate] ' currentGate now contains the gate you are at. Or "" if you're not near any gate. That's the sort of loop and logic you'll need. If you need more help please post the exact code you are trying and I'll be able to see where it's going wrong. Paul
  11. Do you have the lon/lat of each gate? or is that what you're stuck on? Paul
  12. With 2.4 you couldn't easily create a collection of offsets. With 3.0 there is a new untyped offset class that you can use to make this possible. It's also called Offset but you just don't give it a type. Instead of this Dim myOffset as Offset(Of Integer)(&H2BC) it's just this Dim myOffset as Offset(&H2BC, 4) Note that because there is no type the size is always required. Also because you don't set the type when you create it, you need to specify the type when you get the value: Dim myValue as Integer = myOffset.Value(Of Integer) The main advantage of these untyped Offsets is that you can put them in a collection or array e.g. Dim myOffsets as List(Of Offset) Dim myOffset as Offset() Below is a small piece of example code that has a list of offset addresses/sizes and then creates another list of proper Offsets from those. It then processes the group and gets the value back from all the offsets. The class that holds the offset address and size is just this: (You'll already have your own method for storing your list of addresses. This is just for the example). Public Class offsetInfo Public address As Integer Public size As Byte End Class This is the example code: Public Sub OffsetListDemo() ' dummy list that holds a list of offset address, sizes etc to be retreived Dim offsetInfos As List(Of offsetInfo) = New List(Of offsetInfo) ' create 3 dummy offsets offsetInfos.Add(New offsetInfo() With {.address = &H36C, .size = 1}) ' stall warning offsetInfos.Add(New offsetInfo() With {.address = &H366, .size = 2}) ' On ground offsetInfos.Add(New offsetInfo() With {.address = &H2BC, .size = 4}) ' IAS ' Create a list to hold the offsets Dim offsetList As List(Of Offset) = New List(Of Offset)() ' Create an Offset for each address in the list For Each info As offsetInfo In offsetInfos Dim nextOffset As Offset = New Offset("myGroup", info.address, info.size) offsetList.Add(nextOffset) Next info ' process all the offsets in this group FSUIPCConnection.Process("myGroup") ' go through the offsets and get the values For Each fsOffset As Offset In offsetList Select Case fsOffset.DataLength Case 1 Dim value As Boolean = fsOffset.GetValue(Of Boolean) Case 2 Dim value As Boolean = fsOffset.GetValue(Of Short) Case 4 Dim value As Boolean = fsOffset.GetValue(Of Integer) End Select Next fsOffset End Sub I'm not sure about your threading problem. You might need to post more code, or a simple project that demonstrates the error. Paul
  13. Attached is the new DLL with the changes, Adding and removing offsets and groups is now thread-safe. I've run tests with 100 threads all creating a new offset, processing it and deleting the group. Seems to work okay here. However, I did run into another problem which you might also be having: I was running the threads from System.Timers.Timer classes. If I ran the timers too fast then I would get an error that the group doesn't exist. This is the cause: 1. Thread A is created and the timer code is run. 2. Thread A creates the offset in a group of called "Group1". 3. Thread A Processes the group 4. Before this has finished the timer elapses and creates Thread B and runs the timer code 5. Thread B Adds offsets to the group called "Group1" 6. Thread A finished the Process() call and deletes "Group1" 7. Thread B tries to process "Group1" but it's deleted. This is something that you'll need to manage in your code, either by: A. creating your own locking mechanism so the timer doesn't run the code if the last timer tick hasn't finished. b. Increasing the time between timer ticks so no overlap occurs. However you could also try an experimental feature I've added to the DLL. There is a new property called: FSUIPCConnection.GroupsIsolatedToThread This is normally false. If you set this to true right after you open the connection, then all groups/offsets are unique to the thread they are created on. Therefore you can have a group with the same name created on different threads. A thread can not process or delete a group created on another thread. Setting this to true will also solve the "timer too fast" problem described above. If the timer ticks again before the code from the last tick is completed, the timer code will be run on a new thread. This will then have its own copy of the offset group and won't be affected by the previous thread when it deletes the group. Let me know how it goes. Paul FSUIPCClient3.0_RC2.zip
  14. The queuing will mainly occur when calling Process() as there is only one connection and only one message queue in Windows on which to send messages to FSUIPC. Each thread trying to Process() will be queued and given access to the Process() method one at a time. By using the new 'concurrent' collections, the blocking when creating and deleting offsets will be minimised. It will only happen if the threads are accessing the same 'bucket' in the Dictionary. This is pretty random though as it depends on the key used and the hashing algorithm used by .net. I think most of the time it won't block. Reading your original post it seems like you're calling Process() for each offset. That is, you only have one offset in the group. I may have misunderstood, but this is very inefficient as the Process() call is the one that takes a bit of time (it's exchanging data with FSUIPC). So if you have 10 offsets, calling process 10 times (once for each offset) will be 10 times slower than putting all 10 offsets into one group and calling process() once. Of course you'll still have the threading problems, but I just wanted to point that out. Paul
  15. Hi, While the Process() call is thread safe, the creation of offsets is not. It's not possible to open multiple connections for each thread. I'm not sure that would have any advantage because requests from each connection would be put on the same windows message queue when being sent to FSUIPC. So they wouldn't be executed in parallel. I think the best solution will be to make creating offsets thread-safe inside the DLL. The best way of doing that would be to use the new 'concurrent' collections from .NET 4.0 inside the DLL. This would maintain most of the performance from using multiple threads. The alternative is basic locking of the offset collections but then each thread will need to queue for the lock. If you're happy to only target .NET 4.0 or later, and to upgrade to version 3.0 of the DLL then I'll make the changes to 3.0 towards the end of this week. Let me know if this sounds okay for you. Paul
  16. Hi Sébastien, I've attached the latest version of the DLL. There is a method called FSUIPCConnection.IsConnectionOpen() which will tell you if you are connected or not (true/false). There is no property that you can set to make a connection however. You still need to call Open() and Close(). Paul FSUIPCClient3.0_RC1.zip
  17. The SDK and samples are in C++. There is a .NET DLL that allows .NET languages to use SimConnect. However, it is very poorly documented and what little there is is in C#. Paul
  18. If you're using FSUIPC to send the controls then you just need the event ID number. For example, let's say you want to press the VNAV switch on the MCP on the 737. In the PMDG SDK header file it's defined like this: #define EVT_MCP_VNAV_SWITCH (THIRD_PARTY_EVENT_ID_MIN + 386) THIRD_PARTY_EVENT_ID_MIN is defined as: #define THIRD_PARTY_EVENT_ID_MIN 0x00011000 // equals to 69632 So the control number for EVT_MCP_VNAV_SWITCH = 69632 + 386 = 70018. The parameter value is usually one of the mouse buttons: #define MOUSE_FLAG_RIGHTSINGLE 0x80000000 #define MOUSE_FLAG_MIDDLESINGLE 0x40000000 #define MOUSE_FLAG_LEFTSINGLE 0x20000000 ... etc You can put these into VB.NET to make things easier: Private Const MOUSE_FLAG_RIGHTSINGLE As Integer = &H80000000 Private Const MOUSE_FLAG_MIDDLESINGLE As Integer = &H40000000 Private Const MOUSE_FLAG_LEFTSINGLE As Integer = &H20000000 etc.. So finally, to simulate the user clicking the VNAV button with the a single click of the left mouse button you do this: SendControlToFS(70018, MOUSE_FLAG_LEFTSINGLE) ' PMDG 737 VNAV Paul
  19. No, it's all done through FSUIPC. Paul
  20. According to docs: FSUIPC3: You can write to any of the speed offsets: 02B4 - Ground Speed 02B8 - True Airspeed 02BC - Indicated Airspeed FSUIPC4 Only: You can use the new 0558 offset to set the speed. The docs say that 02B8 and 02BC might also be writeable in FSUIPC4 but this is not tested. 02B4 is readonly in FSUIPC4. Paul
  21. Sure, no problem. . Offset declarations... Dim controlParam As Offset(Of Integer) = New Offset(Of Integer)("sendControl", &H3114, True) Dim sendControl As Offset(Of Integer) = New Offset(Of Integer)("sendControl", &H3110, True) ' Must be declared AFTER 3114. Helper sub to send a control and parameter... Private Sub SendControlToFS(controlNumber As Integer, parameterValue As Integer) Me.sendControl.Value = controlNumber Me.controlParam.Value = parameterValue FSUIPCConnection.Process("sendControl") End Sub Paul
  22. You don't need to hold any values. You should be calling pmdg777sk() and pmdg737sk() regularly. You can put these in your main timer loop. In the FsuipcData.vb module, it looks like the sub drivestarttmr() is the place to call them. Somewhere after the call to FSUIPCConnection.Process(). Near where you call checklandinglights() and checkiasFL100(). If you put them here then you don't need the FSUIPCConnection.Process() calls in pmdg777sk() or pmdg737sk(). Paul
  23. The code you've posted looks okay. You haven't shown the declaration for LTS_Strobe_Sw_ON, so I can't check that. It should be: Dim LTS_Strobe_Sw_ON As Offset(Of Byte) = New Offset(Of Byte)(&H648F) If you have the same in your code then I'm not sure why it isn't working. I can't test it here unfortunately. Have you added the EnableDataBroadcast line in 777X_Options.ini? Paul
  24. The code you've posted looks okay. You haven't shown the declaration for LTS_Strobe_Sw_ON, so I can't check that. It should be: Dim LTS_Strobe_Sw_ON As Offset(Of Byte) = New Offset(Of Byte)(&H648F) If you have the same in your code then I'm not sure why it isn't working. I can't test it here unfortunately. Have you added the EnableDataBroadcast line in 777X_Options.ini? Paul
  25. I think the only way to do that is to check the name of the aircraft. You are already reading this: PMDG 777-21HLR Emirates B77L But what is the problem? Are the values not being returned from the 777? Are they wrong? 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.