Skip to content

Commit

Permalink
Add unique ID to connection parameter. (#84)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
gkoh authored Mar 14, 2024
1 parent 820c73b commit 988d1b3
Show file tree
Hide file tree
Showing 13 changed files with 134 additions and 86 deletions.
19 changes: 0 additions & 19 deletions lib/furble/Camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
18 changes: 0 additions & 18 deletions lib/furble/Camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand All @@ -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.
*/
Expand Down Expand Up @@ -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:
Expand Down
40 changes: 21 additions & 19 deletions lib/furble/CanonEOS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,26 @@
#include <NimBLERemoteService.h>

#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<const eos_t *>(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) {
m_Name = pDevice->getName();
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) {
Expand All @@ -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];
}
}

Expand Down Expand Up @@ -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");
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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<eos_t *>(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;
}
Expand Down
16 changes: 11 additions & 5 deletions lib/furble/CanonEOS.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define CANONEOS_H

#include "Camera.h"
#include "Device.h"

namespace Furble {
/**
Expand All @@ -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";
Expand Down Expand Up @@ -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
Expand Down
6 changes: 0 additions & 6 deletions lib/furble/CanonEOSM6.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 2 additions & 3 deletions lib/furble/CanonEOSM6.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 0 additions & 6 deletions lib/furble/CanonEOSRP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 2 additions & 3 deletions lib/furble/CanonEOSRP.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
41 changes: 41 additions & 0 deletions lib/furble/Device.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <Esp.h>

#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
45 changes: 45 additions & 0 deletions lib/furble/Device.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#ifndef DEVICE_H
#define DEVICE_H

#include <cstdint>

#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
7 changes: 4 additions & 3 deletions lib/furble/Fujifilm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <NimBLERemoteCharacteristic.h>
#include <NimBLERemoteService.h>

#include "Device.h"
#include "Fujifilm.h"

typedef struct _fujifilm_t {
Expand Down Expand Up @@ -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<const fujifilm_t *>(data);
m_Name = std::string(fujifilm->name);
m_Address = NimBLEAddress(fujifilm->address, fujifilm->type);
memcpy(m_Token, fujifilm->token, FUJIFILM_TOKEN_LEN);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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<fujifilm_t *>(buffer);
strncpy(x->name, m_Name.c_str(), 64);
x->address = (uint64_t)m_Address;
x->type = m_Address.getType();
Expand Down
Loading

0 comments on commit 988d1b3

Please sign in to comment.