feat(sim): e-ink simulator builds

SIM_EINK=landscape|portrait builds the e-ink firmware for the browser,
drawn by the same EinkGfxDisplay as the panel. index.html and mesh.html
pick a build from the URL. The simulated sensors get a GPS switch, so the
UI's GPS toggle works.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-10-02 19:24:36 +02:00
co-authored by Claude Opus 5.5
parent b0e24bb076
commit 2589fe95ce
6 changed files with 157 additions and 5 deletions
+10 -3
View File
@@ -158,7 +158,13 @@
<div id="log"></div>
<script src="build/meshcore_sim.js"></script>
<!-- ?build=meshcore_sim_eink_landscape (or _portrait) loads another build of
the same UI; the e-ink driver sizes the canvas itself. -->
<script>
document.write('<script src="build/' +
(new URLSearchParams(location.search).get('build') || 'meshcore_sim').replace(/[^\w]/g, '') +
'.js"><\/script>');
</script>
<script>
const statusEl = document.getElementById('status');
const logEl = document.getElementById('log');
@@ -209,11 +215,12 @@
}
}
if (typeof MeshCoreSim !== 'function') {
const SimFactory = window.MeshCoreSimEink || window.MeshCoreSim;
if (typeof SimFactory !== 'function') {
statusEl.textContent = 'error: build/meshcore_sim.js missing or failed to load -- run variants/sim/build_wasm.sh first.';
} else {
statusEl.textContent = 'booting wasm module...';
MeshCoreSim().then((Module) => {
SimFactory().then((Module) => {
window.Module = Module; // exposed for console poking while testing
statusEl.textContent = 'running -- IDBFS-backed identity/prefs persist across a real reload.';
log('module ready; sim_enqueue_key = ' + (typeof Module._sim_enqueue_key));
+8 -2
View File
@@ -231,8 +231,14 @@
<script src="build/meshcore_sim.js"></script>
<script src="build/repeater/meshcore_sim_repeater.js"></script>
<!-- ?a=meshcore_sim_eink_landscape (or _portrait): A is that e-ink build. -->
<script>
const A_BUILD = (new URLSearchParams(location.search).get('a') || '').replace(/[^\w]/g, '');
if (A_BUILD) document.write('<script src="build/' + A_BUILD + '.js"><\/script>');
</script>
<script>
const logEl = document.getElementById('log');
const FactoryA = (opts) => (A_BUILD ? MeshCoreSimEink : MeshCoreSim)(opts);
function log(msg) {
const line = document.createElement('div');
line.textContent = '[' + new Date().toISOString().substr(11, 12) + '] ' + msg;
@@ -384,7 +390,7 @@
async function resetInstance(key) {
log(`resetting instance ${key}...`);
document.getElementById('status-' + key).textContent = 'resetting...';
if (key === 'A') A = wrapInstance(await MeshCoreSim({ simInstanceTag: 'A' }), 'A');
if (key === 'A') A = wrapInstance(await FactoryA({ simInstanceTag: 'A' }), 'A');
else if (key === 'B') B = wrapInstance(await MeshCoreSim({ simInstanceTag: 'B' }), 'B');
else if (key === 'R') R = wrapInstance(await MeshCoreSimRepeater({ simInstanceTag: 'R' }), 'R');
await waitReady(key === 'A' ? A : key === 'B' ? B : R, 'status-' + key);
@@ -394,7 +400,7 @@
async function main() {
log('booting instance A (companion_radio)...');
const modA = await MeshCoreSim({ simInstanceTag: 'A' });
const modA = await FactoryA({ simInstanceTag: 'A' });
log('booting instance B (companion_radio)...');
const modB = await MeshCoreSim({ simInstanceTag: 'B' });
log('booting instance R (simple_repeater)...');