GSX synced loading of fuel

This commit is contained in:
Kilian Hofmann 2026-02-13 21:34:56 +01:00
parent 69680ced03
commit 487ed3f589
10 changed files with 78 additions and 52 deletions

View File

@ -10,6 +10,5 @@ Index: EFB.html
-<script type="text/html" import-async="false" import-script="/Pages/VCockpit/Instruments/aircraft_efb/TFDi_MD11_efb/efb.index.js"></script> -<script type="text/html" import-async="false" import-script="/Pages/VCockpit/Instruments/aircraft_efb/TFDi_MD11_efb/efb.index.js"></script>
+<script type="text/html" import-async="false" import-script="/Pages/VCockpit/Instruments/aircraft_efb/KH_TFDi_MD11_efb/efb.index.js"></script> +<script type="text/html" import-async="false" import-script="/Pages/VCockpit/Instruments/aircraft_efb/KH_TFDi_MD11_efb/efb.index.js"></script>
-<link rel="stylesheet" href="/Pages/VCockpit/Instruments/aircraft_efb/TFDi_MD11_efb/efb.css" /> <link rel="stylesheet" href="/Pages/VCockpit/Instruments/aircraft_efb/TFDi_MD11_efb/efb.css" />
+<link rel="stylesheet" href="/Pages/VCockpit/Instruments/aircraft_efb/KH_TFDi_MD11_efb/efb.css" />
+<link rel="stylesheet" href="/Pages/VCockpit/Instruments/aircraft_efb/KH_TFDi_MD11_efb/App.css" /> +<link rel="stylesheet" href="/Pages/VCockpit/Instruments/aircraft_efb/KH_TFDi_MD11_efb/App.css" />

View File

@ -2,7 +2,7 @@ Index: EFB.js
=================================================================== ===================================================================
--- EFB.js --- EFB.js
+++ EFB.js +++ EFB.js
@@ -40265,11 +40265,11 @@ @@ -50827,11 +50827,11 @@
), ),
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)( /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
"button", "button",
@ -16,7 +16,7 @@ Index: EFB.js
), ),
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)( /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
"button", "button",
@@ -40767,8 +40767,27 @@ @@ -51337,8 +51337,27 @@
] }) ] })
] }) }) }); ] }) }) });
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "tfdidesign-md11-load-manager", "name": "tfdidesign-md11-load-manager",
"version": "0.2.10", "version": "0.2.17",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"type": "module", "type": "module",

View File

