Skip to content

Please allow access to raw / custom advertisement data (with code) #123

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

Closed
tarheele opened this issue Oct 13, 2020 · 6 comments
Closed

Please allow access to raw / custom advertisement data (with code) #123

tarheele opened this issue Oct 13, 2020 · 6 comments
Labels
conclusion: resolved Issue was resolved topic: code Related to content of the project itself type: enhancement Proposed improvement

Comments

@tarheele
Copy link

tarheele commented Oct 13, 2020

Per discussion on the Nano 33 IoT board , I needed access to the raw advertisement data to obtain data from a sensor which embeds the data in that advertisement.

Please consider adding the getAdvertisement() accessor below. Alternately, you could implement access to types within the advertisement like you do access to localName().

I am grateful for AndroidBLE and think this would solve problems which others face also.

BLEDevice.h
int getAdvertisement(uint8_t value[], int length);

BLEDevice.cpp (modified to fix copy/paste error and to check incoming buffer size)

int BLEDevice::getAdvertisement(uint8_t value[], int length)
{
  if (_eirDataLength > length) return 0;  // Check that buffer size is sufficient

  if (_eirDataLength) {
    memcpy(value, _eirData, _eirDataLength);
  }

  return _eirDataLength;
}

Usage Output

20:59:30.800 -> Discovered a peripheral
20:59:30.800 -> -----------------------
20:59:30.800 -> Address: a4:c1:38:38:b1:91
20:59:30.800 -> Local Name: ATC_38B191
20:59:30.800 -> Advertisement 0x16: 0x1A18A4C13838B191010137590BB97C
20:59:30.800 -> Temp: 25.7C  Temp: 78.3F  Humid: 55%  Batt: 89%  Batt: 3001mV
20:59:30.800 -> 
20:59:30.800 -> RSSI: -60
20:59:30.800 -> 
20:59:34.635 -> Discovered a peripheral
20:59:34.635 -> -----------------------
20:59:34.635 -> Address: a4:c1:38:ac:2b:8f
20:59:34.635 -> Local Name: ATC_AC2B8F
20:59:34.635 -> Advertisement 0x16: 0x1A18A4C138AC2B8F00FA38600BFE92
20:59:34.635 -> Temp: 25.0C  Temp: 77.0F  Humid: 56%  Batt: 96%  Batt: 3070mV
20:59:34.635 -> 
20:59:34.635 -> RSSI: -86
20:59:34.635 -> 

Usage Code

#include <ArduinoBLE.h>

/*
  ATC_Scan - Modified from ArduinoBLE Scan to read ATC_MiThermometer (requires AndroidBLE Changes)

  This example scans for https://github.com/atc1441/ATC_MiThermometer devices and prints out their advertising details:
  address, local name, adverised service UUID's.

  The circuit:
  - Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
    Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.

  This example code is in the public domain.
*/

#include <ArduinoBLE.h>

void setup() {
  Serial.begin(9600);
  while (!Serial);

  // begin initialization
  if (!BLE.begin()) {
    Serial.println("starting BLE failed!");

    while (1);
  }

  Serial.println("BLE Central scan");

  // start scanning for peripheral
  BLE.scan();
  
  Serial.println("Started Scan.  Testing waiting 1 minute");
  Serial.println();

  delay(60000);
}

