@packet-net/pdn-aprs 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/LICENSE +661 -0
  3. package/README.md +192 -0
  4. package/THIRD-PARTY-NOTICES.md +5 -0
  5. package/dist/builder.d.ts +232 -0
  6. package/dist/builder.d.ts.map +1 -0
  7. package/dist/builder.js +508 -0
  8. package/dist/builder.js.map +1 -0
  9. package/dist/bytes.d.ts +19 -0
  10. package/dist/bytes.d.ts.map +1 -0
  11. package/dist/bytes.js +120 -0
  12. package/dist/bytes.js.map +1 -0
  13. package/dist/codes.d.ts +13 -0
  14. package/dist/codes.d.ts.map +1 -0
  15. package/dist/codes.js +112 -0
  16. package/dist/codes.js.map +1 -0
  17. package/dist/decode/context.d.ts +33 -0
  18. package/dist/decode/context.d.ts.map +1 -0
  19. package/dist/decode/context.js +65 -0
  20. package/dist/decode/context.js.map +1 -0
  21. package/dist/decode/index.d.ts +10 -0
  22. package/dist/decode/index.d.ts.map +1 -0
  23. package/dist/decode/index.js +121 -0
  24. package/dist/decode/index.js.map +1 -0
  25. package/dist/decode/message.d.ts +5 -0
  26. package/dist/decode/message.d.ts.map +1 -0
  27. package/dist/decode/message.js +190 -0
  28. package/dist/decode/message.js.map +1 -0
  29. package/dist/decode/other.d.ts +25 -0
  30. package/dist/decode/other.d.ts.map +1 -0
  31. package/dist/decode/other.js +326 -0
  32. package/dist/decode/other.js.map +1 -0
  33. package/dist/decode/positioned.d.ts +132 -0
  34. package/dist/decode/positioned.d.ts.map +1 -0
  35. package/dist/decode/positioned.js +1063 -0
  36. package/dist/decode/positioned.js.map +1 -0
  37. package/dist/decode/reports.d.ts +13 -0
  38. package/dist/decode/reports.d.ts.map +1 -0
  39. package/dist/decode/reports.js +375 -0
  40. package/dist/decode/reports.js.map +1 -0
  41. package/dist/decoder.d.ts +23 -0
  42. package/dist/decoder.d.ts.map +1 -0
  43. package/dist/decoder.js +75 -0
  44. package/dist/decoder.js.map +1 -0
  45. package/dist/deviceid-data.d.ts +33 -0
  46. package/dist/deviceid-data.d.ts.map +1 -0
  47. package/dist/deviceid-data.js +2941 -0
  48. package/dist/deviceid-data.js.map +1 -0
  49. package/dist/deviceid.d.ts +12 -0
  50. package/dist/deviceid.d.ts.map +1 -0
  51. package/dist/deviceid.js +86 -0
  52. package/dist/deviceid.js.map +1 -0
  53. package/dist/diagnostics.d.ts +48 -0
  54. package/dist/diagnostics.d.ts.map +1 -0
  55. package/dist/diagnostics.js +65 -0
  56. package/dist/diagnostics.js.map +1 -0
  57. package/dist/encode/common.d.ts +19 -0
  58. package/dist/encode/common.d.ts.map +1 -0
  59. package/dist/encode/common.js +84 -0
  60. package/dist/encode/common.js.map +1 -0
  61. package/dist/encode/index.d.ts +35 -0
  62. package/dist/encode/index.d.ts.map +1 -0
  63. package/dist/encode/index.js +248 -0
  64. package/dist/encode/index.js.map +1 -0
  65. package/dist/encode/other.d.ts +21 -0
  66. package/dist/encode/other.d.ts.map +1 -0
  67. package/dist/encode/other.js +253 -0
  68. package/dist/encode/other.js.map +1 -0
  69. package/dist/encode/position.d.ts +31 -0
  70. package/dist/encode/position.d.ts.map +1 -0
  71. package/dist/encode/position.js +729 -0
  72. package/dist/encode/position.js.map +1 -0
  73. package/dist/header.d.ts +42 -0
  74. package/dist/header.d.ts.map +1 -0
  75. package/dist/header.js +206 -0
  76. package/dist/header.js.map +1 -0
  77. package/dist/index.d.ts +13 -0
  78. package/dist/index.d.ts.map +1 -0
  79. package/dist/index.js +14 -0
  80. package/dist/index.js.map +1 -0
  81. package/dist/neutral.d.ts +22 -0
  82. package/dist/neutral.d.ts.map +1 -0
  83. package/dist/neutral.js +593 -0
  84. package/dist/neutral.js.map +1 -0
  85. package/dist/symbols-data.d.ts +832 -0
  86. package/dist/symbols-data.d.ts.map +1 -0
  87. package/dist/symbols-data.js +173 -0
  88. package/dist/symbols-data.js.map +1 -0
  89. package/dist/symbols.d.ts +35 -0
  90. package/dist/symbols.d.ts.map +1 -0
  91. package/dist/symbols.js +71 -0
  92. package/dist/symbols.js.map +1 -0
  93. package/dist/types.d.ts +458 -0
  94. package/dist/types.d.ts.map +1 -0
  95. package/dist/types.js +4 -0
  96. package/dist/types.js.map +1 -0
  97. package/package.json +68 -0
  98. package/src/builder.ts +617 -0
  99. package/src/bytes.ts +118 -0
  100. package/src/codes.ts +218 -0
  101. package/src/decode/context.ts +63 -0
  102. package/src/decode/index.ts +135 -0
  103. package/src/decode/message.ts +194 -0
  104. package/src/decode/other.ts +307 -0
  105. package/src/decode/positioned.ts +1161 -0
  106. package/src/decode/reports.ts +378 -0
  107. package/src/decoder.ts +76 -0
  108. package/src/deviceid-data.ts +2954 -0
  109. package/src/deviceid.ts +83 -0
  110. package/src/diagnostics.ts +86 -0
  111. package/src/encode/common.ts +87 -0
  112. package/src/encode/index.ts +280 -0
  113. package/src/encode/other.ts +247 -0
  114. package/src/encode/position.ts +656 -0
  115. package/src/header.ts +221 -0
  116. package/src/index.ts +57 -0
  117. package/src/neutral.ts +595 -0
  118. package/src/symbols-data.ts +181 -0
  119. package/src/symbols.ts +85 -0
  120. package/src/types.ts +571 -0
