Quellcode durchsuchen

Merge pull request #1476 from mattzzw/region_via_LoRa

Add cli command `region list {allowed|denied}`, enable output of region cmd via remote cli
ripplebiz vor 6 Monaten
Ursprung
Commit
d81616ec68
3 geänderte Dateien mit 86 neuen und 11 gelöschten Zeilen
  1. 21 2
      examples/simple_repeater/MyMesh.cpp
  2. 61 7
      src/helpers/RegionMap.cpp
  3. 4 2
      src/helpers/RegionMap.h

+ 21 - 2
examples/simple_repeater/MyMesh.cpp

@@ -1072,8 +1072,8 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, char *command, char *reply
 
     const char* parts[4];
     int n = mesh::Utils::parseTextParts(command, parts, 4, ' ');
-    if (n == 1 && sender_timestamp == 0) {
-      region_map.exportTo(Serial);
+    if (n == 1) {
+      region_map.exportTo(reply, 160);
     } else if (n >= 2 && strcmp(parts[1], "load") == 0) {
       temp_map.resetFrom(region_map);   // rebuild regions in a temp instance
       memset(load_stack, 0, sizeof(load_stack));
@@ -1146,6 +1146,25 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, char *command, char *reply
       } else {
         strcpy(reply, "Err - not found");
       }
+    } else if (n >= 3 && strcmp(parts[1], "list") == 0) {
+      uint8_t mask = 0;
+      bool invert = false;
+      
+      if (strcmp(parts[2], "allowed") == 0) {
+        mask = REGION_DENY_FLOOD;
+        invert = false;  // list regions that DON'T have DENY flag
+      } else if (strcmp(parts[2], "denied") == 0) {
+        mask = REGION_DENY_FLOOD;
+        invert = true;   // list regions that DO have DENY flag
+      } else {
+        strcpy(reply, "Err - use 'allowed' or 'denied'");
+        return;
+      }
+      
+      int len = region_map.exportNamesTo(reply, 160, mask, invert);
+      if (len == 0) {
+        strcpy(reply, "-none-");
+      }
     } else {
       strcpy(reply, "Err - ??");
     }

+ 61 - 7
src/helpers/RegionMap.cpp

@@ -2,6 +2,45 @@
 #include <helpers/TxtDataHelpers.h>
 #include <SHA256.h>
 
+// helper class for region map exporter, we emulate Stream with a safe buffer writer.
+
+class BufStream : public Stream {
+public:
+  BufStream(char *buf, size_t max)
+    : _buf(buf), _max(max), _pos(0) {
+    if (_max > 0) _buf[0] = 0;
+  }
+
+  size_t write(uint8_t c) override {
+    if (_pos + 1 >= _max) return 0;
+    _buf[_pos++] = c;
+    _buf[_pos] = 0;
+    return 1;
+  }
+
+  size_t write(const uint8_t *buffer, size_t size) override {
+    size_t written = 0;
+    while (written < size) {
+      if (!write(buffer[written])) break;
+      written++;
+    }
+    return written;
+  }
+
+  int available() override { return 0; }
+  int read() override { return -1; }
+  int peek() override { return -1; }
+  void flush() override {}
+
+  size_t length() const { return _pos; }
+
+private:
+  char *_buf;
+  size_t _max;
+  size_t _pos;
+};
+
+
 RegionMap::RegionMap(TransportKeyStore& store) : _store(&store) {
   next_id = 1; num_regions = 0; home_id = 0;
   wildcard.id = wildcard.parent = 0;
@@ -249,25 +288,40 @@ void RegionMap::exportTo(Stream& out) const {
   printChildRegions(0, &wildcard, out);   // recursive
 }
 
-int RegionMap::exportNamesTo(char *dest, int max_len, uint8_t mask) {
+size_t RegionMap::exportTo(char *dest, size_t max_len) const {
+  if (!dest || max_len == 0) return 0;
+
+  BufStream bs(dest, max_len);
+  exportTo(bs);              // ← reuse existing logic
+  return bs.length();
+}
+
+int RegionMap::exportNamesTo(char *dest, int max_len, uint8_t mask, bool invert) {
   char *dp = dest;
-  if ((wildcard.flags & mask) == 0) {
+  
+  // Check wildcard region
+  bool wildcard_matches = invert ? (wildcard.flags & mask) : !(wildcard.flags & mask);
+  if (wildcard_matches) {
     *dp++ = '*';
     *dp++ = ',';
   }
 
-  for (int i = 0; i < num_regions; i++) {
+    for (int i = 0; i < num_regions; i++) {
     auto region = &regions[i];
-    if ((region->flags & mask) == 0) {   // region allowed? (per 'mask' param)
-      const char* name = skip_hash(region->name);
-      int len = strlen(name);
+    
+    // Check if region matches the filter criteria
+    bool region_matches = invert ? (region->flags & mask) : !(region->flags & mask);
+    
+    if (region_matches) {
+      int len = strlen(skip_hash(region->name));
       if ((dp - dest) + len + 2 < max_len) {   // only append if name will fit
-        memcpy(dp, name, len);
+        memcpy(dp, skip_hash(region->name), len);
         dp += len;
         *dp++ = ',';
       }
     }
   }
+
   if (dp > dest) { dp--; }   // don't include trailing comma
 
   *dp = 0;  // set null terminator

+ 4 - 2
src/helpers/RegionMap.h

@@ -49,7 +49,9 @@ public:
   int getCount() const { return num_regions; }
   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);
+  int exportNamesTo(char *dest, int max_len, uint8_t mask, bool invert = false);
 
-  void exportTo(Stream& out) const;
+  void    exportTo(Stream& out) const;
+  size_t  exportTo(char *dest, size_t max_len) const;
+ 
 };