Skip to content
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

Add Device ID Profile implementation, simple BLE Serial implementation #9

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
78 changes: 78 additions & 0 deletions examples/BLE_ios_serial/BLE_ios_serial.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* This example illustrates use of BLEDeviceID which makes the device
* discoverable on iOS, which requires all Bluetooth devices to implement the
* Device ID Profile:
* https://developer.apple.com/hardwaredrivers/BluetoothDesignGuidelines.pdf
*
* It also shows usage of BLESerial which implements a Stream-compliant serial
* protocol.
*
* This imitates a DFRobot Bluno BLE device which uses a simple serial protocol
* for communication. BLESerial on ESP32 can be used equivalently with
* Serial on Bluno BLE devices.
*
* Connect to "Bluno ESP" using LightBlue or another BLE test app.
* The DFB1 characteristic in the DFB0 service is rewritten every
* two seconds, and values written to this characteristc will be displayed
* on the ESP's serial console.
*/

#include <BLEDevice.h>
#include <BLEDeviceID.h>
#include <BLESerial.h>
#include <BLEServer.h>

BLESerial bleSerial = BLESerial();

void setup() {
Serial.begin(115200);

BLEDevice::init("Bluno ESP");
BLEServer *server = BLEDevice::createServer();

bleSerial.begin(server, BLEUUID((uint16_t)0xDFB0), BLEUUID((uint16_t)0xDFB1));

BLEDeviceID* did = new BLEDeviceID(
server,
"0x0BB9FD999969D238",
"DF Bluno",
"0123456789",
"FW V1.97",
"HW V1.7",
"SW V1.97",
"DFRobot",
"",
1,
0x0010,
0x0D00,
0);
did->start();
server->getAdvertising()->start();
}

// This digit will be the first character of our message.
byte counter = 0;

void loop() {
// The message we'll send to the client.
// First byte will be an incrementing digit.
std::string message = " Hi!";
// Convert counter digit to ASCII and put it in our message.
message[0] = '0' + counter;
counter = (counter + 1) % 10;
bleSerial.write(message.c_str());

if (bleSerial.available() > 0) {
// Read up to 20 characters from the client, plus one for null-termination
char buf[21];
byte len = bleSerial.readBytesUntil('\0', buf, sizeof(buf) - 1);
// Make sure the string is null-terminated.
buf[len] = '\0';
Serial.print("Got serial data: ");
Serial.println(buf);
} else {
Serial.print(millis());
Serial.println(" No serial data.");
}
delay(2000);
}
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ paragraph=This library provides an implementation Bluetooth Low Energy support f
category=Communication
url=https://github.com/nkolban/ESP32_BLE_Arduino
architectures=esp32
includes=BLE.h, BLEUtils.h, BLEScan.h, BLEAdvertisedDevice.h
includes=BLE.h, BLEUtils.h, BLEScan.h, BLEAdvertisedDevice.h, BLEDeviceID.h, BLESerial.h
109 changes: 109 additions & 0 deletions src/BLEDeviceID.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
BLEDeviceID.cpp - Bluetooth Low Energy Device ID Profile implementation.
Copyright (c) 2017 by Grant Patterson. All rights reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include <stdlib.h>

#include "BLEDeviceID.h"

BLEDeviceID::BLEDeviceID(
BLEServer* server,
std::string systemId, // 0x2A23, 64 bits, use strtoull format "0x..."
std::string modelNumber, // 0x2A24
std::string serialNumber, // 0x2A25
std::string firmwareRevision, // 0x2A26
std::string hardwareRevision, // 0x2A27
std::string softwareRevision, // 0x2A28
std::string manufacturerName, // 0x2A29
std::string ieee11073_20601, // 0x2A2A, standard is behind paywall.
// 0x2A50 PnP ID values:
uint8_t vendorIdSource, // 1=Bluetooth SIG, 2=USB Impl. Forum
uint16_t vendorId,
uint16_t productId,
uint16_t productVersion) {
// Need space for 20 handles to hold all the characteristics we have.
service = server->createService(BLEUUID((uint16_t)0x180A), 20);

// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.system_id.xml
// Use strtoull to convert string to 64-bit value.
// systemId should probably be of format "0x0123456789ABCDEF"
unsigned long long systemIdLong = strtoull(systemId.c_str(), NULL, 0);
// Store 64 bits as byte stream; string is convenient
systemId = std::string((char*)&systemIdLong, sizeof(systemIdLong));
// Need to reverse string to correct for bigendian
systemId = std::string(systemId.rbegin(), systemId.rend());
service->createCharacteristic(
BLEUUID((uint16_t)0x2A23),
BLECharacteristic::PROPERTY_READ)
->setValue(systemId);

// Straightforward string values.
service->createCharacteristic(
BLEUUID((uint16_t)0x2A24),
BLECharacteristic::PROPERTY_READ)
->setValue(modelNumber);
service->createCharacteristic(
BLEUUID((uint16_t)0x2A25),
BLECharacteristic::PROPERTY_READ)
->setValue(serialNumber);
service->createCharacteristic(
BLEUUID((uint16_t)0x2A26),
BLECharacteristic::PROPERTY_READ)
->setValue(firmwareRevision);
service->createCharacteristic(
BLEUUID((uint16_t)0x2A27),
BLECharacteristic::PROPERTY_READ)
->setValue(hardwareRevision);
service->createCharacteristic(
BLEUUID((uint16_t)0x2A28),
BLECharacteristic::PROPERTY_READ)
->setValue(softwareRevision);
service->createCharacteristic(
BLEUUID((uint16_t)0x2A29),
BLECharacteristic::PROPERTY_READ)
->setValue(manufacturerName);
// Format is mysterious.
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.ieee_11073-20601_regulatory_certification_data_list.xml
service->createCharacteristic(
BLEUUID((uint16_t)0x2A2A),
BLECharacteristic::PROPERTY_READ)
->setValue(ieee11073_20601);

// Per spec, order these from least-significant octet to most.
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.pnp_id.xml
uint8_t val2a50[7];
val2a50[6] = vendorIdSource;
val2a50[5] = vendorId;
val2a50[4] = vendorId >> 8;
val2a50[3] = productId;
val2a50[2] = productId >> 8;
val2a50[1] = productVersion;
val2a50[0] = productVersion >> 8;
service->createCharacteristic(
BLEUUID((uint16_t)0x2A50),
BLECharacteristic::PROPERTY_READ)
->setValue(val2a50, sizeof(val2a50));
}