@ -21,14 +21,28 @@ export default function Input(props: {
const blurRef = useRef<boolean>(false); const blurRef = useRef<boolean>(false);
const [isFocused, setFocused] = useState(false); const [isFocused, setFocused] = useState(false);
const [showKeyboard, setShowKeyboard] = useState(false); const [showKeyboard, setShowKeyboard] = useState(false);
const [unfocusTimer, setUnfocusTimer] = useState<NodeJS.Timeout | null>(null);
useEffect(() => { useEffect(() => {
if (unfocusTimer) {
clearTimeout(unfocusTimer);
setUnfocusTimer(null);
}
if (isFocused) { if (isFocused) {
setUnfocusTimer(setTimeout(() => ref.current?.blur(), 5e3));
Coherent.trigger('FOCUS_INPUT_FIELD', guid, '', '', '', false); Coherent.trigger('FOCUS_INPUT_FIELD', guid, '', '', '', false);
} else { } else {
console.log('UNFOCUS_INPUT_FIELD'); console.log('UNFOCUS_INPUT_FIELD');
Coherent.trigger('UNFOCUS_INPUT_FIELD', guid); Coherent.trigger('UNFOCUS_INPUT_FIELD', guid);
} }
return () => {
if (unfocusTimer) {
clearTimeout(unfocusTimer);
setUnfocusTimer(null);
}
};
}, [isFocused, guid]); }, [isFocused, guid]);
return ( return (
@ -60,6 +74,11 @@ export default function Input(props: {
}} }}
onChange={(e) => { onChange={(e) => {
if (props.onChange) props.onChange(e.target.value); if (props.onChange) props.onChange(e.target.value);
if (unfocusTimer) {
clearTimeout(unfocusTimer);
setUnfocusTimer(null);
}
if (isFocused) setUnfocusTimer(setTimeout(() => ref.current?.blur(), 5e3));
}} }}
value={props.value} value={props.value}
className={props.className} className={props.className}

View File

@ -26,7 +26,7 @@ const StationEntryPax: FC<StationEntryProps> = ({
const [economy2, setEconomy2] = useState(WASMData.targetPayload.economy2); const [economy2, setEconomy2] = useState(WASMData.targetPayload.economy2);
const [forwardCargo, setForwardCargo] = useState(WASMData.targetPayload.forwardCargo); const [forwardCargo, setForwardCargo] = useState(WASMData.targetPayload.forwardCargo);
const [rearCargo, setRearCargo] = useState(WASMData.targetPayload.rearCargo); const [rearCargo, setRearCargo] = useState(WASMData.targetPayload.rearCargo);
const [fuel, setFuel] = useState(Math.round(WASMData.livePayload.fuel)); const [fuel, setFuel] = useState(Math.round(WASMData.targetPayload.fuel));
const ZFW = () => { const ZFW = () => {
if (loadingState !== 'loaded' && !gsxActive) return Math.round(WASMData.targetPayload.total); if (loadingState !== 'loaded' && !gsxActive) return Math.round(WASMData.targetPayload.total);

View File

@ -453,6 +453,12 @@ extern "C" MSFS_CALLBACK void module_init(void) {
log(stderr, "Could not add L:FSDT_GSX_DEBOARDING_CARGO_PERCENT to data definition, terminating.\n"); log(stderr, "Could not add L:FSDT_GSX_DEBOARDING_CARGO_PERCENT to data definition, terminating.\n");
return; return;
} }
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_GSX, "L:FSDT_GSX_FUELHOSE_CONNECTED", "number",
SIMCONNECT_DATATYPE_FLOAT64);
if (hr != S_OK) {
log(stderr, "Could not add L:FSDT_GSX_FUELHOSE_CONNECTED to data definition, terminating.\n");
return;
}
// User LVars // User LVars
hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_USER_DATA, "L:MD11_EFB_IS_CARGO", "bool", hr = SimConnect_AddToDataDefinition(simConnect, DATA_DEFINITION_USER_DATA, "L:MD11_EFB_IS_CARGO", "bool",
SIMCONNECT_DATATYPE_FLOAT64); SIMCONNECT_DATATYPE_FLOAT64);
@ -619,28 +625,30 @@ extern "C" MSFS_CALLBACK bool Load_Manager_gauge_callback(FsContext ctx, int ser
lookup_var(&tick18); lookup_var(&tick18);
if (fmod(tick18.var_value.n, 3) == 0) sendData(); if (fmod(tick18.var_value.n, 3) == 0) sendData();
if (GSXData->fuelingState == FUELING_STATE_FUELING && abs(liveFuelData->total - targetFuelData->total) < 0.1) { // Terminate
GSXData->fuelingState = FUELING_STATE_FUELD; if (GSXData->fuelingState == FUELING_STATE_FUELING && abs(liveFuelData->total - targetFuelData->total) < 1) {
GSXData->fuelingState = FUELING_STATE_FUELED;
fuel(targetFuelData, simConnect); fuel(targetFuelData, simConnect);
} }
dTime += d->dt; FuelData_t toSet = {};
if (GSXData->fuelingState == FUELING_STATE_FUELING && dTime >= 0.5) { // Force set to lower before connection
if (GSXData->fuelingState == FUELING_STATE_CALLED && targetFuelData->total <= liveFuelData->total) {
distribute(&toSet, max(0, targetFuelData->total - 10000), true, UserData->isER);
FuelData_t toSet = {}; fuel(&toSet, simConnect);
}
// Fuel
else if (GSXData->fuelingState == FUELING_STATE_FUELING && GSXData->fuelConnected > 0) {
dTime += d->dt;
if (targetFuelData->total > liveFuelData->total) { if (dTime < 0.5) break;
distribute(&toSet,
min(targetFuelData->total, distribute(&toSet,
liveFuelData->total + min(max(targetFuelData->total - liveFuelData->total, 1), FUELING_RATE) * dTime), min(targetFuelData->total,
true, UserData->isER); liveFuelData->total + min(max(targetFuelData->total - liveFuelData->total, 1), FUELING_RATE) * dTime),
} else { true, UserData->isER);
distribute(&toSet,
max(targetFuelData->total,
liveFuelData->total + max(min(targetFuelData->total - liveFuelData->total, -1), -FUELING_RATE) * dTime),
true, UserData->isER);
}
dTime = 0; dTime = 0;
@ -1167,6 +1175,7 @@ void CALLBACK MyDispatchProc(SIMCONNECT_RECV *pData, DWORD cbData, void *pContex
GSXData->passengersDeboarded = data->passengersDeboarded; GSXData->passengersDeboarded = data->passengersDeboarded;
GSXData->cargoBoarded = data->cargoBoarded; GSXData->cargoBoarded = data->cargoBoarded;
GSXData->cargoDeboarded = data->cargoDeboarded; GSXData->cargoDeboarded = data->cargoDeboarded;
GSXData->fuelConnected = data->fuelConnected;
if (UserOptions->GSXSync && GSXData->couatlStarted == 1) { if (UserOptions->GSXSync && GSXData->couatlStarted == 1) {
switch ((char)GSXData->boardingState) { switch ((char)GSXData->boardingState) {
@ -1325,13 +1334,18 @@ void CALLBACK MyDispatchProc(SIMCONNECT_RECV *pData, DWORD cbData, void *pContex
break; break;
} }
case GSX_SERVICE_CALLED: {
GSXData->fuelingState = FUELING_STATE_CALLED;
break;
}
case GSX_SERVICE_ACTIVE: { case GSX_SERVICE_ACTIVE: {
GSXData->fuelingState = FUELING_STATE_FUELING; GSXData->fuelingState = FUELING_STATE_FUELING;
break; break;
} }
case GSX_SERVICE_FINISHED: { case GSX_SERVICE_FINISHED: {
GSXData->fuelingState = FUELING_STATE_FUELD; GSXData->fuelingState = FUELING_STATE_FUELED;
fuel(targetFuelData, simConnect); fuel(targetFuelData, simConnect);
break; break;

View File

@ -34,7 +34,7 @@
/******************************** Constants ********************************/ /******************************** Constants ********************************/
// Module identification // Module identification
#define MODULE_NAME "[KHOFMANN TFDi MD-11 Load Manager] " #define MODULE_NAME "[KHOFMANN TFDi MD-11 Load Manager] "
#define VERSION_STRING "2.12-beta" #define VERSION_STRING "2.19"
// COMM BUS // COMM BUS
#define COMM_BUS_LIVE_DATA_EVENT "khofmann_tfdi_md-11_load_manager_live_data" #define COMM_BUS_LIVE_DATA_EVENT "khofmann_tfdi_md-11_load_manager_live_data"
#define COMM_BUS_UPDATE_TARGET_EVENT "khofmann_tfdi_md-11_load_manager_update_target" #define COMM_BUS_UPDATE_TARGET_EVENT "khofmann_tfdi_md-11_load_manager_update_target"

View File

@ -46,6 +46,7 @@
#define CG_TOLERANCE 0.05 #define CG_TOLERANCE 0.05
// GSX States // GSX States
#define GSX_SERVICE_IDLE 1 #define GSX_SERVICE_IDLE 1
#define GSX_SERVICE_CALLED 4
#define GSX_SERVICE_ACTIVE 5 #define GSX_SERVICE_ACTIVE 5
#define GSX_SERVICE_FINISHED 6 #define GSX_SERVICE_FINISHED 6
@ -85,7 +86,7 @@ enum LOADING_STATES {
LOADING_STATE_DEBOARDED, LOADING_STATE_DEBOARDED,
}; };
enum FUELING_STATES { FUELING_STATE_IDLE, FUELING_STATE_FUELING, FUELING_STATE_FUELD }; enum FUELING_STATES { FUELING_STATE_IDLE, FUELING_STATE_CALLED, FUELING_STATE_FUELING, FUELING_STATE_FUELED };
enum CALL_MODES { enum CALL_MODES {
CALL_MODE_SB_SET, CALL_MODE_SB_SET,
@ -114,6 +115,7 @@ typedef struct {
double passengersDeboarded; // Num pax double passengersDeboarded; // Num pax
double cargoBoarded; // In percent double cargoBoarded; // In percent
double cargoDeboarded; // In percent double cargoDeboarded; // In percent
double fuelConnected; // boolean
// Additional properties // Additional properties
enum LOADING_STATES loadingState; enum LOADING_STATES loadingState;

View File

@ -1,3 +0,0 @@
TEST progressive fueling
TEST progressive loading/unloading ZFWCG
Implement minimum fuel in tank (i.e. unusable)

View File

@ -1,45 +1,40 @@
const { applyPatch } = require("diff"); const { applyPatch } = require('diff');
const fs = require("fs"); const fs = require('fs');
const util = require("node:util"); const readline = require('readline');
const exec = util.promisify(require("node:child_process").exec);
const readline = require("readline");
const outPath = const outPath = './PackageSources/html_ui/Pages/VCockpit/Instruments/aircraft_efb/KH_TFDi_MD11_efb';
"./PackageSources/html_ui/Pages/VCockpit/Instruments/aircraft_efb/KH_TFDi_MD11_efb";
fs.copyFileSync("./EFB/efb.css", `${outPath}/efb.css`); let file1Contents = fs.readFileSync('./EFB/efb.js').toString();
let patch = fs.readFileSync('./EFB/efb-js.patch').toString();
let file1Contents = fs.readFileSync("./EFB/efb.js").toString();
let patch = fs.readFileSync("./EFB/efb-js.patch").toString();
let patchedFile = applyPatch(file1Contents, patch); let patchedFile = applyPatch(file1Contents, patch);
fs.writeFileSync(`${outPath}/efb.js`, patchedFile); fs.writeFileSync(`${outPath}/efb.js`, patchedFile);
file1Contents = fs.readFileSync("./EFB/efb.index.js").toString(); file1Contents = fs.readFileSync('./EFB/efb.index.js').toString();
patch = fs.readFileSync("./EFB/efb-index-js.patch").toString(); patch = fs.readFileSync('./EFB/efb-index-js.patch').toString();
patchedFile = applyPatch(file1Contents, patch); patchedFile = applyPatch(file1Contents, patch);
fs.writeFileSync(`${outPath}/efb.index.js`, patchedFile); fs.writeFileSync(`${outPath}/efb.index.js`, patchedFile);
file1Contents = fs.readFileSync("./EFB/efb.html").toString(); file1Contents = fs.readFileSync('./EFB/efb.html').toString();
patch = fs.readFileSync("./EFB/efb-html.patch").toString(); patch = fs.readFileSync('./EFB/efb-html.patch').toString();
patchedFile = applyPatch(file1Contents, patch); patchedFile = applyPatch(file1Contents, patch);
fs.writeFileSync(`${outPath}/efb.html`, patchedFile); fs.writeFileSync(`${outPath}/efb.html`, patchedFile);
var output = ""; var output = '';
var lineReader = readline.createInterface({ var lineReader = readline.createInterface({
input: fs.createReadStream(`${outPath}/App.js`), input: fs.createReadStream(`${outPath}/App.js`),
}); });
lineReader.on("line", (line) => { lineReader.on('line', (line) => {
if (line.startsWith("import")) { if (line.startsWith('import')) {
output += "// " + line + "\n"; output += '// ' + line + '\n';
} else if (line.startsWith("export")) { } else if (line.startsWith('export')) {
output += "window.KH_LM = App;\n"; output += 'window.KH_LM = App;\n';
} else { } else {
output += line + "\n"; output += line + '\n';
} }
}); });
lineReader.on("close", () => { lineReader.on('close', () => {
fs.writeFile(`${outPath}/App.js`, output, (err) => { fs.writeFile(`${outPath}/App.js`, output, (err) => {
if (err) console.log(err); if (err) console.log(err);
console.log("Import/Export removed."); console.log('Import/Export removed.');
}); });
}); });