Document direct retry CLI
This commit is contained in:
1 parent
765ec1447b
commit
cb5e2e7c3d
4 files changed
+255
-7
No files matched your search
@@ -950,6 +950,230 @@ region save
|
||||
- Enables flooding for all child regions automatically
|
||||
- Useful for global networks with specific regional rules
|
||||
|
||||
---
|
||||
### Direct Retry
|
||||
|
||||
Direct retry resends direct-routed packets when the downstream echo is not heard. It applies to direct messages and TRACE packets. It does not change ACK handling.
|
||||
|
||||
#### View or change direct retry state
|
||||
**Usage:**
|
||||
- `get direct.retry`
|
||||
- `set direct.retry <state>`
|
||||
|
||||
**Parameters:**
|
||||
- `state`: `on`|`off`
|
||||
|
||||
**Default:** `on`
|
||||
|
||||
**Examples:**
|
||||
```
|
||||
get direct.retry
|
||||
set direct.retry on
|
||||
set direct.retry off
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### View or apply a direct retry preset
|
||||
**Usage:**
|
||||
- `get retry.preset`
|
||||
- `set retry.preset <preset>`
|
||||
|
||||
**Parameters:**
|
||||
- `preset`: `infra`|`rooftop`|`mobile`
|
||||
|
||||
**Notes:**
|
||||
- `infra`: fewer, slower retries for stable fixed infrastructure.
|
||||
- `rooftop`: default long retry window for weak rooftop links.
|
||||
- `mobile`: long retry count with shorter spacing for moving or changing links.
|
||||
- Changing `direct.retry.count`, `direct.retry.base`, `direct.retry.step`, or `direct.retry.margin` makes the preset report as `custom`.
|
||||
|
||||
**Examples:**
|
||||
```
|
||||
get retry.preset
|
||||
set retry.preset infra
|
||||
set retry.preset rooftop
|
||||
set retry.preset mobile
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### View or change direct retry count
|
||||
**Usage:**
|
||||
- `get direct.retry.count`
|
||||
- `set direct.retry.count <count>`
|
||||
|
||||
**Parameters:**
|
||||
- `count`: Maximum retry attempts after the original send, from `1` to `15`.
|
||||
|
||||
**Default:** `15` with the `rooftop` preset
|
||||
|
||||
**Examples:**
|
||||
```
|
||||
get direct.retry.count
|
||||
set direct.retry.count 1
|
||||
set direct.retry.count 4
|
||||
set direct.retry.count 15
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### View or change direct retry base delay
|
||||
**Usage:**
|
||||
- `get direct.retry.base`
|
||||
- `set direct.retry.base <ms>`
|
||||
|
||||
**Parameters:**
|
||||
- `ms`: First retry wait in milliseconds, from `10` to `5000`.
|
||||
|
||||
**Default:** `175` with the `rooftop` preset
|
||||
|
||||
**Explanation:**
|
||||
- The first retry waits `base` milliseconds after the failed echo window.
|
||||
- Larger values reduce channel pressure and give slow repeaters more time.
|
||||
- Smaller values recover faster but create tighter retry bursts.
|
||||
|
||||
**Examples:**
|
||||
```
|
||||
get direct.retry.base
|
||||
set direct.retry.base 175
|
||||
set direct.retry.base 275
|
||||
set direct.retry.base 500
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### View or change direct retry step delay
|
||||
**Usage:**
|
||||
- `get direct.retry.step`
|
||||
- `set direct.retry.step <ms>`
|
||||
|
||||
**Parameters:**
|
||||
- `ms`: Extra milliseconds added for each subsequent retry, from `0` to `5000`.
|
||||
|
||||
**Default:** `100` with the `rooftop` preset
|
||||
|
||||
**Explanation:**
|
||||
- Retry delay is `base + attempt_index * step`.
|
||||
- With `base=175` and `step=100`, retries wait about `175`, `275`, `375`, `475` ms, and so on.
|
||||
- `step=0` keeps every retry at the same delay.
|
||||
- Larger steps spread retries over time and are safer on busy channels.
|
||||
|
||||
**Examples:**
|
||||
```
|
||||
get direct.retry.step
|
||||
set direct.retry.step 0
|
||||
set direct.retry.step 50
|
||||
set direct.retry.step 100
|
||||
set direct.retry.step 250
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### View or change direct retry SNR margin
|
||||
**Usage:**
|
||||
- `get direct.retry.margin`
|
||||
- `set direct.retry.margin <snr_db>`
|
||||
|
||||
**Parameters:**
|
||||
- `snr_db`: Extra SNR margin above the SF receive floor, from `0` to `40`.
|
||||
|
||||
**Default:** `5.00` with the `rooftop` preset
|
||||
|
||||
**Notes:**
|
||||
- Unknown repeaters are still retried.
|
||||
- Known repeaters below the receive floor plus this margin are skipped.
|
||||
- Failed attempts lower the recent repeater SNR estimate by `0.25 dB`.
|
||||
|
||||
**Examples:**
|
||||
```
|
||||
get direct.retry.margin
|
||||
set direct.retry.margin 0
|
||||
set direct.retry.margin 2.5
|
||||
set direct.retry.margin 5
|
||||
set direct.retry.margin 10
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### View or change adaptive direct retry coding rate
|
||||
**Usage:**
|
||||
- `get direct.retry.cr`
|
||||
- `set direct.retry.cr off`
|
||||
- `set direct.retry.cr <cr4_min>,<cr5_min>,<cr7_min>,<cr8_max>`
|
||||
|
||||
**Parameters:**
|
||||
- `cr4_min`: Minimum SNR in dB to retry at CR4.
|
||||
- `cr5_min`: Minimum SNR in dB to retry at CR5.
|
||||
- `cr7_min`: Minimum SNR in dB to retry at CR7.
|
||||
- `cr8_max`: Maximum SNR in dB that forces CR8.
|
||||
|
||||
**Default:** `10.00,7.50,2.50,2.50`
|
||||
|
||||
**Explanation:**
|
||||
- Higher SNR uses faster coding rates.
|
||||
- Lower SNR uses more robust coding rates.
|
||||
- CR6 is intentionally skipped.
|
||||
- `off` disables per-packet retry CR overrides and uses the current radio CR.
|
||||
- Unknown repeaters start at `+2.00 dB` for adaptive CR selection.
|
||||
- A failed unknown repeater is seeded at `+1.75 dB`.
|
||||
- Each later failure lowers the SNR estimate by `0.25 dB`.
|
||||
|
||||
**Examples:**
|
||||
```
|
||||
get direct.retry.cr
|
||||
set direct.retry.cr off
|
||||
set direct.retry.cr 10.0,7.5,2.5,2.5
|
||||
set direct.retry.cr 12.0,8.0,4.0,1.0
|
||||
set direct.retry.cr 8.0,5.0,1.5,0
|
||||
set direct.retry.cr 6.0,3.0,0,-2.0
|
||||
set direct.retry.cr 20.0,12.0,6.0,2.0
|
||||
set direct.retry.cr 4.0,2.0,0,-4.0
|
||||
```
|
||||
|
||||
**Example profiles:**
|
||||
- Conservative weak-link profile:
|
||||
```
|
||||
set direct.retry.cr 12.0,8.0,4.0,1.0
|
||||
```
|
||||
- Balanced rooftop profile:
|
||||
```
|
||||
set direct.retry.cr 10.0,7.5,2.5,2.5
|
||||
```
|
||||
- Faster strong-link profile:
|
||||
```
|
||||
set direct.retry.cr 6.0,3.0,0,-2.0
|
||||
```
|
||||
- Very cautious noisy-link profile:
|
||||
```
|
||||
set direct.retry.cr 20.0,12.0,6.0,2.0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### View, seed, or clear the recent repeater table
|
||||
**Usage:**
|
||||
- `get recent.repeater`
|
||||
- `get recent.repeater <page>`
|
||||
- `get recent.repeater page <page>`
|
||||
- `set recent.repeater <prefix> <snr_db>`
|
||||
- `clear recent.repeater`
|
||||
|
||||
**Parameters:**
|
||||
- `prefix`: Repeater path-hash prefix as hex.
|
||||
- `snr_db`: SNR in dB.
|
||||
- `page`: 1-based result page.
|
||||
|
||||
**Examples:**
|
||||
```
|
||||
get recent.repeater
|
||||
get recent.repeater 2
|
||||
get recent.repeater page 3
|
||||
set recent.repeater A1B2C3 8.5
|
||||
set recent.repeater 71CE82 -3.25
|
||||
clear recent.repeater
|
||||
```
|
||||
|
||||
---
|
||||
### GPS (When GPS support is compiled in)
|
||||
|
||||
|
||||
@@ -575,7 +575,8 @@ uint8_t MyMesh::getDirectRetryCodingRateForSNR(int8_t snr_x4) const {
|
||||
if (snr_x4 >= _prefs.direct_retry_cr4_snr_x4) return 4;
|
||||
if (snr_x4 >= _prefs.direct_retry_cr5_snr_x4) return 5;
|
||||
if (snr_x4 >= _prefs.direct_retry_cr7_snr_x4) return 7;
|
||||
return 8;
|
||||
if (snr_x4 <= _prefs.direct_retry_cr8_snr_x4) return 8;
|
||||
return 7;
|
||||
}
|
||||
|
||||
uint8_t MyMesh::getDirectRetryPreset() const {
|
||||
@@ -592,6 +593,9 @@ uint32_t MyMesh::getDirectRetryAttemptStepMillis() const {
|
||||
|
||||
bool MyMesh::allowDirectRetry(const mesh::Packet* packet, const uint8_t* next_hop_hash, uint8_t next_hop_hash_len) const {
|
||||
(void)packet;
|
||||
if (!_prefs.direct_retry_enabled) {
|
||||
return false;
|
||||
}
|
||||
if (next_hop_hash == NULL || next_hop_hash_len == 0) {
|
||||
return true;
|
||||
}
|
||||
@@ -1108,6 +1112,7 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
|
||||
_prefs.direct_retry_cr5_snr_x4 = DIRECT_RETRY_CR5_MIN_SNR_X4_DEFAULT;
|
||||
_prefs.direct_retry_cr7_snr_x4 = DIRECT_RETRY_CR7_MIN_SNR_X4_DEFAULT;
|
||||
_prefs.direct_retry_cr8_snr_x4 = DIRECT_RETRY_CR8_MAX_SNR_X4_DEFAULT;
|
||||
_prefs.direct_retry_enabled = 1;
|
||||
_prefs.direct_retry_cr_enabled = 1;
|
||||
_prefs.direct_retry_prefs_magic[0] = DIRECT_RETRY_PREFS_MAGIC_0;
|
||||
_prefs.direct_retry_prefs_magic[1] = DIRECT_RETRY_PREFS_MAGIC_1;
|
||||
|
||||
@@ -101,6 +101,7 @@ static void setDefaultDirectRetryPrefs(NodePrefs* prefs) {
|
||||
prefs->direct_retry_cr5_snr_x4 = DIRECT_RETRY_CR5_MIN_SNR_X4_DEFAULT;
|
||||
prefs->direct_retry_cr7_snr_x4 = DIRECT_RETRY_CR7_MIN_SNR_X4_DEFAULT;
|
||||
prefs->direct_retry_cr8_snr_x4 = DIRECT_RETRY_CR8_MAX_SNR_X4_DEFAULT;
|
||||
prefs->direct_retry_enabled = 1;
|
||||
markDirectRetryPrefsValid(prefs);
|
||||
}
|
||||
|
||||
@@ -209,9 +210,10 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
||||
file.read((uint8_t *)&_prefs->direct_retry_cr5_snr_x4, sizeof(_prefs->direct_retry_cr5_snr_x4)); // 304
|
||||
file.read((uint8_t *)&_prefs->direct_retry_cr7_snr_x4, sizeof(_prefs->direct_retry_cr7_snr_x4)); // 305
|
||||
file.read((uint8_t *)&_prefs->direct_retry_cr8_snr_x4, sizeof(_prefs->direct_retry_cr8_snr_x4)); // 306
|
||||
file.read((uint8_t *)&_prefs->direct_retry_cr_enabled, sizeof(_prefs->direct_retry_cr_enabled)); // 307
|
||||
file.read((uint8_t *)&_prefs->direct_retry_prefs_magic, sizeof(_prefs->direct_retry_prefs_magic)); // 308
|
||||
// next: 310
|
||||
file.read((uint8_t *)&_prefs->direct_retry_enabled, sizeof(_prefs->direct_retry_enabled)); // 307
|
||||
file.read((uint8_t *)&_prefs->direct_retry_cr_enabled, sizeof(_prefs->direct_retry_cr_enabled)); // 308
|
||||
file.read((uint8_t *)&_prefs->direct_retry_prefs_magic, sizeof(_prefs->direct_retry_prefs_magic)); // 309
|
||||
// next: 311
|
||||
|
||||
// sanitise bad pref values
|
||||
_prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f);
|
||||
@@ -253,6 +255,7 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
||||
_prefs->direct_retry_base_ms = constrain(_prefs->direct_retry_base_ms, 10, 5000);
|
||||
_prefs->direct_retry_step_ms = constrain(_prefs->direct_retry_step_ms, 0, 5000);
|
||||
_prefs->direct_retry_snr_margin_x4 = constrain(_prefs->direct_retry_snr_margin_x4, 0, 160);
|
||||
_prefs->direct_retry_enabled = constrain(_prefs->direct_retry_enabled, 0, 1);
|
||||
_prefs->direct_retry_cr_enabled = constrain(_prefs->direct_retry_cr_enabled, 0, 1);
|
||||
|
||||
file.close();
|
||||
@@ -329,9 +332,10 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) {
|
||||
file.write((uint8_t *)&_prefs->direct_retry_cr5_snr_x4, sizeof(_prefs->direct_retry_cr5_snr_x4)); // 304
|
||||
file.write((uint8_t *)&_prefs->direct_retry_cr7_snr_x4, sizeof(_prefs->direct_retry_cr7_snr_x4)); // 305
|
||||
file.write((uint8_t *)&_prefs->direct_retry_cr8_snr_x4, sizeof(_prefs->direct_retry_cr8_snr_x4)); // 306
|
||||
file.write((uint8_t *)&_prefs->direct_retry_cr_enabled, sizeof(_prefs->direct_retry_cr_enabled)); // 307
|
||||
file.write((uint8_t *)&_prefs->direct_retry_prefs_magic, sizeof(_prefs->direct_retry_prefs_magic)); // 308
|
||||
// next: 310
|
||||
file.write((uint8_t *)&_prefs->direct_retry_enabled, sizeof(_prefs->direct_retry_enabled)); // 307
|
||||
file.write((uint8_t *)&_prefs->direct_retry_cr_enabled, sizeof(_prefs->direct_retry_cr_enabled)); // 308
|
||||
file.write((uint8_t *)&_prefs->direct_retry_prefs_magic, sizeof(_prefs->direct_retry_prefs_magic)); // 309
|
||||
// next: 311
|
||||
|
||||
file.close();
|
||||
}
|
||||
@@ -833,6 +837,18 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
} else {
|
||||
strcpy(reply, "Error, must be infra, rooftop, or mobile");
|
||||
}
|
||||
} else if (memcmp(config, "direct.retry ", 13) == 0) {
|
||||
if (memcmp(&config[13], "on", 2) == 0) {
|
||||
_prefs->direct_retry_enabled = 1;
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else if (memcmp(&config[13], "off", 3) == 0) {
|
||||
_prefs->direct_retry_enabled = 0;
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, must be on or off");
|
||||
}
|
||||
} else if (memcmp(config, "direct.retry.margin ", 20) == 0) {
|
||||
if (!looksNumeric(&config[20])) {
|
||||
strcpy(reply, "Error, must be 0-40 dB");
|
||||
@@ -1106,6 +1122,8 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
sprintf(reply, "> %s", StrHelper::ftoa(_prefs->direct_tx_delay_factor));
|
||||
} else if (memcmp(config, "retry.preset", 12) == 0) {
|
||||
sprintf(reply, "> %s", retryPresetName(_prefs->retry_preset));
|
||||
} else if (memcmp(config, "direct.retry", 12) == 0 && (config[12] == 0 || config[12] == ' ')) {
|
||||
sprintf(reply, "> %s", _prefs->direct_retry_enabled ? "on" : "off");
|
||||
} else if (memcmp(config, "direct.retry.margin", 19) == 0) {
|
||||
char margin[12];
|
||||
formatSnrDbX4(margin, sizeof(margin), _prefs->direct_retry_snr_margin_x4);
|
||||
|
||||
@@ -102,6 +102,7 @@ struct NodePrefs { // persisted to file
|
||||
int8_t direct_retry_cr5_snr_x4;
|
||||
int8_t direct_retry_cr7_snr_x4;
|
||||
int8_t direct_retry_cr8_snr_x4;
|
||||
uint8_t direct_retry_enabled;
|
||||
uint8_t direct_retry_cr_enabled;
|
||||
uint8_t direct_retry_prefs_magic[2];
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user