package/README.md ADDED
@@ -0,0 +1,192 @@
1
+ # @packet-net/pdn-aprs
2
+
3
+ An APRS (Automatic Packet Reporting System) encoder and decoder for TypeScript.
4
+
5
+ - Decodes TNC2 / APRS-IS lines and AX.25 frames into a typed data model, with every defect it noticed reported as a diagnostic.
6
+ - Every APRS data type: positions (plain, compressed, Mic-E), objects and items, weather, telemetry, messages and acks, bulletins, status, queries, capabilities, third-party traffic, NMEA, raw weather, user-defined data and the rest.
7
+ - Strict and lenient decoding, with each tolerated defect switchable on or off by itself.
8
+ - An encoder for every type that writes only what the spec allows, and refuses anything else with a reason.
9
+ - A fluent builder for the packets an application usually sends.
10
+ - Every APRS symbol by name, with overlays; device identification from the APRS device database.
11
+ - Zero runtime dependencies; ESM; works in browsers and Node 20 and later. Bytes are `Uint8Array`.
12
+
13
+ It is conformance tested against [aprs-vectors](https://github.com/packet-net/aprs-vectors), the language-neutral test suite shared with [Packet.Aprs](https://github.com/packet-net/packet.net) (C#), [pdn-aprs](https://github.com/packet-net/aprs-rs) (Rust) and [pdn-aprs](https://github.com/packet-net/aprs-py) (Python), and agrees with the C# and Rust implementations over a 6.9-million-packet APRS-IS capture.
14
+
15
+ ## Install
16
+
17
+ ```sh
18
+ npm install @packet-net/pdn-aprs
19
+ ```
20
+
21
+ ## Decoding
22
+
23
+ ```ts
24
+ import { decodeTnc2 } from '@packet-net/pdn-aprs';
25
+
26
+ const packet = decodeTnc2('M0LTE-9>APDR16,WIDE1-1,qAR,G4ABC-10:=5127.00N/00058.80W>088/036/A=000100 Mobile');
27
+
28
+ console.log(packet.source); // M0LTE-9
29
+ console.log(packet.qConstruct?.station); // G4ABC-10
30
+ console.log(packet.device?.model); // APRSdroid
31
+
32
+ if (packet.data.type === 'position') {
33
+ console.log(packet.data.latitude); // 51.45
34
+ console.log(packet.data.courseDegrees); // 88
35
+ console.log(packet.data.altitudeFeet); // 100
36
+ console.log(packet.data.comment); // Mobile
37
+ }
38
+ ```
39
+
40
+ `packet.data` is a discriminated union on `type`, so TypeScript narrows it for you: `position`, `mic-e`, `object`, `item`, `message`, `ack`, `reject`, `bulletin`, `nws-bulletin`, `telemetry`, `telemetry-names`, `telemetry-units`, `telemetry-coefficients`, `telemetry-bits`, `directed-query`, `status`, `weather`, `raw-weather`, `nmea`, `maidenhead-beacon`, `query`, `capabilities`, `third-party`, `user-defined`, `test`, `agrelo-df`, and `unrecognized` when there is nothing to decode. Quantities keep the units APRS sends them in, with the unit in the name (`speedKnots`, `altitudeFeet`, `temperatureF`).
41
+
42
+ A Mic-E report carries half its position in the destination address; the decoder reads both.
43
+
44
+ ```ts
45
+ import { decodeTnc2 } from '@packet-net/pdn-aprs';
46
+
47
+ const micE = decodeTnc2('N0CALL>S32UVT:`(_fn"Oj/');
48
+ if (micE.data.type === 'mic-e') {
49
+ console.log(micE.data.micEMessage); // returning
50
+ console.log(micE.data.longitude); // -112.129
51
+ console.log(micE.data.speedKnots); // 20
52
+ }
53
+ ```
54
+
55
+ AX.25 frames (address, control, PID and information fields, no flags or FCS) decode with `decodeAx25`, and frames straight from a KISS TNC with `decodeKiss`.
56
+
57
+ ## Diagnostics, strict and lenient
58
+
59
+ Real packets are often not quite right. The decoder reports everything it noticed, each with a severity and a code from the vectors' [codes.json](https://github.com/packet-net/aprs-vectors/blob/main/codes.json). By default it is lenient: a defect a receiver can safely work around is a `warning`, and the packet still decodes. A strict decoder rejects it instead, and the data is `unrecognized`.
60
+
61
+ ```ts
62
+ import { decodeTnc2, formatDiagnostic, ParseOptions } from '@packet-net/pdn-aprs';
63
+
64
+ const line = 'N1EOE>APN391:!4216.95n/07243.20w#';
65
+
66
+ const lenient = decodeTnc2(line);
67
+ console.log(lenient.data.type); // position
68
+ console.log(lenient.diagnostics.map(formatDiagnostic).join(' ')); // warning:lowercase-hemisphere warning:lowercase-hemisphere
69
+
70
+ const strict = decodeTnc2(line, ParseOptions.strict);
71
+ console.log(strict.data.type); // unrecognized
72
+
73
+ const almostStrict = decodeTnc2(line, ParseOptions.strict.with('lowercase-hemisphere'));
74
+ console.log(almostStrict.data.type); // position
75
+ ```
76
+
77
+ `ParseOptions.lenient.without(code)` tolerates everything but one code. A header that cannot be used at all throws `AprsHeaderError`, whose `diagnostics` say why.
78
+
79
+ ## Building packets
80
+
81
+ `Aprs.from(...)` starts a packet; pick what it is, set what you need, and `build()` encodes it.
82
+
83
+ ```ts
84
+ import { Aprs, Symbols } from '@packet-net/pdn-aprs';
85
+
86
+ const packet = Aprs.from('M0LTE-9')
87
+ .via('WIDE1-1', 'WIDE2-1')
88
+ .position(51.45, -0.98)
89
+ .symbol(Symbols.car)
90
+ .course(88)
91
+ .speed(36)
92
+ .comment('Mobile')
93
+ .build();
94
+
95
+ console.log(packet.toTnc2()); // M0LTE-9>APZ001,WIDE1-1,WIDE2-1:!5127.00N/00058.80W>088/036Mobile
96
+ const frame = packet.toAx25(); // or toKiss() for a KISS TNC
97
+ console.log(frame.length); // 63
98
+ ```
99
+
100
+ The destination defaults to `APZ001` in the experimental range; give your application's own with `.to(...)`. The builder covers what an application usually sends:
101
+
102
+ ```ts
103
+ import { Aprs, Symbols } from '@packet-net/pdn-aprs';
104
+
105
+ const station = Aprs.from('M0LTE');
106
+
107
+ // A message wanting an ack, and the ack
108
+ console.log(station.message('G4ABC', 'Meet at the club at 8?').id(42).toTnc2()); // M0LTE>APZ001::G4ABC :Meet at the club at 8?{42
109
+ console.log(station.ack('G4ABC', '7').toTnc2()); // M0LTE>APZ001::G4ABC :ack7
110
+
111
+ // Status, with a locator and symbol
112
+ console.log(station.status('On the air').locator('IO91SX', Symbols.house).toTnc2()); // M0LTE>APZ001:>IO91SX/- On the air
113
+
114
+ // An object, with a timestamp (objects always have one; it defaults to now)
115
+ console.log(
116
+ station
117
+ .object('NET', 51.5, -0.1)
118
+ .timestamp({ kind: 'dhm-zulu', day: 26, hour: 19, minute: 30 })
119
+ .symbol(Symbols.redCross)
120
+ .comment('Net control')
121
+ .toTnc2(),
122
+ ); // M0LTE>APZ001:;NET *261930z5130.00N/00006.00W+Net control
123
+
124
+ // Weather at a position
125
+ console.log(
126
+ station
127
+ .weather(51.45, -0.98, { windDirectionDegrees: 220, windSpeedMph: 4, windGustMph: 5, temperatureF: 61, humidityPercent: 80, pressureMbar: 1013.2 })
128
+ .toTnc2(),
129
+ ); // M0LTE>APZ001:!5127.00N/00058.80W_220/004g005t061h80b10132
130
+
131
+ // Telemetry, and a Mic-E position (which computes its destination address)
132
+ console.log(station.telemetry(5, [199, 0, 255, 73, 123], '01101001').toTnc2()); // M0LTE>APZ001:T#005,199,000,255,073,123,01101001
133
+ console.log(station.micE(51.5, -0.1234).symbol(Symbols.car).micEMessage('en-route').speed(20).course(90).toTnc2()); // M0LTE>UQ3PPP:`v_Dn v>/`
134
+ ```
135
+
136
+ Anything the spec does not allow is refused when you build it, with an `AprsEncodeError` saying why: message text over 67 characters, an object name with a trailing space, two data extensions at once. Free text is checked by decoding what was written, so a comment that would read back as something else (an altitude, a PHG code, a `!DAO!`) gets a `/` delimiter in front if that fixes it, and is refused if not.
137
+
138
+ ```ts
139
+ import { Aprs, AprsEncodeError } from '@packet-net/pdn-aprs';
140
+
141
+ try {
142
+ Aprs.from('M0LTE').position(51.45, -0.98).comment('at /A=001234').build();
143
+ } catch (e) {
144
+ console.log(e instanceof AprsEncodeError); // true
145
+ }
146
+ ```
147
+
148
+ The encoder also works on data directly: `encodeInformation(data)` returns the information field bytes (and for Mic-E the destination), and `encodeTnc2` / `encodeAx25` a whole packet. Decoding and encoding again round-trips: data from the decoder encodes back to the same bytes, or to bytes that decode to the same data.
149
+
150
+ ## Symbols
151
+
152
+ Every symbol the APRS symbol tables define is available by name, with its description. Symbols in the alternate table can carry an overlay character.
153
+
154
+ ```ts
155
+ import { describeSymbol, Symbols, symbolName, withOverlay } from '@packet-net/pdn-aprs';
156
+
157
+ console.log(Symbols.car.table + Symbols.car.code); // />
158
+ console.log(describeSymbol(Symbols.digipeater)); // Digi (green star with white center)
159
+
160
+ const igate = withOverlay(Symbols.gateway, 'I');
161
+ console.log(igate.table + igate.code); // I&
162
+ console.log(symbolName(igate)); // gateway
163
+ ```
164
+
165
+ ## Device identification
166
+
167
+ `packet.device` identifies the sending device or software from the [APRS device identification database](https://github.com/aprsorg/aprs-deviceid): by the destination address, or for a Mic-E report by its type code and suffix. `identifyTocall` looks one up directly.
168
+
169
+ ```ts
170
+ import { identifyTocall } from '@packet-net/pdn-aprs';
171
+
172
+ console.log(identifyTocall('APDW18')?.model); // DireWolf
173
+ ```
174
+
175
+ ## Conformance
176
+
177
+ The conformance vectors are a git submodule at `vectors/`. The test suite runs every case with every check the vectors' README defines (the lenient result, the strict result, the single-tolerance check, re-encoding, and the encode cases), one test per check per case: 5,523 tests, all passing. A check this implementation could not pass would be listed in `test/known-differences.json` with the reason and skipped; the list is empty.
178
+
179
+ `scripts/diff-dump.mjs` writes the differential dump that the vectors' `tools/compare.py` reads, for comparing implementations over a whole capture:
180
+
181
+ ```sh
182
+ git submodule update --init
183
+ npm ci && npm run build
184
+ node scripts/diff-dump.mjs lines.hex.gz ts.jsonl.gz
185
+ python3 vectors/tools/compare.py ts.jsonl.gz other.jsonl.gz --names TS Other --lines lines.hex.gz
186
+ ```
187
+
188
+ The examples in this README run as tests too (`test/readme.test.ts`).
189
+
190
+ ## Licence
191
+
192
+ AGPL-3.0-or-later; see [LICENSE](LICENSE). The device identification data is from the APRS device identification database, CC BY-SA 2.0; see [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md).
@@ -0,0 +1,5 @@
1
+ # Third-party notices
2
+
3
+ ## APRS device identification database
4
+
5
+ `src/deviceid-data.ts` is generated by `scripts/generate-deviceid.mjs` from the APRS device identification database, <https://github.com/aprsorg/aprs-deviceid> (commit 845e3f89, 2026-09-18), maintained by Hessu, OH7LZB. It is licensed under the Creative Commons Attribution-ShareAlike 2.0 licence, <https://creativecommons.org/licenses/by-sa/2.0/>. Contact addresses are left out; nothing else is changed.
@@ -0,0 +1,232 @@
1
+ import type { AprsData, AprsSymbol, AprsTimestamp, CompressionType, Dao, MicEMessage, PositionedFields, VoiceFrequency, Weather } from './types.js';
2
+ /** The tocall used when none is given: the experimental `APZ` range. */
3
+ export declare const DEFAULT_DESTINATION = "APZ001";
4
+ /** A packet the builder made: its parts, and the ways to send it. */
5
+ export interface BuiltPacket {
6
+ readonly source: string;
7
+ /** The destination (for Mic-E, the one the encoder computed). */
8
+ readonly destination: string;
9
+ readonly path: readonly string[];
10
+ readonly data: AprsData;
11
+ /** The information field bytes. */
12
+ readonly information: Uint8Array;
13
+ /** The TNC2 / APRS-IS line. */
14
+ toTnc2(): string;
15
+ /** The TNC2 / APRS-IS line as bytes. */
16
+ toTnc2Bytes(): Uint8Array;
17
+ /** The AX.25 UI frame (no flags, no FCS). */
18
+ toAx25(): Uint8Array;
19
+ /** The AX.25 frame wrapped for a KISS TNC. */
20
+ toKiss(port?: number): Uint8Array;
21
+ }
22
+ interface Header {
23
+ source: string;
24
+ destination?: string;
25
+ path: string[];
26
+ }
27
+ /**
28
+ * A timestamp from a `Date`, in UTC: day, hour and minute (`dhm-zulu`, the recommended form),
29
+ * or hours, minutes and seconds (`hms`).
30
+ */
31
+ export declare function timestampOf(date: Date, kind?: 'dhm-zulu' | 'hms'): AprsTimestamp;
32
+ type Mutable<T> = {
33
+ -readonly [K in keyof T]: T[K];
34
+ };
35
+ /** Starts a packet: `Aprs.from('M0LTE-9')`. */
36
+ export declare const Aprs: {
37
+ /** A packet from `source`. */
38
+ from(source: string): PacketBuilder;
39
+ };
40
+ /** The header, then the kind of packet. */
41
+ export declare class PacketBuilder {
42
+ private readonly header;
43
+ constructor(header: Header);
44
+ /** The destination (tocall) identifying the sending software; ignored for Mic-E. */
45
+ to(destination: string): PacketBuilder;
46
+ /** The digipeater path, e.g. `via('WIDE1-1', 'WIDE2-1')`. */
47
+ via(...path: string[]): PacketBuilder;
48
+ /** A position report. */
49
+ position(latitude: number, longitude: number): PositionBuilder;
50
+ /** A weather report at a position (the weather station symbol, unless you pick another `_`). */
51
+ weather(latitude: number, longitude: number, weather: Weather): PositionBuilder;
52
+ /** An object: `timestamp` defaults to now (objects always carry one). */
53
+ object(name: string, latitude: number, longitude: number): ObjectBuilder;
54
+ /** An item. */
55
+ item(name: string, latitude: number, longitude: number): ItemBuilder;
56
+ /** A Mic-E report: its position and message type go in the destination address. */
57
+ micE(latitude: number, longitude: number): MicEBuilder;
58
+ /** A message to `addressee`. */
59
+ message(addressee: string, text: string): MessageBuilder;
60
+ /** An acknowledgement of message `id` from `addressee`. */
61
+ ack(addressee: string, id: string): DataBuilder;
62
+ /** A rejection of message `id` from `addressee`. */
63
+ reject(addressee: string, id: string): DataBuilder;
64
+ /** A bulletin (`id` a digit) or announcement (`id` a letter), optionally to a group. */
65
+ bulletin(id: string, text: string, group?: string): DataBuilder;
66
+ /** A status report. */
67
+ status(text?: string): StatusBuilder;
68
+ /** A telemetry report: sequence, five analog values and eight bits (`'01101001'`, B1 first). */
69
+ telemetry(sequence: number | string, analog: readonly (number | null)[], bits: string): TelemetryBuilder;
70
+ /** Telemetry channel names (`PARM.`), sent to the station whose telemetry they describe. */
71
+ telemetryNames(addressee: string, names: readonly string[]): DataBuilder;
72
+ /** Telemetry units and labels (`UNIT.`). */
73
+ telemetryUnits(addressee: string, units: readonly string[]): DataBuilder;
74
+ /** Telemetry equation coefficients (`EQNS.`): a, b, c for each analog channel. */
75
+ telemetryCoefficients(addressee: string, coefficients: readonly number[]): DataBuilder;
76
+ /** Telemetry bit sense and project title (`BITS.`). */
77
+ telemetryBits(addressee: string, bits: string, project?: string): DataBuilder;
78
+ /** A positionless weather report (not recommended: a weather report with a position is better). */
79
+ weatherReport(weather: Weather, at?: Date): DataBuilder;
80
+ /** Any data, built by hand. */
81
+ data(data: AprsData): DataBuilder;
82
+ }
83
+ /** Builds data that needs nothing more. */
84
+ export declare class DataBuilder {
85
+ protected readonly header: Header;
86
+ protected readonly value: AprsData;
87
+ constructor(header: Header, value: AprsData);
88
+ /** Encodes the packet; throws `AprsEncodeError` if the spec does not allow it. */
89
+ build(): BuiltPacket;
90
+ /** Shorthand for `build().toTnc2()`. */
91
+ toTnc2(): string;
92
+ }
93
+ /** What positions, objects, items and Mic-E reports share. */
94
+ declare abstract class PositionedBuilder<Self> {
95
+ protected readonly header: Header;
96
+ protected fields: Mutable<PositionedFields>;
97
+ constructor(header: Header, latitude: number, longitude: number);
98
+ protected abstract self(): Self;
99
+ /** The display symbol: `Symbols.car`, or its two characters (`'/>'`). */
100
+ symbol(symbol: AprsSymbol | string): Self;
101
+ /** Course over the ground, degrees 1-360 (360 is north). */
102
+ course(degrees: number): Self;
103
+ /** Speed, knots. */
104
+ speed(knots: number): Self;
105
+ /** Altitude, feet. */
106
+ altitude(feet: number): Self;
107
+ /** Altitude, metres (sent in feet, rounded). */
108
+ altitudeMetres(metres: number): Self;
109
+ /** Free text. */
110
+ comment(text: string): Self;
111
+ /** An APRS 1.2 voice frequency, e.g. `frequency(145.5, { tone: 'tone', toneValue: 77 })`. */
112
+ frequency(mhz: number, details?: Omit<VoiceFrequency, 'mhz'>): Self;
113
+ /** Base-91 comment telemetry: a sequence and one to five analog values (0-8280). */
114
+ commentTelemetry(sequence: number, analog: readonly number[], digital?: number): Self;
115
+ /** A `!DAO!` for about a foot of precision (base-91), with its datum (`W` is WGS84). */
116
+ dao(datum?: string, precision?: Dao['precision']): Self;
117
+ /** Blanks 1-4 digits of the position (APRS12c ch. 6). */
118
+ ambiguity(digits: number): Self;
119
+ }
120
+ /** A position (`!`, `=`, `/`, `@`), or an object or item's position. */
121
+ declare abstract class ReportBuilder<Self> extends PositionedBuilder<Self> {
122
+ /** Power, antenna height, gain and directivity codes (APRS12c ch. 7). */
123
+ phg(power: number, height: number, gain: number, directivity?: number, beaconsPerHour?: number): Self;
124
+ /** A pre-calculated radio range, miles. */
125
+ range(miles: number): Self;
126
+ /** Weather data (needs a weather station symbol, `_`). */
127
+ weather(weather: Weather): Self;
128
+ /** The compressed format (APRS12c ch. 9), with its type byte if you want to set it. */
129
+ compressed(compression?: CompressionType): Self;
130
+ }
131
+ /** A position report. */
132
+ export declare class PositionBuilder extends ReportBuilder<PositionBuilder> {
133
+ private timestampValue?;
134
+ private messagingValue;
135
+ protected self(): PositionBuilder;
136
+ /** When the position was fixed: a `Date` (UTC) or a timestamp. */
137
+ timestamp(at: Date | AprsTimestamp, kind?: 'dhm-zulu' | 'hms'): PositionBuilder;
138
+ /** The sender can receive APRS messages. */
139
+ messaging(capable?: boolean): PositionBuilder;
140
+ build(): BuiltPacket;
141
+ toTnc2(): string;
142
+ }
143
+ /** An object report. */
144
+ export declare class ObjectBuilder extends ReportBuilder<ObjectBuilder> {
145
+ private readonly name;
146
+ private timestampValue;
147
+ private killedValue;
148
+ constructor(header: Header, name: string, latitude: number, longitude: number);
149
+ protected self(): ObjectBuilder;
150
+ /** When the object was at this position (defaults to now). */
151
+ timestamp(at: Date | AprsTimestamp, kind?: 'dhm-zulu' | 'hms'): ObjectBuilder;
152
+ /** Kills the object: receivers remove it. */
153
+ killed(killed?: boolean): ObjectBuilder;
154
+ build(): BuiltPacket;
155
+ toTnc2(): string;
156
+ }
157
+ /** An item report. */
158
+ export declare class ItemBuilder extends ReportBuilder<ItemBuilder> {
159
+ private readonly name;
160
+ private killedValue;
161
+ constructor(header: Header, name: string, latitude: number, longitude: number);
162
+ protected self(): ItemBuilder;
163
+ /** Kills the item: receivers remove it. */
164
+ killed(killed?: boolean): ItemBuilder;
165
+ build(): BuiltPacket;
166
+ toTnc2(): string;
167
+ }
168
+ /** A Mic-E report. */
169
+ export declare class MicEBuilder extends PositionedBuilder<MicEBuilder> {
170
+ private messageValue;
171
+ private typeCodeValue;
172
+ private locatorValue?;
173
+ private oldValue;
174
+ protected self(): MicEBuilder;
175
+ /** The Mic-E message: `off-duty` (the default), `en-route`, `in-service`, `returning`, ... */
176
+ micEMessage(message: MicEMessage): MicEBuilder;
177
+ /** Whether the sender can receive messages: the `` ` `` (yes, the default) or `'` type code. */
178
+ messaging(capable?: boolean): MicEBuilder;
179
+ /** A Maidenhead locator in the status text. */
180
+ locator(locator: string): MicEBuilder;
181
+ /** Marks the position as old (not current) GPS data. */
182
+ old(old?: boolean): MicEBuilder;
183
+ build(): BuiltPacket;
184
+ toTnc2(): string;
185
+ }
186
+ /** A message. */
187
+ export declare class MessageBuilder {
188
+ private readonly header;
189
+ private readonly addressee;
190
+ private readonly text;
191
+ private idValue?;
192
+ private replyAckValue?;
193
+ constructor(header: Header, addressee: string, text: string);
194
+ /** A message ID (1-5 letters or digits), so the addressee acknowledges it. */
195
+ id(id: string | number): MessageBuilder;
196
+ /** A reply-ack: the ID of the other station's message this also acknowledges; `''` for none. */
197
+ replyAck(id?: string): MessageBuilder;
198
+ build(): BuiltPacket;
199
+ toTnc2(): string;
200
+ }
201
+ /** A status report. */
202
+ export declare class StatusBuilder {
203
+ private readonly header;
204
+ private readonly text?;
205
+ private timestampValue?;
206
+ private locatorValue?;
207
+ private beamValue?;
208
+ constructor(header: Header, text?: string | undefined);
209
+ /** When (UTC day, hour and minute). A status with a locator has no timestamp. */
210
+ timestamp(at: Date | AprsTimestamp): StatusBuilder;
211
+ /** A Maidenhead locator and a symbol, in place of a timestamp. */
212
+ locator(locator: string, symbol: AprsSymbol | string): StatusBuilder;
213
+ /** Meteor scatter beam heading and power codes (`^B7`). */
214
+ beam(headingCode: string, powerCode: string): StatusBuilder;
215
+ build(): BuiltPacket;
216
+ toTnc2(): string;
217
+ }
218
+ /** A telemetry report. */
219
+ export declare class TelemetryBuilder {
220
+ private readonly header;
221
+ private readonly sequence;
222
+ private readonly analog;
223
+ private readonly bits;
224
+ private commentValue?;
225
+ constructor(header: Header, sequence: string, analog: readonly (number | null)[], bits: string);
226
+ /** Free text after the bits. */
227
+ comment(text: string): TelemetryBuilder;
228
+ build(): BuiltPacket;
229
+ toTnc2(): string;
230
+ }
231
+ export {};
232
+ //# sourceMappingURL=builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"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"}