Skip to content

Add Label AA CPDLC (FANS 1/A Uplink) decoder plugin#411

Open
thepacket wants to merge 1 commit intoairframesio:masterfrom
thepacket:plugin/label-aa
Open

Add Label AA CPDLC (FANS 1/A Uplink) decoder plugin#411
thepacket wants to merge 1 commit intoairframesio:masterfrom
thepacket:plugin/label-aa

Conversation

@thepacket
Copy link
Copy Markdown

Adds a decoder for FANS 1/A CPDLC uplinks carried under label AA.

Handles both ARINC-622 envelope forms:

  • Double-dot qualifier: /USADCXA.AT1.JA788A222E042A4E61CF9D1A4D29A821D08932…
  • Single-dot IMI+sublabel: /FUKJJYA.CR1B-16332201EFEA8E94A95287147

Registration-pattern cascade handles all-hex tails (HL-prefix Korean, B-prefix Taiwan/China, dashed European/Asian, US N-numbers, Japanese JA).

npm run build passes.

New plugin registered in official.ts and MessageDecoder.ts.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 22, 2026

Warning

Rate limit exceeded

@thepacket has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 55 minutes and 25 seconds before requesting another review.

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 25 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: dd5cddab-59e5-4a9f-b18d-760727adb9fc

📥 Commits

Reviewing files that changed from the base of the PR and between 10f9f69 and 4138571.

📒 Files selected for processing (3)
  • lib/MessageDecoder.ts
  • lib/plugins/Label_AA_CPDLC.ts
  • lib/plugins/official.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@kevinelliott kevinelliott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Adds Label_AA_CPDLC for FANS-1/A CPDLC carried under label AA. Handles two ARINC-622 envelope shapes: double-dot service-qualifier (/USADCXA.AT1.JA788A…) and single-dot IMI+sublabel (/FUKJJYA.CR1B-16332…). Surfaces ground address, IMI/qualifier, sublabel, tail, hex payload, and 4-hex CRC; preserves payload as cpdlc_payload_hex for downstream ASN.1 PER decode. Registered in both lib/MessageDecoder.ts and lib/plugins/official.ts. Build passes per the description.

Verdict

Needs changes before merge. The two-form envelope detection and tail-cascade approach are nicely thought out, but the lack of tests is a blocker, and a couple of edge cases need attention before this can ship alongside Label_B6_Forwardslash.

Must Fix

  • No tests. This plugin is the most algorithmically interesting of the five — please add Label_AA_CPDLC.test.ts with at least: (a) a Form 1 message with a clean US/Japan/Korea registration, (b) a Form 2 CR response, (c) a Form 1 message with an all-hex-looking tail (the case the cascade was designed to handle), and (d) malformed inputs. Use lib/plugins/Label_15.test.ts as a template.
  • HL/B-prefix tails missing the dash variant. The cascade at lines 115-121 has ^(HL\d{4}) for Korea but Korean civil tails are HL\d{4} without a dash, while ^([A-Z]-\d{4,5}) covers Chinese B-NNNN and Taiwanese B-NNNNN. What's missing: the unhyphenated Chinese registration form B\d{4,5} that some FANS 1/A messages emit. Add a probe for that, or document that the unhyphenated Chinese case is intentionally left to the fallback.
  • Form 2 single-dot regex over-matches Form 1. The regex at line 78-79 (/^\/(?<ground>[A-Z0-9]{5,9})\.(?<imi>[A-Z]{2})(?<sublabel>[A-Z0-9])(?<rest>.+)$/) would match /USADCXA.AT1.JA788A… (ground=USADCXA, imi=AT, sublabel=1, rest=.JA788A…) if it ran first — but you correctly try doubleDot first. Please add a comment noting the order matters and consider an explicit guard to make the intent obvious to future readers (e.g. require Form 2's third position to not be .).

Should Fix

  • Mixing unshift and push for formatted.items. Lines 182-207 use unshift(...) for the message-type / direction / form / ground-address rows, then lines 168 (ResultFormatter.tail) and 212-256 use push. The result is that tail (pushed at line 168, before the unshift block) ends up after the unshifted block. The visual order in formatted output will be: MSGTYP, DIR, FORM, GNDADDR, TAIL, IMI, SUBLBL, PAYLOAD, CRC, NOTE. That's coherent but accidental — please switch to all-push and reorder explicitly so the order is intentional and easy to audit.
  • payload truncation in display. Line 230-232 — when payload > 96 chars, display is <first 48>…<last 48>. This is fine for human readability, but the truncated value still shows the literal Unicode ellipsis () without a clear "truncated" indicator. Suggest ${payload.substring(0, 48)}…[${payload.length - 96} more]…${payload.substring(payload.length - 48)} so consumers know how much was elided.
  • raw.air_data is non-standard and overlaps with Label_A6_ADS. PR #409 introduces the same key. If both plugins are going to land, the key should be promoted to RawFields in lib/DecoderPluginInterface.ts or renamed (unparsed_body?) for clarity.
  • raw.cpdlc_payload_bytes. Derived from cpdlc_payload_hex.length / 2 — fine, but redundant with the raw hex itself. Either drop it or also expose it for B0/A6 payloads to keep the FANS 1/A trio consistent.
  • direction is set in raw but the key isn't on the canonical RawFields interface. Same comment as #409.

Nits

  • imiDescriptions is only populated for AT1/ATN/CR. Consider extending with AT2/AT3 or noting that those exist (FANS 1/A has more than three IMIs).
  • formatted.items row "Note" with "Payload is ASN.1 PER binary…" is consumer-facing UI text. It might be more idiomatic to expose this as part of the description or a single field rather than a distinct row.
  • The formNote value 'Form 1 (qualifier.tail)' — the description says "qualifier.tail" but Form 1 actually has qualifier dot tail, where the qualifier and tail are separated by a dot. Suggest 'Form 1 (service-qualifier + tail)' or just 'Form 1' with the descriptor doing the explaining.

Tests

Missing entirely. Beyond the four scenarios listed under Must Fix, please add: empty body, body without leading /, double-dot envelope where the rest is too short to extract a payload + CRC.

Notes

  • Registration: confirmed in both lib/MessageDecoder.ts (line 81) and lib/plugins/official.ts (line 67) at the PR HEAD.
  • FANS 1/A consistency: this plugin and PRs #409 and #412 all duplicate the "extract tail from a hex stream" logic (with subtly different cascades and fallbacks) and all introduce overlapping non-standard raw keys (crc, crc_hex, air_data, cpdlc_payload_hex, ads_payload_hex). Strongly suggest landing a small shared helper (e.g. lib/utils/arinc622.ts) before merging the three so the FANS family stays coherent. The existing lib/plugins/Label_B6.ts is a placeholder and could be the home for the shared logic, or a new utils file.

Thanks @thepacket!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants