11
GSX Backdoor / Re: PLEASE MAKE WING WALKERS APART OF GSE GATE PARK EDIT
« Last post by gxsr911 on December 04, 2025, 05:38:29 pm »
THANK YOU SO MUCH!!!! CANT WAIT TO SEE IT!!!!
THANK YOU SO MUCH!!!! CANT WAIT TO SEE IT!!!!import os
import sys
import time
import math
# --- Path Correction ---
HERE = os.path.dirname(os.path.abspath(__file__))
PROJECT_ROOT = os.path.abspath(os.path.join(HERE, '..'))
if PROJECT_ROOT not in sys.path:
sys.path.insert(0, PROJECT_ROOT)
import command_executor
from core.services import simconnect_service
# ==============================================================================
# --- SCRIPT CONFIGURATION ---
# ==============================================================================
# Set to True to call the GSX fuel truck and wait for the hose animation.
# Set to False to skip GSX and start refueling immediately.
USE_GSX = True
# --- Fuel Conversion Constant ---
# Based on standard Jet A1 density. Gallons are required for Fenix A-Vars.
KG_TO_GAL_FACTOR = 3.039 # Approx. KG per US Gallon
# --- Tweakable Parameters ---
REFUEL_RATE_KG_SEC = 15 # Kilograms per second loading rate
UPDATE_INTERVAL_SEC = 1.0 # Seconds between updates for smoother ECAM display and faster GSX state monitoring
# ==============================================================================
def perform_flow(vr, active_profile_path=None):
"""
Progressively adds fuel until the target is reached.
Can optionally integrate with GSX to call the truck and sync with animations.
"""
print("\n--- Progressive Refuel Process ---")
if USE_GSX:
print("--- GSX Integration: ENABLED ---")
else:
print("--- GSX Integration: DISABLED ---")
print("[SETUP] Adding subscriptions...")
command_executor.add_subscription("(L:N_FUEL_PRESEL, Number)")
command_executor.add_subscription("(A:FUEL TANK LEFT MAIN QUANTITY, Gallons)")
command_executor.add_subscription("(A:FUEL TANK RIGHT MAIN QUANTITY, Gallons)")
if USE_GSX:
command_executor.add_subscription("(L:FSDT_GSX_REFUELING_STATE, Number)")
command_executor.add_subscription("(L:FSDT_GSX_FUELHOSE_CONNECTED, Number)")
time.sleep(1.0)
try:
if USE_GSX:
# === PART 1: SILENTLY CALL THE FUEL TRUCK ===
# CRITICAL: Disable GSX internal logic to cede full control to this script.
# This prevents GSX from prematurely ending the service.
print("[GSX_CTL] Disabling internal GSX progressive refueling logic...")
simconnect_service.set_lvar(vr, "FSDT_GSX_SET_DETECT_CUST_REFUEL", 1)
simconnect_service.set_lvar(vr, "FSDT_GSX_SET_PROGRESS_REFUEL", 1)
time.sleep(0.5) # Allow settings to register before calling menu
print("\n[GSX] Requesting Refuel via GSX L-Vars (Silent)...")
simconnect_service.set_lvar(vr, "FSDT_GSX_MENU_OPEN", 1)
time.sleep(1.5)
simconnect_service.set_lvar(vr, "FSDT_GSX_MENU_CHOICE", 2) # 2 = Refueling
time.sleep(1.0)
simconnect_service.set_lvar(vr, "FSDT_GSX_MENU_CHOICE", 0) # Close menu
# --- Wait for a valid fuel target from the user ---
target_fuel_kg = 0.0
while True:
target_fuel_kg_raw = simconnect_service._direct_get_lvar(vr, "N_FUEL_PRESEL")
if target_fuel_kg_raw is not None and target_fuel_kg_raw > 0:
temp_target = float(target_fuel_kg_raw) * 1000.0 if target_fuel_kg_raw < 100 else float(target_fuel_kg_raw)
if temp_target > 100:
target_fuel_kg = temp_target
print(f" Target Fuel Found: {target_fuel_kg:.0f} KG")
if USE_GSX:
# Sync GSX counter max value with the AMOUNT TO FUEL (Delta)
# Not the total amount!
current_fuel_kg = (simconnect_service.get_sim_variable("L:N_FUEL_TOTAL_QTY") or 0.0) * 1000.0
amount_to_refuel = target_fuel_kg - current_fuel_kg
if amount_to_refuel < 0: amount_to_refuel = 0
simconnect_service.set_lvar(vr, "FSDT_GSX_FUEL_COUNTER_MAX", amount_to_refuel)
break
print("Waiting for valid Fuel Pre-selection (>100kg)...")
time.sleep(1.0)
if USE_GSX:
# === PART 2: WAIT FOR GSX TO BE READY ===
print("\n[GSX] Waiting for GSX service to become active (State: 5, Hose: 1)...")
service_ready = False
wait_start = time.time()
last_gsx_state = None
last_hose_state = None
while time.time() - wait_start < 360:
gsx_state = simconnect_service.get_sim_variable("L:FSDT_GSX_REFUELING_STATE")
hose_state = simconnect_service.get_sim_variable("L:FSDT_GSX_FUELHOSE_CONNECTED")
# Only log when state changes
if gsx_state != last_gsx_state or hose_state != last_hose_state:
print(f" > GSX State: {gsx_state}, Hose Connected: {hose_state}")
last_gsx_state = gsx_state
last_hose_state = hose_state
if gsx_state == 5 and hose_state == 1:
print("\n✅ [GSX] Service is active and hose is connected. Starting fuel loading.")
service_ready = True
break
time.sleep(1.0)
if not service_ready:
print("\n❌ [FAILURE] Timeout waiting for GSX service to become active.")
return
# ====================================================================
# --- CORE REFUELING LOGIC (Virtual Accumulator Method) ---
# ====================================================================
# 1. Get current fuel state from the sim ONCE.
initial_left_gal = simconnect_service._direct_get_avar(vr, "FUEL TANK LEFT MAIN QUANTITY", "Gallons")
initial_right_gal = simconnect_service._direct_get_avar(vr, "FUEL TANK RIGHT MAIN QUANTITY", "Gallons")
if initial_left_gal is None or initial_right_gal is None:
print(" [FAILURE] Could not read initial fuel tank quantities. Aborting.")
return
# 2. Initialize VIRTUAL accumulators. These are now the source of truth for the loop.
virtual_left_gal = initial_left_gal
virtual_right_gal = initial_right_gal
virtual_total_kg = (virtual_left_gal + virtual_right_gal) * KG_TO_GAL_FACTOR
# Check if we are defueling or refueling
if virtual_total_kg > target_fuel_kg:
print(f" > Defueling not supported by this script. Aborting.")
return
print(f"\n[REFUEL] Starting State: {virtual_total_kg:.0f} KG | Target: {target_fuel_kg:.0f} KG")
last_loop_time = time.time()
# 3. Loop based on our VIRTUAL state, not the sim's state.
while virtual_total_kg < target_fuel_kg:
current_time = time.time()
dt = current_time - last_loop_time
last_loop_time = current_time
# Calculate how much fuel to add this cycle
kg_to_add_this_cycle = REFUEL_RATE_KG_SEC * dt
# --- ACCURACY FIX: Prevent overshoot on the final step ---
remaining_kg = target_fuel_kg - virtual_total_kg
if kg_to_add_this_cycle > remaining_kg:
kg_to_add_this_cycle = remaining_kg
# 4. Increment VIRTUAL accumulators
gal_to_add_per_tank = (kg_to_add_this_cycle / 2.0) / KG_TO_GAL_FACTOR
virtual_left_gal += gal_to_add_per_tank
virtual_right_gal += gal_to_add_per_tank
virtual_total_kg += kg_to_add_this_cycle
# 5. Force-feed the new VIRTUAL state to the sim.
simconnect_service.execute_rpn(vr, f"{virtual_left_gal} (>A:FUEL TANK LEFT MAIN QUANTITY, Gallons)")
simconnect_service.execute_rpn(vr, f"{virtual_right_gal} (>A:FUEL TANK RIGHT MAIN QUANTITY, Gallons)")
log_msg = f" > [SIMULATING] Current: {virtual_total_kg:.0f} KG / Target: {target_fuel_kg:.0f} KG"
# Optional check for GSX state if enabled
if USE_GSX:
gsx_state = simconnect_service.get_sim_variable("L:FSDT_GSX_REFUELING_STATE")
hose_state = simconnect_service.get_sim_variable("L:FSDT_GSX_FUELHOSE_CONNECTED")
log_msg += f" | GSX State: {gsx_state}"
# The main 'while' loop already checks if the target is met.
# Therefore, if this code is running, we are NOT at the target yet.
# Any GSX state other than "actively refueling" is premature and must be overridden.
if gsx_state != 5 or hose_state != 1:
print(f" > [GSX_OVERRIDE] GSX state not active (State: {gsx_state}, Hose: {hose_state}). Forcing continue.")
simconnect_service.set_lvar(vr, "FSDT_GSX_REFUELING_STATE", 5) # Force back to "in progress"
simconnect_service.set_lvar(vr, "FSDT_GSX_FUELHOSE_CONNECTED", 1) # Force hose to "connected"
print(log_msg)
time.sleep(UPDATE_INTERVAL_SEC)
print(f" [SUCCESS] Target Fuel Level Reached.")
if USE_GSX:
print("[GSX] Fuel target met. Releasing GSX service and stopping animation.")
simconnect_service.set_lvar(vr, "FSDT_GSX_REFUELING_STATE", 6) # Command GSX to "Completed"
# Finalization: Set the exact value one last time to guarantee precision
target_liters_per_tank = (target_fuel_kg / 2.0) / KG_TO_GAL_FACTOR
simconnect_service.execute_rpn(vr, f"{target_liters_per_tank} (>A:FUEL TANK LEFT MAIN QUANTITY, Gallons)")
simconnect_service.execute_rpn(vr, f"{target_liters_per_tank} (>A:FUEL TANK RIGHT MAIN QUANTITY, Gallons)")
print(f" > Final precise fuel set to {target_fuel_kg:.0f} KG.")
except KeyboardInterrupt:
print("\nProcess interrupted by user.")
except Exception as e:
print(f"\n[ERROR] An unexpected error occurred: {e}")
def main():
if not command_executor.start_manager():
print("[FATAL] Could not connect to the simulator. Exiting.")
return
vr = command_executor.get_vr_connection()
if not vr:
print("[FATAL] Failed to get connection object. Exiting.")
command_executor.stop_manager()
return
try:
perform_flow(vr)
except Exception as e:
print(f"An error occurred during the flow: {e}")
finally:
print("\n[TEARDOWN] Disconnecting from the simulator.")
command_executor.stop_manager()
print("--- Test Complete ---")
if __name__ == "__main__":
main()