16 Commits

Author SHA1 Message Date
3c020d25ed feat: handle termination 2019-01-30 09:51:31 -07:00
ed6186f63b fix: make auth an env var
so that it can be passed into docker easily
2019-01-29 17:01:10 -07:00
aefbcabac0 feat: make it fake data 2019-01-28 14:26:21 -07:00
7b5ad0ffc6 2.1.1 2018-11-06 16:11:28 -07:00
c5e8b7f178 fix: saner defaults
3 second fetch timeout and 200km radius
2018-11-06 16:11:12 -07:00
c4870763a9 2.1.0 2018-11-02 16:50:11 -07:00
6591e7eaa8 feat: add raw version of text fields 2018-11-02 16:50:01 -07:00
58d405396e 2.0.1 2018-11-02 16:49:58 -07:00
f7523ae5e2 fix: exit on errors 2018-11-02 16:37:09 -07:00
024a43e20b fix: format undefined fields 2018-11-02 16:37:09 -07:00
d55039f7cb 2.0.0 2018-11-02 15:35:44 -07:00
7eeb251c6b chore: replace node-cron with interval-promise 2018-11-02 15:24:33 -07:00
d290165899 fix: correctly formatted ads-b exchange data 2018-11-02 15:12:11 -07:00
89261d0010 feat: use ads-b exchange data 2018-11-02 14:56:07 -07:00
9f0da54ccf feat: add ads-b exchange source 2018-11-02 14:56:07 -07:00
aca5c03388 chore: change get-data exports
export a function for the specific opensky data, re-org code
2018-11-02 14:56:07 -07:00
10 changed files with 264 additions and 68 deletions

View File

