feat(sim): host-page buzzer mute hook + randomized repeater names

sim_buzzer_toggle_quiet()/sim_buzzer_get_quiet() (UITask.cpp) call the
literal UITask::toggleBuzzer() the real on-device Settings > Buzzer mute
toggle already calls -- persists into NodePrefs.buzzer_quiet, clears
buzzer_auto, saves prefs, shows the real "Buzzer: ON/OFF" alert. Not a
re-implementation, not a host-side Web Audio mute layered on top.

Every simple_repeater instance advertised the literal ADVERT_NAME
("repeater") -- across meshcore-solo-site's cross-visitor relay bridge
every hop in every path/relay list was an indistinguishable wall of
"repeater"s. A SIM_PLATFORM/__EMSCRIPTEN__-only default now picks a
random "<adjective> <geographic feature>" pair from
sim_instance_entropy() (real crypto.getRandomValues()-sourced entropy,
already used for RNG seeding) at first boot -- matches the real,
common ham-radio convention of naming a repeater after the hill it
sits on. Persists normally across reboots via the existing prefs
load/save path, same as a real operator-set name would.

sim_repeater_get_name() added alongside the existing
sim_repeater_get_relay_count() for host-page/test access to the
result.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018iubftDmKNWmkNnhJRz8UH
This commit is contained in:
Jakub
2026-09-05 08:36:02 +02:00
co-authored by Claude Sonnet 5
parent a54922e3d6
commit a18a821326
3 changed files with 48 additions and 0 deletions
@@ -2191,6 +2191,22 @@ extern "C" EMSCRIPTEN_KEEPALIVE int sim_buzzer_freq_hz() {
extern "C" EMSCRIPTEN_KEEPALIVE int sim_buzzer_get_volume() {
return g_sim_ui_task_for_js ? (int)g_sim_ui_task_for_js->buzzerVolume() : 0;
}
// Write side: a host page's own mute control (a button next to the d-pad,
// say) calling this fires UITask::toggleBuzzer() -- the literal function
// the real on-device Settings > Buzzer mute toggle calls, not a
// re-implementation of it. That single call already does everything the
// real toggle does: buzzer.quiet(), writes NodePrefs.buzzer_quiet, clears
// buzzer_auto (manual mute always wins over auto-mute-on-BT-connect,
// same as pressing it on the device would), the_mesh.savePrefs(), and
// the real on-screen "Buzzer: ON/OFF" alert -- so muting from the host
// page's button is visibly the same event as muting from the keypad.
extern "C" EMSCRIPTEN_KEEPALIVE void sim_buzzer_toggle_quiet() {
if (g_sim_ui_task_for_js) g_sim_ui_task_for_js->toggleBuzzer();
}
extern "C" EMSCRIPTEN_KEEPALIVE int sim_buzzer_get_quiet() {
return (g_sim_ui_task_for_js && g_sim_ui_task_for_js->isBuzzerQuiet()) ? 1 : 0;
}
#endif
#endif
+20
View File
@@ -891,7 +891,27 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
_prefs.rx_delay_base = 0.0f; // turn off by default, was 10.0;
_prefs.tx_delay_factor = 0.5f; // was 0.25f
_prefs.direct_tx_delay_factor = 0.3f; // was 0.2
#if defined(SIM_PLATFORM) && defined(__EMSCRIPTEN__)
// Every visitor's own local repeater otherwise advertises the exact same
// literal ADVERT_NAME ("repeater") -- across meshcore-solo-site's
// cross-visitor relay bridge (every visitor's R shares one virtual
// channel) that means every hop in every path/relay list is an
// indistinguishable wall of "repeater"s, confirmed live. Real repeaters
// are near-universally named after the geographic feature they sit on
// (an actual, common ham-radio convention) -- a random "<word> <word>"
// pair both fixes the indistinguishability and reads as a plausible
// real name instead of an obviously synthetic one.
// sim_instance_entropy() (SimInstance.h) is the same real
// crypto.getRandomValues()-sourced entropy already mixed into this
// instance's RNG seed (see SimRNG.h) -- genuinely different per visitor,
// not a fixed per-tag value repeatable across boots.
static const char* RPT_ADJ[] = { "Cedar","Copper","Ember","Foggy","Granite","Iron","Misty","Rusty","Silver","Windy","Amber","Frost","Golden","Stone","Lunar","Quiet" };
static const char* RPT_FEAT[] = { "Ridge","Summit","Hollow","Peak","Creek","Grove","Meadow","Bluff","Hilltop","Overlook","Pines","Notch","Crossing","Basin","Knoll","Ledge" };
uint32_t rn = sim_instance_entropy();
snprintf(_prefs.node_name, sizeof(_prefs.node_name), "%s %s", RPT_ADJ[(rn >> 4) & 15], RPT_FEAT[rn & 15]);
#else
StrHelper::strncpy(_prefs.node_name, ADVERT_NAME, sizeof(_prefs.node_name));
#endif
_prefs.node_lat = ADVERT_LAT;
_prefs.node_lon = ADVERT_LON;
StrHelper::strncpy(_prefs.password, ADMIN_PASSWORD, sizeof(_prefs.password));
+12
View File
@@ -41,6 +41,18 @@ extern "C" EMSCRIPTEN_KEEPALIVE uint32_t sim_repeater_get_relay_count() {
return the_mesh.getNumForwarded();
}
// This instance's own advertised name (NodePrefs.node_name via
// MyMesh::getNodeName()) -- randomized per-visitor at first boot (see the
// SIM_PLATFORM/__EMSCRIPTEN__ branch in MyMesh's constructor) so every
// hop in a cross-visitor path/relay list isn't just an indistinguishable
// wall of the literal "repeater". Returns a pointer straight into
// NodePrefs's own fixed buffer -- valid for the process's whole lifetime,
// same as every other read-only getter here, no ownership handoff needed
// (ccall(..., 'string', ...) on the JS side copies it out immediately).
extern "C" EMSCRIPTEN_KEEPALIVE const char* sim_repeater_get_name() {
return the_mesh.getNodeName();
}
// Same "has setup() actually finished" readiness flag as
// examples/companion_radio/main.cpp -- see that file's comment for why
// this is needed instead of a fixed post-ready delay.