mirror of
https://github.com/meshtastic/firmware.git
synced 2025-05-01 19:46:42 +00:00
Gutting bluetooth
This commit is contained in:
parent
cc5a08fcf0
commit
0c08d7c3dc
@ -2,7 +2,7 @@
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
default_envs = tbeam
|
||||
;default_envs = tbeam
|
||||
;default_envs = tbeam0.7
|
||||
;default_envs = heltec-v1
|
||||
;default_envs = heltec-v2.0
|
||||
@ -21,6 +21,7 @@ default_envs = tbeam
|
||||
;default_envs = meshtastic-diy-v1
|
||||
;default_envs = meshtastic-diy-v1.1
|
||||
;default_envs = m5stack-coreink
|
||||
default_envs = rak4631
|
||||
|
||||
extra_configs = variants/*/platformio.ini
|
||||
|
||||
@ -79,8 +80,6 @@ lib_deps =
|
||||
lib_deps =
|
||||
adafruit/Adafruit BusIO@^1.11.4
|
||||
adafruit/Adafruit Unified Sensor@^1.1.4
|
||||
paulstoffregen/OneWire@^2.3.5
|
||||
robtillaart/DS18B20@^0.1.11
|
||||
adafruit/Adafruit BMP280 Library@^2.6.3
|
||||
adafruit/Adafruit BME280 Library@^2.2.2
|
||||
adafruit/Adafruit BME680 Library@^2.0.1
|
||||
@ -99,11 +98,10 @@ debug_init_break = tbreak setup
|
||||
# Remove -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL for low level BLE logging.
|
||||
# See library directory for BLE logging possible values: .pio/libdeps/tbeam/NimBLE-Arduino/src/log_common/log_common.h
|
||||
# This overrides the BLE logging default of LOG_LEVEL_INFO (1) from: .pio/libdeps/tbeam/NimBLE-Arduino/src/esp_nimble_cfg.h
|
||||
# -DUSE_NEW_ESP32_BLUETOOTH will enable the new NimBLE C++ api
|
||||
build_flags =
|
||||
${arduino_base.build_flags} -Wall -Wextra -Isrc/platform/esp32 -lnimble -std=c++11
|
||||
-DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL
|
||||
-DAXP_DEBUG_PORT=Serial -DUSE_NEW_ESP32_BLUETOOTH -DCONFIG_BT_NIMBLE_ENABLED -DCONFIG_NIMBLE_CPP_LOG_LEVEL=1 -DCONFIG_BT_NIMBLE_MAX_CCCDS=20
|
||||
-DAXP_DEBUG_PORT=Serial -DCONFIG_BT_NIMBLE_ENABLED -DCONFIG_NIMBLE_CPP_LOG_LEVEL=2 -DCONFIG_BT_NIMBLE_MAX_CCCDS=20
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
|
@ -7,10 +7,6 @@
|
||||
#include "power.h"
|
||||
#include <OneButton.h>
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#include "nimble/BluetoothUtil.h"
|
||||
#endif
|
||||
|
||||
namespace concurrency
|
||||
{
|
||||
/**
|
||||
|
@ -33,13 +33,7 @@
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#include "mesh/http/WebServer.h"
|
||||
|
||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
||||
#include "platform/esp32/ESP32Bluetooth.h"
|
||||
#else
|
||||
#include "nimble/BluetoothUtil.h"
|
||||
#endif
|
||||
|
||||
#include "nimble/NimbleBluetooth.h"
|
||||
#endif
|
||||
|
||||
#if HAS_WIFI
|
||||
|
@ -16,6 +16,10 @@
|
||||
#include "modules/PositionModule.h"
|
||||
#include "power.h"
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#include "nimble/NimbleBluetooth.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
receivedPacketQueue - this is a queue of messages we've received from the mesh, which we are keeping to deliver to the phone.
|
||||
It is implemented with a FreeRTos queue (wrapped with a little RTQueue class) of pointers to MeshPacket protobufs (which were
|
||||
|
@ -1,662 +0,0 @@
|
||||
#ifndef USE_NEW_ESP32_BLUETOOTH
|
||||
|
||||
#include "BluetoothUtil.h"
|
||||
#include "BluetoothSoftwareUpdate.h"
|
||||
#include "NimbleBluetoothAPI.h"
|
||||
#include "PhoneAPI.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "configuration.h"
|
||||
#include "esp_bt.h"
|
||||
#include "host/util/util.h"
|
||||
#include "main.h"
|
||||
#include "nimble/NimbleDefs.h"
|
||||
#include "services/gap/ble_svc_gap.h"
|
||||
#include "services/gatt/ble_svc_gatt.h"
|
||||
#include "sleep.h"
|
||||
#include <WiFi.h>
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
#include <nvs_flash.h>
|
||||
#endif
|
||||
|
||||
static bool pinShowing;
|
||||
static uint32_t doublepressed;
|
||||
|
||||
static bool bluetoothActive;
|
||||
|
||||
//put the wider device into a bluetooth pairing mode, and show the pin on screen.
|
||||
//called in this file only
|
||||
static void startCb(uint32_t pin)
|
||||
{
|
||||
pinShowing = true;
|
||||
powerFSM.trigger(EVENT_BLUETOOTH_PAIR);
|
||||
screen->startBluetoothPinScreen(pin);
|
||||
};
|
||||
|
||||
//pairing has ended
|
||||
//called in this file only
|
||||
static void stopCb()
|
||||
{
|
||||
if (pinShowing) {
|
||||
pinShowing = false;
|
||||
screen->stopBluetoothPinScreen();
|
||||
}
|
||||
};
|
||||
|
||||
static uint8_t own_addr_type;
|
||||
|
||||
// Force arduino to keep ble data around
|
||||
extern "C" bool btInUse()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Given a level between 0-100, update the BLE attribute
|
||||
void updateBatteryLevel(uint8_t level)
|
||||
{
|
||||
// FIXME
|
||||
}
|
||||
|
||||
//shutdown the bluetooth and tear down all the data structures. to prevent memory leaks
|
||||
//called here only
|
||||
void deinitBLE()
|
||||
{
|
||||
if (bluetoothActive) {
|
||||
bluetoothActive = false;
|
||||
|
||||
// DEBUG_MSG("Shutting down bluetooth\n");
|
||||
// ble_gatts_show_local();
|
||||
|
||||
// FIXME - do we need to dealloc things? - what needs to stay alive across light sleep?
|
||||
auto ret = nimble_port_stop();
|
||||
assert(ret == ESP_OK);
|
||||
|
||||
nimble_port_deinit(); // teardown nimble datastructures
|
||||
|
||||
// DEBUG_MSG("BLE port_deinit done\n");
|
||||
|
||||
ret = esp_nimble_hci_and_controller_deinit();
|
||||
assert(ret == ESP_OK);
|
||||
|
||||
// DEBUG_MSG("BLE task exiting\n");
|
||||
|
||||
DEBUG_MSG("Done shutting down bluetooth\n");
|
||||
}
|
||||
}
|
||||
|
||||
void loopBLE()
|
||||
{
|
||||
// FIXME
|
||||
}
|
||||
|
||||
extern "C" void ble_store_config_init(void);
|
||||
|
||||
/// Print a macaddr - bytes are sometimes stored in reverse order
|
||||
//called here only
|
||||
static void print_addr(const uint8_t v[], bool isReversed = true)
|
||||
{
|
||||
const int macaddrlen = 6;
|
||||
|
||||
for (int i = 0; i < macaddrlen; i++) {
|
||||
DEBUG_MSG("%02x%c", v[isReversed ? macaddrlen - i : i], (i == macaddrlen - 1) ? '\n' : ':');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs information about a connection to the console.
|
||||
* called here only
|
||||
*/
|
||||
static void print_conn_desc(struct ble_gap_conn_desc *desc)
|
||||
{
|
||||
DEBUG_MSG("handle=%d our_ota_addr_type=%d our_ota_addr=", desc->conn_handle, desc->our_ota_addr.type);
|
||||
print_addr(desc->our_ota_addr.val);
|
||||
DEBUG_MSG(" our_id_addr_type=%d our_id_addr=", desc->our_id_addr.type);
|
||||
print_addr(desc->our_id_addr.val);
|
||||
DEBUG_MSG(" peer_ota_addr_type=%d peer_ota_addr=", desc->peer_ota_addr.type);
|
||||
print_addr(desc->peer_ota_addr.val);
|
||||
DEBUG_MSG(" peer_id_addr_type=%d peer_id_addr=", desc->peer_id_addr.type);
|
||||
print_addr(desc->peer_id_addr.val);
|
||||
DEBUG_MSG(" conn_itvl=%d conn_latency=%d supervision_timeout=%d "
|
||||
"encrypted=%d authenticated=%d bonded=%d\n",
|
||||
desc->conn_itvl, desc->conn_latency, desc->supervision_timeout, desc->sec_state.encrypted,
|
||||
desc->sec_state.authenticated, desc->sec_state.bonded);
|
||||
}
|
||||
|
||||
static void advertise();
|
||||
|
||||
/**
|
||||
* The nimble host executes this callback when a GAP event occurs. The
|
||||
* application associates a GAP event callback with each connection that forms.
|
||||
* bleprph uses the same callback for all connections.
|
||||
*
|
||||
* @param event The type of event being signalled.
|
||||
* @param ctxt Various information pertaining to the event.
|
||||
* @param arg Application-specified argument; unused by
|
||||
* bleprph.
|
||||
*
|
||||
* @return 0 if the application successfully handled the
|
||||
* event; nonzero on failure. The semantics
|
||||
* of the return code is specific to the
|
||||
* particular GAP event being signalled.
|
||||
*/
|
||||
static int gap_event(struct ble_gap_event *event, void *arg)
|
||||
{
|
||||
struct ble_gap_conn_desc desc;
|
||||
int rc;
|
||||
uint32_t now = millis();
|
||||
|
||||
switch (event->type) {
|
||||
case BLE_GAP_EVENT_CONNECT:
|
||||
/* A new connection was established or a connection attempt failed. */
|
||||
DEBUG_MSG("connection %s; status=%d ", event->connect.status == 0 ? "established" : "failed", event->connect.status);
|
||||
if (event->connect.status == 0) {
|
||||
rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
print_conn_desc(&desc);
|
||||
curConnectionHandle = event->connect.conn_handle;
|
||||
}
|
||||
DEBUG_MSG("\n");
|
||||
|
||||
if (event->connect.status != 0) {
|
||||
/* Connection failed; resume advertising. */
|
||||
advertise();
|
||||
}
|
||||
return 0;
|
||||
|
||||
case BLE_GAP_EVENT_DISCONNECT:
|
||||
DEBUG_MSG("disconnect; reason=%d ", event->disconnect.reason);
|
||||
print_conn_desc(&event->disconnect.conn);
|
||||
DEBUG_MSG("\n");
|
||||
|
||||
curConnectionHandle = -1;
|
||||
|
||||
/* Connection terminated; resume advertising. */
|
||||
advertise();
|
||||
return 0;
|
||||
|
||||
case BLE_GAP_EVENT_CONN_UPDATE:
|
||||
/* The central has updated the connection parameters. */
|
||||
DEBUG_MSG("connection updated; status=%d ", event->conn_update.status);
|
||||
rc = ble_gap_conn_find(event->conn_update.conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
print_conn_desc(&desc);
|
||||
DEBUG_MSG("\n");
|
||||
return 0;
|
||||
|
||||
case BLE_GAP_EVENT_ADV_COMPLETE:
|
||||
DEBUG_MSG("advertise complete; reason=%d", event->adv_complete.reason);
|
||||
advertise();
|
||||
return 0;
|
||||
|
||||
case BLE_GAP_EVENT_ENC_CHANGE:
|
||||
/* Encryption has been enabled or disabled for this connection. */
|
||||
DEBUG_MSG("encryption change event; status=%d ", event->enc_change.status);
|
||||
rc = ble_gap_conn_find(event->enc_change.conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
print_conn_desc(&desc);
|
||||
DEBUG_MSG("\n");
|
||||
|
||||
// Remove our custom PIN request screen.
|
||||
stopCb();
|
||||
return 0;
|
||||
|
||||
case BLE_GAP_EVENT_SUBSCRIBE:
|
||||
DEBUG_MSG("subscribe event; conn_handle=%d attr_handle=%d "
|
||||
"reason=%d prevn=%d curn=%d previ=%d curi=%d\n",
|
||||
event->subscribe.conn_handle, event->subscribe.attr_handle, event->subscribe.reason,
|
||||
event->subscribe.prev_notify, event->subscribe.cur_notify, event->subscribe.prev_indicate,
|
||||
event->subscribe.cur_indicate);
|
||||
return 0;
|
||||
|
||||
case BLE_GAP_EVENT_MTU:
|
||||
DEBUG_MSG("mtu update event; conn_handle=%d cid=%d mtu=%d\n", event->mtu.conn_handle, event->mtu.channel_id,
|
||||
event->mtu.value);
|
||||
return 0;
|
||||
|
||||
case BLE_GAP_EVENT_REPEAT_PAIRING:
|
||||
DEBUG_MSG("repeat pairing event; conn_handle=%d "
|
||||
"cur_key_sz=%d cur_auth=%d cur_sc=%d "
|
||||
"new_key_sz=%d new_auth=%d new_sc=%d "
|
||||
"new_bonding=%d\n",
|
||||
event->repeat_pairing.conn_handle, event->repeat_pairing.cur_key_size, event->repeat_pairing.cur_authenticated,
|
||||
event->repeat_pairing.cur_sc, event->repeat_pairing.new_key_size, event->repeat_pairing.new_authenticated,
|
||||
event->repeat_pairing.new_sc, event->repeat_pairing.new_bonding);
|
||||
/* We already have a bond with the peer, but it is attempting to
|
||||
* establish a new secure link. This app sacrifices security for
|
||||
* convenience: just throw away the old bond and accept the new link.
|
||||
*/
|
||||
|
||||
/* Delete the old bond. */
|
||||
rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
ble_store_util_delete_peer(&desc.peer_id_addr);
|
||||
|
||||
/* Return BLE_GAP_REPEAT_PAIRING_RETRY to indicate that the host should
|
||||
* continue with the pairing operation.
|
||||
*/
|
||||
return BLE_GAP_REPEAT_PAIRING_RETRY;
|
||||
|
||||
case BLE_GAP_EVENT_PASSKEY_ACTION:
|
||||
DEBUG_MSG("PASSKEY_ACTION_EVENT started \n");
|
||||
struct ble_sm_io pkey = {0};
|
||||
|
||||
if (event->passkey.params.action == BLE_SM_IOACT_DISP) {
|
||||
pkey.action = event->passkey.params.action;
|
||||
DEBUG_MSG("dp: %d now:%d\n", doublepressed, now);
|
||||
if (doublepressed > 0 && (doublepressed + (30 * 1000)) > now) {
|
||||
DEBUG_MSG("User has overridden passkey or no display available\n");
|
||||
pkey.passkey = defaultBLEPin;
|
||||
} else {
|
||||
DEBUG_MSG("Using random passkey\n");
|
||||
pkey.passkey = random(
|
||||
100000, 999999); // This is the passkey to be entered on peer - we pick a number >100,000 to ensure 6 digits
|
||||
}
|
||||
DEBUG_MSG("*** Enter passkey %d on the peer side ***\n", pkey.passkey);
|
||||
|
||||
startCb(pkey.passkey);
|
||||
|
||||
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
|
||||
DEBUG_MSG("ble_sm_inject_io result: %d\n", rc);
|
||||
} else {
|
||||
DEBUG_MSG("FIXME - unexpected auth type %d\n", event->passkey.params.action);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* Enables advertising with the following parameters:
|
||||
* o General discoverable mode.
|
||||
* o Undirected connectable mode.
|
||||
*
|
||||
* Called here only
|
||||
*/
|
||||
static void advertise(void)
|
||||
{
|
||||
/**
|
||||
* Set the advertisement data included in our advertisements:
|
||||
* o Flags (indicates advertisement type and other general info).
|
||||
* o Advertising tx power.
|
||||
* o Device name.
|
||||
* o 16-bit service UUIDs (alert notifications).
|
||||
*/
|
||||
|
||||
struct ble_hs_adv_fields adv_fields;
|
||||
memset(&adv_fields, 0, sizeof adv_fields);
|
||||
|
||||
/* Advertise two flags:
|
||||
* o Discoverability in forthcoming advertisement (general)
|
||||
* o BLE-only (BR/EDR unsupported).
|
||||
*/
|
||||
adv_fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP;
|
||||
|
||||
/* Indicate that the TX power level field should be included; have the
|
||||
* stack fill this value automatically. This is done by assigning the
|
||||
* special value BLE_HS_ADV_TX_PWR_LVL_AUTO.
|
||||
*/
|
||||
adv_fields.tx_pwr_lvl_is_present = 1;
|
||||
adv_fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
|
||||
|
||||
const char *name = ble_svc_gap_device_name();
|
||||
adv_fields.name = (uint8_t *)name;
|
||||
adv_fields.name_len = strlen(name);
|
||||
adv_fields.name_is_complete = 1;
|
||||
|
||||
auto rc = ble_gap_adv_set_fields(&adv_fields);
|
||||
if (rc != 0) {
|
||||
DEBUG_MSG("error setting advertisement data; rc=%d\n", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
// add scan response fields
|
||||
struct ble_hs_adv_fields scan_fields;
|
||||
memset(&scan_fields, 0, sizeof scan_fields);
|
||||
scan_fields.uuids128 = const_cast<ble_uuid128_t *>(&mesh_service_uuid);
|
||||
scan_fields.num_uuids128 = 1;
|
||||
scan_fields.uuids128_is_complete = 1;
|
||||
|
||||
rc = ble_gap_adv_rsp_set_fields(&scan_fields);
|
||||
if (rc != 0) {
|
||||
DEBUG_MSG("error setting scan response data; rc=%d\n", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Begin advertising. */
|
||||
struct ble_gap_adv_params adv_params;
|
||||
memset(&adv_params, 0, sizeof adv_params);
|
||||
adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
|
||||
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
|
||||
// FIXME - use RPA for first parameter
|
||||
rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER, &adv_params, gap_event, NULL);
|
||||
if (rc != 0) {
|
||||
DEBUG_MSG("error enabling advertisement; rc=%d\n", rc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//callback
|
||||
//doesn't do anything
|
||||
static void on_reset(int reason)
|
||||
{
|
||||
// 19 == BLE_HS_ETIMEOUT_HCI
|
||||
DEBUG_MSG("Resetting state; reason=%d\n", reason);
|
||||
}
|
||||
|
||||
//callback
|
||||
//
|
||||
static void on_sync(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ble_hs_util_ensure_addr(0);
|
||||
assert(rc == 0);
|
||||
|
||||
/* Figure out address to use while advertising (no privacy for now) */
|
||||
rc = ble_hs_id_infer_auto(0, &own_addr_type);
|
||||
if (rc != 0) {
|
||||
DEBUG_MSG("error determining address type; rc=%d\n", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Printing ADDR */
|
||||
uint8_t addr_val[6] = {0};
|
||||
int isPrivate = 0;
|
||||
rc = ble_hs_id_copy_addr(own_addr_type, addr_val, &isPrivate);
|
||||
assert(rc == 0);
|
||||
DEBUG_MSG("BLE advertisting type=%d, Private=%d, Device Address: ", own_addr_type, isPrivate);
|
||||
print_addr(addr_val);
|
||||
DEBUG_MSG("\n");
|
||||
/* Begin advertising. */
|
||||
advertise();
|
||||
}
|
||||
|
||||
//do the bluetooth tasks
|
||||
static void ble_host_task(void *param)
|
||||
{
|
||||
DEBUG_MSG("BLE task running\n");
|
||||
nimble_port_run(); // This function will return only when nimble_port_stop() is executed.
|
||||
|
||||
// DEBUG_MSG("BLE run complete\n");
|
||||
|
||||
nimble_port_freertos_deinit(); // delete the task
|
||||
}
|
||||
|
||||
//saves the stream handles when characteristics are successfully registered
|
||||
void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
|
||||
{
|
||||
char buf[BLE_UUID_STR_LEN];
|
||||
|
||||
switch (ctxt->op) {
|
||||
case BLE_GATT_REGISTER_OP_SVC:
|
||||
DEBUG_MSG("registered service %s with handle=%d\n", ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf), ctxt->svc.handle);
|
||||
break;
|
||||
|
||||
case BLE_GATT_REGISTER_OP_CHR:
|
||||
/* DEBUG_MSG("registering characteristic %s with "
|
||||
"def_handle=%d val_handle=%d\n",
|
||||
ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf), ctxt->chr.def_handle, ctxt->chr.val_handle); */
|
||||
|
||||
if (ctxt->chr.chr_def->uuid == &fromnum_uuid.u) {
|
||||
fromNumValHandle = ctxt->chr.val_handle;
|
||||
// DEBUG_MSG("FromNum handle %d\n", fromNumValHandle);
|
||||
}
|
||||
if (ctxt->chr.chr_def->uuid == &update_result_uuid.u) {
|
||||
updateResultHandle = ctxt->chr.val_handle;
|
||||
// DEBUG_MSG("update result handle %d\n", updateResultHandle);
|
||||
}
|
||||
break;
|
||||
|
||||
case BLE_GATT_REGISTER_OP_DSC:
|
||||
DEBUG_MSG("registering descriptor %s with handle=%d\n", ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf), ctxt->dsc.handle);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function that implements simple read and write handling for a uint32_t
|
||||
*
|
||||
* If a read, the provided value will be returned over bluetooth. If a write, the value from the received packet
|
||||
* will be written into the variable.
|
||||
*
|
||||
* used a few places
|
||||
*/
|
||||
int chr_readwrite32le(uint32_t *v, struct ble_gatt_access_ctxt *ctxt)
|
||||
{
|
||||
uint8_t le[4];
|
||||
|
||||
if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
|
||||
DEBUG_MSG("BLE reading a uint32\n");
|
||||
put_le32(le, *v);
|
||||
auto rc = os_mbuf_append(ctxt->om, le, sizeof(le));
|
||||
assert(rc == 0);
|
||||
} else if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
|
||||
uint16_t len = 0;
|
||||
|
||||
auto rc = ble_hs_mbuf_to_flat(ctxt->om, le, sizeof(le), &len);
|
||||
assert(rc == 0);
|
||||
if (len < sizeof(le)) {
|
||||
DEBUG_MSG("Error: wrongsized write32\n");
|
||||
*v = 0;
|
||||
return BLE_ATT_ERR_UNLIKELY;
|
||||
} else {
|
||||
*v = get_le32(le);
|
||||
DEBUG_MSG("BLE writing a uint32\n");
|
||||
}
|
||||
} else {
|
||||
DEBUG_MSG("Unexpected readwrite32 op\n");
|
||||
return BLE_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper for readwrite access to an array of bytes (with no endian conversion)
|
||||
*/
|
||||
int chr_readwrite8(uint8_t *v, size_t vlen, struct ble_gatt_access_ctxt *ctxt)
|
||||
{
|
||||
if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
|
||||
DEBUG_MSG("BLE reading bytes\n");
|
||||
auto rc = os_mbuf_append(ctxt->om, v, vlen);
|
||||
assert(rc == 0);
|
||||
} else if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
|
||||
uint16_t len = 0;
|
||||
|
||||
auto rc = ble_hs_mbuf_to_flat(ctxt->om, v, vlen, &len);
|
||||
assert(rc == 0);
|
||||
if (len < vlen) {
|
||||
DEBUG_MSG("Error: wrongsized write\n");
|
||||
return BLE_ATT_ERR_UNLIKELY;
|
||||
} else {
|
||||
DEBUG_MSG("BLE writing bytes\n");
|
||||
}
|
||||
} else {
|
||||
DEBUG_MSG("Unexpected readwrite8 op\n");
|
||||
return BLE_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
void disablePin()
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
// This should go somewhere else.
|
||||
void clearNVS()
|
||||
{
|
||||
#ifdef ARCH_ESP32
|
||||
|
||||
// As soon as the LED flashing from double click is done, immediately do a tripple click to
|
||||
// erase nvs memory.
|
||||
if (doublepressed > (millis() - 2000)) {
|
||||
DEBUG_MSG("Clearing NVS memory\n");
|
||||
|
||||
// This will erase ble pairings, ssl key and persistent preferences.
|
||||
nvs_flash_erase();
|
||||
|
||||
DEBUG_MSG("Restarting...\n");
|
||||
ESP.restart();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// This routine is called multiple times, once each time we come back from sleep
|
||||
void reinitBluetooth()
|
||||
{
|
||||
auto isFirstTime = !bluetoothPhoneAPI;
|
||||
|
||||
DEBUG_MSG("Starting bluetooth\n");
|
||||
if (isFirstTime) {
|
||||
bluetoothPhoneAPI = new BluetoothPhoneAPI();
|
||||
}
|
||||
|
||||
// FIXME - if waking from light sleep, only esp_nimble_hci_init?
|
||||
auto res = esp_nimble_hci_and_controller_init(); // : esp_nimble_hci_init();
|
||||
// DEBUG_MSG("BLE result %d\n", res);
|
||||
assert(res == ESP_OK);
|
||||
|
||||
nimble_port_init();
|
||||
|
||||
ble_att_set_preferred_mtu(512);
|
||||
|
||||
res = ble_gatts_reset(); // Teardown the service tables, so the next restart assigns the same handle numbers
|
||||
assert(res == ESP_OK);
|
||||
|
||||
/* Initialize the NimBLE host configuration. */
|
||||
ble_hs_cfg.reset_cb = on_reset;
|
||||
ble_hs_cfg.sync_cb = on_sync;
|
||||
ble_hs_cfg.gatts_register_cb = gatt_svr_register_cb;
|
||||
ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
|
||||
|
||||
ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_DISP_ONLY;
|
||||
ble_hs_cfg.sm_bonding = 1;
|
||||
ble_hs_cfg.sm_mitm = 1;
|
||||
ble_hs_cfg.sm_sc = 1;
|
||||
// per https://github.com/espressif/esp-idf/issues/5530#issuecomment-652933685
|
||||
ble_hs_cfg.sm_our_key_dist = BLE_SM_PAIR_KEY_DIST_ID | BLE_SM_PAIR_KEY_DIST_ENC;
|
||||
ble_hs_cfg.sm_their_key_dist = BLE_SM_PAIR_KEY_DIST_ID | BLE_SM_PAIR_KEY_DIST_ENC;
|
||||
|
||||
// add standard GAP services
|
||||
ble_svc_gap_init();
|
||||
ble_svc_gatt_init();
|
||||
|
||||
res = ble_gatts_count_cfg(gatt_svr_svcs); // assigns handles? see docstring for note about clearing the handle list
|
||||
// before calling SLEEP SUPPORT
|
||||
assert(res == 0);
|
||||
|
||||
res = ble_gatts_add_svcs(gatt_svr_svcs);
|
||||
assert(res == 0);
|
||||
|
||||
reinitUpdateService();
|
||||
|
||||
/* Set the default device name. */
|
||||
res = ble_svc_gap_device_name_set(getDeviceName());
|
||||
assert(res == 0);
|
||||
|
||||
/* XXX Need to have template for store */
|
||||
ble_store_config_init();
|
||||
|
||||
nimble_port_freertos_init(ble_host_task);
|
||||
bluetoothActive = true;
|
||||
}
|
||||
|
||||
bool bluetoothOn;
|
||||
|
||||
// Enable/disable bluetooth.
|
||||
void setBluetoothEnable(bool on)
|
||||
{
|
||||
if (on != bluetoothOn) {
|
||||
DEBUG_MSG("Setting bluetooth enable=%d\n", on);
|
||||
|
||||
bluetoothOn = on;
|
||||
if (on) {
|
||||
if (!isWifiAvailable()) {
|
||||
Serial.printf("Pre BT: %u heap size\n", ESP.getFreeHeap());
|
||||
// ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
|
||||
reinitBluetooth();
|
||||
}
|
||||
} else {
|
||||
// shutdown wifi
|
||||
deinitWifi();
|
||||
|
||||
// We have to totally teardown our bluetooth objects to prevent leaks
|
||||
deinitBLE();
|
||||
|
||||
Serial.printf("Shutdown BT: %u heap size\n", ESP.getFreeHeap());
|
||||
// ESP_ERROR_CHECK( heap_trace_stop() );
|
||||
// heap_trace_dump();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
static BLECharacteristic *batteryLevelC;
|
||||
|
||||
/**
|
||||
* Create a battery level service
|
||||
*/
|
||||
BLEService *createBatteryService(BLEServer *server)
|
||||
{
|
||||
// Create the BLE Service
|
||||
BLEService *pBattery = server->createService(BLEUUID((uint16_t)0x180F));
|
||||
|
||||
batteryLevelC = new BLECharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_BATTERY_LEVEL),
|
||||
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
|
||||
|
||||
addWithDesc(pBattery, batteryLevelC, "Percentage 0 - 100");
|
||||
batteryLevelC->addDescriptor(addBLEDescriptor(new BLE2902())); // Needed so clients can request notification
|
||||
|
||||
// I don't think we need to advertise this? and some phones only see the first thing advertised anyways...
|
||||
// server->getAdvertising()->addServiceUUID(pBattery->getUUID());
|
||||
pBattery->start();
|
||||
|
||||
return pBattery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the battery level we are currently telling clients.
|
||||
* level should be a pct between 0 and 100
|
||||
*/
|
||||
void updateBatteryLevel(uint8_t level)
|
||||
{
|
||||
if (batteryLevelC) {
|
||||
DEBUG_MSG("set BLE battery level %u\n", level);
|
||||
batteryLevelC->setValue(&level, 1);
|
||||
batteryLevelC->notify();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Note: these callbacks might be coming in from a different thread.
|
||||
BLEServer *serve = initBLE(, , getDeviceName(), HW_VENDOR, optstr(APP_VERSION),
|
||||
optstr(HW_VERSION)); // FIXME, use a real name based on the macaddr
|
||||
|
||||
#endif
|
||||
|
||||
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
|
@ -1,35 +0,0 @@
|
||||
#ifndef USE_NEW_ESP32_BLUETOOTH
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
/// We only allow one BLE connection at a time
|
||||
extern int16_t curConnectionHandle;
|
||||
|
||||
// TODO(girts): create a class for the bluetooth utils helpers?
|
||||
using StartBluetoothPinScreenCallback = std::function<void(uint32_t pass_key)>;
|
||||
using StopBluetoothPinScreenCallback = std::function<void(void)>;
|
||||
|
||||
/// Given a level between 0-100, update the BLE attribute
|
||||
void updateBatteryLevel(uint8_t level);
|
||||
void deinitBLE();
|
||||
void loopBLE();
|
||||
void reinitBluetooth();
|
||||
void disablePin();
|
||||
void clearNVS();
|
||||
|
||||
/**
|
||||
* A helper function that implements simple read and write handling for a uint32_t
|
||||
*
|
||||
* If a read, the provided value will be returned over bluetooth. If a write, the value from the received packet
|
||||
* will be written into the variable.
|
||||
*/
|
||||
int chr_readwrite32le(uint32_t *v, struct ble_gatt_access_ctxt *ctxt);
|
||||
|
||||
/**
|
||||
* A helper for readwrite access to an array of bytes (with no endian conversion)
|
||||
*/
|
||||
int chr_readwrite8(uint8_t *v, size_t vlen, struct ble_gatt_access_ctxt *ctxt);
|
||||
|
||||
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
|
@ -1,7 +1,5 @@
|
||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
||||
|
||||
#include "configuration.h"
|
||||
#include "ESP32Bluetooth.h"
|
||||
#include "NimbleBluetooth.h"
|
||||
#include "BluetoothCommon.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "sleep.h"
|
||||
@ -46,7 +44,7 @@ static BluetoothPhoneAPI *bluetoothPhoneAPI;
|
||||
* Subclasses can use this as a hook to provide custom notifications for their transport (i.e. bluetooth notifies)
|
||||
*/
|
||||
|
||||
class ESP32BluetoothToRadioCallback : public NimBLECharacteristicCallbacks
|
||||
class NimbleBluetoothToRadioCallback : public NimBLECharacteristicCallbacks
|
||||
{
|
||||
virtual void onWrite(NimBLECharacteristic *pCharacteristic) {
|
||||
DEBUG_MSG("To Radio onwrite\n");
|
||||
@ -56,7 +54,7 @@ class ESP32BluetoothToRadioCallback : public NimBLECharacteristicCallbacks
|
||||
}
|
||||
};
|
||||
|
||||
class ESP32BluetoothFromRadioCallback : public NimBLECharacteristicCallbacks
|
||||
class NimbleBluetoothFromRadioCallback : public NimBLECharacteristicCallbacks
|
||||
{
|
||||
virtual void onRead(NimBLECharacteristic *pCharacteristic) {
|
||||
DEBUG_MSG("From Radio onread\n");
|
||||
@ -69,7 +67,7 @@ class ESP32BluetoothFromRadioCallback : public NimBLECharacteristicCallbacks
|
||||
}
|
||||
};
|
||||
|
||||
class ESP32BluetoothServerCallback : public NimBLEServerCallbacks
|
||||
class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
|
||||
{
|
||||
virtual uint32_t onPassKeyRequest() {
|
||||
uint32_t passkey = config.bluetooth.fixed_pin;
|
||||
@ -108,10 +106,10 @@ class ESP32BluetoothServerCallback : public NimBLEServerCallbacks
|
||||
}
|
||||
};
|
||||
|
||||
static ESP32BluetoothToRadioCallback *toRadioCallbacks;
|
||||
static ESP32BluetoothFromRadioCallback *fromRadioCallbacks;
|
||||
static NimbleBluetoothToRadioCallback *toRadioCallbacks;
|
||||
static NimbleBluetoothFromRadioCallback *fromRadioCallbacks;
|
||||
|
||||
void ESP32Bluetooth::shutdown()
|
||||
void NimbleBluetooth::shutdown()
|
||||
{
|
||||
// Shutdown bluetooth for minimum power draw
|
||||
DEBUG_MSG("Disable bluetooth\n");
|
||||
@ -121,15 +119,15 @@ void ESP32Bluetooth::shutdown()
|
||||
pAdvertising->stop();
|
||||
}
|
||||
|
||||
bool ESP32Bluetooth::isActive()
|
||||
bool NimbleBluetooth::isActive()
|
||||
{
|
||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||
return bleServer && (bleServer->getConnectedCount() > 0 || pAdvertising->isAdvertising());
|
||||
}
|
||||
|
||||
void ESP32Bluetooth::setup()
|
||||
void NimbleBluetooth::setup()
|
||||
{
|
||||
DEBUG_MSG("Initialise the ESP32 bluetooth module\n");
|
||||
DEBUG_MSG("Initialise the NimBLE bluetooth module\n");
|
||||
|
||||
NimBLEDevice::init(getDeviceName());
|
||||
NimBLEDevice::setPower(ESP_PWR_LVL_P9);
|
||||
@ -145,14 +143,14 @@ void ESP32Bluetooth::setup()
|
||||
}
|
||||
bleServer = NimBLEDevice::createServer();
|
||||
|
||||
ESP32BluetoothServerCallback *serverCallbacks = new ESP32BluetoothServerCallback();
|
||||
NimbleBluetoothServerCallback *serverCallbacks = new NimbleBluetoothServerCallback();
|
||||
bleServer->setCallbacks(serverCallbacks, true);
|
||||
|
||||
setupService();
|
||||
startAdvertising();
|
||||
}
|
||||
|
||||
void ESP32Bluetooth::setupService()
|
||||
void NimbleBluetooth::setupService()
|
||||
{
|
||||
NimBLEService *bleService = bleServer->createService(MESH_SERVICE_UUID);
|
||||
|
||||
@ -163,16 +161,16 @@ void ESP32Bluetooth::setupService()
|
||||
|
||||
bluetoothPhoneAPI = new BluetoothPhoneAPI();
|
||||
|
||||
toRadioCallbacks = new ESP32BluetoothToRadioCallback();
|
||||
toRadioCallbacks = new NimbleBluetoothToRadioCallback();
|
||||
ToRadioCharacteristic->setCallbacks(toRadioCallbacks);
|
||||
|
||||
fromRadioCallbacks = new ESP32BluetoothFromRadioCallback();
|
||||
fromRadioCallbacks = new NimbleBluetoothFromRadioCallback();
|
||||
FromRadioCharacteristic->setCallbacks(fromRadioCallbacks);
|
||||
|
||||
bleService->start();
|
||||
}
|
||||
|
||||
void ESP32Bluetooth::startAdvertising()
|
||||
void NimbleBluetooth::startAdvertising()
|
||||
{
|
||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||
pAdvertising->reset();
|
||||
@ -186,7 +184,7 @@ void updateBatteryLevel(uint8_t level)
|
||||
//blebas.write(level);
|
||||
}
|
||||
|
||||
void ESP32Bluetooth::clearBonds()
|
||||
void NimbleBluetooth::clearBonds()
|
||||
{
|
||||
DEBUG_MSG("Clearing bluetooth bonds!\n");
|
||||
NimBLEDevice::deleteAllBonds();
|
||||
@ -195,7 +193,9 @@ void ESP32Bluetooth::clearBonds()
|
||||
void clearNVS()
|
||||
{
|
||||
NimBLEDevice::deleteAllBonds();
|
||||
#ifdef ARCH_ESP32
|
||||
ESP.restart();
|
||||
#endif
|
||||
}
|
||||
|
||||
void disablePin()
|
||||
@ -218,5 +218,3 @@ void disablePin()
|
||||
|
||||
doublepressed = millis();
|
||||
}
|
||||
|
||||
#endif
|
@ -1,8 +1,6 @@
|
||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
||||
|
||||
#pragma once
|
||||
|
||||
class ESP32Bluetooth
|
||||
class NimbleBluetooth
|
||||
{
|
||||
public:
|
||||
void setup();
|
||||
@ -18,5 +16,3 @@ class ESP32Bluetooth
|
||||
void setBluetoothEnable(bool on);
|
||||
void clearNVS();
|
||||
void disablePin();
|
||||
|
||||
#endif
|
@ -1,75 +0,0 @@
|
||||
#ifndef USE_NEW_ESP32_BLUETOOTH
|
||||
|
||||
#include "NimbleBluetoothAPI.h"
|
||||
#include "PhoneAPI.h"
|
||||
#include "configuration.h"
|
||||
#include "nimble/BluetoothUtil.h"
|
||||
#include "nimble/NimbleDefs.h"
|
||||
|
||||
// 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[FromRadio_size < ToRadio_size ? ToRadio_size : FromRadio_size];
|
||||
static uint32_t fromNum;
|
||||
|
||||
uint16_t fromNumValHandle;
|
||||
|
||||
/// We only allow one BLE connection at a time
|
||||
int16_t curConnectionHandle = -1;
|
||||
|
||||
PhoneAPI *bluetoothPhoneAPI;
|
||||
|
||||
void BluetoothPhoneAPI::onNowHasData(uint32_t fromRadioNum)
|
||||
{
|
||||
PhoneAPI::onNowHasData(fromRadioNum);
|
||||
|
||||
fromNum = fromRadioNum;
|
||||
if (curConnectionHandle >= 0 && fromNumValHandle) {
|
||||
DEBUG_MSG("BLE notify fromNum\n");
|
||||
auto res = ble_gattc_notify(curConnectionHandle, fromNumValHandle);
|
||||
assert(res == 0);
|
||||
} else {
|
||||
DEBUG_MSG("No BLE notify\n");
|
||||
}
|
||||
}
|
||||
|
||||
bool BluetoothPhoneAPI::checkIsConnected() {
|
||||
return curConnectionHandle >= 0;
|
||||
}
|
||||
|
||||
int toradio_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
|
||||
{
|
||||
auto om = ctxt->om;
|
||||
uint16_t len = 0;
|
||||
|
||||
auto rc = ble_hs_mbuf_to_flat(om, trBytes, sizeof(trBytes), &len);
|
||||
if (rc != 0) {
|
||||
return BLE_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
|
||||
/// DEBUG_MSG("toRadioWriteCb data %p, len %u\n", trBytes, len);
|
||||
|
||||
bluetoothPhoneAPI->handleToRadio(trBytes, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fromradio_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
|
||||
{
|
||||
size_t numBytes = bluetoothPhoneAPI->getFromRadio(trBytes);
|
||||
|
||||
DEBUG_MSG("BLE fromRadio called omlen=%d, ourlen=%d\n", OS_MBUF_PKTLEN(ctxt->om),
|
||||
numBytes); // the normal case has omlen 1 here
|
||||
|
||||
// Someone is going to read our value as soon as this callback returns. So fill it with the next message in the queue
|
||||
// or make empty if the queue is empty
|
||||
auto rc = os_mbuf_append(ctxt->om, trBytes, numBytes);
|
||||
assert(rc == 0);
|
||||
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
int fromnum_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
|
||||
{
|
||||
return chr_readwrite32le(&fromNum, ctxt);
|
||||
}
|
||||
|
||||
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
|
@ -1,23 +0,0 @@
|
||||
#ifndef USE_NEW_ESP32_BLUETOOTH
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PhoneAPI.h"
|
||||
|
||||
extern uint16_t fromNumValHandle;
|
||||
|
||||
class BluetoothPhoneAPI : public PhoneAPI
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Subclasses can use this as a hook to provide custom notifications for their transport (i.e. bluetooth notifies)
|
||||
*/
|
||||
virtual void onNowHasData(uint32_t fromRadioNum) override;
|
||||
|
||||
/// Check the current underlying physical link to see if the client is currently connected
|
||||
virtual bool checkIsConnected() override;
|
||||
};
|
||||
|
||||
extern PhoneAPI *bluetoothPhoneAPI;
|
||||
|
||||
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
|
@ -1,50 +0,0 @@
|
||||
#ifndef USE_NEW_ESP32_BLUETOOTH
|
||||
|
||||
#include "NimbleDefs.h"
|
||||
|
||||
// NRF52 wants these constants as byte arrays
|
||||
// Generated here https://yupana-engineering.com/online-uuid-to-c-array-converter - but in REVERSE BYTE ORDER
|
||||
const ble_uuid128_t mesh_service_uuid =
|
||||
BLE_UUID128_INIT(0xfd, 0xea, 0x73, 0xe2, 0xca, 0x5d, 0xa8, 0x9f, 0x1f, 0x46, 0xa8, 0x15, 0x18, 0xb2, 0xa1, 0x6b);
|
||||
|
||||
static const ble_uuid128_t toradio_uuid =
|
||||
BLE_UUID128_INIT(0xe7, 0x01, 0x44, 0x12, 0x66, 0x78, 0xdd, 0xa1, 0xad, 0x4d, 0x9e, 0x12, 0xd2, 0x76, 0x5c, 0xf7);
|
||||
|
||||
static const ble_uuid128_t fromradio_uuid =
|
||||
BLE_UUID128_INIT(0xd5, 0x54, 0xe4, 0xc5, 0x25, 0xc5, 0x31, 0xa5, 0x55, 0x4a, 0x02, 0xee, 0xc2, 0xbc, 0xa2, 0x8b);
|
||||
|
||||
const ble_uuid128_t fromnum_uuid =
|
||||
BLE_UUID128_INIT(0x53, 0x44, 0xe3, 0x47, 0x75, 0xaa, 0x70, 0xa6, 0x66, 0x4f, 0x00, 0xa8, 0x8c, 0xa1, 0x9d, 0xed);
|
||||
|
||||
const struct ble_gatt_svc_def gatt_svr_svcs[] = {
|
||||
{
|
||||
/*** Service: Security test. */
|
||||
.type = BLE_GATT_SVC_TYPE_PRIMARY,
|
||||
.uuid = &mesh_service_uuid.u,
|
||||
.characteristics =
|
||||
(struct ble_gatt_chr_def[]){{
|
||||
.uuid = &toradio_uuid.u,
|
||||
.access_cb = toradio_callback,
|
||||
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_AUTHEN,
|
||||
},
|
||||
{
|
||||
.uuid = &fromradio_uuid.u,
|
||||
.access_cb = fromradio_callback,
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_AUTHEN,
|
||||
},
|
||||
{
|
||||
.uuid = &fromnum_uuid.u,
|
||||
.access_cb = fromnum_callback,
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_NOTIFY,
|
||||
},
|
||||
{
|
||||
0, /* No more characteristics in this service. */
|
||||
}},
|
||||
},
|
||||
|
||||
{
|
||||
0, /* No more services. */
|
||||
},
|
||||
};
|
||||
|
||||
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
|
@ -1,35 +0,0 @@
|
||||
#ifndef USE_NEW_ESP32_BLUETOOTH
|
||||
|
||||
#pragma once
|
||||
|
||||
// Keep nimble #defs from messing up the build
|
||||
#ifndef max
|
||||
#define max max
|
||||
#define min min
|
||||
#endif
|
||||
|
||||
#include "esp_nimble_hci.h"
|
||||
#include "host/ble_hs.h"
|
||||
#include "host/ble_uuid.h"
|
||||
#include "nimble/nimble_port.h"
|
||||
#include "nimble/nimble_port_freertos.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int toradio_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
|
||||
int fromradio_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
|
||||
int fromnum_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
|
||||
extern const struct ble_gatt_svc_def gatt_svr_svcs[];
|
||||
|
||||
extern const ble_uuid128_t mesh_service_uuid, fromnum_uuid;
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
|
@ -1,160 +0,0 @@
|
||||
#ifndef USE_NEW_ESP32_BLUETOOTH
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "../concurrency/LockGuard.h"
|
||||
#include "../graphics/Screen.h"
|
||||
#include "../main.h"
|
||||
#include "BluetoothSoftwareUpdate.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "RadioLibInterface.h"
|
||||
#include "configuration.h"
|
||||
#include "nimble/BluetoothUtil.h"
|
||||
|
||||
#include <CRC32.h>
|
||||
#include <Update.h>
|
||||
|
||||
int16_t updateResultHandle = -1;
|
||||
|
||||
static CRC32 crc;
|
||||
|
||||
static uint32_t updateExpectedSize, updateActualSize;
|
||||
static uint8_t update_result;
|
||||
static uint8_t update_region;
|
||||
|
||||
static concurrency::Lock *updateLock;
|
||||
|
||||
/// Handle writes & reads to total size
|
||||
int update_size_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
|
||||
{
|
||||
concurrency::LockGuard g(updateLock);
|
||||
|
||||
// Check if there is enough to OTA Update
|
||||
chr_readwrite32le(&updateExpectedSize, ctxt);
|
||||
|
||||
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR && updateExpectedSize != 0) {
|
||||
updateActualSize = 0;
|
||||
crc.reset();
|
||||
if (Update.isRunning())
|
||||
Update.abort();
|
||||
bool canBegin = Update.begin(updateExpectedSize, update_region);
|
||||
DEBUG_MSG("Setting region %d update size %u, result %d\n", update_region, updateExpectedSize, canBegin);
|
||||
if (!canBegin) {
|
||||
// Indicate failure by forcing the size to 0 (client will read it back)
|
||||
updateExpectedSize = 0;
|
||||
} else {
|
||||
// This totally breaks abstraction to up up into the app layer for this, but quick hack to make sure we only
|
||||
// talk to one service during the sw update.
|
||||
// DEBUG_MSG("FIXME, crufty shutdown of mesh bluetooth for sw update.");
|
||||
// void stopMeshBluetoothService();
|
||||
// stopMeshBluetoothService();
|
||||
|
||||
screen->startFirmwareUpdateScreen();
|
||||
if (RadioLibInterface::instance)
|
||||
RadioLibInterface::instance->disable(); // FIXME, nasty hack - the RF95 ISR/SPI code on ESP32 can fail while we
|
||||
// are writing flash - shut the radio off during updates
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MAX_BLOCKSIZE_FOR_BT 512
|
||||
|
||||
/// Handle writes to data
|
||||
int update_data_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
|
||||
{
|
||||
concurrency::LockGuard g(updateLock);
|
||||
|
||||
static uint8_t
|
||||
data[MAX_BLOCKSIZE_FOR_BT]; // we temporarily copy here because I'm worried that a fast sender might be able overwrite srcbuf
|
||||
|
||||
uint16_t len = 0;
|
||||
|
||||
auto rc = ble_hs_mbuf_to_flat(ctxt->om, data, sizeof(data), &len);
|
||||
assert(rc == 0);
|
||||
|
||||
// DEBUG_MSG("Writing %u\n", len);
|
||||
crc.update(data, len);
|
||||
Update.write(data, len);
|
||||
updateActualSize += len;
|
||||
powerFSM.trigger(EVENT_FIRMWARE_UPDATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Handle writes to crc32
|
||||
int update_crc32_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
|
||||
{
|
||||
concurrency::LockGuard g(updateLock);
|
||||
uint32_t expectedCRC = 0;
|
||||
chr_readwrite32le(&expectedCRC, ctxt);
|
||||
|
||||
uint32_t actualCRC = crc.finalize();
|
||||
DEBUG_MSG("expected CRC %u\n", expectedCRC);
|
||||
|
||||
uint8_t result = 0xff;
|
||||
|
||||
if (updateActualSize != updateExpectedSize) {
|
||||
DEBUG_MSG("Expected %u bytes, but received %u bytes!\n", updateExpectedSize, updateActualSize);
|
||||
result = 0xe1; // FIXME, use real error codes
|
||||
} else if (actualCRC != expectedCRC) // Check the CRC before asking the update to happen.
|
||||
{
|
||||
DEBUG_MSG("Invalid CRC! expected=%u, actual=%u\n", expectedCRC, actualCRC);
|
||||
result = 0xe0; // FIXME, use real error codes
|
||||
} else {
|
||||
if (Update.end()) {
|
||||
if (update_region == U_SPIFFS) {
|
||||
DEBUG_MSG("Filesystem updated!\n");
|
||||
nodeDB.saveToDisk(); // Since we just wiped the filesystem, we need to save our current state
|
||||
} else {
|
||||
DEBUG_MSG("Appload updated, rebooting in 5 seconds!\n");
|
||||
rebootAtMsec = millis() + 5000;
|
||||
}
|
||||
} else {
|
||||
DEBUG_MSG("Error Occurred. Error #: %d\n", Update.getError());
|
||||
}
|
||||
result = Update.getError();
|
||||
}
|
||||
|
||||
if (RadioLibInterface::instance)
|
||||
RadioLibInterface::instance->startReceive(); // Resume radio
|
||||
|
||||
assert(updateResultHandle >= 0);
|
||||
update_result = result;
|
||||
DEBUG_MSG("BLE notify update result\n");
|
||||
auto res = ble_gattc_notify(curConnectionHandle, updateResultHandle);
|
||||
assert(res == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int update_result_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
|
||||
{
|
||||
return chr_readwrite8(&update_result, sizeof(update_result), ctxt);
|
||||
}
|
||||
|
||||
int update_region_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
|
||||
{
|
||||
return chr_readwrite8(&update_region, sizeof(update_region), ctxt);
|
||||
}
|
||||
|
||||
/*
|
||||
See bluetooth-api.md
|
||||
|
||||
*/
|
||||
void reinitUpdateService()
|
||||
{
|
||||
if (!updateLock)
|
||||
updateLock = new concurrency::Lock();
|
||||
|
||||
auto res = ble_gatts_count_cfg(gatt_update_svcs); // assigns handles? see docstring for note about clearing the handle list
|
||||
// before calling SLEEP SUPPORT
|
||||
assert(res == 0);
|
||||
|
||||
res = ble_gatts_add_svcs(gatt_update_svcs);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
|
@ -1,29 +0,0 @@
|
||||
#ifndef USE_NEW_ESP32_BLUETOOTH
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "nimble/NimbleDefs.h"
|
||||
|
||||
void reinitUpdateService();
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int update_size_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
int update_data_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
int update_result_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
int update_crc32_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
int update_region_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
|
||||
extern const struct ble_gatt_svc_def gatt_update_svcs[];
|
||||
|
||||
extern const ble_uuid128_t update_result_uuid, update_region_uuid;
|
||||
|
||||
extern int16_t updateResultHandle;
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
|
@ -1,73 +0,0 @@
|
||||
#ifndef USE_NEW_ESP32_BLUETOOTH
|
||||
#include "BluetoothSoftwareUpdate.h"
|
||||
|
||||
// NRF52 wants these constants as byte arrays
|
||||
// Generated here https://yupana-engineering.com/online-uuid-to-c-array-converter - but in REVERSE BYTE ORDER
|
||||
|
||||
// "cb0b9a0b-a84c-4c0d-bdbb-442e3144ee30"
|
||||
const ble_uuid128_t update_service_uuid =
|
||||
BLE_UUID128_INIT(0x30, 0xee, 0x44, 0x31, 0x2e, 0x44, 0xbb, 0xbd, 0x0d, 0x4c, 0x4c, 0xa8, 0x0b, 0x9a, 0x0b, 0xcb);
|
||||
|
||||
// "e74dd9c0-a301-4a6f-95a1-f0e1dbea8e1e" write|read
|
||||
const ble_uuid128_t update_size_uuid =
|
||||
BLE_UUID128_INIT(0x1e, 0x8e, 0xea, 0xdb, 0xe1, 0xf0, 0xa1, 0x95, 0x6f, 0x4a, 0x01, 0xa3, 0xc0, 0xd9, 0x4d, 0xe7);
|
||||
|
||||
// "e272ebac-d463-4b98-bc84-5cc1a39ee517" write
|
||||
const ble_uuid128_t update_data_uuid =
|
||||
BLE_UUID128_INIT(0x17, 0xe5, 0x9e, 0xa3, 0xc1, 0x5c, 0x84, 0xbc, 0x98, 0x4b, 0x63, 0xd4, 0xac, 0xeb, 0x72, 0xe2);
|
||||
|
||||
// "4826129c-c22a-43a3-b066-ce8f0d5bacc6" write
|
||||
const ble_uuid128_t update_crc32_uuid =
|
||||
BLE_UUID128_INIT(0xc6, 0xac, 0x5b, 0x0d, 0x8f, 0xce, 0x66, 0xb0, 0xa3, 0x43, 0x2a, 0xc2, 0x9c, 0x12, 0x26, 0x48);
|
||||
|
||||
// "5e134862-7411-4424-ac4a-210937432c77" read|notify
|
||||
const ble_uuid128_t update_result_uuid =
|
||||
BLE_UUID128_INIT(0x77, 0x2c, 0x43, 0x37, 0x09, 0x21, 0x4a, 0xac, 0x24, 0x44, 0x11, 0x74, 0x62, 0x48, 0x13, 0x5e);
|
||||
|
||||
// "5e134862-7411-4424-ac4a-210937432c67" write
|
||||
const ble_uuid128_t update_region_uuid =
|
||||
BLE_UUID128_INIT(0x67, 0x2c, 0x43, 0x37, 0x09, 0x21, 0x4a, 0xac, 0x24, 0x44, 0x11, 0x74, 0x62, 0x48, 0x13, 0x5e);
|
||||
|
||||
const struct ble_gatt_svc_def gatt_update_svcs[] = {
|
||||
{
|
||||
/*** Service: Security test. */
|
||||
.type = BLE_GATT_SVC_TYPE_PRIMARY,
|
||||
.uuid = &update_service_uuid.u,
|
||||
.characteristics =
|
||||
(struct ble_gatt_chr_def[]){{
|
||||
.uuid = &update_size_uuid.u,
|
||||
.access_cb = update_size_callback,
|
||||
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_AUTHEN | BLE_GATT_CHR_F_READ |
|
||||
BLE_GATT_CHR_F_READ_AUTHEN,
|
||||
},
|
||||
{
|
||||
.uuid = &update_data_uuid.u,
|
||||
.access_cb = update_data_callback,
|
||||
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_AUTHEN,
|
||||
},
|
||||
{
|
||||
.uuid = &update_crc32_uuid.u,
|
||||
.access_cb = update_crc32_callback,
|
||||
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_AUTHEN,
|
||||
},
|
||||
{
|
||||
.uuid = &update_result_uuid.u,
|
||||
.access_cb = update_result_callback,
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_NOTIFY,
|
||||
},
|
||||
{
|
||||
.uuid = &update_region_uuid.u,
|
||||
.access_cb = update_region_callback,
|
||||
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_AUTHEN,
|
||||
},
|
||||
{
|
||||
0, /* No more characteristics in this service. */
|
||||
}},
|
||||
},
|
||||
|
||||
{
|
||||
0, /* No more services. */
|
||||
},
|
||||
};
|
||||
|
||||
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
|
@ -6,6 +6,9 @@
|
||||
// defaults for ESP32 architecture
|
||||
//
|
||||
|
||||
#ifndef HAS_BLUETOOTH
|
||||
#define HAS_BLUETOOTH 1
|
||||
#endif
|
||||
#ifndef HAS_WIFI
|
||||
#define HAS_WIFI 1
|
||||
#endif
|
||||
|
@ -1,15 +1,10 @@
|
||||
#include "BluetoothSoftwareUpdate.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "configuration.h"
|
||||
#include "esp_task_wdt.h"
|
||||
#include "main.h"
|
||||
|
||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
||||
#include "ESP32Bluetooth.h"
|
||||
#include "nimble/NimbleBluetooth.h"
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
#else
|
||||
#include "nimble/BluetoothUtil.h"
|
||||
#endif
|
||||
|
||||
#include "sleep.h"
|
||||
#include "target_specific.h"
|
||||
@ -19,9 +14,7 @@
|
||||
#include <nvs.h>
|
||||
#include <nvs_flash.h>
|
||||
|
||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
||||
ESP32Bluetooth *esp32Bluetooth;
|
||||
#endif
|
||||
NimbleBluetooth *nimbleBluetooth;
|
||||
|
||||
void getMacAddr(uint8_t *dmac)
|
||||
{
|
||||
@ -39,21 +32,19 @@ static void printBLEinfo() {
|
||||
}
|
||||
|
||||
} */
|
||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
||||
void setBluetoothEnable(bool on) {
|
||||
|
||||
if (!isWifiAvailable()) {
|
||||
if (!esp32Bluetooth) {
|
||||
esp32Bluetooth = new ESP32Bluetooth();
|
||||
if (!nimbleBluetooth) {
|
||||
nimbleBluetooth = new NimbleBluetooth();
|
||||
}
|
||||
if (on && !esp32Bluetooth->isActive()) {
|
||||
esp32Bluetooth->setup();
|
||||
if (on && !nimbleBluetooth->isActive()) {
|
||||
nimbleBluetooth->setup();
|
||||
} else {
|
||||
esp32Bluetooth->shutdown();
|
||||
nimbleBluetooth->shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void esp32Setup()
|
||||
{
|
||||
|
@ -5,7 +5,9 @@
|
||||
//
|
||||
// defaults for NRF52 architecture
|
||||
//
|
||||
|
||||
#ifndef HAS_BLUETOOTH
|
||||
#define HAS_BLUETOOTH 1
|
||||
#endif
|
||||
#ifndef HAS_SCREEN
|
||||
#define HAS_SCREEN 1
|
||||
#endif
|
||||
|
@ -16,8 +16,6 @@
|
||||
#include <driver/rtc_io.h>
|
||||
#include <driver/uart.h>
|
||||
|
||||
#include "nimble/BluetoothUtil.h"
|
||||
|
||||
esp_sleep_source_t wakeCause; // the reason we booted this time
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user