Bladeren bron

Merge pull request #890 from fdlamotte/CommonCLI--gps-management

CommonCLI: gps management commands
ripplebiz 10 maanden geleden
bovenliggende
commit
487b7c6576

+ 19 - 2
examples/simple_repeater/MyMesh.cpp

@@ -289,8 +289,16 @@ mesh::Packet *MyMesh::createSelfAdvert() {
   uint8_t app_data[MAX_ADVERT_DATA_SIZE];
   uint8_t app_data_len;
   {
-    AdvertDataBuilder builder(ADV_TYPE_REPEATER, _prefs.node_name, _prefs.node_lat, _prefs.node_lon);
-    app_data_len = builder.encodeTo(app_data);
+    if (_prefs.advert_loc_policy == ADVERT_LOC_NONE) {
+        AdvertDataBuilder builder(ADV_TYPE_REPEATER, _prefs.node_name);
+        app_data_len = builder.encodeTo(app_data);
+    } else if (_prefs.advert_loc_policy == ADVERT_LOC_SHARE) {
+        AdvertDataBuilder builder(ADV_TYPE_REPEATER, _prefs.node_name, sensors.node_lat, sensors.node_lon);
+        app_data_len = builder.encodeTo(app_data);
+    } else {
+        AdvertDataBuilder builder(ADV_TYPE_REPEATER, _prefs.node_name, _prefs.node_lat, _prefs.node_lon);
+        app_data_len = builder.encodeTo(app_data);
+    }
   }
 
   return createAdvert(self_id, app_data, app_data_len);
@@ -631,7 +639,12 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
   _prefs.bridge_pkt_src = 0;    // logTx
   _prefs.bridge_baud = 115200;  // baud rate
   _prefs.bridge_channel = 1;    // channel 1
+
   StrHelper::strncpy(_prefs.bridge_secret, "LVSITANOS", sizeof(_prefs.bridge_secret));
+
+  // GPS defaults
+  _prefs.gps_enabled = 0;
+  _prefs.gps_interval = 0;
 }
 
 void MyMesh::begin(FILESYSTEM *fs) {
@@ -653,6 +666,10 @@ void MyMesh::begin(FILESYSTEM *fs) {
 
   updateAdvertTimer();
   updateFloodAdvertTimer();
+
+#if ENV_INCLUDE_GPS == 1
+  applyGpsPrefs();
+#endif
 }
 
 void MyMesh::applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) {

+ 6 - 0
examples/simple_repeater/MyMesh.h

@@ -135,6 +135,12 @@ protected:
     return _prefs.multi_acks;
   }
 
+#if ENV_INCLUDE_GPS == 1
+  void applyGpsPrefs() {
+    sensors.setSettingByKey("gps", _prefs.gps_enabled?"1":"0");
+  }
+#endif
+
   void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len) override;
   int searchPeersByHash(const uint8_t* hash) override;
   void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override;

+ 14 - 2
examples/simple_room_server/MyMesh.cpp

