Skip to content

Update examples #790

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading