Add Label 81 MVA (Aircraft Movement Message) decoder plugin#406
Add Label 81 MVA (Aircraft Movement Message) decoder plugin#406thepacket wants to merge 1 commit into
Conversation
New plugin registered in official.ts and MessageDecoder.ts.
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 55 minutes and 32 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
kevinelliott
left a comment
There was a problem hiding this comment.
Summary
Adds a Label_81_MVA plugin for APAC/Jetstar IATA AHM 780 MVA payloads. Handles arrival (AA), departure (AD), and a single SI FB supplementary line. Registered correctly.
Verdict
Changes requested — solid scaffolding, but there are duplicate formatted entries, missing tests, and a few correctness items.
Must Fix
- No tests. Please add coverage for: arrival example from the PR body, a departure (
AD0827/0837) variant, missingSIline, missing on-blocks (AA0945-only), and a malformed line-2 negative case. - Duplicate timestamp items. You call
ResultFormatter.timestamp(...)(which pushescode:'TIMESTAMP') and then push{type:'actual_touchdown', code:'AAT', ...}/code:'ADB'etc. with the same underlying value. Result: the same touchdown time appears twice informatted.items. Either drop the explicitAAT/ADB/...rows or drop thetimestamp()call. (See "common antipatterns" —timestamp()+ explicit{type:'time'}push.) ResultFormatter.timestamp()is conceptually wrong here. This isn't a "message timestamp", it's a touchdown / off-blocks event time. Prefer the dedicated helpers —ResultFormatter.on()for AA touchdown,ResultFormatter.in()for on-blocks,ResultFormatter.out()for off-blocks,ResultFormatter.off()for takeoff. That also fixes the duplicate-row problem and aligns withLabel_44_*.
Should Fix
- Airport code length not validated against type. Line-2 captures
airport: [A-Z]{3,4}. A 3-char value is IATA, a 4-char value is ICAO, butarrivalAirport(decodeResult, airport)/departureAirport(decodeResult, airport)default to ICAO — so a 3-char IATA gets stored inraw.arrival_icao/raw.departure_icao. Branch on length and pass'IATA'when it’s 3 chars. - HHMM range validation.
aaTouchdown.substring(0,2)produces e.g.99:99for invalid inputs. Validate hours< 24and minutes< 60before formatting/pushing. raw.actual_touchdown / actual_on_blocks / actual_off_blocks / actual_takeoffuse aHH:MMstring form while the project convention (perRawFields) uses seconds-since-midnight numeric (on_time,in_time,out_time,off_time). Switch to the dedicated formatters and you get this for free.SI FBvalue is currently emitted as a free-form string ("FB (Fuel on Board): 37") rather than viaResultFormatter.currentFuel(). Use the formatter so consumers can pick upraw.fuel_on_boardnumerically.raw.flight_numberset both manually (line 76) and viaResultFormatter.flightNumber(line 80). The formatter already setsraw.flight_number. Drop the manual assignment.
Nits
lines[2]/lines[3]index access is positional — ifSIarrives without the time line, theSIparsing won’t happen. Consider scanning the lines for anSIprefix instead.- Tail regex
[A-Z0-9-]{3,10}accepts a leading-like-VHOYR. Fine in practice, but a minor anchor ([A-Z0-9](?:[A-Z0-9-]{1,8}[A-Z0-9])?) would be safer. raw.airportis renamed at the formatted-row level to "Airport of Movement" — keep the raw key consistent with the formatted label (raw.airport_of_movementor surface asraw.arrival_icao/departure_icaoand rely on those).
Tests
Missing. See Must Fix.
Notes
- Registration LGTM. No collision risk — no other Label_81 plugin exists.
- CodeRabbit rate-limited; that comment can be ignored.
Thanks @thepacket!
There was a problem hiding this comment.
Pull request overview
Adds a new label 81 decoder for APAC/Jetstar MVA/MVT aircraft movement messages and registers it with the decoder/plugin export surface.
Changes:
- Introduces
Label_81_MVAto parse MVA/MVT message type, flight identity, movement times, airport, and SI supplementary data. - Registers and exports the new plugin through the existing decoder plugin architecture.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 9 comments.
| File | Description |
|---|---|
lib/plugins/Label_81_MVA.ts |
Adds the new label 81 MVA/MVT decoder implementation. |
lib/MessageDecoder.ts |
Registers the new plugin in the default decoder plugin list. |
lib/plugins/official.ts |
Re-exports the new plugin for public plugin access. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| decode(message: Message, options: Options = {}): DecodeResult { | ||
| const decodeResult = this.initResult( | ||
| message, | ||
| 'Aircraft-Initiated Movement Message (MVA)', |
| this.setDecodeLevel(decodeResult, false); | ||
| return decodeResult; |
| if (aaOnBlocks) { | ||
| decodeResult.raw.actual_on_blocks = `${aaOnBlocks.substring(0, 2)}:${aaOnBlocks.substring(2, 4)}`; | ||
| } | ||
| ResultFormatter.arrivalAirport(decodeResult, airport); |
| ResultFormatter.timestamp( | ||
| decodeResult, | ||
| DateTimeUtils.convertHHMMSSToTod(aaTouchdown + '00'), | ||
| ); |
| if (adTakeoff) { | ||
| decodeResult.raw.actual_takeoff = `${adTakeoff.substring(0, 2)}:${adTakeoff.substring(2, 4)}`; | ||
| } | ||
| ResultFormatter.departureAirport(decodeResult, airport); |
| decodeResult.raw.actual_off_blocks = `${adOffBlocks.substring(0, 2)}:${adOffBlocks.substring(2, 4)}`; | ||
| if (adTakeoff) { | ||
| decodeResult.raw.actual_takeoff = `${adTakeoff.substring(0, 2)}:${adTakeoff.substring(2, 4)}`; | ||
| } | ||
| ResultFormatter.departureAirport(decodeResult, airport); | ||
| ResultFormatter.timestamp( | ||
| decodeResult, | ||
| DateTimeUtils.convertHHMMSSToTod(adOffBlocks + '00'), |
| } | ||
| } |
| const siLabelMap: Record<string, string> = { | ||
| FB: 'Fuel on Board', | ||
| }; | ||
| const siLabel = siLabelMap[siTag] | ||
| ? `${siTag} (${siLabelMap[siTag]})` | ||
| : siTag; | ||
| decodeResult.formatted.items.push({ | ||
| type: 'supplementary', | ||
| code: 'SI', | ||
| label: 'Supplementary Info', | ||
| value: `${siLabel}: ${siValue}`, | ||
| }); |
| }; | ||
| } | ||
|
|
||
| decode(message: Message, options: Options = {}): DecodeResult { |
Adds a decoder for APAC/Jetstar label 81 carrying IATA AHM 780 MVA (Aircraft-Initiated Movement Message) payloads.
Wire format
Both
MVA(arrivalAA) andAD(departure) shapes handled. Supplementary infoSI FBsurfaced as Fuel on Board.npm run buildpasses.