Skip to content

Conversation

@makrsmark
Copy link
Collaborator

@makrsmark makrsmark commented Dec 22, 2025

Summary by CodeRabbit

  • New Features
    • Added support for decoding H2-02E weather reports with wind data parsing, including wind direction, speed, temperature readings, and location details.

✏️ Tip: You can customize this high-level summary in your review settings.

@jazzberry-ai
Copy link

jazzberry-ai bot commented Dec 22, 2025

Bug Report

Name Severity Example test case Description
Waypoint name/coordinate overlap in Label_H1_02E20.ts Medium const text = "02E20ABCDEFGHIJKLMN40000E01000012343500M123123000G Q"; In the parseWeatherReport function of Label_H1_02E20.ts, the waypoint name is extracted using text.substring(0,12), while the coordinate string is extracted using text.substring(0,13). This overlap causes the waypoint name to be truncated and the coordinates to be parsed incorrectly. The coordinate parsing should start after the waypoint name.

Comments? Email us.

@coderabbitai
Copy link

coderabbitai bot commented Dec 22, 2025

Warning

Rate limit exceeded

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

⌛ 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.

📥 Commits

Reviewing files that changed from the base of the PR and between 735359f and 68250e9.

📒 Files selected for processing (1)
  • lib/plugins/Label_H2_02E.ts

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Add a new H2-02E weather report decoder plugin (Label_H2_02E) that parses fixed-width weather formats containing wind, temperature, and flight-level data. Introduce a Wind type interface, refactor wind data collection in h1_helper.ts, and add windData() formatting method to ResultFormatter.

Changes

Cohort / File(s) Summary
Plugin Framework Registration
lib/MessageDecoder.ts, lib/plugins/official.ts
Register new Label_H2_02E plugin in MessageDecoder constructor and export from official plugins module.
Wind Data Type Definition
lib/types/wind.ts
New Wind interface with waypoint (object), flightLevel, windDirection, windSpeed, and optional temperature properties.
Wind Data Utilities
lib/utils/h1_helper.ts
Refactor wind data collection to use local Wind[] array; consolidate wind entries via single ResultFormatter.windData() call instead of per-loop pushes; change waypoint representation from string to object.
Wind Formatting
lib/utils/result_formatter.ts
Add static windData() method to assign wind data to DecodeResult and build formatted text descriptions including temperature details.
H2-02E Decoder Plugin
lib/plugins/Label\_H2\_02E.ts
New decoder plugin that validates H2-02E messages (trailing "Q"), parses fixed-width 32-character weather reports (coordinates, time, flight level, temperature, wind), and returns Wind objects with optional temperature.
Decoder Plugin Tests
lib/plugins/Label\_H2\_02E.test.ts
Comprehensive test suite covering plugin metadata, three valid decode scenarios (discord and website examples), and invalid message handling; validates wind_data array, coordinates, altitude, wind, and temperature fields.

Sequence Diagram

sequenceDiagram
    participant Msg as Message
    participant Plugin as Label_H2_02E<br/>(Decoder Plugin)
    participant Parser as parseWeatherReport()
    participant Utils as DateTimeUtils<br/>CoordinateUtils
    participant Formatter as ResultFormatter
    participant Result as DecodeResult

    Msg->>Plugin: decode(message)
    
    Note over Plugin: Validate message<br/>termination with "Q"
    
    Plugin->>Plugin: Parse header<br/>Extract Q-prefixed segments
    
    loop For each weather segment
        Plugin->>Parser: parseWeatherReport(text)
        Parser->>Utils: Extract coordinates<br/>time, altitude
        Utils-->>Parser: Parsed values
        Parser->>Utils: Decode wind direction<br/>speed, temperature
        Utils-->>Parser: Wind values
        Parser-->>Plugin: Wind object
        Plugin->>Plugin: Collect into windData[]
    end
    
    Plugin->>Formatter: windData(decodeResult, windData[])
    Formatter->>Result: Assign raw.wind_data
    Formatter->>Result: Build & append<br/>formatted items
    Formatter-->>Plugin: Updated DecodeResult
    
    Plugin-->>Msg: Return DecodeResult<br/>(decoded, full/partial level)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • initial H1 PWI decoding #138: Modifies wind-data handling in lib/utils/h1_helper.ts with structured Wind representation and Result formatting integration—directly overlaps with wind data refactoring.
  • Adding Label 16 Decoders #232: Adds new decoder plugin and updates MessageDecoder/lib/plugins/official.ts exports—follows same plugin registration pattern.
  • Adding label 2P decoding #225: Adds decoder plugin with MessageDecoder registration and official.ts export changes—parallel plugin-framework modifications.

