From 5a14e6673c1dedaade9d2416bacadac8c190372b Mon Sep 17 00:00:00 2001 From: Mark Bumiller Date: Wed, 13 Nov 2024 08:51:25 -0500 Subject: [PATCH] adding label 15 takeoff decoding --- lib/plugins/Label_15.test.ts | 40 +++++++++++++++++++++++++++++++---- lib/plugins/Label_15.ts | 16 ++++++++++++-- lib/utils/result_formatter.ts | 26 ++++++++++++++++------- 3 files changed, 68 insertions(+), 14 deletions(-) diff --git a/lib/plugins/Label_15.test.ts b/lib/plugins/Label_15.test.ts index 6b34589..d99c6c0 100644 --- a/lib/plugins/Label_15.test.ts +++ b/lib/plugins/Label_15.test.ts @@ -19,7 +19,7 @@ describe('Label_15', () => { }); }); - test('decodes short variant missing ???', () => { + test('decodes short variant missing unkown', () => { const text = '(2N38448W 77216--- 28 20 7(Z' const decodeResult = plugin.decode({ text: text }); @@ -65,16 +65,48 @@ describe('Label_15', () => { expect(decodeResult.remaining.text).toBe('--- 42'); }); - test('decodes long variant', () => { + test('decodes off variant no unkown', () => { const text = '(2N39018W 77284OFF11112418101313--------(Z' const decodeResult = plugin.decode({ text: text }); expect(decodeResult.decoded).toBe(true); expect(decodeResult.decoder.decodeLevel).toBe('partial'); - expect(decodeResult.formatted.items.length).toBe(1); + expect(decodeResult.formatted.items.length).toBe(2); expect(decodeResult.formatted.items[0].label).toBe('Aircraft Position'); expect(decodeResult.formatted.items[0].value).toBe('39.030 N, 77.473 W'); - expect(decodeResult.remaining.text).toBe('OFF11112418101313--------'); + expect(decodeResult.formatted.items[1].label).toBe('Takeoff Time'); + expect(decodeResult.formatted.items[1].value).toBe('2024-11-11T18:10:00Z'); + expect(decodeResult.remaining.text).toBe('1313--------'); + }); + + test('decodes off variant no date and unknown', () => { + // https://app.airframes.io/messages/3593342701 + const text = '(2N42589W 83520OFF------13280606--------(Z' + const decodeResult = plugin.decode({ text: text }); + + expect(decodeResult.decoded).toBe(true); + expect(decodeResult.decoder.decodeLevel).toBe('partial'); + expect(decodeResult.formatted.items.length).toBe(2); + expect(decodeResult.formatted.items[0].label).toBe('Aircraft Position'); + expect(decodeResult.formatted.items[0].value).toBe('42.982 N, 83.867 W'); + expect(decodeResult.formatted.items[1].label).toBe('Takeoff Time'); + expect(decodeResult.formatted.items[1].value).toBe('13:28:00'); + expect(decodeResult.remaining.text).toBe('0606--------'); + }); + + test('decodes off variant all fields', () => { + // https://app.airframes.io/messages/3603048708 + const text = '(2N39042W 77308OFF1311240327B1818 015(Z' + const decodeResult = plugin.decode({ text: text }); + + expect(decodeResult.decoded).toBe(true); + expect(decodeResult.decoder.decodeLevel).toBe('partial'); + expect(decodeResult.formatted.items.length).toBe(2); + expect(decodeResult.formatted.items[0].label).toBe('Aircraft Position'); + expect(decodeResult.formatted.items[0].value).toBe('39.070 N, 77.513 W'); + expect(decodeResult.formatted.items[1].label).toBe('Takeoff Time'); + expect(decodeResult.formatted.items[1].value).toBe('2024-11-13T03:27:00Z'); + expect(decodeResult.remaining.text).toBe('B1818 015'); }); test('does not decode Label 15 ', () => { diff --git a/lib/plugins/Label_15.ts b/lib/plugins/Label_15.ts index 9ab602d..37a157a 100644 --- a/lib/plugins/Label_15.ts +++ b/lib/plugins/Label_15.ts @@ -1,3 +1,4 @@ +import { DateTimeUtils } from '../DateTimeUtils'; import { DecoderPlugin } from '../DecoderPlugin'; import { DecodeResult, Message, Options } from '../DecoderPluginInterface'; import { CoordinateUtils } from '../utils/coordinate_utils'; @@ -30,8 +31,19 @@ export class Label_15 extends DecoderPlugin { ResultFormatter.altitude(decodeResult, 100 * Number(alt)); } ResultFormatter.temperature(decodeResult, between.substring(22).replaceAll(" ", "0")); - } else { // long variant - ResultFormatter.unknown(decodeResult, between.substring(13)); + } else if(between.substring(13,16) === 'OFF') { // off variant + const ddmmyy = between.substring(16, 22); + const hhmm = between.substring(22, 26); + if(ddmmyy != '------') { + const mmddyy = ddmmyy.substring(2, 4) + ddmmyy.substring(0, 2) + ddmmyy.substring(4); + console.log(`Decoder: mmddyy: ${mmddyy}, hhmm: ${hhmm}`); + ResultFormatter.off(decodeResult, DateTimeUtils.convertDateTimeToEpoch(hhmm+'00', mmddyy), 'epoch'); + } else { + ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(hhmm), 'tod'); + } + ResultFormatter.unknown(decodeResult, between.substring(26)); + } else { + ResultFormatter.unknown(decodeResult, between.substring(26)); } } else { if (options.debug) { diff --git a/lib/utils/result_formatter.ts b/lib/utils/result_formatter.ts index 44e152a..9cb8524 100644 --- a/lib/utils/result_formatter.ts +++ b/lib/utils/result_formatter.ts @@ -284,14 +284,24 @@ export class ResultFormatter { }); } - static off(decodeResult: DecodeResult, time: number) { - decodeResult.raw.off_time = time; - decodeResult.formatted.items.push({ - type: 'time_of_day', - code: 'OFF', - label: 'Takeoff Time', - value: DateTimeUtils.timestampToString(time, 'tod'), - }); + static off(decodeResult: DecodeResult, time: number, type: 'tod' | 'epoch' = 'tod') { + if (type === 'tod') { + decodeResult.raw.off_time = time; + decodeResult.formatted.items.push({ + type: 'time_of_day', + code: 'OFF', + label: 'Takeoff Time', + value: DateTimeUtils.timestampToString(time, 'tod'), + }); + } else { + decodeResult.raw.off_date = time; + decodeResult.formatted.items.push({ + type: 'epoch', + code: 'OFF', + label: 'Takeoff Time', + value: DateTimeUtils.timestampToString(time, 'epoch'), + }); + } } static on(decodeResult: DecodeResult, time: number) {