Compare commits

...

2 Commits

Author SHA1 Message Date
Dirk Hohndel
385498b9d0 core/BT: simplify detection of bluetooth names
Instead of that super long if-else if chain, have something more
structured using a table for the common case of prefix based names.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-01-23 14:26:54 -08:00
Dirk Hohndel
73d00a68c8 core/BT: improve BT name detection for Pelagic dive computers
It would be so much nicer if we could just let libdivecomputer do this,
but the filter function there doesn't quite do things the way we need
them to be. Which is why we have our own function here.

This is a small attempt to rationalize the code that we have to make it
easier to maintain.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-01-23 14:26:20 -08:00

View File

@ -17,6 +17,71 @@ namespace {
} }
BTDiscovery *BTDiscovery::m_instance = NULL; BTDiscovery *BTDiscovery::m_instance = NULL;
struct modelPattern {
uint16_t model;
const char *vendor;
const char *product;
};
static struct modelPattern model[] = {
{ 0x4552, "Oceanic", "Pro Plus X" },
{ 0x455A, "Aqualung", "i750TC" },
{ 0x4647, "Sherwood", "Sage" },
{ 0x4648, "Aqualung", "i300C" },
{ 0x4649, "Aqualung", "i200C" },
{ 0x4651, "Aqualung", "i770R" },
{ 0x4652, "Aqualung", "i550C" },
{ 0x4653, "Oceanic", "Geo 4.0" },
{ 0x4654, "Oceanic", "Veo 4.0" },
{ 0x4655, "Sherwood", "Wisdom 4" },
{ 0x4656, "Oceanic", "Pro Plus 4" },
{ 0x4743, "Aqualung", "i470TC" }
};
struct namePattern {
const char *prefix;
const char *vendor;
const char *product;
};
static struct namePattern name[] = {
// Shearwater dive computers
{ "Predator", "Shearwater", "Predator" },
// both the Petrel and Petrel 2 identify as "Petrel" as BT/BLE device
// but only the Petrel 2 is listed as available dive computer on iOS (which requires BLE support)
// so always pick the "Petrel 2" as product when seeing a Petrel
{ "Petrel", "Shearwater", "Petrel 2" },
{ "Perdix", "Shearwater", "Perdix" },
{ "Teric", "Shearwater", "Teric" },
{ "Peregrine", "Shearwater", "Peregrine" },
{ "NERD 2", "Shearwater", "NERD 2" },
{ "NERD", "Shearwater", "NERD" }, // order is important, test for the more specific one first
{ "Predator", "Shearwater", "Predator" },
{ "Predator", "Shearwater", "Predator" },
{ "Predator", "Shearwater", "Predator" },
// Suunto dive computers
{ "EON Steel", "Suunto", "EON Steel" },
{ "EON Core", "Suunto", "EON Core" },
{ "Suunto D5", "Suunto", "D5" },
// Scubapro dive computers
{ "G2", "Scubapro", "G2" },
{ "HUD", "Scubapro", "G2 HUD" },
{ "Aladin", "Scubapro", "Aladin Sport Matrix" },
{ "A1", "Scubapro", "Aladin A1" },
// Mares dive computers
{ "Mares Genius", "Mares", "Genius" },
{ "Mares", "Mares", "Quad" }, // we actually don't know and just pick a common one - user needs to fix in UI
// Cress dive computers
{ "CARESIO_", "Cressi", "Cartesio" },
{ "GOA_", "Cressi", "Goa" },
// Deepblu dive computesr
{ "COSMIQ", "Deepblu", "Cosmiq+" },
// Oceans dive computers
{ "S1", "Oceans", "S1" },
// McLean dive computers
{ "McLean Extreme", "McLean", "Extreme" },
// Tecdiving dive computers
{ "DiveComputer", "Tecdiving", "DiveComputer.eu" }
};
static dc_descriptor_t *getDeviceType(QString btName) static dc_descriptor_t *getDeviceType(QString btName)
// central function to convert a BT name to a Subsurface known vendor/model pair // central function to convert a BT name to a Subsurface known vendor/model pair
{ {
@ -34,83 +99,6 @@ static dc_descriptor_t *getDeviceType(QString btName)
// just use a default product that allows the codoe to download from the // just use a default product that allows the codoe to download from the
// user's dive computer // user's dive computer
else product = "OSTC 2"; else product = "OSTC 2";
} else if (btName.startsWith("Predator") ||
btName.startsWith("Petrel") ||
btName.startsWith("Perdix") ||
btName.startsWith("Teric") ||
btName.startsWith("Peregrine") ||
btName.startsWith("NERD")) {
vendor = "Shearwater";
// both the Petrel and Petrel 2 identify as "Petrel" as BT/BLE device
// but only the Petrel 2 is listed as available dive computer on iOS (which requires BLE support)
// so always pick the "Petrel 2" as product when seeing a Petrel
if (btName.startsWith("Petrel")) product = "Petrel 2";
if (btName.startsWith("Perdix")) product = "Perdix";
if (btName.startsWith("Predator")) product = "Predator";
if (btName.startsWith("Teric")) product = "Teric";
if (btName.startsWith("Peregrine")) product = "Peregrine";
if (btName.startsWith("NERD")) product = "Nerd"; // next line might override this
if (btName.startsWith("NERD 2")) product = "Nerd 2";
} else if (btName.startsWith("EON Steel")) {
vendor = "Suunto";
product = "EON Steel";
} else if (btName.startsWith("EON Core")) {
vendor = "Suunto";
product = "EON Core";
} else if (btName.startsWith("Suunto D5")) {
vendor = "Suunto";
product = "D5";
} else if (btName.startsWith("G2") || btName.startsWith("Aladin") || btName.startsWith("HUD") || btName.startsWith("A1")) {
vendor = "Scubapro";
if (btName.startsWith("G2")) product = "G2";
if (btName.startsWith("HUD")) product = "G2 HUD";
if (btName.startsWith("Aladin")) product = "Aladin Sport Matrix";
if (btName.startsWith("A1")) product = "Aladin A1";
} else if (btName.startsWith("Mares")) {
vendor = "Mares";
// we don't know which of the dive computers it is,
// so let's just randomly pick one
product = "Quad";
// Some we can pick out directly
if (btName.startsWith("Mares Genius"))
product = "Genius";
} else if (btName.startsWith("CARTESIO_")) {
vendor = "Cressi";
product = "Cartesio";
} else if (btName.startsWith("GOA_")) {
vendor = "Cressi";
product = "Goa";
} else if (btName.contains(QRegularExpression("^FI\\d{6}$"))) {
// The Pelagic dive computers (generally branded as Oceanic or Aqualung)
// show up with a two-byte model code followed by six bytes of serial
// number. The model code matches the hex model (so "FQ" is 0x4651,
// where 'F' is 46h and 'Q' is 51h in ASCII).
vendor = "Aqualung";
product = "i200C";
} else if (btName.contains(QRegularExpression("^FH\\d{6}$"))) {
vendor = "Aqualung";
product = "i300C";
} else if (btName.contains(QRegularExpression("^FQ\\d{6}$"))) {
vendor = "Aqualung";
product = "i770R";
} else if (btName.contains(QRegularExpression("^FR\\d{6}$"))) {
vendor = "Aqualung";
product = "i550C";
} else if (btName.contains(QRegularExpression("^FS\\d{6}$"))) {
vendor = "Oceanic";
product = "Geo 4.0";
} else if (btName.contains(QRegularExpression("^FT\\d{6}$"))) {
vendor = "Oceanic";
product = "Veo 4.0";
} else if (btName.contains(QRegularExpression("^FU\\d{6}$"))) {
vendor = "Sherwood";
product = "Wisdom 4";
} else if (btName.contains(QRegularExpression("^FV\\d{6}$"))) {
vendor = "Oceanic";
product = "ProPlus 4";
} else if (btName.contains(QRegularExpression("^ER\\d{6}$"))) {
vendor = "Oceanic";
product = "Pro Plus X";
} else if (btName.contains(QRegularExpression("^DS\\d{6}"))) { } else if (btName.contains(QRegularExpression("^DS\\d{6}"))) {
// The Ratio bluetooth name looks like the Pelagic ones, // The Ratio bluetooth name looks like the Pelagic ones,
// but that seems to be just happenstance. // but that seems to be just happenstance.
@ -121,18 +109,31 @@ static dc_descriptor_t *getDeviceType(QString btName)
// eventhough the physical model states iX3M. // eventhough the physical model states iX3M.
vendor = "Ratio"; vendor = "Ratio";
product = "iX3M GPS Easy"; // we don't know which of the GPS models, so set one product = "iX3M GPS Easy"; // we don't know which of the GPS models, so set one
} else if (btName == "COSMIQ") { } else if (btName.contains(QRegularExpression("^[A-Z]{2}\\d{6}"))) {
vendor = "Deepblu"; // try the Pelagic/Aqualung name patterns
product = "Cosmiq+"; // the source of truth for this data is in libdivecomputer/src/descriptor.c
} else if (btName.startsWith("S1")) { // we'd prefer to use the filter functions there but current design makes that really challenging
vendor = "Oceans"; // The Pelagic dive computers (generally branded as Oceanic, Aqualung, or Sherwood)
product = "S1"; // show up with a two-byte model code followed by six bytes of serial
} else if (btName.startsWith("McLean Extreme")) { // number. The model code matches the hex model (so "FQ" is 0x4651,
vendor = "McLean"; // where 'F' is 46h and 'Q' is 51h in ASCII).
product = "Extreme"; for (uint16_t i = 0; i < sizeof(model) / sizeof(struct modelPattern); i++) {
} else if (btName.startsWith("DiveComputer")) { QString pattern = QString("^%1%2\\d{6}$").arg(QChar(model[i].model >> 8)).arg(QChar(model[i].model & 0xFF));
vendor = "Tecdiving"; qDebug() << "trying pattern" << pattern;
product = "DiveComputer.eu"; if (btName.contains(QRegularExpression(pattern))) {
vendor = model[i].vendor;
product = model[i].product;
break;
}
}
} else { // finally try all the string prefix based ones
for (uint16_t i = 0; i < sizeof(name) / sizeof(struct namePattern); i++) {
if (btName.startsWith(name[i].prefix)) {
vendor = name[i].vendor;
product = name[i].product;
break;
}
}
} }
// check if we found a known dive computer // check if we found a known dive computer