void BLEDeviceID::start() {
service->start();
}

#endif // CONFIG_BT_ENABLED
55 changes: 55 additions & 0 deletions src/BLEDeviceID.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
BLEDeviceID.h - Bluetooth Low Energy Device ID Profile implementation.
Copyright (c) 2017 by Grant Patterson. All rights reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef MAIN_BLEDeviceID_H_
#define MAIN_BLEDeviceID_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include <inttypes.h>
#include <string>

#include "BLEService.h"

class BLEDeviceID {
public:
// Specify server and all values needed to implement the Device ID spec:
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.device_information.xml
BLEDeviceID(
BLEServer* server,
std::string systemId, // 0x2A23, 64 bits, use strtoull format "0x..."
std::string modelNumber, // 0x2A24
std::string serialNumber, // 0x2A25
std::string firmwareRevision, // 0x2A26
std::string hardwareRevision, // 0x2A27
std::string softwareRevision, // 0x2A28
std::string manufacturerName, // 0x2A29
std::string ieee11073_20601, // 0x2A2A, standard is behind paywall.
// 0x2A50 PnP ID values:
uint8_t vendorIdSource, // 1=Bluetooth SIG, 2=USB Impl. Forum
uint16_t vendorId,
uint16_t productId,
uint16_t productVersion);
void start();

protected:
BLEService* service;
};

#endif // CONFIG_BT_ENABLED
#endif /* MAIN_BLEDeviceID_H_ */
94 changes: 94 additions & 0 deletions src/BLESerial.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
BLESerial.cpp - Bluetooth Low Energy Serial library.
Copyright (c) 2017 by Grant Patterson. All rights reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "BLESerial.h"

BLESerial::BLESerial() {
}

// From BLECharacteristicCallbacks
void BLESerial::onWrite(BLECharacteristic* characteristic) {
buffer += characteristic->getValue();
}

void BLESerial::begin(BLEServer* server, BLEUUID service_uuid, BLEUUID characteristic_uuid)
{
service = server->createService(service_uuid);
buffer = "";
characteristic = service->createCharacteristic(characteristic_uuid,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY);
BLEDescriptor* desc = new BLEDescriptor(BLEUUID((uint16_t)0x2901));
desc->setValue("Serial");
characteristic->addDescriptor(desc);
characteristic->setCallbacks(this);
service->start();
}

void BLESerial::end() {
}

void BLESerial::setDebugOutput(bool en) {
}

int BLESerial::available(void) {
return buffer.size();
}

int BLESerial::peek(void) {
if (available()) {
return (int)buffer[0];
}
return -1;
}

int BLESerial::read(void) {
if (available()) {
int result = (int)buffer[0];
buffer.erase(0, 1);
return result;
}
return -1;
}

void BLESerial::flush() {
// Pretty sure this is supposed to go both ways in Arduino.
buffer.clear();
}

size_t BLESerial::write(uint8_t c) {
characteristic->setValue(&c, 1);
characteristic->notify();
return 1;
}

size_t BLESerial::write(const uint8_t *buffer, size_t size) {
characteristic->setValue((uint8_t*)buffer, size);
characteristic->notify();
return size;
}

uint32_t BLESerial::baudRate() {
return 0;
}

BLESerial::operator bool() const {
return true;
}
Loading