From 988d1b3f807c375521389c92dd587b63449a70ed Mon Sep 17 00:00:00 2001 From: Guo-Rong <5484552+gkoh@users.noreply.github.com> Date: Thu, 14 Mar 2024 16:14:25 +1030 Subject: [PATCH] Add unique ID to connection parameter. (#84) * Minor C++ refactor. Use static_cast where possible. Migrate to class function binding rather than static. Default to parent class constructor using initialisers. * Add unique ID to connection parameter. When connecting, append a subset of the ESP32 'unique' identifier, which is derived from the device MAC address. --- lib/furble/Camera.cpp | 19 ----------------- lib/furble/Camera.h | 18 ---------------- lib/furble/CanonEOS.cpp | 40 +++++++++++++++++----------------- lib/furble/CanonEOS.h | 16 +++++++++----- lib/furble/CanonEOSM6.cpp | 6 ------ lib/furble/CanonEOSM6.h | 5 ++--- lib/furble/CanonEOSRP.cpp | 6 ------ lib/furble/CanonEOSRP.h | 5 ++--- lib/furble/Device.cpp | 41 +++++++++++++++++++++++++++++++++++ lib/furble/Device.h | 45 +++++++++++++++++++++++++++++++++++++++ lib/furble/Fujifilm.cpp | 7 +++--- lib/furble/Furble.cpp | 3 ++- src/furble.cpp | 9 +++++--- 13 files changed, 134 insertions(+), 86 deletions(-) create mode 100644 lib/furble/Device.cpp create mode 100644 lib/furble/Device.h diff --git a/lib/furble/Camera.cpp b/lib/furble/Camera.cpp index 49b6d5f..edb0b87 100644 --- a/lib/furble/Camera.cpp +++ b/lib/furble/Camera.cpp @@ -28,25 +28,6 @@ void Camera::updateProgress(progressFunc pFunc, void *ctx, float value) { } } -/** - * Generate a 32-bit PRNG. - */ -static uint32_t xorshift(uint32_t x) { - /* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */ - x ^= x << 13; - x ^= x << 17; - x ^= x << 5; - return x; -} - -void Camera::getUUID128(uuid128_t *uuid) { - uint32_t chip_id = (uint32_t)ESP.getEfuseMac(); - for (size_t i = 0; i < UUID128_AS_32_LEN; i++) { - chip_id = xorshift(chip_id); - uuid->uint32[i] = chip_id; - } -} - bool Camera::isConnected(void) { return m_Client->isConnected(); } diff --git a/lib/furble/Camera.h b/lib/furble/Camera.h index c8ae6d6..f1b8836 100644 --- a/lib/furble/Camera.h +++ b/lib/furble/Camera.h @@ -9,9 +9,6 @@ #define MAX_NAME (64) -#define UUID128_LEN (16) -#define UUID128_AS_32_LEN (UUID128_LEN / sizeof(uint32_t)) - // Progress update function typedef void(progressFunc(void *, float)); @@ -22,16 +19,6 @@ namespace Furble { */ class Camera { public: - /** - * UUID type. - */ - typedef struct _uuid128_t { - union { - uint32_t uint32[UUID128_AS_32_LEN]; - uint8_t uint8[UUID128_LEN]; - }; - } uuid128_t; - /** * GPS data type. */ @@ -99,11 +86,6 @@ class Camera { const char *getName(void); - /** - * Generate a device consistent 128-bit UUID. - */ - static void getUUID128(uuid128_t *uuid); - void fillSaveName(char *name); protected: diff --git a/lib/furble/CanonEOS.cpp b/lib/furble/CanonEOS.cpp index aa61061..b318f62 100644 --- a/lib/furble/CanonEOS.cpp +++ b/lib/furble/CanonEOS.cpp @@ -5,19 +5,18 @@ #include #include "CanonEOS.h" +#include "Device.h" namespace Furble { -static volatile uint8_t pair_result = 0x00; - CanonEOS::CanonEOS(const void *data, size_t len) { if (len != sizeof(eos_t)) throw; - const eos_t *eos = (eos_t *)data; + const eos_t *eos = static_cast(data); m_Name = std::string(eos->name); m_Address = NimBLEAddress(eos->address, eos->type); - memcpy(&m_Uuid, &eos->uuid, sizeof(uuid128_t)); + memcpy(&m_Uuid, &eos->uuid, sizeof(Device::uuid128_t)); } CanonEOS::CanonEOS(NimBLEAdvertisedDevice *pDevice) { @@ -25,7 +24,7 @@ CanonEOS::CanonEOS(NimBLEAdvertisedDevice *pDevice) { m_Address = pDevice->getAddress(); Serial.println("Name = " + String(m_Name.c_str())); Serial.println("Address = " + String(m_Address.toString().c_str())); - getUUID128(&m_Uuid); + Device::getUUID128(&m_Uuid); } CanonEOS::~CanonEOS(void) { @@ -34,13 +33,13 @@ CanonEOS::~CanonEOS(void) { } // Handle pairing notification -static void pairResultCallback(BLERemoteCharacteristic *pBLERemoteCharacteristic, - uint8_t *pData, - size_t length, - bool isNotify) { +void CanonEOS::pairCallback(BLERemoteCharacteristic *pBLERemoteCharacteristic, + uint8_t *pData, + size_t length, + bool isNotify) { if (!isNotify && (length > 0)) { Serial.printf("Got pairing callback: 0x%02x\n", pData[0]); - pair_result = pData[0]; + m_PairResult = pData[0]; } } @@ -77,11 +76,13 @@ bool CanonEOS::write_prefix(NimBLEClient *pClient, * handled by the underlying NimBLE and ESP32 libraries. */ bool CanonEOS::connect(progressFunc pFunc, void *pCtx) { + using namespace std::placeholders; + if (NimBLEDevice::isBonded(m_Address)) { // Already bonded? Assume pair acceptance! - pair_result = CANON_EOS_PAIR_ACCEPT; + m_PairResult = CANON_EOS_PAIR_ACCEPT; } else { - pair_result = 0x00; + m_PairResult = 0x00; } Serial.println("Connecting"); @@ -105,13 +106,14 @@ bool CanonEOS::connect(progressFunc pFunc, void *pCtx) { NimBLERemoteCharacteristic *pChr = pSvc->getCharacteristic(CANON_EOS_CHR_NAME_UUID); if ((pChr != nullptr) && pChr->canIndicate()) { Serial.println("Subscribed for pairing indication"); - pChr->subscribe(false, pairResultCallback); + pChr->subscribe(false, std::bind(&CanonEOS::pairCallback, this, _1, _2, _3, _4)); } } Serial.println("Identifying 1!"); + const char *name = Device::getStringID(); if (!write_prefix(m_Client, CANON_EOS_SVC_IDEN_UUID, CANON_EOS_CHR_NAME_UUID, 0x01, - (uint8_t *)FURBLE_STR, strlen(FURBLE_STR))) + (uint8_t *)name, strlen(name))) return false; updateProgress(pFunc, pCtx, 30.0f); @@ -125,7 +127,7 @@ bool CanonEOS::connect(progressFunc pFunc, void *pCtx) { Serial.println("Identifying 3!"); if (!write_prefix(m_Client, CANON_EOS_SVC_IDEN_UUID, CANON_EOS_CHR_IDEN_UUID, 0x04, - (uint8_t *)FURBLE_STR, strlen(FURBLE_STR))) + (uint8_t *)name, strlen(name))) return false; updateProgress(pFunc, pCtx, 50.0f); @@ -150,13 +152,13 @@ bool CanonEOS::connect(progressFunc pFunc, void *pCtx) { for (unsigned int i = 0; i < 60; i++) { float progress = 70.0f + (float(i) / 6.0f); updateProgress(pFunc, pCtx, progress); - if (pair_result != 0x00) { + if (m_PairResult != 0x00) { break; } delay(1000); } - if (pair_result != CANON_EOS_PAIR_ACCEPT) { + if (m_PairResult != CANON_EOS_PAIR_ACCEPT) { bool deleted = NimBLEDevice::deleteBond(m_Address); Serial.printf("Rejected, delete pairing: %d\n", deleted); return false; @@ -219,11 +221,11 @@ bool CanonEOS::serialise(void *buffer, size_t bytes) { if (bytes != sizeof(eos_t)) { return false; } - eos_t *x = (eos_t *)buffer; + eos_t *x = static_cast(buffer); strncpy(x->name, m_Name.c_str(), MAX_NAME); x->address = (uint64_t)m_Address; x->type = m_Address.getType(); - memcpy(&x->uuid, &m_Uuid, sizeof(uuid128_t)); + memcpy(&x->uuid, &m_Uuid, sizeof(Device::uuid128_t)); return true; } diff --git a/lib/furble/CanonEOS.h b/lib/furble/CanonEOS.h index 4d4fec6..dc39d0f 100644 --- a/lib/furble/CanonEOS.h +++ b/lib/furble/CanonEOS.h @@ -2,6 +2,7 @@ #define CANONEOS_H #include "Camera.h" +#include "Device.h" namespace Furble { /** @@ -15,10 +16,10 @@ class CanonEOS: public Camera { protected: typedef struct _eos_t { - char name[MAX_NAME]; /** Human readable device name. */ - uint64_t address; /** Device MAC address. */ - uint8_t type; /** Address type. */ - uuid128_t uuid; /** Our UUID. */ + char name[MAX_NAME]; /** Human readable device name. */ + uint64_t address; /** Device MAC address. */ + uint8_t type; /** Address type. */ + Device::uuid128_t uuid; /** Our UUID. */ } eos_t; const char *CANON_EOS_SVC_IDEN_UUID = "00010000-0000-1000-0000-d8492fffa821"; @@ -65,7 +66,12 @@ class CanonEOS: public Camera { size_t getSerialisedBytes(void); bool serialise(void *buffer, size_t bytes); - uuid128_t m_Uuid; + Device::uuid128_t m_Uuid; + + private: + volatile uint8_t m_PairResult = 0x00; + + void pairCallback(NimBLERemoteCharacteristic *, uint8_t *, size_t, bool); }; } // namespace Furble diff --git a/lib/furble/CanonEOSM6.cpp b/lib/furble/CanonEOSM6.cpp index 4c758cd..efc7741 100644 --- a/lib/furble/CanonEOSM6.cpp +++ b/lib/furble/CanonEOSM6.cpp @@ -8,12 +8,6 @@ namespace Furble { -CanonEOSM6::CanonEOSM6(const void *data, size_t len) : CanonEOS(data, len) {} - -CanonEOSM6::CanonEOSM6(NimBLEAdvertisedDevice *pDevice) : CanonEOS(pDevice) {} - -CanonEOSM6::~CanonEOSM6(void) {} - const size_t CANON_EOS_M6_ADV_DATA_LEN = 21; const uint8_t CANON_EOS_M6_ID_0 = 0xa9; const uint8_t CANON_EOS_M6_ID_1 = 0x01; diff --git a/lib/furble/CanonEOSM6.h b/lib/furble/CanonEOSM6.h index f0b866d..2e821cc 100644 --- a/lib/furble/CanonEOSM6.h +++ b/lib/furble/CanonEOSM6.h @@ -9,9 +9,8 @@ namespace Furble { */ class CanonEOSM6: public CanonEOS { public: - CanonEOSM6(const void *data, size_t len); - CanonEOSM6(NimBLEAdvertisedDevice *pDevice); - ~CanonEOSM6(void); + CanonEOSM6(const void *data, size_t len) : CanonEOS(data, len){}; + CanonEOSM6(NimBLEAdvertisedDevice *pDevice) : CanonEOS(pDevice){}; /** * Determine if the advertised BLE device is a Canon EOS M6. diff --git a/lib/furble/CanonEOSRP.cpp b/lib/furble/CanonEOSRP.cpp index 37ce906..cf30eed 100644 --- a/lib/furble/CanonEOSRP.cpp +++ b/lib/furble/CanonEOSRP.cpp @@ -8,12 +8,6 @@ namespace Furble { -CanonEOSRP::CanonEOSRP(const void *data, size_t len) : CanonEOS(data, len) {} - -CanonEOSRP::CanonEOSRP(NimBLEAdvertisedDevice *pDevice) : CanonEOS(pDevice) {} - -CanonEOSRP::~CanonEOSRP(void) {} - const size_t CANON_EOS_RP_ADV_DATA_LEN = 8; const uint8_t CANON_EOS_RP_ID_0 = 0xa9; const uint8_t CANON_EOS_RP_ID_1 = 0x01; diff --git a/lib/furble/CanonEOSRP.h b/lib/furble/CanonEOSRP.h index 6e6568d..0c088a0 100644 --- a/lib/furble/CanonEOSRP.h +++ b/lib/furble/CanonEOSRP.h @@ -9,9 +9,8 @@ namespace Furble { */ class CanonEOSRP: public CanonEOS { public: - CanonEOSRP(const void *data, size_t len); - CanonEOSRP(NimBLEAdvertisedDevice *pDevice); - ~CanonEOSRP(void); + CanonEOSRP(const void *data, size_t len) : CanonEOS(data, len){}; + CanonEOSRP(NimBLEAdvertisedDevice *pDevice) : CanonEOS(pDevice){}; /** * Determine if the advertised BLE device is a Canon EOS RP. diff --git a/lib/furble/Device.cpp b/lib/furble/Device.cpp new file mode 100644 index 0000000..da5135e --- /dev/null +++ b/lib/furble/Device.cpp @@ -0,0 +1,41 @@ +#include + +#include "Device.h" +#include "FurbleTypes.h" + +namespace Furble { + +Device::uuid128_t Device::g_Uuid; +char Device::g_StringID[DEVICE_ID_STR_MAX]; + +/** + * Generate a 32-bit PRNG. + */ +static uint32_t xorshift(uint32_t x) { + /* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */ + x ^= x << 13; + x ^= x << 17; + x ^= x << 5; + return x; +} + +void Device::init(void) { + uint32_t chip_id = (uint32_t)ESP.getEfuseMac(); + for (size_t i = 0; i < UUID128_AS_32_LEN; i++) { + chip_id = xorshift(chip_id); + g_Uuid.uint32[i] = chip_id; + } + + // truncate ID to 5 hex characters (arbitrary, just make it 'nice' to read) + snprintf(g_StringID, DEVICE_ID_STR_MAX, "%s-%05x", FURBLE_STR, g_Uuid.uint32[0] & 0xFFFFF); +} + +void Device::getUUID128(uuid128_t *uuid) { + *uuid = g_Uuid; +} + +const char *Device::getStringID(void) { + return g_StringID; +} + +} // namespace Furble diff --git a/lib/furble/Device.h b/lib/furble/Device.h new file mode 100644 index 0000000..4760ef8 --- /dev/null +++ b/lib/furble/Device.h @@ -0,0 +1,45 @@ +#ifndef DEVICE_H +#define DEVICE_H + +#include + +#define DEVICE_ID_STR_MAX (16) +#define UUID128_LEN (16) +#define UUID128_AS_32_LEN (UUID128_LEN / sizeof(uint32_t)) + +namespace Furble { + +class Device { + public: + /** + * UUID type. + */ + typedef struct _uuid128_t { + union { + uint32_t uint32[UUID128_AS_32_LEN]; + uint8_t uint8[UUID128_LEN]; + }; + } uuid128_t; + + /** + * Initialise the device. + */ + static void init(void); + + /** + * Return a device consistent 128-bit UUID. + */ + static void getUUID128(uuid128_t *uuid); + + /** + * Return pseudo-unique identifier string of this device. + */ + static const char *getStringID(void); + + private: + static uuid128_t g_Uuid; + static char g_StringID[DEVICE_ID_STR_MAX]; +}; +} // namespace Furble + +#endif diff --git a/lib/furble/Fujifilm.cpp b/lib/furble/Fujifilm.cpp index 3e042a1..3dfe7de 100644 --- a/lib/furble/Fujifilm.cpp +++ b/lib/furble/Fujifilm.cpp @@ -4,6 +4,7 @@ #include #include +#include "Device.h" #include "Fujifilm.h" typedef struct _fujifilm_t { @@ -93,7 +94,7 @@ Fujifilm::Fujifilm(const void *data, size_t len) { if (len != sizeof(fujifilm_t)) throw; - const fujifilm_t *fujifilm = (fujifilm_t *)data; + const fujifilm_t *fujifilm = static_cast(data); m_Name = std::string(fujifilm->name); m_Address = NimBLEAddress(fujifilm->address, fujifilm->type); memcpy(m_Token, fujifilm->token, FUJIFILM_TOKEN_LEN); @@ -178,7 +179,7 @@ bool Fujifilm::connect(progressFunc pFunc, void *pCtx) { pChr = pSvc->getCharacteristic(FUJIFILM_CHR_IDEN_UUID); if (!pChr->canWrite()) return false; - if (!pChr->writeValue(FURBLE_STR, true)) + if (!pChr->writeValue(Device::getStringID(), true)) return false; Serial.println("Identified!"); updateProgress(pFunc, pCtx, 40.0f); @@ -323,7 +324,7 @@ bool Fujifilm::serialise(void *buffer, size_t bytes) { if (bytes != sizeof(fujifilm_t)) { return false; } - fujifilm_t *x = (fujifilm_t *)buffer; + fujifilm_t *x = static_cast(buffer); strncpy(x->name, m_Name.c_str(), 64); x->address = (uint64_t)m_Address; x->type = m_Address.getType(); diff --git a/lib/furble/Furble.cpp b/lib/furble/Furble.cpp index f42468c..2d58ce6 100644 --- a/lib/furble/Furble.cpp +++ b/lib/furble/Furble.cpp @@ -1,6 +1,7 @@ #include #include +#include "Device.h" #include "Furble.h" namespace Furble { @@ -22,7 +23,7 @@ class Scan::AdvertisedCallback: public NimBLEAdvertisedDeviceCallbacks { void Scan::init(esp_power_level_t power, scanResultCallback scanCallback) { m_ScanResultCallback = scanCallback; - NimBLEDevice::init(FURBLE_STR); + NimBLEDevice::init(Device::getStringID()); NimBLEDevice::setPower(power); NimBLEDevice::setSecurityAuth(true, true, true); Scan::m_Scan = NimBLEDevice::getScan(); diff --git a/src/furble.cpp b/src/furble.cpp index 1def98e..d276ef1 100644 --- a/src/furble.cpp +++ b/src/furble.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -14,7 +15,7 @@ const uint32_t SCAN_DURATION = 10; * Progress bar update function. */ void update_progress_bar(void *ctx, float value) { - ezProgressBar *progress_bar = (ezProgressBar *)ctx; + ezProgressBar *progress_bar = static_cast(ctx); progress_bar->value(value); } @@ -34,7 +35,8 @@ static void about(void) { version = "unknown"; } - ez.msgBox(FURBLE_STR " - About", "Version: " + version, "Back", true); + ez.msgBox(FURBLE_STR " - About", "Version: " + version + "|ID: " + Furble::Device::getStringID(), + "Back", true); } static void show_shutter_control(bool shutter_locked, unsigned long lock_start_ms) { @@ -149,7 +151,7 @@ static void remote_control(FurbleCtx *fctx) { } uint16_t disconnectDetect(void *private_data) { - FurbleCtx *fctx = (FurbleCtx *)private_data; + FurbleCtx *fctx = static_cast(private_data); Furble::Camera *camera = fctx->camera; if (camera->isConnected()) @@ -294,6 +296,7 @@ void setup() { #include ez.begin(); + Furble::Device::init(); furble_gps_init(); Furble::Scan::init(settings_load_esp_tx_power(), onScanResult);