
Paul Henty
Members-
Posts
1,728 -
Joined
-
Days Won
78
Content Type
Profiles
Forums
Events
Gallery
Downloads
Everything posted by Paul Henty
-
Sorry Piotr, I really don't know what the problem could be. You haven't put the .ini file entries in FSUIPC4,.ini by mistake? Paul
-
I can confirm this is working with the 3.1.21 version of my DLL. Also FSUIPC Version 4.975a. This is the code I used: Just a simple form with a button and a text box. public frmCDUTest() { InitializeComponent(); } private PMDG_NGX_CDU_Screen cdu0 = null; private void frmCDUTest_Load(object sender, EventArgs e) { FSUIPCConnection.Open(); cdu0 = new PMDG_NGX_CDU_Screen(0x5400); } private void Button1_Click(object sender, EventArgs e) { cdu0.RefreshData(); this.txtCDU.Text = cdu0.ToString("\r\n"); } Using the PMDG 737-800 NGX. In the file: \SteamLibrary\steamapps\common\FSX\PMDG\PMDG 737 NGX\737NGX_Options.ini I added: [SDK] EnableDataBroadcast=1 EnableCDUBroadcast.0=1 EnableCDUBroadcast.1=0 PMDG Version numbers: On the CDU: PMDG Setup -> About says 1.1 In the document: \SteamLibrary\steamapps\common\FSX\PMDG\PMDG 737 NGX\README_PMDG_737-800-900_NGX.txt it says: v1.10.6461 at the top. Hope that helps... Paul
-
Best way to make browser interface with FSUIPC?
Paul Henty replied to Firefly's topic in FSUIPC Support Pete Dowson Modules
I've got WebSockets working. Here's a quick video of real time updates every 100ms. https://youtu.be/E6RR94O8nfs This is the JavaScript for this page: var fsuipcURL = "ws://127.0.0.1:2048/fsuipc"; var ws; function btnConnectClick(e) { if (!ws) { // create a new WebSocket using the URL with the 'fsuipc' protocol. ws = new WebSocket(fsuipcURL, "fsuipc"); ws.onopen = function () { alert("Socket Open..."); }; ws.onmessage = function (evt) { // Find out which request was responded to and process it var response = JSON.parse(evt.data); switch (response.name) { case 'info': showInfo(response); break; case 'offsetsTest': showOffsetData(response); break; } }; ws.onclose = function () { // websocket is closed. alert("Connection is closed..."); ws = null; }; } } function btnInfoClick(e) { // make a request to the sever for info. request = { request: 'info', name: 'info' }; if (ws) { ws.send(JSON.stringify(request)); } } function btnReadOffsetsClick(e) { // make a request to the sever to read offset data // First setup a data structure containing the offset requests // This contains an array of ofset objects. Each object contains: // name: used to identify the value when the response comes back (can be anything) // address: Hexadecimal address of the offset // type: the type of data in the offset. Must be: // 'int' (signed integer) // 'uint' (unsigned integer) // 'string' // 'float' // size: The size of the offset in bytes request = { request: 'offsets.read', // Tell the server to read offsets name: 'offsetsTest', // An ID so we can match the response interval: 100, // Send every 100ms - specfiy 0 for read once (no repeat). offsets: [ { name: 'altitude', address: '0570', type: 'int', size: 8 }, { name: 'avionicsMaster', address: '2E80', type: 'uint', size: 4 }, { name: 'heading', address: '0580', type: 'uint', size: 4 }, { name: 'aircraftName', address: '3D00', type: 'string', size: 256 }, ] }; if (ws) { ws.send(JSON.stringify(request)); } } function showInfo(response) { if (response.success) { var data = response.data; // Create a table to display the data displayHTML = '<table>'; // enumerate each returned data item and add as a row to the table for (var propertyName in data) { displayHTML += '<tr>'; displayHTML += '<td>' + propertyName + '</td><td>' + data[propertyName] + '</td>'; displayHTML += '</tr>'; } displayHTML += "</table>"; } else { displayHTML = "Request failed with error code: " + response.errorCode + " " + response.errorMessage; } document.getElementById('fsuipcInfo').innerHTML = displayHTML; } function showOffsetData(response) { // clear error display document.getElementById('fsuipcReadOffsets').innerHTML = ''; var displayHTML = ""; if (response.success) { var data = response.data; // display each offset value on the page document.getElementById('aircraftName').innerText = data['aircraftName']; document.getElementById('avionicsMaster').innerText = data['avionicsMaster'] > 0 ? 'ON' : 'OFF'; // convert heading from FS units to degrees var headingDegrees = data['heading'] * 360 / (65536 * 65536); document.getElementById('headingTrue').innerText = headingDegrees.toFixed(0); // convert altitude metres to feet var altitudeFeet = data['altitude'] / (65535 * 65535) * 3.28084; document.getElementById('altitude').innerText = altitudeFeet.toFixed(0); } else { displayHTML = "Request failed with error code: " + response.errorCode + " " + response.errorMessage; } // set any error HTML into the div document.getElementById('fsuipcReadOffsets').innerHTML = displayHTML; } Is that more like what you had in mind? If so, I'll get it to a stable version with offset read and write so you can test it. Let me know if you have any other comments or suggestions. Paul -
Hi Bastian, This is a bug in the sample application. The pause should not be declared as write-only. It works fine if you take that out. In your own application you can make it a normal read/write offset. Or if you just want to control the pause you can make it write-only, but you should put it in a group so you can process() it only when you need to send the pause state. I'll fix the problem in the next version of the example code application. Paul
-
Hi Peter, It's quite complicated to compile and run .NET code at runtime. It's usually called Dynamic Execution. I don't think it's needed here however; there is a way you can do this with the base (untyped) Offset class. I suggest something along these lines... Text File: In the text file have the following: pin, controlName, offset address, type, size e.g. 23, EVT_MCP_LVL_CHG_SWITCH, FFFF, byte, 1 Dictionary: Create a structure to hold the pin, the event, the offset, and a method to get the offset value back as an int: internal struct pinInfo { public int pin; public string eventName; public Offset offset; public string offsetType; public pinInfo(int Pin, string EventName, Offset FSUIPCOffset, string OffsetType) { this.pin = Pin; this.eventName = EventName; this.offset = FSUIPCOffset; this.offsetType = OffsetType; } public int getOffsetValue() { int value = 0; switch (this.offsetType) { case "byte": value = (int)this.offset.GetValue<byte>(); break; case "short": value = (int)this.offset.GetValue<short>(); break; case "int": value = this.offset.GetValue<int>(); break; } return value; } } Create the dictionary to hold these entries, keyed on the pin: Dictionary<int, pinInfo> pins = new Dictionary<int, pinInfo>(); Populating the dictionary: As you read each line in the text file, create an instance of pinInfo and add to the dictionary: // these would be from the file... string pinID = "23"; string controlName = "EVT_MCP_LVL_CHG_SWITCH"; string offsetAddressHex = "FFFF"; string offsetType = "byte"; string offsetSize = "1"; // convert pin to int int pinInt = int.Parse(pinID); // convert offset address from string to int (as hexadecimal) int offsetAddressInt = int.Parse(offsetAddressHex, NumberStyles.HexNumber); // convert size to int int offsetSizeInt = int.Parse(offsetSize); // convert event string to int int eventInt = (int)Enum.Parse(typeof(PMDG_737_NGX_Control), controlName, false); // create (untyped) offset Offset offset = new Offset(offsetAddressInt, offsetSizeInt); // create new pinInfo and add to the dictionary pinInfo newPin = new pinInfo(pinInt, eventInt, offset, offsetType); pins.Add(newPin.pin, newPin); Using the dictionary: When the pin number arrives, get the pinInfo using the pin number. Then use the pin info to get the offset value and send the control: int incommingPinNumber = 23; pinInfo pin = pins[incommingPinNumber]; FSUIPCConnection.SendControlToFS(pin.controlID, pin.getOffsetValue()); Paul
-
Yes the broadcast is working fine then. I really don't know what else to suggest other than to make sure you have the latest updates to whatever version of FSUIPC you are using, my dll, and the PMDG Aircraft. Paul
-
Hi Peter, Glad to hear it's all going well. I like the dictionary idea. As well as cutting down on the code, it will also allow you to change and add switches without recompiling the code. Paul
-
Looks like the PMDG info just isn't being broadcast. It would be worth trying some of the other PMDG offsets and see if they work. If they don't, it's definitely a problem with the PMDG broadcast rather than your (or my) code. Paul
-
Is cdu.Powered still false? Which plane are you using? Paul
-
The offset address should be in hexadecimal: PMDG_NGX_CDU_Screen cdu = new PMDG_NGX_CDU_Screen(0x5400); Paul
-
That's OK. Can you post your code here so I can check it? Paul
-
Hi Piotr, Have you enabled the CDU broadcast in the PMDG ini file? Here is the relevant info from "Offset Mapping for PMDG 737NGX.pdf": To enable the data communication output from the PMDG aircraft, you will need to open the file 737NGX_Options.ini (located in the FSX folder PMDG\PMDG 737 NGX, and add the following lines to the end of the file: [SDK] EnableDataBroadcast=1 For CDU screen data you also need one or both of these lines: EnableCDUBroadcast.0=1 EnableCDUBroadcast.1=1 Which enable the contents of the corresponding CDU screen to be sent to FSUIPC. Paul
-
Well done. That looks great. Paul
-
Best way to make browser interface with FSUIPC?
Paul Henty replied to Firefly's topic in FSUIPC Support Pete Dowson Modules
Hi Allan, Thanks for the feedback. I can see that the WebSockets model would be a better solution. I'll look into it... Paul -
Best way to make browser interface with FSUIPC?
Paul Henty replied to Firefly's topic in FSUIPC Support Pete Dowson Modules
I have a proof of concept working. It uses HTTP requests. I can't see any advantage in using WebSockets as FSUIPC itself does not have duplex communication. It's only one-way poll & response from client to FSUIPC. Just to make sure I'm on the right track, and check if this this would be useful, I've posted some javascript below that I've used for testing. This runs directly in a browser, completely client-side. It talks to the HTTP server program that is located on the flight sim PC (or can be on a different PC if connecting to the flight sim over WideFS). The URL consists of the IP of the server and port number (setup in the server program) followed by /fsuipc/ and then the type of request you are making. e.g. to request offset data it might look like this: http://localhost:2048/fsuipc/offsets You'll make an AJAX POST request to this URL, passing a JSON stringified array of offset requests (details in the code below). Then you'll get back another JSON string containing the values which you can turn into a Javascript object to use. Here's the Javascript for reading three offsets: var fsuipcURL = "http://localhost:2048/fsuipc/"; function btnReadOffsetsClick(e) { // make a request to the sever to read offset data // First setup a data structure containing the offset requests // This is an array of offset objects. Each object contains: // name: used to identify the value when the response comes back (can be anything) // address: Hexadecimal address of the offset // type: the type of data in the offset. Must be: // 'int' (signed integer) // 'uint' (unsigned integer) // 'string' // 'float' // size: The size of the offset in bytes offsets = [ { name: 'avionicsMaster', address: '2E80', type: 'uint', size: 4}, { name: 'heading', address: '0580', type: 'uint', size: 4}, { name: 'aircraftName', address: '3D00', type: 'string', size: 256 }, ]; // create the URL var offsetsURL = fsuipcURL + "offsets"; // create a new AJAX request object var xhttp = new XMLHttpRequest(); // setup a function to execute when the data is returned xhttp.onreadystatechange = function () { showOffsetData(this); }; // make the request xhttp.open("POST", offsetsURL, true); xhttp.send(JSON.stringify(offsets)); } function showOffsetData(e) { // clear error display document.getElementById('fsuipcReadOffsets').innerHTML = ''; var displayHTML = ""; if (e.readyState >= 3 && e.status == 200) { // decode the JSON response var response = JSON.parse(e.responseText); if (response.Success) { var data = response.Data; // display each offset value on the page document.getElementById('aircraftName').innerText = data['aircraftName']; document.getElementById('avionicsMaster').innerText = data['avionicsMaster'] > 0 ? 'ON' : 'OFF'; // convert heading from FS units to degrees var headingDegrees = data['heading'] * 360 / (65536 * 65536); document.getElementById('headingTrue').innerText = headingDegrees.toFixed(2); } else { displayHTML = "Request failed with error code: " + response.ErrorCode + " " + response.ErrorMessage; } } else { displayHTML = "Error communicating with FSUIPC Web Services. "; } // set any error HTML into the div document.getElementById('fsuipcReadOffsets').innerHTML = displayHTML; } This is the result: Do you think this would work? Thanks, Paul -
request simple c# demo script
Paul Henty replied to michielsweb's topic in FSUIPC Client DLL for .NET
Hi Piotr, It looks like you've used some example code written in Visual Basic.NET. C# uses [] to access array elements, not () like VB, so it would be: string row3Text = cdu.Rows[2].ToString(); char R3C1Char = cdu.Rows[2].Cells[0].Symbol; Paul -
request simple c# demo script
Paul Henty replied to michielsweb's topic in FSUIPC Client DLL for .NET
The packages.config look fine to me. Does Visual Studio say the error is in Packages.config or somewhere else? If you double-click it it should take you to the file and line with the problem. Paul -
request simple c# demo script
Paul Henty replied to michielsweb's topic in FSUIPC Client DLL for .NET
Hi Piotr, A few things that could cause this: You don't have my client DLL added as a reference. You don't have using FSUIPC; at the top of the class. You must be using version 3 of my DLL (version 2 doesn't have SendControlToFS). Please see my website for instructions on how to install the DLL or update from version 2 to the latest version (3.1.21) http://fsuipc.paulhenty.com/#help Paul -
Best way to make browser interface with FSUIPC?
Paul Henty replied to Firefly's topic in FSUIPC Support Pete Dowson Modules
Hi John, Yes I've thought about it as I've seen some other requests for this in past but I didn't have the time for new project. As you say, a small application that runs in the system tray that provides an http interface should be fairly straight forward. As well as the basic offset read/write I could also expose the helper classes in the DLL like accessing weather and AI traffic. I guess the main advantage of a separate program is that it'll work with all version of FSUIPC/Flight Sims. I'll investigate his week as I don't think it'll be too big a project and I'll report back. Paul -
It sounds possible to create a .net application using the library you found and my FSUIPC dll for .NET. I don't have a stream deck however so I can't really help with that aspect. If you haven't seen this, there is currently an active thread in the main FSUIPC forum about using the stream deck with FSUIPC without programming. Paul
-
using airport database features from another class
Paul Henty replied to Jason Fayre's topic in FSUIPC Client DLL for .NET
Hi Jason, It sounds like you are trying to use the AirportDatabase before the connection to FSUIPC is open. It's not a good exception as it doesn't tell you what the real problem is. I'll correct this in the next release. Paul -
Version 3.1.21 is now available on NuGet which includes Taxiways in the Airports Database. This feature must be enabled by setting the LoadTaxiways property to true. This adds roughly 30% to the initial database loading time. The Airports now have a Taxiways collection which works in the same way as the gates, runways etc. The FsTaxiway class contains the following information: string Name FsAirport Airport FsLatLonPoint StartPoint FsLatLonPoint EndPoint double MinimumWidthMetres double MinimumWidthFeet double MaximumWidthMetres double MaximumWidthFeet bool IsPlayerOnTaxiway List<FsTaxiwaySegments> Segments A taxiway might be made up of multiple segments. Each taxiway has at least one segment. The StartPoint is the start point of the first segment. The EndPoint is the end point of the last segment. IsPlayerOnTaxiway will tell you if the player is on any of the segments making up this taxiway. You must set the Reference Position first for this to work. (See the examples application for this). The FsTaxiwaySegment class contains the following information: FsTaxiwaySegmentType Type FsLatLonPoint StartPoint double StartWidthMetres double StartWidthFeet FsLatLonPoint EndPoint double EndWidthMetres double EndWidthFeet FsLatLonQuadrilateral Bounds bool IsPlayerOnSegment FsTaxiwaySegment Next FsTaxiwaySegment Previous Start and End points are on the centre line of the Taxiway. Bounds defines the locations of the four corners of the Taxiway Segment. The AirportsDatabase class now has properties to decide what elements to load into the database. LoadGates LoadHelipads LoadFrequencies LoadTaxiways To preserve the behaviour of previous versions, all are set to True by default EXCEPT LoadTaxiways which is False. Example of getting all named taxiways at EGJJ: AirportsDatabase DB = FSUIPCConnection.AirportsDatabase; DB.LoadTaxiways = true; DB.Load(); FsAirport egjj = DB.Airports["EGJJ"]; foreach(FsTaxiway taxiway in egjj.Taxiways) { if (!string.IsNullOrWhiteSpace(taxiway.Name)) { Debug.WriteLine(taxiway.Name); } } Paul
-
Hi Peter, The minimum version of the .NET framework that my DLL will work with is 4.0. Your project seems to be targeting version 3.5 which is from the days of Windows XP, so very old. You'll need to change the target runtime by going to PROJECT -> Properties: The minimum I recommend is 4.5 which will run on any Windows from Vista onwards. Paul
-
Just an update: I've had a look at this and it's in progress. I'm hoping to get a new version out next week with taxiways included. Paul
-
FSUIPC Client DLL --> Connectivity MSFS
Paul Henty replied to Delphi's topic in FSUIPC Client DLL for .NET
Hi Ruediger, Yes it's working for others. All the reports so far regarding connection problems with FSUIPC7 were solved by making all the programs run with the same privilege levels. MSFS, the FSUIPC7.exe, and your application .exe must be run either all 'as administrator', or none 'as admin'. Hopefully that's the problem here as it's an easy fix. Please note that not all offsets and controls are working in FSUIPC7 yet. Paul