1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

(C#) I can read! Can I write?

Discussion in 'SimConnect' started by raysot, 25/10/06.

  1. raysot

    raysot

    Joined:
    18/10/06
    Messages:
    14
    Country:
    us-washington
    Success comes in small steps...

    Finally, with the help of some enterprising souls here, I can see FSX from a remote client and read data...

    Like so:
    simconnect.AddToDataDefinition(DEFINITIONS.Struct1, "Autopilot Master", "Boolean", SIMCONNECT_DATATYPE.INT64, 0.0f, SimConnect.SIMCONNECT_UNUSED);

    Basically just add that to an existing STRUCT, get the data and everyone is happy.

    Let's say now that I want to change something, like toggle the A/P Master.

    The SDK comes with a few C# examples on how to read data, but none on how to write. Can anyone help?
  2. curious

    curious

    Joined:
    21/10/06
    Messages:
    9
    To write you use SetDataOnSimObject. You can use the same struct that you created for reading the variable (as long as it is a settable variable in FSX, not every variable that you can read can be written).

    So at a high level the steps are:

    1) write the value you want to set into your struct (e.g. struct.variable = value)
    2) call SetDataOnSimObject (e.g. simconnect.SetDataOnSimObject(DEFINITIONS.DEFFORYOURSTRUCT, objectIdThatYouWantToSetDataFor, SIMCONNECT_DATA_SET_FLAG.DEFAULT, struct);

    Hope this points you in the right direction. The SimConnect doco and the autocomplete functionality in VS 2005 are very useful too.
  3. raysot

    raysot

    Joined:
    18/10/06
    Messages:
    14
    Country:
    us-washington
    It helps.. however now I'm getting an exception:

    Exception 3:
    SIMCONNECT_EXCEPTION_UNRECOGNIZED_ID = 3,

    I'm working with the Managed Data Request example and have the following line(s)

    simconnect.SetDataOnSimObject(DEFINITIONS.Struct1, 5, SIMCONNECT_DATA_SET_FLAG.TAGGED, s1);

    displayText("Title: " + s1.title);
    displayText("Lat: " + s1.latitude);
    displayText("Lon: " + s1.longitude);
    displayText("Alt: " + Math.Round(s1.altitude, 0));
    displayText("A/P: " + s1.GearHandlePosition);



    Should be straightforward, but.....
  4. raysot

    raysot

    Joined:
    18/10/06
    Messages:
    14
    Country:
    us-washington
    Ok... I need to see code. I give up...Has anyone out there had any success in writing a value to FSX via C#? There's a slew of posts stating that "Oh yeah.. all you need is -this- or -that- or -the other thing-

    Are there any brave souls that can post a working, extremely short, bug-free example in C#?

    My money is on Black [No]:D :D

    Back in high school, Math story problems were my worst nightmare... If I can "see" a system in action and working, then that whole elusive "Understanding" part starts to fall into place
    ...
  5. Pete Dowson

    Pete Dowson

    Joined:
    25/9/06
    Messages:
    315
    Country:
    unitedkingdom
    Correct, and unfortunately all of the A/P values are examples of those that cannot be written directly. They have to be set by Sim Events, which are merely FS controls (also known as KEY Events in old Gauge-speak, I understand).

    I don't know C# so I can't give examples, but in C/C++ you use the SimConnect_MapClientEventToSimEvent call to associate your own ID with a named Sim Event (I use the Gauges.h defined KEY_ IDs for this), then, when you want to send that event you use Simconnect_TransmitClientEvent.

    The names of the available events are in the Event IDs.htm file, though that's not complete. For a complete list see my list of FSX controls, installed when you install FSUIPC4.

    Regards

    Pete
  6. curious

    curious

    Joined:
    21/10/06
    Messages:
    9
    Here is a very short example of setting a variable in C#:

    Code:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using Microsoft.FlightSimulator.SimConnect;
    using System.Runtime.InteropServices;
    
    namespace SetData
    {
        public partial class Form1 : Form
        {
            // User-defined win32 event
            const int WM_USER_SIMCONNECT = 0x0402;
    
            // SimConnect object
            SimConnect simconnect = null;
    
            enum DEFINITIONS
            {
                Struct1,
            }
    
            enum DATA_REQUESTS
            {
                REQUEST_1,
            };
    
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
            struct Struct1
            {
                public double altitude;
            };
    
            public Form1()
            {
                InitializeComponent();
            }
    
            protected override void DefWndProc(ref Message m)
            {
                if (m.Msg == WM_USER_SIMCONNECT)
                {
                    if (simconnect != null)
                    {
                        simconnect.ReceiveMessage();
                    }
                }
                else
                {
                    base.DefWndProc(ref m);
                }
            }
    
            private void btnConnect_Click(object sender, EventArgs e)
            {
                simconnect = new SimConnect("SetData", this.Handle, WM_USER_SIMCONNECT, null, 0);
    
                simconnect.AddToDataDefinition(DEFINITIONS.Struct1, "Plane Altitude", "feet", SIMCONNECT_DATATYPE.FLOAT64, 0.0f, SimConnect.SIMCONNECT_UNUSED);
    
                simconnect.RegisterDataDefineStruct<Struct1>(DEFINITIONS.Struct1);
            }
    
            private void btnSetData_Click(object sender, EventArgs e)
            {
                Struct1 s1 = new Struct1();
                s1.altitude = 5000;
                simconnect.SetDataOnSimObject(DEFINITIONS.Struct1, SimConnect.SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_DATA_SET_FLAG.DEFAULT, s1);
            }
        }
    }
    There is no fluff for error checking etc, just two buttons. The first connects to FSX, the second sets the aircraft altitude to 5000 feet. I have compiled and tested this code and it works.

    I think the unrecognized id exception you were seeing is because of the 5 that was used for the object id. If there is no object with id 5 (and there probably isn't) then you get the exception. If you want to set data for the user aircraft (which actually has an id of 1) the easiest way to do it is by using the SIMCONNECT_OBJECT_ID_USER constant.

    Also, I think that tagged data is not supported with C#.

    And yes, this SimConnect stuff is hard at first, there are just too many things that need to be just right for it to work :)
  7. Don Lafontaine

    Don Lafontaine

    Joined:
    7/10/06
    Messages:
    3
    Country:
    ca-quebec
    Wow, that's awful. Are you telling me that setting for instance Altitude to hold I would have to send a series of keys? If that's the case, then I hope MS makes some serious changes to Simconnect to allow us to write directly.

    Can you show me a code snippet (In C) on how to set the altitude? I'd like to see what is involved.

    Thanks

    Don Lafontaine
  8. curious

    curious

    Joined:
    21/10/06
    Messages:
    9
    I finally realized that I can view and reply on this forum in threaded mode.

    Here is some more code. This shows how to use events to turn on the autopilot, which I think is what you really wanted to do:

    Code:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using Microsoft.FlightSimulator.SimConnect;
    using System.Runtime.InteropServices;
    
    namespace SetEvent
    {
        public partial class Form1 : Form
        {
            const int WM_USER_SIMCONNECT = 0x0402;
    
            SimConnect simconnect = null;
    
            enum EVENTS
            {
                KEY_AUTOPILOT_ON,
            };
    
            enum GROUP
            {
                ID_PRIORITY_STANDARD = 1900000000,
            };
    
            public Form1()
            {
                InitializeComponent();
            }
    
            protected override void DefWndProc(ref Message m)
            {
                if (m.Msg == WM_USER_SIMCONNECT)
                {
                    if (simconnect != null)
                    {
                        simconnect.ReceiveMessage();
                    }
                }
                else
                {
                    base.DefWndProc(ref m);
                }
            }
    
            private void btnConnect_Click(object sender, EventArgs e)
            {
                simconnect = new SimConnect("SetEvent", this.Handle, WM_USER_SIMCONNECT, null, 0);
            }
    
            private void btnSetEvent_Click(object sender, EventArgs e)
            {
                simconnect.MapClientEventToSimEvent(EVENTS.KEY_AUTOPILOT_ON, "autopilot_on");
    
                simconnect.TransmitClientEvent(SimConnect.SIMCONNECT_OBJECT_ID_USER, EVENTS.KEY_AUTOPILOT_ON, 0, GROUP.ID_PRIORITY_STANDARD , SIMCONNECT_EVENT_FLAG.GROUPID_IS_PRIORITY);
            }
        }
    }
    Again, no error checking or other fluff. The first button makes the connection to FSX, the second button maps the autopilot_on event and then transmits it to FSX. I tested this with the 737 to make sure it works.

    There is a little bit of 'magic' going on that I don't yet understand. There are several priority levels and I found by trail and error that it only works if the priority level is at least 'STANDARD'. This priority level is defined in SimConnect.h as 1900000000, so that is where that number came from (I could not find a definition for it in C#).
  9. raysot

    raysot

    Joined:
    18/10/06
    Messages:
    14
    Country:
    us-washington
    Can you please re-post that code? It looks like the tail-end of the longer statements got truncated.

    Or you can send to raysot @ comcast.net

    Thanks,
    Ray
  10. curious

    curious

    Joined:
    21/10/06
    Messages:
    9
    There should be a horizontal scrollbar underneath the code listing. Using that scrollbar you can see the end of the lines. If that does not work for you (I'm using IE6 and I see the scrollbar) let me know and I'll email you a copy of the code.
  11. raysot

    raysot

    Joined:
    18/10/06
    Messages:
    14
    Country:
    us-washington
    You're right.. My apologies... I need my coffee! :)
  12. curious

    curious

    Joined:
    21/10/06
    Messages:
    9
    Interesting question. I looked through the Event IDs and found "ap_alt_var_set_english", which "sets altitude reference in feet".

    I modified the code to turn on the autopilot that I posted earlier today and much to my surprise it actually worked:

    Code:
            // changed to add an event for the altitude
            enum EVENTS
            {
                KEY_AUTOPILOT_ON,
                KEY_REF_ALT_FEET,
            };
    
            // changed to set the autopilot hold altitude to 5000 feet
            simconnect.MapClientEventToSimEvent(EVENTS.KEY_REF_ALT_FEET, "AP_ALT_VAR_SET_ENGLISH");
            simconnect.TransmitClientEvent(SimConnect.SIMCONNECT_OBJECT_ID_USER, EVENTS.KEY_REF_ALT_FEET, 5000, GROUP.ID_PRIORITY_STANDARD, SIMCONNECT_EVENT_FLAG.GROUPID_IS_PRIORITY);
    This sets the autopilot hold altitude to 5000 feet.
  13. Javier

    Javier

    Joined:
    15/10/06
    Messages:
    31
    Country:
    spain
    Actually I think you still need to toggle it with AP_PANEL_ALTITUDE_HOLD for example but the code is a good one to the original question.

    /Javier.
  14. Pete Dowson

    Pete Dowson

    Joined:
    25/9/06
    Messages:
    315
    Country:
    unitedkingdom
    No! Where's this idea of "a series of keys" come from? Sorry if I misled you someplace.

    There are several Sim Events to set the Altitude on the A/P. Two main ones which do both appear in the dox are

    AP_ALT_VAR_SET_METRIC
    AP_ALT_VAR_SET_ENGLISH

    The altitude (in metres or feet respectively) are the parameter for each, respectively.

    As I said there's a list of most of the Events you can use in the SDK. Didn't you look?

    There's also one called AP_PANEL_ALTITUDE_SET, in the table in FSX's CONTROLS.DLL and therefore listed in my List of FSX controls, but I don't know if that one works -- the ones listed in the official doc certainly do.

    The Sim Event system is pretty much identical to the Trigger_Key_Event system for gauges, as in previous FS versions, and the main KEY_ IDs are listed still in the Gauges header, in the Panels SDK.

    Pete
    Last edited: 26/10/06
  15. Pete Dowson

    Pete Dowson

    Joined:
    25/9/06
    Messages:
    315
    Country:
    unitedkingdom
    In general, unless you only ever wanted to send that once, you should really just do all the Mapping of event IDs during initialisation, then send the actual events as and when needed.

    Then it's just one line each time, same as the gauges "trigger_key_event". In fact I'm reasonably sure that's what this effectively does, just bypassing the PANELS.DLL front-end.

    Regards

    Pete

Share This Page