mirror of
https://github.com/meshtastic/firmware.git
synced 2025-08-01 11:25:44 +00:00
Bluetooth mode unification and behavior tweaks (#1636)
* Esp32 bluetooth modes * Comment * Gutting bluetooth * Cleanup * Security * Testing * NRF bluetooth security * Reboot on saved lora or bluetooth settings * Cleanup * Fixes * Stub for platforms without screens * Fixed just-works in esp32 * Cleanup * Display device name in boot screen * Added waypoint module routing * chmod * Words * Protos * Backing out partition changes for testing * Revert "Backing out partition changes for testing" This reverts commit191ed6489c
. * Chmod PR artifacts * Trying setInitialState again * Revert "Trying setInitialState again" This reverts commit703eac7277
. * External notification module * Cleanup * Pin display formatting
This commit is contained in:
parent
c85e9f53c7
commit
b54073a8a1
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -52,7 +52,8 @@
|
|||||||
"shared_mutex": "cpp",
|
"shared_mutex": "cpp",
|
||||||
"iostream": "cpp",
|
"iostream": "cpp",
|
||||||
"esp_nimble_hci.h": "c",
|
"esp_nimble_hci.h": "c",
|
||||||
"map": "cpp"
|
"map": "cpp",
|
||||||
|
"random": "cpp"
|
||||||
},
|
},
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
"Blox",
|
"Blox",
|
||||||
|
0
bin/device-install.bat
Normal file → Executable file
0
bin/device-install.bat
Normal file → Executable file
0
bin/device-update.bat
Normal file → Executable file
0
bin/device-update.bat
Normal file → Executable file
@ -21,6 +21,7 @@ default_envs = tbeam
|
|||||||
;default_envs = meshtastic-diy-v1
|
;default_envs = meshtastic-diy-v1
|
||||||
;default_envs = meshtastic-diy-v1.1
|
;default_envs = meshtastic-diy-v1.1
|
||||||
;default_envs = m5stack-coreink
|
;default_envs = m5stack-coreink
|
||||||
|
;default_envs = rak4631
|
||||||
|
|
||||||
extra_configs = variants/*/platformio.ini
|
extra_configs = variants/*/platformio.ini
|
||||||
|
|
||||||
@ -79,8 +80,6 @@ lib_deps =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
adafruit/Adafruit BusIO@^1.11.4
|
adafruit/Adafruit BusIO@^1.11.4
|
||||||
adafruit/Adafruit Unified Sensor@^1.1.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 BMP280 Library@^2.6.3
|
||||||
adafruit/Adafruit BME280 Library@^2.2.2
|
adafruit/Adafruit BME280 Library@^2.2.2
|
||||||
adafruit/Adafruit BME680 Library@^2.0.1
|
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.
|
# 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
|
# 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
|
# 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 =
|
build_flags =
|
||||||
${arduino_base.build_flags} -Wall -Wextra -Isrc/platform/esp32 -lnimble -std=c++11
|
${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
|
-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 =
|
lib_deps =
|
||||||
${arduino_base.lib_deps}
|
${arduino_base.lib_deps}
|
||||||
${networking_base.lib_deps}
|
${networking_base.lib_deps}
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 2fadf011e574c180afb395bc2a751b3f7e56839c
|
Subproject commit 579308947366b35f7eb6908d5eaabd0114bba244
|
@ -7,10 +7,6 @@
|
|||||||
#include "power.h"
|
#include "power.h"
|
||||||
#include <OneButton.h>
|
#include <OneButton.h>
|
||||||
|
|
||||||
#ifdef ARCH_ESP32
|
|
||||||
#include "nimble/BluetoothUtil.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace concurrency
|
namespace concurrency
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -240,6 +240,7 @@ Fsm powerFSM(&stateBOOT);
|
|||||||
void PowerFSM_setup()
|
void PowerFSM_setup()
|
||||||
{
|
{
|
||||||
bool isRouter = (config.device.role == Config_DeviceConfig_Role_Router ? 1 : 0);
|
bool isRouter = (config.device.role == Config_DeviceConfig_Role_Router ? 1 : 0);
|
||||||
|
uint32_t screenOnSecs = config.display.screen_on_secs ? config.display.screen_on_secs : default_screen_on_secs;
|
||||||
bool hasPower = isPowered();
|
bool hasPower = isPowered();
|
||||||
|
|
||||||
DEBUG_MSG("PowerFSM init, USB power=%d\n", hasPower);
|
DEBUG_MSG("PowerFSM init, USB power=%d\n", hasPower);
|
||||||
@ -251,8 +252,7 @@ void PowerFSM_setup()
|
|||||||
|
|
||||||
// We need this transition, because we might not transition if we were waiting to enter light-sleep, because when we wake from
|
// We need this transition, because we might not transition if we were waiting to enter light-sleep, because when we wake from
|
||||||
// light sleep we _always_ transition to NB or dark and
|
// light sleep we _always_ transition to NB or dark and
|
||||||
powerFSM.add_transition(&stateLS, isRouter ? &stateNB : &stateDARK, EVENT_PACKET_FOR_PHONE, NULL,
|
powerFSM.add_transition(&stateLS, isRouter ? &stateNB : &stateDARK, EVENT_PACKET_FOR_PHONE, NULL, "Received packet, exiting light sleep");
|
||||||
"Received packet, exiting light sleep");
|
|
||||||
powerFSM.add_transition(&stateNB, &stateNB, EVENT_PACKET_FOR_PHONE, NULL, "Received packet, resetting win wake");
|
powerFSM.add_transition(&stateNB, &stateNB, EVENT_PACKET_FOR_PHONE, NULL, "Received packet, resetting win wake");
|
||||||
|
|
||||||
// Handle press events - note: we ignore button presses when in API mode
|
// Handle press events - note: we ignore button presses when in API mode
|
||||||
@ -261,8 +261,7 @@ void PowerFSM_setup()
|
|||||||
powerFSM.add_transition(&stateDARK, &stateON, EVENT_PRESS, NULL, "Press");
|
powerFSM.add_transition(&stateDARK, &stateON, EVENT_PRESS, NULL, "Press");
|
||||||
powerFSM.add_transition(&statePOWER, &statePOWER, EVENT_PRESS, screenPress, "Press");
|
powerFSM.add_transition(&statePOWER, &statePOWER, EVENT_PRESS, screenPress, "Press");
|
||||||
powerFSM.add_transition(&stateON, &stateON, EVENT_PRESS, screenPress, "Press"); // reenter On to restart our timers
|
powerFSM.add_transition(&stateON, &stateON, EVENT_PRESS, screenPress, "Press"); // reenter On to restart our timers
|
||||||
powerFSM.add_transition(&stateSERIAL, &stateSERIAL, EVENT_PRESS, screenPress,
|
powerFSM.add_transition(&stateSERIAL, &stateSERIAL, EVENT_PRESS, screenPress, "Press"); // Allow button to work while in serial API
|
||||||
"Press"); // Allow button to work while in serial API
|
|
||||||
|
|
||||||
// Handle critically low power battery by forcing deep sleep
|
// Handle critically low power battery by forcing deep sleep
|
||||||
powerFSM.add_transition(&stateBOOT, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
powerFSM.add_transition(&stateBOOT, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||||
@ -333,10 +332,7 @@ void PowerFSM_setup()
|
|||||||
powerFSM.add_transition(&stateDARK, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update");
|
powerFSM.add_transition(&stateDARK, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update");
|
||||||
powerFSM.add_transition(&stateON, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update");
|
powerFSM.add_transition(&stateON, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update");
|
||||||
|
|
||||||
powerFSM.add_timed_transition(&stateON, &stateDARK,
|
powerFSM.add_timed_transition(&stateON, &stateDARK, screenOnSecs, NULL, "Screen-on timeout");
|
||||||
config.display.screen_on_secs ? config.display.screen_on_secs
|
|
||||||
: 60 * 1000 * 10,
|
|
||||||
NULL, "Screen-on timeout");
|
|
||||||
|
|
||||||
// On most boards we use light-sleep to be our main state, but on NRF52 we just stay in DARK
|
// On most boards we use light-sleep to be our main state, but on NRF52 we just stay in DARK
|
||||||
State *lowPowerState = &stateLS;
|
State *lowPowerState = &stateLS;
|
||||||
@ -348,17 +344,12 @@ void PowerFSM_setup()
|
|||||||
|
|
||||||
// See: https://github.com/meshtastic/Meshtastic-device/issues/1071
|
// See: https://github.com/meshtastic/Meshtastic-device/issues/1071
|
||||||
if (isRouter || config.power.is_power_saving) {
|
if (isRouter || config.power.is_power_saving) {
|
||||||
powerFSM.add_timed_transition(&stateNB, &stateLS,
|
uint32_t minWakeSecs = config.power.min_wake_secs ? config.power.min_wake_secs : default_min_wake_secs * 1000;
|
||||||
config.power.min_wake_secs ? config.power.min_wake_secs
|
uint32_t waitBluetoothSecs = config.power.wait_bluetooth_secs ? config.power.wait_bluetooth_secs : default_wait_bluetooth_secs * 1000;
|
||||||
: default_min_wake_secs * 1000,
|
|
||||||
NULL, "Min wake timeout");
|
powerFSM.add_timed_transition(&stateNB, &stateLS, minWakeSecs, NULL, "Min wake timeout");
|
||||||
powerFSM.add_timed_transition(&stateDARK, &stateLS,
|
powerFSM.add_timed_transition(&stateDARK, &stateLS, waitBluetoothSecs, NULL, "Bluetooth timeout");
|
||||||
config.power.wait_bluetooth_secs
|
meshSds = config.power.mesh_sds_timeout_secs ? config.power.mesh_sds_timeout_secs : default_mesh_sds_timeout_secs;
|
||||||
? config.power.wait_bluetooth_secs
|
|
||||||
: default_wait_bluetooth_secs * 1000,
|
|
||||||
NULL, "Bluetooth timeout");
|
|
||||||
meshSds = config.power.mesh_sds_timeout_secs ? config.power.mesh_sds_timeout_secs
|
|
||||||
: default_mesh_sds_timeout_secs;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -14,4 +14,5 @@ enum class Cmd {
|
|||||||
STOP_BOOT_SCREEN,
|
STOP_BOOT_SCREEN,
|
||||||
PRINT,
|
PRINT,
|
||||||
START_SHUTDOWN_SCREEN,
|
START_SHUTDOWN_SCREEN,
|
||||||
|
START_REBOOT_SCREEN,
|
||||||
};
|
};
|
@ -228,26 +228,17 @@ static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
|||||||
// Used when booting without a region set
|
// Used when booting without a region set
|
||||||
static void drawWelcomeScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
static void drawWelcomeScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
{
|
{
|
||||||
|
display->setFont(FONT_SMALL);
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
display->drawString(64 + x, y, "//\\ E S H T /\\ S T / C");
|
||||||
|
display->drawString(64 + x, y + FONT_HEIGHT_SMALL, getDeviceName());
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
|
||||||
if ((millis() / 10000) % 2) {
|
if ((millis() / 10000) % 2) {
|
||||||
display->setFont(FONT_SMALL);
|
|
||||||
|
|
||||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
|
||||||
display->drawString(64 + x, y, "//\\ E S H T /\\ S T / C");
|
|
||||||
|
|
||||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
|
||||||
|
|
||||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 2 - 3, "Set the region using the");
|
display->drawString(x, y + FONT_HEIGHT_SMALL * 2 - 3, "Set the region using the");
|
||||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 3 - 3, "Meshtastic Android, iOS,");
|
display->drawString(x, y + FONT_HEIGHT_SMALL * 3 - 3, "Meshtastic Android, iOS,");
|
||||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 4 - 3, "Flasher or CLI client.");
|
display->drawString(x, y + FONT_HEIGHT_SMALL * 4 - 3, "Flasher or CLI client.");
|
||||||
} else {
|
} else {
|
||||||
display->setFont(FONT_SMALL);
|
|
||||||
|
|
||||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
|
||||||
display->drawString(64 + x, y, "//\\ E S H T /\\ S T / C");
|
|
||||||
|
|
||||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
|
||||||
|
|
||||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 2 - 3, "Visit meshtastic.org");
|
display->drawString(x, y + FONT_HEIGHT_SMALL * 2 - 3, "Visit meshtastic.org");
|
||||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 3 - 3, "for more information.");
|
display->drawString(x, y + FONT_HEIGHT_SMALL * 3 - 3, "for more information.");
|
||||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 4 - 3, "");
|
display->drawString(x, y + FONT_HEIGHT_SMALL * 4 - 3, "");
|
||||||
@ -299,8 +290,13 @@ static void drawFrameBluetooth(OLEDDisplay *display, OLEDDisplayUiState *state,
|
|||||||
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Enter this code");
|
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Enter this code");
|
||||||
|
|
||||||
display->setFont(FONT_LARGE);
|
display->setFont(FONT_LARGE);
|
||||||
display->drawString(64 + x, 26 + y, btPIN);
|
|
||||||
|
|
||||||
|
auto displayPin = new String(btPIN);
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display->drawString(12 + x, 26 + y, displayPin->substring(0, 3));
|
||||||
|
display->drawString(72 + x, 26 + y, displayPin->substring(3, 6));
|
||||||
|
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
display->setFont(FONT_SMALL);
|
display->setFont(FONT_SMALL);
|
||||||
char buf[30];
|
char buf[30];
|
||||||
const char *name = "Name: ";
|
const char *name = "Name: ";
|
||||||
@ -317,6 +313,14 @@ static void drawFrameShutdown(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
|||||||
display->drawString(64 + x, 26 + y, "Shutting down...");
|
display->drawString(64 + x, 26 + y, "Shutting down...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void drawFrameReboot(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
|
||||||
|
display->setFont(FONT_MEDIUM);
|
||||||
|
display->drawString(64 + x, 26 + y, "Rebooting...");
|
||||||
|
}
|
||||||
|
|
||||||
static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
{
|
{
|
||||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
@ -329,9 +333,6 @@ static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
|||||||
} else {
|
} else {
|
||||||
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait . . ");
|
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait . . ");
|
||||||
}
|
}
|
||||||
|
|
||||||
// display->setFont(FONT_LARGE);
|
|
||||||
// display->drawString(64 + x, 26 + y, btPIN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draw the last text message we received
|
/// Draw the last text message we received
|
||||||
@ -1042,6 +1043,9 @@ int32_t Screen::runOnce()
|
|||||||
case Cmd::START_SHUTDOWN_SCREEN:
|
case Cmd::START_SHUTDOWN_SCREEN:
|
||||||
handleShutdownScreen();
|
handleShutdownScreen();
|
||||||
break;
|
break;
|
||||||
|
case Cmd::START_REBOOT_SCREEN:
|
||||||
|
handleRebootScreen();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
DEBUG_MSG("BUG: invalid cmd\n");
|
DEBUG_MSG("BUG: invalid cmd\n");
|
||||||
}
|
}
|
||||||
@ -1234,6 +1238,18 @@ void Screen::handleShutdownScreen()
|
|||||||
setFastFramerate();
|
setFastFramerate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Screen::handleRebootScreen()
|
||||||
|
{
|
||||||
|
DEBUG_MSG("showing reboot screen\n");
|
||||||
|
showingNormalScreen = false;
|
||||||
|
|
||||||
|
static FrameCallback rebootFrames[] = {drawFrameReboot};
|
||||||
|
|
||||||
|
ui.disableAllIndicators();
|
||||||
|
ui.setFrames(rebootFrames, 1);
|
||||||
|
setFastFramerate();
|
||||||
|
}
|
||||||
|
|
||||||
void Screen::handleStartFirmwareUpdateScreen()
|
void Screen::handleStartFirmwareUpdateScreen()
|
||||||
{
|
{
|
||||||
DEBUG_MSG("showing firmware screen\n");
|
DEBUG_MSG("showing firmware screen\n");
|
||||||
|
@ -20,6 +20,7 @@ class Screen
|
|||||||
void forceDisplay() {}
|
void forceDisplay() {}
|
||||||
void startBluetoothPinScreen(uint32_t pin) {}
|
void startBluetoothPinScreen(uint32_t pin) {}
|
||||||
void stopBluetoothPinScreen() {}
|
void stopBluetoothPinScreen() {}
|
||||||
|
void startRebootScreen() {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,6 +168,13 @@ class Screen : public concurrency::OSThread
|
|||||||
enqueueCmd(cmd);
|
enqueueCmd(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void startRebootScreen()
|
||||||
|
{
|
||||||
|
ScreenCmd cmd;
|
||||||
|
cmd.cmd = Cmd::START_REBOOT_SCREEN;
|
||||||
|
enqueueCmd(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
/// Stops showing the bluetooth PIN screen.
|
/// Stops showing the bluetooth PIN screen.
|
||||||
void stopBluetoothPinScreen() { enqueueCmd(ScreenCmd{.cmd = Cmd::STOP_BLUETOOTH_PIN_SCREEN}); }
|
void stopBluetoothPinScreen() { enqueueCmd(ScreenCmd{.cmd = Cmd::STOP_BLUETOOTH_PIN_SCREEN}); }
|
||||||
|
|
||||||
@ -280,6 +288,7 @@ class Screen : public concurrency::OSThread
|
|||||||
void handlePrint(const char *text);
|
void handlePrint(const char *text);
|
||||||
void handleStartFirmwareUpdateScreen();
|
void handleStartFirmwareUpdateScreen();
|
||||||
void handleShutdownScreen();
|
void handleShutdownScreen();
|
||||||
|
void handleRebootScreen();
|
||||||
/// Rebuilds our list of frames (screens) to default ones.
|
/// Rebuilds our list of frames (screens) to default ones.
|
||||||
void setFrames();
|
void setFrames();
|
||||||
|
|
||||||
|
@ -33,13 +33,7 @@
|
|||||||
|
|
||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
#include "mesh/http/WebServer.h"
|
#include "mesh/http/WebServer.h"
|
||||||
|
#include "nimble/NimbleBluetooth.h"
|
||||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
|
||||||
#include "platform/esp32/ESP32Bluetooth.h"
|
|
||||||
#else
|
|
||||||
#include "nimble/BluetoothUtil.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAS_WIFI
|
#if HAS_WIFI
|
||||||
|
@ -16,6 +16,10 @@
|
|||||||
#include "modules/PositionModule.h"
|
#include "modules/PositionModule.h"
|
||||||
#include "power.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.
|
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
|
It is implemented with a FreeRTos queue (wrapped with a little RTQueue class) of pointers to MeshPacket protobufs (which were
|
||||||
|
@ -179,12 +179,11 @@ extern NodeDB nodeDB;
|
|||||||
#define default_sds_secs 365 * 24 * 60 * 60
|
#define default_sds_secs 365 * 24 * 60 * 60
|
||||||
#define default_ls_secs IF_ROUTER(24 * 60 * 60, 5 * 60)
|
#define default_ls_secs IF_ROUTER(24 * 60 * 60, 5 * 60)
|
||||||
#define default_min_wake_secs 10
|
#define default_min_wake_secs 10
|
||||||
|
#define default_screen_on_secs 60 * 1000 * 10
|
||||||
|
|
||||||
inline uint32_t getIntervalOrDefaultMs(uint32_t interval)
|
inline uint32_t getIntervalOrDefaultMs(uint32_t interval)
|
||||||
{
|
{
|
||||||
if (interval > 0)
|
if (interval > 0) return interval * 1000;
|
||||||
return interval * 1000;
|
|
||||||
return default_broadcast_interval_secs * 1000;
|
return default_broadcast_interval_secs * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,13 +116,11 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
|
|||||||
*/
|
*/
|
||||||
size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
||||||
{
|
{
|
||||||
|
DEBUG_MSG("getFromRadio, state=%d\n", state);
|
||||||
if (!available()) {
|
if (!available()) {
|
||||||
// DEBUG_MSG("getFromRadio, !available\n");
|
// DEBUG_MSG("PhoneAPI::getFromRadio, !available\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_MSG("getFromRadio, state=%d\n", state);
|
|
||||||
|
|
||||||
// In case we send a FromRadio packet
|
// In case we send a FromRadio packet
|
||||||
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
|
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
|
||||||
|
|
||||||
@ -278,7 +276,10 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhoneAPI::handleDisconnect() {}
|
void PhoneAPI::handleDisconnect()
|
||||||
|
{
|
||||||
|
DEBUG_MSG("PhoneAPI disconnect\n");
|
||||||
|
}
|
||||||
|
|
||||||
void PhoneAPI::releasePhonePacket()
|
void PhoneAPI::releasePhonePacket()
|
||||||
{
|
{
|
||||||
@ -294,35 +295,28 @@ void PhoneAPI::releasePhonePacket()
|
|||||||
bool PhoneAPI::available()
|
bool PhoneAPI::available()
|
||||||
{
|
{
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case STATE_SEND_NOTHING:
|
case STATE_SEND_NOTHING:
|
||||||
return false;
|
return false;
|
||||||
|
case STATE_SEND_MY_INFO:
|
||||||
case STATE_SEND_MY_INFO:
|
return true;
|
||||||
return true;
|
case STATE_SEND_CONFIG:
|
||||||
|
return true;
|
||||||
case STATE_SEND_CONFIG:
|
case STATE_SEND_MODULECONFIG:
|
||||||
return true;
|
return true;
|
||||||
|
case STATE_SEND_NODEINFO:
|
||||||
case STATE_SEND_MODULECONFIG:
|
if (!nodeInfoForPhone)
|
||||||
return true;
|
nodeInfoForPhone = nodeDB.readNextInfo();
|
||||||
|
return true; // Always say we have something, because we might need to advance our state machine
|
||||||
case STATE_SEND_NODEINFO:
|
case STATE_SEND_COMPLETE_ID:
|
||||||
if (!nodeInfoForPhone)
|
return true;
|
||||||
nodeInfoForPhone = nodeDB.readNextInfo();
|
case STATE_SEND_PACKETS: {
|
||||||
return true; // Always say we have something, because we might need to advance our state machine
|
// Try to pull a new packet from the service (if we haven't already)
|
||||||
|
if (!packetForPhone)
|
||||||
case STATE_SEND_COMPLETE_ID:
|
packetForPhone = service.getForPhone();
|
||||||
return true;
|
bool hasPacket = !!packetForPhone;
|
||||||
|
// DEBUG_MSG("available hasPacket=%d\n", hasPacket);
|
||||||
case STATE_SEND_PACKETS: {
|
return hasPacket;
|
||||||
// Try to pull a new packet from the service (if we haven't already)
|
|
||||||
if (!packetForPhone)
|
|
||||||
packetForPhone = service.getForPhone();
|
|
||||||
bool hasPacket = !!packetForPhone;
|
|
||||||
// DEBUG_MSG("available hasPacket=%d\n", hasPacket);
|
|
||||||
return hasPacket;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(0); // unexpected state - FIXME, make an error code and reboot
|
assert(0); // unexpected state - FIXME, make an error code and reboot
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ class PhoneAPI
|
|||||||
// Call this when the client drops the connection, resets the state to STATE_SEND_NOTHING
|
// Call this when the client drops the connection, resets the state to STATE_SEND_NOTHING
|
||||||
// Unregisters our observer. A closed connection **can** be reopened by calling init again.
|
// Unregisters our observer. A closed connection **can** be reopened by calling init again.
|
||||||
virtual void close();
|
virtual void close();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a ToRadio protobuf
|
* Handle a ToRadio protobuf
|
||||||
* @return true true if a packet was queued for sending (so that caller can yield)
|
* @return true true if a packet was queued for sending (so that caller can yield)
|
||||||
@ -81,6 +81,8 @@ class PhoneAPI
|
|||||||
|
|
||||||
bool isConnected() { return state != STATE_SEND_NOTHING; }
|
bool isConnected() { return state != STATE_SEND_NOTHING; }
|
||||||
|
|
||||||
|
void setInitialState() { state = STATE_SEND_MY_INFO; }
|
||||||
|
|
||||||
/// emit a debugging log character, FIXME - implement
|
/// emit a debugging log character, FIXME - implement
|
||||||
void debugOut(char c) { }
|
void debugOut(char c) { }
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ void ReliableRouter::sniffReceived(const MeshPacket *p, const Routing *c)
|
|||||||
// We intentionally don't check wasSeenRecently, because it is harmless to delete non existent retransmission records
|
// We intentionally don't check wasSeenRecently, because it is harmless to delete non existent retransmission records
|
||||||
if (ackId || nakId) {
|
if (ackId || nakId) {
|
||||||
if (ackId) {
|
if (ackId) {
|
||||||
DEBUG_MSG("Received a ack for 0x%x, stopping retransmissions\n", ackId);
|
DEBUG_MSG("Received an ack for 0x%x, stopping retransmissions\n", ackId);
|
||||||
stopRetransmission(p->to, ackId);
|
stopRetransmission(p->to, ackId);
|
||||||
} else {
|
} else {
|
||||||
DEBUG_MSG("Received a nak for 0x%x, stopping retransmissions\n", nakId);
|
DEBUG_MSG("Received a nak for 0x%x, stopping retransmissions\n", nakId);
|
||||||
|
@ -165,7 +165,7 @@ extern const pb_msgdesc_t OEMStore_msg;
|
|||||||
|
|
||||||
/* Maximum encoded size of messages (where known) */
|
/* Maximum encoded size of messages (where known) */
|
||||||
#define ChannelFile_size 630
|
#define ChannelFile_size 630
|
||||||
#define DeviceState_size 22536
|
#define DeviceState_size 22218
|
||||||
#define OEMStore_size 2106
|
#define OEMStore_size 2106
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -21,7 +21,7 @@ PB_BIND(Routing, Routing, AUTO)
|
|||||||
PB_BIND(Data, Data, 2)
|
PB_BIND(Data, Data, 2)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(Location, Location, AUTO)
|
PB_BIND(Waypoint, Waypoint, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(MeshPacket, MeshPacket, 2)
|
PB_BIND(MeshPacket, MeshPacket, 2)
|
||||||
|
@ -245,24 +245,38 @@ typedef struct _Compressed {
|
|||||||
Compressed_data_t data;
|
Compressed_data_t data;
|
||||||
} Compressed;
|
} Compressed;
|
||||||
|
|
||||||
/* Location of a waypoint to associate with a message */
|
typedef PB_BYTES_ARRAY_T(237) Data_payload_t;
|
||||||
typedef struct _Location {
|
/* (Formerly called SubPacket)
|
||||||
/* Id of the location */
|
The payload portion fo a packet, this is the actual bytes that are sent
|
||||||
uint32_t id;
|
inside a radio packet (because from/to are broken out by the comms library) */
|
||||||
/* latitude_i */
|
typedef struct _Data {
|
||||||
int32_t latitude_i;
|
/* Formerly named typ and of type Type */
|
||||||
/* longitude_i */
|
PortNum portnum;
|
||||||
int32_t longitude_i;
|
/* TODO: REPLACE */
|
||||||
/* Time the location is to expire (epoch) */
|
Data_payload_t payload;
|
||||||
uint32_t expire;
|
/* Not normally used, but for testing a sender can request that recipient
|
||||||
/* If true, only allow the original sender to update the location. */
|
responds in kind (i.e. if it received a position, it should unicast back it's position).
|
||||||
bool locked;
|
Note: that if you set this on a broadcast you will receive many replies. */
|
||||||
/* Name of the location - max 30 chars */
|
bool want_response;
|
||||||
char name[30];
|
/* The address of the destination node.
|
||||||
/* *
|
This field is is filled in by the mesh radio device software, application
|
||||||
Description of the location - max 100 chars */
|
layer software should never need it.
|
||||||
char description[100];
|
RouteDiscovery messages _must_ populate this.
|
||||||
} Location;
|
Other message types might need to if they are doing multihop routing. */
|
||||||
|
uint32_t dest;
|
||||||
|
/* The address of the original sender for this message.
|
||||||
|
This field should _only_ be populated for reliable multihop packets (to keep
|
||||||
|
packets small). */
|
||||||
|
uint32_t source;
|
||||||
|
/* Only used in routing or response messages.
|
||||||
|
Indicates the original message ID that this message is reporting failure on. (formerly called original_id) */
|
||||||
|
uint32_t request_id;
|
||||||
|
/* If set, this message is intened to be a reply to a previously sent message with the defined id. */
|
||||||
|
uint32_t reply_id;
|
||||||
|
/* Defaults to false. If true, then what is in the payload should be treated as an emoji like giving
|
||||||
|
a message a heart or poop emoji. */
|
||||||
|
uint32_t emoji;
|
||||||
|
} Data;
|
||||||
|
|
||||||
/* Debug output from the device.
|
/* Debug output from the device.
|
||||||
To minimize the size of records inside the device code, if a time/source/level is not set
|
To minimize the size of records inside the device code, if a time/source/level is not set
|
||||||
@ -461,91 +475,24 @@ typedef struct _User {
|
|||||||
bool is_licensed;
|
bool is_licensed;
|
||||||
} User;
|
} User;
|
||||||
|
|
||||||
typedef PB_BYTES_ARRAY_T(237) Data_payload_t;
|
/* Waypoint message, used to share arbitrary locations across the mesh */
|
||||||
/* (Formerly called SubPacket)
|
typedef struct _Waypoint {
|
||||||
The payload portion fo a packet, this is the actual bytes that are sent
|
/* Id of the waypoint */
|
||||||
inside a radio packet (because from/to are broken out by the comms library) */
|
uint32_t id;
|
||||||
typedef struct _Data {
|
/* latitude_i */
|
||||||
/* Formerly named typ and of type Type */
|
int32_t latitude_i;
|
||||||
PortNum portnum;
|
/* longitude_i */
|
||||||
/* TODO: REPLACE */
|
int32_t longitude_i;
|
||||||
Data_payload_t payload;
|
/* Time the waypoint is to expire (epoch) */
|
||||||
/* Not normally used, but for testing a sender can request that recipient
|
uint32_t expire;
|
||||||
responds in kind (i.e. if it received a position, it should unicast back it's position).
|
/* If true, only allow the original sender to update the waypoint. */
|
||||||
Note: that if you set this on a broadcast you will receive many replies. */
|
bool locked;
|
||||||
bool want_response;
|
/* Name of the waypoint - max 30 chars */
|
||||||
/* The address of the destination node.
|
char name[30];
|
||||||
This field is is filled in by the mesh radio device software, application
|
/* *
|
||||||
layer software should never need it.
|
Description of the waypoint - max 100 chars */
|
||||||
RouteDiscovery messages _must_ populate this.
|
char description[100];
|
||||||
Other message types might need to if they are doing multihop routing. */
|
} Waypoint;
|
||||||
uint32_t dest;
|
|
||||||
/* The address of the original sender for this message.
|
|
||||||
This field should _only_ be populated for reliable multihop packets (to keep
|
|
||||||
packets small). */
|
|
||||||
uint32_t source;
|
|
||||||
/* Only used in routing or response messages.
|
|
||||||
Indicates the original message ID that this message is reporting failure on. (formerly called original_id) */
|
|
||||||
uint32_t request_id;
|
|
||||||
/* If set, this message is intened to be a reply to a previously sent message with the defined id. */
|
|
||||||
uint32_t reply_id;
|
|
||||||
/* Defaults to false. If true, then what is in the payload should be treated as an emoji like giving
|
|
||||||
a message a heart or poop emoji. */
|
|
||||||
uint32_t emoji;
|
|
||||||
/* Location structure */
|
|
||||||
bool has_location;
|
|
||||||
Location location;
|
|
||||||
} Data;
|
|
||||||
|
|
||||||
/* The bluetooth to device link:
|
|
||||||
Old BTLE protocol docs from TODO, merge in above and make real docs...
|
|
||||||
use protocol buffers, and NanoPB
|
|
||||||
messages from device to phone:
|
|
||||||
POSITION_UPDATE (..., time)
|
|
||||||
TEXT_RECEIVED(from, text, time)
|
|
||||||
OPAQUE_RECEIVED(from, payload, time) (for signal messages or other applications)
|
|
||||||
messages from phone to device:
|
|
||||||
SET_MYID(id, human readable long, human readable short) (send down the unique ID
|
|
||||||
string used for this node, a human readable string shown for that id, and a very
|
|
||||||
short human readable string suitable for oled screen) SEND_OPAQUE(dest, payload)
|
|
||||||
(for signal messages or other applications) SEND_TEXT(dest, text) Get all
|
|
||||||
nodes() (returns list of nodes, with full info, last time seen, loc, battery
|
|
||||||
level etc) SET_CONFIG (switches device to a new set of radio params and
|
|
||||||
preshared key, drops all existing nodes, force our node to rejoin this new group)
|
|
||||||
Full information about a node on the mesh */
|
|
||||||
typedef struct _NodeInfo {
|
|
||||||
/* The node number */
|
|
||||||
uint32_t num;
|
|
||||||
/* The user info for this node */
|
|
||||||
bool has_user;
|
|
||||||
User user;
|
|
||||||
/* This position data. Note: before 1.2.14 we would also store the last time we've heard from this node in position.time, that is no longer true.
|
|
||||||
Position.time now indicates the last time we received a POSITION from that node. */
|
|
||||||
bool has_position;
|
|
||||||
Position position;
|
|
||||||
/* Returns the Signal-to-noise ratio (SNR) of the last received message,
|
|
||||||
as measured by the receiver. Return SNR of the last received message in dB */
|
|
||||||
float snr;
|
|
||||||
/* Set to indicate the last time we received a packet from this node */
|
|
||||||
uint32_t last_heard;
|
|
||||||
/* The latest device metrics for the node. */
|
|
||||||
bool has_device_metrics;
|
|
||||||
DeviceMetrics device_metrics;
|
|
||||||
} NodeInfo;
|
|
||||||
|
|
||||||
/* A Routing control Data packet handled by the routing module */
|
|
||||||
typedef struct _Routing {
|
|
||||||
pb_size_t which_variant;
|
|
||||||
union {
|
|
||||||
/* A route request going from the requester */
|
|
||||||
RouteDiscovery route_request;
|
|
||||||
/* A route reply */
|
|
||||||
RouteDiscovery route_reply;
|
|
||||||
/* A failure in delivering a message (usually used for routing control messages, but might be provided
|
|
||||||
in addition to ack.fail_id to provide details on the type of failure). */
|
|
||||||
Routing_Error error_reason;
|
|
||||||
};
|
|
||||||
} Routing;
|
|
||||||
|
|
||||||
typedef PB_BYTES_ARRAY_T(256) MeshPacket_encrypted_t;
|
typedef PB_BYTES_ARRAY_T(256) MeshPacket_encrypted_t;
|
||||||
/* A packet envelope sent/received over the mesh
|
/* A packet envelope sent/received over the mesh
|
||||||
@ -619,6 +566,56 @@ typedef struct _MeshPacket {
|
|||||||
MeshPacket_Delayed delayed;
|
MeshPacket_Delayed delayed;
|
||||||
} MeshPacket;
|
} MeshPacket;
|
||||||
|
|
||||||
|
/* The bluetooth to device link:
|
||||||
|
Old BTLE protocol docs from TODO, merge in above and make real docs...
|
||||||
|
use protocol buffers, and NanoPB
|
||||||
|
messages from device to phone:
|
||||||
|
POSITION_UPDATE (..., time)
|
||||||
|
TEXT_RECEIVED(from, text, time)
|
||||||
|
OPAQUE_RECEIVED(from, payload, time) (for signal messages or other applications)
|
||||||
|
messages from phone to device:
|
||||||
|
SET_MYID(id, human readable long, human readable short) (send down the unique ID
|
||||||
|
string used for this node, a human readable string shown for that id, and a very
|
||||||
|
short human readable string suitable for oled screen) SEND_OPAQUE(dest, payload)
|
||||||
|
(for signal messages or other applications) SEND_TEXT(dest, text) Get all
|
||||||
|
nodes() (returns list of nodes, with full info, last time seen, loc, battery
|
||||||
|
level etc) SET_CONFIG (switches device to a new set of radio params and
|
||||||
|
preshared key, drops all existing nodes, force our node to rejoin this new group)
|
||||||
|
Full information about a node on the mesh */
|
||||||
|
typedef struct _NodeInfo {
|
||||||
|
/* The node number */
|
||||||
|
uint32_t num;
|
||||||
|
/* The user info for this node */
|
||||||
|
bool has_user;
|
||||||
|
User user;
|
||||||
|
/* This position data. Note: before 1.2.14 we would also store the last time we've heard from this node in position.time, that is no longer true.
|
||||||
|
Position.time now indicates the last time we received a POSITION from that node. */
|
||||||
|
bool has_position;
|
||||||
|
Position position;
|
||||||
|
/* Returns the Signal-to-noise ratio (SNR) of the last received message,
|
||||||
|
as measured by the receiver. Return SNR of the last received message in dB */
|
||||||
|
float snr;
|
||||||
|
/* Set to indicate the last time we received a packet from this node */
|
||||||
|
uint32_t last_heard;
|
||||||
|
/* The latest device metrics for the node. */
|
||||||
|
bool has_device_metrics;
|
||||||
|
DeviceMetrics device_metrics;
|
||||||
|
} NodeInfo;
|
||||||
|
|
||||||
|
/* A Routing control Data packet handled by the routing module */
|
||||||
|
typedef struct _Routing {
|
||||||
|
pb_size_t which_variant;
|
||||||
|
union {
|
||||||
|
/* A route request going from the requester */
|
||||||
|
RouteDiscovery route_request;
|
||||||
|
/* A route reply */
|
||||||
|
RouteDiscovery route_reply;
|
||||||
|
/* A failure in delivering a message (usually used for routing control messages, but might be provided
|
||||||
|
in addition to ack.fail_id to provide details on the type of failure). */
|
||||||
|
Routing_Error error_reason;
|
||||||
|
};
|
||||||
|
} Routing;
|
||||||
|
|
||||||
/* Packets from the radio to the phone will appear on the fromRadio characteristic.
|
/* Packets from the radio to the phone will appear on the fromRadio characteristic.
|
||||||
It will support READ and NOTIFY. When a new packet arrives the device will BLE notify?
|
It will support READ and NOTIFY. When a new packet arrives the device will BLE notify?
|
||||||
It will sit in that descriptor until consumed by the phone,
|
It will sit in that descriptor until consumed by the phone,
|
||||||
@ -730,8 +727,8 @@ extern "C" {
|
|||||||
#define User_init_default {"", "", "", {0}, _HardwareModel_MIN, 0}
|
#define User_init_default {"", "", "", {0}, _HardwareModel_MIN, 0}
|
||||||
#define RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
#define RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
||||||
#define Routing_init_default {0, {RouteDiscovery_init_default}}
|
#define Routing_init_default {0, {RouteDiscovery_init_default}}
|
||||||
#define Data_init_default {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, Location_init_default}
|
#define Data_init_default {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0}
|
||||||
#define Location_init_default {0, 0, 0, 0, 0, "", ""}
|
#define Waypoint_init_default {0, 0, 0, 0, 0, "", ""}
|
||||||
#define MeshPacket_init_default {0, 0, 0, 0, {Data_init_default}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN, 0, _MeshPacket_Delayed_MIN}
|
#define MeshPacket_init_default {0, 0, 0, 0, {Data_init_default}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN, 0, _MeshPacket_Delayed_MIN}
|
||||||
#define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0, false, DeviceMetrics_init_default}
|
#define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0, false, DeviceMetrics_init_default}
|
||||||
#define MyNodeInfo_init_default {0, 0, "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, 0}
|
#define MyNodeInfo_init_default {0, 0, "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, 0}
|
||||||
@ -744,8 +741,8 @@ extern "C" {
|
|||||||
#define User_init_zero {"", "", "", {0}, _HardwareModel_MIN, 0}
|
#define User_init_zero {"", "", "", {0}, _HardwareModel_MIN, 0}
|
||||||
#define RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
#define RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
||||||
#define Routing_init_zero {0, {RouteDiscovery_init_zero}}
|
#define Routing_init_zero {0, {RouteDiscovery_init_zero}}
|
||||||
#define Data_init_zero {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, Location_init_zero}
|
#define Data_init_zero {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0}
|
||||||
#define Location_init_zero {0, 0, 0, 0, 0, "", ""}
|
#define Waypoint_init_zero {0, 0, 0, 0, 0, "", ""}
|
||||||
#define MeshPacket_init_zero {0, 0, 0, 0, {Data_init_zero}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN, 0, _MeshPacket_Delayed_MIN}
|
#define MeshPacket_init_zero {0, 0, 0, 0, {Data_init_zero}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN, 0, _MeshPacket_Delayed_MIN}
|
||||||
#define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0, false, DeviceMetrics_init_zero}
|
#define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0, false, DeviceMetrics_init_zero}
|
||||||
#define MyNodeInfo_init_zero {0, 0, "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, 0}
|
#define MyNodeInfo_init_zero {0, 0, "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, 0}
|
||||||
@ -758,13 +755,14 @@ extern "C" {
|
|||||||
/* Field tags (for use in manual encoding/decoding) */
|
/* Field tags (for use in manual encoding/decoding) */
|
||||||
#define Compressed_portnum_tag 1
|
#define Compressed_portnum_tag 1
|
||||||
#define Compressed_data_tag 2
|
#define Compressed_data_tag 2
|
||||||
#define Location_id_tag 1
|
#define Data_portnum_tag 1
|
||||||
#define Location_latitude_i_tag 2
|
#define Data_payload_tag 2
|
||||||
#define Location_longitude_i_tag 3
|
#define Data_want_response_tag 3
|
||||||
#define Location_expire_tag 4
|
#define Data_dest_tag 4
|
||||||
#define Location_locked_tag 5
|
#define Data_source_tag 5
|
||||||
#define Location_name_tag 6
|
#define Data_request_id_tag 6
|
||||||
#define Location_description_tag 7
|
#define Data_reply_id_tag 7
|
||||||
|
#define Data_emoji_tag 8
|
||||||
#define LogRecord_message_tag 1
|
#define LogRecord_message_tag 1
|
||||||
#define LogRecord_time_tag 2
|
#define LogRecord_time_tag 2
|
||||||
#define LogRecord_source_tag 3
|
#define LogRecord_source_tag 3
|
||||||
@ -816,24 +814,13 @@ extern "C" {
|
|||||||
#define User_macaddr_tag 4
|
#define User_macaddr_tag 4
|
||||||
#define User_hw_model_tag 6
|
#define User_hw_model_tag 6
|
||||||
#define User_is_licensed_tag 7
|
#define User_is_licensed_tag 7
|
||||||
#define Data_portnum_tag 1
|
#define Waypoint_id_tag 1
|
||||||
#define Data_payload_tag 2
|
#define Waypoint_latitude_i_tag 2
|
||||||
#define Data_want_response_tag 3
|
#define Waypoint_longitude_i_tag 3
|
||||||
#define Data_dest_tag 4
|
#define Waypoint_expire_tag 4
|
||||||
#define Data_source_tag 5
|
#define Waypoint_locked_tag 5
|
||||||
#define Data_request_id_tag 6
|
#define Waypoint_name_tag 6
|
||||||
#define Data_reply_id_tag 7
|
#define Waypoint_description_tag 7
|
||||||
#define Data_emoji_tag 8
|
|
||||||
#define Data_location_tag 9
|
|
||||||
#define NodeInfo_num_tag 1
|
|
||||||
#define NodeInfo_user_tag 2
|
|
||||||
#define NodeInfo_position_tag 3
|
|
||||||
#define NodeInfo_snr_tag 4
|
|
||||||
#define NodeInfo_last_heard_tag 5
|
|
||||||
#define NodeInfo_device_metrics_tag 6
|
|
||||||
#define Routing_route_request_tag 1
|
|
||||||
#define Routing_route_reply_tag 2
|
|
||||||
#define Routing_error_reason_tag 3
|
|
||||||
#define MeshPacket_from_tag 1
|
#define MeshPacket_from_tag 1
|
||||||
#define MeshPacket_to_tag 2
|
#define MeshPacket_to_tag 2
|
||||||
#define MeshPacket_channel_tag 3
|
#define MeshPacket_channel_tag 3
|
||||||
@ -847,6 +834,15 @@ extern "C" {
|
|||||||
#define MeshPacket_priority_tag 12
|
#define MeshPacket_priority_tag 12
|
||||||
#define MeshPacket_rx_rssi_tag 13
|
#define MeshPacket_rx_rssi_tag 13
|
||||||
#define MeshPacket_delayed_tag 15
|
#define MeshPacket_delayed_tag 15
|
||||||
|
#define NodeInfo_num_tag 1
|
||||||
|
#define NodeInfo_user_tag 2
|
||||||
|
#define NodeInfo_position_tag 3
|
||||||
|
#define NodeInfo_snr_tag 4
|
||||||
|
#define NodeInfo_last_heard_tag 5
|
||||||
|
#define NodeInfo_device_metrics_tag 6
|
||||||
|
#define Routing_route_request_tag 1
|
||||||
|
#define Routing_route_reply_tag 2
|
||||||
|
#define Routing_error_reason_tag 3
|
||||||
#define FromRadio_id_tag 1
|
#define FromRadio_id_tag 1
|
||||||
#define FromRadio_my_info_tag 3
|
#define FromRadio_my_info_tag 3
|
||||||
#define FromRadio_node_info_tag 4
|
#define FromRadio_node_info_tag 4
|
||||||
@ -920,13 +916,11 @@ X(a, STATIC, SINGULAR, FIXED32, dest, 4) \
|
|||||||
X(a, STATIC, SINGULAR, FIXED32, source, 5) \
|
X(a, STATIC, SINGULAR, FIXED32, source, 5) \
|
||||||
X(a, STATIC, SINGULAR, FIXED32, request_id, 6) \
|
X(a, STATIC, SINGULAR, FIXED32, request_id, 6) \
|
||||||
X(a, STATIC, SINGULAR, FIXED32, reply_id, 7) \
|
X(a, STATIC, SINGULAR, FIXED32, reply_id, 7) \
|
||||||
X(a, STATIC, SINGULAR, FIXED32, emoji, 8) \
|
X(a, STATIC, SINGULAR, FIXED32, emoji, 8)
|
||||||
X(a, STATIC, OPTIONAL, MESSAGE, location, 9)
|
|
||||||
#define Data_CALLBACK NULL
|
#define Data_CALLBACK NULL
|
||||||
#define Data_DEFAULT NULL
|
#define Data_DEFAULT NULL
|
||||||
#define Data_location_MSGTYPE Location
|
|
||||||
|
|
||||||
#define Location_FIELDLIST(X, a) \
|
#define Waypoint_FIELDLIST(X, a) \
|
||||||
X(a, STATIC, SINGULAR, UINT32, id, 1) \
|
X(a, STATIC, SINGULAR, UINT32, id, 1) \
|
||||||
X(a, STATIC, SINGULAR, SFIXED32, latitude_i, 2) \
|
X(a, STATIC, SINGULAR, SFIXED32, latitude_i, 2) \
|
||||||
X(a, STATIC, SINGULAR, SFIXED32, longitude_i, 3) \
|
X(a, STATIC, SINGULAR, SFIXED32, longitude_i, 3) \
|
||||||
@ -934,8 +928,8 @@ X(a, STATIC, SINGULAR, UINT32, expire, 4) \
|
|||||||
X(a, STATIC, SINGULAR, BOOL, locked, 5) \
|
X(a, STATIC, SINGULAR, BOOL, locked, 5) \
|
||||||
X(a, STATIC, SINGULAR, STRING, name, 6) \
|
X(a, STATIC, SINGULAR, STRING, name, 6) \
|
||||||
X(a, STATIC, SINGULAR, STRING, description, 7)
|
X(a, STATIC, SINGULAR, STRING, description, 7)
|
||||||
#define Location_CALLBACK NULL
|
#define Waypoint_CALLBACK NULL
|
||||||
#define Location_DEFAULT NULL
|
#define Waypoint_DEFAULT NULL
|
||||||
|
|
||||||
#define MeshPacket_FIELDLIST(X, a) \
|
#define MeshPacket_FIELDLIST(X, a) \
|
||||||
X(a, STATIC, SINGULAR, FIXED32, from, 1) \
|
X(a, STATIC, SINGULAR, FIXED32, from, 1) \
|
||||||
@ -1042,7 +1036,7 @@ extern const pb_msgdesc_t User_msg;
|
|||||||
extern const pb_msgdesc_t RouteDiscovery_msg;
|
extern const pb_msgdesc_t RouteDiscovery_msg;
|
||||||
extern const pb_msgdesc_t Routing_msg;
|
extern const pb_msgdesc_t Routing_msg;
|
||||||
extern const pb_msgdesc_t Data_msg;
|
extern const pb_msgdesc_t Data_msg;
|
||||||
extern const pb_msgdesc_t Location_msg;
|
extern const pb_msgdesc_t Waypoint_msg;
|
||||||
extern const pb_msgdesc_t MeshPacket_msg;
|
extern const pb_msgdesc_t MeshPacket_msg;
|
||||||
extern const pb_msgdesc_t NodeInfo_msg;
|
extern const pb_msgdesc_t NodeInfo_msg;
|
||||||
extern const pb_msgdesc_t MyNodeInfo_msg;
|
extern const pb_msgdesc_t MyNodeInfo_msg;
|
||||||
@ -1058,7 +1052,7 @@ extern const pb_msgdesc_t Compressed_msg;
|
|||||||
#define RouteDiscovery_fields &RouteDiscovery_msg
|
#define RouteDiscovery_fields &RouteDiscovery_msg
|
||||||
#define Routing_fields &Routing_msg
|
#define Routing_fields &Routing_msg
|
||||||
#define Data_fields &Data_msg
|
#define Data_fields &Data_msg
|
||||||
#define Location_fields &Location_msg
|
#define Waypoint_fields &Waypoint_msg
|
||||||
#define MeshPacket_fields &MeshPacket_msg
|
#define MeshPacket_fields &MeshPacket_msg
|
||||||
#define NodeInfo_fields &NodeInfo_msg
|
#define NodeInfo_fields &NodeInfo_msg
|
||||||
#define MyNodeInfo_fields &MyNodeInfo_msg
|
#define MyNodeInfo_fields &MyNodeInfo_msg
|
||||||
@ -1070,19 +1064,19 @@ extern const pb_msgdesc_t Compressed_msg;
|
|||||||
|
|
||||||
/* Maximum encoded size of messages (where known) */
|
/* Maximum encoded size of messages (where known) */
|
||||||
#define Compressed_size 243
|
#define Compressed_size 243
|
||||||
#define Data_size 429
|
#define Data_size 270
|
||||||
#define FromRadio_size 489
|
#define FromRadio_size 330
|
||||||
#define Location_size 156
|
|
||||||
#define LogRecord_size 81
|
#define LogRecord_size 81
|
||||||
#define MeshPacket_size 480
|
#define MeshPacket_size 321
|
||||||
#define MyNodeInfo_size 197
|
#define MyNodeInfo_size 197
|
||||||
#define NodeInfo_size 263
|
#define NodeInfo_size 263
|
||||||
#define Position_size 142
|
#define Position_size 142
|
||||||
#define RouteDiscovery_size 40
|
#define RouteDiscovery_size 40
|
||||||
#define Routing_size 42
|
#define Routing_size 42
|
||||||
#define ToRadio_PeerInfo_size 8
|
#define ToRadio_PeerInfo_size 8
|
||||||
#define ToRadio_size 483
|
#define ToRadio_size 324
|
||||||
#define User_size 77
|
#define User_size 77
|
||||||
|
#define Waypoint_size 156
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
|
@ -72,7 +72,7 @@ typedef struct _ModuleConfig_ExternalNotificationConfig {
|
|||||||
} ModuleConfig_ExternalNotificationConfig;
|
} ModuleConfig_ExternalNotificationConfig;
|
||||||
|
|
||||||
typedef struct _ModuleConfig_MQTTConfig {
|
typedef struct _ModuleConfig_MQTTConfig {
|
||||||
bool disabled;
|
bool enabled;
|
||||||
char address[32];
|
char address[32];
|
||||||
char username[32];
|
char username[32];
|
||||||
char password[32];
|
char password[32];
|
||||||
@ -187,7 +187,7 @@ extern "C" {
|
|||||||
#define ModuleConfig_ExternalNotificationConfig_active_tag 4
|
#define ModuleConfig_ExternalNotificationConfig_active_tag 4
|
||||||
#define ModuleConfig_ExternalNotificationConfig_alert_message_tag 5
|
#define ModuleConfig_ExternalNotificationConfig_alert_message_tag 5
|
||||||
#define ModuleConfig_ExternalNotificationConfig_alert_bell_tag 6
|
#define ModuleConfig_ExternalNotificationConfig_alert_bell_tag 6
|
||||||
#define ModuleConfig_MQTTConfig_disabled_tag 1
|
#define ModuleConfig_MQTTConfig_enabled_tag 1
|
||||||
#define ModuleConfig_MQTTConfig_address_tag 2
|
#define ModuleConfig_MQTTConfig_address_tag 2
|
||||||
#define ModuleConfig_MQTTConfig_username_tag 3
|
#define ModuleConfig_MQTTConfig_username_tag 3
|
||||||
#define ModuleConfig_MQTTConfig_password_tag 4
|
#define ModuleConfig_MQTTConfig_password_tag 4
|
||||||
@ -240,7 +240,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,canned_message,payloadVariant
|
|||||||
#define ModuleConfig_payloadVariant_canned_message_MSGTYPE ModuleConfig_CannedMessageConfig
|
#define ModuleConfig_payloadVariant_canned_message_MSGTYPE ModuleConfig_CannedMessageConfig
|
||||||
|
|
||||||
#define ModuleConfig_MQTTConfig_FIELDLIST(X, a) \
|
#define ModuleConfig_MQTTConfig_FIELDLIST(X, a) \
|
||||||
X(a, STATIC, SINGULAR, BOOL, disabled, 1) \
|
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
|
||||||
X(a, STATIC, SINGULAR, STRING, address, 2) \
|
X(a, STATIC, SINGULAR, STRING, address, 2) \
|
||||||
X(a, STATIC, SINGULAR, STRING, username, 3) \
|
X(a, STATIC, SINGULAR, STRING, username, 3) \
|
||||||
X(a, STATIC, SINGULAR, STRING, password, 4) \
|
X(a, STATIC, SINGULAR, STRING, password, 4) \
|
||||||
|
@ -48,7 +48,8 @@ typedef enum _PortNum {
|
|||||||
PortNum_ADMIN_APP = 6,
|
PortNum_ADMIN_APP = 6,
|
||||||
/* Compressed TEXT_MESSAGE payloads. */
|
/* Compressed TEXT_MESSAGE payloads. */
|
||||||
PortNum_TEXT_MESSAGE_COMPRESSED_APP = 7,
|
PortNum_TEXT_MESSAGE_COMPRESSED_APP = 7,
|
||||||
/* Waypoint payloads. */
|
/* Waypoint payloads.
|
||||||
|
Payload is a [Waypoint](/docs/developers/protobufs/api#waypoint) message */
|
||||||
PortNum_WAYPOINT_APP = 8,
|
PortNum_WAYPOINT_APP = 8,
|
||||||
/* Provides a 'ping' service that replies to any packet it receives.
|
/* Provides a 'ping' service that replies to any packet it receives.
|
||||||
Also serves as a small example module. */
|
Also serves as a small example module. */
|
||||||
|
@ -170,45 +170,54 @@ void AdminModule::handleSetOwner(const User &o)
|
|||||||
|
|
||||||
void AdminModule::handleSetConfig(const Config &c)
|
void AdminModule::handleSetConfig(const Config &c)
|
||||||
{
|
{
|
||||||
|
bool requiresReboot = false;
|
||||||
switch (c.which_payloadVariant) {
|
switch (c.which_payloadVariant) {
|
||||||
case Config_device_tag:
|
case Config_device_tag:
|
||||||
DEBUG_MSG("Setting config: Device\n");
|
DEBUG_MSG("Setting config: Device\n");
|
||||||
config.has_device = true;
|
config.has_device = true;
|
||||||
config.device = c.payloadVariant.device;
|
config.device = c.payloadVariant.device;
|
||||||
break;
|
break;
|
||||||
case Config_position_tag:
|
case Config_position_tag:
|
||||||
DEBUG_MSG("Setting config: Position\n");
|
DEBUG_MSG("Setting config: Position\n");
|
||||||
config.has_position = true;
|
config.has_position = true;
|
||||||
config.position = c.payloadVariant.position;
|
config.position = c.payloadVariant.position;
|
||||||
break;
|
break;
|
||||||
case Config_power_tag:
|
case Config_power_tag:
|
||||||
DEBUG_MSG("Setting config: Power\n");
|
DEBUG_MSG("Setting config: Power\n");
|
||||||
config.has_power = true;
|
config.has_power = true;
|
||||||
config.power = c.payloadVariant.power;
|
config.power = c.payloadVariant.power;
|
||||||
break;
|
break;
|
||||||
case Config_wifi_tag:
|
case Config_wifi_tag:
|
||||||
DEBUG_MSG("Setting config: WiFi\n");
|
DEBUG_MSG("Setting config: WiFi\n");
|
||||||
config.has_wifi = true;
|
config.has_wifi = true;
|
||||||
config.wifi = c.payloadVariant.wifi;
|
config.wifi = c.payloadVariant.wifi;
|
||||||
break;
|
break;
|
||||||
case Config_display_tag:
|
case Config_display_tag:
|
||||||
DEBUG_MSG("Setting config: Display\n");
|
DEBUG_MSG("Setting config: Display\n");
|
||||||
config.has_display = true;
|
config.has_display = true;
|
||||||
config.display = c.payloadVariant.display;
|
config.display = c.payloadVariant.display;
|
||||||
break;
|
break;
|
||||||
case Config_lora_tag:
|
case Config_lora_tag:
|
||||||
DEBUG_MSG("Setting config: LoRa\n");
|
DEBUG_MSG("Setting config: LoRa\n");
|
||||||
config.has_lora = true;
|
config.has_lora = true;
|
||||||
config.lora = c.payloadVariant.lora;
|
config.lora = c.payloadVariant.lora;
|
||||||
break;
|
requiresReboot = true;
|
||||||
case Config_bluetooth_tag:
|
break;
|
||||||
DEBUG_MSG("Setting config: Bluetooth\n");
|
case Config_bluetooth_tag:
|
||||||
config.has_bluetooth = true;
|
DEBUG_MSG("Setting config: Bluetooth\n");
|
||||||
config.bluetooth = c.payloadVariant.bluetooth;
|
config.has_bluetooth = true;
|
||||||
break;
|
config.bluetooth = c.payloadVariant.bluetooth;
|
||||||
|
requiresReboot = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
service.reloadConfig();
|
service.reloadConfig();
|
||||||
|
// Reboot 5 seconds after a config that requires rebooting is set
|
||||||
|
if (requiresReboot) {
|
||||||
|
DEBUG_MSG("Rebooting due to config changes\n");
|
||||||
|
screen->startRebootScreen();
|
||||||
|
rebootAtMsec = millis() + (5 * 1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdminModule::handleSetModuleConfig(const ModuleConfig &c)
|
void AdminModule::handleSetModuleConfig(const ModuleConfig &c)
|
||||||
|
@ -13,8 +13,9 @@
|
|||||||
#include "modules/ReplyModule.h"
|
#include "modules/ReplyModule.h"
|
||||||
#include "modules/RoutingModule.h"
|
#include "modules/RoutingModule.h"
|
||||||
#include "modules/TextMessageModule.h"
|
#include "modules/TextMessageModule.h"
|
||||||
#include "modules/Telemetry/DeviceTelemetry.h"
|
#include "modules/WaypointModule.h"
|
||||||
#if HAS_TELEMETRY
|
#if HAS_TELEMETRY
|
||||||
|
#include "modules/Telemetry/DeviceTelemetry.h"
|
||||||
#include "modules/Telemetry/EnvironmentTelemetry.h"
|
#include "modules/Telemetry/EnvironmentTelemetry.h"
|
||||||
#endif
|
#endif
|
||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
@ -34,6 +35,7 @@ void setupModules()
|
|||||||
adminModule = new AdminModule();
|
adminModule = new AdminModule();
|
||||||
nodeInfoModule = new NodeInfoModule();
|
nodeInfoModule = new NodeInfoModule();
|
||||||
positionModule = new PositionModule();
|
positionModule = new PositionModule();
|
||||||
|
waypointModule = new WaypointModule();
|
||||||
textMessageModule = new TextMessageModule();
|
textMessageModule = new TextMessageModule();
|
||||||
|
|
||||||
// Note: if the rest of meshtastic doesn't need to explicitly use your module, you do not need to assign the instance
|
// Note: if the rest of meshtastic doesn't need to explicitly use your module, you do not need to assign the instance
|
||||||
@ -70,6 +72,8 @@ void setupModules()
|
|||||||
storeForwardModule = new StoreForwardModule();
|
storeForwardModule = new StoreForwardModule();
|
||||||
|
|
||||||
new RangeTestModule();
|
new RangeTestModule();
|
||||||
|
#elif defined(ARCH_NRF52)
|
||||||
|
new ExternalNotificationModule();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// NOTE! This module must be added LAST because it likes to check for replies from other modules and avoid sending extra acks
|
// NOTE! This module must be added LAST because it likes to check for replies from other modules and avoid sending extra acks
|
||||||
|
17
src/modules/WaypointModule.cpp
Normal file
17
src/modules/WaypointModule.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include "configuration.h"
|
||||||
|
#include "WaypointModule.h"
|
||||||
|
#include "NodeDB.h"
|
||||||
|
#include "PowerFSM.h"
|
||||||
|
|
||||||
|
WaypointModule *waypointModule;
|
||||||
|
|
||||||
|
ProcessMessage WaypointModule::handleReceived(const MeshPacket &mp)
|
||||||
|
{
|
||||||
|
auto &p = mp.decoded;
|
||||||
|
DEBUG_MSG("Received waypoint msg from=0x%0x, id=0x%x, msg=%.*s\n", mp.from, mp.id, p.payload.size, p.payload.bytes);
|
||||||
|
|
||||||
|
|
||||||
|
notifyObservers(&mp);
|
||||||
|
|
||||||
|
return ProcessMessage::CONTINUE; // Let others look at this message also if they want
|
||||||
|
}
|
25
src/modules/WaypointModule.h
Normal file
25
src/modules/WaypointModule.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "SinglePortModule.h"
|
||||||
|
#include "Observer.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waypoint message handling for meshtastic
|
||||||
|
*/
|
||||||
|
class WaypointModule : public SinglePortModule, public Observable<const MeshPacket *>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Constructor
|
||||||
|
* name is for debugging output
|
||||||
|
*/
|
||||||
|
WaypointModule() : SinglePortModule("waypoint", PortNum_WAYPOINT_APP) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/** Called to handle a particular incoming message
|
||||||
|
|
||||||
|
@return ProcessMessage::STOP if you've guaranteed you've handled this message and no other handlers should be considered for it
|
||||||
|
*/
|
||||||
|
virtual ProcessMessage handleReceived(const MeshPacket &mp) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern WaypointModule *waypointModule;
|
@ -175,9 +175,7 @@ bool MQTT::wantsLink() const
|
|||||||
{
|
{
|
||||||
bool hasChannel = false;
|
bool hasChannel = false;
|
||||||
|
|
||||||
if (moduleConfig.mqtt.disabled) {
|
if (moduleConfig.mqtt.enabled) {
|
||||||
// DEBUG_MSG("MQTT disabled...\n");
|
|
||||||
} else {
|
|
||||||
// No need for link if no channel needed it
|
// No need for link if no channel needed it
|
||||||
size_t numChan = channels.getNumChannels();
|
size_t numChan = channels.getNumChannels();
|
||||||
for (size_t i = 0; i < numChan; i++) {
|
for (size_t i = 0; i < numChan; i++) {
|
||||||
|
@ -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 "configuration.h"
|
||||||
#include "ESP32Bluetooth.h"
|
#include "NimbleBluetooth.h"
|
||||||
#include "BluetoothCommon.h"
|
#include "BluetoothCommon.h"
|
||||||
#include "PowerFSM.h"
|
#include "PowerFSM.h"
|
||||||
#include "sleep.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)
|
* 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) {
|
virtual void onWrite(NimBLECharacteristic *pCharacteristic) {
|
||||||
DEBUG_MSG("To Radio onwrite\n");
|
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) {
|
virtual void onRead(NimBLECharacteristic *pCharacteristic) {
|
||||||
DEBUG_MSG("From Radio onread\n");
|
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() {
|
virtual uint32_t onPassKeyRequest() {
|
||||||
uint32_t passkey = config.bluetooth.fixed_pin;
|
uint32_t passkey = config.bluetooth.fixed_pin;
|
||||||
@ -100,6 +98,7 @@ class ESP32BluetoothServerCallback : public NimBLEServerCallbacks
|
|||||||
passkeyShowing = false;
|
passkeyShowing = false;
|
||||||
screen->stopBluetoothPinScreen();
|
screen->stopBluetoothPinScreen();
|
||||||
}
|
}
|
||||||
|
// bluetoothPhoneAPI->setInitialState();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onDisconnect(NimBLEServer* pServer, ble_gap_conn_desc *desc)
|
virtual void onDisconnect(NimBLEServer* pServer, ble_gap_conn_desc *desc)
|
||||||
@ -108,10 +107,10 @@ class ESP32BluetoothServerCallback : public NimBLEServerCallbacks
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static ESP32BluetoothToRadioCallback *toRadioCallbacks;
|
static NimbleBluetoothToRadioCallback *toRadioCallbacks;
|
||||||
static ESP32BluetoothFromRadioCallback *fromRadioCallbacks;
|
static NimbleBluetoothFromRadioCallback *fromRadioCallbacks;
|
||||||
|
|
||||||
void ESP32Bluetooth::shutdown()
|
void NimbleBluetooth::shutdown()
|
||||||
{
|
{
|
||||||
// Shutdown bluetooth for minimum power draw
|
// Shutdown bluetooth for minimum power draw
|
||||||
DEBUG_MSG("Disable bluetooth\n");
|
DEBUG_MSG("Disable bluetooth\n");
|
||||||
@ -121,58 +120,63 @@ void ESP32Bluetooth::shutdown()
|
|||||||
pAdvertising->stop();
|
pAdvertising->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESP32Bluetooth::isActive()
|
bool NimbleBluetooth::isActive()
|
||||||
{
|
{
|
||||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||||
return bleServer && (bleServer->getConnectedCount() > 0 || pAdvertising->isAdvertising());
|
return bleServer && (bleServer->getConnectedCount() > 0 || pAdvertising->isAdvertising());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESP32Bluetooth::setup()
|
void NimbleBluetooth::setup()
|
||||||
{
|
{
|
||||||
DEBUG_MSG("Initialise the ESP32 bluetooth module\n");
|
// Uncomment for testing
|
||||||
|
// NimbleBluetooth::clearBonds();
|
||||||
|
|
||||||
|
DEBUG_MSG("Initialise the NimBLE bluetooth module\n");
|
||||||
|
|
||||||
NimBLEDevice::init(getDeviceName());
|
NimBLEDevice::init(getDeviceName());
|
||||||
NimBLEDevice::setPower(ESP_PWR_LVL_P9);
|
NimBLEDevice::setPower(ESP_PWR_LVL_P9);
|
||||||
|
|
||||||
// FIXME fails in iOS
|
if (config.bluetooth.mode != Config_BluetoothConfig_PairingMode_NoPin) {
|
||||||
if (config.bluetooth.mode == Config_BluetoothConfig_PairingMode_NoPin) {
|
|
||||||
NimBLEDevice::setSecurityIOCap(BLE_HS_IO_NO_INPUT_OUTPUT);
|
|
||||||
NimBLEDevice::setSecurityAuth(true, false, true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
NimBLEDevice::setSecurityAuth(true, true, true);
|
NimBLEDevice::setSecurityAuth(true, true, true);
|
||||||
NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY);
|
NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY);
|
||||||
}
|
}
|
||||||
bleServer = NimBLEDevice::createServer();
|
bleServer = NimBLEDevice::createServer();
|
||||||
|
|
||||||
ESP32BluetoothServerCallback *serverCallbacks = new ESP32BluetoothServerCallback();
|
NimbleBluetoothServerCallback *serverCallbacks = new NimbleBluetoothServerCallback();
|
||||||
bleServer->setCallbacks(serverCallbacks, true);
|
bleServer->setCallbacks(serverCallbacks, true);
|
||||||
|
|
||||||
setupService();
|
setupService();
|
||||||
startAdvertising();
|
startAdvertising();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESP32Bluetooth::setupService()
|
void NimbleBluetooth::setupService()
|
||||||
{
|
{
|
||||||
NimBLEService *bleService = bleServer->createService(MESH_SERVICE_UUID);
|
NimBLEService *bleService = bleServer->createService(MESH_SERVICE_UUID);
|
||||||
|
NimBLECharacteristic *ToRadioCharacteristic;
|
||||||
//define the characteristics that the app is looking for
|
NimBLECharacteristic *FromRadioCharacteristic;
|
||||||
NimBLECharacteristic *ToRadioCharacteristic = bleService->createCharacteristic(TORADIO_UUID, NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_AUTHEN | NIMBLE_PROPERTY::WRITE_ENC);
|
// Define the characteristics that the app is looking for
|
||||||
NimBLECharacteristic *FromRadioCharacteristic = bleService->createCharacteristic(FROMRADIO_UUID, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_AUTHEN | NIMBLE_PROPERTY::READ_ENC);
|
if (config.bluetooth.mode == Config_BluetoothConfig_PairingMode_NoPin) {
|
||||||
fromNumCharacteristic = bleService->createCharacteristic(FROMNUM_UUID, NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_AUTHEN | NIMBLE_PROPERTY::READ_ENC);
|
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);
|
||||||
|
}
|
||||||
bluetoothPhoneAPI = new BluetoothPhoneAPI();
|
bluetoothPhoneAPI = new BluetoothPhoneAPI();
|
||||||
|
|
||||||
toRadioCallbacks = new ESP32BluetoothToRadioCallback();
|
toRadioCallbacks = new NimbleBluetoothToRadioCallback();
|
||||||
ToRadioCharacteristic->setCallbacks(toRadioCallbacks);
|
ToRadioCharacteristic->setCallbacks(toRadioCallbacks);
|
||||||
|
|
||||||
fromRadioCallbacks = new ESP32BluetoothFromRadioCallback();
|
fromRadioCallbacks = new NimbleBluetoothFromRadioCallback();
|
||||||
FromRadioCharacteristic->setCallbacks(fromRadioCallbacks);
|
FromRadioCharacteristic->setCallbacks(fromRadioCallbacks);
|
||||||
|
|
||||||
bleService->start();
|
bleService->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESP32Bluetooth::startAdvertising()
|
void NimbleBluetooth::startAdvertising()
|
||||||
{
|
{
|
||||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||||
pAdvertising->reset();
|
pAdvertising->reset();
|
||||||
@ -186,7 +190,7 @@ void updateBatteryLevel(uint8_t level)
|
|||||||
//blebas.write(level);
|
//blebas.write(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESP32Bluetooth::clearBonds()
|
void NimbleBluetooth::clearBonds()
|
||||||
{
|
{
|
||||||
DEBUG_MSG("Clearing bluetooth bonds!\n");
|
DEBUG_MSG("Clearing bluetooth bonds!\n");
|
||||||
NimBLEDevice::deleteAllBonds();
|
NimBLEDevice::deleteAllBonds();
|
||||||
@ -195,7 +199,9 @@ void ESP32Bluetooth::clearBonds()
|
|||||||
void clearNVS()
|
void clearNVS()
|
||||||
{
|
{
|
||||||
NimBLEDevice::deleteAllBonds();
|
NimBLEDevice::deleteAllBonds();
|
||||||
|
#ifdef ARCH_ESP32
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void disablePin()
|
void disablePin()
|
||||||
@ -218,5 +224,3 @@ void disablePin()
|
|||||||
|
|
||||||
doublepressed = millis();
|
doublepressed = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
@ -1,8 +1,6 @@
|
|||||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
class ESP32Bluetooth
|
class NimbleBluetooth
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void setup();
|
void setup();
|
||||||
@ -18,5 +16,3 @@ class ESP32Bluetooth
|
|||||||
void setBluetoothEnable(bool on);
|
void setBluetoothEnable(bool on);
|
||||||
void clearNVS();
|
void clearNVS();
|
||||||
void disablePin();
|
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
|
// defaults for ESP32 architecture
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#ifndef HAS_BLUETOOTH
|
||||||
|
#define HAS_BLUETOOTH 1
|
||||||
|
#endif
|
||||||
#ifndef HAS_WIFI
|
#ifndef HAS_WIFI
|
||||||
#define HAS_WIFI 1
|
#define HAS_WIFI 1
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,15 +1,10 @@
|
|||||||
#include "BluetoothSoftwareUpdate.h"
|
|
||||||
#include "PowerFSM.h"
|
#include "PowerFSM.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "esp_task_wdt.h"
|
#include "esp_task_wdt.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
#include "nimble/NimbleBluetooth.h"
|
||||||
#include "ESP32Bluetooth.h"
|
|
||||||
#include "mesh/http/WiFiAPClient.h"
|
#include "mesh/http/WiFiAPClient.h"
|
||||||
#else
|
|
||||||
#include "nimble/BluetoothUtil.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
#include "target_specific.h"
|
#include "target_specific.h"
|
||||||
@ -19,41 +14,26 @@
|
|||||||
#include <nvs.h>
|
#include <nvs.h>
|
||||||
#include <nvs_flash.h>
|
#include <nvs_flash.h>
|
||||||
|
|
||||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
NimbleBluetooth *nimbleBluetooth;
|
||||||
ESP32Bluetooth *esp32Bluetooth;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void getMacAddr(uint8_t *dmac)
|
void getMacAddr(uint8_t *dmac)
|
||||||
{
|
{
|
||||||
assert(esp_efuse_mac_get_default(dmac) == ESP_OK);
|
assert(esp_efuse_mac_get_default(dmac) == ESP_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
static void printBLEinfo() {
|
|
||||||
int dev_num = esp_ble_get_bond_device_num();
|
|
||||||
|
|
||||||
esp_ble_bond_dev_t *dev_list = (esp_ble_bond_dev_t *)malloc(sizeof(esp_ble_bond_dev_t) * dev_num);
|
|
||||||
esp_ble_get_bond_device_list(&dev_num, dev_list);
|
|
||||||
for (int i = 0; i < dev_num; i++) {
|
|
||||||
// esp_ble_remove_bond_device(dev_list[i].bd_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
} */
|
|
||||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
|
||||||
void setBluetoothEnable(bool on) {
|
void setBluetoothEnable(bool on) {
|
||||||
|
|
||||||
if (!isWifiAvailable()) {
|
if (!isWifiAvailable() && config.bluetooth.enabled == true) {
|
||||||
if (!esp32Bluetooth) {
|
if (!nimbleBluetooth) {
|
||||||
esp32Bluetooth = new ESP32Bluetooth();
|
nimbleBluetooth = new NimbleBluetooth();
|
||||||
}
|
}
|
||||||
if (on && !esp32Bluetooth->isActive()) {
|
if (on && !nimbleBluetooth->isActive()) {
|
||||||
esp32Bluetooth->setup();
|
nimbleBluetooth->setup();
|
||||||
} else {
|
} else {
|
||||||
esp32Bluetooth->shutdown();
|
nimbleBluetooth->shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void esp32Setup()
|
void esp32Setup()
|
||||||
{
|
{
|
||||||
@ -123,7 +103,6 @@ Periodic axpDebugOutput(axpDebugRead);
|
|||||||
void esp32Loop()
|
void esp32Loop()
|
||||||
{
|
{
|
||||||
esp_task_wdt_reset(); // service our app level watchdog
|
esp_task_wdt_reset(); // service our app level watchdog
|
||||||
//loopBLE();
|
|
||||||
|
|
||||||
// for debug printing
|
// for debug printing
|
||||||
// radio.radioIf.canSleep();
|
// radio.radioIf.canSleep();
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "NRF52Bluetooth.h"
|
#include "NRF52Bluetooth.h"
|
||||||
#include "BluetoothCommon.h"
|
#include "BluetoothCommon.h"
|
||||||
|
#include "PowerFSM.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "mesh/PhoneAPI.h"
|
#include "mesh/PhoneAPI.h"
|
||||||
#include "mesh/mesh-pb-constants.h"
|
#include "mesh/mesh-pb-constants.h"
|
||||||
@ -22,7 +24,7 @@ static BLEDfu bledfu; // DFU software update helper service
|
|||||||
static uint8_t fromRadioBytes[FromRadio_size];
|
static uint8_t fromRadioBytes[FromRadio_size];
|
||||||
static uint8_t toRadioBytes[ToRadio_size];
|
static uint8_t toRadioBytes[ToRadio_size];
|
||||||
|
|
||||||
static bool bleConnected;
|
static uint16_t connectionHandle;
|
||||||
|
|
||||||
class BluetoothPhoneAPI : public PhoneAPI
|
class BluetoothPhoneAPI : public PhoneAPI
|
||||||
{
|
{
|
||||||
@ -39,13 +41,14 @@ class BluetoothPhoneAPI : public PhoneAPI
|
|||||||
|
|
||||||
/// Check the current underlying physical link to see if the client is currently connected
|
/// Check the current underlying physical link to see if the client is currently connected
|
||||||
virtual bool checkIsConnected() override {
|
virtual bool checkIsConnected() override {
|
||||||
return bleConnected;
|
BLEConnection *connection = Bluefruit.Connection(connectionHandle);
|
||||||
|
return connection->connected();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static BluetoothPhoneAPI *bluetoothPhoneAPI;
|
static BluetoothPhoneAPI *bluetoothPhoneAPI;
|
||||||
|
|
||||||
void connect_callback(uint16_t conn_handle)
|
void onConnect(uint16_t conn_handle)
|
||||||
{
|
{
|
||||||
// Get the reference to current connection
|
// Get the reference to current connection
|
||||||
BLEConnection *connection = Bluefruit.Connection(conn_handle);
|
BLEConnection *connection = Bluefruit.Connection(conn_handle);
|
||||||
@ -54,7 +57,7 @@ void connect_callback(uint16_t conn_handle)
|
|||||||
connection->getPeerName(central_name, sizeof(central_name));
|
connection->getPeerName(central_name, sizeof(central_name));
|
||||||
|
|
||||||
DEBUG_MSG("BLE Connected to %s\n", central_name);
|
DEBUG_MSG("BLE Connected to %s\n", central_name);
|
||||||
bleConnected = true;
|
// bluetoothPhoneAPI->setInitialState();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,15 +65,12 @@ void connect_callback(uint16_t conn_handle)
|
|||||||
* @param conn_handle connection where this event happens
|
* @param conn_handle connection where this event happens
|
||||||
* @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
|
* @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
|
||||||
*/
|
*/
|
||||||
void disconnect_callback(uint16_t conn_handle, uint8_t reason)
|
void onDisconnect(uint16_t conn_handle, uint8_t reason)
|
||||||
{
|
{
|
||||||
// FIXME - we currently assume only one active connection
|
|
||||||
bleConnected = false;
|
|
||||||
|
|
||||||
DEBUG_MSG("BLE 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 onCCCD(uint16_t conn_hdl, BLECharacteristic *chr, uint16_t cccd_value)
|
||||||
{
|
{
|
||||||
// Display the raw request packet
|
// Display the raw request packet
|
||||||
DEBUG_MSG("CCCD Updated: %u\n", cccd_value);
|
DEBUG_MSG("CCCD Updated: %u\n", cccd_value);
|
||||||
@ -126,7 +126,7 @@ static void authorizeRead(uint16_t conn_hdl)
|
|||||||
/**
|
/**
|
||||||
* client is starting read, pull the bytes from our API class
|
* 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)
|
void onFromRadio(uint16_t conn_hdl, BLECharacteristic *chr, ble_gatts_evt_read_t *request)
|
||||||
{
|
{
|
||||||
if (request->offset == 0) {
|
if (request->offset == 0) {
|
||||||
// If the read is long, we will get multiple authorize invocations - we only populate data on the first
|
// If the read is long, we will get multiple authorize invocations - we only populate data on the first
|
||||||
@ -141,7 +141,7 @@ void fromRadioAuthorizeCb(uint16_t conn_hdl, BLECharacteristic *chr, ble_gatts_e
|
|||||||
authorizeRead(conn_hdl);
|
authorizeRead(conn_hdl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void toRadioWriteCb(uint16_t conn_hdl, BLECharacteristic *chr, uint8_t *data, uint16_t len)
|
void onToRadio(uint16_t conn_hdl, BLECharacteristic *chr, uint8_t *data, uint16_t len)
|
||||||
{
|
{
|
||||||
DEBUG_MSG("toRadioWriteCb data %p, len %u\n", data, len);
|
DEBUG_MSG("toRadioWriteCb data %p, len %u\n", data, len);
|
||||||
|
|
||||||
@ -151,7 +151,7 @@ void toRadioWriteCb(uint16_t conn_hdl, BLECharacteristic *chr, uint8_t *data, ui
|
|||||||
/**
|
/**
|
||||||
* client is starting read, pull the bytes from our API class
|
* 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)
|
void onFromNumAuthorize(uint16_t conn_hdl, BLECharacteristic *chr, ble_gatts_evt_read_t *request)
|
||||||
{
|
{
|
||||||
DEBUG_MSG("fromNumAuthorizeCb\n");
|
DEBUG_MSG("fromNumAuthorizeCb\n");
|
||||||
|
|
||||||
@ -168,39 +168,37 @@ void setupMeshService(void)
|
|||||||
// 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!
|
||||||
|
|
||||||
fromNum.setProperties(CHR_PROPS_NOTIFY | CHR_PROPS_READ);
|
|
||||||
fromNum.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); // FIXME, secure this!!!
|
|
||||||
fromNum.setFixedLen(0); // Variable len (either 0 or 4) FIXME consider changing protocol so it is fixed 4 byte len, where 0 means empty
|
fromNum.setFixedLen(0); // Variable len (either 0 or 4) FIXME consider changing protocol so it is fixed 4 byte len, where 0 means empty
|
||||||
fromNum.setMaxLen(4);
|
fromNum.setMaxLen(4);
|
||||||
fromNum.setCccdWriteCallback(cccd_callback); // Optionally capture CCCD updates
|
fromNum.setCccdWriteCallback(onCCCD); // Optionally capture CCCD updates
|
||||||
// We don't yet need to hook the fromNum auth callback
|
// We don't yet need to hook the fromNum auth callback
|
||||||
// fromNum.setReadAuthorizeCallback(fromNumAuthorizeCb);
|
// fromNum.setReadAuthorizeCallback(fromNumAuthorizeCb);
|
||||||
fromNum.write32(0); // Provide default fromNum of 0
|
fromNum.write32(0); // Provide default fromNum of 0
|
||||||
fromNum.begin();
|
fromNum.begin();
|
||||||
|
|
||||||
fromRadio.setProperties(CHR_PROPS_READ);
|
fromRadio.setProperties(CHR_PROPS_READ);
|
||||||
fromRadio.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); // FIXME secure this!
|
// fromRadio.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); // FIXME secure this!
|
||||||
fromRadio.setMaxLen(sizeof(fromRadioBytes));
|
fromRadio.setMaxLen(sizeof(fromRadioBytes));
|
||||||
fromRadio.setReadAuthorizeCallback(
|
fromRadio.setReadAuthorizeCallback(
|
||||||
fromRadioAuthorizeCb,
|
onFromRadio,
|
||||||
false); // We don't call this callback via the adafruit queue, because we can safely run in the BLE context
|
false); // We don't call this callback via the adafruit queue, because we can safely run in the BLE context
|
||||||
fromRadio.setBuffer(fromRadioBytes, sizeof(fromRadioBytes)); // we preallocate our fromradio buffer so we won't waste space
|
fromRadio.setBuffer(fromRadioBytes, sizeof(fromRadioBytes)); // we preallocate our fromradio buffer so we won't waste space
|
||||||
// for two copies
|
// for two copies
|
||||||
fromRadio.begin();
|
fromRadio.begin();
|
||||||
|
|
||||||
toRadio.setProperties(CHR_PROPS_WRITE);
|
toRadio.setProperties(CHR_PROPS_WRITE);
|
||||||
toRadio.setPermission(SECMODE_OPEN, SECMODE_OPEN); // FIXME secure this!
|
// toRadio.setPermission(SECMODE_OPEN, SECMODE_OPEN); // FIXME secure this!
|
||||||
toRadio.setFixedLen(0);
|
toRadio.setFixedLen(0);
|
||||||
toRadio.setMaxLen(512);
|
toRadio.setMaxLen(512);
|
||||||
toRadio.setBuffer(toRadioBytes, sizeof(toRadioBytes));
|
toRadio.setBuffer(toRadioBytes, sizeof(toRadioBytes));
|
||||||
// We don't call this callback via the adafruit queue, because we can safely run in the BLE context
|
// We don't call this callback via the adafruit queue, because we can safely run in the BLE context
|
||||||
toRadio.setWriteCallback(toRadioWriteCb, false);
|
toRadio.setWriteCallback(onToRadio, false);
|
||||||
toRadio.begin();
|
toRadio.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME, turn off soft device access for debugging
|
// FIXME, turn off soft device access for debugging
|
||||||
static bool isSoftDeviceAllowed = true;
|
static bool isSoftDeviceAllowed = true;
|
||||||
|
static uint32_t configuredPasskey;
|
||||||
|
|
||||||
void NRF52Bluetooth::shutdown()
|
void NRF52Bluetooth::shutdown()
|
||||||
{
|
{
|
||||||
@ -211,9 +209,14 @@ void NRF52Bluetooth::shutdown()
|
|||||||
|
|
||||||
void NRF52Bluetooth::setup()
|
void NRF52Bluetooth::setup()
|
||||||
{
|
{
|
||||||
|
// Uncomment for testing
|
||||||
|
// Bluefruit.Periph.clearBonds();
|
||||||
|
// Bluefruit.Central.clearBonds();
|
||||||
|
|
||||||
// Initialise the Bluefruit module
|
// Initialise the Bluefruit module
|
||||||
DEBUG_MSG("Initialise the Bluefruit nRF52 module\n");
|
DEBUG_MSG("Initialise the Bluefruit nRF52 module\n");
|
||||||
Bluefruit.autoConnLed(false);
|
Bluefruit.autoConnLed(false);
|
||||||
|
Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
|
||||||
Bluefruit.begin();
|
Bluefruit.begin();
|
||||||
|
|
||||||
// Clear existing data.
|
// Clear existing data.
|
||||||
@ -221,12 +224,29 @@ void NRF52Bluetooth::setup()
|
|||||||
Bluefruit.Advertising.clearData();
|
Bluefruit.Advertising.clearData();
|
||||||
Bluefruit.ScanResponse.clearData();
|
Bluefruit.ScanResponse.clearData();
|
||||||
|
|
||||||
|
if (config.bluetooth.mode != Config_BluetoothConfig_PairingMode_NoPin) {
|
||||||
|
configuredPasskey = config.bluetooth.mode == Config_BluetoothConfig_PairingMode_FixedPin ?
|
||||||
|
config.bluetooth.fixed_pin : random(100000, 999999);
|
||||||
|
auto pinString = std::to_string(configuredPasskey);
|
||||||
|
DEBUG_MSG("Bluetooth pin set to '%i'\n", configuredPasskey);
|
||||||
|
Bluefruit.Security.setPIN(pinString.c_str());
|
||||||
|
Bluefruit.Security.setIOCaps(true, false, false);
|
||||||
|
Bluefruit.Security.setPairPasskeyCallback(NRF52Bluetooth::onPairingPasskey);
|
||||||
|
Bluefruit.Security.setPairCompleteCallback(NRF52Bluetooth::onPairingCompleted);
|
||||||
|
Bluefruit.Security.setSecuredCallback(NRF52Bluetooth::onConnectionSecured);
|
||||||
|
meshBleService.setPermission(SECMODE_ENC_WITH_MITM, SECMODE_ENC_WITH_MITM);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Bluefruit.Security.setIOCaps(false, false, false);
|
||||||
|
meshBleService.setPermission(SECMODE_OPEN, SECMODE_OPEN);
|
||||||
|
}
|
||||||
|
|
||||||
// Set the advertised device name (keep it short!)
|
// Set the advertised device name (keep it short!)
|
||||||
Bluefruit.setName(getDeviceName());
|
Bluefruit.setName(getDeviceName());
|
||||||
|
|
||||||
// Set the connect/disconnect callback handlers
|
// Set the connect/disconnect callback handlers
|
||||||
Bluefruit.Periph.setConnectCallback(connect_callback);
|
Bluefruit.Periph.setConnectCallback(onConnect);
|
||||||
Bluefruit.Periph.setDisconnectCallback(disconnect_callback);
|
Bluefruit.Periph.setDisconnectCallback(onDisconnect);
|
||||||
|
|
||||||
// Configure and Start the Device Information Service
|
// Configure and Start the Device Information Service
|
||||||
DEBUG_MSG("Configuring the Device Information Service\n");
|
DEBUG_MSG("Configuring the Device Information Service\n");
|
||||||
@ -251,7 +271,6 @@ void NRF52Bluetooth::setup()
|
|||||||
// Setup the advertising packet(s)
|
// Setup the advertising packet(s)
|
||||||
DEBUG_MSG("Setting up the advertising payload(s)\n");
|
DEBUG_MSG("Setting up the advertising payload(s)\n");
|
||||||
startAdv();
|
startAdv();
|
||||||
|
|
||||||
DEBUG_MSG("Advertising\n");
|
DEBUG_MSG("Advertising\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -271,3 +290,41 @@ void NRF52Bluetooth::clearBonds()
|
|||||||
Bluefruit.Periph.clearBonds();
|
Bluefruit.Periph.clearBonds();
|
||||||
Bluefruit.Central.clearBonds();
|
Bluefruit.Central.clearBonds();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NRF52Bluetooth::onConnectionSecured(uint16_t conn_handle)
|
||||||
|
{
|
||||||
|
DEBUG_MSG("BLE connection secured\n");
|
||||||
|
BLEConnection* connection = Bluefruit.Connection(conn_handle);
|
||||||
|
|
||||||
|
if (!connection->secured())
|
||||||
|
{
|
||||||
|
connection->requestPairing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NRF52Bluetooth::onPairingPasskey(uint16_t conn_handle, uint8_t const passkey[6], bool match_request)
|
||||||
|
{
|
||||||
|
DEBUG_MSG("BLE pairing process started with passkey %.3s %.3s\n", passkey, passkey+3);
|
||||||
|
screen->startBluetoothPinScreen(configuredPasskey);
|
||||||
|
|
||||||
|
if (match_request)
|
||||||
|
{
|
||||||
|
uint32_t start_time = millis();
|
||||||
|
while(millis() < start_time + 30000)
|
||||||
|
{
|
||||||
|
if (!Bluefruit.connected(conn_handle)) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DEBUG_MSG("BLE passkey pairing: match_request=%i\n", match_request);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NRF52Bluetooth::onPairingCompleted(uint16_t conn_handle, uint8_t auth_status)
|
||||||
|
{
|
||||||
|
if (auth_status == BLE_GAP_SEC_STATUS_SUCCESS)
|
||||||
|
DEBUG_MSG("BLE pairing success\n");
|
||||||
|
else
|
||||||
|
DEBUG_MSG("BLE pairing failed\n");
|
||||||
|
|
||||||
|
screen->stopBluetoothPinScreen();
|
||||||
|
}
|
||||||
|
@ -6,5 +6,10 @@ class NRF52Bluetooth
|
|||||||
void setup();
|
void setup();
|
||||||
void shutdown();
|
void shutdown();
|
||||||
void clearBonds();
|
void clearBonds();
|
||||||
};
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void onConnectionSecured(uint16_t conn_handle);
|
||||||
|
void convertToUint8(uint8_t target[4], uint32_t source);
|
||||||
|
static bool onPairingPasskey(uint16_t conn_handle, uint8_t const passkey[6], bool match_request);
|
||||||
|
static void onPairingCompleted(uint16_t conn_handle, uint8_t auth_status);
|
||||||
|
};
|
||||||
|
@ -5,7 +5,9 @@
|
|||||||
//
|
//
|
||||||
// defaults for NRF52 architecture
|
// defaults for NRF52 architecture
|
||||||
//
|
//
|
||||||
|
#ifndef HAS_BLUETOOTH
|
||||||
|
#define HAS_BLUETOOTH 1
|
||||||
|
#endif
|
||||||
#ifndef HAS_SCREEN
|
#ifndef HAS_SCREEN
|
||||||
#define HAS_SCREEN 1
|
#define HAS_SCREEN 1
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <Adafruit_nRFCrypto.h>
|
#include <Adafruit_nRFCrypto.h>
|
||||||
// #include <Adafruit_USBD_Device.h>
|
// #include <Adafruit_USBD_Device.h>
|
||||||
|
#include "NodeDB.h"
|
||||||
|
|
||||||
#include "NRF52Bluetooth.h"
|
#include "NRF52Bluetooth.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
@ -68,7 +69,7 @@ static const bool useSoftDevice = true; // Set to false for easier debugging
|
|||||||
|
|
||||||
void setBluetoothEnable(bool on)
|
void setBluetoothEnable(bool on)
|
||||||
{
|
{
|
||||||
if (on != bleOn) {
|
if (on != bleOn && config.bluetooth.enabled == true) {
|
||||||
if (on) {
|
if (on) {
|
||||||
if (!nrf52Bluetooth) {
|
if (!nrf52Bluetooth) {
|
||||||
if (!useSoftDevice)
|
if (!useSoftDevice)
|
||||||
@ -81,9 +82,8 @@ void setBluetoothEnable(bool on)
|
|||||||
initBrownout();
|
initBrownout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if (nrf52Bluetooth) {
|
||||||
if (nrf52Bluetooth)
|
nrf52Bluetooth->shutdown();
|
||||||
nrf52Bluetooth->shutdown();
|
|
||||||
}
|
}
|
||||||
bleOn = on;
|
bleOn = on;
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
#include <driver/rtc_io.h>
|
#include <driver/rtc_io.h>
|
||||||
#include <driver/uart.h>
|
#include <driver/uart.h>
|
||||||
|
|
||||||
#include "nimble/BluetoothUtil.h"
|
|
||||||
|
|
||||||
esp_sleep_source_t wakeCause; // the reason we booted this time
|
esp_sleep_source_t wakeCause; // the reason we booted this time
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user