Feat/mesh beacon (#10618)
* Tips robot virtual node / relayer to different LoRa modes & channels
Note that this commit has details hardcoded for the Wellington (NZ)
mesh, and also requires the following patch to the protobufs:
-----
diff --git a/meshtastic/mesh.proto b/meshtastic/mesh.proto
index 03162d8..ec54c99 100644
--- a/meshtastic/mesh.proto
+++ b/meshtastic/mesh.proto
@@ -1393,6 +1393,21 @@ message MeshPacket {
* Set by the firmware internally, clients are not supposed to set this.
*/
uint32 tx_after = 20;
+
+ /*
+ * The modem preset to use fo rthis packet
+ */
+ uint32 modem_preset = 21;
+
+ /*
+ * The frequency slot to use for this packet
+ */
+ uint32 frequency_slot = 22;
+
+ /*
+ * Whether the packet has a nonstandard radio config
+ */
+ bool nonstandard_radio_config = 23;
}
/*
-----
* fix: repair mesh tips CI build
* feat: add MeshBeacon module (Phase 1 — proto + generated code + initial stub)
* feat(beacon): implement broadcaster + listener (phases 2-5)
* feat(beacon): wire RadioLibInterface hooks + admin validation (phases 6-7)
* fix(beacon): fix LocalModuleConfig flat access (no payload_variant), add localonly proto field
* feat(beacon): fix broadcaster inheritance, add preset/region validation + proto cache
- MeshBeaconBroadcastModule now inherits ProtobufModule<meshtastic_MeshBeacon>
(alongside private MeshBeaconModule + OSThread), giving it allocDataPacket()
and setStartDelay() without extra includes.
- Payload cache: rebuildCache() encodes the MeshBeacon protobuf once and stores
it in payloadCache[]/payloadCacheSize; sendBeacon() only calls rebuildCache()
when payloadCacheDirty==true. AdminModule calls invalidateCache() after saving
new config so the next broadcast picks up changes.
- Region/preset validation in handleSetModuleConfig (mesh_beacon_tag):
broadcast_on_preset is validated against the device's current region via
RadioInterface::validateConfigLora(); broadcast_offer_region is validated via
RadioInterface::validateConfigRegion(). Invalid values are zeroed with a
LOG_WARN before saving.
* feat(beacon): add unit tests for MeshBeaconModule and AdminModule configuration validation
* remove old meshtips
* more validation in NodeDB and AdminModule, and userprefs for baked in goodness
* copilot is my gravity
* mmmmm... beacon
* oops
* Enhance unit tests for MeshBeaconModule with detailed validation checks and output formatting
* new lines. Why not?
* finally
* legacy mode activate!
* Update protobufs (#17)
Co-authored-by: NomDeTom <116762865+NomDeTom@users.noreply.github.com>
* better logic, fixed a test
* updated for packet signing
fixed a test
added guards for licensed/ham mode
* channel numbers
* beacon: encrypt on the beacon channel PSK; fix split note
When broadcast_on_channel overrides the primary channel's name/PSK, the
beacon was encrypted with the PRIMARY PSK: perhapsEncode keys encryption
off the primary slot, but the radio-thread channel switch happens only
after encryption. sendBeaconPacket() now installs the beacon channel into
the primary slot for the synchronous duration of send() (cooperative
threading => no interleaving) so encryption/hash use the beacon channel,
then restores it. A shared beaconChannelSettings() helper builds the
channel for both the encrypt-time swap and the RF-time swap so the
key+hash cannot drift.
Also: correct the legacy-split comments (both packets go out on the same
beacon radio settings, not the normal config) and merge the two
consecutive `if (hasText)` blocks in the listener (cppcheck
duplicateCondition).
Tests: add channelPskOverride_swapsBeaconChannelAndRestores and
noChannelOverride_doesNotSwapPrimary; MockRouter snapshots the primary
channel at send() time.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test/beacon: drain toPhoneQueue in tearDown to fix LSan leak abort
The listener delivers received text via MeshService::sendToPhone(), which
enqueues the packet into toPhoneQueue and takes ownership. Nothing dequeues
it in tests, so the three listener tests carrying message text stranded a
MeshPacket each — 1272 bytes / 3 allocations that LeakSanitizer flagged at
process exit, aborting the coverage run (surfaced by pio as [ERRORED] /
SIGHUP even though all 40 assertions passed).
Drain the phone queue in tearDown (getForPhone()/releaseToPool) so the
packets return to packetPool. Suite is now GREEN with no sanitizer abort.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* legacy hop override for zero-hoppers
* ever more beacons
* beacon: comment out broadcast_send_as_node pending further review
Functionality preserved in comments with full signing/has_bitfield notes
for when it is re-enabled. Proto tag 3 retained on the wire.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test/beacon: fix fromIsCustomNodeWhenSet now that send-as-node is disabled
broadcast_send_as_node is commented out; from is always the local node.
Update the test assertion and doc comment to match current behaviour.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Update protobufs (#21)
Co-authored-by: NomDeTom <116762865+NomDeTom@users.noreply.github.com>
* flags for beacons
* beacon: do more with less — slot-index targets + validation
Multi-target beacons embedded a full ChannelSettings in every BroadcastTarget,
blowing ModuleConfig past the 512-byte BLE FromRadio budget so the firmware would
not compile. Targets now reference an existing channel-table slot by channel_index
and the broadcaster resolves it via channels.getByIndex() at TX time. Net effect:
the same multi-target capability for a fraction of the bytes —
FromRadio 609 -> 510 B, MeshBeaconConfig 596 -> 324 B, AdminMessage 615 -> 511 B.
- proto: BroadcastTarget.channel (embedded) -> channel_index (uint32 ref); regen all
generated headers (size constants propagate to admin/localonly/deviceonly/mesh).
- broadcaster: resolve channel_index from the channel table; an out-of-range or blank
slot falls back to the default channel for the target preset rather than borrowing
the primary's name/PSK.
- AdminModule: validate broadcast_targets entries on write (region/preset sanitised
like the single-target fields; channel_index range-checked).
- userPrefs: TARGET_<n>_CHANNEL_{NAME,NUM,PSK} collapse to a single CHANNEL_INDEX.
- docs: two-step (set_channel -> set_module_config) multi-target setup, inline-vs-
reference distinction, and single-/multi-target are equal (not "legacy") options.
- tests: target validation + channel-index resolution incl. blank-slot fallback
(47/47 green on `./bin/run-tests.sh -e native -f test_mesh_beacon`).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NRAF5csgsMn6p1zEcFL8Qz
* throttling after reboot
* address copilot review
* simplify
* fix(beacon): use 0x%08x for node/packet IDs in logs; register test suite
The %#08lx log specifiers passed uint32_t (NodeNum/PacketId) to a %lx
length modifier — undefined behaviour on 64-bit (native test) targets and
non-standard width. Switch to the project-standard 0x%08x. Also bump
test/native-suite-count to 25 for the added test_mesh_beacon suite.
clod helped too
* copilot & clarity
clod helped too
* refactor(beacon): use auto for the sanitized config copy
clod helped too
* fix(beacon): guard empty-payload sends; gate has_mesh_beacon on build flag; document ISR_TX pre-switch
clod helped too
---------
Co-authored-by: Steve Gilberd <steve@erayd.net>
Co-authored-by: Darafei Praliaskouski <me@komzpa.net>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
GitHub
Steve Gilberd
Darafei Praliaskouski
github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Claude Opus 4.8
parent
ad132e9540
commit
ec5d230305
+5
-5
@@ -105,6 +105,11 @@ class Channels
|
||||
|
||||
bool setDefaultPresetCryptoForHash(ChannelHash channelHash);
|
||||
|
||||
/**
|
||||
* Validate a channel, fixing any errors as needed
|
||||
*/
|
||||
meshtastic_Channel &fixupChannel(ChannelIndex chIndex);
|
||||
|
||||
int16_t getHash(ChannelIndex i) { return hashes[i]; }
|
||||
|
||||
private:
|
||||
@@ -124,11 +129,6 @@ class Channels
|
||||
*/
|
||||
int16_t generateHash(ChannelIndex channelNum);
|
||||
|
||||
/**
|
||||
* Validate a channel, fixing any errors as needed
|
||||
*/
|
||||
meshtastic_Channel &fixupChannel(ChannelIndex chIndex);
|
||||
|
||||
/**
|
||||
* Writes the default lora config
|
||||
*/
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#define default_screen_on_secs IF_ROUTER(1, 60 * 10)
|
||||
#define default_node_info_broadcast_secs 3 * 60 * 60
|
||||
#define default_neighbor_info_broadcast_secs 6 * 60 * 60
|
||||
#define default_mesh_beacon_min_broadcast_interval_secs 3600
|
||||
#define min_node_info_broadcast_secs 60 * 60 // No regular broadcasts of more than once an hour
|
||||
#define min_neighbor_info_broadcast_secs 4 * 60 * 60
|
||||
#define default_map_publish_interval_secs 60 * 60
|
||||
|
||||
@@ -1308,6 +1308,152 @@ void NodeDB::installDefaultModuleConfig()
|
||||
moduleConfig.ambient_lighting.green = (myNodeInfo.my_node_num & 0x00FF00) >> 8;
|
||||
moduleConfig.ambient_lighting.blue = myNodeInfo.my_node_num & 0x0000FF;
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_BEACON
|
||||
moduleConfig.has_mesh_beacon = true;
|
||||
// Default flags: listen on, broadcast off, legacy split on.
|
||||
moduleConfig.mesh_beacon.flags = meshtastic_ModuleConfig_MeshBeaconConfig_Flags_FLAG_LISTEN_ENABLED |
|
||||
meshtastic_ModuleConfig_MeshBeaconConfig_Flags_FLAG_LEGACY_SPLIT;
|
||||
// Set or clear a single beacon flag bit from a USERPREFS boolean.
|
||||
#define BEACON_APPLY_FLAG(enabled, flag) \
|
||||
do { \
|
||||
if (enabled) \
|
||||
moduleConfig.mesh_beacon.flags |= (uint32_t)(flag); \
|
||||
else \
|
||||
moduleConfig.mesh_beacon.flags &= ~(uint32_t)(flag); \
|
||||
} while (0)
|
||||
#ifdef USERPREFS_MESH_BEACON_LISTEN_ENABLED
|
||||
BEACON_APPLY_FLAG(USERPREFS_MESH_BEACON_LISTEN_ENABLED, meshtastic_ModuleConfig_MeshBeaconConfig_Flags_FLAG_LISTEN_ENABLED);
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_BROADCAST_ENABLED
|
||||
BEACON_APPLY_FLAG(USERPREFS_MESH_BEACON_BROADCAST_ENABLED,
|
||||
meshtastic_ModuleConfig_MeshBeaconConfig_Flags_FLAG_BROADCAST_ENABLED);
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_MESSAGE
|
||||
strncpy(moduleConfig.mesh_beacon.broadcast_message, USERPREFS_MESH_BEACON_MESSAGE,
|
||||
sizeof(moduleConfig.mesh_beacon.broadcast_message) - 1);
|
||||
moduleConfig.mesh_beacon.broadcast_message[sizeof(moduleConfig.mesh_beacon.broadcast_message) - 1] = '\0';
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_INTERVAL_SECS
|
||||
moduleConfig.mesh_beacon.broadcast_interval_secs =
|
||||
(USERPREFS_MESH_BEACON_INTERVAL_SECS != 0 &&
|
||||
USERPREFS_MESH_BEACON_INTERVAL_SECS < default_mesh_beacon_min_broadcast_interval_secs)
|
||||
? default_mesh_beacon_min_broadcast_interval_secs
|
||||
: USERPREFS_MESH_BEACON_INTERVAL_SECS;
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_OFFER_PRESET
|
||||
moduleConfig.mesh_beacon.has_broadcast_offer_preset = true;
|
||||
moduleConfig.mesh_beacon.broadcast_offer_preset = USERPREFS_MESH_BEACON_OFFER_PRESET;
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_OFFER_REGION
|
||||
moduleConfig.mesh_beacon.broadcast_offer_region = USERPREFS_MESH_BEACON_OFFER_REGION;
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_OFFER_CHANNEL_NAME
|
||||
moduleConfig.mesh_beacon.has_broadcast_offer_channel = true;
|
||||
strncpy(moduleConfig.mesh_beacon.broadcast_offer_channel.name, USERPREFS_MESH_BEACON_OFFER_CHANNEL_NAME,
|
||||
sizeof(moduleConfig.mesh_beacon.broadcast_offer_channel.name) - 1);
|
||||
moduleConfig.mesh_beacon.broadcast_offer_channel.name[sizeof(moduleConfig.mesh_beacon.broadcast_offer_channel.name) - 1] =
|
||||
'\0';
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_OFFER_CHANNEL_PSK
|
||||
moduleConfig.mesh_beacon.has_broadcast_offer_channel = true;
|
||||
static const uint8_t beaconOfferPsk[] = USERPREFS_MESH_BEACON_OFFER_CHANNEL_PSK;
|
||||
static_assert(sizeof(beaconOfferPsk) <= sizeof(moduleConfig.mesh_beacon.broadcast_offer_channel.psk.bytes),
|
||||
"USERPREFS_MESH_BEACON_OFFER_CHANNEL_PSK exceeds the 32-byte channel PSK buffer");
|
||||
memcpy(moduleConfig.mesh_beacon.broadcast_offer_channel.psk.bytes, beaconOfferPsk, sizeof(beaconOfferPsk));
|
||||
moduleConfig.mesh_beacon.broadcast_offer_channel.psk.size = sizeof(beaconOfferPsk);
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_ON_PRESET
|
||||
moduleConfig.mesh_beacon.has_broadcast_on_preset = true;
|
||||
moduleConfig.mesh_beacon.broadcast_on_preset = USERPREFS_MESH_BEACON_ON_PRESET;
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_ON_REGION
|
||||
moduleConfig.mesh_beacon.broadcast_on_region = USERPREFS_MESH_BEACON_ON_REGION;
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_ON_CHANNEL_NAME
|
||||
moduleConfig.mesh_beacon.has_broadcast_on_channel = true;
|
||||
strncpy(moduleConfig.mesh_beacon.broadcast_on_channel.name, USERPREFS_MESH_BEACON_ON_CHANNEL_NAME,
|
||||
sizeof(moduleConfig.mesh_beacon.broadcast_on_channel.name) - 1);
|
||||
moduleConfig.mesh_beacon.broadcast_on_channel.name[sizeof(moduleConfig.mesh_beacon.broadcast_on_channel.name) - 1] = '\0';
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_ON_CHANNEL_PSK
|
||||
moduleConfig.mesh_beacon.has_broadcast_on_channel = true;
|
||||
static const uint8_t beaconOnPsk[] = USERPREFS_MESH_BEACON_ON_CHANNEL_PSK;
|
||||
static_assert(sizeof(beaconOnPsk) <= sizeof(moduleConfig.mesh_beacon.broadcast_on_channel.psk.bytes),
|
||||
"USERPREFS_MESH_BEACON_ON_CHANNEL_PSK exceeds the 32-byte channel PSK buffer");
|
||||
memcpy(moduleConfig.mesh_beacon.broadcast_on_channel.psk.bytes, beaconOnPsk, sizeof(beaconOnPsk));
|
||||
moduleConfig.mesh_beacon.broadcast_on_channel.psk.size = sizeof(beaconOnPsk);
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_ON_CHANNEL_NUM
|
||||
moduleConfig.mesh_beacon.has_broadcast_on_channel = true;
|
||||
moduleConfig.mesh_beacon.broadcast_on_channel.channel_num = USERPREFS_MESH_BEACON_ON_CHANNEL_NUM;
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_LEGACY_SPLIT
|
||||
BEACON_APPLY_FLAG(USERPREFS_MESH_BEACON_LEGACY_SPLIT, meshtastic_ModuleConfig_MeshBeaconConfig_Flags_FLAG_LEGACY_SPLIT);
|
||||
#endif
|
||||
#undef BEACON_APPLY_FLAG
|
||||
// Per-preset broadcast targets (up to 4). Each TARGET_<N>_* key bumps broadcast_targets_count as needed.
|
||||
#define BEACON_TARGET_PRESET(N, VAL) \
|
||||
do { \
|
||||
if (moduleConfig.mesh_beacon.broadcast_targets_count < (N) + 1) \
|
||||
moduleConfig.mesh_beacon.broadcast_targets_count = (N) + 1; \
|
||||
moduleConfig.mesh_beacon.broadcast_targets[(N)].has_preset = true; \
|
||||
moduleConfig.mesh_beacon.broadcast_targets[(N)].preset = (VAL); \
|
||||
} while (0)
|
||||
#define BEACON_TARGET_REGION(N, VAL) \
|
||||
do { \
|
||||
if (moduleConfig.mesh_beacon.broadcast_targets_count < (N) + 1) \
|
||||
moduleConfig.mesh_beacon.broadcast_targets_count = (N) + 1; \
|
||||
moduleConfig.mesh_beacon.broadcast_targets[(N)].region = (VAL); \
|
||||
} while (0)
|
||||
// Target channel is referenced by index into the device's channel table (0..MAX_NUM_CHANNELS-1).
|
||||
#define BEACON_TARGET_CH_INDEX(N, VAL) \
|
||||
do { \
|
||||
if (moduleConfig.mesh_beacon.broadcast_targets_count < (N) + 1) \
|
||||
moduleConfig.mesh_beacon.broadcast_targets_count = (N) + 1; \
|
||||
moduleConfig.mesh_beacon.broadcast_targets[(N)].has_channel_index = true; \
|
||||
moduleConfig.mesh_beacon.broadcast_targets[(N)].channel_index = (VAL); \
|
||||
} while (0)
|
||||
#ifdef USERPREFS_MESH_BEACON_TARGET_0_PRESET
|
||||
BEACON_TARGET_PRESET(0, USERPREFS_MESH_BEACON_TARGET_0_PRESET);
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_TARGET_0_REGION
|
||||
BEACON_TARGET_REGION(0, USERPREFS_MESH_BEACON_TARGET_0_REGION);
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_TARGET_0_CHANNEL_INDEX
|
||||
BEACON_TARGET_CH_INDEX(0, USERPREFS_MESH_BEACON_TARGET_0_CHANNEL_INDEX);
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_TARGET_1_PRESET
|
||||
BEACON_TARGET_PRESET(1, USERPREFS_MESH_BEACON_TARGET_1_PRESET);
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_TARGET_1_REGION
|
||||
BEACON_TARGET_REGION(1, USERPREFS_MESH_BEACON_TARGET_1_REGION);
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_TARGET_1_CHANNEL_INDEX
|
||||
BEACON_TARGET_CH_INDEX(1, USERPREFS_MESH_BEACON_TARGET_1_CHANNEL_INDEX);
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_TARGET_2_PRESET
|
||||
BEACON_TARGET_PRESET(2, USERPREFS_MESH_BEACON_TARGET_2_PRESET);
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_TARGET_2_REGION
|
||||
BEACON_TARGET_REGION(2, USERPREFS_MESH_BEACON_TARGET_2_REGION);
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_TARGET_2_CHANNEL_INDEX
|
||||
BEACON_TARGET_CH_INDEX(2, USERPREFS_MESH_BEACON_TARGET_2_CHANNEL_INDEX);
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_TARGET_3_PRESET
|
||||
BEACON_TARGET_PRESET(3, USERPREFS_MESH_BEACON_TARGET_3_PRESET);
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_TARGET_3_REGION
|
||||
BEACON_TARGET_REGION(3, USERPREFS_MESH_BEACON_TARGET_3_REGION);
|
||||
#endif
|
||||
#ifdef USERPREFS_MESH_BEACON_TARGET_3_CHANNEL_INDEX
|
||||
BEACON_TARGET_CH_INDEX(3, USERPREFS_MESH_BEACON_TARGET_3_CHANNEL_INDEX);
|
||||
#endif
|
||||
#undef BEACON_TARGET_PRESET
|
||||
#undef BEACON_TARGET_REGION
|
||||
#undef BEACON_TARGET_CH_INDEX
|
||||
#endif // !MESHTASTIC_EXCLUDE_BEACON
|
||||
|
||||
initModuleConfigIntervals();
|
||||
}
|
||||
|
||||
@@ -2758,6 +2904,9 @@ bool NodeDB::saveToDiskNoRetry(int saveWhat)
|
||||
moduleConfig.has_audio = true;
|
||||
moduleConfig.has_paxcounter = true;
|
||||
moduleConfig.has_statusmessage = true;
|
||||
#if !MESHTASTIC_EXCLUDE_BEACON
|
||||
moduleConfig.has_mesh_beacon = true;
|
||||
#endif
|
||||
|
||||
success &=
|
||||
saveProto(moduleConfigFileName, meshtastic_LocalModuleConfig_size, &meshtastic_LocalModuleConfig_msg, &moduleConfig);
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
#include "error.h"
|
||||
#include "main.h"
|
||||
#include "mesh-pb-constants.h"
|
||||
#if !MESHTASTIC_EXCLUDE_BEACON
|
||||
#include "modules/MeshBeaconModule.h"
|
||||
#endif
|
||||
#include <pb_decode.h>
|
||||
#include <pb_encode.h>
|
||||
|
||||
@@ -365,7 +368,15 @@ void RadioLibInterface::onNotify(uint32_t notification)
|
||||
|
||||
switch (notification) {
|
||||
case ISR_TX:
|
||||
handleTransmitInterrupt();
|
||||
handleTransmitInterrupt(); // completeSending() already restored the radio to the home config
|
||||
#if !MESHTASTIC_EXCLUDE_BEACON
|
||||
// Pre-switch the radio to the NEXT queued packet's beacon config (no-op for normal traffic).
|
||||
// Not required for correctness — TRANSMIT_DELAY_COMPLETED would switch before CAD anyway — but
|
||||
// doing it here lets the next beacon skip the switch-only delay cycle and, more importantly,
|
||||
// keeps the post-TX listen window (and the CAD/LBT that follows) on the channel we're about to
|
||||
// transmit on. Only engages when the next packet is itself a beacon — exactly when we want it.
|
||||
MeshBeaconModule::reconfigureForBeaconTX(this, txQueue.getFront());
|
||||
#endif
|
||||
startReceive();
|
||||
setTransmitDelay();
|
||||
break;
|
||||
@@ -388,9 +399,27 @@ void RadioLibInterface::onNotify(uint32_t notification)
|
||||
if (delay_remaining > 0) {
|
||||
// There's still some delay pending on this packet, so resume waiting for it to elapse
|
||||
notifyLater(delay_remaining, TRANSMIT_DELAY_COMPLETED, false);
|
||||
#if !MESHTASTIC_EXCLUDE_BEACON
|
||||
} else if (MeshBeaconModule::beaconTxConfigInvalid(txp)) {
|
||||
// The beacon's target radio config is invalid (bad preset/region, or an
|
||||
// unlicensed node keying up on a ham-only region). Drop the packet — never
|
||||
// transmit it on the current (home) config — and move on to the next queued packet.
|
||||
LOG_DEBUG("Beacon: invalid TX radio config, dropping packet 0x%08x", txp->id);
|
||||
meshtastic_MeshPacket *bad = txQueue.dequeue();
|
||||
MeshBeaconModule::clearTargetRadioSettings(bad);
|
||||
packetPool.release(bad);
|
||||
setTransmitDelay();
|
||||
} else if (MeshBeaconModule::reconfigureForBeaconTX(this, txp)) {
|
||||
setTransmitDelay();
|
||||
#endif
|
||||
} else {
|
||||
if (isChannelActive()) { // check if there is currently a LoRa packet on the channel
|
||||
startReceive(); // try receiving this packet, afterwards we'll be trying to transmit again
|
||||
#if !MESHTASTIC_EXCLUDE_BEACON
|
||||
if (!MeshBeaconModule::hasTargetRadioSettings(txp))
|
||||
#endif
|
||||
{
|
||||
startReceive(); // try receiving this packet, afterwards we'll be trying to transmit again
|
||||
}
|
||||
setTransmitDelay();
|
||||
} else {
|
||||
// Send any outgoing packets we have ready as fast as possible to keep the time between channel scan and
|
||||
@@ -522,6 +551,10 @@ void RadioLibInterface::completeSending()
|
||||
if (!isFromUs(p))
|
||||
txRelay++;
|
||||
printPacket("Completed sending", p);
|
||||
#if !MESHTASTIC_EXCLUDE_BEACON
|
||||
MeshBeaconModule::clearTargetRadioSettings(p);
|
||||
MeshBeaconModule::reconfigureForBeaconTX(this, nullptr);
|
||||
#endif
|
||||
|
||||
// We are done sending that packet, release it
|
||||
packetPool.release(p);
|
||||
@@ -682,6 +715,13 @@ bool RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
|
||||
channel scan and actual transmit as low as possible to avoid collisions. */
|
||||
if (disabled || !config.lora.tx_enabled) {
|
||||
LOG_WARN("Drop Tx packet because LoRa Tx disabled");
|
||||
#if !MESHTASTIC_EXCLUDE_BEACON
|
||||
// This packet may have already triggered a beacon radio switch in TRANSMIT_DELAY_COMPLETED;
|
||||
// since it never reaches completeSending() here, restore the radio so it isn't left on the
|
||||
// beacon config (which would also break RX on the home channel).
|
||||
MeshBeaconModule::clearTargetRadioSettings(txp);
|
||||
MeshBeaconModule::reconfigureForBeaconTX(this, nullptr);
|
||||
#endif
|
||||
packetPool.release(txp);
|
||||
return false;
|
||||
} else {
|
||||
|
||||
@@ -832,6 +832,19 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
|
||||
skipHandle = true;
|
||||
}
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_BEACON
|
||||
// Beacon listening is disabled: drop beacon packets so they are neither surfaced to the
|
||||
// phone nor handled on-device (same pattern as the disabled neighbor-info case above).
|
||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag &&
|
||||
p->decoded.portnum == meshtastic_PortNum_MESH_BEACON_APP &&
|
||||
(!moduleConfig.has_mesh_beacon ||
|
||||
!(moduleConfig.mesh_beacon.flags & meshtastic_ModuleConfig_MeshBeaconConfig_Flags_FLAG_LISTEN_ENABLED))) {
|
||||
LOG_DEBUG("Beacon listening is disabled, ignore beacon packet");
|
||||
cancelSending(p->from, p->id);
|
||||
skipHandle = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool shouldIgnoreNonstandardPorts =
|
||||
config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY;
|
||||
#if USERPREFS_EVENT_MODE
|
||||
|
||||
Reference in New Issue
Block a user