@@ -116,8 +116,16 @@ mesh::Packet *MyMesh::createSelfAdvert() {
   uint8_t app_data[MAX_ADVERT_DATA_SIZE];
   uint8_t app_data_len;
   {
-    AdvertDataBuilder builder(ADV_TYPE_ROOM, _prefs.node_name, _prefs.node_lat, _prefs.node_lon);
-    app_data_len = builder.encodeTo(app_data);
+    if (_prefs.advert_loc_policy == ADVERT_LOC_NONE) {
+        AdvertDataBuilder builder(ADV_TYPE_REPEATER, _prefs.node_name);
+        app_data_len = builder.encodeTo(app_data);
+    } else if (_prefs.advert_loc_policy == ADVERT_LOC_SHARE) {
+        AdvertDataBuilder builder(ADV_TYPE_REPEATER, _prefs.node_name, sensors.node_lat, sensors.node_lon);
+        app_data_len = builder.encodeTo(app_data);
+    } else {
+        AdvertDataBuilder builder(ADV_TYPE_REPEATER, _prefs.node_name, _prefs.node_lat, _prefs.node_lon);
+        app_data_len = builder.encodeTo(app_data);
+    }
   }
 
   return createAdvert(self_id, app_data, app_data_len);
@@ -632,6 +640,10 @@ void MyMesh::begin(FILESYSTEM *fs) {
 
   updateAdvertTimer();
   updateFloodAdvertTimer();
+
+#if ENV_INCLUDE_GPS == 1
+  applyGpsPrefs();
+#endif
 }
 
 void MyMesh::applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) {

+ 6 - 0
examples/simple_room_server/MyMesh.h

@@ -149,6 +149,12 @@ protected:
   bool onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override;
   void onAckRecv(mesh::Packet* packet, uint32_t ack_crc) override;
 
+#if ENV_INCLUDE_GPS == 1
+  void applyGpsPrefs() {
+    sensors.setSettingByKey("gps", _prefs.gps_enabled?"1":"0");
+  }
+#endif
+
 public:
   MyMesh(mesh::MainBoard& board, mesh::Radio& radio, mesh::MillisecondClock& ms, mesh::RNG& rng, mesh::RTCClock& rtc, mesh::MeshTables& tables);
 

+ 14 - 2
examples/simple_sensor/SensorMesh.cpp

@@ -241,8 +241,16 @@ mesh::Packet* SensorMesh::createSelfAdvert() {
   uint8_t app_data[MAX_ADVERT_DATA_SIZE];
   uint8_t app_data_len;
   {
-    AdvertDataBuilder builder(ADV_TYPE_SENSOR, _prefs.node_name, _prefs.node_lat, _prefs.node_lon);
-    app_data_len = builder.encodeTo(app_data);
+    if (_prefs.advert_loc_policy == ADVERT_LOC_NONE) {
+        AdvertDataBuilder builder(ADV_TYPE_REPEATER, _prefs.node_name);
+        app_data_len = builder.encodeTo(app_data);
+    } else if (_prefs.advert_loc_policy == ADVERT_LOC_SHARE) {
+        AdvertDataBuilder builder(ADV_TYPE_REPEATER, _prefs.node_name, sensors.node_lat, sensors.node_lon);
+        app_data_len = builder.encodeTo(app_data);
+    } else {
+        AdvertDataBuilder builder(ADV_TYPE_REPEATER, _prefs.node_name, _prefs.node_lat, _prefs.node_lon);
+        app_data_len = builder.encodeTo(app_data);
+    }
   }
 
   return createAdvert(self_id, app_data, app_data_len);
@@ -697,6 +705,10 @@ void SensorMesh::begin(FILESYSTEM* fs) {
 
   updateAdvertTimer();
   updateFloodAdvertTimer();
+
+#if ENV_INCLUDE_GPS == 1
+  applyGpsPrefs();
+#endif
 }
 
 bool SensorMesh::formatFileSystem() {

+ 5 - 0
examples/simple_sensor/SensorMesh.h

@@ -149,4 +149,9 @@ private:
 
   void sendAlert(const ClientInfo* c, Trigger* t);
 
+  #if ENV_INCLUDE_GPS == 1
+  void applyGpsPrefs() {
+    sensors.setSettingByKey("gps", _prefs.gps_enabled?"1":"0");
+  }
+#endif
 };

+ 139 - 4
src/helpers/CommonCLI.cpp

@@ -62,8 +62,15 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
     file.read((uint8_t *)&_prefs->bridge_delay, sizeof(_prefs->bridge_delay));                     // 128
     file.read((uint8_t *)&_prefs->bridge_pkt_src, sizeof(_prefs->bridge_pkt_src));                 // 130
     file.read((uint8_t *)&_prefs->bridge_baud, sizeof(_prefs->bridge_baud));                       // 131
-    file.read((uint8_t *)&_prefs->bridge_channel, sizeof(_prefs->bridge_channel));                 // 132
-    file.read((uint8_t *)&_prefs->bridge_secret, sizeof(_prefs->bridge_secret));                   // 133
+    file.read((uint8_t *)&_prefs->bridge_channel, sizeof(_prefs->bridge_channel));                 // 135
+    file.read((uint8_t *)&_prefs->bridge_secret, sizeof(_prefs->bridge_secret));                   // 136
+    file.read(pad, 4);                                                                             // 152
+    file.read((uint8_t *)&_prefs->gps_enabled, sizeof(_prefs->gps_enabled));                       // 156
+    file.read((uint8_t *)&_prefs->gps_interval, sizeof(_prefs->gps_interval));                     // 157
+    if (file.read((uint8_t *)&_prefs->advert_loc_policy, sizeof (_prefs->advert_loc_policy)) == -1) {
+      _prefs->advert_loc_policy = ADVERT_LOC_PREFS; // default value
+    }                                                                                               // 161
+    // 162
 
     // sanitise bad pref values
     _prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f);
@@ -84,6 +91,9 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
     _prefs->bridge_baud = constrain(_prefs->bridge_baud, 9600, 115200);
     _prefs->bridge_channel = constrain(_prefs->bridge_channel, 0, 14);
 
+    _prefs->gps_enabled = constrain(_prefs->gps_enabled, 0, 1);
+    _prefs->advert_loc_policy = constrain(_prefs->advert_loc_policy, 0, 2);
+
     file.close();
   }
 }
