From 993e4efa8ed812d49197929f940d9be482219c70 Mon Sep 17 00:00:00 2001 From: Mark Bumiller Date: Thu, 17 Oct 2024 17:57:20 -0400 Subject: [PATCH 1/4] Adding label 24 / parsing --- lib/MessageDecoder.ts | 1 + lib/plugins/Label_24_Slash.test.ts | 66 ++++++++++++++++++++++++++++++ lib/plugins/Label_24_Slash.ts | 56 +++++++++++++++++++++++++ lib/plugins/official.ts | 1 + 4 files changed, 124 insertions(+) create mode 100644 lib/plugins/Label_24_Slash.test.ts create mode 100644 lib/plugins/Label_24_Slash.ts diff --git a/lib/MessageDecoder.ts b/lib/MessageDecoder.ts index 03af1b9..81f0b20 100644 --- a/lib/MessageDecoder.ts +++ b/lib/MessageDecoder.ts @@ -25,6 +25,7 @@ export class MessageDecoder { this.registerPlugin(new Plugins.Label_16_N_Space(this)); this.registerPlugin(new Plugins.Label_20_POS(this)); this.registerPlugin(new Plugins.Label_21_POS(this)); + this.registerPlugin(new Plugins.Label_24_Slash(this)); this.registerPlugin(new Plugins.Label_30_Slash_EA(this)); this.registerPlugin(new Plugins.Label_44_ETA(this)); this.registerPlugin(new Plugins.Label_44_IN(this)); diff --git a/lib/plugins/Label_24_Slash.test.ts b/lib/plugins/Label_24_Slash.test.ts new file mode 100644 index 0000000..630247e --- /dev/null +++ b/lib/plugins/Label_24_Slash.test.ts @@ -0,0 +1,66 @@ +import { MessageDecoder } from '../MessageDecoder'; +import { Label_24_Slash } from './Label_24_Slash'; + +describe('Label_24_Slash', () => { + let plugin: Label_24_Slash; + + beforeEach(() => { + const decoder = new MessageDecoder(); + plugin = new Label_24_Slash(decoder); + }); + + test('matches qualifiers', () => { + expect(plugin.decode).toBeDefined(); + expect(plugin.name).toBe('label-24-slash'); + expect(plugin.qualifiers).toBeDefined(); + expect(plugin.qualifiers()).toEqual({ + labels: ['24'], + preambles: ['/'], + }); + }); + + + test('valid', () => { + // https://app.airframes.io/messages/3439806391 + const text = '/241710/1021/04WM/34962/N53.13/E001.33/3374/1056/'; + const decodeResult = plugin.decode({ text: text }); + expect(decodeResult.decoded).toBe(true); + expect(decodeResult.decoder.decodeLevel).toBe('partial'); + expect(decodeResult.raw.message_timestamp).toBe(1729160460); + expect(decodeResult.raw.flight_number).toBe('04WM'); + expect(decodeResult.raw.altitude).toBe(34962); + expect(decodeResult.raw.position.latitude).toBe(53.13); + expect(decodeResult.raw.position.longitude).toBe(1.33); + expect(decodeResult.raw.eta_time).toBe(39360); + expect(decodeResult.formatted.items.length).toBe(3); + expect(decodeResult.remaining.text).toBe('3374'); + }); + + + test('2valid', () => { + // https://app.airframes.io/messages/3439806391 + const text = '/241710/1021/04WM/34962/N53.13/E001.33/3374/1056/'; + const decodeResult = plugin.decode({ text: text }); + console.log(JSON.stringify(decodeResult, null, 2)); + expect(decodeResult.decoded).toBe(true); + expect(decodeResult.decoder.decodeLevel).toBe('partial'); + expect(decodeResult.raw.message_timestamp).toBe(1729160460); + expect(decodeResult.raw.flight_number).toBe('04WM'); + expect(decodeResult.raw.altitude).toBe(34962); + expect(decodeResult.raw.position.latitude).toBe(53.13); + expect(decodeResult.raw.position.longitude).toBe(1.33); + expect(decodeResult.raw.eta_time).toBe(39360); + expect(decodeResult.formatted.items.length).toBe(3); + expect(decodeResult.remaining.text).toBe('3374'); + }); + + test('does not decode invalid', () => { + + const text = '/ Bogus message'; + const decodeResult = plugin.decode({ text: text }); + + expect(decodeResult.decoded).toBe(false); + expect(decodeResult.decoder.decodeLevel).toBe('none'); + expect(decodeResult.message.text).toBe(text); + }); +}); \ No newline at end of file diff --git a/lib/plugins/Label_24_Slash.ts b/lib/plugins/Label_24_Slash.ts new file mode 100644 index 0000000..f763892 --- /dev/null +++ b/lib/plugins/Label_24_Slash.ts @@ -0,0 +1,56 @@ +import { DateTimeUtils } from '../DateTimeUtils'; +import { DecoderPlugin } from '../DecoderPlugin'; +import { DecodeResult, Message, Options } from '../DecoderPluginInterface'; +import { ResultFormatter } from '../utils/result_formatter'; + +// Position Report +export class Label_24_Slash extends DecoderPlugin { + name = 'label-24-slash'; + + qualifiers() { // eslint-disable-line class-methods-use-this + return { + labels: ['24'], + preambles: ['/'], + }; + } + + decode(message: Message, options: Options = {}) : DecodeResult { + const decodeResult = this.defaultResult(); + decodeResult.decoder.name = this.name; + decodeResult.formatted.description = 'Position Report'; + decodeResult.message = message; + + const fields = message.text.split('/'); + + if (fields.length == 10 && fields[0] == '' && fields[9] == '') { // begin and ends with `/` + const mmddyy = fields[1].substring(4,6) + fields[1].substring(2,4) + fields[1].substring(0,2); // YYDDMM + const hhmmss = fields[2] + '00'; + decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(hhmmss,mmddyy); + ResultFormatter.flightNumber(decodeResult, fields[3]); + ResultFormatter.altitude(decodeResult, Number(fields[4])); + const lat = fields[5]; + const lon = fields[6]; + const position = { + latitude: (lat[0] === 'N' ? 1 : -1) * Number(lat.substring(1)), + longitude: (lon[0] === 'E' ? 1 : -1) * Number(lon.substring(1)), + }; + ResultFormatter.position(decodeResult, position); + ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[8]+'00')); + decodeResult.remaining.text = fields[7]; + + decodeResult.decoded = true; + decodeResult.decoder.decodeLevel = 'partial'; + } else { + // Unknown! + if(options.debug) { + console.log(`DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}`); + } + decodeResult.decoded = false; + decodeResult.decoder.decodeLevel = 'none'; + } + return decodeResult; + } +} + +export default {}; + diff --git a/lib/plugins/official.ts b/lib/plugins/official.ts index c3d777a..eaed8f9 100644 --- a/lib/plugins/official.ts +++ b/lib/plugins/official.ts @@ -10,6 +10,7 @@ export * from './Label_16_N_Space'; export * from './Label_1M_Slash'; export * from './Label_20_POS'; export * from './Label_21_POS'; +export * from './Label_24_Slash'; export * from './Label_30_Slash_EA'; export * from './Label_44_ETA'; export * from './Label_44_IN'; From 517ef59f90c06807a12bb92ac1bac4fa45cece3f Mon Sep 17 00:00:00 2001 From: Mark Bumiller Date: Thu, 17 Oct 2024 17:58:51 -0400 Subject: [PATCH 2/4] remove copied test --- lib/plugins/Label_24_Slash.test.ts | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/lib/plugins/Label_24_Slash.test.ts b/lib/plugins/Label_24_Slash.test.ts index 630247e..f7793cf 100644 --- a/lib/plugins/Label_24_Slash.test.ts +++ b/lib/plugins/Label_24_Slash.test.ts @@ -36,24 +36,6 @@ describe('Label_24_Slash', () => { expect(decodeResult.remaining.text).toBe('3374'); }); - - test('2valid', () => { - // https://app.airframes.io/messages/3439806391 - const text = '/241710/1021/04WM/34962/N53.13/E001.33/3374/1056/'; - const decodeResult = plugin.decode({ text: text }); - console.log(JSON.stringify(decodeResult, null, 2)); - expect(decodeResult.decoded).toBe(true); - expect(decodeResult.decoder.decodeLevel).toBe('partial'); - expect(decodeResult.raw.message_timestamp).toBe(1729160460); - expect(decodeResult.raw.flight_number).toBe('04WM'); - expect(decodeResult.raw.altitude).toBe(34962); - expect(decodeResult.raw.position.latitude).toBe(53.13); - expect(decodeResult.raw.position.longitude).toBe(1.33); - expect(decodeResult.raw.eta_time).toBe(39360); - expect(decodeResult.formatted.items.length).toBe(3); - expect(decodeResult.remaining.text).toBe('3374'); - }); - test('does not decode invalid', () => { const text = '/ Bogus message'; From 7abf5fd4797431f8bcfb143956c43c799a3f0fe4 Mon Sep 17 00:00:00 2001 From: Mark Bumiller Date: Thu, 17 Oct 2024 20:44:09 -0400 Subject: [PATCH 3/4] PR Feedback --- lib/plugins/Label_24_Slash.test.ts | 7 +++++++ lib/plugins/Label_24_Slash.ts | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/plugins/Label_24_Slash.test.ts b/lib/plugins/Label_24_Slash.test.ts index f7793cf..4b852b1 100644 --- a/lib/plugins/Label_24_Slash.test.ts +++ b/lib/plugins/Label_24_Slash.test.ts @@ -33,6 +33,13 @@ describe('Label_24_Slash', () => { expect(decodeResult.raw.position.longitude).toBe(1.33); expect(decodeResult.raw.eta_time).toBe(39360); expect(decodeResult.formatted.items.length).toBe(3); + expect(decodeResult.formatted.items[0].label).toBe('Altitude'); + expect(decodeResult.formatted.items[0].value).toBe('34962 feet'); + expect(decodeResult.formatted.items[1].label).toBe('Aircraft Position'); + expect(decodeResult.formatted.items[1].value).toBe('53.130 N, 1.330 E'); + expect(decodeResult.formatted.items[2].label).toBe('Estimated Time of Arrival'); + expect(decodeResult.formatted.items[2].value).toBe('10:56:00'); + expect(decodeResult.remaining.text).toBe('3374'); }); diff --git a/lib/plugins/Label_24_Slash.ts b/lib/plugins/Label_24_Slash.ts index f763892..9cb26af 100644 --- a/lib/plugins/Label_24_Slash.ts +++ b/lib/plugins/Label_24_Slash.ts @@ -43,7 +43,7 @@ export class Label_24_Slash extends DecoderPlugin { } else { // Unknown! if(options.debug) { - console.log(`DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}`); + console.log(`DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}. Message: ${message.text}`); } decodeResult.decoded = false; decodeResult.decoder.decodeLevel = 'none'; From 7da831ffd721284b3ff9646b3d05f09600e42ddc Mon Sep 17 00:00:00 2001 From: Mark Bumiller Date: Sun, 20 Oct 2024 20:01:03 -0400 Subject: [PATCH 4/4] normalizing results - eta can be seconds in day (tod) or seconds since epoch - airports can be icao or iata --- lib/plugins/Label_1M_Slash.test.ts | 32 ++++++---- lib/plugins/Label_1M_Slash.ts | 32 +++------- lib/plugins/Label_21_POS.test.ts | 2 +- lib/plugins/Label_30_Slash_EA.test.ts | 8 +-- lib/plugins/Label_30_Slash_EA.ts | 23 ++----- lib/plugins/Label_44_POS.test.ts | 4 +- lib/plugins/Label_80.test.ts | 8 +-- lib/plugins/Label_83.test.ts | 8 +-- lib/plugins/Label_8E.test.ts | 8 +-- lib/plugins/Label_8E.ts | 19 +----- lib/plugins/Label_HX.test.ts | 2 +- lib/plugins/Label_QQ.test.ts | 12 ++-- lib/utils/result_formatter.ts | 90 +++++++++++++++++++-------- 13 files changed, 124 insertions(+), 124 deletions(-) diff --git a/lib/plugins/Label_1M_Slash.test.ts b/lib/plugins/Label_1M_Slash.test.ts index 3483ef3..67b830d 100644 --- a/lib/plugins/Label_1M_Slash.test.ts +++ b/lib/plugins/Label_1M_Slash.test.ts @@ -15,7 +15,7 @@ test('decodes Label 8E sample 1', () => { const text = '/BA0843/ETA01/230822/LDSP/EGLL/EGSS/2JK0\n1940/EGLL27L/10'; const decodeResult = decoderPlugin.decode({ text: text }); - + expect(decodeResult.decoded).toBe(true); expect(decodeResult.decoder.decodeLevel).toBe('partial'); expect(decodeResult.decoder.name).toBe('label-1m-slash'); @@ -26,19 +26,25 @@ test('decodes Label 8E sample 1', () => { expect(decodeResult.raw.arrival_runway).toBe('27L'); expect(decodeResult.raw.departure_icao).toBe('LDSP'); expect(decodeResult.raw.flight_number).toBe('BA0843'); - expect(decodeResult.formatted.items.length).toBe(3); - expect(decodeResult.formatted.items[0].type).toBe('eta'); - expect(decodeResult.formatted.items[0].code).toBe('ETA'); - expect(decodeResult.formatted.items[0].label).toBe('Estimated Time of Arrival'); - // Check for the minutes as typescript doesn't have a UTC time string method - // so the hour will depend on the test host timezone. - expect((decodeResult.formatted.items[0].value as string).includes('40')).toBe(true); - expect(decodeResult.formatted.items[1].type).toBe('destination'); + expect(decodeResult.formatted.items.length).toBe(5); + expect(decodeResult.formatted.items[0].type).toBe('icao'); + expect(decodeResult.formatted.items[0].code).toBe('ORG'); + expect(decodeResult.formatted.items[0].label).toBe('Origin'); + expect(decodeResult.formatted.items[0].value).toBe('LDSP'); + expect(decodeResult.formatted.items[1].type).toBe('icao'); expect(decodeResult.formatted.items[1].code).toBe('DST'); expect(decodeResult.formatted.items[1].label).toBe('Destination'); expect(decodeResult.formatted.items[1].value).toBe('EGLL'); - expect(decodeResult.formatted.items[2].type).toBe('origin'); - expect(decodeResult.formatted.items[2].code).toBe('ORG'); - expect(decodeResult.formatted.items[2].label).toBe('Origin'); - expect(decodeResult.formatted.items[2].value).toBe('LDSP'); + expect(decodeResult.formatted.items[2].type).toBe('icao'); + expect(decodeResult.formatted.items[2].code).toBe('ALT_DST'); + expect(decodeResult.formatted.items[2].label).toBe('Alternate Destination'); + expect(decodeResult.formatted.items[2].value).toBe('EGSS'); + expect(decodeResult.formatted.items[3].type).toBe('runway'); + expect(decodeResult.formatted.items[3].code).toBe('ARWY'); + expect(decodeResult.formatted.items[3].label).toBe('Arrival Runway'); + expect(decodeResult.formatted.items[3].value).toBe('27L'); + expect(decodeResult.formatted.items[4].type).toBe('epoch'); + expect(decodeResult.formatted.items[4].code).toBe('ETA'); + expect(decodeResult.formatted.items[4].label).toBe('Estimated Time of Arrival'); + expect(decodeResult.formatted.items[4].value).toBe('2023-08-22T19:40:00Z'); }); diff --git a/lib/plugins/Label_1M_Slash.ts b/lib/plugins/Label_1M_Slash.ts index 425a0a6..612f1ca 100644 --- a/lib/plugins/Label_1M_Slash.ts +++ b/lib/plugins/Label_1M_Slash.ts @@ -1,6 +1,7 @@ import { DateTimeUtils } from '../DateTimeUtils'; import { DecoderPlugin } from '../DecoderPlugin'; import { DecodeResult, Message, Options } from '../DecoderPluginInterface'; +import { ResultFormatter } from '../utils/result_formatter'; export class Label_1M_Slash extends DecoderPlugin { name = 'label-1m-slash'; @@ -30,34 +31,17 @@ export class Label_1M_Slash extends DecoderPlugin { decodeResult.raw.flight_number = results[0]; // results[1]: ETA01 (???) // results[2]: 230822 - UTC date of eta - decodeResult.raw.departure_icao = results[3]; - decodeResult.raw.arrival_icao = results[4]; - decodeResult.raw.alternate_icao = results[5]; + ResultFormatter.departureAirport(decodeResult, results[3]); + ResultFormatter.arrivalAirport(decodeResult, results[4]); + ResultFormatter.alternateAirport(decodeResult, results[5]); // results[6]: 2JK0 (???) // results[7] 1940 - UTC eta - decodeResult.raw.arrival_runway = results[8].replace(decodeResult.raw.arrival_icao, ""); // results[8] EGLL27L + ResultFormatter.arrivalRunway(decodeResult, results[8].replace(results[4], "")); // results[8] EGLL27L // results[9]: 10(space) (???) - decodeResult.formatted.items.push({ - type: 'eta', - code: 'ETA', - label: 'Estimated Time of Arrival', - value: DateTimeUtils.UTCDateTimeToString(results[2], results[7]), - }); - - decodeResult.formatted.items.push({ - type: 'destination', - code: 'DST', - label: 'Destination', - value: decodeResult.raw.arrival_icao, - }); - - decodeResult.formatted.items.push({ - type: 'origin', - code: 'ORG', - label: 'Origin', - value: decodeResult.raw.departure_icao, - }); + const yymmdd = results[2]; + ResultFormatter.eta(decodeResult, DateTimeUtils.convertDateTimeToEpoch(results[7]+'00', yymmdd.substring(2,4)+yymmdd.substring(4,6)+yymmdd.substring(0,2)), 'epoch') + } decodeResult.decoded = true; diff --git a/lib/plugins/Label_21_POS.test.ts b/lib/plugins/Label_21_POS.test.ts index fca2bc0..e7ef7ac 100644 --- a/lib/plugins/Label_21_POS.test.ts +++ b/lib/plugins/Label_21_POS.test.ts @@ -46,7 +46,7 @@ describe('Label_21_POS', () => { expect(decodeResult.formatted.items[4].code).toBe('ETA'); expect(decodeResult.formatted.items[4].label).toBe('Estimated Time of Arrival'); expect(decodeResult.formatted.items[4].value).toBe('20:47:48'); - expect(decodeResult.formatted.items[5].type).toBe('destination'); + expect(decodeResult.formatted.items[5].type).toBe('icao'); expect(decodeResult.formatted.items[5].code).toBe('DST'); expect(decodeResult.formatted.items[5].label).toBe('Destination'); expect(decodeResult.formatted.items[5].value).toBe('KTPA'); diff --git a/lib/plugins/Label_30_Slash_EA.test.ts b/lib/plugins/Label_30_Slash_EA.test.ts index 028161a..bd04040 100644 --- a/lib/plugins/Label_30_Slash_EA.test.ts +++ b/lib/plugins/Label_30_Slash_EA.test.ts @@ -23,13 +23,11 @@ test('decodes Label 30 sample 1', () => { expect(decodeResult.message.text).toBe(text); expect(decodeResult.raw.arrival_icao).toBe('KSFO'); expect(decodeResult.formatted.items.length).toBe(2); - expect(decodeResult.formatted.items[0].type).toBe('eta'); + expect(decodeResult.formatted.items[0].type).toBe('time_of_day'); expect(decodeResult.formatted.items[0].code).toBe('ETA'); expect(decodeResult.formatted.items[0].label).toBe('Estimated Time of Arrival'); - // This test is a bit rough as typescript doesn't have a UTC time string - // method so the hour will be depend on the test host timezone. - expect((decodeResult.formatted.items[0].value as string).includes('19')).toBe(true); - expect(decodeResult.formatted.items[1].type).toBe('destination'); + expect(decodeResult.formatted.items[0].value).toBe('17:19:00'); + expect(decodeResult.formatted.items[1].type).toBe('icao'); expect(decodeResult.formatted.items[1].code).toBe('DST'); expect(decodeResult.formatted.items[1].label).toBe('Destination'); expect(decodeResult.formatted.items[1].value).toBe('KSFO'); diff --git a/lib/plugins/Label_30_Slash_EA.ts b/lib/plugins/Label_30_Slash_EA.ts index 9677d64..ead3afe 100644 --- a/lib/plugins/Label_30_Slash_EA.ts +++ b/lib/plugins/Label_30_Slash_EA.ts @@ -1,6 +1,7 @@ import { DateTimeUtils } from '../DateTimeUtils'; import { DecoderPlugin } from '../DecoderPlugin'; import { DecodeResult, Message, Options } from '../DecoderPluginInterface'; +import { ResultFormatter } from '../utils/result_formatter'; export class Label_30_Slash_EA extends DecoderPlugin { name = 'label-30-slash-ea'; @@ -28,24 +29,10 @@ export class Label_30_Slash_EA extends DecoderPlugin { } } - decodeResult.formatted.items.push({ - type: 'eta', - code: 'ETA', - label: 'Estimated Time of Arrival', - value: DateTimeUtils.UTCToString(results[0].substr(2, 4)), - }); - - if (results[1].substr(0, 2) === "DS") { - decodeResult.raw.arrival_icao = results[1].substr(2, 4); - decodeResult.formatted.items.push({ - type: 'destination', - code: 'DST', - label: 'Destination', - value: decodeResult.raw.arrival_icao, - }); - - // We don't know what the /SK section means. We have seen various numbers - // after the /SK. + ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(results[0].substr(2, 4)+'00')); + + if (results[1].substring(0,2) === "DS") { + ResultFormatter.arrivalAirport(decodeResult, results[1].substring(2, 6)); decodeResult.remaining.text = "/".concat(results[2]); } else { decodeResult.remaining.text = "/".concat(results[1], "/", results[2]) diff --git a/lib/plugins/Label_44_POS.test.ts b/lib/plugins/Label_44_POS.test.ts index 7fb5d65..d13fd4f 100644 --- a/lib/plugins/Label_44_POS.test.ts +++ b/lib/plugins/Label_44_POS.test.ts @@ -39,11 +39,11 @@ test('decodes Label 44 Preamble POS02 variant 1', () => { expect(decodeResult.formatted.items[0].code).toBe('POS'); expect(decodeResult.formatted.items[0].label).toBe('Aircraft Position'); expect(decodeResult.formatted.items[0].value).toBe('38.285 N, 77.845 W'); - expect(decodeResult.formatted.items[1].type).toBe('origin'); + expect(decodeResult.formatted.items[1].type).toBe('icao'); expect(decodeResult.formatted.items[1].code).toBe('ORG'); expect(decodeResult.formatted.items[1].label).toBe('Origin'); expect(decodeResult.formatted.items[1].value).toBe('KJFK'); - expect(decodeResult.formatted.items[2].type).toBe('destination'); + expect(decodeResult.formatted.items[2].type).toBe('icao'); expect(decodeResult.formatted.items[2].code).toBe('DST'); expect(decodeResult.formatted.items[2].label).toBe('Destination'); expect(decodeResult.formatted.items[2].value).toBe('KUZA'); diff --git a/lib/plugins/Label_80.test.ts b/lib/plugins/Label_80.test.ts index 1cfe2f8..0fccfc9 100644 --- a/lib/plugins/Label_80.test.ts +++ b/lib/plugins/Label_80.test.ts @@ -30,11 +30,11 @@ test('decodes Label 80 variant 1', () => { expect(decodeResult.raw.position.longitude).toBe(-95.133); expect(decodeResult.raw.altitude).toBe(15608); expect(decodeResult.formatted.items.length).toBe(8); - expect(decodeResult.formatted.items[0].type).toBe('origin'); + expect(decodeResult.formatted.items[0].type).toBe('icao'); expect(decodeResult.formatted.items[0].code).toBe('ORG'); expect(decodeResult.formatted.items[0].label).toBe('Origin'); expect(decodeResult.formatted.items[0].value).toBe('KIAH'); - expect(decodeResult.formatted.items[1].type).toBe('destination'); + expect(decodeResult.formatted.items[1].type).toBe('icao'); expect(decodeResult.formatted.items[1].code).toBe('DST'); expect(decodeResult.formatted.items[1].label).toBe('Destination'); expect(decodeResult.formatted.items[1].value).toBe('MMGL'); @@ -77,11 +77,11 @@ test('decodes Label 80 variant 2', () => { expect(decodeResult.raw.position.latitude).toBe(35.391999999999996); // FIXME?: 35.392 expect(decodeResult.raw.position.longitude).toBe(-79.372); expect(decodeResult.formatted.items.length).toBe(16); - expect(decodeResult.formatted.items[0].type).toBe('origin'); + expect(decodeResult.formatted.items[0].type).toBe('icao'); expect(decodeResult.formatted.items[0].code).toBe('ORG'); expect(decodeResult.formatted.items[0].label).toBe('Origin'); expect(decodeResult.formatted.items[0].value).toBe('KIAD'); - expect(decodeResult.formatted.items[1].type).toBe('destination'); + expect(decodeResult.formatted.items[1].type).toBe('icao'); expect(decodeResult.formatted.items[1].code).toBe('DST'); expect(decodeResult.formatted.items[1].label).toBe('Destination'); expect(decodeResult.formatted.items[1].value).toBe('MSLP'); diff --git a/lib/plugins/Label_83.test.ts b/lib/plugins/Label_83.test.ts index 7d639ad..d0a90c7 100644 --- a/lib/plugins/Label_83.test.ts +++ b/lib/plugins/Label_83.test.ts @@ -32,9 +32,9 @@ test('decodes Label 83 variant 1', () => { expect(decodeResult.raw.heading).toBe('140.0'); expect(decodeResult.remaining.text).toBe('19700'); expect(decodeResult.formatted.items.length).toBe(6); - expect(decodeResult.formatted.items[0].type).toBe('origin'); + expect(decodeResult.formatted.items[0].type).toBe('icao'); expect(decodeResult.formatted.items[0].value).toBe('KLAX'); - expect(decodeResult.formatted.items[1].type).toBe('destination'); + expect(decodeResult.formatted.items[1].type).toBe('icao'); expect(decodeResult.formatted.items[1].value).toBe('KEWR'); expect(decodeResult.formatted.items[2].type).toBe('aircraft_position'); expect(decodeResult.formatted.items[2].value).toBe('40.530 N, 74.470 W'); @@ -70,9 +70,9 @@ test('decodes Label 83 variant 1 (C-band)', () => { expect(decodeResult.raw.heading).toBe('-107.6'); expect(decodeResult.remaining.text).toBe('64900'); expect(decodeResult.formatted.items.length).toBe(6); - expect(decodeResult.formatted.items[0].type).toBe('origin'); + expect(decodeResult.formatted.items[0].type).toBe('icao'); expect(decodeResult.formatted.items[0].value).toBe('KIAH'); - expect(decodeResult.formatted.items[1].type).toBe('destination'); + expect(decodeResult.formatted.items[1].type).toBe('icao'); expect(decodeResult.formatted.items[1].value).toBe('RJAA'); expect(decodeResult.formatted.items[2].type).toBe('aircraft_position'); expect(decodeResult.formatted.items[2].value).toBe('39.120 N, 175.100 W'); diff --git a/lib/plugins/Label_8E.test.ts b/lib/plugins/Label_8E.test.ts index 03088d0..0272085 100644 --- a/lib/plugins/Label_8E.test.ts +++ b/lib/plugins/Label_8E.test.ts @@ -20,13 +20,11 @@ test('decodes Label 8E sample 1', () => { expect(decodeResult.message.text).toBe('EGSS,1618'); expect(decodeResult.raw.arrival_icao).toBe('EGSS'); expect(decodeResult.formatted.items.length).toBe(2); - expect(decodeResult.formatted.items[0].type).toBe('eta'); + expect(decodeResult.formatted.items[0].type).toBe('time_of_day'); expect(decodeResult.formatted.items[0].code).toBe('ETA'); expect(decodeResult.formatted.items[0].label).toBe('Estimated Time of Arrival'); - // Check for the minutes as typescript doesn't have a UTC time string method - // so the hour will depend on the test host timezone. - expect((decodeResult.formatted.items[0].value as string).includes('18')).toBe(true); - expect(decodeResult.formatted.items[1].type).toBe('destination'); + expect(decodeResult.formatted.items[0].value).toBe('16:18:00'); + expect(decodeResult.formatted.items[1].type).toBe('icao'); expect(decodeResult.formatted.items[1].code).toBe('DST'); expect(decodeResult.formatted.items[1].label).toBe('Destination'); expect(decodeResult.formatted.items[1].value).toBe('EGSS'); diff --git a/lib/plugins/Label_8E.ts b/lib/plugins/Label_8E.ts index bcc606f..df2ff88 100644 --- a/lib/plugins/Label_8E.ts +++ b/lib/plugins/Label_8E.ts @@ -1,6 +1,7 @@ import { DateTimeUtils } from '../DateTimeUtils'; import { DecoderPlugin } from '../DecoderPlugin'; import { DecodeResult, Message, Options } from '../DecoderPluginInterface'; +import { ResultFormatter } from '../utils/result_formatter'; // ETA export class Label_8E extends DecoderPlugin { @@ -28,22 +29,8 @@ export class Label_8E extends DecoderPlugin { console.log(results.groups); } - decodeResult.formatted.items.push({ - type: 'eta', - code: 'ETA', - label: 'Estimated Time of Arrival', - value: DateTimeUtils.UTCToString(results.groups.arrival_eta), - }); - - - decodeResult.raw.arrival_icao = results.groups.arrival_icao; - decodeResult.formatted.items.push({ - type: 'destination', - code: 'DST', - label: 'Destination', - value: decodeResult.raw.arrival_icao, - }); - + ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(results.groups.arrival_eta + '00')); + ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao); } decodeResult.decoded = true; diff --git a/lib/plugins/Label_HX.test.ts b/lib/plugins/Label_HX.test.ts index 217e0e8..6ff2f31 100644 --- a/lib/plugins/Label_HX.test.ts +++ b/lib/plugins/Label_HX.test.ts @@ -47,7 +47,7 @@ test('decodes Label HX variant 2', () => { expect(decodeResult.raw.departure_icao).toBe('GSP'); expect(decodeResult.remaining.text).toBe('B02'); expect(decodeResult.formatted.items.length).toBe(1); - expect(decodeResult.formatted.items[0].type).toBe('origin'); + expect(decodeResult.formatted.items[0].type).toBe('icao'); expect(decodeResult.formatted.items[0].code).toBe('ORG'); expect(decodeResult.formatted.items[0].label).toBe('Origin'); expect(decodeResult.formatted.items[0].value).toBe('GSP'); diff --git a/lib/plugins/Label_QQ.test.ts b/lib/plugins/Label_QQ.test.ts index 120a1fd..efa318b 100644 --- a/lib/plugins/Label_QQ.test.ts +++ b/lib/plugins/Label_QQ.test.ts @@ -31,11 +31,11 @@ test('decodes Label QQ variant 1', () => { expect(decodeResult.raw.groundspeed).toBe('175'); expect(decodeResult.remaining.text).toBe('028,0042'); expect(decodeResult.formatted.items.length).toBe(5); - expect(decodeResult.formatted.items[0].type).toBe('origin'); + expect(decodeResult.formatted.items[0].type).toBe('icao'); expect(decodeResult.formatted.items[0].code).toBe('ORG'); expect(decodeResult.formatted.items[0].label).toBe('Origin'); expect(decodeResult.formatted.items[0].value).toBe('KSDL'); - expect(decodeResult.formatted.items[1].type).toBe('destination'); + expect(decodeResult.formatted.items[1].type).toBe('icao'); expect(decodeResult.formatted.items[1].code).toBe('DST'); expect(decodeResult.formatted.items[1].label).toBe('Destination'); expect(decodeResult.formatted.items[1].value).toBe('KLAS'); @@ -74,11 +74,11 @@ test('decodes Label QQ variant 2', () => { expect(decodeResult.raw.position.longitude).toBe(-118.16833333333334); expect(decodeResult.remaining.text).toBe('---,020,0009'); expect(decodeResult.formatted.items.length).toBe(4); - expect(decodeResult.formatted.items[0].type).toBe('origin'); + expect(decodeResult.formatted.items[0].type).toBe('icao'); expect(decodeResult.formatted.items[0].code).toBe('ORG'); expect(decodeResult.formatted.items[0].label).toBe('Origin'); expect(decodeResult.formatted.items[0].value).toBe('KLGB'); - expect(decodeResult.formatted.items[1].type).toBe('destination'); + expect(decodeResult.formatted.items[1].type).toBe('icao'); expect(decodeResult.formatted.items[1].code).toBe('DST'); expect(decodeResult.formatted.items[1].label).toBe('Destination'); expect(decodeResult.formatted.items[1].value).toBe('KLAX'); @@ -110,11 +110,11 @@ test('decodes Label QQ variant 3', () => { expect(decodeResult.raw.wheels_off).toBe('0058'); expect(decodeResult.remaining.text).toBe('/OFFRPT/090155'); expect(decodeResult.formatted.items.length).toBe(3); - expect(decodeResult.formatted.items[0].type).toBe('origin'); + expect(decodeResult.formatted.items[0].type).toBe('icao'); expect(decodeResult.formatted.items[0].code).toBe('ORG'); expect(decodeResult.formatted.items[0].label).toBe('Origin'); expect(decodeResult.formatted.items[0].value).toBe('CYOW'); - expect(decodeResult.formatted.items[1].type).toBe('destination'); + expect(decodeResult.formatted.items[1].type).toBe('icao'); expect(decodeResult.formatted.items[1].code).toBe('DST'); expect(decodeResult.formatted.items[1].label).toBe('Destination'); expect(decodeResult.formatted.items[1].value).toBe('KMEM'); diff --git a/lib/utils/result_formatter.ts b/lib/utils/result_formatter.ts index 60bf31e..3781439 100644 --- a/lib/utils/result_formatter.ts +++ b/lib/utils/result_formatter.ts @@ -32,14 +32,24 @@ export class ResultFormatter { decodeResult.raw.flight_number = value; }; - static departureAirport(decodeResult: DecodeResult, value: string) { - decodeResult.raw.departure_icao = value; - decodeResult.formatted.items.push({ - type: 'origin', - code: 'ORG', - label: 'Origin', - value: decodeResult.raw.departure_icao, - }); + static departureAirport(decodeResult: DecodeResult, value: string, type: 'IATA' | 'ICAO' = 'ICAO') { + if (type === 'ICAO') { + decodeResult.raw.departure_icao = value; + decodeResult.formatted.items.push({ + type: 'icao', + code: 'ORG', + label: 'Origin', + value: value, + }); + } else { + decodeResult.raw.departure_iata = value; + decodeResult.formatted.items.push({ + type: 'iata', + code: 'ORG', + label: 'Origin', + value: value, + }); + } }; static departureRunway(decodeResult: DecodeResult, value: string) { @@ -52,34 +62,54 @@ export class ResultFormatter { }); } - static arrivalAirport(decodeResult: DecodeResult, value: string) { - decodeResult.raw.arrival_icao = value; - decodeResult.formatted.items.push({ - type: 'destination', - code: 'DST', - label: 'Destination', - value: decodeResult.raw.arrival_icao, - }); + static arrivalAirport(decodeResult: DecodeResult, value: string, type: 'IATA' | 'ICAO' = 'ICAO') { + if (type === 'ICAO') { + decodeResult.raw.arrival_icao = value; + decodeResult.formatted.items.push({ + type: 'icao', + code: 'DST', + label: 'Destination', + value: value, + }); + } else { + decodeResult.raw.arrival_iata = value; + decodeResult.formatted.items.push({ + type: 'iata', + code: 'DST', + label: 'Destination', + value: value, + }); + } }; static alternateAirport(decodeResult: DecodeResult, value: string) { decodeResult.raw.alternate_icao = value; decodeResult.formatted.items.push({ - type: 'destination', + type: 'icao', code: 'ALT_DST', label: 'Alternate Destination', value: decodeResult.raw.alternate_icao, }); }; - static eta(decodeResult: DecodeResult, time: number) { - decodeResult.raw.eta_time = time; - decodeResult.formatted.items.push({ - type: 'time_of_day', - code: 'ETA', - label: 'Estimated Time of Arrival', - value: DateTimeUtils.timestampToString(time, 'tod'), - }); + static eta(decodeResult: DecodeResult, time: number, type: 'tod' | 'epoch' = 'tod') { + if (type === 'tod') { + decodeResult.raw.eta_time = time; + decodeResult.formatted.items.push({ + type: 'time_of_day', + code: 'ETA', + label: 'Estimated Time of Arrival', + value: DateTimeUtils.timestampToString(time, 'tod'), + }); + } else { + decodeResult.raw.eta_date = time; + decodeResult.formatted.items.push({ + type: 'epoch', + code: 'ETA', + label: 'Estimated Time of Arrival', + value: DateTimeUtils.timestampToString(time, 'epoch'), + }); + } } static arrivalRunway(decodeResult: DecodeResult, value: string) { @@ -223,6 +253,16 @@ export class ResultFormatter { }); } + static text(decodeResult: DecodeResult, text: string) { + decodeResult.raw.text = text; + decodeResult.formatted.items.push({ + type: 'text', + code: 'TEXT', + label: 'Text Message', + value: text, + }); + } + static unknown(decodeResult: DecodeResult, value: string) { decodeResult.remaining.text += ',' + value; };