Skip to content

Commit 1eb082e

Browse files
committed
Updated Eddystone classes and beacon scanner
1 parent 52b6e84 commit 1eb082e

File tree

9 files changed

+140
-101
lines changed

9 files changed

+140
-101
lines changed

libraries/BLE/examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.ino

Lines changed: 21 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp
33
Ported to Arduino ESP32 by Evandro Copercini
44
Changed to a beacon scanner to report iBeacon, EddystoneURL and EddystoneTLM beacons by beegee-tokyo
5+
Upgraded Eddystone part by Tomas Pilny on Feb 20, 2023
6+
57
*/
68

79
#include <Arduino.h>
@@ -63,62 +65,33 @@ class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
6365
}
6466
}
6567

66-
uint8_t *payLoad = advertisedDevice.getPayload();
67-
// search for Eddystone Service Data in the advertising payload
68-
// *payload shall point to eddystone data or to its end when not found
69-
const uint8_t serviceDataEddystone[3] = {0x16, 0xAA, 0xFE}; // it has Eddystone BLE UUID
70-
const size_t payLoadLen = advertisedDevice.getPayloadLength();
71-
uint8_t *payLoadEnd = payLoad + payLoadLen - 1; // address of the end of payLoad space
72-
while (payLoad < payLoadEnd) {
73-
if (payLoad[1] == serviceDataEddystone[0] && payLoad[2] == serviceDataEddystone[1] && payLoad[3] == serviceDataEddystone[2]) {
74-
// found!
75-
payLoad += 4;
76-
break;
68+
if (advertisedDevice.getFrameType() == BLE_EDDYSTONE_URL_FRAME)
69+
{
70+
Serial.println("Found an EddystoneURL beacon!");
71+
BLEEddystoneURL EddystoneURL = BLEEddystoneURL(&advertisedDevice);
72+
Serial.printf("URL bytes: 0x");
73+
std::string url = EddystoneURL.getURL();
74+
for(auto byte : url){
75+
Serial.printf("%02X", byte);
7776
}
78-
payLoad += *payLoad + 1; // payLoad[0] has the field Length
77+
Serial.printf("\n");
78+
Serial.printf("Decoded URL: %s\n", EddystoneURL.getDecodedURL().c_str());
79+
Serial.printf("TX power %d (Raw 0x%02X)\n", EddystoneURL.getPower(), EddystoneURL.getPower());
80+
Serial.println("\n");
7981
}
8082

81-
if (payLoad < payLoadEnd) // Eddystone Service Data and respective BLE UUID were found
83+
if (advertisedDevice.getFrameType() == BLE_EDDYSTONE_TLM_FRAME)
8284
{
83-
if (*payLoad == 0x10)
84-
{
85-
Serial.println("Found an EddystoneURL beacon!");
86-
BLEEddystoneURL foundEddyURL = BLEEddystoneURL();
87-
uint8_t URLLen = *(payLoad - 4) - 3; // Get Field Length less 3 bytes (type and UUID)
88-
foundEddyURL.setData(std::string((char*)payLoad, URLLen));
89-
std::string bareURL = foundEddyURL.getURL();
90-
if (bareURL[0] == 0x00)
91-
{
92-
// dumps all bytes in advertising payload
93-
Serial.println("DATA-->");
94-
uint8_t *payLoad = advertisedDevice.getPayload();
95-
for (int idx = 0; idx < payLoadLen; idx++)
96-
{
97-
Serial.printf("0x%02X ", payLoad[idx]);
98-
}
99-
Serial.println("\nInvalid Data");
100-
return;
101-
}
102-
103-
Serial.printf("Found URL: %s\n", foundEddyURL.getURL().c_str());
104-
Serial.printf("Decoded URL: %s\n", foundEddyURL.getDecodedURL().c_str());
105-
Serial.printf("TX power %d\n", foundEddyURL.getPower());
106-
Serial.println("\n");
107-
}
108-
else if (*payLoad == 0x20)
109-
{
11085
Serial.println("Found an EddystoneTLM beacon!");
111-
BLEEddystoneTLM eddystoneTLM;
112-
eddystoneTLM.setData(std::string((char*)payLoad, 14));
113-
Serial.printf("Reported battery voltage: %dmV\n", eddystoneTLM.getVolt());
114-
Serial.printf("Reported temperature: %.2f°C (raw data=0x%04X)\n", eddystoneTLM.getTemp(), eddystoneTLM.getRawTemp());
115-
Serial.printf("Reported advertise count: %lu\n", eddystoneTLM.getCount());
116-
Serial.printf("Reported time since last reboot: %lus\n", eddystoneTLM.getTime());
86+
BLEEddystoneTLM EddystoneTLM(&advertisedDevice);
87+
Serial.printf("Reported battery voltage: %dmV\n", EddystoneTLM.getVolt());
88+
Serial.printf("Reported temperature: %.2f°C (raw data=0x%04X)\n", EddystoneTLM.getTemp(), EddystoneTLM.getRawTemp());
89+
Serial.printf("Reported advertise count: %d\n", EddystoneTLM.getCount());
90+
Serial.printf("Reported time since last reboot: %ds\n", EddystoneTLM.getTime());
11791
Serial.println("\n");
118-
Serial.print(eddystoneTLM.toString().c_str());
92+
Serial.print(EddystoneTLM.toString().c_str());
11993
Serial.println("\n");
12094
}
121-
}
12295
}
12396
};
12497

