forked from espressif/arduino-esp32
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBLE_Beacon_Scanner.ino
153 lines (134 loc) · 5.46 KB
/
BLE_Beacon_Scanner.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp
Ported to Arduino ESP32 by Evandro Copercini
Changed to a beacon scanner to report iBeacon, EddystoneURL and EddystoneTLM beacons by beegee-tokyo
*/
#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include <BLEEddystoneURL.h>
#include <BLEEddystoneTLM.h>
#include <BLEBeacon.h>
#define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00) >> 8) + (((x)&0xFF) << 8))
int scanTime = 5; //In seconds
BLEScan *pBLEScan;
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
{
void onResult(BLEAdvertisedDevice advertisedDevice)
{
if (advertisedDevice.haveName())
{
Serial.print("Device name: ");
Serial.println(advertisedDevice.getName().c_str());
Serial.println("");
}
if (advertisedDevice.haveServiceUUID())
{
BLEUUID devUUID = advertisedDevice.getServiceUUID();
Serial.print("Found ServiceUUID: ");
Serial.println(devUUID.toString().c_str());
Serial.println("");
}
else
{
if (advertisedDevice.haveManufacturerData() == true)
{
std::string strManufacturerData = advertisedDevice.getManufacturerData();
uint8_t cManufacturerData[100];
strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0);
if (strManufacturerData.length() == 25 && cManufacturerData[0] == 0x4C && cManufacturerData[1] == 0x00)
{
Serial.println("Found an iBeacon!");
BLEBeacon oBeacon = BLEBeacon();
oBeacon.setData(strManufacturerData);
Serial.printf("iBeacon Frame\n");
Serial.printf("ID: %04X Major: %d Minor: %d UUID: %s Power: %d\n", oBeacon.getManufacturerId(), ENDIAN_CHANGE_U16(oBeacon.getMajor()), ENDIAN_CHANGE_U16(oBeacon.getMinor()), oBeacon.getProximityUUID().toString().c_str(), oBeacon.getSignalPower());
}
else
{
Serial.println("Found another manufacturers beacon!");
Serial.printf("strManufacturerData: %d ", strManufacturerData.length());
for (int i = 0; i < strManufacturerData.length(); i++)
{
Serial.printf("[%X]", cManufacturerData[i]);
}
Serial.printf("\n");
}
}
return;
}
uint8_t *payLoad = advertisedDevice.getPayload();
BLEUUID checkUrlUUID = (uint16_t)0xfeaa;
if (advertisedDevice.getServiceUUID().equals(checkUrlUUID))
{
if (payLoad[11] == 0x10)
{
Serial.println("Found an EddystoneURL beacon!");
BLEEddystoneURL foundEddyURL = BLEEddystoneURL();
std::string eddyContent((char *)&payLoad[11]); // incomplete EddystoneURL struct!
foundEddyURL.setData(eddyContent);
std::string bareURL = foundEddyURL.getURL();
if (bareURL[0] == 0x00)
{
size_t payLoadLen = advertisedDevice.getPayloadLength();
Serial.println("DATA-->");
for (int idx = 0; idx < payLoadLen; idx++)
{
Serial.printf("0x%08X ", payLoad[idx]);
}
Serial.println("\nInvalid Data");
return;
}
Serial.printf("Found URL: %s\n", foundEddyURL.getURL().c_str());
Serial.printf("Decoded URL: %s\n", foundEddyURL.getDecodedURL().c_str());
Serial.printf("TX power %d\n", foundEddyURL.getPower());
Serial.println("\n");
}
else if (payLoad[11] == 0x20)
{
Serial.println("Found an EddystoneTLM beacon!");
BLEEddystoneTLM foundEddyURL = BLEEddystoneTLM();
std::string eddyContent((char *)&payLoad[11]); // incomplete EddystoneURL struct!
eddyContent = "01234567890123";
for (int idx = 0; idx < 14; idx++)
{
eddyContent[idx] = payLoad[idx + 11];
}
foundEddyURL.setData(eddyContent);
Serial.printf("Reported battery voltage: %dmV\n", foundEddyURL.getVolt());
Serial.printf("Reported temperature from TLM class: %.2fC\n", (double)foundEddyURL.getTemp());
int temp = (int)payLoad[16] + (int)(payLoad[15] << 8);
float calcTemp = temp / 256.0f;
Serial.printf("Reported temperature from data: %.2fC\n", calcTemp);
Serial.printf("Reported advertise count: %d\n", foundEddyURL.getCount());
Serial.printf("Reported time since last reboot: %ds\n", foundEddyURL.getTime());
Serial.println("\n");
Serial.print(foundEddyURL.toString().c_str());
Serial.println("\n");
}
}
}
};
void setup()
{
Serial.begin(115200);
Serial.println("Scanning...");
BLEDevice::init("");
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
pBLEScan->setInterval(100);
pBLEScan->setWindow(99); // less or equal setInterval value
}
void loop()
{
// put your main code here, to run repeatedly:
BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
Serial.print("Devices found: ");
Serial.println(foundDevices.getCount());
Serial.println("Scan done!");
pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory
delay(2000);
}