* new CLI commands: region, region load, region save, region get, region allow

This commit is contained in:
Scott Powell
2025-11-03 22:53:14 +11:00
parent f797744f7c
commit ecd30f4d36
5 changed files with 219 additions and 22 deletions
+120 -8
View File
@@ -2,25 +2,106 @@
#include <helpers/TxtDataHelpers.h>
#include <SHA256.h>
void RegionMap::load(FILESYSTEM* _fs) {
// TODO
}
void RegionMap::save(FILESYSTEM* _fs) {
// TODO
RegionMap::RegionMap(TransportKeyStore& store) : _store(&store) {
next_id = 1; num_regions = 0;
wildcard.id = wildcard.parent = 0;
wildcard.flags = REGION_ALLOW_FLOOD; // default behaviour, allow flood
strcpy(wildcard.name, "(*)");
}
RegionEntry* RegionMap::putRegion(const char* name, uint16_t parent_id) {
static File openWrite(FILESYSTEM* _fs, const char* filename) {
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
_fs->remove(filename);
return _fs->open(filename, FILE_O_WRITE);
#elif defined(RP2040_PLATFORM)
return _fs->open(filename, "w");
#else
return _fs->open(filename, "w", true);
#endif
}
bool RegionMap::load(FILESYSTEM* _fs) {
if (_fs->exists("/regions2")) {
#if defined(RP2040_PLATFORM)
File file = _fs->open("/regions2", "r");
#else
File file = _fs->open("/regions2");
#endif
if (file) {
uint8_t pad[128];
num_regions = 0; next_id = 1;
bool success = file.read(pad, 7) == 7; // reserved header
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);
if (success) {
while (num_regions < MAX_REGION_ENTRIES) {
auto r = &regions[num_regions];
success = file.read((uint8_t *) &r->id, sizeof(r->id)) == sizeof(r->id);
success = success && file.read((uint8_t *) &r->parent, sizeof(r->parent)) == sizeof(r->parent);
success = success && file.read((uint8_t *) r->name, sizeof(r->name)) == sizeof(r->name);
success = success && file.read((uint8_t *) &r->flags, sizeof(r->flags)) == sizeof(r->flags);
success = success && file.read(pad, sizeof(pad)) == sizeof(pad);
if (!success) break; // EOF
if (r->id >= next_id) { // make sure next_id is valid
next_id = r->id + 1;
}
num_regions++;
}
}
file.close();
return true;
}
}
return false; // failed
}
bool RegionMap::save(FILESYSTEM* _fs) {
File file = openWrite(_fs, "/regions2");
if (file) {
uint8_t pad[128];
memset(pad, 0, sizeof(pad));
bool success = file.write(pad, 7) == 7; // reserved header
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);
if (success) {
for (int i = 0; i < num_regions; i++) {
auto r = &regions[i];
success = file.write((uint8_t *) &r->id, sizeof(r->id)) == sizeof(r->id);
success = success && file.write((uint8_t *) &r->parent, sizeof(r->parent)) == sizeof(r->parent);
success = success && file.write((uint8_t *) r->name, sizeof(r->name)) == sizeof(r->name);
success = success && file.write((uint8_t *) &r->flags, sizeof(r->flags)) == sizeof(r->flags);
success = success && file.write(pad, sizeof(pad)) == sizeof(pad);
if (!success) break; // write failed
}
}
file.close();
return true;
}
return false; // failed
}
RegionEntry* RegionMap::putRegion(const char* name, uint16_t parent_id, uint16_t id) {
auto region = findByName(name);
if (region) {
if (region->id == parent_id) return NULL; // ERROR: invalid parent!
region->parent = parent_id; // re-parent / move this region in the hierarchy
} else {
if (num_regions >= MAX_REGION_ENTRIES) return NULL; // full!
if (id == 0 && num_regions >= MAX_REGION_ENTRIES) return NULL; // full!
region = &regions[num_regions++]; // alloc new RegionEntry
region->flags = 0;
region->id = next_id++;
region->id = id == 0 ? next_id++ : id;
StrHelper::strncpy(region->name, name, sizeof(region->name));
region->parent = parent_id;
}
@@ -58,6 +139,14 @@ RegionEntry* RegionMap::findByName(const char* name) {
return NULL; // not found
}
RegionEntry* RegionMap::findByNamePrefix(const char* prefix) {
for (int i = 0; i < num_regions; i++) {
auto region = &regions[i];
if (memcmp(prefix, region->name, strlen(prefix)) == 0) return region;
}
return NULL; // not found
}
RegionEntry* RegionMap::findById(uint16_t id) {
if (id == 0) return &wildcard; // special root Region
@@ -94,3 +183,26 @@ bool RegionMap::clear() {
num_regions = 0;
return true; // success
}
void RegionMap::printChildRegions(int indent, const RegionEntry* parent, Stream& out) const {
for (int i = 0; i < indent; i++) {
out.print(' ');
}
if (parent->flags & REGION_ALLOW_FLOOD) {
out.printf("%s F\n", parent->name);
} else {
out.printf("%s\n", parent->name);
}
for (int i = 0; i < num_regions; i++) {
auto r = &regions[i];
if (r->parent == parent->id) {
printChildRegions(indent + 1, r, out);
}
}
}
void RegionMap::exportTo(Stream& out) const {
printChildRegions(0, &wildcard, out); // recursive
}