BLYNK
HOME       📲 GETTING STARTED       📗 DOCS       ❓HELP CENTER       👉 SKETCH BUILDER

Bluetooth bridge help (rebroadcast BLE signal) for Dexcom

To whom it may concern,
My college senior design team and I are working on a project to recieve bluetooth BLE data from a Dexcom G6 transmitter to an arduino nano 33 iot and rebroadcast this data to another arduino nano 33 iot. The intent of the project to to provide a much wider range for the Dexcom transmitter. Is there a way to rebroadcast this data from one arduino to the next? I’ve seen tutorials for a bridge setup but that was with a device connected directly to an analog or digital pin to the board, not a BLE signaled input. I was thinking of somehow setting the BLE input to virtual pins but I’m not sure that’s possible. I have attached the code my team member put together to scan for dexcom devices. On our arduino serial monitor screen, we can see the UUIDs of the Dexcom transmitter. We are just trying to rebroadcast this information and eventually rebroadcast this information through a series of arduinos throughout an entire house. Any help would be greatly appreciated.

-Blynk app on iphone Xr with arduino nano 33 iot

//  This code is (ultimately) designed to identify and re-broadcast
//  data packets from a Dexcom transmitter to an endpoint such as a
//  smartphone or the Dexcom receiver.
//
//  8  Jan 2021 :  Initial revision using Arduino examples
//  14 Jan 2021 :  Separated code into setup and loop instead of just setup
//  28 Jan 2021 :  Realised scan() is a background process, put into setup
//  1  Feb 2021 :  Added some basic attribute and characteristic sections
//  2  Feb 2021 :  Used Service ID from BT SIG document for Dexcom (0xFEBC)
//  8  Feb 2021 :  Can see Dexcom advert for G5 and G6 (can't connect)
//  10 Feb 2021 :  need stopScan() to prep transmitter for connection
//  11 Feb 2021 :  able to view the discrete UUIDs for characteristics
//  12 Feb 2021 :  start of rewrite into discrete functions instead of one loop
//  15 Feb 2021 :  working again - really struggled with parameter passing
//  16 Feb 2021 :  finally figured out how to read characteristic data
//  17 Feb 2021 :  starting integration of peripheral functionality

// include any libraries or functions here
#include <ArduinoBLE.h>

//************************************************************************//
// Variable Declaration                                                   //
//************************************************************************//
bool connectFlag = false;                           // stable BLE connection indicator
bool repeatForever = true;                          // false = stop after 1 scan, true = repeats
bool initDone = false;                              // for bypassing peripheral code setup
bool centCon = false;                               // toggle for turning off repeated messages

byte devCount = 0;                                  // num. of devices found
byte charCount = 0;                                 // characteristics counter
byte descCount = 0;                                 // descriptors counter
byte servCount = 0;                                 // number of services offered
byte charBuf[512];                                  // characteristic read buffer
byte descBuf[512];                                  // descriptor read buffer

char periphAddr[18];                                // MAC address of advertising peripheral
const byte maxNodeCnt = 16;                         // maximum num. of BLE devices supported
const char dexcomUUID[5] = "febc";                  // Dexcom corporate service ID + null
const char* servDexcomUUID;                         // services UUID pointer
const uint16_t companyID = {0x00d0};                // mfg data - peripheral code
const uint8_t mfgBuf[2] = {0xdb, 0x03};             // mfg data - peripheral code

float version = 11.0;                               // version control?  What version control?

String periphAddrDB[maxNodeCnt] = {periphAddr};     // (volatile) list of BLE peripherals

BLEDevice central;                                  // globally declared for all functions
BLEDevice peripheral;                               // globally declared for all functions
BLEService servDexcom;                              // variable for BLE service
BLECharacteristic charDexcom;                       // variable for BLE characteristic
BLEDescriptor descDexcom;                           // variable for BLE descriptor


//************************************************************************//
// Setup                                                                  //
//************************************************************************//
void setup() {

  pinMode(LED_BUILTIN, OUTPUT); // visible connection indicator
  Serial.begin(115200);         // faster speed loses less messages
  while (!Serial);              // waits for serial monitor to open
  
  initBluetoothHardware(repeatForever);
  scanForPeripheral(dexcomUUID);
}

