From d9df8307ca3291cdc51e88a799ec90b7bb8b8d15 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Mon, 1 Jun 2026 16:49:31 +1000 Subject: [PATCH] * first draft --- examples/companion_radio/DataStore.cpp | 6 +++++- examples/companion_radio/DataStore.h | 2 +- examples/companion_radio/MyMesh.cpp | 19 ++++++++++++++++++- examples/companion_radio/MyMesh.h | 4 ++-- src/helpers/BaseChatMesh.cpp | 21 +++++++++++---------- src/helpers/BaseChatMesh.h | 6 ++++-- 6 files changed, 41 insertions(+), 17 deletions(-) diff --git a/examples/companion_radio/DataStore.cpp b/examples/companion_radio/DataStore.cpp index c7988bb3..bf2f36c3 100644 --- a/examples/companion_radio/DataStore.cpp +++ b/examples/companion_radio/DataStore.cpp @@ -309,7 +309,7 @@ File file = openRead(_getContactsChannelsFS(), "/contacts3"); } } -void DataStore::saveContacts(DataStoreHost* host) { +void DataStore::saveContacts(DataStoreHost* host, bool (*filter)(const ContactInfo& c)) { File file = openWrite(_getContactsChannelsFS(), "/contacts3"); if (file) { uint32_t idx = 0; @@ -317,6 +317,10 @@ void DataStore::saveContacts(DataStoreHost* host) { uint8_t unused = 0; while (host->getContactForSave(idx, c)) { + if (filter && !filter(c)) { + idx++; // advance to next contact + continue; + } bool success = (file.write(c.id.pub_key, 32) == 32); success = success && (file.write((uint8_t *)&c.name, 32) == 32); success = success && (file.write(&c.type, 1) == 1); diff --git a/examples/companion_radio/DataStore.h b/examples/companion_radio/DataStore.h index 58b4d5d2..af5ee7af 100644 --- a/examples/companion_radio/DataStore.h +++ b/examples/companion_radio/DataStore.h @@ -36,7 +36,7 @@ public: void loadPrefs(NodePrefs& prefs, double& node_lat, double& node_lon); void savePrefs(const NodePrefs& prefs, double node_lat, double node_lon); void loadContacts(DataStoreHost* host); - void saveContacts(DataStoreHost* host); + void saveContacts(DataStoreHost* host, bool (*filter)(const ContactInfo& c) = NULL); void loadChannels(DataStoreHost* host); void saveChannels(DataStoreHost* host); void migrateToSecondaryFS(); diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index f1804219..d75d6776 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -1536,6 +1536,15 @@ void MyMesh::handleCmdFrame(size_t len) { } else if (cmd_frame[0] == CMD_SEND_ANON_REQ && len > 1 + PUB_KEY_SIZE) { uint8_t *pub_key = &cmd_frame[1]; ContactInfo *recipient = lookupContactByPubKey(pub_key, PUB_KEY_SIZE); + ContactInfo anon; + if (recipient == NULL) { // FIRMWARE_VER_CODE 13+, allow non-contact requests + memset(&anon, 0, sizeof(anon)); + memcpy(anon.id.pub_key, pub_key, PUB_KEY_SIZE); + anon.out_path_len = OUT_PATH_UNKNOWN; + anon.type = ADV_TYPE_NONE; // unknown + + if (addContact(anon)) recipient = &anon; + } uint8_t *data = &cmd_frame[1 + PUB_KEY_SIZE]; if (recipient) { uint32_t tag, est_timeout; @@ -1552,7 +1561,7 @@ void MyMesh::handleCmdFrame(size_t len) { _serial->writeFrame(out_frame, 10); } } else { - writeErrFrame(ERR_CODE_NOT_FOUND); // contact not found + writeErrFrame(ERR_CODE_TABLE_FULL); // contacts full } } else if (cmd_frame[0] == CMD_SEND_STATUS_REQ && len >= 1 + PUB_KEY_SIZE) { uint8_t *pub_key = &cmd_frame[1]; @@ -1983,6 +1992,14 @@ void MyMesh::handleCmdFrame(size_t len) { } } +static bool save_filter(const ContactInfo& c) { + return c.type != ADV_TYPE_NONE; // don't save the transient/anon entries +} + +void MyMesh::saveContacts() { + _store->saveContacts(this, save_filter); +} + void MyMesh::enterCLIRescue() { _cli_rescue = true; cli_command[0] = 0; diff --git a/examples/companion_radio/MyMesh.h b/examples/companion_radio/MyMesh.h index f189a2c5..bbb0d4cb 100644 --- a/examples/companion_radio/MyMesh.h +++ b/examples/companion_radio/MyMesh.h @@ -5,7 +5,7 @@ #include "AbstractUITask.h" /*------------ Frame Protocol --------------*/ -#define FIRMWARE_VER_CODE 12 +#define FIRMWARE_VER_CODE 13 #ifndef FIRMWARE_BUILD_DATE #define FIRMWARE_BUILD_DATE "19 Apr 2026" @@ -201,7 +201,7 @@ private: // helpers, short-cuts void saveChannels() { _store->saveChannels(this); } - void saveContacts() { _store->saveContacts(this); } + void saveContacts(); DataStore* _store; NodePrefs _prefs; diff --git a/src/helpers/BaseChatMesh.cpp b/src/helpers/BaseChatMesh.cpp index e2b116b4..5a720c83 100644 --- a/src/helpers/BaseChatMesh.cpp +++ b/src/helpers/BaseChatMesh.cpp @@ -76,7 +76,7 @@ ContactInfo* BaseChatMesh::allocateContactSlot() { uint32_t oldest_lastmod = 0xFFFFFFFF; for (int i = 0; i < num_contacts; i++) { bool is_favourite = (contacts[i].flags & 0x01) != 0; - if (!is_favourite && contacts[i].lastmod < oldest_lastmod) { + if (!is_favourite && contacts[i].lastmod < oldest_lastmod && contacts[i].type != ADV_TYPE_NONE) { oldest_lastmod = contacts[i].lastmod; oldest_idx = i; } @@ -164,16 +164,17 @@ void BaseChatMesh::onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id, from->sync_since = 0; from->shared_secret_valid = false; } + // update - putBlobByKey(id.pub_key, PUB_KEY_SIZE, temp_buf, plen); - StrHelper::strncpy(from->name, parser.getName(), sizeof(from->name)); - from->type = parser.getType(); - if (parser.hasLatLon()) { - from->gps_lat = parser.getIntLat(); - from->gps_lon = parser.getIntLon(); - } - from->last_advert_timestamp = timestamp; - from->lastmod = getRTCClock()->getCurrentTime(); + putBlobByKey(id.pub_key, PUB_KEY_SIZE, temp_buf, plen); + StrHelper::strncpy(from->name, parser.getName(), sizeof(from->name)); + from->type = parser.getType(); + if (parser.hasLatLon()) { + from->gps_lat = parser.getIntLat(); + from->gps_lon = parser.getIntLon(); + } + from->last_advert_timestamp = timestamp; + from->lastmod = getRTCClock()->getCurrentTime(); onDiscoveredContact(*from, is_new, packet->path_len, packet->path); // let UI know } diff --git a/src/helpers/BaseChatMesh.h b/src/helpers/BaseChatMesh.h index 88af3c7a..bd92d9d8 100644 --- a/src/helpers/BaseChatMesh.h +++ b/src/helpers/BaseChatMesh.h @@ -37,6 +37,8 @@ public: #define MAX_CONTACTS 32 #endif +#define MAX_ANON_CONTACTS 8 + #ifndef MAX_CONNECTIONS #define MAX_CONNECTIONS 16 #endif @@ -58,9 +60,9 @@ class BaseChatMesh : public mesh::Mesh { friend class ContactsIterator; - ContactInfo contacts[MAX_CONTACTS]; + ContactInfo contacts[MAX_CONTACTS+MAX_ANON_CONTACTS]; int num_contacts; - int sort_array[MAX_CONTACTS]; + int sort_array[MAX_CONTACTS+MAX_ANON_CONTACTS]; int matching_peer_indexes[MAX_SEARCH_RESULTS]; unsigned long txt_send_timeout; #ifdef MAX_GROUP_CHANNELS