From 0c4544c1e1788f3396330c86016b66df8643fd3b Mon Sep 17 00:00:00 2001 From: Stuart Buchanan Date: Thu, 18 Jan 2018 19:37:50 +0000 Subject: [PATCH] Add Config Store and MFD Header display. ConfigStore for storing and retrieving config settings (needs XML import/export) Header display with 4 different header fields (all configurable) Publisher for ADC and FMS. --- Aircraft/Instruments-3d/FG1000/Models/MFD.svg | 107 ++++------------- .../AirportInfo/AirportInfoController.nas | 1 - .../FG1000/Nasal/ConfigStore.nas | 110 ++++++++++++++++++ .../Nasal/Interfaces/GenericADCPublisher.nas | 28 +++++ .../Nasal/Interfaces/GenericEISPublisher.nas | 1 - .../Nasal/Interfaces/GenericFMSPublisher.nas | 73 ++++++++++++ Aircraft/Instruments-3d/FG1000/Nasal/MFD.nas | 4 + .../FG1000/Nasal/Surround/Surround.nas | 62 +++++++++- .../Nasal/Surround/SurroundController.nas | 10 ++ Aircraft/Instruments-3d/FG1000/Nasal/gui.nas | 15 +++ Nasal/notifications.nas | 4 +- 11 files changed, 324 insertions(+), 91 deletions(-) create mode 100644 Aircraft/Instruments-3d/FG1000/Nasal/ConfigStore.nas create mode 100644 Aircraft/Instruments-3d/FG1000/Nasal/Interfaces/GenericADCPublisher.nas create mode 100644 Aircraft/Instruments-3d/FG1000/Nasal/Interfaces/GenericFMSPublisher.nas diff --git a/Aircraft/Instruments-3d/FG1000/Models/MFD.svg b/Aircraft/Instruments-3d/FG1000/Models/MFD.svg index ae5961c3f..a01e3c8cb 100644 --- a/Aircraft/Instruments-3d/FG1000/Models/MFD.svg +++ b/Aircraft/Instruments-3d/FG1000/Models/MFD.svg @@ -23,11 +23,11 @@ borderopacity="0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="1.4142135" - inkscape:cx="208.90255" - inkscape:cy="491.35422" + inkscape:zoom="2.828427" + inkscape:cx="445.86013" + inkscape:cy="589.65442" inkscape:document-units="px" - inkscape:current-layer="SurroundGroup" + inkscape:current-layer="MFD-navbox" showgrid="true" inkscape:window-width="2495" inkscape:window-height="1416" @@ -450,73 +450,6 @@ id="path4370" inkscape:connector-curvature="0" /> - - - DIS - --.- - ETE - --:-- - DTK TRK ETE --:-- + y="19.752344">--:-- 0) { + # Determine the distance to travel, based on + # - current distance to the next WP, + # - length of each subsequent leg. + dst = getprop("/instrumentation/gps/wp/wp[1]/distance-nm") or 0.0; + + if (plan.indexOfWP(plan.currentWP()) < (plan.getPlanSize() -1)) { + for(var i=plan.indexOfWP(plan.currentWP()) + 1; i < plan.getPlanSize(); i = i+1) { + var leg = plan.getWP(i); + if (leg != nil ) dst = dst + leg.leg_distance; + } + } + } + + gpsdata["FMSDistance"] = dst; + var spd = getprop("/instrumentation/gps/indicated-ground-speed-kt") or 1.0; + var time_hrs = dst / spd; + + gpsdata["FMSEstimatedTimeEnroute"] = time_hrs; + gpsdata["FMSFuelOverDestination"] = total_fuel - time_hrs * fuel_flow; + + var notification = notifications.PFDEventNotification.new( + "MFD", + 1, + notifications.PFDEventNotification.FMSData, + gpsdata); + + me._transmitter.NotifyAll(notification); + }, + +}; diff --git a/Aircraft/Instruments-3d/FG1000/Nasal/MFD.nas b/Aircraft/Instruments-3d/FG1000/Nasal/MFD.nas index a58b57835..2682546b6 100644 --- a/Aircraft/Instruments-3d/FG1000/Nasal/MFD.nas +++ b/Aircraft/Instruments-3d/FG1000/Nasal/MFD.nas @@ -8,6 +8,8 @@ io.include("constants.nas"); var nasal_dir = getprop("/sim/fg-root") ~ "/Aircraft/Instruments-3d/FG1000/Nasal/"; +io.load_nasal(nasal_dir ~ '/ConfigStore.nas', "fg1000"); + io.load_nasal(nasal_dir ~ '/MFDPage.nas', "fg1000"); io.load_nasal(nasal_dir ~ '/MFDPageController.nas', "fg1000"); @@ -71,6 +73,8 @@ var MFD = Surround : nil, }; + obj.ConfigStore = fg1000.ConfigStore.new(); + obj._svg = myCanvas.createGroup("softkeys"); obj._svg.set("clip-frame", canvas.Element.LOCAL); obj._svg.set("clip", "rect(0px, 1024px, 768px, 0px)"); diff --git a/Aircraft/Instruments-3d/FG1000/Nasal/Surround/Surround.nas b/Aircraft/Instruments-3d/FG1000/Nasal/Surround/Surround.nas index dd569e05f..a541f623a 100644 --- a/Aircraft/Instruments-3d/FG1000/Nasal/Surround/Surround.nas +++ b/Aircraft/Instruments-3d/FG1000/Nasal/Surround/Surround.nas @@ -38,6 +38,27 @@ var PAGE_GROUPS = [ } ]; +# Mapping for header labels to specific FMS or ADC messages, and sprintf formatting +# to use +var HEADER_MAPPING = { + "BRG" : { message : "FMSLegBearing", format : "%d"}, + "XTK" : { message : "FMSLegCourseError", format : "%.1fnm"}, + "DIS" : { message : "FMSDistance", format : "%.1fnm"}, + "DTK" : { message : "FMSLegDesiredTrack", format : "%d"}, + "END" : { message : "EnduranceHrs", format : "%.1fhrs"}, + "ESA" : { message : "EnRouteSafeAltitude", format : "%dft"}, # TODO + "ETA" : { message : "FMSEstimatedTimeArrival", format : ""}, # TODO + "ETE" : { message : "FMSEstimatedTimeEnroute", format : ""}, + "FOD" : { message : "FMSFuelOverDestination", format : "%dgal"}, + "FOB" : { message : "FuelOnBoard", format : "%dgal"}, + "GS" : { message : "FMSGroundspeed", format : "%dkts"}, + "MSA" : { message : "MinimumSafeAltitude", format : "%dft"}, # TODO + "TAS" : { message : "ADCTrueAirspeed", format : "%dkts"}, + "TKE" : { message : "FMSLegTrackErrorAngle", format : "%d"}, + "TRK" : { message : "FMSLegTrack", format : "%d"}, + "VSR" : { message : "FMSLegVerticalSpeedRequired", format : "%dfpm"}, # TODO +}; + var Surround = { new : func (mfd, myCanvas, device, svg) @@ -52,7 +73,11 @@ var Surround = "Comm2StandbyFreq", "Comm2SelectedFreq", "Nav1StandbyFreq", "Nav1SelectedFreq", "Nav2StandbyFreq", "Nav2SelectedFreq", - "Nav1ID", "Nav2ID" + "Nav1ID", "Nav2ID", + "Header1Label", "Header1Value", + "Header2Label", "Header2Value", + "Header3Label", "Header3Value", + "Header4Label", "Header4Value", ]; obj.addTextElements(textElements); @@ -181,6 +206,41 @@ var Surround = } }, + # Update Header data with FMS or ADC data. + updateHeaderData : func(data) { + var headers = ["Header1", "Header2", "Header3", "Header4"]; + foreach (var header; headers) { + + # Get the currently configured heading and set the surround to display it. + var label = me.mfd.ConfigStore.get("MFD" ~ header); + assert(label != nil, "No header configured in ConfigStore for " ~ header); + me.setTextElement(header ~ "Label", label); + + # Determine how it maps to Emesary data notifications + var mapping = HEADER_MAPPING[label]; + assert(mapping != nil, "No header mapping for " ~ label); + + if (data[mapping.message] != nil) { + # Format and display the value + var value = sprintf(mapping.format, data[mapping.message]); + + if (mapping.message == "FMSEstimatedTimeEnroute") { + # Special case to format time strings. + var hrs = int(data[mapping.message]); + var mins = int(60*(data[mapping.message] - hrs)); + var secs = int(3600*(data[mapping.message] - hrs - mins/60)); + + if (hrs == 0) { + value = sprintf("%d:%02d", mins, secs); + } else { + value = sprintf("%d:%02d", hrs, mins); + } + } + me.setTextElement(header ~ "Value", value); + } + } + }, + addPage : func(name, page) { me._pageList[name] = page; diff --git a/Aircraft/Instruments-3d/FG1000/Nasal/Surround/SurroundController.nas b/Aircraft/Instruments-3d/FG1000/Nasal/Surround/SurroundController.nas index 4db5bd687..ea15cfc0c 100644 --- a/Aircraft/Instruments-3d/FG1000/Nasal/Surround/SurroundController.nas +++ b/Aircraft/Instruments-3d/FG1000/Nasal/Surround/SurroundController.nas @@ -359,11 +359,21 @@ var SurroundController = { if (notification.Device_Id == pfd_obj.device_id and notification.NotificationType == notifications.PFDEventNotification.DefaultType) { + if (notification.Event_Id == notifications.PFDEventNotification.NavComData and notification.EventParameter != nil) { return controller.handleNavComData(notification.EventParameter); } + + if (((notification.Event_Id == notifications.PFDEventNotification.FMSData) or + (notification.Event_Id == notifications.PFDEventNotification.ADCData) ) + and notification.EventParameter != nil) + { + # Pass FMS and ADC data straight to the page to display in the header fields + return controller._page.updateHeaderData(notification.EventParameter); + } + } return emesary.Transmitter.ReceiptStatus_NotProcessed; }; diff --git a/Aircraft/Instruments-3d/FG1000/Nasal/gui.nas b/Aircraft/Instruments-3d/FG1000/Nasal/gui.nas index d01469f0a..bf2e601a2 100644 --- a/Aircraft/Instruments-3d/FG1000/Nasal/gui.nas +++ b/Aircraft/Instruments-3d/FG1000/Nasal/gui.nas @@ -110,6 +110,9 @@ var MFDGUI = io.load_nasal(nasal_dir ~ 'Interfaces/GenericNavComUpdater.nas', "fg1000"); io.load_nasal(nasal_dir ~ 'Interfaces/NavDataInterface.nas', "fg1000"); + io.load_nasal(nasal_dir ~ 'Interfaces/GenericFMSPublisher.nas', "fg1000"); + io.load_nasal(nasal_dir ~ 'Interfaces/GenericADCPublisher.nas', "fg1000"); + # Now create the MFD itself if (obj.scale > 0.999) { # If we're at full scale, then create it directly in this Canvas as that @@ -154,6 +157,12 @@ var MFDGUI = obj.navdataInterface = fg1000.NavDataInterface.new(obj.mfd.getDevice()); obj.navdataInterface.start(); + obj.gpsPublisher = fg1000.GenericFMSPublisher.new(); + obj.gpsPublisher.start(); + + obj.adcPublisher = fg1000.GenericADCPublisher.new(); + obj.adcPublisher.start(); + # Add a event listener for the mouse wheel, which is used for turning the # knobs. obj.myCanvas.addEventListener("wheel", func(e) @@ -231,6 +240,12 @@ var MFDGUI = me.navdataInterface.stop(); me.navdataInterface =nil; + me.gpsPublisher.stop(); + me.gpsPublisher = nil; + + me.adcPublisher.stop(); + me.adcPublisher = nil; + # Clean up the window itself call(canvas.Window.del, [], me.window); }, diff --git a/Nasal/notifications.nas b/Nasal/notifications.nas index 7f5d47dc3..b71222f4a 100644 --- a/Nasal/notifications.nas +++ b/Nasal/notifications.nas @@ -554,7 +554,9 @@ var PFDEventNotification = HardKeyPushed : 4, #event parameter contains single { Id: , Value: } tuple EngineData : 5, #event parameter contains an array of hashes, each containing information about a given engine. NavComData : 6, #event parameter contains a hash of updated Nav/Com settings - NavData : 7, #event parameter contrains a singel { Id: , Value: } tuple requesting a paricular type of NavData + NavData : 7, #event parameter contrains a single { Id: , Value: } tuple requesting a particular type of NavData + FMSData : 8, #event parameter containing a hash of updated GPS/FMS information (track, ground-speed, waypoint legs etc.) + ADCData : 8, #event parameter containing a hash of updated Air Data Computer information (track, ground-speed etc.) DefaultType : "PFDEventNotification",