From 5fc8fd1ead79b659193923a05d393944e5f1478a Mon Sep 17 00:00:00 2001 From: liquidraver <504870+liquidraver@users.noreply.github.com> Date: Sun, 14 Jun 2026 22:25:32 +0200 Subject: [PATCH] shared canonical path for UI adverts --- zephcore/app/CompanionMesh.cpp | 39 ++++++++++++------- zephcore/app/CompanionMesh.h | 12 ++++++ zephcore/helpers/BaseChatMesh.h | 8 ++++ .../helpers/ui-joystick/screens/system.cpp | 7 ++-- zephcore/helpers/ui/ui_mesh_actions.cpp | 24 +++--------- 5 files changed, 54 insertions(+), 36 deletions(-) diff --git a/zephcore/app/CompanionMesh.cpp b/zephcore/app/CompanionMesh.cpp index 094b406..5441a11 100644 --- a/zephcore/app/CompanionMesh.cpp +++ b/zephcore/app/CompanionMesh.cpp @@ -272,6 +272,27 @@ void CompanionMesh::sendFloodScoped(const mesh::GroupChannel &channel, mesh::Pac sendFloodScopedDefault(pkt, delay_millis); } +bool CompanionMesh::sendSelfAdvert(bool flood) +{ + mesh::Packet *adv; + if (prefs.advert_loc_policy == 0) { /* ADVERT_LOC_NONE */ + adv = createSelfAdvert(prefs.node_name); + } else { + adv = createSelfAdvert(prefs.node_name, prefs.node_lat, prefs.node_lon); + } + if (!adv) { + return false; + } + if (flood) { + TransportKey default_scope; + memcpy(default_scope.key, prefs.default_scope_key, sizeof(default_scope.key)); + sendFloodScoped(default_scope, adv, (uint32_t)0); + } else { + sendZeroHop(adv); + } + return true; +} + bool CompanionMesh::onContactPathRecv(ContactInfo &from, uint8_t *in_path, uint8_t in_path_len, uint8_t *out_path, uint8_t out_path_len, uint8_t extra_type, uint8_t *extra, uint8_t extra_len) { @@ -2040,21 +2061,9 @@ bool CompanionMesh::handleProtocolFrame(const uint8_t *data, size_t len) } case CMD_SEND_SELF_ADVERT: { - mesh::Packet *adv; - if (prefs.advert_loc_policy == 0) { /* ADVERT_LOC_NONE */ - adv = createSelfAdvert(prefs.node_name); - } else { - adv = createSelfAdvert(prefs.node_name, prefs.node_lat, prefs.node_lon); - } - if (adv) { - /* Optional param: data[1] == 1 means flood, else zero-hop */ - if (len >= 2 && data[1] == 1) { - TransportKey default_scope; - memcpy(default_scope.key, prefs.default_scope_key, sizeof(default_scope.key)); - sendFloodScoped(default_scope, adv, (uint32_t)0); - } else { - sendZeroHop(adv); - } + /* Optional param: data[1] == 1 means flood, else zero-hop */ + bool flood = (len >= 2 && data[1] == 1); + if (sendSelfAdvert(flood)) { sendPacketOk(); } else { sendPacketError(ERR_TABLE_FULL); diff --git a/zephcore/app/CompanionMesh.h b/zephcore/app/CompanionMesh.h index 9e993a7..24d9b95 100644 --- a/zephcore/app/CompanionMesh.h +++ b/zephcore/app/CompanionMesh.h @@ -109,6 +109,18 @@ public: int getOfflineQueueCount() const { return _offline_queue_count; } + /** + * Build and send a self advert using the configured location policy, + * path-hash mode, and default transport scope. This is the canonical + * path shared by the BLE/USB CMD_SEND_SELF_ADVERT handler and the UI + * (button / joystick) advert actions, so flood adverts always honor + * prefs.path_hash_mode and the region scope regardless of trigger. + * + * @param flood true for a flood advert, false for zero-hop. + * @return false if the packet pool was full (advert not sent). + */ + bool sendSelfAdvert(bool flood) override; + /** * Handle a protocol frame from BLE. * Returns true if frame was handled. diff --git a/zephcore/helpers/BaseChatMesh.h b/zephcore/helpers/BaseChatMesh.h index 34162c7..610472b 100644 --- a/zephcore/helpers/BaseChatMesh.h +++ b/zephcore/helpers/BaseChatMesh.h @@ -178,6 +178,14 @@ protected: public: mesh::Packet *createSelfAdvert(const char *name); mesh::Packet *createSelfAdvert(const char *name, double lat, double lon); + + /* Build and send a self advert honoring the node's location policy, + * path-hash mode, and transport scope. Overridden by CompanionMesh + * (the only mesh with interactive advert UI triggers); the base default + * does nothing and returns false. Lets UI screens that only hold a + * BaseChatMesh* trigger adverts via the canonical scoped path instead + * of a bare sendFlood() that drops path_hash_mode and scope. */ + virtual bool sendSelfAdvert(bool flood) { (void)flood; return false; } int sendMessage(const ContactInfo &recipient, uint32_t timestamp, uint8_t attempt, const char *text, uint32_t &expected_ack, uint32_t &est_timeout); int sendCommandData(const ContactInfo &recipient, uint32_t timestamp, uint8_t attempt, const char *text, diff --git a/zephcore/helpers/ui-joystick/screens/system.cpp b/zephcore/helpers/ui-joystick/screens/system.cpp index bb419ae..349fccc 100644 --- a/zephcore/helpers/ui-joystick/screens/system.cpp +++ b/zephcore/helpers/ui-joystick/screens/system.cpp @@ -605,9 +605,10 @@ bool AdvertScreen::handleInput(char key) return true; } if (_selected == ADVERT_ITEM_SEND_FLOOD) { - mesh::Packet *pkt = mesh->createSelfAdvert(node_name); - if (pkt) { mesh->sendFlood(pkt); _task->showAlert("Advert flood sent", 1000); } - else { _task->showAlert("Advert failed", 1000); } + /* Canonical scoped path: honors prefs.path_hash_mode and the + * default transport scope (a bare sendFlood() would drop both). */ + if (mesh->sendSelfAdvert(true)) { _task->showAlert("Advert flood sent", 1000); } + else { _task->showAlert("Advert failed", 1000); } return true; } diff --git a/zephcore/helpers/ui/ui_mesh_actions.cpp b/zephcore/helpers/ui/ui_mesh_actions.cpp index d6bc326..5663ebc 100644 --- a/zephcore/helpers/ui/ui_mesh_actions.cpp +++ b/zephcore/helpers/ui/ui_mesh_actions.cpp @@ -215,24 +215,12 @@ extern "C" void mesh_handle_ui_actions(void) if (actions & (UI_ACTION_FLOOD_ADVERT | UI_ACTION_ZEROHOP_ADVERT)) { bool flood = !!(actions & UI_ACTION_FLOOD_ADVERT); - mesh::Packet *adv; - if (s_mesh->prefs.advert_loc_policy == 0) { - adv = s_mesh->createSelfAdvert( - s_mesh->prefs.node_name); - } else { - adv = s_mesh->createSelfAdvert( - s_mesh->prefs.node_name, - s_mesh->prefs.node_lat, - s_mesh->prefs.node_lon); - } - if (adv) { - if (flood) { - s_mesh->sendFlood(adv); - LOG_INF("flood advert sent (button)"); - } else { - s_mesh->sendZeroHop(adv); - LOG_INF("zero-hop advert sent (button)"); - } + /* Route through the shared canonical path so flood adverts honor + * prefs.path_hash_mode and the default transport scope, matching + * the mobile-app CMD_SEND_SELF_ADVERT behavior. */ + if (s_mesh->sendSelfAdvert(flood)) { + LOG_INF("%s advert sent (button)", + flood ? "flood" : "zero-hop"); } }