diff --git a/client.js b/client.js index 243abd7..8f116da 100644 --- a/client.js +++ b/client.js @@ -8,6 +8,7 @@ import query_overpass from 'query-overpass'; import config from 'config'; import { iso2dec } from './iso2dec.js'; import {Mutex, Semaphore, withTimeout} from 'async-mutex'; +import uniqueRandomArray from 'unique-random-array'; var log = bunyan.createLogger({name: config.get('app.name'), level: config.get('app.log_level')}); @@ -35,6 +36,76 @@ export function cacheStats(){ return stats; } +async function getVatsimServers(){ + const url = config.get('data.vatsim.statusUrl'); + var ttlMs = cache.getTtl(url); + let data; + // VATSIM data is refreshed every 15s. Check 10s out from expiry. + if (ttlMs == undefined || ttlMs - Date.now() <= 10000) { + try{ + // Download fresh VATSIM data + if(ttlMs == undefined){ + // If there is nothing cached - retry forever. + const res = await fetch(url, { + retryOptions: { + retryMaxDuration: 30000, // Max 30s retrying + retryInitialDelay: 1000, // 1s initial wait + retryBackoff: 500 // 0.5s backoff + }, + headers: { + 'User-Agent': userAgent + } + }) + .then(res => res.json()) + .then( data => { + return data; + }) + log.trace({res: res}); + data = res; + }else{ + // If there is an old cache, timeout quickly. + const res = await fetch(url, { + retryOptions: { + retryMaxDuration: 2000, + retryInitialDelay: 500, + retryBackoff: 1.0 // no backoff + }, + headers: { + 'User-Agent': userAgent + } + }) + .then(res => res.json()) + .then( data => { + return data; + }) + log.trace({res: res}); + data = res; + } + log.info({ + cache: 'set', + url: url, + keys: Object.keys(data).length + }) + cache.set(url, data, 30); + }catch(err){ + if ( err instanceof FetchError) { + // Failed to download - load from cache + data = cache.get(url); + } else { + log.error(err); + } + }; + }else{ + data = cache.get(url); + log.debug({ + cache: 'get', + url: url, + keys: Object.keys(data).length + }) + } + return data; +} + export async function getOSMAerodromeData (areaName) { log.info(`getOSMAerodromeData`); var data = await mutex.runExclusive(async () => { @@ -85,8 +156,12 @@ export async function getOSMAerodromeData (areaName) { return data; }; -export async function getVatsimData (url) { - var ttlMs = cache.getTtl(url); +export async function getVatsimData () { + const vatsimServers = await getVatsimServers(); + var getUrl = uniqueRandomArray(vatsimServers.data.v3); + var url = getUrl(); + log.debug(`VATSIM data URL: ${url}`); + var ttlMs = cache.getTtl('getVatsimData'); let data; // VATSIM data is refreshed every 15s. Check 10s out from expiry. if (ttlMs == undefined || ttlMs - Date.now() <= 10000) { @@ -134,7 +209,7 @@ export async function getVatsimData (url) { url: url, keys: Object.keys(data).length }) - cache.set(url, data, 30); + cache.set('getVatsimData', data, 30); }catch(err){ if ( err instanceof FetchError) { // Failed to download - load from cache @@ -144,7 +219,7 @@ export async function getVatsimData (url) { } }; }else{ - data = cache.get(url); + data = cache.get('getVatsimData'); log.debug({ cache: 'get', url: url, diff --git a/config/default.json b/config/default.json index e447e89..50290b9 100644 --- a/config/default.json +++ b/config/default.json @@ -21,37 +21,52 @@ ], "sectors": { "standard": [ + "BN-TRT_CTR", "BN-ARA_CTR", - "BN-ISA_CTR", "BN-KEN_CTR", + "BN-ISA_CTR", "BN-INL_CTR", "BN-ARM_CTR", - "BN-TRT_CTR", + "ML-OLW_CTR", "ML-ASP_CTR", "ML-ARM_CTR", - "ML-OLW_CTR", - "ML-PIY_CTR", "ML-TBD_CTR", - "ML-TAS_CTR", + "ML-PIY_CTR", + "ML-BIK_CTR", "ML-ELW_CTR", - "ML-BIK_CTR" + "ML-TAS_CTR", + "BN-TSN_FSS", + "ML-IND_FSS" ] - } + }, + "majorAerodromes": [ + "YSSY", + "YMML", + "YBBN", + "YPPH", + "YPAD", + "YBCG", + "YBCS", + "YSCB", + "YMHB", + "YPDN" + ] }, "data": { "vatsim": { - "dataUrl": "https://data.vatsim.net/v3/vatsim-data.json" + "statusUrl": "https://status.vatsim.net/status.json" }, "vatsys": { "fir_boundariesUrl": "https://raw.githubusercontent.com/vatSys/australia-dataset/master/Maps/FIR_BOUNDARIES.xml", "volumesUrl": "https://raw.githubusercontent.com/vatSys/australia-dataset/master/Volumes.xml", "sectorsUrl": "https://raw.githubusercontent.com/vatSys/australia-dataset/master/Sectors.xml", "coastlineUrl": "https://raw.githubusercontent.com/vatSys/australia-dataset/master/Maps/COAST_ALL.xml", - "coloursUrl": "https://raw.githubusercontent.com/vatSys/australia-dataset/master/Colours.xml" + "coloursUrl": "https://raw.githubusercontent.com/vatSys/australia-dataset/master/Colours.xml", + "profileUrl": "https://raw.githubusercontent.com/vatSys/australia-dataset/master/Profile.xml" }, "osm": { "overpassUrl": "https://lz4.overpass-api.de/api/interpreter", - "aerodromesArea": "New South Wales" + "aerodromesArea": "Australia" } } } \ No newline at end of file diff --git a/config/production.json b/config/production.json index 0112017..df5ee17 100644 --- a/config/production.json +++ b/config/production.json @@ -54,7 +54,7 @@ }, "data": { "vatsim": { - "dataUrl": "https://data.vatsim.net/v3/vatsim-data.json" + "statusUrl": "https://status.vatsim.net/status.json" }, "vatsys": { "fir_boundariesUrl": "https://raw.githubusercontent.com/vatSys/australia-dataset/master/Maps/FIR_BOUNDARIES.xml", diff --git a/package.json b/package.json index ba9101f..80e7785 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "node-fetch": "^2.6.1", "query-overpass": "https://github.com/Kahn/query-overpass.git", "rgb2hex": "^0.2.5", + "unique-random-array": "^3.0.0", "xml-js": "^1.6.11" }, "devDependencies": { diff --git a/pilots.js b/pilots.js index 8cd5202..149bb79 100644 --- a/pilots.js +++ b/pilots.js @@ -9,7 +9,7 @@ var log = bunyan.createLogger({name: config.get('app.name'), level: config.get(' export async function getPilots(){ try{ var firs = await getLineFeatures(config.get('data.vatsys.fir_boundariesUrl')); - var vatsimData = await getVatsimData(config.get('data.vatsim.dataUrl')); + var vatsimData = await getVatsimData(); var aerodromes = await getOSMAerodromeData(config.get('data.osm.aerodromesArea')); }catch(err){ log.error(err) diff --git a/public/map.js b/public/map.js index b796991..545880b 100644 --- a/public/map.js +++ b/public/map.js @@ -155,16 +155,19 @@ var map = new mapboxgl.Map({ map.dragRotate.disable(); map.touchZoomRotate.disableRotation(); -map.addControl(new mapboxgl.AttributionControl({ - customAttribution: 'vatsim-map' -})) - // Light / Dark switch var theme = findGetParameter('theme') || 'light'; if(theme == 'dark'){ map.setStyle(styleDark); } +async function getDataset() { + var response = await fetch(`${window.location.protocol}//${window.location.hostname}:${window.location.port}/v1/dataset`); + var json = await response.json(); + dataset = json; + return json; +}; + async function getPilots() { var dataApi = findGetParameter('dataApi'); if(dataApi != false){ @@ -490,8 +493,15 @@ async function setPilotMarkers () { getPilots(); -map.on('load', function () { +(async () => { +var dataset = await getDataset(); +console.log(dataset); +map.addControl(new mapboxgl.AttributionControl({ + customAttribution: `vatSys ${dataset.Profile._attributes.Name} dataset AIRAC ${dataset.Profile.Version._attributes.AIRAC}${dataset.Profile.Version._attributes.Revision} | vatsim-map` +})) +})(); +map.on('load', function () { map.addSource('aircraftMarkersSource', { 'type': 'geojson', 'data': null diff --git a/public/sectormap.html b/public/sectormap.html index b373c10..aea38ec 100644 --- a/public/sectormap.html +++ b/public/sectormap.html @@ -14,6 +14,7 @@ top: 0; bottom: 0; width: 100%; + z-index: 0; } .mapboxgl-popup-content { @@ -25,6 +26,13 @@ /* line-height: 1.4; */ white-space: pre-line; } + #mgl-map-overlay { + position: absolute; + top: 10px; + left: 10px; + z-index: 1; + background-color: #fff; + }
@@ -43,6 +51,15 @@ +