Skip to content

Commit 8baf2f9

Browse files
authored
Adding back Label 4J POS parsing (#182)
was removed when moving to a common H1 parser. Adding it back in
1 parent 1a2cc4c commit 8baf2f9

File tree

3 files changed

+135
-60
lines changed

3 files changed

+135
-60
lines changed

lib/plugins/Label_4J_POS.test.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { MessageDecoder } from '../MessageDecoder';
2+
import { Label_4J_POS } from './Label_4J_POS';
3+
4+
describe('Label 4J POS', () => {
5+
6+
let plugin: Label_4J_POS;
7+
8+
beforeEach(() => {
9+
const decoder = new MessageDecoder();
10+
plugin = new Label_4J_POS(decoder);
11+
});
12+
13+
14+
test('matches qualifiers', () => {
15+
expect(plugin.decode).toBeDefined();
16+
expect(plugin.name).toBe('label-4j-pos');
17+
expect(plugin.qualifiers).toBeDefined();
18+
expect(plugin.qualifiers()).toEqual({
19+
labels: ['4J'],
20+
preambles: ['POS/'],
21+
});
22+
});
23+
24+
25+
test('decodes msg 1', () => {
26+
// https://app.airframes.io/messages/2434848463
27+
const text = 'POS/ID91459S,BANKR31,/DC03032024,142813/MR64,0/ET31539/PSN39277W077359,142800,240,N39300W077110,031430,N38560W077150,M28,27619,MT370/CG311,160,350/FB732/VR329071';
28+
const decodeResult = plugin.decode({ text: text });
29+
30+
expect(decodeResult.decoded).toBe(true);
31+
expect(decodeResult.decoder.decodeLevel).toBe('partial');
32+
expect(decodeResult.formatted.description).toBe('Position Report');
33+
expect(decodeResult.raw.message_timestamp).toBe(1709476093);
34+
expect(decodeResult.raw.flight_number).toBe('BANKR31');
35+
expect(decodeResult.raw.mission_number).toBe('');
36+
expect(decodeResult.formatted.items.length).toBe(7);
37+
expect(decodeResult.formatted.items[0].label).toBe('Tail');
38+
expect(decodeResult.formatted.items[0].value).toBe('91459S');
39+
expect(decodeResult.formatted.items[1].label).toBe('Estimated Time of Arrival');
40+
expect(decodeResult.formatted.items[1].value).toBe('15:39:00');
41+
expect(decodeResult.formatted.items[2].label).toBe('Aircraft Position');
42+
expect(decodeResult.formatted.items[2].value).toBe('39.462 N, 77.598 W');
43+
expect(decodeResult.formatted.items[3].label).toBe('Aircraft Route');
44+
expect(decodeResult.formatted.items[3].value).toBe('(39.500 N, 77.183 W)@14:28:00 > (38.933 N, 77.250 W)@03:14:30 > ?');
45+
expect(decodeResult.formatted.items[4].label).toBe('Altitude');
46+
expect(decodeResult.formatted.items[4].value).toBe('24000 feet');
47+
expect(decodeResult.formatted.items[5].label).toBe('Outside Air Temperature (C)');
48+
expect(decodeResult.formatted.items[5].value).toBe('-28 degrees');
49+
expect(decodeResult.formatted.items[6].label).toBe('Message Checksum');
50+
expect(decodeResult.formatted.items[6].value).toBe('0x9071');
51+
expect(decodeResult.remaining.text).toBe('MR64,0,27619,MT370/CG311,160,350/FB732/VR32');
52+
});
53+
54+
// this can probably go away, as it's the same format as msg 1
55+
// but it was in Label_H1_POS.test.ts
56+
test('decodes msg 2', () => {
57+
// https://app.airframes.io/messages/3157551384
58+
const text = 'POS/ID91517S,WIDE21,7PZWTCP21222/DC09082024,140706/MR238,2/ET91456/PSN37375W077368,140700,300,JAXSN,091417,LOOEY,M26,21329,M080T490/CG293,160,350/FB583/VR32C696';
59+
const decodeResult = plugin.decode({ text: text });
60+
61+
expect(decodeResult.decoded).toBe(true);
62+
expect(decodeResult.decoder.decodeLevel).toBe('partial')
63+
expect(decodeResult.formatted.description).toBe('Position Report');
64+
expect(decodeResult.raw.message_timestamp).toBe(1725804426);
65+
expect(decodeResult.raw.flight_number).toBe('WIDE21');
66+
expect(decodeResult.raw.mission_number).toBe('7PZWTCP21222');
67+
expect(decodeResult.formatted.items.length).toBe(7);
68+
expect(decodeResult.formatted.items[0].label).toBe('Tail');
69+
expect(decodeResult.formatted.items[0].value).toBe('91517S');
70+
expect(decodeResult.formatted.items[1].label).toBe('Estimated Time of Arrival');
71+
expect(decodeResult.formatted.items[1].value).toBe('14:56:00');
72+
expect(decodeResult.formatted.items[2].label).toBe('Aircraft Position');
73+
expect(decodeResult.formatted.items[2].value).toBe('37.625 N, 77.613 W');
74+
expect(decodeResult.formatted.items[3].label).toBe('Aircraft Route');
75+
expect(decodeResult.formatted.items[3].value).toBe('JAXSN@14:07:00 > LOOEY@09:14:17 > ?');
76+
expect(decodeResult.formatted.items[4].label).toBe('Altitude');
77+
expect(decodeResult.formatted.items[4].value).toBe('30000 feet');
78+
expect(decodeResult.formatted.items[5].label).toBe('Outside Air Temperature (C)');
79+
expect(decodeResult.formatted.items[5].value).toBe('-26 degrees');
80+
expect(decodeResult.formatted.items[6].label).toBe('Message Checksum');
81+
expect(decodeResult.formatted.items[6].value).toBe('0xc696');
82+
expect(decodeResult.remaining.text).toBe('MR238,2,21329,M080T490/CG293,160,350/FB583/VR32');
83+
});
84+
85+
test('decodes <invalid>', () => {
86+
87+
const text = 'POS/ Bogus message';
88+
const decodeResult = plugin.decode({ text: text });
89+
90+
expect(decodeResult.decoded).toBe(false);
91+
expect(decodeResult.decoder.decodeLevel).toBe('none');
92+
expect(decodeResult.formatted.description).toBe('Position Report');
93+
expect(decodeResult.formatted.items.length).toBe(0);
94+
});
95+
});

lib/plugins/Label_4J_POS.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { DecoderPlugin } from '../DecoderPlugin';
2+
import { DecodeResult, Message, Options } from '../DecoderPluginInterface';
3+
import { H1Helper } from '../utils/h1_helper';
4+
import { ResultFormatter } from '../utils/result_formatter';
5+
6+
export class Label_4J_POS extends DecoderPlugin {
7+
name = 'label-4j-pos';
8+
qualifiers() { // eslint-disable-line class-methods-use-this
9+
return {
10+
labels: ['4J'],
11+
preambles: ['POS/'],
12+
};
13+
}
14+
15+
// copied from Label_H1.ts since i don't really want to have to have
16+
// something named like that decode more than 1 type
17+
// if we figure out a good name, i'll combine them
18+
decode(message: Message, options: Options = {}) : DecodeResult {
19+
let decodeResult = this.defaultResult();
20+
decodeResult.decoder.name = this.name;
21+
decodeResult.message = message;
22+
23+
const msg = message.text.replace(/\n|\r/g, "");
24+
const decoded = H1Helper.decodeH1Message(decodeResult, msg);
25+
decodeResult.decoded = decoded;
26+
27+
decodeResult.decoder.decodeLevel = !decodeResult.remaining.text ? 'full' : 'partial';
28+
if (decodeResult.formatted.items.length === 0) {
29+
if (options.debug) {
30+
console.log(`Decoder: Unknown H1 message: ${message.text}`);
31+
}
32+
ResultFormatter.unknown(decodeResult, message.text);
33+
decodeResult.decoded = false;
34+
decodeResult.decoder.decodeLevel = 'none';
35+
}
36+
return decodeResult;
37+
}
38+
}
39+
40+
export default {};

lib/plugins/Label_H1_POS.test.ts

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -276,36 +276,6 @@ describe('Label_H1 POS', () => {
276276
expect(decodeResult.remaining.text).toBe('188,4,M12,246048,374K,282K,1223,133,,70,151437,73/PR1223,222,133,,44,40,252074,M22,180,P0');
277277
});
278278

279-
test('variant 7', () => {
280-
281-
// https://app.airframes.io/messages/2434848463
282-
const text = 'POS/ID91459S,BANKR31,/DC03032024,142813/MR64,0/ET31539/PSN39277W077359,142800,240,N39300W077110,031430,N38560W077150,M28,27619,MT370/CG311,160,350/FB732/VR329071';
283-
const decodeResult = plugin.decode({ text: text });
284-
285-
expect(decodeResult.decoded).toBe(true);
286-
expect(decodeResult.decoder.decodeLevel).toBe('partial');
287-
expect(decodeResult.formatted.description).toBe('Position Report');
288-
expect(decodeResult.raw.message_timestamp).toBe(1709476093);
289-
expect(decodeResult.raw.flight_number).toBe('BANKR31');
290-
expect(decodeResult.raw.mission_number).toBe('');
291-
expect(decodeResult.formatted.items.length).toBe(7);
292-
expect(decodeResult.formatted.items[0].label).toBe('Tail');
293-
expect(decodeResult.formatted.items[0].value).toBe('91459S');
294-
expect(decodeResult.formatted.items[1].label).toBe('Estimated Time of Arrival');
295-
expect(decodeResult.formatted.items[1].value).toBe('15:39:00');
296-
expect(decodeResult.formatted.items[2].label).toBe('Aircraft Position');
297-
expect(decodeResult.formatted.items[2].value).toBe('39.462 N, 77.598 W');
298-
expect(decodeResult.formatted.items[3].label).toBe('Aircraft Route');
299-
expect(decodeResult.formatted.items[3].value).toBe('(39.500 N, 77.183 W)@14:28:00 > (38.933 N, 77.250 W)@03:14:30 > ?');
300-
expect(decodeResult.formatted.items[4].label).toBe('Altitude');
301-
expect(decodeResult.formatted.items[4].value).toBe('24000 feet');
302-
expect(decodeResult.formatted.items[5].label).toBe('Outside Air Temperature (C)');
303-
expect(decodeResult.formatted.items[5].value).toBe('-28 degrees');
304-
expect(decodeResult.formatted.items[6].label).toBe('Message Checksum');
305-
expect(decodeResult.formatted.items[6].value).toBe('0x9071');
306-
expect(decodeResult.remaining.text).toBe('MR64,0,27619,MT370/CG311,160,350/FB732/VR32');
307-
});
308-
309279
test('#variant 7', () => {
310280

311281
// https://app.airframes.io/messages/2434835903
@@ -482,36 +452,6 @@ describe('Label_H1 POS', () => {
482452
expect(decodeResult.remaining.text).toBe('.POS,,27282,241,MANUAL,0,813');
483453
});
484454

485-
test('decodes Label 4J Preamble POS variant 7', () => {
486-
487-
// https://app.airframes.io/messages/3157551384
488-
const text = 'POS/ID91517S,WIDE21,7PZWTCP21222/DC09082024,140706/MR238,2/ET91456/PSN37375W077368,140700,300,JAXSN,091417,LOOEY,M26,21329,M080T490/CG293,160,350/FB583/VR32C696';
489-
const decodeResult = plugin.decode({ text: text });
490-
491-
expect(decodeResult.decoded).toBe(true);
492-
expect(decodeResult.decoder.decodeLevel).toBe('partial')
493-
expect(decodeResult.formatted.description).toBe('Position Report');
494-
expect(decodeResult.raw.message_timestamp).toBe(1725804426);
495-
expect(decodeResult.raw.flight_number).toBe('WIDE21');
496-
expect(decodeResult.raw.mission_number).toBe('7PZWTCP21222');
497-
expect(decodeResult.formatted.items.length).toBe(7);
498-
expect(decodeResult.formatted.items[0].label).toBe('Tail');
499-
expect(decodeResult.formatted.items[0].value).toBe('91517S');
500-
expect(decodeResult.formatted.items[1].label).toBe('Estimated Time of Arrival');
501-
expect(decodeResult.formatted.items[1].value).toBe('14:56:00');
502-
expect(decodeResult.formatted.items[2].label).toBe('Aircraft Position');
503-
expect(decodeResult.formatted.items[2].value).toBe('37.625 N, 77.613 W');
504-
expect(decodeResult.formatted.items[3].label).toBe('Aircraft Route');
505-
expect(decodeResult.formatted.items[3].value).toBe('JAXSN@14:07:00 > LOOEY@09:14:17 > ?');
506-
expect(decodeResult.formatted.items[4].label).toBe('Altitude');
507-
expect(decodeResult.formatted.items[4].value).toBe('30000 feet');
508-
expect(decodeResult.formatted.items[5].label).toBe('Outside Air Temperature (C)');
509-
expect(decodeResult.formatted.items[5].value).toBe('-26 degrees');
510-
expect(decodeResult.formatted.items[6].label).toBe('Message Checksum');
511-
expect(decodeResult.formatted.items[6].value).toBe('0xc696');
512-
expect(decodeResult.remaining.text).toBe('MR238,2,21329,M080T490/CG293,160,350/FB583/VR32');
513-
});
514-
515455
test('decodes Label H1 Preamble #M1BPOS <invalid>', () => {
516456

517457
const text = '#M1BPOS Bogus message';

0 commit comments

Comments
 (0)