Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix GPS geotag support for different firmware versions. #96

Merged
merged 8 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions lib/furble/CameraList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ static std::vector<index_entry_t> load_index(void) {
if (bytes > 0 && (bytes % sizeof(index_entry_t) == 0)) {
uint8_t buffer[bytes] = {0};
size_t count = bytes / sizeof(index_entry_t);
Serial.println("Index entries: " + String(count));
Serial.printf("Index entries: %d\r\n", count);
m_Prefs.getBytes(FURBLE_PREF_INDEX, buffer, bytes);
index_entry_t *entry = (index_entry_t *)buffer;

for (int i = 0; i < count; i++) {
Serial.println("Loading index entry: " + String(entry[i].name));
Serial.printf("Loading index entry: %s\r\n", entry[i].name);
index.push_back(entry[i]);
}
}
Expand All @@ -57,7 +57,7 @@ static std::vector<index_entry_t> load_index(void) {
static void add_index(std::vector<index_entry_t> &index, index_entry_t &entry) {
bool exists = false;
for (size_t i = 0; i < index.size(); i++) {
Serial.println("[" + String(i) + "] " + String(index[i].name) + " : " + String(entry.name));
Serial.printf("[%d] %s : %s\r\n", i, index[i].name, entry.name);
if (strcmp(index[i].name, entry.name) == 0) {
Serial.println("Overwriting existing entry");
index[i] = entry;
Expand Down Expand Up @@ -87,10 +87,9 @@ void CameraList::save(Camera *pCamera) {
if (pCamera->serialise(dbuffer, dbytes)) {
// Store the entry and the index if serialisation succeeds
m_Prefs.putBytes(entry.name, dbuffer, dbytes);
Serial.println("Saved " + String(entry.name));
Serial.printf("Saved %s\r\n", entry.name);
save_index(index);
Serial.print("Index entries: ");
Serial.println(index.size());
Serial.printf("Index entries: %d\r\n", index.size());
}

m_Prefs.end();
Expand Down
4 changes: 2 additions & 2 deletions lib/furble/CanonEOS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ CanonEOS::CanonEOS(const void *data, size_t len) {
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()));
Serial.printf("Name = %s\r\n", m_Name.c_str());
Serial.printf("Address = %s\r\n", m_Address.toString().c_str());
Device::getUUID128(&m_Uuid);
}

Expand Down
144 changes: 74 additions & 70 deletions lib/furble/Fujifilm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ static const NimBLEUUID FUJIFILM_SVC_GEOTAG_UUID =
static const NimBLEUUID FUJIFILM_CHR_GEOTAG_UUID =
NimBLEUUID("0f36ec14-29e5-411a-a1b6-64ee8383f090");

static const uint16_t FUJIFILM_CHR_CONFIGURE = 0x5022;
static const uint16_t FUJIFILM_GEOTAG_UPDATE = 0x5042;
static const NimBLEUUID FUJIFILM_GEOTAG_UPDATE = NimBLEUUID("ad06c7b7-f41a-46f4-a29a-712055319122");

static const uint8_t FUJIFILM_SHUTTER_CMD[2] = {0x01, 0x00};
static const uint8_t FUJIFILM_SHUTTER_PRESS[2] = {0x02, 0x00};
Expand All @@ -58,35 +57,28 @@ static const uint8_t FUJIFILM_SHUTTER_FOCUS[2] = {0x03, 0x00};
namespace Furble {

static void print_token(const uint8_t *token) {
Serial.println("Token = " + String(token[0], HEX) + String(token[1], HEX) + String(token[2], HEX)
+ String(token[3], HEX));
Serial.printf("Token = %02x%02x%02x%02x\r\n", token[0], token[1], token[2], token[3]);
}

void Fujifilm::notify(BLERemoteCharacteristic *pChr, uint8_t *pData, size_t length, bool isNotify) {
Serial.printf("Got %s callback: %u bytes from 0x%04x\r\n",
isNotify ? "notification" : "indication", length, pChr->getHandle());
Serial.printf("Got %s callback: %u bytes from %s\r\n", isNotify ? "notification" : "indication",
length, pChr->getUUID().toString().c_str());
if (length > 0) {
for (int i = 0; i < length; i++) {
Serial.printf(" [%d] 0x%02x\r\n", i, pData[i]);
}
}

switch (pChr->getHandle()) {
case FUJIFILM_CHR_CONFIGURE:
if ((length >= 2) && (pData[0] == 0x02) && (pData[1] == 0x00)) {
m_Configured = true;
}
break;

case FUJIFILM_GEOTAG_UPDATE:
if ((length >= 2) && (pData[0] == 0x01) && (pData[1] == 0x00) && m_GeoDataValid) {
m_GeoRequested = true;
}
break;

default:
Serial.println("Unhandled notification handle.");
break;
if (pChr->getUUID() == FUJIFILM_CHR_NOT1_UUID) {
if ((length >= 2) && (pData[0] == 0x02) && (pData[1] == 0x00)) {
m_Configured = true;
}
} else if (pChr->getUUID() == FUJIFILM_GEOTAG_UPDATE) {
if ((length >= 2) && (pData[0] == 0x01) && (pData[1] == 0x00)) {
m_GeoRequested = true;
}
} else {
Serial.println("Unhandled notification handle.");
}
}

Expand All @@ -108,8 +100,8 @@ Fujifilm::Fujifilm(NimBLEAdvertisedDevice *pDevice) {
m_Token[1] = data[4];
m_Token[2] = data[5];
m_Token[3] = data[6];
Serial.println("Name = " + String(m_Name.c_str()));
Serial.println("Address = " + String(m_Address.toString().c_str()));
Serial.printf("Name = %s\r\n", m_Name.c_str());
Serial.printf("Address = %s\r\n", m_Address.toString().c_str());
print_token(m_Token);
}

Expand Down Expand Up @@ -188,11 +180,21 @@ bool Fujifilm::connect(progressFunc pFunc, void *pCtx) {
pSvc = m_Client->getService(FUJIFILM_SVC_CONF_UUID);
// indications
pSvc->getCharacteristic(FUJIFILM_CHR_IND1_UUID)
->subscribe(false, std::bind(&Fujifilm::notify, this, _1, _2, _3, _4), true);
->subscribe(
false,
[this](BLERemoteCharacteristic *pChr, uint8_t *pData, size_t length, bool isNotify) {
this->notify(pChr, pData, length, isNotify);
},
true);
updateProgress(pFunc, pCtx, 50.0f);

pSvc->getCharacteristic(FUJIFILM_CHR_IND2_UUID)
->subscribe(false, std::bind(&Fujifilm::notify, this, _1, _2, _3, _4), true);
->subscribe(
false,
[this](BLERemoteCharacteristic *pChr, uint8_t *pData, size_t length, bool isNotify) {
this->notify(pChr, pData, length, isNotify);
},
true);

// wait for up to 5000ms callback
for (unsigned int i = 0; i < 5000; i += 100) {
Expand All @@ -206,28 +208,30 @@ bool Fujifilm::connect(progressFunc pFunc, void *pCtx) {
updateProgress(pFunc, pCtx, 60.0f);
// notifications
pSvc->getCharacteristic(FUJIFILM_CHR_NOT1_UUID)
->subscribe(true, std::bind(&Fujifilm::notify, this, _1, _2, _3, _4), true);
->subscribe(
true,
[this](BLERemoteCharacteristic *pChr, uint8_t *pData, size_t length, bool isNotify) {
this->notify(pChr, pData, length, isNotify);
},
true);

updateProgress(pFunc, pCtx, 70.0f);
pSvc->getCharacteristic(FUJIFILM_CHR_NOT2_UUID)
->subscribe(true, std::bind(&Fujifilm::notify, this, _1, _2, _3, _4), true);
->subscribe(
true,
[this](BLERemoteCharacteristic *pChr, uint8_t *pData, size_t length, bool isNotify) {
this->notify(pChr, pData, length, isNotify);
},
true);

updateProgress(pFunc, pCtx, 80.0f);
pSvc->getCharacteristic(FUJIFILM_CHR_IND3_UUID)
->subscribe(false, std::bind(&Fujifilm::notify, this, _1, _2, _3, _4), true);

updateProgress(pFunc, pCtx, 90.0f);
// wait for up to 5000ms for geotag request
for (unsigned int i = 0; i < 5000; i += 100) {
if (m_GeoRequested) {
sendGeoData();
m_GeoRequested = false;
break;
}
updateProgress(pFunc, pCtx, 90.0f + (((float)i / 5000.0f) * 10.0f));
delay(100);
}

->subscribe(
false,
[this](BLERemoteCharacteristic *pChr, uint8_t *pData, size_t length, bool isNotify) {
this->notify(pChr, pData, length, isNotify);
},
true);
Serial.println("Configured");

updateProgress(pFunc, pCtx, 100.0f);
Expand Down Expand Up @@ -260,52 +264,52 @@ void Fujifilm::focusRelease(void) {
shutterRelease();
}

void Fujifilm::sendGeoData(void) {
void Fujifilm::sendGeoData(gps_t &gps, timesync_t &timesync) {
NimBLERemoteService *pSvc = m_Client->getService(FUJIFILM_SVC_GEOTAG_UUID);
NimBLERemoteCharacteristic *pChr = pSvc->getCharacteristic(FUJIFILM_CHR_GEOTAG_UUID);
if (pSvc == nullptr) {
return;
}

geotag_t geotag = {.latitude = (int32_t)(m_GPS.latitude * 10000000),
.longitude = (int32_t)(m_GPS.longitude * 10000000),
.altitude = (int32_t)m_GPS.altitude,
.pad = {0},
.gps_time = {
.year = (uint16_t)m_TimeSync.year,
.day = (uint8_t)m_TimeSync.day,
.month = (uint8_t)m_TimeSync.month,
.hour = (uint8_t)m_TimeSync.hour,
.minute = (uint8_t)m_TimeSync.minute,
.second = (uint8_t)m_TimeSync.second,
}};
NimBLERemoteCharacteristic *pChr = pSvc->getCharacteristic(FUJIFILM_CHR_GEOTAG_UUID);
if (pChr == nullptr) {
return;
}

if (pChr->canWrite()) {
geotag_t geotag = {.latitude = (int32_t)(gps.latitude * 10000000),
.longitude = (int32_t)(gps.longitude * 10000000),
.altitude = (int32_t)gps.altitude,
.pad = {0},
.gps_time = {
.year = (uint16_t)timesync.year,
.day = (uint8_t)timesync.day,
.month = (uint8_t)timesync.month,
.hour = (uint8_t)timesync.hour,
.minute = (uint8_t)timesync.minute,
.second = (uint8_t)timesync.second,
}};

Serial.printf("Sending geotag data (%u bytes) to 0x%04x\r\n", sizeof(geotag),
pChr->getHandle());
Serial.printf(" lat: %f, %d\r\n", m_GPS.latitude, geotag.latitude);
Serial.printf(" lon: %f, %d\r\n", m_GPS.longitude, geotag.longitude);
Serial.printf(" alt: %f, %d\r\n", m_GPS.altitude, geotag.altitude);
Serial.printf(" lat: %f, %d\r\n", gps.latitude, geotag.latitude);
Serial.printf(" lon: %f, %d\r\n", gps.longitude, geotag.longitude);
Serial.printf(" alt: %f, %d\r\n", gps.altitude, geotag.altitude);

pChr->writeValue((uint8_t *)&geotag, sizeof(geotag), true);
}
}

void Fujifilm::updateGeoData(gps_t &gps, timesync_t &timesync) {
m_GPS = gps;
m_TimeSync = timesync;
m_GeoDataValid = true;

if (m_GeoRequested) {
sendGeoData();
sendGeoData(gps, timesync);
m_GeoRequested = false;
}
}

void Fujifilm::print(void) {
Serial.print("Name: ");
Serial.println(m_Name.c_str());
Serial.print("Address: ");
Serial.println(m_Address.toString().c_str());
Serial.print("Type: ");
Serial.println(m_Address.getType());
Serial.printf("Name: %s\r\n", m_Name.c_str());
Serial.printf("Address: %s\r\n", m_Address.toString().c_str());
Serial.printf("Type: %d\r\n", m_Address.getType());
}

void Fujifilm::disconnect(void) {
Expand Down
6 changes: 1 addition & 5 deletions lib/furble/Fujifilm.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,12 @@ class Fujifilm: public Camera {
size_t getSerialisedBytes(void);
bool serialise(void *buffer, size_t bytes);
void notify(NimBLERemoteCharacteristic *, uint8_t *, size_t, bool);
void sendGeoData();
void sendGeoData(gps_t &gps, timesync_t &timesync);

uint8_t m_Token[FUJIFILM_TOKEN_LEN] = {0};

bool m_Configured = false;

bool m_GeoDataValid = false;
gps_t m_GPS = {0};
timesync_t m_TimeSync = {0};

volatile bool m_GeoRequested = false;
};

Expand Down
5 changes: 1 addition & 4 deletions src/furble.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ static void remote_control(FurbleCtx *fctx) {
show_shutter_control(false, 0);

do {
M5.update();
ez.yield();

furble_gps_update_geodata(camera);

Expand Down Expand Up @@ -137,9 +137,6 @@ static void remote_control(FurbleCtx *fctx) {
continue;
}
}

ez.yield();
delay(50);
} while (camera->isConnected());
}

Expand Down
6 changes: 3 additions & 3 deletions src/interval.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <Furble.h>
#include <M5ez.h>

#include "furble_gps.h"
#include "furble_ui.h"
#include "interval.h"
#include "settings.h"
Expand Down Expand Up @@ -78,8 +79,9 @@ static void do_interval(FurbleCtx *fctx, interval_t *interval) {
ez.backlight.inactivity(NEVER);

do {
ez.yield();
furble_gps_update_geodata(camera);
now = millis();
M5.update();

if (fctx->reconnected) {
fctx->reconnected = false;
Expand Down Expand Up @@ -130,9 +132,7 @@ static void do_interval(FurbleCtx *fctx, interval_t *interval) {
active = false;
}

ez.yield();
display_interval_msg(state, icount, &interval->count, now, next);
delay(10);
} while (active && camera->isConnected());
ez.backlight.inactivity(USER_SET);
}
Expand Down
11 changes: 4 additions & 7 deletions src/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ static void show_gps_info(void) {
bool first = true;

do {
if (M5.BtnB.wasReleased()) {
break;
}

bool updated = furble_gps.location.isUpdated() || furble_gps.date.isUpdated()
|| furble_gps.time.isUpdated();

Expand All @@ -114,14 +118,7 @@ static void show_gps_info(void) {
ez.msgBox("GPS Data", buffer, "Back", false);
}

M5.update();

if (M5.BtnB.wasPressed()) {
break;
}

ez.yield();
delay(100);
} while (true);
}

Expand Down