Closed
Description
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();
}
}