//************************************************************************//
// Main Loop                                                              //
//************************************************************************//
void loop() {

  // through a lot of experimentation it seems some BLE functions need to
  // be called in the main loop otherwise the 'peripheral' object does not
  // propagate the characteristics correctly to subsequent functions. Maybe
  // that's just my poor coding abilities but I freely admit I am a hack

  peripheral = BLE.available();                 // any advertising BLE devices?
  if (peripheral) {     

    if (getPeripheralAttributes(devCount)) {    // get BLE general qualities
      stopScanningForPeripheral();              // turn off scanner, switch to interrogator

      if (connectPeripheral()) {                // connect to BLE device
        getPeripheralServices();                // get services and characteristics
        disconnectPeripheral();                 // release device, go to sleep
        devCount++;                             // device added to database RAM
      }
      if (repeatForever) {
        scanForPeripheral(dexcomUUID);
      } else {
        BLE.end();
        while (true);                           // endless loop
      }
    }
  }

//  if (devCount > 0) {
  if (true) {

    if (!initDone) {
      // peripheral not available now so act like one instead, so there
      // these are hard-wired settings just for initial testing of P->C connection

      // BLE characteristic property bit mask (0x3F : left = msb, right = lsb)
      // BLEBroadcast, BLERead, BLEWriteWithoutResponse, BLEWrite, BLENotify, BLEIndicate 
      BLEService testService0("1800");    // straight outta Compton
      BLEUnsignedCharCharacteristic testCharacteristic0("2a00", BLEWriteWithoutResponse | BLENotify);
      BLEUnsignedCharCharacteristic testCharacteristic1("2a01", BLENotify);
      BLEUnsignedCharCharacteristic testCharacteristic2("2a04", BLENotify);

      BLEService testService1("1801");
      BLEUnsignedCharCharacteristic testCharacteristic3("2a05", BLEBroadcast);
      byte testDescBuf[2] = {0x0, 0x0};
      BLEDescriptor testDescriptor0("2902", testDescBuf, sizeof(testDescBuf));

      BLEService testService2("f8083532-849e-531c-c594-30f1f86a4ea5");
      BLEUnsignedCharCharacteristic testCharacteristic4("f8083533-849e-531c-c594-30f1f86a4ea5", BLERead | BLENotify);
      BLEUnsignedCharCharacteristic testCharacteristic5("f8083534-849e-531c-c594-30f1f86a4ea5", BLEBroadcast | BLEWriteWithoutResponse);
      BLEUnsignedCharCharacteristic testCharacteristic6("f8083535-849e-531c-c594-30f1f86a4ea5", BLEBroadcast | BLEWriteWithoutResponse | BLENotify);
      BLEUnsignedCharCharacteristic testCharacteristic7("f8083536-849e-531c-c594-30f1f86a4ea5", BLERead | BLEWriteWithoutResponse | BLENotify);
      BLEUnsignedCharCharacteristic testCharacteristic8("f8083537-849e-531c-c594-30f1f86a4ea5", BLERead);

      BLEService testService3("180a");
      BLEUnsignedCharCharacteristic testCharacteristic9("2a29", BLERead);
      BLEUnsignedCharCharacteristic testCharacteristic10("2a24", BLERead);
      BLEUnsignedCharCharacteristic testCharacteristic11("2a26", BLERead);

//      BLE.setAdvertisedService(testService0);
//      BLE.setAdvertisedService(testService1);
//      BLE.setAdvertisedService(testService2);
//      BLE.setAdvertisedService(testService3);

      testService0.addCharacteristic(testCharacteristic0);
      testService0.addCharacteristic(testCharacteristic1);
      testService0.addCharacteristic(testCharacteristic2);
      testService1.addCharacteristic(testCharacteristic3);
      testService2.addCharacteristic(testCharacteristic4);
      testService2.addCharacteristic(testCharacteristic5);
      testService2.addCharacteristic(testCharacteristic6);
      testService2.addCharacteristic(testCharacteristic7);
      testService2.addCharacteristic(testCharacteristic8);
      testService3.addCharacteristic(testCharacteristic9);
      testService3.addCharacteristic(testCharacteristic10);
      testService3.addCharacteristic(testCharacteristic11);

      testCharacteristic3.addDescriptor(testDescriptor0);

//      byte testBuf[8] = {68, 101, 120, 99, 111, 109, 87, 84};
//      testCharacteristic0.writeValue(32);
      
      BLE.addService(testService0);   // add the service after it has been configured
      BLE.addService(testService1);   // add the service after it has been configured
      BLE.addService(testService2);   // add the service after it has been configured
      BLE.addService(testService3);   // add the service after it has been configured

      BLE.setLocalName("Fake Dexcom");
      BLE.setManufacturerData(companyID, mfgBuf, sizeof(mfgBuf));
      BLE.setAppearance(0x181F);
      BLE.setDeviceName("Fake Dexcom");
//      BLE.setAdvertisedServiceUuid("febc");

      BLE.setConnectable(true);
      BLE.advertise();
      Serial.println("Advertising enabled");
      initDone = true;
    }

    central = BLE.central();

    if (central && !centCon) {
      BLE.stopAdvertise();
      if (!centCon) {
        Serial.println();
        Serial.print("Connected to central: ");
        Serial.println(central.address());
        centCon = true;   // toggles to disconnected state
      }
    }
    if (!central && centCon) {
      Serial.println("Central disconnected");
      centCon = false;    // toggles back to connected state
    }
  }
}

