Skip to content

Add Label B0 AFN (FANS 1/A Logon) decoder plugin#412

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

Add Label B0 AFN (FANS 1/A Logon) decoder plugin#412
thepacket wants to merge 1 commit intoairframesio:masterfrom
thepacket:plugin/label-b0

Conversation

@thepacket
Copy link
Copy Markdown

Adds a decoder for FANS 1/A AFN-Contact messages carried under label B0 (parallel to label A0, different operators / sub-networks).

Wire format

/SOUCAYA.AFN/FMHUAL984,.N78004,AA92FB,080809/FCPPIKCAYA,0F897

Surfaces ATSU, application, callsign, tail, ICAO 24-bit, UTC time, capability blocks (FCPP variant included in the descriptor alternation), and CRC.

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 23 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 23 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: f39d2a7e-0718-4e84-b2ec-f87bdd9937eb

📥 Commits

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

📒 Files selected for processing (3)
  • lib/MessageDecoder.ts
  • lib/plugins/Label_B0_AFN.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_B0_AFN for the FANS 1/A AFN-Contact (FN_CON / CPDLC logon request) message. Parses the /<ATSU>.AFN/FMH<callsign>,.<tail>,<icao24>,<HHMMSS>/<cap-block>... envelope and surfaces ATSU, callsign, tail, ICAO 24-bit address, UTC time, capability blocks, and trailing CRC. Registered in both lib/MessageDecoder.ts and lib/plugins/official.ts. Build passes per the description.

Verdict

Needs changes before merge. Solid envelope decomposition and capability-block parsing, but the formatted output has duplicated rows from antipatterns flagged in the project conventions, and there are no tests.

Must Fix

  • No tests. Please add Label_B0_AFN.test.ts covering: (a) the wire-format example from the PR description, (b) a header without ICAO24 or time (the regex's optional groups), (c) multiple capability blocks, (d) no capability blocks. Use lib/plugins/Label_15.test.ts as a template.
  • Duplicate Time row (project antipattern). Lines 108-112 call ResultFormatter.timestamp(...) which already pushes a {type:'time', code:'TIMESTAMP', label:'Message Timestamp'} item. Then lines 211-218 explicitly push another {type:'time', code:'TIME', label:'Logon Time (UTC)'} row using the same HHMMSS string. Two time rows for the same value. Pick one — either keep ResultFormatter.timestamp (preferred — uses canonical message_timestamp raw key and consistent formatting) and drop the explicit push, or drop the formatter call and only push the explicit row.
  • Duplicate Callsign row (project antipattern). Line 98 calls ResultFormatter.flightNumber(decodeResult, callsign) which adds a Flight Number item. Then lines 195-201 push a separate {code:'CALLSIGN', label:'Callsign'} row with the same value. Two rows, same string. Use ResultFormatter.callsign(...) (which exists at lib/utils/result_formatter.ts line 93-101) instead of flightNumber(...), and drop the manual push — or vice versa.
  • HHMMSS validation missing. Line 107: any 6-digit string passes through to DateTimeUtils.convertHHMMSSToTod. A malformed 999999 will produce a nonsensical time-of-day value silently. Validate hh<24, mm<60, ss<60 before calling the converter (see PR #413 line 71-74 for an example of the same check).

Should Fix

  • Header regex tail group is too permissive. Line 83: (?<tail>[A-Z0-9-]{3,10})?. With no anchor, this can absorb the next-field separator if a comma is missing. The wire format always uses ,. to delimit callsign and tail; consider requiring the leading . and matching [A-Z0-9-]{3,10} only after it, e.g. \.(?<tail>[A-Z0-9-]{3,10}). As written the optional-comma + optional-dot pattern (,?\.?) accepts inputs the spec wouldn't.
  • atsu_address raw key vs. existing ground_address. RawFields.ground_address already exists in the canonical interface (lib/DecoderPluginInterface.ts line 107). Using a new key atsu_address for the same concept fragments downstream consumers. Suggest using ground_address and adding a separate display label "ATSU Address" if you want the human-readable form to differ.
  • capability_blocks raw value is the structured array. That's fine for downstream code, but the formatted output flattens each block into a one-row string "/FCPP → token1, token2". Worth considering whether the block's individual flags (e.g. capability bits) could be parsed into named fields rather than left as opaque tokens — even partial enrichment would make this more useful.
  • Non-standard raw.icao_24bit. Other parts of the codebase don't have this key. Add to RawFields if it's going to land, or reuse a canonical alternative.
  • Direction is hardcoded. "Downlink (aircraft → ground)" — this is correct for an FN_CON, but if/when B0 ever carries a logon-acknowledge from the ground side, the hardcoding will be wrong. Comment or guard.

Nits

  • The descriptor says "AFN — ATS Facilities Notification (FANS 1/A CPDLC Logon)" but the formatted message-type row says "AFN Contact (FN_CON) — FANS 1/A CPDLC Logon Request" and the application row says "AFN (ATS Facilities Notification)". Three slightly different descriptions of the same thing in three places — consider unifying.
  • parsedCaps.forEach((cap, i) => { const idx = i + 1; … type: \capability_block_${idx}`, code: `CAP${idx}` … })— emitting per-block typed rows means downstream type matching becomes a moving target. Suggest a single row with all blocks, or a stable row type likecapability_block` and an index column inside the value.
  • "Application" row hardcodes "AFN (ATS Facilities Notification)" but the regex already requires .AFN/ literally — the row carries no information beyond what the descriptor already states. Consider dropping it.

Tests

Missing entirely. Suggested fixtures, beyond the four scenarios under Must Fix:

  • Header with , but no ..
  • Last capability block where the final token is exactly 4 hex chars (so flagPart is empty after CRC strip — the code currently leaves an empty string in the tokens array).
  • Last capability block where the final token is < 5 chars (the ^[A-F0-9]{5,}$ guard skips CRC stripping — verify behavior).

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 shares CRC-stripping and tail-detection patterns with PRs #409 and #411. Please coordinate raw-key naming (crc vs crc_hex, tail vs air_address, ground_address vs atsu_address) across the trio before merging — landing them with three different conventions for the same fields will be painful to undo. See review on PR #411 for the suggested shared-helper approach.

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