Просмотр исходного кода

* Refactor: new AdvertDataHelpers.h

Scott Powell 1 год назад
Родитель
Сommit
068aeee87f

+ 7 - 26
examples/simple_repeater/main.cpp

@@ -13,6 +13,7 @@
 #include <helpers/StaticPoolPacketManager.h>
 #include <helpers/SimpleMeshTables.h>
 #include <helpers/IdentityStore.h>
+#include <helpers/AdvertDataHelpers.h>
 #include <RTClib.h>
 
 /* ------------------------------ Config -------------------------------- */
@@ -345,34 +346,14 @@ public:
     num_clients = 0;
   }
 
-  #define ADV_TYPE_NONE         0   // unknown
-  #define ADV_TYPE_CHAT         1
-  #define ADV_TYPE_REPEATER     2
-  //FUTURE: 3..15
-
-  #define ADV_LATLON_MASK       0x10
-  #define ADV_BATTERY_MASK      0x20
-  #define ADV_TEMPERATURE_MASK  0x40
-  #define ADV_NAME_MASK         0x80
-
   void sendSelfAdvertisement() {
-    uint8_t app_data[MAX_ADVERT_DATA_SIZE+32];
-    app_data[0] = ADV_TYPE_REPEATER | ADV_NAME_MASK;
-    int i = 1;
-    int32_t lat = ADVERT_LAT * 1E6;
-    int32_t lon = ADVERT_LON * 1E6;
-    if (!(lat == 0 && lon == 0)) {
-      app_data[0] |= ADV_LATLON_MASK;
-      memcpy(&app_data[i], &lat, 4); i += 4;
-      memcpy(&app_data[i], &lon, 4); i += 4;
+    uint8_t app_data[MAX_ADVERT_DATA_SIZE];
+    uint8_t app_data_len;
+    {
+      AdvertDataBuilder builder(ADV_TYPE_REPEATER, ADVERT_NAME, ADVERT_LAT, ADVERT_LON);
+      app_data_len = builder.encodeTo(app_data);
     }
-    strcpy((char *)&app_data[i], ADVERT_NAME);
-    int app_data_len = i + strlen(ADVERT_NAME);
-    if (app_data_len > MAX_ADVERT_DATA_SIZE) {
-      app_data_len = MAX_ADVERT_DATA_SIZE;
-      app_data[MAX_ADVERT_DATA_SIZE - 1] = 0;  // truncate the ADVERT_NAME
-    }
- 
+
     mesh::Packet* pkt = createAdvert(self_id, app_data, app_data_len);
     if (pkt) {
       sendFlood(pkt, 800);  // add slight delay

+ 8 - 27
examples/simple_room_server/main.cpp

@@ -13,6 +13,7 @@
 #include <helpers/StaticPoolPacketManager.h>
 #include <helpers/SimpleMeshTables.h>
 #include <helpers/IdentityStore.h>
+#include <helpers/AdvertDataHelpers.h>
 #include <RTClib.h>
 
 /* ------------------------------ Config -------------------------------- */
@@ -422,35 +423,14 @@ public:
     memset(posts, 0, sizeof(posts));
   }
 
-  #define ADV_TYPE_NONE         0   // unknown
-  #define ADV_TYPE_CHAT         1
-  #define ADV_TYPE_REPEATER     2
-  #define ADV_TYPE_ROOM         3   // New kid on the block!
-  //FUTURE: 4..15
-
-  #define ADV_LATLON_MASK       0x10
-  #define ADV_BATTERY_MASK      0x20
-  #define ADV_TEMPERATURE_MASK  0x40
-  #define ADV_NAME_MASK         0x80
-
   void sendSelfAdvertisement() {
-    uint8_t app_data[MAX_ADVERT_DATA_SIZE+32];
-    app_data[0] = ADV_TYPE_ROOM | ADV_NAME_MASK;
-    int i = 1;
-    int32_t lat = ADVERT_LAT * 1E6;
-    int32_t lon = ADVERT_LON * 1E6;
-    if (!(lat == 0 && lon == 0)) {
-      app_data[0] |= ADV_LATLON_MASK;
-      memcpy(&app_data[i], &lat, 4); i += 4;
-      memcpy(&app_data[i], &lon, 4); i += 4;
+    uint8_t app_data[MAX_ADVERT_DATA_SIZE];
+    uint8_t app_data_len;
+    {
+      AdvertDataBuilder builder(ADV_TYPE_ROOM, ADVERT_NAME, ADVERT_LAT, ADVERT_LON);
+      app_data_len = builder.encodeTo(app_data);
     }
-    strcpy((char *)&app_data[i], ADVERT_NAME);
-    int app_data_len = i + strlen(ADVERT_NAME);
-    if (app_data_len > MAX_ADVERT_DATA_SIZE) {
-      app_data_len = MAX_ADVERT_DATA_SIZE;
-      app_data[MAX_ADVERT_DATA_SIZE - 1] = 0;  // truncate the ADVERT_NAME
-    }
- 
+
     mesh::Packet* pkt = createAdvert(self_id, app_data, app_data_len);
     if (pkt) {
       sendFlood(pkt, 1200);  // add slight delay
@@ -504,6 +484,7 @@ public:
         if (c->pending_ack && millisHasNowPassed(c->ack_timeout)) {
           c->push_failures++;
           c->pending_ack = 0;   // reset  (TODO: keep prev expected_ack's in a list, incase they arrive LATER, after we retry)
+          MESH_DEBUG_PRINTLN("pending ACK timed out: push_failures: %d", (uint32_t)c->push_failures);
 
           if (c->push_failures >= 3) {
             evict(c);

+ 11 - 11
examples/simple_secure_chat/main.cpp

@@ -7,6 +7,7 @@
 #include <helpers/ArduinoHelpers.h>
 #include <helpers/StaticPoolPacketManager.h>
 #include <helpers/SimpleMeshTables.h>
+#include <helpers/AdvertDataHelpers.h>
 
 /* ---------------------------------- CONFIGURATION ------------------------------------- */
 
@@ -132,14 +133,11 @@ protected:
       }
     }
     // unknown node
-    if (app_data_len > 0 && app_data[0] == (ADV_TYPE_CHAT | ADV_NAME_MASK)) {  // is it a 'Chat' node (with a name)?
+    AdvertDataParser parser(app_data, app_data_len);
+    if (parser.getType() == ADV_TYPE_CHAT && parser.hasName()) {  // is it a 'Chat' node (with a name)?
       // automatically add to our contacts
-      char name[32];
-      memcpy(name, &app_data[1], app_data_len - 1);
-      name[app_data_len - 1] = 0;  // need null terminator
-
-      addContact(name, id);
-      Serial.printf("   ADDED contact: %s\n", name);
+      addContact(parser.getName(), id);
+      Serial.printf("   ADDED contact: %s\n", parser.getName());
     } else {
       Serial.printf("   Unknown app_data type: %02X, len=%d\n", app_data[0], app_data_len);
     }
@@ -268,10 +266,12 @@ public:
   }
 
   void sendSelfAdvert() {
-    uint8_t app_data[32];
-    app_data[0] = ADV_TYPE_CHAT | ADV_NAME_MASK;
-    strcpy((char *)&app_data[1], USER_NAME);
-    int app_data_len = 1 + strlen(USER_NAME);
+    uint8_t app_data[MAX_ADVERT_DATA_SIZE];
+    uint8_t app_data_len;
+    {
+      AdvertDataBuilder builder(ADV_TYPE_CHAT, USER_NAME);
+      app_data_len = builder.encodeTo(app_data);
+    }
  
     mesh::Packet* adv = createAdvert(self_id, app_data, app_data_len);
     if (adv) {

+ 101 - 0
src/helpers/AdvertDataHelpers.h

@@ -0,0 +1,101 @@
+#pragma once
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define ADV_TYPE_NONE         0   // unknown
+#define ADV_TYPE_CHAT         1
+#define ADV_TYPE_REPEATER     2
+#define ADV_TYPE_ROOM         3   // New kid on the block!
+//FUTURE: 4..15
+
+#define ADV_LATLON_MASK       0x10
+#define ADV_BATTERY_MASK      0x20
+#define ADV_TEMPERATURE_MASK  0x40
+#define ADV_NAME_MASK         0x80
+
+class AdvertDataBuilder {
+  uint8_t _type;
+  const char* _name;
+  int32_t _lat, _lon;
+public:
+  AdvertDataBuilder(uint8_t adv_type) : _type(adv_type), _name(NULL), _lat(0), _lon(0) { }
+  AdvertDataBuilder(uint8_t adv_type, const char* name) : _type(adv_type), _name(name), _lat(0), _lon(0)  { }
+  AdvertDataBuilder(uint8_t adv_type, const char* name, double lat, double lon) : 
+      _type(adv_type), _name(name), _lat(lat * 1E6), _lon(lon * 1E6)  { }
+
+  /**
+   * \brief  encode the given advertisement data.
+   * \param app_data  dest array, must be MAX_ADVERT_DATA_SIZE
+   * \returns  the encoded length in bytes
+   */
+  uint8_t encodeTo(uint8_t app_data[]) {
+    app_data[0] = _type;
+    int i = 1;
+    if (!(_lat == 0 && _lon == 0)) {
+      app_data[0] |= ADV_LATLON_MASK;
+      memcpy(&app_data[i], &_lat, 4); i += 4;
+      memcpy(&app_data[i], &_lon, 4); i += 4;
+    }
+    // TODO:  BATTERY encoding
+    // TODO:  TEMPERATURE encoding
+    if (_name && *_name != 0) { 
+      app_data[0] |= ADV_NAME_MASK;
+      const char* sp = _name;
+      while (*sp && i < MAX_ADVERT_DATA_SIZE) {
+        app_data[i++] = *sp++;
+      }
+    }
+    return i;
+  }
+};
+
+class AdvertDataParser {
+  uint8_t _flags;
+  bool _valid;
+  char _name[MAX_ADVERT_DATA_SIZE];
+  int32_t _lat, _lon;
+public:
+  AdvertDataParser(const uint8_t app_data[], uint8_t app_data_len) {
+    _name[0] = 0;
+    _lat = _lon = 0;
+    _flags = app_data[0];
+    _valid = false;
+
+    int i = 1;
+    if (_flags & ADV_LATLON_MASK) {
+      memcpy(&_lat, &app_data[i], 4); i += 4;
+      memcpy(&_lon, &app_data[i], 4); i += 4;
+    }
+    if (_flags & ADV_BATTERY_MASK) {
+      /* TODO: somewhere to store battery volts? */ i += 2;
+    }
+    if (_flags & ADV_TEMPERATURE_MASK) {
+      /* TODO: somewhere to store temperature? */ i += 2;
+    }
+
+    if (app_data_len >= i) {
+      int nlen = 0;
+      if (_flags & ADV_NAME_MASK) {
+        nlen = app_data_len - i;  // remainder of app_data
+      }
+      if (nlen > 0) {
+        memcpy(_name, &app_data[i], nlen);
+        _name[nlen] = 0;  // set null terminator
+      }
+      _valid = true;
+    }
+  }
+
+  bool isValid() const { return _valid; }
+  uint8_t getType() const { return _flags & 0x0F; }
+
+  bool hasName() const { _name[0] != 0; }
+  const char* getName() const { return _name; }
+
+  bool hasLatLon() const { return !(_lat == 0 && _lon == 0); }
+  int32_t getIntLat() const { return _lat; }
+  int32_t getIntLon() const { return _lon; }
+  double getLat() const { return ((double)_lat) / 1000000.0; }
+  double getLon() const { return ((double)_lon) / 1000000.0; }
+};