@@ -1,5 +1,20 @@
### Changelog ### Changelog
#### [v2.1.1](https://git.w33ble.com/w33ble/adsb-index/compare/v2.1.0...v2.1.1) (6 November 2018)
- fix: saner defaults [`c5e8b7f`](https://git.w33ble.com/w33ble/adsb-index/commit/c5e8b7f178a8bbc76b72eea08afc4d578baababb)
#### [v2.1.0](https://git.w33ble.com/w33ble/adsb-index/compare/v2.0.1...v2.1.0) (2 November 2018)
- feat: add raw version of text fields [`6591e7e`](https://git.w33ble.com/w33ble/adsb-index/commit/6591e7eaa8c9c317a55632f856310cdd3f783464)
#### [v2.0.1](https://git.w33ble.com/w33ble/adsb-index/compare/v2.0.0...v2.0.1) (2 November 2018)
- fix: format undefined fields [`024a43e`](https://git.w33ble.com/w33ble/adsb-index/commit/024a43e20b7ebcf79ef5625df2021a41fa9b2ce9)
- fix: exit on errors [`f7523ae`](https://git.w33ble.com/w33ble/adsb-index/commit/f7523ae5e20414dfec597050051566adbba9a310)
### [v2.0.0](https://git.w33ble.com/w33ble/adsb-index/compare/v1.0.1...v2.0.0) (2 November 2018)
- feat: add ads-b exchange source [`9f0da54`](https://git.w33ble.com/w33ble/adsb-index/commit/9f0da54ccfc639ec6367ea85ec39bea117fd3108)
- feat: use ads-b exchange data [`89261d0`](https://git.w33ble.com/w33ble/adsb-index/commit/89261d0010315ad248dcfdcf25916d952de648d8)
- fix: correctly formatted ads-b exchange data [`d290165`](https://git.w33ble.com/w33ble/adsb-index/commit/d2901658990a5984ef69fc34f7372e3894a3ac74)
#### [v1.0.1](https://git.w33ble.com/w33ble/adsb-index/compare/v1.0.0...v1.0.1) (2 November 2018) #### [v1.0.1](https://git.w33ble.com/w33ble/adsb-index/compare/v1.0.0...v1.0.1) (2 November 2018)
- fix: format api data correctly [`6def944`](https://git.w33ble.com/w33ble/adsb-index/commit/6def9449be415c50390a2eaa4fd124bd5fa548b6) - fix: format api data correctly [`6def944`](https://git.w33ble.com/w33ble/adsb-index/commit/6def9449be415c50390a2eaa4fd124bd5fa548b6)

View File

@@ -13,4 +13,8 @@ WORKDIR /app
VOLUME /app/data VOLUME /app/data
COPY --from=0 /build . COPY --from=0 /build .
COPY . . COPY . .
ENTRYPOINT ["yarn", "start"]
ENV ELASTICSEARCH_HOST="host.docker.internal"
ENV ELASTICSEARCH_PORT="9200"
ENTRYPOINT ["node", "bin/index", "-t", "5"]

View File

@@ -1,6 +1,6 @@
# adsb-index # fake-adsb-index
ADS-B indexing script. FAKE ADS-B indexing script.
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/w33ble/adsb-index/master/LICENSE) [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/w33ble/adsb-index/master/LICENSE)
[![npm](https://img.shields.io/npm/v/adsb-index.svg)](https://www.npmjs.com/package/adsb-index) [![npm](https://img.shields.io/npm/v/adsb-index.svg)](https://www.npmjs.com/package/adsb-index)

View File

@@ -1,24 +1,30 @@
/* eslint no-global-assign: 0 no-console: 0 */ /* eslint no-global-assign: 0 no-console: 0 */
require = require('esm')(module); require = require('esm')(module);
const getopts = require('getopts'); const getopts = require('getopts');
const cron = require('node-cron'); const runInterval = require('interval-promise');
const mod = require('../src/index.mjs').default; const mod = require('../src/index.mjs').default;
const logger = require('../src/lib/logger.mjs').default; const logger = require('../src/lib/logger.mjs').default;
const { index, interval, ...elasticsearch } = getopts(process.argv.slice(2), { const esHost = process.env.ELASTICSEARCH_HOST || 'localhost';
const esPort = process.env.ELASTICSEARCH_PORT || '9200';
const auth = process.env.ELASTICSEARCH_AUTH || '';
const { index, interval, lat, lon, radius, ...esConfig } = getopts(process.argv.slice(2), {
string: ['host', 'auth', 'log', 'index'], string: ['host', 'auth', 'log', 'index'],
alias: { alias: {
h: 'host', h: 'host',
u: 'auth',
l: 'log', l: 'log',
i: 'index', i: 'index',
t: 'interval', t: 'interval',
}, },
default: { default: {
host: 'localhost:9200', host: `${esHost}:${esPort}`,
log: 'error', log: 'error',
index: 'adsb-data', index: 'adsb-data',
interval: 0, interval: 0,
lat: 33.433638,
lon: -112.008113,
radius: 200,
}, },
}); });
@@ -28,21 +34,26 @@ function handleError(err) {
} }
async function fetchAndIndex() { async function fetchAndIndex() {
return mod(index, { elasticsearch }); logger.debug('Fetching and indexing data...');
return mod(index, { elasticsearch: { ...esConfig, auth }, filter: { lat, lon, radius } });
} }
async function run() { async function run() {
// initial kickoff // initial kickoff
await fetchAndIndex().catch(handleError); await fetchAndIndex().catch(handleError);
if (interval === 0) return; // listen for termination
const terminate = () => {
console.log('Terminating...');
process.exit(0);
};
process.on('SIGINT', terminate);
process.on('SIGTERM', terminate);
// scheduled running // scheduled running
logger.debug(`Starting cron (${interval}s)...`); if (interval === 0) return;
cron.schedule(`${interval} * * * * *`, () => { logger.debug(`Starting interval (${interval}s)...`);
logger.debug('Running cron...'); runInterval(() => fetchAndIndex().catch(handleError), interval * 1000);
fetchAndIndex();
});
} }
run().catch(handleError); run().catch(handleError);

View File

@@ -1,6 +1,6 @@
{ {
"name": "adsb-index", "name": "adsb-index",
"version": "1.0.1", "version": "2.1.1",
"private": true, "private": true,
"description": "ADS-B indexing script", "description": "ADS-B indexing script",
"bin": "bin/index.js", "bin": "bin/index.js",
@@ -53,7 +53,7 @@
"elasticsearch": "^15.2.0", "elasticsearch": "^15.2.0",
"esm": "^3.0.17", "esm": "^3.0.17",
"getopts": "^2.2.2", "getopts": "^2.2.2",
"node-cron": "^2.0.3" "interval-promise": "^1.3.0"
}, },
"devDependencies": { "devDependencies": {
"@w33ble/npm-auto-tools": "*", "@w33ble/npm-auto-tools": "*",

View File

@@ -1,9 +1,7 @@
import elasticsearch from 'elasticsearch'; import elasticsearch from 'elasticsearch';
import logger from './lib/logger.mjs'; import logger from './lib/logger.mjs';
import { createIndex, bulkInsert } from './lib/data-source.mjs'; import { createIndex, bulkInsert } from './lib/data-source.mjs';
import getData from './lib/get-data.mjs'; import { getAdbsExchangeData } from './lib/get-data.mjs';
const positionSourceMap = ['ADS-B', 'ASTERIX', 'MLAT'];
export default async function(indexName, opts = {}) { export default async function(indexName, opts = {}) {
const client = new elasticsearch.Client({ const client = new elasticsearch.Client({
@@ -18,29 +16,9 @@ export default async function(indexName, opts = {}) {
// create the target index // create the target index
const index = await createIndex(client, indexName); const index = await createIndex(client, indexName);
const records = await getData(); const records = await getAdbsExchangeData(opts.filter);
logger.debug(`ADS-B records:, ${records.length}`); logger.debug(`Record count:, ${records.length}`);
// index all the data await bulkInsert(client, index, records);
const documents = records.map(rec => ({
transponder: `${rec[0]}`.toLowerCase(),
callsign: `${rec[1]}`.trim(),
origin_country: rec[2],
time_position: new Date(rec[3] * 1000),
last_contact: new Date(rec[4] * 1000),
location: rec[5] && rec[6] ? `${rec[6]},${rec[5]}` : null,
lat: rec[6],
lon: rec[5],
baro_altitude: rec[7],
geo_altitude: rec[13],
on_ground: rec[8],
velocity: rec[9],
vertical_rate: rec[11],
squawk: rec[14],
spi: rec[15],
position_source: positionSourceMap[rec[16]],
}));
await bulkInsert(client, index, documents);
logger.debug(`Successfully indexed ${records.length} records to ${index}`); logger.debug(`Successfully indexed ${records.length} records to ${index}`);
} }

View File

@@ -26,6 +26,9 @@ export async function createIndex(client, index) {
mappings: { mappings: {
[doctype]: { [doctype]: {
properties: { properties: {
operator: { type: 'text', fields: { raw: { type: 'keyword' } } },
aircraft: { type: 'text', fields: { raw: { type: 'keyword' } } },
aircraft_manufacturer: { type: 'keyword' },
transponder: { type: 'keyword' }, transponder: { type: 'keyword' },
callsign: { type: 'keyword' }, callsign: { type: 'keyword' },
origin_country: { type: 'keyword' }, origin_country: { type: 'keyword' },
@@ -42,6 +45,8 @@ export async function createIndex(client, index) {
squawk: { type: 'keyword' }, squawk: { type: 'keyword' },
spi: { type: 'boolean' }, spi: { type: 'boolean' },
position_source: { type: 'keyword' }, position_source: { type: 'keyword' },
from: { type: 'text', fields: { raw: { type: 'keyword' } } },
to: { type: 'text', fields: { raw: { type: 'keyword' } } },
}, },
}, },
}, },

View File

@@ -1,13 +1,9 @@
import axios from 'axios'; import axios from 'axios';
const api = 'https://opensky-network.org/api';
export default axios.create({ export default axios.create({
baseURL: api,
timeout: 3000, timeout: 3000,
responseType: 'json', responseType: 'json',
headers: { headers: {
'X-Custom-Header': 'foobar',
'Content-Type': 'application/json; charset=utf-8', 'Content-Type': 'application/json; charset=utf-8',
}, },
}); });

View File

@@ -1,6 +1,206 @@
import fetch from './fetch.mjs'; /* eslint import/prefer-default-export: 0 */
export default async function getData() { const aircrafts = [
const res = await fetch.get('/states/all'); {
return res.data.states; transponder: 'abe09a',
callsign: 'SWA146',
origin_country: 'United States',
time_position: '2019-01-28T20:49:35.234Z',
last_contact: '2019-01-28T20:49:35.234Z',
location: '33.440986,-112.079717',
lat: 33.440986,
lon: -112.079717,
baro_altitude: 1950,
geo_altitude: 2000,
on_ground: false,
velocity: 162.1,
vertical_rate: -832,
squawk: '1523',
spi: false,
position_source: 'ADS-B',
operator: 'Southwest Airlines',
aircraft: '2014 BOEING 737-8H4',
aircraft_manufacturer: 'Boeing',
from: 'KHOU William P Hobby, Houston, United States',
to: 'KONT Ontario, United States',
},
{
transponder: 'acc1ee',
callsign: 'AAL2450',
origin_country: 'United States',
time_position: '2019-01-28T20:49:07.341Z',
last_contact: '2019-01-28T20:49:07.341Z',
location: '33.431071,-112.004887',
lat: 33.431071,
lon: -112.004887,
baro_altitude: 1150,
geo_altitude: 1200,
on_ground: false,
velocity: 125,
vertical_rate: 64,
squawk: '',
spi: false,
position_source: 'ADS-B',
operator: 'AMERICAN AIRLINES INC - FORT WORTH, TX',
aircraft: '1999 BOEING 737-823',
aircraft_manufacturer: 'Boeing',
from: 'KLAX Los Angeles, United States',
to: 'KDFW Dallas Fort Worth, Dallas-Fort Worth, United States',
},
{
transponder: 'a742c2',
callsign: 'AAL2197',
origin_country: 'United States',
time_position: '2019-01-28T20:46:30.215Z',
last_contact: '2019-01-28T20:46:30.215Z',
location: '33.431053,-112.020776',
lat: 33.431053,
lon: -112.020776,
baro_altitude: 1475,
geo_altitude: 1525,
on_ground: false,
velocity: 183,
vertical_rate: 3264,
squawk: '2656',
spi: false,
position_source: 'ADS-B',
operator: 'American Airlines',
aircraft: '2013 AIRBUS A321-231',
aircraft_manufacturer: 'Airbus',
from: 'KMCO Orlando, United States',
to: 'KDFW Dallas Fort Worth, Dallas-Fort Worth, United States',
},
{
transponder: 'a23c2e',
callsign: 'ASH5742',
origin_country: 'United States',
time_position: '2019-01-28T20:40:09.162Z',
last_contact: '2019-01-28T20:40:09.162Z',
location: '33.440826,-112.020557',
lat: 33.440826,
lon: -112.020557,
baro_altitude: 1100,
geo_altitude: 1088,
on_ground: false,
velocity: 138,
vertical_rate: -320,
squawk: '2444',
spi: false,
position_source: 'ADS-B',
operator: 'BANK OF UTAH TRUSTEE - SALT LAKE CITY, UT',
aircraft: '2006 BOMBARDIER INC CL-600-2D24',
aircraft_manufacturer: 'Bombardier',
from: 'N/A',
to: 'N/A',
},
{
transponder: 'a91e6e',
callsign: 'N/A',
origin_country: 'United States',
time_position: '2019-01-28T19:02:32.530Z',
last_contact: '2019-01-28T19:02:32.530Z',
location: '33.435703,-112.003822',
lat: 33.435703,
lon: -112.003822,
baro_altitude: 1350,
geo_altitude: 1530,
on_ground: false,
velocity: 130,
vertical_rate: -384,
squawk: '1363',
spi: false,
position_source: 'ADS-B',
operator: 'Spirit Airlines',
aircraft: 'Airbus A321 231SL',
aircraft_manufacturer: 'Airbus',
from: 'N/A',
to: 'N/A',
},
{
transponder: 'a8a7f1',
callsign: 'NKS1167',
origin_country: 'United States',
time_position: '2019-01-28T00:20:20.803Z',
last_contact: '2019-01-28T00:20:20.803Z',
location: '33.440826,-111.981006',
lat: 33.440826,
lon: -111.981006,
baro_altitude: 1200,
geo_altitude: 1259,
on_ground: false,
velocity: 143,
vertical_rate: -768,
squawk: '6513',
spi: false,
position_source: 'ADS-B',
operator: 'Spirit Airlines',
aircraft: '2015 AIRBUS A321-231',
aircraft_manufacturer: 'Airbus',
from: 'N/A',
to: 'N/A',
},
{
transponder: 'aa56db',
callsign: 'UAL1139',
origin_country: 'United States',
time_position: '2019-01-28T21:04:05.916Z',
last_contact: '2019-01-28T21:04:05.916Z',
location: '33.429953,-112.004802',
lat: 33.429953,
lon: -112.004802,
baro_altitude: 1100,
geo_altitude: 1251,
on_ground: false,
velocity: 156,
vertical_rate: -960,
squawk: '3352',
spi: false,
position_source: 'ADS-B',
operator: 'United Airlines',
aircraft: '2010 BOEING 737-824',
aircraft_manufacturer: 'Boeing',
from: 'KIAD Washington Dulles, United States',
to: 'MWCR Owen Roberts, Georgetown, Cayman Islands',
},
{
transponder: 'abb601',
callsign: 'SWA1386',
origin_country: 'United States',
time_position: '2019-01-28T21:02:07.189Z',
last_contact: '2019-01-28T21:02:07.189Z',
location: '33.432129,-111.9989',
lat: 33.432129,
lon: -111.9989,
baro_altitude: 1875,
geo_altitude: 1925,
on_ground: false,
velocity: 23,
vertical_rate: -832,
squawk: '7427',
spi: false,
position_source: 'ADS-B',
operator: 'Southwest Airlines',
aircraft: 'Boeing 737NG 800/W',
aircraft_manufacturer: 'Boeing',
from: 'KFLL Fort Lauderdale Hollywood, United States',
to: 'KPIT Pittsburgh, United States',
},
];
export async function getAdbsExchangeData() {
const count = Math.ceil(Math.random() * 3);
const now = new Date();
const records = [];
for (let i = 0; i < count; i += 1) {
const idx = Math.floor(Math.random() * (aircrafts.length - 1));
records.push({
...aircrafts[idx],
time_position: now.toISOString(),
last_contact: now.toISOString(),
});
}
return records;
} }

View File

@@ -1245,6 +1245,11 @@ inquirer@^3.0.6:
strip-ansi "^4.0.0" strip-ansi "^4.0.0"
through "^2.3.6" through "^2.3.6"
interval-promise@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/interval-promise/-/interval-promise-1.3.0.tgz#26fc4fbcd18605162d0dd012c2cc5657c4f8bc22"
integrity sha512-AebPZJ0o6D1jWg487njjrhfzBp6/hfmtWCMQhXr0SXD7Zg5RexQe4Y6joYiGieJziP7W7WEMQWxFKSbywXmhbw==
is-accessor-descriptor@^0.1.6: is-accessor-descriptor@^0.1.6:
version "0.1.6" version "0.1.6"
resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
@@ -1826,14 +1831,6 @@ nice-try@^1.0.4:
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
node-cron@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/node-cron/-/node-cron-2.0.3.tgz#b9649784d0d6c00758410eef22fa54a10e3f602d"
integrity sha512-eJI+QitXlwcgiZwNNSRbqsjeZMp5shyajMR81RZCqeW0ZDEj4zU9tpd4nTh/1JsBiKbF8d08FCewiipDmVIYjg==
dependencies:
opencollective-postinstall "^2.0.0"
tz-offset "0.0.1"
node-fetch@^2.1.2, node-fetch@^2.2.0: node-fetch@^2.1.2, node-fetch@^2.2.0:
version "2.2.0" version "2.2.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.2.0.tgz#4ee79bde909262f9775f731e3656d0db55ced5b5" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.2.0.tgz#4ee79bde909262f9775f731e3656d0db55ced5b5"
@@ -1934,11 +1931,6 @@ onetime@^2.0.0:
dependencies: dependencies:
mimic-fn "^1.0.0" mimic-fn "^1.0.0"
opencollective-postinstall@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.1.tgz#798e83e168f7b91949061c2683f762af747f17cc"
integrity sha512-saQQ9hjLwu/oS0492eyYotoh+bra1819cfAT5rjY/e4REWwuc8IgZ844Oo44SiftWcJuBiqp0SA0BFVbmLX0IQ==
optimist@^0.6.1: optimist@^0.6.1:
version "0.6.1" version "0.6.1"
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
@@ -2629,11 +2621,6 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
tz-offset@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/tz-offset/-/tz-offset-0.0.1.tgz#fef920257024d3583ed9072a767721a18bdb8a76"
integrity sha512-kMBmblijHJXyOpKzgDhKx9INYU4u4E1RPMB0HqmKSgWG8vEcf3exEfLh4FFfzd3xdQOw9EuIy/cP0akY6rHopQ==
uglify-js@^3.1.4: uglify-js@^3.1.4:
version "3.4.9" version "3.4.9"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3"