@squawk/mode-s 0.3.0 → 0.3.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.
package/dist/acas.d.ts CHANGED
@@ -7,6 +7,15 @@ import type { AcasResolutionAdvisoryReport } from './types/index.js';
7
7
  * TC28/ST2's ME uses that same first byte for its type-code-and-subtype
8
8
  * header instead - either way, content starts at bit 8).
9
9
  *
10
+ * This function assumes `payload` is already known to carry a genuine BDS
11
+ * 3,0 report - it does not itself check DF16's register-identifier byte,
12
+ * since a TC28/ST2 caller's first byte is never that identifier by
13
+ * construction. A DF16 caller must check that byte itself before calling
14
+ * this (see `decodeModeSMessage`'s DF16 branch) - DF16's MV is a
15
+ * general-purpose Comm-B register slot that can legitimately carry a
16
+ * different register, unlike TC28/ST2 which is gated by its own type-code
17
+ * and subtype instead.
18
+ *
10
19
  * @param payload - The 7-byte field: DF16's MV, or a type-code-28 subtype-2 ME.
11
20
  * @returns The decoded report, or undefined if the Threat Type Indicator is the reserved value (not a legitimate report).
12
21
  */
@@ -1 +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"}
1
+ {"version":3,"file":"acas.d.ts","sourceRoot":"","sources":["../src/acas.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,4BAA4B,EAG7B,MAAM,kBAAkB,CAAC;AA4D1B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,UAAU,GAClB,4BAA4B,GAAG,SAAS,CAuC1C"}
package/dist/acas.js CHANGED
@@ -55,6 +55,15 @@ function decodeAdvisoryType(active, corrective, downwardSense, increasedRate, se
55
55
  * TC28/ST2's ME uses that same first byte for its type-code-and-subtype
56
56
  * header instead - either way, content starts at bit 8).
57
57
  *
58
+ * This function assumes `payload` is already known to carry a genuine BDS
59
+ * 3,0 report - it does not itself check DF16's register-identifier byte,
60
+ * since a TC28/ST2 caller's first byte is never that identifier by
61
+ * construction. A DF16 caller must check that byte itself before calling
62
+ * this (see `decodeModeSMessage`'s DF16 branch) - DF16's MV is a
63
+ * general-purpose Comm-B register slot that can legitimately carry a
64
+ * different register, unlike TC28/ST2 which is gated by its own type-code
65
+ * and subtype instead.
66
+ *
58
67
  * @param payload - The 7-byte field: DF16's MV, or a type-code-28 subtype-2 ME.
59
68
  * @returns The decoded report, or undefined if the Threat Type Indicator is the reserved value (not a legitimate report).
60
69
  */
@@ -1 +1 @@
1
- {"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../src/message.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EACV,mBAAmB,EAGpB,MAAM,kBAAkB,CAAC;AAuN1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG,mBAAmB,GAAG,SAAS,CAiGrF"}
1
+ {"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../src/message.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EACV,mBAAmB,EAGpB,MAAM,kBAAkB,CAAC;AA0N1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG,mBAAmB,GAAG,SAAS,CA2GrF"}
package/dist/message.js CHANGED
@@ -20,6 +20,8 @@ import { decodeAirborneVelocity } from './velocity.js';
20
20
  * rather than a legitimate code.
21
21
  */
22
22
  const MAX_PLAUSIBLE_INTERROGATOR_CODE = 127;
23
+ /** BDS 3,0 (ACAS Active Resolution Advisory) register identifier, per ICAO Annex 10 Vol IV - the value a DF16 reply's MV field starts with when (and only when) it actually carries an RA report. */
24
+ const BDS_3_0_IDENTIFIER = 0x30;
23
25
  const TYPE_CODE_CATEGORIES = [
24
26
  { min: 0, max: 0, category: 'airborneBaroPosition' },
25
27
  { min: 1, max: 4, category: 'identification' },
@@ -254,10 +256,20 @@ export function decodeModeSMessage(bytes) {
254
256
  };
255
257
  }
256
258
  if (envelope.downlinkFormat === 16) {
259
+ const mv = bytes.slice(4, 11);
260
+ // Unlike TC28/ST2 (gated by its own type-code+subtype, checked before
261
+ // decodeAcasResolutionAdvisory is ever called), DF16's MV field is a
262
+ // general-purpose Comm-B register slot - it only carries a BDS 3,0
263
+ // report when its own register-identifier byte says so. A transponder
264
+ // can legitimately reply to a UF16 interrogation with a different
265
+ // register loaded into MV, so decoding it unconditionally would
266
+ // misinterpret unrelated register content as a phantom Resolution
267
+ // Advisory.
268
+ const isBds30 = extractBits(mv, 0, 8) === BDS_3_0_IDENTIFIER;
257
269
  return {
258
270
  kind: 'longAirAirSurveillanceReply',
259
271
  ...decodeAirAirSurveillanceCore(bytes, envelope.crcRemainder),
260
- resolutionAdvisory: decodeAcasResolutionAdvisory(bytes.slice(4, 11)),
272
+ resolutionAdvisory: isBds30 ? decodeAcasResolutionAdvisory(mv) : undefined,
261
273
  };
262
274
  }
263
275
  if (envelope.downlinkFormat === 4) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@squawk/mode-s",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "description": "Decode raw Mode-S/ADS-B messages: DF/CRC parsing, CPR position, velocity, identification, and altitude",
6
6
  "author": "Neil Cochran",