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

feat(efb): Fix refresh of atc list issue during flight #5186

Merged
merged 28 commits into from
Jul 3, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
c37d88d
display page with the list of ATCs
ZeroKaa May 27, 2021
b4bb9bd
code simplification
ZeroKaa May 27, 2021
de71d86
fix sorting issue
ZeroKaa May 27, 2021
429bdae
clean console.log
ZeroKaa May 27, 2021
bc9b0b8
performance improvment
ZeroKaa May 27, 2021
87651a6
remove useless css file
ZeroKaa May 28, 2021
8d95683
add wrap for text atis
ZeroKaa Jun 14, 2021
7fd37c1
align with new api-client version
ZeroKaa Jun 15, 2021
9ff8d37
Merge branch 'flypados-v2' of https://github.com/flybywiresim/a32nx i…
ZeroKaa Jun 15, 2021
eb63dae
merge
ZeroKaa Jun 15, 2021
db6ab62
merge
ZeroKaa Jun 15, 2021
b7947e3
Revert "merge"
ZeroKaa Jun 16, 2021
6df3834
update api-client package
ZeroKaa Jun 16, 2021
ef45e2b
Update ATC.tsx
ZeroKaa Jun 16, 2021
d04ed0a
Revert "Update ATC.tsx"
ZeroKaa Jun 16, 2021
b3b1159
fix issue on atc list refresh
ZeroKaa Jun 16, 2021
1e3e78e
remove console.log
ZeroKaa Jun 16, 2021
c17baa3
add atis controllers in ATC page
ZeroKaa Jun 16, 2021
ea223d2
remove console.log
ZeroKaa Jun 16, 2021
234aa34
decrease refresh rate
ZeroKaa Jun 22, 2021
28fe087
Merge branch 'flypados-v2' of https://github.com/flybywiresim/a32nx i…
ZeroKaa Jun 22, 2021
fc726c9
fix refresh issue
ZeroKaa Jun 24, 2021
16b2a96
remove double load
ZeroKaa Jun 24, 2021
373e071
increase font-size
ZeroKaa Jun 24, 2021
6967808
fix distance calculation
ZeroKaa Jun 24, 2021
e983dbe
use useCallback and useInterval
ZeroKaa Jun 28, 2021
c72a812
add atisSource as dependency
ZeroKaa Jun 30, 2021
abe3d46
try to repect rules of hook
ZeroKaa Jun 30, 2021
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
Next Next commit
display page with the list of ATCs
  • Loading branch information
ZeroKaa committed May 27, 2021
commit c37d88d63784d998472d52e151df9b4b05ad9dc0
49 changes: 49 additions & 0 deletions src/instruments/src/EFB/ATC/ATC.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
.atc-buttons {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
}

.atc-button {
margin: 5px;
&.active{
color:yellow;
}
}

.button-content {
width: 200px;
max-width: 200px;
display: flex;
font-size: 1rem;
align-items: center;
.left {
margin-right: 2px;
}
.right {
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.freq {
font-size: 1rem;
}
}
}

.active-frequency {
font-size: 1.5rem;
display: flex;
color: yellow;
}


.active-atis {
margin-top: 2rem;
font-size: 1.4rem;
p {
font-size: 1.4rem;
margin: 1rem 0;
}
}
171 changes: 171 additions & 0 deletions src/instruments/src/EFB/ATC/ATC.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import React, { useState, useEffect } from 'react';
import classNames from 'classnames';
import * as apiClient from '@flybywiresim/api-client';
import { IconBuildingLighthouse, IconChartRadar, IconCircleCheck, IconPlaneArrival, IconPlaneDeparture, IconTrafficLights } from '@tabler/icons';
import { useSimVar, useSplitSimVar } from '../../Common/simVars';
import './ATC.scss';
import Button from '../Components/Button/Button';
import { usePersistentProperty } from '../../Common/persistence';

export declare class ATCInfoExtended extends apiClient.ATCInfo {
distance: number;
}