void loop() {
  // check if a peripheral has been discovered
  BLEDevice peripheral = BLE.available();

  // Scan only for ATC_ devices
  if (peripheral && peripheral.hasLocalName() && peripheral.localName().startsWith("ATC_")) {
    // discovered a peripheral
    Serial.println("Discovered a peripheral");
    Serial.println("-----------------------");

    // print address
    Serial.print("Address: ");
    Serial.println(peripheral.address());


    // print the local name, if present
    if (peripheral.hasLocalName()) {
      Serial.print("Local Name: ");
      Serial.println(peripheral.localName());
    }

    uint8_t advertisement[64] = {0};
    int adLength = peripheral.getAdvertisement(advertisement,64);
    Serial.print("Advertisement 0x16: 0x");
    uint8_t sensorAdvertisementData[64];  // TODO - allocate according to length or spec

   // zero out array, though really only first byte (length byte) needs to be zeroed
   for (int x = 0; x < sizeof(sensorAdvertisementData); x++)
   {
     sensorAdvertisementData[x] = 0;
   }

  int16_t temp = 0;
  uint8_t humid = 0;
  uint8_t batt_p = 0;
  uint16_t batt_mv = 0;


  int sensorAdvertisementLength = 0;
   for (int i = 0; i < 64;) {
     int eirLength = advertisement[i++];
     int eirType = advertisement[i++];

     if (eirType == 0x16) {  // ATC custom advertisement type

       // copy each byte and print.  could have used memcpy and sprintf
       sensorAdvertisementLength = eirLength;
       for (int j = 0; j < (eirLength - 1); j++) {
         uint8_t thisByte = advertisement[i + j];
         sensorAdvertisementData[j] = thisByte;
         if (thisByte <= 0xF) Serial.print("0");
         Serial.print(thisByte,HEX);
       }
       Serial.println();


       if (sensorAdvertisementLength >= 13  ) {
          temp = sensorAdvertisementData[8] << 8 | sensorAdvertisementData[9];
          humid = sensorAdvertisementData[10];
          batt_p = sensorAdvertisementData[11];
          batt_mv = sensorAdvertisementData[12] << 8 | sensorAdvertisementData[13];
          float tempFloatC = (float)temp / 10;
          float tempFloatF = (((float)temp / 10) * 9/5) + 32;
          Serial.print("Temp: ");
          Serial.print(tempFloatC,1);
          Serial.print("C  Temp: ");
          Serial.print(tempFloatF,1);
          Serial.print("F  Humid: ");
          Serial.print(humid);
          Serial.print("%  Batt: ");
          Serial.print(batt_p);
          Serial.print("%  Batt: ");
          Serial.print(batt_mv);
          Serial.println("mV");
          Serial.println();
       }
       
       break;
     }
     i += (eirLength - 1);
   }
   
    // print the RSSI
    Serial.print("RSSI: ");
    Serial.println(peripheral.rssi());

    Serial.println();
  }
}
@per1234 per1234 added the type: enhancement Proposed improvement label Oct 13, 2020
@tarheele
Copy link
Author

Apologies. Two changes:

  1. Fixed copy/paste error where I omitted the first source code line
  2. Added buffer size check

BLEDevice.cpp

int BLEDevice::getAdvertisement(uint8_t value[], int length)
{
  if (_eirDataLength > length) return 0;  // Check that buffer size is sufficient

  if (_eirDataLength) {
    memcpy(value, _eirData, _eirDataLength);
  }

  return _eirDataLength;
}

@polldo
Copy link
Contributor

polldo commented Oct 26, 2020

Hi @tarheele , I understand your needs.
I recently have been refactoring the advertising mechanism (#117)
I also tried to address the problem of retrieving raw advertising data from discovered peripherals, you can see it from this commit of this branch, but it is still a work in progress and I'm not convinced about it.

@tlossen
Copy link
Contributor

tlossen commented Dec 25, 2020

i'm also interested in accessing the raw advertisement data. i am working with a ruuvi tag which is broadcasting sensor data in the same way. seems to be a common use case.

@polldo
Copy link
Contributor

polldo commented May 27, 2021

Hi @tlossen @tarheele thanks for your help. This PR #183 should address this issue, can you please test this and report feedbacks?
Thanks again!

@axelcordes
Copy link

hi @polldo do you know, when the feature will be available? I also would like to read ruuvi advertising data.

@per1234
Copy link
Contributor

per1234 commented May 13, 2022

Closing as resolved by #183

Thanks so much for your valuable suggestion @tarheele!

@per1234 per1234 closed this as completed May 13, 2022
@per1234 per1234 added conclusion: resolved Issue was resolved topic: code Related to content of the project itself labels May 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
conclusion: resolved Issue was resolved topic: code Related to content of the project itself type: enhancement Proposed improvement
Projects
None yet
Development

No branches or pull requests

5 participants