WRiker2701 Posted December 13, 2022 Report Posted December 13, 2022 Hi i'm working on a C# plugin for Voice Attack which communicates internally with MSFS variables. I integrated FSUIPCs dll into my project, and i managed to code the way to set controls in the aircraft through FSUIPCConnection.SendControlToFS and the PMDG_737_NGX_Control enum. That one was pretty simple. My issue now is to find the way to retrieve the value of a condition variable (the ones listed in the PMDG 737 SDK header file) by inputting the name of the variable. I understand i should use offsets for this, so i am currently trying the following code. "varName" would be the name of the variable as for example "APU_EGTNeedle". "PMDGConditionVariables" is another class that contains a "PMDGVarAddress" Enum with a list of variables and their hex addresses, and a "PMDGVarTypes" enum that contains the same list of variables linked with a number "variableTypeC". This number is then linked with a type of variable so that the GetValue() method can be used differently with each type of variable as it needs to. This should deliver the variable value as a float number and the whole TriggerReqPMDG() method returns the value of the variable so i can use it later with certain purposes. I'm far from being a professional programmer so i'm sure there are maybe more efficient ways to do this, but what worries me at this point is why the code isn't returning the actual variable value, but only zeros. Any variable i ask for delivers a zero after GetValue(). Any ideas? I already edited the 737 options ini file by the way. Cheers! public float TriggerReqPMDG(string varName) { try { float valueFloat = 0; string variableType = "Bool"; int variableLength = 0; FSUIPCConnection.Open(); int address = (int)Enum.Parse(typeof(PMDGConditionVariables.PMDGVarAddress), varName); int variableTypeC = (int)Enum.Parse(typeof(PMDGConditionVariables.PMDGVarTypes), varName); switch (variableTypeC) { case 1: variableLength = 4; variableType = "Float"; break; case 2: variableLength = 2; variableType = "Char"; break; } Offset myOffset = new Offset(address, variableLength); switch (variableType) { case "Float": valueFloat = myOffset.GetValue<float>(); break; case "Uchar": char valueChar = myOffset.GetValue<char>(); valueFloat = Convert.ToInt64(valueChar); break; case "Bool": bool valueBool = myOffset.GetValue<bool>(); valueFloat = Convert.ToInt64(valueBool); break; } FSUIPCConnection.Close(); return valueFloat; Cheers!
Paul Henty Posted December 14, 2022 Report Posted December 14, 2022 Hi, There are a few mistakes: 1. You're not calling Process(): This is the main problem. Process() tells my DLL to get the latest values from FSUIPC. Without that nothing is ever read. Offset myOffset = new Offset(address, variableLength); FSUIPCConnection.Process(); 2. Your first switch statement doesn't contain an entry for 'bool' so the variableLength will be 0. 3. You're trying to convert to float but asking for an Int64... valueFloat = Convert.ToInt64(...); should be: valueFloat = Convert.ToSingle(...); 4. 'bool' and 'char' are not supported by my DLL as they have no equivalents in FSUIPC. Bools in FSUIPC are stored as integers of any size with a value of 0 or 1. For the PMDG offsets they are usually a 'byte' type (Length 1) with the value 0 or 1. You'll need something like this: case "Bool": byte valueByte = myOffset.GetValue<byte>(); valueFloat = Convert.ToSingle(valueByte); valueBool = (valueByte > 0); break; 5. For Char you should use 'string' if you're trying to get back text from the char[] arrays: Of course these is no way to convert these to float: case "Char": string valueString = myOffset.GetValue<string>(); break; The size of the offset should be set to the number of characters in the PMDG documentation: e.g. for AIR_DisplayLandAlt - char[6] : Offset AIR_DisplayLandAlt = new Offset(0x6572, 6); 6. It's best not to keep opening and closing the connection if possible. Open it when your application starts and close it before it unloads. 7. When you create new temporary offsets it's important to dispose of them. If you don't they stay active and take up space in the FSUIPC data table. Eventually your app will crash because the table will be full. Call the myOffset.Disconnect() method when you're finished with it. This will remove it from the FSUIPC table and allow the .NET garbage collector to dispose of it. With those changes you should be able to read proper values. Paul
WRiker2701 Posted December 14, 2022 Author Report Posted December 14, 2022 Thank you for your suggestions! Now it works, cheers!
WRiker2701 Posted December 15, 2022 Author Report Posted December 15, 2022 Sorry How about setting a value to one of these variables? Is something like this okay? string variableType = "NULL"; int variableLength = 0; int address = (int)Enum.Parse(typeof(PMDGConditionVariables.PMDGVarAddress), varName); int variableTypeC = (int)Enum.Parse(typeof(PMDGConditionVariables.PMDGVarTypes), varName); SWITCH GOES IN HERE TO GET variableType and variableLength for each varName. Too long and out of the point for copying it here Offset myOffset = new Offset("", address, variableLength, true); FSUIPCConnection.Process(); (SWITCH GOES IN HERE FOR EACH TYPE CASE) in the case of byte type it continues: String[] strArr = varData.Split('-'); byte[] newValue = new byte[strArr.Length]; for (int i = 0; i < strArr.Length; i++) newValue[i] = Convert.ToByte(strArr[i], 16); myOffset.SetValue(newValue); break; "varData" would be the input data to set the value to, in string type, so this would convert that string into byte array and saves it in "newValue". I've tested this code in other compilations and it works correctly to convert "01-00-01-00" kind of strings. For the case of the rest of types i'm thinking on myOffset.SetValue(varData); break; Just this because i see the SetValue() code converts strings in other numbered types. Then after the break comes this: myOffset.Disconnect(); This code is not working as of now. After trying it the variable doesn't change and the application stops processing new variable requests, so i wanted to know if maybe it's not the right way to set these values. Thanks!
WRiker2701 Posted December 15, 2022 Author Report Posted December 15, 2022 Oh i just noticed in the 737 offset document that these are all READ ONLY. That's probably the issue i guess, my bad if so, for what variables is this SetValue() method useful, events and K variables??
Paul Henty Posted December 15, 2022 Report Posted December 15, 2022 SetValue() can be used on any writable offset which is most of them listed in the FSUIPC Offsets Status pdf. These offsets mainly map to K Variables internally. Events (Also known as controls) can be sent using FSUIPCConnection.SendControlToFS(). The PMDG SDK uses different methods for reading and controlling the aircraft. Using FSUIPC, reading is done with the special offset area. Controlling the aircraft is done by sending controls (events). There are helper Enums built into my DLL for PMDG aircraft (e.g. PMDG_737_NGX_Control). The values of these can be passed to FSUIPCConnection.SendControlToFS(). You also need to send a parameter value with the control. This can be a direct value (e.g. 0 or 1 for simple off/on switches) or a mouse button code to simulate a mouse click. See the PMDG .h file for details of the mouse codes. Paul 1
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now