Kotlin owns the download so tiles land in the exact dir the engine reads (files/brouter/segments4) — no Rust path guessing. processBrouterCommand now dispatches: dltile:<tile> streams brouter.de/brouter/segments4/<tile>.rd5 to a .tmp then renames, writing progress/final state to brouter_dl_<tile>.json; listtiles writes brouter_tiles.json. Tile names are sanitized ([A-Za-z0-9_]). Rust relays: brouter_download_tile / brouter_download_status / brouter_list_tiles. JS: BRouter.downloadTile/downloadStatus/listTiles/downloadTileAndWait. Compiles into the apk. Not yet exercised on device (phone offline) — the tile selection UI and the end-to-end download->offline-route test are the remaining Stage 2 work. IMPLEMENTATION_PLAN updated.
51 lines
2.2 KiB
JavaScript
51 lines
2.2 KiB
JavaScript
// Offline routing via the embedded BRouter engine.
|
|
// JS → Rust command `brouter_route` → Kotlin (btools.router) → GPX back.
|
|
// BRouter.route(points, profile):
|
|
// points — array of [lon, lat] pairs (BRouter order; NOT [lat, lon])
|
|
// profile — "trekking" (planning) | "shortest" (gap fill); default "trekking"
|
|
// Returns a GPX string (parse with parseRouteGPX) or throws with the engine's error.
|
|
// Needs the region .rd5 segments present on device (files/brouter/segments4).
|
|
window.BRouter = {
|
|
async route(points, profile) {
|
|
let lonlats = JSON.stringify((points || []).map(p => [p[0], p[1]]));
|
|
let raw = await window.__TAURI__.core.invoke("brouter_route", {
|
|
lonlats,
|
|
profile: profile || "trekking",
|
|
});
|
|
let res;
|
|
try { res = JSON.parse(raw); } catch (e) { throw new Error("brouter: bad result: " + raw); }
|
|
if (!res.ok) throw new Error("brouter: " + (res.error || "unknown error"));
|
|
return res.gpx;
|
|
},
|
|
|
|
// --- Segment (.rd5) delivery (Stage 2) — Kotlin downloads into files/brouter/segments4 ---
|
|
|
|
// Kick off a tile download (e.g. "E35_N45"); returns immediately. Poll downloadStatus.
|
|
async downloadTile(tile) {
|
|
return window.__TAURI__.core.invoke("brouter_download_tile", { tile });
|
|
},
|
|
|
|
// { state: "downloading"|"done"|"error", bytes, total?, error? } — {} if not started yet.
|
|
async downloadStatus(tile) {
|
|
let raw = await window.__TAURI__.core.invoke("brouter_download_status", { tile });
|
|
try { return JSON.parse(raw); } catch (e) { return {}; }
|
|
},
|
|
|
|
// Downloaded tiles present on device: [{ name, bytes }].
|
|
async listTiles() {
|
|
let raw = await window.__TAURI__.core.invoke("brouter_list_tiles");
|
|
try { return JSON.parse(raw); } catch (e) { return []; }
|
|
},
|
|
|
|
// Convenience: download a tile and resolve when done (or reject on error). onProgress(bytes,total).
|
|
async downloadTileAndWait(tile, onProgress) {
|
|
await this.downloadTile(tile);
|
|
for (;;) {
|
|
await new Promise(r => setTimeout(r, 700));
|
|
let s = await this.downloadStatus(tile);
|
|
if (s.state === "downloading" && onProgress) onProgress(s.bytes || 0, s.total || 0);
|
|
if (s.state === "done") return s;
|
|
if (s.state === "error") throw new Error("brouter tile: " + (s.error || "download failed"));
|
|
}
|
|
},
|
|
};
|