libraries/BLE/examples/BLE_EddystoneURL_Beacon/BLE_EddystoneURL_Beacon.ino

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
#include "BLEBeacon.h"
2727
#include "BLEAdvertising.h"
2828
#include "BLEEddystoneURL.h"
29-
3029
#include "esp_sleep.h"
30+
3131
char unprintable[] = {0x01, 0xFF, 0xDE, 0xAD};
3232
String URL[] = {
3333
"http://www.espressif.com/", // prefix 0x00, suffix 0x00
@@ -40,6 +40,7 @@ String URL[] = {
4040
// "", // Empty string - setSmartURL() will return 0 = ERR
4141
// String(unprintable), // Unprintable characters / corrupted String - setSmartURL() will return 0 = ERR
4242
};
43+
4344
#define GPIO_DEEP_SLEEP_DURATION 10 // sleep x seconds and then wake up
4445
#define BEACON_POWER ESP_PWR_LVL_N12
4546
RTC_DATA_ATTR static time_t last; // remember last boot in RTC Memory
@@ -50,15 +51,12 @@ RTC_DATA_ATTR static uint32_t bootcount; // remember number of boots in RTC Memo
5051
BLEAdvertising *pAdvertising;
5152
struct timeval now;
5253

53-
std::string BEACON_UUID("8ec76ea3-6668-48da-9866-75be8bc86f4d"); // UUID v1 128-Bit (may use linux tool uuidgen or random numbers via https://www.uuidgenerator.net/)
54-
5554
int setBeacon()
5655
{
5756
BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
5857
BLEAdvertisementData oScanResponseData = BLEAdvertisementData();
5958

6059
BLEEddystoneURL EddystoneURL;
61-
EddystoneURL.setUUID(BLEUUID(BEACON_UUID));
6260
EddystoneURL.setPower(BEACON_POWER); // This is only information about the power. The actual power is set by `BLEDevice::setPower(BEACON_POWER)`
6361
if(EddystoneURL.setSmartURL(URL[bootcount%(sizeof(URL)/sizeof(URL[0]))])){
6462
String frame = EddystoneURL.getFrame();
@@ -67,6 +65,7 @@ int setBeacon()
6765
oScanResponseData.setName("ESP32 URLBeacon");
6866
pAdvertising->setAdvertisementData(oAdvertisementData);
6967
pAdvertising->setScanResponseData(oScanResponseData);
68+
Serial.printf("Advertise URL \"%s\"\n", URL[bootcount%(sizeof(URL)/sizeof(URL[0]))].c_str());
7069
return 1; // OK
7170
}else{
7271
Serial.println("Smart URL set ERR");

libraries/BLE/src/BLEAdvertisedDevice.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,22 @@ esp_ble_addr_type_t BLEAdvertisedDevice::getAddressType() {
584584
return m_addressType;
585585
}
586586

587+
ble_frame_type_t BLEAdvertisedDevice::getFrameType(){
588+
for(int i = 0; i < m_payloadLength; ++i){
589+
log_d("check [%d]=0x%02X", i, m_payload[i]);
590+
if(m_payload[i] == 0x16 && m_payloadLength >= i+3 && m_payload[i+1] == 0xAA && m_payload[i+2] == 0xFE && m_payload[i+3] == 0x00){
591+
return BLE_EDDYSTONE_UUID_FRAME;
592+
}
593+
if(m_payload[i] == 0x16 && m_payloadLength >= i+3 && m_payload[i+1] == 0xAA && m_payload[i+2] == 0xFE && m_payload[i+3] == 0x10){
594+
return BLE_EDDYSTONE_URL_FRAME;
595+
}
596+
if(m_payload[i] == 0x16 && m_payloadLength >= i+3 && m_payload[i+1] == 0xAA && m_payload[i+2] == 0xFE && m_payload[i+3] == 0x20){
597+
return BLE_EDDYSTONE_TLM_FRAME;
598+
}
599+
}
600+
return BLE_UNKNOWN_FRAME;
601+
}
602+
587603
void BLEAdvertisedDevice::setAddressType(esp_ble_addr_type_t type) {
588604
m_addressType = type;
589605
}

libraries/BLE/src/BLEAdvertisedDevice.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,19 @@
1414
#include <esp_gattc_api.h>
1515

1616
#include <map>
17-
#include <vector>
17+
//#include <vector>
1818

1919
#include "BLEAddress.h"
2020
#include "BLEScan.h"
2121
#include "BLEUUID.h"
2222

23+
typedef enum {
24+
BLE_UNKNOWN_FRAME,
25+
BLE_EDDYSTONE_UUID_FRAME,
26+
BLE_EDDYSTONE_URL_FRAME,
27+
BLE_EDDYSTONE_TLM_FRAME,
28+
BLE_FRAME_MAX
29+
} ble_frame_type_t;
2330

2431
class BLEScan;
2532
/**
@@ -48,9 +55,10 @@ class BLEAdvertisedDevice {
4855
int getServiceDataUUIDCount();
4956
int getServiceUUIDCount();
5057
int8_t getTXPower();
51-
uint8_t* getPayload();
52-
size_t getPayloadLength();
58+
uint8_t* getPayload();
59+
size_t getPayloadLength();
5360
esp_ble_addr_type_t getAddressType();
61+
ble_frame_type_t getFrameType();
5462
void setAddressType(esp_ble_addr_type_t type);
5563

5664

libraries/BLE/src/BLEEddystoneTLM.cpp

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,45 +22,56 @@
2222
static const char LOG_TAG[] = "BLEEddystoneTLM";
2323

2424
BLEEddystoneTLM::BLEEddystoneTLM() {
25-
beaconUUID = 0xFEAA;
26-
m_eddystoneData.frameType = EDDYSTONE_TLM_FRAME_TYPE;
27-
m_eddystoneData.version = 0;
28-
m_eddystoneData.volt = 3300; // 3300mV = 3.3V
29-
m_eddystoneData.temp = (uint16_t) ((float) 23.00)/256;
30-
m_eddystoneData.advCount = 0;
31-
m_eddystoneData.tmil = 0;
25+
beaconUUID = 0xFEAA;
26+
m_eddystoneData.frameType = EDDYSTONE_TLM_FRAME_TYPE;
27+
m_eddystoneData.version = 0;
28+
m_eddystoneData.volt = 3300; // 3300mV = 3.3V
29+
m_eddystoneData.temp = (uint16_t) ((float) 23.00)/256;
30+
m_eddystoneData.advCount = 0;
31+
m_eddystoneData.tmil = 0;
3232
} // BLEEddystoneTLM
3333

34+
BLEEddystoneTLM::BLEEddystoneTLM(BLEAdvertisedDevice *advertisedDevice){
35+
char* payload = (char*)advertisedDevice->getPayload();
36+
for(int i = 0; i < advertisedDevice->getPayloadLength(); ++i){
37+
if(payload[i] == 0x16 && advertisedDevice->getPayloadLength() >= i+2+sizeof(m_eddystoneData) && payload[i+1] == 0xAA && payload[i+2] == 0xFE && payload[i+3] == 0x20){
38+
log_d("Eddystone TLM data frame starting at byte [%d]", i+3);
39+
setData(std::string(payload+i+3, sizeof(m_eddystoneData)));
40+
break;
41+
}
42+
}
43+
}
44+
3445
std::string BLEEddystoneTLM::getData() {
35-
return std::string((char*) &m_eddystoneData, sizeof(m_eddystoneData));
46+
return std::string((char*) &m_eddystoneData, sizeof(m_eddystoneData));
3647
} // getData
3748

3849
BLEUUID BLEEddystoneTLM::getUUID() {
39-
return BLEUUID(beaconUUID);
50+
return BLEUUID(beaconUUID);
4051
} // getUUID
4152

4253
uint8_t BLEEddystoneTLM::getVersion() {
43-
return m_eddystoneData.version;
54+
return m_eddystoneData.version;
4455
} // getVersion
4556

4657
uint16_t BLEEddystoneTLM::getVolt() {
47-
return ENDIAN_CHANGE_U16(m_eddystoneData.volt);
58+
return ENDIAN_CHANGE_U16(m_eddystoneData.volt);
4859
} // getVolt
4960

5061
float BLEEddystoneTLM::getTemp() {
5162
return EDDYSTONE_TEMP_U16_TO_FLOAT(m_eddystoneData.temp);
5263
} // getTemp
5364

5465
uint16_t BLEEddystoneTLM::getRawTemp() {
55-
return ENDIAN_CHANGE_U16(m_eddystoneData.temp);
66+
return ENDIAN_CHANGE_U16(m_eddystoneData.temp);
5667
} // getRawTemp
5768

5869
uint32_t BLEEddystoneTLM::getCount() {
59-
return ENDIAN_CHANGE_U32(m_eddystoneData.advCount);
70+
return ENDIAN_CHANGE_U32(m_eddystoneData.advCount);
6071
} // getCount
6172

6273
uint32_t BLEEddystoneTLM::getTime() {
63-
return (ENDIAN_CHANGE_U32(m_eddystoneData.tmil)) / 10;
74+
return (ENDIAN_CHANGE_U32(m_eddystoneData.tmil)) / 10;
6475
} // getTime
6576

6677
std::string BLEEddystoneTLM::toString() {
@@ -116,9 +127,10 @@ std::string BLEEddystoneTLM::toString() {
116127
/**
117128
* Set the raw data for the beacon record.
118129
* Example:
119-
* uint8_t *payLoad = advertisedDevice.getPayload();
120-
* eddystoneTLM.setData(std::string((char*)payLoad+22, advertisedDevice.getPayloadLength() - 22));
121-
* Note: the offset 22 works for current implementation of example BLE_EddystoneTLM Beacon.ino, however it is not static and will be reimplemented
130+
* uint8_t *payload = advertisedDevice.getPayload();
131+
* eddystoneTLM.setData(std::string((char*)payload+22, advertisedDevice.getPayloadLength() - 22));
132+
* Note: the offset 22 works for current implementation of example BLE_EddystoneTLM Beacon.ino, however
133+
* the position is not static and it is programmers responsibility to align the data.
122134
* Data frame:
123135
* | Field || Len | Type | UUID | EddyStone TLM |
124136
* | Offset || 0 | 1 | 2 | 4 |
@@ -132,35 +144,35 @@ std::string BLEEddystoneTLM::toString() {
132144
* | Data || 0x20 | ?? | ?? | ?? | ?? | ?? | | | | | | | | |
133145
*/
134146
void BLEEddystoneTLM::setData(std::string data) {
135-
if (data.length() != sizeof(m_eddystoneData)) {
136-
log_e("Unable to set the data ... length passed in was %d and expected %d", data.length(), sizeof(m_eddystoneData));
137-
return;
138-
}
147+
if (data.length() != sizeof(m_eddystoneData)) {
148+
log_e("Unable to set the data ... length passed in was %d and expected %d", data.length(), sizeof(m_eddystoneData));
149+
return;
150+
}
139151
memcpy(&m_eddystoneData, data.data(), data.length());
140152
} // setData
141153

142154
void BLEEddystoneTLM::setUUID(BLEUUID l_uuid) {
143-
beaconUUID = l_uuid.getNative()->uuid.uuid16;
155+
beaconUUID = l_uuid.getNative()->uuid.uuid16;
144156
} // setUUID
145157

146158
void BLEEddystoneTLM::setVersion(uint8_t version) {
147-
m_eddystoneData.version = version;
159+
m_eddystoneData.version = version;
148160
} // setVersion
149161

150162
void BLEEddystoneTLM::setVolt(uint16_t volt) {
151-
m_eddystoneData.volt = volt;
163+
m_eddystoneData.volt = volt;
152164
} // setVolt
153165

154166
void BLEEddystoneTLM::setTemp(float temp) {
155-
m_eddystoneData.temp = EDDYSTONE_TEMP_FLOAT_TO_U16(temp);
167+
m_eddystoneData.temp = EDDYSTONE_TEMP_FLOAT_TO_U16(temp);
156168
} // setTemp
157169

158170
void BLEEddystoneTLM::setCount(uint32_t advCount) {
159-
m_eddystoneData.advCount = advCount;
171+
m_eddystoneData.advCount = advCount;
160172
} // setCount
161173

162174
void BLEEddystoneTLM::setTime(uint32_t tmil) {
163-
m_eddystoneData.tmil = tmil;
175+
m_eddystoneData.tmil = tmil;
164176
} // setTime
165177

166178
#endif

libraries/BLE/src/BLEEddystoneTLM.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#if SOC_BLE_SUPPORTED
1212

1313
#include "BLEUUID.h"
14+
#include <BLEAdvertisedDevice.h>
1415

1516
#define EDDYSTONE_TLM_FRAME_TYPE 0x20
1617
#define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00)>>8) + (((x)&0xFF)<<8))
@@ -26,6 +27,7 @@
2627
class BLEEddystoneTLM {
2728
public:
2829
BLEEddystoneTLM();
30+
BLEEddystoneTLM(BLEAdvertisedDevice *advertisedDevice);
2931
std::string getData();
3032
BLEUUID getUUID();
3133
uint8_t getVersion();

0 commit comments

Comments
 (0)