export const ATC = () => {
const [controllers, setControllers] = useState<ATCInfoExtended[]>();
const [frequency, setFrequency] = useSplitSimVar('COM ACTIVE FREQUENCY:1', 'Hz', 'K:COM_RADIO_SET_HZ', 'Hz', 500);
const [currentFrequency, setCurrentFrequency] = useState<string>();
const [currentAtc, setCurrentAtc] = useState<ATCInfoExtended>();
const [currentLatitude] = useSimVar('GPS POSITION LAT', 'Degrees', 5000);
const [currentLongitude] = useSimVar('GPS POSITION LON', 'Degrees', 5000);
const [atisSource] = usePersistentProperty('CONFIG_ATIS_SRC', 'FAA');

useEffect(() => {
loadAtc();
setInterval(() => loadAtc(), 2 * 60 * 1000);
}, []);

useEffect(() => {
setAtc();
}, [frequency]);

useEffect(() => {
loadAtc();
}, [atisSource]);

const loadAtc = () => {
apiClient.ATC.getAtc((atisSource as string).toLowerCase()).then((res) => {
let allAtc : ATCInfoExtended[] = res as ATCInfoExtended[];
for (const a of allAtc) {
a.distance = getDistanceFromLatLonInNm(a.latitude, a.longitude, currentLatitude, currentLongitude);
}
allAtc = allAtc.slice(0, 26);
allAtc.push({ callsign: 'UNICOM', frequency: '122.800', type: apiClient.AtcType.radar, visualRange: 999999, distance: 0, latitude: 0, longitude: 0, textAtis: [] });
allAtc.sort((a1, a2) => (a1.distance > a2.distance ? 1 : -1));
setControllers(allAtc.filter((a) => a.distance <= a.visualRange
&& a.callsign.indexOf('_OBS') === -1
&& parseFloat(a.frequency) <= 136.975));
if (frequency) {
const converted = fromFrequency(frequency);
const ctl = allAtc.find((c) => c.frequency === converted);
setCurrentAtc(ctl);
}
});
};

const setAtc = () => {
const converted = fromFrequency(frequency);
setCurrentFrequency(converted);
const c = controllers?.find((c) => c.frequency === converted);
setCurrentAtc(c);
};

const getDistanceFromLatLonInNm = (lat1, lon1, lat2, lon2) : number => {
const R = 6371; // Radius of the earth in km
const dLat = deg2rad(lat2 - lat1); // deg2rad below
const dLon = deg2rad(lon2 - lon1);
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2))
* Math.sin(dLon / 2) * Math.sin(dLon / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
const d = R * c * 0.5399568; // Distance in nm
return d;
};

const deg2rad = (deg) => deg * (Math.PI / 180);

const toFrequency = (frequency:string) : number => {
if (frequency) {
return parseFloat(`${frequency.replace('.', '').padEnd(9, '0')}.000`);
}
return 0;
};

const fromFrequency = (frequency:number) : string => {
if (frequency) {
let converted : string = frequency.toString().replace('.', '');
converted = `${converted.substring(0, 3)}.${converted.substring(3)}`;
return parseFloat(converted).toFixed(3);
}
return '';
};

return (
<div className="flex p-6 w-full">
{ (atisSource === 'IVAO' || atisSource === 'VATSIM') && (
<div className="w-8/12">
<h1 className="text-white font-medium mb-4 text-2xl">
{atisSource}
{' - '}
Controllers currently in range
</h1>
<div className="bg-gray-800 rounded-xl p-2 text-white shadow-lg">
<div className="flex p-2 w-full atc-buttons">
{ controllers && controllers.map((atc) => (
<Button
className={classNames({ 'atc-button': true, 'active': atc.frequency === currentFrequency })}
id="atc.callsign"
onClick={() => setFrequency(toFrequency(atc.frequency))}
>
<div className="button-content">
<div className="left">
{ atc.type === apiClient.AtcType.radar && <IconChartRadar size="2rem" /> }
{ atc.type === apiClient.AtcType.ground && <IconTrafficLights size="2rem" /> }
{ atc.type === apiClient.AtcType.departure && <IconPlaneDeparture size="2rem" /> }
{ atc.type === apiClient.AtcType.approach && <IconPlaneArrival size="2rem" /> }
{ atc.type === apiClient.AtcType.tower && <IconBuildingLighthouse size="2rem" /> }
{ atc.type === apiClient.AtcType.delivery && <IconCircleCheck size="2rem" /> }
</div>
<div className="right">
<div>
{atc.callsign}
</div>
<div className="freq">
{atc.frequency}
</div>
</div>
</div>
</Button>
))}
</div>
</div>
</div>
)}

{ (atisSource !== 'IVAO' && atisSource !== 'VATSIM') && (
<div className="w-12/12">
<h1 className="text-white font-medium mb-4 text-2xl">
Only available when 'IVAO' or 'VATSIM' is selected as ATIS/ATC source in the settings page
</h1>
</div>
)}

{ (atisSource === 'IVAO' || atisSource === 'VATSIM') && (
<div className="w-4/12 ml-4">
<h1 className="text-white font-medium mb-4 text-2xl">Active frequency</h1>
<div className="bg-gray-800 rounded-xl p-6 text-white shadow-lg">
<div>
<div className="active-frequency">
<div className="mr-4">
{currentFrequency && currentFrequency.toString()}
</div>
<div>
{currentAtc && currentAtc.callsign}
</div>
</div>
<div className="active-atis">
{ currentAtc?.textAtis && currentAtc.textAtis.map((line) => (
<p>{line}</p>
)) }
</div>
</div>
</div>

</div>
)}

</div>
);
};

