FG1000: EIS Fuel totalizer function
FG1000 requires fuel quantity to be entered manually and uses a flow computer to calculate the amount used. Strange but true!
This commit is contained in:
parent
f8eb701d62
commit
f32a376a3e
8 changed files with 246 additions and 22 deletions
|
@ -44,7 +44,7 @@ var EIS =
|
|||
return obj;
|
||||
},
|
||||
|
||||
updateData : func(engineData) {
|
||||
updateEngineData : func(engineData) {
|
||||
me.setTextElement("RPMDisplay", sprintf("%i", engineData.RPM));
|
||||
me.setTextElement("ManDisplay", sprintf("%.1f", engineData.Man));
|
||||
me.setTextElement("MBusVolts", sprintf("%.01f", engineData.MBusVolts));
|
||||
|
@ -55,16 +55,18 @@ var EIS =
|
|||
me._oilTempPointer.setValue(engineData.OilTemperatureF);
|
||||
me._EGTPointer.setValue(engineData.EGTNorm);
|
||||
me._EGTCylinder.setValue(engineData.EGTNorm);
|
||||
me._leftFuelPointer.setValue(engineData.LeftFuelUSGal);
|
||||
me._rightFuelPointer.setValue(engineData.RightFuelUSGal);
|
||||
|
||||
me._RPMPointer.setValue(engineData.RPM);
|
||||
me._ManPointer.setValue(engineData.Man);
|
||||
},
|
||||
|
||||
updateFuelData : func(fuelData) {
|
||||
me._leftFuelPointer.setValue(fuelData.LeftFuelUSGal);
|
||||
me._rightFuelPointer.setValue(fuelData.RightFuelUSGal);
|
||||
},
|
||||
|
||||
# Menu tree . engineMenu is referenced from most pages as softkey 0:
|
||||
# pg.addMenuItem(0, "ENGINE", pg, pg.mfd.EISPage.engineMenu);
|
||||
|
||||
engineMenu : func(device, pg, menuitem) {
|
||||
pg.clearMenu();
|
||||
pg.resetMenuColors();
|
||||
|
@ -93,7 +95,7 @@ var EIS =
|
|||
pg.addMenuItem(0, "ENGINE", pg, pg.mfd.EIS.engineMenu);
|
||||
pg.addMenuItem(1, "LEAN", pg, pg.mfd.EIS.leanMenu);
|
||||
pg.addMenuItem(2, "SYSTEM", pg, pg.mfd.EIS.systemMenu);
|
||||
pg.addMenuItem(3, "RST FUEL", pg);
|
||||
pg.addMenuItem(3, "RST FUEL", pg, func(dev, pg, mi) { pg.mfd.EIS.getController().setFuelQuantity(0); });
|
||||
pg.addMenuItem(4, "GAL REM", pg, pg.mfd.EIS.galRemMenu);
|
||||
pg.addMenuItem(5, "BACK", pg, pg.mfd.EIS.engineMenu);
|
||||
device.updateMenus();
|
||||
|
@ -105,11 +107,11 @@ var EIS =
|
|||
pg.addMenuItem(0, "ENGINE", pg, pg.mfd.EIS.engineMenu);
|
||||
pg.addMenuItem(1, "LEAN", pg, pg.mfd.EIS.leanMenu);
|
||||
pg.addMenuItem(2, "SYSTEM", pg, pg.mfd.EIS.systemMenu);
|
||||
pg.addMenuItem(3, "-10 GAL", pg);
|
||||
pg.addMenuItem(4, "-1 GAL", pg);
|
||||
pg.addMenuItem(5, "+1 GAL", pg);
|
||||
pg.addMenuItem(6, "+10 GAL", pg);
|
||||
pg.addMenuItem(7, "44 GAL", pg);
|
||||
pg.addMenuItem(3, "-10 GAL", pg, func(dev, pg, mi) { pg.mfd.EIS.getController().updateFuelQuantity(-10); } );
|
||||
pg.addMenuItem(4, "-1 GAL", pg, func(dev, pg, mi) { pg.mfd.EIS.getController().updateFuelQuantity(-1); });
|
||||
pg.addMenuItem(5, "+1 GAL", pg, func(dev, pg, mi) { pg.mfd.EIS.getController().updateFuelQuantity(1); });
|
||||
pg.addMenuItem(6, "+10 GAL", pg, func(dev, pg, mi) { pg.mfd.EIS.getController().updateFuelQuantity(10); });
|
||||
pg.addMenuItem(7, "44 GAL", pg, func(dev, pg, mi) { pg.mfd.EIS.getController().setFuelQuantity(44); });
|
||||
pg.addMenuItem(8, "BACK", pg, pg.mfd.EIS.engineMenu);
|
||||
device.updateMenus();
|
||||
},
|
||||
|
|
|
@ -46,16 +46,27 @@ var EISController =
|
|||
"OilPressurePSI",
|
||||
"OilTemperatureF",
|
||||
"EGTNorm",
|
||||
"VacuumSuctionInHG",
|
||||
"LeftFuelUSGal",
|
||||
"RightFuelUSGal"];
|
||||
"VacuumSuctionInHG"];
|
||||
|
||||
foreach (var val; elements) {
|
||||
if (data[val] == nil) data[val] = 0;
|
||||
}
|
||||
|
||||
# Display it
|
||||
me._page.updateData(data);
|
||||
me._page.updateEngineData(data);
|
||||
return emesary.Transmitter.ReceiptStatus_OK;
|
||||
},
|
||||
|
||||
# Function to handle the data provided from the FuelData Emesary Notification.
|
||||
# This implementation assumes a vector containing hashes of "FuelUSGal" entries
|
||||
handleFuelData : func (fuelData) {
|
||||
assert(size(fuelData) > 1, "handleEngineData expects vector of size > 1");
|
||||
var data = {};
|
||||
data["LeftFuelUSGal"] = (fuelData[0]["FuelUSGal"] or 0);
|
||||
data["RightFuelUSGal"] = (fuelData[1]["FuelUSGal"] or 0);
|
||||
|
||||
# Display it
|
||||
me._page.updateFuelData(data);
|
||||
return emesary.Transmitter.ReceiptStatus_OK;
|
||||
},
|
||||
|
||||
|
@ -71,10 +82,18 @@ var EISController =
|
|||
{
|
||||
if (notification.NotificationType == notifications.PFDEventNotification.DefaultType and
|
||||
notification.Event_Id == notifications.PFDEventNotification.EngineData and
|
||||
notification.EventParameter != nil)
|
||||
notification.EventParameter.Id == "EngineData")
|
||||
{
|
||||
return controller.handleEngineData(notification.EventParameter);
|
||||
return controller.handleEngineData(notification.EventParameter.Value);
|
||||
}
|
||||
|
||||
if (notification.NotificationType == notifications.PFDEventNotification.DefaultType and
|
||||
notification.Event_Id == notifications.PFDEventNotification.FuelData and
|
||||
notification.EventParameter.Id == "FuelData")
|
||||
{
|
||||
return controller.handleFuelData(notification.EventParameter.Value);
|
||||
}
|
||||
|
||||
return emesary.Transmitter.ReceiptStatus_NotProcessed;
|
||||
};
|
||||
}
|
||||
|
@ -96,4 +115,26 @@ var EISController =
|
|||
me.DeRegisterWithEmesary();
|
||||
},
|
||||
|
||||
setFuelQuantity : func(val) {
|
||||
me.sendFuelUpdateNotification("SetFuelQuantity", val);
|
||||
},
|
||||
|
||||
updateFuelQuantity : func(val) {
|
||||
me.sendFuelUpdateNotification("UpdateFuelQuantity", val);
|
||||
},
|
||||
|
||||
# Send an update to fuel quantities
|
||||
sendFuelUpdateNotification : func(type, val)
|
||||
{
|
||||
# Use Emesary to set the default DTO waypoint
|
||||
var notification = notifications.PFDEventNotification.new(
|
||||
"MFD",
|
||||
me._page.mfd.getDeviceID(),
|
||||
notifications.PFDEventNotification.FuelData,
|
||||
{Id: type, Value: val});
|
||||
|
||||
var response = me.transmitter.NotifyAll(notification);
|
||||
if (me.transmitter.IsFailed(response)) print("Failed to set Fuel Data notification " ~ type ~ " " ~ val);
|
||||
},
|
||||
|
||||
};
|
||||
|
|
|
@ -39,9 +39,6 @@ var GenericEISPublisher =
|
|||
obj.addPropMap("EGTNorm", "/engines/engine[0]/egt-norm");
|
||||
obj.addPropMap("VacuumSuctionInHG", "/systems/vacuum/suction-inhg");
|
||||
|
||||
obj.addPropMap("LeftFuelUSGal", "/consumables/fuel/tank[0]/indicated-level-gal_us");
|
||||
obj.addPropMap("RightFuelUSGal", "/consumables/fuel/tank[1]/indicated-level-gal_us");
|
||||
|
||||
return obj;
|
||||
},
|
||||
|
||||
|
@ -62,7 +59,7 @@ var GenericEISPublisher =
|
|||
"MFD",
|
||||
1,
|
||||
notifications.PFDEventNotification.EngineData,
|
||||
engineData);
|
||||
{ Id: "EngineData", Value: engineData } );
|
||||
|
||||
me._transmitter.NotifyAll(notification);
|
||||
},
|
||||
|
|
|
@ -76,8 +76,8 @@ var GenericFMSPublisher =
|
|||
if (gpsdata["FMSLegDistanceNM"] == -1) gpsdata["FMSLegDistanceNM"] = nil;
|
||||
|
||||
# A couple of calculated values used by the MFD Header display
|
||||
var total_fuel = getprop("/consumables/fuel/tank[0]/indicated-level-gal_us") or 0.0;
|
||||
total_fuel = total_fuel + (getprop("/consumables/fuel/tank[1]/indicated-level-gal_us") or 0.0);
|
||||
var total_fuel = getprop("/consumables/fuel/tank[0]/fg1000-indicated-level-gal_us") or 0.0;
|
||||
total_fuel = total_fuel + (getprop("/consumables/fuel/tank[1]/fg1000-indicated-level-gal_us") or 0.0);
|
||||
var fuel_flow = getprop("/engines/engine[0]/fuel-flow-gph") or 1.0;
|
||||
gpsdata["FuelOnBoard"] = total_fuel;
|
||||
gpsdata["EnduranceHrs"] = total_fuel / fuel_flow;
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
# Copyright 2018 Stuart Buchanan
|
||||
# This file is part of FlightGear.
|
||||
#
|
||||
# FlightGear is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# FlightGear is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with FlightGear. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Emesary interface to set fuel information, mainly updating fuel levels.
|
||||
#
|
||||
|
||||
var GenericFuelInterface = {
|
||||
|
||||
new : func ()
|
||||
{
|
||||
var obj = { parents : [ GenericFuelInterface ] };
|
||||
|
||||
# Emesary
|
||||
obj._recipient = nil;
|
||||
obj._transmitter = emesary.GlobalTransmitter;
|
||||
obj._registered = 0;
|
||||
|
||||
return obj;
|
||||
},
|
||||
|
||||
# Simply update the fuel quantities with the increment. Note that we assume
|
||||
# the increment is added to both left and right tanks, rather than being a
|
||||
# total quanity split between tanks.
|
||||
updateFuelQuantity : func(incr)
|
||||
{
|
||||
var fuel = getprop("/consumables/fuel/tank[0]/fg1000-indicated-level-gal_us") + incr;
|
||||
setprop("/consumables/fuel/tank[0]/fg1000-indicated-level-gal_us", fuel);
|
||||
|
||||
fuel = getprop("/consumables/fuel/tank[1]/fg1000-indicated-level-gal_us") + incr;
|
||||
setprop("/consumables/fuel/tank[1]/fg1000-indicated-level-gal_us", fuel);
|
||||
},
|
||||
|
||||
# Set the fuel quantities. Note that we assume we are setting the value
|
||||
# to both tanks, rather than splitting between them.
|
||||
setFuelQuantity : func(val)
|
||||
{
|
||||
setprop("/consumables/fuel/tank[0]/fg1000-indicated-level-gal_us", val);
|
||||
setprop("/consumables/fuel/tank[1]/fg1000-indicated-level-gal_us", val);
|
||||
},
|
||||
|
||||
RegisterWithEmesary : func()
|
||||
{
|
||||
if (me._recipient == nil){
|
||||
me._recipient = emesary.Recipient.new("FuelInterface");
|
||||
var controller = me;
|
||||
|
||||
# Note that unlike the various keys, this data isn't specific to a particular
|
||||
# Device - it's shared by all. Hence we don't check for the notificaiton
|
||||
# Device_Id.
|
||||
me._recipient.Receive = func(notification)
|
||||
{
|
||||
if (notification.NotificationType == notifications.PFDEventNotification.DefaultType and
|
||||
notification.Event_Id == notifications.PFDEventNotification.FuelData and
|
||||
notification.EventParameter != nil)
|
||||
{
|
||||
var id = notification.EventParameter.Id;
|
||||
|
||||
if (id == "UpdateFuelQuantity") {
|
||||
notification.EventParameter.Value = controller.updateFuelQuantity(notification.EventParameter.Value);
|
||||
return emesary.Transmitter.ReceiptStatus_Finished;
|
||||
}
|
||||
if (id == "SetFuelQuantity") {
|
||||
notification.EventParameter.Value = controller.setFuelQuantity(notification.EventParameter.Value);
|
||||
return emesary.Transmitter.ReceiptStatus_Finished;
|
||||
}
|
||||
}
|
||||
return emesary.Transmitter.ReceiptStatus_NotProcessed;
|
||||
};
|
||||
}
|
||||
|
||||
me._transmitter.Register(me._recipient);
|
||||
me._registered = 1;
|
||||
},
|
||||
|
||||
DeRegisterWithEmesary : func()
|
||||
{
|
||||
# remove registration from transmitter; but keep the recipient once it is created.
|
||||
if (me._registered == 1) me._transmitter.DeRegister(me._recipient);
|
||||
me._registered = 0;
|
||||
},
|
||||
|
||||
|
||||
start : func() {
|
||||
me.RegisterWithEmesary();
|
||||
},
|
||||
stop : func() {
|
||||
me.DeRegisterWithEmesary();
|
||||
},
|
||||
|
||||
};
|
|
@ -0,0 +1,72 @@
|
|||
# Copyright 2018 Stuart Buchanan
|
||||
# This file is part of FlightGear.
|
||||
#
|
||||
# FlightGear is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# FlightGear is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with FlightGear. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Fuel Publisher, providing information about fuel tank contents
|
||||
var GenericFuelPublisher =
|
||||
{
|
||||
|
||||
new : func (frequency=1.0) {
|
||||
var obj = {
|
||||
parents : [
|
||||
GenericFuelPublisher,
|
||||
PeriodicPropertyPublisher.new(notifications.PFDEventNotification.FuelData, frequency)
|
||||
],
|
||||
};
|
||||
|
||||
obj.deltaT = frequency;
|
||||
|
||||
|
||||
# Hack to handle most aircraft not having proper engine hours
|
||||
if (getprop("/engines/engine[0]/hours") == nil) setprop("/engines/engine[0]/hours", 157.0);
|
||||
|
||||
# Assume pilot has correct fuel quantities entered at Start of Day
|
||||
var tanks = props.getNode("/consumables/fuel",1).getChildren("tank");
|
||||
|
||||
foreach(var tank; tanks) {
|
||||
var actual = tank.getNode("level-gal_us", 1).getValue();
|
||||
var indicatedNode = tank.getNode("fg1000-indicated-level-gal_us", 1);
|
||||
if (indicatedNode.getValue() == nil) indicatedNode.setValue(actual);
|
||||
}
|
||||
|
||||
return obj;
|
||||
},
|
||||
|
||||
# Custom publish method as we package the values into an array of fuel tanks,
|
||||
# assuming that fuel is drawn evenly from both tanks.
|
||||
publish : func() {
|
||||
var tank_data = [];
|
||||
var tanks = props.getNode("/consumables/fuel",1).getChildren("tank");
|
||||
|
||||
foreach(var tank; tanks) {
|
||||
var indicatedNode = tank.getNode("fg1000-indicated-level-gal_us", 1);
|
||||
var fuel = indicatedNode.getValue();
|
||||
if (fuel == nil) fuel = 0;
|
||||
var fuel_flow = getprop("/engines/engine[0]/fuel-flow-gph");
|
||||
if (fuel_flow == nil) fuel_flow = 0;
|
||||
fuel = fuel - fuel_flow*me.deltaT/3600.0/2;
|
||||
indicatedNode.setValue(fuel);
|
||||
append(tank_data, {"FuelUSGal": fuel});
|
||||
}
|
||||
|
||||
var notification = notifications.PFDEventNotification.new(
|
||||
"MFD",
|
||||
1,
|
||||
notifications.PFDEventNotification.FuelData,
|
||||
{ Id : "FuelData", Value : tank_data} );
|
||||
|
||||
me._transmitter.NotifyAll(notification);
|
||||
},
|
||||
};
|
|
@ -26,6 +26,8 @@ io.load_nasal(nasal_dir ~ 'Interfaces/GenericNavComUpdater.nas', "fg1000");
|
|||
io.load_nasal(nasal_dir ~ 'Interfaces/GenericFMSPublisher.nas', "fg1000");
|
||||
io.load_nasal(nasal_dir ~ 'Interfaces/GenericFMSUpdater.nas', "fg1000");
|
||||
io.load_nasal(nasal_dir ~ 'Interfaces/GenericADCPublisher.nas', "fg1000");
|
||||
io.load_nasal(nasal_dir ~ 'Interfaces/GenericFuelInterface.nas', "fg1000");
|
||||
io.load_nasal(nasal_dir ~ 'Interfaces/GenericFuelPublisher.nas', "fg1000");
|
||||
|
||||
var GenericInterfaceController = {
|
||||
|
||||
|
@ -53,6 +55,8 @@ var GenericInterfaceController = {
|
|||
obj.gpsPublisher = fg1000.GenericFMSPublisher.new();
|
||||
obj.gpsUpdater = fg1000.GenericFMSUpdater.new();
|
||||
obj.adcPublisher = fg1000.GenericADCPublisher.new();
|
||||
obj.fuelPublisher = fg1000.GenericFuelPublisher.new();
|
||||
obj.fuelInterface = fg1000.GenericFuelInterface.new();
|
||||
|
||||
return obj;
|
||||
},
|
||||
|
@ -66,6 +70,8 @@ var GenericInterfaceController = {
|
|||
me.gpsPublisher.start();
|
||||
me.gpsUpdater.start();
|
||||
me.adcPublisher.start();
|
||||
me.fuelPublisher.start();
|
||||
me.fuelInterface.start();
|
||||
},
|
||||
|
||||
stop : func() {
|
||||
|
@ -77,5 +83,7 @@ var GenericInterfaceController = {
|
|||
me.gpsPublisher.stop();
|
||||
me.gpsUpdater.stop();
|
||||
me.adcPublisher.stop();
|
||||
me.fuelPublisher.stop();
|
||||
me.fuelInterface.stop();
|
||||
},
|
||||
};
|
||||
|
|
|
@ -559,6 +559,7 @@ var PFDEventNotification =
|
|||
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 : 9, #event parameter containing a hash of updated Air Data Computer information (track, ground-speed etc.)
|
||||
FuelData: 10, #event parameter contains a single { Id: , Value: } tuple either updating or requesting a particular type of fuel data
|
||||
|
||||
DefaultType : "PFDEventNotification",
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue