forked from meshtastic/firmware
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMeshBeaconModule.h
More file actions
163 lines (143 loc) · 7.43 KB
/
Copy pathMeshBeaconModule.h
File metadata and controls
163 lines (143 loc) · 7.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#pragma once
#include "MeshRadio.h"
#include "Observer.h"
#include "ProtobufModule.h"
#include "RadioInterface.h"
#include "concurrency/OSThread.h"
#include "mesh/generated/meshtastic/mesh_beacon.pb.h"
#include "mesh/generated/meshtastic/module_config.pb.h"
// Short aliases for the MeshBeaconConfig.flags bitfield (see module_config.proto MeshBeaconConfig.Flags).
#define MESH_BEACON_FLAG_LISTEN_ENABLED meshtastic_ModuleConfig_MeshBeaconConfig_Flags_FLAG_LISTEN_ENABLED
#define MESH_BEACON_FLAG_BROADCAST_ENABLED meshtastic_ModuleConfig_MeshBeaconConfig_Flags_FLAG_BROADCAST_ENABLED
#define MESH_BEACON_FLAG_LEGACY_SPLIT meshtastic_ModuleConfig_MeshBeaconConfig_Flags_FLAG_LEGACY_SPLIT
// Sidecar entry pairing a packet ID with target radio settings for beacon TX.
typedef struct {
bool inUse;
PacketId id;
meshtastic_Config_LoRaConfig_ModemPreset preset;
uint16_t slot;
// When true, reconfigureForBeaconTX sets hop_start=1 so pre-2.7.20 firmware
// (which drops hop_start==0 packets) accepts the zero-hop beacon.
bool legacyHopOverride;
// Per-target radio settings. UNSET region means use current lora.region.
meshtastic_Config_LoRaConfig_RegionCode region;
bool has_channel;
meshtastic_ChannelSettings channel;
} MeshBeaconModule_TargetRadioSettings;
/**
* Base class: holds the radio-switching sidecar table and static helpers.
* The sidecar avoids touching MeshPacket proto fields for per-packet radio state.
*/
class MeshBeaconModule
{
public:
MeshBeaconModule();
/**
* Reconfigure the radio for beacon TX, or restore to original config if p is NULL.
* Returns true if the radio was reconfigured (caller must re-run transmit delay for CCA).
* Driven by broadcast_on_preset / broadcast_on_channel from MeshBeaconConfig.
*/
static bool reconfigureForBeaconTX(RadioInterface *iface, meshtastic_MeshPacket *p);
/**
* Associate target radio settings with an outgoing packet by its ID.
* Sidecar holds 8 entries; evicts slot 0 on overflow.
*/
static void
setTargetRadioSettings(const meshtastic_MeshPacket *p, meshtastic_Config_LoRaConfig_ModemPreset preset, uint16_t slot,
bool legacyHopOverride = false,
meshtastic_Config_LoRaConfig_RegionCode region = meshtastic_Config_LoRaConfig_RegionCode_UNSET,
bool has_channel = false, const meshtastic_ChannelSettings *channel = nullptr);
/**
* Returns true if the sidecar table contains an entry for this packet's ID.
* Used by RadioLibInterface to gate the channel-active check.
*/
static bool hasTargetRadioSettings(const meshtastic_MeshPacket *p);
/**
* Remove the sidecar entry for this packet after it has been sent.
* Called from RadioLibInterface::completeSending().
*/
static void clearTargetRadioSettings(const meshtastic_MeshPacket *p);
/**
* True if p is tagged for a beacon radio switch whose target config must NOT be transmitted:
* preset invalid for the target region, or an unlicensed node would key up on a ham-only
* (licensed-only) region. The radio driver drops such packets rather than sending them on the
* current config. False for any packet without a sidecar entry (normal traffic is never affected).
*/
static bool beaconTxConfigInvalid(const meshtastic_MeshPacket *p);
protected:
/**
* Build the ChannelSettings the beacon transmits on: the base (primary) channel overlaid with
* any broadcast_on_channel overrides, defaulting an empty name to the target preset's display
* name. Shared by the encrypt-time channel swap and the radio-thread RF swap so the channel
* key + hash are identical at both points.
*/
static meshtastic_ChannelSettings beaconChannelSettings(const meshtastic_ChannelSettings &base,
meshtastic_Config_LoRaConfig_ModemPreset preset,
const meshtastic_ChannelSettings *overrideChannel = nullptr);
static meshtastic_Config_LoRaConfig_ModemPreset originalModemPreset;
static uint16_t originalLoraChannel;
static meshtastic_Config_LoRaConfig_RegionCode originalRegion;
static meshtastic_ChannelSettings originalPrimaryChannel;
};
/**
* Broadcaster: periodically sends MeshBeacon packets on the configured preset/channel.
* Active only when the FLAG_BROADCAST_ENABLED bit is set in moduleConfig.mesh_beacon.flags.
* Inherits ProtobufModule to access allocDataProtobuf + setStartDelay.
*
* Packet flow:
* Normal (combined): one MESH_BEACON_APP carrying offer + message on the beacon radio config.
* Legacy split: two packets when both text and offer are present and FLAG_LEGACY_SPLIT is set,
* both sent on the same beacon radio settings:
* A) MESH_BEACON_APP with offer only (no text).
* B) TEXT_MESSAGE_APP with the text (for clients that only decode TEXT_MESSAGE_APP).
*/
class MeshBeaconBroadcastModule : private MeshBeaconModule,
public ProtobufModule<meshtastic_MeshBeacon>,
private concurrency::OSThread
{
public:
MeshBeaconBroadcastModule();
// Mark the cached payload dirty (call after config change).
void invalidateCache() { payloadCacheDirty = true; }
protected:
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &, meshtastic_MeshBeacon *) override { return false; }
virtual int32_t runOnce() override;
protected:
void sendBeacon();
void rebuildCache();
// Send one beacon packet. When overrideChannel is set and has a name/PSK override,
// the packet is encrypted with that channel's key (not the primary's).
void sendBeaconPacket(meshtastic_MeshPacket *p, meshtastic_Config_LoRaConfig_ModemPreset targetPreset,
bool has_channel = false, const meshtastic_ChannelSettings *overrideChannel = nullptr);
bool payloadCacheDirty = true;
uint8_t payloadCache[meshtastic_MeshBeacon_size] = {};
pb_size_t payloadCacheSize = 0;
};
extern MeshBeaconBroadcastModule *meshBeaconBroadcastModule;
/**
* Listener: receives MESH_BEACON_APP packets and caches any offered channel/preset for the client
* app to retrieve. It does NOT unwrap the text into a separate message - the original beacon packet
* already reaches the client (handler returns CONTINUE), which reads `message` from it directly.
* Does NOT auto-apply offered settings - client app must do so explicitly.
* Active only when the FLAG_LISTEN_ENABLED bit is set in moduleConfig.mesh_beacon.flags.
*/
class MeshBeaconListenerModule : public ProtobufModule<meshtastic_MeshBeacon>, public Observable<const meshtastic_MeshPacket *>
{
public:
MeshBeaconListenerModule();
struct BeaconOffer {
bool valid;
NodeNum sender;
bool has_channel;
meshtastic_ChannelSettings channel;
meshtastic_Config_LoRaConfig_RegionCode region;
meshtastic_Config_LoRaConfig_ModemPreset preset;
uint32_t received_at;
};
// Last received offer - accessible to admin/API for client app retrieval.
static BeaconOffer lastReceivedOffer;
protected:
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_MeshBeacon *b) override;
virtual bool wantPacket(const meshtastic_MeshPacket *p) override;
};
extern MeshBeaconListenerModule *meshBeaconListenerModule;