Skip to content

Commit d7a3d41

Browse files
committed
Merge branch 'default-scope' into dev
2 parents 9f680d1 + 91f3fa0 commit d7a3d41

15 files changed

Lines changed: 964 additions & 590 deletions

File tree

docs/cli_commands.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,16 @@ This document provides an overview of CLI commands that can be sent to MeshCore
714714

715715
---
716716

717+
#### View or change the default scope region for this node
718+
**Usage:**
719+
- `region default`
720+
- `region default {name|<null>}`
721+
722+
**Parameters:**
723+
- `name`: Region name, or <null> to reset/clear
724+
725+
---
726+
717727
#### Create a new region
718728
**Usage:**
719729
- `region put <name> [parent_name]`

examples/companion_radio/DataStore.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,9 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no
230230
file.read((uint8_t *)&_prefs.gps_interval, sizeof(_prefs.gps_interval)); // 86
231231
file.read((uint8_t *)&_prefs.autoadd_config, sizeof(_prefs.autoadd_config)); // 87
232232
file.read((uint8_t *)&_prefs.autoadd_max_hops, sizeof(_prefs.autoadd_max_hops)); // 88
233-
file.read((uint8_t *)&_prefs.rx_boosted_gain, sizeof(_prefs.rx_boosted_gain)); // 89
233+
file.read((uint8_t *)&_prefs.rx_boosted_gain, sizeof(_prefs.rx_boosted_gain)); // 89
234+
file.read((uint8_t *)_prefs.default_scope_name, sizeof(_prefs.default_scope_name)); // 90
235+
file.read((uint8_t *)_prefs.default_scope_key, sizeof(_prefs.default_scope_key)); // 121
234236

235237
file.close();
236238
}
@@ -268,7 +270,9 @@ void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_
268270
file.write((uint8_t *)&_prefs.gps_interval, sizeof(_prefs.gps_interval)); // 86
269271
file.write((uint8_t *)&_prefs.autoadd_config, sizeof(_prefs.autoadd_config)); // 87
270272
file.write((uint8_t *)&_prefs.autoadd_max_hops, sizeof(_prefs.autoadd_max_hops)); // 88
271-
file.write((uint8_t *)&_prefs.rx_boosted_gain, sizeof(_prefs.rx_boosted_gain)); // 89
273+
file.write((uint8_t *)&_prefs.rx_boosted_gain, sizeof(_prefs.rx_boosted_gain)); // 89
274+
file.write((uint8_t *)_prefs.default_scope_name, sizeof(_prefs.default_scope_name)); // 90
275+
file.write((uint8_t *)_prefs.default_scope_key, sizeof(_prefs.default_scope_key)); // 121
272276

273277
file.close();
274278
}

examples/companion_radio/MyMesh.cpp

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
#define CMD_SEND_BINARY_REQ 50
5151
#define CMD_FACTORY_RESET 51
5252
#define CMD_SEND_PATH_DISCOVERY_REQ 52
53-
#define CMD_SET_FLOOD_SCOPE 54 // v8+
53+
#define CMD_SET_FLOOD_SCOPE_KEY 54 // v8+
5454
#define CMD_SEND_CONTROL_DATA 55 // v8+
5555
#define CMD_GET_STATS 56 // v8+, second byte is stats type
5656
#define CMD_SEND_ANON_REQ 57
@@ -59,6 +59,8 @@
5959
#define CMD_GET_ALLOWED_REPEAT_FREQ 60
6060
#define CMD_SET_PATH_HASH_MODE 61
6161
#define CMD_SEND_CHANNEL_DATA 62
62+
#define CMD_SET_DEFAULT_FLOOD_SCOPE 63
63+
#define CMD_GET_DEFAULT_FLOOD_SCOPE 64
6264

6365
// Stats sub-types for CMD_GET_STATS
6466
#define STATS_TYPE_CORE 0
@@ -93,6 +95,7 @@
9395
#define RESP_CODE_AUTOADD_CONFIG 25
9496
#define RESP_ALLOWED_REPEAT_FREQ 26
9597
#define RESP_CODE_CHANNEL_DATA_RECV 27
98+
#define RESP_CODE_DEFAULT_FLOOD_SCOPE 28
9699

