Implemented Query, Telemetry, Weather and RawGPS parsing
This commit is contained in:
39
test/frame.query.test.ts
Normal file
39
test/frame.query.test.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { expect } from "vitest";
|
||||
import { describe, it } from "vitest";
|
||||
import { Dissected } from "@hamradio/packet";
|
||||
import { Frame } from "../src/frame";
|
||||
import { QueryPayload } from "../src/frame.types";
|
||||
|
||||
describe("Frame decode - Query", () => {
|
||||
it("decodes simple query without target", () => {
|
||||
const frame = Frame.fromString("SRC>DEST:?APRS");
|
||||
const payload = frame.decode() as QueryPayload;
|
||||
expect(payload).not.toBeNull();
|
||||
expect(payload.type).toBe("query");
|
||||
expect(payload.queryType).toBe("APRS");
|
||||
expect(payload.target).toBeUndefined();
|
||||
});
|
||||
|
||||
it("decodes query with target", () => {
|
||||
const frame = Frame.fromString("SRC>DEST:?PING N0CALL");
|
||||
const payload = frame.decode() as QueryPayload;
|
||||
expect(payload).not.toBeNull();
|
||||
expect(payload.type).toBe("query");
|
||||
expect(payload.queryType).toBe("PING");
|
||||
expect(payload.target).toBe("N0CALL");
|
||||
});
|
||||
|
||||
it("returns structure sections when requested", () => {
|
||||
const frame = Frame.fromString("SRC>DEST:?PING N0CALL");
|
||||
const result = frame.decode(true) as {
|
||||
payload: QueryPayload;
|
||||
structure: Dissected;
|
||||
};
|
||||
expect(result).toHaveProperty("payload");
|
||||
expect(result.payload.type).toBe("query");
|
||||
expect(Array.isArray(result.structure)).toBe(true);
|
||||
const names = result.structure.map((s) => s.name);
|
||||
expect(names).toContain("query type");
|
||||
expect(names).toContain("query target");
|
||||
});
|
||||
});
|
||||
48
test/frame.rawgps.test.ts
Normal file
48
test/frame.rawgps.test.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { Frame } from "../src/frame";
|
||||
import type { RawGPSPayload } from "../src/frame.types";
|
||||
import { Dissected } from "@hamradio/packet";
|
||||
|
||||
describe("Raw GPS decoding", () => {
|
||||
it("decodes simple NMEA sentence as raw-gps payload", () => {
|
||||
const sentence =
|
||||
"GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A";
|
||||
const frameStr = `SRC>DEST:$${sentence}`;
|
||||
|
||||
const f = Frame.parse(frameStr);
|
||||
const payload = f.decode(false) as RawGPSPayload | null;
|
||||
|
||||
expect(payload).not.toBeNull();
|
||||
expect(payload?.type).toBe("raw-gps");
|
||||
expect(payload?.sentence).toBe(sentence);
|
||||
expect(payload?.position).toBeDefined();
|
||||
expect(typeof payload?.position?.latitude).toBe("number");
|
||||
expect(typeof payload?.position?.longitude).toBe("number");
|
||||
});
|
||||
|
||||
it("returns structure when requested", () => {
|
||||
const sentence =
|
||||
"GPGGA,092750.000,5321.6802,N,00630.3372,W,1,08,1.0,73.0,M,0.0,M,,*6A";
|
||||
const frameStr = `SRC>DEST:$${sentence}`;
|
||||
|
||||
const f = Frame.parse(frameStr);
|
||||
const result = f.decode(true) as {
|
||||
payload: RawGPSPayload | null;
|
||||
structure: Dissected;
|
||||
};
|
||||
|
||||
expect(result.payload).not.toBeNull();
|
||||
expect(result.payload?.type).toBe("raw-gps");
|
||||
expect(result.payload?.sentence).toBe(sentence);
|
||||
expect(result.payload?.position).toBeDefined();
|
||||
expect(typeof result.payload?.position?.latitude).toBe("number");
|
||||
expect(typeof result.payload?.position?.longitude).toBe("number");
|
||||
expect(result.structure).toBeDefined();
|
||||
const rawSection = result.structure.find((s) => s.name === "raw-gps");
|
||||
expect(rawSection).toBeDefined();
|
||||
const posSection = result.structure.find(
|
||||
(s) => s.name === "raw-gps-position",
|
||||
);
|
||||
expect(posSection).toBeDefined();
|
||||
});
|
||||
});
|
||||
59
test/frame.telemetry.test.ts
Normal file
59
test/frame.telemetry.test.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { describe, it } from "vitest";
|
||||
import {
|
||||
TelemetryDataPayload,
|
||||
TelemetryParameterPayload,
|
||||
TelemetryUnitPayload,
|
||||
TelemetryCoefficientsPayload,
|
||||
TelemetryBitSensePayload,
|
||||
} from "../src/frame.types";
|
||||
import { Frame } from "../src/frame";
|
||||
import { expect } from "vitest";
|
||||
|
||||
describe("Frame decode - Telemetry", () => {
|
||||
it("decodes telemetry data payload", () => {
|
||||
const frame = Frame.fromString("SRC>DEST:T#1 10,20,30,40,50 7");
|
||||
const payload = frame.decode() as TelemetryDataPayload;
|
||||
expect(payload).not.toBeNull();
|
||||
expect(payload.type).toBe("telemetry-data");
|
||||
expect(payload.sequence).toBe(1);
|
||||
expect(Array.isArray(payload.analog)).toBe(true);
|
||||
expect(payload.analog.length).toBe(5);
|
||||
expect(payload.digital).toBe(7);
|
||||
});
|
||||
|
||||
it("decodes telemetry parameters list", () => {
|
||||
const frame = Frame.fromString("SRC>DEST:TPARAM Temp,Hum,Wind");
|
||||
const payload = frame.decode() as TelemetryParameterPayload;
|
||||
expect(payload).not.toBeNull();
|
||||
expect(payload.type).toBe("telemetry-parameters");
|
||||
expect(Array.isArray(payload.names)).toBe(true);
|
||||
expect(payload.names).toEqual(["Temp", "Hum", "Wind"]);
|
||||
});
|
||||
|
||||
it("decodes telemetry units list", () => {
|
||||
const frame = Frame.fromString("SRC>DEST:TUNIT C,% ,mph");
|
||||
const payload = frame.decode() as TelemetryUnitPayload;
|
||||
expect(payload).not.toBeNull();
|
||||
expect(payload.type).toBe("telemetry-units");
|
||||
expect(payload.units).toEqual(["C", "%", "mph"]);
|
||||
});
|
||||
|
||||
it("decodes telemetry coefficients", () => {
|
||||
const frame = Frame.fromString("SRC>DEST:TCOEFF A:1,2 B:3,4 C:5,6");
|
||||
const payload = frame.decode() as TelemetryCoefficientsPayload;
|
||||
expect(payload).not.toBeNull();
|
||||
expect(payload.type).toBe("telemetry-coefficients");
|
||||
expect(payload.coefficients.a).toEqual([1, 2]);
|
||||
expect(payload.coefficients.b).toEqual([3, 4]);
|
||||
expect(payload.coefficients.c).toEqual([5, 6]);
|
||||
});
|
||||
|
||||
it("decodes telemetry bitsense with project", () => {
|
||||
const frame = Frame.fromString("SRC>DEST:TBITS 255 ProjectX");
|
||||
const payload = frame.decode() as TelemetryBitSensePayload;
|
||||
expect(payload).not.toBeNull();
|
||||
expect(payload.type).toBe("telemetry-bitsense");
|
||||
expect(payload.sense).toBe(255);
|
||||
expect(payload.projectName).toBe("ProjectX");
|
||||
});
|
||||
});
|
||||
37
test/frame.weather.test.ts
Normal file
37
test/frame.weather.test.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { Frame } from "../src/frame";
|
||||
import { WeatherPayload } from "../src/frame.types";
|
||||
import { Dissected } from "@hamradio/packet";
|
||||
|
||||
describe("Frame decode - Weather", () => {
|
||||
it("parses weather with timestamp, wind, temp, rain, humidity and pressure", () => {
|
||||
const data = "SRC>DEST:_120345z180/10g15t072r000p025P050h50b10132";
|
||||
const frame = Frame.fromString(data);
|
||||
const payload = frame.decode() as WeatherPayload;
|
||||
expect(payload).not.toBeNull();
|
||||
expect(payload.type).toBe("weather");
|
||||
expect(payload.timestamp).toBeDefined();
|
||||
expect(payload.windDirection).toBe(180);
|
||||
expect(payload.windSpeed).toBe(10);
|
||||
expect(payload.windGust).toBe(15);
|
||||
expect(payload.temperature).toBe(72);
|
||||
expect(payload.rainLast24Hours).toBe(25);
|
||||
expect(payload.rainSinceMidnight).toBe(50);
|
||||
expect(payload.humidity).toBe(50);
|
||||
expect(payload.pressure).toBe(10132);
|
||||
});
|
||||
|
||||
it("emits structure when requested", () => {
|
||||
const data = "SRC>DEST:_120345z180/10g15t072r000p025P050h50b10132";
|
||||
const frame = Frame.fromString(data);
|
||||
const res = frame.decode(true) as {
|
||||
payload: WeatherPayload;
|
||||
structure: Dissected;
|
||||
};
|
||||
expect(res.payload).not.toBeNull();
|
||||
expect(Array.isArray(res.structure)).toBe(true);
|
||||
const names = res.structure.map((s) => s.name);
|
||||
expect(names).toContain("timestamp");
|
||||
expect(names).toContain("weather");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user