//************************************************************************//
// initBluetoothHardware                                                  //
//  inputs  : continuous loop indicator                                   //
//  outputs : nuthin                                                      //
//************************************************************************//
void initBluetoothHardware(bool loopFlag) {
  
  // initialize the BLE hardware, tell user about awesome program
  BLE.begin();

  Serial.println();
  Serial.print("Dexcom 2020 - Transmitter Discovery v");
  Serial.println(version, 1);
  Serial.print("Program set to ");
  if (loopFlag) {
    Serial.println("run continuously");
  } else {
    Serial.println("run one loop");
  }
}

//************************************************************************//
// scanForPeripheral                                                      //
//  inputs  : UUID pointer to scan for                                    //
//  outputs : nuthin                                                      //
//************************************************************************//
void scanForPeripheral(const char *peripheralUUID) {

  // start looking for BLE peripherals - UUID parameter makes it specific
  BLE.scanForUuid(peripheralUUID, false);
}

//************************************************************************//
// stopScanningForPeripheral                                              //
//  inputs  : nuthin                                                      //
//  outputs : nuthin                                                      //
//************************************************************************//
void stopScanningForPeripheral(void) {
  
  // stop looking for BLE peripheral advertisements
  BLE.stopScan();
  delay(1);
}

//************************************************************************//
// connectPeripheral                                                      //
//  inputs  : nuthin                                                      //
//  outputs : connected to device or didn't                               //
//************************************************************************//
bool connectPeripheral(void) {
  
  // test for a valid and stable BLE connection after starting a scan
  bool connectFlag = false;
  Serial.print(" Connecting ...");

  if (peripheral.connect()) {
    digitalWrite(LED_BUILTIN, HIGH);
    Serial.println(" connected");
    connectFlag = true;
  } else {
    Serial.println(" failed to connect!");
  }

  return connectFlag;
}

//************************************************************************//
// disconnectPeripheral                                                   //
//  inputs  : nuthin                                                      //
//  outputs : nuthin                                                      //
//************************************************************************//
void disconnectPeripheral(void) {

  // disconnect from a BLE peripheral
  peripheral.disconnect();
  digitalWrite(LED_BUILTIN, LOW);
  Serial.println(" Peripheral disconnected");
}

//************************************************************************//
// getPeripheralAttributes                                                //
//  inputs  : number of devices found/saved                               //
//  outputs : found unique device or didn't                               //
//************************************************************************//
bool getPeripheralAttributes(byte devCount) {

  // if a unique peripheral exists, display/save all its attributes
  bool dupe = false;
  String devAddress = peripheral.address();

  for (byte d = 0; d < devCount; d++) {     // search for a duplicate MAC address
    if (periphAddrDB[d] == devAddress) {    // if one is found then jump out of
      d = devCount;                         // the loop stop processing, otherwise
      dupe = true;                          // show the attributes and save them thar
    }
  }
  if (!dupe) {
    Serial.println();
    Serial.print("Found ");
    Serial.print(devAddress);
    Serial.print(" '");
    Serial.print(peripheral.localName());
    Serial.print("' 0x");
    Serial.println(peripheral.advertisedServiceUuid());
    periphAddrDB[devCount] = devAddress;
  }
 
  return !dupe;
}

