diff --git a/lib/MessageDecoder.ts b/lib/MessageDecoder.ts index 507acec..7cc4572 100644 --- a/lib/MessageDecoder.ts +++ b/lib/MessageDecoder.ts @@ -2,6 +2,7 @@ import { DecodeResult, DecoderPluginInterface, Message, Options } from './Decode import * as Plugins from './plugins/official'; import { MIAMCoreUtils } from './utils/miam'; +import { ResultFormatter } from './utils/result_formatter'; export class MessageDecoder { name: string; @@ -95,6 +96,14 @@ export class MessageDecoder { } } + // C-Band puts a 10 char header in front of some message types + // First 4 chars are some kind of message number + // Last 6 chars are the flight number + let cband = message.text.match(/^(?[A-Z]\d{2}[A-Z])(?[A-Z0-9]{2})(?[0-9]{4})/); + if (cband?.groups) { + message.text = message.text.substring(10); + } + // console.log('All plugins'); // console.log(this.plugins); const usablePlugins = this.plugins.filter((plugin) => { @@ -150,6 +159,11 @@ export class MessageDecoder { } } + if (cband?.groups && cband?.input) { + ResultFormatter.flightNumber(result, cband.groups.airline + Number(cband.groups.number)); + message.text = cband.input; + } + if (options.debug) { console.log('Result'); console.log(result); diff --git a/lib/plugins/Label_1L_Slash.ts b/lib/plugins/Label_1L_Slash.ts index e47513a..4f59f23 100644 --- a/lib/plugins/Label_1L_Slash.ts +++ b/lib/plugins/Label_1L_Slash.ts @@ -80,4 +80,4 @@ export class Label_1L_Slash extends DecoderPlugin { // eslint-disable-line camel } } -export default {}; \ No newline at end of file +export default {}; diff --git a/lib/plugins/Label_30_Slash_EA.test.ts b/lib/plugins/Label_30_Slash_EA.test.ts index bd04040..ebe6a27 100644 --- a/lib/plugins/Label_30_Slash_EA.test.ts +++ b/lib/plugins/Label_30_Slash_EA.test.ts @@ -14,7 +14,7 @@ test('decodes Label 30 sample 1', () => { }); const text = '/EA1719/DSKSFO/SK23'; - const decodeResult = decoderPlugin.decode({ text: text }); + const decodeResult = decoder.decode({ label: "30", text: text }); expect(decodeResult.decoded).toBe(true); expect(decodeResult.decoder.decodeLevel).toBe('partial'); diff --git a/lib/plugins/Label_4A.test.ts b/lib/plugins/Label_4A.test.ts index 9be952d..d099168 100644 --- a/lib/plugins/Label_4A.test.ts +++ b/lib/plugins/Label_4A.test.ts @@ -15,11 +15,10 @@ test('matches Label 4A qualifiers', () => { test('decodes Label 4A, variant 1', () => { const decoder = new MessageDecoder(); - const decoderPlugin = new Label_4A(decoder); // https://app.airframes.io/messages/3451492279 const text = '063200,1910,.N343FR,FFT2028,KSLC,KORD,1,0632,RT0,LT0,'; - const decodeResult = decoderPlugin.decode({ text: text }); + const decodeResult = decoder.decode({ label: "4A", text: text }); expect(decodeResult.decoded).toBe(true); expect(decodeResult.decoder.decodeLevel).toBe('partial'); @@ -27,7 +26,7 @@ test('decodes Label 4A, variant 1', () => { expect(decodeResult.formatted.description).toBe('Latest New Format'); expect(decodeResult.message.text).toBe(text); expect(decodeResult.remaining.text).toBe('RT0,LT0,'); - expect(decodeResult.formatted.items.length).toBe(6); + expect(decodeResult.formatted.items.length).toBe(5); expect(decodeResult.formatted.items[0].code).toBe('MSG_TOD'); expect(decodeResult.formatted.items[0].value).toBe('06:32:00'); expect(decodeResult.formatted.items[1].code).toBe('TAIL'); @@ -42,11 +41,10 @@ test('decodes Label 4A, variant 1', () => { test('decodes Label 4A, variant 1, no callsign', () => { const decoder = new MessageDecoder(); - const decoderPlugin = new Label_4A(decoder); // https://app.airframes.io/messages/3452310240 const text = '101606,1910,.N317FR,,KMDW,----,1,1016,RT0,LT1,'; - const decodeResult = decoderPlugin.decode({ text: text }); + const decodeResult = decoder.decode({ label: "4A", text: text }); expect(decodeResult.decoded).toBe(true); expect(decodeResult.decoder.decodeLevel).toBe('partial'); @@ -54,7 +52,7 @@ test('decodes Label 4A, variant 1, no callsign', () => { expect(decodeResult.formatted.description).toBe('Latest New Format'); expect(decodeResult.message.text).toBe(text); expect(decodeResult.remaining.text).toBe('RT0,LT1,'); - expect(decodeResult.formatted.items.length).toBe(5); + expect(decodeResult.formatted.items.length).toBe(4); expect(decodeResult.formatted.items[0].code).toBe('MSG_TOD'); expect(decodeResult.formatted.items[0].value).toBe('10:16:06'); expect(decodeResult.formatted.items[1].code).toBe('TAIL'); @@ -67,11 +65,10 @@ test('decodes Label 4A, variant 1, no callsign', () => { test('decodes Label 4A, variant 2', () => { const decoder = new MessageDecoder(); - const decoderPlugin = new Label_4A(decoder); // https://app.airframes.io/messages/3461807403 const text = 'N45129W093113MSP/07 ,204436123VECTORS,,P04,268044858,46904221'; - const decodeResult = decoderPlugin.decode({ text: text }); + const decodeResult = decoder.decode({ label: "4A", text: text }); expect(decodeResult.decoded).toBe(true); expect(decodeResult.decoder.decodeLevel).toBe('partial'); @@ -92,11 +89,10 @@ test('decodes Label 4A, variant 2', () => { test('decodes Label 4A, variant 2, C-Band', () => { const decoder = new MessageDecoder(); - const decoderPlugin = new Label_4A(decoder); // https://app.airframes.io/messages/3461407615 const text = 'M60ALH0752N22456E077014OSE35 ,192027370VEX36 ,192316,M46,275043309,85220111'; - const decodeResult = decoderPlugin.decode({ text: text }); + const decodeResult = decoder.decode({ label: "4A", text: text }); expect(decodeResult.decoded).toBe(true); expect(decodeResult.decoder.decodeLevel).toBe('partial'); @@ -105,25 +101,24 @@ test('decodes Label 4A, variant 2, C-Band', () => { expect(decodeResult.message.text).toBe(text); expect(decodeResult.remaining.text).toBe('275043309,85220111'); expect(decodeResult.formatted.items.length).toBe(5); - expect(decodeResult.formatted.items[0].code).toBe('FLIGHT'); - expect(decodeResult.formatted.items[0].value).toBe('LH752'); - expect(decodeResult.formatted.items[1].code).toBe('POS'); - expect(decodeResult.formatted.items[1].value).toBe('22.456 N, 77.014 E'); - expect(decodeResult.formatted.items[2].code).toBe('ALT'); - expect(decodeResult.formatted.items[2].value).toBe('37000 feet'); - expect(decodeResult.formatted.items[3].code).toBe('ROUTE'); - expect(decodeResult.formatted.items[3].value).toBe('OSE35@19:20:27 > VEX36@19:23:16'); - expect(decodeResult.formatted.items[4].code).toBe('OATEMP'); - expect(decodeResult.formatted.items[4].value).toBe('-46 degrees'); + expect(decodeResult.formatted.items[0].code).toBe('POS'); + expect(decodeResult.formatted.items[0].value).toBe('22.456 N, 77.014 E'); + expect(decodeResult.formatted.items[1].code).toBe('ALT'); + expect(decodeResult.formatted.items[1].value).toBe('37000 feet'); + expect(decodeResult.formatted.items[2].code).toBe('ROUTE'); + expect(decodeResult.formatted.items[2].value).toBe('OSE35@19:20:27 > VEX36@19:23:16'); + expect(decodeResult.formatted.items[3].code).toBe('OATEMP'); + expect(decodeResult.formatted.items[3].value).toBe('-46 degrees'); + expect(decodeResult.formatted.items[4].code).toBe('FLIGHT'); + expect(decodeResult.formatted.items[4].value).toBe('LH752'); }); test('decodes Label 4A, variant 3', () => { const decoder = new MessageDecoder(); - const decoderPlugin = new Label_4A(decoder); // https://globe.adsbexchange.com/?icao=A39AC6&showTrace=2024-09-22×tamp=1727009085 const text = '124442,1320, 138,33467,N 41.093,W 72.677'; - const decodeResult = decoderPlugin.decode({ text: text }); + const decodeResult = decoder.decode({ label: "4A", text: text }); expect(decodeResult.decoded).toBe(true); expect(decodeResult.decoder.decodeLevel).toBe('partial'); @@ -144,15 +139,14 @@ test('decodes Label 4A, variant 3', () => { test('decodes Label 4A_DIS ', () => { const decoder = new MessageDecoder(); - const decoderPlugin = new Label_4A(decoder); // https://app.airframes.io/messages/3449413366 const text = 'DIS01,182103,WEN3100,WRONG CREW HAHAHA'; - const decodeResult = decoderPlugin.decode({ text: text }); + const decodeResult = decoder.decode({ label: "4A", text: text }); - expect(decodeResult.decoded).toBe(false); - expect(decodeResult.decoder.decodeLevel).toBe('none'); - expect(decodeResult.decoder.name).toBe('label-4a'); - expect(decodeResult.formatted.description).toBe('Latest New Format'); - expect(decodeResult.formatted.items.length).toBe(0); +// expect(decodeResult.decoded).toBe(false); +// expect(decodeResult.decoder.decodeLevel).toBe('none'); + expect(decodeResult.decoder.name).not.toBe('label-4a'); +// expect(decodeResult.formatted.description).toBe('Latest New Format'); +// expect(decodeResult.formatted.items.length).toBe(0); }); diff --git a/lib/plugins/Label_4A.ts b/lib/plugins/Label_4A.ts index 574e83c..c90d2ec 100644 --- a/lib/plugins/Label_4A.ts +++ b/lib/plugins/Label_4A.ts @@ -20,16 +20,8 @@ export class Label_4A extends DecoderPlugin { decodeResult.message = message; decodeResult.formatted.description = 'Latest New Format'; - - // Inmarsat C-band seems to prefix normal messages with a message number and flight number - let text = message.text; - if (text.match(/^M\d{2}A\w{6}/)) { - ResultFormatter.flightNumber(decodeResult, message.text.substring(4, 10).replace(/^([A-Z]+)0*/g, "$1")); - text = text.substring(10); - } - decodeResult.decoded = true; - const fields = text.split(","); + const fields = message.text.split(","); if (fields.length === 11) { // variant 1 ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[0])); @@ -38,7 +30,6 @@ export class Label_4A extends DecoderPlugin { ResultFormatter.callsign(decodeResult, fields[3]); ResultFormatter.departureAirport(decodeResult, fields[4]); ResultFormatter.arrivalAirport(decodeResult, fields[5]); - ResultFormatter.altitude(decodeResult, Number(text.substring(48, 51)) * 100); ResultFormatter.unknownArr(decodeResult, fields.slice(8)); } else if (fields.length === 6) { if (fields[0].match(/^[NS]/)) { @@ -68,7 +59,7 @@ export class Label_4A extends DecoderPlugin { } } else { decodeResult.decoded = false; - ResultFormatter.unknown(decodeResult, text); + ResultFormatter.unknown(decodeResult, message.text); } if (decodeResult.decoded) { diff --git a/lib/plugins/Label_4N.test.ts b/lib/plugins/Label_4N.test.ts index 36b2b3d..0630194 100644 --- a/lib/plugins/Label_4N.test.ts +++ b/lib/plugins/Label_4N.test.ts @@ -11,11 +11,10 @@ test('matches Label 4N qualifiers', () => { test('decodes Label 4N variant 1', () => { const decoder = new MessageDecoder(); - const decoderPlugin = new Label_4N(decoder); // https://globe.adsbexchange.com/?icao=A15027&showTrace=2024-09-23×tamp=1727057017 const text = '22024N MCI JFK1\r\n0013 0072 N040586 W074421 230'; - const decodeResult = decoderPlugin.decode({ text: text }); + const decodeResult = decoder.decode({ label: "4N", text: text }); expect(decodeResult.decoded).toBe(true); expect(decodeResult.decoder.decodeLevel).toBe('partial'); @@ -37,11 +36,10 @@ test('decodes Label 4N variant 1', () => { test('decodes Label 4N variant 2B', () => { const decoder = new MessageDecoder(); - const decoderPlugin = new Label_4N(decoder); // https://app.airframes.io/messages/3421601874 const text = '285,B,69005074-507,10/12,+36.081,-094.810,35014,002.3,ELP,SDF,SDF,17R/,17L/,0,0,,,,,,0,0,0,0,1,,,,,247.0,014.2,261.2,421A'; - const decodeResult = decoderPlugin.decode({ text: text }); + const decodeResult = decoder.decode({ label: "4N", text: text }); expect(decodeResult.decoded).toBe(true); expect(decodeResult.decoder.decodeLevel).toBe('partial'); @@ -71,11 +69,10 @@ test('decodes Label 4N variant 2B', () => { test('decodes Label 4N variant 2C', () => { const decoder = new MessageDecoder(); - const decoderPlugin = new Label_4N(decoder); // https://globe.adsbexchange.com/?icao=A3E08D&showTrace=2024-09-24×tamp=1727181643 const text = '285,C,,09/24,,,,,EWR,PHL,PHL,09R/,/,0,0,,,,,,1,0,0,0,1,0,,0,0,198.5,014.5,213.0,9BCD'; - const decodeResult = decoderPlugin.decode({ text: text }); + const decodeResult = decoder.decode({ label: "4N", text: text }); expect(decodeResult.decoded).toBe(true); expect(decodeResult.decoder.decodeLevel).toBe('partial'); @@ -99,11 +96,10 @@ test('decodes Label 4N variant 2C', () => { test('decodes Label 4N variant 2C (C-band)', () => { const decoder = new MessageDecoder(); - const decoderPlugin = new Label_4N(decoder); // https://app.airframes.io/messages/3422221702 const text = 'M85AUP0109285,C,,10/12,,,,,NRT,ANC,ANC,07R/,33/,0,0,,,,,,0,0,0,0,1,0,,0,0,709.8,048.7,758.5,75F3'; - const decodeResult = decoderPlugin.decode({ text: text }); + const decodeResult = decoder.decode({ label: "4N", text: text }); expect(decodeResult.decoded).toBe(true); expect(decodeResult.decoder.decodeLevel).toBe('partial'); @@ -114,28 +110,27 @@ test('decodes Label 4N variant 2C (C-band)', () => { expect(decodeResult.raw.date).toBe('10/12'); expect(decodeResult.remaining.text).toBe('C,0,0,0,0,0,0,1,0,0,0,709.8,048.7,758.5'); expect(decodeResult.formatted.items.length).toBe(7); - expect(decodeResult.formatted.items[0].code).toBe('FLIGHT'); - expect(decodeResult.formatted.items[0].value).toBe('UP109'); - expect(decodeResult.formatted.items[1].code).toBe('ORG'); - expect(decodeResult.formatted.items[1].value).toBe('NRT'); - expect(decodeResult.formatted.items[2].code).toBe('DST'); + expect(decodeResult.formatted.items[0].code).toBe('ORG'); + expect(decodeResult.formatted.items[0].value).toBe('NRT'); + expect(decodeResult.formatted.items[1].code).toBe('DST'); + expect(decodeResult.formatted.items[1].value).toBe('ANC'); + expect(decodeResult.formatted.items[2].code).toBe('ALT_DST'); expect(decodeResult.formatted.items[2].value).toBe('ANC'); - expect(decodeResult.formatted.items[3].code).toBe('ALT_DST'); - expect(decodeResult.formatted.items[3].value).toBe('ANC'); - expect(decodeResult.formatted.items[4].code).toBe('ARWY'); - expect(decodeResult.formatted.items[4].value).toBe('07R'); - expect(decodeResult.formatted.items[5].code).toBe('ALT_ARWY'); - expect(decodeResult.formatted.items[5].value).toBe('33'); - expect(decodeResult.formatted.items[6].code).toBe('CHECKSUM'); - expect(decodeResult.formatted.items[6].value).toBe('0x75f3'); + expect(decodeResult.formatted.items[3].code).toBe('ARWY'); + expect(decodeResult.formatted.items[3].value).toBe('07R'); + expect(decodeResult.formatted.items[4].code).toBe('ALT_ARWY'); + expect(decodeResult.formatted.items[4].value).toBe('33'); + expect(decodeResult.formatted.items[5].code).toBe('CHECKSUM'); + expect(decodeResult.formatted.items[5].value).toBe('0x75f3'); + expect(decodeResult.formatted.items[6].code).toBe('FLIGHT'); + expect(decodeResult.formatted.items[6].value).toBe('UP109'); }); test('decodes Label 4N ', () => { const decoder = new MessageDecoder(); - const decoderPlugin = new Label_4N(decoder); const text = '4N Bogus message'; - const decodeResult = decoderPlugin.decode({ text: text }); + const decodeResult = decoder.decode({ label: "4N", text: text }); expect(decodeResult.decoded).toBe(false); expect(decodeResult.decoder.decodeLevel).toBe('none'); diff --git a/lib/plugins/Label_4N.ts b/lib/plugins/Label_4N.ts index 9606975..dc2da8a 100644 --- a/lib/plugins/Label_4N.ts +++ b/lib/plugins/Label_4N.ts @@ -18,23 +18,16 @@ export class Label_4N extends DecoderPlugin { decodeResult.message = message; decodeResult.formatted.description = 'Airline Defined'; - // Inmarsat C-band seems to prefix normal messages with a message number and flight number - let text = message.text; - if (text.match(/^M\d{2}A\w{6}/)) { - ResultFormatter.flightNumber(decodeResult, message.text.substring(4, 10).replace(/^([A-Z]+)0*/g, "$1")); - text = text.substring(10); - } - decodeResult.decoded = true; - const fields = text.split(","); - if (text.length === 51) { + const fields = message.text.split(","); + if (message.text.length === 51) { // variant 1 - decodeResult.raw.day = text.substring(0, 2); - ResultFormatter.departureAirport(decodeResult, text.substring(8, 11)); - ResultFormatter.arrivalAirport(decodeResult, text.substring(13, 16)); - ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinatesDecimalMinutes(text.substring(30, 45).replace(/^(.)0/, "$1"))); - ResultFormatter.altitude(decodeResult, Number(text.substring(48, 51)) * 100); - ResultFormatter.unknownArr(decodeResult, [text.substring(2, 4), text.substring(19, 29)], " "); + decodeResult.raw.day = message.text.substring(0, 2); + ResultFormatter.departureAirport(decodeResult, message.text.substring(8, 11)); + ResultFormatter.arrivalAirport(decodeResult, message.text.substring(13, 16)); + ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinatesDecimalMinutes(message.text.substring(30, 45).replace(/^(.)0/, "$1"))); + ResultFormatter.altitude(decodeResult, Number(message.text.substring(48, 51)) * 100); + ResultFormatter.unknownArr(decodeResult, [message.text.substring(2, 4), message.text.substring(19, 29)], " "); } else if (fields.length === 33) { // variant 2 decodeResult.raw.date = fields[3]; @@ -53,7 +46,7 @@ export class Label_4N extends DecoderPlugin { ResultFormatter.unknownArr(decodeResult, [...fields.slice(1,3), fields[7], ...fields.slice(13, 32)].filter((f) => f != "")); } else { decodeResult.decoded = false; - ResultFormatter.unknown(decodeResult, text); + ResultFormatter.unknown(decodeResult, message.text); } if (decodeResult.decoded) { diff --git a/lib/plugins/Label_83.test.ts b/lib/plugins/Label_83.test.ts index b6f916d..f3335c0 100644 --- a/lib/plugins/Label_83.test.ts +++ b/lib/plugins/Label_83.test.ts @@ -11,11 +11,10 @@ test('matches Label 83 qualifiers', () => { test('decodes Label 83 variant 1', () => { const decoder = new MessageDecoder(); - const decoderPlugin = new Label_83(decoder); // https://globe.adsbexchange.com/?icao=A2A3B5&showTrace=2024-09-22×tamp=1726967032 const text = 'KLAX,KEWR,220103, 40.53,- 74.47, 3836,212, 140.0, 19700'; - const decodeResult = decoderPlugin.decode({ text: text }); + const decodeResult = decoder.decode({ label: "83", text: text }); expect(decodeResult.decoded).toBe(true); expect(decodeResult.decoder.decodeLevel).toBe('partial'); @@ -48,11 +47,10 @@ test('decodes Label 83 variant 1', () => { test('decodes Label 83 variant 1 (C-band)', () => { const decoder = new MessageDecoder(); - const decoderPlugin = new Label_83(decoder); // https://app.airframes.io/messages/3413113024 const text = 'M05AUA0007KIAH,RJAA,110012, 39.12,-175.10,39001,265,-107.6, 64900'; - const decodeResult = decoderPlugin.decode({ text: text }); + const decodeResult = decoder.decode({ label: "83", text: text }); expect(decodeResult.decoded).toBe(true); expect(decodeResult.decoder.decodeLevel).toBe('partial'); @@ -70,29 +68,28 @@ 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(7); - expect(decodeResult.formatted.items[0].type).toBe('flight_number'); - expect(decodeResult.formatted.items[0].value).toBe('UA7'); + expect(decodeResult.formatted.items[0].type).toBe('icao'); + expect(decodeResult.formatted.items[0].value).toBe('KIAH'); expect(decodeResult.formatted.items[1].type).toBe('icao'); - expect(decodeResult.formatted.items[1].value).toBe('KIAH'); - expect(decodeResult.formatted.items[2].type).toBe('icao'); - expect(decodeResult.formatted.items[2].value).toBe('RJAA'); - expect(decodeResult.formatted.items[3].type).toBe('aircraft_position'); - expect(decodeResult.formatted.items[3].value).toBe('39.120 N, 175.100 W'); - expect(decodeResult.formatted.items[4].type).toBe('altitude'); - expect(decodeResult.formatted.items[4].value).toBe('39001 feet'); - expect(decodeResult.formatted.items[5].type).toBe('aircraft_groundspeed'); - expect(decodeResult.formatted.items[5].value).toBe('265 knots'); - expect(decodeResult.formatted.items[6].type).toBe('heading'); - expect(decodeResult.formatted.items[6].value).toBe('-107.6'); + 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'); + expect(decodeResult.formatted.items[3].type).toBe('altitude'); + expect(decodeResult.formatted.items[3].value).toBe('39001 feet'); + expect(decodeResult.formatted.items[4].type).toBe('aircraft_groundspeed'); + expect(decodeResult.formatted.items[4].value).toBe('265 knots'); + expect(decodeResult.formatted.items[5].type).toBe('heading'); + expect(decodeResult.formatted.items[5].value).toBe('-107.6'); + expect(decodeResult.formatted.items[6].type).toBe('flight_number'); + expect(decodeResult.formatted.items[6].value).toBe('UA7'); }); test('decodes Label 83 variant 2', () => { const decoder = new MessageDecoder(); - const decoderPlugin = new Label_83(decoder); // https://globe.adsbexchange.com/?icao=478F43&showTrace=2024-09-22×tamp=1727022863 const text = '4DH3 ETAT2 0907/22 ENGM/KEWR .LN-RKO\r\n/ETA 1641'; - const decodeResult = decoderPlugin.decode({ text: text }); + const decodeResult = decoder.decode({ label: "83", text: text }); expect(decodeResult.decoded).toBe(true); expect(decodeResult.decoder.decodeLevel).toBe('partial'); @@ -118,11 +115,10 @@ test('decodes Label 83 variant 2', () => { test('decodes Label 83 variant 3', () => { const decoder = new MessageDecoder(); - const decoderPlugin = new Label_83(decoder); // https://globe.adsbexchange.com/?icao=AC15A1&showTrace=2024-09-22×tamp=1726977342 const text = '001PR22035539N4038.6W07427.80292500008'; - const decodeResult = decoderPlugin.decode({ text: text }); + const decodeResult = decoder.decode({ label: "83", text: text }); expect(decodeResult.decoded).toBe(true); expect(decodeResult.decoder.decodeLevel).toBe('partial'); @@ -143,11 +139,10 @@ test('decodes Label 83 variant 3', () => { test('decodes Label 83 variant 3 (C-band)', () => { const decoder = new MessageDecoder(); - const decoderPlugin = new Label_83(decoder); // https://app.airframes.io/messages/3413346742 const text = 'M09AXA0001001PR11013423N0556.6E11603.0000000----'; - const decodeResult = decoderPlugin.decode({ text: text }); + const decodeResult = decoder.decode({ label: "83", text: text }); expect(decodeResult.decoded).toBe(true); expect(decodeResult.decoder.decodeLevel).toBe('partial'); @@ -161,20 +156,19 @@ test('decodes Label 83 variant 3 (C-band)', () => { expect(decodeResult.raw.altitude).toBe(0); expect(decodeResult.remaining.text).toBe('0----'); expect(decodeResult.formatted.items.length).toBe(3); - expect(decodeResult.formatted.items[0].type).toBe('flight_number'); - expect(decodeResult.formatted.items[0].value).toBe('XA1'); - expect(decodeResult.formatted.items[1].type).toBe('aircraft_position'); - expect(decodeResult.formatted.items[1].value).toBe('5.943 N, 116.050 E'); - expect(decodeResult.formatted.items[2].type).toBe('altitude'); - expect(decodeResult.formatted.items[2].value).toBe('0 feet'); + expect(decodeResult.formatted.items[0].type).toBe('aircraft_position'); + expect(decodeResult.formatted.items[0].value).toBe('5.943 N, 116.050 E'); + expect(decodeResult.formatted.items[1].type).toBe('altitude'); + expect(decodeResult.formatted.items[1].value).toBe('0 feet'); + expect(decodeResult.formatted.items[2].type).toBe('flight_number'); + expect(decodeResult.formatted.items[2].value).toBe('XA1'); }); test('decodes Label 83 ', () => { const decoder = new MessageDecoder(); - const decoderPlugin = new Label_83(decoder); const text = '83 Bogus message'; - const decodeResult = decoderPlugin.decode({ text: text }); + const decodeResult = decoder.decode({ label: "83", text: text }); expect(decodeResult.decoded).toBe(false); expect(decodeResult.decoder.decodeLevel).toBe('none'); diff --git a/lib/plugins/Label_83.ts b/lib/plugins/Label_83.ts index 4687e13..804eea7 100644 --- a/lib/plugins/Label_83.ts +++ b/lib/plugins/Label_83.ts @@ -19,17 +19,10 @@ export class Label_83 extends DecoderPlugin { decodeResult.message = message; decodeResult.formatted.description = 'Airline Defined'; - // Inmarsat C-band seems to prefix normal messages with a message number and flight number - let text = message.text; - if (text.match(/^M\d{2}A\w{6}/)) { - ResultFormatter.flightNumber(decodeResult, message.text.substring(4, 10).replace(/^([A-Z]+)0*/g, "$1")); - text = text.substring(10); - } - decodeResult.decoded = true; - if (text.substring(0, 10) === "4DH3 ETAT2") { + if (message.text.substring(0, 10) === "4DH3 ETAT2") { // variant 2 - const fields = text.split(/\s+/); + const fields = message.text.split(/\s+/); if (fields[2].length > 5) { decodeResult.raw.day = fields[2].substring(5); } @@ -39,17 +32,17 @@ export class Label_83 extends DecoderPlugin { ResultFormatter.arrivalAirport(decodeResult, subfields[1]); ResultFormatter.tail(decodeResult, fields[4].replace(/\./g, "")); ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[6] + "00")); - } else if (text.substring(0, 5) === "001PR") { + } else if (message.text.substring(0, 5) === "001PR") { // variant 3 - decodeResult.raw.day = text.substring(5, 7); - const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(text.substring(13, 28).replace(/\./g, "")) + decodeResult.raw.day = message.text.substring(5, 7); + const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(message.text.substring(13, 28).replace(/\./g, "")) if (position) { ResultFormatter.position(decodeResult, position); } - ResultFormatter.altitude(decodeResult, Number(text.substring(28, 33))); - ResultFormatter.unknown(decodeResult, text.substring(33)); + ResultFormatter.altitude(decodeResult, Number(message.text.substring(28, 33))); + decodeResult.remaining.text = message.text.substring(33); } else { - const fields = text.replace(/\s/g, "").split(','); + const fields = message.text.replace(/\s/g, "").split(','); if (fields.length === 9) { // variant 1 ResultFormatter.departureAirport(decodeResult, fields[0]);