export default ATC;
9 changes: 8 additions & 1 deletion src/instruments/src/EFB/Efb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import Performance from './Performance/Performance';
import Navigation from './Navigation/Navigation';
import Settings from './Settings/Settings';
import store from './Store';
import ATC from './ATC/ATC';

type TimeState = {
currentTime: Date,
Expand Down Expand Up @@ -119,7 +120,7 @@ const Efb = () => {
initTime: new Date(),
timeSinceStart: '00:00',
});
const [currentPageIndex, setCurrentPageIndex] = useState<0 | 1 | 2 | 3 | 4 | 5 | 6>(0);
const [currentPageIndex, setCurrentPageIndex] = useState<0 | 1 | 2 | 3 | 4 | 5 | 6 | 7>(0);

useEffect(() => {
switch (currentPageIndex) {
Expand All @@ -136,6 +137,9 @@ const Efb = () => {
history.push('/navigation');
break;
case 5:
history.push('/atc');
break;
case 6:
history.push('/settings');
break;
default:
Expand Down Expand Up @@ -260,6 +264,9 @@ const Efb = () => {
<Route path="/navigation">
<Navigation />
</Route>
<Route path="/atc">
<ATC />
</Route>
<Route path="/settings">
<Settings simbriefUsername={simbriefUsername} setSimbriefUsername={setSimbriefUsername} />
</Route>
Expand Down
2 changes: 1 addition & 1 deletion src/instruments/src/EFB/Settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ const PlaneSettings = () => {

<div className="divide-y divide-gray-700 flex flex-col">
<div className="mb-3.5 flex flex-row justify-between items-center">
<span className="text-lg text-gray-300">ATIS Source</span>
<span className="text-lg text-gray-300">ATIS/ATC Source</span>
<SelectGroup>
{atisSourceButtons.map((button) => (
<SelectItem
Expand Down
10 changes: 8 additions & 2 deletions src/instruments/src/EFB/ToolBar/ToolBar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { IconClipboard, IconMap, IconCalculator, IconSettings, IconTruck } from '@tabler/icons';
import { IconClipboard, IconMap, IconCalculator, IconSettings, IconTruck, IconBuildingLighthouse } from '@tabler/icons';
import logo from '../Assets/fbw-logo.svg';

type ToolbarProps = {
Expand Down Expand Up @@ -58,11 +58,17 @@ class ToolBar extends React.Component<ToolbarProps, ToolbarState> {
<IconMap className="mx-auto" size={45} color="white" stroke={1} strokeLinejoin="miter" />
</a>
</li>
<li className={this.state.activeIndex === 5 ? c.active : c.inactive}>
<a onClick={() => this.handleClick(5)}>
<IconBuildingLighthouse className="mx-auto" size={45} color="white" stroke={1} strokeLinejoin="miter" />
</a>
</li>

</ul>
</div>
<div className="mb-6">
<div className="mx-6 border-t-2 border-gray-700 mt-6" />
<div className={this.state.activeIndex === 5 ? `${c.active} mt-6` : `${c.inactive} mt-6`} onClick={() => this.handleClick(5)}>
<div className={this.state.activeIndex === 6 ? `${c.active} mt-6` : `${c.inactive} mt-6`} onClick={() => this.handleClick(6)}>
<IconSettings className="mx-auto" size={45} color="white" stroke={1} strokeLinejoin="miter" />
</div>
</div>
Expand Down