97100
#define MAX_CHANNEL_DATA_LENGTH (MAX_FRAME_SIZE - 9)
98101

@@ -479,27 +482,32 @@ bool MyMesh::allowPacketForward(const mesh::Packet* packet) {
479482
return _prefs.client_repeat != 0;
480483
}
481484

482-
void MyMesh::sendFloodScoped(const ContactInfo& recipient, mesh::Packet* pkt, uint32_t delay_millis) {
483-
// TODO: dynamic send_scope, depending on recipient and current 'home' Region
484-
if (send_scope.isNull()) {
485+
void MyMesh::sendFloodScoped(const TransportKey& scope, mesh::Packet* pkt, uint32_t delay_millis) {
486+
if (scope.isNull()) {
485487
sendFlood(pkt, delay_millis, _prefs.path_hash_mode + 1);
486488
} else {
487489
uint16_t codes[2];
488-
codes[0] = send_scope.calcTransportCode(pkt);
490+
codes[0] = scope.calcTransportCode(pkt);
489491
codes[1] = 0; // REVISIT: set to 'home' Region, for sender/return region?
490492
sendFlood(pkt, codes, delay_millis, _prefs.path_hash_mode + 1);
491493
}
492494
}
495+
496+
void MyMesh::sendFloodScoped(const ContactInfo& recipient, mesh::Packet* pkt, uint32_t delay_millis) {
497+
// TODO: dynamic send_scope, depending on recipient and current 'home' Region
498+
TransportKey default_scope;
499+
memcpy(&default_scope.key, _prefs.default_scope_key, sizeof(default_scope.key));
500+
501+
auto scope = send_scope.isNull() ? &default_scope : &send_scope;
502+
sendFloodScoped(*scope, pkt, delay_millis);
503+
}
493504
void MyMesh::sendFloodScoped(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t delay_millis) {
494505
// TODO: have per-channel send_scope
495-
if (send_scope.isNull()) {
496-
sendFlood(pkt, delay_millis, _prefs.path_hash_mode + 1);
497-
} else {
498-
uint16_t codes[2];
499-
codes[0] = send_scope.calcTransportCode(pkt);
500-
codes[1] = 0; // REVISIT: set to 'home' Region, for sender/return region?
501-
sendFlood(pkt, codes, delay_millis, _prefs.path_hash_mode + 1);
502-
}
506+
TransportKey default_scope;
507+
memcpy(&default_scope.key, _prefs.default_scope_key, sizeof(default_scope.key));
508+
509+
auto scope = send_scope.isNull() ? &default_scope : &send_scope;
510+
sendFloodScoped(*scope, pkt, delay_millis);
503511
}
504512

505513
void MyMesh::onMessageRecv(const ContactInfo &from, mesh::Packet *pkt, uint32_t sender_timestamp,
@@ -893,6 +901,17 @@ void MyMesh::begin(bool has_display) {
893901
strcpy(_prefs.node_name, pub_key_hex);
894902
#endif
895903

904+
// if build provides default-scope, init with that
905+
#ifdef DEFAULT_FLOOD_SCOPE_NAME
906+
strcpy(_prefs.default_scope_name, DEFAULT_FLOOD_SCOPE_NAME);
907+
{
908+
TransportKeyStore temp;
909+
TransportKey key;
910+
temp.getAutoKeyFor(0, "#" DEFAULT_FLOOD_SCOPE_NAME, key);
911+
memcpy(_prefs.default_scope_key, key.key, sizeof(key.key));
912+
}
913+
#endif
914+
896915
// load persisted prefs
897916
_store->loadPrefs(_prefs, sensors.node_lat, sensors.node_lon);
898917

@@ -1210,7 +1229,9 @@ void MyMesh::handleCmdFrame(size_t len) {
12101229
if (pkt) {
12111230
if (len >= 2 && cmd_frame[1] == 1) { // optional param (1 = flood, 0 = zero hop)
12121231
unsigned long delay_millis = 0;
1213-
sendFlood(pkt, delay_millis, _prefs.path_hash_mode + 1);
1232+
TransportKey default_scope;
1233+
memcpy(&default_scope.key, _prefs.default_scope_key, sizeof(default_scope.key));
1234+
sendFloodScoped(default_scope, pkt, delay_millis);
12141235
} else {
12151236
sendZeroHop(pkt);
12161237
}
@@ -1862,13 +1883,39 @@ void MyMesh::handleCmdFrame(size_t len) {
18621883
} else {
18631884
writeErrFrame(ERR_CODE_FILE_IO_ERROR);
18641885
}
1865-
} else if (cmd_frame[0] == CMD_SET_FLOOD_SCOPE && len >= 2 && cmd_frame[1] == 0) {
1886+
} else if (cmd_frame[0] == CMD_SET_FLOOD_SCOPE_KEY && len >= 2 && cmd_frame[1] == 0) {
18661887
if (len >= 2 + 16) {
18671888
memcpy(send_scope.key, &cmd_frame[2], sizeof(send_scope.key)); // set curr scope TransportKey
18681889
} else {
18691890
memset(send_scope.key, 0, sizeof(send_scope.key)); // set scope to null
18701891
}
18711892
writeOKFrame();
1893+
} else if (cmd_frame[0] == CMD_SET_DEFAULT_FLOOD_SCOPE && len >= 1) {
1894+
if (len >= 1+31+16) {
1895+
int n = strlen((char *) &cmd_frame[1]);
1896+
if (n > 0 && n < 31) {
1897+
strcpy(_prefs.default_scope_name, (char *) &cmd_frame[1]);
1898+
memcpy(_prefs.default_scope_key, &cmd_frame[1+31], 16);
1899+
savePrefs();
1900+
writeOKFrame();
1901+
} else {
1902+
writeErrFrame(ERR_CODE_ILLEGAL_ARG);
1903+
}
1904+
} else {
1905+
memset(_prefs.default_scope_name, 0, sizeof(_prefs.default_scope_name)); // set default scope to null
1906+
memset(_prefs.default_scope_key, 0, sizeof(_prefs.default_scope_key));
1907+
savePrefs();
1908+
writeOKFrame();
1909+
}
1910+
} else if (cmd_frame[0] == CMD_GET_DEFAULT_FLOOD_SCOPE) {
1911+
out_frame[0] = RESP_CODE_DEFAULT_FLOOD_SCOPE;
1912+
if (strlen(_prefs.default_scope_name) > 0) {
1913+
memcpy(&out_frame[1], _prefs.default_scope_name, 31);
1914+
memcpy(&out_frame[1+31], _prefs.default_scope_key, 16);
1915+
_serial->writeFrame(out_frame, 1+31+16);
1916+
} else {
1917+
_serial->writeFrame(out_frame, 1); // no name or key means null
1918+
}
18721919
} else if (cmd_frame[0] == CMD_SEND_CONTROL_DATA && len >= 2 && (cmd_frame[1] & 0x80) != 0) {
18731920
auto resp = createControlData(&cmd_frame[1], len - 1);
18741921
if (resp) {

examples/companion_radio/MyMesh.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include "AbstractUITask.h"
66

77
/*------------ Frame Protocol --------------*/
8-
#define FIRMWARE_VER_CODE 10
8+
#define FIRMWARE_VER_CODE 11
99

1010
#ifndef FIRMWARE_BUILD_DATE
1111
#define FIRMWARE_BUILD_DATE "20 Mar 2026"
@@ -112,6 +112,7 @@ class MyMesh : public BaseChatMesh, public DataStoreHost {
112112
bool filterRecvFloodPacket(mesh::Packet* packet) override;
113113
bool allowPacketForward(const mesh::Packet* packet) override;
114114

115+
void sendFloodScoped(const TransportKey& scope, mesh::Packet* pkt, uint32_t delay_millis);
115116
void sendFloodScoped(const ContactInfo& recipient, mesh::Packet* pkt, uint32_t delay_millis=0) override;
116117
void sendFloodScoped(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t delay_millis=0) override;
117118

examples/companion_radio/NodePrefs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,6 @@ struct NodePrefs { // persisted to file
3232
uint8_t client_repeat;
3333
uint8_t path_hash_mode; // which path mode to use when sending
3434
uint8_t autoadd_max_hops; // 0 = no limit, 1 = direct (0 hops), N = up to N-1 hops (max 64)
35+
char default_scope_name[31];
36+
uint8_t default_scope_key[16];
3537
};

0 commit comments

Comments
 (0)