function MessagePanel(el) {
this.el = el;
this.render();
this.initClearButton();
}
MessagePanel.prototype.supportsMessage = function(message) {
return false;
};
MessagePanel.prototype.render = function() {
};
MessagePanel.prototype.pushMessage = function(message) {
};
// automatic clearing is not enabled by default. call this method from the constructor to enable
MessagePanel.prototype.initClearTimer = function() {
var me = this;
if (me.removalInterval) clearInterval(me.removalInterval);
me.removalInterval = setInterval(function () {
me.clearMessages(1000);
}, 15000);
};
MessagePanel.prototype.clearMessages = function(toRemain) {
var $elements = $(this.el).find('tbody tr');
// limit to 1000 entries in the list since browsers get laggy at some point
var toRemove = $elements.length - toRemain;
if (toRemove <= 0) return;
$elements.slice(0, toRemove).remove();
};
MessagePanel.prototype.initClearButton = function() {
var me = this;
me.clearButton = $(
'
Current link: ' + mediaadv['current_link']['descr'];
}
if ('links_avail' in mediaadv) {
details += '
Available links: ' + mediaadv['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 ADS-C report
';
details += '
Position: ' + basic_report['lat'] + ', ' + basic_report['lon'] + '
';
details += '
Altitude: ' + basic_report['alt'] + '
';
} else if ('cancel_all_contracts' in tag) {
details += '
Cancel all ADS-C contracts
';
} else if ('cancel_contract' in tag) {
details += '
Cancel ADS-C contract
';
} else {
details += '
Unsupported tag
';
}
});
} else {
details += '
Other ADS-C data
';
}
}
} else {
// plain text
details += '
Label: ' + acars['label'] + '
';
details += '
' + acars['msg_text'] + '
';
}
return details;
};
AircraftMessagePanel.prototype.handleFlight = function(raw) {
return raw.replace(/^([0-9A-Z]{2})0*([0-9A-Z]+$)/, '$1$2');
};
HfdlMessagePanel = function(el) {
AircraftMessagePanel.call(this, el);
this.initClearTimer();
}
HfdlMessagePanel.prototype = Object.create(AircraftMessagePanel.prototype);
HfdlMessagePanel.prototype.render = function() {
$(this.el).append($(
'
' +
'' +
'| Source | ' +
'Destination | ' +
'Details | ' +
'
' +
'' +
'
'
));
};
HfdlMessagePanel.prototype.supportsMessage = function(message) {
return message['mode'] === 'HFDL';
};
HfdlMessagePanel.prototype.renderPosition = function(hfnpdu) {
if ('pos' in hfnpdu) {
var pos = hfnpdu['pos'];
var lat = pos['lat'] || 180;
var lon = pos['lon'] || 180;
if (Math.abs(lat) <= 90 && Math.abs(lon) <= 180) {
return '
Position: ' + pos['lat'] + ', ' + pos['lon'] + '
';
}
}
return '';
};
HfdlMessagePanel.prototype.renderLogon = function(lpdu) {
var details = ''
if (lpdu['ac_info'] && lpdu['ac_info']['icao']) {
details += '
ICAO: ' + lpdu['ac_info']['icao'] + '
';
}
if (lpdu['hfnpdu']) {
var hfnpdu = lpdu['hfnpdu'];
if (hfnpdu['flight_id'] && hfnpdu['flight_id'] !== '') {
details += '
Flight: ' + this.handleFlight(lpdu['hfnpdu']['flight_id']) + '
'
}
details += this.renderPosition(hfnpdu);
}
return details;
};
HfdlMessagePanel.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['id'];
}
// TODO remove safety net once parsing is complete
try {
var payload = message['hfdl'];
if ('spdu' in payload) {
var spdu = payload['spdu'];
src = renderAddress(spdu['src']);
details = '
HFDL Squitter message
'
details += '
Systable version: ' + spdu['systable_version'] + '
';
if ('gs_status' in spdu) {
details += spdu['gs_status'].map(function(gs){
return '
Ground station ' + gs['gs']['id'] + ' is operating on frequency ids ' + gs['freqs'].map(function(f) {return f['id']; }).join(', ') + '
';
}).join('')
}
} else if ('lpdu' in payload) {
var lpdu = payload['lpdu'];
src = renderAddress(lpdu['src']);
dst = renderAddress(lpdu['dst']);
if (lpdu['type']['id'] === 13 || lpdu['type']['id'] === 29) {
// unnumbered data
var hfnpdu = lpdu['hfnpdu'];
if (hfnpdu['type']['id'] === 209) {
// performance data
details = '
Performance data
';
details += '
Flight: ' + this.handleFlight(hfnpdu['flight_id']) + '
';
details += this.renderPosition(hfnpdu);
} else if (hfnpdu['type']['id'] === 255) {
// enveloped data
if ('acars' in hfnpdu) {
details = this.renderAcars(hfnpdu['acars']);
}
}
} else if (lpdu['type']['id'] === 47) {
// logon denied
details = '
Logon denied
';
} else if (lpdu['type']['id'] === 63) {
details = '
Logoff request
';
if (lpdu['ac_info'] && lpdu['ac_info']['icao']) {
details += '
ICAO: ' + lpdu['ac_info']['icao'] + '
';
}
} else if (lpdu['type']['id'] === 79) {
details = '
Logon resume
';
details += this.renderLogon(lpdu);
} else if (lpdu['type']['id'] === 95) {
details = '
Logon resume confirmation
';
} else if (lpdu['type']['id'] === 143) {
details = '
Logon request
';
details += this.renderLogon(lpdu);
} else if (lpdu['type']['id'] === 159) {
details = '
Logon confirmation
';
if (lpdu['ac_info'] && lpdu['ac_info']['icao']) {
details += '
ICAO: ' + lpdu['ac_info']['icao'] + '
';
}
if (lpdu['assigned_ac_id']) {
details += '
Assigned aircraft ID: ' + lpdu['assigned_ac_id'] + '
';
}
} else if (lpdu['type']['id'] === 191) {
details = '
Logon request (DLS)
';
details += this.renderLogon(lpdu);
}
}
} catch (e) {
console.error(e, e.stack);
}
$b.append($(
'
' +
'| ' + src + ' | ' +
'' + dst + ' | ' +
'' + details + ' | ' +
'
'
));
this.scrollToBottom();
};
$.fn.hfdlMessagePanel = function() {
if (!this.data('panel')) {
this.data('panel', new HfdlMessagePanel(this));
}
return this.data('panel');
};
Vdl2MessagePanel = function(el) {
AircraftMessagePanel.call(this, el);
this.initClearTimer();
}
Vdl2MessagePanel.prototype = Object.create(AircraftMessagePanel.prototype);
Vdl2MessagePanel.prototype.render = function() {
$(this.el).append($(
'
' +
'' +
'| Source | ' +
'Destination | ' +
'Details | ' +
'
' +
'' +
'
'
));
};
Vdl2MessagePanel.prototype.supportsMessage = function(message) {
return message['mode'] === 'VDL2';
};
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) + '
';
}
}
}
if ('adsc_v2' in cotp) {
var adsc_v2 = cotp['adsc_v2']
details = '
ADS-C v2 Frame
';
if ('adsc_report' in adsc_v2) {
var adsc_report = adsc_v2['adsc_report'];
var data = adsc_report['data'];
if ('periodic_report' in data) {
details += '
Periodic report
';
details += this.processReport(data['periodic_report']['report_data']);
} else if ('event_report' in data) {
details += '
Event report
';
details += this.processReport(data['event_report']['report_data']);
}
}
}
}
}
} 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($(
'
' +
'| ' + src + ' | ' +
'' + dst + ' | ' +
'' + details + ' | ' +
'
'
));
this.scrollToBottom();
};
Vdl2MessagePanel.prototype.processReport = function(report) {
var details = '';
if ('position' in report) {
var position = report['position'];
var lat = position['lat']
var lon = position['lon']
details += '
Position: ' +
lat['deg'] + '° ' + lat['min'] + '\' ' + lat['sec'] + '" ' + lat['dir'] + ', ' +
lon['deg'] + '° ' + lon['min'] + '\' ' + lon['sec'] + '" ' + lon['dir'] +
'
';
details += '
Altitude: ' + position['alt']['val'] + ' ' + position['alt']['unit'] + '
';
}
return details;
}
$.fn.vdl2MessagePanel = function() {
if (!this.data('panel')) {
this.data('panel', new Vdl2MessagePanel(this));
}
return this.data('panel');
};