All,
I would like to scan for a BLE device’s advertisement data, parse that data and then display a result (this time a distance measurement). I can see that the BLE device is indeed advertising, from my phone (passive scanning), and it has data coming through. I’m also seeing the specific MAC address of the device, so I can pick it up.
I have the following working but I’m unsure as to a few aspects;
- parsing data as little or big endian (is there a standard option or is each manufacturer different?
- Should I be looking in BleAdvertisingData advData = scanResults.advertisingData();
or BleAdvertisingData scanRespData = scanResults.scanResponse()? I would guess, given the name, .advertisingData()? - Any tips for an easy way to parse the 31 bytes of data?
#include "Particle.h"
#define BLE_PEER_ADDRESS {0xEA, 0xD5, 0xF7, 0xAB, 0xEF, 0x60} //Barra BLE Radar MAC Address = 60:EF:AB:F7:D5:EA
//Barra Advertising Name = DM1199804
SYSTEM_MODE(AUTOMATIC);
SerialLogHandler logHandler(LOG_LEVEL_INFO);
const BleAddress ble_peer_address = BleAddress(BLE_PEER_ADDRESS);
uint32_t serialnumber = 0;
//int BLE_MAX_ADV_DATA_LEN = 50;
void setup() {
(void)logHandler;
}
void loop() {
Vector<BleScanResult> scanResults = BLE.scan();
for (int x = 0; x < scanResults.size(); x++) {
if (strncmp(scanResults[x].address().toString(), ble_peer_address.toString(), 17) == 0) { //focus on the first 17 characters, as this is the length of the MAC address.
Log.info("Found matching device %s", scanResults[x].address().toString().c_str());
BleAdvertisingData advData = scanResults[x].advertisingData();
BleAdvertisingData scanRespData = scanResults[x].scanResponse();
uint8_t buffer[BLE_MAX_ADV_DATA_LEN];
//size_t len = scanRespData.get(buffer, BLE_MAX_ADV_DATA_LEN);
size_t len = advData.get(buffer, BLE_MAX_ADV_DATA_LEN);
Log.info("Length of Buffer = %d bytes", sizeof(buffer)); //confirm size of buffer (31 bytes)
//The buffer is normally 31 bytes in size (standard BLE maximum).
//All records will start with this block. Length = 11 [0 to 10] which includes Record Length, Sequence Number, RTC datetime and Log Reason.
/*DM Barra Radar Length = 15 bytes [11-25] (therefore it is , tag type 20), which includes all the data with the following:
0 to 4 (11-14) uint32 of length 4 = Tag Serial Number
5 to 6 (15-16) uint16 of length 2 = Battery Voltage in mV
7 to 8 (17-18) uint16 of length 2 = Distance of Strongest Peak (mm)
9 to 10 (19-20) int16 of length 2 = Strength of strongest Peak (dB)
11 to 12 (21-22) uint16 of length 2 = Distance of second strongest peak (mm)
13 to 14 (23-24) int16 of length 2 = Stregth of second strongest peak (dB)
15 (25) Byte : 1 of length 0.1 = Object Detected Flag (Bit zero indicates object detected)
15 (25) Byte : 7 of length 0.7 = Reserved (set to 0)*/
for (uint8_t i = 0; i < (sizeof(buffer)); i++){
Serial.printf("%X", buffer[i]);
}
//uint16_t FieldID = buffer[0];
//Log.info("FieldID: %d", FieldID);
//delay(200);
uint16_t length = (static_cast<uint16_t>(buffer[1]) << 8) | buffer[0];
Log.info("Record Length: %d", length);
delay(200);
serialnumber = ((uint32_t)buffer[11]<<24) |
((uint32_t)buffer[12]<<16) |
((uint32_t)buffer[13]<<8) |
((uint32_t)buffer[14]);
Log.info("Serial Number: %" PRIu32, serialnumber);
delay(200);
Log.info("RSSI : %d", scanResults[x].rssi());
uint16_t batteryvoltage = (static_cast<uint16_t>(buffer[16]) << 8) | buffer[15];
Log.info("Battery Voltage (mV): %hu", batteryvoltage);
delay(200);
uint16_t firstdistance = (static_cast<uint16_t>(buffer[18]) << 8) | buffer[17];
Log.info("First Distance (mm): %.2lf", firstdistance);
delay(200);
int16_t firststrength = (static_cast<int16_t>(buffer[20]) << 8) | buffer[19];
Log.info("First Strength (dB): %hu", firststrength);
delay(200);
uint16_t seconddistance = (static_cast<uint16_t>(buffer[22]) << 8) | buffer[21];
Log.info("Second Distance (mm): %.2lf", seconddistance);
delay(200);
int16_t secondstrength = (static_cast<int16_t>(buffer[24]) << 8) | buffer[23];
Log.info("Second Strength (dB): %hu", secondstrength);
delay(200);
String name = scanResults[x].advertisingData().deviceName();
Log.info("Advertising name: %s", name.c_str());
delay(1000);
memset(buffer, 0, sizeof(buffer));
}
}
//}
//}
delay(3000);
}
@ScruffR - you’ve previously been the GOAT on all such things. Have you tried this before and got it working?