diff --git a/htdocs/lib/MessagePanel.js b/htdocs/lib/MessagePanel.js
index 54fcee32..3ecca55e 100644
--- a/htdocs/lib/MessagePanel.js
+++ b/htdocs/lib/MessagePanel.js
@@ -64,7 +64,7 @@ function WsjtMessagePanel(el) {
this.modes = [].concat(this.qsoModes, this.beaconModes);
}
-WsjtMessagePanel.prototype = new MessagePanel();
+WsjtMessagePanel.prototype = Object.create(MessagePanel.prototype);
WsjtMessagePanel.prototype.supportsMessage = function(message) {
return this.modes.indexOf(message['mode']) >= 0;
@@ -133,7 +133,7 @@ function PacketMessagePanel(el) {
this.initClearTimer();
}
-PacketMessagePanel.prototype = new MessagePanel();
+PacketMessagePanel.prototype = Object.create(MessagePanel.prototype);
PacketMessagePanel.prototype.supportsMessage = function(message) {
return message['mode'] === 'APRS';
@@ -239,7 +239,7 @@ PocsagMessagePanel = function(el) {
this.initClearTimer();
}
-PocsagMessagePanel.prototype = new MessagePanel();
+PocsagMessagePanel.prototype = Object.create(MessagePanel.prototype);
PocsagMessagePanel.prototype.supportsMessage = function(message) {
return message['mode'] === 'Pocsag';
@@ -282,7 +282,7 @@ AdsbMessagePanel = function(el) {
this.initClearTimer();
}
-AdsbMessagePanel.prototype = new MessagePanel();
+AdsbMessagePanel.prototype = Object.create(MessagePanel.prototype);
AdsbMessagePanel.prototype.supportsMessage = function(message) {
return message["mode"] === "ADSB";
@@ -405,7 +405,7 @@ IsmMessagePanel = function(el) {
this.initClearTimer();
};
-IsmMessagePanel.prototype = new MessagePanel();
+IsmMessagePanel.prototype = Object.create(MessagePanel.prototype);
IsmMessagePanel.prototype.supportsMessage = function(message) {
return message['mode'] === 'ISM';
@@ -462,12 +462,60 @@ $.fn.ismMessagePanel = function() {
return this.data('panel');
};
-HfdlMessagePanel = function(el) {
+AircraftMessagePanel = function(el) {
MessagePanel.call(this, el);
+}
+
+AircraftMessagePanel.prototype = Object.create(MessagePanel.prototype);
+
+AircraftMessagePanel.prototype.renderAcars = function(acars) {
+ var details = '
Current link: ' + acars['current_link']['descr'];
+ }
+ if ('links_avail' in acars) {
+ details += '
Available links: ' + acars['links_avail'].map(function (l) {
+ return l['descr'];
+ }).join(', ') + '
';
+ }
+ } else if ('arinc622' in acars) {
+ var arinc622 = acars['arinc622'];
+ if ('adsc' in arinc622) {
+ var adsc = arinc622['adsc'];
+ if ('tags' in adsc) {
+ adsc['tags'].forEach(function(tag) {
+ if ('basic_report' in tag) {
+ var basic_report = tag['basic_report'];
+ details += '
Basic report
';
+ details += '
Position: ' + basic_report['lat'] + ', ' + basic_report['lon'] + '
';
+ details += '
Altitude: ' + basic_report['alt'] + '
';
+ } else {
+ details += '
Unsupported tag
';
+ }
+ });
+ } else {
+ details += '
Other ADS-C data
';
+ }
+ }
+ } else {
+ // plain text
+ details += '
' + acars['msg_text'] + '
';
+ }
+ return details;
+}
+
+HfdlMessagePanel = function(el) {
+ AircraftMessagePanel.call(this, el);
this.initClearTimer();
}
-HfdlMessagePanel.prototype = new MessagePanel();
+HfdlMessagePanel.prototype = Object.create(AircraftMessagePanel.prototype);
HfdlMessagePanel.prototype.render = function() {
$(this.el).append($(
@@ -533,13 +581,7 @@ HfdlMessagePanel.prototype.pushMessage = function(message) {
} else if (hfnpdu['type']['id'] === 255) {
// enveloped data
if ('acars' in hfnpdu) {
- var acars = hfnpdu['acars'];
- details = '
ACARS message
';
- if ('flight' in acars) {
- details += '
Flight: ' + acars['flight'] + '
';
- }
- details += '
Registration: ' + acars['reg'].replace(/^\.+/g, '') + '
';
- details += '
' + acars['msg_text'] + '
';
+ details = this.renderAcars(hfnpdu['acars']);
}
}
} else if (lpdu['type']['id'] === 47) {
@@ -599,18 +641,20 @@ $.fn.hfdlMessagePanel = function() {
};
Vdl2MessagePanel = function(el) {
- MessagePanel.apply(this, el);
+ AircraftMessagePanel.call(this, el);
this.initClearTimer();
}
-Vdl2MessagePanel.prototype = new MessagePanel();
+Vdl2MessagePanel.prototype = Object.create(AircraftMessagePanel.prototype);
Vdl2MessagePanel.prototype.render = function() {
$(this.el).append($(
'
' +
'' +
- '| TODO | ' +
- '
' +
+ 'Source | ' +
+ 'Destination | ' +
+ 'Details | ' +
+ '' +
'' +
'
'
));
@@ -622,9 +666,77 @@ Vdl2MessagePanel.prototype.supportsMessage = function(message) {
Vdl2MessagePanel.prototype.pushMessage = function(message) {
var $b = $(this.el).find('tbody');
+ var src = '';
+ var dst = '';
+ var details = JSON.stringify(message);
+
+ var renderAddress = function(a) {
+ return '
' + a['addr'] + '
' + a['type'] + ( 'status' in a ? ' (' + a['status'] + ')' : '' ) + '
'
+ }
+
+ // TODO remove safety net once parsing is complete
+ try {
+ var payload = message['vdl2'];
+ if ('avlc' in payload) {
+ var avlc = payload['avlc'];
+ src = renderAddress(avlc['src']);
+ dst = renderAddress(avlc['dst']);
+
+ if (avlc['frame_type'] === 'S') {
+ details = '
Supervisory frame
';
+ if (avlc['cmd'] === 'Receive Ready') {
+ details = '
Receive Ready
';
+ }
+ } else if (avlc['frame_type'] === 'I') {
+ details = '
Information frame
';
+ if ('acars' in avlc) {
+ details = this.renderAcars(avlc['acars']);
+ } else if ('x25' in avlc) {
+ var x25 = avlc['x25'];
+ if (!('reasm_status' in x25) || ['skipped', 'complete'].includes(x25['reasm_status'])) {
+ details = '
X.25 frame
';
+ if ('clnp' in x25) {
+ var clnp = x25['clnp']
+ if ('cotp' in clnp) {
+ var cotp = clnp['cotp'];
+ if ('cpdlc' in cotp) {
+ var cpdlc = cotp['cpdlc'];
+ details = '
CPDLC
';
+ if ('atc_downlink_message' in cpdlc) {
+ var atc_downlink_message = cpdlc['atc_downlink_message'];
+ if ('msg_data' in atc_downlink_message) {
+ var msg_data = atc_downlink_message['msg_data'];
+ if ('msg_elements' in msg_data) {
+ details += '
' + msg_data['msg_elements'].map(function(e) { return e['msg_element']['choice_label']; }).join(', ') + '
';
+ }
+ } else {
+ details += '
' + JSON.stringify(cpdlc) + '
';
+ }
+ }
+ }
+ }
+ }
+ } else {
+ details = '
Partial X.25 frame
';
+ }
+ }
+ } else if (avlc['frame_type'] === 'U') {
+ details = '
Unnumbered frame
';
+ if ('xid' in avlc) {
+ var xid = avlc['xid'];
+ details = '
' + xid['type_descr'] + '
';
+ }
+ }
+ }
+ } catch (e) {
+ console.error(e, e.stack);
+ }
+
$b.append($(
'
' +
- '| ' + JSON.stringify(message) + ' | ' +
+ '' + src + ' | ' +
+ '' + dst + ' | ' +
+ '' + details + ' | ' +
'
'
));
this.scrollToBottom();