Skip to content

Library Usage Question #1

@stacyh3

Description

@stacyh3

Hello, I'm trying to use your Adafruit nrf52 library to scan for CODED PHY advertisements on my nrf52840. Do you have any examples of this? The example that I see uses the nRF device to transmit, but I want to receive. I believe that I have replaced the Adafruit library successfully with your implementation. This is what I have for code so far. I'm pretty sure that I'm missing something simple. If you happen to have time to take a look at this, I'd appreciate the help. I only care about the CODED PHY, that's why the other two are commented out. I'm receiving those, just fine.

#include <bluefruit.h>

void setup()
{
  Serial.begin(115200);

  // Wait for serial connection (optional - remove for standalone operation)
  while (!Serial && millis() < 5000)
  {
    delay(10);
  }

  // Initialize Bluefruit
  Bluefruit.begin();
  Bluefruit.setName("CSH3-BLE-Scanner");

  // Set maximum power for better range
  Bluefruit.setTxPower(4);

  // Configure scanner
  Bluefruit.Scanner.setRxCallback(scan_callback);
  Bluefruit.Scanner.restartOnDisconnect(true);
  Bluefruit.Scanner.setInterval(160, 80); // Interval and window in 0.625ms units
  Bluefruit.Scanner.useActiveScan(false); // Passive scanning to capture all advertisements

  // Start scanning
  Bluefruit.Scanner.start();
}

void loop()
{
  // Main loop - scanning happens in background via callbacks
  delay(100);
}

void scan_callback(ble_gap_evt_adv_report_t *report)
{
  // Get current timestamp
  unsigned long timestamp = millis();

  // Encode MAC address
  char macStr[18];
  snprintf(macStr, sizeof(macStr), "%02X:%02X:%02X:%02X:%02X:%02X",
           report->peer_addr.addr[5], report->peer_addr.addr[4], report->peer_addr.addr[3],
           report->peer_addr.addr[2], report->peer_addr.addr[1], report->peer_addr.addr[0]);

  // Determine address type
  const char *addrType = (report->peer_addr.addr_type == BLE_GAP_ADDR_TYPE_PUBLIC) ? "Public" : "Random";

  // Determine PHY
  const char *phyStr = "Unknown";
  switch (report->primary_phy)
  {
    // case BLE_GAP_PHY_1MBPS:
    //   phyStr = "1M";
    //   break;
    // case BLE_GAP_PHY_2MBPS:
    //   phyStr = "2M";
    //   break;
    case BLE_GAP_PHY_CODED:
      phyStr = "Coded";
      break;
  }

  // Convert raw data to hex string
  String hexData = "";
  for (int i = 0; i < report->data.len; i++)
  {
    if (report->data.p_data[i] < 0x10)
      hexData += "0";
    hexData += String(report->data.p_data[i], HEX);
    if (i < report->data.len - 1)
      hexData += " ";
  }

  // Parse advertisement fields
  String parsedFields = parseAdvertisementDataJSON(report->data.p_data, report->data.len);

  // Output as JSON
  Serial.print("{");
  Serial.print("\"timestamp\":");
  Serial.print(timestamp);
  Serial.print(",\"rssi\":");
  Serial.print(report->rssi);
  Serial.print(",\"mac\":\"");
  Serial.print(macStr);
  Serial.print("\"");
  Serial.print(",\"addr_type\":\"");
  Serial.print(addrType);
  Serial.print("\"");
  Serial.print(",\"phy\":\"");
  Serial.print(phyStr);
  Serial.print("\"");
  Serial.print(",\"len\":");
  Serial.print(report->data.len);
  Serial.print(",\"data\":\"");
  Serial.print(hexData);
  Serial.print("\"");
  Serial.print(",\"fields\":");
  Serial.print(parsedFields);
  Serial.println("}");

  Bluefruit.Scanner.resume();
}

// Parse advertisement data and return as JSON object string
String parseAdvertisementDataJSON(uint8_t *data, uint8_t len)
{
  uint8_t pos = 0;
  String json = "[";
  bool first = true;
  while (pos < len)
  {
    uint8_t fieldLen = data[pos];
    if (fieldLen == 0 || pos + fieldLen >= len)
      break;
    uint8_t fieldType = data[pos + 1];
    uint8_t *fieldData = &data[pos + 2];
    uint8_t fieldDataLen = fieldLen - 1;
    if (!first)
      json += ",";
    json += "{\"type\":\"";
    switch (fieldType)
    {
    case 0x01:
      json += "Flags";
      break;
    case 0x02:
      json += "Incomplete16BitUUIDs";
      break;
    case 0x03:
      json += "Complete16BitUUIDs";
      break;
    case 0x08:
      json += "ShortName";
      break;
    case 0x09:
      json += "CompleteName";
      break;
    case 0xFF:
      json += "ManufacturerData";
      break;
    default:
      json += "Type0x";
      char buf[3];
      snprintf(buf, sizeof(buf), "%02X", fieldType);
      json += buf;
      break;
    }
    json += "\",";
    json += "\"value\":";
    // Value formatting
    if (fieldType == 0x08 || fieldType == 0x09)
    {
      // Name as string
      json += "\"";
      for (int i = 0; i < fieldDataLen; i++)
      {
        json += (char)fieldData[i];
      }
      json += "\"";
    }
    else if (fieldType == 0x02 || fieldType == 0x03)
    {
      // UUIDs as array
      json += "[";
      for (int i = 0; i < fieldDataLen; i += 2)
      {
        if (i > 0)
          json += ",";
        uint16_t uuid = (fieldData[i + 1] << 8) | fieldData[i];
        json += String(uuid);
      }
      json += "]";
    }
    else
    {
      // Hex string
      json += "\"";
      for (int i = 0; i < fieldDataLen; i++)
      {
        if (fieldData[i] < 0x10)
          json += "0";
        json += String(fieldData[i], HEX);
      }
      json += "\"";
    }
    json += "}";
    first = false;
    pos += fieldLen + 1;
  }
  json += "]";
  return json;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions