Also parse the extras from the comment field
This commit is contained in:
97
test/frame.extras.test.ts
Normal file
97
test/frame.extras.test.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import type { Dissected, Field, Segment } from "@hamradio/packet";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { Frame } from "../src/frame";
|
||||
import type { PositionPayload } from "../src/frame.types";
|
||||
|
||||
describe("APRS extras test vectors (RNG / PHG / CSE/DDD / SPD / DFS)", () => {
|
||||
it("parses PHG from position with messaging (spec vector 1)", () => {
|
||||
const raw = "NOCALL>APZRAZ,qAS,PA2RDK-14:=5154.19N/00627.77E>PHG500073 de NOCALL";
|
||||
const frame = Frame.fromString(raw);
|
||||
const res = frame.decode(true) as { payload: PositionPayload | null; structure: Dissected };
|
||||
const { payload } = res;
|
||||
|
||||
expect(payload).not.toBeNull();
|
||||
expect(payload!.position.phg).toBeDefined();
|
||||
// PHG500073 parsed per spec: p=5 -> 25 W, h='0' -> 10 ft, g='0' -> 0 dBi
|
||||
expect(payload!.position.phg!.power).toBe(25);
|
||||
expect(payload!.position.phg!.height).toBeCloseTo(3.048, 3);
|
||||
expect(payload!.position.phg!.gain).toBe(0);
|
||||
});
|
||||
|
||||
it("parses PHG token with hyphen separators (spec vector 2)", () => {
|
||||
const raw = "NOCALL>APRS,TCPIP*,qAC,NINTH:;P-PA3RD *061000z5156.26NP00603.29E#PHG0210DAPNET";
|
||||
const frame = Frame.fromString(raw);
|
||||
const res = frame.decode(true) as { payload: PositionPayload | null; structure: Dissected };
|
||||
const { payload, structure } = res;
|
||||
|
||||
expect(payload).not.toBeNull();
|
||||
// Use a spec PHG example: PHG0210 -> p=0 -> power 0 W, h=2 -> 40 ft
|
||||
expect(payload!.position.phg).toBeDefined();
|
||||
expect(payload!.position.phg!.power).toBe(0);
|
||||
expect(payload!.position.phg!.height).toBeCloseTo(12.192, 3);
|
||||
|
||||
const commentSeg = structure.find((s) => /comment/i.test(String(s.name))) as Segment | undefined;
|
||||
expect(commentSeg).toBeDefined();
|
||||
const fields = (commentSeg!.fields ?? []) as Field[];
|
||||
const hasPHG = fields.some((f) => f.name === "PHG");
|
||||
expect(hasPHG).toBe(true);
|
||||
});
|
||||
|
||||
it("parses DFS token with long numeric strength", () => {
|
||||
const raw = "N0CALL>APRS,WIDE1-1:!4500.00N/07000.00W#DFS2360/Your Comment";
|
||||
const frame = Frame.fromString(raw);
|
||||
const res = frame.decode(true) as { payload: PositionPayload | null; structure: Dissected };
|
||||
const { payload, structure } = res;
|
||||
|
||||
expect(payload).not.toBeNull();
|
||||
expect(payload!.position.dfs).toBeDefined();
|
||||
// DFSshgd: strength is single-digit s value (here '2')
|
||||
expect(payload!.position.dfs!.strength).toBe(2);
|
||||
|
||||
const commentSeg = structure.find((s) => /comment/i.test(String(s.name))) as Segment | undefined;
|
||||
expect(commentSeg).toBeDefined();
|
||||
const fieldsDFS = (commentSeg!.fields ?? []) as Field[];
|
||||
const hasDFS = fieldsDFS.some((f) => f.name === "DFS");
|
||||
expect(hasDFS).toBe(true);
|
||||
});
|
||||
|
||||
it("parses course/speed in DDD/SSS form and altitude /A=", () => {
|
||||
const raw = "N0CALL>APRS,WIDE1-1:!4500.00N/07000.00W>090/045/A=001234";
|
||||
const frame = Frame.fromString(raw);
|
||||
const res = frame.decode(true) as { payload: PositionPayload | null; structure: Dissected };
|
||||
const { payload, structure } = res;
|
||||
|
||||
expect(payload).not.toBeNull();
|
||||
expect(payload!.position.course).toBe(90);
|
||||
// Speed is converted from knots to km/h
|
||||
expect(payload!.position.speed).toBeCloseTo(45 * 1.852, 3);
|
||||
// Altitude 001234 ft -> meters
|
||||
expect(Math.round((payload!.position.altitude || 0) / 0.3048)).toBe(1234);
|
||||
|
||||
const commentSeg = structure.find((s) => /comment/i.test(String(s.name))) as Segment | undefined;
|
||||
expect(commentSeg).toBeDefined();
|
||||
const fieldsCSE = (commentSeg!.fields ?? []) as Field[];
|
||||
const hasCSE = fieldsCSE.some((f) => f.name === "CSE/SPD");
|
||||
expect(hasCSE).toBe(true);
|
||||
});
|
||||
|
||||
it("parses combined tokens: DDD/SSS PHG and DFS", () => {
|
||||
const raw = "N0CALL>APRS,WIDE1-1:!4500.00N/07000.00W>090/045PHG5132/DFS2132";
|
||||
const frame = Frame.fromString(raw);
|
||||
const res = frame.decode(true) as { payload: PositionPayload | null; structure: Dissected };
|
||||
const { payload, structure } = res;
|
||||
|
||||
expect(payload).not.toBeNull();
|
||||
expect(payload!.position.course).toBe(90);
|
||||
expect(payload!.position.speed).toBeCloseTo(45 * 1.852, 3);
|
||||
expect(payload!.position.phg).toBeDefined();
|
||||
expect(payload!.position.dfs).toBeDefined();
|
||||
expect(payload!.position.dfs!.strength).toBe(2);
|
||||
|
||||
const commentSeg = structure.find((s) => /comment/i.test(String(s.name))) as Segment | undefined;
|
||||
expect(commentSeg).toBeDefined();
|
||||
const fieldsCombined = (commentSeg!.fields ?? []) as Field[];
|
||||
expect(fieldsCombined.some((f) => ["CSE/SPD", "PHG", "DFS"].includes(String(f.name)))).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user