Jump to content
The simFlight Network Forums

Paul Henty

Members
  • Posts

    1,648
  • Joined

  • Days Won

    74

Posts posted by Paul Henty

  1. FSUIPC only has the height of the cloud layer.

    You could try sampling the weather from various lon/lat points around the aircraft. This might give you a rough idea of how far the clouds extend.

    I'm not sure how slow/fast that will be though, or if it will bear any relation to the clouds you can see on the screen. 

    Paul

  2. Hi Axel,

    It's not possible to target the dll to .NET Standard because it uses some WinForms libraries which are not included in .NET Standard. That's why I have to target net6.0-windows and not plain net6.0.

    In any case, FSUIPC uses the Win32 API for communication so the dll cannot run on any other platform except windows. 

    I can look at adding net7.0-windows to the target frameworks if that would be of any use?

    Paul

  3. I don't have any of the PMDG aircraft so I can't answer any specific questions about them.

    In the SDK I can see controls for the ch selectors, but they don't appear in the readable data structure, so there will be no offset for them. As far as the SDK is concerned these are write-only. I don't know why.

    Maybe ask in the PMDG support forums.

    Paul

  4. Hi Andy,

    The basic FSUIPC weather facilities can tell you the general conditions at either the player location, at lat/lon location, or a weather station (airport). However, it cannot tell you exact positions of clouds etc. You can know the player is in a "broken" cloud layer with rain for example, but you won't know if the player is inside one of the clouds or not.

    Examples of using the weather facilities are in the Example Application. It's not available in FSUIPC7 however. (Uses offset 0xC000).

    Quote

    If not, what would it take to add something that can do this?

    FSUIPC4, 5 and 6 have a link to a third-party weather application called ActiveSky Next, If you have that, FSUIPC can extract a weather radar bitmap or array to a file on the disk. Potentially your application could use that to work out positions of actual clouds\rain (as displayed by ActiveSky). They don't seem to have a version for MSFS though. 

    See the document called "ASN WX Radar facilities in FSUIPC.pdf" in the FSUIPC documents folder.

    Paul

  5. New Offsets:

            public Offset<byte> ELEC_annunBatteryOFF { get; private set; }
            public Offset<byte> FIRE_annunCargoDEPRESS { get; private set; }
            public Offset<byte> MCP_panelPowered { get; private set; }
            public Offset<byte>[] COMM_RadioPanelPowered { get; private set; }
            public Offset<byte>[] COMM_AudioControlPanelPowered { get; private set; }
            public Offset<byte> TCAS_ATC_panelPowered { get; private set; }
            public Offset<byte>[] FIRE_HandleIllumination { get; private set; }
            public Offset<byte> WheelChocksSet { get; private set; }

    New Controls:

            // Window heat & anti-fog power (747-8)
            EVT_OH_WINDHT_ANTIFOG_PWR_SIDE_L = (THIRD_PARTY_EVENT_ID_MIN + 242),
            EVT_OH_WINDHT_ANTIFOG_PWR_SIDE_L_GUARD = (THIRD_PARTY_EVENT_ID_MIN + 10242),
            EVT_OH_WINDHT_ANTIFOG_PWR_FWD_L = (THIRD_PARTY_EVENT_ID_MIN + 243),
            EVT_OH_WINDHT_ANTIFOG_PWR_FWD_L_GUARD = (THIRD_PARTY_EVENT_ID_MIN + 10243),
            EVT_OH_WINDHT_ANTIFOG_PWR_SIDE_R = (THIRD_PARTY_EVENT_ID_MIN + 244),
            EVT_OH_WINDHT_ANTIFOG_PWR_SIDE_R_GUARD = (THIRD_PARTY_EVENT_ID_MIN + 10244),
            EVT_OH_WINDHT_ANTIFOG_PWR_FWD_R = (THIRD_PARTY_EVENT_ID_MIN + 245),
            EVT_OH_WINDHT_ANTIFOG_PWR_FWD_R_GUARD = (THIRD_PARTY_EVENT_ID_MIN + 10245),
    
           EVT_OH_ELEC_TOWING_PWR = (THIRD_PARTY_EVENT_ID_MIN + 287),
            // Overhead Maintenance - EMU MAINT (747-8)
            EVT_OH_EMU_MAINT_PWR_SWITCH = (THIRD_PARTY_EVENT_ID_MIN + 288),
            EVT_OH_EMU_MAINT_PWR_GUARD = (THIRD_PARTY_EVENT_ID_MIN + 10288),
    
            // EFB
            EVT_EFB_L_START = (THIRD_PARTY_EVENT_ID_MIN + 1700),
            EVT_EFB_L_MENU = (EVT_EFB_L_START + 0),
            EVT_EFB_L_BACK = (EVT_EFB_L_START + 1),
            EVT_EFB_L_PAGE_UP = (EVT_EFB_L_START + 2),
            EVT_EFB_L_PAGE_DOWN = (EVT_EFB_L_START + 3),
            EVT_EFB_L_XFR = (EVT_EFB_L_START + 4),
            EVT_EFB_L_ENTER = (EVT_EFB_L_START + 5),
            EVT_EFB_L_ZOOM_IN = (EVT_EFB_L_START + 6),
            EVT_EFB_L_ZOOM_OUT = (EVT_EFB_L_START + 7),
            EVT_EFB_L_ARROW_UP = (EVT_EFB_L_START + 8),
            EVT_EFB_L_ARROW_DOWN = (EVT_EFB_L_START + 9),
            EVT_EFB_L_ARROW_LEFT = (EVT_EFB_L_START + 10),
            EVT_EFB_L_ARROW_RIGHT = (EVT_EFB_L_START + 11),
            EVT_EFB_L_LSK_1L = (EVT_EFB_L_START + 12),
            EVT_EFB_L_LSK_2L = (EVT_EFB_L_START + 13),
            EVT_EFB_L_LSK_3L = (EVT_EFB_L_START + 14),
            EVT_EFB_L_LSK_4L = (EVT_EFB_L_START + 15),
            EVT_EFB_L_LSK_5L = (EVT_EFB_L_START + 16),
            EVT_EFB_L_LSK_6L = (EVT_EFB_L_START + 17),
            EVT_EFB_L_LSK_7L = (EVT_EFB_L_START + 18),
            EVT_EFB_L_LSK_8L = (EVT_EFB_L_START + 19),
            EVT_EFB_L_LSK_1R = (EVT_EFB_L_START + 20),
            EVT_EFB_L_LSK_2R = (EVT_EFB_L_START + 21),
            EVT_EFB_L_LSK_3R = (EVT_EFB_L_START + 22),
            EVT_EFB_L_LSK_4R = (EVT_EFB_L_START + 23),
            EVT_EFB_L_LSK_5R = (EVT_EFB_L_START + 24),
            EVT_EFB_L_LSK_6R = (EVT_EFB_L_START + 25),
            EVT_EFB_L_LSK_7R = (EVT_EFB_L_START + 26),
            EVT_EFB_L_LSK_8R = (EVT_EFB_L_START + 27),
            EVT_EFB_L_BRIGHTNESS = (EVT_EFB_L_START + 28),
            EVT_EFB_L_POWER = (EVT_EFB_L_START + 29),
            EVT_EFB_L_KEY_START = (EVT_EFB_L_START + 30),
            EVT_EFB_L_KEY_A = (EVT_EFB_L_KEY_START + 0),
            EVT_EFB_L_KEY_B = (EVT_EFB_L_KEY_START + 1),
            EVT_EFB_L_KEY_C = (EVT_EFB_L_KEY_START + 2),
            EVT_EFB_L_KEY_D = (EVT_EFB_L_KEY_START + 3),
            EVT_EFB_L_KEY_E = (EVT_EFB_L_KEY_START + 4),
            EVT_EFB_L_KEY_F = (EVT_EFB_L_KEY_START + 5),
            EVT_EFB_L_KEY_G = (EVT_EFB_L_KEY_START + 6),
            EVT_EFB_L_KEY_H = (EVT_EFB_L_KEY_START + 7),
            EVT_EFB_L_KEY_I = (EVT_EFB_L_KEY_START + 8),
            EVT_EFB_L_KEY_J = (EVT_EFB_L_KEY_START + 9),
            EVT_EFB_L_KEY_K = (EVT_EFB_L_KEY_START + 10),
            EVT_EFB_L_KEY_L = (EVT_EFB_L_KEY_START + 11),
            EVT_EFB_L_KEY_M = (EVT_EFB_L_KEY_START + 12),
            EVT_EFB_L_KEY_N = (EVT_EFB_L_KEY_START + 13),
            EVT_EFB_L_KEY_O = (EVT_EFB_L_KEY_START + 14),
            EVT_EFB_L_KEY_P = (EVT_EFB_L_KEY_START + 15),
            EVT_EFB_L_KEY_Q = (EVT_EFB_L_KEY_START + 16),
            EVT_EFB_L_KEY_R = (EVT_EFB_L_KEY_START + 17),
            EVT_EFB_L_KEY_S = (EVT_EFB_L_KEY_START + 18),
            EVT_EFB_L_KEY_T = (EVT_EFB_L_KEY_START + 19),
            EVT_EFB_L_KEY_U = (EVT_EFB_L_KEY_START + 20),
            EVT_EFB_L_KEY_V = (EVT_EFB_L_KEY_START + 21),
            EVT_EFB_L_KEY_W = (EVT_EFB_L_KEY_START + 22),
            EVT_EFB_L_KEY_X = (EVT_EFB_L_KEY_START + 23),
            EVT_EFB_L_KEY_Y = (EVT_EFB_L_KEY_START + 24),
            EVT_EFB_L_KEY_Z = (EVT_EFB_L_KEY_START + 25),
            EVT_EFB_L_KEY_0 = (EVT_EFB_L_KEY_START + 26),
            EVT_EFB_L_KEY_1 = (EVT_EFB_L_KEY_START + 27),
            EVT_EFB_L_KEY_2 = (EVT_EFB_L_KEY_START + 28),
            EVT_EFB_L_KEY_3 = (EVT_EFB_L_KEY_START + 29),
            EVT_EFB_L_KEY_4 = (EVT_EFB_L_KEY_START + 30),
            EVT_EFB_L_KEY_5 = (EVT_EFB_L_KEY_START + 31),
            EVT_EFB_L_KEY_6 = (EVT_EFB_L_KEY_START + 32),
            EVT_EFB_L_KEY_7 = (EVT_EFB_L_KEY_START + 33),
            EVT_EFB_L_KEY_8 = (EVT_EFB_L_KEY_START + 34),
            EVT_EFB_L_KEY_9 = (EVT_EFB_L_KEY_START + 35),
            EVT_EFB_L_KEY_SPACE = (EVT_EFB_L_KEY_START + 36),
            EVT_EFB_L_KEY_PLUS = (EVT_EFB_L_KEY_START + 37),
            EVT_EFB_L_KEY_MINUS = (EVT_EFB_L_KEY_START + 38),
            EVT_EFB_L_KEY_DOT = (EVT_EFB_L_KEY_START + 39),
            EVT_EFB_L_KEY_SLASH = (EVT_EFB_L_KEY_START + 40),
            EVT_EFB_L_KEY_BACKSPACE = (EVT_EFB_L_KEY_START + 41),
            EVT_EFB_L_KEY_DEL = (EVT_EFB_L_KEY_START + 42),
            EVT_EFB_L_KEY_EQUAL = (EVT_EFB_L_KEY_START + 43),
            EVT_EFB_L_KEY_MULTIPLY = (EVT_EFB_L_KEY_START + 44),
            EVT_EFB_L_KEY_LEFT_PAR = (EVT_EFB_L_KEY_START + 45),
            EVT_EFB_L_KEY_RIGHT_PAR = (EVT_EFB_L_KEY_START + 46),
            EVT_EFB_L_KEY_QUEST = (EVT_EFB_L_KEY_START + 47),
            EVT_EFB_L_KEY_QUOTE = (EVT_EFB_L_KEY_START + 48),
            EVT_EFB_L_KEY_COMMA = (EVT_EFB_L_KEY_START + 49),
            EVT_EFB_L_KEY_PAGE_UP = (EVT_EFB_L_KEY_START + 50),
            EVT_EFB_L_KEY_PAGE_DOWN = (EVT_EFB_L_KEY_START + 51),
            EVT_EFB_L_KEY_ENTER = (EVT_EFB_L_KEY_START + 52),
            EVT_EFB_L_KEY_ARROW_UP = (EVT_EFB_L_KEY_START + 53),
            EVT_EFB_L_KEY_ARROW_DOWN = (EVT_EFB_L_KEY_START + 54),
            EVT_EFB_L_KEY_END = (EVT_EFB_L_KEY_START + 54),
            EVT_EFB_L_END = (EVT_EFB_L_KEY_START + 54),
            EVT_EFB_R_START = (EVT_EFB_L_END + 1),
            EVT_EFB_R_MENU = (EVT_EFB_R_START + 0),
            EVT_EFB_R_BACK = (EVT_EFB_R_START + 1),
            EVT_EFB_R_PAGE_UP = (EVT_EFB_R_START + 2),
            EVT_EFB_R_PAGE_DOWN = (EVT_EFB_R_START + 3),
            EVT_EFB_R_XFR = (EVT_EFB_R_START + 4),
            EVT_EFB_R_ENTER = (EVT_EFB_R_START + 5),
            EVT_EFB_R_ZOOM_IN = (EVT_EFB_R_START + 6),
            EVT_EFB_R_ZOOM_OUT = (EVT_EFB_R_START + 7),
            EVT_EFB_R_ARROW_UP = (EVT_EFB_R_START + 8),
            EVT_EFB_R_ARROW_DOWN = (EVT_EFB_R_START + 9),
            EVT_EFB_R_ARROW_LEFT = (EVT_EFB_R_START + 10),
            EVT_EFB_R_ARROW_RIGHT = (EVT_EFB_R_START + 11),
            EVT_EFB_R_LSK_1L = (EVT_EFB_R_START + 12),
            EVT_EFB_R_LSK_2L = (EVT_EFB_R_START + 13),
            EVT_EFB_R_LSK_3L = (EVT_EFB_R_START + 14),
            EVT_EFB_R_LSK_4L = (EVT_EFB_R_START + 15),
            EVT_EFB_R_LSK_5L = (EVT_EFB_R_START + 16),
            EVT_EFB_R_LSK_6L = (EVT_EFB_R_START + 17),
            EVT_EFB_R_LSK_7L = (EVT_EFB_R_START + 18),
            EVT_EFB_R_LSK_8L = (EVT_EFB_R_START + 19),
            EVT_EFB_R_LSK_1R = (EVT_EFB_R_START + 20),
            EVT_EFB_R_LSK_2R = (EVT_EFB_R_START + 20),
            EVT_EFB_R_LSK_3R = (EVT_EFB_R_START + 22),
            EVT_EFB_R_LSK_4R = (EVT_EFB_R_START + 23),
            EVT_EFB_R_LSK_5R = (EVT_EFB_R_START + 24),
            EVT_EFB_R_LSK_6R = (EVT_EFB_R_START + 25),
            EVT_EFB_R_LSK_7R = (EVT_EFB_R_START + 26),
            EVT_EFB_R_LSK_8R = (EVT_EFB_R_START + 27),
            EVT_EFB_R_BRIGHTNESS = (EVT_EFB_R_START + 28),
            EVT_EFB_R_POWER = (EVT_EFB_R_START + 29),
            EVT_EFB_R_KEY_START = (EVT_EFB_R_START + 30),
            EVT_EFB_R_KEY_A = (EVT_EFB_R_KEY_START + 0),
            EVT_EFB_R_KEY_B = (EVT_EFB_R_KEY_START + 1),
            EVT_EFB_R_KEY_C = (EVT_EFB_R_KEY_START + 2),
            EVT_EFB_R_KEY_D = (EVT_EFB_R_KEY_START + 3),
            EVT_EFB_R_KEY_E = (EVT_EFB_R_KEY_START + 4),
            EVT_EFB_R_KEY_F = (EVT_EFB_R_KEY_START + 5),
            EVT_EFB_R_KEY_G = (EVT_EFB_R_KEY_START + 6),
            EVT_EFB_R_KEY_H = (EVT_EFB_R_KEY_START + 7),
            EVT_EFB_R_KEY_I = (EVT_EFB_R_KEY_START + 8),
            EVT_EFB_R_KEY_J = (EVT_EFB_R_KEY_START + 9),
            EVT_EFB_R_KEY_K = (EVT_EFB_R_KEY_START + 10),
            EVT_EFB_R_KEY_L = (EVT_EFB_R_KEY_START + 11),
            EVT_EFB_R_KEY_M = (EVT_EFB_R_KEY_START + 12),
            EVT_EFB_R_KEY_N = (EVT_EFB_R_KEY_START + 13),
            EVT_EFB_R_KEY_O = (EVT_EFB_R_KEY_START + 14),
            EVT_EFB_R_KEY_P = (EVT_EFB_R_KEY_START + 15),
            EVT_EFB_R_KEY_Q = (EVT_EFB_R_KEY_START + 16),
            EVT_EFB_R_KEY_R = (EVT_EFB_R_KEY_START + 17),
            EVT_EFB_R_KEY_S = (EVT_EFB_R_KEY_START + 18),
            EVT_EFB_R_KEY_T = (EVT_EFB_R_KEY_START + 19),
            EVT_EFB_R_KEY_U = (EVT_EFB_R_KEY_START + 20),
            EVT_EFB_R_KEY_V = (EVT_EFB_R_KEY_START + 21),
            EVT_EFB_R_KEY_W = (EVT_EFB_R_KEY_START + 22),
            EVT_EFB_R_KEY_X = (EVT_EFB_R_KEY_START + 23),
            EVT_EFB_R_KEY_Y = (EVT_EFB_R_KEY_START + 24),
            EVT_EFB_R_KEY_Z = (EVT_EFB_R_KEY_START + 25),
            EVT_EFB_R_KEY_0 = (EVT_EFB_R_KEY_START + 26),
            EVT_EFB_R_KEY_1 = (EVT_EFB_R_KEY_START + 27),
            EVT_EFB_R_KEY_2 = (EVT_EFB_R_KEY_START + 28),
            EVT_EFB_R_KEY_3 = (EVT_EFB_R_KEY_START + 29),
            EVT_EFB_R_KEY_4 = (EVT_EFB_R_KEY_START + 30),
            EVT_EFB_R_KEY_5 = (EVT_EFB_R_KEY_START + 31),
            EVT_EFB_R_KEY_6 = (EVT_EFB_R_KEY_START + 32),
            EVT_EFB_R_KEY_7 = (EVT_EFB_R_KEY_START + 33),
            EVT_EFB_R_KEY_8 = (EVT_EFB_R_KEY_START + 34),
            EVT_EFB_R_KEY_9 = (EVT_EFB_R_KEY_START + 35),
            EVT_EFB_R_KEY_SPACE = (EVT_EFB_R_KEY_START + 36),
            EVT_EFB_R_KEY_PLUS = (EVT_EFB_R_KEY_START + 37),
            EVT_EFB_R_KEY_MINUS = (EVT_EFB_R_KEY_START + 38),
            EVT_EFB_R_KEY_DOT = (EVT_EFB_R_KEY_START + 39),
            EVT_EFB_R_KEY_SLASH = (EVT_EFB_R_KEY_START + 40),
            EVT_EFB_R_KEY_BACKSPACE = (EVT_EFB_R_KEY_START + 41),
            EVT_EFB_R_KEY_DEL = (EVT_EFB_R_KEY_START + 42),
            EVT_EFB_R_KEY_EQUAL = (EVT_EFB_R_KEY_START + 43),
            EVT_EFB_R_KEY_MULTIPLY = (EVT_EFB_R_KEY_START + 44),
            EVT_EFB_R_KEY_LEFT_PAR = (EVT_EFB_R_KEY_START + 45),
            EVT_EFB_R_KEY_RIGHT_PAR = (EVT_EFB_R_KEY_START + 46),
            EVT_EFB_R_KEY_QUEST = (EVT_EFB_R_KEY_START + 47),
            EVT_EFB_R_KEY_QUOTE = (EVT_EFB_R_KEY_START + 48),
            EVT_EFB_R_KEY_COMMA = (EVT_EFB_R_KEY_START + 49),
            EVT_EFB_R_KEY_PAGE_UP = (EVT_EFB_R_KEY_START + 50),
            EVT_EFB_R_KEY_PAGE_DOWN = (EVT_EFB_R_KEY_START + 51),
            EVT_EFB_R_KEY_ENTER = (EVT_EFB_R_KEY_START + 52),
            EVT_EFB_R_KEY_ARROW_UP = (EVT_EFB_R_KEY_START + 53),
            EVT_EFB_R_KEY_ARROW_DOWN = (EVT_EFB_R_KEY_START + 54),
            EVT_EFB_R_KEY_END = (EVT_EFB_R_KEY_START + 54),
            EVT_EFB_R_END = (EVT_EFB_R_KEY_START + 54),
            // Parameter: 1000000 x (action code) + 1000 x (X Coordinate) + (Y Coordinate)
            // action codes: 0 = mouse move, 1 = mouse click, 2= mouse release, 3 = mouse wheel up, 4 = mouse wheel down
            // X / Y Coordinates: 0..1000 of EFB_SCREEN_WIDTH / EFB_SCREEN_HEIGHT (not required for action codes 3 & 4)
            EVT_EFB_L_SCREEN_ACTION = (THIRD_PARTY_EVENT_ID_MIN + 1900),
            EVT_EFB_R_SCREEN_ACTION = (THIRD_PARTY_EVENT_ID_MIN + 1901),
    
            // Internal use
            EVT_SC_SENSORS_START = (THIRD_PARTY_EVENT_ID_MIN + 14650),
            EVT_SC_SENSOR_THROTTLE_1 = (EVT_SC_SENSORS_START + 0),
            EVT_SC_SENSOR_THROTTLE_2 = (EVT_SC_SENSORS_START + 1),
            EVT_SC_SENSOR_THROTTLE_3 = (EVT_SC_SENSORS_START + 2),
            EVT_SC_SENSOR_THROTTLE_4 = (EVT_SC_SENSORS_START + 3),
            EVT_SC_SENSOR_REVERSER_1 = (EVT_SC_SENSORS_START + 4),
            EVT_SC_SENSOR_REVERSER_2 = (EVT_SC_SENSORS_START + 5),
            EVT_SC_SENSOR_REVERSER_3 = (EVT_SC_SENSORS_START + 6),
            EVT_SC_SENSOR_REVERSER_4 = (EVT_SC_SENSORS_START + 7),
            EVT_SC_SENSOR_SPEEDBRAKE = (EVT_SC_SENSORS_START + 8),
            EVT_SC_SENSOR_FLAPS = (EVT_SC_SENSORS_START + 9),
            EVT_SC_SENSORS_LAST = EVT_SC_SENSOR_FLAPS,
            EVT_SC_AXIS_START = (THIRD_PARTY_EVENT_ID_MIN + 14680),
            EVT_SC_AXIS_OUTBD_DISPL_CAPT = (EVT_SC_AXIS_START + 0),
            EVT_SC_AXIS_INBD_DISPL_CAPT = (EVT_SC_AXIS_START + 1),
            EVT_SC_AXIS_EICAS_UPR = (EVT_SC_AXIS_START + 2),
            EVT_SC_AXIS_EICAS_LWR = (EVT_SC_AXIS_START + 3),
            EVT_SC_AXIS_INBD_DISPL_FO = (EVT_SC_AXIS_START + 4),
            EVT_SC_AXIS_OUTBD_DISPL_FO = (EVT_SC_AXIS_START + 5),
            EVT_SC_AXIS_INBD_TERR_CAPT = (EVT_SC_AXIS_START + 6),
            EVT_SC_AXIS_INBD_TERR_FO = (EVT_SC_AXIS_START + 7),
            EVT_SC_AXIS_EICAS_LWR_TERR = (EVT_SC_AXIS_START + 8),
            EVT_SC_AXIS_LAST = EVT_SC_AXIS_EICAS_LWR_TERR,

    Paul

  6. Okay, just tried here in a new 4.8 winforms app and works okay:

            private async void button1_Click(object sender, EventArgs e)
            {
                FSUIPCConnection.Open();
                AirportsDatabase db = FSUIPCConnection.AirportsDatabase;
                await db.RebuildDatabaseAsync();
                MessageBox.Show("Done");
            }
    Quote

    we aren't getting any response from RebuildDatabaseAsync

    Are you using await? If not, it will just start the rebuild on a background thread and your code will just continue.

    Paul

  7. Hi Andy,

    The example code solutions had the nuget paths messed up because I was using them in a larger project.

    I've sorted them out and re-uploaded them. Please download the latest from the website - 1.4.1.

    If you can get that to work then we'll look at the problem you're having in your app.

    A couple of questions

    What version of .NET is your application targeting?

    Are you getting any callbacks to the progress class?

    Paul 

  8. Hi Andy,

    Thanks for the report. I've added the second APUFieldReset offset. 

    Version 3.3.1 is now on NuGet.

    The events seem to have both switches there already:

            EVT_OH_ELEC_APU_FIELD1_SWITCH = (THIRD_PARTY_EVENT_ID_MIN + 278),
            EVT_OH_ELEC_APU_FIELD1_GUARD = (THIRD_PARTY_EVENT_ID_MIN + 10278),
            EVT_OH_ELEC_APU_FIELD2_SWITCH = (THIRD_PARTY_EVENT_ID_MIN + 279),
            EVT_OH_ELEC_APU_FIELD2_GUARD = (THIRD_PARTY_EVENT_ID_MIN + 10279),

    Paul

     

  9. Jason, Andy.

    The new version 3.3.0 is now on NuGet with the changes outlined above.

    You will need to rewrite some of your Airports Database code to use the new methods. The strategy is to limit the data you load into RAM and the number of airports you process when calling SetReferenceLocation().

    Details are in this post:

    More detailed examples are available in the Example Code application. Link in the post above.

    Sorry you have to change your code, but it just could work the way it was. 

    Let me know if you need any help with it.

    Paul

     

  10. Version 3.3.0 is now on NuGet with the change to the TextMenu I mentioned (The menu is now kept when a single line message arrives).

    Note there are also extensive breaking changes to the Airports Database if you're using that feature.

    Also if you're using .NET 4 Framework, the DLL no longer supports 4.0 as it's now out of support. It now targets 4.6.2 instead.

    Paul

  11. Introduction

    Version 3.3.0 of the FSUIPCClientDLL has significant changes to the Airports Database module. This post explains why this was needed, the main differences and quick exmples of how to use this feature from V3.3.0 onwards.

    More detailed examples can be found in the Example Code Applications (C# / VB.NET) available on the website:

    http://fsuipc.paulhenty.com/#downloads

    Full details of all changes in V3.3.0 can be found here:

    http://fsuipc.paulhenty.com/#revisionHistory


    Why change it?

    The feature was first introduced around the time of FSX and early P3D versions. These products shared the same airports database and was small enough that everything could be comfortably stored in RAM (roughly 300mb). This included all airports, gates, helipads, runways and taxiways.

    The information was read directly from the MakeRunways text files (.csv/.xml) when the application started and stored in RAM for the lifetime of the application.

    With modern flight simulators and scenery (especially MSFS) this method of dealing with the Airports Database has become unworkable. 

    The default scenery from a standard install of MSFS takes up over 3GB of RAM. That's a lot for an application to take up, especially one running on the Flight Sim machine. Processing this amount of information makes the application run slowly (e.g. setting the Reference Position on all airports). Also, the time taken to read and parse the MakeRunways text files is now quite slow. It's not good to have to wait for this process to complete every time your application starts.

    The Airports Database has been partially redesigned and rewritten to work with the large amount of data from the latest Flight Simulators.

    Instead of holding the data in memory, it is instead held in binary files on the hard disk in a way that it can be accessed very quickly.

    The importing of the MakeRunways files only needs to be done when they have changed (or if it's the first time you or your users have used your application). After that the data is read from the binary files, so your application's start up can be much faster.

    There is also more control over what gets loaded into RAM and what data gets processed. Whereas before, all airports, runways, gates etc were loaded into RAM and processed, the new Airports Database lets you control this so you only load and process the data your application needs.

    For example, if you need to know which taxiway the player is on, you can now do so by only loading taxiways for that airport and only testing that airport.

    The new ways of using the Airports Database require a little more thought and care than the old way, but the old way is just too inefficient to work on large datasets.


    Things that haven't changed:

    The database objects (FsAirport, FsRunway, FsGate etc) have not changed. Your current code that uses these objects will not need to be changed.


    The differences:

    Data Stored in Binary Files

    The data is not read from the MakeRunways output files every time your application starts. The MakeRunways data is parsed and then stored in binary files in a way that the data can be quickly accessed. The data is read from these binary files. The MakeRunways data only needs to be imported (parsed) again if they change.


    Control of loading of Components (Runways, Gates, Taxiways etc)

    When you load the database initially, the only data that's loaded is the list of all airports. No component data (Runways, Gates, Taxiways etc) is loaded. If you want that information you can request that it's loaded. This can be done for a single airport or a collection of airports. 

    This keeps the memory footprint down.


    Collections of Airports

    When you load the database you get a collection containing all airports. You're free to use that collection if your application requires it (e.g. flight planning). However, if you're application only needs to work with a subset of airports (e.g. airports in a 100nm range of the player, or a specific list of airports used by a Virtual Airline) you can create a new collection of airports that is more relevant to your application. You can do this manually or by filtering the main airports collection.

    This means you are only processing airports and loading data that is relevant to your application. This improves memory usage and processing times.


    Managing the Database as your Application Runs

    Throughout the lifetime of your application, you may use combinations of the above techniques to keep the memory use and processing times to a minimum. 

    Here's an example: You might use the full airports list to get the airports in 60nm of the player. Then you might load runways for those airports to find those with ILS facilities. Then after the user picks an airport you might load Gate information for that single airport so the player can choose a gate. Your application might then keep checking that FsGate object to known when the player has arrived there.


    Integration with AITrafficServices

    Integration with AITrafficServices is no longer automatic. If you want the integrated features you need to pass a collection of airports (or a single airport) and the components you wish to process to AITrafficServices.RefreshAITrafficInformation(). 

    Note that this method automatically loads component information on demand as it's required. There's no way for you to know what needs to be loaded in advance.

     

    (Re)Building the Database:

    The database needs to be built before you can use the database and also whenever the MakeRunways output files change. This is typically when the user has updated their scenery.

    The rebuild method runs in the background so it doesn't block the User Interface.

    The easiest way to call this method is with the Async-Await pattern. This will wait until the rebuild in complete and then continue executing your code. E.g.

    C#

    private async void btnRebuild_Click(object sender, EventArgs e)
    {
         AirportsDatabase db = FSUIPCConnection.AirportsDatabase;
         await db.RebuildDatabaseAsync();
         MessageBox.Show("Rebuild Complete");
    }

    VB.NET

    Private Async Sub btnRebuild_Click(ByVal sender As Object, ByVal e As EventArgs)
         Dim db = FSUIPCConnection.AirportsDatabase
         Await db.RebuildDatabaseAsync()
         MessageBox.Show("Rebuild Complete")
    End Sub

    You can also pass a Progress object to RebuildDatabaseAsync to receive progress reports during the rebuild. See the Example Code application for this. 


    Usage:

    1. Get a reference to the Airports Database:

    C#

    AirportsDatabase db = FSUIPCConnection.AirportsDatabase;

    VB.NET

    Dim db = FSUIPCConnection.AirportsDatabase


    2. Set the Make Runways Folder (Optional)

    You can optionally set a path to the MakeRunways output files. If you are using the database with an open FSUIPC Connection this path will be set automatically to the flight simulator main folder. This is where the MakeRunways files are by default.

    If you're using the database without an FSUIPC Connection, or want to point to a different folder than the default you can set the MakeRunwaysFolder property.

    C#

    db.MakeRunwaysFolder = @"C:\Path\To\MakeRunways\Output\Files";

    VB.NET

    db.MakeRunwaysFolder = "C:\Path\To\MakeRunways\Output\Files"


    3. Load the Database:

    Call Load() to load in the main collection of airports.

    C#

    if (db.DatabaseFilesExist)
    {
        db.Load();
    }

    VB.NET

    If db.DatabaseFilesExist Then
       db.Load()
    End If

    4. Get a specific airport using the ICAO indexer:

    C#

    FsAirport heathrow = db.Airports["EGLL"];

    VB.NET

    Dim heathrow = db.Airports("EGLL")


    5a. Get a cut-down collection of airports by filtering the main collection 

    C#

    FsAirportCollection localAirports = db.Airports.InRangeOfKilometres(80);
    FsAirportCollection londonAirports = db.Airports.FindAll(ap => ap.City == "London" && ap.Country == "United Kingdom");

    VB.NET

    Dim localAirports = db.Airports.InRangeOfKilometres(80)
    Dim londonAirports = db.Airports.FindAll(Function(ap) Equals(ap.City, "London") AndAlso Equals(ap.Country, "United Kingdom"))


    5b. Or make your own custom collection of airports:

    C#

    string[] virtualAirlineAirportCodes = new string[] { "EGLL", "LFPG", "EDDF", "EIDW", "EGPF", "EGJJ" };
    FsAirportCollection virtualAirlineAiports = new FsAirportCollection();
    foreach(string icao in virtualAirlineAirportCodes)
    {
        virtualAirlineAiports.Add(db.Airports[icao]);
    }

    VB.NET

    Dim virtualAirlineAirportCodes = New String() {"EGLL", "LFPG", "EDDF", "EIDW", "EGPF", "EGJJ"}
    Dim virtualAirlineAiports As FsAirportCollection = New FsAirportCollection()
    For Each icao In virtualAirlineAirportCodes
        virtualAirlineAiports.Add(db.Airports(icao))
    Next

    7. Load components for an individual airport or a collection 

    C#

    heathrow.LoadComponents(AirportComponents.Runways | AirportComponents.Gates);
    virtualAirlineAiports.LoadComponents(AirportComponents.All);

    VB.NET

    heathrow.LoadComponents(AirportComponents.Runways Or AirportComponents.Gates)
    virtualAirlineAiports.LoadComponents(AirportComponents.All)


    8. Use the component information after loading:

    C#

    foreach(FsRunway rw in heathrow.Runways)
    {
        this.cbxRunways.Items.Add(rw.ID + " (" + rw.LengthFeet.ToString("N0") + " ft)");
    }

    VB.NET

    For Each rw In heathrow.Runways
        cbxRunways.Items.Add(rw.ID & " (" & rw.LengthFeet.ToString("N0") & " ft)")
    Next

    9. Set the Reference Location for an individual airport or a collection:

    This will calculate the distance, bearing etc to the airport or each airport in the collection.

    You can choose which loaded components are processed.

    Setting reference location for all airports in the collection (No components processed - distance, bearings and boundary checks for airports only).

    C#

    localAirports.SetReferenceLocation(AirportComponents.None);

    VB.NET

    localAirports.SetReferenceLocation(AirportComponents.None)

    Setting reference location for one airport. Also calculate distance, bearings, boundary checks for runways and gates:

    C#

    heathrow.SetReferenceLocation(AirportComponents.Runways | AirportComponents.Gates);

    VB.NET

    heathrow.SetReferenceLocation(AirportComponents.Runways Or AirportComponents.Gates)

    10. Fill in the AITraffic Properties by passing a collection to the AITrafficServices.

    This example will populate the airport, runway and gate information for AITraffic for all virtual airline airports. 

    C#

    AITrafficServices traffic = FSUIPCConnection.AITrafficServices;
    traffic.RefreshAITrafficInformation(virtualAirlineAiports, AirportComponents.Runways | AirportComponents.Gates);

    VB.NET

    Dim traffic = FSUIPCConnection.AITrafficServices
    traffic.RefreshAITrafficInformation(virtualAirlineAiports, AirportComponents.Runways Or AirportComponents.Gates)

    Paul

     

    • Thanks 1
  12. I've made some changes to the TextMenu helper. 

    The TextMenu class is just a helper for the 0xB000 offset in FSUIPC. I can only supply the information I get from that offset.

    The way this offset works is that it holds the LAST message that was sent to the screen (regardless of if it was single line or a menu). If a menu appears and then a single line message B000 will only contain the single line message. 

    However, I have changed my DLL so that TextMenu will now keep the last Menu data until a new Menu message arrives. Same with single line messages. Note however that ToString() will still only return the last message, and IsMenu will still only refer to the last message. 

    The menu data will only be cleared when a Menu message arrives with no text. On FSX this happens if the user clears the menu themselves, but not if the menu is closed by the application (eg. GSX). It might be different in P3D. If not, then there's no way you can tell when menus get closed by GSX. This is a limitation of either FSUIPC or SimConnect.

    Note also that in FSX the single line messages never receive a 'cleared' message. So the last single line message will stay until a new single line message arrives.

    The changes will be in the next version (3.3.0) which will be available in week or two. I'll let you know when it's out.

    Quote
    • Once a menu has been shown .isMenu stays True (is False unless Menu has been shown first time)

    I can't see that with FSX/FSUIPC4. If it's happening with P3D it might be a problem with FSUIPC6. You can monitor offset 0xB004 (4 byte int) to test this yourself. Single line messages are 0 & 1, Menu = 2. I can only pass on what FSUIPC gives me.

    Quote

    Changed stays True in any case I tested, even if the menu disappears

    Again, not with FSUIPC4. The changed flag is true when the value in offset 0xB000 (4-byte int) changes. This indicates if a new message has arrived. It shouldn't be true all the time. If a menu get's cleared and a clear message is received then Changed should be true the next time you call RefreshData(). After that is should be false (until a new message arrives). You can monitor 0XB000 to see what FSUIPC is sending.

    Paul  

  13. Happy New Year to you too.

    This current behaviour is by design as it follows FSUIPC behaviour. The same offset is used to read single line messages and multiline menus, so menus get overwritten by messages in FSUIPC. This allow users to read the last message that was sent and also know when messages are removed from the screen.

    There might be something I can do/suggest, but are two things I'm not clear on...

    1. When a menu is on the screen and a new single-line message arrives, does the menu disappear or is it still on the screen and functional?

    2. Do you want the menu items available even when the menu has gone from the screen (But a new menu has not arrived)?

    Paul

  14. I've had a look at the Load() and SetReferenceLocation() functions. There is no more optimisation that can be done. The problem is just the amount of data it has to load and work through.

    The solution to this is to rewrite the airports database to make is possible to only load the airports/data you need or is relevant at the time. This will do two things:

    1. Limit the memory taken by your application

    2. Make the SetReferenceLocation() much faster because it's not calculating distances to every runway on the planet.

    This will mean rewriting your code airports database a little, but the current system is not viable.

    I'm going to use a database to store the airport information on the disk in a way that it can be retrieved very quickly. (Parsing the CSV files is slow so this will only need to be done when the MakeRunways files change). A side benefit of this is that your application won't need to go through the lengthy Load() procedure every time it starts up.

    This will probably take a few weeks as I also need to update the example code projects.

    In the mean time you might be able to improve the situation in your application by not loading data you don't need. For example if you don't use the Taxiway information then turn it off with AirportsDatabase.LoadTaxiways = false. Same with any other data you don't use.

    Paul

       

  15. So after some investigation, the problem is the mainly the MSFS taxiways. They seem to be made up of many more segments than FSX. 

    When I wrote the airports database in the FSX days it was no problem loading everything into memory. The database with all taxiways only took about 600mb and the SetReferencePosition() only takes around 70ms on my machine.

    With the MSFS data, the entire in-memory database (with Taxiways) is now 2.6Gb. This is quite a large program to be running on the MSFS computer.

    The main problem however is that the SetReferencePosition() now takes 350ms. If you're trying to run that every 250ms you can see the problem - it's longer than the timer tick,

    I assume you're loading the Taxiways because I remember you having a feature to give call outs of which taxiway the pilot was on. Perhaps you can confirm.

    Loading the entire database into memory is just not feasible now with MSFS. It's not just a question of making optimisations, it really needs a rethink of how the database is handled and when things get loaded. 

    I'll see if I can come up with a plan over the next few days.  I'll keep you updated.

    Paul

  16. Hi Andy,

    So if I understand correctly it's not the actual loading of the database (AirportsDatabase.Load()) that causes the issues, it's repeatedly calling the SetReferenceLocation() with a large airports database.

    Quote

    Is there any other way to constantly track the users location in the world?

    SetReferenceLocation() updates the AirportsDatabase using the current location. It will calculate the distance to the nearby airports, what runway you are on (if you're in the boundary of the airport) etc.

    If that's what you need every 250ms then there's no other way to do that.

    If you only need to know the players Lon/Lat you can just use the offsets that provide that information.

    If you can confirm that SetReferenceLocation() is the problem I will see if I can optimise it. It would be best if I have the large MSFS generated database to work with. If you have an easy way to get it to me (e.g. Google drive/Dropbox link) please send it to me in a private message on here. Otherwise I can maybe fake a larger database with the FSX one.

    Also, are you using the AI Traffic services as well?

    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.