Suggested reviewers

  • kevinelliott
  • fredclausen

Poem

🐰 Wind whispers from the weather report so clear,
H2-02E brings coordinates near,
Fixed-width numbers parsed with care and grace,
Temperature and altitude find their place!

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title states 'Adding Label H2 header 02E parser' but the objectives indicate this is for 'Label H1 header 02E parser' (from PR #294 title). The code changes reference Label_H2_02E plugin and H2 labels, but the PR objectives mention Label H1. This creates a discrepancy between the PR title and stated objectives. Clarify whether this PR is for Label H1 or H2. Update the title to match the actual implementation (Label_H2_02E plugin with H2 labels) and verify it aligns with PR #294 objectives.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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.

@@ -0,0 +1,12 @@
import { Waypoint } from "./waypoint";

export interface Wind {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'm tempted to make this Weather and have an altitude with units (flight level or feet)

Copy link
Contributor

Choose a reason for hiding this comment

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

This makes me think further about us needing to find a standard unit (with conversion capability) in everything we do!

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds support for parsing Label H1 header 02E20 messages, which are weather reports containing wind and temperature data at various waypoints along a flight route.

Key Changes:

  • Introduces a new Wind type interface to standardize wind data representation
  • Creates a new Label_H1_02E20 decoder plugin to parse 02E20 weather report messages
  • Refactors wind data formatting into a centralized ResultFormatter.windData() method

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
lib/types/wind.ts Defines new Wind interface for structured wind data representation
lib/plugins/Label_H1_02E20.ts Implements decoder for 02E20 weather report messages
lib/plugins/Label_H1_02E20.test.ts Adds comprehensive test coverage for the new decoder
lib/utils/result_formatter.ts Adds centralized windData() method for formatting wind information
lib/utils/h1_helper.ts Refactored to use new Wind type and centralized formatting
lib/plugins/official.ts Exports new Label_H1_02E20 plugin
lib/MessageDecoder.ts Registers the new Label_H1_02E20 plugin

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

let text = `${RouteUtils.waypointToString(wind.waypoint)} at FL${wind.flightLevel}: ${wind.windDirection}° at ${wind.windSpeed}kt`;
if (wind.temperature) {
text += `, ${wind.temperature.degreesC}°C at FL${wind.temperature.flightLevel}`;

Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

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

Empty line inside the if block is unnecessary and inconsistent with the rest of the codebase's style.

Suggested change

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@jazzberry-ai
Copy link

jazzberry-ai bot commented Dec 22, 2025

Bug Report

Name Severity Example test case Description
Off-by-one error in Label_H1_02E20.ts waypoint name parsing Low The parseWeatherReport function in Label_H1_02E20.ts extracts the waypoint name using text.substring(0,12), while the coordinate parsing uses text.substring(0,13). The waypoint name extraction in parseWeatherReport should use the same substring range as the coordinate parsing or be adjusted to exclude the coordinate prefix. The waypoint.name should be the origin and destination airports and not the lat/lon

Comments? Email us.

@jazzberry-ai
Copy link

jazzberry-ai bot commented Dec 22, 2025

Bug Report

Name Severity Example test case Description
Incorrect waypoint name in parseWeatherReport Low 02E20HEGNLKPRN40359E02208116253601M627259020G The parseWeatherReport function in lib/plugins/Label_H1_02E20.ts extracts the waypoint name using text.substring(0,12). The coordinate string is extracted using text.substring(0,13), so the waypoint name is incorrect.

Comments? Email us.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
lib/utils/result_formatter.ts (1)

396-411: Fix indentation inconsistencies in the method.

The method has inconsistent indentation that differs from the rest of the class. The opening static keyword has extra leading spaces, and the closing braces are misaligned.

🔎 Proposed fix for indentation
-        static windData(decodeResult: DecodeResult, windData: Wind[]) {
-        decodeResult.raw.wind_data = windData;
-        for(const wind of windData) {
-            let text = `${RouteUtils.waypointToString(wind.waypoint)} at FL${wind.flightLevel}: ${wind.windDirection}° at ${wind.windSpeed}kt`;
-            if (wind.temperature) {
-                text += `, ${wind.temperature.degreesC}°C at FL${wind.temperature.flightLevel}`;
-
-            }
-            decodeResult.formatted.items.push({
-                type: 'wind_data',
-                code: 'WIND',
-                label: 'Wind Data',
-                value: text,
-            });
-    }
-    }
+    static windData(decodeResult: DecodeResult, windData: Wind[]) {
+        decodeResult.raw.wind_data = windData;
+        for (const wind of windData) {
+            let text = `${RouteUtils.waypointToString(wind.waypoint)} at FL${wind.flightLevel}: ${wind.windDirection}° at ${wind.windSpeed}kt`;
+            if (wind.temperature) {
+                text += `, ${wind.temperature.degreesC}°C at FL${wind.temperature.flightLevel}`;
+            }
+            decodeResult.formatted.items.push({
+                type: 'wind_data',
+                code: 'WIND',
+                label: 'Wind Data',
+                value: text,
+            });
+        }
+    }

Also removes the unnecessary empty line at line 402 inside the if block.

lib/plugins/Label_H1_02E20.ts (1)

52-52: Add semicolon for consistency.

While JavaScript allows omitting semicolons, the project consistently uses them elsewhere.

🔎 Suggested fix
-        continue
+        continue;
🧹 Nitpick comments (3)
lib/types/wind.ts (1)

3-12: Well-structured interface definition.

The Wind interface correctly models the weather data with required and optional fields. Consider adding JSDoc comments to document the units (e.g., windSpeed in knots, windDirection in degrees, flightLevel in hundreds of feet) for clarity, similar to the documentation style in Waypoint interface.

lib/plugins/Label_H1_02E20.ts (2)

24-32: Consider filtering empty parts from split.

The split(' ') call will create empty strings when there are consecutive spaces in the message (which appears common in the test data). While the current code handles this, filtering empty parts would be more efficient and clearer.

🔎 Suggested refactor
-    const parts = message.text.split(' ');
+    const parts = message.text.split(' ').filter(p => p.length > 0);

82-82: Remove or document commented code.

The commented line about altitude calculation should either be removed if it's not needed, or uncommented with a clear explanation of why both altitude and flight level are tracked.

🔎 Suggested fix
-  // const altitude = parseInt(text.substring(17,21), 10) * 10; // use FL instead
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b47d71e and 0648bd2.

📒 Files selected for processing (7)
  • lib/MessageDecoder.ts
  • lib/plugins/Label_H1_02E20.test.ts
  • lib/plugins/Label_H1_02E20.ts
  • lib/plugins/official.ts
  • lib/types/wind.ts
  • lib/utils/h1_helper.ts
  • lib/utils/result_formatter.ts
🧰 Additional context used
🧬 Code graph analysis (4)
lib/utils/result_formatter.ts (3)
lib/DecoderPluginInterface.ts (1)
  • DecodeResult (20-42)
lib/types/wind.ts (1)
  • Wind (3-12)
lib/utils/route_utils.ts (1)
  • RouteUtils (6-86)
lib/types/wind.ts (1)
lib/types/waypoint.ts (1)
  • Waypoint (12-47)
lib/utils/h1_helper.ts (2)
lib/types/wind.ts (1)
  • Wind (3-12)
lib/utils/result_formatter.ts (1)
  • ResultFormatter (12-424)
lib/plugins/Label_H1_02E20.ts (5)
lib/DecoderPluginInterface.ts (3)
  • Message (4-8)
  • Options (13-15)
  • DecodeResult (20-42)
lib/utils/result_formatter.ts (3)
  • windData (396-411)
  • ResultFormatter (12-424)
  • text (386-394)
lib/types/wind.ts (1)
  • Wind (3-12)
lib/utils/coordinate_utils.ts (1)
  • CoordinateUtils (1-76)
lib/DateTimeUtils.ts (1)
  • DateTimeUtils (1-75)
🔇 Additional comments (8)
lib/plugins/official.ts (1)

50-50: LGTM!

The new plugin export follows the existing pattern and maintains alphabetical ordering among the H1 plugins.

lib/MessageDecoder.ts (1)

59-59: LGTM!

The plugin is correctly registered before the generic Label_H1 plugin, ensuring the more specific H1-02E20 decoder is matched first when applicable.

lib/utils/h1_helper.ts (1)

303-341: Good refactor to centralized wind data handling.

The refactor from incremental mutations to batch collection with a final ResultFormatter.windData() call improves code clarity and maintainability. The waypoint object construction correctly satisfies the Waypoint interface requirements, and the temperature parsing with 'M' for negative values is handled correctly.

Minor: Consider removing the unnecessary empty lines at lines 305, 330, and 340 for consistency with the surrounding code style.

lib/plugins/Label_H1_02E20.test.ts (1)

1-159: Excellent test coverage!

The test suite is comprehensive and well-structured. It covers:

  • Plugin metadata validation (name, qualifiers)
  • Multiple valid input scenarios with varying data
  • Invalid input handling
  • Both raw data parsing and formatted output validation
lib/plugins/Label_H1_02E20.ts (4)

1-16: LGTM!

The plugin structure and qualifiers are correctly defined.


34-46: LGTM!

The header parsing logic correctly extracts the airport codes and first wind report, with proper error handling for invalid data.


64-67: LGTM!

The result formatting and decode level logic correctly reflect whether the entire message was parsed.


70-108: Solid parsing logic with clear field extraction.

The method correctly parses the fixed-width wind report format with appropriate validation (length check, 'G' marker). The coordinate, time, flight level, temperature, and wind data extraction all follow the expected format.

@jazzberry-ai
Copy link

jazzberry-ai bot commented Dec 22, 2025

Bug Report

| Name | Severity | Example test case | Description |\n|---|---|---|---|\n| DoS in Label_H1_02E20 | Medium | Craft an ACARS message with Label H1 and preamble 02E20. Include a weather report string like "02E20HEGNLKPRN40XXXE02208116253601M627259020G Q". | The parseWeatherReport function attempts to parse invalid coordinates, leading to wasted processing time and potential denial of service. |\n

Comments? Email us.

@jazzberry-ai
Copy link

jazzberry-ai bot commented Dec 23, 2025

An error occured.

This error may be due to rate limits. If this error persists, please email us.

@jazzberry-ai
Copy link

jazzberry-ai bot commented Dec 23, 2025

An error occured.

This error may be due to rate limits. If this error persists, please email us.

@makrsmark makrsmark changed the title Adding Label H1 header 02E20 parser Adding Label H1 header 02E parser Dec 23, 2025
@jazzberry-ai
Copy link

jazzberry-ai bot commented Dec 23, 2025

An error occured.

This error may be due to rate limits. If this error persists, please email us.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (7)
lib/plugins/Label_H1_02E.test.ts (2)

38-69: Consider adding raw Wind object structure validation.

While the test thoroughly validates the formatted output strings, it only checks weather.length but doesn't validate the structure of the underlying Wind objects (e.g., waypoint.latitude, windSpeed, temperature.degreesC). Consider adding assertions to verify the raw data structure matches expected values.

Example: Add raw data validation
 expect(weather.length).toBe(6);
+// Validate first wind entry raw structure
+expect(weather[0].waypoint.latitude).toBeCloseTo(40.598, 3);
+expect(weather[0].waypoint.longitude).toBeCloseTo(22.135, 3);
+expect(weather[0].flightLevel).toBe(360);
+expect(weather[0].windDirection).toBe(259);
+expect(weather[0].windSpeed).toBe(20);
+expect(weather[0].temperature?.degreesC).toBeCloseTo(-62.7, 1);

155-164: Consider adding more edge case tests.

The invalid message test is good, but consider adding tests for additional edge cases:

  • A valid message with no wind data entries (just header + 'Q')
  • A message with a malformed header but valid trailing 'Q'
  • A message with some valid and some invalid wind entries (to test partial decoding)
  • Boundary cases for coordinates, temperatures, flight levels
lib/plugins/Label_H1_02E.ts (5)

42-47: Consider extracting duplicate remaining text logic.

Lines 46, 52, and 59 contain duplicate logic for appending to decodeResult.remaining.text. This pattern could be extracted into a helper method to improve maintainability.

Example helper method
+private appendToRemaining(decodeResult: DecodeResult, text: string): void {
+  decodeResult.remaining.text += (decodeResult.remaining.text ? ' ' : '') + text;
+}

 const firstWind = this.parseWeatherReport(header.substring(13));
 if(firstWind) {
   windData.push(firstWind);
 } else {
-  decodeResult.remaining.text += (decodeResult.remaining.text ? ' ' : '') + header.substring(13);
+  this.appendToRemaining(decodeResult, header.substring(13));
 }

Also applies to: 49-61


63-64: Remove extra blank lines.

Lines 63-64 contain unnecessary blank lines that should be removed for consistency with the codebase style.

Proposed fix
     }
   }
-
-
-
   ResultFormatter.windData(decodeResult, windData);

71-71: Fix inconsistent spacing.

Line 71 has inconsistent spacing before private. Remove the leading space for consistency.

Proposed fix
- private parseWeatherReport(text: string): Wind | null {
+private parseWeatherReport(text: string): Wind | null {

79-79: Remove commented-out code.

Line 79 contains commented-out altitude calculation code. If this code is no longer needed, remove it. If it's useful for reference, consider moving it to documentation or commit history.

Proposed fix
 const flightLevel = parseInt(text.substring(17,20), 10);
-// const altitude = parseInt(text.substring(17,21), 10) * 10; // use FL instead
 const tempSign = text[21] === 'M' ? -1 : 1;

85-87: Improve validation comment clarity.

The comment // G? on line 85 is not very informative. Consider clarifying what the 'G' character represents in the protocol.

Proposed improvement
-// G?
+// Verify trailing 'G' flag (protocol terminator for wind entry)
 if(text[31] !== 'G') {
   return null;
 }
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0648bd2 and c66a6a2.

📒 Files selected for processing (4)
  • lib/MessageDecoder.ts
  • lib/plugins/Label_H1_02E.test.ts
  • lib/plugins/Label_H1_02E.ts
  • lib/plugins/official.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/plugins/official.ts
  • lib/MessageDecoder.ts
🧰 Additional context used
🧬 Code graph analysis (2)
lib/plugins/Label_H1_02E.test.ts (3)
lib/plugins/Label_H1_02E.ts (1)
  • Label_H1_02E (8-106)
lib/MessageDecoder.ts (1)
  • MessageDecoder (6-176)
lib/utils/result_formatter.ts (1)
  • text (386-394)
lib/plugins/Label_H1_02E.ts (5)
lib/DecoderPluginInterface.ts (3)
  • Message (4-8)
  • Options (13-15)
  • DecodeResult (20-42)
lib/utils/result_formatter.ts (2)
  • windData (396-411)
  • text (386-394)
lib/types/wind.ts (1)
  • Wind (3-12)
lib/utils/coordinate_utils.ts (1)
  • CoordinateUtils (1-76)
lib/DateTimeUtils.ts (1)
  • DateTimeUtils (1-75)
🔇 Additional comments (5)
lib/plugins/Label_H1_02E.test.ts (3)

1-10: LGTM! Test setup is correct.

The test setup properly instantiates MessageDecoder and the plugin before each test.


11-19: LGTM! Metadata validation is thorough.

The test properly validates the plugin's name and qualifiers.


72-153: LGTM with same suggestion as example 1.

These test cases follow the same thorough pattern as example 1. The same suggestion about adding raw Wind object validation applies here as well.

lib/plugins/Label_H1_02E.ts (2)

1-16: LGTM! Class structure and qualifiers are correct.

The plugin properly extends DecoderPlugin and defines appropriate qualifiers for H1 label with 02E preamble.


107-107: No action needed—this export pattern is standard across the plugin codebase.

The export default {} pattern at line 107 is consistent with the established convention used across all plugin files in the lib/plugins/ directory (30+ files follow this exact pattern). This appears to be an intentional part of the plugin architecture rather than an unnecessary export.

Likely an incorrect or invalid review comment.

Comment on lines 37 to 41
const header = parts[0];
// header.substring(0,3) is '02E'
ResultFormatter.day(decodeResult, parseInt(header.substring(3,5)));
ResultFormatter.departureAirport(decodeResult, header.substring(5,9));
ResultFormatter.arrivalAirport(decodeResult, header.substring(9,13));
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add header length validation before substring operations.

The code performs substring operations on header without first validating its length. If the header is shorter than 13 characters (the minimum required), these operations could silently produce incorrect results or unexpected behavior.

Suggested fix
 const header = parts[0];
+if (header.length < 13) {
+  decodeResult.remaining.text = message.text;
+  decodeResult.decoded = false;
+  decodeResult.decoder.decodeLevel = 'none';
+  return decodeResult;
+}
 // header.substring(0,3) is '02E'
 ResultFormatter.day(decodeResult, parseInt(header.substring(3,5), 10));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const header = parts[0];
// header.substring(0,3) is '02E'
ResultFormatter.day(decodeResult, parseInt(header.substring(3,5)));
ResultFormatter.departureAirport(decodeResult, header.substring(5,9));
ResultFormatter.arrivalAirport(decodeResult, header.substring(9,13));
const header = parts[0];
if (header.length < 13) {
decodeResult.remaining.text = message.text;
decodeResult.decoded = false;
decodeResult.decoder.decodeLevel = 'none';
return decodeResult;
}
// header.substring(0,3) is '02E'
ResultFormatter.day(decodeResult, parseInt(header.substring(3,5), 10));
ResultFormatter.departureAirport(decodeResult, header.substring(5,9));
ResultFormatter.arrivalAirport(decodeResult, header.substring(9,13));
🤖 Prompt for AI Agents
In lib/plugins/Label_H1_02E.ts around lines 37 to 41, the code calls
substring(3,5), substring(5,9) and substring(9,13) on header without checking
its length; add a guard that verifies header.length >= 13 before performing
these substrings and handle the failure path (throw a descriptive Error or log
and return/skip processing) so you never call substring on a too-short string;
then only call ResultFormatter.day/departureAirport/arrivalAirport when the
header is valid.

@jazzberry-ai
Copy link

jazzberry-ai bot commented Dec 23, 2025

Bug Report

Name Severity Example test case Description
Potential NaN in Day of Month Medium Provide a message where the day of month part of the header contains non-numeric characters, such as '02EINVALID...'. The code parses the day of the month using parseInt(header.substring(3,5)). If the substring contains non-numeric characters, parseInt returns NaN. The code doesn't check for NaN before passing it to ResultFormatter.day, which could lead to unexpected behavior or errors. While ResultFormatter.day does convert the value to a string, it would be better to check for NaN before this point.
Missing Validation for Airport Codes Low Provide a message with invalid ICAO airport codes in the header, such as '02E20HELLWORLD...'. The code extracts departure and arrival airport codes from the header and passes them to ResultFormatter.departureAirport and ResultFormatter.arrivalAirport without any validation. If the header contains invalid characters in these positions, it could lead to incorrect or misleading information in the decoded output.
Potential NaN values from coordinate parsing Medium Pass coordinate string containing non-numeric characters, e.g., N12A45W123B56. The decodeStringCoordinatesDecimalMinutes function does not sanitize the coordinate string to check if the input contains characters other than digits (apart from the direction). If the coordinate string contains invalid characters, the Number() conversion will result in NaN. While initial direction is checked, NaN is not explicitly checked, which can propagate into latitude and longitude calculation. If NaN is obtained then a garbled position may be presented.

Comments? Email us.

@makrsmark makrsmark changed the title Adding Label H1 header 02E parser Adding Label H2 header 02E parser Dec 23, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
lib/plugins/Label_H2_02E.ts (2)

37-41: Add header length validation before substring operations.

The header length is not validated before performing substring operations. If header is shorter than 13 characters, these operations will produce incorrect or empty results.

This issue was raised in a previous review and remains unresolved.

Suggested fix
 const header = parts[0];
+if (header.length < 13) {
+  decodeResult.remaining.text = message.text;
+  decodeResult.decoded = false;
+  decodeResult.decoder.decodeLevel = 'none';
+  return decodeResult;
+}
 // header.substring(0,3) is '02E'

39-39: Specify radix in parseInt to avoid potential octal interpretation.

parseInt(header.substring(3,5)) lacks an explicit radix. For day values with leading zeros (e.g., "01", "09"), this could cause issues in older environments.

This issue was raised in a previous review and remains unresolved.

Suggested fix
-ResultFormatter.day(decodeResult, parseInt(header.substring(3,5)));
+ResultFormatter.day(decodeResult, parseInt(header.substring(3,5), 10));
🧹 Nitpick comments (2)
lib/plugins/Label_H2_02E.ts (2)

71-105: Fix inconsistent indentation in parseWeatherReport method.

The method body uses 2-space indentation while the class uses 2-space indentation, but the method content appears to use 1 or 2 spaces inconsistently relative to the method declaration.

Suggested fix
 private parseWeatherReport(text: string): Wind | null {
-  const posString = text.substring(0,13);
-  const pos = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(posString);
-  if (text.length !== 32 || !pos) {
-    return null;
-  }
+    const posString = text.substring(0,13);
+    const pos = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(posString);
+    if (text.length !== 32 || !pos) {
+      return null;
+    }
     // ... rest of method with consistent 4-space indentation

107-107: Remove or replace the empty default export.

export default {} exports an empty object, which provides no value. Consider either removing this line or exporting the plugin class as default if that's the intended pattern.

Suggested fix
-export default {};

Or if a default export is needed:

-export default {};
+export default Label_H2_02E;
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c66a6a2 and 735359f.

📒 Files selected for processing (4)
  • lib/MessageDecoder.ts
  • lib/plugins/Label_H2_02E.test.ts
  • lib/plugins/Label_H2_02E.ts
  • lib/plugins/official.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/plugins/official.ts
  • lib/MessageDecoder.ts
🧰 Additional context used
🧬 Code graph analysis (1)
lib/plugins/Label_H2_02E.test.ts (3)
lib/plugins/Label_H2_02E.ts (1)
  • Label_H2_02E (8-106)
lib/MessageDecoder.ts (1)
  • MessageDecoder (6-176)
lib/utils/result_formatter.ts (1)
  • text (386-394)
🔇 Additional comments (2)
lib/plugins/Label_H2_02E.test.ts (1)

1-165: Test coverage looks comprehensive.

The test suite provides good coverage with:

  • Plugin metadata validation (name, qualifiers)
  • Three positive decoding scenarios with different message formats
  • One invalid message case to verify error handling

Minor note: The describe block name "Label_H2 02E" uses a space while the class name uses an underscore (Label_H2_02E). This is cosmetic but worth keeping consistent.

lib/plugins/Label_H2_02E.ts (1)

77-77: The function convertHHMMSSToTod is explicitly designed to handle both 4-character (HHMM) and 6-character (HHMMSS) input formats. The implementation at lines 33-35 checks the input length and automatically appends '00' for seconds when a 4-character string is provided. The JSDoc comment at line 29 correctly documents this: @param time HHMMSS or HHMM. The code at line 77 is correct and requires no changes.

@jazzberry-ai
Copy link

jazzberry-ai bot commented Dec 23, 2025

Bug Report

Name Severity Example test case Description
Single-digit day of month not parsed correctly High H202E01EIDWKORD... The plugin Label_H2_02E fails to parse the day of month correctly when it is a single digit. The code assumes that the day is always represented by two digits. This has been fixed by adding a check and padding with a zero if needed.

Comments? Email us.

@jazzberry-ai
Copy link

jazzberry-ai bot commented Dec 23, 2025

Bug Report

Name Severity Example test case Description
Incorrect Header Length Validation Medium Message with a header length != 45 The code validates the header length with header.length === 45. This might be too strict. It should also validate the header prefix "02E" and ensure the existence of departure and arrival airports in the header string. If these checks are missing, it could lead to incorrect parsing or exceptions. The validation should be more flexible, focusing on required data rather than strict length.
Day of Month Parsing Low Message with an invalid day of month The code extracts the day of the month using parseInt(header.substring(3, 5), 10). If the input string doesn't represent a valid number (e.g., contains letters or is empty), parseInt will return NaN. The code doesn't explicitly check for NaN, which could lead to unexpected behavior later.

Comments? Email us.

Copy link
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.

LGTM. Let's merge away!

@@ -0,0 +1,12 @@
import { Waypoint } from "./waypoint";

export interface Wind {
Copy link
Contributor

Choose a reason for hiding this comment

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

This makes me think further about us needing to find a standard unit (with conversion capability) in everything we do!

@makrsmark makrsmark merged commit 56cebf0 into airframesio:master Dec 23, 2025
6 checks passed
@makrsmark makrsmark deleted the feature/label-h1-weather branch December 23, 2025 20:29
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