Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/MessageDecoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export class MessageDecoder {
this.registerPlugin(new Plugins.Label_13Through18_Slash(this));
this.registerPlugin(new Plugins.Label_15(this));
this.registerPlugin(new Plugins.Label_15_FST(this));
this.registerPlugin(new Plugins.Label_16_Honeywell(this));
this.registerPlugin(new Plugins.Label_16_N_Space(this));
this.registerPlugin(new Plugins.Label_16_POSA1(this));
this.registerPlugin(new Plugins.Label_16_TOD(this));
Expand Down
71 changes: 71 additions & 0 deletions lib/plugins/Label_16_Honeywell.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { MessageDecoder } from "../MessageDecoder";
import { Label_16_Honeywell } from "./Label_16_Honeywell";

describe("Label_16_Honeywell", () => {
let plugin: Label_16_Honeywell;

beforeEach(() => {
const decoder = new MessageDecoder();
plugin = new Label_16_Honeywell(decoder);
});

test("matches qualifiers", () => {
expect(plugin.decode).toBeDefined();
expect(plugin.name).toBe("label-16-honeywell");
expect(plugin.qualifiers).toBeDefined();
expect(plugin.qualifiers()).toEqual({
labels: ["16"],
preambles: ["(2"],
});
});

test("decodes variant 1", () => {
const text = "(2AAABN39211W 77144KTEBMMTO-/A(Z";
const decodeResult = plugin.decode({ text: text });

expect(decodeResult.decoded).toBe(true);
expect(decodeResult.decoder.decodeLevel).toBe("partial");
expect(decodeResult.raw.position.latitude).toBeCloseTo(39.352, 3);
expect(decodeResult.raw.position.longitude).toBeCloseTo(-77.24, 3);
expect(decodeResult.raw.departure_icao).toBe("KTEB");
expect(decodeResult.raw.arrival_icao).toBe("MMTO");
expect(decodeResult.formatted.items.length).toBe(3);
expect(decodeResult.remaining.text).toBe("AAAB/A");
});

test("decodes variant 2", () => {
const text = "(2AAAAN37265W 78334-SSI /O(Z";
const decodeResult = plugin.decode({ text: text });

expect(decodeResult.decoded).toBe(true);
expect(decodeResult.decoder.decodeLevel).toBe("partial");
expect(decodeResult.raw.position.latitude).toBeCloseTo(37.442, 3);
expect(decodeResult.raw.position.longitude).toBeCloseTo(-78.557, 3);
expect(decodeResult.raw.route.waypoints[0].name).toBe("SSI");
expect(decodeResult.formatted.items.length).toBe(2);
expect(decodeResult.remaining.text).toBe("AAAA/O");
});

test("decodes variant 3", () => {
const text = "(2AAABN37197W 78404-SLOJOGRONK/O(Z";
const decodeResult = plugin.decode({ text: text });

expect(decodeResult.decoded).toBe(true);
expect(decodeResult.decoder.decodeLevel).toBe("partial");
expect(decodeResult.raw.position.latitude).toBeCloseTo(37.328, 3);
expect(decodeResult.raw.position.longitude).toBeCloseTo(-78.673, 3);
expect(decodeResult.raw.route.waypoints[0].name).toBe("SLOJO");
expect(decodeResult.raw.route.waypoints[1].name).toBe("GRONK");
expect(decodeResult.formatted.items.length).toBe(2);
expect(decodeResult.remaining.text).toBe("AAAB/O");
});

test("does not decode <invalid>", () => {
const text = "(2 Bogus message";
const decodeResult = plugin.decode({ text: text });

expect(decodeResult.decoded).toBe(false);
expect(decodeResult.decoder.decodeLevel).toBe("none");
expect(decodeResult.message.text).toBe(text);
});
});
85 changes: 85 additions & 0 deletions lib/plugins/Label_16_Honeywell.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { DecoderPlugin } from "../DecoderPlugin";
import { DecodeResult, Message, Options } from "../DecoderPluginInterface";
import { CoordinateUtils } from "../utils/coordinate_utils";
import { ResultFormatter } from "../utils/result_formatter";

// Honeywell Label 16 Position Report
export class Label_16_Honeywell extends DecoderPlugin {
name = "label-16-honeywell";

qualifiers() {
// eslint-disable-line class-methods-use-this
return {
labels: ["16"],
preambles: ["(2"],
};
}

decode(message: Message, options: Options = {}): DecodeResult {
const decodeResult = this.defaultResult();
decodeResult.decoder.name = this.name;
decodeResult.formatted.description = "Position Report";
decodeResult.message = message;

if (message.text.startsWith("(2") && message.text.endsWith("(Z") && message.text.length >= 29) {
const between = message.text.substring(2, message.text.length - 2);
ResultFormatter.unknown(decodeResult, between.substring(0, 4), ""); // Session ID
ResultFormatter.position(
decodeResult,
CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
between.substring(4, 17),
),
);
if (between.charAt(17) === "-") {
// Waypoint mode
const waypoint1 = between.substring(18, 23).trim();
const waypoint2 = between.substring(23, 28).trim();
if (waypoint2) {
ResultFormatter.route(decodeResult, {
waypoints: [{ name: waypoint1 }, { name: waypoint2 }],
});
} else {
ResultFormatter.route(decodeResult, {
waypoints: [{ name: waypoint1 }],
});
}
} else {
// Route mode
ResultFormatter.departureAirport(
decodeResult,
between.substring(17, 21),
);
ResultFormatter.arrivalAirport(decodeResult, between.substring(21, 25));
//ignore the rest (should just be '-')
}
/*
const phases: { [key: string]: string } = {
'/O': 'En Route',
'/A': 'Arrival',
'/D': 'Departure',
'/P': 'Preflight',
'/C': 'Climb',
};
*/
ResultFormatter.unknown(
decodeResult,
between.substring(between.length - 2),
"",
);
} else {
if (options.debug) {
console.log(`Decoder: Unknown 16 Honeywell message: ${message.text}`);
}
ResultFormatter.unknown(decodeResult, message.text);
decodeResult.decoded = false;
decodeResult.decoder.decodeLevel = "none";
return decodeResult;
}

decodeResult.decoded = true;
decodeResult.decoder.decodeLevel = "partial";
return decodeResult;
}
}

export default {};
1 change: 1 addition & 0 deletions lib/plugins/official.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export * from './Label_12_POS';
export * from './Label_13Through18_Slash';
export * from './Label_15';
export * from './Label_15_FST';
export * from './Label_16_Honeywell';
export * from './Label_16_N_Space';
export * from './Label_16_POSA1';
export * from './Label_16_TOD';
Expand Down