mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-29 02:51:17 +00:00
WIP of adding NRF52 bluetooth API, we take a hardfault in Bluefruit init
This commit is contained in:
parent
3400bcde85
commit
4147786b12
@ -1,8 +1,22 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common lib functions for all platforms that have bluetooth
|
* Common lib functions for all platforms that have bluetooth
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define MESH_SERVICE_UUID "6ba1b218-15a8-461f-9fa8-5dcae273eafd"
|
||||||
|
|
||||||
|
#define TORADIO_UUID "f75c76d2-129e-4dad-a1dd-7866124401e7"
|
||||||
|
#define FROMRADIO_UUID "8ba2bcc2-ee02-4a55-a531-c525c5e454d5"
|
||||||
|
#define FROMNUM_UUID "ed9da18c-a800-4f66-a670-aa7547e34453"
|
||||||
|
|
||||||
|
// NRF52 wants these constants without the hypen and I'm lazy
|
||||||
|
#define MESH_SERVICE_UUID_16 ((const uint8_t *)"6ba1b21815a8461f9fa85dcae273eafd")
|
||||||
|
#define TORADIO_UUID_16 ((const uint8_t *)"f75c76d2129e4dada1dd7866124401e7")
|
||||||
|
#define FROMRADIO_UUID_16 ((const uint8_t *)"8ba2bcc2ee024a55a531c525c5e454d5")
|
||||||
|
#define FROMNUM_UUID_16 ((const uint8_t *)"ed9da18ca8004f66a670aa7547e34453")
|
||||||
|
|
||||||
/// Given a level between 0-100, update the BLE attribute
|
/// Given a level between 0-100, update the BLE attribute
|
||||||
void updateBatteryLevel(uint8_t level);
|
void updateBatteryLevel(uint8_t level);
|
@ -5,6 +5,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <esp_gatt_defs.h>
|
#include <esp_gatt_defs.h>
|
||||||
|
|
||||||
|
#include "BluetoothCommon.h"
|
||||||
#include "CallbackCharacteristic.h"
|
#include "CallbackCharacteristic.h"
|
||||||
#include "GPS.h"
|
#include "GPS.h"
|
||||||
#include "MeshService.h"
|
#include "MeshService.h"
|
||||||
@ -39,26 +40,20 @@ class BluetoothPhoneAPI : public PhoneAPI
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
BluetoothPhoneAPI *bluetoothPhoneAPI;
|
static BluetoothPhoneAPI *bluetoothPhoneAPI;
|
||||||
|
|
||||||
|
|
||||||
class ToRadioCharacteristic : public CallbackCharacteristic
|
class ToRadioCharacteristic : public CallbackCharacteristic
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ToRadioCharacteristic() : CallbackCharacteristic("f75c76d2-129e-4dad-a1dd-7866124401e7", BLECharacteristic::PROPERTY_WRITE) {}
|
ToRadioCharacteristic() : CallbackCharacteristic(TORADIO_UUID, BLECharacteristic::PROPERTY_WRITE) {}
|
||||||
|
|
||||||
void onWrite(BLECharacteristic *c)
|
void onWrite(BLECharacteristic *c) { bluetoothPhoneAPI->handleToRadio(c->getData(), c->getValue().length()); }
|
||||||
{
|
|
||||||
bluetoothPhoneAPI->handleToRadio(c->getData(), c->getValue().length());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FromRadioCharacteristic : public CallbackCharacteristic
|
class FromRadioCharacteristic : public CallbackCharacteristic
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FromRadioCharacteristic() : CallbackCharacteristic("8ba2bcc2-ee02-4a55-a531-c525c5e454d5", BLECharacteristic::PROPERTY_READ)
|
FromRadioCharacteristic() : CallbackCharacteristic(FROMRADIO_UUID, BLECharacteristic::PROPERTY_READ) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void onRead(BLECharacteristic *c)
|
void onRead(BLECharacteristic *c)
|
||||||
{
|
{
|
||||||
@ -78,9 +73,8 @@ class FromNumCharacteristic : public CallbackCharacteristic
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FromNumCharacteristic()
|
FromNumCharacteristic()
|
||||||
: CallbackCharacteristic("ed9da18c-a800-4f66-a670-aa7547e34453", BLECharacteristic::PROPERTY_WRITE |
|
: CallbackCharacteristic(FROMNUM_UUID, BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_READ |
|
||||||
BLECharacteristic::PROPERTY_READ |
|
BLECharacteristic::PROPERTY_NOTIFY)
|
||||||
BLECharacteristic::PROPERTY_NOTIFY)
|
|
||||||
{
|
{
|
||||||
// observe(&service.fromNumChanged);
|
// observe(&service.fromNumChanged);
|
||||||
}
|
}
|
||||||
@ -100,7 +94,7 @@ BLEService *createMeshBluetoothService(BLEServer *server)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the BLE Service, we need more than the default of 15 handles
|
// Create the BLE Service, we need more than the default of 15 handles
|
||||||
BLEService *service = server->createService(BLEUUID("6ba1b218-15a8-461f-9fa8-5dcae273eafd"), 30, 0);
|
BLEService *service = server->createService(BLEUUID(MESH_SERVICE_UUID), 30, 0);
|
||||||
|
|
||||||
assert(!meshFromNumCharacteristic);
|
assert(!meshFromNumCharacteristic);
|
||||||
meshFromNumCharacteristic = new FromNumCharacteristic;
|
meshFromNumCharacteristic = new FromNumCharacteristic;
|
||||||
|
@ -1,23 +1,38 @@
|
|||||||
#include "NRF52Bluetooth.h"
|
#include "NRF52Bluetooth.h"
|
||||||
|
#include "BluetoothCommon.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "BluetoothCommon.h"
|
|
||||||
#include <bluefruit.h>
|
#include <bluefruit.h>
|
||||||
|
|
||||||
/* HRM Service Definitions
|
static BLEService meshBleService = BLEService(BLEUuid(MESH_SERVICE_UUID_16));
|
||||||
* Heart Rate Monitor Service: 0x180D
|
static BLECharacteristic fromNum = BLECharacteristic(BLEUuid(FROMNUM_UUID_16));
|
||||||
* Heart Rate Measurement Char: 0x2A37
|
static BLECharacteristic fromRadio = BLECharacteristic(BLEUuid(FROMRADIO_UUID_16));
|
||||||
* Body Sensor Location Char: 0x2A38
|
static BLECharacteristic toRadio = BLECharacteristic(BLEUuid(TORADIO_UUID_16));
|
||||||
*/
|
|
||||||
BLEService hrms = BLEService(UUID16_SVC_HEART_RATE);
|
|
||||||
BLECharacteristic hrmc = BLECharacteristic(UUID16_CHR_HEART_RATE_MEASUREMENT);
|
|
||||||
BLECharacteristic bslc = BLECharacteristic(UUID16_CHR_BODY_SENSOR_LOCATION);
|
|
||||||
|
|
||||||
BLEDis bledis; // DIS (Device Information Service) helper class instance
|
static BLEDis bledis; // DIS (Device Information Service) helper class instance
|
||||||
BLEBas blebas; // BAS (Battery Service) helper class instance
|
static BLEBas blebas; // BAS (Battery Service) helper class instance
|
||||||
BLEDfu bledfu; // DFU software update helper service
|
static BLEDfu bledfu; // DFU software update helper service
|
||||||
|
|
||||||
uint8_t bps = 0;
|
// This scratch buffer is used for various bluetooth reads/writes - but it is safe because only one bt operation can be in
|
||||||
|
// proccess at once
|
||||||
|
// static uint8_t trBytes[_max(_max(_max(_max(ToRadio_size, RadioConfig_size), User_size), MyNodeInfo_size), FromRadio_size)];
|
||||||
|
static uint8_t fromRadioBytes[FromRadio_size];
|
||||||
|
|
||||||
|
class BluetoothPhoneAPI : public PhoneAPI
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 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");
|
||||||
|
fromNum.notify32(fromRadioNum);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static BluetoothPhoneAPI *bluetoothPhoneAPI;
|
||||||
|
|
||||||
void connect_callback(uint16_t conn_handle)
|
void connect_callback(uint16_t conn_handle)
|
||||||
{
|
{
|
||||||
@ -27,7 +42,7 @@ void connect_callback(uint16_t conn_handle)
|
|||||||
char central_name[32] = {0};
|
char central_name[32] = {0};
|
||||||
connection->getPeerName(central_name, sizeof(central_name));
|
connection->getPeerName(central_name, sizeof(central_name));
|
||||||
|
|
||||||
DEBUG_MSG("Connected to %s\n", central_name);
|
DEBUG_MSG("BLE Connected to %s\n", central_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,9 +53,8 @@ void connect_callback(uint16_t conn_handle)
|
|||||||
void disconnect_callback(uint16_t conn_handle, uint8_t reason)
|
void disconnect_callback(uint16_t conn_handle, uint8_t reason)
|
||||||
{
|
{
|
||||||
(void)conn_handle;
|
(void)conn_handle;
|
||||||
(void)reason;
|
|
||||||
|
|
||||||
DEBUG_MSG("Disconnected, reason = 0x%x\n", reason);
|
DEBUG_MSG("BLE Disconnected, reason = 0x%x\n", reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cccd_callback(uint16_t conn_hdl, BLECharacteristic *chr, uint16_t cccd_value)
|
void cccd_callback(uint16_t conn_hdl, BLECharacteristic *chr, uint16_t cccd_value)
|
||||||
@ -50,11 +64,11 @@ void cccd_callback(uint16_t conn_hdl, BLECharacteristic *chr, uint16_t cccd_valu
|
|||||||
|
|
||||||
// Check the characteristic this CCCD update is associated with in case
|
// Check the characteristic this CCCD update is associated with in case
|
||||||
// this handler is used for multiple CCCD records.
|
// this handler is used for multiple CCCD records.
|
||||||
if (chr->uuid == hrmc.uuid) {
|
if (chr->uuid == fromNum.uuid) {
|
||||||
if (chr->notifyEnabled(conn_hdl)) {
|
if (chr->notifyEnabled(conn_hdl)) {
|
||||||
DEBUG_MSG("Heart Rate Measurement 'Notify' enabled\n");
|
DEBUG_MSG("fromNum 'Notify' enabled\n");
|
||||||
} else {
|
} else {
|
||||||
DEBUG_MSG("Heart Rate Measurement 'Notify' disabled\n");
|
DEBUG_MSG("fromNum 'Notify' disabled\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,7 +80,7 @@ void startAdv(void)
|
|||||||
Bluefruit.Advertising.addTxPower();
|
Bluefruit.Advertising.addTxPower();
|
||||||
|
|
||||||
// Include HRM Service UUID
|
// Include HRM Service UUID
|
||||||
Bluefruit.Advertising.addService(hrms);
|
Bluefruit.Advertising.addService(meshBleService);
|
||||||
|
|
||||||
// Include Name
|
// Include Name
|
||||||
Bluefruit.Advertising.addName();
|
Bluefruit.Advertising.addName();
|
||||||
@ -86,67 +100,72 @@ void startAdv(void)
|
|||||||
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
|
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupHRM(void)
|
/**
|
||||||
|
* client is starting read, pull the bytes from our API class
|
||||||
|
*/
|
||||||
|
void fromRadioAuthorizeCb(uint16_t conn_hdl, BLECharacteristic *chr, ble_gatts_evt_read_t *request)
|
||||||
{
|
{
|
||||||
// Configure the Heart Rate Monitor service
|
size_t numBytes = bluetoothPhoneAPI->getFromRadio(fromRadioBytes);
|
||||||
// See: https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.heart_rate.xml
|
|
||||||
// Supported Characteristics:
|
DEBUG_MSG("fromRadioAuthorizeCb numBytes=%u\n", numBytes);
|
||||||
// Name UUID Requirement Properties
|
|
||||||
// ---------------------------- ------ ----------- ----------
|
// Someone is going to read our value as soon as this callback returns. So fill it with the next message in the queue
|
||||||
// Heart Rate Measurement 0x2A37 Mandatory Notify
|
// or make empty if the queue is empty
|
||||||
// Body Sensor Location 0x2A38 Optional Read
|
chr->write(fromRadioBytes, numBytes);
|
||||||
// Heart Rate Control Point 0x2A39 Conditional Write <-- Not used here
|
}
|
||||||
hrms.begin();
|
|
||||||
|
void toRadioWriteCb(uint16_t conn_hdl, BLECharacteristic *chr, uint8_t *data, uint16_t len)
|
||||||
|
{
|
||||||
|
DEBUG_MSG("toRadioWriteCb data %p, len %u\n", data, len);
|
||||||
|
|
||||||
|
bluetoothPhoneAPI->handleToRadio(data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* client is starting read, pull the bytes from our API class
|
||||||
|
*/
|
||||||
|
void fromNumAuthorizeCb(uint16_t conn_hdl, BLECharacteristic *chr, ble_gatts_evt_read_t *request)
|
||||||
|
{
|
||||||
|
DEBUG_MSG("fromNumAuthorizeCb FIXME - implement\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupMeshService(void)
|
||||||
|
{
|
||||||
|
bluetoothPhoneAPI = new BluetoothPhoneAPI();
|
||||||
|
bluetoothPhoneAPI->init();
|
||||||
|
|
||||||
|
meshBleService.begin();
|
||||||
|
|
||||||
// Note: You must call .begin() on the BLEService before calling .begin() on
|
// Note: You must call .begin() on the BLEService before calling .begin() on
|
||||||
// any characteristic(s) within that service definition.. Calling .begin() on
|
// any characteristic(s) within that service definition.. Calling .begin() on
|
||||||
// a BLECharacteristic will cause it to be added to the last BLEService that
|
// a BLECharacteristic will cause it to be added to the last BLEService that
|
||||||
// was 'begin()'ed!
|
// was 'begin()'ed!
|
||||||
|
|
||||||
// Configure the Heart Rate Measurement characteristic
|
fromNum.setProperties(CHR_PROPS_NOTIFY | CHR_PROPS_READ);
|
||||||
// See:
|
fromNum.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); // FIXME, secure this!!!
|
||||||
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.heart_rate_measurement.xml
|
fromNum.setFixedLen(
|
||||||
// Properties = Notify
|
0); // Variable len (either 0 or 4) FIXME consider changing protocol so it is fixed 4 byte len, where 0 means empty
|
||||||
// Min Len = 1
|
fromNum.setMaxLen(4);
|
||||||
// Max Len = 8
|
fromNum.setCccdWriteCallback(cccd_callback); // Optionally capture CCCD updates
|
||||||
// B0 = UINT8 - Flag (MANDATORY)
|
fromNum.setReadAuthorizeCallback(fromNumAuthorizeCb);
|
||||||
// b5:7 = Reserved
|
fromNum.begin();
|
||||||
// b4 = RR-Internal (0 = Not present, 1 = Present)
|
// uint8_t hrmdata[2] = {0b00000110, 0x40}; // Set the characteristic to use 8-bit values, with the sensor connected and
|
||||||
// b3 = Energy expended status (0 = Not present, 1 = Present)
|
// detected
|
||||||
// b1:2 = Sensor contact status (0+1 = Not supported, 2 = Supported but contact not detected, 3 = Supported and
|
// hrmc.write(hrmdata, 2);
|
||||||
// detected) b0 = Value format (0 = UINT8, 1 = UINT16)
|
|
||||||
// B1 = UINT8 - 8-bit heart rate measurement value in BPM
|
|
||||||
// B2:3 = UINT16 - 16-bit heart rate measurement value in BPM
|
|
||||||
// B4:5 = UINT16 - Energy expended in joules
|
|
||||||
// B6:7 = UINT16 - RR Internal (1/1024 second resolution)
|
|
||||||
hrmc.setProperties(CHR_PROPS_NOTIFY);
|
|
||||||
hrmc.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS);
|
|
||||||
hrmc.setFixedLen(2);
|
|
||||||
hrmc.setCccdWriteCallback(cccd_callback); // Optionally capture CCCD updates
|
|
||||||
hrmc.begin();
|
|
||||||
uint8_t hrmdata[2] = {0b00000110, 0x40}; // Set the characteristic to use 8-bit values, with the sensor connected and detected
|
|
||||||
hrmc.write(hrmdata, 2);
|
|
||||||
|
|
||||||
// Configure the Body Sensor Location characteristic
|
fromRadio.setProperties(CHR_PROPS_READ);
|
||||||
// See:
|
fromRadio.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); // FIXME secure this!
|
||||||
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.body_sensor_location.xml
|
fromRadio.setMaxLen(512);
|
||||||
// Properties = Read
|
fromRadio.setReadAuthorizeCallback(fromRadioAuthorizeCb);
|
||||||
// Min Len = 1
|
fromRadio.setBuffer(fromRadioBytes,
|
||||||
// Max Len = 1
|
sizeof(fromRadioBytes)); // we preallocate our fromradio buffer so we won't waste space for two copies
|
||||||
// B0 = UINT8 - Body Sensor Location
|
fromRadio.begin();
|
||||||
// 0 = Other
|
|
||||||
// 1 = Chest
|
toRadio.setProperties(CHR_PROPS_WRITE);
|
||||||
// 2 = Wrist
|
toRadio.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); // FIXME secure this!
|
||||||
// 3 = Finger
|
toRadio.setMaxLen(512);
|
||||||
// 4 = Hand
|
toRadio.setWriteCallback(toRadioWriteCb);
|
||||||
// 5 = Ear Lobe
|
toRadio.begin();
|
||||||
// 6 = Foot
|
|
||||||
// 7:255 = Reserved
|
|
||||||
bslc.setProperties(CHR_PROPS_READ);
|
|
||||||
bslc.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS);
|
|
||||||
bslc.setFixedLen(1);
|
|
||||||
bslc.begin();
|
|
||||||
bslc.write8(2); // Set the characteristic to 'Wrist' (2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME, turn off soft device access for debugging
|
// FIXME, turn off soft device access for debugging
|
||||||
@ -174,14 +193,14 @@ void NRF52Bluetooth::setup()
|
|||||||
// Start the BLE Battery Service and set it to 100%
|
// Start the BLE Battery Service and set it to 100%
|
||||||
DEBUG_MSG("Configuring the Battery Service\n");
|
DEBUG_MSG("Configuring the Battery Service\n");
|
||||||
blebas.begin();
|
blebas.begin();
|
||||||
blebas.write(42); // FIXME, report real power levels
|
blebas.write(0); // Unknown battery level for now
|
||||||
|
|
||||||
bledfu.begin(); // Install the DFU helper
|
bledfu.begin(); // Install the DFU helper
|
||||||
|
|
||||||
// Setup the Heart Rate Monitor service using
|
// Setup the Heart Rate Monitor service using
|
||||||
// BLEService and BLECharacteristic classes
|
// BLEService and BLECharacteristic classes
|
||||||
DEBUG_MSG("Configuring the Heart Rate Monitor Service\n");
|
DEBUG_MSG("Configuring the Mesh bluetooth service\n");
|
||||||
setupHRM();
|
setupMeshService();
|
||||||
|
|
||||||
// Supposedly debugging works with soft device if you disable advertising
|
// Supposedly debugging works with soft device if you disable advertising
|
||||||
if (isSoftDeviceAllowed) {
|
if (isSoftDeviceAllowed) {
|
||||||
@ -194,8 +213,9 @@ void NRF52Bluetooth::setup()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Given a level between 0-100, update the BLE attribute
|
/// Given a level between 0-100, update the BLE attribute
|
||||||
void updateBatteryLevel(uint8_t level) {
|
void updateBatteryLevel(uint8_t level)
|
||||||
// FIXME - implement
|
{
|
||||||
|
blebas.write(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -52,9 +52,9 @@ void setBluetoothEnable(bool on)
|
|||||||
if (on != bleOn) {
|
if (on != bleOn) {
|
||||||
if (on) {
|
if (on) {
|
||||||
if (!nrf52Bluetooth) {
|
if (!nrf52Bluetooth) {
|
||||||
DEBUG_MSG("DISABLING NRF52 BLUETOOTH WHILE DEBUGGING\n");
|
// DEBUG_MSG("DISABLING NRF52 BLUETOOTH WHILE DEBUGGING\n");
|
||||||
//nrf52Bluetooth = new NRF52Bluetooth();
|
nrf52Bluetooth = new NRF52Bluetooth();
|
||||||
//nrf52Bluetooth->setup();
|
nrf52Bluetooth->setup();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DEBUG_MSG("FIXME: implement BLE disable\n");
|
DEBUG_MSG("FIXME: implement BLE disable\n");
|
||||||
|
Loading…
Reference in New Issue
Block a user