mirror of
https://github.com/agessaman/MeshCore.git
synced 2026-08-28 20:38:18 +00:00
Tune repeater flood controls and retries
This commit is contained in:
+39
-14
@@ -531,7 +531,7 @@ send text.flood checking ridge link
|
||||
**Parameters:**
|
||||
- `state`: `on`|`off`
|
||||
|
||||
**Default:** `on`
|
||||
**Default:** `flood.channel.data on`; `flood.channel.data.hops h=all`
|
||||
|
||||
---
|
||||
|
||||
@@ -771,19 +771,28 @@ send text.flood checking ridge link
|
||||
#### Forward flood group data packets on repeaters
|
||||
**Usage:**
|
||||
- `get flood.channel.data`
|
||||
- `get flood.channel.data.hops`
|
||||
- `set flood.channel.data <on|off>`
|
||||
- `set flood.channel.data.hops <all|1-7>`
|
||||
|
||||
**Parameters:**
|
||||
- `on`: Retransmit received flood `GRP_DATA` channel packets.
|
||||
- `off`: Do not retransmit received flood `GRP_DATA` channel packets.
|
||||
- `all`: When `flood.channel.data` is `off`, block `GRP_DATA` at any received flood hop count.
|
||||
- `1-7`: When `flood.channel.data` is `off`, repeat `GRP_DATA` at this hop count or lower and block longer paths.
|
||||
|
||||
**Default:** `on`
|
||||
**Default:** `flood.channel.data on`; `flood.channel.data.hops h=all`
|
||||
|
||||
**Forwarding behavior:** Repeater firmware only. The repeater still receives and
|
||||
logs the packet when logging is enabled; this only blocks retransmission.
|
||||
This is checked before `flood.channel.block` and applies to flood `GRP_DATA`
|
||||
packets regardless of channel key, subject to `flood.channel.block.hops`.
|
||||
Flood group text (`GRP_TXT`) is unaffected by this setting.
|
||||
packets regardless of channel key. Flood group text (`GRP_TXT`) is unaffected by
|
||||
this setting.
|
||||
|
||||
`flood.channel.data.hops` is separate from `flood.channel.block.hops`.
|
||||
`flood.channel.block.hops` does not restrict unkeyed `GRP_DATA` packets. With
|
||||
the default `flood.channel.data on`, `GRP_DATA` repeats normally even when
|
||||
`flood.channel.block.hops` is set for keyed channel blocks.
|
||||
|
||||
`get flood.channel.data` includes the active hop gate as `h=all` or `h>N`.
|
||||
|
||||
@@ -818,22 +827,29 @@ row with the same derived channel prefix or name, otherwise it uses the next
|
||||
empty slot. If all 15 slots are full, the command fails. With `.n`, the command
|
||||
writes that slot.
|
||||
|
||||
**Default row:** Repeater firmware seeds a new block list with
|
||||
`#wardriving h=4` in slot 1. This is a normal row, so it can be changed with
|
||||
`set flood.channel.block #wardriving h=<all|1-7|default>` or removed with
|
||||
`del flood.channel.block #wardriving`. Once the block list has been saved, the
|
||||
firmware uses the saved list and does not recreate the default after deletion.
|
||||
|
||||
**Forwarding behavior:** Repeater firmware only. This only affects received
|
||||
flood `GRP_TXT` and `GRP_DATA` channel packets. The repeater still receives and
|
||||
logs the packet, but it does not retransmit it when a configured block entry can
|
||||
validate/decode it. If `flood.channel.data` is `off`, all flood `GRP_DATA`
|
||||
packets over the hop gate are blocked before this per-channel check runs.
|
||||
validate/decode it. If `flood.channel.data` is `off`, `GRP_DATA` packets are
|
||||
checked against the separate `flood.channel.data.hops` gate before this
|
||||
per-channel check runs.
|
||||
|
||||
**Hop gate:** `flood.channel.block.hops` defaults to `all`, which preserves the
|
||||
original behavior. When set to `N` from `1` to `7`, both `flood.channel.data off`
|
||||
and block rows that inherit the global setting only block packets whose received
|
||||
flood path hash count is greater than `N`; packets at `N` hops or lower can
|
||||
still repeat. For example, `set flood.channel.block.hops 1` repeats zero-hop and
|
||||
one-hop matches but blocks two-hop and longer matches.
|
||||
original behavior. When set to `N` from `1` to `7`, block rows that inherit the
|
||||
global setting only block packets whose received flood path hash count is
|
||||
greater than `N`; packets at `N` hops or lower can still repeat. For example,
|
||||
`set flood.channel.block.hops 1` repeats zero-hop and one-hop matches but blocks
|
||||
two-hop and longer matches.
|
||||
|
||||
Each block row can override the global hop gate with `h=<all|1-7|default>`.
|
||||
For example, `set flood.channel.block #wardriving h=3` blocks `#wardriving`
|
||||
matches above three hops, while `set flood.channel.block #bot h=7` blocks
|
||||
For example, the seeded `#wardriving h=4` row blocks `#wardriving` matches
|
||||
above four hops, while `set flood.channel.block #bot h=7` blocks
|
||||
`#bot` matches above seven hops. Use `h=default` to make the row inherit the
|
||||
global setting again.
|
||||
|
||||
@@ -856,7 +872,7 @@ MAC/decrypt.
|
||||
set flood.channel.block #test
|
||||
set flood.channel.block.2 9cd8fcf22a47333b591d96a2b848b73f #test
|
||||
set flood.channel.block.hops 3
|
||||
set flood.channel.block #wardriving h=3
|
||||
set flood.channel.block #wardriving h=4
|
||||
set flood.channel.block #bot h=7
|
||||
get flood.channel.block
|
||||
get flood.channel.block.hops
|
||||
@@ -1383,6 +1399,9 @@ set flood.retry.bucket 2 none
|
||||
|
||||
**Default:** `15` with the `rooftop` preset
|
||||
|
||||
**Note:** Direct-routed type 2 text packets always use 21 retry attempts,
|
||||
regardless of this setting or the short-path cap.
|
||||
|
||||
**Examples:**
|
||||
```
|
||||
get direct.retry.count
|
||||
@@ -1405,6 +1424,9 @@ set direct.retry.count 15
|
||||
|
||||
**Explanation:**
|
||||
- The first retry waits `base` milliseconds after the failed echo window.
|
||||
- The failed echo window includes a packet-length add-on. TRACE and
|
||||
ANON_REQ/type 7 packets keep the existing 4x line-time add-on. TXT_MSG/type 2
|
||||
packets use 7x. Other direct retry packets use 6x.
|
||||
- For non-TRACE direct paths shorter than 6 remaining hops, the effective wait is scaled by `hops / 6`.
|
||||
- Non-TRACE direct paths with 6 or more remaining hops use the configured value unchanged.
|
||||
- TRACE retries shorter than 16 remaining hops use `hops / 16`; 16 or more remaining hops use the configured value unchanged.
|
||||
@@ -1433,6 +1455,9 @@ set direct.retry.base 500
|
||||
|
||||
**Explanation:**
|
||||
- Retry delay is `base + attempt_index * step`.
|
||||
- This is added after the failed echo window. TRACE and ANON_REQ/type 7 packets
|
||||
keep the existing 4x packet-length add-on. TXT_MSG/type 2 packets use 7x.
|
||||
Other direct retry packets use 6x.
|
||||
- For non-TRACE direct paths shorter than 6 remaining hops, that computed delay is scaled by `hops / 6`.
|
||||
- Non-TRACE direct paths with 6 or more remaining hops use the computed delay unchanged.
|
||||
- TRACE retries shorter than 16 remaining hops use `hops / 16`; 16 or more remaining hops use the computed delay unchanged.
|
||||
|
||||
@@ -77,9 +77,10 @@ set flood.retry.ignore none
|
||||
| `battery.alert.low` | Warning threshold percentage. Must be greater than `battery.alert.critical`. | `get battery.alert.low`, `set battery.alert.low <1-100>` | `set battery.alert.low 20` |
|
||||
| `battery.alert.critical` | Critical threshold percentage. Critical warnings repeat more often. | `get battery.alert.critical`, `set battery.alert.critical <0-99>` | `set battery.alert.critical 10` |
|
||||
| `recent.repeater` | Shows, seeds, or clears the recent repeater prefix/SNR table used by direct retry and bridge freshness checks. | `get recent.repeater`, `get recent.repeater <page>`, `set recent.repeater <prefix> <snr_db>`, `clear recent.repeater` | `set recent.repeater A1B2C3 -8.5` |
|
||||
| `flood.channel.data` | Turns forwarding of flood `GRP_DATA` channel packets on or off, subject to the channel block hop gate. | `get flood.channel.data`, `set flood.channel.data on/off` | `set flood.channel.data off` |
|
||||
| `flood.channel.block` | Blocks selected flood `GRP_TXT`/`GRP_DATA` channels when the key validates the packet. Add `h=<all|1-7|default>` for a per-channel hop override. | `get flood.channel.block`, `set flood.channel.block[.n] <key|#channel> [name] [h=...]`, `del flood.channel.block[.n]` | `set flood.channel.block #wardriving h=3` |
|
||||
| `flood.channel.block.hops` | Limits channel/data forwarding to short flood paths. `all` blocks matching packets at any hop count; `1`-`7` repeats packets at that hop count or lower and blocks longer matches. | `get flood.channel.block.hops`, `set flood.channel.block.hops <all|1-7>` | `set flood.channel.block.hops 3` |
|
||||
| `flood.channel.data` | Turns forwarding of flood `GRP_DATA` channel packets on or off. With the default `on`, `GRP_DATA` repeats normally even when `flood.channel.block.hops` is set. | `get flood.channel.data`, `set flood.channel.data on/off` | `set flood.channel.data off` |
|
||||
| `flood.channel.data.hops` | Separate hop gate used only when `flood.channel.data` is `off`; `all` blocks `GRP_DATA` at any hop count, `1`-`7` repeats at that hop count or lower and blocks longer paths. | `get flood.channel.data.hops`, `set flood.channel.data.hops <all|1-7>` | `set flood.channel.data.hops 7` |
|
||||
| `flood.channel.block` | Blocks selected flood `GRP_TXT`/`GRP_DATA` channels when the key validates the packet. New repeater block lists start with editable/deletable `#wardriving h=4`. Add `h=<all|1-7|default>` for a per-channel hop override. | `get flood.channel.block`, `set flood.channel.block[.n] <key|#channel> [name] [h=...]`, `del flood.channel.block[.n]` | `set flood.channel.block #wardriving h=4` |
|
||||
| `flood.channel.block.hops` | Limits keyed channel-block matches to short flood paths. `all` blocks matching packets at any hop count; `1`-`7` repeats packets at that hop count or lower and blocks longer matches. This does not restrict unkeyed `GRP_DATA`; use `flood.channel.data.hops` for that. | `get flood.channel.block.hops`, `set flood.channel.block.hops <all|1-7>` | `set flood.channel.block.hops 3` |
|
||||
| `outpath` | Overrides the primary direct route used for replies to the current remote client. | `get outpath`, `set outpath <hops>`, `set outpath direct`, `set outpath clear`, `set outpath flood` | `set outpath A1B2C3,D4E5F6` |
|
||||
| `altpath` | Adds a secondary direct route for repeater replies to the current remote client. | `get altpath`, `set altpath <hops>`, `set altpath direct`, `set altpath clear`, `set altpath flood` | `set altpath 71CE82,BA09F0` |
|
||||
|
||||
@@ -189,8 +190,8 @@ Direct retry applies to direct-routed packets. A queued resend is canceled when
|
||||
| `retry.preset` | Applies shared direct and flood retry defaults. Values: `infra`, `rooftop`, `mobile` or `0`, `1`, `2`. | `get retry.preset`, `set retry.preset <value>` | `set retry.preset rooftop` |
|
||||
| `direct.retry.heard` | Uses the recent repeater table as the direct retry eligibility gate. | `get direct.retry.heard`, `set direct.retry.heard on/off` | `set direct.retry.heard on` |
|
||||
| `direct.retry.margin` | SNR margin in dB above the SF-specific receive floor. | `get direct.retry.margin`, `set direct.retry.margin <0-40>` | `set direct.retry.margin 5` |
|
||||
| `direct.retry.count` | Maximum direct retry attempts after initial TX. | `get direct.retry.count`, `set direct.retry.count <1-15>` | `set direct.retry.count 15` |
|
||||
| `direct.retry.base` | Base wait in milliseconds before retry; non-TRACE paths under 6 remaining hops scale by `hops / 6`, TRACE paths under 16 by `hops / 16`. | `get direct.retry.base`, `set direct.retry.base <10-5000>` | `set direct.retry.base 175` |
|
||||
| `direct.retry.count` | Maximum direct retry attempts after initial TX. Direct-routed type 2 text packets always use 21 attempts regardless of this setting or the short-path cap. | `get direct.retry.count`, `set direct.retry.count <1-15>` | `set direct.retry.count 15` |
|
||||
| `direct.retry.base` | Base wait in milliseconds before retry; packet-length add-on is 4x for TRACE and ANON_REQ/type 7, 7x for TXT_MSG/type 2, and 6x for other direct retry packets. Non-TRACE paths under 6 remaining hops scale by `hops / 6`, TRACE paths under 16 by `hops / 16`. | `get direct.retry.base`, `set direct.retry.base <10-5000>` | `set direct.retry.base 175` |
|
||||
| `direct.retry.step` | Milliseconds added per retry attempt before the same short-path scaling. | `get direct.retry.step`, `set direct.retry.step <0-5000>` | `set direct.retry.step 100` |
|
||||
| `direct.retry.cr` | Adaptive coding-rate thresholds for repeater direct retry packets. Repeaters use `CR4`, `CR5`, `CR7`, or `CR8`, then escalate by attempt: CR4, CR5, CR7, CR7, then CR8 from a CR4 start; CR5, CR7, CR7, then CR8 from a CR5 start. Non-repeaters start at the current radio CR and follow the same escalation pattern, clamped at CR8. | `get direct.retry.cr`, `set direct.retry.cr <cr4_min>,<cr5_min>,<cr7_min>,<cr8_max>`, `set direct.retry.cr off` | `set direct.retry.cr 10.0,7.5,2.5,0` |
|
||||
|
||||
|
||||
@@ -83,6 +83,10 @@
|
||||
#define LAZY_CONTACTS_WRITE_DELAY 5000
|
||||
|
||||
#define FLOOD_CHANNEL_BLOCK_FILE "/flood_ch_block"
|
||||
#define DEFAULT_FLOOD_CHANNEL_BLOCK_NAME "#wardriving"
|
||||
#ifndef DEFAULT_FLOOD_CHANNEL_BLOCK_HOPS
|
||||
#define DEFAULT_FLOOD_CHANNEL_BLOCK_HOPS 4
|
||||
#endif
|
||||
|
||||
#ifndef REPEATERS_CHANNEL_KEY_HEX
|
||||
#define REPEATERS_CHANNEL_KEY_HEX "89db441e2814dccf0dbd2e8cc5f501a3"
|
||||
@@ -675,6 +679,14 @@ bool MyMesh::floodChannelBlockHopApplies(const mesh::Packet* packet, uint8_t max
|
||||
return max_hops == FLOOD_CHANNEL_BLOCK_HOPS_ALL || packet->getPathHashCount() > max_hops;
|
||||
}
|
||||
|
||||
bool MyMesh::floodChannelDataHopApplies(const mesh::Packet* packet) const {
|
||||
if (packet == NULL) {
|
||||
return false;
|
||||
}
|
||||
uint8_t max_hops = _prefs.flood_channel_data_max_hops;
|
||||
return max_hops == FLOOD_CHANNEL_BLOCK_HOPS_ALL || packet->getPathHashCount() > max_hops;
|
||||
}
|
||||
|
||||
bool MyMesh::floodChannelBlockMatches(const FloodChannelBlockEntry& entry, const mesh::Packet* packet) const {
|
||||
if (!entry.active || packet == NULL || !packet->isRouteFlood()) {
|
||||
return false;
|
||||
@@ -715,7 +727,7 @@ bool MyMesh::allowPacketForward(const mesh::Packet *packet) {
|
||||
if (packet->getPayloadType() == PAYLOAD_TYPE_ADVERT && packet->getPathHashCount() >= _prefs.flood_max_advert) return false;
|
||||
if (!_prefs.flood_channel_data_enabled
|
||||
&& packet->getPayloadType() == PAYLOAD_TYPE_GRP_DATA
|
||||
&& floodChannelBlockHopApplies(packet, _prefs.flood_channel_block_max_hops)) {
|
||||
&& floodChannelDataHopApplies(packet)) {
|
||||
MESH_DEBUG_PRINTLN("allowPacketForward: flood.channel.data off, blocking GRP_DATA hops=%d",
|
||||
packet->getPathHashCount());
|
||||
return false;
|
||||
@@ -992,7 +1004,14 @@ uint32_t MyMesh::getDirectRetryEchoDelay(const mesh::Packet* packet) const {
|
||||
|
||||
// Wait roughly long enough for our TX, the next hop's receive/forward window, and its echo back.
|
||||
uint32_t bits = ((uint32_t)packet->getRawLength()) * 8;
|
||||
uint32_t scaled_wait_millis = (uint32_t)((((float)bits) * 4.0f) / kbps);
|
||||
uint8_t payload_type = packet->getPayloadType();
|
||||
float length_factor = 6.0f;
|
||||
if (payload_type == PAYLOAD_TYPE_TRACE || payload_type == PAYLOAD_TYPE_ANON_REQ) {
|
||||
length_factor = 4.0f;
|
||||
} else if (payload_type == PAYLOAD_TYPE_TXT_MSG) {
|
||||
length_factor = 7.0f;
|
||||
}
|
||||
uint32_t scaled_wait_millis = (uint32_t)((((float)bits) * length_factor) / kbps);
|
||||
return base_wait_millis + scaled_wait_millis;
|
||||
}
|
||||
|
||||
@@ -1011,6 +1030,10 @@ static uint8_t decodeDirectRetryTraceHashSize(uint8_t flags, uint8_t route_bytes
|
||||
}
|
||||
|
||||
uint8_t MyMesh::getDirectRetryMaxAttempts(const mesh::Packet* packet) const {
|
||||
if (packet != NULL && packet->getPayloadType() == PAYLOAD_TYPE_TXT_MSG) {
|
||||
return 21;
|
||||
}
|
||||
|
||||
uint8_t configured_attempts = getDirectRetryConfiguredMaxAttempts();
|
||||
uint8_t total_hops = 0;
|
||||
|
||||
@@ -2212,6 +2235,7 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
|
||||
_prefs.flood_retry_advert_enabled = FLOOD_RETRY_ADVERT_DEFAULT;
|
||||
_prefs.flood_channel_data_enabled = 1;
|
||||
_prefs.flood_channel_block_max_hops = FLOOD_CHANNEL_BLOCK_HOPS_ALL;
|
||||
_prefs.flood_channel_data_max_hops = FLOOD_CHANNEL_BLOCK_HOPS_ALL;
|
||||
_prefs.battery_alert_enabled = 0;
|
||||
_prefs.battery_alert_low_percent = BATTERY_ALERT_LOW_PERCENT_DEFAULT;
|
||||
_prefs.battery_alert_critical_percent = BATTERY_ALERT_CRITICAL_PERCENT_DEFAULT;
|
||||
@@ -3037,9 +3061,28 @@ void MyMesh::deriveFloodChannelBlockPrefix(const uint8_t* secret, uint8_t key_le
|
||||
mesh::Utils::sha256(prefix, FLOOD_CHANNEL_BLOCK_PREFIX_LEN, secret, key_len);
|
||||
}
|
||||
|
||||
void MyMesh::seedDefaultFloodChannelBlocks() {
|
||||
auto& entry = flood_channel_blocks[0];
|
||||
clearFloodChannelBlockEntry(entry);
|
||||
entry.active = true;
|
||||
entry.key_len = CIPHER_KEY_SIZE;
|
||||
entry.max_hops = DEFAULT_FLOOD_CHANNEL_BLOCK_HOPS;
|
||||
mesh::Utils::sha256(entry.secret, CIPHER_KEY_SIZE,
|
||||
(const uint8_t*)DEFAULT_FLOOD_CHANNEL_BLOCK_NAME,
|
||||
strlen(DEFAULT_FLOOD_CHANNEL_BLOCK_NAME));
|
||||
memset(&entry.secret[CIPHER_KEY_SIZE], 0, PUB_KEY_SIZE - CIPHER_KEY_SIZE);
|
||||
deriveFloodChannelBlockPrefix(entry.secret, entry.key_len, entry.hash_prefix);
|
||||
StrHelper::strncpy(entry.name, DEFAULT_FLOOD_CHANNEL_BLOCK_NAME, sizeof(entry.name));
|
||||
}
|
||||
|
||||
void MyMesh::loadFloodChannelBlocks() {
|
||||
memset(flood_channel_blocks, 0, sizeof(flood_channel_blocks));
|
||||
if (_fs == NULL || !_fs->exists(FLOOD_CHANNEL_BLOCK_FILE)) {
|
||||
if (_fs == NULL) {
|
||||
return;
|
||||
}
|
||||
if (!_fs->exists(FLOOD_CHANNEL_BLOCK_FILE)) {
|
||||
seedDefaultFloodChannelBlocks();
|
||||
saveFloodChannelBlocks();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -204,11 +204,13 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
|
||||
bool isMillisTimerDue(unsigned long timestamp) const;
|
||||
void loadFloodChannelBlocks();
|
||||
bool saveFloodChannelBlocks();
|
||||
void seedDefaultFloodChannelBlocks();
|
||||
void clearFloodChannelBlockEntry(FloodChannelBlockEntry& entry);
|
||||
void deriveFloodChannelBlockPrefix(const uint8_t* secret, uint8_t key_len,
|
||||
uint8_t prefix[FLOOD_CHANNEL_BLOCK_PREFIX_LEN]) const;
|
||||
uint8_t resolveFloodChannelBlockHops(uint8_t max_hops) const;
|
||||
bool floodChannelBlockHopApplies(const mesh::Packet* packet, uint8_t max_hops) const;
|
||||
bool floodChannelDataHopApplies(const mesh::Packet* packet) const;
|
||||
bool floodChannelBlockMatches(const FloodChannelBlockEntry& entry, const mesh::Packet* packet) const;
|
||||
bool shouldBlockFloodChannelForward(const mesh::Packet* packet) const;
|
||||
int findFloodChannelBlockBySelector(const char* selector) const;
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
namespace mesh {
|
||||
|
||||
static const uint8_t DIRECT_RETRY_MAX_ATTEMPTS_DEFAULT = 15;
|
||||
static const uint8_t DIRECT_RETRY_MAX_ATTEMPTS_HARD_MAX = 15;
|
||||
static const uint8_t DIRECT_RETRY_MAX_ATTEMPTS_HARD_MAX = 21;
|
||||
static const uint8_t FLOOD_RETRY_MAX_ATTEMPTS_DEFAULT = 15;
|
||||
static const uint8_t FLOOD_RETRY_MAX_ATTEMPTS_HARD_MAX = 15;
|
||||
static const uint8_t FLOOD_RETRY_MAX_PATH_DEFAULT = 1;
|
||||
|
||||
@@ -704,6 +704,7 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
||||
_prefs->direct_retry_recent_enabled = DIRECT_RETRY_RECENT_DEFAULT;
|
||||
_prefs->flood_channel_data_enabled = 1;
|
||||
_prefs->flood_channel_block_max_hops = FLOOD_CHANNEL_BLOCK_HOPS_ALL;
|
||||
_prefs->flood_channel_data_max_hops = FLOOD_CHANNEL_BLOCK_HOPS_ALL;
|
||||
bool has_flood_retry_prefs = file.available() >= 2;
|
||||
if (has_flood_retry_prefs) {
|
||||
file.read((uint8_t *)&_prefs->flood_retry_attempts, sizeof(_prefs->flood_retry_attempts)); // 311
|
||||
@@ -741,6 +742,9 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
||||
if (file.available() >= (int)sizeof(_prefs->flood_channel_block_max_hops)) {
|
||||
file.read((uint8_t *)&_prefs->flood_channel_block_max_hops, sizeof(_prefs->flood_channel_block_max_hops));
|
||||
}
|
||||
if (file.available() >= (int)sizeof(_prefs->flood_channel_data_max_hops)) {
|
||||
file.read((uint8_t *)&_prefs->flood_channel_data_max_hops, sizeof(_prefs->flood_channel_data_max_hops));
|
||||
}
|
||||
}
|
||||
// next: 674
|
||||
|
||||
@@ -807,6 +811,10 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
||||
&& (_prefs->flood_channel_block_max_hops < 1 || _prefs->flood_channel_block_max_hops > 7)) {
|
||||
_prefs->flood_channel_block_max_hops = FLOOD_CHANNEL_BLOCK_HOPS_ALL;
|
||||
}
|
||||
if (_prefs->flood_channel_data_max_hops != FLOOD_CHANNEL_BLOCK_HOPS_ALL
|
||||
&& (_prefs->flood_channel_data_max_hops < 1 || _prefs->flood_channel_data_max_hops > 7)) {
|
||||
_prefs->flood_channel_data_max_hops = FLOOD_CHANNEL_BLOCK_HOPS_ALL;
|
||||
}
|
||||
if (_prefs->battery_alert_low_percent < 1
|
||||
|| _prefs->battery_alert_low_percent > 100
|
||||
|| _prefs->battery_alert_critical_percent >= _prefs->battery_alert_low_percent) {
|
||||
@@ -906,6 +914,7 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) {
|
||||
file.write((uint8_t *)&_prefs->direct_retry_recent_enabled, sizeof(_prefs->direct_retry_recent_enabled));
|
||||
file.write((uint8_t *)&_prefs->flood_channel_data_enabled, sizeof(_prefs->flood_channel_data_enabled));
|
||||
file.write((uint8_t *)&_prefs->flood_channel_block_max_hops, sizeof(_prefs->flood_channel_block_max_hops));
|
||||
file.write((uint8_t *)&_prefs->flood_channel_data_max_hops, sizeof(_prefs->flood_channel_data_max_hops));
|
||||
// next: 674
|
||||
|
||||
file.close();
|
||||
@@ -1550,6 +1559,15 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
} else {
|
||||
strcpy(reply, "Error, must be 0-5000 ms");
|
||||
}
|
||||
} else if (memcmp(config, "flood.channel.data.hops ", 24) == 0) {
|
||||
uint8_t max_hops;
|
||||
if (parseFloodChannelBlockHops(&config[24], max_hops)) {
|
||||
_prefs->flood_channel_data_max_hops = max_hops;
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, must be all or 1-7");
|
||||
}
|
||||
} else if (memcmp(config, "flood.channel.data ", 19) == 0) {
|
||||
if (strcmp(&config[19], "on") == 0) {
|
||||
_prefs->flood_channel_data_enabled = 1;
|
||||
@@ -1940,9 +1958,13 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
sprintf(reply, "> %s", StrHelper::ftoa(_prefs->rx_delay_base));
|
||||
} else if (memcmp(config, "txdelay", 7) == 0) {
|
||||
sprintf(reply, "> %s", StrHelper::ftoa(_prefs->tx_delay_factor));
|
||||
} else if (memcmp(config, "flood.channel.data", 18) == 0) {
|
||||
} else if (strcmp(config, "flood.channel.data.hops") == 0) {
|
||||
char hops[8];
|
||||
formatFloodChannelBlockHops(hops, _prefs->flood_channel_block_max_hops);
|
||||
formatFloodChannelBlockHops(hops, _prefs->flood_channel_data_max_hops);
|
||||
sprintf(reply, "> %s", hops);
|
||||
} else if (strcmp(config, "flood.channel.data") == 0) {
|
||||
char hops[8];
|
||||
formatFloodChannelBlockHops(hops, _prefs->flood_channel_data_max_hops);
|
||||
sprintf(reply, "> %s %s", _prefs->flood_channel_data_enabled ? "on" : "off", hops);
|
||||
} else if (memcmp(config, "flood.channel.block.hops", 24) == 0) {
|
||||
char hops[8];
|
||||
|
||||
@@ -170,6 +170,7 @@ struct NodePrefs { // persisted to file
|
||||
uint8_t direct_retry_recent_enabled;
|
||||
uint8_t flood_channel_data_enabled;
|
||||
uint8_t flood_channel_block_max_hops;
|
||||
uint8_t flood_channel_data_max_hops;
|
||||
};
|
||||
|
||||
class CommonCLICallbacks {
|
||||
|
||||
@@ -28,6 +28,8 @@ build_src_filter = ${lora_e5.build_src_filter}
|
||||
[env:wio-e5-repeater_bridge_rs232]
|
||||
extends = lora_e5
|
||||
build_flags = ${lora_e5.build_flags}
|
||||
-flto
|
||||
-D MESH_ENABLE_RECENT_REPEATERS=1
|
||||
-D LORA_TX_POWER=22
|
||||
-D ADVERT_NAME='"WIO-E5 Repeater"'
|
||||
-D ADMIN_PASSWORD='"password"'
|
||||
|
||||
Reference in New Issue
Block a user