Files
AR-GPS/frontend/js/bridge.js
T

68 lines
2.5 KiB
JavaScript

'use strict';
/**
* GPS Navigator — Qt WebChannel bridge.
*
* qwebchannel.js is injected by PyQt5 at DocumentCreation time (before any
* page script runs), so QWebChannel is always available here.
*
* Exposes:
* window._py(method, arg1, ...) → Promise that resolves with the return value
* window.py → the registered bridge object (set after init)
*/
(function () {
// _py('method', arg1, arg2, ...) → Promise<result>
// Works for both void slots (resolves undefined) and value-returning slots.
window._py = function (method) {
var args = Array.prototype.slice.call(arguments, 1);
return new Promise(function (resolve) {
window.py[method].apply(window.py, args.concat([resolve]));
});
};
function _initChannel() {
if (typeof QWebChannel === 'undefined' || typeof qt === 'undefined') {
// Running in a plain browser (dev mode) — no bridge available.
console.warn('[bridge] QWebChannel not available — dev mode, no GPS bridge');
window.py = null;
// Let the app start anyway (it will show "no GPS" state)
if (typeof window.bootApp === 'function') window.bootApp();
return;
}
new QWebChannel(qt.webChannelTransport, function (channel) {
window.py = channel.objects.py;
// ── GPS messages: Python signal → JS handler ────────────────────────
// Qt queues this signal delivery from the NMEA reader thread to the
// main thread, so it always arrives in the JS event loop safely.
window.py.gpsMessage.connect(function (json_str) {
try {
var msg = JSON.parse(json_str);
if (typeof window.handleGPSMsg === 'function') {
window.handleGPSMsg(msg);
}
} catch (e) {
console.error('[bridge] gpsMessage parse error:', e, json_str);
}
});
// ── Start GPS autodetect (signal handler is now connected) ───────────
window.py.autodetect_and_start();
// ── Boot the application ─────────────────────────────────────────────
if (typeof window.bootApp === 'function') {
window.bootApp();
}
});
}
// Run after DOM + all other scripts are loaded
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', _initChannel);
} else {
_initChannel();
}
})();