Files
firmware/src/nimble/NimbleBluetooth.cpp

227 lines
7.1 KiB
C++
Raw Normal View History

2022-02-15 06:52:00 +13:00
#include "configuration.h"
#include "NimbleBluetooth.h"
2022-02-15 06:52:00 +13:00
#include "BluetoothCommon.h"
2022-03-06 05:43:26 +13:00
#include "PowerFSM.h"
#include "sleep.h"
2022-02-15 06:52:00 +13:00
#include "main.h"
#include "mesh/PhoneAPI.h"
#include "mesh/mesh-pb-constants.h"
#include <NimBLEDevice.h>
NimBLECharacteristic *fromNumCharacteristic;
2022-02-15 06:52:00 +13:00
NimBLEServer *bleServer;
2022-03-06 05:43:26 +13:00
static bool passkeyShowing;
static uint32_t doublepressed;
class BluetoothPhoneAPI : public PhoneAPI
2022-02-15 06:52:00 +13:00
{
/**
* Subclasses can use this as a hook to provide custom notifications for their transport (i.e. bluetooth notifies)
*/
virtual void onNowHasData(uint32_t fromRadioNum)
{
PhoneAPI::onNowHasData(fromRadioNum);
DEBUG_MSG("BLE notify fromNum\n");
uint8_t val[4];
put_le32(val, fromRadioNum);
2022-02-15 06:52:00 +13:00
fromNumCharacteristic->setValue(val, sizeof(val));
fromNumCharacteristic->notify();
}
2022-02-15 06:52:00 +13:00
/// Check the current underlying physical link to see if the client is currently connected
virtual bool checkIsConnected()
{
return bleServer && bleServer->getConnectedCount() > 0;
2022-02-15 06:52:00 +13:00
}
};
2022-02-15 06:52:00 +13:00
static BluetoothPhoneAPI *bluetoothPhoneAPI;
/**
* Subclasses can use this as a hook to provide custom notifications for their transport (i.e. bluetooth notifies)
*/
2022-02-15 06:52:00 +13:00
class NimbleBluetoothToRadioCallback : public NimBLECharacteristicCallbacks
{
2022-02-15 06:52:00 +13:00
virtual void onWrite(NimBLECharacteristic *pCharacteristic) {
2022-03-06 05:43:26 +13:00
DEBUG_MSG("To Radio onwrite\n");
auto val = pCharacteristic->getValue();
2022-02-15 06:52:00 +13:00
bluetoothPhoneAPI->handleToRadio(val.data(), val.length());
2022-02-15 06:52:00 +13:00
}
};
class NimbleBluetoothFromRadioCallback : public NimBLECharacteristicCallbacks
{
2022-02-15 06:52:00 +13:00
virtual void onRead(NimBLECharacteristic *pCharacteristic) {
2022-03-06 05:43:26 +13:00
DEBUG_MSG("From Radio onread\n");
uint8_t fromRadioBytes[FromRadio_size];
2022-02-15 06:52:00 +13:00
size_t numBytes = bluetoothPhoneAPI->getFromRadio(fromRadioBytes);
std::string fromRadioByteString(fromRadioBytes, fromRadioBytes + numBytes);
pCharacteristic->setValue(fromRadioByteString);
}
};
class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
{
2022-03-06 05:43:26 +13:00
virtual uint32_t onPassKeyRequest() {
uint32_t passkey = config.bluetooth.fixed_pin;
2022-03-06 05:43:26 +13:00
if (doublepressed > 0 && (doublepressed + (30 * 1000)) > millis()) {
DEBUG_MSG("User has set BLE pairing mode to fixed-pin\n");
config.bluetooth.mode = Config_BluetoothConfig_PairingMode_FixedPin;
nodeDB.saveToDisk();
} else if (config.bluetooth.mode == Config_BluetoothConfig_PairingMode_RandomPin) {
2022-03-06 05:43:26 +13:00
DEBUG_MSG("Using random passkey\n");
// This is the passkey to be entered on peer - we pick a number >100,000 to ensure 6 digits
passkey = random(100000, 999999);
2022-03-06 05:43:26 +13:00
}
DEBUG_MSG("*** Enter passkey %d on the peer side ***\n", passkey);
powerFSM.trigger(EVENT_BLUETOOTH_PAIR);
screen->startBluetoothPinScreen(passkey);
passkeyShowing = true;
return passkey;
}
virtual void onAuthenticationComplete(ble_gap_conn_desc *desc)
{
2022-03-06 05:43:26 +13:00
DEBUG_MSG("BLE authentication complete\n");
if (passkeyShowing) {
passkeyShowing = false;
screen->stopBluetoothPinScreen();
}
// bluetoothPhoneAPI->setInitialState();
2022-03-06 05:43:26 +13:00
}
virtual void onDisconnect(NimBLEServer* pServer, ble_gap_conn_desc *desc)
{
DEBUG_MSG("BLE disconnect\n");
}
2022-03-06 05:43:26 +13:00
};
2022-02-15 06:52:00 +13:00
static NimbleBluetoothToRadioCallback *toRadioCallbacks;
static NimbleBluetoothFromRadioCallback *fromRadioCallbacks;
2022-02-15 06:52:00 +13:00
void NimbleBluetooth::shutdown()
2022-02-15 06:52:00 +13:00
{
// Shutdown bluetooth for minimum power draw
2022-03-06 05:43:26 +13:00
DEBUG_MSG("Disable bluetooth\n");
2022-02-15 06:52:00 +13:00
//Bluefruit.Advertising.stop();
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
pAdvertising->reset();
pAdvertising->stop();
2022-02-15 06:52:00 +13:00
}
bool NimbleBluetooth::isActive()
{
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
return bleServer && (bleServer->getConnectedCount() > 0 || pAdvertising->isAdvertising());
}
void NimbleBluetooth::setup()
2022-02-15 06:52:00 +13:00
{
// Uncomment for testing
// NimbleBluetooth::clearBonds();
DEBUG_MSG("Initialise the NimBLE bluetooth module\n");
2022-02-15 06:52:00 +13:00
NimBLEDevice::init(getDeviceName());
2022-02-15 06:52:00 +13:00
NimBLEDevice::setPower(ESP_PWR_LVL_P9);
if (config.bluetooth.mode != Config_BluetoothConfig_PairingMode_NoPin) {
NimBLEDevice::setSecurityAuth(true, true, true);
NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY);
}
2022-02-15 06:52:00 +13:00
bleServer = NimBLEDevice::createServer();
2022-03-06 05:43:26 +13:00
NimbleBluetoothServerCallback *serverCallbacks = new NimbleBluetoothServerCallback();
bleServer->setCallbacks(serverCallbacks, true);
2022-03-06 05:43:26 +13:00
setupService();
startAdvertising();
}
void NimbleBluetooth::setupService()
{
2022-02-15 06:52:00 +13:00
NimBLEService *bleService = bleServer->createService(MESH_SERVICE_UUID);
NimBLECharacteristic *ToRadioCharacteristic;
NimBLECharacteristic *FromRadioCharacteristic;
// Define the characteristics that the app is looking for
if (config.bluetooth.mode == Config_BluetoothConfig_PairingMode_NoPin) {
ToRadioCharacteristic = bleService->createCharacteristic(TORADIO_UUID, NIMBLE_PROPERTY::WRITE);
FromRadioCharacteristic = bleService->createCharacteristic(FROMRADIO_UUID, NIMBLE_PROPERTY::READ);
fromNumCharacteristic = bleService->createCharacteristic(FROMNUM_UUID, NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ);
}
else {
ToRadioCharacteristic = bleService->createCharacteristic(TORADIO_UUID, NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_AUTHEN | NIMBLE_PROPERTY::WRITE_ENC);
FromRadioCharacteristic = bleService->createCharacteristic(FROMRADIO_UUID, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_AUTHEN | NIMBLE_PROPERTY::READ_ENC);
fromNumCharacteristic = bleService->createCharacteristic(FROMNUM_UUID, NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_AUTHEN | NIMBLE_PROPERTY::READ_ENC);
}
2022-02-15 06:52:00 +13:00
bluetoothPhoneAPI = new BluetoothPhoneAPI();
toRadioCallbacks = new NimbleBluetoothToRadioCallback();
2022-02-15 06:52:00 +13:00
ToRadioCharacteristic->setCallbacks(toRadioCallbacks);
fromRadioCallbacks = new NimbleBluetoothFromRadioCallback();
2022-02-15 06:52:00 +13:00
FromRadioCharacteristic->setCallbacks(fromRadioCallbacks);
bleService->start();
}
2022-02-15 06:52:00 +13:00
void NimbleBluetooth::startAdvertising()
{
2022-02-15 06:52:00 +13:00
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
pAdvertising->reset();
2022-02-15 06:52:00 +13:00
pAdvertising->addServiceUUID(MESH_SERVICE_UUID);
pAdvertising->start(0);
2022-02-15 06:52:00 +13:00
}
/// Given a level between 0-100, update the BLE attribute
void updateBatteryLevel(uint8_t level)
{
//blebas.write(level);
}
void NimbleBluetooth::clearBonds()
2022-02-15 06:52:00 +13:00
{
DEBUG_MSG("Clearing bluetooth bonds!\n");
NimBLEDevice::deleteAllBonds();
2022-02-15 06:52:00 +13:00
}
void clearNVS()
{
2022-03-06 05:43:26 +13:00
NimBLEDevice::deleteAllBonds();
#ifdef ARCH_ESP32
2022-03-06 05:43:26 +13:00
ESP.restart();
#endif
2022-02-15 06:52:00 +13:00
}
void disablePin()
{
2022-03-06 05:43:26 +13:00
DEBUG_MSG("User Override, disabling bluetooth pin requirement\n");
// keep track of when it was pressed, so we know it was within X seconds
// Flash the LED
setLed(true);
delay(100);
setLed(false);
delay(100);
setLed(true);
delay(100);
setLed(false);
delay(100);
setLed(true);
delay(100);
setLed(false);
doublepressed = millis();
2022-02-15 06:52:00 +13:00
}