asterix-parser 1.0.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.
@@ -0,0 +1,1785 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cat021Process = void 0;
4
+ const common_1 = require("../common");
5
+ const preprocess_1 = require("../preprocess");
6
+ /**
7
+ * CAT 021 파싱
8
+ * @param record 단일 Record 파싱 결과
9
+ * @param bitArr Asterix 바이트 데이터
10
+ * @param currentPos 데이터 아이템 시작 인덱스
11
+ * @param dataItem 데이터 아이템 이름
12
+ * @param diLength 데이터 아이템 길이
13
+ */
14
+ const cat021Process = (record, bitArr, currentPos, dataItem, diLength) => {
15
+ switch (dataItem) {
16
+ case "di008": {
17
+ di008(record, bitArr, currentPos);
18
+ break;
19
+ }
20
+ case "di010": {
21
+ di010(record, bitArr, currentPos);
22
+ break;
23
+ }
24
+ case "di015": {
25
+ di015(record, bitArr, currentPos);
26
+ break;
27
+ }
28
+ case "di016": {
29
+ di016(record, bitArr, currentPos);
30
+ break;
31
+ }
32
+ case "di020": {
33
+ di020(record, bitArr, currentPos);
34
+ break;
35
+ }
36
+ case "di040": {
37
+ di040(record, bitArr, currentPos);
38
+ break;
39
+ }
40
+ case "di070": {
41
+ di070(record, bitArr, currentPos);
42
+ break;
43
+ }
44
+ case "di071": {
45
+ di071(record, bitArr, currentPos);
46
+ break;
47
+ }
48
+ case "di072": {
49
+ di072(record, bitArr, currentPos);
50
+ break;
51
+ }
52
+ case "di073": {
53
+ di073(record, bitArr, currentPos);
54
+ break;
55
+ }
56
+ case "di074": {
57
+ di074(record, bitArr, currentPos);
58
+ break;
59
+ }
60
+ case "di075": {
61
+ di075(record, bitArr, currentPos);
62
+ break;
63
+ }
64
+ case "di076": {
65
+ di076(record, bitArr, currentPos);
66
+ break;
67
+ }
68
+ case "di077": {
69
+ di077(record, bitArr, currentPos);
70
+ break;
71
+ }
72
+ case "di080": {
73
+ di080(record, bitArr, currentPos);
74
+ break;
75
+ }
76
+ case "di090": {
77
+ di090(record, bitArr, currentPos);
78
+ break;
79
+ }
80
+ case "di110": {
81
+ di110(record, bitArr, currentPos);
82
+ break;
83
+ }
84
+ case "di130": {
85
+ di130(record, bitArr, currentPos);
86
+ break;
87
+ }
88
+ case "di131": {
89
+ di131(record, bitArr, currentPos);
90
+ break;
91
+ }
92
+ case "di132": {
93
+ di132(record, bitArr, currentPos);
94
+ break;
95
+ }
96
+ case "di140": {
97
+ di140(record, bitArr, currentPos);
98
+ break;
99
+ }
100
+ case "di145": {
101
+ di145(record, bitArr, currentPos);
102
+ break;
103
+ }
104
+ case "di146": {
105
+ di146(record, bitArr, currentPos);
106
+ break;
107
+ }
108
+ case "di148": {
109
+ di148(record, bitArr, currentPos);
110
+ break;
111
+ }
112
+ case "di150": {
113
+ di150(record, bitArr, currentPos);
114
+ break;
115
+ }
116
+ case "di151": {
117
+ di151(record, bitArr, currentPos);
118
+ break;
119
+ }
120
+ case "di152": {
121
+ di152(record, bitArr, currentPos);
122
+ break;
123
+ }
124
+ case "di155": {
125
+ di155(record, bitArr, currentPos);
126
+ break;
127
+ }
128
+ case "di157": {
129
+ di157(record, bitArr, currentPos);
130
+ break;
131
+ }
132
+ case "di160": {
133
+ di160(record, bitArr, currentPos);
134
+ break;
135
+ }
136
+ case "di161": {
137
+ di161(record, bitArr, currentPos);
138
+ break;
139
+ }
140
+ case "di165": {
141
+ di165(record, bitArr, currentPos);
142
+ break;
143
+ }
144
+ case "di170": {
145
+ di170(record, bitArr, currentPos);
146
+ break;
147
+ }
148
+ case "di200": {
149
+ di200(record, bitArr, currentPos);
150
+ break;
151
+ }
152
+ case "di210": {
153
+ di210(record, bitArr, currentPos);
154
+ break;
155
+ }
156
+ case "di220": {
157
+ di220(record, bitArr, currentPos);
158
+ break;
159
+ }
160
+ case "di230": {
161
+ di230(record, bitArr, currentPos);
162
+ break;
163
+ }
164
+ case "di250": {
165
+ di250(record, bitArr, currentPos);
166
+ break;
167
+ }
168
+ case "di260": {
169
+ di260(record, bitArr, currentPos);
170
+ break;
171
+ }
172
+ case "di271": {
173
+ di271(record, bitArr, currentPos);
174
+ break;
175
+ }
176
+ case "di295": {
177
+ di295(record, bitArr, currentPos);
178
+ break;
179
+ }
180
+ case "di400": {
181
+ di400(record, bitArr, currentPos);
182
+ break;
183
+ }
184
+ case "SP": {
185
+ sp(record, bitArr, currentPos, diLength);
186
+ break;
187
+ }
188
+ case "RE": {
189
+ re(record, bitArr, currentPos, diLength);
190
+ break;
191
+ }
192
+ default:
193
+ break;
194
+ }
195
+ };
196
+ exports.cat021Process = cat021Process;
197
+ /**
198
+ * Data Item I021/008, Aircraft Operational Status
199
+ * 비행 중 항공기에서 이용 가능한 서비스 확인
200
+ * @param record 단일 Record 파싱 결과
201
+ * @param bitArr Asterix 바이트 데이터
202
+ * @param currentPos 데이터 아이템 시작 인덱스
203
+ */
204
+ const di008 = (record, bitArr, currentPos) => {
205
+ const octet1 = bitArr[currentPos];
206
+ if ((octet1 & (1 << 7)) === 0) {
207
+ record["021_008_RA"] = "TCAS II or ACAS RA not active (0)";
208
+ }
209
+ else {
210
+ record["021_008_RA"] = "TCAS RA active (1)";
211
+ }
212
+ const tcOctet = (0, common_1.octetOfRange)(octet1, 6, 5, 1);
213
+ switch (tcOctet) {
214
+ case 0:
215
+ record["021_008_TC"] = "no capability for Trajectory Change Reports (0)";
216
+ break;
217
+ case 1:
218
+ record["021_008_TC"] = "support for TC+0 reports only (1)";
219
+ break;
220
+ case 2:
221
+ record["021_008_TC"] = "support for multiple TC reports (2)";
222
+ break;
223
+ case 3:
224
+ record["021_008_TC"] = "reserved (3)";
225
+ break;
226
+ default:
227
+ record["021_008_TC"] = "UNDEFINED";
228
+ break;
229
+ }
230
+ if ((octet1 & (1 << 4)) === 0) {
231
+ record["021_008_TS"] = "no capability to support Target State Reports (0)";
232
+ }
233
+ else {
234
+ record["021_008_TS"] = "capable of supporting target State Reports (1)";
235
+ }
236
+ if ((octet1 & (1 << 3)) === 0) {
237
+ record["021_008_ARV"] = "no capability to generate ARV-reports (0)";
238
+ }
239
+ else {
240
+ record["021_008_ARV"] = "capable of generate ARV-reports (1)";
241
+ }
242
+ if ((octet1 & (1 << 2)) === 0) {
243
+ record["021_008_CDTI/A"] = "CDTI not operational (0)";
244
+ }
245
+ else {
246
+ record["021_008_CDTI/A"] = "CDTI operational (1)";
247
+ }
248
+ if ((octet1 & (1 << 1)) === 0) {
249
+ record["021_008_Not TCAS"] = "TCAS operational (0)";
250
+ }
251
+ else {
252
+ record["021_008_Not TCAS"] = "TCAS not operational (1)";
253
+ }
254
+ if ((octet1 & (1 << 0)) === 0) {
255
+ record["021_008_SA"] = "Antenna Diversity (0)";
256
+ }
257
+ else {
258
+ record["021_008_SA"] = "Single Antenna only (1)";
259
+ }
260
+ };
261
+ /**
262
+ * Data Item I021/010, Data Source Identifier
263
+ * 데이터를 수신받은 시스템의 ID 값
264
+ * 고정 길이, 2 octet
265
+ * @param record 단일 Record 파싱 결과
266
+ * @param bitArr Asterix 바이트 데이터
267
+ * @param currentPos 데이터 아이템 시작 인덱스
268
+ */
269
+ const di010 = (record, bitArr, currentPos) => {
270
+ const octet1 = bitArr[currentPos++];
271
+ const octet2 = bitArr[currentPos++];
272
+ record["021_010_SAC"] = octet1;
273
+ record["021_010_SIC"] = octet2;
274
+ };
275
+ /**
276
+ * Data Item I021/015, Service Identification
277
+ * 한 명 이상의 사용자에게 제공한 서비스의 ID 값
278
+ * 고정 길이, 1 octet
279
+ * @param record 단일 Record 파싱 결과
280
+ * @param bitArr Asterix 바이트 데이터
281
+ * @param currentPos 데이터 아이템 시작 인덱스
282
+ */
283
+ const di015 = (record, bitArr, currentPos) => {
284
+ const octet = bitArr[currentPos];
285
+ record["021_015_Service Identification"] = octet;
286
+ };
287
+ /**
288
+ * Data Item I021/016, Service Management
289
+ * 지상국 (SIC 코드로 식별됨)에서 제공하는 서비스 식별
290
+ * 고정 길이, 1 octet
291
+ * LSB(스케일링 계수): 0.5 s
292
+ * @param record 단일 Record 파싱 결과
293
+ * @param bitArr Asterix 바이트 데이터
294
+ * @param currentPos 데이터 아이템 시작 인덱스
295
+ */
296
+ const di016 = (record, bitArr, currentPos) => {
297
+ const octet = bitArr[currentPos];
298
+ const rpValue = octet * 0.5;
299
+ record["021_016_RP"] = (rpValue === 0) ? "Data driven mode" : rpValue;
300
+ };
301
+ /**
302
+ * Data Item I021/020, Emitter Category
303
+ * 송신(출발지) ADS-B 장치의 특성
304
+ * 고정 길이, 1 octet
305
+ * @param record 단일 Record 파싱 결과
306
+ * @param bitArr Asterix 바이트 데이터
307
+ * @param currentPos 데이터 아이템 시작 인덱스
308
+ */
309
+ const di020 = (record, bitArr, currentPos) => {
310
+ const octet = bitArr[currentPos];
311
+ switch (octet) {
312
+ case 0:
313
+ record["021_020_ECAT"] = "No ADS-B Emitter Category Information (0)";
314
+ break;
315
+ case 1:
316
+ record["021_020_ECAT"] = "light aircraft <= 15500 lbs (1)";
317
+ break;
318
+ case 2:
319
+ record["021_020_ECAT"] = "15500 lbs < small aircraft < 75000 lbs (2)";
320
+ break;
321
+ case 3:
322
+ record["021_020_ECAT"] = "75000 lbs < medium a/c < 300000 lbs (3)";
323
+ break;
324
+ case 4:
325
+ record["021_020_ECAT"] = "High Vortex Large (4)";
326
+ break;
327
+ case 5:
328
+ record["021_020_ECAT"] = "300000 lbs <= heavy aircraft (5)";
329
+ break;
330
+ case 6:
331
+ record["021_020_ECAT"] = "highly manoeuvrable (5g acceleration capability) and high speed (> 400 knots cruise) (6)";
332
+ break;
333
+ case 7:
334
+ record["021_020_ECAT"] = "reserved (7)";
335
+ break;
336
+ case 8:
337
+ record["021_020_ECAT"] = "reserved (8)";
338
+ break;
339
+ case 9:
340
+ record["021_020_ECAT"] = "reserved (9)";
341
+ break;
342
+ case 10:
343
+ record["021_020_ECAT"] = "rotocraft (10)";
344
+ break;
345
+ case 11:
346
+ record["021_020_ECAT"] = "glider / sailplane (11)";
347
+ break;
348
+ case 12:
349
+ record["021_020_ECAT"] = "lighter-than-air (12)";
350
+ break;
351
+ case 13:
352
+ record["021_020_ECAT"] = "unmanned aerial vehicle (13)";
353
+ break;
354
+ case 14:
355
+ record["021_020_ECAT"] = "space / transatmospheric vehicle (14)";
356
+ break;
357
+ case 15:
358
+ record["021_020_ECAT"] = "ultralight / handglider / paraglider (15)";
359
+ break;
360
+ case 16:
361
+ record["021_020_ECAT"] = "parachutist / skydiver (16)";
362
+ break;
363
+ case 17:
364
+ record["021_020_ECAT"] = "reserved (17)";
365
+ break;
366
+ case 18:
367
+ record["021_020_ECAT"] = "reserved (18)";
368
+ break;
369
+ case 19:
370
+ record["021_020_ECAT"] = "reserved (19)";
371
+ break;
372
+ case 20:
373
+ record["021_020_ECAT"] = "surface emergency vehicle (20)";
374
+ break;
375
+ case 21:
376
+ record["021_020_ECAT"] = "surface service vehicle (21)";
377
+ break;
378
+ case 22:
379
+ record["021_020_ECAT"] = "fixed ground or tethered obstruction (22)";
380
+ break;
381
+ case 23:
382
+ record["021_020_ECAT"] = "cluster obstacle (23)";
383
+ break;
384
+ case 24:
385
+ record["021_020_ECAT"] = "line obstacle (24)";
386
+ break;
387
+ default:
388
+ record["021_020_ECAT"] = "UNDEFINED";
389
+ break;
390
+ }
391
+ };
392
+ /**
393
+ * Data Item I021/040, Target Report Descriptor
394
+ * 시스템에 의해 전송되는 데이터의 유형 및 특성
395
+ * 가변 길이
396
+ * @param record 단일 Record 파싱 결과
397
+ * @param bitArr Asterix 바이트 데이터
398
+ * @param currentPos 데이터 아이템 시작 인덱스
399
+ */
400
+ const di040 = (record, bitArr, currentPos) => {
401
+ const octet1 = bitArr[currentPos++];
402
+ const atpOctet = (0, common_1.octetOfRange)(octet1, 7, 5, 2);
403
+ switch (atpOctet) {
404
+ case 0:
405
+ record["021_040_ATP"] = "24-Bit ICAO address (0)";
406
+ break;
407
+ case 1:
408
+ record["021_040_ATP"] = "Duplicate address (1)";
409
+ break;
410
+ case 2:
411
+ record["021_040_ATP"] = "Surface vehicle address (2)";
412
+ break;
413
+ case 3:
414
+ record["021_040_ATP"] = "Anonymous address (3)";
415
+ break;
416
+ case 4:
417
+ record["021_040_ATP"] = "Reserved for future use (4)";
418
+ break;
419
+ case 5:
420
+ record["021_040_ATP"] = "Reserved for future use (5)";
421
+ break;
422
+ case 6:
423
+ record["021_040_ATP"] = "Reserved for future use (6)";
424
+ break;
425
+ case 7:
426
+ record["021_040_ATP"] = "Reserved for future use (7)";
427
+ break;
428
+ default:
429
+ record["021_040_ATP"] = "UNDEFINED";
430
+ break;
431
+ }
432
+ const arcOctet = (0, common_1.octetOfRange)(octet1, 4, 3, 1);
433
+ switch (arcOctet) {
434
+ case 0:
435
+ record["021_040_ARC"] = "25 ft (0)";
436
+ break;
437
+ case 1:
438
+ record["021_040_ARC"] = "100 ft (1)";
439
+ break;
440
+ case 2:
441
+ record["021_040_ARC"] = "Unknown (2)";
442
+ break;
443
+ case 3:
444
+ record["021_040_ARC"] = "Invalid (3)";
445
+ break;
446
+ default:
447
+ record["021_040_ARC"] = "UNDEFINED";
448
+ break;
449
+ }
450
+ if ((octet1 & (1 << 2)) === 0) {
451
+ record["021_040_RC"] = "Default (0)";
452
+ }
453
+ else {
454
+ record["021_040_RC"] = "Range Check passed, CPR Validation pending (1)";
455
+ }
456
+ if ((octet1 & (1 << 1)) === 0) {
457
+ record["021_040_RAB"] = "Report from target transponder (0)";
458
+ }
459
+ else {
460
+ record["021_040_RAB"] = "Report from field monitor (fixed transponder) (1)";
461
+ }
462
+ if ((octet1 & 1) == 0)
463
+ return;
464
+ const octet2 = bitArr[currentPos++];
465
+ if ((octet2 & (1 << 7)) === 0) {
466
+ record["021_040_DRC"] = "No differential correction (ADS-B) (0)";
467
+ }
468
+ else {
469
+ record["021_040_DRC"] = "Differential correction (ADS-B) (1)";
470
+ }
471
+ if ((octet2 & (1 << 6)) === 0) {
472
+ record["021_040_GBS"] = "Ground Bit not set (0)";
473
+ }
474
+ else {
475
+ record["021_040_GBS"] = "Ground Bit set (1)";
476
+ }
477
+ if ((octet2 & (1 << 5)) === 0) {
478
+ record["021_040_SIM"] = "Actual target report (0)";
479
+ }
480
+ else {
481
+ record["021_040_SIM"] = "Simulated target report (1)";
482
+ }
483
+ if ((octet2 & (1 << 4)) === 0) {
484
+ record["021_040_TST"] = "Default (0)";
485
+ }
486
+ else {
487
+ record["021_040_TST"] = "Test Target (1)";
488
+ }
489
+ if ((octet2 & (1 << 3)) === 0) {
490
+ record["021_040_SAA"] = "Equipment capable to provide Selected Altitude (0)";
491
+ }
492
+ else {
493
+ record["021_040_SAA"] = "Equipment not capable to provide Selected Altitude (1)";
494
+ }
495
+ const clOctet = (0, common_1.octetOfRange)(octet2, 2, 1, 1);
496
+ switch (clOctet) {
497
+ case 0:
498
+ record["021_040_CL"] = "Report valid (0)";
499
+ break;
500
+ case 1:
501
+ record["021_040_CL"] = "Report suspect (1)";
502
+ break;
503
+ case 2:
504
+ record["021_040_CL"] = "No information (2)";
505
+ break;
506
+ case 3:
507
+ record["021_040_CL"] = "Reserved for future use (3)";
508
+ break;
509
+ default:
510
+ record["021_040_CL"] = "UNDEFINED";
511
+ break;
512
+ }
513
+ if ((octet2 & 1) == 0)
514
+ return;
515
+ const octet3 = bitArr[currentPos++];
516
+ if ((octet3 & (1 << 6)) === 0) {
517
+ record["021_040_LLC"] = "default (0)";
518
+ }
519
+ else {
520
+ record["021_040_LLC"] = "Target is suspect (see note) (1)";
521
+ }
522
+ if ((octet3 & (1 << 5)) === 0) {
523
+ record["021_040_IPC"] = "default (see note) (0)";
524
+ }
525
+ else {
526
+ record["021_040_IPC"] = "Independent Position Check failed (1)";
527
+ }
528
+ if ((octet3 & (1 << 4)) === 0) {
529
+ record["021_040_NOGO"] = "NOGO-bit not set (0)";
530
+ }
531
+ else {
532
+ record["021_040_NOGO"] = "NOGO-bit set (1)";
533
+ }
534
+ if ((octet3 & (1 << 3)) === 0) {
535
+ record["021_040_CPR"] = "CPR Validation correct (0)";
536
+ }
537
+ else {
538
+ record["021_040_CPR"] = "CPR Validation failed (1)";
539
+ }
540
+ if ((octet3 & (1 << 2)) === 0) {
541
+ record["021_040_LDPJ"] = "LDPJ not detected (0)";
542
+ }
543
+ else {
544
+ record["021_040_LDPJ"] = "LDPJ detected (1)";
545
+ }
546
+ if ((octet3 & (1 << 1)) === 0) {
547
+ record["021_040_RCF"] = "default (0)";
548
+ }
549
+ else {
550
+ record["021_040_RCF"] = "Range Check failed (1)";
551
+ }
552
+ };
553
+ /**
554
+ * Data Item I021/070, Mode 3/A Code in Octal Representation
555
+ * 8진수 표현으로 변환된 Mode-3/A 코드
556
+ * 고정 길이, 1 octet
557
+ * @param record 단일 Record 파싱 결과
558
+ * @param bitArr Asterix 바이트 데이터
559
+ * @param currentPos 데이터 아이템 시작 인덱스
560
+ */
561
+ const di070 = (record, bitArr, currentPos) => {
562
+ const octet1 = bitArr[currentPos++];
563
+ const octet2 = bitArr[currentPos++];
564
+ const aStr = (0, common_1.octetOfRange)(octet1, 3, 1, 2).toString();
565
+ const bStr = (((0, common_1.octetOfRange)(octet1, 0, 0, 0) << 2) | (0, common_1.octetOfRange)(octet2, 7, 6, 1)).toString();
566
+ const cStr = (0, common_1.octetOfRange)(octet2, 5, 3, 2).toString();
567
+ const dStr = (0, common_1.octetOfRange)(octet2, 2, 0, 2).toString();
568
+ record["021_070_Mode-3/A"] = aStr + bStr + cStr + dStr;
569
+ };
570
+ /**
571
+ * Data Item I021/071, Time of Applicability for Position
572
+ * 보고된 위치 정보의 유효 시간 (지난 자정 이후 경과된 시간 형태, 협정 세계시(UTC)로 표시)
573
+ * 고정 길이, 3 octet
574
+ * LSB(스케일링 계수): 1/128 s
575
+ * @param record 단일 Record 파싱 결과
576
+ * @param bitArr Asterix 바이트 데이터
577
+ * @param currentPos 데이터 아이템 시작 인덱스
578
+ */
579
+ const di071 = (record, bitArr, currentPos) => {
580
+ const octet1 = bitArr[currentPos++];
581
+ const octet2 = bitArr[currentPos++];
582
+ const octet3 = bitArr[currentPos++];
583
+ const tapOctet = octet1 << (8 * 2) | octet2 << (8) | octet3;
584
+ record["021_071_Time of Applicability of Position"] = tapOctet / 128;
585
+ };
586
+ /**
587
+ * Data Item I021/072, Time of Applicability for Velocity
588
+ * 보고된 속도 정보의 유효 시간 (측정 시점), (지난 자정 이후 경과된 시간 형태, 협정 세계시(UTC)로 표시)
589
+ * 고정 길이, 3 octet
590
+ * LSB(스케일링 계수): 1/128 s
591
+ * @param record 단일 Record 파싱 결과
592
+ * @param bitArr Asterix 바이트 데이터
593
+ * @param currentPos 데이터 아이템 시작 인덱스
594
+ */
595
+ const di072 = (record, bitArr, currentPos) => {
596
+ const octet1 = bitArr[currentPos++];
597
+ const octet2 = bitArr[currentPos++];
598
+ const octet3 = bitArr[currentPos++];
599
+ const tavOctet = octet1 << (8 * 2) | octet2 << (8) | octet3;
600
+ record["021_072_Time of Applicability of Velocity"] = tavOctet / 128;
601
+ };
602
+ /**
603
+ * Data Item I021/073, Time of Message Reception for Position
604
+ * 지상국에서 최종 위치 스퀴터(Squitter)를 수신한 시간 (지난 자정 이후 경과된 시간 형태, 협정 세계시(UTC)로 표시
605
+ * 고정 길이, 3 octet
606
+ * LSB(스케일링 계수): 1/128 s
607
+ * @param record 단일 Record 파싱 결과
608
+ * @param bitArr Asterix 바이트 데이터
609
+ * @param currentPos 데이터 아이템 시작 인덱스
610
+ */
611
+ const di073 = (record, bitArr, currentPos) => {
612
+ const octet1 = bitArr[currentPos++];
613
+ const octet2 = bitArr[currentPos++];
614
+ const octet3 = bitArr[currentPos++];
615
+ const tmrpOctet = octet1 << (8 * 2) | octet2 << (8) | octet3;
616
+ record["021_073_Time of Message Reception of Position"] = tmrpOctet / 128;
617
+ };
618
+ /**
619
+ * Data Item I021/074, Time of Message Reception of Position–High Precision
620
+ * 지상국이 최종 ADS-B 위치 정보를 수신한 시각 (UTC 시각의 초 단위 이하(분수)로 표현)
621
+ * 고정 길이, 4 octet
622
+ * LSB(스케일링 계수): 2^-30s
623
+ * @param record 단일 Record 파싱 결과
624
+ * @param bitArr Asterix 바이트 데이터
625
+ * @param currentPos 데이터 아이템 시작 인덱스
626
+ */
627
+ const di074 = (record, bitArr, currentPos) => {
628
+ const octet1 = bitArr[currentPos++];
629
+ const fsiOctet = (0, common_1.octetOfRange)(octet1, 7, 6, 1);
630
+ switch (fsiOctet) {
631
+ case 0:
632
+ record["021_074_FSI"] = "TOMRp whole seconds = (I021/073) Whole seconds (0)";
633
+ break;
634
+ case 1:
635
+ record["021_074_FSI"] = "TOMRp whole seconds = (I021/073) Whole seconds + 1 (1)";
636
+ break;
637
+ case 2:
638
+ record["021_074_FSI"] = "TOMRp whole seconds = (I021/073) Whole seconds - 1 (2)";
639
+ break;
640
+ case 3:
641
+ record["021_074_FSI"] = "Reserved (3)";
642
+ break;
643
+ default:
644
+ record["021_074_FSI"] = "UNDEFINED";
645
+ break;
646
+ }
647
+ const tmrpFrontOctet = (0, common_1.octetOfRange)(octet1, 5, 0, 5);
648
+ const octet2 = bitArr[currentPos++];
649
+ const octet3 = bitArr[currentPos++];
650
+ const octet4 = bitArr[currentPos++];
651
+ const tmrpOctet = (tmrpFrontOctet << (8 * 3)) | (octet2 << (8 * 2)) | (octet3 << (8)) | octet4;
652
+ const tmrp = tmrpOctet / (1 << 30);
653
+ record["021_074_Time of Message Reception of Position - high precision"] = tmrp;
654
+ };
655
+ /**
656
+ * Data Item I021/075, Time of Message Reception for Velocity
657
+ * 지상국에서 최종 속도 스퀴터(Squitter)를 수신한 시간 (지난 자정 이후 경과된 시간 형태, 협정 세계시(UTC)로 표시)
658
+ * 고정 길이, 3 octet
659
+ * LSB(스케일링 계수): 1/128 s
660
+ * @param record 단일 Record 파싱 결과
661
+ * @param bitArr Asterix 바이트 데이터
662
+ * @param currentPos 데이터 아이템 시작 인덱스
663
+ */
664
+ const di075 = (record, bitArr, currentPos) => {
665
+ const octet1 = bitArr[currentPos++];
666
+ const octet2 = bitArr[currentPos++];
667
+ const octet3 = bitArr[currentPos++];
668
+ const ttiOctet = octet1 << (8 * 2) | octet2 << (8) | octet3;
669
+ record["021_075_Time of Message Reception of Velocity"] = ttiOctet / 128;
670
+ };
671
+ /**
672
+ * Data Item I021/076, Time of Message Reception of Velocity–High Precision
673
+ * 지상국이 최종 ADS-B 속도 정보를 수신한 시각 (UTC 시각의 초 단위 이하(분수)로 표현
674
+ * 고정 길이, 4 octet
675
+ * LSB(스케일링 계수): 2^-30s
676
+ * @param record 단일 Record 파싱 결과
677
+ * @param bitArr Asterix 바이트 데이터
678
+ * @param currentPos 데이터 아이템 시작 인덱스
679
+ */
680
+ const di076 = (record, bitArr, currentPos) => {
681
+ const octet1 = bitArr[currentPos++];
682
+ const fsiOctet = (0, common_1.octetOfRange)(octet1, 7, 6, 1);
683
+ switch (fsiOctet) {
684
+ case 3:
685
+ record["021_076_FSI"] = "Reserved (3)";
686
+ break;
687
+ case 2:
688
+ record["021_076_FSI"] = "TOMRv whole seconds = (I021/075) Whole seconds - 1 (2)";
689
+ break;
690
+ case 1:
691
+ record["021_076_FSI"] = "TOMRv whole seconds = (I021/075) Whole seconds + 1 (1)";
692
+ break;
693
+ case 0:
694
+ record["021_076_FSI"] = "TOMRv whole seconds = (I021/075) Whole seconds (0)";
695
+ break;
696
+ default:
697
+ record["021_076_FSI"] = "UNDEFINED";
698
+ break;
699
+ }
700
+ const tmrvFrontOctet = (0, common_1.octetOfRange)(octet1, 5, 0, 5);
701
+ const octet2 = bitArr[currentPos++];
702
+ const octet3 = bitArr[currentPos++];
703
+ const octet4 = bitArr[currentPos++];
704
+ const tmrvOctet = (tmrvFrontOctet << (8 * 3)) | (octet2 << (8 * 2)) | (octet3 << (8)) | octet4;
705
+ const tmrv = tmrvOctet / (1 << 30);
706
+ record["021_076_Time of Message Reception of Velocity - high precision"] = tmrv;
707
+ };
708
+ /**
709
+ * Data Item I021/077, Time of ASTERIX Report Transmission
710
+ * ASTERIX 카테고리 021 보고서 송신 시각 (지난 자정 이후 경과된 시간 형태, 협정 세계시(UTC)로 표시)
711
+ * 고정 길이, 3 octet
712
+ * LSB(스케일링 계수): 1/128 s
713
+ * @param record 단일 Record 파싱 결과
714
+ * @param bitArr Asterix 바이트 데이터
715
+ * @param currentPos 데이터 아이템 시작 인덱스
716
+ */
717
+ const di077 = (record, bitArr, currentPos) => {
718
+ const octet1 = bitArr[currentPos++];
719
+ const octet2 = bitArr[currentPos++];
720
+ const octet3 = bitArr[currentPos++];
721
+ const ttiOctet = octet1 << (8 * 2) | octet2 << (8) | octet3;
722
+ record["021_077_Time of ASTERIX Report Transmission"] = ttiOctet / 128;
723
+ };
724
+ /**
725
+ * Data Item I021/080, Target Address
726
+ * 타겟의 주소
727
+ * 고정 길이, 3 octet
728
+ * @param record 단일 Record 파싱 결과
729
+ * @param bitArr Asterix 바이트 데이터
730
+ * @param currentPos 데이터 아이템 시작 인덱스
731
+ */
732
+ const di080 = (record, bitArr, currentPos) => {
733
+ const octet1 = bitArr[currentPos++];
734
+ const octet2 = bitArr[currentPos++];
735
+ const octet3 = bitArr[currentPos++];
736
+ const taOctet = octet1 << (8 * 2) | octet2 << (8) | octet3;
737
+ record["021_080_Target Address"] = taOctet.toString(16).toUpperCase().padStart(6, '0');
738
+ };
739
+ /**
740
+ * Data Item I021/090, Quality Indicators
741
+ * MOPS 버전에 따라 항공기(a/c)가 송신하는 ADS-B 품질 지표
742
+ * 가변 길이
743
+ * @param record 단일 Record 파싱 결과
744
+ * @param bitArr Asterix 바이트 데이터
745
+ * @param currentPos 데이터 아이템 시작 인덱스
746
+ */
747
+ const di090 = (record, bitArr, currentPos) => {
748
+ const octet1 = bitArr[currentPos++];
749
+ const nuacOctet = (0, common_1.octetOfRange)(octet1, 7, 5, 2);
750
+ record["021_090_NUCrorNACv"] = nuacOctet;
751
+ const nuicOctet = (0, common_1.octetOfRange)(octet1, 4, 1, 3);
752
+ record["021_090_NUCporNIC"] = nuicOctet;
753
+ // 마지막 비트가 0이면 종료
754
+ if ((octet1 & 1) == 0)
755
+ return;
756
+ const octet2 = bitArr[currentPos++];
757
+ const nicOctet = (octet2 & (1 << 7)) !== 0 ? 1 : 0;
758
+ record["021_090_NICbaro"] = nicOctet;
759
+ const silOctet = (0, common_1.octetOfRange)(octet2, 6, 5, 1);
760
+ record["021_090_SIL"] = silOctet;
761
+ const nacpOctet = (0, common_1.octetOfRange)(octet2, 4, 1, 3);
762
+ record["021_090_NACp"] = nacpOctet;
763
+ // 마지막 비트가 0이면 종료
764
+ if ((octet2 & 1) == 0)
765
+ return;
766
+ const octet3 = bitArr[currentPos++];
767
+ const silsOctet = (octet3 & (1 << 5)) !== 0 ? 1 : 0;
768
+ record["021_090_SILS"] = silsOctet;
769
+ const sdaOctet = (0, common_1.octetOfRange)(octet3, 4, 3, 1);
770
+ record["021_090_SDA"] = sdaOctet;
771
+ const gvaOctet = (0, common_1.octetOfRange)(octet3, 2, 1, 1);
772
+ record["021_090_GVA"] = gvaOctet;
773
+ if ((octet3 & 1) == 0)
774
+ return;
775
+ const octet4 = bitArr[currentPos++];
776
+ const picOctet = (0, common_1.octetOfRange)(octet4, 7, 4, 3);
777
+ record["021_090_PIC"] = picOctet;
778
+ };
779
+ /**
780
+ * Data Item I021/110, Trajectory Intent
781
+ * 항공기의 4D 예상(계획) 경로를 나타내는 보고서
782
+ * 가변 길이
783
+ * TID - 2의 보수 처리 필요
784
+ * @param record 단일 Record 파싱 결과
785
+ * @param bitArr Asterix 바이트 데이터
786
+ * @param currentPos 데이터 아이템 시작 인덱스
787
+ */
788
+ const di110 = (record, bitArr, currentPos) => {
789
+ const octet1 = bitArr[currentPos++];
790
+ if ((octet1 & (1 << 7)) !== 0) {
791
+ // TIS O
792
+ di110TIS(record, bitArr, currentPos);
793
+ currentPos++;
794
+ }
795
+ if ((octet1 & (1 << 6)) !== 0) {
796
+ // TID O
797
+ di110TID(record, bitArr, currentPos);
798
+ currentPos++;
799
+ }
800
+ };
801
+ /**
802
+ * Data Item I021/110, Subfield 1
803
+ * Trajectory Intent Status
804
+ * @param record 단일 Record 파싱 결과
805
+ * @param bitArr Asterix 바이트 데이터
806
+ * @param currentPos 데이터 아이템 시작 인덱스
807
+ */
808
+ const di110TIS = (record, bitArr, currentPos) => {
809
+ const octet1 = bitArr[currentPos++];
810
+ // NAV
811
+ if ((octet1 & (1 << 7)) === 0) {
812
+ record["021_110_NAV"] = "Trajectory Intent Data is available for this aircraft (0)";
813
+ }
814
+ else {
815
+ record["021_110_NAV"] = "Trajectory Intent Data is not available for this aircraft (1)";
816
+ }
817
+ // NVB
818
+ if ((octet1 & (1 << 6)) === 0) {
819
+ record["021_110_NVB"] = "Trajectory Intent Data is valid (0)";
820
+ }
821
+ else {
822
+ record["021_110_NVB"] = "Trajectory Intent Data is not valid (1)";
823
+ }
824
+ };
825
+ /**
826
+ * Data Item I021/110, Subfield 2
827
+ * Trajectory Intent Data
828
+ * @param record 단일 Record 파싱 결과
829
+ * @param bitArr Asterix 바이트 데이터
830
+ * @param currentPos 데이터 아이템 시작 인덱스
831
+ */
832
+ const di110TID = (record, bitArr, currentPos) => {
833
+ const octet1 = bitArr[currentPos++];
834
+ for (let index = 0; index < octet1; index++) {
835
+ const octet2 = bitArr[currentPos++];
836
+ if ((octet2 & (1 << 7)) === 0) {
837
+ record["021_110_NVB_" + (index + 1)] = "Trajectory Intent Data is valid (0)";
838
+ }
839
+ else {
840
+ record["021_110_NVB_" + (index + 1)] = "Trajectory Intent Data is not valid (1)";
841
+ }
842
+ if ((octet2 & (1 << 6)) === 0) {
843
+ record["021_110_NC_" + (index + 1)] = "TCP compliance (0)";
844
+ }
845
+ else {
846
+ record["021_110_NC_" + (index + 1)] = "TCP non-compliance (1)";
847
+ }
848
+ record["021_110_TCP number_" + (index + 1)] = (0, common_1.octetOfRange)(octet2, 5, 0, 5);
849
+ const octet3 = bitArr[currentPos++];
850
+ const octet4 = bitArr[currentPos++];
851
+ const altOctet = octet3 << (8) | octet4;
852
+ const alt = (0, common_1.twosCompliment)(altOctet, 16) * 10;
853
+ record["021_110_Altitude_" + (index + 1)] = alt;
854
+ const octet5 = bitArr[currentPos++];
855
+ const octet6 = bitArr[currentPos++];
856
+ const octet7 = bitArr[currentPos++];
857
+ const latOctet = octet5 << (8 * 2) | octet6 << (8) | octet7;
858
+ const octet8 = bitArr[currentPos++];
859
+ const octet9 = bitArr[currentPos++];
860
+ const octet10 = bitArr[currentPos++];
861
+ const lonOctet = octet8 << (8 * 2) | octet9 << (8) | octet10;
862
+ const lat = (0, common_1.twosCompliment)(latOctet, 24) * 180.0 / (1 << 23);
863
+ const lon = (0, common_1.twosCompliment)(lonOctet, 24) * 180.0 / (1 << 23);
864
+ record["021_110_Latitude In WGS-84_" + (index + 1)] = lat;
865
+ record["021_110_Longitude In WGS-84_" + (index + 1)] = lon;
866
+ const octet11 = bitArr[currentPos++];
867
+ const ptOctet = (0, common_1.octetOfRange)(octet11, 7, 4, 3);
868
+ switch (ptOctet) {
869
+ case 0:
870
+ record["021_110_Point Type_" + (index + 1)] = "Unknown (0)";
871
+ break;
872
+ case 1:
873
+ record["021_110_Point Type_" + (index + 1)] = "Fly by waypoint (LT) (1)";
874
+ break;
875
+ case 2:
876
+ record["021_110_Point Type_" + (index + 1)] = "Fly over waypoint (LT) (2)";
877
+ break;
878
+ case 3:
879
+ record["021_110_Point Type_" + (index + 1)] = "Hold pattern (LT) (3)";
880
+ break;
881
+ case 4:
882
+ record["021_110_Point Type_" + (index + 1)] = "Procedure hold (LT) (4)";
883
+ break;
884
+ case 5:
885
+ record["021_110_Point Type_" + (index + 1)] = "Procedure turn (LT) (5)";
886
+ break;
887
+ case 6:
888
+ record["021_110_Point Type_" + (index + 1)] = "RF leg (LT) (6)";
889
+ break;
890
+ case 7:
891
+ record["021_110_Point Type_" + (index + 1)] = "Top of climb (VT) (7)";
892
+ break;
893
+ case 8:
894
+ record["021_110_Point Type_" + (index + 1)] = "Top of descent (VT) (8)";
895
+ break;
896
+ case 9:
897
+ record["021_110_Point Type_" + (index + 1)] = "Start of level (VT) (9)";
898
+ break;
899
+ case 10:
900
+ record["021_110_Point Type_" + (index + 1)] = "Cross-over altitude (VT) (10)";
901
+ break;
902
+ case 11:
903
+ record["021_110_Point Type_" + (index + 1)] = "Transition altitude (VT) (11)";
904
+ break;
905
+ default:
906
+ record["021_110_Point Type_" + (index + 1)] = "UNDEFINED";
907
+ break;
908
+ }
909
+ const tdOctet = (0, common_1.octetOfRange)(octet11, 3, 2, 1);
910
+ switch (tdOctet) {
911
+ case 0:
912
+ record["021_110_TD_" + (index + 1)] = "N/A (0)";
913
+ break;
914
+ case 1:
915
+ record["021_110_TD_" + (index + 1)] = "Turn right (1)";
916
+ break;
917
+ case 2:
918
+ record["021_110_TD_" + (index + 1)] = "Turn left (2)";
919
+ break;
920
+ case 3:
921
+ record["021_110_TD_" + (index + 1)] = "No turn (3)";
922
+ break;
923
+ default:
924
+ record["021_110_TD_" + (index + 1)] = "UNDEFINED";
925
+ break;
926
+ }
927
+ if ((octet11 & (1 << 1)) === 0) {
928
+ record["021_110_TRA_" + (index + 1)] = "TTR not available (0)";
929
+ }
930
+ else {
931
+ record["021_110_TRA_" + (index + 1)] = "TTR available (1)";
932
+ }
933
+ if ((octet11 & (1)) === 0) {
934
+ record["021_110_TOA_" + (index + 1)] = "TOV available (0)";
935
+ }
936
+ else {
937
+ record["021_110_TOA_" + (index + 1)] = "TOV not available (1)";
938
+ }
939
+ const octet12 = bitArr[currentPos++];
940
+ const octet13 = bitArr[currentPos++];
941
+ const octet14 = bitArr[currentPos++];
942
+ const tovOctet = octet12 << (8 * 2) | octet13 << (8) | octet14;
943
+ record["021_110_TOV_" + (index + 1)] = tovOctet;
944
+ const octet15 = bitArr[currentPos++];
945
+ const octet16 = bitArr[currentPos++];
946
+ const ttrOctet = octet15 << (8) | octet16;
947
+ record["021_110_TTR_" + (index + 1)] = ttrOctet * 0.01;
948
+ }
949
+ };
950
+ /**
951
+ * Data Item I021/130, Position in WGS-84 Co-ordinates
952
+ * WGS-84 좌표계 기준 위치
953
+ * 고정 길이, 6 octet
954
+ * 2의 보수 처리 필요
955
+ * @param record 단일 Record 파싱 결과
956
+ * @param bitArr Asterix 바이트 데이터
957
+ * @param currentPos 데이터 아이템 시작 인덱스
958
+ */
959
+ const di130 = (record, bitArr, currentPos) => {
960
+ const octet1 = bitArr[currentPos++];
961
+ const octet2 = bitArr[currentPos++];
962
+ const octet3 = bitArr[currentPos++];
963
+ const latOctet = octet1 << (8 * 2) | octet2 << (8) | octet3;
964
+ const octet4 = bitArr[currentPos++];
965
+ const octet5 = bitArr[currentPos++];
966
+ const octet6 = bitArr[currentPos++];
967
+ const lonOctet = octet4 << (8 * 2) | octet5 << (8) | octet6;
968
+ const lat = (0, common_1.twosCompliment)(latOctet, 24) * 180.0 / (1 << 23);
969
+ const lon = (0, common_1.twosCompliment)(lonOctet, 24) * 180.0 / (1 << 23);
970
+ record["021_130_Latitude In WGS-84"] = lat;
971
+ record["021_130_Longitude In WGS-84"] = lon;
972
+ };
973
+ /**
974
+ * Data Item I021/131, High-Resolution Position in WGS-84 Co-ordinates
975
+ * WGS-84 좌표계 기준 위치
976
+ * 고정 길이, 8 octet
977
+ * 2의 보수 처리 필요
978
+ * @param record 단일 Record 파싱 결과
979
+ * @param bitArr Asterix 바이트 데이터
980
+ * @param currentPos 데이터 아이템 시작 인덱스
981
+ */
982
+ const di131 = (record, bitArr, currentPos) => {
983
+ const octet1 = bitArr[currentPos++];
984
+ const octet2 = bitArr[currentPos++];
985
+ const octet3 = bitArr[currentPos++];
986
+ const octet4 = bitArr[currentPos++];
987
+ const latOctet = octet1 << (8 * 3) | octet2 << (8 * 2) | octet3 << (8) | octet4;
988
+ const octet5 = bitArr[currentPos++];
989
+ const octet6 = bitArr[currentPos++];
990
+ const octet7 = bitArr[currentPos++];
991
+ const octet8 = bitArr[currentPos++];
992
+ const lonOctet = octet5 << (8 * 3) | octet6 << (8 * 2) | octet7 << (8) | octet8;
993
+ const lat = (0, common_1.twosCompliment)(latOctet, 32) * 180.0 / (1 << 30);
994
+ const lon = (0, common_1.twosCompliment)(lonOctet, 32) * 180.0 / (1 << 30);
995
+ record["021_131_Latitude In WGS-84"] = lat;
996
+ record["021_131_Longitude In WGS-84"] = lon;
997
+ };
998
+ /**
999
+ * Data Item I021/132, Message Amplitude
1000
+ * 지상국에서 수신한 ADS-B 메시지의 진폭(dBm 단위)으로, 2의 보수 방식으로 인코딩됨
1001
+ * 고정 길이, 1 octet
1002
+ * LSB(스케일링 계수): 1 dBm
1003
+ * 2의 보수 처리 필요
1004
+ * @param record 단일 Record 파싱 결과
1005
+ * @param bitArr Asterix 바이트 데이터
1006
+ * @param currentPos 데이터 아이템 시작 인덱스
1007
+ */
1008
+ const di132 = (record, bitArr, currentPos) => {
1009
+ const octet1 = bitArr[currentPos++];
1010
+ const mam = (0, common_1.twosCompliment)(octet1, 8);
1011
+ record["021_132_MAM"] = mam;
1012
+ };
1013
+ /**
1014
+ * Data Item I021/140, Geometric Height
1015
+ * WGS-84로 정의된 지구 타원체의 접평면으로부터의 최소 높이이며, 2의 보수 형식으로 표현됨
1016
+ * 고정 길이, 2 octet
1017
+ * LSB(스케일링 계수): 6.25 ft
1018
+ * 2의 보수 처리 필요
1019
+ * @param record 단일 Record 파싱 결과
1020
+ * @param bitArr Asterix 바이트 데이터
1021
+ * @param currentPos 데이터 아이템 시작 인덱스
1022
+ */
1023
+ const di140 = (record, bitArr, currentPos) => {
1024
+ const octet1 = bitArr[currentPos++];
1025
+ const octet2 = bitArr[currentPos++];
1026
+ const geoAltOctet = octet1 << (8) | octet2;
1027
+ const geoAlt = (0, common_1.twosCompliment)(geoAltOctet, 16) * 6.25;
1028
+ record["021_140_Geometric Height (GH)"] = geoAlt;
1029
+ };
1030
+ /**
1031
+ * Data Item I021/145, Flight Level
1032
+ * QNH 보정을 거치지 않은 기압 측정치 기반의 비행 고도(Flight Level)이며, 2의 보수 형식으로 표현됨
1033
+ * 고정 길이, 2 octet
1034
+ * LSB(스케일링 계수): 1 / 4 FL
1035
+ * 2의 보수 처리 필요
1036
+ * @param record 단일 Record 파싱 결과
1037
+ * @param bitArr Asterix 바이트 데이터
1038
+ * @param currentPos 데이터 아이템 시작 인덱스
1039
+ */
1040
+ const di145 = (record, bitArr, currentPos) => {
1041
+ const octet1 = bitArr[currentPos++];
1042
+ const octet2 = bitArr[currentPos++];
1043
+ const flOctet = octet1 << (8) | octet2;
1044
+ const fl = (0, common_1.twosCompliment)(flOctet, 16) * 0.25;
1045
+ record["021_145_Fligth Level"] = fl;
1046
+ };
1047
+ /**
1048
+ * Data Item I021/146, Selected Altitude
1049
+ * 항공 전자 장치(Avionics)에서 제공되는 선택 고도(Selected Altitude)로,
1050
+ * 조종사가 MCP/FCU에 입력한 관제 지시 고도(ATC Cleared Altitude) 또는 FMS(비행 관리 시스템) 선택 고도 중 하나에 해당함
1051
+ * 고정 길이, 2 octet
1052
+ * LSB(스케일링 계수): 25ft
1053
+ * 2의 보수 처리 필요
1054
+ * @param record 단일 Record 파싱 결과
1055
+ * @param bitArr Asterix 바이트 데이터
1056
+ * @param currentPos 데이터 아이템 시작 인덱스
1057
+ */
1058
+ const di146 = (record, bitArr, currentPos) => {
1059
+ const octet1 = bitArr[currentPos++];
1060
+ if ((octet1 & (1 << 7)) === 0) {
1061
+ record["021_146_SAS"] = "No source information provided (0)";
1062
+ }
1063
+ else {
1064
+ record["021_146_SAS"] = "Source Information provided (1)";
1065
+ }
1066
+ const sourceOctet = (0, common_1.octetOfRange)(octet1, 6, 5, 1);
1067
+ switch (sourceOctet) {
1068
+ case 0:
1069
+ record["021_146_Source"] = "Unknown (0)";
1070
+ break;
1071
+ case 1:
1072
+ record["021_146_Source"] = "Aircraft Altitude (Holding Altitude) (1)";
1073
+ break;
1074
+ case 2:
1075
+ record["021_146_Source"] = "MCP/FCU Selected Altitude (2)";
1076
+ break;
1077
+ case 3:
1078
+ record["021_146_Source"] = "FMS Selected Altitude (3)";
1079
+ break;
1080
+ default:
1081
+ record["021_146_Source"] = "UNDEFINED";
1082
+ break;
1083
+ }
1084
+ const altFrontOctet = (0, common_1.octetOfRange)(octet1, 4, 0, 4);
1085
+ const octet2 = bitArr[currentPos++];
1086
+ const altOctet = altFrontOctet << (8) | octet2;
1087
+ const alt = (0, common_1.twosCompliment)(altOctet, 13) * 25;
1088
+ record["021_146_Altitude"] = alt;
1089
+ };
1090
+ /**
1091
+ * Data Item I021/148, Final State Selected Altitude
1092
+ * 고도 제어 패널(MCP/FCU)로부터 추출된, 항공 교통 관제(ATC) 승인 고도와 일치하는 수직 의도(Vertical Intent) 값
1093
+ * 고정 길이, 2 octet
1094
+ * LSB(스케일링 계수): 25ft
1095
+ * 2의 보수 처리 필요
1096
+ * @param record 단일 Record 파싱 결과
1097
+ * @param bitArr Asterix 바이트 데이터
1098
+ * @param currentPos 데이터 아이템 시작 인덱스
1099
+ */
1100
+ const di148 = (record, bitArr, currentPos) => {
1101
+ const octet1 = bitArr[currentPos++];
1102
+ if ((octet1 & (1 << 7)) === 0) {
1103
+ record["021_148_MV"] = "Not active or unknown (0)";
1104
+ }
1105
+ else {
1106
+ record["021_148_MV"] = "Active (1)";
1107
+ }
1108
+ if ((octet1 & (1 << 6)) === 0) {
1109
+ record["021_148_AH"] = "Not active or unknown (0)";
1110
+ }
1111
+ else {
1112
+ record["021_148_AH"] = "Active (1)";
1113
+ }
1114
+ if ((octet1 & (1 << 5)) === 0) {
1115
+ record["021_148_AM"] = "Not active or unknown (0)";
1116
+ }
1117
+ else {
1118
+ record["021_148_AM"] = "Active (1)";
1119
+ }
1120
+ const altFrontOctet = (0, common_1.octetOfRange)(octet1, 4, 0, 4);
1121
+ const octet2 = bitArr[currentPos++];
1122
+ const altOctet = altFrontOctet << (8) | octet2;
1123
+ const alt = (0, common_1.twosCompliment)(altOctet, 13) * 25;
1124
+ record["021_148_Altitude"] = alt;
1125
+ };
1126
+ /**
1127
+ * Data Item I021/150, Air Speed
1128
+ * 산출 대기 속도 (공기 벡터의 구성 요소)
1129
+ * 고정 길이, 2 octet
1130
+ * LSB(스케일링 계수): 2^-14 NM/s / 0.001
1131
+ * @param record 단일 Record 파싱 결과
1132
+ * @param bitArr Asterix 바이트 데이터
1133
+ * @param currentPos 데이터 아이템 시작 인덱스
1134
+ */
1135
+ const di150 = (record, bitArr, currentPos) => {
1136
+ const octet1 = bitArr[currentPos++];
1137
+ const asFrontOctet = (0, common_1.octetOfRange)(octet1, 6, 0, 6);
1138
+ const octet2 = bitArr[currentPos++];
1139
+ const asOctet = asFrontOctet << (8) | octet2;
1140
+ if ((octet1 & (1 << 7)) === 0) {
1141
+ record["021_150_IM"] = "Air Speed = IAS (1)";
1142
+ record["021_150_Air Speed"] = asOctet / (1 << 14);
1143
+ }
1144
+ else {
1145
+ record["021_150_IM"] = "Air Speed = Mach (0)";
1146
+ record["021_150_Air Speed"] = asOctet * 0.001;
1147
+ }
1148
+ };
1149
+ /**
1150
+ * Data Item I021/151 True Airspeed
1151
+ * 진대기 속도
1152
+ * 고정 길이, 2 octet
1153
+ * LSB(스케일링 계수): 1 knot
1154
+ * @param record 단일 Record 파싱 결과
1155
+ * @param bitArr Asterix 바이트 데이터
1156
+ * @param currentPos 데이터 아이템 시작 인덱스
1157
+ */
1158
+ const di151 = (record, bitArr, currentPos) => {
1159
+ const octet1 = bitArr[currentPos++];
1160
+ if ((octet1 & (1 << 7)) === 0) {
1161
+ record["021_150_IM"] = "Value in defined range (0)";
1162
+ }
1163
+ else {
1164
+ record["021_150_IM"] = "Value exceeds defined range (1)";
1165
+ }
1166
+ const tasFrontOctet = (0, common_1.octetOfRange)(octet1, 6, 0, 6);
1167
+ const octet2 = bitArr[currentPos++];
1168
+ const tasOctet = tasFrontOctet << (8) | octet2;
1169
+ record["021_151_True Air Speed"] = tasOctet;
1170
+ };
1171
+ /**
1172
+ * Data Item I021/152, Magnetic Heading
1173
+ * 항공기의 기수(코 부분)가 가리키는 방향을 자북(지구 자기장의 북쪽)을 기준으로 측정된 각도
1174
+ * 고정 길이, 2 octet
1175
+ * LSB(스케일링 계수): 360 / 2^16
1176
+ * @param record 단일 Record 파싱 결과
1177
+ * @param bitArr Asterix 바이트 데이터
1178
+ * @param currentPos 데이터 아이템 시작 인덱스
1179
+ */
1180
+ const di152 = (record, bitArr, currentPos) => {
1181
+ const octet1 = bitArr[currentPos++];
1182
+ const octet2 = bitArr[currentPos++];
1183
+ const mhOctet = octet1 << (8) | octet2;
1184
+ const mh = (mhOctet * 360.0) / (1 << 16);
1185
+ record["021_152_Magnetic Heading"] = mh;
1186
+ };
1187
+ /**
1188
+ * Data Item I021/155, Barometric Vertical Rate
1189
+ * 기압 수직 속도이며, 2의 보수 형식으로 표현됨
1190
+ * 고정 길이, 2 octet
1191
+ * LSB(스케일링 계수): 6.25 feet/minute
1192
+ * @param record 단일 Record 파싱 결과
1193
+ * @param bitArr Asterix 바이트 데이터
1194
+ * @param currentPos 데이터 아이템 시작 인덱스
1195
+ */
1196
+ const di155 = (record, bitArr, currentPos) => {
1197
+ const octet1 = bitArr[currentPos++];
1198
+ if ((octet1 & (1 << 7)) === 0) {
1199
+ record["021_155_RE"] = "Value in defined range (0)";
1200
+ }
1201
+ else {
1202
+ record["021_155_RE"] = "Value exceeds defined range (1)";
1203
+ }
1204
+ const bvrFrontOctet = (0, common_1.octetOfRange)(octet1, 6, 0, 6);
1205
+ const octet2 = bitArr[currentPos++];
1206
+ const bvrOctet = bvrFrontOctet << (8) | octet2;
1207
+ const bvr = (0, common_1.twosCompliment)(bvrOctet, 15) * 6.25;
1208
+ record["021_155_Barometric Vertical Rate"] = bvr;
1209
+ };
1210
+ /**
1211
+ * Data Item I021/157, Geometric Vertical Rate
1212
+ * WGS-84를 기준으로 한 기하학적 수직 속도이며, 2의 보수 형식으로 표현됨
1213
+ * 고정 길이, 2 octet
1214
+ * LSB(스케일링 계수): 6.25 feet/minute
1215
+ * @param record 단일 Record 파싱 결과
1216
+ * @param bitArr Asterix 바이트 데이터
1217
+ * @param currentPos 데이터 아이템 시작 인덱스
1218
+ */
1219
+ const di157 = (record, bitArr, currentPos) => {
1220
+ const octet1 = bitArr[currentPos++];
1221
+ if ((octet1 & (1 << 7)) === 0) {
1222
+ record["021_157_RE"] = "Value in defined range (0)";
1223
+ }
1224
+ else {
1225
+ record["021_157_RE"] = "Value exceeds defined range (1)";
1226
+ }
1227
+ const bvrFrontOctet = (0, common_1.octetOfRange)(octet1, 6, 0, 6);
1228
+ const octet2 = bitArr[currentPos++];
1229
+ const bvrOctet = bvrFrontOctet << (8) | octet2;
1230
+ const bvr = (0, common_1.twosCompliment)(bvrOctet, 15) * 6.25;
1231
+ record["021_157_Geometric Vertical Rate"] = bvr;
1232
+ };
1233
+ /**
1234
+ * Data Item I021/160, Airborne Ground Vector
1235
+ * 공중 지면 벡터(Airborne Ground Vector)의 구성 요소인 지표 속도(Ground Speed)와 지적(Track Angle)
1236
+ * 고정 길이, 4 octet
1237
+ * LSB(스케일링 계수): 2^-14 NM/s
1238
+ * @param record 단일 Record 파싱 결과
1239
+ * @param bitArr Asterix 바이트 데이터
1240
+ * @param currentPos 데이터 아이템 시작 인덱스
1241
+ */
1242
+ const di160 = (record, bitArr, currentPos) => {
1243
+ const octet1 = bitArr[currentPos++];
1244
+ if ((octet1 & (1 << 7)) === 0) {
1245
+ record["021_160_RE"] = "Value in defined range (0)";
1246
+ }
1247
+ else {
1248
+ record["021_160_RE"] = "Value exceeds defined range (1)";
1249
+ }
1250
+ const gsFrontOctet = (0, common_1.octetOfRange)(octet1, 6, 0, 6);
1251
+ const octet2 = bitArr[currentPos++];
1252
+ const gsOctet = gsFrontOctet << (8) | octet2;
1253
+ const gs = gsOctet / (1 << 14);
1254
+ record["021_160_Ground Speed"] = gs;
1255
+ const octet3 = bitArr[currentPos++];
1256
+ const octet4 = bitArr[currentPos++];
1257
+ const taOctet = octet3 << (8) | octet4;
1258
+ const ta = (taOctet * 360) / (1 << 16);
1259
+ record["021_160_Track Angle"] = ta;
1260
+ };
1261
+ /**
1262
+ * Data Item I021/161, Track Number
1263
+ * 특정 트랙 파일 내에서 개별 트랙 기록을 구분하는 고유한 참조용 정수 값
1264
+ * 고정 길이, 2 octet
1265
+ * @param record 단일 Record 파싱 결과
1266
+ * @param bitArr Asterix 바이트 데이터
1267
+ * @param currentPos 데이터 아이템 시작 인덱스
1268
+ */
1269
+ const di161 = (record, bitArr, currentPos) => {
1270
+ const octet1 = bitArr[currentPos++];
1271
+ const tnFrontOctet = (0, common_1.octetOfRange)(octet1, 3, 0, 3);
1272
+ const octet2 = bitArr[currentPos++];
1273
+ const tnOctet = tnFrontOctet << (8) | octet2;
1274
+ record["021_161_TRACK NUMBER"] = tnOctet;
1275
+ };
1276
+ /**
1277
+ * Data Item I021/165, Track Angle Rate
1278
+ * 2의 보수 형식으로 표현된 선회율(회전 속도)
1279
+ * 고정 길이, 4 octet
1280
+ * LSB(스케일링 계수): 1/32 °/s
1281
+ * 2의 보수 필요
1282
+ * @param record 단일 Record 파싱 결과
1283
+ * @param bitArr Asterix 바이트 데이터
1284
+ * @param currentPos 데이터 아이템 시작 인덱스
1285
+ */
1286
+ const di165 = (record, bitArr, currentPos) => {
1287
+ const octet1 = bitArr[currentPos++];
1288
+ const tarFrontOctet = (0, common_1.octetOfRange)(octet1, 1, 0, 1);
1289
+ const octet2 = bitArr[currentPos++];
1290
+ const tarOctet = tarFrontOctet << (8) | octet2;
1291
+ const tar = tarOctet / 32;
1292
+ record["021_165_TAR"] = tar;
1293
+ };
1294
+ /**
1295
+ * Data Item I021/170, Target Identification
1296
+ * 타겟(항공기 또는 차량)이 보고한 8자 이내의 고유 식별 정
1297
+ * 고정 길이, 6 octet
1298
+ * @param record 단일 Record 파싱 결과
1299
+ * @param bitArr Asterix 바이트 데이터
1300
+ * @param currentPos 데이터 아이템 시작 인덱스
1301
+ */
1302
+ const di170 = (record, bitArr, currentPos) => {
1303
+ const octet1 = bitArr[currentPos++];
1304
+ const octet2 = bitArr[currentPos++];
1305
+ const octet3 = bitArr[currentPos++];
1306
+ const char123Octet = (octet1 << (8 * 2)) | (octet2 << 8) | octet3;
1307
+ const char1Octet = (0, common_1.octetOfRange)(char123Octet, 23, 18, 5);
1308
+ const char2Octet = (0, common_1.octetOfRange)(char123Octet, 17, 12, 5);
1309
+ const char3Octet = (0, common_1.octetOfRange)(char123Octet, 11, 6, 5);
1310
+ const char4Octet = (0, common_1.octetOfRange)(char123Octet, 5, 0, 5);
1311
+ const octet4 = bitArr[currentPos++];
1312
+ const octet5 = bitArr[currentPos++];
1313
+ const octet6 = bitArr[currentPos++];
1314
+ const char456Octet = (octet4 << (8 * 2)) | (octet5 << 8) | octet6;
1315
+ const char5Octet = (0, common_1.octetOfRange)(char456Octet, 23, 18, 5);
1316
+ const char6Octet = (0, common_1.octetOfRange)(char456Octet, 17, 12, 5);
1317
+ const char7Octet = (0, common_1.octetOfRange)(char456Octet, 11, 6, 5);
1318
+ const char8Octet = (0, common_1.octetOfRange)(char456Octet, 5, 0, 5);
1319
+ const convertedChars = [
1320
+ char1Octet, char2Octet, char3Octet, char4Octet,
1321
+ char5Octet, char6Octet, char7Octet, char8Octet
1322
+ ].map(code => (0, common_1.getChar)(code)) // 숫자를 문자로 변환
1323
+ .filter(char => char !== "") // 빈 문자열("") 제거
1324
+ .join(""); // 하나의 문자열로 합치기
1325
+ record["021_170_Target Identification"] = convertedChars;
1326
+ };
1327
+ /**
1328
+ * Data Item I021/200, Target Status
1329
+ * 타겟(추적 대상)의 상태
1330
+ * 고정 길이, 1 octet
1331
+ * @param record 단일 Record 파싱 결과
1332
+ * @param bitArr Asterix 바이트 데이터
1333
+ * @param currentPos 데이터 아이템 시작 인덱스
1334
+ */
1335
+ const di200 = (record, bitArr, currentPos) => {
1336
+ const octet1 = bitArr[currentPos++];
1337
+ if ((octet1 & (1 << 7)) === 0) {
1338
+ record["021_200_ICF"] = "No intent change active (0)";
1339
+ }
1340
+ else {
1341
+ record["021_200_ICF"] = "Intent change flag raised (1)";
1342
+ }
1343
+ if ((octet1 & (1 << 6)) === 0) {
1344
+ record["021_200_LNAV"] = "LNAV Mode engaged (0)";
1345
+ }
1346
+ else {
1347
+ record["021_200_LNAV"] = "LNAV Mode not engaged (1)";
1348
+ }
1349
+ if ((octet1 & (1 << 5)) === 0) {
1350
+ record["021_200_ME"] = "No military emergency (0)";
1351
+ }
1352
+ else {
1353
+ record["021_200_ME"] = "Military emergency (1)";
1354
+ }
1355
+ const psOctet = (0, common_1.octetOfRange)(octet1, 4, 2, 2);
1356
+ switch (psOctet) {
1357
+ case 0:
1358
+ record["021_200_PS"] = "No emergency / not reported (0)";
1359
+ break;
1360
+ case 1:
1361
+ record["021_200_PS"] = "General emergency (1)";
1362
+ break;
1363
+ case 2:
1364
+ record["021_200_PS"] = "Lifeguard / medical emergency (2)";
1365
+ break;
1366
+ case 3:
1367
+ record["021_200_PS"] = "Minimum fuel (3)";
1368
+ break;
1369
+ case 4:
1370
+ record["021_200_PS"] = "No communications (4)";
1371
+ break;
1372
+ case 5:
1373
+ record["021_200_PS"] = "Unlawful interference (5)";
1374
+ break;
1375
+ case 6:
1376
+ record["021_200_PS"] = "'Downed' Aircraft (6)";
1377
+ break;
1378
+ default:
1379
+ record["021_200_PS"] = "UNDEFINED";
1380
+ break;
1381
+ }
1382
+ const ssOctet = (0, common_1.octetOfRange)(octet1, 1, 0, 1);
1383
+ switch (ssOctet) {
1384
+ case 0:
1385
+ record["021_200_SS"] = "No condition reported (0)";
1386
+ break;
1387
+ case 1:
1388
+ record["021_200_SS"] = "Permanent Alert (Emergency condition) (1)";
1389
+ break;
1390
+ case 2:
1391
+ record["021_200_SS"] = "Temporary Alert (change in Mode 3/A Code other than emergency) (2)";
1392
+ break;
1393
+ case 3:
1394
+ record["021_200_SS"] = "SPI set (3)";
1395
+ break;
1396
+ default:
1397
+ record["021_200_SS"] = "UNDEFINED";
1398
+ break;
1399
+ }
1400
+ };
1401
+ /**
1402
+ * Data Item I021/210, MOPS Version
1403
+ * 항공기(a/c)가 ADS-B 데이터를 송신하기 위해 사용하는 MOPS(최소 운용 성능 표준) 버전 식별
1404
+ * 고정 길이, 1 octet
1405
+ * @param record 단일 Record 파싱 결과
1406
+ * @param bitArr Asterix 바이트 데이터
1407
+ * @param currentPos 데이터 아이템 시작 인덱스
1408
+ */
1409
+ const di210 = (record, bitArr, currentPos) => {
1410
+ const octet1 = bitArr[currentPos++];
1411
+ if ((octet1 & (1 << 6)) === 0) {
1412
+ record["021_210_VNS"] = "The MOPS Version is supported by the GS (0)";
1413
+ }
1414
+ else {
1415
+ record["021_210_VNS"] = "The MOPS Version is not supported by the GS (1)";
1416
+ }
1417
+ const vnOctet = (0, common_1.octetOfRange)(octet1, 5, 3, 2);
1418
+ switch (vnOctet) {
1419
+ case 0:
1420
+ record["021_210_VN"] = "ED102/DO-260 [Ref. 7] (0)";
1421
+ break;
1422
+ case 1:
1423
+ record["021_210_VN"] = "DO-260A [Ref. 8] (1)";
1424
+ break;
1425
+ case 2:
1426
+ record["021_210_VN"] = "ED102A/DO-260B [Ref. 10] (2)";
1427
+ break;
1428
+ case 3:
1429
+ record["021_210_VN"] = "ED-102B/DO-260C [Ref. 11] (3)";
1430
+ break;
1431
+ default:
1432
+ record["021_210_VN"] = "UNDEFINED";
1433
+ break;
1434
+ }
1435
+ const lttOctet = (0, common_1.octetOfRange)(octet1, 2, 0, 2);
1436
+ switch (lttOctet) {
1437
+ case 0:
1438
+ record["021_210_LTT"] = "Other (0)";
1439
+ break;
1440
+ case 1:
1441
+ record["021_210_LTT"] = "UAT (1)";
1442
+ break;
1443
+ case 2:
1444
+ record["021_210_LTT"] = "1090 ES (2)";
1445
+ break;
1446
+ case 3:
1447
+ record["021_210_LTT"] = "VDL 4 (3)";
1448
+ break;
1449
+ case 4:
1450
+ record["021_210_LTT"] = "Not assigned (4)";
1451
+ break;
1452
+ case 5:
1453
+ record["021_210_LTT"] = "Not assigned (5)";
1454
+ break;
1455
+ case 6:
1456
+ record["021_210_LTT"] = "Not assigned (6)";
1457
+ break;
1458
+ case 7:
1459
+ record["021_210_LTT"] = "Not assigned (7)";
1460
+ break;
1461
+ default:
1462
+ record["021_210_LTT"] = "UNDEFINED";
1463
+ break;
1464
+ }
1465
+ };
1466
+ /**
1467
+ * Data Item I021/220, Met Information
1468
+ * 기상 정보
1469
+ * 가변 길이
1470
+ * @param record 단일 Record 파싱 결과
1471
+ * @param bitArr Asterix 바이트 데이터
1472
+ * @param currentPos 데이터 아이템 시작 인덱스
1473
+ */
1474
+ const di220 = (record, bitArr, currentPos) => {
1475
+ const octet1 = bitArr[currentPos++];
1476
+ if ((octet1 & (1 << 7)) != 0) {
1477
+ // WS
1478
+ const octet1 = bitArr[currentPos++];
1479
+ const octet2 = bitArr[currentPos++];
1480
+ const wsOctet = (octet1 << 8) | octet2;
1481
+ record["021_220_Wind Speed"] = wsOctet;
1482
+ }
1483
+ if ((octet1 & (1 << 6)) != 0) {
1484
+ // WD
1485
+ const octet1 = bitArr[currentPos++];
1486
+ const octet2 = bitArr[currentPos++];
1487
+ const wdOctet = (octet1 << 8) | octet2;
1488
+ record["021_220_Wind Direction"] = wdOctet;
1489
+ }
1490
+ if ((octet1 & (1 << 5)) != 0) {
1491
+ // TMP
1492
+ const octet1 = bitArr[currentPos++];
1493
+ const octet2 = bitArr[currentPos++];
1494
+ const wdOctet = (octet1 << 8) | octet2;
1495
+ record["021_220_Temperature"] = wdOctet;
1496
+ }
1497
+ if ((octet1 & (1 << 4)) != 0) {
1498
+ // TRB
1499
+ const octet1 = bitArr[currentPos++];
1500
+ record["021_220_Turbulence"] = octet1;
1501
+ }
1502
+ };
1503
+ /**
1504
+ * Data Item I021/230, Roll Angle
1505
+ * 선회 중인 항공기의 롤 각도(Roll Angle, 경사각)를 2의 보수 형식으로 표현한 것
1506
+ * 고정 길이, 2 octet
1507
+ * LSB(스케일링 계수): 0.01 degree
1508
+ * 2의 보수 필요
1509
+ * @param record 단일 Record 파싱 결과
1510
+ * @param bitArr Asterix 바이트 데이터
1511
+ * @param currentPos 데이터 아이템 시작 인덱스
1512
+ */
1513
+ const di230 = (record, bitArr, currentPos) => {
1514
+ const octet1 = bitArr[currentPos++];
1515
+ const octet2 = bitArr[currentPos++];
1516
+ const raOctet = (octet1 << 8) | octet2;
1517
+ const ra = (0, common_1.twosCompliment)(raOctet, 16) * 0.01;
1518
+ record["021_230_Roll Angle"] = ra;
1519
+ };
1520
+ /**
1521
+ * Data Item I021/250, Mode S MB Data
1522
+ * 항공기 트랜스폰더(송수신기)로부터 추출된 Mode S Comm B 데이터
1523
+ * 가변 길이
1524
+ * @param record 단일 Record 파싱 결과
1525
+ * @param bitArr Asterix 바이트 데이터
1526
+ * @param currentPos 데이터 아이템 시작 인덱스
1527
+ */
1528
+ const di250 = (record, bitArr, currentPos) => {
1529
+ const octet1 = bitArr[currentPos++];
1530
+ for (let index = 0; index < octet1; index++) {
1531
+ const octet2 = bitArr[currentPos++];
1532
+ const octet3 = bitArr[currentPos++];
1533
+ const octet4 = bitArr[currentPos++];
1534
+ const octet5 = bitArr[currentPos++];
1535
+ const octet6 = bitArr[currentPos++];
1536
+ const octet7 = bitArr[currentPos++];
1537
+ const octet8 = bitArr[currentPos++];
1538
+ const mbOctet = (octet2 << (8 * 6)) | (octet3 << (8 * 5)) |
1539
+ (octet4 << (8 * 4)) | (octet5 << (8 * 3)) |
1540
+ (octet6 << (8 * 2)) | (octet7 << 8) | octet8;
1541
+ record["021_230_MB DATA_" + (index + 1)] = mbOctet;
1542
+ const octet9 = bitArr[currentPos++];
1543
+ const bds1Octet = (0, common_1.octetOfRange)(octet9, 7, 4, 3);
1544
+ const bds2Octet = (0, common_1.octetOfRange)(octet9, 3, 0, 3);
1545
+ record["021_230_BDS1_" + (index + 1)] = bds1Octet;
1546
+ record["021_230_BDS2_" + (index + 1)] = bds2Octet;
1547
+ }
1548
+ };
1549
+ /**
1550
+ * Data Item I021/260, ACAS Resolution Advisory Report
1551
+ * RA 메시지 및 위협 식별 데이터를 송신하는 트랜스폰더와 연결된 ACAS가 생성한, 현재 활성화된 회피 지시(RA) 정보(있는 경우)
1552
+ * 고정 길이, 7 octet
1553
+ * @param record 단일 Record 파싱 결과
1554
+ * @param bitArr Asterix 바이트 데이터
1555
+ * @param currentPos 데이터 아이템 시작 인덱스
1556
+ */
1557
+ const di260 = (record, bitArr, currentPos) => {
1558
+ const octet1 = bitArr[currentPos++];
1559
+ const typOctet = (0, common_1.octetOfRange)(octet1, 7, 3, 4);
1560
+ record["021_260_TYP"] = typOctet;
1561
+ const stypOctet = (0, common_1.octetOfRange)(octet1, 2, 0, 2);
1562
+ record["021_260_STYP"] = stypOctet;
1563
+ const octet2 = bitArr[currentPos++];
1564
+ const octet3 = bitArr[currentPos++];
1565
+ const araOctet = (octet2 << 6) | (0, common_1.octetOfRange)(octet3, 7, 2, 5);
1566
+ record["021_260_ARA"] = araOctet;
1567
+ const octet4 = bitArr[currentPos++];
1568
+ const racOctet = (0, common_1.octetOfRange)(octet3, 1, 0, 1) | (0, common_1.octetOfRange)(octet4, 7, 6, 1);
1569
+ record["021_260_RAC"] = racOctet;
1570
+ record["021_260_RAT"] = ((octet4 & (1 << 5)) != 0) ? 1 : 0;
1571
+ record["021_260_MTE"] = ((octet4 & (1 << 4)) != 0) ? 1 : 0;
1572
+ record["021_260_TTI"] = (0, common_1.octetOfRange)(octet4, 3, 2, 1);
1573
+ const tidFrontValue = (0, common_1.octetOfRange)(octet4, 1, 0, 1);
1574
+ const octet5 = bitArr[currentPos++];
1575
+ const octet6 = bitArr[currentPos++];
1576
+ const octet7 = bitArr[currentPos++];
1577
+ record["021_260_TID"] = (tidFrontValue << (8 * 3)) | (octet5 << (8 * 2)) | (octet6 << 8) | (octet7);
1578
+ };
1579
+ /**
1580
+ * Data Item I021/271, Surface Capabilities and Characteristics\
1581
+ * 지상 활주 중(지상에 있는 동안) 항공기의 운용 가능 능력
1582
+ * 가변 길이
1583
+ * @param record 단일 Record 파싱 결과
1584
+ * @param bitArr Asterix 바이트 데이터
1585
+ * @param currentPos 데이터 아이템 시작 인덱스
1586
+ */
1587
+ const di271 = (record, bitArr, currentPos) => {
1588
+ const octet1 = bitArr[currentPos++];
1589
+ if ((octet1 & (1 << 5)) === 0) {
1590
+ record["021_271_POA"] = "Position transmitted is not ADS-B position reference point (0)";
1591
+ }
1592
+ else {
1593
+ record["021_271_POA"] = "Position transmitted is ADS-B position reference point (1)";
1594
+ }
1595
+ if ((octet1 & (1 << 4)) === 0) {
1596
+ record["021_271_CDTI/S"] = "CDTI not operational (0)";
1597
+ }
1598
+ else {
1599
+ record["021_271_CDTI/S"] = "CDTI operational (1)";
1600
+ }
1601
+ if ((octet1 & (1 << 3)) === 0) {
1602
+ record["021_271_B2 low"] = ">= 70 Watts (0)";
1603
+ }
1604
+ else {
1605
+ record["021_271_B2 low"] = "< 70 Watts (1)";
1606
+ }
1607
+ if ((octet1 & (1 << 2)) === 0) {
1608
+ record["021_271_RAS"] = "Aircraft not receiving ATC-services (0)";
1609
+ }
1610
+ else {
1611
+ record["021_271_RAS"] = "Aircraft receiving ATC services (1)";
1612
+ }
1613
+ if ((octet1 & (1 << 1)) === 0) {
1614
+ record["021_271_IDENT"] = "IDENT switch not active (0)";
1615
+ }
1616
+ else {
1617
+ record["021_271_IDENT"] = "IDENT switch active (1)";
1618
+ }
1619
+ if ((octet1 & (1)) === 0)
1620
+ return;
1621
+ const octet2 = bitArr[currentPos++];
1622
+ const lwValue = (0, common_1.octetOfRange)(octet2, 7, 4, 3);
1623
+ record["021_271_LW"] = lwValue;
1624
+ };
1625
+ /**
1626
+ * Data Item I021/295, Data Ages
1627
+ * 제공된 데이터의 생성 경과 시간(데이터의 신선도)
1628
+ * 가변 길이
1629
+ * @param record 단일 Record 파싱 결과
1630
+ * @param bitArr Asterix 바이트 데이터
1631
+ * @param currentPos 데이터 아이템 시작 인덱스
1632
+ */
1633
+ const di295 = (record, bitArr, currentPos) => {
1634
+ const { bits, headerLen } = (0, preprocess_1.parseIndicator)(bitArr, currentPos);
1635
+ currentPos += headerLen;
1636
+ if ((0, common_1.isBitSet)(bits, 1, currentPos)) {
1637
+ // AOS
1638
+ const octet1 = bitArr[currentPos++];
1639
+ record["021_295_AOS"] = octet1 * 0.1;
1640
+ }
1641
+ if ((0, common_1.isBitSet)(bits, 2, currentPos)) {
1642
+ // TRD
1643
+ const octet1 = bitArr[currentPos++];
1644
+ record["021_295_TRD"] = octet1 * 0.1;
1645
+ }
1646
+ if ((0, common_1.isBitSet)(bits, 3, currentPos)) {
1647
+ // M3A
1648
+ const octet1 = bitArr[currentPos++];
1649
+ record["021_295_M3A"] = octet1 * 0.1;
1650
+ }
1651
+ if ((0, common_1.isBitSet)(bits, 4, currentPos)) {
1652
+ // QI
1653
+ const octet1 = bitArr[currentPos++];
1654
+ record["021_295_QI"] = octet1 * 0.1;
1655
+ }
1656
+ if ((0, common_1.isBitSet)(bits, 5, currentPos)) {
1657
+ // TI
1658
+ const octet1 = bitArr[currentPos++];
1659
+ record["021_295_TI"] = octet1 * 0.1;
1660
+ }
1661
+ if ((0, common_1.isBitSet)(bits, 6, currentPos)) {
1662
+ // MAM
1663
+ const octet1 = bitArr[currentPos++];
1664
+ record["021_295_MAM"] = octet1 * 0.1;
1665
+ }
1666
+ if ((0, common_1.isBitSet)(bits, 7, currentPos)) {
1667
+ // GH
1668
+ const octet1 = bitArr[currentPos++];
1669
+ record["021_295_GH"] = octet1 * 0.1;
1670
+ }
1671
+ if ((0, common_1.isBitSet)(bits, 8, currentPos)) {
1672
+ // FL
1673
+ const octet1 = bitArr[currentPos++];
1674
+ record["021_295_FL"] = octet1 * 0.1;
1675
+ }
1676
+ if ((0, common_1.isBitSet)(bits, 9, currentPos)) {
1677
+ // ISA
1678
+ const octet1 = bitArr[currentPos++];
1679
+ record["021_295_ISA"] = octet1 * 0.1;
1680
+ }
1681
+ if ((0, common_1.isBitSet)(bits, 10, currentPos)) {
1682
+ // FSA
1683
+ const octet1 = bitArr[currentPos++];
1684
+ record["021_295_FSA"] = octet1 * 0.1;
1685
+ }
1686
+ if ((0, common_1.isBitSet)(bits, 11, currentPos)) {
1687
+ // AS
1688
+ const octet1 = bitArr[currentPos++];
1689
+ record["021_295_AS"] = octet1 * 0.1;
1690
+ }
1691
+ if ((0, common_1.isBitSet)(bits, 12, currentPos)) {
1692
+ // TAS
1693
+ const octet1 = bitArr[currentPos++];
1694
+ record["021_295_TAS"] = octet1 * 0.1;
1695
+ }
1696
+ if ((0, common_1.isBitSet)(bits, 13, currentPos)) {
1697
+ // MH
1698
+ const octet1 = bitArr[currentPos++];
1699
+ record["021_295_MH"] = octet1 * 0.1;
1700
+ }
1701
+ if ((0, common_1.isBitSet)(bits, 14, currentPos)) {
1702
+ // BVR
1703
+ const octet1 = bitArr[currentPos++];
1704
+ record["021_295_BVR"] = octet1 * 0.1;
1705
+ }
1706
+ if ((0, common_1.isBitSet)(bits, 15, currentPos)) {
1707
+ // GVR
1708
+ const octet1 = bitArr[currentPos++];
1709
+ record["021_295_GVR"] = octet1 * 0.1;
1710
+ }
1711
+ if ((0, common_1.isBitSet)(bits, 16, currentPos)) {
1712
+ // GV
1713
+ const octet1 = bitArr[currentPos++];
1714
+ record["021_295_GV"] = octet1 * 0.1;
1715
+ }
1716
+ if ((0, common_1.isBitSet)(bits, 17, currentPos)) {
1717
+ // TAR
1718
+ const octet1 = bitArr[currentPos++];
1719
+ record["021_295_TAR"] = octet1 * 0.1;
1720
+ }
1721
+ if ((0, common_1.isBitSet)(bits, 18, currentPos)) {
1722
+ // TI
1723
+ const octet1 = bitArr[currentPos++];
1724
+ record["021_295_TI"] = octet1 * 0.1;
1725
+ }
1726
+ if ((0, common_1.isBitSet)(bits, 19, currentPos)) {
1727
+ // TS
1728
+ const octet1 = bitArr[currentPos++];
1729
+ record["021_295_TS"] = octet1 * 0.1;
1730
+ }
1731
+ if ((0, common_1.isBitSet)(bits, 20, currentPos)) {
1732
+ // MET
1733
+ const octet1 = bitArr[currentPos++];
1734
+ record["021_295_MET"] = octet1 * 0.1;
1735
+ }
1736
+ if ((0, common_1.isBitSet)(bits, 21, currentPos)) {
1737
+ // ROA
1738
+ const octet1 = bitArr[currentPos++];
1739
+ record["021_295_ROA"] = octet1 * 0.1;
1740
+ }
1741
+ if ((0, common_1.isBitSet)(bits, 22, currentPos)) {
1742
+ // ARA
1743
+ const octet1 = bitArr[currentPos++];
1744
+ record["021_295_ARA"] = octet1 * 0.1;
1745
+ }
1746
+ if ((0, common_1.isBitSet)(bits, 23, currentPos)) {
1747
+ // SCC
1748
+ const octet1 = bitArr[currentPos++];
1749
+ record["021_295_SCC"] = octet1 * 0.1;
1750
+ }
1751
+ };
1752
+ /**
1753
+ * Data Item I021/400, Receiver ID
1754
+ * 분산 시스템 내 지상국 식별자(명칭)
1755
+ * 고정 길이, 1 octet
1756
+ * @param record 단일 Record 파싱 결과
1757
+ * @param bitArr Asterix 바이트 데이터
1758
+ * @param currentPos 데이터 아이템 시작 인덱스
1759
+ */
1760
+ const di400 = (record, bitArr, currentPos) => {
1761
+ const octet1 = bitArr[currentPos++];
1762
+ record["021_400_RID"] = octet1;
1763
+ };
1764
+ /**
1765
+ * Data Item SP - 문서 상에 파싱 규칙 없음
1766
+ * 가변 길이
1767
+ * @param record 단일 Record 파싱 결과
1768
+ * @param bitArr Asterix 바이트 데이터
1769
+ * @param currentPos 데이터 아이템 시작 인덱스
1770
+ * @param diLength 메모리 재할당 방지
1771
+ */
1772
+ const sp = (record, bitArr, currentPos, diLength) => {
1773
+ record["021_SP"] = (0, preprocess_1.getHexString)(bitArr, currentPos, diLength);
1774
+ };
1775
+ /**
1776
+ * Data Item RE - 문서 상에 파싱 규칙 없음
1777
+ * 가변 길이
1778
+ * @param record 단일 Record 파싱 결과
1779
+ * @param bitArr Asterix 바이트 데이터
1780
+ * @param currentPos 데이터 아이템 시작 인덱스
1781
+ * @param diLength 데이터 길이
1782
+ */
1783
+ const re = (record, bitArr, currentPos, diLength) => {
1784
+ record["021_RE"] = (0, preprocess_1.getHexString)(bitArr, currentPos, diLength);
1785
+ };