Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: EFB Setting to enable MCDU Server connection to avoid too many connection attempts #6947

Merged
merged 12 commits into from
Mar 23, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Refactor to have three MCDO Connect Modes: AUTO ON, AUTO OFF, PERM OFF
  • Loading branch information
frankkopp committed Mar 21, 2022
commit aa5e99c19509ddddf1b87e2d18181a877b26dbee
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ class A320_Neo_CDU_MainDisplay extends FMCMainDisplay {
this.updateRequest = false;
this.initB = false;
this.lastPowerState = 0;
this.socket = undefined;
this.socketConnectionRetries = 0;
this.PageTimeout = {
Fast: 500,
Medium: 1000,
Expand Down Expand Up @@ -119,6 +117,18 @@ class A320_Neo_CDU_MainDisplay extends FMCMainDisplay {
AOCSentMsgs: 74,
AOCFreeText: 75,
};

// Handling of MCDU Sever connection attempts
this.socket = undefined;
this.socketConnectionAttempts = 0;
this.maxConnectionAttempts = 60;
this.mcduServerConnect = NXDataStore.get("CONFIG_EXTERNAL_MCDU_SERVER_ENABLED", 'AUTO ON');
if (this.mcduServerConnect === 'AUTO OFF') {
NXDataStore.set("CONFIG_EXTERNAL_MCDU_SERVER_ENABLED", 'AUTO ON');
this.mcduServerConnect = 'AUTO ON';
} else if (this.mcduServerConnect === 'PERM OFF') {
console.log("MCDU server connection attempts permanently deactivated.");
}
}

setupFmgcTriggers() {
Expand Down Expand Up @@ -294,29 +304,39 @@ class A320_Neo_CDU_MainDisplay extends FMCMainDisplay {
}

// The MCDU is a client to the MCDU Server and tries to connect in regular intervals.
const connectionEnabled = NXDataStore.get("CONFIG_EXTERNAL_MCDU_SERVER_ENABLED", '1');
const maxConnectionAttempts = 60;
// Due to an issue with the sim's Coherent engine we need to avoid trying
// to connect the websocket continuously. The below solution based on an EFB setting
// and a maximal number of attempts should mitigate the issue until
// Asobo has fixed the core issue.
if (this.mcduServerConnectUpdateThrottler.canUpdate(_deltaTime) !== -1) {
// try to connect websocket if enabled and none existing
if (connectionEnabled === '1' && (!this.socket || this.socket.readyState !== 1)) {
// we try to connect for 5min then we deactivate the connection setting
if (this.socketConnectionRetries++ >= maxConnectionAttempts) {
// Try to connect websocket if enabled in EFB and no connection established
this.mcduServerConnect = NXDataStore.get("CONFIG_EXTERNAL_MCDU_SERVER_ENABLED", 'AUTO ON');
if (this.mcduServerConnect === 'AUTO ON' && (!this.socket || this.socket.readyState !== 1)) {
// We try to connect for a fixed amount of attempts, then we deactivate the connection setting
if (this.socketConnectionAttempts++ >= this.maxConnectionAttempts) {
console.log("Maximum number of connection attempts to MCDU Server exceeded. No more attempts.");
NXDataStore.set("CONFIG_EXTERNAL_MCDU_SERVER_ENABLED", '0');
this.socketConnectionRetries = 0;
NXDataStore.set("CONFIG_EXTERNAL_MCDU_SERVER_ENABLED", 'AUTO OFF');
this.socketConnectionAttempts = 0;
} else {
console.log(`Attempting MCDU Server connection ${this.socketConnectionRetries} of ${maxConnectionAttempts} attempts.`);
console.log(`Attempting MCDU Server connection ${this.socketConnectionAttempts} of ${this.maxConnectionAttempts} attempts.`);
this.connectWebsocket(NXDataStore.get("CONFIG_EXTERNAL_MCDU_PORT", "8380"));
}
} else if (connectionEnabled !== '1' && this.socket && this.socket.readyState === 1) {
// if there is a socket existing but enabled setting has been changed then close connection
this.socket.close();
delete this.socket;
} else if (this.mcduServerConnect !== 'AUTO ON') {
if (this.socketConnectionAttempts > 0) {
console.log("MCDU server connection attempts deactivated. No more attempts.");
this.socketConnectionAttempts = 0;
}
if (this.socket && this.socket.readyState === 1) {
Saschl marked this conversation as resolved.
Show resolved Hide resolved
// If there is a connection established but the EFB setting has been changed
// then close connection
this.socket.close();
delete this.socket;
}
}
}

// There is no (known) event when power is turned on or off (e.g. Ext Pwr) and remote clients
// would not be updated (cleared or updated). Therefore monitoring power is necessary.
// would not be updated (cleared or updated). Therefore, monitoring power is necessary.
// every 500ms
if (this.powerCheckUpdateThrottler.canUpdate(_deltaTime) !== -1
&& this.socket && this.socket.readyState) {
Expand Down Expand Up @@ -1444,13 +1464,25 @@ class A320_Neo_CDU_MainDisplay extends FMCMainDisplay {
*/
connectWebsocket(port) {

if (this.socket && this.socket.readyState) {
this.socket.close();
const url = `ws://127.0.0.1:${port}`;

// There seems to be an issue with the sim's Coherent engine that
// makes it impossible to completely remove websocket objects after
// an unsuccessful connection attempt. Tests have shown the below
// leaves open sockets (visible in Coherent GT Debugger) leading
// to slow degradation of performance for some users.
// Therefore, it should be avoided to continuously do connection attempts.
// See above where this method is called for the mitigating solution.
if (this.socket) {
if (this.socket.readyState !== 0) {
// Trying to close a socket in readState == 0 leads to
// an error message ('WebSocket is closed before the connection is established')
// in the console.
this.socket.close();
}
delete this.socket;
}

const url = `ws://127.0.0.1:${port}`;

this.socket = new WebSocket(url);

this.socket.onerror = () => {
Expand All @@ -1466,7 +1498,7 @@ class A320_Neo_CDU_MainDisplay extends FMCMainDisplay {
(new NXNotif).showNotification({title: "MCDU CONNECTED", message: "Successfully connected to MCDU server.", timeout: 5000});
this.sendToSocket("mcduConnected");
this.sendUpdate();
this.socketConnectionRetries = 0;
this.socketConnectionAttempts = 0;
};

this.socket.onmessage = (event) => {
Expand Down
27 changes: 19 additions & 8 deletions src/instruments/src/EFB/Settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ const SimOptionsPage = () => {
const [dynamicRegistration, setDynamicRegistration] = usePersistentProperty('DYNAMIC_REGISTRATION_DECAL', '0');
const [defaultBaro, setDefaultBaro] = usePersistentProperty('CONFIG_INIT_BARO_UNIT', 'AUTO');
const [mcduServerPort, setMcduServerPort] = usePersistentProperty('CONFIG_EXTERNAL_MCDU_PORT', '8380');
const [mcduServerEnabled, setMcduServerEnabled] = usePersistentProperty('CONFIG_EXTERNAL_MCDU_SERVER_ENABLED', '1');
const [mcduServerEnabled, setMcduServerEnabled] = usePersistentProperty('CONFIG_EXTERNAL_MCDU_SERVER_ENABLED', 'AUTO ON');
const [radioReceiverUsage, setRadioReceiverUsage] = usePersistentProperty('RADIO_RECEIVER_USAGE_ENABLED', '0');
const [, setRadioReceiverUsageSimVar] = useSimVar('L:A32NX_RADIO_RECEIVER_USAGE_ENABLED', 'number', 0);

Expand All @@ -265,6 +265,12 @@ const SimOptionsPage = () => {
{ name: 'hPa', setting: 'HPA' },
];

const mcduServerMode: ButtonType[] = [
{ name: 'Auto On', setting: 'AUTO ON' },
{ name: 'Auto Off', setting: 'AUTO OFF' },
{ name: 'Perm Off', setting: 'PERM OFF' },
];

useEffect(() => {
setShowNavbar(!showThrottleSettings);
}, [showThrottleSettings]);
Expand Down Expand Up @@ -338,14 +344,19 @@ const SimOptionsPage = () => {

<div className="py-4 flex flex-row justify-between items-center">
<span>
<span className="text-lg text-gray-300">Enable MCDU Server Connection (deactivates after 5min)</span>
<span className="text-lg text-gray-300">Enable MCDU Server Connection (Auto On deactivates after 5 minutes if no successful connection)</span>
</span>
<Toggle
value={mcduServerEnabled === '1'}
onToggle={(value) => {
setMcduServerEnabled(value ? '1' : '0');
}}
/>
<SelectGroup>
{mcduServerMode.map((button) => (
<SelectItem
enabled
onSelect={() => setMcduServerEnabled(button.setting)}
selected={mcduServerEnabled === button.setting}
>
{button.name}
</SelectItem>
))}
</SelectGroup>
</div>

<div className="py-4 flex flex-row justify-between items-center">
Expand Down