@airframes/acars-decoder 1.8.13 → 1.9.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/License.md +21 -0
- package/README.md +8 -11
- package/dist/index.d.mts +154 -2
- package/dist/index.d.ts +154 -2
- package/dist/index.js +634 -681
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +634 -681
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -122,56 +122,6 @@ var IcaoDecoder = class _IcaoDecoder {
|
|
|
122
122
|
}
|
|
123
123
|
};
|
|
124
124
|
|
|
125
|
-
// lib/DecoderPlugin.ts
|
|
126
|
-
var DecoderPlugin = class {
|
|
127
|
-
decoder;
|
|
128
|
-
name = "unknown";
|
|
129
|
-
defaultResult() {
|
|
130
|
-
return {
|
|
131
|
-
decoded: false,
|
|
132
|
-
decoder: {
|
|
133
|
-
name: "unknown",
|
|
134
|
-
type: "pattern-match",
|
|
135
|
-
decodeLevel: "none"
|
|
136
|
-
},
|
|
137
|
-
formatted: {
|
|
138
|
-
description: "Unknown",
|
|
139
|
-
items: []
|
|
140
|
-
},
|
|
141
|
-
raw: {},
|
|
142
|
-
remaining: {}
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
options;
|
|
146
|
-
constructor(decoder, options = {}) {
|
|
147
|
-
this.decoder = decoder;
|
|
148
|
-
this.options = options;
|
|
149
|
-
}
|
|
150
|
-
id() {
|
|
151
|
-
console.log(
|
|
152
|
-
"DecoderPlugin subclass has not overriden id() to provide a unique ID for this plugin!"
|
|
153
|
-
);
|
|
154
|
-
return "abstract_decoder_plugin";
|
|
155
|
-
}
|
|
156
|
-
meetsStateRequirements() {
|
|
157
|
-
return true;
|
|
158
|
-
}
|
|
159
|
-
// onRegister(store: Store<any>) {
|
|
160
|
-
// this.store = store;
|
|
161
|
-
// }
|
|
162
|
-
qualifiers() {
|
|
163
|
-
const labels = [];
|
|
164
|
-
return {
|
|
165
|
-
labels
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
decode(message) {
|
|
169
|
-
const decodeResult = this.defaultResult();
|
|
170
|
-
decodeResult.remaining.text = message.text;
|
|
171
|
-
return decodeResult;
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
|
|
175
125
|
// lib/utils/coordinate_utils.ts
|
|
176
126
|
var CoordinateUtils = class _CoordinateUtils {
|
|
177
127
|
/**
|
|
@@ -181,11 +131,11 @@ var CoordinateUtils = class _CoordinateUtils {
|
|
|
181
131
|
* @returns An object with latitude and longitude properties
|
|
182
132
|
*/
|
|
183
133
|
static decodeStringCoordinates(stringCoords) {
|
|
184
|
-
const firstChar = stringCoords.
|
|
185
|
-
let middleChar = stringCoords.
|
|
134
|
+
const firstChar = stringCoords.charAt(0);
|
|
135
|
+
let middleChar = stringCoords.charAt(6);
|
|
186
136
|
let longitudeChars = stringCoords.substring(7, 13);
|
|
187
|
-
if (middleChar
|
|
188
|
-
middleChar = stringCoords.
|
|
137
|
+
if (middleChar === " ") {
|
|
138
|
+
middleChar = stringCoords.charAt(7);
|
|
189
139
|
longitudeChars = stringCoords.substring(8, 14);
|
|
190
140
|
}
|
|
191
141
|
if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
|
|
@@ -203,24 +153,26 @@ var CoordinateUtils = class _CoordinateUtils {
|
|
|
203
153
|
* @returns An object with latitude and longitude properties
|
|
204
154
|
*/
|
|
205
155
|
static decodeStringCoordinatesDecimalMinutes(stringCoords) {
|
|
206
|
-
const firstChar = stringCoords.
|
|
207
|
-
let middleChar = stringCoords.
|
|
156
|
+
const firstChar = stringCoords.charAt(0);
|
|
157
|
+
let middleChar = stringCoords.charAt(6);
|
|
208
158
|
let longitudeChars = stringCoords.substring(7, 13);
|
|
209
|
-
if (middleChar
|
|
210
|
-
middleChar = stringCoords.
|
|
159
|
+
if (middleChar === " ") {
|
|
160
|
+
middleChar = stringCoords.charAt(7);
|
|
211
161
|
longitudeChars = stringCoords.substring(8, 14);
|
|
212
162
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
const lonDeg = Math.trunc(Number(longitudeChars) / 1e3);
|
|
216
|
-
const lonMin = Number(longitudeChars) % 1e3 / 10;
|
|
217
|
-
if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
|
|
218
|
-
return {
|
|
219
|
-
latitude: (latDeg + latMin / 60) * _CoordinateUtils.getDirection(firstChar),
|
|
220
|
-
longitude: (lonDeg + lonMin / 60) * _CoordinateUtils.getDirection(middleChar)
|
|
221
|
-
};
|
|
163
|
+
if (firstChar !== "N" && firstChar !== "S" || middleChar !== "W" && middleChar !== "E") {
|
|
164
|
+
return void 0;
|
|
222
165
|
}
|
|
223
|
-
|
|
166
|
+
const latRaw = Number(stringCoords.substring(1, 6));
|
|
167
|
+
const lonRaw = Number(longitudeChars);
|
|
168
|
+
const latDeg = Math.trunc(latRaw / 1e3);
|
|
169
|
+
const latMin = latRaw % 1e3 / 10;
|
|
170
|
+
const lonDeg = Math.trunc(lonRaw / 1e3);
|
|
171
|
+
const lonMin = lonRaw % 1e3 / 10;
|
|
172
|
+
return {
|
|
173
|
+
latitude: (latDeg + latMin / 60) * _CoordinateUtils.getDirection(firstChar),
|
|
174
|
+
longitude: (lonDeg + lonMin / 60) * _CoordinateUtils.getDirection(middleChar)
|
|
175
|
+
};
|
|
224
176
|
}
|
|
225
177
|
static coordinateString(coords) {
|
|
226
178
|
const latDir = coords.latitude > 0 ? "N" : "S";
|
|
@@ -251,25 +203,13 @@ var DateTimeUtils = class {
|
|
|
251
203
|
// Expects a six digit date string and a four digit UTC time string
|
|
252
204
|
// (DDMMYY) (HHMM)
|
|
253
205
|
static UTCDateTimeToString(dateString, timeString) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
utcDate.setUTCHours(
|
|
262
|
-
+timeString.substr(0, 2),
|
|
263
|
-
+timeString.substr(2, 2),
|
|
264
|
-
+timeString.substr(4, 2)
|
|
265
|
-
);
|
|
266
|
-
} else {
|
|
267
|
-
utcDate.setUTCHours(
|
|
268
|
-
+timeString.substr(0, 2),
|
|
269
|
-
+timeString.substr(2, 2),
|
|
270
|
-
0
|
|
271
|
-
);
|
|
272
|
-
}
|
|
206
|
+
const day = +dateString.substr(0, 2);
|
|
207
|
+
const month = +dateString.substr(2, 2) - 1;
|
|
208
|
+
const year = dateString.length === 6 ? 2e3 + +dateString.substr(4, 2) : (/* @__PURE__ */ new Date()).getUTCFullYear();
|
|
209
|
+
const hours = +timeString.substr(0, 2);
|
|
210
|
+
const minutes = +timeString.substr(2, 2);
|
|
211
|
+
const seconds = timeString.length === 6 ? +timeString.substr(4, 2) : 0;
|
|
212
|
+
const utcDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds));
|
|
273
213
|
return utcDate.toUTCString();
|
|
274
214
|
}
|
|
275
215
|
/**
|
|
@@ -614,7 +554,7 @@ var ResultFormatter = class {
|
|
|
614
554
|
decodeResult.raw.fuel_remaining = value;
|
|
615
555
|
decodeResult.formatted.items.push({
|
|
616
556
|
type: "fuel_remaining",
|
|
617
|
-
code: "
|
|
557
|
+
code: "FUEL_REM",
|
|
618
558
|
label: "Fuel Remaining",
|
|
619
559
|
value: decodeResult.raw.fuel_remaining.toString()
|
|
620
560
|
});
|
|
@@ -1008,7 +948,7 @@ var ResultFormatter = class {
|
|
|
1008
948
|
type: "sequence",
|
|
1009
949
|
code: "SEQ",
|
|
1010
950
|
label: "Sequence Number",
|
|
1011
|
-
value: decodeResult.raw.sequence_number
|
|
951
|
+
value: decodeResult.raw.sequence_number.toString()
|
|
1012
952
|
});
|
|
1013
953
|
}
|
|
1014
954
|
static sequenceResponse(decodeResult, value) {
|
|
@@ -1017,7 +957,7 @@ var ResultFormatter = class {
|
|
|
1017
957
|
type: "sequence",
|
|
1018
958
|
code: "SEQ_RESP",
|
|
1019
959
|
label: "Sequence Response",
|
|
1020
|
-
value: decodeResult.raw.sequence_response
|
|
960
|
+
value: decodeResult.raw.sequence_response.toString()
|
|
1021
961
|
});
|
|
1022
962
|
}
|
|
1023
963
|
static unknown(decodeResult, value, sep = ",") {
|
|
@@ -1029,7 +969,101 @@ var ResultFormatter = class {
|
|
|
1029
969
|
}
|
|
1030
970
|
};
|
|
1031
971
|
|
|
972
|
+
// lib/DecoderPlugin.ts
|
|
973
|
+
var DecoderPlugin = class {
|
|
974
|
+
decoder;
|
|
975
|
+
name = "unknown";
|
|
976
|
+
defaultResult() {
|
|
977
|
+
return {
|
|
978
|
+
decoded: false,
|
|
979
|
+
decoder: {
|
|
980
|
+
name: "unknown",
|
|
981
|
+
type: "pattern-match",
|
|
982
|
+
decodeLevel: "none"
|
|
983
|
+
},
|
|
984
|
+
formatted: {
|
|
985
|
+
description: "Unknown",
|
|
986
|
+
items: []
|
|
987
|
+
},
|
|
988
|
+
raw: {},
|
|
989
|
+
remaining: {}
|
|
990
|
+
};
|
|
991
|
+
}
|
|
992
|
+
/**
|
|
993
|
+
* Creates a DecodeResult pre-populated with the plugin name, description, and message.
|
|
994
|
+
* Replaces the common boilerplate at the start of every decode() method.
|
|
995
|
+
*/
|
|
996
|
+
initResult(message, description) {
|
|
997
|
+
const result = this.defaultResult();
|
|
998
|
+
result.decoder.name = this.name;
|
|
999
|
+
result.formatted.description = description;
|
|
1000
|
+
result.message = message;
|
|
1001
|
+
return result;
|
|
1002
|
+
}
|
|
1003
|
+
/**
|
|
1004
|
+
* Sets the decoded flag and decodeLevel on a result.
|
|
1005
|
+
* If decoded is true and no explicit level is given, infers 'full' or 'partial'
|
|
1006
|
+
* based on whether remaining.text is set.
|
|
1007
|
+
*/
|
|
1008
|
+
setDecodeLevel(result, decoded, level) {
|
|
1009
|
+
result.decoded = decoded;
|
|
1010
|
+
if (decoded) {
|
|
1011
|
+
result.decoder.decodeLevel = level ?? (result.remaining.text ? "partial" : "full");
|
|
1012
|
+
} else {
|
|
1013
|
+
result.decoder.decodeLevel = "none";
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
/**
|
|
1017
|
+
* Logs a debug message prefixed with the plugin name, only if options.debug is true.
|
|
1018
|
+
*/
|
|
1019
|
+
debug(options, ...args) {
|
|
1020
|
+
if (options.debug) {
|
|
1021
|
+
console.log(`[${this.name}]`, ...args);
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
/**
|
|
1025
|
+
* Marks a result as a failed decode with 'none' level, sets the remaining text
|
|
1026
|
+
* as unknown, and logs a debug message. Returns the result for convenient early return.
|
|
1027
|
+
*/
|
|
1028
|
+
failUnknown(result, text, options = {}) {
|
|
1029
|
+
this.debug(options, `Unknown message: ${text}`);
|
|
1030
|
+
ResultFormatter.unknown(result, text);
|
|
1031
|
+
result.decoded = false;
|
|
1032
|
+
result.decoder.decodeLevel = "none";
|
|
1033
|
+
return result;
|
|
1034
|
+
}
|
|
1035
|
+
options;
|
|
1036
|
+
constructor(decoder, options = {}) {
|
|
1037
|
+
this.decoder = decoder;
|
|
1038
|
+
this.options = options;
|
|
1039
|
+
}
|
|
1040
|
+
id() {
|
|
1041
|
+
console.log(
|
|
1042
|
+
"DecoderPlugin subclass has not overriden id() to provide a unique ID for this plugin!"
|
|
1043
|
+
);
|
|
1044
|
+
return "abstract_decoder_plugin";
|
|
1045
|
+
}
|
|
1046
|
+
meetsStateRequirements() {
|
|
1047
|
+
return true;
|
|
1048
|
+
}
|
|
1049
|
+
// onRegister(store: Store<any>) {
|
|
1050
|
+
// this.store = store;
|
|
1051
|
+
// }
|
|
1052
|
+
qualifiers() {
|
|
1053
|
+
const labels = [];
|
|
1054
|
+
return {
|
|
1055
|
+
labels
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
1058
|
+
decode(message, options = {}) {
|
|
1059
|
+
const decodeResult = this.defaultResult();
|
|
1060
|
+
decodeResult.remaining.text = message.text;
|
|
1061
|
+
return decodeResult;
|
|
1062
|
+
}
|
|
1063
|
+
};
|
|
1064
|
+
|
|
1032
1065
|
// lib/plugins/CBand.ts
|
|
1066
|
+
var CBAND_HEADER = /^(?<msgno>[A-Z]\d{2}[A-Z])(?<airline>[A-Z0-9]{2})(?<number>[0-9]{4})/;
|
|
1033
1067
|
var CBand = class extends DecoderPlugin {
|
|
1034
1068
|
name = "c-band";
|
|
1035
1069
|
qualifiers() {
|
|
@@ -1038,35 +1072,43 @@ var CBand = class extends DecoderPlugin {
|
|
|
1038
1072
|
};
|
|
1039
1073
|
}
|
|
1040
1074
|
decode(message, options = {}) {
|
|
1041
|
-
|
|
1075
|
+
const text = message.text;
|
|
1076
|
+
if (text.length < 10) {
|
|
1077
|
+
const result = this.defaultResult();
|
|
1078
|
+
result.decoder.name = this.name;
|
|
1079
|
+
result.message = message;
|
|
1080
|
+
return result;
|
|
1081
|
+
}
|
|
1082
|
+
const cband = CBAND_HEADER.exec(text);
|
|
1083
|
+
if (!cband?.groups) {
|
|
1084
|
+
const result = this.defaultResult();
|
|
1085
|
+
result.decoder.name = this.name;
|
|
1086
|
+
result.message = message;
|
|
1087
|
+
return result;
|
|
1088
|
+
}
|
|
1089
|
+
const decoded = this.decoder.decode(
|
|
1090
|
+
{
|
|
1091
|
+
label: message.label,
|
|
1092
|
+
sublabel: message.sublabel,
|
|
1093
|
+
text: text.substring(10)
|
|
1094
|
+
},
|
|
1095
|
+
options
|
|
1096
|
+
);
|
|
1097
|
+
const decodeResult = this.defaultResult();
|
|
1042
1098
|
decodeResult.decoder.name = this.name;
|
|
1043
1099
|
decodeResult.message = message;
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
const messageText = message.text.substring(10);
|
|
1049
|
-
const decoded = this.decoder.decode(
|
|
1050
|
-
{
|
|
1051
|
-
label: message.label,
|
|
1052
|
-
sublabel: message.sublabel,
|
|
1053
|
-
text: messageText
|
|
1054
|
-
},
|
|
1055
|
-
options
|
|
1100
|
+
if (decoded.decoded) {
|
|
1101
|
+
ResultFormatter.flightNumber(
|
|
1102
|
+
decodeResult,
|
|
1103
|
+
cband.groups.airline + Number(cband.groups.number)
|
|
1056
1104
|
);
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
decodeResult.decoder.name = this.name + "-" + decoded.decoder.name;
|
|
1065
|
-
decodeResult.raw = { ...decodeResult.raw, ...decoded.raw };
|
|
1066
|
-
decodeResult.formatted.description = decoded.formatted.description;
|
|
1067
|
-
decodeResult.formatted.items.push(...decoded.formatted.items);
|
|
1068
|
-
decodeResult.remaining = decoded.remaining;
|
|
1069
|
-
}
|
|
1105
|
+
decodeResult.decoded = true;
|
|
1106
|
+
decodeResult.decoder.decodeLevel = decoded.decoder.decodeLevel;
|
|
1107
|
+
decodeResult.decoder.name = this.name + "-" + decoded.decoder.name;
|
|
1108
|
+
decodeResult.raw = { ...decodeResult.raw, ...decoded.raw };
|
|
1109
|
+
decodeResult.formatted.description = decoded.formatted.description;
|
|
1110
|
+
decodeResult.formatted.items.push(...decoded.formatted.items);
|
|
1111
|
+
decodeResult.remaining = decoded.remaining;
|
|
1070
1112
|
}
|
|
1071
1113
|
return decodeResult;
|
|
1072
1114
|
}
|
|
@@ -1151,7 +1193,9 @@ var FlightPlanUtils = class _FlightPlanUtils {
|
|
|
1151
1193
|
label: "Route Status",
|
|
1152
1194
|
value: "Route Planned"
|
|
1153
1195
|
});
|
|
1154
|
-
|
|
1196
|
+
if (header.length > 2) {
|
|
1197
|
+
addRoute(decodeResult, header.substring(2));
|
|
1198
|
+
}
|
|
1155
1199
|
} else if (header.startsWith("RI")) {
|
|
1156
1200
|
decodeResult.raw.route_status = "RI";
|
|
1157
1201
|
decodeResult.formatted.items.push({
|
|
@@ -1249,6 +1293,11 @@ function addCompanyRoute(decodeResult, value) {
|
|
|
1249
1293
|
}
|
|
1250
1294
|
|
|
1251
1295
|
// lib/utils/arinc_702_helper.ts
|
|
1296
|
+
function asciiStringToBytes(data) {
|
|
1297
|
+
const bytes = new Uint8Array(data.length);
|
|
1298
|
+
for (let i = 0; i < data.length; i++) bytes[i] = data.charCodeAt(i) & 255;
|
|
1299
|
+
return bytes;
|
|
1300
|
+
}
|
|
1252
1301
|
var Arinc702Helper = class _Arinc702Helper {
|
|
1253
1302
|
/**
|
|
1254
1303
|
* Decodes an ARINC 702 message
|
|
@@ -1767,7 +1816,7 @@ function processSummary(decodeResult, data) {
|
|
|
1767
1816
|
}
|
|
1768
1817
|
function crc16IbmSdlcRev(data) {
|
|
1769
1818
|
let crc = 65535;
|
|
1770
|
-
const bytes =
|
|
1819
|
+
const bytes = asciiStringToBytes(data);
|
|
1771
1820
|
for (const byte of bytes) {
|
|
1772
1821
|
crc ^= byte;
|
|
1773
1822
|
for (let i = 0; i < 8; i++) {
|
|
@@ -1788,7 +1837,7 @@ function crc16IbmSdlcRev(data) {
|
|
|
1788
1837
|
function crc16Genibus(data) {
|
|
1789
1838
|
let crc = 65535;
|
|
1790
1839
|
const polynomial = 4129;
|
|
1791
|
-
const bytes =
|
|
1840
|
+
const bytes = asciiStringToBytes(data);
|
|
1792
1841
|
for (const byte of bytes) {
|
|
1793
1842
|
crc ^= byte << 8;
|
|
1794
1843
|
for (let i = 0; i < 8; i++) {
|
|
@@ -1813,6 +1862,7 @@ function processMessageReference(decodeResult, data) {
|
|
|
1813
1862
|
}
|
|
1814
1863
|
|
|
1815
1864
|
// lib/plugins/ARINC_702.ts
|
|
1865
|
+
var NEWLINE_REGEX = /[\n\r]/g;
|
|
1816
1866
|
var Arinc702 = class extends DecoderPlugin {
|
|
1817
1867
|
name = "arinc-702";
|
|
1818
1868
|
qualifiers() {
|
|
@@ -1824,7 +1874,7 @@ var Arinc702 = class extends DecoderPlugin {
|
|
|
1824
1874
|
let decodeResult = this.defaultResult();
|
|
1825
1875
|
decodeResult.decoder.name = this.name;
|
|
1826
1876
|
decodeResult.message = message;
|
|
1827
|
-
const msg = message.text.replace(
|
|
1877
|
+
const msg = message.text.replace(NEWLINE_REGEX, "");
|
|
1828
1878
|
let decoded = false;
|
|
1829
1879
|
decoded = Arinc702Helper.decodeH1Message(decodeResult, msg);
|
|
1830
1880
|
if (decoded) {
|
|
@@ -2098,19 +2148,10 @@ var Label_10_POS = class extends DecoderPlugin {
|
|
|
2098
2148
|
};
|
|
2099
2149
|
}
|
|
2100
2150
|
decode(message, options = {}) {
|
|
2101
|
-
const decodeResult = this.
|
|
2102
|
-
decodeResult.decoder.name = this.name;
|
|
2103
|
-
decodeResult.formatted.description = "Position Report";
|
|
2104
|
-
decodeResult.message = message;
|
|
2151
|
+
const decodeResult = this.initResult(message, "Position Report");
|
|
2105
2152
|
const parts = message.text.split(",");
|
|
2106
2153
|
if (parts.length !== 12) {
|
|
2107
|
-
|
|
2108
|
-
console.log(`Decoder: Unknown 10 message: ${message.text}`);
|
|
2109
|
-
}
|
|
2110
|
-
ResultFormatter.unknown(decodeResult, message.text);
|
|
2111
|
-
decodeResult.decoded = false;
|
|
2112
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2113
|
-
return decodeResult;
|
|
2154
|
+
return this.failUnknown(decodeResult, message.text, options);
|
|
2114
2155
|
}
|
|
2115
2156
|
const lat = parts[1].trim();
|
|
2116
2157
|
const lon = parts[2].trim();
|
|
@@ -2125,8 +2166,7 @@ var Label_10_POS = class extends DecoderPlugin {
|
|
|
2125
2166
|
...parts.slice(3, 7),
|
|
2126
2167
|
...parts.slice(8)
|
|
2127
2168
|
]);
|
|
2128
|
-
decodeResult
|
|
2129
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
2169
|
+
this.setDecodeLevel(decodeResult, true, "partial");
|
|
2130
2170
|
return decodeResult;
|
|
2131
2171
|
}
|
|
2132
2172
|
};
|
|
@@ -2253,19 +2293,10 @@ var Label_12_POS = class extends DecoderPlugin {
|
|
|
2253
2293
|
};
|
|
2254
2294
|
}
|
|
2255
2295
|
decode(message, options = {}) {
|
|
2256
|
-
const decodeResult = this.
|
|
2257
|
-
decodeResult.decoder.name = this.name;
|
|
2258
|
-
decodeResult.formatted.description = "Position Report";
|
|
2259
|
-
decodeResult.message = message;
|
|
2296
|
+
const decodeResult = this.initResult(message, "Position Report");
|
|
2260
2297
|
const data = message.text.substring(3).split(",");
|
|
2261
2298
|
if (!message.text.startsWith("POS") || data.length !== 12) {
|
|
2262
|
-
|
|
2263
|
-
console.log(`Decoder: Unknown 12 message: ${message.text}`);
|
|
2264
|
-
}
|
|
2265
|
-
ResultFormatter.unknown(decodeResult, message.text);
|
|
2266
|
-
decodeResult.decoded = false;
|
|
2267
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2268
|
-
return decodeResult;
|
|
2299
|
+
return this.failUnknown(decodeResult, message.text, options);
|
|
2269
2300
|
}
|
|
2270
2301
|
const lat = data[0].substring(0, 8);
|
|
2271
2302
|
const lon = data[0].substring(8);
|
|
@@ -2299,8 +2330,7 @@ var Label_12_POS = class extends DecoderPlugin {
|
|
|
2299
2330
|
ResultFormatter.departureAirport(decodeResult, data[9]);
|
|
2300
2331
|
ResultFormatter.arrivalAirport(decodeResult, data[10]);
|
|
2301
2332
|
ResultFormatter.unknown(decodeResult, data[11]);
|
|
2302
|
-
decodeResult
|
|
2303
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
2333
|
+
this.setDecodeLevel(decodeResult, true, "partial");
|
|
2304
2334
|
return decodeResult;
|
|
2305
2335
|
}
|
|
2306
2336
|
};
|
|
@@ -2413,10 +2443,7 @@ var Label_15 = class extends DecoderPlugin {
|
|
|
2413
2443
|
};
|
|
2414
2444
|
}
|
|
2415
2445
|
decode(message, options = {}) {
|
|
2416
|
-
const decodeResult = this.
|
|
2417
|
-
decodeResult.decoder.name = this.name;
|
|
2418
|
-
decodeResult.formatted.description = "Position Report";
|
|
2419
|
-
decodeResult.message = message;
|
|
2446
|
+
const decodeResult = this.initResult(message, "Position Report");
|
|
2420
2447
|
if (message.text.startsWith("(2") && message.text.endsWith("(Z")) {
|
|
2421
2448
|
const between = message.text.substring(2, message.text.length - 2);
|
|
2422
2449
|
ResultFormatter.position(
|
|
@@ -2454,16 +2481,9 @@ var Label_15 = class extends DecoderPlugin {
|
|
|
2454
2481
|
ResultFormatter.unknown(decodeResult, between.substring(26));
|
|
2455
2482
|
}
|
|
2456
2483
|
} else {
|
|
2457
|
-
|
|
2458
|
-
console.log(`Decoder: Unknown 15 message: ${message.text}`);
|
|
2459
|
-
}
|
|
2460
|
-
ResultFormatter.unknown(decodeResult, message.text);
|
|
2461
|
-
decodeResult.decoded = false;
|
|
2462
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2463
|
-
return decodeResult;
|
|
2484
|
+
return this.failUnknown(decodeResult, message.text, options);
|
|
2464
2485
|
}
|
|
2465
|
-
decodeResult
|
|
2466
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
2486
|
+
this.setDecodeLevel(decodeResult, true, "partial");
|
|
2467
2487
|
return decodeResult;
|
|
2468
2488
|
}
|
|
2469
2489
|
};
|
|
@@ -2478,10 +2498,7 @@ var Label_15_FST = class extends DecoderPlugin {
|
|
|
2478
2498
|
};
|
|
2479
2499
|
}
|
|
2480
2500
|
decode(message, options = {}) {
|
|
2481
|
-
const decodeResult = this.
|
|
2482
|
-
decodeResult.decoder.name = this.name;
|
|
2483
|
-
decodeResult.formatted.description = "Position Report";
|
|
2484
|
-
decodeResult.message = message;
|
|
2501
|
+
const decodeResult = this.initResult(message, "Position Report");
|
|
2485
2502
|
const parts = message.text.split(" ");
|
|
2486
2503
|
const header = parts[0];
|
|
2487
2504
|
const stringCoords = header.substring(13);
|
|
@@ -2497,15 +2514,12 @@ var Label_15_FST = class extends DecoderPlugin {
|
|
|
2497
2514
|
Number(stringCoords.substring(15)) * 100
|
|
2498
2515
|
);
|
|
2499
2516
|
} else {
|
|
2500
|
-
decodeResult.
|
|
2501
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2502
|
-
return decodeResult;
|
|
2517
|
+
return this.failUnknown(decodeResult, message.text, options);
|
|
2503
2518
|
}
|
|
2504
2519
|
ResultFormatter.departureAirport(decodeResult, header.substring(5, 9));
|
|
2505
2520
|
ResultFormatter.arrivalAirport(decodeResult, header.substring(9, 13));
|
|
2506
2521
|
ResultFormatter.unknownArr(decodeResult, parts.slice(1), " ");
|
|
2507
|
-
decodeResult
|
|
2508
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
2522
|
+
this.setDecodeLevel(decodeResult, true, "partial");
|
|
2509
2523
|
return decodeResult;
|
|
2510
2524
|
}
|
|
2511
2525
|
};
|
|
@@ -2644,19 +2658,10 @@ var Label_16_POSA1 = class extends DecoderPlugin {
|
|
|
2644
2658
|
};
|
|
2645
2659
|
}
|
|
2646
2660
|
decode(message, options = {}) {
|
|
2647
|
-
const decodeResult = this.
|
|
2648
|
-
decodeResult.decoder.name = this.name;
|
|
2649
|
-
decodeResult.formatted.description = "Position Report";
|
|
2650
|
-
decodeResult.message = message;
|
|
2661
|
+
const decodeResult = this.initResult(message, "Position Report");
|
|
2651
2662
|
const fields = message.text.split(",");
|
|
2652
2663
|
if (fields.length !== 11 || !fields[0].startsWith("POSA1")) {
|
|
2653
|
-
|
|
2654
|
-
console.log(`Decoder: Unknown 16 message: ${message.text}`);
|
|
2655
|
-
}
|
|
2656
|
-
decodeResult.remaining.text = message.text;
|
|
2657
|
-
decodeResult.decoded = false;
|
|
2658
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2659
|
-
return decodeResult;
|
|
2664
|
+
return this.failUnknown(decodeResult, message.text, options);
|
|
2660
2665
|
}
|
|
2661
2666
|
ResultFormatter.position(
|
|
2662
2667
|
decodeResult,
|
|
@@ -2674,8 +2679,7 @@ var Label_16_POSA1 = class extends DecoderPlugin {
|
|
|
2674
2679
|
{ name: nextWaypoint, time: nextTime }
|
|
2675
2680
|
]
|
|
2676
2681
|
});
|
|
2677
|
-
decodeResult
|
|
2678
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
2682
|
+
this.setDecodeLevel(decodeResult, true, "partial");
|
|
2679
2683
|
return decodeResult;
|
|
2680
2684
|
}
|
|
2681
2685
|
};
|
|
@@ -3057,42 +3061,31 @@ var Label_20_POS = class extends DecoderPlugin {
|
|
|
3057
3061
|
};
|
|
3058
3062
|
}
|
|
3059
3063
|
decode(message, options = {}) {
|
|
3060
|
-
const decodeResult = this.
|
|
3061
|
-
decodeResult.decoder.name = this.name;
|
|
3062
|
-
decodeResult.formatted.description = "Position Report";
|
|
3063
|
-
decodeResult.message = message;
|
|
3064
|
+
const decodeResult = this.initResult(message, "Position Report");
|
|
3064
3065
|
decodeResult.raw.preamble = message.text.substring(0, 3);
|
|
3065
3066
|
const content = message.text.substring(3);
|
|
3066
3067
|
const fields = content.split(",");
|
|
3067
3068
|
if (fields.length == 11) {
|
|
3068
|
-
|
|
3069
|
-
console.log(`DEBUG: ${this.name}: Variation 1 detected`);
|
|
3070
|
-
}
|
|
3069
|
+
this.debug(options, "Variation 1 detected");
|
|
3071
3070
|
const rawCoords = fields[0];
|
|
3072
3071
|
ResultFormatter.position(
|
|
3073
3072
|
decodeResult,
|
|
3074
3073
|
CoordinateUtils.decodeStringCoordinates(rawCoords)
|
|
3075
3074
|
);
|
|
3076
|
-
decodeResult
|
|
3077
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
3075
|
+
this.setDecodeLevel(decodeResult, true, "full");
|
|
3078
3076
|
} else if (fields.length == 5) {
|
|
3079
|
-
|
|
3080
|
-
console.log(`DEBUG: ${this.name}: Variation 2 detected`);
|
|
3081
|
-
}
|
|
3077
|
+
this.debug(options, "Variation 2 detected");
|
|
3082
3078
|
const position = CoordinateUtils.decodeStringCoordinates(fields[0]);
|
|
3083
3079
|
if (position) {
|
|
3084
3080
|
ResultFormatter.position(decodeResult, position);
|
|
3085
3081
|
}
|
|
3086
|
-
decodeResult
|
|
3087
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
3082
|
+
this.setDecodeLevel(decodeResult, true, "full");
|
|
3088
3083
|
} else {
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
decodeResult.decoded = false;
|
|
3095
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
3084
|
+
this.debug(
|
|
3085
|
+
options,
|
|
3086
|
+
`Unknown variation. Field count: ${fields.length}, content: ${content}`
|
|
3087
|
+
);
|
|
3088
|
+
this.setDecodeLevel(decodeResult, false);
|
|
3096
3089
|
}
|
|
3097
3090
|
return decodeResult;
|
|
3098
3091
|
}
|
|
@@ -3108,10 +3101,7 @@ var Label_21_POS = class extends DecoderPlugin {
|
|
|
3108
3101
|
};
|
|
3109
3102
|
}
|
|
3110
3103
|
decode(message, options = {}) {
|
|
3111
|
-
const decodeResult = this.
|
|
3112
|
-
decodeResult.decoder.name = this.name;
|
|
3113
|
-
decodeResult.formatted.description = "Position Report";
|
|
3114
|
-
decodeResult.message = message;
|
|
3104
|
+
const decodeResult = this.initResult(message, "Position Report");
|
|
3115
3105
|
decodeResult.raw.preamble = message.text.substring(0, 3);
|
|
3116
3106
|
const content = message.text.substring(3);
|
|
3117
3107
|
const fields = content.split(",");
|
|
@@ -3133,16 +3123,13 @@ var Label_21_POS = class extends DecoderPlugin {
|
|
|
3133
3123
|
fields[4],
|
|
3134
3124
|
fields[5]
|
|
3135
3125
|
]);
|
|
3136
|
-
decodeResult
|
|
3137
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
3126
|
+
this.setDecodeLevel(decodeResult, true, "partial");
|
|
3138
3127
|
} else {
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
decodeResult.decoded = false;
|
|
3145
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
3128
|
+
this.debug(
|
|
3129
|
+
options,
|
|
3130
|
+
`Unknown variation. Field count: ${fields.length}, content: ${content}`
|
|
3131
|
+
);
|
|
3132
|
+
this.setDecodeLevel(decodeResult, false);
|
|
3146
3133
|
}
|
|
3147
3134
|
return decodeResult;
|
|
3148
3135
|
}
|
|
@@ -3170,15 +3157,11 @@ var Label_22_OFF = class extends DecoderPlugin {
|
|
|
3170
3157
|
};
|
|
3171
3158
|
}
|
|
3172
3159
|
decode(message, options = {}) {
|
|
3173
|
-
const decodeResult = this.
|
|
3174
|
-
decodeResult.decoder.name = this.name;
|
|
3175
|
-
decodeResult.formatted.description = "Takeoff Report";
|
|
3176
|
-
decodeResult.message = message;
|
|
3160
|
+
const decodeResult = this.initResult(message, "Takeoff Report");
|
|
3177
3161
|
if (message.text.startsWith("OFF01")) {
|
|
3178
3162
|
const fields = message.text.substring(5).split("/");
|
|
3179
3163
|
if (fields.length != 2) {
|
|
3180
|
-
decodeResult
|
|
3181
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
3164
|
+
this.setDecodeLevel(decodeResult, false);
|
|
3182
3165
|
return decodeResult;
|
|
3183
3166
|
}
|
|
3184
3167
|
ResultFormatter.flightNumber(decodeResult, fields[0]);
|
|
@@ -3204,13 +3187,11 @@ var Label_22_OFF = class extends DecoderPlugin {
|
|
|
3204
3187
|
DateTimeUtils.convertHHMMSSToTod(fields[1].substring(16, 22))
|
|
3205
3188
|
);
|
|
3206
3189
|
ResultFormatter.unknown(decodeResult, fields[1].substring(22));
|
|
3207
|
-
decodeResult
|
|
3208
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
3190
|
+
this.setDecodeLevel(decodeResult, true, "partial");
|
|
3209
3191
|
} else if (message.text.startsWith("OFF02\r\n")) {
|
|
3210
3192
|
const fields = message.text.substring(7).split(",");
|
|
3211
3193
|
if (fields.length != 4) {
|
|
3212
|
-
decodeResult
|
|
3213
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
3194
|
+
this.setDecodeLevel(decodeResult, false);
|
|
3214
3195
|
return decodeResult;
|
|
3215
3196
|
}
|
|
3216
3197
|
ResultFormatter.departureAirport(decodeResult, fields[0]);
|
|
@@ -3220,13 +3201,11 @@ var Label_22_OFF = class extends DecoderPlugin {
|
|
|
3220
3201
|
DateTimeUtils.convertHHMMSSToTod(fields[2])
|
|
3221
3202
|
);
|
|
3222
3203
|
ResultFormatter.unknown(decodeResult, fields[3]);
|
|
3223
|
-
decodeResult
|
|
3224
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
3204
|
+
this.setDecodeLevel(decodeResult, true, "partial");
|
|
3225
3205
|
} else if (message.text.startsWith("OFF02")) {
|
|
3226
3206
|
const fields = message.text.substring(5).split("/");
|
|
3227
3207
|
if (fields.length != 2) {
|
|
3228
|
-
decodeResult
|
|
3229
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
3208
|
+
this.setDecodeLevel(decodeResult, false);
|
|
3230
3209
|
return decodeResult;
|
|
3231
3210
|
}
|
|
3232
3211
|
ResultFormatter.flightNumber(decodeResult, fields[0]);
|
|
@@ -3255,14 +3234,10 @@ var Label_22_OFF = class extends DecoderPlugin {
|
|
|
3255
3234
|
decodeResult,
|
|
3256
3235
|
DateTimeUtils.convertHHMMSSToTod(fields[1].substring(36, 40))
|
|
3257
3236
|
);
|
|
3258
|
-
decodeResult
|
|
3259
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
3237
|
+
this.setDecodeLevel(decodeResult, true, "partial");
|
|
3260
3238
|
} else {
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
}
|
|
3264
|
-
decodeResult.decoded = false;
|
|
3265
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
3239
|
+
this.debug(options, "Unknown variation.");
|
|
3240
|
+
this.setDecodeLevel(decodeResult, false);
|
|
3266
3241
|
}
|
|
3267
3242
|
return decodeResult;
|
|
3268
3243
|
}
|
|
@@ -3278,19 +3253,14 @@ var Label_22_POS = class extends DecoderPlugin {
|
|
|
3278
3253
|
};
|
|
3279
3254
|
}
|
|
3280
3255
|
decode(message, options = {}) {
|
|
3281
|
-
const decodeResult = this.
|
|
3282
|
-
decodeResult.decoder.name = this.name;
|
|
3283
|
-
decodeResult.formatted.description = "Position Report";
|
|
3284
|
-
decodeResult.message = message;
|
|
3256
|
+
const decodeResult = this.initResult(message, "Position Report");
|
|
3285
3257
|
const fields = message.text.split(",");
|
|
3286
3258
|
if (fields.length !== 11) {
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
decodeResult.decoded = false;
|
|
3293
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
3259
|
+
this.debug(
|
|
3260
|
+
options,
|
|
3261
|
+
`Unknown variation. Field count: ${fields.length}, content: ${fields.join(",")}`
|
|
3262
|
+
);
|
|
3263
|
+
this.setDecodeLevel(decodeResult, false);
|
|
3294
3264
|
return decodeResult;
|
|
3295
3265
|
}
|
|
3296
3266
|
const latStr = fields[0].substring(1, 8);
|
|
@@ -3307,8 +3277,7 @@ var Label_22_POS = class extends DecoderPlugin {
|
|
|
3307
3277
|
);
|
|
3308
3278
|
ResultFormatter.altitude(decodeResult, Number(fields[3]));
|
|
3309
3279
|
ResultFormatter.unknownArr(decodeResult, [fields[1], ...fields.slice(4)]);
|
|
3310
|
-
decodeResult
|
|
3311
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
3280
|
+
this.setDecodeLevel(decodeResult, true, "partial");
|
|
3312
3281
|
return decodeResult;
|
|
3313
3282
|
}
|
|
3314
3283
|
};
|
|
@@ -3600,218 +3569,143 @@ var Label_44_ETA = class extends DecoderPlugin {
|
|
|
3600
3569
|
};
|
|
3601
3570
|
}
|
|
3602
3571
|
decode(message, options = {}) {
|
|
3603
|
-
const
|
|
3604
|
-
decodeResult.decoder.name = this.name;
|
|
3605
|
-
decodeResult.formatted.description = "ETA Report";
|
|
3606
|
-
decodeResult.message = message;
|
|
3572
|
+
const result = this.initResult(message, "ETA Report");
|
|
3607
3573
|
const data = message.text.split(",");
|
|
3608
|
-
if (data.length
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
return
|
|
3574
|
+
if (data.length < 9) {
|
|
3575
|
+
return this.failUnknown(result, message.text, options);
|
|
3576
|
+
}
|
|
3577
|
+
this.debug(options, "ETA Report: fields", data);
|
|
3578
|
+
ResultFormatter.position(
|
|
3579
|
+
result,
|
|
3580
|
+
CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[1])
|
|
3581
|
+
);
|
|
3582
|
+
ResultFormatter.altitude(result, 100 * Number(data[2]));
|
|
3583
|
+
ResultFormatter.departureAirport(result, data[3]);
|
|
3584
|
+
ResultFormatter.arrivalAirport(result, data[4]);
|
|
3585
|
+
ResultFormatter.month(result, Number(data[5].substring(0, 2)));
|
|
3586
|
+
ResultFormatter.day(result, Number(data[5].substring(2, 4)));
|
|
3587
|
+
ResultFormatter.timestamp(
|
|
3588
|
+
result,
|
|
3589
|
+
DateTimeUtils.convertHHMMSSToTod(data[6])
|
|
3590
|
+
);
|
|
3591
|
+
ResultFormatter.eta(result, DateTimeUtils.convertHHMMSSToTod(data[7]));
|
|
3592
|
+
const fuel = Number(data[8]);
|
|
3593
|
+
if (!isNaN(fuel)) {
|
|
3594
|
+
ResultFormatter.remainingFuel(result, fuel);
|
|
3595
|
+
}
|
|
3596
|
+
if (data.length > 9) {
|
|
3597
|
+
ResultFormatter.unknownArr(result, data.slice(9));
|
|
3598
|
+
}
|
|
3599
|
+
this.setDecodeLevel(result, true, "full");
|
|
3600
|
+
return result;
|
|
3601
|
+
}
|
|
3602
|
+
};
|
|
3603
|
+
|
|
3604
|
+
// lib/plugins/Label_44_Base.ts
|
|
3605
|
+
var Label_44_Base = class extends DecoderPlugin {
|
|
3606
|
+
decode(message, options = {}) {
|
|
3607
|
+
const result = this.initResult(message, this.description);
|
|
3608
|
+
const data = message.text.split(",");
|
|
3609
|
+
if (data.length < this.minFields) {
|
|
3610
|
+
return this.failUnknown(result, message.text, options);
|
|
3611
|
+
}
|
|
3612
|
+
this.debug(options, `${this.description}: fields`, data);
|
|
3613
|
+
ResultFormatter.position(
|
|
3614
|
+
result,
|
|
3615
|
+
CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[1])
|
|
3616
|
+
);
|
|
3617
|
+
ResultFormatter.departureAirport(result, data[2]);
|
|
3618
|
+
ResultFormatter.arrivalAirport(result, data[3]);
|
|
3619
|
+
ResultFormatter.month(result, Number(data[4].substring(0, 2)));
|
|
3620
|
+
ResultFormatter.day(result, Number(data[4].substring(2, 4)));
|
|
3621
|
+
this.decodeEventFields(result, data, options);
|
|
3622
|
+
this.setDecodeLevel(result, true, "full");
|
|
3623
|
+
return result;
|
|
3624
|
+
}
|
|
3625
|
+
/**
|
|
3626
|
+
* Helper to parse a fuel value from a CSV field.
|
|
3627
|
+
* Returns undefined if the value is not a valid number.
|
|
3628
|
+
*/
|
|
3629
|
+
parseFuel(result, value) {
|
|
3630
|
+
const fuel = Number(value);
|
|
3631
|
+
if (!isNaN(fuel)) {
|
|
3632
|
+
ResultFormatter.remainingFuel(result, fuel);
|
|
3633
|
+
}
|
|
3634
|
+
}
|
|
3635
|
+
/**
|
|
3636
|
+
* Helper to add any remaining fields as unknown.
|
|
3637
|
+
*/
|
|
3638
|
+
addRemainingFields(result, data, startIndex) {
|
|
3639
|
+
if (data.length > startIndex) {
|
|
3640
|
+
ResultFormatter.unknownArr(result, data.slice(startIndex));
|
|
3645
3641
|
}
|
|
3646
|
-
decodeResult.decoded = true;
|
|
3647
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
3648
|
-
return decodeResult;
|
|
3649
3642
|
}
|
|
3650
3643
|
};
|
|
3651
3644
|
|
|
3652
3645
|
// lib/plugins/Label_44_IN.ts
|
|
3653
|
-
var Label_44_IN = class extends
|
|
3646
|
+
var Label_44_IN = class extends Label_44_Base {
|
|
3654
3647
|
name = "label-44-in";
|
|
3648
|
+
get description() {
|
|
3649
|
+
return "In Gate Report";
|
|
3650
|
+
}
|
|
3651
|
+
get minFields() {
|
|
3652
|
+
return 7;
|
|
3653
|
+
}
|
|
3655
3654
|
qualifiers() {
|
|
3656
3655
|
return {
|
|
3657
3656
|
labels: ["44"],
|
|
3658
3657
|
preambles: ["00IN01", "00IN02", "00IN03", "IN01", "IN02", "IN03"]
|
|
3659
3658
|
};
|
|
3660
3659
|
}
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
decodeResult.message = message;
|
|
3666
|
-
const data = message.text.split(",");
|
|
3667
|
-
if (data.length >= 7) {
|
|
3668
|
-
if (options.debug) {
|
|
3669
|
-
console.log("Label 44 In Air Report: groups");
|
|
3670
|
-
console.log(data);
|
|
3671
|
-
}
|
|
3672
|
-
ResultFormatter.position(
|
|
3673
|
-
decodeResult,
|
|
3674
|
-
CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[1])
|
|
3675
|
-
);
|
|
3676
|
-
ResultFormatter.departureAirport(decodeResult, data[2]);
|
|
3677
|
-
ResultFormatter.arrivalAirport(decodeResult, data[3]);
|
|
3678
|
-
ResultFormatter.month(decodeResult, Number(data[4].substring(0, 2)));
|
|
3679
|
-
ResultFormatter.day(decodeResult, Number(data[4].substring(2, 4)));
|
|
3680
|
-
ResultFormatter.in(
|
|
3681
|
-
decodeResult,
|
|
3682
|
-
DateTimeUtils.convertHHMMSSToTod(data[5])
|
|
3683
|
-
);
|
|
3684
|
-
const fuel = Number(data[6]);
|
|
3685
|
-
if (!isNaN(fuel)) {
|
|
3686
|
-
ResultFormatter.remainingFuel(decodeResult, Number(fuel));
|
|
3687
|
-
}
|
|
3688
|
-
if (data.length > 7) {
|
|
3689
|
-
ResultFormatter.unknownArr(decodeResult, data.slice(7));
|
|
3690
|
-
}
|
|
3691
|
-
} else {
|
|
3692
|
-
if (options.debug) {
|
|
3693
|
-
console.log(`Decoder: Unknown 44 message: ${message.text}`);
|
|
3694
|
-
}
|
|
3695
|
-
ResultFormatter.unknown(decodeResult, message.text);
|
|
3696
|
-
decodeResult.decoded = false;
|
|
3697
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
3698
|
-
return decodeResult;
|
|
3699
|
-
}
|
|
3700
|
-
decodeResult.decoded = true;
|
|
3701
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
3702
|
-
return decodeResult;
|
|
3660
|
+
decodeEventFields(result, data, _options) {
|
|
3661
|
+
ResultFormatter.in(result, DateTimeUtils.convertHHMMSSToTod(data[5]));
|
|
3662
|
+
this.parseFuel(result, data[6]);
|
|
3663
|
+
this.addRemainingFields(result, data, 7);
|
|
3703
3664
|
}
|
|
3704
3665
|
};
|
|
3705
3666
|
|
|
3706
3667
|
// lib/plugins/Label_44_OFF.ts
|
|
3707
|
-
var Label_44_OFF = class extends
|
|
3668
|
+
var Label_44_OFF = class extends Label_44_Base {
|
|
3708
3669
|
name = "label-44-off";
|
|
3670
|
+
get description() {
|
|
3671
|
+
return "Off Runway Report";
|
|
3672
|
+
}
|
|
3673
|
+
get minFields() {
|
|
3674
|
+
return 8;
|
|
3675
|
+
}
|
|
3709
3676
|
qualifiers() {
|
|
3710
3677
|
return {
|
|
3711
3678
|
labels: ["44"],
|
|
3712
3679
|
preambles: ["00OFF01", "00OFF02", "00OFF03", "OFF01", "OFF02", "OFF03"]
|
|
3713
3680
|
};
|
|
3714
3681
|
}
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
const data = message.text.split(",");
|
|
3721
|
-
if (data.length >= 8) {
|
|
3722
|
-
if (options.debug) {
|
|
3723
|
-
console.log("Label 44 Off Runway Report: groups");
|
|
3724
|
-
console.log(data);
|
|
3725
|
-
}
|
|
3726
|
-
ResultFormatter.position(
|
|
3727
|
-
decodeResult,
|
|
3728
|
-
CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[1])
|
|
3729
|
-
);
|
|
3730
|
-
ResultFormatter.departureAirport(decodeResult, data[2]);
|
|
3731
|
-
ResultFormatter.arrivalAirport(decodeResult, data[3]);
|
|
3732
|
-
ResultFormatter.month(decodeResult, Number(data[4].substring(0, 2)));
|
|
3733
|
-
ResultFormatter.day(decodeResult, Number(data[4].substring(2, 4)));
|
|
3734
|
-
ResultFormatter.off(
|
|
3735
|
-
decodeResult,
|
|
3736
|
-
DateTimeUtils.convertHHMMSSToTod(data[5])
|
|
3737
|
-
);
|
|
3738
|
-
ResultFormatter.eta(
|
|
3739
|
-
decodeResult,
|
|
3740
|
-
DateTimeUtils.convertHHMMSSToTod(data[6])
|
|
3741
|
-
);
|
|
3742
|
-
const fuel = Number(data[7]);
|
|
3743
|
-
if (!isNaN(fuel)) {
|
|
3744
|
-
ResultFormatter.remainingFuel(decodeResult, Number(fuel));
|
|
3745
|
-
}
|
|
3746
|
-
if (data.length > 8) {
|
|
3747
|
-
ResultFormatter.unknownArr(decodeResult, data.slice(8));
|
|
3748
|
-
}
|
|
3749
|
-
} else {
|
|
3750
|
-
if (options.debug) {
|
|
3751
|
-
console.log(`Decoder: Unknown 44 message: ${message.text}`);
|
|
3752
|
-
}
|
|
3753
|
-
ResultFormatter.unknown(decodeResult, message.text);
|
|
3754
|
-
decodeResult.decoded = false;
|
|
3755
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
3756
|
-
return decodeResult;
|
|
3757
|
-
}
|
|
3758
|
-
decodeResult.decoded = true;
|
|
3759
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
3760
|
-
return decodeResult;
|
|
3682
|
+
decodeEventFields(result, data, _options) {
|
|
3683
|
+
ResultFormatter.off(result, DateTimeUtils.convertHHMMSSToTod(data[5]));
|
|
3684
|
+
ResultFormatter.eta(result, DateTimeUtils.convertHHMMSSToTod(data[6]));
|
|
3685
|
+
this.parseFuel(result, data[7]);
|
|
3686
|
+
this.addRemainingFields(result, data, 8);
|
|
3761
3687
|
}
|
|
3762
3688
|
};
|
|
3763
3689
|
|
|
3764
3690
|
// lib/plugins/Label_44_ON.ts
|
|
3765
|
-
var Label_44_ON = class extends
|
|
3691
|
+
var Label_44_ON = class extends Label_44_Base {
|
|
3766
3692
|
name = "label-44-on";
|
|
3693
|
+
get description() {
|
|
3694
|
+
return "On Runway Report";
|
|
3695
|
+
}
|
|
3696
|
+
get minFields() {
|
|
3697
|
+
return 7;
|
|
3698
|
+
}
|
|
3767
3699
|
qualifiers() {
|
|
3768
3700
|
return {
|
|
3769
3701
|
labels: ["44"],
|
|
3770
3702
|
preambles: ["00ON01", "00ON02", "00ON03", "ON01", "ON02", "ON03"]
|
|
3771
3703
|
};
|
|
3772
3704
|
}
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
decodeResult.message = message;
|
|
3778
|
-
const data = message.text.split(",");
|
|
3779
|
-
if (data.length >= 7) {
|
|
3780
|
-
if (options.debug) {
|
|
3781
|
-
console.log("Label 44 On Runway Report: groups");
|
|
3782
|
-
console.log(data);
|
|
3783
|
-
}
|
|
3784
|
-
ResultFormatter.position(
|
|
3785
|
-
decodeResult,
|
|
3786
|
-
CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[1])
|
|
3787
|
-
);
|
|
3788
|
-
ResultFormatter.departureAirport(decodeResult, data[2]);
|
|
3789
|
-
ResultFormatter.arrivalAirport(decodeResult, data[3]);
|
|
3790
|
-
ResultFormatter.month(decodeResult, Number(data[4].substring(0, 2)));
|
|
3791
|
-
ResultFormatter.day(decodeResult, Number(data[4].substring(2, 4)));
|
|
3792
|
-
ResultFormatter.on(
|
|
3793
|
-
decodeResult,
|
|
3794
|
-
DateTimeUtils.convertHHMMSSToTod(data[5])
|
|
3795
|
-
);
|
|
3796
|
-
const fuel = Number(data[6]);
|
|
3797
|
-
if (!isNaN(fuel)) {
|
|
3798
|
-
ResultFormatter.remainingFuel(decodeResult, Number(fuel));
|
|
3799
|
-
}
|
|
3800
|
-
if (data.length > 7) {
|
|
3801
|
-
ResultFormatter.unknownArr(decodeResult, data.slice(7));
|
|
3802
|
-
}
|
|
3803
|
-
} else {
|
|
3804
|
-
if (options.debug) {
|
|
3805
|
-
console.log(`Decoder: Unknown 44 message: ${message.text}`);
|
|
3806
|
-
}
|
|
3807
|
-
ResultFormatter.unknown(decodeResult, message.text);
|
|
3808
|
-
decodeResult.decoded = false;
|
|
3809
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
3810
|
-
return decodeResult;
|
|
3811
|
-
}
|
|
3812
|
-
decodeResult.decoded = true;
|
|
3813
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
3814
|
-
return decodeResult;
|
|
3705
|
+
decodeEventFields(result, data, _options) {
|
|
3706
|
+
ResultFormatter.on(result, DateTimeUtils.convertHHMMSSToTod(data[5]));
|
|
3707
|
+
this.parseFuel(result, data[6]);
|
|
3708
|
+
this.addRemainingFields(result, data, 7);
|
|
3815
3709
|
}
|
|
3816
3710
|
};
|
|
3817
3711
|
|
|
@@ -3825,17 +3719,11 @@ var Label_44_POS = class extends DecoderPlugin {
|
|
|
3825
3719
|
};
|
|
3826
3720
|
}
|
|
3827
3721
|
decode(message, options = {}) {
|
|
3828
|
-
const decodeResult = this.
|
|
3829
|
-
decodeResult.decoder.name = this.name;
|
|
3830
|
-
decodeResult.formatted.description = "Position Report";
|
|
3831
|
-
decodeResult.message = message;
|
|
3722
|
+
const decodeResult = this.initResult(message, "Position Report");
|
|
3832
3723
|
const regex = /^.*,(?<unsplit_coords>.*),(?<flight_level_or_ground>.*),(?<departure_icao>.*),(?<arrival_icao>.*),(?<current_date>.*),(?<current_time>.*),(?<eta_time>.*),(?<fuel_in_tons>.*)$/;
|
|
3833
3724
|
const results = message.text.match(regex);
|
|
3834
3725
|
if (results?.groups) {
|
|
3835
|
-
|
|
3836
|
-
console.log("Label 44 Position Report: groups");
|
|
3837
|
-
console.log(results.groups);
|
|
3838
|
-
}
|
|
3726
|
+
this.debug(options, "Position Report: groups", results.groups);
|
|
3839
3727
|
ResultFormatter.position(
|
|
3840
3728
|
decodeResult,
|
|
3841
3729
|
CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
|
|
@@ -3868,10 +3756,10 @@ var Label_44_POS = class extends DecoderPlugin {
|
|
|
3868
3756
|
);
|
|
3869
3757
|
ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
|
|
3870
3758
|
ResultFormatter.altitude(decodeResult, flight_level * 100);
|
|
3759
|
+
this.setDecodeLevel(decodeResult, true, "full");
|
|
3760
|
+
return decodeResult;
|
|
3871
3761
|
}
|
|
3872
|
-
decodeResult.
|
|
3873
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
3874
|
-
return decodeResult;
|
|
3762
|
+
return this.failUnknown(decodeResult, message.text, options);
|
|
3875
3763
|
}
|
|
3876
3764
|
};
|
|
3877
3765
|
|
|
@@ -3949,10 +3837,7 @@ var Label_4A = class extends DecoderPlugin {
|
|
|
3949
3837
|
};
|
|
3950
3838
|
}
|
|
3951
3839
|
decode(message, options = {}) {
|
|
3952
|
-
const decodeResult = this.
|
|
3953
|
-
decodeResult.decoder.name = this.name;
|
|
3954
|
-
decodeResult.message = message;
|
|
3955
|
-
decodeResult.formatted.description = "Latest New Format";
|
|
3840
|
+
const decodeResult = this.initResult(message, "Latest New Format");
|
|
3956
3841
|
decodeResult.decoded = true;
|
|
3957
3842
|
const fields = message.text.split(",");
|
|
3958
3843
|
if (fields.length === 11) {
|
|
@@ -3966,7 +3851,8 @@ var Label_4A = class extends DecoderPlugin {
|
|
|
3966
3851
|
ResultFormatter.arrivalAirport(decodeResult, fields[5]);
|
|
3967
3852
|
ResultFormatter.unknownArr(decodeResult, fields.slice(8));
|
|
3968
3853
|
} else if (fields.length === 6) {
|
|
3969
|
-
|
|
3854
|
+
const f0 = fields[0];
|
|
3855
|
+
if (f0.length > 0 && (f0[0] === "N" || f0[0] === "S")) {
|
|
3970
3856
|
ResultFormatter.position(
|
|
3971
3857
|
decodeResult,
|
|
3972
3858
|
CoordinateUtils.decodeStringCoordinates(fields[0].substring(0, 13))
|
|
@@ -4008,13 +3894,7 @@ var Label_4A = class extends DecoderPlugin {
|
|
|
4008
3894
|
decodeResult.decoded = false;
|
|
4009
3895
|
ResultFormatter.unknown(decodeResult, message.text);
|
|
4010
3896
|
}
|
|
4011
|
-
|
|
4012
|
-
if (!decodeResult.remaining.text)
|
|
4013
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
4014
|
-
else decodeResult.decoder.decodeLevel = "partial";
|
|
4015
|
-
} else {
|
|
4016
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
4017
|
-
}
|
|
3897
|
+
this.setDecodeLevel(decodeResult, decodeResult.decoded);
|
|
4018
3898
|
return decodeResult;
|
|
4019
3899
|
}
|
|
4020
3900
|
};
|
|
@@ -4029,10 +3909,7 @@ var Label_4A_01 = class extends DecoderPlugin {
|
|
|
4029
3909
|
};
|
|
4030
3910
|
}
|
|
4031
3911
|
decode(message, options = {}) {
|
|
4032
|
-
const decodeResult = this.
|
|
4033
|
-
decodeResult.decoder.name = this.name;
|
|
4034
|
-
decodeResult.message = message;
|
|
4035
|
-
decodeResult.formatted.description = "Latest New Format";
|
|
3912
|
+
const decodeResult = this.initResult(message, "Latest New Format");
|
|
4036
3913
|
decodeResult.decoded = true;
|
|
4037
3914
|
let rgx = message.text.match(
|
|
4038
3915
|
/^01([A-Z]{2})([A-Z]{2})\s*(\w+)\/(\d{6})([A-Z]{4})([A-Z]{4})\r\n([+-]\s*\d+)(\d{3}\.\d)([+-]\s*\d+\.\d)/
|
|
@@ -4053,13 +3930,7 @@ var Label_4A_01 = class extends DecoderPlugin {
|
|
|
4053
3930
|
decodeResult.decoded = false;
|
|
4054
3931
|
ResultFormatter.unknown(decodeResult, message.text);
|
|
4055
3932
|
}
|
|
4056
|
-
|
|
4057
|
-
if (!decodeResult.remaining.text)
|
|
4058
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
4059
|
-
else decodeResult.decoder.decodeLevel = "partial";
|
|
4060
|
-
} else {
|
|
4061
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
4062
|
-
}
|
|
3933
|
+
this.setDecodeLevel(decodeResult, decodeResult.decoded);
|
|
4063
3934
|
return decodeResult;
|
|
4064
3935
|
}
|
|
4065
3936
|
};
|
|
@@ -4074,10 +3945,7 @@ var Label_4A_DIS = class extends DecoderPlugin {
|
|
|
4074
3945
|
};
|
|
4075
3946
|
}
|
|
4076
3947
|
decode(message, options = {}) {
|
|
4077
|
-
const decodeResult = this.
|
|
4078
|
-
decodeResult.decoder.name = this.name;
|
|
4079
|
-
decodeResult.message = message;
|
|
4080
|
-
decodeResult.formatted.description = "Latest New Format";
|
|
3948
|
+
const decodeResult = this.initResult(message, "Latest New Format");
|
|
4081
3949
|
decodeResult.decoded = true;
|
|
4082
3950
|
const fields = message.text.split(",");
|
|
4083
3951
|
ResultFormatter.timestamp(
|
|
@@ -4086,13 +3954,7 @@ var Label_4A_DIS = class extends DecoderPlugin {
|
|
|
4086
3954
|
);
|
|
4087
3955
|
ResultFormatter.callsign(decodeResult, fields[2]);
|
|
4088
3956
|
ResultFormatter.text(decodeResult, fields.slice(3).join(""));
|
|
4089
|
-
|
|
4090
|
-
if (!decodeResult.remaining.text)
|
|
4091
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
4092
|
-
else decodeResult.decoder.decodeLevel = "partial";
|
|
4093
|
-
} else {
|
|
4094
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
4095
|
-
}
|
|
3957
|
+
this.setDecodeLevel(decodeResult, decodeResult.decoded);
|
|
4096
3958
|
return decodeResult;
|
|
4097
3959
|
}
|
|
4098
3960
|
};
|
|
@@ -4107,10 +3969,7 @@ var Label_4A_DOOR = class extends DecoderPlugin {
|
|
|
4107
3969
|
};
|
|
4108
3970
|
}
|
|
4109
3971
|
decode(message, options = {}) {
|
|
4110
|
-
const decodeResult = this.
|
|
4111
|
-
decodeResult.decoder.name = this.name;
|
|
4112
|
-
decodeResult.message = message;
|
|
4113
|
-
decodeResult.formatted.description = "Latest New Format";
|
|
3972
|
+
const decodeResult = this.initResult(message, "Latest New Format");
|
|
4114
3973
|
decodeResult.decoded = true;
|
|
4115
3974
|
const fields = message.text.split(" ");
|
|
4116
3975
|
if (fields.length === 3) {
|
|
@@ -4127,13 +3986,7 @@ var Label_4A_DOOR = class extends DecoderPlugin {
|
|
|
4127
3986
|
decodeResult.decoded = false;
|
|
4128
3987
|
ResultFormatter.unknown(decodeResult, message.text);
|
|
4129
3988
|
}
|
|
4130
|
-
|
|
4131
|
-
if (!decodeResult.remaining.text)
|
|
4132
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
4133
|
-
else decodeResult.decoder.decodeLevel = "partial";
|
|
4134
|
-
} else {
|
|
4135
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
4136
|
-
}
|
|
3989
|
+
this.setDecodeLevel(decodeResult, decodeResult.decoded);
|
|
4137
3990
|
return decodeResult;
|
|
4138
3991
|
}
|
|
4139
3992
|
};
|
|
@@ -4380,6 +4233,9 @@ var Label_4T_ETA = class extends DecoderPlugin {
|
|
|
4380
4233
|
};
|
|
4381
4234
|
|
|
4382
4235
|
// lib/plugins/Label_80.ts
|
|
4236
|
+
var POS_REGEX = /^(?<latd>[NS])(?<lat>.+)(?<lngd>[EW])(?<lng>.+)/;
|
|
4237
|
+
var WS_REGEX = /\s+/;
|
|
4238
|
+
var NEWLINE_REGEX2 = /\r?\n/;
|
|
4383
4239
|
var Label_80 = class extends DecoderPlugin {
|
|
4384
4240
|
name = "label-80";
|
|
4385
4241
|
qualifiers() {
|
|
@@ -4389,10 +4245,11 @@ var Label_80 = class extends DecoderPlugin {
|
|
|
4389
4245
|
};
|
|
4390
4246
|
}
|
|
4391
4247
|
decode(message, options = {}) {
|
|
4392
|
-
const decodeResult = this.
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4248
|
+
const decodeResult = this.initResult(
|
|
4249
|
+
message,
|
|
4250
|
+
"Airline Defined Position Report"
|
|
4251
|
+
);
|
|
4252
|
+
const lines = message.text.split(NEWLINE_REGEX2);
|
|
4396
4253
|
if (lines.length === 1 && lines[0].includes(",")) {
|
|
4397
4254
|
this.parseCsvFormat(lines[0], decodeResult);
|
|
4398
4255
|
} else {
|
|
@@ -4417,8 +4274,7 @@ var Label_80 = class extends DecoderPlugin {
|
|
|
4417
4274
|
}
|
|
4418
4275
|
}
|
|
4419
4276
|
if (decodeResult.formatted.items.length > 0) {
|
|
4420
|
-
decodeResult
|
|
4421
|
-
decodeResult.decoder.decodeLevel = decodeResult.remaining.text === void 0 ? "full" : "partial";
|
|
4277
|
+
this.setDecodeLevel(decodeResult, true);
|
|
4422
4278
|
}
|
|
4423
4279
|
return decodeResult;
|
|
4424
4280
|
}
|
|
@@ -4428,7 +4284,7 @@ var Label_80 = class extends DecoderPlugin {
|
|
|
4428
4284
|
ResultFormatter.unknown(results, header, "/");
|
|
4429
4285
|
return;
|
|
4430
4286
|
}
|
|
4431
|
-
const msgInfo = fields[0].split(
|
|
4287
|
+
const msgInfo = fields[0].split(WS_REGEX);
|
|
4432
4288
|
if (msgInfo.length === 3) {
|
|
4433
4289
|
ResultFormatter.unknownArr(results, msgInfo.slice(0, 2), " ");
|
|
4434
4290
|
ResultFormatter.flightNumber(results, msgInfo[2]);
|
|
@@ -4436,14 +4292,14 @@ var Label_80 = class extends DecoderPlugin {
|
|
|
4436
4292
|
ResultFormatter.unknown(results, header, "/");
|
|
4437
4293
|
return;
|
|
4438
4294
|
}
|
|
4439
|
-
const otherInfo1 = fields[1].split(
|
|
4295
|
+
const otherInfo1 = fields[1].split(WS_REGEX);
|
|
4440
4296
|
if (otherInfo1.length === 2) {
|
|
4441
4297
|
ResultFormatter.day(results, parseInt(otherInfo1[0], 10));
|
|
4442
4298
|
ResultFormatter.departureAirport(results, otherInfo1[1]);
|
|
4443
4299
|
} else {
|
|
4444
4300
|
ResultFormatter.unknownArr(results, otherInfo1, " ");
|
|
4445
4301
|
}
|
|
4446
|
-
const otherInfo2 = fields[2].split(
|
|
4302
|
+
const otherInfo2 = fields[2].split(WS_REGEX);
|
|
4447
4303
|
if (otherInfo2.length === 2) {
|
|
4448
4304
|
ResultFormatter.arrivalAirport(results, otherInfo2[0]);
|
|
4449
4305
|
ResultFormatter.tail(results, otherInfo2[1].replace(".", ""));
|
|
@@ -4455,7 +4311,7 @@ var Label_80 = class extends DecoderPlugin {
|
|
|
4455
4311
|
}
|
|
4456
4312
|
}
|
|
4457
4313
|
parseTags(part, results) {
|
|
4458
|
-
const kvPair = part.split(
|
|
4314
|
+
const kvPair = part.split(WS_REGEX);
|
|
4459
4315
|
if (kvPair.length < 2) {
|
|
4460
4316
|
ResultFormatter.unknown(results, part, "/");
|
|
4461
4317
|
return;
|
|
@@ -4463,9 +4319,8 @@ var Label_80 = class extends DecoderPlugin {
|
|
|
4463
4319
|
const tag = kvPair[0];
|
|
4464
4320
|
const val = kvPair.slice(1).join(" ");
|
|
4465
4321
|
switch (tag) {
|
|
4466
|
-
case "POS":
|
|
4467
|
-
const
|
|
4468
|
-
const posResult = val.match(posRegex);
|
|
4322
|
+
case "POS": {
|
|
4323
|
+
const posResult = POS_REGEX.exec(val);
|
|
4469
4324
|
const lat = Number(posResult?.groups?.lat) * (posResult?.groups?.latd === "S" ? -1 : 1);
|
|
4470
4325
|
const lon = Number(posResult?.groups?.lng) * (posResult?.groups?.lngd === "W" ? -1 : 1);
|
|
4471
4326
|
const position = {
|
|
@@ -4474,6 +4329,7 @@ var Label_80 = class extends DecoderPlugin {
|
|
|
4474
4329
|
};
|
|
4475
4330
|
ResultFormatter.position(results, position);
|
|
4476
4331
|
break;
|
|
4332
|
+
}
|
|
4477
4333
|
case "ALT":
|
|
4478
4334
|
ResultFormatter.altitude(results, parseInt(val.replace("+", ""), 10));
|
|
4479
4335
|
break;
|
|
@@ -4506,10 +4362,11 @@ var Label_80 = class extends DecoderPlugin {
|
|
|
4506
4362
|
DateTimeUtils.convertHHMMSSToTod(val)
|
|
4507
4363
|
);
|
|
4508
4364
|
break;
|
|
4509
|
-
case "ETA":
|
|
4365
|
+
case "ETA": {
|
|
4510
4366
|
const hhmm = val.split(".")[0].replace(":", "");
|
|
4511
4367
|
ResultFormatter.eta(results, DateTimeUtils.convertHHMMSSToTod(hhmm));
|
|
4512
4368
|
break;
|
|
4369
|
+
}
|
|
4513
4370
|
case "HDG":
|
|
4514
4371
|
ResultFormatter.heading(results, parseInt(val, 10));
|
|
4515
4372
|
break;
|
|
@@ -4533,7 +4390,7 @@ var Label_80 = class extends DecoderPlugin {
|
|
|
4533
4390
|
if (csvParts.length !== 9) {
|
|
4534
4391
|
return;
|
|
4535
4392
|
}
|
|
4536
|
-
const header = csvParts[0].trim().split(
|
|
4393
|
+
const header = csvParts[0].trim().split(WS_REGEX);
|
|
4537
4394
|
ResultFormatter.unknown(results, header[0], " ");
|
|
4538
4395
|
ResultFormatter.unknown(results, header[1], " ");
|
|
4539
4396
|
ResultFormatter.position(
|
|
@@ -4556,6 +4413,9 @@ var Label_80 = class extends DecoderPlugin {
|
|
|
4556
4413
|
};
|
|
4557
4414
|
|
|
4558
4415
|
// lib/plugins/Label_83.ts
|
|
4416
|
+
var WS_REGEX2 = /\s+/;
|
|
4417
|
+
var ALL_WS_REGEX = /\s/g;
|
|
4418
|
+
var ALL_DOTS_REGEX = /\./g;
|
|
4559
4419
|
var Label_83 = class extends DecoderPlugin {
|
|
4560
4420
|
name = "label-83";
|
|
4561
4421
|
qualifiers() {
|
|
@@ -4570,8 +4430,8 @@ var Label_83 = class extends DecoderPlugin {
|
|
|
4570
4430
|
decodeResult.formatted.description = "Airline Defined";
|
|
4571
4431
|
decodeResult.decoded = true;
|
|
4572
4432
|
const text = message.text;
|
|
4573
|
-
if (text.
|
|
4574
|
-
const fields = text.split(
|
|
4433
|
+
if (text.startsWith("4DH3 ETAT2")) {
|
|
4434
|
+
const fields = text.split(WS_REGEX2);
|
|
4575
4435
|
if (fields[2].length > 5) {
|
|
4576
4436
|
decodeResult.raw.day = fields[2].substring(5);
|
|
4577
4437
|
}
|
|
@@ -4579,15 +4439,15 @@ var Label_83 = class extends DecoderPlugin {
|
|
|
4579
4439
|
const subfields = fields[3].split("/");
|
|
4580
4440
|
ResultFormatter.departureAirport(decodeResult, subfields[0]);
|
|
4581
4441
|
ResultFormatter.arrivalAirport(decodeResult, subfields[1]);
|
|
4582
|
-
ResultFormatter.tail(decodeResult, fields[4].replace(
|
|
4442
|
+
ResultFormatter.tail(decodeResult, fields[4].replace(ALL_DOTS_REGEX, ""));
|
|
4583
4443
|
ResultFormatter.eta(
|
|
4584
4444
|
decodeResult,
|
|
4585
4445
|
DateTimeUtils.convertHHMMSSToTod(fields[6] + "00")
|
|
4586
4446
|
);
|
|
4587
|
-
} else if (text.
|
|
4447
|
+
} else if (text.startsWith("001PR")) {
|
|
4588
4448
|
decodeResult.raw.day = text.substring(5, 7);
|
|
4589
4449
|
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
|
|
4590
|
-
text.substring(13, 28).replace(
|
|
4450
|
+
text.substring(13, 28).replace(ALL_DOTS_REGEX, "")
|
|
4591
4451
|
);
|
|
4592
4452
|
if (position) {
|
|
4593
4453
|
ResultFormatter.position(decodeResult, position);
|
|
@@ -4595,15 +4455,15 @@ var Label_83 = class extends DecoderPlugin {
|
|
|
4595
4455
|
ResultFormatter.altitude(decodeResult, Number(text.substring(28, 33)));
|
|
4596
4456
|
ResultFormatter.unknown(decodeResult, text.substring(33));
|
|
4597
4457
|
} else {
|
|
4598
|
-
const fields = text.replace(
|
|
4458
|
+
const fields = text.replace(ALL_WS_REGEX, "").split(",");
|
|
4599
4459
|
if (fields.length === 9) {
|
|
4600
4460
|
ResultFormatter.departureAirport(decodeResult, fields[0]);
|
|
4601
4461
|
ResultFormatter.arrivalAirport(decodeResult, fields[1]);
|
|
4602
4462
|
decodeResult.raw.day = fields[2].substring(0, 2);
|
|
4603
4463
|
decodeResult.raw.time = fields[2].substring(2);
|
|
4604
4464
|
ResultFormatter.position(decodeResult, {
|
|
4605
|
-
latitude: Number(fields[3]
|
|
4606
|
-
longitude: Number(fields[4]
|
|
4465
|
+
latitude: Number(fields[3]),
|
|
4466
|
+
longitude: Number(fields[4])
|
|
4607
4467
|
});
|
|
4608
4468
|
ResultFormatter.altitude(decodeResult, Number(fields[5]));
|
|
4609
4469
|
ResultFormatter.groundspeed(decodeResult, Number(fields[6]));
|
|
@@ -4667,13 +4527,15 @@ var Label_B6_Forwardslash = class extends DecoderPlugin {
|
|
|
4667
4527
|
};
|
|
4668
4528
|
}
|
|
4669
4529
|
decode(message, options = {}) {
|
|
4670
|
-
const decodeResult = this.
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4530
|
+
const decodeResult = this.initResult(message, "CPDLC Message");
|
|
4531
|
+
const body = message.text.substring(1);
|
|
4532
|
+
if (body.length > 0) {
|
|
4533
|
+
ResultFormatter.text(decodeResult, body);
|
|
4534
|
+
this.setDecodeLevel(decodeResult, true, "partial");
|
|
4535
|
+
} else {
|
|
4536
|
+
this.setDecodeLevel(decodeResult, false);
|
|
4676
4537
|
}
|
|
4538
|
+
this.debug(options, "CPDLC body:", body);
|
|
4677
4539
|
return decodeResult;
|
|
4678
4540
|
}
|
|
4679
4541
|
};
|
|
@@ -4944,10 +4806,7 @@ var Label_H1_FLR = class extends DecoderPlugin {
|
|
|
4944
4806
|
};
|
|
4945
4807
|
}
|
|
4946
4808
|
decode(message, options = {}) {
|
|
4947
|
-
|
|
4948
|
-
decodeResult.decoder.name = this.name;
|
|
4949
|
-
decodeResult.formatted.description = "Fault Log Report";
|
|
4950
|
-
decodeResult.message = message;
|
|
4809
|
+
const decodeResult = this.initResult(message, "Fault Log Report");
|
|
4951
4810
|
const parts = message.text.split("/FR");
|
|
4952
4811
|
if (parts.length > 1) {
|
|
4953
4812
|
const fields = parts[0].split("/");
|
|
@@ -4971,15 +4830,9 @@ var Label_H1_FLR = class extends DecoderPlugin {
|
|
|
4971
4830
|
label: "Fault Report",
|
|
4972
4831
|
value: decodeResult.raw.fault_message
|
|
4973
4832
|
});
|
|
4974
|
-
decodeResult
|
|
4975
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
4833
|
+
this.setDecodeLevel(decodeResult, true, "partial");
|
|
4976
4834
|
} else {
|
|
4977
|
-
|
|
4978
|
-
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
4979
|
-
}
|
|
4980
|
-
ResultFormatter.unknown(decodeResult, message.text);
|
|
4981
|
-
decodeResult.decoded = false;
|
|
4982
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
4835
|
+
return this.failUnknown(decodeResult, message.text, options);
|
|
4983
4836
|
}
|
|
4984
4837
|
return decodeResult;
|
|
4985
4838
|
}
|
|
@@ -4994,30 +4847,21 @@ var Label_H1_M_POS = class extends DecoderPlugin {
|
|
|
4994
4847
|
};
|
|
4995
4848
|
}
|
|
4996
4849
|
decode(message, options = {}) {
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
4850
|
+
const decodeResult = this.initResult(
|
|
4851
|
+
message,
|
|
4852
|
+
"M-Series Periodic Position Report"
|
|
4853
|
+
);
|
|
5001
4854
|
const headerRegex = /^M(\d{2})A([A-Z]{2})(\d{4})/;
|
|
5002
4855
|
const headerMatch = message.text.match(headerRegex);
|
|
5003
4856
|
if (!headerMatch) {
|
|
5004
|
-
|
|
5005
|
-
console.log(`Decoder: Unknown H1 M-POS message: ${message.text}`);
|
|
5006
|
-
}
|
|
5007
|
-
ResultFormatter.unknown(decodeResult, message.text);
|
|
5008
|
-
decodeResult.decoded = false;
|
|
5009
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
5010
|
-
return decodeResult;
|
|
4857
|
+
return this.failUnknown(decodeResult, message.text, options);
|
|
5011
4858
|
}
|
|
5012
4859
|
const airline = headerMatch[2];
|
|
5013
4860
|
const flightNum = headerMatch[3];
|
|
5014
4861
|
const afterHeader = message.text.substring(headerMatch[0].length);
|
|
5015
4862
|
const fields = afterHeader.split(",");
|
|
5016
4863
|
if (fields.length < 7) {
|
|
5017
|
-
|
|
5018
|
-
decodeResult.decoded = false;
|
|
5019
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
5020
|
-
return decodeResult;
|
|
4864
|
+
return this.failUnknown(decodeResult, message.text, options);
|
|
5021
4865
|
}
|
|
5022
4866
|
ResultFormatter.flightNumber(decodeResult, `${airline}${flightNum}`);
|
|
5023
4867
|
ResultFormatter.departureAirport(decodeResult, fields[0]);
|
|
@@ -5041,15 +4885,48 @@ var Label_H1_M_POS = class extends DecoderPlugin {
|
|
|
5041
4885
|
if (fields.length > 7) {
|
|
5042
4886
|
ResultFormatter.unknownArr(decodeResult, fields.slice(7));
|
|
5043
4887
|
}
|
|
5044
|
-
|
|
5045
|
-
|
|
4888
|
+
this.setDecodeLevel(
|
|
4889
|
+
decodeResult,
|
|
4890
|
+
true,
|
|
4891
|
+
fields.length > 7 ? "partial" : "full"
|
|
4892
|
+
);
|
|
5046
4893
|
return decodeResult;
|
|
5047
4894
|
}
|
|
5048
4895
|
};
|
|
5049
4896
|
|
|
4897
|
+
// lib/utils/compression.ts
|
|
4898
|
+
var pako = __toESM(require("pako"));
|
|
4899
|
+
function inflateData(data, raw) {
|
|
4900
|
+
const chunks = [];
|
|
4901
|
+
const inflator = new pako.Inflate({ windowBits: raw ? -15 : 15 });
|
|
4902
|
+
inflator.onData = (chunk) => {
|
|
4903
|
+
chunks.push(chunk);
|
|
4904
|
+
};
|
|
4905
|
+
inflator.push(data, 2);
|
|
4906
|
+
if (chunks.length === 0) return void 0;
|
|
4907
|
+
if (chunks.length === 1) return chunks[0];
|
|
4908
|
+
const totalLen = chunks.reduce((sum, c) => sum + c.length, 0);
|
|
4909
|
+
const result = new Uint8Array(totalLen);
|
|
4910
|
+
let offset = 0;
|
|
4911
|
+
for (const chunk of chunks) {
|
|
4912
|
+
result.set(chunk, offset);
|
|
4913
|
+
offset += chunk.length;
|
|
4914
|
+
}
|
|
4915
|
+
return result;
|
|
4916
|
+
}
|
|
4917
|
+
function base64ToUint8Array(base64) {
|
|
4918
|
+
const cleaned = base64.replace(/-/g, "+").replace(/_/g, "/").replace(/[^A-Za-z0-9+/]/g, "");
|
|
4919
|
+
const padded = cleaned + "=".repeat((4 - cleaned.length % 4) % 4);
|
|
4920
|
+
const binary = atob(padded);
|
|
4921
|
+
const bytes = new Uint8Array(binary.length);
|
|
4922
|
+
for (let i = 0; i < binary.length; i++) {
|
|
4923
|
+
bytes[i] = binary.charCodeAt(i);
|
|
4924
|
+
}
|
|
4925
|
+
return bytes;
|
|
4926
|
+
}
|
|
4927
|
+
|
|
5050
4928
|
// lib/plugins/Label_H1_OHMA.ts
|
|
5051
|
-
var
|
|
5052
|
-
var import_node_buffer = require("buffer");
|
|
4929
|
+
var textDecoder = new TextDecoder();
|
|
5053
4930
|
var Label_H1_OHMA = class extends DecoderPlugin {
|
|
5054
4931
|
name = "label-h1-ohma";
|
|
5055
4932
|
qualifiers() {
|
|
@@ -5065,12 +4942,12 @@ var Label_H1_OHMA = class extends DecoderPlugin {
|
|
|
5065
4942
|
decodeResult.message = message;
|
|
5066
4943
|
const data = message.text.split("OHMA")[1];
|
|
5067
4944
|
try {
|
|
5068
|
-
const compressedBuffer =
|
|
5069
|
-
const
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
const jsonText = result
|
|
4945
|
+
const compressedBuffer = base64ToUint8Array(data);
|
|
4946
|
+
const result = inflateData(compressedBuffer, false);
|
|
4947
|
+
if (!result || result.length === 0) {
|
|
4948
|
+
throw new Error("Decompression produced no output");
|
|
4949
|
+
}
|
|
4950
|
+
const jsonText = textDecoder.decode(result);
|
|
5074
4951
|
let formattedMsg;
|
|
5075
4952
|
let jsonMessage;
|
|
5076
4953
|
try {
|
|
@@ -5400,10 +5277,7 @@ var Label_H1_WRN = class extends DecoderPlugin {
|
|
|
5400
5277
|
};
|
|
5401
5278
|
}
|
|
5402
5279
|
decode(message, options = {}) {
|
|
5403
|
-
|
|
5404
|
-
decodeResult.decoder.name = this.name;
|
|
5405
|
-
decodeResult.formatted.description = "Warning Message";
|
|
5406
|
-
decodeResult.message = message;
|
|
5280
|
+
const decodeResult = this.initResult(message, "Warning Message");
|
|
5407
5281
|
const parts = message.text.split("/WN");
|
|
5408
5282
|
if (parts.length > 1) {
|
|
5409
5283
|
const fields = parts[0].split("/");
|
|
@@ -5424,15 +5298,9 @@ var Label_H1_WRN = class extends DecoderPlugin {
|
|
|
5424
5298
|
label: "Warning Message",
|
|
5425
5299
|
value: decodeResult.raw.warning_message
|
|
5426
5300
|
});
|
|
5427
|
-
decodeResult
|
|
5428
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
5301
|
+
this.setDecodeLevel(decodeResult, true, "partial");
|
|
5429
5302
|
} else {
|
|
5430
|
-
|
|
5431
|
-
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
5432
|
-
}
|
|
5433
|
-
ResultFormatter.unknown(decodeResult, message.text);
|
|
5434
|
-
decodeResult.decoded = false;
|
|
5435
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
5303
|
+
return this.failUnknown(decodeResult, message.text, options);
|
|
5436
5304
|
}
|
|
5437
5305
|
return decodeResult;
|
|
5438
5306
|
}
|
|
@@ -5484,10 +5352,47 @@ var Label_HX = class extends DecoderPlugin {
|
|
|
5484
5352
|
}
|
|
5485
5353
|
};
|
|
5486
5354
|
|
|
5355
|
+
// lib/utils/ascii85.ts
|
|
5356
|
+
function ascii85Decode(input) {
|
|
5357
|
+
let str = input;
|
|
5358
|
+
if (str.startsWith("<~")) str = str.slice(2);
|
|
5359
|
+
if (str.endsWith("~>")) str = str.slice(0, -2);
|
|
5360
|
+
str = str.replace(/\s/g, "");
|
|
5361
|
+
if (str.length === 0) return new Uint8Array(0);
|
|
5362
|
+
const output = [];
|
|
5363
|
+
let i = 0;
|
|
5364
|
+
while (i < str.length) {
|
|
5365
|
+
if (str[i] === "z") {
|
|
5366
|
+
output.push(0, 0, 0, 0);
|
|
5367
|
+
i++;
|
|
5368
|
+
continue;
|
|
5369
|
+
}
|
|
5370
|
+
const remaining = str.length - i;
|
|
5371
|
+
const chunkLen = Math.min(5, remaining);
|
|
5372
|
+
if (chunkLen === 1) break;
|
|
5373
|
+
let padded = str.slice(i, i + chunkLen);
|
|
5374
|
+
while (padded.length < 5) padded += "u";
|
|
5375
|
+
let value = 0;
|
|
5376
|
+
for (let j = 0; j < 5; j++) {
|
|
5377
|
+
const digit = padded.charCodeAt(j) - 33;
|
|
5378
|
+
if (digit < 0 || digit > 84) return null;
|
|
5379
|
+
value = value * 85 + digit;
|
|
5380
|
+
}
|
|
5381
|
+
if (chunkLen === 5 && value > 4294967295) return null;
|
|
5382
|
+
const v = value >>> 0;
|
|
5383
|
+
const numBytes = chunkLen === 5 ? 4 : chunkLen - 1;
|
|
5384
|
+
if (numBytes >= 1) output.push(v >>> 24 & 255);
|
|
5385
|
+
if (numBytes >= 2) output.push(v >>> 16 & 255);
|
|
5386
|
+
if (numBytes >= 3) output.push(v >>> 8 & 255);
|
|
5387
|
+
if (numBytes >= 4) output.push(v & 255);
|
|
5388
|
+
i += chunkLen;
|
|
5389
|
+
}
|
|
5390
|
+
return new Uint8Array(output);
|
|
5391
|
+
}
|
|
5392
|
+
|
|
5487
5393
|
// lib/utils/miam.ts
|
|
5488
|
-
var
|
|
5489
|
-
var
|
|
5490
|
-
var import_node_buffer2 = require("buffer");
|
|
5394
|
+
var textDecoder2 = new TextDecoder();
|
|
5395
|
+
var textEncoder = new TextEncoder();
|
|
5491
5396
|
var MIAMVersion = /* @__PURE__ */ ((MIAMVersion2) => {
|
|
5492
5397
|
MIAMVersion2[MIAMVersion2["V1"] = 1] = "V1";
|
|
5493
5398
|
MIAMVersion2[MIAMVersion2["V2"] = 2] = "V2";
|
|
@@ -5574,7 +5479,7 @@ var MIAMCoreUtils = class {
|
|
|
5574
5479
|
error: "Empty MIAM message header"
|
|
5575
5480
|
};
|
|
5576
5481
|
}
|
|
5577
|
-
let hdr =
|
|
5482
|
+
let hdr = ascii85Decode("<~" + rawHdr + "~>");
|
|
5578
5483
|
if (!hdr || hdr.length < hpad) {
|
|
5579
5484
|
return {
|
|
5580
5485
|
decoded: false,
|
|
@@ -5586,17 +5491,24 @@ var MIAMCoreUtils = class {
|
|
|
5586
5491
|
if (rawBody.length > 0) {
|
|
5587
5492
|
if ("0123".indexOf(bpad) >= 0) {
|
|
5588
5493
|
const bpadValue = parseInt(bpad);
|
|
5589
|
-
|
|
5590
|
-
if (
|
|
5494
|
+
const decoded = ascii85Decode("<~" + rawBody + "~>");
|
|
5495
|
+
if (decoded === null) {
|
|
5496
|
+
return {
|
|
5497
|
+
decoded: false,
|
|
5498
|
+
error: "Ascii85 decode failed for MIAM message body"
|
|
5499
|
+
};
|
|
5500
|
+
}
|
|
5501
|
+
body = decoded;
|
|
5502
|
+
if (body.length >= bpadValue) {
|
|
5591
5503
|
body = body.subarray(0, body.length - bpadValue);
|
|
5592
5504
|
}
|
|
5593
5505
|
} else if (bpad === "-") {
|
|
5594
|
-
body =
|
|
5506
|
+
body = textEncoder.encode(rawBody);
|
|
5595
5507
|
}
|
|
5596
5508
|
}
|
|
5597
5509
|
hdr = hdr.subarray(0, hdr.length - hpad);
|
|
5598
|
-
const version = hdr
|
|
5599
|
-
const pduType = hdr
|
|
5510
|
+
const version = hdr[0] & 15;
|
|
5511
|
+
const pduType = hdr[0] >> 4 & 15;
|
|
5600
5512
|
if (isMIAMVersion(version) && isMIAMCorePdu(pduType)) {
|
|
5601
5513
|
const versionPduHandler = this.VersionPduHandlerTable[version][pduType];
|
|
5602
5514
|
return versionPduHandler(hdr, body);
|
|
@@ -5893,7 +5805,7 @@ var MIAMCoreUtils = class {
|
|
|
5893
5805
|
];
|
|
5894
5806
|
let crc = (seed || 0) & 65535;
|
|
5895
5807
|
for (let i = 0; i < buf.length; i++) {
|
|
5896
|
-
crc = (crc << 8 >>> 0 ^ crctable[(crc >>> 8 ^ buf
|
|
5808
|
+
crc = (crc << 8 >>> 0 ^ crctable[(crc >>> 8 ^ buf[i]) >>> 0 & 255]) >>> 0;
|
|
5897
5809
|
}
|
|
5898
5810
|
return crc & 65535;
|
|
5899
5811
|
}
|
|
@@ -6158,7 +6070,7 @@ var MIAMCoreUtils = class {
|
|
|
6158
6070
|
];
|
|
6159
6071
|
let crc = seed || 0;
|
|
6160
6072
|
for (let i = 0; i < buf.length; i++) {
|
|
6161
|
-
crc = (crc << 8 >>> 0 ^ crctable[(crc >>> 24 ^ buf
|
|
6073
|
+
crc = (crc << 8 >>> 0 ^ crctable[(crc >>> 24 ^ buf[i]) >>> 0]) >>> 0;
|
|
6162
6074
|
}
|
|
6163
6075
|
return crc;
|
|
6164
6076
|
}
|
|
@@ -6195,7 +6107,7 @@ var MIAMCoreUtils = class {
|
|
|
6195
6107
|
let msgNum = 0;
|
|
6196
6108
|
let ackOptions = 0;
|
|
6197
6109
|
if (version === 1 /* V1 */) {
|
|
6198
|
-
pduSize = hdr
|
|
6110
|
+
pduSize = hdr[1] << 16 | hdr[2] << 8 | hdr[3];
|
|
6199
6111
|
const msgSize = hdr.length + (body === void 0 ? 0 : body.length);
|
|
6200
6112
|
if (pduSize > msgSize) {
|
|
6201
6113
|
pduIsComplete = false;
|
|
@@ -6204,17 +6116,17 @@ var MIAMCoreUtils = class {
|
|
|
6204
6116
|
);
|
|
6205
6117
|
}
|
|
6206
6118
|
hdr = hdr.subarray(4);
|
|
6207
|
-
tail = hdr.subarray(0, 7)
|
|
6119
|
+
tail = textDecoder2.decode(hdr.subarray(0, 7));
|
|
6208
6120
|
hdr = hdr.subarray(7);
|
|
6209
6121
|
} else if (version === 2 /* V2 */) {
|
|
6210
6122
|
hdr = hdr.subarray(1);
|
|
6211
6123
|
}
|
|
6212
|
-
msgNum = hdr
|
|
6213
|
-
ackOptions = hdr
|
|
6124
|
+
msgNum = hdr[0] >> 1 & 127;
|
|
6125
|
+
ackOptions = hdr[0] & 1;
|
|
6214
6126
|
hdr = hdr.subarray(1);
|
|
6215
|
-
pduCompression = (hdr
|
|
6216
|
-
pduEncoding = hdr
|
|
6217
|
-
pduAppType = hdr
|
|
6127
|
+
pduCompression = (hdr[0] << 2 | hdr[1] >> 6 & 3) & 7;
|
|
6128
|
+
pduEncoding = hdr[1] >> 4 & 3;
|
|
6129
|
+
pduAppType = hdr[1] & 15;
|
|
6218
6130
|
hdr = hdr.subarray(2);
|
|
6219
6131
|
let appIdLen;
|
|
6220
6132
|
if (isMIAMCoreApp(pduAppType)) {
|
|
@@ -6240,12 +6152,12 @@ var MIAMCoreUtils = class {
|
|
|
6240
6152
|
error: "Header too short for v" + version + " appType: " + pduAppType
|
|
6241
6153
|
};
|
|
6242
6154
|
}
|
|
6243
|
-
pduAppId = hdr.subarray(0, appIdLen)
|
|
6155
|
+
pduAppId = textDecoder2.decode(hdr.subarray(0, appIdLen));
|
|
6244
6156
|
hdr = hdr.subarray(appIdLen);
|
|
6245
6157
|
if (crcLen === 4) {
|
|
6246
|
-
pduCrc = hdr
|
|
6158
|
+
pduCrc = hdr[0] << 24 | hdr[1] << 16 | hdr[2] << 8 | hdr[3];
|
|
6247
6159
|
} else if (crcLen === 2) {
|
|
6248
|
-
pduCrc = hdr
|
|
6160
|
+
pduCrc = hdr[0] << 8 | hdr[1];
|
|
6249
6161
|
}
|
|
6250
6162
|
hdr = hdr.subarray(crcLen);
|
|
6251
6163
|
if (body !== void 0 && body.length > 0) {
|
|
@@ -6253,10 +6165,12 @@ var MIAMCoreUtils = class {
|
|
|
6253
6165
|
pduCompression
|
|
6254
6166
|
) >= 0) {
|
|
6255
6167
|
try {
|
|
6256
|
-
const
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6168
|
+
const inflated = inflateData(body, true);
|
|
6169
|
+
if (inflated === void 0) {
|
|
6170
|
+
pduErrors.push("Inflation produced no output for body");
|
|
6171
|
+
} else {
|
|
6172
|
+
pduData = inflated;
|
|
6173
|
+
}
|
|
6260
6174
|
} catch (e) {
|
|
6261
6175
|
pduErrors.push("Inflation failed for body: " + e);
|
|
6262
6176
|
}
|
|
@@ -6314,12 +6228,12 @@ var MIAMCoreUtils = class {
|
|
|
6314
6228
|
label,
|
|
6315
6229
|
...sublabel ? { sublabel } : {},
|
|
6316
6230
|
...mfi ? { mfi } : {},
|
|
6317
|
-
...pduData ? { text:
|
|
6231
|
+
...pduData ? { text: textDecoder2.decode(pduData) } : {}
|
|
6318
6232
|
};
|
|
6319
6233
|
} else {
|
|
6320
6234
|
pdu.non_acars = {
|
|
6321
6235
|
appId: pduAppId,
|
|
6322
|
-
...pduData ? { text:
|
|
6236
|
+
...pduData ? { text: textDecoder2.decode(pduData) } : {}
|
|
6323
6237
|
};
|
|
6324
6238
|
}
|
|
6325
6239
|
return {
|
|
@@ -6440,12 +6354,11 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
6440
6354
|
};
|
|
6441
6355
|
}
|
|
6442
6356
|
decode(message, options = {}) {
|
|
6443
|
-
const decodeResult = this.
|
|
6444
|
-
decodeResult.decoder.name = this.name;
|
|
6357
|
+
const decodeResult = this.initResult(message, "Ground Station Squitter");
|
|
6445
6358
|
decodeResult.raw.preamble = message.text.substring(0, 4);
|
|
6446
|
-
decodeResult.raw.version = message.text.substring(1, 2);
|
|
6359
|
+
decodeResult.raw.version = Number(message.text.substring(1, 2));
|
|
6447
6360
|
decodeResult.raw.network = message.text.substring(3, 4);
|
|
6448
|
-
if (decodeResult.raw.version ===
|
|
6361
|
+
if (decodeResult.raw.version === 2) {
|
|
6449
6362
|
const regex = /0(\d)X(?<org>\w)(?<iata>\w\w\w)(?<icao>\w\w\w\w)(?<station>\d)(?<lat>\d+)(?<latd>[NS])(?<lng>\d+)(?<lngd>[EW])V(?<vfreq>\d+)\/.*/;
|
|
6450
6363
|
const result = message.text.match(regex);
|
|
6451
6364
|
if (result?.groups && result.length >= 8) {
|
|
@@ -6461,7 +6374,6 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
6461
6374
|
decodeResult.raw.vdlFrequency = Number(result.groups.vfreq) / 1e3;
|
|
6462
6375
|
}
|
|
6463
6376
|
}
|
|
6464
|
-
decodeResult.formatted.description = "Ground Station Squitter";
|
|
6465
6377
|
var formattedNetwork = "Unknown";
|
|
6466
6378
|
if (decodeResult.raw.network == "A") {
|
|
6467
6379
|
formattedNetwork = "ARINC";
|
|
@@ -6479,7 +6391,7 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
6479
6391
|
type: "version",
|
|
6480
6392
|
code: "VER",
|
|
6481
6393
|
label: "Version",
|
|
6482
|
-
value: decodeResult.raw.version
|
|
6394
|
+
value: String(decodeResult.raw.version)
|
|
6483
6395
|
}
|
|
6484
6396
|
];
|
|
6485
6397
|
if (decodeResult.raw.groundStation) {
|
|
@@ -6532,8 +6444,7 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
6532
6444
|
value: `${decodeResult.raw.vdlFrequency} MHz`
|
|
6533
6445
|
});
|
|
6534
6446
|
}
|
|
6535
|
-
decodeResult
|
|
6536
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
6447
|
+
this.setDecodeLevel(decodeResult, true, "full");
|
|
6537
6448
|
return decodeResult;
|
|
6538
6449
|
}
|
|
6539
6450
|
};
|
|
@@ -6685,103 +6596,130 @@ var Label_QQ = class extends DecoderPlugin {
|
|
|
6685
6596
|
};
|
|
6686
6597
|
|
|
6687
6598
|
// lib/MessageDecoder.ts
|
|
6599
|
+
var pluginClasses = [
|
|
6600
|
+
CBand,
|
|
6601
|
+
Arinc702,
|
|
6602
|
+
Label_ColonComma,
|
|
6603
|
+
Label_5Z_Slash,
|
|
6604
|
+
Label_10_LDR,
|
|
6605
|
+
Label_10_POS,
|
|
6606
|
+
Label_10_Slash,
|
|
6607
|
+
Label_12_N_Space,
|
|
6608
|
+
Label_12_POS,
|
|
6609
|
+
Label_13Through18_Slash,
|
|
6610
|
+
Label_15,
|
|
6611
|
+
Label_15_FST,
|
|
6612
|
+
Label_16_Honeywell,
|
|
6613
|
+
Label_16_N_Space,
|
|
6614
|
+
Label_16_POSA1,
|
|
6615
|
+
Label_16_TOD,
|
|
6616
|
+
Label_1L_3Line,
|
|
6617
|
+
Label_1L_070,
|
|
6618
|
+
Label_1L_660,
|
|
6619
|
+
Label_1L_Slash,
|
|
6620
|
+
Label_20_POS,
|
|
6621
|
+
Label_21_POS,
|
|
6622
|
+
Label_22_OFF,
|
|
6623
|
+
Label_22_POS,
|
|
6624
|
+
Label_24_Slash,
|
|
6625
|
+
Label_2P_FM3,
|
|
6626
|
+
Label_2P_FM4,
|
|
6627
|
+
Label_2P_FM5,
|
|
6628
|
+
Label_30_Slash_EA,
|
|
6629
|
+
Label_44_ETA,
|
|
6630
|
+
Label_44_IN,
|
|
6631
|
+
Label_44_OFF,
|
|
6632
|
+
Label_44_ON,
|
|
6633
|
+
Label_44_POS,
|
|
6634
|
+
Label_44_Slash,
|
|
6635
|
+
Label_4A,
|
|
6636
|
+
Label_4A_01,
|
|
6637
|
+
Label_4A_DIS,
|
|
6638
|
+
Label_4A_DOOR,
|
|
6639
|
+
Label_4A_Slash_01,
|
|
6640
|
+
Label_4N,
|
|
6641
|
+
Label_4T_AGFSR,
|
|
6642
|
+
Label_4T_ETA,
|
|
6643
|
+
Label_B6_Forwardslash,
|
|
6644
|
+
Label_H2_02E,
|
|
6645
|
+
Label_H1_ATIS,
|
|
6646
|
+
Label_H1_EZF,
|
|
6647
|
+
Label_H1_FLR,
|
|
6648
|
+
Label_H1_M_POS,
|
|
6649
|
+
Label_H1_OHMA,
|
|
6650
|
+
Label_H1_OFP,
|
|
6651
|
+
Label_H1_Paren,
|
|
6652
|
+
Label_H1_WRN,
|
|
6653
|
+
Label_H1_StarPOS,
|
|
6654
|
+
Label_HX,
|
|
6655
|
+
Label_58,
|
|
6656
|
+
Label_80,
|
|
6657
|
+
Label_83,
|
|
6658
|
+
Label_8E,
|
|
6659
|
+
Label_1M_Slash,
|
|
6660
|
+
Label_MA,
|
|
6661
|
+
Label_SQ,
|
|
6662
|
+
Label_QP,
|
|
6663
|
+
Label_QQ,
|
|
6664
|
+
Label_QR,
|
|
6665
|
+
Label_QS
|
|
6666
|
+
];
|
|
6688
6667
|
var MessageDecoder = class {
|
|
6689
6668
|
name;
|
|
6690
6669
|
plugins;
|
|
6691
6670
|
debug;
|
|
6671
|
+
/** Maps a label string to the candidate entries (wildcard + label-specific) in registration order. */
|
|
6672
|
+
candidatesByLabel = /* @__PURE__ */ new Map();
|
|
6673
|
+
/** Wildcard entries (plugins that register the '*' label). */
|
|
6674
|
+
wildcardEntries = [];
|
|
6675
|
+
/** Membership set for wildcard entries to dedupe when a plugin also registers a specific label. */
|
|
6676
|
+
wildcardSet = /* @__PURE__ */ new Set();
|
|
6692
6677
|
constructor() {
|
|
6693
6678
|
this.name = "acars-decoder-typescript";
|
|
6694
6679
|
this.plugins = [];
|
|
6695
6680
|
this.debug = false;
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
this.registerPlugin(new Label_5Z_Slash(this));
|
|
6700
|
-
this.registerPlugin(new Label_10_LDR(this));
|
|
6701
|
-
this.registerPlugin(new Label_10_POS(this));
|
|
6702
|
-
this.registerPlugin(new Label_10_Slash(this));
|
|
6703
|
-
this.registerPlugin(new Label_12_N_Space(this));
|
|
6704
|
-
this.registerPlugin(new Label_12_POS(this));
|
|
6705
|
-
this.registerPlugin(new Label_13Through18_Slash(this));
|
|
6706
|
-
this.registerPlugin(new Label_15(this));
|
|
6707
|
-
this.registerPlugin(new Label_15_FST(this));
|
|
6708
|
-
this.registerPlugin(new Label_16_Honeywell(this));
|
|
6709
|
-
this.registerPlugin(new Label_16_N_Space(this));
|
|
6710
|
-
this.registerPlugin(new Label_16_POSA1(this));
|
|
6711
|
-
this.registerPlugin(new Label_16_TOD(this));
|
|
6712
|
-
this.registerPlugin(new Label_1L_3Line(this));
|
|
6713
|
-
this.registerPlugin(new Label_1L_070(this));
|
|
6714
|
-
this.registerPlugin(new Label_1L_660(this));
|
|
6715
|
-
this.registerPlugin(new Label_1L_Slash(this));
|
|
6716
|
-
this.registerPlugin(new Label_20_POS(this));
|
|
6717
|
-
this.registerPlugin(new Label_21_POS(this));
|
|
6718
|
-
this.registerPlugin(new Label_22_OFF(this));
|
|
6719
|
-
this.registerPlugin(new Label_22_POS(this));
|
|
6720
|
-
this.registerPlugin(new Label_24_Slash(this));
|
|
6721
|
-
this.registerPlugin(new Label_2P_FM3(this));
|
|
6722
|
-
this.registerPlugin(new Label_2P_FM4(this));
|
|
6723
|
-
this.registerPlugin(new Label_2P_FM5(this));
|
|
6724
|
-
this.registerPlugin(new Label_30_Slash_EA(this));
|
|
6725
|
-
this.registerPlugin(new Label_44_ETA(this));
|
|
6726
|
-
this.registerPlugin(new Label_44_IN(this));
|
|
6727
|
-
this.registerPlugin(new Label_44_OFF(this));
|
|
6728
|
-
this.registerPlugin(new Label_44_ON(this));
|
|
6729
|
-
this.registerPlugin(new Label_44_POS(this));
|
|
6730
|
-
this.registerPlugin(new Label_44_Slash(this));
|
|
6731
|
-
this.registerPlugin(new Label_4A(this));
|
|
6732
|
-
this.registerPlugin(new Label_4A_01(this));
|
|
6733
|
-
this.registerPlugin(new Label_4A_DIS(this));
|
|
6734
|
-
this.registerPlugin(new Label_4A_DOOR(this));
|
|
6735
|
-
this.registerPlugin(new Label_4A_Slash_01(this));
|
|
6736
|
-
this.registerPlugin(new Label_4N(this));
|
|
6737
|
-
this.registerPlugin(new Label_4T_AGFSR(this));
|
|
6738
|
-
this.registerPlugin(new Label_4T_ETA(this));
|
|
6739
|
-
this.registerPlugin(new Label_B6_Forwardslash(this));
|
|
6740
|
-
this.registerPlugin(new Label_H2_02E(this));
|
|
6741
|
-
this.registerPlugin(new Label_H1_ATIS(this));
|
|
6742
|
-
this.registerPlugin(new Label_H1_EZF(this));
|
|
6743
|
-
this.registerPlugin(new Label_H1_FLR(this));
|
|
6744
|
-
this.registerPlugin(new Label_H1_M_POS(this));
|
|
6745
|
-
this.registerPlugin(new Label_H1_OHMA(this));
|
|
6746
|
-
this.registerPlugin(new Label_H1_OFP(this));
|
|
6747
|
-
this.registerPlugin(new Label_H1_Paren(this));
|
|
6748
|
-
this.registerPlugin(new Label_H1_WRN(this));
|
|
6749
|
-
this.registerPlugin(new Label_H1_StarPOS(this));
|
|
6750
|
-
this.registerPlugin(new Label_HX(this));
|
|
6751
|
-
this.registerPlugin(new Label_58(this));
|
|
6752
|
-
this.registerPlugin(new Label_80(this));
|
|
6753
|
-
this.registerPlugin(new Label_83(this));
|
|
6754
|
-
this.registerPlugin(new Label_8E(this));
|
|
6755
|
-
this.registerPlugin(new Label_1M_Slash(this));
|
|
6756
|
-
this.registerPlugin(new Label_MA(this));
|
|
6757
|
-
this.registerPlugin(new Label_SQ(this));
|
|
6758
|
-
this.registerPlugin(new Label_QP(this));
|
|
6759
|
-
this.registerPlugin(new Label_QQ(this));
|
|
6760
|
-
this.registerPlugin(new Label_QR(this));
|
|
6761
|
-
this.registerPlugin(new Label_QS(this));
|
|
6681
|
+
for (const PluginClass of pluginClasses) {
|
|
6682
|
+
this.registerPlugin(new PluginClass(this));
|
|
6683
|
+
}
|
|
6762
6684
|
}
|
|
6763
6685
|
registerPlugin(plugin) {
|
|
6764
6686
|
this.plugins.push(plugin);
|
|
6687
|
+
const qualifiers = plugin.qualifiers();
|
|
6688
|
+
const entry = {
|
|
6689
|
+
plugin,
|
|
6690
|
+
preambles: qualifiers.preambles && qualifiers.preambles.length > 0 ? qualifiers.preambles : void 0
|
|
6691
|
+
};
|
|
6692
|
+
for (const label of qualifiers.labels) {
|
|
6693
|
+
if (label === "*") {
|
|
6694
|
+
if (!this.wildcardSet.has(plugin)) {
|
|
6695
|
+
this.wildcardEntries.push(entry);
|
|
6696
|
+
this.wildcardSet.add(plugin);
|
|
6697
|
+
const wildcardInsertIndex = this.wildcardEntries.length - 1;
|
|
6698
|
+
for (const bucket of this.candidatesByLabel.values()) {
|
|
6699
|
+
bucket.splice(wildcardInsertIndex, 0, entry);
|
|
6700
|
+
}
|
|
6701
|
+
}
|
|
6702
|
+
} else {
|
|
6703
|
+
let bucket = this.candidatesByLabel.get(label);
|
|
6704
|
+
if (!bucket) {
|
|
6705
|
+
bucket = this.wildcardEntries.slice();
|
|
6706
|
+
this.candidatesByLabel.set(label, bucket);
|
|
6707
|
+
}
|
|
6708
|
+
if (!this.wildcardSet.has(plugin)) {
|
|
6709
|
+
bucket.push(entry);
|
|
6710
|
+
}
|
|
6711
|
+
}
|
|
6712
|
+
}
|
|
6765
6713
|
return true;
|
|
6766
6714
|
}
|
|
6767
6715
|
decode(message, options = {}) {
|
|
6768
|
-
const
|
|
6769
|
-
|
|
6770
|
-
if (qualifiers.labels.includes(message.label) || qualifiers.labels.length === 1 && qualifiers.labels[0] === "*") {
|
|
6771
|
-
if (qualifiers.preambles && qualifiers.preambles.length > 0) {
|
|
6772
|
-
const matching = qualifiers.preambles.filter((preamble) => {
|
|
6773
|
-
return message.text.substring(0, preamble.length) === preamble;
|
|
6774
|
-
});
|
|
6775
|
-
return matching.length >= 1;
|
|
6776
|
-
} else {
|
|
6777
|
-
return true;
|
|
6778
|
-
}
|
|
6779
|
-
}
|
|
6780
|
-
return false;
|
|
6781
|
-
});
|
|
6716
|
+
const text = message.text;
|
|
6717
|
+
const candidates = this.candidatesByLabel.get(message.label) ?? this.wildcardEntries;
|
|
6782
6718
|
if (options.debug) {
|
|
6783
6719
|
console.log("Usable plugins");
|
|
6784
|
-
console.log(
|
|
6720
|
+
console.log(
|
|
6721
|
+
candidates.filter((e) => this.matchesPreambles(text, e.preambles)).map((e) => e.plugin)
|
|
6722
|
+
);
|
|
6785
6723
|
}
|
|
6786
6724
|
let result = {
|
|
6787
6725
|
decoded: false,
|
|
@@ -6793,7 +6731,7 @@ var MessageDecoder = class {
|
|
|
6793
6731
|
},
|
|
6794
6732
|
message,
|
|
6795
6733
|
remaining: {
|
|
6796
|
-
text
|
|
6734
|
+
text
|
|
6797
6735
|
},
|
|
6798
6736
|
raw: {},
|
|
6799
6737
|
formatted: {
|
|
@@ -6801,10 +6739,14 @@ var MessageDecoder = class {
|
|
|
6801
6739
|
items: []
|
|
6802
6740
|
}
|
|
6803
6741
|
};
|
|
6804
|
-
for (let i = 0; i <
|
|
6805
|
-
const
|
|
6806
|
-
|
|
6807
|
-
|
|
6742
|
+
for (let i = 0; i < candidates.length; i++) {
|
|
6743
|
+
const entry = candidates[i];
|
|
6744
|
+
if (!this.matchesPreambles(text, entry.preambles)) {
|
|
6745
|
+
continue;
|
|
6746
|
+
}
|
|
6747
|
+
const pluginResult = entry.plugin.decode(message, options);
|
|
6748
|
+
if (pluginResult.decoded) {
|
|
6749
|
+
result = pluginResult;
|
|
6808
6750
|
break;
|
|
6809
6751
|
}
|
|
6810
6752
|
}
|
|
@@ -6814,6 +6756,17 @@ var MessageDecoder = class {
|
|
|
6814
6756
|
}
|
|
6815
6757
|
return result;
|
|
6816
6758
|
}
|
|
6759
|
+
matchesPreambles(text, preambles) {
|
|
6760
|
+
if (!preambles) {
|
|
6761
|
+
return true;
|
|
6762
|
+
}
|
|
6763
|
+
for (let i = 0; i < preambles.length; i++) {
|
|
6764
|
+
if (text.startsWith(preambles[i])) {
|
|
6765
|
+
return true;
|
|
6766
|
+
}
|
|
6767
|
+
}
|
|
6768
|
+
return false;
|
|
6769
|
+
}
|
|
6817
6770
|
};
|
|
6818
6771
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6819
6772
|
0 && (module.exports = {
|