brandonharwood14 Posted September 16, 2023 Report Posted September 16, 2023 Hi Paul, Firstly thank you for all the documentation and work you have put in along side all the other contributors of FSUIPC and the WAPI. I'm hoping to gain some insight on the information below. A bit of backstory before I get to the main talking points: I am trying to create my own C# application to work in conjunction with my hardware for my company. Where the use of Arduino based microcontrollers or my own custom microcontrollers send serial data via USB to the PC and C# program which in tern translates that into events or appropriate code to be sent to flight simulator. I have completed the program for X-Plane but now moving on to MSFS2020 there are many more hurdles to overcome. I am hoping to use my C# program in conjunction with your WASM module and FSUIPC to achieve all the functionality needed for various avionics units. From what I can work out some functionality for certain things in FS2020 are achieved via the use of WASM modules, LVars and HVars. I believe are the ones in particular that I would be interested in given my software only needs to send events to the simulator for avionics. GNS530/430, GTN750,650 G1000, G3000 etc. So my question is how/what is the best way to send this information to the flight simulator. is Calculator code the best way to send not only standard events but also L/Hvars? or as mentioned by John in this thread is the use of Presets the better option. As for presets, how are they supposed to be typed into the C# code or is there a txt file that needs to be placed somewhere specific and then references in C#? in VS2022 I have so far been able to connect to FSUIPC and send basic events to the simulator such as turning avionics on and off. selecting the GPS drives nav1. But no matter how hard I try I cannot figure out how to use calculator code nor presets. How is this sent to the simulator and could you please give me a C# example of this? I have been through your example code but still have come up at a loss. sorry! Any help would be greatly appreciated. Thanks - Brandon
Paul Henty Posted September 16, 2023 Report Posted September 16, 2023 Hi Brandon, Quote how/what is the best way to send this information to the flight simulator. is Calculator code the best way to send not only standard events but also L/Hvars? or as mentioned by John in this thread is the use of Presets the better option. Presets are just containers for calculator code, so they end up executing calculator code eventually. They are useful in the FSUIPC front-end, but if you are using code then it's just an extra step. Also the way you call presets from code via FSUIPC is not very efficient. If you're using code I would stick to either sending calculator code or using the HVars/LVars directly using the MSFSVariableServices class in my DLL. Which you choose is down to personal preference/convenience/situation. For example, if you're just wanting to read/write a single LVar or activate a single HVar then using the direct method might be easier: MSFSVariableServices.HVars["MyHVar"].Set(); However, if you've found some complicated calculator code on the web, or in a preset, then you might not want to decode what it's doing and replicated the logic yourself. In this instance it would be easier just to copy the code into your application and send it via MSFSVariableServices.ExecuteCalculateCode() For aircraft where LVars/HVars are not available you may need to fall back on 'legacy' methods like Events (aka Controls) and Offsets. In this case you need an FSUIPC Connection. Events/Controls perform actions in the aircraft (Like HVars). Use the FSUIPCConnection.SendControlToFS() feature. To read data use the Offsets. Some offsets can also be written to. Quote As for presets, how are they supposed to be typed into the C# code or is there a txt file that needs to be placed somewhere specific and then references in C#? I don't recommend executing presets themselves from code. It's best to just take the underlying calculator code from the preset and execute that. You can copy it directly into your source code. Alternatively, you can have your application read it from your own text file if you want to be able to modify/add calculator code without recompiling your application. Quote How is this sent to the simulator and could you please give me a C# example of this? If you have not already downloaded the MSFSVariableServices example code project please get it from here: http://fsuipc.paulhenty.com/#downloads It doesn't have an example for calculator code but it will show you how to make a connection and use LVars/Hvars directly. In this thread I give an example of executing calculator code as well as using the same HVar directly. There is also a link to a good website where you can find the underlying calculator code for all the presets. Feel free to ask further questions. It's a bit confusing if you're coming into this new because there are two systems in use for MSFS: The legacy Events/Controls/Offsets system and the newer LVars/HVars/Calculator code system. Paul
John Dowson Posted September 17, 2023 Report Posted September 17, 2023 Note also that if you do want to call a preset (available in FSUIPC) from an FSUIPC client app, you can do this by writing the preset name (preceded by 'P:') to offset 0x7C50. John
brandonharwood14 Posted September 23, 2023 Author Report Posted September 23, 2023 Thank you both for your support on this topic. I haven't had a chance to test anything yet as we are currently moving homes. Hopefully have my PC setup properly soon to try this out but I think from your suggestion Paul I will be just executing Calculator Code to set the 'H:xyz' Vars for the applicable Hardware that our customers may have. I'm thinking I may just put all the applicable HVars into a Text file and read them in C# app. The reason I've chosen just Calculator Code is, If I'm not mistaken, LVars and HVars have to be accompanied by a file associated with a particular aircraft to be directly linked? instead of the method above where it just blindly tries to send the calculator code and executes it, if the program can? I believe I will definitely need a connection to FSUIPC for legacy controls too for it seems some autopilot functionality etc. just taking a peak at a particular .ini file by another company that sells similar devices; most of the commands are HVars and some of them legacy events. - This I dont think I will have a problem with as I have already managed to manipulate certain Quote In this thread I give an example of executing calculator code as well as using the same HVar directly. There is also a link to a good website where you can find the underlying calculator code for all the presets. This link will also helped a lot! thank you. One question I have is (hope this isn't a silly one...): does 'Legacy' events just send SimConnect events Via FSUIPC? Thanks - Brandon
Paul Henty Posted September 23, 2023 Report Posted September 23, 2023 Quote The reason I've chosen just Calculator Code is, If I'm not mistaken, LVars and HVars have to be accompanied by a file associated with a particular aircraft to be directly linked? I believe HVars need a file to be accessed directly by the WASM module. LVars don't need the file. Quote instead of the method above where it just blindly tries to send the calculator code and executes it, if the program can? I think that's also correct. Quote does 'Legacy' events just send SimConnect events Via FSUIPC? Probably yes. FSUIPC4 and above uses SimConnect in the background for most things. @John Dowson will be able to confirm. Paul
John Dowson Posted September 23, 2023 Report Posted September 23, 2023 2 minutes ago, Paul Henty said: Quote does 'Legacy' events just send SimConnect events Via FSUIPC? Probably yes. FSUIPC4 and above uses SimConnect in the background for most things. @John Dowson will be able to confirm. Yes - everything goes via SimConnect anyway, either to the FS or the WASM. But you can also send "legacy" events via calculator code, using them as k-type variables.
brandonharwood14 Posted September 30 Author Report Posted September 30 Hi @Paul Henty I have been working a lot lately with FSUIPC7 and the WASM module and it has been working great as far as buttons presses and encoder turns go on our hardware. I have now moved to Autopilot module and am trying to get the simulator to check certain configurations/modes that the autopilot is in and then pass this to my hardware with a serial string. Please see example below: I can get the code to work and actually send the serial strings to the arduino that is connected to my software but sometimes the ".ValueChanged" function doesnt actually flag that it has changed even though it has and thus throws my mode indicator LED's on my hardware out of wack. is there any chance you could please look into this? If I look into the values and flags of the ".ValueChanged" function provided by FSUIPC7 and VS it shows the value and I can watch the value change from 0 to 1 or visa versa but the inbuilt flag called "ValueChanged" stays false. is there anything my code needs more than this? or am I not using something that I should? Thank you! Regards Brandon private Offset<ushort> AltHold = new Offset<ushort>(0x07D0); private Offset<ushort> HdgHold = new Offset<ushort>(0x07C8); private Offset<ushort> VSHold = new Offset<ushort>(0x07EC); private Offset<ushort> AprHold = new Offset<ushort>(0x0800); private Offset<ushort> YDHold = new Offset<ushort>(0x0808); private Offset<ushort> LvlHold = new Offset<ushort>(0x07C0); private Offset<ushort> NavHold = new Offset<ushort>(0x07C4); private Offset<ushort> APHold = new Offset<ushort>(0x07BC); //HDG Hold if (this.HdgHold.ValueChanged) { if (this.HdgHold.Value == 1) { Debug.WriteLine("HDG Hold value: 1"); if (connectedPorts.Count > 0) { foreach (SerialPortStream port in connectedPorts) { foreach (DeviceInfo deviceInfo in connectedDevices) { if (deviceInfo.DeviceType == "G507" && AutoPilotDeviceList != null && port.IsOpen) { port.Write("Heading_on\n"); } } } } } else if (this.HdgHold.Value == 0) { Debug.WriteLine("HDG Hold value: 0"); if (connectedPorts.Count > 0) { foreach (SerialPortStream port in connectedPorts) { foreach (DeviceInfo deviceInfo in connectedDevices) { if (deviceInfo.DeviceType == "G507" && AutoPilotDeviceList != null && port.IsOpen) { port.Write("Heading_off\n"); } } } } } }
Paul Henty Posted September 30 Report Posted September 30 Hi Brandon, I can't see anything wrong with the code you've pasted, but it doesn't show where you are calling Process(). The built-in ValueChanged flag only tells you if the change happed on the last Process(), so if you're checking values on a different timer or thread than the Process() calls you could miss the change. (Two process calls go by between your checks for ValueChanged). Could that be what's happening? If so I could make it so that ValueChanged is preserved until you actually test for the change. The ValueChanged feature was added long before multi-threading and async programming was easy in .NET, so it's really designed for a single thread, synchornous application. If that's not the case and your checks are definitely made after every process() on a single thread, please let me know and paste the code where you call Process() and I'll look into it some more. Paul
brandonharwood14 Posted Sunday at 12:02 PM Author Report Posted Sunday at 12:02 PM On 9/30/2024 at 6:49 PM, Paul Henty said: Hi Brandon, I can't see anything wrong with the code you've pasted, but it doesn't show where you are calling Process(). The built-in ValueChanged flag only tells you if the change happed on the last Process(), so if you're checking values on a different timer or thread than the Process() calls you could miss the change. (Two process calls go by between your checks for ValueChanged). Could that be what's happening? If so I could make it so that ValueChanged is preserved until you actually test for the change. The ValueChanged feature was added long before multi-threading and async programming was easy in .NET, so it's really designed for a single thread, synchornous application. If that's not the case and your checks are definitely made after every process() on a single thread, please let me know and paste the code where you call Process() and I'll look into it some more. Paul Hi Paul, Thanks for this information, I think this is exactly what is happening I am not calling Process(), I will try and get it going with process in the code and see if it helps things along. It is an async application and as time has gone by the code has gotten larger and larger so this could also be adding to my confusion hah... Thanks again for getting back to me, now that I have my PC set up again after moving I can try and get this sorted. Cheers Brandon
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