//************************************************************************//
// getPeripheralServices                                                  //
//  inputs  : nuthin                                                      //
//  outputs : nuthin                                                      //
//************************************************************************//
void getPeripheralServices(void) {
  
  // breakout services and characteristics
  if (peripheral.discoverAttributes()) {    // VERY IMPORTANT - unlocks stuff

    Serial.println(" Discovering services and their characteristics:");
    servCount = peripheral.serviceCount();
    Serial.print("  Number of services found: ");
    Serial.println(servCount);

    for (int s = 0; s < servCount; s++) {
      servDexcom = peripheral.service(s);
      Serial.print("  Service ");
      Serial.print(s);
      Serial.print(": 0x");
      Serial.println(servDexcom.uuid());
      getPeripheralCharacteristics();        // nested functions, oh baby
    }
  }
}

//************************************************************************//
// getPeripheralCharacteristics                                           //
//  inputs  : nuthin                                                      //
//  outputs : nuthin                                                      //
//************************************************************************//
void getPeripheralCharacteristics(void) {

  // BLE characteristic property bit mask (0x3F : left = msb, right = lsb)
  // BLEBroadcast, BLERead, BLEWriteWithoutResponse, BLEWrite, BLENotify, BLEIndicate 
  charCount = servDexcom.characteristicCount();
  Serial.print("   Number of characteristics found: ");
  Serial.println(charCount);
  for (int c = 0; c < charCount; c++) {
    charDexcom = servDexcom.characteristic(c);
    Serial.print("   Characteristic ");
    Serial.print(c);
    Serial.print(": 0x");
    Serial.print(charDexcom.uuid());
    Serial.print(" 0x");
    Serial.print(charDexcom.properties(), HEX);
      
    if (charDexcom.canRead()) {
      Serial.print(" readable!");
      charDexcom.read();                      // starts a "read cycle request"
      word cLen = charDexcom.valueLength();   // 512 bytes is BLE maximum
      Serial.print(" [");
      Serial.print(cLen);
      Serial.print("]");
      charDexcom.readValue(charBuf, cLen);    // charBuf is declared globally
      for (int v = 0; v < cLen; v++) {
        Serial.print(" ");
        Serial.print(charBuf[v]);
      }
    } else {
      Serial.print(" not readable"); 
    }
    if (charDexcom.canSubscribe()) Serial.print(" subscribable!");
    if (charDexcom.canWrite()) Serial.print(" writeable!");
    Serial.println();
    getPeripheralDescriptors();
  }
}

//************************************************************************//
// getPeripheralDescriptors                                               //
//  inputs  : nuthin                                                      //
//  outputs : nuthin                                                      //
//************************************************************************//
void getPeripheralDescriptors(void) {

  descCount = charDexcom.descriptorCount();
  if (descCount > 0) {
    Serial.print("    Number of descriptors found: ");
    Serial.println(descCount);

    for (int d = 0; d < descCount; d++) {
      descDexcom = charDexcom.descriptor(d);
      Serial.print("    Descriptor ");
      Serial.print(d);
      Serial.print(": 0x");
      Serial.print(descDexcom.uuid());
 
      descDexcom.read();
      word dLen = descDexcom.valueLength();
      Serial.print(" [");
      Serial.print(dLen);
      Serial.print("]");

      charDexcom.readValue(descBuf, dLen);    // descBuf is declared globally
      for (int g = 0; g < dLen; g++) {
        Serial.print(" ");
        Serial.print(descBuf[g]);
      }
      Serial.println();
    }
  }
}

@jarvis1lsu please edit your post, using the pencil icon at the bottom, and add triple backticks at the beginning and end of your code so that it displays correctly.
Triple backticks look like this:
```

Pete.

sorry about that sir… it should be correct now.

If it was me doing this, I’d use Open MQTT Gateway (OMG), and send the data to the second device via MQTT messages.

Pete.

Thank you for your help. I’m not very familiar with OMG but I will definitely dig in to it!

Is there a way to do this within the blynk app? The time constraints of the project and the learning curve of learning about the MQTT options are looking to be a hurdle.

No. You’ll have to dig in and tweak yourself the Blynk library.