From 5881b04a31b9d75ac565da262a16eca8e25a3519 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Wed, 16 Jul 2025 19:25:28 +1000 Subject: [PATCH] * companion: optional double ACKs, new prefs.multi_acks --- examples/companion_radio/DataStore.cpp | 10 ++++++---- examples/companion_radio/MyMesh.cpp | 9 ++++++++- examples/companion_radio/MyMesh.h | 1 + examples/companion_radio/NodePrefs.h | 2 +- src/helpers/BaseChatMesh.cpp | 10 +++++++--- 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/examples/companion_radio/DataStore.cpp b/examples/companion_radio/DataStore.cpp index 5c19d7a1..b5d70edc 100644 --- a/examples/companion_radio/DataStore.cpp +++ b/examples/companion_radio/DataStore.cpp @@ -154,7 +154,7 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no file.read((uint8_t *)&_prefs.freq, sizeof(_prefs.freq)); // 56 file.read((uint8_t *)&_prefs.sf, sizeof(_prefs.sf)); // 60 file.read((uint8_t *)&_prefs.cr, sizeof(_prefs.cr)); // 61 - file.read((uint8_t *)&_prefs.reserved1, sizeof(_prefs.reserved1)); // 62 + file.read(pad, 1); // 62 file.read((uint8_t *)&_prefs.manual_add_contacts, sizeof(_prefs.manual_add_contacts)); // 63 file.read((uint8_t *)&_prefs.bw, sizeof(_prefs.bw)); // 64 file.read((uint8_t *)&_prefs.tx_power_dbm, sizeof(_prefs.tx_power_dbm)); // 68 @@ -163,7 +163,8 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no file.read((uint8_t *)&_prefs.telemetry_mode_env, sizeof(_prefs.telemetry_mode_env)); // 71 file.read((uint8_t *)&_prefs.rx_delay_base, sizeof(_prefs.rx_delay_base)); // 72 file.read((uint8_t *)&_prefs.advert_loc_policy, sizeof(_prefs.advert_loc_policy)); // 76 - file.read(pad, 3); // 77 + file.read((uint8_t *)&_prefs.multi_acks, sizeof(_prefs.multi_acks)); // 77 + file.read(pad, 2); // 78 file.read((uint8_t *)&_prefs.ble_pin, sizeof(_prefs.ble_pin)); // 80 file.close(); @@ -184,7 +185,7 @@ void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_ file.write((uint8_t *)&_prefs.freq, sizeof(_prefs.freq)); // 56 file.write((uint8_t *)&_prefs.sf, sizeof(_prefs.sf)); // 60 file.write((uint8_t *)&_prefs.cr, sizeof(_prefs.cr)); // 61 - file.write((uint8_t *)&_prefs.reserved1, sizeof(_prefs.reserved1)); // 62 + file.write(pad, 1); // 62 file.write((uint8_t *)&_prefs.manual_add_contacts, sizeof(_prefs.manual_add_contacts)); // 63 file.write((uint8_t *)&_prefs.bw, sizeof(_prefs.bw)); // 64 file.write((uint8_t *)&_prefs.tx_power_dbm, sizeof(_prefs.tx_power_dbm)); // 68 @@ -193,7 +194,8 @@ void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_ file.write((uint8_t *)&_prefs.telemetry_mode_env, sizeof(_prefs.telemetry_mode_env)); // 71 file.write((uint8_t *)&_prefs.rx_delay_base, sizeof(_prefs.rx_delay_base)); // 72 file.write((uint8_t *)&_prefs.advert_loc_policy, sizeof(_prefs.advert_loc_policy)); // 76 - file.write(pad, 3); // 77 + file.write((uint8_t *)&_prefs.multi_acks, sizeof(_prefs.multi_acks)); // 77 + file.write(pad, 2); // 78 file.write((uint8_t *)&_prefs.ble_pin, sizeof(_prefs.ble_pin)); // 80 file.close(); diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index 9331a50c..939c93de 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -210,6 +210,10 @@ int MyMesh::calcRxDelay(float score, uint32_t air_time) const { return (int)((pow(_prefs.rx_delay_base, 0.85f - score) - 1.0) * air_time); } +uint8_t MyMesh::getExtraAckTransmitCount() const { + return _prefs.multi_acks; +} + void MyMesh::logRxRaw(float snr, float rssi, const uint8_t raw[], int len) { if (_serial->isConnected() && len + 3 <= MAX_FRAME_SIZE) { int i = 0; @@ -719,7 +723,7 @@ void MyMesh::handleCmdFrame(size_t len) { i += 4; memcpy(&out_frame[i], &lon, 4); i += 4; - out_frame[i++] = 0; // reserved + out_frame[i++] = _prefs.multi_acks; // new v7+ out_frame[i++] = _prefs.advert_loc_policy; out_frame[i++] = (_prefs.telemetry_mode_env << 4) | (_prefs.telemetry_mode_loc << 2) | (_prefs.telemetry_mode_base); // v5+ @@ -1050,6 +1054,9 @@ void MyMesh::handleCmdFrame(size_t len) { if (len >= 4) { _prefs.advert_loc_policy = cmd_frame[3]; + if (len >= 5) { + _prefs.multi_acks = cmd_frame[4]; + } } } savePrefs(); diff --git a/examples/companion_radio/MyMesh.h b/examples/companion_radio/MyMesh.h index 81bf261e..cd4a72dc 100644 --- a/examples/companion_radio/MyMesh.h +++ b/examples/companion_radio/MyMesh.h @@ -97,6 +97,7 @@ protected: float getAirtimeBudgetFactor() const override; int getInterferenceThreshold() const override; int calcRxDelay(float score, uint32_t air_time) const override; + uint8_t getExtraAckTransmitCount() const override; void logRxRaw(float snr, float rssi, const uint8_t raw[], int len) override; bool isAutoAddEnabled() const override; diff --git a/examples/companion_radio/NodePrefs.h b/examples/companion_radio/NodePrefs.h index bf4739e4..bfde7218 100644 --- a/examples/companion_radio/NodePrefs.h +++ b/examples/companion_radio/NodePrefs.h @@ -14,7 +14,7 @@ struct NodePrefs { // persisted to file float freq; uint8_t sf; uint8_t cr; - uint8_t reserved1; + uint8_t multi_acks; uint8_t manual_add_contacts; float bw; uint8_t tx_power_dbm; diff --git a/src/helpers/BaseChatMesh.cpp b/src/helpers/BaseChatMesh.cpp index c5e2915c..476e6e8f 100644 --- a/src/helpers/BaseChatMesh.cpp +++ b/src/helpers/BaseChatMesh.cpp @@ -36,11 +36,15 @@ void BaseChatMesh::sendAckTo(const ContactInfo& dest, uint32_t ack_hash) { mesh::Packet* ack = createAck(ack_hash); if (ack) sendFlood(ack, TXT_ACK_DELAY); } else { - mesh::Packet* a1 = createMultiAck(ack_hash, 1); - if (a1) sendDirect(a1, dest.out_path, dest.out_path_len, TXT_ACK_DELAY); + uint32_t d = TXT_ACK_DELAY; + if (getExtraAckTransmitCount() > 0) { + mesh::Packet* a1 = createMultiAck(ack_hash, 1); + if (a1) sendDirect(a1, dest.out_path, dest.out_path_len, d); + d += 300; + } mesh::Packet* a2 = createAck(ack_hash); - if (a2) sendDirect(a2, dest.out_path, dest.out_path_len, TXT_ACK_DELAY + 300); + if (a2) sendDirect(a2, dest.out_path, dest.out_path_len, d); } }