mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-10-09 11:16:39 +00:00
feat(ui-lvgl): offline raster map from the microSD
Map screen (Home > Map): Web-Mercator tiles from /maps/{z}/{x}/{y}.png on
the card (Meshtastic MUI layout; per-column TPK1 .pak also read), drag to
pan, +/- zoom, re-centre/follow GPS, Nearby nodes with a position as
markers opening node detail. Tiles decode one per loop pass into a
12-slot RGB565 cache in PSRAM. map/TileProvider.h is the swap point for a
later vector renderer: the screen only calls renderTile(). The tile set's
credit line comes from maps/attribution.txt.
L2 mounts the card over SDMMC 1-bit (CLK 2, CMD 3, D0 1). LVGL's lodepng
is enabled; note its LVGL patch returns an lv_draw_buf_t*, not pixels.
LVGL pool 2 MB for PNG decoding. Fonts gain map / users icons.
tools/maps/fetch_tiles.py prepares a card for an area (presets for
Poland), requires an explicit tile URL (tile.openstreetmap.org blocks
offline use) and stops on placeholder images. The LVGL sim preloads
web/maps into the L2's /sdcard and puts its GPS on Kraków.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,10 @@
|
||||
cd variants/sim/web && python3 -m http.server 8080
|
||||
and open http://localhost:8080/lvgl.html .
|
||||
|
||||
Map: tiles in web/maps (tools/maps/fetch_tiles.py --preset krakow --out
|
||||
variants/sim/web --manifest) are copied into the L2's /sdcard/maps at boot,
|
||||
and its GPS is put on Kraków's Old Town.
|
||||
|
||||
The mouse is the finger: press / drag / release on the LCD. Holding a key
|
||||
on the on-screen keyboard opens its accent popup, as on the device.
|
||||
|
||||
@@ -144,12 +148,31 @@
|
||||
inst.call('sim_test_disable_screen_timeout', 'number');
|
||||
}
|
||||
|
||||
// Map tiles listed in maps/manifest.json -> the instance's /sdcard/maps.
|
||||
async function loadMaps(inst) {
|
||||
let list;
|
||||
try { list = await (await fetch('maps/manifest.json')).json(); }
|
||||
catch (e) { log('no maps/manifest.json (map will be empty)'); return; }
|
||||
const FS = inst.mod.FS;
|
||||
await Promise.all(list.map(async (rel) => {
|
||||
const buf = new Uint8Array(await (await fetch('maps/' + rel)).arrayBuffer());
|
||||
const path = '/sdcard/maps/' + rel;
|
||||
FS.mkdirTree(path.substring(0, path.lastIndexOf('/')));
|
||||
FS.writeFile(path, buf);
|
||||
}));
|
||||
log('map: ' + list.length + ' tiles loaded');
|
||||
}
|
||||
|
||||
async function bootL() {
|
||||
document.getElementById('status-L').textContent = 'booting…';
|
||||
if (L) L.call('sim_stop_main_loop', null);
|
||||
L = wrap(await MeshCoreSimLvgl({ simInstanceTag: 'L' }), 'L');
|
||||
const ok = await waitReady(L);
|
||||
if (ok) prepare(L);
|
||||
if (ok) {
|
||||
prepare(L);
|
||||
L.call('sim_location_set', null, ['number', 'number', 'number'], [50.0614, 19.9372, 220]);
|
||||
await loadMaps(L);
|
||||
}
|
||||
document.getElementById('status-L').textContent = ok ? 'ready' : 'boot timed out';
|
||||
return ok;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user