44 ESP32之低功耗蓝牙(BLE)服务端编程 - 基于Arduino
例1 服务器最简编程
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#define SERVICE_UUID "b0afd88d-5807-4533-b27b-a48cc3a32e30" //服务UUID
#define CHARACTERISTIC_UUID "7057310c-1e37-4a0a-9ae1-6ed8ccb995b1" //特征UUID
void setup() {
Serial.begin(115200);
Serial.println("Starting BLE work!");
delay(500);
BLEDevice::init("Fish Fish"); //初始化蓝牙设备
auto local_address = BLEDevice::getAddress(); //获取本机地址
Serial.println(local_address.toString().c_str());
BLEServer *pServer = BLEDevice::createServer(); //创建一个服务器
BLEService *pService = pServer->createService(SERVICE_UUID); //创建一个服务
BLECharacteristic *pCharacteristic = pService->createCharacteristic( //在服务里创建一个特征
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setValue("Hello World."); //给特征赋值
pService->start(); //Service开始提供服务
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); //获取广播器
pAdvertising->addServiceUUID(SERVICE_UUID); //将Service加入广播
pAdvertising->setScanResponse(true); //允许扫描回复
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising(); //开始广播
Serial.println("Characteristic defined! Now you can read it in your phone!");
}
void loop() {
}
例2 添加自动再次广播
同时只能处理一个或多个客户端
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#define SERVICE_UUID "b0afd88d-5807-4533-b27b-a48cc3a32e30" //服务UUID
#define CHARACTERISTIC_UUID "7057310c-1e37-4a0a-9ae1-6ed8ccb995b1" //特征UUID
bool isAdvertising = true; //是否在广播
int clientCount = 0; //目前已有客户端数量
//服务器连接与断开连接回调类
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
Serial.println("client connected...");
clientCount++;
isAdvertising = false; //因为只要有客户端连上来,就会关闭广播
};
void onDisconnect(BLEServer* pServer) {
Serial.println("client disconnected...");
clientCount--;
}
};
void setup() {
Serial.begin(115200);
Serial.println("Starting BLE work!");
delay(500);
BLEDevice::init("Fish Fish"); //初始化蓝牙设备
auto local_address = BLEDevice::getAddress(); //获取本机地址
Serial.println(local_address.toString().c_str());
BLEServer *pServer = BLEDevice::createServer(); //创建一个服务器
pServer->setCallbacks(new MyServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID); //创建一个服务
BLECharacteristic *pCharacteristic = pService->createCharacteristic( //在服务里创建一个特征
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setValue("Hello World."); //给特征赋值
pService->start(); //Service开始提供服务
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); //获取广播器
pAdvertising->addServiceUUID(SERVICE_UUID); //将Service加入广播
pAdvertising->setScanResponse(true); //允许扫描回复
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising(); //开始广播
Serial.println("Characteristic defined! Now you can read it in your phone!");
}
void loop() {
if(BLEDevice::getInitialized() && !isAdvertising && clientCount<1)
{
delay(500); //让蓝牙设备留一段处理的时间
BLEDevice::startAdvertising(); //重新开始广播
isAdvertising = true;
Serial.println("start advertising");
}
delay(50);
}
例3 添加配对认证(静态密码)
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#define SERVICE_UUID "b0afd88d-5807-4533-b27b-a48cc3a32e30" //服务UUID
#define CHARACTERISTIC_UUID "7057310c-1e37-4a0a-9ae1-6ed8ccb995b1" //特征UUID
bool isAdvertising = true; //是否在广播
int clientCount = 0; //目前已有客户端数量
class MySecurity : public BLESecurityCallbacks {
uint32_t onPassKeyRequest(){
Serial.println("PassKeyRequest!");
return 334455;
}
//显示本机要求的静态码
void onPassKeyNotify(uint32_t pass_key){
Serial.printf("On passkey Notify number:%d", pass_key);
}
bool onSecurityRequest(){
Serial.println("On Security Request!");
return true;
}
//认证结果
void onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl){
if(cmpl.success){
Serial.println("onAuthenticationComplete!");
} else {
Serial.println("onAuthentication not Complete!");
}
}
//显示动态码并确定是否同意配对
bool onConfirmPIN(uint32_t pin){
Serial.printf("onConfirmPIN %d !", pin);
//return false;
return true; //返回true同意配对,返回false拒绝配对
}
};
//服务器连接与断开连接回调类
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
Serial.println("client connected...");
clientCount++;
isAdvertising = false; //因为只要有客户端连上来,就会关闭广播
};
void onDisconnect(BLEServer* pServer) {
Serial.println("client disconnected...");
clientCount--;
}
};
void setup() {
Serial.begin(115200);
Serial.println("Starting BLE work!");
delay(500);
BLEDevice::init("Fish Fish"); //初始化蓝牙设备
BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT_MITM);
BLEDevice::setSecurityCallbacks(new MySecurity());
BLESecurity *pSecurity = new BLESecurity();
pSecurity->setStaticPIN(112233); //这个是设置静态密码
auto local_address = BLEDevice::getAddress(); //获取本机地址
Serial.println(local_address.toString().c_str());
BLEServer *pServer = BLEDevice::createServer(); //创建一个服务器
pServer->setCallbacks(new MyServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID); //创建一个服务
BLECharacteristic *pCharacteristic = pService->createCharacteristic( //在服务里创建一个特征
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setValue("Hello World."); //给特征赋值
pService->start(); //Service开始提供服务
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); //获取广播器
pAdvertising->addServiceUUID(SERVICE_UUID); //将Service加入广播
pAdvertising->setScanResponse(true); //允许扫描回复
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising(); //开始广播
Serial.println("Characteristic defined! Now you can read it in your phone!");
}
void loop() {
if(BLEDevice::getInitialized() && !isAdvertising && clientCount<1)
{
delay(500); //让蓝牙设备留一段处理的时间
BLEDevice::startAdvertising(); //重新开始广播
isAdvertising = true;
Serial.println("start advertising");
}
delay(50);
}
例4 添加配对认证(交互认证)
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#define SERVICE_UUID "b0afd88d-5807-4533-b27b-a48cc3a32e30" //服务UUID
#define CHARACTERISTIC_UUID "7057310c-1e37-4a0a-9ae1-6ed8ccb995b1" //特征UUID
bool isAdvertising = true; //是否在广播
int clientCount = 0; //目前已有客户端数量
class MySecurity : public BLESecurityCallbacks {
uint32_t onPassKeyRequest(){
Serial.println("PassKeyRequest!");
return 334455;
}
//显示本机要求的静态码
void onPassKeyNotify(uint32_t pass_key){
Serial.printf("On passkey Notify number:%d", pass_key);
}
bool onSecurityRequest(){
Serial.println("On Security Request!");
return true;
}
//认证结果
void onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl){
if(cmpl.success){
Serial.println("onAuthenticationComplete!");
} else {
Serial.println("onAuthentication not Complete!");
}
}
//显示动态码并确定是否同意配对
bool onConfirmPIN(uint32_t pin){
Serial.printf("onConfirmPIN %d !", pin);
//return false;
return true; //返回true同意配对,返回false拒绝配对
}
};
//服务器连接与断开连接回调类
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
Serial.println("client connected...");
clientCount++;
isAdvertising = false; //因为只要有客户端连上来,就会关闭广播
};
void onDisconnect(BLEServer* pServer) {
Serial.println("client disconnected...");
clientCount--;
}
};
void setup() {
Serial.begin(115200);
Serial.println("Starting BLE work!");
delay(500);
BLEDevice::init("Fish Fish"); //初始化蓝牙设备
BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT_MITM);
BLEDevice::setSecurityCallbacks(new MySecurity());
BLESecurity *pSecurity = new BLESecurity();
pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_MITM_BOND);
pSecurity->setCapability(ESP_IO_CAP_IO); //显示yes,no
//pSecurity->setCapability(ESP_IO_CAP_NONE); //没有IO设备
pSecurity->setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);
auto local_address = BLEDevice::getAddress(); //获取本机地址
Serial.println(local_address.toString().c_str());
BLEServer *pServer = BLEDevice::createServer(); //创建一个服务器
pServer->setCallbacks(new MyServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID); //创建一个服务
BLECharacteristic *pCharacteristic = pService->createCharacteristic( //在服务里创建一个特征
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setValue("Hello World."); //给特征赋值
pService->start(); //Service开始提供服务
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); //获取广播器
pAdvertising->addServiceUUID(SERVICE_UUID); //将Service加入广播
pAdvertising->setScanResponse(true); //允许扫描回复
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising(); //开始广播
Serial.println("Characteristic defined! Now you can read it in your phone!");
}
void loop() {
if(BLEDevice::getInitialized() && !isAdvertising && clientCount<1)
{
delay(500); //让蓝牙设备留一段处理的时间
BLEDevice::startAdvertising(); //重新开始广播
isAdvertising = true;
Serial.println("start advertising");
}
delay(50);
}
例5 多特征,加密及notify
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <AsyncTimer.h>
#include <BLE2902.h>
#include <BLEUUID.h>
#define SERVICE_UUID "b0afd88d-5807-4533-b27b-a48cc3a32e30" //服务UUID
#define CHARACTERISTIC_UUID "7057310c-1e37-4a0a-9ae1-6ed8ccb995b1" //特征UUID
#define COUNT_CHARACTERISTIC_UUID "37582929-48c3-4dd0-8e4f-0b29c5640489" //计数器特征
uint32_t value = 0;
BLECharacteristic *countCharacteristic = NULL;
AsyncTimer t;
bool isAdvertising = true; //是否在广播
int clientCount = 0; //目前已有客户端数量
class MySecurity : public BLESecurityCallbacks {
uint32_t onPassKeyRequest(){
Serial.println("PassKeyRequest!");
return 334455;
}
//显示本机要求的静态码
void onPassKeyNotify(uint32_t pass_key){
Serial.printf("On passkey Notify number:%d", pass_key);
}
bool onSecurityRequest(){
Serial.println("On Security Request!");
return true;
}
//认证结果
void onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl){
if(cmpl.success){
Serial.println("onAuthenticationComplete!");
} else {
Serial.println("onAuthentication not Complete!");
}
}
//显示动态码并确定是否同意配对
bool onConfirmPIN(uint32_t pin){
Serial.printf("onConfirmPIN %d !", pin);
//return false;
return true; //返回true同意配对,返回false拒绝配对
}
};
//服务器连接与断开连接回调类
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
Serial.println("client connected...");
clientCount++;
isAdvertising = false; //因为只要有客户端连上来,就会关闭广播
};
void onDisconnect(BLEServer* pServer) {
Serial.println("client disconnected...");
clientCount--;
}
};
void setup() {
Serial.begin(115200);
Serial.println("Starting BLE work!");
delay(500);
BLEDevice::init("Fish Fish"); //初始化蓝牙设备
BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT_MITM);
BLEDevice::setSecurityCallbacks(new MySecurity());
BLESecurity *pSecurity = new BLESecurity();
pSecurity->setStaticPIN(112233); //这个是设置静态密码
auto local_address = BLEDevice::getAddress(); //获取本机地址
Serial.println(local_address.toString().c_str());
BLEServer *pServer = BLEDevice::createServer(); //创建一个服务器
pServer->setCallbacks(new MyServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID); //创建一个服务
BLECharacteristic *pCharacteristic = pService->createCharacteristic( //在服务里创建一个特征
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);
pCharacteristic->setValue("Hello World."); //给特征赋值
countCharacteristic = pService->createCharacteristic(
COUNT_CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
countCharacteristic->setValue(value);
countCharacteristic->addDescriptor(new BLE2902()); //要启用notify和indicate的都要添加这个描述符
BLEDescriptor *pCountName = new BLEDescriptor(BLEUUID((uint16_t)0x2901));
pCountName->setValue("My Counter");
countCharacteristic->addDescriptor(pCountName);
pService->start(); //Service开始提供服务
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); //获取广播器
pAdvertising->addServiceUUID(SERVICE_UUID); //将Service加入广播
pAdvertising->setScanResponse(true); //允许扫描回复
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising(); //开始广播
Serial.println("Characteristic defined! Now you can read it in your phone!");
//每3秒计数器加1,并发通知
t.setInterval([]{
Serial.println("plus...");
value++;
if(countCharacteristic && clientCount>0)
{
countCharacteristic->setValue(value);
countCharacteristic->notify(); //发通知
//countCharacteristic->indicate();
Serial.println("notify");
}
}, 3000);
//处理自动广播问题
t.setInterval([]{
if(BLEDevice::getInitialized() && !isAdvertising && clientCount<1)
{
delay(500); //让蓝牙设备留一段处理的时间
BLEDevice::startAdvertising(); //重新开始广播
isAdvertising = true;
Serial.println("start advertising");
}
}, 50);
}
void loop() {
t.handle();
}
例6 特征读写回调
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <AsyncTimer.h>
#include <BLE2902.h>
#include <BLEUUID.h>
#define SERVICE_UUID "b0afd88d-5807-4533-b27b-a48cc3a32e30" //服务UUID
#define CHARACTERISTIC_UUID "7057310c-1e37-4a0a-9ae1-6ed8ccb995b1" //特征UUID
#define COUNT_CHARACTERISTIC_UUID "37582929-48c3-4dd0-8e4f-0b29c5640489" //计数器特征
uint32_t value = 0;
BLECharacteristic *countCharacteristic = NULL;
AsyncTimer t;
bool isAdvertising = true; //是否在广播
int clientCount = 0; //目前已有客户端数量
class MyCharacteristicCallbacks: public BLECharacteristicCallbacks{
virtual void onRead(BLECharacteristic* pCharacteristic, esp_ble_gatts_cb_param_t* param)
{
auto p = param->read;
auto conn_id = p.conn_id;
BLEAddress address(p.bda);
Serial.printf("Read.. %d, %s\r\n", conn_id, address.toString().c_str());
}
virtual void onWrite(BLECharacteristic* pCharacteristic, esp_ble_gatts_cb_param_t* param)
{
auto p = param->read;
auto conn_id = p.conn_id;
BLEAddress address(p.bda);
Serial.printf("Write.. %d, %s\r\n", conn_id, address.toString().c_str());
}
virtual void onNotify(BLECharacteristic* pCharacteristic)
{
Serial.println("notify...");
}
};
class MySecurity : public BLESecurityCallbacks {
uint32_t onPassKeyRequest(){
Serial.println("PassKeyRequest!");
return 334455;
}
//显示本机要求的静态码
void onPassKeyNotify(uint32_t pass_key){
Serial.printf("On passkey Notify number:%d", pass_key);
}
bool onSecurityRequest(){
Serial.println("On Security Request!");
return true;
}
//认证结果
void onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl){
if(cmpl.success){
Serial.println("onAuthenticationComplete!");
} else {
Serial.println("onAuthentication not Complete!");
}
}
//显示动态码并确定是否同意配对
bool onConfirmPIN(uint32_t pin){
Serial.printf("onConfirmPIN %d !", pin);
//return false;
return true; //返回true同意配对,返回false拒绝配对
}
};
//服务器连接与断开连接回调类
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
Serial.println("client connected...");
clientCount++;
isAdvertising = false; //因为只要有客户端连上来,就会关闭广播
};
void onDisconnect(BLEServer* pServer) {
Serial.println("client disconnected...");
clientCount--;
}
};
void setup() {
Serial.begin(115200);
Serial.println("Starting BLE work!");
delay(500);
BLEDevice::init("Fish Fish"); //初始化蓝牙设备
BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT_MITM);
BLEDevice::setSecurityCallbacks(new MySecurity());
BLESecurity *pSecurity = new BLESecurity();
pSecurity->setStaticPIN(112233); //这个是设置静态密码
auto local_address = BLEDevice::getAddress(); //获取本机地址
Serial.println(local_address.toString().c_str());
BLEServer *pServer = BLEDevice::createServer(); //创建一个服务器
pServer->setCallbacks(new MyServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID); //创建一个服务
BLECharacteristic *pCharacteristic = pService->createCharacteristic( //在服务里创建一个特征
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);
pCharacteristic->setValue("Hello World."); //给特征赋值
pCharacteristic->setCallbacks(new MyCharacteristicCallbacks());
countCharacteristic = pService->createCharacteristic(
COUNT_CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
countCharacteristic->setValue(value);
countCharacteristic->addDescriptor(new BLE2902()); //要启用notify和indicate的都要添加这个描述符
BLEDescriptor *pCountName = new BLEDescriptor(BLEUUID((uint16_t)0x2901));
pCountName->setValue("My Counter");
countCharacteristic->addDescriptor(pCountName);
countCharacteristic->setCallbacks(new MyCharacteristicCallbacks());
pService->start(); //Service开始提供服务
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); //获取广播器
pAdvertising->addServiceUUID(SERVICE_UUID); //将Service加入广播
pAdvertising->setScanResponse(true); //允许扫描回复
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising(); //开始广播
Serial.println("Characteristic defined! Now you can read it in your phone!");
//每3秒计数器加1,并发通知
t.setInterval([]{
value++;
if(countCharacteristic && clientCount>0)
{
countCharacteristic->setValue(value);
countCharacteristic->notify(); //发通知
//countCharacteristic->indicate();
}
}, 3000);
//处理自动广播问题
t.setInterval([]{
if(BLEDevice::getInitialized() && !isAdvertising && clientCount<1)
{
delay(500); //让蓝牙设备留一段处理的时间
BLEDevice::startAdvertising(); //重新开始广播
isAdvertising = true;
Serial.println("start advertising");
}
}, 50);
}
void loop() {
t.handle();
}