@@ -131,8 +141,13 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) {
     file.write((uint8_t *)&_prefs->bridge_delay, sizeof(_prefs->bridge_delay));                     // 128
     file.write((uint8_t *)&_prefs->bridge_pkt_src, sizeof(_prefs->bridge_pkt_src));                 // 130
     file.write((uint8_t *)&_prefs->bridge_baud, sizeof(_prefs->bridge_baud));                       // 131
-    file.write((uint8_t *)&_prefs->bridge_channel, sizeof(_prefs->bridge_channel));                 // 132
-    file.write((uint8_t *)&_prefs->bridge_secret, sizeof(_prefs->bridge_secret));                   // 133
+    file.write((uint8_t *)&_prefs->bridge_channel, sizeof(_prefs->bridge_channel));                 // 135
+    file.write((uint8_t *)&_prefs->bridge_secret, sizeof(_prefs->bridge_secret));                   // 136
+    file.write(pad, 4);                                                                             // 152
+    file.write((uint8_t *)&_prefs->gps_enabled, sizeof(_prefs->gps_enabled));                       // 156
+    file.write((uint8_t *)&_prefs->gps_interval, sizeof(_prefs->gps_interval));                     // 157
+    file.write((uint8_t *)&_prefs->advert_loc_policy, sizeof(_prefs->advert_loc_policy));           // 161
+    // 162
 
     file.close();
   }
