@squawk/mode-s 0.1.0
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.
- package/README.md +243 -0
- package/dist/acas.d.ts +14 -0
- package/dist/acas.d.ts.map +1 -0
- package/dist/acas.js +90 -0
- package/dist/altitude.d.ts +34 -0
- package/dist/altitude.d.ts.map +1 -0
- package/dist/altitude.js +99 -0
- package/dist/bits.d.ts +41 -0
- package/dist/bits.d.ts.map +1 -0
- package/dist/bits.js +55 -0
- package/dist/comm-b.d.ts +37 -0
- package/dist/comm-b.d.ts.map +1 -0
- package/dist/comm-b.js +245 -0
- package/dist/cpr.d.ts +71 -0
- package/dist/cpr.d.ts.map +1 -0
- package/dist/cpr.js +220 -0
- package/dist/emergency-status.d.ts +10 -0
- package/dist/emergency-status.d.ts.map +1 -0
- package/dist/emergency-status.js +21 -0
- package/dist/frame.d.ts +42 -0
- package/dist/frame.d.ts.map +1 -0
- package/dist/frame.js +68 -0
- package/dist/identification.d.ts +10 -0
- package/dist/identification.d.ts.map +1 -0
- package/dist/identification.js +64 -0
- package/dist/identity.d.ts +11 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +20 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/message.d.ts +40 -0
- package/dist/message.d.ts.map +1 -0
- package/dist/message.js +293 -0
- package/dist/mode-ac.d.ts +17 -0
- package/dist/mode-ac.d.ts.map +1 -0
- package/dist/mode-ac.js +86 -0
- package/dist/operational-status.d.ts +9 -0
- package/dist/operational-status.d.ts.map +1 -0
- package/dist/operational-status.js +23 -0
- package/dist/surface-movement.d.ts +9 -0
- package/dist/surface-movement.d.ts.map +1 -0
- package/dist/surface-movement.js +37 -0
- package/dist/target-state-status.d.ts +9 -0
- package/dist/target-state-status.d.ts.map +1 -0
- package/dist/target-state-status.js +34 -0
- package/dist/test-utils.d.ts +7 -0
- package/dist/test-utils.d.ts.map +1 -0
- package/dist/test-utils.js +17 -0
- package/dist/types/acas.d.ts +82 -0
- package/dist/types/acas.d.ts.map +1 -0
- package/dist/types/acas.js +1 -0
- package/dist/types/comm-b.d.ts +69 -0
- package/dist/types/comm-b.d.ts.map +1 -0
- package/dist/types/comm-b.js +1 -0
- package/dist/types/cpr.d.ts +25 -0
- package/dist/types/cpr.d.ts.map +1 -0
- package/dist/types/cpr.js +1 -0
- package/dist/types/emergency-status.d.ts +6 -0
- package/dist/types/emergency-status.d.ts.map +1 -0
- package/dist/types/emergency-status.js +1 -0
- package/dist/types/frame.d.ts +32 -0
- package/dist/types/frame.d.ts.map +1 -0
- package/dist/types/frame.js +1 -0
- package/dist/types/identification.d.ts +9 -0
- package/dist/types/identification.d.ts.map +1 -0
- package/dist/types/identification.js +1 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +11 -0
- package/dist/types/message.d.ts +235 -0
- package/dist/types/message.d.ts.map +1 -0
- package/dist/types/message.js +1 -0
- package/dist/types/mode-ac.d.ts +16 -0
- package/dist/types/mode-ac.d.ts.map +1 -0
- package/dist/types/mode-ac.js +1 -0
- package/dist/types/operational-status.d.ts +28 -0
- package/dist/types/operational-status.d.ts.map +1 -0
- package/dist/types/operational-status.js +1 -0
- package/dist/types/target-state-status.d.ts +34 -0
- package/dist/types/target-state-status.d.ts.map +1 -0
- package/dist/types/target-state-status.js +1 -0
- package/dist/types/velocity.d.ts +35 -0
- package/dist/types/velocity.d.ts.map +1 -0
- package/dist/types/velocity.js +1 -0
- package/dist/velocity.d.ts +9 -0
- package/dist/velocity.d.ts.map +1 -0
- package/dist/velocity.js +73 -0
- package/package.json +61 -0
package/README.md
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
<h1><img src="../../../assets/squawk-logo.svg" alt="squawk logo" width="48" height="48" style="vertical-align: middle"> @squawk/mode-s</h1>
|
|
2
|
+
|
|
3
|
+
[](../../../LICENSE.md) [](https://www.npmjs.com/package/@squawk/mode-s) 
|
|
4
|
+
|
|
5
|
+
Decodes raw Mode-S/ADS-B messages: downlink format and CRC extraction, CPR
|
|
6
|
+
position, airborne velocity, aircraft identification, altitude (both the
|
|
7
|
+
ADS-B position-message field and legacy Gillham-coded surveillance replies),
|
|
8
|
+
squawk identity, emergency status, ACAS/TCAS Resolution Advisories, target
|
|
9
|
+
state and status, aircraft operational status, and Enhanced Surveillance
|
|
10
|
+
Comm-B registers (selected vertical intention, track and turn, heading and
|
|
11
|
+
speed). Transport-agnostic - it operates on already-framed message bytes and
|
|
12
|
+
has no opinion about where they came from (a live Beast feed, a logged
|
|
13
|
+
capture, or any other source). For a Beast binary parser and live TCP client
|
|
14
|
+
built on top of this package, see [`@squawk/beast`](../beast).
|
|
15
|
+
|
|
16
|
+
Part of the [@squawk](https://www.npmjs.com/org/squawk) aviation library suite. See all packages on npm.
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install @squawk/mode-s
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
### Decoding a whole message
|
|
27
|
+
|
|
28
|
+
`decodeModeSMessage` is the main entry point - it reads the downlink format,
|
|
29
|
+
validates the CRC, and routes to the right per-type decoder, returning a
|
|
30
|
+
single discriminated result.
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { decodeModeSMessage } from '@squawk/mode-s';
|
|
34
|
+
|
|
35
|
+
const decoded = decodeModeSMessage(rawMessageBytes); // 7 or 14 raw bytes
|
|
36
|
+
if (decoded?.kind === 'extendedSquitterPosition') {
|
|
37
|
+
console.log(decoded.icaoHex, decoded.latCpr, decoded.lonCpr, decoded.altitudeFt);
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`bytes`' length must match what its downlink format implies (7 bytes for a
|
|
42
|
+
short message, 14 for long) or the message is rejected outright - a length
|
|
43
|
+
mismatch means the buffer is truncated or corrupted, not a genuine message
|
|
44
|
+
of that format.
|
|
45
|
+
|
|
46
|
+
DF17/18 (extended squitter) messages are only decoded when their CRC checks
|
|
47
|
+
out exactly - a corrupted squitter reports as undecodable rather than
|
|
48
|
+
returning plausible-looking wrong data. DF18 is further gated on its control
|
|
49
|
+
field: CF=0/1/2/5/6 share DF17's type-code-coded ME layout and decode the
|
|
50
|
+
same way; CF=3 (TIS-B coarse format) uses a different field layout this
|
|
51
|
+
package does not decode, and CF=4/7 carry no per-aircraft state. Every
|
|
52
|
+
decoded DF17/18 message carries `messageSource`, so a consumer can tell a
|
|
53
|
+
real, direct ICAO address from an anonymous or ground-derived one rather
|
|
54
|
+
than losing that distinction after the gate:
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
const decoded = decodeModeSMessage(rawMessageBytes);
|
|
58
|
+
if (decoded?.kind === 'extendedSquitterPosition' && decoded.messageSource !== 'icaoDirect') {
|
|
59
|
+
// decoded.icaoHex may not be a registered ICAO address (anonymousDirect/anonymousTisb),
|
|
60
|
+
// or the position may be ground-derived rather than heard directly (icaoTisb/adsr)
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
DF0/4/5/20/21 (Mode-S surveillance replies) are targeted responses whose CRC
|
|
65
|
+
is XORed with the responding aircraft's ICAO address rather than being a
|
|
66
|
+
plain checksum, so their `candidateIcaoHex` needs cross-checking against an
|
|
67
|
+
address already known from squitter traffic before it can be trusted - this
|
|
68
|
+
package doesn't perform that cross-check itself. DF20/21 (`'commBAltitudeReply'`/`'commBIdentityReply'`)
|
|
69
|
+
carry the same altitude/squawk payload as DF4/5 plus a 56-bit MB field,
|
|
70
|
+
decoded into `commBRegisters` - see
|
|
71
|
+
[Enhanced Surveillance Comm-B registers](#enhanced-surveillance-comm-b-registers).
|
|
72
|
+
|
|
73
|
+
### Resolving CPR position
|
|
74
|
+
|
|
75
|
+
Airborne and surface position messages carry raw CPR-encoded lat/lon
|
|
76
|
+
fields, not a directly usable position - resolving them needs either a
|
|
77
|
+
paired even/odd frame or a nearby reference position, and pairing state
|
|
78
|
+
(tracking the most recent even and odd frame per aircraft) is the caller's
|
|
79
|
+
responsibility, not this package's:
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { decodeAirborneCprPair, decodeAirborneCprWithReference } from '@squawk/mode-s';
|
|
83
|
+
|
|
84
|
+
// From a paired even + odd frame (global decode, no reference needed)
|
|
85
|
+
const position = decodeAirborneCprPair(evenFrame, oddFrame, 'even');
|
|
86
|
+
|
|
87
|
+
// From a single frame plus a known-nearby reference (e.g. the aircraft's
|
|
88
|
+
// last known position, or the receiver's own location for a new aircraft)
|
|
89
|
+
const position2 = decodeAirborneCprWithReference('even', frame, referencePosition);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`decodeSurfaceCprPair` / `decodeSurfaceCprWithReference` are the equivalents
|
|
93
|
+
for on-ground traffic (type codes 5-8), which additionally need a reference
|
|
94
|
+
position to resolve the correct hemisphere and longitude quadrant.
|
|
95
|
+
|
|
96
|
+
An airborne position message with type code 0 signals that no position fix
|
|
97
|
+
is currently available - `latCpr`/`lonCpr` are undefined in that case even
|
|
98
|
+
though `altitudeFt` may still be populated.
|
|
99
|
+
|
|
100
|
+
### ACAS / TCAS Resolution Advisories
|
|
101
|
+
|
|
102
|
+
An active Resolution Advisory reaches `decodeModeSMessage` two ways: DF16
|
|
103
|
+
(a targeted air-air surveillance reply, replacing DF0 while an RA is active)
|
|
104
|
+
and a DF17/18 type-code-28 subtype-2 message (the same report broadcast over
|
|
105
|
+
ADS-B so aircraft without interrogation capability can still see it).
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
const decoded = decodeModeSMessage(rawMessageBytes);
|
|
109
|
+
if (decoded?.kind === 'longAirAirSurveillanceReply' && decoded.resolutionAdvisory?.active) {
|
|
110
|
+
console.log(decoded.resolutionAdvisory.advisoryType); // e.g. 'climb', 'crossingDescend', 'increaseClimb'
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
`advisoryType` names the RA per RTCA DO-185B Table 2-16 (`climb`, `descend`,
|
|
115
|
+
`crossingClimb`, `crossingDescend`, `increaseClimb`, `increaseDescent`,
|
|
116
|
+
`reduceClimb`, `reduceDescent`, `doNotClimb`, `doNotDescend`,
|
|
117
|
+
`reversalToClimb`, `reversalToDescend`), derived from the report's
|
|
118
|
+
corrective/sense/rate/crossing/reversal flags - all of which are also
|
|
119
|
+
exposed individually on `AcasResolutionAdvisoryReport`, along with the
|
|
120
|
+
Resolution Advisory Complement flags (`doNotPassBelow`/`doNotPassAbove`;
|
|
121
|
+
`doNotTurnLeft`/`doNotTurnRight` are decoded for completeness but TCAS II
|
|
122
|
+
issues vertical RAs only, so they are expected to always be false). `advisoryType`
|
|
123
|
+
is undefined when no RA is currently active, or for the one flag combination
|
|
124
|
+
DO-185B leaves undefined (positive + preventive).
|
|
125
|
+
|
|
126
|
+
`threat` identifies what the RA is responding to, discriminated by
|
|
127
|
+
`threat.threatType`:
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
if (decoded.resolutionAdvisory?.threat.threatType === 'icaoAddress') {
|
|
131
|
+
console.log(decoded.resolutionAdvisory.threat.threatIcaoHex);
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`'none'` carries no further fields; `'icaoAddress'` carries `threatIcaoHex`;
|
|
136
|
+
`'altitudeRangeBearing'` carries `threatAltitudeFt`/`threatRangeNm`/`threatBearingDeg`
|
|
137
|
+
(each independently undefined if that specific field is unavailable).
|
|
138
|
+
|
|
139
|
+
### Target state and status
|
|
140
|
+
|
|
141
|
+
A type-code-29 ADS-B message reports what the aircraft's flight management
|
|
142
|
+
system is currently targeting - selected altitude, selected heading, and
|
|
143
|
+
which autopilot modes are engaged - not the aircraft's actual state:
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
const decoded = decodeModeSMessage(rawMessageBytes);
|
|
147
|
+
if (decoded?.kind === 'extendedSquitterTargetStateAndStatus') {
|
|
148
|
+
console.log(
|
|
149
|
+
decoded.targetStateAndStatus.selectedAltitudeFt,
|
|
150
|
+
decoded.targetStateAndStatus.selectedHeadingDeg,
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Each field is independently undefined when its source data isn't available -
|
|
156
|
+
`selectedAltitudeSource` further distinguishes an MCP/FCU-selected altitude
|
|
157
|
+
from an FMS-selected one. `autopilotEngaged`/`vnavModeActive`/`altitudeHoldModeActive`/`approachModeActive`/`lnavModeActive`
|
|
158
|
+
are reported together (all defined or all undefined) since they share a
|
|
159
|
+
single status bit; `tcasOperational` has its own independent status.
|
|
160
|
+
|
|
161
|
+
### Aircraft operational status
|
|
162
|
+
|
|
163
|
+
A type-code-31 ADS-B message reports the transmitting aircraft's ADS-B
|
|
164
|
+
version, surveillance integrity/accuracy figures, and heading reference -
|
|
165
|
+
metadata about the quality of the aircraft's other broadcasts rather than
|
|
166
|
+
its position or state:
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
const decoded = decodeModeSMessage(rawMessageBytes);
|
|
170
|
+
if (decoded?.kind === 'extendedSquitterOperationalStatus') {
|
|
171
|
+
console.log(
|
|
172
|
+
decoded.operationalStatus.adsbVersion,
|
|
173
|
+
decoded.operationalStatus.navAccuracyCategoryPosition,
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
`capabilityClassCode`/`operationalModeCode` are exposed as their raw 16-bit
|
|
179
|
+
values rather than individually decoded sub-fields. `nicBaro` is only
|
|
180
|
+
populated for an airborne report on ADS-B version 1+; `silSupplementPerHour`
|
|
181
|
+
is only populated on version 2, where SIL changes from "per sample" to a
|
|
182
|
+
choice between per-sample and per-hour.
|
|
183
|
+
|
|
184
|
+
### Enhanced Surveillance Comm-B registers
|
|
185
|
+
|
|
186
|
+
DF20/21's 56-bit MB field can carry any of several "Enhanced Surveillance"
|
|
187
|
+
Comm-B registers (BDS 4,0 selected vertical intention, BDS 5,0 track and
|
|
188
|
+
turn report, BDS 6,0 heading and speed report), but unlike a DF17/18 ME
|
|
189
|
+
field's type code, nothing in the message itself declares which one. This
|
|
190
|
+
package validates the MB field's bytes against each register's expected
|
|
191
|
+
structure (status-bit consistency, reserved bits, physically-plausible
|
|
192
|
+
ranges) and returns every register that plausibly matches - usually exactly
|
|
193
|
+
one, occasionally none, and occasionally more than one when the bytes are
|
|
194
|
+
genuinely ambiguous (BDS 5,0 and 6,0 are the pair most likely to overlap):
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
const decoded = decodeModeSMessage(rawMessageBytes);
|
|
198
|
+
if (decoded?.kind === 'commBAltitudeReply') {
|
|
199
|
+
for (const register of decoded.commBRegisters) {
|
|
200
|
+
if (register.bdsCode === '5,0') {
|
|
201
|
+
console.log(register.rollAngleDeg, register.trueTrackDeg, register.groundSpeedKt);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
`inferCommBRegisters(mb)` is also exported directly for callers working with
|
|
208
|
+
a raw MB field outside of `decodeModeSMessage`'s DF20/21 dispatch.
|
|
209
|
+
|
|
210
|
+
### Mode A/C
|
|
211
|
+
|
|
212
|
+
Mode A/C predates Mode-S and carries no ICAO address, so it has no natural
|
|
213
|
+
key in an ICAO-hex-indexed tracking model - it's decoded here, but
|
|
214
|
+
deliberately not part of `decodeModeSMessage`'s dispatch:
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
import { decodeModeAc } from '@squawk/mode-s';
|
|
218
|
+
|
|
219
|
+
const reply = decodeModeAc(twoRawBytes);
|
|
220
|
+
console.log(reply.squawk, reply.identActive, reply.altitudeFt);
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## API
|
|
224
|
+
|
|
225
|
+
- `decodeModeSMessage(bytes)` - decodes a raw 7 or 14 byte Mode-S message into a discriminated `DecodedModeSMessage`.
|
|
226
|
+
- `decodeModeAc(bytes)` - decodes a raw 2-byte Mode A/C reply.
|
|
227
|
+
- `parseModeSFrame(bytes)`, `extractDownlinkFormat(bytes)`, `computeCrc24(bytes)` - lower-level envelope parsing, used internally by `decodeModeSMessage`.
|
|
228
|
+
- `decodeAirborneCprPair`, `decodeAirborneCprWithReference`, `decodeSurfaceCprPair`, `decodeSurfaceCprWithReference`, `cprNumLongitudeZones` - CPR position resolution.
|
|
229
|
+
- `decodeAirborneVelocity(me)` - airborne velocity/heading from a type-19 ME field.
|
|
230
|
+
- `decodeIdentification(me)` - callsign and category from a type 1-4 ME field.
|
|
231
|
+
- `decodeIdentityCode(idField)` - 4-digit octal squawk from a 13-bit identity field (shared by DF5/21 and ADS-B emergency status).
|
|
232
|
+
- `decodeAltitudeCode(altitudeCode)`, `decodeAdsbPositionAltitude(field)`, `decodeAdsbGnssAltitude(field)` - altitude decoding.
|
|
233
|
+
- `decodeSurfaceMovement(field)` - ground speed from a surface position message's movement field.
|
|
234
|
+
- `decodeEmergencyState(rawState)` - emergency/priority state from an ADS-B aircraft status message.
|
|
235
|
+
- `decodeAcasResolutionAdvisory(payload)` - ACAS/TCAS Resolution Advisory report from a DF16 MV field or a type-code-28 subtype-2 ME field.
|
|
236
|
+
- `decodeTargetStateAndStatus(me)` - target state and status from a type-29 ME field.
|
|
237
|
+
- `decodeAircraftOperationalStatus(me)` - operational status from a type-31 ME field.
|
|
238
|
+
- `inferCommBRegisters(mb)` - every Enhanced Surveillance Comm-B register (BDS 4,0/5,0/6,0) a DF20/21 MB field plausibly holds.
|
|
239
|
+
- `decodeSelectedVerticalIntention(mb)`, `decodeTrackAndTurnReport(mb)`, `decodeHeadingAndSpeedReport(mb)` - decode a single Comm-B register directly, given its BDS code is already known.
|
|
240
|
+
|
|
241
|
+
Every decoder that can fail to produce a result returns `undefined` rather
|
|
242
|
+
than throwing - a message that doesn't decode cleanly (unsupported type,
|
|
243
|
+
failed CRC, reserved value) is an expected outcome, not an exceptional one.
|
package/dist/acas.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AcasResolutionAdvisoryReport } from './types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Decodes an ACAS/TCAS Resolution Advisory report (BDS 3,0 content), shared
|
|
4
|
+
* by DF16's MV field and a DF17/18 type-code-28 subtype-2 ME field - both
|
|
5
|
+
* carry the same 48 bits of content starting at bit 8 of the 7-byte buffer
|
|
6
|
+
* (DF16's MV reserves its first byte for a register-identifier convention;
|
|
7
|
+
* TC28/ST2's ME uses that same first byte for its type-code-and-subtype
|
|
8
|
+
* header instead - either way, content starts at bit 8).
|
|
9
|
+
*
|
|
10
|
+
* @param payload - The 7-byte field: DF16's MV, or a type-code-28 subtype-2 ME.
|
|
11
|
+
* @returns The decoded report, or undefined if the Threat Type Indicator is the reserved value (not a legitimate report).
|
|
12
|
+
*/
|
|
13
|
+
export declare function decodeAcasResolutionAdvisory(payload: Uint8Array): AcasResolutionAdvisoryReport | undefined;
|
|
14
|
+
//# sourceMappingURL=acas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acas.d.ts","sourceRoot":"","sources":["../src/acas.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,4BAA4B,EAG7B,MAAM,kBAAkB,CAAC;AA4D1B;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,UAAU,GAClB,4BAA4B,GAAG,SAAS,CAuC1C"}
|
package/dist/acas.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { decodeAltitudeCode } from './altitude.js';
|
|
2
|
+
import { extractBits, formatHexAddress } from './bits.js';
|
|
3
|
+
/** Reserved Threat Type Indicator value - not a legitimate report. */
|
|
4
|
+
const TTI_RESERVED = 3;
|
|
5
|
+
/** Decodes the threat-identity data (bits 28-55) per the Threat Type Indicator, `threatTypeIndicator`. */
|
|
6
|
+
function decodeThreat(payload, threatTypeIndicator) {
|
|
7
|
+
if (threatTypeIndicator === 1) {
|
|
8
|
+
return {
|
|
9
|
+
threatType: 'icaoAddress',
|
|
10
|
+
threatIcaoHex: formatHexAddress(extractBits(payload, 30, 24)),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
if (threatTypeIndicator === 2) {
|
|
14
|
+
const rangeRaw = extractBits(payload, 43, 7);
|
|
15
|
+
const bearingRaw = extractBits(payload, 50, 6);
|
|
16
|
+
return {
|
|
17
|
+
threatType: 'altitudeRangeBearing',
|
|
18
|
+
threatAltitudeFt: decodeAltitudeCode(extractBits(payload, 30, 13)),
|
|
19
|
+
threatRangeNm: rangeRaw > 0 ? (rangeRaw - 1) / 10 : undefined,
|
|
20
|
+
threatBearingDeg: bearingRaw > 0 ? 6 * (bearingRaw - 1) + 3 : undefined,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return { threatType: 'none' };
|
|
24
|
+
}
|
|
25
|
+
function decodeAdvisoryType(active, corrective, downwardSense, increasedRate, senseReversal, altitudeCrossing, positive) {
|
|
26
|
+
if (!active) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
if (!corrective) {
|
|
30
|
+
// Preventive: DO-185B defines no positive-preventive RA type.
|
|
31
|
+
if (positive) {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
return downwardSense ? 'doNotClimb' : 'doNotDescend';
|
|
35
|
+
}
|
|
36
|
+
if (senseReversal) {
|
|
37
|
+
return downwardSense ? 'reversalToDescend' : 'reversalToClimb';
|
|
38
|
+
}
|
|
39
|
+
if (increasedRate) {
|
|
40
|
+
return downwardSense ? 'increaseDescent' : 'increaseClimb';
|
|
41
|
+
}
|
|
42
|
+
if (!positive) {
|
|
43
|
+
return downwardSense ? 'reduceClimb' : 'reduceDescent';
|
|
44
|
+
}
|
|
45
|
+
if (downwardSense) {
|
|
46
|
+
return altitudeCrossing ? 'crossingDescend' : 'descend';
|
|
47
|
+
}
|
|
48
|
+
return altitudeCrossing ? 'crossingClimb' : 'climb';
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Decodes an ACAS/TCAS Resolution Advisory report (BDS 3,0 content), shared
|
|
52
|
+
* by DF16's MV field and a DF17/18 type-code-28 subtype-2 ME field - both
|
|
53
|
+
* carry the same 48 bits of content starting at bit 8 of the 7-byte buffer
|
|
54
|
+
* (DF16's MV reserves its first byte for a register-identifier convention;
|
|
55
|
+
* TC28/ST2's ME uses that same first byte for its type-code-and-subtype
|
|
56
|
+
* header instead - either way, content starts at bit 8).
|
|
57
|
+
*
|
|
58
|
+
* @param payload - The 7-byte field: DF16's MV, or a type-code-28 subtype-2 ME.
|
|
59
|
+
* @returns The decoded report, or undefined if the Threat Type Indicator is the reserved value (not a legitimate report).
|
|
60
|
+
*/
|
|
61
|
+
export function decodeAcasResolutionAdvisory(payload) {
|
|
62
|
+
const threatTypeIndicator = extractBits(payload, 28, 2);
|
|
63
|
+
if (threatTypeIndicator === TTI_RESERVED) {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
const active = extractBits(payload, 8, 1) === 1;
|
|
67
|
+
const corrective = extractBits(payload, 9, 1) === 1;
|
|
68
|
+
const downwardSense = extractBits(payload, 10, 1) === 1;
|
|
69
|
+
const increasedRate = extractBits(payload, 11, 1) === 1;
|
|
70
|
+
const senseReversal = extractBits(payload, 12, 1) === 1;
|
|
71
|
+
const altitudeCrossing = extractBits(payload, 13, 1) === 1;
|
|
72
|
+
const positive = extractBits(payload, 14, 1) === 1;
|
|
73
|
+
return {
|
|
74
|
+
active,
|
|
75
|
+
advisoryType: decodeAdvisoryType(active, corrective, downwardSense, increasedRate, senseReversal, altitudeCrossing, positive),
|
|
76
|
+
corrective,
|
|
77
|
+
downwardSense,
|
|
78
|
+
increasedRate,
|
|
79
|
+
senseReversal,
|
|
80
|
+
altitudeCrossing,
|
|
81
|
+
positive,
|
|
82
|
+
doNotPassBelow: extractBits(payload, 22, 1) === 1,
|
|
83
|
+
doNotPassAbove: extractBits(payload, 23, 1) === 1,
|
|
84
|
+
doNotTurnLeft: extractBits(payload, 24, 1) === 1,
|
|
85
|
+
doNotTurnRight: extractBits(payload, 25, 1) === 1,
|
|
86
|
+
terminated: extractBits(payload, 26, 1) === 1,
|
|
87
|
+
multipleThreat: extractBits(payload, 27, 1) === 1,
|
|
88
|
+
threat: decodeThreat(payload, threatTypeIndicator),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decodes a 13-bit Mode-S altitude code (the AC field of DF0/4/16/20
|
|
3
|
+
* surveillance replies) to feet, per ICAO Annex 10 Vol. IV / RTCA DO-260.
|
|
4
|
+
*
|
|
5
|
+
* The field supports two encodings, selected by the Q bit: a 25-foot
|
|
6
|
+
* linear encoding (Q=1), or a 100-foot Gillham (Gray code) encoding
|
|
7
|
+
* (Q=0) - the legacy scheme shared with Mode-C. Bit layout, MSB first:
|
|
8
|
+
* `C1 A1 C2 A2 C4 A4 M B1 Q B2 D2 B4 D4`.
|
|
9
|
+
*
|
|
10
|
+
* @param altitudeCode - The raw 13-bit AC field, 0-8191.
|
|
11
|
+
* @returns Altitude in feet, or undefined if the field is all-zero (altitude unknown), reports the rare M (metric) encoding, or contains an invalid Gillham value.
|
|
12
|
+
*/
|
|
13
|
+
export declare function decodeAltitudeCode(altitudeCode: number): number | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Decodes the 12-bit altitude field of an ADS-B airborne position message
|
|
16
|
+
* (type codes 9-18, barometric altitude). The field omits the M bit that
|
|
17
|
+
* {@link decodeAltitudeCode}'s 13-bit AC field carries, so it is
|
|
18
|
+
* re-inserted (always 0 - the M encoding never appears in ADS-B position
|
|
19
|
+
* messages) before delegating to the shared Gillham/linear decoder.
|
|
20
|
+
*
|
|
21
|
+
* @param positionAltitudeField - The raw 12-bit altitude field from bits 8-19 of an airborne position ME field.
|
|
22
|
+
* @returns Altitude in feet, or undefined if unavailable.
|
|
23
|
+
*/
|
|
24
|
+
export declare function decodeAdsbPositionAltitude(positionAltitudeField: number): number | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Decodes the GNSS altitude field of an ADS-B airborne position message
|
|
27
|
+
* (type codes 20-22). Unlike barometric altitude, this field is a plain
|
|
28
|
+
* 12-bit integer in meters - no Gillham or linear-code decoding involved.
|
|
29
|
+
*
|
|
30
|
+
* @param gnssAltitudeField - The raw 12-bit altitude field from bits 8-19 of a GNSS-altitude position ME field.
|
|
31
|
+
* @returns Altitude in feet.
|
|
32
|
+
*/
|
|
33
|
+
export declare function decodeAdsbGnssAltitude(gnssAltitudeField: number): number;
|
|
34
|
+
//# sourceMappingURL=altitude.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"altitude.d.ts","sourceRoot":"","sources":["../src/altitude.ts"],"names":[],"mappings":"AAiBA;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAyD3E;AAED;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAC,qBAAqB,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG5F;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAExE"}
|
package/dist/altitude.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { bitAt } from './bits.js';
|
|
2
|
+
/** 13-bit field width shared by the altitude (AC) and identity (ID) fields. */
|
|
3
|
+
const FIELD_WIDTH = 13;
|
|
4
|
+
/**
|
|
5
|
+
* Converts an unsigned Gillham code (a reflected Gray-code variant) to a
|
|
6
|
+
* plain binary integer via the standard Gray-to-binary fold.
|
|
7
|
+
*/
|
|
8
|
+
function grayToBinary(value, bitWidth) {
|
|
9
|
+
let result = value;
|
|
10
|
+
for (let shift = 1; shift < bitWidth; shift *= 2) {
|
|
11
|
+
result ^= result >> shift;
|
|
12
|
+
}
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Decodes a 13-bit Mode-S altitude code (the AC field of DF0/4/16/20
|
|
17
|
+
* surveillance replies) to feet, per ICAO Annex 10 Vol. IV / RTCA DO-260.
|
|
18
|
+
*
|
|
19
|
+
* The field supports two encodings, selected by the Q bit: a 25-foot
|
|
20
|
+
* linear encoding (Q=1), or a 100-foot Gillham (Gray code) encoding
|
|
21
|
+
* (Q=0) - the legacy scheme shared with Mode-C. Bit layout, MSB first:
|
|
22
|
+
* `C1 A1 C2 A2 C4 A4 M B1 Q B2 D2 B4 D4`.
|
|
23
|
+
*
|
|
24
|
+
* @param altitudeCode - The raw 13-bit AC field, 0-8191.
|
|
25
|
+
* @returns Altitude in feet, or undefined if the field is all-zero (altitude unknown), reports the rare M (metric) encoding, or contains an invalid Gillham value.
|
|
26
|
+
*/
|
|
27
|
+
export function decodeAltitudeCode(altitudeCode) {
|
|
28
|
+
if (altitudeCode === 0) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
const bitOf = (pos) => bitAt(altitudeCode, pos, FIELD_WIDTH);
|
|
32
|
+
const mBit = bitOf(6);
|
|
33
|
+
const qBit = bitOf(8);
|
|
34
|
+
if (mBit === 0 && qBit === 1) {
|
|
35
|
+
// 25-foot linear encoding: drop the M and Q bits, the remaining 11 bits
|
|
36
|
+
// form the value - the top 6 bits (C1A1C2A2C4A4), then B1, then the
|
|
37
|
+
// bottom 4 bits (B2D2B4D4).
|
|
38
|
+
const topSixBits = (altitudeCode >> 7) & 0x3f;
|
|
39
|
+
const bottomFourBits = altitudeCode & 0xf;
|
|
40
|
+
const n = (topSixBits << 5) | (bitOf(7) << 4) | bottomFourBits;
|
|
41
|
+
return n * 25 - 1000;
|
|
42
|
+
}
|
|
43
|
+
if (mBit === 0 && qBit === 0) {
|
|
44
|
+
const c1 = bitOf(0);
|
|
45
|
+
const a1 = bitOf(1);
|
|
46
|
+
const c2 = bitOf(2);
|
|
47
|
+
const a2 = bitOf(3);
|
|
48
|
+
const c4 = bitOf(4);
|
|
49
|
+
const a4 = bitOf(5);
|
|
50
|
+
const b1 = bitOf(7);
|
|
51
|
+
const b2 = bitOf(9);
|
|
52
|
+
const d2 = bitOf(10);
|
|
53
|
+
const b4 = bitOf(11);
|
|
54
|
+
const d4 = bitOf(12);
|
|
55
|
+
// Re-order into an 8-bit 500 ft Gillham counter and a 3-bit 100 ft
|
|
56
|
+
// Gillham counter, per ICAO Annex 10 Vol. IV / DO-260.
|
|
57
|
+
const gray500 = (d2 << 7) | (d4 << 6) | (a1 << 5) | (a2 << 4) | (a4 << 3) | (b1 << 2) | (b2 << 1) | b4;
|
|
58
|
+
const gray100 = (c1 << 2) | (c2 << 1) | c4;
|
|
59
|
+
const n500 = grayToBinary(gray500, 8);
|
|
60
|
+
let n100 = grayToBinary(gray100, 4);
|
|
61
|
+
if (n100 === 0 || n100 === 5 || n100 === 6) {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
if (n100 === 7) {
|
|
65
|
+
n100 = 5;
|
|
66
|
+
}
|
|
67
|
+
if (n500 % 2 === 1) {
|
|
68
|
+
n100 = 6 - n100;
|
|
69
|
+
}
|
|
70
|
+
return n500 * 500 + n100 * 100 - 1300;
|
|
71
|
+
}
|
|
72
|
+
// M = 1: rare, non-standard meter-based encoding. Not decoded.
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Decodes the 12-bit altitude field of an ADS-B airborne position message
|
|
77
|
+
* (type codes 9-18, barometric altitude). The field omits the M bit that
|
|
78
|
+
* {@link decodeAltitudeCode}'s 13-bit AC field carries, so it is
|
|
79
|
+
* re-inserted (always 0 - the M encoding never appears in ADS-B position
|
|
80
|
+
* messages) before delegating to the shared Gillham/linear decoder.
|
|
81
|
+
*
|
|
82
|
+
* @param positionAltitudeField - The raw 12-bit altitude field from bits 8-19 of an airborne position ME field.
|
|
83
|
+
* @returns Altitude in feet, or undefined if unavailable.
|
|
84
|
+
*/
|
|
85
|
+
export function decodeAdsbPositionAltitude(positionAltitudeField) {
|
|
86
|
+
const altitudeCode = ((positionAltitudeField >> 6) << 7) | (positionAltitudeField & 0x3f);
|
|
87
|
+
return decodeAltitudeCode(altitudeCode);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Decodes the GNSS altitude field of an ADS-B airborne position message
|
|
91
|
+
* (type codes 20-22). Unlike barometric altitude, this field is a plain
|
|
92
|
+
* 12-bit integer in meters - no Gillham or linear-code decoding involved.
|
|
93
|
+
*
|
|
94
|
+
* @param gnssAltitudeField - The raw 12-bit altitude field from bits 8-19 of a GNSS-altitude position ME field.
|
|
95
|
+
* @returns Altitude in feet.
|
|
96
|
+
*/
|
|
97
|
+
export function decodeAdsbGnssAltitude(gnssAltitudeField) {
|
|
98
|
+
return Math.round(gnssAltitudeField * 3.28084);
|
|
99
|
+
}
|
package/dist/bits.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts an unsigned integer from `bitLength` bits starting at `bitOffset`
|
|
3
|
+
* (0-indexed from the MSB of `bytes`), crossing byte boundaries as needed.
|
|
4
|
+
*
|
|
5
|
+
* JavaScript's bitwise operators work on 32-bit signed integers, so a raw
|
|
6
|
+
* Mode-S ME field (56 bits) can't be treated as one shifted integer the way
|
|
7
|
+
* a language with arbitrary-precision integers can. This reads bit by bit
|
|
8
|
+
* instead, safe for any field up to 31 bits - comfortably more than any
|
|
9
|
+
* single field this package decodes.
|
|
10
|
+
*
|
|
11
|
+
* @param bytes - The byte array to read from.
|
|
12
|
+
* @param bitOffset - Index of the first bit to read, 0-indexed from the MSB of `bytes[0]`.
|
|
13
|
+
* @param bitLength - Number of bits to read.
|
|
14
|
+
* @returns The extracted value as an unsigned integer.
|
|
15
|
+
*/
|
|
16
|
+
export declare function extractBits(bytes: Uint8Array, bitOffset: number, bitLength: number): number;
|
|
17
|
+
/**
|
|
18
|
+
* Extracts a single bit directly from an already-extracted integer field,
|
|
19
|
+
* at `bitPosition` (0-indexed from the MSB of a `fieldWidth`-bit field).
|
|
20
|
+
* For fields already narrow enough to fit safely in a plain 32-bit
|
|
21
|
+
* bitwise op (comfortably true for anything this package decodes, e.g. a
|
|
22
|
+
* 13-bit identity or altitude code) - {@link extractBits}'s byte-array
|
|
23
|
+
* form exists to cross byte boundaries within a much wider ME field, which
|
|
24
|
+
* a single already-extracted small field never needs to do.
|
|
25
|
+
*
|
|
26
|
+
* @param value - The field's value, e.g. a 13-bit integer in [0, 8191].
|
|
27
|
+
* @param bitPosition - Index of the bit to read, 0-indexed from the MSB.
|
|
28
|
+
* @param fieldWidth - Total width of the field in bits.
|
|
29
|
+
* @returns The bit at that position, 0 or 1.
|
|
30
|
+
*/
|
|
31
|
+
export declare function bitAt(value: number, bitPosition: number, fieldWidth: number): number;
|
|
32
|
+
/**
|
|
33
|
+
* Formats a 24-bit value (an ICAO address, a recovered CRC-XOR address, or
|
|
34
|
+
* any other 24-bit identifier this package handles) as 6 uppercase hex
|
|
35
|
+
* digits, zero-padded.
|
|
36
|
+
*
|
|
37
|
+
* @param value - The 24-bit value, 0-16777215.
|
|
38
|
+
* @returns The value as 6 uppercase hex digits.
|
|
39
|
+
*/
|
|
40
|
+
export declare function formatHexAddress(value: number): string;
|
|
41
|
+
//# sourceMappingURL=bits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bits.d.ts","sourceRoot":"","sources":["../src/bits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAW3F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAEpF;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD"}
|
package/dist/bits.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts an unsigned integer from `bitLength` bits starting at `bitOffset`
|
|
3
|
+
* (0-indexed from the MSB of `bytes`), crossing byte boundaries as needed.
|
|
4
|
+
*
|
|
5
|
+
* JavaScript's bitwise operators work on 32-bit signed integers, so a raw
|
|
6
|
+
* Mode-S ME field (56 bits) can't be treated as one shifted integer the way
|
|
7
|
+
* a language with arbitrary-precision integers can. This reads bit by bit
|
|
8
|
+
* instead, safe for any field up to 31 bits - comfortably more than any
|
|
9
|
+
* single field this package decodes.
|
|
10
|
+
*
|
|
11
|
+
* @param bytes - The byte array to read from.
|
|
12
|
+
* @param bitOffset - Index of the first bit to read, 0-indexed from the MSB of `bytes[0]`.
|
|
13
|
+
* @param bitLength - Number of bits to read.
|
|
14
|
+
* @returns The extracted value as an unsigned integer.
|
|
15
|
+
*/
|
|
16
|
+
export function extractBits(bytes, bitOffset, bitLength) {
|
|
17
|
+
let value = 0;
|
|
18
|
+
for (let i = 0; i < bitLength; i++) {
|
|
19
|
+
const bitPos = bitOffset + i;
|
|
20
|
+
const byteIndex = bitPos >> 3;
|
|
21
|
+
const bitInByte = 7 - (bitPos & 7);
|
|
22
|
+
const byte = bytes[byteIndex] ?? 0;
|
|
23
|
+
const bit = (byte >> bitInByte) & 1;
|
|
24
|
+
value = (value << 1) | bit;
|
|
25
|
+
}
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Extracts a single bit directly from an already-extracted integer field,
|
|
30
|
+
* at `bitPosition` (0-indexed from the MSB of a `fieldWidth`-bit field).
|
|
31
|
+
* For fields already narrow enough to fit safely in a plain 32-bit
|
|
32
|
+
* bitwise op (comfortably true for anything this package decodes, e.g. a
|
|
33
|
+
* 13-bit identity or altitude code) - {@link extractBits}'s byte-array
|
|
34
|
+
* form exists to cross byte boundaries within a much wider ME field, which
|
|
35
|
+
* a single already-extracted small field never needs to do.
|
|
36
|
+
*
|
|
37
|
+
* @param value - The field's value, e.g. a 13-bit integer in [0, 8191].
|
|
38
|
+
* @param bitPosition - Index of the bit to read, 0-indexed from the MSB.
|
|
39
|
+
* @param fieldWidth - Total width of the field in bits.
|
|
40
|
+
* @returns The bit at that position, 0 or 1.
|
|
41
|
+
*/
|
|
42
|
+
export function bitAt(value, bitPosition, fieldWidth) {
|
|
43
|
+
return (value >> (fieldWidth - 1 - bitPosition)) & 1;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Formats a 24-bit value (an ICAO address, a recovered CRC-XOR address, or
|
|
47
|
+
* any other 24-bit identifier this package handles) as 6 uppercase hex
|
|
48
|
+
* digits, zero-padded.
|
|
49
|
+
*
|
|
50
|
+
* @param value - The 24-bit value, 0-16777215.
|
|
51
|
+
* @returns The value as 6 uppercase hex digits.
|
|
52
|
+
*/
|
|
53
|
+
export function formatHexAddress(value) {
|
|
54
|
+
return value.toString(16).padStart(6, '0').toUpperCase();
|
|
55
|
+
}
|
package/dist/comm-b.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { CommBRegister, HeadingAndSpeedReport, SelectedVerticalIntention, TrackAndTurnReport } from './types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Decodes a BDS 4,0 (Selected Vertical Intention) register.
|
|
4
|
+
*
|
|
5
|
+
* @param mb - The 7-byte MB field of a DF20/21 Comm-B reply, already known (or inferred via {@link inferCommBRegisters}) to be BDS 4,0.
|
|
6
|
+
* @returns The decoded selected vertical intention.
|
|
7
|
+
*/
|
|
8
|
+
export declare function decodeSelectedVerticalIntention(mb: Uint8Array): SelectedVerticalIntention;
|
|
9
|
+
/**
|
|
10
|
+
* Decodes a BDS 5,0 (Track and Turn Report) register.
|
|
11
|
+
*
|
|
12
|
+
* @param mb - The 7-byte MB field of a DF20/21 Comm-B reply, already known (or inferred via {@link inferCommBRegisters}) to be BDS 5,0.
|
|
13
|
+
* @returns The decoded track and turn report.
|
|
14
|
+
*/
|
|
15
|
+
export declare function decodeTrackAndTurnReport(mb: Uint8Array): TrackAndTurnReport;
|
|
16
|
+
/**
|
|
17
|
+
* Decodes a BDS 6,0 (Heading and Speed Report) register.
|
|
18
|
+
*
|
|
19
|
+
* @param mb - The 7-byte MB field of a DF20/21 Comm-B reply, already known (or inferred via {@link inferCommBRegisters}) to be BDS 6,0.
|
|
20
|
+
* @returns The decoded heading and speed report.
|
|
21
|
+
*/
|
|
22
|
+
export declare function decodeHeadingAndSpeedReport(mb: Uint8Array): HeadingAndSpeedReport;
|
|
23
|
+
/**
|
|
24
|
+
* Infers which "Enhanced Surveillance" Comm-B register(s) a DF20/21 MB
|
|
25
|
+
* field plausibly holds, and decodes each. Unlike DF17/18's type-code-coded
|
|
26
|
+
* ME field, a Comm-B MB field carries no self-declared register identifier
|
|
27
|
+
* for BDS 4,0/5,0/6,0 - this package would rather report every plausible
|
|
28
|
+
* candidate (via structural and range validation, matching pyModeS's own
|
|
29
|
+
* approach to this exact ambiguity) than silently guess a single wrong
|
|
30
|
+
* answer. In practice this is usually unambiguous; BDS 5,0 and 6,0 are the
|
|
31
|
+
* pair most likely to both pass validation for the same bytes.
|
|
32
|
+
*
|
|
33
|
+
* @param mb - The 7-byte MB field of a DF20/21 Comm-B reply.
|
|
34
|
+
* @returns Every register this MB field plausibly holds - empty if none, one if unambiguous, more than one if genuinely ambiguous.
|
|
35
|
+
*/
|
|
36
|
+
export declare function inferCommBRegisters(mb: Uint8Array): CommBRegister[];
|
|
37
|
+
//# sourceMappingURL=comm-b.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comm-b.d.ts","sourceRoot":"","sources":["../src/comm-b.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EACb,qBAAqB,EACrB,yBAAyB,EACzB,kBAAkB,EACnB,MAAM,kBAAkB,CAAC;AA6E1B;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,EAAE,EAAE,UAAU,GAAG,yBAAyB,CAkBzF;AA6CD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,UAAU,GAAG,kBAAkB,CA0B3E;AAoDD;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,EAAE,EAAE,UAAU,GAAG,qBAAqB,CAoBjF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,UAAU,GAAG,aAAa,EAAE,CAYnE"}
|