diff --git a/docs/cli_commands.md b/docs/cli_commands.md index da39fca2..78c73f8d 100644 --- a/docs/cli_commands.md +++ b/docs/cli_commands.md @@ -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 ` +- `set flood.channel.data.hops ` **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=` 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=`. -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. diff --git a/docs/halo_keymind_settings.md b/docs/halo_keymind_settings.md index 1e1b0d04..2ee56723 100644 --- a/docs/halo_keymind_settings.md +++ b/docs/halo_keymind_settings.md @@ -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 `, `set recent.repeater `, `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=` for a per-channel hop override. | `get flood.channel.block`, `set flood.channel.block[.n] [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 ` | `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 ` | `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=` for a per-channel hop override. | `get flood.channel.block`, `set flood.channel.block[.n] [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 ` | `set flood.channel.block.hops 3` | | `outpath` | Overrides the primary direct route used for replies to the current remote client. | `get outpath`, `set outpath `, `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 `, `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 ` | `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 ,,,`, `set direct.retry.cr off` | `set direct.retry.cr 10.0,7.5,2.5,0` | diff --git a/examples/simple_repeater/MyMesh.cpp b/examples/simple_repeater/MyMesh.cpp index 03e3f355..6809014d 100644 --- a/examples/simple_repeater/MyMesh.cpp +++ b/examples/simple_repeater/MyMesh.cpp @@ -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; } diff --git a/examples/simple_repeater/MyMesh.h b/examples/simple_repeater/MyMesh.h index 536fc951..f52afa69 100644 --- a/examples/simple_repeater/MyMesh.h +++ b/examples/simple_repeater/MyMesh.h @@ -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; diff --git a/src/Mesh.cpp b/src/Mesh.cpp index 9af12b53..7f9cba6d 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -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; diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index 3127a0ba..20ff7ed7 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -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]; diff --git a/src/helpers/CommonCLI.h b/src/helpers/CommonCLI.h index b9943481..9179e811 100644 --- a/src/helpers/CommonCLI.h +++ b/src/helpers/CommonCLI.h @@ -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 { diff --git a/variants/wio-e5-dev/platformio.ini b/variants/wio-e5-dev/platformio.ini index 22bdc3c8..393df69a 100644 --- a/variants/wio-e5-dev/platformio.ini +++ b/variants/wio-e5-dev/platformio.ini @@ -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"'