Merge branch 'meshcore-dev:main' into muzi-base-duo

This commit is contained in:
Ev 2026-04-19 11:24:33 -04:00 committed by GitHub
commit e59dc47c0b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
49 changed files with 1286 additions and 857 deletions

File diff suppressed because it is too large Load diff

View file

@ -4,6 +4,7 @@
#include <helpers/IdentityStore.h>
#include <helpers/SensorManager.h>
#include <helpers/ClientACL.h>
#include <helpers/RegionMap.h>
#if defined(WITH_RS232_BRIDGE) || defined(WITH_ESPNOW_BRIDGE)
#define WITH_BRIDGE
@ -88,6 +89,16 @@ public:
virtual void clearStats() = 0;
virtual void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) = 0;
virtual void startRegionsLoad() {
// no op by default
}
virtual bool saveRegions() {
return false;
}
virtual void onDefaultRegionChanged(const RegionEntry* r) {
// no op by default
}
virtual void setBridgeState(bool enable) {
// no op by default
};
@ -107,6 +118,7 @@ class CommonCLI {
CommonCLICallbacks* _callbacks;
mesh::MainBoard* _board;
SensorManager* _sensors;
RegionMap* _region_map;
ClientACL* _acl;
char tmp[PRV_KEY_SIZE*2 + 4];
@ -114,12 +126,16 @@ class CommonCLI {
void savePrefs();
void loadPrefsInt(FILESYSTEM* _fs, const char* filename);
void handleRegionCmd(char* command, char* reply);
void handleGetCmd(uint32_t sender_timestamp, char* command, char* reply);
void handleSetCmd(uint32_t sender_timestamp, char* command, char* reply);
public:
CommonCLI(mesh::MainBoard& board, mesh::RTCClock& rtc, SensorManager& sensors, ClientACL& acl, NodePrefs* prefs, CommonCLICallbacks* callbacks)
: _board(&board), _rtc(&rtc), _sensors(&sensors), _acl(&acl), _prefs(prefs), _callbacks(callbacks) { }
CommonCLI(mesh::MainBoard& board, mesh::RTCClock& rtc, SensorManager& sensors, RegionMap& region_map, ClientACL& acl, NodePrefs* prefs, CommonCLICallbacks* callbacks)
: _board(&board), _rtc(&rtc), _sensors(&sensors), _region_map(&region_map), _acl(&acl), _prefs(prefs), _callbacks(callbacks) { }
void loadPrefs(FILESYSTEM* _fs);
void savePrefs(FILESYSTEM* _fs);
void handleCommand(uint32_t sender_timestamp, const char* command, char* reply);
void handleCommand(uint32_t sender_timestamp, char* command, char* reply);
uint8_t buildAdvertData(uint8_t node_type, uint8_t* app_data);
};

View file

@ -3,6 +3,10 @@
#include <MeshCore.h>
#include <Arduino.h>
#ifndef USER_BTN_PRESSED
#define USER_BTN_PRESSED LOW
#endif
#if defined(ESP_PLATFORM)
#include <rom/rtc.h>

View file

@ -42,7 +42,8 @@ private:
RegionMap::RegionMap(TransportKeyStore& store) : _store(&store) {
next_id = 1; num_regions = 0; home_id = 0;
next_id = 1; num_regions = 0;
default_id = home_id = 0;
wildcard.id = wildcard.parent = 0;
wildcard.flags = 0; // default behaviour, allow flood and direct
strcpy(wildcard.name, "*");
@ -79,9 +80,11 @@ bool RegionMap::load(FILESYSTEM* _fs, const char* path) {
if (file) {
uint8_t pad[128];
num_regions = 0; next_id = 1; home_id = 0;
num_regions = 0; next_id = 1;
default_id = home_id = 0;
bool success = file.read(pad, 5) == 5; // reserved header
bool success = file.read(pad, 3) == 3; // reserved header
success = success && file.read((uint8_t *) &default_id, sizeof(default_id)) == sizeof(default_id);
success = success && file.read((uint8_t *) &home_id, sizeof(home_id)) == sizeof(home_id);
success = success && file.read((uint8_t *) &wildcard.flags, sizeof(wildcard.flags)) == sizeof(wildcard.flags);
success = success && file.read((uint8_t *) &next_id, sizeof(next_id)) == sizeof(next_id);
@ -117,7 +120,8 @@ bool RegionMap::save(FILESYSTEM* _fs, const char* path) {
uint8_t pad[128];
memset(pad, 0, sizeof(pad));
bool success = file.write(pad, 5) == 5; // reserved header
bool success = file.write(pad, 3) == 3; // reserved header
success = success && file.write((uint8_t *) &default_id, sizeof(default_id)) == sizeof(default_id);
success = success && file.write((uint8_t *) &home_id, sizeof(home_id)) == sizeof(home_id);
success = success && file.write((uint8_t *) &wildcard.flags, sizeof(wildcard.flags)) == sizeof(wildcard.flags);
success = success && file.write((uint8_t *) &next_id, sizeof(next_id)) == sizeof(next_id);
@ -164,24 +168,29 @@ RegionEntry* RegionMap::putRegion(const char* name, uint16_t parent_id, uint16_t
return region;
}
int RegionMap::getTransportKeysFor(const RegionEntry& src, TransportKey dest[], int max_num) {
int num;
if (src.name[0] == '$') { // private region
num = _store->loadKeysFor(src.id, dest, max_num);
} else if (src.name[0] == '#') { // auto hashtag region
_store->getAutoKeyFor(src.id, src.name, dest[0]);
num = 1;
} else { // new: implicit auto hashtag region
char tmp[sizeof(src.name)+1];
tmp[0] = '#';
strcpy(&tmp[1], src.name);
_store->getAutoKeyFor(src.id, tmp, dest[0]);
num = 1;
}
return num;
}
RegionEntry* RegionMap::findMatch(mesh::Packet* packet, uint8_t mask) {
for (int i = 0; i < num_regions; i++) {
auto region = &regions[i];
if ((region->flags & mask) == 0) { // does region allow this? (per 'mask' param)
TransportKey keys[4];
int num;
if (region->name[0] == '$') { // private region
num = _store->loadKeysFor(region->id, keys, 4);
} else if (region->name[0] == '#') { // auto hashtag region
_store->getAutoKeyFor(region->id, region->name, keys[0]);
num = 1;
} else { // new: implicit auto hashtag region
char tmp[sizeof(region->name)];
tmp[0] = '#';
strcpy(&tmp[1], region->name);
_store->getAutoKeyFor(region->id, tmp, keys[0]);
num = 1;
}
int num = getTransportKeysFor(*region, keys, 4);
for (int j = 0; j < num; j++) {
uint16_t code = keys[j].calcTransportCode(packet);
if (packet->transport_codes[0] == code) { // a match!!
@ -237,6 +246,14 @@ void RegionMap::setHomeRegion(const RegionEntry* home) {
home_id = home ? home->id : 0;
}
RegionEntry* RegionMap::getDefaultRegion() {
return default_id == 0 ? NULL : findById(default_id);
}
void RegionMap::setDefaultRegion(const RegionEntry* def) {
default_id = def ? def->id : 0;
}
bool RegionMap::removeRegion(const RegionEntry& region) {
if (region.id == 0) return false; // failed (cannot remove the wildcard Region)

View file

@ -16,11 +16,13 @@ struct RegionEntry {
uint16_t parent;
uint8_t flags;
char name[31];
bool isWildcard() const { return id == 0; }
};
class RegionMap {
TransportKeyStore* _store;
uint16_t next_id, home_id;
uint16_t next_id, home_id, default_id;
uint16_t num_regions;
RegionEntry regions[MAX_REGION_ENTRIES];
RegionEntry wildcard;
@ -43,6 +45,8 @@ public:
RegionEntry* findById(uint16_t id);
RegionEntry* getHomeRegion(); // NOTE: can be NULL
void setHomeRegion(const RegionEntry* home);
RegionEntry* getDefaultRegion(); // NOTE: can be NULL
void setDefaultRegion(const RegionEntry* def);
bool removeRegion(const RegionEntry& region);
bool clear();
void resetFrom(const RegionMap& src) { num_regions = 0; next_id = src.next_id; }
@ -50,6 +54,7 @@ public:
const RegionEntry* getByIdx(int i) const { return &regions[i]; }
const RegionEntry* getRoot() const { return &wildcard; }
int exportNamesTo(char *dest, int max_len, uint8_t mask, bool invert = false);
int getTransportKeysFor(const RegionEntry& src, TransportKey dest[], int max_num);
void exportTo(Stream& out) const;
size_t exportTo(char *dest, size_t max_len) const;

View file

@ -181,6 +181,13 @@ void SerialBLEInterface::begin(const char* prefix, char* name, uint32_t pin_code
bleuart.begin();
bleuart.setRxCallback(onBleUartRX);
// Register DFU on the main BLE stack so paired clients can discover it
// without switching the device into a separate OTA-only BLE mode first.
bledfu.setPermission(SECMODE_ENC_WITH_MITM, SECMODE_ENC_WITH_MITM);
bledfu.begin();
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
Bluefruit.Advertising.addService(bleuart);

View file

@ -8,6 +8,7 @@
#endif
class SerialBLEInterface : public BaseSerialInterface {
BLEDfu bledfu;
BLEUart bleuart;
bool _isEnabled;
bool _isDeviceConnected;

View file

@ -62,9 +62,15 @@ LPS22HBClass LPS22HB(*TELEM_WIRE);
#endif
#if ENV_INCLUDE_INA3221
#ifndef TELEM_INA3221_ADDRESS
#define TELEM_INA3221_ADDRESS 0x42 // INA3221 3 channel current sensor I2C address
#endif
#ifndef TELEM_INA3221_SHUNT_VALUE
#define TELEM_INA3221_SHUNT_VALUE 0.100 // most variants will have a 0.1 ohm shunts
#endif
#ifndef TELEM_INA3221_NUM_CHANNELS
#define TELEM_INA3221_NUM_CHANNELS 3
#endif
#include <Adafruit_INA3221.h>
static Adafruit_INA3221 INA3221;
#endif