mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-15 15:22:34 +00:00
Compare commits
36 Commits
v1.3.36.7e
...
v1.3.39.dd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ddc3727155 | ||
|
|
ef9bfc9104 | ||
|
|
3bb645d4fe | ||
|
|
8f99258fc4 | ||
|
|
b54073a8a1 | ||
|
|
c85e9f53c7 | ||
|
|
4cfc229e77 | ||
|
|
bbd7c5063d | ||
|
|
05df849a6d | ||
|
|
ccbc01a753 | ||
|
|
d6d936b5d2 | ||
|
|
b028af0d82 | ||
|
|
86d3759f55 | ||
|
|
aadaf332cf | ||
|
|
4dea95d03f | ||
|
|
1253abd138 | ||
|
|
80e3cee006 | ||
|
|
ca9113ad05 | ||
|
|
63c8f15d38 | ||
|
|
73a1ea59f4 | ||
|
|
97712a9dc4 | ||
|
|
20e43fcf34 | ||
|
|
f66c8572b4 | ||
|
|
64f852e3f7 | ||
|
|
ea90e4d2de | ||
|
|
dd720f2fe6 | ||
|
|
808fef7e91 | ||
|
|
70e6dc3c67 | ||
|
|
279149e40f | ||
|
|
4588995fba | ||
|
|
11ae248c5e | ||
|
|
a0a5147c42 | ||
|
|
b8aac2c5b6 | ||
|
|
de22f20876 | ||
|
|
9b5211dc65 | ||
|
|
0b4fb72d58 |
73
.github/workflows/main_matrix.yml
vendored
73
.github/workflows/main_matrix.yml
vendored
@@ -6,6 +6,7 @@ on:
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
- "**.yml"
|
||||
- "version.properties"
|
||||
|
||||
# Note: This is different from "pull_request". Need to specify ref when doing checkouts.
|
||||
pull_request_target:
|
||||
@@ -380,6 +381,11 @@ jobs:
|
||||
# For diagnostics
|
||||
- name: Show artifacts
|
||||
run: ls -lR
|
||||
|
||||
- name: Device scripts permissions
|
||||
run: |
|
||||
chmod +x ./output/device-install.sh
|
||||
chmod +x ./output/device-update.sh
|
||||
|
||||
- name: Zip firmware
|
||||
run: zip -j -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
|
||||
@@ -403,17 +409,51 @@ jobs:
|
||||
artifacts-dir: pr
|
||||
artifacts: ./firmware-${{ steps.version.outputs.version }}.zip
|
||||
|
||||
- name: Verify version.properties change
|
||||
uses: tj-actions/verify-changed-files@v10.1
|
||||
id: verify-changed-files
|
||||
release-artifacts:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
needs: [gather-artifacts, after-checks]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
files: |
|
||||
version.properties
|
||||
python-version: 3.x
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
|
||||
id: version
|
||||
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: firmware-${{ steps.version.outputs.version }}
|
||||
path: ./output
|
||||
|
||||
- name: Device scripts permissions
|
||||
run: |
|
||||
chmod +x ./output/device-install.sh
|
||||
chmod +x ./output/device-update.sh
|
||||
|
||||
- name: Zip firmware
|
||||
run: zip -j -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
|
||||
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: debug-elfs-${{ steps.version.outputs.version }}.zip
|
||||
path: ./elfs
|
||||
|
||||
- name: Zip Elfs
|
||||
run: zip -j -r ./debug-elfs-${{ steps.version.outputs.version }}.zip ./elfs
|
||||
|
||||
# For diagnostics
|
||||
- name: Show artifacts
|
||||
run: ls -lR
|
||||
|
||||
- name: Create release
|
||||
uses: actions/create-release@v1
|
||||
id: create_release
|
||||
if: contains(steps.verify-changed-files.outputs.changed_files, 'version.properties') && ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
|
||||
with:
|
||||
draft: true
|
||||
prerelease: true
|
||||
@@ -426,7 +466,6 @@ jobs:
|
||||
|
||||
- name: Add bins to release
|
||||
uses: actions/upload-release-asset@v1
|
||||
if: contains(steps.verify-changed-files.outputs.changed_files, 'version.properties') && ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
with:
|
||||
@@ -435,17 +474,8 @@ jobs:
|
||||
asset_name: firmware-${{ steps.version.outputs.version }}.zip
|
||||
asset_content_type: application/zip
|
||||
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: debug-elfs-${{ steps.version.outputs.version }}.zip
|
||||
path: ./elfs
|
||||
|
||||
- name: Zip Elfs
|
||||
run: zip -j -r ./debug-elfs-${{ steps.version.outputs.version }}.zip ./elfs
|
||||
|
||||
- name: Add debug elfs to release
|
||||
uses: actions/upload-release-asset@v1
|
||||
if: contains(steps.verify-changed-files.outputs.changed_files, 'version.properties') && ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
with:
|
||||
@@ -453,3 +483,14 @@ jobs:
|
||||
asset_path: ./debug-elfs-${{ steps.version.outputs.version }}.zip
|
||||
asset_name: debug-elfs-${{ steps.version.outputs.version }}.zip
|
||||
asset_content_type: application/zip
|
||||
|
||||
- name: Bump version.properties
|
||||
run: >-
|
||||
bin/bump_version.py
|
||||
|
||||
- name: Create version.properties pull request
|
||||
uses: peter-evans/create-pull-request@v3
|
||||
with:
|
||||
add-paths: |
|
||||
version.properties
|
||||
|
||||
|
||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -52,7 +52,8 @@
|
||||
"shared_mutex": "cpp",
|
||||
"iostream": "cpp",
|
||||
"esp_nimble_hci.h": "c",
|
||||
"map": "cpp"
|
||||
"map": "cpp",
|
||||
"random": "cpp"
|
||||
},
|
||||
"cSpell.words": [
|
||||
"Blox",
|
||||
|
||||
16
bin/bump_version.py
Executable file
16
bin/bump_version.py
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python
|
||||
"""Bump the version number"""
|
||||
|
||||
lines = None
|
||||
|
||||
with open('version.properties', 'r', encoding='utf-8') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
with open('version.properties', 'w', encoding='utf-8') as f:
|
||||
for line in lines:
|
||||
if line.lstrip().startswith("build = "):
|
||||
words = line.split(" = ")
|
||||
ver = f'build = {int(words[1]) + 1}'
|
||||
f.write(f'{ver}\n')
|
||||
else:
|
||||
f.write(line)
|
||||
4
bin/device-install.bat
Normal file → Executable file
4
bin/device-install.bat
Normal file → Executable file
@@ -31,7 +31,7 @@ IF EXIST %FILENAME% (
|
||||
%PYTHON% -m esptool --baud 115200 erase_flash
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x1000 system-info.bin
|
||||
for %%f in (littlefs-*.bin) do (
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x00390000 %%f
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x2B0000 %%f
|
||||
)
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x10000 %FILENAME%
|
||||
) else (
|
||||
@@ -39,4 +39,4 @@ IF EXIST %FILENAME% (
|
||||
goto HELP
|
||||
)
|
||||
|
||||
:EOF
|
||||
:EOF
|
||||
|
||||
@@ -48,7 +48,7 @@ if [ -f "${FILENAME}" ]; then
|
||||
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
|
||||
"$PYTHON" -m esptool erase_flash
|
||||
"$PYTHON" -m esptool write_flash 0x1000 system-info.bin
|
||||
"$PYTHON" -m esptool write_flash 0x00390000 littlefs-*.bin
|
||||
"$PYTHON" -m esptool write_flash 0x2B0000 littlefs-*.bin
|
||||
"$PYTHON" -m esptool write_flash 0x10000 ${FILENAME}
|
||||
else
|
||||
echo "Invalid file: ${FILENAME}"
|
||||
|
||||
4
bin/device-update.bat
Normal file → Executable file
4
bin/device-update.bat
Normal file → Executable file
@@ -29,11 +29,9 @@ IF "__%FILENAME%__" == "____" (
|
||||
IF EXIST %FILENAME% (
|
||||
echo Trying to flash update %FILENAME%
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x10000 %FILENAME%
|
||||
echo Erasing the otadata partition, which will turn off flash flippy-flop and force the first image to be used
|
||||
%PYTHON% -m esptool --baud 115200 erase_region 0xe000 0x2000
|
||||
) else (
|
||||
echo "Invalid file: %FILENAME%"
|
||||
goto HELP
|
||||
)
|
||||
|
||||
:EOF
|
||||
:EOF
|
||||
|
||||
@@ -45,8 +45,6 @@ shift "$((OPTIND-1))"
|
||||
if [ -f "${FILENAME}" ]; then
|
||||
echo "Trying to flash update ${FILENAME}."
|
||||
$PYTHON -m esptool --baud 115200 write_flash 0x10000 ${FILENAME}
|
||||
echo "Erasing the otadata partition, which will turn off flash flippy-flop and force the first image to be used"
|
||||
$PYTHON -m esptool --baud 115200 erase_region 0xe000 0x2000
|
||||
else
|
||||
echo "Invalid file: ${FILENAME}"
|
||||
show_help
|
||||
|
||||
31
boards/generic_wl5e.json
Normal file
31
boards/generic_wl5e.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"build": {
|
||||
"core": "stm32",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DSTM32WLxx -DSTM32WLE5xx -DARDUINO_GENERIC_WLE5CCUX",
|
||||
"f_cpu": "48000000L",
|
||||
"mcu": "stm32wle5ccu",
|
||||
"variant": "STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U",
|
||||
"product_line": "STM32WLE5xx"
|
||||
},
|
||||
"debug": {
|
||||
"default_tools": [
|
||||
"stlink"
|
||||
],
|
||||
"jlink_device": "STM32WLE5CC",
|
||||
"openocd_target": "stm32wlx",
|
||||
"svd_path": "STM32WLE5_CM4.svd"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "BB-STM32WL",
|
||||
"upload": {
|
||||
"maximum_ram_size": 65536,
|
||||
"maximum_size": 262144,
|
||||
"protocol": "cmsis-dap",
|
||||
"protocols": [
|
||||
"cmsis-dap"
|
||||
]
|
||||
},
|
||||
"url": "https://www.st.com/en/microcontrollers-microprocessors/stm32wl-series.html",
|
||||
"vendor": "ST"
|
||||
}
|
||||
@@ -3,6 +3,5 @@
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x5000,
|
||||
otadata, data, ota, 0xe000, 0x2000,
|
||||
app0, app, ota_0, 0x10000, 0x1c0000,
|
||||
app1, app, ota_1, 0x1d0000,0x1c0000,
|
||||
spiffs, data, spiffs, 0x390000,0x070000,
|
||||
app0, app, ota_0, 0x10000, 0x2A0000,
|
||||
spiffs, data, spiffs, 0x2B0000,0x150000,
|
||||
|
@@ -21,6 +21,7 @@ default_envs = tbeam
|
||||
;default_envs = meshtastic-diy-v1
|
||||
;default_envs = meshtastic-diy-v1.1
|
||||
;default_envs = m5stack-coreink
|
||||
;default_envs = rak4631
|
||||
|
||||
extra_configs = variants/*/platformio.ini
|
||||
|
||||
@@ -79,8 +80,6 @@ lib_deps =
|
||||
lib_deps =
|
||||
adafruit/Adafruit BusIO@^1.11.4
|
||||
adafruit/Adafruit Unified Sensor@^1.1.4
|
||||
paulstoffregen/OneWire@^2.3.5
|
||||
robtillaart/DS18B20@^0.1.11
|
||||
adafruit/Adafruit BMP280 Library@^2.6.3
|
||||
adafruit/Adafruit BME280 Library@^2.2.2
|
||||
adafruit/Adafruit BME680 Library@^2.0.1
|
||||
@@ -99,11 +98,10 @@ debug_init_break = tbreak setup
|
||||
# Remove -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL for low level BLE logging.
|
||||
# See library directory for BLE logging possible values: .pio/libdeps/tbeam/NimBLE-Arduino/src/log_common/log_common.h
|
||||
# This overrides the BLE logging default of LOG_LEVEL_INFO (1) from: .pio/libdeps/tbeam/NimBLE-Arduino/src/esp_nimble_cfg.h
|
||||
# -DUSE_NEW_ESP32_BLUETOOTH will enable the new NimBLE C++ api
|
||||
build_flags =
|
||||
${arduino_base.build_flags} -Wall -Wextra -Isrc/platform/esp32 -lnimble -std=c++11
|
||||
-DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL
|
||||
-DAXP_DEBUG_PORT=Serial -DUSE_NEW_ESP32_BLUETOOTH -DCONFIG_BT_NIMBLE_ENABLED -DCONFIG_NIMBLE_CPP_LOG_LEVEL=1
|
||||
-DAXP_DEBUG_PORT=Serial -DCONFIG_BT_NIMBLE_ENABLED -DCONFIG_NIMBLE_CPP_LOG_LEVEL=2 -DCONFIG_BT_NIMBLE_MAX_CCCDS=20
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
@@ -184,4 +182,24 @@ lib_ignore =
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
https://github.com/kokke/tiny-AES-c.git
|
||||
https://github.com/kokke/tiny-AES-c.git
|
||||
|
||||
[stm32wl5e_base]
|
||||
platform = ststm32
|
||||
board = generic_wl5e
|
||||
framework = arduino
|
||||
build_type = debug
|
||||
build_flags =
|
||||
${arduino_base.build_flags}
|
||||
-Isrc/platform/stm32wl -g
|
||||
-DHAL_SUBGHZ_MODULE_ENABLED
|
||||
# Arduino/PlatformIO framework-arduinoststm32 package does not presently have SUBGHZSPI support
|
||||
# -DPIN_SPI_MOSI=PINSUBGHZSPIMOSI -DPIN_SPI_MISO=PINSUBGHZSPIMISO -DPIN_SPI_SCK=PINSUBGHZSPISCK
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<graphics> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040>
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
https://github.com/jgromes/RadioLib.git
|
||||
https://github.com/kokke/tiny-AES-c.git
|
||||
lib_ignore =
|
||||
mathertel/OneButton@^2.0.3
|
||||
|
||||
Submodule protobufs updated: c473ed7a6a...5793089473
@@ -7,10 +7,6 @@
|
||||
#include "power.h"
|
||||
#include <OneButton.h>
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#include "nimble/BluetoothUtil.h"
|
||||
#endif
|
||||
|
||||
namespace concurrency
|
||||
{
|
||||
/**
|
||||
|
||||
@@ -240,6 +240,7 @@ Fsm powerFSM(&stateBOOT);
|
||||
void PowerFSM_setup()
|
||||
{
|
||||
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();
|
||||
|
||||
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
|
||||
// light sleep we _always_ transition to NB or dark and
|
||||
powerFSM.add_transition(&stateLS, isRouter ? &stateNB : &stateDARK, EVENT_PACKET_FOR_PHONE, NULL,
|
||||
"Received packet, exiting light sleep");
|
||||
powerFSM.add_transition(&stateLS, isRouter ? &stateNB : &stateDARK, EVENT_PACKET_FOR_PHONE, NULL, "Received packet, exiting light sleep");
|
||||
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
|
||||
@@ -261,8 +261,7 @@ void PowerFSM_setup()
|
||||
powerFSM.add_transition(&stateDARK, &stateON, EVENT_PRESS, NULL, "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(&stateSERIAL, &stateSERIAL, EVENT_PRESS, screenPress,
|
||||
"Press"); // Allow button to work while in serial API
|
||||
powerFSM.add_transition(&stateSERIAL, &stateSERIAL, EVENT_PRESS, screenPress, "Press"); // Allow button to work while in serial API
|
||||
|
||||
// Handle critically low power battery by forcing deep sleep
|
||||
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(&stateON, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update");
|
||||
|
||||
powerFSM.add_timed_transition(&stateON, &stateDARK,
|
||||
config.display.screen_on_secs ? config.display.screen_on_secs
|
||||
: 60 * 1000 * 10,
|
||||
NULL, "Screen-on timeout");
|
||||
powerFSM.add_timed_transition(&stateON, &stateDARK, screenOnSecs, NULL, "Screen-on timeout");
|
||||
|
||||
// On most boards we use light-sleep to be our main state, but on NRF52 we just stay in DARK
|
||||
State *lowPowerState = &stateLS;
|
||||
@@ -348,17 +344,12 @@ void PowerFSM_setup()
|
||||
|
||||
// See: https://github.com/meshtastic/Meshtastic-device/issues/1071
|
||||
if (isRouter || config.power.is_power_saving) {
|
||||
powerFSM.add_timed_transition(&stateNB, &stateLS,
|
||||
config.power.min_wake_secs ? config.power.min_wake_secs
|
||||
: default_min_wake_secs * 1000,
|
||||
NULL, "Min wake timeout");
|
||||
powerFSM.add_timed_transition(&stateDARK, &stateLS,
|
||||
config.power.wait_bluetooth_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;
|
||||
uint32_t minWakeSecs = config.power.min_wake_secs ? config.power.min_wake_secs : default_min_wake_secs * 1000;
|
||||
uint32_t waitBluetoothSecs = config.power.wait_bluetooth_secs ? config.power.wait_bluetooth_secs : default_wait_bluetooth_secs * 1000;
|
||||
|
||||
powerFSM.add_timed_transition(&stateNB, &stateLS, minWakeSecs, NULL, "Min wake timeout");
|
||||
powerFSM.add_timed_transition(&stateDARK, &stateLS, waitBluetoothSecs, NULL, "Bluetooth timeout");
|
||||
meshSds = config.power.mesh_sds_timeout_secs ? config.power.mesh_sds_timeout_secs : default_mesh_sds_timeout_secs;
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
@@ -38,20 +38,13 @@ size_t RedirectablePrint::write(uint8_t c)
|
||||
size_t RedirectablePrint::vprintf(const char *format, va_list arg)
|
||||
{
|
||||
va_list copy;
|
||||
static char printBuf[160];
|
||||
|
||||
va_copy(copy, arg);
|
||||
int len = vsnprintf(printBuf, printBufLen, format, copy);
|
||||
int len = vsnprintf(printBuf, sizeof(printBuf), format, copy);
|
||||
va_end(copy);
|
||||
if (len < 0) {
|
||||
va_end(arg);
|
||||
return 0;
|
||||
};
|
||||
if (len >= (int)printBufLen) {
|
||||
delete[] printBuf;
|
||||
printBufLen *= 2;
|
||||
printBuf = new char[printBufLen];
|
||||
len = vsnprintf(printBuf, printBufLen, format, arg);
|
||||
}
|
||||
|
||||
if (len < 0) return 0;
|
||||
|
||||
len = Print::write(printBuf, len);
|
||||
return len;
|
||||
|
||||
@@ -12,10 +12,6 @@ class RedirectablePrint : public Print
|
||||
{
|
||||
Print *dest;
|
||||
|
||||
/// We dynamically grow this scratch buffer if necessary
|
||||
char *printBuf = new char[64];
|
||||
size_t printBufLen = 64;
|
||||
|
||||
/// Used to allow multiple logDebug messages to appear on a single log line
|
||||
bool isContinuationMessage = false;
|
||||
|
||||
|
||||
@@ -14,4 +14,5 @@ enum class Cmd {
|
||||
STOP_BOOT_SCREEN,
|
||||
PRINT,
|
||||
START_SHUTDOWN_SCREEN,
|
||||
START_REBOOT_SCREEN,
|
||||
};
|
||||
@@ -81,7 +81,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// #define DISABLE_NTP
|
||||
|
||||
// Disable the welcome screen and allow
|
||||
#define DISABLE_WELCOME_UNSET
|
||||
//#define DISABLE_WELCOME_UNSET
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// OLED & Input
|
||||
|
||||
@@ -228,26 +228,17 @@ static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
// Used when booting without a region set
|
||||
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) {
|
||||
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 * 3 - 3, "Meshtastic Android, iOS,");
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 4 - 3, "Flasher or CLI client.");
|
||||
} 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 * 3 - 3, "for more information.");
|
||||
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->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);
|
||||
char buf[30];
|
||||
const char *name = "Name: ";
|
||||
@@ -317,6 +313,14 @@ static void drawFrameShutdown(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
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)
|
||||
{
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
@@ -329,9 +333,6 @@ static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
} else {
|
||||
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
|
||||
@@ -1042,6 +1043,9 @@ int32_t Screen::runOnce()
|
||||
case Cmd::START_SHUTDOWN_SCREEN:
|
||||
handleShutdownScreen();
|
||||
break;
|
||||
case Cmd::START_REBOOT_SCREEN:
|
||||
handleRebootScreen();
|
||||
break;
|
||||
default:
|
||||
DEBUG_MSG("BUG: invalid cmd\n");
|
||||
}
|
||||
@@ -1234,6 +1238,18 @@ void Screen::handleShutdownScreen()
|
||||
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()
|
||||
{
|
||||
DEBUG_MSG("showing firmware screen\n");
|
||||
|
||||
@@ -20,6 +20,7 @@ class Screen
|
||||
void forceDisplay() {}
|
||||
void startBluetoothPinScreen(uint32_t pin) {}
|
||||
void stopBluetoothPinScreen() {}
|
||||
void startRebootScreen() {}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -167,6 +168,13 @@ class Screen : public concurrency::OSThread
|
||||
enqueueCmd(cmd);
|
||||
}
|
||||
|
||||
void startRebootScreen()
|
||||
{
|
||||
ScreenCmd cmd;
|
||||
cmd.cmd = Cmd::START_REBOOT_SCREEN;
|
||||
enqueueCmd(cmd);
|
||||
}
|
||||
|
||||
/// Stops showing the 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 handleStartFirmwareUpdateScreen();
|
||||
void handleShutdownScreen();
|
||||
void handleRebootScreen();
|
||||
/// Rebuilds our list of frames (screens) to default ones.
|
||||
void setFrames();
|
||||
|
||||
|
||||
@@ -33,13 +33,7 @@
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#include "mesh/http/WebServer.h"
|
||||
|
||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
||||
#include "platform/esp32/ESP32Bluetooth.h"
|
||||
#else
|
||||
#include "nimble/BluetoothUtil.h"
|
||||
#endif
|
||||
|
||||
#include "nimble/NimbleBluetooth.h"
|
||||
#endif
|
||||
|
||||
#if HAS_WIFI
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
#include "modules/PositionModule.h"
|
||||
#include "power.h"
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#include "nimble/NimbleBluetooth.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
receivedPacketQueue - this is a queue of messages we've received from the mesh, which we are keeping to deliver to the phone.
|
||||
It is implemented with a FreeRTos queue (wrapped with a little RTQueue class) of pointers to MeshPacket protobufs (which were
|
||||
|
||||
@@ -150,14 +150,18 @@ void NodeDB::installDefaultConfig()
|
||||
config.has_position = true;
|
||||
config.has_power = true;
|
||||
config.has_wifi = true;
|
||||
config.has_bluetooth = true;
|
||||
|
||||
config.lora.region = Config_LoRaConfig_RegionCode_Unset;
|
||||
config.lora.modem_preset = Config_LoRaConfig_ModemPreset_LongFast;
|
||||
resetRadioConfig();
|
||||
strncpy(config.device.ntp_server, "0.pool.ntp.org", 32);
|
||||
// FIXME: Default to bluetooth capability of platform as default
|
||||
config.bluetooth.enabled = true;
|
||||
config.bluetooth.fixed_pin = defaultBLEPin;
|
||||
config.bluetooth.mode = screen_found ? Config_BluetoothConfig_PairingMode_RandomPin : Config_BluetoothConfig_PairingMode_FixedPin;
|
||||
// for backward compat, default position flags are ALT+MSL
|
||||
config.position.position_flags =
|
||||
(Config_PositionConfig_PositionFlags_POS_ALTITUDE | Config_PositionConfig_PositionFlags_POS_ALT_MSL);
|
||||
config.position.position_flags = (Config_PositionConfig_PositionFlags_POS_ALTITUDE | Config_PositionConfig_PositionFlags_POS_ALT_MSL);
|
||||
}
|
||||
|
||||
void NodeDB::installDefaultModuleConfig()
|
||||
@@ -452,6 +456,7 @@ void NodeDB::saveToDisk()
|
||||
config.has_position = true;
|
||||
config.has_power = true;
|
||||
config.has_wifi = true;
|
||||
config.has_bluetooth = true;
|
||||
saveProto(configFileName, LocalConfig_size, sizeof(LocalConfig), LocalConfig_fields, &config);
|
||||
|
||||
moduleConfig.has_canned_message = true;
|
||||
|
||||
@@ -13,7 +13,7 @@ DeviceState versions used to be defined in the .proto file but really only this
|
||||
#define here.
|
||||
*/
|
||||
|
||||
#define DEVICESTATE_CUR_VER 14
|
||||
#define DEVICESTATE_CUR_VER 15
|
||||
#define DEVICESTATE_MIN_VER DEVICESTATE_CUR_VER
|
||||
|
||||
extern DeviceState devicestate;
|
||||
@@ -179,12 +179,11 @@ extern NodeDB nodeDB;
|
||||
#define default_sds_secs 365 * 24 * 60 * 60
|
||||
#define default_ls_secs IF_ROUTER(24 * 60 * 60, 5 * 60)
|
||||
#define default_min_wake_secs 10
|
||||
|
||||
#define default_screen_on_secs 60 * 1000 * 10
|
||||
|
||||
inline uint32_t getIntervalOrDefaultMs(uint32_t interval)
|
||||
{
|
||||
if (interval > 0)
|
||||
return interval * 1000;
|
||||
if (interval > 0) return interval * 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)
|
||||
{
|
||||
DEBUG_MSG("getFromRadio, state=%d\n", state);
|
||||
if (!available()) {
|
||||
// DEBUG_MSG("getFromRadio, !available\n");
|
||||
// DEBUG_MSG("PhoneAPI::getFromRadio, !available\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEBUG_MSG("getFromRadio, state=%d\n", state);
|
||||
|
||||
// In case we send a FromRadio packet
|
||||
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
|
||||
|
||||
@@ -189,15 +187,18 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
||||
fromRadioScratch.config.which_payloadVariant = Config_lora_tag;
|
||||
fromRadioScratch.config.payloadVariant.lora = config.lora;
|
||||
break;
|
||||
case Config_bluetooth_tag:
|
||||
fromRadioScratch.config.which_payloadVariant = Config_bluetooth_tag;
|
||||
fromRadioScratch.config.payloadVariant.bluetooth = config.bluetooth;
|
||||
break;
|
||||
}
|
||||
|
||||
// NOTE: The phone app needs to know the ls_secs value so it can properly expect sleep behavior.
|
||||
// So even if we internally use 0 to represent 'use default' we still need to send the value we are
|
||||
// using to the app (so that even old phone apps work with new device loads).
|
||||
|
||||
config_state++;
|
||||
// Advance when we have sent all of our config objects
|
||||
if (config_state > Config_lora_tag) {
|
||||
if (config_state > Config_bluetooth_tag) {
|
||||
state = STATE_SEND_MODULECONFIG;
|
||||
config_state = ModuleConfig_mqtt_tag;
|
||||
}
|
||||
@@ -275,7 +276,10 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PhoneAPI::handleDisconnect() {}
|
||||
void PhoneAPI::handleDisconnect()
|
||||
{
|
||||
DEBUG_MSG("PhoneAPI disconnect\n");
|
||||
}
|
||||
|
||||
void PhoneAPI::releasePhonePacket()
|
||||
{
|
||||
@@ -291,35 +295,28 @@ void PhoneAPI::releasePhonePacket()
|
||||
bool PhoneAPI::available()
|
||||
{
|
||||
switch (state) {
|
||||
case STATE_SEND_NOTHING:
|
||||
return false;
|
||||
|
||||
case STATE_SEND_MY_INFO:
|
||||
return true;
|
||||
|
||||
case STATE_SEND_CONFIG:
|
||||
return true;
|
||||
|
||||
case STATE_SEND_MODULECONFIG:
|
||||
return true;
|
||||
|
||||
case STATE_SEND_NODEINFO:
|
||||
if (!nodeInfoForPhone)
|
||||
nodeInfoForPhone = nodeDB.readNextInfo();
|
||||
return true; // Always say we have something, because we might need to advance our state machine
|
||||
|
||||
case STATE_SEND_COMPLETE_ID:
|
||||
return true;
|
||||
|
||||
case STATE_SEND_PACKETS: {
|
||||
// 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;
|
||||
case STATE_SEND_NOTHING:
|
||||
return false;
|
||||
case STATE_SEND_MY_INFO:
|
||||
return true;
|
||||
case STATE_SEND_CONFIG:
|
||||
return true;
|
||||
case STATE_SEND_MODULECONFIG:
|
||||
return true;
|
||||
case STATE_SEND_NODEINFO:
|
||||
if (!nodeInfoForPhone)
|
||||
nodeInfoForPhone = nodeDB.readNextInfo();
|
||||
return true; // Always say we have something, because we might need to advance our state machine
|
||||
case STATE_SEND_COMPLETE_ID:
|
||||
return true;
|
||||
case STATE_SEND_PACKETS: {
|
||||
// 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:
|
||||
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
|
||||
// Unregisters our observer. A closed connection **can** be reopened by calling init again.
|
||||
virtual void close();
|
||||
|
||||
|
||||
/**
|
||||
* Handle a ToRadio protobuf
|
||||
* @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; }
|
||||
|
||||
void setInitialState() { state = STATE_SEND_MY_INFO; }
|
||||
|
||||
/// emit a debugging log character, FIXME - implement
|
||||
void debugOut(char c) { }
|
||||
|
||||
|
||||
@@ -43,6 +43,10 @@ RadioLibInterface::RadioLibInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq
|
||||
: NotifiedWorkerThread("RadioIf"), module(cs, irq, rst, busy, spi, spiSettings), iface(_iface)
|
||||
{
|
||||
instance = this;
|
||||
#if defined(ARCH_STM32WL) && defined(USE_SX1262)
|
||||
module.setCb_digitalWrite(stm32wl_emulate_digitalWrite);
|
||||
module.setCb_digitalRead(stm32wl_emulate_digitalRead);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
|
||||
@@ -67,6 +67,12 @@ bool ReliableRouter::shouldFilterReceived(MeshPacket *p)
|
||||
sendAckNak(Routing_Error_NONE, getFrom(p), p->id, p->channel);
|
||||
DEBUG_MSG("acking a repeated want_ack packet\n");
|
||||
}
|
||||
} else if (wasSeenRecently(p, false) && p->hop_limit == HOP_RELIABLE) {
|
||||
// retransmission on broadcast has hop_limit still equal to HOP_RELIABLE
|
||||
DEBUG_MSG("Resending implicit ack for a repeated floodmsg\n");
|
||||
MeshPacket *tosend = packetPool.allocCopy(*p);
|
||||
tosend->hop_limit--; // bump down the hop count
|
||||
Router::send(tosend);
|
||||
}
|
||||
|
||||
return FloodingRouter::shouldFilterReceived(p);
|
||||
@@ -106,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
|
||||
if (ackId || nakId) {
|
||||
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);
|
||||
} else {
|
||||
DEBUG_MSG("Received a nak for 0x%x, stopping retransmissions\n", nakId);
|
||||
|
||||
@@ -21,7 +21,8 @@ typedef enum _AdminMessage_ConfigType {
|
||||
AdminMessage_ConfigType_POWER_CONFIG = 2,
|
||||
AdminMessage_ConfigType_WIFI_CONFIG = 3,
|
||||
AdminMessage_ConfigType_DISPLAY_CONFIG = 4,
|
||||
AdminMessage_ConfigType_LORA_CONFIG = 5
|
||||
AdminMessage_ConfigType_LORA_CONFIG = 5,
|
||||
AdminMessage_ConfigType_BLUETOOTH_CONFIG = 6
|
||||
} AdminMessage_ConfigType;
|
||||
|
||||
typedef enum _AdminMessage_ModuleConfigType {
|
||||
@@ -88,30 +89,12 @@ typedef struct _AdminMessage {
|
||||
bool exit_simulator;
|
||||
/* Tell the node to reboot in this many seconds (or <0 to cancel reboot) */
|
||||
int32_t reboot_seconds;
|
||||
/* Get the Canned Message Module message part1 in the response to this message. */
|
||||
bool get_canned_message_module_part1_request;
|
||||
/* TODO: REPLACE */
|
||||
char get_canned_message_module_part1_response[201];
|
||||
/* Get the Canned Message Module message part2 in the response to this message. */
|
||||
bool get_canned_message_module_part2_request;
|
||||
/* TODO: REPLACE */
|
||||
char get_canned_message_module_part2_response[201];
|
||||
/* Get the Canned Message Module message part3 in the response to this message. */
|
||||
bool get_canned_message_module_part3_request;
|
||||
/* TODO: REPLACE */
|
||||
char get_canned_message_module_part3_response[201];
|
||||
/* Get the Canned Message Module message part4 in the response to this message. */
|
||||
bool get_canned_message_module_part4_request;
|
||||
/* TODO: REPLACE */
|
||||
char get_canned_message_module_part4_response[201];
|
||||
/* Set the canned message module part 1 text. */
|
||||
char set_canned_message_module_part1[201];
|
||||
/* Set the canned message module part 2 text. */
|
||||
char set_canned_message_module_part2[201];
|
||||
/* Set the canned message module part 3 text. */
|
||||
char set_canned_message_module_part3[201];
|
||||
/* Set the canned message module part 4 text. */
|
||||
char set_canned_message_module_part4[201];
|
||||
/* Get the Canned Message Module messages in the response to this message. */
|
||||
bool get_canned_message_module_messages_request;
|
||||
/* Get the Canned Message Module messages in the response to this message. */
|
||||
char get_canned_message_module_messages_response[201];
|
||||
/* Set the Canned Message Module messages text. */
|
||||
char set_canned_message_module_messages[201];
|
||||
/* Tell the node to shutdown in this many seconds (or <0 to cancel shutdown) */
|
||||
int32_t shutdown_seconds;
|
||||
/* Request the node to send device metadata (firmware, protobuf version, etc) */
|
||||
@@ -124,8 +107,8 @@ typedef struct _AdminMessage {
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _AdminMessage_ConfigType_MIN AdminMessage_ConfigType_DEVICE_CONFIG
|
||||
#define _AdminMessage_ConfigType_MAX AdminMessage_ConfigType_LORA_CONFIG
|
||||
#define _AdminMessage_ConfigType_ARRAYSIZE ((AdminMessage_ConfigType)(AdminMessage_ConfigType_LORA_CONFIG+1))
|
||||
#define _AdminMessage_ConfigType_MAX AdminMessage_ConfigType_BLUETOOTH_CONFIG
|
||||
#define _AdminMessage_ConfigType_ARRAYSIZE ((AdminMessage_ConfigType)(AdminMessage_ConfigType_BLUETOOTH_CONFIG+1))
|
||||
|
||||
#define _AdminMessage_ModuleConfigType_MIN AdminMessage_ModuleConfigType_MQTT_CONFIG
|
||||
#define _AdminMessage_ModuleConfigType_MAX AdminMessage_ModuleConfigType_CANNEDMSG_CONFIG
|
||||
@@ -160,18 +143,9 @@ extern "C" {
|
||||
#define AdminMessage_confirm_set_radio_tag 33
|
||||
#define AdminMessage_exit_simulator_tag 34
|
||||
#define AdminMessage_reboot_seconds_tag 35
|
||||
#define AdminMessage_get_canned_message_module_part1_request_tag 36
|
||||
#define AdminMessage_get_canned_message_module_part1_response_tag 37
|
||||
#define AdminMessage_get_canned_message_module_part2_request_tag 38
|
||||
#define AdminMessage_get_canned_message_module_part2_response_tag 39
|
||||
#define AdminMessage_get_canned_message_module_part3_request_tag 40
|
||||
#define AdminMessage_get_canned_message_module_part3_response_tag 41
|
||||
#define AdminMessage_get_canned_message_module_part4_request_tag 42
|
||||
#define AdminMessage_get_canned_message_module_part4_response_tag 43
|
||||
#define AdminMessage_set_canned_message_module_part1_tag 44
|
||||
#define AdminMessage_set_canned_message_module_part2_tag 45
|
||||
#define AdminMessage_set_canned_message_module_part3_tag 46
|
||||
#define AdminMessage_set_canned_message_module_part4_tag 47
|
||||
#define AdminMessage_get_canned_message_module_messages_request_tag 36
|
||||
#define AdminMessage_get_canned_message_module_messages_response_tag 37
|
||||
#define AdminMessage_set_canned_message_module_messages_tag 44
|
||||
#define AdminMessage_shutdown_seconds_tag 51
|
||||
#define AdminMessage_get_device_metadata_request_tag 52
|
||||
#define AdminMessage_get_device_metadata_response_tag 53
|
||||
@@ -197,18 +171,9 @@ X(a, STATIC, ONEOF, BOOL, (variant,confirm_set_channel,confirm_set_chan
|
||||
X(a, STATIC, ONEOF, BOOL, (variant,confirm_set_radio,confirm_set_radio), 33) \
|
||||
X(a, STATIC, ONEOF, BOOL, (variant,exit_simulator,exit_simulator), 34) \
|
||||
X(a, STATIC, ONEOF, INT32, (variant,reboot_seconds,reboot_seconds), 35) \
|
||||
X(a, STATIC, ONEOF, BOOL, (variant,get_canned_message_module_part1_request,get_canned_message_module_part1_request), 36) \
|
||||
X(a, STATIC, ONEOF, STRING, (variant,get_canned_message_module_part1_response,get_canned_message_module_part1_response), 37) \
|
||||
X(a, STATIC, ONEOF, BOOL, (variant,get_canned_message_module_part2_request,get_canned_message_module_part2_request), 38) \
|
||||
X(a, STATIC, ONEOF, STRING, (variant,get_canned_message_module_part2_response,get_canned_message_module_part2_response), 39) \
|
||||
X(a, STATIC, ONEOF, BOOL, (variant,get_canned_message_module_part3_request,get_canned_message_module_part3_request), 40) \
|
||||
X(a, STATIC, ONEOF, STRING, (variant,get_canned_message_module_part3_response,get_canned_message_module_part3_response), 41) \
|
||||
X(a, STATIC, ONEOF, BOOL, (variant,get_canned_message_module_part4_request,get_canned_message_module_part4_request), 42) \
|
||||
X(a, STATIC, ONEOF, STRING, (variant,get_canned_message_module_part4_response,get_canned_message_module_part4_response), 43) \
|
||||
X(a, STATIC, ONEOF, STRING, (variant,set_canned_message_module_part1,set_canned_message_module_part1), 44) \
|
||||
X(a, STATIC, ONEOF, STRING, (variant,set_canned_message_module_part2,set_canned_message_module_part2), 45) \
|
||||
X(a, STATIC, ONEOF, STRING, (variant,set_canned_message_module_part3,set_canned_message_module_part3), 46) \
|
||||
X(a, STATIC, ONEOF, STRING, (variant,set_canned_message_module_part4,set_canned_message_module_part4), 47) \
|
||||
X(a, STATIC, ONEOF, BOOL, (variant,get_canned_message_module_messages_request,get_canned_message_module_messages_request), 36) \
|
||||
X(a, STATIC, ONEOF, STRING, (variant,get_canned_message_module_messages_response,get_canned_message_module_messages_response), 37) \
|
||||
X(a, STATIC, ONEOF, STRING, (variant,set_canned_message_module_messages,set_canned_message_module_messages), 44) \
|
||||
X(a, STATIC, ONEOF, INT32, (variant,shutdown_seconds,shutdown_seconds), 51) \
|
||||
X(a, STATIC, ONEOF, UINT32, (variant,get_device_metadata_request,get_device_metadata_request), 52) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,get_device_metadata_response,get_device_metadata_response), 53)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(CannedMessageModuleConfig, CannedMessageModuleConfig, 2)
|
||||
PB_BIND(CannedMessageModuleConfig, CannedMessageModuleConfig, AUTO)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -13,13 +13,7 @@
|
||||
/* Canned message module configuration. */
|
||||
typedef struct _CannedMessageModuleConfig {
|
||||
/* Predefined messages for canned message module separated by '|' characters. */
|
||||
char messagesPart1[201];
|
||||
/* TODO: REPLACE */
|
||||
char messagesPart2[201];
|
||||
/* TODO: REPLACE */
|
||||
char messagesPart3[201];
|
||||
/* TODO: REPLACE */
|
||||
char messagesPart4[201];
|
||||
char messages[201];
|
||||
} CannedMessageModuleConfig;
|
||||
|
||||
|
||||
@@ -28,21 +22,15 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define CannedMessageModuleConfig_init_default {"", "", "", ""}
|
||||
#define CannedMessageModuleConfig_init_zero {"", "", "", ""}
|
||||
#define CannedMessageModuleConfig_init_default {""}
|
||||
#define CannedMessageModuleConfig_init_zero {""}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define CannedMessageModuleConfig_messagesPart1_tag 11
|
||||
#define CannedMessageModuleConfig_messagesPart2_tag 12
|
||||
#define CannedMessageModuleConfig_messagesPart3_tag 13
|
||||
#define CannedMessageModuleConfig_messagesPart4_tag 14
|
||||
#define CannedMessageModuleConfig_messages_tag 1
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define CannedMessageModuleConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, STRING, messagesPart1, 11) \
|
||||
X(a, STATIC, SINGULAR, STRING, messagesPart2, 12) \
|
||||
X(a, STATIC, SINGULAR, STRING, messagesPart3, 13) \
|
||||
X(a, STATIC, SINGULAR, STRING, messagesPart4, 14)
|
||||
X(a, STATIC, SINGULAR, STRING, messages, 1)
|
||||
#define CannedMessageModuleConfig_CALLBACK NULL
|
||||
#define CannedMessageModuleConfig_DEFAULT NULL
|
||||
|
||||
@@ -52,7 +40,7 @@ extern const pb_msgdesc_t CannedMessageModuleConfig_msg;
|
||||
#define CannedMessageModuleConfig_fields &CannedMessageModuleConfig_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define CannedMessageModuleConfig_size 812
|
||||
#define CannedMessageModuleConfig_size 203
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -27,6 +27,10 @@ PB_BIND(Config_DisplayConfig, Config_DisplayConfig, AUTO)
|
||||
PB_BIND(Config_LoRaConfig, Config_LoRaConfig, 2)
|
||||
|
||||
|
||||
PB_BIND(Config_BluetoothConfig, Config_BluetoothConfig, AUTO)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -92,7 +92,19 @@ typedef enum _Config_LoRaConfig_ModemPreset {
|
||||
Config_LoRaConfig_ModemPreset_ShortFast = 6
|
||||
} Config_LoRaConfig_ModemPreset;
|
||||
|
||||
typedef enum _Config_BluetoothConfig_PairingMode {
|
||||
Config_BluetoothConfig_PairingMode_RandomPin = 0,
|
||||
Config_BluetoothConfig_PairingMode_FixedPin = 1,
|
||||
Config_BluetoothConfig_PairingMode_NoPin = 2
|
||||
} Config_BluetoothConfig_PairingMode;
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _Config_BluetoothConfig {
|
||||
bool enabled;
|
||||
Config_BluetoothConfig_PairingMode mode;
|
||||
uint32_t fixed_pin;
|
||||
} Config_BluetoothConfig;
|
||||
|
||||
typedef struct _Config_DeviceConfig {
|
||||
Config_DeviceConfig_Role role;
|
||||
bool serial_disabled;
|
||||
@@ -160,6 +172,7 @@ typedef struct _Config {
|
||||
Config_WiFiConfig wifi;
|
||||
Config_DisplayConfig display;
|
||||
Config_LoRaConfig lora;
|
||||
Config_BluetoothConfig bluetooth;
|
||||
} payloadVariant;
|
||||
} Config;
|
||||
|
||||
@@ -193,6 +206,10 @@ typedef struct _Config {
|
||||
#define _Config_LoRaConfig_ModemPreset_MAX Config_LoRaConfig_ModemPreset_ShortFast
|
||||
#define _Config_LoRaConfig_ModemPreset_ARRAYSIZE ((Config_LoRaConfig_ModemPreset)(Config_LoRaConfig_ModemPreset_ShortFast+1))
|
||||
|
||||
#define _Config_BluetoothConfig_PairingMode_MIN Config_BluetoothConfig_PairingMode_RandomPin
|
||||
#define _Config_BluetoothConfig_PairingMode_MAX Config_BluetoothConfig_PairingMode_NoPin
|
||||
#define _Config_BluetoothConfig_PairingMode_ARRAYSIZE ((Config_BluetoothConfig_PairingMode)(Config_BluetoothConfig_PairingMode_NoPin+1))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -206,6 +223,7 @@ extern "C" {
|
||||
#define Config_WiFiConfig_init_default {0, _Config_WiFiConfig_WiFiMode_MIN, "", ""}
|
||||
#define Config_DisplayConfig_init_default {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0}
|
||||
#define Config_LoRaConfig_init_default {0, _Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, {0, 0, 0}}
|
||||
#define Config_BluetoothConfig_init_default {0, _Config_BluetoothConfig_PairingMode_MIN, 0}
|
||||
#define Config_init_zero {0, {Config_DeviceConfig_init_zero}}
|
||||
#define Config_DeviceConfig_init_zero {_Config_DeviceConfig_Role_MIN, 0, 0, 0, ""}
|
||||
#define Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0}
|
||||
@@ -213,8 +231,12 @@ extern "C" {
|
||||
#define Config_WiFiConfig_init_zero {0, _Config_WiFiConfig_WiFiMode_MIN, "", ""}
|
||||
#define Config_DisplayConfig_init_zero {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0}
|
||||
#define Config_LoRaConfig_init_zero {0, _Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, {0, 0, 0}}
|
||||
#define Config_BluetoothConfig_init_zero {0, _Config_BluetoothConfig_PairingMode_MIN, 0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define Config_BluetoothConfig_enabled_tag 1
|
||||
#define Config_BluetoothConfig_mode_tag 2
|
||||
#define Config_BluetoothConfig_fixed_pin_tag 3
|
||||
#define Config_DeviceConfig_role_tag 1
|
||||
#define Config_DeviceConfig_serial_disabled_tag 2
|
||||
#define Config_DeviceConfig_factory_reset_tag 3
|
||||
@@ -260,6 +282,7 @@ extern "C" {
|
||||
#define Config_wifi_tag 4
|
||||
#define Config_display_tag 5
|
||||
#define Config_lora_tag 6
|
||||
#define Config_bluetooth_tag 7
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define Config_FIELDLIST(X, a) \
|
||||
@@ -268,7 +291,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,position,payloadVariant.posit
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,power,payloadVariant.power), 3) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,wifi,payloadVariant.wifi), 4) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,display,payloadVariant.display), 5) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,lora,payloadVariant.lora), 6)
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,lora,payloadVariant.lora), 6) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,bluetooth,payloadVariant.bluetooth), 7)
|
||||
#define Config_CALLBACK NULL
|
||||
#define Config_DEFAULT NULL
|
||||
#define Config_payloadVariant_device_MSGTYPE Config_DeviceConfig
|
||||
@@ -277,6 +301,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,lora,payloadVariant.lora),
|
||||
#define Config_payloadVariant_wifi_MSGTYPE Config_WiFiConfig
|
||||
#define Config_payloadVariant_display_MSGTYPE Config_DisplayConfig
|
||||
#define Config_payloadVariant_lora_MSGTYPE Config_LoRaConfig
|
||||
#define Config_payloadVariant_bluetooth_MSGTYPE Config_BluetoothConfig
|
||||
|
||||
#define Config_DeviceConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UENUM, role, 1) \
|
||||
@@ -341,6 +366,13 @@ X(a, STATIC, REPEATED, UINT32, ignore_incoming, 103)
|
||||
#define Config_LoRaConfig_CALLBACK NULL
|
||||
#define Config_LoRaConfig_DEFAULT NULL
|
||||
|
||||
#define Config_BluetoothConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
|
||||
X(a, STATIC, SINGULAR, UENUM, mode, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, fixed_pin, 3)
|
||||
#define Config_BluetoothConfig_CALLBACK NULL
|
||||
#define Config_BluetoothConfig_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t Config_msg;
|
||||
extern const pb_msgdesc_t Config_DeviceConfig_msg;
|
||||
extern const pb_msgdesc_t Config_PositionConfig_msg;
|
||||
@@ -348,6 +380,7 @@ extern const pb_msgdesc_t Config_PowerConfig_msg;
|
||||
extern const pb_msgdesc_t Config_WiFiConfig_msg;
|
||||
extern const pb_msgdesc_t Config_DisplayConfig_msg;
|
||||
extern const pb_msgdesc_t Config_LoRaConfig_msg;
|
||||
extern const pb_msgdesc_t Config_BluetoothConfig_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define Config_fields &Config_msg
|
||||
@@ -357,8 +390,10 @@ extern const pb_msgdesc_t Config_LoRaConfig_msg;
|
||||
#define Config_WiFiConfig_fields &Config_WiFiConfig_msg
|
||||
#define Config_DisplayConfig_fields &Config_DisplayConfig_msg
|
||||
#define Config_LoRaConfig_fields &Config_LoRaConfig_msg
|
||||
#define Config_BluetoothConfig_fields &Config_BluetoothConfig_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define Config_BluetoothConfig_size 10
|
||||
#define Config_DeviceConfig_size 42
|
||||
#define Config_DisplayConfig_size 16
|
||||
#define Config_LoRaConfig_size 67
|
||||
|
||||
@@ -165,7 +165,7 @@ extern const pb_msgdesc_t OEMStore_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define ChannelFile_size 630
|
||||
#define DeviceState_size 23994
|
||||
#define DeviceState_size 22218
|
||||
#define OEMStore_size 2106
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -31,6 +31,9 @@ typedef struct _LocalConfig {
|
||||
/* The part of the config that is specific to the Lora Radio */
|
||||
bool has_lora;
|
||||
Config_LoRaConfig lora;
|
||||
/* The part of the config that is specific to the Bluetooth settings */
|
||||
bool has_bluetooth;
|
||||
Config_BluetoothConfig bluetooth;
|
||||
/* A version integer used to invalidate old save files when we make
|
||||
incompatible changes This integer is set at build time and is private to
|
||||
NodeDB.cpp in the device code. */
|
||||
@@ -71,9 +74,9 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define LocalConfig_init_default {false, Config_DeviceConfig_init_default, false, Config_PositionConfig_init_default, false, Config_PowerConfig_init_default, false, Config_WiFiConfig_init_default, false, Config_DisplayConfig_init_default, false, Config_LoRaConfig_init_default, 0}
|
||||
#define LocalConfig_init_default {false, Config_DeviceConfig_init_default, false, Config_PositionConfig_init_default, false, Config_PowerConfig_init_default, false, Config_WiFiConfig_init_default, false, Config_DisplayConfig_init_default, false, Config_LoRaConfig_init_default, false, Config_BluetoothConfig_init_default, 0}
|
||||
#define LocalModuleConfig_init_default {false, ModuleConfig_MQTTConfig_init_default, false, ModuleConfig_SerialConfig_init_default, false, ModuleConfig_ExternalNotificationConfig_init_default, false, ModuleConfig_StoreForwardConfig_init_default, false, ModuleConfig_RangeTestConfig_init_default, false, ModuleConfig_TelemetryConfig_init_default, false, ModuleConfig_CannedMessageConfig_init_default, 0}
|
||||
#define LocalConfig_init_zero {false, Config_DeviceConfig_init_zero, false, Config_PositionConfig_init_zero, false, Config_PowerConfig_init_zero, false, Config_WiFiConfig_init_zero, false, Config_DisplayConfig_init_zero, false, Config_LoRaConfig_init_zero, 0}
|
||||
#define LocalConfig_init_zero {false, Config_DeviceConfig_init_zero, false, Config_PositionConfig_init_zero, false, Config_PowerConfig_init_zero, false, Config_WiFiConfig_init_zero, false, Config_DisplayConfig_init_zero, false, Config_LoRaConfig_init_zero, false, Config_BluetoothConfig_init_zero, 0}
|
||||
#define LocalModuleConfig_init_zero {false, ModuleConfig_MQTTConfig_init_zero, false, ModuleConfig_SerialConfig_init_zero, false, ModuleConfig_ExternalNotificationConfig_init_zero, false, ModuleConfig_StoreForwardConfig_init_zero, false, ModuleConfig_RangeTestConfig_init_zero, false, ModuleConfig_TelemetryConfig_init_zero, false, ModuleConfig_CannedMessageConfig_init_zero, 0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
@@ -83,7 +86,8 @@ extern "C" {
|
||||
#define LocalConfig_wifi_tag 4
|
||||
#define LocalConfig_display_tag 5
|
||||
#define LocalConfig_lora_tag 6
|
||||
#define LocalConfig_version_tag 7
|
||||
#define LocalConfig_bluetooth_tag 7
|
||||
#define LocalConfig_version_tag 8
|
||||
#define LocalModuleConfig_mqtt_tag 1
|
||||
#define LocalModuleConfig_serial_tag 2
|
||||
#define LocalModuleConfig_external_notification_tag 3
|
||||
@@ -101,7 +105,8 @@ X(a, STATIC, OPTIONAL, MESSAGE, power, 3) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, wifi, 4) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, display, 5) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, lora, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, version, 7)
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, bluetooth, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, version, 8)
|
||||
#define LocalConfig_CALLBACK NULL
|
||||
#define LocalConfig_DEFAULT NULL
|
||||
#define LocalConfig_device_MSGTYPE Config_DeviceConfig
|
||||
@@ -110,6 +115,7 @@ X(a, STATIC, SINGULAR, UINT32, version, 7)
|
||||
#define LocalConfig_wifi_MSGTYPE Config_WiFiConfig
|
||||
#define LocalConfig_display_MSGTYPE Config_DisplayConfig
|
||||
#define LocalConfig_lora_MSGTYPE Config_LoRaConfig
|
||||
#define LocalConfig_bluetooth_MSGTYPE Config_BluetoothConfig
|
||||
|
||||
#define LocalModuleConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, mqtt, 1) \
|
||||
@@ -138,7 +144,7 @@ extern const pb_msgdesc_t LocalModuleConfig_msg;
|
||||
#define LocalModuleConfig_fields &LocalModuleConfig_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define LocalConfig_size 321
|
||||
#define LocalConfig_size 333
|
||||
#define LocalModuleConfig_size 268
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -21,7 +21,7 @@ PB_BIND(Routing, Routing, AUTO)
|
||||
PB_BIND(Data, Data, 2)
|
||||
|
||||
|
||||
PB_BIND(Location, Location, AUTO)
|
||||
PB_BIND(Waypoint, Waypoint, AUTO)
|
||||
|
||||
|
||||
PB_BIND(MeshPacket, MeshPacket, 2)
|
||||
|
||||
@@ -245,24 +245,38 @@ typedef struct _Compressed {
|
||||
Compressed_data_t data;
|
||||
} Compressed;
|
||||
|
||||
/* Location of a waypoint to associate with a message */
|
||||
typedef struct _Location {
|
||||
/* Id of the location */
|
||||
uint32_t id;
|
||||
/* latitude_i */
|
||||
int32_t latitude_i;
|
||||
/* longitude_i */
|
||||
int32_t longitude_i;
|
||||
/* Time the location is to expire (epoch) */
|
||||
uint32_t expire;
|
||||
/* If true, only allow the original sender to update the location. */
|
||||
bool locked;
|
||||
/* Name of the location - max 30 chars */
|
||||
char name[30];
|
||||
/* *
|
||||
Description of the location - max 100 chars */
|
||||
char description[100];
|
||||
} Location;
|
||||
typedef PB_BYTES_ARRAY_T(237) Data_payload_t;
|
||||
/* (Formerly called SubPacket)
|
||||
The payload portion fo a packet, this is the actual bytes that are sent
|
||||
inside a radio packet (because from/to are broken out by the comms library) */
|
||||
typedef struct _Data {
|
||||
/* Formerly named typ and of type Type */
|
||||
PortNum portnum;
|
||||
/* TODO: REPLACE */
|
||||
Data_payload_t payload;
|
||||
/* Not normally used, but for testing a sender can request that recipient
|
||||
responds in kind (i.e. if it received a position, it should unicast back it's position).
|
||||
Note: that if you set this on a broadcast you will receive many replies. */
|
||||
bool want_response;
|
||||
/* The address of the destination node.
|
||||
This field is is filled in by the mesh radio device software, application
|
||||
layer software should never need it.
|
||||
RouteDiscovery messages _must_ populate this.
|
||||
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.
|
||||
To minimize the size of records inside the device code, if a time/source/level is not set
|
||||
@@ -459,104 +473,26 @@ typedef struct _User {
|
||||
If this user is a licensed operator, set this flag.
|
||||
Also, "long_name" should be their licence number. */
|
||||
bool is_licensed;
|
||||
/* Transmit power at antenna connector, in decibel-milliwatt
|
||||
An optional self-reported value useful in network planning, discovery
|
||||
and positioning - along with ant_gain_dbi and ant_azimuth below */
|
||||
uint32_t tx_power_dbm;
|
||||
/* Antenna gain (applicable to both Tx and Rx), in decibel-isotropic */
|
||||
uint32_t ant_gain_dbi;
|
||||
/* Directional antenna true azimuth *if applicable*, in degrees (0-360)
|
||||
Only applicable in case of stationary nodes with a directional antenna
|
||||
Zero = not applicable (mobile or omni) or not specified
|
||||
(use a value of 360 to indicate an antenna azimuth of zero degrees) */
|
||||
uint32_t ant_azimuth;
|
||||
} User;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(237) Data_payload_t;
|
||||
/* (Formerly called SubPacket)
|
||||
The payload portion fo a packet, this is the actual bytes that are sent
|
||||
inside a radio packet (because from/to are broken out by the comms library) */
|
||||
typedef struct _Data {
|
||||
/* Formerly named typ and of type Type */
|
||||
PortNum portnum;
|
||||
/* TODO: REPLACE */
|
||||
Data_payload_t payload;
|
||||
/* Not normally used, but for testing a sender can request that recipient
|
||||
responds in kind (i.e. if it received a position, it should unicast back it's position).
|
||||
Note: that if you set this on a broadcast you will receive many replies. */
|
||||
bool want_response;
|
||||
/* The address of the destination node.
|
||||
This field is is filled in by the mesh radio device software, application
|
||||
layer software should never need it.
|
||||
RouteDiscovery messages _must_ populate this.
|
||||
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;
|
||||
/* 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;
|
||||
/* Waypoint message, used to share arbitrary locations across the mesh */
|
||||
typedef struct _Waypoint {
|
||||
/* Id of the waypoint */
|
||||
uint32_t id;
|
||||
/* latitude_i */
|
||||
int32_t latitude_i;
|
||||
/* longitude_i */
|
||||
int32_t longitude_i;
|
||||
/* Time the waypoint is to expire (epoch) */
|
||||
uint32_t expire;
|
||||
/* If true, only allow the original sender to update the waypoint. */
|
||||
bool locked;
|
||||
/* Name of the waypoint - max 30 chars */
|
||||
char name[30];
|
||||
/* *
|
||||
Description of the waypoint - max 100 chars */
|
||||
char description[100];
|
||||
} Waypoint;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(256) MeshPacket_encrypted_t;
|
||||
/* A packet envelope sent/received over the mesh
|
||||
@@ -630,6 +566,56 @@ typedef struct _MeshPacket {
|
||||
MeshPacket_Delayed delayed;
|
||||
} 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.
|
||||
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,
|
||||
@@ -738,11 +724,11 @@ extern "C" {
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define Position_init_default {0, 0, 0, 0, _Position_LocSource_MIN, _Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define User_init_default {"", "", "", {0}, _HardwareModel_MIN, 0, 0, 0, 0}
|
||||
#define User_init_default {"", "", "", {0}, _HardwareModel_MIN, 0}
|
||||
#define RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
||||
#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 Location_init_default {0, 0, 0, 0, 0, "", ""}
|
||||
#define Data_init_default {_PortNum_MIN, {0, {0}}, 0, 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 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}
|
||||
@@ -752,11 +738,11 @@ extern "C" {
|
||||
#define ToRadio_PeerInfo_init_default {0, 0}
|
||||
#define Compressed_init_default {_PortNum_MIN, {0, {0}}}
|
||||
#define Position_init_zero {0, 0, 0, 0, _Position_LocSource_MIN, _Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define User_init_zero {"", "", "", {0}, _HardwareModel_MIN, 0, 0, 0, 0}
|
||||
#define User_init_zero {"", "", "", {0}, _HardwareModel_MIN, 0}
|
||||
#define RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
||||
#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 Location_init_zero {0, 0, 0, 0, 0, "", ""}
|
||||
#define Data_init_zero {_PortNum_MIN, {0, {0}}, 0, 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 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}
|
||||
@@ -769,13 +755,14 @@ extern "C" {
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define Compressed_portnum_tag 1
|
||||
#define Compressed_data_tag 2
|
||||
#define Location_id_tag 1
|
||||
#define Location_latitude_i_tag 2
|
||||
#define Location_longitude_i_tag 3
|
||||
#define Location_expire_tag 4
|
||||
#define Location_locked_tag 5
|
||||
#define Location_name_tag 6
|
||||
#define Location_description_tag 7
|
||||
#define Data_portnum_tag 1
|
||||
#define Data_payload_tag 2
|
||||
#define Data_want_response_tag 3
|
||||
#define Data_dest_tag 4
|
||||
#define Data_source_tag 5
|
||||
#define Data_request_id_tag 6
|
||||
#define Data_reply_id_tag 7
|
||||
#define Data_emoji_tag 8
|
||||
#define LogRecord_message_tag 1
|
||||
#define LogRecord_time_tag 2
|
||||
#define LogRecord_source_tag 3
|
||||
@@ -827,27 +814,13 @@ extern "C" {
|
||||
#define User_macaddr_tag 4
|
||||
#define User_hw_model_tag 6
|
||||
#define User_is_licensed_tag 7
|
||||
#define User_tx_power_dbm_tag 10
|
||||
#define User_ant_gain_dbi_tag 11
|
||||
#define User_ant_azimuth_tag 12
|
||||
#define Data_portnum_tag 1
|
||||
#define Data_payload_tag 2
|
||||
#define Data_want_response_tag 3
|
||||
#define Data_dest_tag 4
|
||||
#define Data_source_tag 5
|
||||
#define Data_request_id_tag 6
|
||||
#define Data_reply_id_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 Waypoint_id_tag 1
|
||||
#define Waypoint_latitude_i_tag 2
|
||||
#define Waypoint_longitude_i_tag 3
|
||||
#define Waypoint_expire_tag 4
|
||||
#define Waypoint_locked_tag 5
|
||||
#define Waypoint_name_tag 6
|
||||
#define Waypoint_description_tag 7
|
||||
#define MeshPacket_from_tag 1
|
||||
#define MeshPacket_to_tag 2
|
||||
#define MeshPacket_channel_tag 3
|
||||
@@ -861,6 +834,15 @@ extern "C" {
|
||||
#define MeshPacket_priority_tag 12
|
||||
#define MeshPacket_rx_rssi_tag 13
|
||||
#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_my_info_tag 3
|
||||
#define FromRadio_node_info_tag 4
|
||||
@@ -908,10 +890,7 @@ X(a, STATIC, SINGULAR, STRING, long_name, 2) \
|
||||
X(a, STATIC, SINGULAR, STRING, short_name, 3) \
|
||||
X(a, STATIC, SINGULAR, FIXED_LENGTH_BYTES, macaddr, 4) \
|
||||
X(a, STATIC, SINGULAR, UENUM, hw_model, 6) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_licensed, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, tx_power_dbm, 10) \
|
||||
X(a, STATIC, SINGULAR, UINT32, ant_gain_dbi, 11) \
|
||||
X(a, STATIC, SINGULAR, UINT32, ant_azimuth, 12)
|
||||
X(a, STATIC, SINGULAR, BOOL, is_licensed, 7)
|
||||
#define User_CALLBACK NULL
|
||||
#define User_DEFAULT NULL
|
||||
|
||||
@@ -937,13 +916,11 @@ X(a, STATIC, SINGULAR, FIXED32, dest, 4) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, source, 5) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, request_id, 6) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, reply_id, 7) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, emoji, 8) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, location, 9)
|
||||
X(a, STATIC, SINGULAR, FIXED32, emoji, 8)
|
||||
#define Data_CALLBACK 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, SFIXED32, latitude_i, 2) \
|
||||
X(a, STATIC, SINGULAR, SFIXED32, longitude_i, 3) \
|
||||
@@ -951,8 +928,8 @@ X(a, STATIC, SINGULAR, UINT32, expire, 4) \
|
||||
X(a, STATIC, SINGULAR, BOOL, locked, 5) \
|
||||
X(a, STATIC, SINGULAR, STRING, name, 6) \
|
||||
X(a, STATIC, SINGULAR, STRING, description, 7)
|
||||
#define Location_CALLBACK NULL
|
||||
#define Location_DEFAULT NULL
|
||||
#define Waypoint_CALLBACK NULL
|
||||
#define Waypoint_DEFAULT NULL
|
||||
|
||||
#define MeshPacket_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, from, 1) \
|
||||
@@ -1059,7 +1036,7 @@ extern const pb_msgdesc_t User_msg;
|
||||
extern const pb_msgdesc_t RouteDiscovery_msg;
|
||||
extern const pb_msgdesc_t Routing_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 NodeInfo_msg;
|
||||
extern const pb_msgdesc_t MyNodeInfo_msg;
|
||||
@@ -1075,7 +1052,7 @@ extern const pb_msgdesc_t Compressed_msg;
|
||||
#define RouteDiscovery_fields &RouteDiscovery_msg
|
||||
#define Routing_fields &Routing_msg
|
||||
#define Data_fields &Data_msg
|
||||
#define Location_fields &Location_msg
|
||||
#define Waypoint_fields &Waypoint_msg
|
||||
#define MeshPacket_fields &MeshPacket_msg
|
||||
#define NodeInfo_fields &NodeInfo_msg
|
||||
#define MyNodeInfo_fields &MyNodeInfo_msg
|
||||
@@ -1087,19 +1064,19 @@ extern const pb_msgdesc_t Compressed_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define Compressed_size 243
|
||||
#define Data_size 429
|
||||
#define FromRadio_size 489
|
||||
#define Location_size 156
|
||||
#define Data_size 270
|
||||
#define FromRadio_size 330
|
||||
#define LogRecord_size 81
|
||||
#define MeshPacket_size 480
|
||||
#define MeshPacket_size 321
|
||||
#define MyNodeInfo_size 197
|
||||
#define NodeInfo_size 281
|
||||
#define NodeInfo_size 263
|
||||
#define Position_size 142
|
||||
#define RouteDiscovery_size 40
|
||||
#define Routing_size 42
|
||||
#define ToRadio_PeerInfo_size 8
|
||||
#define ToRadio_size 483
|
||||
#define User_size 95
|
||||
#define ToRadio_size 324
|
||||
#define User_size 77
|
||||
#define Waypoint_size 156
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -72,7 +72,7 @@ typedef struct _ModuleConfig_ExternalNotificationConfig {
|
||||
} ModuleConfig_ExternalNotificationConfig;
|
||||
|
||||
typedef struct _ModuleConfig_MQTTConfig {
|
||||
bool disabled;
|
||||
bool enabled;
|
||||
char address[32];
|
||||
char username[32];
|
||||
char password[32];
|
||||
@@ -187,7 +187,7 @@ extern "C" {
|
||||
#define ModuleConfig_ExternalNotificationConfig_active_tag 4
|
||||
#define ModuleConfig_ExternalNotificationConfig_alert_message_tag 5
|
||||
#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_username_tag 3
|
||||
#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_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, username, 3) \
|
||||
X(a, STATIC, SINGULAR, STRING, password, 4) \
|
||||
|
||||
@@ -48,7 +48,8 @@ typedef enum _PortNum {
|
||||
PortNum_ADMIN_APP = 6,
|
||||
/* Compressed TEXT_MESSAGE payloads. */
|
||||
PortNum_TEXT_MESSAGE_COMPRESSED_APP = 7,
|
||||
/* Waypoint payloads. */
|
||||
/* Waypoint payloads.
|
||||
Payload is a [Waypoint](/docs/developers/protobufs/api#waypoint) message */
|
||||
PortNum_WAYPOINT_APP = 8,
|
||||
/* Provides a 'ping' service that replies to any packet it receives.
|
||||
Also serves as a small example module. */
|
||||
|
||||
@@ -170,80 +170,94 @@ void AdminModule::handleSetOwner(const User &o)
|
||||
|
||||
void AdminModule::handleSetConfig(const Config &c)
|
||||
{
|
||||
bool requiresReboot = false;
|
||||
switch (c.which_payloadVariant) {
|
||||
case Config_device_tag:
|
||||
DEBUG_MSG("Setting config: Device\n");
|
||||
config.has_device = true;
|
||||
config.device = c.payloadVariant.device;
|
||||
break;
|
||||
case Config_position_tag:
|
||||
DEBUG_MSG("Setting config: Position\n");
|
||||
config.has_position = true;
|
||||
config.position = c.payloadVariant.position;
|
||||
break;
|
||||
case Config_power_tag:
|
||||
DEBUG_MSG("Setting config: Power\n");
|
||||
config.has_power = true;
|
||||
config.power = c.payloadVariant.power;
|
||||
break;
|
||||
case Config_wifi_tag:
|
||||
DEBUG_MSG("Setting config: WiFi\n");
|
||||
config.has_wifi = true;
|
||||
config.wifi = c.payloadVariant.wifi;
|
||||
break;
|
||||
case Config_display_tag:
|
||||
DEBUG_MSG("Setting config: Display\n");
|
||||
config.has_display = true;
|
||||
config.display = c.payloadVariant.display;
|
||||
break;
|
||||
case Config_lora_tag:
|
||||
DEBUG_MSG("Setting config: LoRa\n");
|
||||
config.has_lora = true;
|
||||
config.lora = c.payloadVariant.lora;
|
||||
break;
|
||||
case Config_device_tag:
|
||||
DEBUG_MSG("Setting config: Device\n");
|
||||
config.has_device = true;
|
||||
config.device = c.payloadVariant.device;
|
||||
break;
|
||||
case Config_position_tag:
|
||||
DEBUG_MSG("Setting config: Position\n");
|
||||
config.has_position = true;
|
||||
config.position = c.payloadVariant.position;
|
||||
break;
|
||||
case Config_power_tag:
|
||||
DEBUG_MSG("Setting config: Power\n");
|
||||
config.has_power = true;
|
||||
config.power = c.payloadVariant.power;
|
||||
break;
|
||||
case Config_wifi_tag:
|
||||
DEBUG_MSG("Setting config: WiFi\n");
|
||||
config.has_wifi = true;
|
||||
config.wifi = c.payloadVariant.wifi;
|
||||
break;
|
||||
case Config_display_tag:
|
||||
DEBUG_MSG("Setting config: Display\n");
|
||||
config.has_display = true;
|
||||
config.display = c.payloadVariant.display;
|
||||
break;
|
||||
case Config_lora_tag:
|
||||
DEBUG_MSG("Setting config: LoRa\n");
|
||||
config.has_lora = true;
|
||||
config.lora = c.payloadVariant.lora;
|
||||
requiresReboot = true;
|
||||
break;
|
||||
case Config_bluetooth_tag:
|
||||
DEBUG_MSG("Setting config: Bluetooth\n");
|
||||
config.has_bluetooth = true;
|
||||
config.bluetooth = c.payloadVariant.bluetooth;
|
||||
requiresReboot = true;
|
||||
break;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
switch (c.which_payloadVariant) {
|
||||
case ModuleConfig_mqtt_tag:
|
||||
DEBUG_MSG("Setting module config: MQTT\n");
|
||||
moduleConfig.has_mqtt = true;
|
||||
moduleConfig.mqtt = c.payloadVariant.mqtt;
|
||||
break;
|
||||
case ModuleConfig_serial_tag:
|
||||
DEBUG_MSG("Setting module config: Serial\n");
|
||||
moduleConfig.has_serial = true;
|
||||
moduleConfig.serial = c.payloadVariant.serial;
|
||||
break;
|
||||
case ModuleConfig_external_notification_tag:
|
||||
DEBUG_MSG("Setting module config: External Notification\n");
|
||||
moduleConfig.has_external_notification = true;
|
||||
moduleConfig.external_notification = c.payloadVariant.external_notification;
|
||||
break;
|
||||
case ModuleConfig_store_forward_tag:
|
||||
DEBUG_MSG("Setting module config: Store & Forward\n");
|
||||
moduleConfig.has_store_forward = true;
|
||||
moduleConfig.store_forward = c.payloadVariant.store_forward;
|
||||
break;
|
||||
case ModuleConfig_range_test_tag:
|
||||
DEBUG_MSG("Setting module config: Range Test\n");
|
||||
moduleConfig.has_range_test = true;
|
||||
moduleConfig.range_test = c.payloadVariant.range_test;
|
||||
break;
|
||||
case ModuleConfig_telemetry_tag:
|
||||
DEBUG_MSG("Setting module config: Telemetry\n");
|
||||
moduleConfig.has_telemetry = true;
|
||||
moduleConfig.telemetry = c.payloadVariant.telemetry;
|
||||
break;
|
||||
case ModuleConfig_canned_message_tag:
|
||||
DEBUG_MSG("Setting module config: Canned Message\n");
|
||||
moduleConfig.has_canned_message = true;
|
||||
moduleConfig.canned_message = c.payloadVariant.canned_message;
|
||||
break;
|
||||
case ModuleConfig_mqtt_tag:
|
||||
DEBUG_MSG("Setting module config: MQTT\n");
|
||||
moduleConfig.has_mqtt = true;
|
||||
moduleConfig.mqtt = c.payloadVariant.mqtt;
|
||||
break;
|
||||
case ModuleConfig_serial_tag:
|
||||
DEBUG_MSG("Setting module config: Serial\n");
|
||||
moduleConfig.has_serial = true;
|
||||
moduleConfig.serial = c.payloadVariant.serial;
|
||||
break;
|
||||
case ModuleConfig_external_notification_tag:
|
||||
DEBUG_MSG("Setting module config: External Notification\n");
|
||||
moduleConfig.has_external_notification = true;
|
||||
moduleConfig.external_notification = c.payloadVariant.external_notification;
|
||||
break;
|
||||
case ModuleConfig_store_forward_tag:
|
||||
DEBUG_MSG("Setting module config: Store & Forward\n");
|
||||
moduleConfig.has_store_forward = true;
|
||||
moduleConfig.store_forward = c.payloadVariant.store_forward;
|
||||
break;
|
||||
case ModuleConfig_range_test_tag:
|
||||
DEBUG_MSG("Setting module config: Range Test\n");
|
||||
moduleConfig.has_range_test = true;
|
||||
moduleConfig.range_test = c.payloadVariant.range_test;
|
||||
break;
|
||||
case ModuleConfig_telemetry_tag:
|
||||
DEBUG_MSG("Setting module config: Telemetry\n");
|
||||
moduleConfig.has_telemetry = true;
|
||||
moduleConfig.telemetry = c.payloadVariant.telemetry;
|
||||
break;
|
||||
case ModuleConfig_canned_message_tag:
|
||||
DEBUG_MSG("Setting module config: Canned Message\n");
|
||||
moduleConfig.has_canned_message = true;
|
||||
moduleConfig.canned_message = c.payloadVariant.canned_message;
|
||||
break;
|
||||
}
|
||||
|
||||
service.reloadConfig();
|
||||
@@ -309,8 +323,12 @@ void AdminModule::handleGetConfig(const MeshPacket &req, const uint32_t configTy
|
||||
res.get_config_response.which_payloadVariant = Config_lora_tag;
|
||||
res.get_config_response.payloadVariant.lora = config.lora;
|
||||
break;
|
||||
case AdminMessage_ConfigType_BLUETOOTH_CONFIG:
|
||||
DEBUG_MSG("Getting config: Bluetooth\n");
|
||||
res.get_config_response.which_payloadVariant = Config_bluetooth_tag;
|
||||
res.get_config_response.payloadVariant.bluetooth = config.bluetooth;
|
||||
break;
|
||||
}
|
||||
|
||||
// NOTE: The phone app needs to know the ls_secs value so it can properly expect sleep behavior.
|
||||
// So even if we internally use 0 to represent 'use default' we still need to send the value we are
|
||||
// using to the app (so that even old phone apps work with new device loads).
|
||||
|
||||
@@ -46,16 +46,14 @@ CannedMessageModule::CannedMessageModule()
|
||||
*
|
||||
* @return int Returns the number of messages found.
|
||||
*/
|
||||
// FIXME: This is just one set of messages now
|
||||
int CannedMessageModule::splitConfiguredMessages()
|
||||
{
|
||||
int messageIndex = 0;
|
||||
int i = 0;
|
||||
|
||||
// collect all the message parts
|
||||
strcpy(this->messageStore, cannedMessageModuleConfig.messagesPart1);
|
||||
strcat(this->messageStore, cannedMessageModuleConfig.messagesPart2);
|
||||
strcat(this->messageStore, cannedMessageModuleConfig.messagesPart3);
|
||||
strcat(this->messageStore, cannedMessageModuleConfig.messagesPart4);
|
||||
strcpy(this->messageStore, cannedMessageModuleConfig.messages);
|
||||
|
||||
// The first message points to the beginning of the store.
|
||||
this->messages[messageIndex++] = this->messageStore;
|
||||
@@ -294,10 +292,7 @@ bool CannedMessageModule::saveProtoForModule()
|
||||
*/
|
||||
void CannedMessageModule::installDefaultCannedMessageModuleConfig()
|
||||
{
|
||||
memset(cannedMessageModuleConfig.messagesPart1, 0, sizeof(cannedMessageModuleConfig.messagesPart1));
|
||||
memset(cannedMessageModuleConfig.messagesPart2, 0, sizeof(cannedMessageModuleConfig.messagesPart2));
|
||||
memset(cannedMessageModuleConfig.messagesPart3, 0, sizeof(cannedMessageModuleConfig.messagesPart3));
|
||||
memset(cannedMessageModuleConfig.messagesPart4, 0, sizeof(cannedMessageModuleConfig.messagesPart4));
|
||||
memset(cannedMessageModuleConfig.messages, 0, sizeof(cannedMessageModuleConfig.messages));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -315,51 +310,15 @@ AdminMessageHandleResult CannedMessageModule::handleAdminMessageForModule(const
|
||||
AdminMessageHandleResult result;
|
||||
|
||||
switch (request->which_variant) {
|
||||
case AdminMessage_get_canned_message_module_part1_request_tag:
|
||||
DEBUG_MSG("Client is getting radio canned message part1\n");
|
||||
this->handleGetCannedMessageModulePart1(mp, response);
|
||||
case AdminMessage_get_canned_message_module_messages_request_tag:
|
||||
DEBUG_MSG("Client is getting radio canned messages\n");
|
||||
this->handleGetCannedMessageModuleMessages(mp, response);
|
||||
result = AdminMessageHandleResult::HANDLED_WITH_RESPONSE;
|
||||
break;
|
||||
|
||||
case AdminMessage_get_canned_message_module_part2_request_tag:
|
||||
DEBUG_MSG("Client is getting radio canned message part2\n");
|
||||
this->handleGetCannedMessageModulePart2(mp, response);
|
||||
result = AdminMessageHandleResult::HANDLED_WITH_RESPONSE;
|
||||
break;
|
||||
|
||||
case AdminMessage_get_canned_message_module_part3_request_tag:
|
||||
DEBUG_MSG("Client is getting radio canned message part3\n");
|
||||
this->handleGetCannedMessageModulePart3(mp, response);
|
||||
result = AdminMessageHandleResult::HANDLED_WITH_RESPONSE;
|
||||
break;
|
||||
|
||||
case AdminMessage_get_canned_message_module_part4_request_tag:
|
||||
DEBUG_MSG("Client is getting radio canned message part4\n");
|
||||
this->handleGetCannedMessageModulePart4(mp, response);
|
||||
result = AdminMessageHandleResult::HANDLED_WITH_RESPONSE;
|
||||
break;
|
||||
|
||||
case AdminMessage_set_canned_message_module_part1_tag:
|
||||
DEBUG_MSG("Client is setting radio canned message part 1\n");
|
||||
this->handleSetCannedMessageModulePart1(request->set_canned_message_module_part1);
|
||||
result = AdminMessageHandleResult::HANDLED;
|
||||
break;
|
||||
|
||||
case AdminMessage_set_canned_message_module_part2_tag:
|
||||
DEBUG_MSG("Client is setting radio canned message part 2\n");
|
||||
this->handleSetCannedMessageModulePart2(request->set_canned_message_module_part2);
|
||||
result = AdminMessageHandleResult::HANDLED;
|
||||
break;
|
||||
|
||||
case AdminMessage_set_canned_message_module_part3_tag:
|
||||
DEBUG_MSG("Client is setting radio canned message part 3\n");
|
||||
this->handleSetCannedMessageModulePart3(request->set_canned_message_module_part3);
|
||||
result = AdminMessageHandleResult::HANDLED;
|
||||
break;
|
||||
|
||||
case AdminMessage_set_canned_message_module_part4_tag:
|
||||
DEBUG_MSG("Client is setting radio canned message part 4\n");
|
||||
this->handleSetCannedMessageModulePart4(request->set_canned_message_module_part4);
|
||||
case AdminMessage_set_canned_message_module_messages_tag:
|
||||
DEBUG_MSG("Client is setting radio canned messages\n");
|
||||
this->handleSetCannedMessageModuleMessages(request->set_canned_message_module_messages);
|
||||
result = AdminMessageHandleResult::HANDLED;
|
||||
break;
|
||||
|
||||
@@ -370,49 +329,23 @@ AdminMessageHandleResult CannedMessageModule::handleAdminMessageForModule(const
|
||||
return result;
|
||||
}
|
||||
|
||||
void CannedMessageModule::handleGetCannedMessageModulePart1(const MeshPacket &req, AdminMessage *response)
|
||||
void CannedMessageModule::handleGetCannedMessageModuleMessages(const MeshPacket &req, AdminMessage *response)
|
||||
{
|
||||
DEBUG_MSG("*** handleGetCannedMessageModulePart1\n");
|
||||
DEBUG_MSG("*** handleGetCannedMessageModuleMessages\n");
|
||||
assert(req.decoded.want_response);
|
||||
|
||||
response->which_variant = AdminMessage_get_canned_message_module_part1_response_tag;
|
||||
strcpy(response->get_canned_message_module_part1_response, cannedMessageModuleConfig.messagesPart1);
|
||||
response->which_variant = AdminMessage_get_canned_message_module_messages_response_tag;
|
||||
strcpy(response->get_canned_message_module_messages_response, cannedMessageModuleConfig.messages);
|
||||
}
|
||||
|
||||
void CannedMessageModule::handleGetCannedMessageModulePart2(const MeshPacket &req, AdminMessage *response)
|
||||
{
|
||||
DEBUG_MSG("*** handleGetCannedMessageModulePart2\n");
|
||||
assert(req.decoded.want_response);
|
||||
|
||||
response->which_variant = AdminMessage_get_canned_message_module_part2_response_tag;
|
||||
strcpy(response->get_canned_message_module_part2_response, cannedMessageModuleConfig.messagesPart2);
|
||||
}
|
||||
|
||||
void CannedMessageModule::handleGetCannedMessageModulePart3(const MeshPacket &req, AdminMessage *response)
|
||||
{
|
||||
DEBUG_MSG("*** handleGetCannedMessageModulePart3\n");
|
||||
assert(req.decoded.want_response);
|
||||
|
||||
response->which_variant = AdminMessage_get_canned_message_module_part3_response_tag;
|
||||
strcpy(response->get_canned_message_module_part3_response, cannedMessageModuleConfig.messagesPart3);
|
||||
}
|
||||
|
||||
void CannedMessageModule::handleGetCannedMessageModulePart4(const MeshPacket &req, AdminMessage *response)
|
||||
{
|
||||
DEBUG_MSG("*** handleGetCannedMessageModulePart4\n");
|
||||
assert(req.decoded.want_response);
|
||||
|
||||
response->which_variant = AdminMessage_get_canned_message_module_part4_response_tag;
|
||||
strcpy(response->get_canned_message_module_part4_response, cannedMessageModuleConfig.messagesPart4);
|
||||
}
|
||||
|
||||
void CannedMessageModule::handleSetCannedMessageModulePart1(const char *from_msg)
|
||||
void CannedMessageModule::handleSetCannedMessageModuleMessages(const char *from_msg)
|
||||
{
|
||||
int changed = 0;
|
||||
|
||||
if (*from_msg) {
|
||||
changed |= strcmp(cannedMessageModuleConfig.messagesPart1, from_msg);
|
||||
strcpy(cannedMessageModuleConfig.messagesPart1, from_msg);
|
||||
changed |= strcmp(cannedMessageModuleConfig.messages, from_msg);
|
||||
strcpy(cannedMessageModuleConfig.messages, from_msg);
|
||||
DEBUG_MSG("*** from_msg.text:%s\n", from_msg);
|
||||
}
|
||||
|
||||
@@ -421,45 +354,4 @@ void CannedMessageModule::handleSetCannedMessageModulePart1(const char *from_msg
|
||||
}
|
||||
}
|
||||
|
||||
void CannedMessageModule::handleSetCannedMessageModulePart2(const char *from_msg)
|
||||
{
|
||||
int changed = 0;
|
||||
|
||||
if (*from_msg) {
|
||||
changed |= strcmp(cannedMessageModuleConfig.messagesPart2, from_msg);
|
||||
strcpy(cannedMessageModuleConfig.messagesPart2, from_msg);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
this->saveProtoForModule();
|
||||
}
|
||||
}
|
||||
|
||||
void CannedMessageModule::handleSetCannedMessageModulePart3(const char *from_msg)
|
||||
{
|
||||
int changed = 0;
|
||||
|
||||
if (*from_msg) {
|
||||
changed |= strcmp(cannedMessageModuleConfig.messagesPart3, from_msg);
|
||||
strcpy(cannedMessageModuleConfig.messagesPart3, from_msg);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
this->saveProtoForModule();
|
||||
}
|
||||
}
|
||||
|
||||
void CannedMessageModule::handleSetCannedMessageModulePart4(const char *from_msg)
|
||||
{
|
||||
int changed = 0;
|
||||
|
||||
if (*from_msg) {
|
||||
changed |= strcmp(cannedMessageModuleConfig.messagesPart4, from_msg);
|
||||
strcpy(cannedMessageModuleConfig.messagesPart4, from_msg);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
this->saveProtoForModule();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -39,15 +39,8 @@ class CannedMessageModule :
|
||||
void eventDown();
|
||||
void eventSelect();
|
||||
|
||||
void handleGetCannedMessageModulePart1(const MeshPacket &req, AdminMessage *response);
|
||||
void handleGetCannedMessageModulePart2(const MeshPacket &req, AdminMessage *response);
|
||||
void handleGetCannedMessageModulePart3(const MeshPacket &req, AdminMessage *response);
|
||||
void handleGetCannedMessageModulePart4(const MeshPacket &req, AdminMessage *response);
|
||||
|
||||
void handleSetCannedMessageModulePart1(const char *from_msg);
|
||||
void handleSetCannedMessageModulePart2(const char *from_msg);
|
||||
void handleSetCannedMessageModulePart3(const char *from_msg);
|
||||
void handleSetCannedMessageModulePart4(const char *from_msg);
|
||||
void handleGetCannedMessageModuleMessages(const MeshPacket &req, AdminMessage *response);
|
||||
void handleSetCannedMessageModuleMessages(const char *from_msg);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
@@ -116,7 +116,6 @@ ExternalNotificationModule::ExternalNotificationModule()
|
||||
// restrict to the admin channel for rx
|
||||
boundChannel = Channels::gpioChannel;
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#ifdef EXT_NOTIFY_OUT
|
||||
|
||||
/*
|
||||
@@ -149,12 +148,10 @@ ExternalNotificationModule::ExternalNotificationModule()
|
||||
enabled = false;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
ProcessMessage ExternalNotificationModule::handleReceived(const MeshPacket &mp)
|
||||
{
|
||||
#ifdef ARCH_ESP32
|
||||
#ifdef EXT_NOTIFY_OUT
|
||||
|
||||
if (moduleConfig.external_notification.enabled) {
|
||||
@@ -182,8 +179,6 @@ ProcessMessage ExternalNotificationModule::handleReceived(const MeshPacket &mp)
|
||||
} else {
|
||||
DEBUG_MSG("External Notification Module Disabled\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
return ProcessMessage::CONTINUE; // Let others look at this message also if they want
|
||||
|
||||
@@ -6,15 +6,15 @@
|
||||
#include "input/facesKbI2cImpl.h"
|
||||
#include "modules/AdminModule.h"
|
||||
#include "modules/CannedMessageModule.h"
|
||||
#include "modules/ExternalNotificationModule.h"
|
||||
#include "modules/NodeInfoModule.h"
|
||||
#include "modules/PositionModule.h"
|
||||
#include "modules/RemoteHardwareModule.h"
|
||||
#include "modules/ReplyModule.h"
|
||||
#include "modules/RoutingModule.h"
|
||||
#include "modules/TextMessageModule.h"
|
||||
#include "modules/Telemetry/DeviceTelemetry.h"
|
||||
#include "modules/WaypointModule.h"
|
||||
#if HAS_TELEMETRY
|
||||
#include "modules/Telemetry/DeviceTelemetry.h"
|
||||
#include "modules/Telemetry/EnvironmentTelemetry.h"
|
||||
#endif
|
||||
#ifdef ARCH_ESP32
|
||||
@@ -22,7 +22,9 @@
|
||||
#include "modules/esp32/SerialModule.h"
|
||||
#include "modules/esp32/StoreForwardModule.h"
|
||||
#endif
|
||||
|
||||
#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
|
||||
#include "modules/ExternalNotificationModule.h"
|
||||
#endif
|
||||
/**
|
||||
* Create module instances here. If you are adding a new module, you must 'new' it here (or somewhere else)
|
||||
*/
|
||||
@@ -34,6 +36,7 @@ void setupModules()
|
||||
adminModule = new AdminModule();
|
||||
nodeInfoModule = new NodeInfoModule();
|
||||
positionModule = new PositionModule();
|
||||
waypointModule = new WaypointModule();
|
||||
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
|
||||
@@ -70,6 +73,8 @@ void setupModules()
|
||||
storeForwardModule = new StoreForwardModule();
|
||||
|
||||
new RangeTestModule();
|
||||
#elif defined(ARCH_NRF52)
|
||||
new ExternalNotificationModule();
|
||||
#endif
|
||||
|
||||
// NOTE! This module must be added LAST because it likes to check for replies from other modules and avoid sending extra acks
|
||||
|
||||
@@ -54,8 +54,7 @@ NodeInfoModule::NodeInfoModule()
|
||||
: ProtobufModule("nodeinfo", PortNum_NODEINFO_APP, User_fields), concurrency::OSThread("NodeInfoModule")
|
||||
{
|
||||
isPromiscuous = true; // We always want to update our nodedb, even if we are sniffing on others
|
||||
setIntervalFromNow(30 *
|
||||
1000); // Send our initial owner announcement 30 seconds after we start (to give network time to setup)
|
||||
setIntervalFromNow(30 * 1000); // Send our initial owner announcement 30 seconds after we start (to give network time to setup)
|
||||
}
|
||||
|
||||
int32_t NodeInfoModule::runOnce()
|
||||
@@ -69,6 +68,5 @@ int32_t NodeInfoModule::runOnce()
|
||||
DEBUG_MSG("Sending our nodeinfo to mesh (wantReplies=%d)\n", requestReplies);
|
||||
sendOurNodeInfo(NODENUM_BROADCAST, requestReplies); // Send our info (don't request replies)
|
||||
|
||||
return config.position.position_broadcast_secs ? config.position.position_broadcast_secs
|
||||
: default_broadcast_interval_secs * 1000;
|
||||
return default_broadcast_interval_secs * 1000;
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <typeinfo>
|
||||
|
||||
BMP280Sensor::BMP280Sensor() :
|
||||
TelemetrySensor(TelemetrySensorType_BME280, "BMP280")
|
||||
TelemetrySensor(TelemetrySensorType_BMP280, "BMP280")
|
||||
{
|
||||
}
|
||||
|
||||
@@ -27,4 +27,4 @@ bool BMP280Sensor::getMetrics(Telemetry *measurement) {
|
||||
measurement->variant.environment_metrics.barometric_pressure = bmp280.readPressure() / 100.0F;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (moduleConfig.mqtt.disabled) {
|
||||
// DEBUG_MSG("MQTT disabled...\n");
|
||||
} else {
|
||||
if (moduleConfig.mqtt.enabled) {
|
||||
// No need for link if no channel needed it
|
||||
size_t numChan = channels.getNumChannels();
|
||||
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
|
||||
226
src/nimble/NimbleBluetooth.cpp
Normal file
226
src/nimble/NimbleBluetooth.cpp
Normal file
@@ -0,0 +1,226 @@
|
||||
#include "configuration.h"
|
||||
#include "NimbleBluetooth.h"
|
||||
#include "BluetoothCommon.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "sleep.h"
|
||||
#include "main.h"
|
||||
#include "mesh/PhoneAPI.h"
|
||||
#include "mesh/mesh-pb-constants.h"
|
||||
#include <NimBLEDevice.h>
|
||||
|
||||
NimBLECharacteristic *fromNumCharacteristic;
|
||||
NimBLEServer *bleServer;
|
||||
|
||||
static bool passkeyShowing;
|
||||
static uint32_t doublepressed;
|
||||
|
||||
class BluetoothPhoneAPI : public PhoneAPI
|
||||
{
|
||||
/**
|
||||
* Subclasses can use this as a hook to provide custom notifications for their transport (i.e. bluetooth notifies)
|
||||
*/
|
||||
virtual void onNowHasData(uint32_t fromRadioNum)
|
||||
{
|
||||
PhoneAPI::onNowHasData(fromRadioNum);
|
||||
|
||||
DEBUG_MSG("BLE notify fromNum\n");
|
||||
|
||||
uint8_t val[4];
|
||||
put_le32(val, fromRadioNum);
|
||||
|
||||
fromNumCharacteristic->setValue(val, sizeof(val));
|
||||
fromNumCharacteristic->notify();
|
||||
}
|
||||
|
||||
/// Check the current underlying physical link to see if the client is currently connected
|
||||
virtual bool checkIsConnected()
|
||||
{
|
||||
return bleServer && bleServer->getConnectedCount() > 0;
|
||||
}
|
||||
};
|
||||
|
||||
static BluetoothPhoneAPI *bluetoothPhoneAPI;
|
||||
/**
|
||||
* Subclasses can use this as a hook to provide custom notifications for their transport (i.e. bluetooth notifies)
|
||||
*/
|
||||
|
||||
class NimbleBluetoothToRadioCallback : public NimBLECharacteristicCallbacks
|
||||
{
|
||||
virtual void onWrite(NimBLECharacteristic *pCharacteristic) {
|
||||
DEBUG_MSG("To Radio onwrite\n");
|
||||
auto val = pCharacteristic->getValue();
|
||||
|
||||
bluetoothPhoneAPI->handleToRadio(val.data(), val.length());
|
||||
}
|
||||
};
|
||||
|
||||
class NimbleBluetoothFromRadioCallback : public NimBLECharacteristicCallbacks
|
||||
{
|
||||
virtual void onRead(NimBLECharacteristic *pCharacteristic) {
|
||||
DEBUG_MSG("From Radio onread\n");
|
||||
uint8_t fromRadioBytes[FromRadio_size];
|
||||
size_t numBytes = bluetoothPhoneAPI->getFromRadio(fromRadioBytes);
|
||||
|
||||
std::string fromRadioByteString(fromRadioBytes, fromRadioBytes + numBytes);
|
||||
|
||||
pCharacteristic->setValue(fromRadioByteString);
|
||||
}
|
||||
};
|
||||
|
||||
class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
|
||||
{
|
||||
virtual uint32_t onPassKeyRequest() {
|
||||
uint32_t passkey = config.bluetooth.fixed_pin;
|
||||
|
||||
if (doublepressed > 0 && (doublepressed + (30 * 1000)) > millis()) {
|
||||
DEBUG_MSG("User has set BLE pairing mode to fixed-pin\n");
|
||||
config.bluetooth.mode = Config_BluetoothConfig_PairingMode_FixedPin;
|
||||
nodeDB.saveToDisk();
|
||||
} else if (config.bluetooth.mode == Config_BluetoothConfig_PairingMode_RandomPin) {
|
||||
DEBUG_MSG("Using random passkey\n");
|
||||
// This is the passkey to be entered on peer - we pick a number >100,000 to ensure 6 digits
|
||||
passkey = random(100000, 999999);
|
||||
}
|
||||
DEBUG_MSG("*** Enter passkey %d on the peer side ***\n", passkey);
|
||||
|
||||
powerFSM.trigger(EVENT_BLUETOOTH_PAIR);
|
||||
screen->startBluetoothPinScreen(passkey);
|
||||
passkeyShowing = true;
|
||||
|
||||
return passkey;
|
||||
}
|
||||
|
||||
virtual void onAuthenticationComplete(ble_gap_conn_desc *desc)
|
||||
{
|
||||
DEBUG_MSG("BLE authentication complete\n");
|
||||
|
||||
if (passkeyShowing) {
|
||||
passkeyShowing = false;
|
||||
screen->stopBluetoothPinScreen();
|
||||
}
|
||||
// bluetoothPhoneAPI->setInitialState();
|
||||
}
|
||||
|
||||
virtual void onDisconnect(NimBLEServer* pServer, ble_gap_conn_desc *desc)
|
||||
{
|
||||
DEBUG_MSG("BLE disconnect\n");
|
||||
}
|
||||
};
|
||||
|
||||
static NimbleBluetoothToRadioCallback *toRadioCallbacks;
|
||||
static NimbleBluetoothFromRadioCallback *fromRadioCallbacks;
|
||||
|
||||
void NimbleBluetooth::shutdown()
|
||||
{
|
||||
// Shutdown bluetooth for minimum power draw
|
||||
DEBUG_MSG("Disable bluetooth\n");
|
||||
//Bluefruit.Advertising.stop();
|
||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||
pAdvertising->reset();
|
||||
pAdvertising->stop();
|
||||
}
|
||||
|
||||
bool NimbleBluetooth::isActive()
|
||||
{
|
||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||
return bleServer && (bleServer->getConnectedCount() > 0 || pAdvertising->isAdvertising());
|
||||
}
|
||||
|
||||
void NimbleBluetooth::setup()
|
||||
{
|
||||
// Uncomment for testing
|
||||
// NimbleBluetooth::clearBonds();
|
||||
|
||||
DEBUG_MSG("Initialise the NimBLE bluetooth module\n");
|
||||
|
||||
NimBLEDevice::init(getDeviceName());
|
||||
NimBLEDevice::setPower(ESP_PWR_LVL_P9);
|
||||
|
||||
if (config.bluetooth.mode != Config_BluetoothConfig_PairingMode_NoPin) {
|
||||
NimBLEDevice::setSecurityAuth(true, true, true);
|
||||
NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY);
|
||||
}
|
||||
bleServer = NimBLEDevice::createServer();
|
||||
|
||||
NimbleBluetoothServerCallback *serverCallbacks = new NimbleBluetoothServerCallback();
|
||||
bleServer->setCallbacks(serverCallbacks, true);
|
||||
|
||||
setupService();
|
||||
startAdvertising();
|
||||
}
|
||||
|
||||
void NimbleBluetooth::setupService()
|
||||
{
|
||||
NimBLEService *bleService = bleServer->createService(MESH_SERVICE_UUID);
|
||||
NimBLECharacteristic *ToRadioCharacteristic;
|
||||
NimBLECharacteristic *FromRadioCharacteristic;
|
||||
// Define the characteristics that the app is looking for
|
||||
if (config.bluetooth.mode == Config_BluetoothConfig_PairingMode_NoPin) {
|
||||
ToRadioCharacteristic = bleService->createCharacteristic(TORADIO_UUID, NIMBLE_PROPERTY::WRITE);
|
||||
FromRadioCharacteristic = bleService->createCharacteristic(FROMRADIO_UUID, NIMBLE_PROPERTY::READ);
|
||||
fromNumCharacteristic = bleService->createCharacteristic(FROMNUM_UUID, NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ);
|
||||
}
|
||||
else {
|
||||
ToRadioCharacteristic = bleService->createCharacteristic(TORADIO_UUID, NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_AUTHEN | NIMBLE_PROPERTY::WRITE_ENC);
|
||||
FromRadioCharacteristic = bleService->createCharacteristic(FROMRADIO_UUID, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_AUTHEN | NIMBLE_PROPERTY::READ_ENC);
|
||||
fromNumCharacteristic = bleService->createCharacteristic(FROMNUM_UUID, NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_AUTHEN | NIMBLE_PROPERTY::READ_ENC);
|
||||
}
|
||||
bluetoothPhoneAPI = new BluetoothPhoneAPI();
|
||||
|
||||
toRadioCallbacks = new NimbleBluetoothToRadioCallback();
|
||||
ToRadioCharacteristic->setCallbacks(toRadioCallbacks);
|
||||
|
||||
fromRadioCallbacks = new NimbleBluetoothFromRadioCallback();
|
||||
FromRadioCharacteristic->setCallbacks(fromRadioCallbacks);
|
||||
|
||||
bleService->start();
|
||||
}
|
||||
|
||||
void NimbleBluetooth::startAdvertising()
|
||||
{
|
||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||
pAdvertising->reset();
|
||||
pAdvertising->addServiceUUID(MESH_SERVICE_UUID);
|
||||
pAdvertising->start(0);
|
||||
}
|
||||
|
||||
/// Given a level between 0-100, update the BLE attribute
|
||||
void updateBatteryLevel(uint8_t level)
|
||||
{
|
||||
//blebas.write(level);
|
||||
}
|
||||
|
||||
void NimbleBluetooth::clearBonds()
|
||||
{
|
||||
DEBUG_MSG("Clearing bluetooth bonds!\n");
|
||||
NimBLEDevice::deleteAllBonds();
|
||||
}
|
||||
|
||||
void clearNVS()
|
||||
{
|
||||
NimBLEDevice::deleteAllBonds();
|
||||
#ifdef ARCH_ESP32
|
||||
ESP.restart();
|
||||
#endif
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
18
src/nimble/NimbleBluetooth.h
Normal file
18
src/nimble/NimbleBluetooth.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
class NimbleBluetooth
|
||||
{
|
||||
public:
|
||||
void setup();
|
||||
void shutdown();
|
||||
void clearBonds();
|
||||
bool isActive();
|
||||
|
||||
private:
|
||||
void setupService();
|
||||
void startAdvertising();
|
||||
};
|
||||
|
||||
void setBluetoothEnable(bool on);
|
||||
void clearNVS();
|
||||
void disablePin();
|
||||
@@ -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,264 +0,0 @@
|
||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
||||
|
||||
#include "configuration.h"
|
||||
#include "ESP32Bluetooth.h"
|
||||
#include "BluetoothCommon.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "sleep.h"
|
||||
#include "main.h"
|
||||
#include "mesh/PhoneAPI.h"
|
||||
#include "mesh/mesh-pb-constants.h"
|
||||
#include <NimBLEDevice.h>
|
||||
|
||||
//static BLEService meshBleService = BLEService(BLEUuid(MESH_SERVICE_UUID_16));
|
||||
//static BLECharacteristic fromNum = BLECharacteristic(BLEUuid(FROMNUM_UUID_16));
|
||||
//static BLECharacteristic fromRadio = BLECharacteristic(BLEUuid(FROMRADIO_UUID_16));
|
||||
//static BLECharacteristic toRadio = BLECharacteristic(BLEUuid(TORADIO_UUID_16));
|
||||
|
||||
//static BLEDis bledis; // DIS (Device Information Service) helper class instance
|
||||
//static BLEBas blebas; // BAS (Battery Service) helper class instance
|
||||
//static BLEDfu bledfu; // DFU software update helper service
|
||||
|
||||
// This scratch buffer is used for various bluetooth reads/writes - but it is safe because only one bt operation can be in
|
||||
// proccess at once
|
||||
// static uint8_t trBytes[_max(_max(_max(_max(ToRadio_size, RadioConfig_size), User_size), MyNodeInfo_size), FromRadio_size)];
|
||||
static uint8_t fromRadioBytes[FromRadio_size];
|
||||
|
||||
NimBLECharacteristic *FromNumCharacteristic;
|
||||
NimBLEServer *bleServer;
|
||||
|
||||
static bool passkeyShowing;
|
||||
static uint32_t doublepressed;
|
||||
|
||||
/**
|
||||
* Subclasses can use this as a hook to provide custom notifications for their transport (i.e. bluetooth notifies)
|
||||
*/
|
||||
void BluetoothPhoneAPI::onNowHasData(uint32_t fromRadioNum)
|
||||
{
|
||||
PhoneAPI::onNowHasData(fromRadioNum);
|
||||
|
||||
DEBUG_MSG("BLE notify fromNum\n");
|
||||
//fromNum.notify32(fromRadioNum);
|
||||
|
||||
uint8_t val[4];
|
||||
put_le32(val, fromRadioNum);
|
||||
|
||||
std::string fromNumByteString(&val[0], &val[0] + sizeof(val));
|
||||
|
||||
FromNumCharacteristic->setValue(fromNumByteString);
|
||||
FromNumCharacteristic->notify();
|
||||
}
|
||||
|
||||
/// Check the current underlying physical link to see if the client is currently connected
|
||||
bool BluetoothPhoneAPI::checkIsConnected() {
|
||||
if (bleServer && bleServer->getConnectedCount() > 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PhoneAPI *bluetoothPhoneAPI;
|
||||
|
||||
class ESP32BluetoothToRadioCallback : public NimBLECharacteristicCallbacks {
|
||||
virtual void onWrite(NimBLECharacteristic *pCharacteristic) {
|
||||
DEBUG_MSG("To Radio onwrite\n");
|
||||
auto val = pCharacteristic->getValue();
|
||||
|
||||
bluetoothPhoneAPI->handleToRadio(val.data(), val.length());
|
||||
}
|
||||
};
|
||||
|
||||
class ESP32BluetoothFromRadioCallback : public NimBLECharacteristicCallbacks {
|
||||
virtual void onRead(NimBLECharacteristic *pCharacteristic) {
|
||||
DEBUG_MSG("From Radio onread\n");
|
||||
size_t numBytes = bluetoothPhoneAPI->getFromRadio(fromRadioBytes);
|
||||
|
||||
std::string fromRadioByteString(fromRadioBytes, fromRadioBytes + numBytes);
|
||||
|
||||
pCharacteristic->setValue(fromRadioByteString);
|
||||
}
|
||||
};
|
||||
|
||||
class ESP32BluetoothServerCallback : public NimBLEServerCallbacks {
|
||||
virtual uint32_t onPassKeyRequest() {
|
||||
|
||||
uint32_t passkey = 0;
|
||||
|
||||
if (doublepressed > 0 && (doublepressed + (30 * 1000)) > millis()) {
|
||||
DEBUG_MSG("User has overridden passkey\n");
|
||||
passkey = defaultBLEPin;
|
||||
} else {
|
||||
DEBUG_MSG("Using random passkey\n");
|
||||
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", passkey);
|
||||
|
||||
powerFSM.trigger(EVENT_BLUETOOTH_PAIR);
|
||||
screen->startBluetoothPinScreen(passkey);
|
||||
passkeyShowing = true;
|
||||
|
||||
return passkey;
|
||||
}
|
||||
|
||||
virtual void onAuthenticationComplete(ble_gap_conn_desc *desc) {
|
||||
DEBUG_MSG("BLE authentication complete\n");
|
||||
|
||||
if (passkeyShowing) {
|
||||
passkeyShowing = false;
|
||||
screen->stopBluetoothPinScreen();
|
||||
}
|
||||
}
|
||||
virtual void onDisconnect(NimBLEServer* pServer, ble_gap_conn_desc *desc) {
|
||||
DEBUG_MSG("BLE disconnect\n");
|
||||
}
|
||||
};
|
||||
|
||||
static ESP32BluetoothToRadioCallback *toRadioCallbacks;
|
||||
static ESP32BluetoothFromRadioCallback *fromRadioCallbacks;
|
||||
|
||||
void ESP32Bluetooth::shutdown()
|
||||
{
|
||||
// Shutdown bluetooth for minimum power draw
|
||||
DEBUG_MSG("Disable bluetooth\n");
|
||||
//Bluefruit.Advertising.stop();
|
||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||
pAdvertising->reset();
|
||||
pAdvertising->stop();
|
||||
}
|
||||
|
||||
void ESP32Bluetooth::setup()
|
||||
{
|
||||
// Initialise the Bluefruit module
|
||||
DEBUG_MSG("Initialise the ESP32 bluetooth module\n");
|
||||
//Bluefruit.autoConnLed(false);
|
||||
//Bluefruit.begin();
|
||||
|
||||
// Set the advertised device name (keep it short!)
|
||||
//Bluefruit.setName(getDeviceName());
|
||||
|
||||
// Set the connect/disconnect callback handlers
|
||||
//Bluefruit.Periph.setConnectCallback(connect_callback);
|
||||
//Bluefruit.Periph.setDisconnectCallback(disconnect_callback);
|
||||
|
||||
// Configure and Start the Device Information Service
|
||||
DEBUG_MSG("Configuring the Device Information Service\n");
|
||||
// FIXME, we should set a mfg string based on our HW_VENDOR enum
|
||||
// bledis.setManufacturer(HW_VENDOR);
|
||||
//bledis.setModel(optstr(HW_VERSION));
|
||||
//bledis.setFirmwareRev(optstr(APP_VERSION));
|
||||
//bledis.begin();
|
||||
|
||||
// Start the BLE Battery Service and set it to 100%
|
||||
//DEBUG_MSG("Configuring the Battery Service\n");
|
||||
//blebas.begin();
|
||||
//blebas.write(0); // Unknown battery level for now
|
||||
|
||||
//bledfu.begin(); // Install the DFU helper
|
||||
|
||||
// Setup the Heart Rate Monitor service using
|
||||
// BLEService and BLECharacteristic classes
|
||||
DEBUG_MSG("Configuring the Mesh bluetooth service\n");
|
||||
//setupMeshService();
|
||||
|
||||
// Supposedly debugging works with soft device if you disable advertising
|
||||
//if (isSoftDeviceAllowed) {
|
||||
// Setup the advertising packet(s)
|
||||
// DEBUG_MSG("Setting up the advertising payload(s)\n");
|
||||
// startAdv();
|
||||
|
||||
// DEBUG_MSG("Advertising\n");
|
||||
//}
|
||||
|
||||
//NimBLEDevice::deleteAllBonds();
|
||||
|
||||
NimBLEDevice::init(getDeviceName());
|
||||
NimBLEDevice::setPower(ESP_PWR_LVL_P9);
|
||||
|
||||
NimBLEDevice::setSecurityAuth(true, true, true);
|
||||
NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY);
|
||||
bleServer = NimBLEDevice::createServer();
|
||||
|
||||
ESP32BluetoothServerCallback *serverCallbacks = new ESP32BluetoothServerCallback();
|
||||
bleServer->setCallbacks(serverCallbacks, true);
|
||||
|
||||
NimBLEService *bleService = bleServer->createService(MESH_SERVICE_UUID);
|
||||
//NimBLECharacteristic *pNonSecureCharacteristic = bleService->createCharacteristic("1234", NIMBLE_PROPERTY::READ );
|
||||
//NimBLECharacteristic *pSecureCharacteristic = bleService->createCharacteristic("1235", NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::READ_AUTHEN);
|
||||
|
||||
//define the characteristics that the app is looking for
|
||||
NimBLECharacteristic *ToRadioCharacteristic = bleService->createCharacteristic(TORADIO_UUID, NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_AUTHEN | NIMBLE_PROPERTY::WRITE_ENC);
|
||||
NimBLECharacteristic *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();
|
||||
|
||||
toRadioCallbacks = new ESP32BluetoothToRadioCallback();
|
||||
ToRadioCharacteristic->setCallbacks(toRadioCallbacks);
|
||||
|
||||
fromRadioCallbacks = new ESP32BluetoothFromRadioCallback();
|
||||
FromRadioCharacteristic->setCallbacks(fromRadioCallbacks);
|
||||
|
||||
//uint8_t val[4];
|
||||
//uint32_t zero = 0;
|
||||
//put_le32(val, zero);
|
||||
//std::string fromNumByteString(&val[0], &val[0] + sizeof(val));
|
||||
//FromNumCharacteristic->setValue(fromNumByteString);
|
||||
|
||||
bleService->start();
|
||||
//pNonSecureCharacteristic->setValue("Hello Non Secure BLE");
|
||||
//pSecureCharacteristic->setValue("Hello Secure BLE");
|
||||
|
||||
//FromRadioCharacteristic->setValue("FromRadioString");
|
||||
//ToRadioCharacteristic->setCallbacks()
|
||||
|
||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||
pAdvertising->reset();
|
||||
pAdvertising->addServiceUUID(MESH_SERVICE_UUID);
|
||||
pAdvertising->start(0);
|
||||
}
|
||||
|
||||
|
||||
/// Given a level between 0-100, update the BLE attribute
|
||||
void updateBatteryLevel(uint8_t level)
|
||||
{
|
||||
//blebas.write(level);
|
||||
}
|
||||
|
||||
void ESP32Bluetooth::clearBonds()
|
||||
{
|
||||
DEBUG_MSG("Clearing bluetooth bonds!\n");
|
||||
//bond_print_list(BLE_GAP_ROLE_PERIPH);
|
||||
//bond_print_list(BLE_GAP_ROLE_CENTRAL);
|
||||
|
||||
//Bluefruit.Periph.clearBonds();
|
||||
//Bluefruit.Central.clearBonds();
|
||||
NimBLEDevice::deleteAllBonds();
|
||||
}
|
||||
|
||||
void clearNVS() {
|
||||
NimBLEDevice::deleteAllBonds();
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,33 +0,0 @@
|
||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
||||
|
||||
#pragma once
|
||||
|
||||
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;
|
||||
|
||||
class ESP32Bluetooth
|
||||
{
|
||||
public:
|
||||
void setup();
|
||||
void shutdown();
|
||||
void clearBonds();
|
||||
};
|
||||
|
||||
void setBluetoothEnable(bool on);
|
||||
void clearNVS();
|
||||
void disablePin();
|
||||
|
||||
#endif
|
||||
@@ -1,73 +0,0 @@
|
||||
#ifndef USE_NEW_ESP32_BLUETOOTH
|
||||
#include "BluetoothSoftwareUpdate.h"
|
||||
|
||||
// NRF52 wants these constants as byte arrays
|
||||
// Generated here https://yupana-engineering.com/online-uuid-to-c-array-converter - but in REVERSE BYTE ORDER
|
||||
|
||||
// "cb0b9a0b-a84c-4c0d-bdbb-442e3144ee30"
|
||||
const ble_uuid128_t update_service_uuid =
|
||||
BLE_UUID128_INIT(0x30, 0xee, 0x44, 0x31, 0x2e, 0x44, 0xbb, 0xbd, 0x0d, 0x4c, 0x4c, 0xa8, 0x0b, 0x9a, 0x0b, 0xcb);
|
||||
|
||||
// "e74dd9c0-a301-4a6f-95a1-f0e1dbea8e1e" write|read
|
||||
const ble_uuid128_t update_size_uuid =
|
||||
BLE_UUID128_INIT(0x1e, 0x8e, 0xea, 0xdb, 0xe1, 0xf0, 0xa1, 0x95, 0x6f, 0x4a, 0x01, 0xa3, 0xc0, 0xd9, 0x4d, 0xe7);
|
||||
|
||||
// "e272ebac-d463-4b98-bc84-5cc1a39ee517" write
|
||||
const ble_uuid128_t update_data_uuid =
|
||||
BLE_UUID128_INIT(0x17, 0xe5, 0x9e, 0xa3, 0xc1, 0x5c, 0x84, 0xbc, 0x98, 0x4b, 0x63, 0xd4, 0xac, 0xeb, 0x72, 0xe2);
|
||||
|
||||
// "4826129c-c22a-43a3-b066-ce8f0d5bacc6" write
|
||||
const ble_uuid128_t update_crc32_uuid =
|
||||
BLE_UUID128_INIT(0xc6, 0xac, 0x5b, 0x0d, 0x8f, 0xce, 0x66, 0xb0, 0xa3, 0x43, 0x2a, 0xc2, 0x9c, 0x12, 0x26, 0x48);
|
||||
|
||||
// "5e134862-7411-4424-ac4a-210937432c77" read|notify
|
||||
const ble_uuid128_t update_result_uuid =
|
||||
BLE_UUID128_INIT(0x77, 0x2c, 0x43, 0x37, 0x09, 0x21, 0x4a, 0xac, 0x24, 0x44, 0x11, 0x74, 0x62, 0x48, 0x13, 0x5e);
|
||||
|
||||
// "5e134862-7411-4424-ac4a-210937432c67" write
|
||||
const ble_uuid128_t update_region_uuid =
|
||||
BLE_UUID128_INIT(0x67, 0x2c, 0x43, 0x37, 0x09, 0x21, 0x4a, 0xac, 0x24, 0x44, 0x11, 0x74, 0x62, 0x48, 0x13, 0x5e);
|
||||
|
||||
const struct ble_gatt_svc_def gatt_update_svcs[] = {
|
||||
{
|
||||
/*** Service: Security test. */
|
||||
.type = BLE_GATT_SVC_TYPE_PRIMARY,
|
||||
.uuid = &update_service_uuid.u,
|
||||
.characteristics =
|
||||
(struct ble_gatt_chr_def[]){{
|
||||
.uuid = &update_size_uuid.u,
|
||||
.access_cb = update_size_callback,
|
||||
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_AUTHEN | BLE_GATT_CHR_F_READ |
|
||||
BLE_GATT_CHR_F_READ_AUTHEN,
|
||||
},
|
||||
{
|
||||
.uuid = &update_data_uuid.u,
|
||||
.access_cb = update_data_callback,
|
||||
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_AUTHEN,
|
||||
},
|
||||
{
|
||||
.uuid = &update_crc32_uuid.u,
|
||||
.access_cb = update_crc32_callback,
|
||||
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_AUTHEN,
|
||||
},
|
||||
{
|
||||
.uuid = &update_result_uuid.u,
|
||||
.access_cb = update_result_callback,
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_NOTIFY,
|
||||
},
|
||||
{
|
||||
.uuid = &update_region_uuid.u,
|
||||
.access_cb = update_region_callback,
|
||||
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_AUTHEN,
|
||||
},
|
||||
{
|
||||
0, /* No more characteristics in this service. */
|
||||
}},
|
||||
},
|
||||
|
||||
{
|
||||
0, /* No more services. */
|
||||
},
|
||||
};
|
||||
|
||||
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
|
||||
@@ -6,6 +6,9 @@
|
||||
// defaults for ESP32 architecture
|
||||
//
|
||||
|
||||
#ifndef HAS_BLUETOOTH
|
||||
#define HAS_BLUETOOTH 1
|
||||
#endif
|
||||
#ifndef HAS_WIFI
|
||||
#define HAS_WIFI 1
|
||||
#endif
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
#include "BluetoothSoftwareUpdate.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "configuration.h"
|
||||
#include "esp_task_wdt.h"
|
||||
#include "main.h"
|
||||
|
||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
||||
#include "ESP32Bluetooth.h"
|
||||
#include "nimble/NimbleBluetooth.h"
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
#else
|
||||
#include "nimble/BluetoothUtil.h"
|
||||
#endif
|
||||
|
||||
#include "sleep.h"
|
||||
#include "target_specific.h"
|
||||
@@ -19,41 +14,26 @@
|
||||
#include <nvs.h>
|
||||
#include <nvs_flash.h>
|
||||
|
||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
||||
ESP32Bluetooth *esp32Bluetooth;
|
||||
#endif
|
||||
NimbleBluetooth *nimbleBluetooth;
|
||||
|
||||
void getMacAddr(uint8_t *dmac)
|
||||
{
|
||||
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) {
|
||||
|
||||
if (!isWifiAvailable()) {
|
||||
if (!esp32Bluetooth) {
|
||||
esp32Bluetooth = new ESP32Bluetooth();
|
||||
if (!isWifiAvailable() && config.bluetooth.enabled == true) {
|
||||
if (!nimbleBluetooth) {
|
||||
nimbleBluetooth = new NimbleBluetooth();
|
||||
}
|
||||
if (on) {
|
||||
esp32Bluetooth->setup();
|
||||
if (on && !nimbleBluetooth->isActive()) {
|
||||
nimbleBluetooth->setup();
|
||||
} else {
|
||||
esp32Bluetooth->shutdown();
|
||||
nimbleBluetooth->shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void esp32Setup()
|
||||
{
|
||||
@@ -123,7 +103,6 @@ Periodic axpDebugOutput(axpDebugRead);
|
||||
void esp32Loop()
|
||||
{
|
||||
esp_task_wdt_reset(); // service our app level watchdog
|
||||
//loopBLE();
|
||||
|
||||
// for debug printing
|
||||
// radio.radioIf.canSleep();
|
||||
|
||||
@@ -23,6 +23,7 @@ static uint8_t fromRadioBytes[FromRadio_size];
|
||||
static uint8_t toRadioBytes[ToRadio_size];
|
||||
|
||||
static bool bleConnected;
|
||||
static uint16_t connectionHandle;
|
||||
|
||||
class BluetoothPhoneAPI : public PhoneAPI
|
||||
{
|
||||
@@ -39,13 +40,14 @@ class BluetoothPhoneAPI : public PhoneAPI
|
||||
|
||||
/// Check the current underlying physical link to see if the client is currently connected
|
||||
virtual bool checkIsConnected() override {
|
||||
return bleConnected;
|
||||
BLEConnection *connection = Bluefruit.Connection(connectionHandle);
|
||||
return connection->connected();
|
||||
}
|
||||
};
|
||||
|
||||
static BluetoothPhoneAPI *bluetoothPhoneAPI;
|
||||
|
||||
void connect_callback(uint16_t conn_handle)
|
||||
void onConnect(uint16_t conn_handle)
|
||||
{
|
||||
// Get the reference to current connection
|
||||
BLEConnection *connection = Bluefruit.Connection(conn_handle);
|
||||
@@ -62,7 +64,7 @@ void connect_callback(uint16_t conn_handle)
|
||||
* @param conn_handle connection where this event happens
|
||||
* @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;
|
||||
@@ -70,7 +72,7 @@ void disconnect_callback(uint16_t conn_handle, uint8_t 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
|
||||
DEBUG_MSG("CCCD Updated: %u\n", cccd_value);
|
||||
@@ -126,16 +128,12 @@ static void authorizeRead(uint16_t conn_hdl)
|
||||
/**
|
||||
* 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 onFromRadioAuthorize(uint16_t conn_hdl, BLECharacteristic *chr, ble_gatts_evt_read_t *request)
|
||||
{
|
||||
if (request->offset == 0) {
|
||||
// If the read is long, we will get multiple authorize invocations - we only populate data on the first
|
||||
|
||||
size_t numBytes = bluetoothPhoneAPI->getFromRadio(fromRadioBytes);
|
||||
|
||||
// DEBUG_MSG("fromRadioAuthorizeCb numBytes=%u\n", numBytes);
|
||||
// if (numBytes >= 2) DEBUG_MSG("fromRadio bytes %x %x\n", fromRadioBytes[0], fromRadioBytes[1]);
|
||||
|
||||
// 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
|
||||
fromRadio.write(fromRadioBytes, numBytes);
|
||||
@@ -145,7 +143,7 @@ void fromRadioAuthorizeCb(uint16_t conn_hdl, BLECharacteristic *chr, ble_gatts_e
|
||||
authorizeRead(conn_hdl);
|
||||
}
|
||||
|
||||
void toRadioWriteCb(uint16_t conn_hdl, BLECharacteristic *chr, uint8_t *data, uint16_t len)
|
||||
void onToRadioWrite(uint16_t conn_hdl, BLECharacteristic *chr, uint8_t *data, uint16_t len)
|
||||
{
|
||||
DEBUG_MSG("toRadioWriteCb data %p, len %u\n", data, len);
|
||||
|
||||
@@ -155,7 +153,7 @@ void toRadioWriteCb(uint16_t conn_hdl, BLECharacteristic *chr, uint8_t *data, ui
|
||||
/**
|
||||
* 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");
|
||||
|
||||
@@ -172,44 +170,39 @@ void setupMeshService(void)
|
||||
// any characteristic(s) within that service definition.. Calling .begin() on
|
||||
// a BLECharacteristic will cause it to be added to the last BLEService that
|
||||
// was 'begin()'ed!
|
||||
auto secMode = config.bluetooth.mode == Config_BluetoothConfig_PairingMode_NoPin ? SECMODE_OPEN : SECMODE_ENC_NO_MITM;
|
||||
|
||||
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.setPermission(secMode, 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.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
|
||||
// fromNum.setReadAuthorizeCallback(fromNumAuthorizeCb);
|
||||
fromNum.write32(0); // Provide default fromNum of 0
|
||||
fromNum.begin();
|
||||
// uint8_t hrmdata[2] = {0b00000110, 0x40}; // Set the characteristic to use 8-bit values, with the sensor connected and
|
||||
// detected
|
||||
// hrmc.write(hrmdata, 2);
|
||||
|
||||
fromRadio.setProperties(CHR_PROPS_READ);
|
||||
fromRadio.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); // FIXME secure this!
|
||||
fromRadio.setPermission(secMode, SECMODE_NO_ACCESS);
|
||||
fromRadio.setMaxLen(sizeof(fromRadioBytes));
|
||||
fromRadio.setReadAuthorizeCallback(
|
||||
fromRadioAuthorizeCb,
|
||||
false); // We don't call this callback via the adafruit queue, because we can safely run in the BLE context
|
||||
fromRadio.setReadAuthorizeCallback(onFromRadioAuthorize, 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
|
||||
// for two copies
|
||||
fromRadio.begin();
|
||||
|
||||
toRadio.setProperties(CHR_PROPS_WRITE);
|
||||
toRadio.setPermission(SECMODE_OPEN, SECMODE_OPEN); // FIXME secure this!
|
||||
toRadio.setPermission(secMode, secMode); // FIXME secure this!
|
||||
toRadio.setFixedLen(0);
|
||||
toRadio.setMaxLen(512);
|
||||
toRadio.setBuffer(toRadioBytes, sizeof(toRadioBytes));
|
||||
toRadio.setWriteCallback(
|
||||
toRadioWriteCb,
|
||||
false); // 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(onToRadioWrite, false);
|
||||
toRadio.begin();
|
||||
}
|
||||
|
||||
// FIXME, turn off soft device access for debugging
|
||||
static bool isSoftDeviceAllowed = true;
|
||||
static uint32_t configuredPasskey;
|
||||
|
||||
void NRF52Bluetooth::shutdown()
|
||||
{
|
||||
@@ -221,8 +214,9 @@ void NRF52Bluetooth::shutdown()
|
||||
void NRF52Bluetooth::setup()
|
||||
{
|
||||
// Initialise the Bluefruit module
|
||||
DEBUG_MSG("Initialise the Bluefruit nRF52 module\n");
|
||||
DEBUG_MSG("Initialize the Bluefruit nRF52 module\n");
|
||||
Bluefruit.autoConnLed(false);
|
||||
Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
|
||||
Bluefruit.begin();
|
||||
|
||||
// Clear existing data.
|
||||
@@ -230,17 +224,31 @@ void NRF52Bluetooth::setup()
|
||||
Bluefruit.Advertising.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!)
|
||||
Bluefruit.setName(getDeviceName());
|
||||
|
||||
// Set the connect/disconnect callback handlers
|
||||
Bluefruit.Periph.setConnectCallback(connect_callback);
|
||||
Bluefruit.Periph.setDisconnectCallback(disconnect_callback);
|
||||
Bluefruit.Periph.setConnectCallback(onConnect);
|
||||
Bluefruit.Periph.setDisconnectCallback(onDisconnect);
|
||||
|
||||
// Configure and Start the Device Information Service
|
||||
DEBUG_MSG("Configuring the Device Information Service\n");
|
||||
// FIXME, we should set a mfg string based on our HW_VENDOR enum
|
||||
// bledis.setManufacturer(HW_VENDOR);
|
||||
bledis.setModel(optstr(HW_VERSION));
|
||||
bledis.setFirmwareRev(optstr(APP_VERSION));
|
||||
bledis.begin();
|
||||
@@ -249,7 +257,6 @@ void NRF52Bluetooth::setup()
|
||||
DEBUG_MSG("Configuring the Battery Service\n");
|
||||
blebas.begin();
|
||||
blebas.write(0); // Unknown battery level for now
|
||||
|
||||
bledfu.begin(); // Install the DFU helper
|
||||
|
||||
// Setup the Heart Rate Monitor service using
|
||||
@@ -258,7 +265,8 @@ void NRF52Bluetooth::setup()
|
||||
setupMeshService();
|
||||
|
||||
// Supposedly debugging works with soft device if you disable advertising
|
||||
if (isSoftDeviceAllowed) {
|
||||
if (isSoftDeviceAllowed)
|
||||
{
|
||||
// Setup the advertising packet(s)
|
||||
DEBUG_MSG("Setting up the advertising payload(s)\n");
|
||||
startAdv();
|
||||
@@ -282,3 +290,36 @@ void NRF52Bluetooth::clearBonds()
|
||||
Bluefruit.Periph.clearBonds();
|
||||
Bluefruit.Central.clearBonds();
|
||||
}
|
||||
|
||||
void NRF52Bluetooth::onConnectionSecured(uint16_t conn_handle)
|
||||
{
|
||||
DEBUG_MSG("BLE connection secured\n");
|
||||
//bluetoothPhoneAPI->setInitialState();
|
||||
}
|
||||
|
||||
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 shutdown();
|
||||
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
|
||||
//
|
||||
|
||||
#ifndef HAS_BLUETOOTH
|
||||
#define HAS_BLUETOOTH 1
|
||||
#endif
|
||||
#ifndef HAS_SCREEN
|
||||
#define HAS_SCREEN 1
|
||||
#endif
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <stdio.h>
|
||||
#include <Adafruit_nRFCrypto.h>
|
||||
// #include <Adafruit_USBD_Device.h>
|
||||
#include "NodeDB.h"
|
||||
|
||||
#include "NRF52Bluetooth.h"
|
||||
#include "error.h"
|
||||
@@ -68,7 +69,7 @@ static const bool useSoftDevice = true; // Set to false for easier debugging
|
||||
|
||||
void setBluetoothEnable(bool on)
|
||||
{
|
||||
if (on != bleOn) {
|
||||
if (on != bleOn && config.bluetooth.enabled == true) {
|
||||
if (on) {
|
||||
if (!nrf52Bluetooth) {
|
||||
if (!useSoftDevice)
|
||||
@@ -81,9 +82,8 @@ void setBluetoothEnable(bool on)
|
||||
initBrownout();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (nrf52Bluetooth)
|
||||
nrf52Bluetooth->shutdown();
|
||||
} else if (nrf52Bluetooth) {
|
||||
nrf52Bluetooth->shutdown();
|
||||
}
|
||||
bleOn = on;
|
||||
}
|
||||
|
||||
36
src/platform/stm32wl/STM32WLCryptoEngine.cpp
Normal file
36
src/platform/stm32wl/STM32WLCryptoEngine.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "configuration.h"
|
||||
#include "CryptoEngine.h"
|
||||
#include "aes.hpp"
|
||||
|
||||
class STM32WLCryptoEngine : public CryptoEngine
|
||||
{
|
||||
public:
|
||||
STM32WLCryptoEngine() {}
|
||||
|
||||
~STM32WLCryptoEngine() {}
|
||||
|
||||
/**
|
||||
* Encrypt a packet
|
||||
*
|
||||
* @param bytes is updated in place
|
||||
*/
|
||||
virtual void encrypt(uint32_t fromNode, uint64_t packetNum, size_t numBytes, uint8_t *bytes) override
|
||||
{
|
||||
if (key.length > 0) {
|
||||
AES_ctx ctx;
|
||||
initNonce(fromNode, packetNum);
|
||||
AES_init_ctx_iv(&ctx, key.bytes, nonce);
|
||||
AES_CTR_xcrypt_buffer(&ctx, bytes, numBytes);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void decrypt(uint32_t fromNode, uint64_t packetNum, size_t numBytes, uint8_t *bytes) override
|
||||
{
|
||||
// For CTR, the implementation is the same
|
||||
encrypt(fromNode, packetNum, numBytes, bytes);
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
CryptoEngine *crypto = new STM32WLCryptoEngine();
|
||||
31
src/platform/stm32wl/architecture.h
Normal file
31
src/platform/stm32wl/architecture.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#define ARCH_STM32WL
|
||||
|
||||
//
|
||||
// defaults for STM32WL architecture
|
||||
//
|
||||
|
||||
//
|
||||
// set HW_VENDOR
|
||||
//
|
||||
|
||||
#ifndef HW_VENDOR
|
||||
#define HW_VENDOR HardwareModel_PRIVATE_HW
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void stm32wl_emulate_digitalWrite(long unsigned int pin, long unsigned int value);
|
||||
int stm32wl_emulate_digitalRead(long unsigned int pin);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* virtual pins for stm32wl_emulate_digitalWrite() / stm32wl_emulate_digitalRead() to recognize */
|
||||
#define SX126X_CS 1000
|
||||
#define SX126X_DIO1 1001
|
||||
#define SX126X_RESET 1003
|
||||
#define SX126X_BUSY 1004
|
||||
|
||||
67
src/platform/stm32wl/layer.c
Normal file
67
src/platform/stm32wl/layer.c
Normal file
@@ -0,0 +1,67 @@
|
||||
#include <stdbool.h>
|
||||
#include "architecture.h"
|
||||
#include "stm32wlxx.h"
|
||||
#include "stm32wlxx_hal.h"
|
||||
|
||||
void HardFault_Handler(void)
|
||||
{
|
||||
asm("bkpt");
|
||||
}
|
||||
|
||||
void stm32wl_emulate_digitalWrite(long unsigned int pin, long unsigned int value)
|
||||
{
|
||||
switch (pin)
|
||||
{
|
||||
case SX126X_CS: /* active low */
|
||||
if (value)
|
||||
LL_PWR_UnselectSUBGHZSPI_NSS();
|
||||
else
|
||||
LL_PWR_SelectSUBGHZSPI_NSS();
|
||||
break;
|
||||
case SX126X_RESET: /* active low */
|
||||
if (value)
|
||||
LL_RCC_RF_DisableReset();
|
||||
else
|
||||
{
|
||||
LL_RCC_RF_EnableReset();
|
||||
LL_RCC_HSE_EnableTcxo();
|
||||
LL_RCC_HSE_Enable();
|
||||
while (!LL_RCC_HSE_IsReady());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
asm("bkpt");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool irq_happened;
|
||||
|
||||
void SUBGHZ_Radio_IRQHandler(void)
|
||||
{
|
||||
NVIC_DisableIRQ(SUBGHZ_Radio_IRQn);
|
||||
irq_happened = true;
|
||||
}
|
||||
|
||||
int stm32wl_emulate_digitalRead(long unsigned int pin)
|
||||
{
|
||||
int outcome = 0;
|
||||
|
||||
switch (pin)
|
||||
{
|
||||
case SX126X_BUSY:
|
||||
// return ((LL_PWR_IsActiveFlag_RFBUSYMS() & LL_PWR_IsActiveFlag_RFBUSYS()) == 1UL);
|
||||
outcome = LL_PWR_IsActiveFlag_RFBUSYS();
|
||||
break;
|
||||
case SX126X_DIO1:
|
||||
default:
|
||||
NVIC_ClearPendingIRQ(SUBGHZ_Radio_IRQn);
|
||||
irq_happened = false;
|
||||
NVIC_EnableIRQ(SUBGHZ_Radio_IRQn);
|
||||
for (int i = 0; i < 64; i++) asm("nop");
|
||||
outcome = irq_happened;
|
||||
break;
|
||||
}
|
||||
return outcome;
|
||||
}
|
||||
|
||||
27
src/platform/stm32wl/main-stm32wl.cpp
Normal file
27
src/platform/stm32wl/main-stm32wl.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include <stm32wle5xx.h>
|
||||
#include <stm32wlxx_hal.h>
|
||||
#include "configuration.h"
|
||||
#include "RTC.h"
|
||||
|
||||
void setBluetoothEnable(bool on) {}
|
||||
|
||||
void playStartMelody() {}
|
||||
|
||||
void updateBatteryLevel(uint8_t level) {}
|
||||
|
||||
void getMacAddr(uint8_t *dmac)
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
dmac[i] = i;
|
||||
}
|
||||
|
||||
void cpuDeepSleep(uint64_t msecToWake) {}
|
||||
|
||||
/* pacify libc_nano */
|
||||
extern "C" {
|
||||
int _gettimeofday( struct timeval *tv, void *tzvp )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
#include <driver/rtc_io.h>
|
||||
#include <driver/uart.h>
|
||||
|
||||
#include "nimble/BluetoothUtil.h"
|
||||
|
||||
esp_sleep_source_t wakeCause; // the reason we booted this time
|
||||
#endif
|
||||
|
||||
|
||||
4
variants/wio-e5/platformio.ini
Normal file
4
variants/wio-e5/platformio.ini
Normal file
@@ -0,0 +1,4 @@
|
||||
[env:wio-e5]
|
||||
extends = stm32wl5e_base
|
||||
build_flags = ${stm32wl5e_base.build_flags} -Ivariants/wio-e5 -DHAL_DAC_MODULE_ONLY
|
||||
-DSERIAL_UART_INSTANCE=1 -DPIN_SERIAL_RX=PB7 -DPIN_SERIAL_TX=PB6
|
||||
29
variants/wio-e5/variant.h
Normal file
29
variants/wio-e5/variant.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Wio-E5 mini (formerly LoRa-E5 mini)
|
||||
https://www.seeedstudio.com/LoRa-E5-mini-STM32WLE5JC-p-4869.html
|
||||
https://www.seeedstudio.com/LoRa-E5-Wireless-Module-p-4745.html
|
||||
*/
|
||||
|
||||
/*
|
||||
This variant is a work in progress.
|
||||
Do not expect a working Meshtastic device with this target.
|
||||
*/
|
||||
|
||||
#ifndef _VARIANT_WIOE5_
|
||||
#define _VARIANT_WIOE5_
|
||||
|
||||
//Arduino/PlatformIO support for SUBGHZSPI is not currently available
|
||||
//#define USE_SX1262
|
||||
|
||||
#ifdef USE_SX1262
|
||||
#define HAS_RADIO 1
|
||||
|
||||
/* module only transmits through RFO_HP */
|
||||
#define SX126X_RXEN PA5
|
||||
#define SX126X_TXEN PA4
|
||||
|
||||
/* TCXO fed by internal LDO option behind PB0 pin */
|
||||
#define SX126X_E22
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
[VERSION]
|
||||
major = 1
|
||||
minor = 3
|
||||
build = 36
|
||||
build = 39
|
||||
|
||||
Reference in New Issue
Block a user