Skip to content

Commit

Permalink
Update examples
Browse files Browse the repository at this point in the history
  • Loading branch information
h2zero committed Dec 10, 2024
1 parent 740a1e7 commit 1e7b5c7
Show file tree
Hide file tree
Showing 26 changed files with 857 additions and 2,170 deletions.
202 changes: 73 additions & 129 deletions examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.ino
Original file line number Diff line number Diff line change
Expand Up @@ -3,151 +3,95 @@
Ported to Arduino ESP32 by Evandro Copercini
*/

/** NimBLE differences highlighted in comment blocks **/

/*******original********
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include "BLEEddystoneURL.h"
#include "BLEEddystoneTLM.h"
#include "BLEBeacon.h"
***********************/

#include <Arduino.h>

#include <NimBLEDevice.h>
#include <NimBLEAdvertisedDevice.h>
#include "NimBLEEddystoneURL.h"
#include "NimBLEEddystoneTLM.h"
#include "NimBLEBeacon.h"

#define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00) >> 8) + (((x)&0xFF) << 8))

int scanTime = 5 * 1000; //In milliseconds
BLEScan *pBLEScan;
#define ENDIAN_CHANGE_U16(x) ((((x) & 0xFF00) >> 8) + (((x) & 0xFF) << 8))

class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
{
/*** Only a reference to the advertised device is passed now
void onResult(BLEAdvertisedDevice advertisedDevice) { **/
void onResult(BLEAdvertisedDevice *advertisedDevice)
{
if (advertisedDevice->haveName())
{
Serial.print("Device name: ");
Serial.println(advertisedDevice->getName().c_str());
Serial.println("");
}
int scanTime = 5 * 1000; // In milliseconds
NimBLEScan* pBLEScan;

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");
}
class ScanCallbacks : public NimBLEScanCallbacks {
void onResult(const NimBLEAdvertisedDevice* advertisedDevice) override {
if (advertisedDevice->haveName()) {
Serial.print("Device name: ");
Serial.println(advertisedDevice->getName().c_str());
Serial.println("");
}
return;
}

BLEUUID eddyUUID = (uint16_t)0xfeaa;

if (advertisedDevice->getServiceUUID().equals(eddyUUID))
{
std::string serviceData = advertisedDevice->getServiceData(eddyUUID);
if (serviceData[0] == 0x10)
{
Serial.println("Found an EddystoneURL beacon!");
BLEEddystoneURL foundEddyURL = BLEEddystoneURL();

foundEddyURL.setData(serviceData);
std::string bareURL = foundEddyURL.getURL();
if (bareURL[0] == 0x00)
{
Serial.println("DATA-->");
for (int idx = 0; idx < serviceData.length(); idx++)
{
Serial.printf("0x%08X ", serviceData[idx]);
if (advertisedDevice->haveServiceUUID()) {
NimBLEUUID 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();
if (strManufacturerData.length() == 25 && strManufacturerData[0] == 0x4C && strManufacturerData[1] == 0x00) {
Serial.println("Found an iBeacon!");
NimBLEBeacon oBeacon = NimBLEBeacon();
oBeacon.setData(reinterpret_cast<const uint8_t*>(strManufacturerData.data()), strManufacturerData.length());
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]", strManufacturerData[i]);
}
Serial.printf("\n");
}
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 (serviceData[0] == 0x20)
{
Serial.println("Found an EddystoneTLM beacon!");
BLEEddystoneTLM foundEddyURL = BLEEddystoneTLM();
foundEddyURL.setData(serviceData);

Serial.printf("Reported battery voltage: %dmV\n", foundEddyURL.getVolt());
Serial.printf("Reported temperature from TLM class: %.2fC\n", (double)foundEddyURL.getTemp());
int temp = (int)serviceData[5] + (int)(serviceData[4] << 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");
NimBLEUUID eddyUUID = (uint16_t)0xfeaa;

if (advertisedDevice->getServiceUUID().equals(eddyUUID)) {
std::string serviceData = advertisedDevice->getServiceData(eddyUUID);
if (serviceData[0] == 0x20) {
Serial.println("Found an EddystoneTLM beacon!");
NimBLEEddystoneTLM foundEddyTLM = NimBLEEddystoneTLM();
foundEddyTLM.setData(reinterpret_cast<const uint8_t*>(serviceData.data()), serviceData.length());

Serial.printf("Reported battery voltage: %dmV\n", foundEddyTLM.getVolt());
Serial.printf("Reported temperature from TLM class: %.2fC\n", (double)foundEddyTLM.getTemp());
int temp = (int)serviceData[5] + (int)(serviceData[4] << 8);
float calcTemp = temp / 256.0f;
Serial.printf("Reported temperature from data: %.2fC\n", calcTemp);
Serial.printf("Reported advertise count: %d\n", foundEddyTLM.getCount());
Serial.printf("Reported time since last reboot: %ds\n", foundEddyTLM.getTime());
Serial.println("\n");
Serial.print(foundEddyTLM.toString().c_str());
Serial.println("\n");
}
}
}
}
};

void setup()
{
Serial.begin(115200);
Serial.println("Scanning...");

BLEDevice::init("");
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setScanCallbacks(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
} scanCallbacks;

void setup() {
Serial.begin(115200);
Serial.println("Scanning...");

NimBLEDevice::init("Beacon-scanner");
pBLEScan = BLEDevice::getScan();
pBLEScan->setScanCallbacks(&scanCallbacks);
pBLEScan->setActiveScan(true);
pBLEScan->setInterval(100);
pBLEScan->setWindow(100);
}

void loop()
{
// put your main code here, to run repeatedly:
BLEScanResults foundDevices = pBLEScan->getResults(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);
void loop() {
NimBLEScanResults foundDevices = pBLEScan->getResults(scanTime, false);
Serial.print("Devices found: ");
Serial.println(foundDevices.getCount());
Serial.println("Scan done!");
pBLEScan->clearResults(); // delete results scan buffer to release memory
delay(2000);
}
1 change: 0 additions & 1 deletion examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ Initiates a BLE device scan.
Checks if the discovered devices are
- an iBeacon
- an Eddystone TLM beacon
- an Eddystone URL beacon

and sends the decoded beacon information over Serial log
140 changes: 55 additions & 85 deletions examples/BLE_EddystoneTLM_Beacon/BLE_EddystoneTLM_Beacon.ino
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
EddystoneTLM beacon for NimBLE by BeeGee based on https://github.com/pcbreflux/espressif/blob/master/esp32/arduino/sketchbook/ESP32_Eddystone_TLM_deepsleep/ESP32_Eddystone_TLM_deepsleep.ino
EddystoneTLM beacon by BeeGee based on
https://github.com/pcbreflux/espressif/blob/master/esp32/arduino/sketchbook/ESP32_Eddystone_TLM_deepsleep/ESP32_Eddystone_TLM_deepsleep.ino
EddystoneTLM frame specification https://github.com/google/eddystone/blob/master/eddystone-tlm/tlm-plain.md
*/

Expand All @@ -13,102 +14,71 @@
5. Stop advertising.
6. deep sleep
To read data advertised by this beacon use second ESP with example sketch BLE_Beacon_Scanner
*/

#include "NimBLEDevice.h"
#include "NimBLEBeacon.h"
#include "NimBLEAdvertising.h"
#include "NimBLEEddystoneURL.h"
#include <Arduino.h>
#include <NimBLEDevice.h>
#include <NimBLEEddystoneTLM.h>
#include <sys/time.h>
#include <esp_sleep.h>

#include "sys/time.h"
#include "esp_sleep.h"
#define GPIO_DEEP_SLEEP_DURATION 10 // sleep x seconds and then wake up
#define BEACON_POWER 3 // 3dbm

#define GPIO_DEEP_SLEEP_DURATION 10 // sleep x seconds and then wake up

// UUID 1 128-Bit (may use linux tool uuidgen or random numbers via https://www.uuidgenerator.net/)
#define BEACON_UUID "8ec76ea3-6668-48da-9866-75be8bc86f4d"

RTC_DATA_ATTR static time_t last; // remember last boot in RTC Memory
RTC_DATA_ATTR static time_t last; // remember last boot in RTC Memory
RTC_DATA_ATTR static uint32_t bootcount; // remember number of boots in RTC Memory
NimBLEAdvertising* pAdvertising;
struct timeval nowTimeStruct;

BLEAdvertising *pAdvertising;
struct timeval nowTimeStruct;

time_t lastTenth;
#define BEACON_UUID \
"8ec76ea3-6668-48da-9866-75be8bc86f4d" // UUID 1 128-Bit (may use linux tool uuidgen or random numbers via https://www.uuidgenerator.net/)

// Check
// https://github.com/google/eddystone/blob/master/eddystone-tlm/tlm-plain.md
// and http://www.hugi.scene.org/online/coding/hugi%2015%20-%20cmtadfix.htm
// for the temperature value. It is a 8.8 fixed-point notation
void setBeacon()
{
char beacon_data[25];
uint16_t beconUUID = 0xFEAA;
uint16_t volt = random(2800, 3700); // 3300mV = 3.3V
float tempFloat = random(2000, 3100) / 100.0f;
Serial.printf("Random temperature is %.2fC\n", tempFloat);
int temp = (int)(tempFloat * 256); //(uint16_t)((float)23.00);
Serial.printf("Converted to 8.8 format %0X%0X\n", (temp >> 8), (temp & 0xFF));

BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
BLEAdvertisementData oScanResponseData = BLEAdvertisementData();

oScanResponseData.setFlags(0x06); // GENERAL_DISC_MODE 0x02 | BR_EDR_NOT_SUPPORTED 0x04
oScanResponseData.setCompleteServices(BLEUUID(beconUUID));

beacon_data[0] = 0x20; // Eddystone Frame Type (Unencrypted Eddystone-TLM)
beacon_data[1] = 0x00; // TLM version
beacon_data[2] = (volt >> 8); // Battery voltage, 1 mV/bit i.e. 0xCE4 = 3300mV = 3.3V
beacon_data[3] = (volt & 0xFF); //
beacon_data[4] = (temp >> 8); // Beacon temperature
beacon_data[5] = (temp & 0xFF); //
beacon_data[6] = ((bootcount & 0xFF000000) >> 24); // Advertising PDU count
beacon_data[7] = ((bootcount & 0xFF0000) >> 16); //
beacon_data[8] = ((bootcount & 0xFF00) >> 8); //
beacon_data[9] = (bootcount & 0xFF); //
beacon_data[10] = ((lastTenth & 0xFF000000) >> 24); // Time since power-on or reboot as 0.1 second resolution counter
beacon_data[11] = ((lastTenth & 0xFF0000) >> 16); //
beacon_data[12] = ((lastTenth & 0xFF00) >> 8); //
beacon_data[13] = (lastTenth & 0xFF); //

oScanResponseData.setServiceData(BLEUUID(beconUUID), std::string(beacon_data, 14));
oAdvertisementData.setName("TLMBeacon");
pAdvertising->setAdvertisementData(oAdvertisementData);
pAdvertising->setScanResponseData(oScanResponseData);
void setBeacon() {
NimBLEEddystoneTLM eddystoneTLM;
eddystoneTLM.setVolt((uint16_t)random(2800, 3700)); // 3300mV = 3.3V
eddystoneTLM.setTemp(random(-3000, 3000)); // 3000 = 30.00 ˚C
Serial.printf("Random Battery voltage is %d mV = 0x%04X\n", eddystoneTLM.getVolt(), eddystoneTLM.getVolt());
Serial.printf("Random Temperature is: %d.%d 0x%04X\n",
eddystoneTLM.getTemp() / 256,
eddystoneTLM.getTemp() % 256 * 100 / 256);

NimBLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
NimBLEAdvertisementData oScanResponseData = BLEAdvertisementData();
oScanResponseData.setServiceData(NimBLEUUID("FEAA"),
reinterpret_cast<const uint8_t*>(&eddystoneTLM.getData()),
sizeof(NimBLEEddystoneTLM::BeaconData));

oAdvertisementData.setName("ESP32 TLM Beacon");
pAdvertising->setAdvertisementData(oAdvertisementData);
pAdvertising->setScanResponseData(oScanResponseData);
}

void setup()
{

Serial.begin(115200);
gettimeofday(&nowTimeStruct, NULL);

Serial.printf("start ESP32 %d\n", bootcount++);

Serial.printf("deep sleep (%lds since last reset, %lds since last boot)\n", nowTimeStruct.tv_sec, nowTimeStruct.tv_sec - last);

last = nowTimeStruct.tv_sec;
lastTenth = nowTimeStruct.tv_sec * 10; // Time since last reset as 0.1 second resolution counter

// Create the BLE Device
BLEDevice::init("TLMBeacon");

BLEDevice::setPower(ESP_PWR_LVL_N12);

pAdvertising = BLEDevice::getAdvertising();
pAdvertising->enableScanResponse(true);

setBeacon();
// Start advertising
pAdvertising->start();
Serial.println("Advertizing started for 10s ...");
delay(10000);
pAdvertising->stop();
Serial.printf("enter deep sleep for 10s\n");
esp_deep_sleep(1000000LL * GPIO_DEEP_SLEEP_DURATION);
Serial.printf("in deep sleep\n");
void setup() {
Serial.begin(115200);
gettimeofday(&nowTimeStruct, NULL);

Serial.printf("Starting ESP32. Bootcount = %lu\n", bootcount++);
Serial.printf("Deep sleep (%llds since last reset, %llds since last boot)\n",
nowTimeStruct.tv_sec,
nowTimeStruct.tv_sec - last);
last = nowTimeStruct.tv_sec;

NimBLEDevice::init("TLMBeacon");
NimBLEDevice::setPower(BEACON_POWER);

pAdvertising = NimBLEDevice::getAdvertising();
setBeacon();
pAdvertising->start();
Serial.println("Advertising started for 10s ...");
delay(10000);
pAdvertising->stop();
Serial.printf("Enter deep sleep for 10s\n");
esp_deep_sleep(1000000LL * GPIO_DEEP_SLEEP_DURATION);
}

void loop()
{
}
void loop() {}
Loading

0 comments on commit 1e7b5c7

Please sign in to comment.