@@ -504,6 +519,126 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
       sprintf(reply, "%s (Build: %s)", _callbacks->getFirmwareVer(), _callbacks->getBuildDate());
     } else if (memcmp(command, "board", 5) == 0) {
       sprintf(reply, "%s", _board->getManufacturerName());
+    } else if (memcmp(command, "sensor get ", 11) == 0) {
+      const char* key = command + 11;
+      const char* val = sensors.getSettingByKey(key);
+      if (val != NULL) {
+        sprintf(reply, "> %s", val);
+      } else {
+        strcpy(reply, "null");
+      }
+    } else if (memcmp(command, "sensor set ", 11) == 0) {
+      strcpy(tmp, &command[11]);
+      const char *parts[2]; 
+      int num = mesh::Utils::parseTextParts(tmp, parts, 2, ' ');
+      const char *key = (num > 0) ? parts[0] : "";
+      const char *value = (num > 1) ? parts[1] : "null";
+      if (sensors.setSettingByKey(key, value)) {
+        strcpy(reply, "ok");
+      } else {
+        strcpy(reply, "can't find custom var");
+      }
+    } else if (memcmp(command, "sensor list", 11) == 0) {
+      char* dp = reply;
+      int start = 0;
+      int end = sensors.getNumSettings();
+      if (strlen(command) > 11) {
+        start = _atoi(command+12);
+      }
+      if (start >= end) {
+        strcpy(reply, "no custom var");
+      } else {
+        sprintf(dp, "%d vars\n", end);
+        dp = strchr(dp, 0);
+        int i;
+        for (i = start; i < end && (dp-reply < 134); i++) {
+          sprintf(dp, "%s=%s\n", 
+            sensors.getSettingName(i),
+            sensors.getSettingValue(i));
+          dp = strchr(dp, 0);
+        }
+        if (i < end) {
+          sprintf(dp, "... next:%d", i);
+        } else {
+          *(dp-1) = 0; // remove last CR
+        }
+      }
+#if ENV_INCLUDE_GPS == 1
+    } else if (memcmp(command, "gps on", 6) == 0) {
+      if (sensors.setSettingByKey("gps", "1")) {
+        _prefs->gps_enabled = 1;
+        savePrefs();
+        strcpy(reply, "ok");
+      } else {
+        strcpy(reply, "gps toggle not found");
+      }
+    } else if (memcmp(command, "gps off", 7) == 0) {
+      if (sensors.setSettingByKey("gps", "0")) {
+        _prefs->gps_enabled = 0;
+        savePrefs();
+        strcpy(reply, "ok");
+      } else {
+        strcpy(reply, "gps toggle not found");
+      }
+    } else if (memcmp(command, "gps sync", 8) == 0) {
+      LocationProvider * l = sensors.getLocationProvider();
+      if (l != NULL) {
+        l->syncTime();
+      }
+    } else if (memcmp(command, "gps setloc", 10) == 0) {
+      _prefs->node_lat = sensors.node_lat;
+      _prefs->node_lon = sensors.node_lon;
+      savePrefs();
+      strcpy(reply, "ok");
+    } else if (memcmp(command, "gps advert", 10) == 0) {
+      if (strlen(command) == 10) {
+        switch (_prefs->advert_loc_policy) {
+          case ADVERT_LOC_NONE:
+            strcpy(reply, "> none");
+            break;
+          case ADVERT_LOC_PREFS:
+            strcpy(reply, "> prefs");
+            break;
+          case ADVERT_LOC_SHARE:
+            strcpy(reply, "> share");
+            break;
+          default:
+            strcpy(reply, "error");
+        }
+      } else if (memcmp(command+11, "none", 4) == 0) {
+        _prefs->advert_loc_policy = ADVERT_LOC_NONE;
+        savePrefs();
+        strcpy(reply, "ok");
+      } else if (memcmp(command+11, "share", 5) == 0) {
+        _prefs->advert_loc_policy = ADVERT_LOC_SHARE;
+        savePrefs();
+        strcpy(reply, "ok");
+      } else if (memcmp(command+11, "prefs", 4) == 0) {
+        _prefs->advert_loc_policy = ADVERT_LOC_PREFS;
+        savePrefs();
+        strcpy(reply, "ok");
+      } else {
+        strcpy(reply, "error");
+      }
+    } else if (memcmp(command, "gps", 3) == 0) {
+      LocationProvider * l = sensors.getLocationProvider();
+      if (l != NULL) {
+        bool enabled = l->isEnabled(); // is EN pin on ?
+        bool fix = l->isValid();       // has fix ?
+        int sats = l->satellitesCount();
+        bool active = !strcmp(sensors.getSettingByKey("gps"), "1");
+        if (enabled) {
+          sprintf(reply, "on, %s, %s, %d sats",
+            active?"active":"deactivated", 
+            fix?"fix":"no fix", 
+            sats);
+        } else {
+          strcpy(reply, "off");
+        }
+      } else {
+        strcpy(reply, "Can't find GPS");
+      }
+#endif
     } else if (memcmp(command, "log start", 9) == 0) {
       _callbacks->setLoggingOn(true);
       strcpy(reply, "   logging on");

+ 9 - 0
src/helpers/CommonCLI.h

@@ -2,11 +2,16 @@
 
 #include "Mesh.h"
 #include <helpers/IdentityStore.h>
+#include <target.h>
 
 #if defined(WITH_RS232_BRIDGE) || defined(WITH_ESPNOW_BRIDGE)
 #define WITH_BRIDGE
 #endif
 
+#define ADVERT_LOC_NONE       0
+#define ADVERT_LOC_SHARE      1
+#define ADVERT_LOC_PREFS      2
+
 struct NodePrefs { // persisted to file
   float airtime_factor;
   char node_name[32];
@@ -37,6 +42,10 @@ struct NodePrefs { // persisted to file
   uint32_t bridge_baud;   // 9600, 19200, 38400, 57600, 115200 (default 115200)
   uint8_t bridge_channel; // 1-14 (ESP-NOW only)
   char bridge_secret[16]; // for XOR encryption of bridge packets (ESP-NOW only)
+  // Gps settings
+  uint8_t gps_enabled;
+  uint32_t gps_interval; // in seconds
+  uint8_t advert_loc_policy;
 };
 
 class CommonCLICallbacks {

+ 21 - 0
src/helpers/SensorManager.h

@@ -23,4 +23,25 @@ public:
   virtual const char* getSettingValue(int i) const { return NULL; }
   virtual bool setSettingValue(const char* name, const char* value) { return false; }
   virtual LocationProvider* getLocationProvider() { return NULL; }
+
+  // Helper functions to manage setting by keys (useful in many places ...)
+  const char* getSettingByKey(const char* key) {
+    int num = getNumSettings();
+    for (int i = 0; i < num; i++) {
+      if (strcmp(getSettingName(i), key) == 0) {
+        return getSettingValue(i);
+      }
+    }
+    return NULL;
+  }
+
+  bool setSettingByKey(const char* key, const char* value) {
+    int num = getNumSettings();
+    for (int i = 0; i < num; i++) {
+      if (strcmp(getSettingName(i), key) == 0) {
+        return setSettingValue(key, value);
+      }
+    }
+    return false;
+  }
 };

+ 16 - 9
src/helpers/sensors/EnvironmentSensorManager.cpp

@@ -387,27 +387,34 @@ bool EnvironmentSensorManager::querySensors(uint8_t requester_permissions, Cayen
 
 
 int EnvironmentSensorManager::getNumSettings() const {
+  int settings = 0;
   #if ENV_INCLUDE_GPS
-    return gps_detected ? 1 : 0;  // only show GPS setting if GPS is detected
-  #else
-    return 0;
+    if (gps_detected) settings++;  // only show GPS setting if GPS is detected
   #endif
+  return settings;
 }
 
 const char* EnvironmentSensorManager::getSettingName(int i) const {
+  int settings = 0;
   #if ENV_INCLUDE_GPS
-    return (gps_detected && i == 0) ? "gps" : NULL;
-  #else
-    return NULL;
+    if (gps_detected && i == settings++) {
+      return "gps";
+    }
   #endif
+  // convenient way to add params (needed for some tests)
+//  if (i == settings++) return "param.2";
+  return NULL;
 }
 
 const char* EnvironmentSensorManager::getSettingValue(int i) const {
+  int settings = 0;
   #if ENV_INCLUDE_GPS
-  if (gps_detected && i == 0) {
-    return gps_active ? "1" : "0";
-  }
+    if (gps_detected && i == settings++) {
+      return gps_active ? "1" : "0";
+    }
   #endif
+  // convenient way to add params ...
+//  if (i == settings++) return "2";
   return NULL;
 }
 

+ 1 - 0
src/helpers/sensors/LocationProvider.h

@@ -21,4 +21,5 @@ public:
     virtual void begin() = 0;
     virtual void stop() = 0;
     virtual void loop() = 0;
+    virtual bool isEnabled() = 0;
 };

+ 10 - 0
src/helpers/sensors/MicroNMEALocationProvider.h

@@ -78,6 +78,16 @@ public :
         }        
     }
 
+    bool isEnabled() override {
+        // directly read the enable pin if present as gps can be
+        // activated/deactivated outside of here ...
+        if (_pin_en != -1) {
+            return digitalRead(_pin_en) == PIN_GPS_EN_ACTIVE;
+        } else {
+            return true; // no enable so must be active
+        }
+    }
+
     void syncTime() override { nmea.clear(); LocationProvider::syncTime(); }
     long getLatitude() override { return nmea.getLatitude(); }
     long getLongitude() override { return nmea.getLongitude(); }