diff --git a/lib/MessageDecoder.ts b/lib/MessageDecoder.ts index b40f43a..2815911 100644 --- a/lib/MessageDecoder.ts +++ b/lib/MessageDecoder.ts @@ -78,6 +78,7 @@ const pluginClasses = [ Plugins.Label_QQ, Plugins.Label_QR, Plugins.Label_QS, + Plugins.Label_5U_WXR, ]; export class MessageDecoder { diff --git a/lib/plugins/Label_5U_WXR.ts b/lib/plugins/Label_5U_WXR.ts new file mode 100644 index 0000000..9955083 --- /dev/null +++ b/lib/plugins/Label_5U_WXR.ts @@ -0,0 +1,134 @@ +import { DecoderPlugin } from '../DecoderPlugin'; +import { DecodeResult, Message, Options } from '../DecoderPluginInterface'; +import { ResultFormatter } from '../utils/result_formatter'; + +/** + * Label 5U — Autonomous Weather Information Request (WXRQ) + * + * Downlink sent by the aircraft (typically shortly after takeoff or prior + * to arrival) requesting weather data (e.g. METAR) for a destination or + * alternate airport. + * + * Wire format (only the first three documented fields are decoded here): + * + * OS KHRL /WXRKHRL , + * | | | | + * | | | └── Trailing list delimiter (ignored — may precede + * | | | additional comma-separated entries, e.g. alternates) + * | | └─────────── Weather request: `/WXR` + target ICAO (e.g. /WXRKHRL) + * | └──────────────── Destination airport ICAO (4 chars) + * └─────────────────── Message subtype / system identifier + * (undocumented — exposed raw, per analyst guidance) + * + * Observed example: `OS KHRL/WXRKHRL,` + */ +export class Label_5U_WXR extends DecoderPlugin { + name = 'label-5u-wxr'; + + qualifiers() { + return { + labels: ['5U'], + }; + } + + decode(message: Message, options: Options = {}): DecodeResult { + const decodeResult = this.initResult( + message, + 'Autonomous Weather Information Request (WXRQ)', + ); + + const text = (message.text || '').trim(); + if (!text) { + this.setDecodeLevel(decodeResult, false); + return decodeResult; + } + + // ── Form B: Air France / Airbus-style slash-delimited ICAO list ── + // //[/…] + // Example: `3LFRB/EINN/BIKF` + const formB = text.match( + /^(?\d+)(?[A-Z]{4}(?:\/[A-Z]{4})+)\s*$/, + ); + if (formB?.groups) { + const count = formB.groups.count; + const icaos = formB.groups.icaos.split('/'); + const [dep, dest, ...alternates] = icaos; + + decodeResult.raw.count = count; + decodeResult.raw.icaos = icaos; + ResultFormatter.departureAirport(decodeResult, dep); + if (dest) ResultFormatter.arrivalAirport(decodeResult, dest); + + decodeResult.formatted.items.unshift( + { + type: 'message_type', + code: 'MSGTYP', + label: 'Message Type', + value: 'Weather Information Request (WXRQ)', + }, + { + type: 'count', + code: 'COUNT', + label: 'Sequence / Count', + value: count, + }, + ); + alternates.forEach((alt, i) => { + decodeResult.formatted.items.push({ + type: 'alternate', + code: `ALT${i + 1}`, + label: i === 0 ? 'Alternate' : `Alternate ${i + 1}`, + value: alt, + }); + }); + decodeResult.formatted.items.push({ + type: 'wxr_request', + code: 'WXRREQ', + label: 'Weather Requested For', + value: icaos.join(', '), + }); + + this.setDecodeLevel(decodeResult, true, 'full'); + return decodeResult; + } + + // ── Form A: ` /WXR` (e.g. `OS KHRL/WXRKHRL,`) ── + const regex = + /^(?[A-Z]{1,4})\s+(?[A-Z]{3,4})\/WXR(?[A-Z]{3,4})/; + const m = text.match(regex); + if (!m?.groups) { + this.setDecodeLevel(decodeResult, false); + return decodeResult; + } + + const { subtype, dest, wxrIcao } = m.groups; + + decodeResult.raw.subtype = subtype; + ResultFormatter.arrivalAirport(decodeResult, dest); + decodeResult.raw.wxr_request_icao = wxrIcao; + + decodeResult.formatted.items.unshift( + { + type: 'message_type', + code: 'MSGTYP', + label: 'Message Type', + value: 'Weather Information Request (WXRQ)', + }, + { + type: 'subtype', + code: 'SUBTYPE', + label: 'Subtype', + value: subtype, + }, + ); + decodeResult.formatted.items.push({ + type: 'wxr_request', + code: 'WXRREQ', + label: 'Weather Request', + value: `WXR for ${wxrIcao}`, + }); + + this.setDecodeLevel(decodeResult, true, 'full'); + return decodeResult; + } +} diff --git a/lib/plugins/official.ts b/lib/plugins/official.ts index 0d3d6fa..9474ef7 100644 --- a/lib/plugins/official.ts +++ b/lib/plugins/official.ts @@ -64,3 +64,4 @@ export * from './Label_QR'; export * from './Label_QP'; export * from './Label_QS'; export * from './Label_QQ'; +export * from './Label_5U_WXR';