Hi guys, I am trying to get BLE to work with ESP and I am stuck with this issue. Here's the complete code:
#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>
#ifdef HM_10
#include <SoftwareSerial.h>
#endif
namespace
{
//globals
bool fIsInitialized = false;
uint8_t fCounter = 0U;
uint16_t fPin = 0xFFU;
}
namespace ble
{
/**
* @brief Callbacks associated with the operation of a %BLE server.
*/
class ServerCallbacks: public BLEServerCallbacks
{
using Base = BLEServerCallbacks;
uint16_t fConnId = 0xFFFFU;
esp_ble_gatts_cb_param_t * fConnParams = nullptr;
public:
uint16_t getConnId() const
{
return fConnId;
}
virtual ~ServerCallbacks(){};
/**
* @brief Handle a new client connection.
*
* When a new client connects, we are invoked.
*
* @param [in] pServer A reference to the %BLE server that received the client connection.
*/
virtual void onConnect(BLEServer *pServer) override
{
fConnId = pServer->getConnId();
Serial.printf("BLE Connected: id: %d, mtu %d\n", fConnId, pServer->getPeerMTU(fConnId));
Base::onConnect(pServer);
}
virtual void onConnect(BLEServer *pServer, esp_ble_gatts_cb_param_t *param) override
{
fConnId = pServer->getConnId();
Serial.printf("BLE Connected: id: %d, mtu %d, param: %d\n", fConnId, pServer->getPeerMTU(fConnId));
fConnParams = param;
Base::onConnect(pServer);
}
/**
* @brief Handle an existing client disconnection.
*
* When an existing client disconnects, we are invoked.
*
* @param [in] pServer A reference to the %BLE server that received the existing client disconnection.
*/
virtual void onDisconnect(BLEServer *pServer)
{
Base::onDisconnect(pServer);
pServer->getAdvertising()->start();
}
/**
* @brief Handle a new client connection.
*
* When the MTU changes this method is invoked.
*
* @param [in] pServer A reference to the %BLE server that received the client connection.
* @param [in] param A reference to esp_ble_gatts_cb_param_t.
*/
virtual void onMtuChanged(BLEServer *pServer, esp_ble_gatts_cb_param_t *param) override
{
Base::onMtuChanged(pServer, param);
}
}; // BLEServerCallbacks
class EncryptionCallbacks : public BLESecurityCallbacks
{
uint32_t onPassKeyRequest()
{
Serial.printf("PassKeyRequest\n");
return fPin;
}
void onPassKeyNotify(uint32_t pass_key)
{
Serial.printf("The passkey Notify number:%d\n", pass_key);
}
bool onConfirmPIN(uint32_t pass_key)
{
Serial.printf("The passkey YES/NO number:%d\n", pass_key);
vTaskDelay(5000);
return true;
}
bool onSecurityRequest()
{
Serial.printf("SecurityRequest\n");
return true;
}
void onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl)
{
if (cmpl.success)
{
Serial.printf("Starting BLE work!\n");
}
else
{
Serial.printf("Authentication failed: %d\n", cmpl.fail_reason);
}
}
};
class ConfigurationCharacteristics : public BLECharacteristicCallbacks
{
void onWrite(BLECharacteristic *pCharacteristic)
{
std::string value = pCharacteristic->getValue();
if (value.length() > 0)
{
for (int i = 0; i < value.length(); i++)
Serial.print(value[i]);
}
Serial.println();
}
};
BLECharacteristic * setupService(BLEServer& server, const char * SERVICE_UUID, const char * CHARACTERISTIC_UUID, const uint32_t PROPERTIES)
{
BLEService *pService = server.createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
PROPERTIES);
pCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);
auto p = new BLE2902();
p->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);
pCharacteristic->addDescriptor(p);
return pCharacteristic;
}
void setupSecurity(const uint32_t pin)
{
BLESecurity *pSecurity = new BLESecurity();
uint8_t rsp_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
uint32_t passkey = pin;
uint8_t auth_option = ESP_BLE_ONLY_ACCEPT_SPECIFIED_AUTH_DISABLE;
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, &passkey, sizeof(uint32_t));
pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_BOND);
pSecurity->setCapability(ESP_IO_CAP_OUT);
pSecurity->setKeySize(16);
esp_ble_gap_set_security_param(ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTH, &auth_option, sizeof(uint8_t));
pSecurity->setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_RSP_KEY, &rsp_key, sizeof(uint8_t));
}
}
namespace constants
{
int RX_BLE = 12U; // From schematic
int TX_BLE = 11U; // From schematic
constexpr unsigned long READ_TIMEOUT = 2000U;
constexpr unsigned short INIT_DELAY = 500U;
constexpr unsigned long COM_TIMEOUT = 1000U;
const uint8_t MAC_ADDRESS_BYTE_LENGTH = 6U;
const String SERVICE_UUID = "3B661E69-F877-4CE8-9E89-D8DAB6F25DAA";
const String CHARACTERISTIC_UUID = "82C314B2-E53A-4D5E-B021-FC5887B4373F";
const std::__cxx11::string DEVICE_NAME = "Killswitch";
}
namespace crc
{
uint16_t crc16(const char* data_p, uint8_t length)
{
uint8_t x;
uint16_t crc = 0xFFFFU;
while (length--)
{
x = crc >> 8U ^ *data_p++;
x ^= x>>4;
crc = (crc << 8U) ^ (static_cast<uint16_t>(x << 12U)) ^ (static_cast<uint16_t>(x <<5U)) ^ (static_cast<uint16_t>(x));
}
return crc;
}
}
namespace io
{
void turnOn(const int pin)
{
digitalWrite(pin, HIGH);
}
void turnOff(const int pin)
{
digitalWrite(pin, LOW);
}
}
namespace com
{
bool initBluetooth()
{
if (!btStart())
{
Serial.println("Failed to initialize controller\n");
return false;
}
if (esp_bluedroid_init() != ESP_OK)
{
Serial.println("Failed to initialize bluedroid\n");
return false;
}
if (esp_bluedroid_enable() != ESP_OK)
{
Serial.println("Failed to enable bluedroid\n");
return false;
}
return true;
}
void printDeviceAddress()
{
// Print code here
const uint8_t* point = esp_bt_dev_get_address();
char mac_address[12] = {0U};
for (char i = 0; i < constants::MAC_ADDRESS_BYTE_LENGTH; i++)
{
char str[3];
sprintf(str, "%02X", (int)point[i]);
mac_address[(i*2)] = str[0];
mac_address[(i*2)+1] = str[1];
Serial.print(str);
if (i < 5)
{
Serial.print(":");
}
}
Serial.print("\n");
fPin = crc::crc16(mac_address, sizeof(mac_address));
Serial.print("Device BLE Pin: "); Serial.print(fPin); Serial.print("\n");
}
}
void initializeBluetoothModule()
{
//generate pin
while (!com::initBluetooth());
com::printDeviceAddress();
//setup server
BLEDevice::init(constants::DEVICE_NAME);
BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT);
BLEDevice::setSecurityCallbacks(new ble::EncryptionCallbacks());
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new ble::ServerCallbacks());
auto pCharacteristic = ble::setupService(*pServer, constants::SERVICE_UUID.c_str(), constants::CHARACTERISTIC_UUID.c_str(), BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE);
pCharacteristic->setValue("Hello World");
pServer->getServiceByUUID(constants::SERVICE_UUID.c_str())->start();
pServer->getAdvertising()->start();
ble::setupSecurity(fPin);
Serial.println("Characteristic defined! Now you can read it in your phone!");
}
// the setup function runs once when you press reset or power the board
void setup()
{
// Open console Serial port
Serial.begin(115200);
while (!Serial);
Serial.printf("Sketch: %s\n", __FILE__);
Serial.print(F("Uploaded: ")); Serial.println(__DATE__);
Serial.println(F("Started"));
//give some time for serial coms to establish
delay(constants::INIT_DELAY);
initializeBluetoothModule();
Serial.println("Bluetooth initialization done...\n");
}
// the loop function runs over and over again forever
void loop()
{
vTaskDelay(10);
}
On the opposite side, an iPhone X SE works perfectly with this exact same code. I have tried using several google "fixes" but without success.
Also here's the log of the code above:
Device BLE Pin: 60927
Characteristic defined! Now you can read it in your phone!
Bluetooth initialization done...
BLE Connected: id: 0, mtu 23
BLE Connected: id: 0, mtu 23, param: 1073490300
The passkey Notify number:60927
Authentication failed: 81
Hi guys, I am trying to get BLE to work with ESP and I am stuck with this issue. Here's the complete code:
On the opposite side, an iPhone X SE works perfectly with this exact same code. I have tried using several google "fixes" but without success.
Also here's the log of the code above:
I would be grateful for any help! Thanks!