From 068aeee87f2cb787c747dfadc47129fbc20ed892 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Fri, 24 Jan 2025 11:41:37 +1100 Subject: [PATCH] * Refactor: new AdvertDataHelpers.h --- examples/simple_repeater/main.cpp | 33 ++------- examples/simple_room_server/main.cpp | 35 +++------- examples/simple_secure_chat/main.cpp | 22 +++--- src/helpers/AdvertDataHelpers.h | 101 +++++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 64 deletions(-) create mode 100644 src/helpers/AdvertDataHelpers.h diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index cb19cf14..29187afd 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include /* ------------------------------ 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 diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index c80cd4c7..02b8dc46 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include /* ------------------------------ 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); diff --git a/examples/simple_secure_chat/main.cpp b/examples/simple_secure_chat/main.cpp index f7b3617c..58094de6 100644 --- a/examples/simple_secure_chat/main.cpp +++ b/examples/simple_secure_chat/main.cpp @@ -7,6 +7,7 @@ #include #include #include +#include /* ---------------------------------- 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) { diff --git a/src/helpers/AdvertDataHelpers.h b/src/helpers/AdvertDataHelpers.h new file mode 100644 index 00000000..985e28bc --- /dev/null +++ b/src/helpers/AdvertDataHelpers.h @@ -0,0 +1,101 @@ +#pragma once + +#include +#include + +#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; } +};