Compare commits

...

113 Commits

Author SHA1 Message Date
Ben Meadors
e87ecc210a Wifi enabled plumbed in (#1677)
* Wifi enabled

* Wifi requires reboot

* Increment DEVICESTATE_CUR_VER
2022-09-06 14:06:44 -05:00
Vladislav Osmanov
cb3010b58c OLED Cyrillic Support for v1.3 (#1640)
* Extended ASCII codes and cyrillic support

(cherry picked from commit e977840805)

* Fixed `ё`, `Ё` letters

(cherry picked from commit 2f4a2ccb2f)

* Fixed `customFontTableLookup` execution flow

(cherry picked from commit 377f909f36)

* [OLED] Specifying the language by defining it in `platformio.ini`

(cherry picked from commit ddd8132b24)

* [OLED] localization guide

(cherry picked from commit a3267c886f)

* [OLED] Cyrillic support

Localization guide has been moved to https://github.com/meshtastic/Meshtastic/tree/master/docs/developers/Firmware

https://meshtastic.org/docs/developers/Firmware/oled-l10n-guide

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2022-09-04 15:00:10 -05:00
Ben Meadors
285ba9639e Fix screen on secs (#1673)
* Fix screen on secs

* getIntervalOrDefaultMs

* Display correction

* Paren
2022-09-03 22:10:11 -05:00
Ben Meadors
84e438f72f Mqtt json_enabled (#1672)
* Payload variants

* Waypoints and fixes

* Remove json send to mesh. I think protobuf messages already do that

* whoops

* Added json_enabled mqtt config
2022-09-03 14:06:10 -05:00
lewis he
8fb8212434 i2cScan probe adds another ssd1306 subclass new to output logs correctly (#1671) 2022-09-03 07:26:49 -05:00
Neil Hao
70e1a208d5 'snow_screen_hotfix' (#1670) 2022-09-02 19:43:33 -05:00
Ben Meadors
9d3cac7cdb MQTT Json Payload variants (#1667)
* Payload variants

* Waypoints and fixes

* Remove json send to mesh. I think protobuf messages already do that

* whoops
2022-09-01 17:54:24 -05:00
Thomas Göttgens
221843e176 Merge pull request #1663 from lewisxhe/master 2022-08-30 20:27:41 +02:00
lewishe
1922034c44 Add t-beam sx1268 support 2022-08-30 11:59:57 +08:00
Ben Meadors
7f586f7099 Better logging and cleanup (#1662) 2022-08-29 07:31:02 -05:00
lewis he
0efa1b25c5 Add t-echo sx1268 support (#1657) 2022-08-29 07:26:17 -05:00
Tom
fd27a40edb Reboot after factory reset (#1653)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2022-08-25 12:07:20 -05:00
Ben Meadors
1013aff9b6 Screen changes and fixes (#1651)
* Fixed bluetooth reinit bug

* Remove screen transition ms

* Whoops

* hasScreen is smarter now

* Oops
2022-08-25 11:25:05 -05:00
Ben Meadors
d7e5eb4d22 Upgrade unishox-2 to 1.0.3 (#1650) 2022-08-25 07:12:38 -05:00
Ben Meadors
9a03b2e49d Same as NodeDB position_broadcast_secs bug but different (#1645)
* intervalMs
2022-08-24 17:29:09 -05:00
github-actions[bot]
e7831f13c5 [create-pull-request] automated change (#1641)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2022-08-24 17:28:43 -05:00
Ben Meadors
ddc3727155 Fixed NRF52 bluetooth 2022-08-23 14:03:10 -05:00
Ben Meadors
ef9bfc9104 Enable external notification module for nrf52 2022-08-23 13:16:20 -05:00
Ben Meadors
3bb645d4fe Fixed huge nodeinfo bug 2022-08-23 13:12:41 -05:00
Ben Meadors
8f99258fc4 Update main_matrix.yml 2022-08-22 18:31:56 -05:00
Ben Meadors
b54073a8a1 Bluetooth mode unification and behavior tweaks (#1636)
* Esp32 bluetooth modes

* Comment

* Gutting bluetooth

* Cleanup

* Security

* Testing

* NRF bluetooth security

* Reboot on saved lora or bluetooth settings

* Cleanup

* Fixes

* Stub for platforms without screens

* Fixed just-works in esp32

* Cleanup

* Display device name in boot screen

* Added waypoint module routing

* chmod

* Words

* Protos

* Backing out partition changes for testing

* Revert "Backing out partition changes for testing"

This reverts commit 191ed6489c.

* Chmod PR artifacts

* Trying setInitialState again

* Revert "Trying setInitialState again"

This reverts commit 703eac7277.

* External notification module

* Cleanup

* Pin display formatting
2022-08-22 16:41:23 -05:00
Ben Meadors
c85e9f53c7 Chmod PR artifacts 2022-08-20 12:53:34 -05:00
Ben Meadors
4cfc229e77 Update device-update.sh 2022-08-19 13:35:54 -05:00
Ben Meadors
bbd7c5063d Removed ota erasure 2022-08-19 13:34:41 -05:00
Ben Meadors
05df849a6d Repartitioned 2022-08-19 13:33:58 -05:00
Ben Meadors
ccbc01a753 Repartitioned 2022-08-19 13:33:02 -05:00
Sacha Weatherstone
d6d936b5d2 Remove OTA partition (#1635) 2022-08-18 16:19:32 -05:00
Ben Meadors
b028af0d82 Bluetooth modes (#1633)
* Formatting and comments

* Esp32 bluetooth modes

* Comment
2022-08-16 20:42:43 -05:00
Ben Meadors
86d3759f55 New bluetooth config protos and canned messages consolidation (#1632)
* Bluetooth and canned messages refactor

* More can of worms messages

* Set has_bluetooth and default pin

* Defaults
2022-08-15 21:06:55 -05:00
majbthrd
aadaf332cf add stm32wl5e platform and wio-e5 variant (#1631)
Co-authored-by: Peter Lawrence <12226419+majbthrd@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2022-08-15 07:54:45 -05:00
Ben Meadors
4dea95d03f Update version.properties 2022-08-14 20:22:52 -05:00
Ben Meadors
1253abd138 Syntax error 2022-08-14 15:56:55 -05:00
Ben Meadors
80e3cee006 NimBLE enhanced logging (do not merge) (#1629)
* Change log level to debug

* Don't reinit active bluetooth services

* Chmod +x before zip and adding to release
2022-08-14 15:27:21 -05:00
Ben Meadors
ca9113ad05 Update version.properties 2022-08-14 15:16:47 -05:00
GUVWAF
63c8f15d38 Resend implicit ACK for a repeated broadcast (#1628) 2022-08-13 10:09:43 -05:00
Ben Meadors
73a1ea59f4 Update BMP280Sensor.cpp (#1627) 2022-08-12 20:11:32 -05:00
Ben Meadors
97712a9dc4 Update ESP32Bluetooth.cpp (#1625)
* Update ESP32Bluetooth.cpp

* Update ESP32Bluetooth.h
2022-08-12 14:14:14 -05:00
Ben Meadors
20e43fcf34 Update version.properties 2022-08-12 13:55:02 -05:00
majbthrd
f66c8572b4 use fixed-size buffer in RedirectablePrint::vprintf() (#1622)
Co-authored-by: Peter Lawrence <12226419+majbthrd@users.noreply.github.com>
Co-authored-by: Garth Vander Houwen <garthvh@yahoo.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2022-08-12 13:41:16 -05:00
Ben Meadors
64f852e3f7 Update main_matrix.yml 2022-08-12 07:21:20 -05:00
Ben Meadors
ea90e4d2de Update main_matrix.yml 2022-08-12 07:04:36 -05:00
Ben Meadors
dd720f2fe6 Tweak 2022-08-11 19:23:51 -05:00
Ben Meadors
808fef7e91 Update main_matrix.yml 2022-08-11 18:50:02 -05:00
Ben Meadors
70e6dc3c67 chmod 2022-08-11 17:54:48 -05:00
Ben Meadors
279149e40f version.properties bump 2022-08-11 17:35:32 -05:00
Ben Meadors
4588995fba Chmod bump_version 2022-08-11 16:30:22 -05:00
Ben Meadors
11ae248c5e Update main_matrix.yml 2022-08-11 16:19:27 -05:00
Ben Meadors
a0a5147c42 Update main_matrix.yml 2022-08-11 15:58:16 -05:00
Ben Meadors
b8aac2c5b6 Create bump_version.py 2022-08-11 15:27:44 -05:00
Ben Meadors
de22f20876 Turn region screen back on (#1621) 2022-08-11 14:24:35 -05:00
Ben Meadors
9b5211dc65 Syntax 2022-08-11 09:03:18 -05:00
Ben Meadors
0b4fb72d58 Guard the assets (#1618)
* Guard the assets

* Indicated legacy build-all

* Hopefully fixed
2022-08-11 08:56:38 -05:00
Ben Meadors
7e03019cc4 Zip elfs 2022-08-11 07:22:19 -05:00
Ben Meadors
780f4383f4 Trying elves again 2022-08-11 07:07:04 -05:00
Ben Meadors
8148f06773 Paths 2022-08-10 20:59:45 -05:00
Ben Meadors
d5780af362 Elves live in trees 2022-08-10 20:24:37 -05:00
Ben Meadors
82ed7a2084 Elves are released 2022-08-10 20:09:01 -05:00
Ben Meadors
dd5fd3744d Debug elfs 2022-08-10 19:25:27 -05:00
Ben Meadors
afb5fca6e1 Correct path 2022-08-10 19:21:59 -05:00
Ben Meadors
95d75fdfee Bins 2022-08-10 19:06:31 -05:00
Ben Meadors
029a6b16ba Release the correct archiva 2022-08-10 18:47:06 -05:00
Ben Meadors
9be3099ca6 Remove release workflow 2022-08-10 18:10:15 -05:00
Ben Meadors
b6126e6e63 Disable release workflow 2022-08-10 18:07:11 -05:00
Ben Meadors
d6dfdc314e Update version.properties 2022-08-10 18:05:32 -05:00
Ben Meadors
78666e9b36 Oops 2022-08-10 18:00:41 -05:00
Ben Meadors
3abba0ce39 Release in CI hopefully 2022-08-10 17:59:47 -05:00
Ben Meadors
2c8e030b3d Bump whitespace for build 2022-08-10 16:32:27 -05:00
Ben Meadors
eed7408f00 Remove checks from pico for now 2022-08-10 16:28:11 -05:00
Ben Meadors
cabd1eb8c0 plz work 2022-08-10 16:17:49 -05:00
Ben Meadors
f46c11a047 Line break 2022-08-10 16:12:35 -05:00
Ben Meadors
cdd5e16e25 Path 2022-08-10 16:10:03 -05:00
Ben Meadors
a6c9a819f8 Chmod path 2022-08-10 16:05:10 -05:00
Ben Meadors
2e72397898 Chmod 2022-08-10 16:03:41 -05:00
Ben Meadors
f554226226 Add print back 2022-08-10 15:53:19 -05:00
Ben Meadors
2d1897a36f chmod 2022-08-10 15:52:53 -05:00
Ben Meadors
fe1ed3f284 Pico build in PR (#1617)
* Pico build in PR

* Missed refs

* Update main_matrix.yml
2022-08-10 15:33:42 -05:00
Ben Meadors
3251cd510a Bump version 2022-08-10 13:11:32 -05:00
Ben Meadors
7d0411cd15 Esp32 NimBLE experiments (#1613)
* Delete callbacks on bleServer on destruct

* Trying things
2022-08-10 12:44:52 -05:00
Thomas Göttgens
1d1ccd6b19 Merge pull request #1615 from meshtastic/src-cleanup
Put a bit of order in the src directory
2022-08-10 16:04:44 +02:00
Thomas Göttgens
3b8566747c Merge branch 'master' into src-cleanup 2022-08-10 15:47:08 +02:00
Thomas Göttgens
3cc584d855 Merge pull request #1616 from neilhao/master
'Station-g1-patch1'
2022-08-10 15:46:26 +02:00
neil
90d3cc2ff8 'Station-g1-patch1' 2022-08-10 19:26:43 +08:00
Thomas Göttgens
d125b0ec3c Merge branch 'master' into src-cleanup 2022-08-10 11:39:47 +02:00
Thomas Göttgens
5e842dd735 Put a bit of order in the src directory, group and name things appropriately 2022-08-10 11:31:29 +02:00
Thomas Göttgens
bbc0baa31d Merge pull request #1611 from meshtastic/RP2040-Platform
Raspberry Pi Pico target (with sparkfun lora hat)
2022-08-10 10:14:43 +02:00
Thomas Göttgens
31788feab1 Update platformio.ini 2022-08-10 10:03:47 +02:00
Thomas Göttgens
2c37be58ac Merge branch 'RP2040-Platform' of github.com:meshtastic/Meshtastic-device 2022-08-10 10:01:58 +02:00
Thomas Göttgens
836782b3c1 Merge branch 'master' into RP2040-Platform 2022-08-10 10:01:36 +02:00
Thomas Göttgens
cfc44cd608 Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-08-10 10:00:40 +02:00
Thomas Göttgens
519f31ed60 fix portduino build 2022-08-10 10:00:23 +02:00
Sacha Weatherstone
e04d6b3f56 Update protobufs 2022-08-09 12:22:46 +10:00
Thomas Göttgens
25c851a929 Merge branch 'master' into RP2040-Platform 2022-08-08 23:17:33 +02:00
Thomas Göttgens
0c8fb6e27f Raspberry Pi Pico target (with sparkfun lora hat) does compile but needs further work.
Also contains a small fix to make PRIVATE_HW targets build again for nRF52 architectures
2022-08-08 23:11:19 +02:00
Thomas Göttgens
8490bdd14e Merge pull request #1609 from meshtastic/AXP192-CLEANUP
Axp192 cleanup
2022-08-08 16:50:57 +02:00
Thomas Göttgens
22a5cf04d3 Another one. 2022-08-08 16:29:34 +02:00
Thomas Göttgens
ddc5a59ece Missed one or two 2022-08-08 16:16:50 +02:00
Thomas Göttgens
6382f67b89 Replace TBEAM_V10 macro guards with more appropriate HAS_AXP192. Also eliminates symbol redefinition of AXP192_SLAVE_ADDRESS 2022-08-08 16:13:38 +02:00
Ben Meadors
401b5d92aa 1.3.34 2022-08-08 07:29:36 -05:00
Ben Meadors
572f9f9295 Get device metadata admin message (#1607)
* Get device metadata admin message

* Bump device state version
2022-08-08 07:19:04 -05:00
Thomas Göttgens
96ce40040c Merge pull request #1608 from meshtastic/compass-orientation
wire in compass display setting
2022-08-08 09:30:30 +02:00
Thomas Göttgens
d0a1aad7d1 wire in compass display setting 2022-08-08 09:00:29 +02:00
Ben Meadors
ab0095cb05 1.3.33 release 2022-08-07 16:06:18 -05:00
Ben Meadors
591ae7a803 Change state order to send node info before config (#1606)
* Change state order to send node info before config

* Kill groups
2022-08-07 16:03:58 -05:00
Ben Meadors
de47cc55a0 Don't reply with null island (#1605) 2022-08-07 15:08:46 -05:00
Garth Vander Houwen
7e6c22f542 Update version.properties 2022-08-06 12:56:10 -07:00
Garth Vander Houwen
2fac581fa3 Merge pull request #1602 from meshtastic/WiFi_enum
Combine WIFI state into an enum
2022-08-06 12:55:45 -07:00
Garth Vander Houwen
1155727a45 Merge branch 'master' into WiFi_enum 2022-08-06 12:38:19 -07:00
Ben Meadors
1c8e64319c Update nimble to 1.4 (#1600)
* Update nimble version

* Back down a version

* Nimble 1.4

* Change log level of Nimble. Too chatty

* Log level

* Log level of 1 (error)
2022-08-06 14:16:11 -05:00
Sacha Weatherstone
ca1e687fd4 update protobufs 2022-08-06 21:29:59 +10:00
Sacha Weatherstone
4c215530f6 Update protobufs 2022-08-06 16:35:52 +10:00
Sacha Weatherstone
472fb6e5b0 Update protobufs & fix build 2022-08-06 16:31:40 +10:00
Garth Vander Houwen
00846439d0 Update version.properties 2022-08-05 16:52:10 -07:00
Ben Meadors
a10e56265b Update nimble version (#1599)
* Update nimble version

* Back down a version
2022-08-05 16:11:22 -05:00
128 changed files with 3396 additions and 3434 deletions

View File

@@ -41,6 +41,7 @@ jobs:
- board: station-g1
- board: m5stack-core
- board: m5stack-coreink
# - board: pico
runs-on: ubuntu-latest
steps:
@@ -125,7 +126,6 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install -U platformio adafruit-nrfutil littlefs-python
pip install -U --pre meshtastic
- name: Upgrade platformio
run: |
@@ -196,7 +196,6 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install -U platformio adafruit-nrfutil
pip install -U --pre meshtastic
- name: Upgrade platformio
run: |
@@ -218,6 +217,60 @@ jobs:
release/*.elf
retention-days: 90
build-rpi2040:
strategy:
fail-fast: false
max-parallel: 2
matrix:
include:
- board: pico
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
submodules: "recursive"
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: 3.x
- name: Cache python libs
uses: actions/cache@v1
id: cache-pip # needed in if test
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip
- name: Upgrade python tools
run: |
python -m pip install --upgrade pip
pip install -U platformio adafruit-nrfutil
- name: Upgrade platformio
run: |
pio upgrade
- name: Build Raspberry Pi 2040
run: ./bin/build-rpi2040.sh ${{ matrix.board }}
- name: Get release version string
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v2
with:
name: firmware-${{ matrix.board }}-${{ steps.version.outputs.version }}.zip
path: |
release/*.uf2
release/*.elf
retention-days: 90
build-native:
runs-on: ubuntu-latest
steps:
@@ -289,7 +342,7 @@ jobs:
gather-artifacts:
runs-on: ubuntu-latest
needs: [build-esp32, build-nrf52, build-native]
needs: [build-esp32, build-nrf52, build-native, build-rpi2040]
steps:
- name: Checkout code
uses: actions/checkout@v3
@@ -328,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
@@ -350,3 +408,89 @@ jobs:
artifacts-branch: device
artifacts-dir: pr
artifacts: ./firmware-${{ steps.version.outputs.version }}.zip
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:
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
with:
draft: true
prerelease: true
release_name: Meshtastic Device ${{ steps.version.outputs.version }} alpha - Public Preview
tag_name: v${{ steps.version.outputs.version }}
body: |
Autogenerated by github action, developer should edit as required before publishing...
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Add bins to release
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./firmware-${{ steps.version.outputs.version }}.zip
asset_name: firmware-${{ steps.version.outputs.version }}.zip
asset_content_type: application/zip
- name: Add debug elfs to release
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
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

View File

@@ -1,92 +0,0 @@
name: Make Release
on:
# Can optionally take parameters from the github UI, more info here https://github.blog/changelog/2020-07-06-github-actions-manual-triggers-with-workflow_dispatch/#:~:text=You%20can%20now%20create%20workflows,the%20workflow%20is%20run%20on.
workflow_dispatch:
# inputs:
# Only want to run if version.properties is bumped in master
push:
branches:
- master
paths:
- "version.properties"
jobs:
release-build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
submodules: "recursive"
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: 3.x
# Will be available in steps.version.outputs.version
- name: Get release version string
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
id: version
# Note: we don't use caches on release builds because we don't want to accidentally not have a virgin build machine
- name: Upgrade python tools
# We actually want to run this every time
# if: steps.cache-pip.outputs.cache-hit != 'true'
run: |
python -m pip install --upgrade pip
pip install -U platformio meshtastic adafruit-nrfutil littlefs-python
- name: Upgrade platformio
run: |
pio upgrade
- name: Pull web ui
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: "meshtastic/meshtastic-web"
file: "build.tar"
target: "build.tar"
token: ${{ secrets.GITHUB_TOKEN }}
- name: Unpack web ui
run: |
tar -xf build.tar -C data/static
rm build.tar
- name: Build everything
run: bin/build-all.sh
- name: Create release
uses: actions/create-release@v1
id: create_release
with:
draft: true
prerelease: true
release_name: ${{ steps.version.outputs.version }} alpha
tag_name: v${{ steps.version.outputs.version }}
body: |
Autogenerated by github action, developer should edit as required before publishing...
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Add bins to release
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: release/archive/firmware-${{ steps.version.outputs.version }}.zip
asset_name: firmware-${{ steps.version.outputs.version }}.zip
asset_content_type: application/zip
- name: Add debug elfs to release
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: release/archive/elfs-${{ steps.version.outputs.version }}.zip
asset_name: debug-elfs-${{ steps.version.outputs.version }}.zip
asset_content_type: application/zip

View File

@@ -52,7 +52,8 @@
"shared_mutex": "cpp",
"iostream": "cpp",
"esp_nimble_hci.h": "c",
"map": "cpp"
"map": "cpp",
"random": "cpp"
},
"cSpell.words": [
"Blox",

36
bin/build-rpi2040.sh Executable file
View File

@@ -0,0 +1,36 @@
#!/usr/bin/env bash
set -e
VERSION=`bin/buildinfo.py long`
SHORT_VERSION=`bin/buildinfo.py short`
OUTDIR=release/
rm -f $OUTDIR/firmware*
rm -r $OUTDIR/* || true
# Make sure our submodules are current
git submodule update
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
platformio lib update
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
rm -f .pio/build/$1/firmware.*
# The shell vars the build tool expects to find
export APP_VERSION=$VERSION
basename=firmware-$1-$VERSION
pio run --environment $1 # -v
SRCELF=.pio/build/$1/firmware.elf
cp $SRCELF $OUTDIR/$basename.elf
echo "Copying uf2 file"
SRCBIN=.pio/build/$1/firmware.uf2
cp $SRCBIN $OUTDIR/$basename.uf2
cp bin/device-install.* $OUTDIR
cp bin/device-update.* $OUTDIR

16
bin/bump_version.py Executable file
View 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
View 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

View File

@@ -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
View 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

View File

@@ -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
View 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"
}

View File

@@ -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,
1 # FIXME! using the genpartitions based table doesn't work on TTGO so for now I stay with my old memory map
3 # Name, Type, SubType, Offset, Size, Flags
4 nvs, data, nvs, 0x9000, 0x5000,
5 otadata, data, ota, 0xe000, 0x2000,
6 app0, app, ota_0, 0x10000, 0x1c0000, app0, app, ota_0, 0x10000, 0x2A0000,
7 app1, app, ota_1, 0x1d0000,0x1c0000, spiffs, data, spiffs, 0x2B0000,0x150000,
spiffs, data, spiffs, 0x390000,0x070000,

View File

@@ -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
@@ -65,7 +66,7 @@ lib_deps =
build_flags = ${env.build_flags} -Os
# -DRADIOLIB_GODMODE
build_src_filter = ${env.build_src_filter} -<portduino/>
build_src_filter = ${env.build_src_filter} -<platform/portduino/>
; Common libs for communicating over TCP/IP networks such as MQTT
[networking_base]
@@ -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
@@ -92,24 +91,23 @@ lib_deps =
extends = arduino_base
platform = espressif32@3.5.0
build_src_filter =
${arduino_base.build_src_filter} -<nrf52/> -<stm32wl>
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040>
upload_speed = 115200
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/esp32 -Isrc/esp32-mfix-esp32-psram-cache-issue -lnimble -std=c++11
${arduino_base.build_flags} -Wall -Wextra -Isrc/platform/esp32 -lnimble -std=c++11
-DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL
-DAXP_DEBUG_PORT=Serial -DUSE_NEW_ESP32_BLUETOOTH
-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}
${environmental_base.lib_deps}
https://github.com/meshtastic/esp32_https_server.git
h2zero/NimBLE-Arduino@1.3.7
h2zero/NimBLE-Arduino@1.4.0
arduino-libraries/NTPClient@^3.1.0
lorol/LittleFS_esp32@^1.0.6
https://github.com/meshtastic/AXP202X_Library.git#8404abb6d4b486748636bc6ad72d2a47baaf5460
@@ -142,9 +140,9 @@ build_type = debug ; I'm debugging with ICE a lot now
; note: liboberon provides the AES256 implementation for NRF52 (though not using the hardware acceleration of the NRF52840 - FIXME)
build_flags =
${arduino_base.build_flags} -Wno-unused-variable
-Isrc/nrf52
-Isrc/platform/nrf52
build_src_filter =
${arduino_base.build_src_filter} -<esp32/> -<stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/>
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/rp2040>
lib_ignore =
BluetoothOTA
@@ -165,3 +163,43 @@ board = nrf52840_dk
[env:feather_nrf52832]
extends = nrf52_base
board = adafruit_feather_nrf52832
; Common settings for rp2040 Processor based targets
[rp2040_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
extends = arduino_base
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
build_flags =
${arduino_base.build_flags} -Wno-unused-variable
-Isrc/platform/rp2040
-D__PLAT_RP2040__
# -D _POSIX_THREADS
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/nrf52/> -<platform/stm32wl>
lib_ignore =
BluetoothOTA
lib_deps =
${arduino_base.lib_deps}
${environmental_base.lib_deps}
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

View File

@@ -7,10 +7,6 @@
#include "power.h"
#include <OneButton.h>
#ifdef ARCH_ESP32
#include "nimble/BluetoothUtil.h"
#endif
namespace concurrency
{
/**
@@ -132,7 +128,7 @@ class ButtonThread : public concurrency::OSThread
#endif
// If user button is held down for 5 seconds, shutdown the device.
if ((millis() - longPressTime > 5 * 1000) && (longPressTime > 0)) {
#ifdef TBEAM_V10
#ifdef HAS_AXP192
if (axp192_found == true) {
setLed(false);
power->shutdown();

View File

@@ -44,7 +44,7 @@ bool renameFile(const char* pathFrom, const char* pathTo)
void listDir(const char * dirname, uint8_t levels)
{
#ifdef FSCom
File root = FSCom.open(dirname);
File root = FSCom.open(dirname, FILE_O_READ);
if(!root){
return;
}
@@ -71,7 +71,7 @@ void listDir(const char * dirname, uint8_t levels)
void rmDir(const char * dirname)
{
#ifdef FSCom
File file = FSCom.open(dirname);
File file = FSCom.open(dirname, FILE_O_READ);
if(!file){
return;
}

View File

@@ -13,6 +13,15 @@
#define FILE_O_READ "r"
#endif
#if defined(ARCH_RP2040)
// RP2040
#include "LittleFS.h"
#define FSCom LittleFS
#define FSBegin() FSCom.begin()
#define FILE_O_WRITE "w"
#define FILE_O_READ "r"
#endif
#if defined(ARCH_ESP32)
// ESP32 version
#include "LITTLEFS.h"

View File

@@ -7,9 +7,7 @@
#include "utils.h"
#include "buzz/buzz.h"
#ifdef TBEAM_V10
// FIXME. nasty hack cleanup how we load axp192
#undef AXP192_SLAVE_ADDRESS
#ifdef HAS_AXP192
#include "axp20x.h"
AXP20X_Class axp;
@@ -158,8 +156,21 @@ class AnalogBatteryLevel : public HasBatteryLevel
/// If we see a battery voltage higher than physics allows - assume charger is pumping
/// in power
#ifndef BAT_FULLVOLT
#define BAT_FULLVOLT 4200
#endif
#ifndef BAT_EMPTYVOLT
#define BAT_EMPTYVOLT 3270
#endif
#ifndef BAT_CHARGINGVOLT
#define BAT_CHARGINGVOLT 4210
#endif
#ifndef BAT_NOBATVOLT
#define BAT_NOBATVOLT 2230
#endif
/// For heltecs with no battery connected, the measured voltage is 2204, so raising to 2230 from 2100
const float fullVolt = 4200, emptyVolt = 3270, chargingVolt = 4210, noBatVolt = 2230;
const float fullVolt = BAT_FULLVOLT, emptyVolt = BAT_EMPTYVOLT, chargingVolt = BAT_CHARGINGVOLT, noBatVolt = BAT_NOBATVOLT;
float last_read_value = 0.0;
uint32_t last_read_time_ms = 0;
};
@@ -221,7 +232,7 @@ bool Power::setup()
void Power::shutdown()
{
#ifdef TBEAM_V10
#ifdef HAS_AXP192
DEBUG_MSG("Shutting down\n");
axp.setChgLEDMode(AXP20X_LED_OFF);
axp.shutdown();
@@ -293,7 +304,7 @@ int32_t Power::runOnce()
{
readPowerStatus();
#ifdef TBEAM_V10
#ifdef HAS_AXP192
// WE no longer use the IRQ line to wake the CPU (due to false wakes from sleep), but we do poll
// the IRQ status by reading the registers over I2C
axp.readIRQ();
@@ -343,7 +354,7 @@ int32_t Power::runOnce()
*/
bool Power::axp192Init()
{
#ifdef TBEAM_V10
#ifdef HAS_AXP192
if (axp192_found) {
if (!axp.begin(Wire, AXP192_SLAVE_ADDRESS)) {
batteryLevel = &axp;

View File

@@ -12,7 +12,7 @@
static bool isPowered()
{
// Circumvent the battery sensing logic and assumes constant power if no battery pin or power mgmt IC
#if !defined(BATTERY_PIN) && !defined(AXP192_SLAVE_ADDRESS)
#if !defined(BATTERY_PIN) && !defined(HAS_AXP192)
return true;
#endif
@@ -51,8 +51,7 @@ static uint32_t secsSlept;
static void lsEnter()
{
DEBUG_MSG("lsEnter begin, ls_secs=%u\n",
config.power.ls_secs ? config.power.ls_secs : default_ls_secs);
DEBUG_MSG("lsEnter begin, ls_secs=%u\n", config.power.ls_secs > 0 ? config.power.ls_secs : default_ls_secs);
screen->setOn(false);
secsSlept = 0; // How long have we been sleeping this time
@@ -66,7 +65,7 @@ static void lsIdle()
#ifdef ARCH_ESP32
// Do we have more sleeping to do?
if (secsSlept < config.power.ls_secs ? config.power.ls_secs : default_ls_secs * 1000) {
if (secsSlept < config.power.ls_secs ? config.power.ls_secs : default_ls_secs) {
// Briefly come out of sleep long enough to blink the led once every few seconds
uint32_t sleepTime = 30;
@@ -200,8 +199,7 @@ static void onEnter()
uint32_t now = millis();
if (now - lastPingMs >
30 * 1000) { // if more than a minute since our last press, ask node we are looking at to update their state
if ((now - lastPingMs) > 30 * 1000) { // if more than a minute since our last press, ask node we are looking at to update their state
if (displayedNodeNum)
service.sendNetworkPing(displayedNodeNum, true); // Refresh the currently displayed node
lastPingMs = now;
@@ -251,8 +249,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 +258,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 +329,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, getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), 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 +341,9 @@ 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;
powerFSM.add_timed_transition(&stateNB, &stateLS, getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL, "Min wake timeout");
powerFSM.add_timed_transition(&stateDARK, &stateLS, getConfiguredOrDefaultMs(config.power.wait_bluetooth_secs, default_wait_bluetooth_secs), NULL, "Bluetooth timeout");
meshSds = config.power.mesh_sds_timeout_secs ? config.power.mesh_sds_timeout_secs : default_mesh_sds_timeout_secs;
} else {

View File

@@ -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;

View File

@@ -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;

View File

@@ -14,4 +14,5 @@ enum class Cmd {
STOP_BOOT_SCREEN,
PRINT,
START_SHUTDOWN_SCREEN,
START_REBOOT_SCREEN,
};

View File

@@ -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

View File

@@ -1 +0,0 @@
// Placeholder FIXME

View File

@@ -3,6 +3,10 @@
#include <Wire.h>
#include "mesh/generated/telemetry.pb.h"
#ifdef HAS_AXP192
#include "axp20x.h"
#endif
#if HAS_WIRE
uint16_t getRegisterValue(uint8_t address, uint8_t reg, uint8_t length) {
uint16_t value = 0x00;
@@ -41,7 +45,7 @@ uint8_t oled_probe(byte addr)
if (r == 0x08 || r == 0x00) {
o_probe = 2; // SH1106
} else if ( r == 0x03 || r == 0x06 || r == 0x07) {
} else if ( r == 0x03 || r == 0x04 || r == 0x06 || r == 0x07) {
o_probe = 1; // SSD1306
}
c++;
@@ -110,7 +114,7 @@ void scanI2Cdevice(void)
screen_found = addr;
DEBUG_MSG("st7567 display found\n");
}
#ifdef AXP192_SLAVE_ADDRESS
#ifdef HAS_AXP192
if (addr == AXP192_SLAVE_ADDRESS) {
axp192_found = true;
DEBUG_MSG("axp192 PMU found\n");

View File

@@ -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

View File

@@ -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

View File

@@ -1,259 +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 valueString = pCharacteristic->getValue();
bluetoothPhoneAPI->handleToRadio(reinterpret_cast<const uint8_t*>(&valueString[0]), pCharacteristic->getDataLength());
}
};
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();
}
}
};
static ESP32BluetoothToRadioCallback *toRadioCallbacks;
static ESP32BluetoothFromRadioCallback *fromRadioCallbacks;
void ESP32Bluetooth::shutdown()
{
// Shutdown bluetooth for minimum power draw
DEBUG_MSG("Disable bluetooth\n");
//Bluefruit.Advertising.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);
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->addServiceUUID(MESH_SERVICE_UUID);
pAdvertising->start();
}
/// 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();
}
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

View File

@@ -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

View File

@@ -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

View File

@@ -44,6 +44,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "mesh/http/WiFiAPClient.h"
#endif
#ifdef OLED_RU
#include "fonts/OLEDDisplayFontsRU.h"
#endif
using namespace meshtastic; /** @todo remove */
extern bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct);
@@ -65,11 +69,6 @@ static FrameCallback normalFrames[MAX_NUM_NODES + NUM_EXTRA_FRAMES];
static uint32_t targetFramerate = IDLE_FRAMERATE;
static char btPIN[16] = "888888";
// This defines the layout of the compass.
// If true, North with remain static at the top of the compass.
// If false, your current heading is static at the top of the compass.
bool compassNorthTop = false;
// This image definition is here instead of images.h because it's modified dynamically by the drawBattery function
uint8_t imgBattery[16] = {0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xE7, 0x3C};
@@ -105,7 +104,11 @@ static uint16_t displayWidth, displayHeight;
#define FONT_MEDIUM ArialMT_Plain_24
#define FONT_LARGE ArialMT_Plain_24
#else
#ifdef OLED_RU
#define FONT_SMALL ArialMT_Plain_10_RU
#else
#define FONT_SMALL ArialMT_Plain_10
#endif
#define FONT_MEDIUM ArialMT_Plain_16
#define FONT_LARGE ArialMT_Plain_24
#endif
@@ -117,9 +120,6 @@ static uint16_t displayWidth, displayHeight;
#define getStringCenteredX(s) ((SCREEN_WIDTH - display->getStringWidth(s)) / 2)
#ifndef SCREEN_TRANSITION_MSECS
#define SCREEN_TRANSITION_MSECS 300
#endif
/**
* Draw the icon with extra info printed around the corners
@@ -233,26 +233,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, "");
@@ -304,8 +295,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: ";
@@ -322,6 +318,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);
@@ -334,9 +338,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
@@ -693,7 +694,7 @@ static void drawNodeHeading(OLEDDisplay *display, int16_t compassX, int16_t comp
static void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t compassY, float myHeading)
{
//If north is supposed to be at the top of the compass we want rotation to be +0
if(compassNorthTop)
if(config.display.compass_north_top)
myHeading = -0;
Point N1(-0.04f, 0.65f), N2(0.04f, 0.65f);
@@ -791,7 +792,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
GeoCoord::bearing(DegD(op.latitude_i), DegD(op.longitude_i), DegD(p.latitude_i), DegD(p.longitude_i));
// If the top of the compass is a static north then bearingToOther can be drawn on the compass directly
// If the top of the compass is not a static north we need adjust bearingToOther based on heading
if(!compassNorthTop)
if(!config.display.compass_north_top)
bearingToOther -= myHeading;
drawNodeHeading(display, compassX, compassY, bearingToOther);
}
@@ -906,7 +907,7 @@ void Screen::setup()
displayWidth = dispdev.width();
displayHeight = dispdev.height();
ui.setTimePerTransition(SCREEN_TRANSITION_MSECS);
ui.setTimePerTransition(0);
ui.setIndicatorPosition(BOTTOM);
// Defines where the first frame is located in the bar.
@@ -1047,6 +1048,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");
}
@@ -1070,10 +1074,6 @@ int32_t Screen::runOnce()
DEBUG_MSG("Setting idle framerate\n");
targetFramerate = IDLE_FRAMERATE;
#ifdef ARCH_ESP32
setCPUFast(false); // Turn up the CPU to improve screen animations
#endif
ui.setTargetFPS(targetFramerate);
forceDisplay();
}
@@ -1239,6 +1239,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");
@@ -1302,10 +1314,6 @@ void Screen::setFastFramerate()
// We are about to start a transition so speed up fps
targetFramerate = SCREEN_TRANSITION_FRAMERATE;
#ifdef ARCH_ESP32
setCPUFast(true); // Turn up the CPU to improve screen animations
#endif
ui.setTargetFPS(targetFramerate);
setInterval(0); // redraw ASAP
runASAP = true;
@@ -1370,7 +1378,7 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
if (isSoftAPForced()) {
display->drawString(x, y, String("WiFi: Software AP (Admin)"));
} else if (config.wifi.ap_mode) {
} else if (config.wifi.mode == Config_WiFiConfig_WiFiMode_AccessPoint || config.wifi.mode == Config_WiFiConfig_WiFiMode_AccessPointHidden) {
display->drawString(x, y, String("WiFi: Software AP"));
} else if (WiFi.status() != WL_CONNECTED) {
display->drawString(x, y, String("WiFi: Not Connected"));
@@ -1393,8 +1401,8 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
- WL_NO_SHIELD: assigned when no WiFi shield is present;
*/
if (WiFi.status() == WL_CONNECTED || isSoftAPForced() || config.wifi.ap_mode) {
if (config.wifi.ap_mode || isSoftAPForced()) {
if (WiFi.status() == WL_CONNECTED || isSoftAPForced() || config.wifi.mode == Config_WiFiConfig_WiFiMode_AccessPoint || config.wifi.mode == Config_WiFiConfig_WiFiMode_AccessPointHidden) {
if (config.wifi.mode == Config_WiFiConfig_WiFiMode_AccessPoint || config.wifi.mode == Config_WiFiConfig_WiFiMode_AccessPointHidden || isSoftAPForced()) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IP: " + String(WiFi.softAPIP().toString().c_str()));
// Number of connections to the AP. Default max for the esp32 is 4
@@ -1486,7 +1494,7 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
}
} else {
if (config.wifi.ap_mode) {
if (config.wifi.mode == Config_WiFiConfig_WiFiMode_AccessPoint || config.wifi.mode == Config_WiFiConfig_WiFiMode_AccessPointHidden) {
if ((millis() / 10000) % 2) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: " + String(wifiName));
} else {

View File

@@ -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}); }
@@ -204,7 +212,7 @@ class Screen : public concurrency::OSThread
uint8_t last = LASTCHAR; // get last char
LASTCHAR = ch;
switch (last) { // conversion depnding on first UTF8-character
switch (last) { // conversion depending on first UTF8-character
case 0xC2: {
SKIPREST = false;
return (uint8_t)ch;
@@ -213,10 +221,23 @@ class Screen : public concurrency::OSThread
SKIPREST = false;
return (uint8_t)(ch | 0xC0);
}
// map UTF-8 cyrillic chars to it Windows-1251 (CP-1251) ASCII codes
// note: in this case we must use compatible font - provided ArialMT_Plain_10/16/24 by 'ThingPulse/esp8266-oled-ssd1306' library
// have empty chars for non-latin ASCII symbols
case 0xD0: {
SKIPREST = false;
if (ch == 129) return (uint8_t)(168); // Ё
if (ch > 143 && ch < 192) return (uint8_t)(ch + 48);
}
case 0xD1: {
SKIPREST = false;
if (ch == 145) return (uint8_t)(184); // ё
if (ch > 127 && ch < 144) return (uint8_t)(ch + 112);
}
}
// We want to strip out prefix chars for two-byte char formats
if (ch == 0xC2 || ch == 0xC3 || ch == 0x82)
if (ch == 0xC2 || ch == 0xC3 || ch == 0x82 || ch == 0xD0 || ch == 0xD1)
return (uint8_t)0;
// If we already returned an unconvertable-character symbol for this unconvertable-character sequence, return NULs for the
@@ -280,6 +301,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();

View File

@@ -0,0 +1,426 @@
#include "OLEDDisplayFontsRU.h"
// Font generated or edited with the glyphEditor
const uint8_t ArialMT_Plain_10_RU[] PROGMEM = {
0x0A, // Width: 10
0x0D, // Height: 13
0x20, // First char: 32
0xE0, // Number of chars: 224
// Jump Table:
0xFF, 0xFF, 0x00, 0x0A, // 32
0x00, 0x00, 0x04, 0x03, // 33
0x00, 0x04, 0x05, 0x04, // 34
0x00, 0x09, 0x09, 0x06, // 35
0x00, 0x12, 0x0A, 0x06, // 36
0x00, 0x1C, 0x10, 0x09, // 37
0x00, 0x2C, 0x0E, 0x08, // 38
0x00, 0x3A, 0x01, 0x02, // 39
0x00, 0x3B, 0x06, 0x04, // 40
0x00, 0x41, 0x06, 0x04, // 41
0x00, 0x47, 0x05, 0x04, // 42
0x00, 0x4C, 0x09, 0x06, // 43
0x00, 0x55, 0x04, 0x03, // 44
0x00, 0x59, 0x03, 0x03, // 45
0x00, 0x5C, 0x04, 0x03, // 46
0x00, 0x60, 0x05, 0x04, // 47
0x00, 0x65, 0x0A, 0x06, // 48
0x00, 0x6F, 0x08, 0x05, // 49
0x00, 0x77, 0x0A, 0x06, // 50
0x00, 0x81, 0x0A, 0x06, // 51
0x00, 0x8B, 0x0B, 0x07, // 52
0x00, 0x96, 0x0A, 0x06, // 53
0x00, 0xA0, 0x0A, 0x06, // 54
0x00, 0xAA, 0x09, 0x06, // 55
0x00, 0xB3, 0x0A, 0x06, // 56
0x00, 0xBD, 0x0A, 0x06, // 57
0x00, 0xC7, 0x04, 0x03, // 58
0x00, 0xCB, 0x04, 0x03, // 59
0x00, 0xCF, 0x0A, 0x06, // 60
0x00, 0xD9, 0x09, 0x06, // 61
0x00, 0xE2, 0x09, 0x06, // 62
0x00, 0xEB, 0x0B, 0x07, // 63
0x00, 0xF6, 0x14, 0x0B, // 64
0x01, 0x0A, 0x0E, 0x08, // 65
0x01, 0x18, 0x0C, 0x07, // 66
0x01, 0x24, 0x0C, 0x07, // 67
0x01, 0x30, 0x0B, 0x07, // 68
0x01, 0x3B, 0x0C, 0x07, // 69
0x01, 0x47, 0x09, 0x06, // 70
0x01, 0x50, 0x0D, 0x08, // 71
0x01, 0x5D, 0x0C, 0x07, // 72
0x01, 0x69, 0x04, 0x03, // 73
0x01, 0x6D, 0x08, 0x05, // 74
0x01, 0x75, 0x0E, 0x08, // 75
0x01, 0x83, 0x0C, 0x07, // 76
0x01, 0x8F, 0x10, 0x09, // 77
0x01, 0x9F, 0x0C, 0x07, // 78
0x01, 0xAB, 0x0E, 0x08, // 79
0x01, 0xB9, 0x0B, 0x07, // 80
0x01, 0xC4, 0x0E, 0x08, // 81
0x01, 0xD2, 0x0C, 0x07, // 82
0x01, 0xDE, 0x0C, 0x07, // 83
0x01, 0xEA, 0x0B, 0x07, // 84
0x01, 0xF5, 0x0C, 0x07, // 85
0x02, 0x01, 0x0D, 0x08, // 86
0x02, 0x0E, 0x11, 0x0A, // 87
0x02, 0x1F, 0x0E, 0x08, // 88
0x02, 0x2D, 0x0D, 0x08, // 89
0x02, 0x3A, 0x0C, 0x07, // 90
0x02, 0x46, 0x06, 0x04, // 91
0x02, 0x4C, 0x06, 0x04, // 92
0x02, 0x52, 0x04, 0x03, // 93
0x02, 0x56, 0x09, 0x06, // 94
0x02, 0x5F, 0x0C, 0x07, // 95
0x02, 0x6B, 0x03, 0x03, // 96
0x02, 0x6E, 0x0A, 0x06, // 97
0x02, 0x78, 0x0A, 0x06, // 98
0x02, 0x82, 0x0A, 0x06, // 99
0x02, 0x8C, 0x0A, 0x06, // 100
0x02, 0x96, 0x0A, 0x06, // 101
0x02, 0xA0, 0x05, 0x04, // 102
0x02, 0xA5, 0x0A, 0x06, // 103
0x02, 0xAF, 0x0A, 0x06, // 104
0x02, 0xB9, 0x04, 0x03, // 105
0x02, 0xBD, 0x04, 0x03, // 106
0x02, 0xC1, 0x08, 0x05, // 107
0x02, 0xC9, 0x04, 0x03, // 108
0x02, 0xCD, 0x10, 0x09, // 109
0x02, 0xDD, 0x0A, 0x06, // 110
0x02, 0xE7, 0x0A, 0x06, // 111
0x02, 0xF1, 0x0A, 0x06, // 112
0x02, 0xFB, 0x0A, 0x06, // 113
0x03, 0x05, 0x05, 0x04, // 114
0x03, 0x0A, 0x08, 0x05, // 115
0x03, 0x12, 0x06, 0x04, // 116
0x03, 0x18, 0x0A, 0x06, // 117
0x03, 0x22, 0x09, 0x06, // 118
0x03, 0x2B, 0x0E, 0x08, // 119
0x03, 0x39, 0x0A, 0x06, // 120
0x03, 0x43, 0x09, 0x06, // 121
0x03, 0x4C, 0x0A, 0x06, // 122
0x03, 0x56, 0x06, 0x04, // 123
0x03, 0x5C, 0x04, 0x03, // 124
0x03, 0x60, 0x05, 0x04, // 125
0x03, 0x65, 0x09, 0x06, // 126
0xFF, 0xFF, 0x00, 0x0A, // 127
0xFF, 0xFF, 0x00, 0x0A, // 128
0xFF, 0xFF, 0x00, 0x0A, // 129
0xFF, 0xFF, 0x00, 0x0A, // 130
0xFF, 0xFF, 0x00, 0x0A, // 131
0xFF, 0xFF, 0x00, 0x0A, // 132
0xFF, 0xFF, 0x00, 0x0A, // 133
0xFF, 0xFF, 0x00, 0x0A, // 134
0xFF, 0xFF, 0x00, 0x0A, // 135
0xFF, 0xFF, 0x00, 0x0A, // 136
0xFF, 0xFF, 0x00, 0x0A, // 137
0xFF, 0xFF, 0x00, 0x0A, // 138
0xFF, 0xFF, 0x00, 0x0A, // 139
0xFF, 0xFF, 0x00, 0x0A, // 140
0xFF, 0xFF, 0x00, 0x0A, // 141
0xFF, 0xFF, 0x00, 0x0A, // 142
0xFF, 0xFF, 0x00, 0x0A, // 143
0xFF, 0xFF, 0x00, 0x0A, // 144
0xFF, 0xFF, 0x00, 0x0A, // 145
0xFF, 0xFF, 0x00, 0x0A, // 146
0xFF, 0xFF, 0x00, 0x0A, // 147
0xFF, 0xFF, 0x00, 0x0A, // 148
0xFF, 0xFF, 0x00, 0x0A, // 149
0xFF, 0xFF, 0x00, 0x0A, // 150
0xFF, 0xFF, 0x00, 0x0A, // 151
0xFF, 0xFF, 0x00, 0x0A, // 152
0xFF, 0xFF, 0x00, 0x0A, // 153
0xFF, 0xFF, 0x00, 0x0A, // 154
0xFF, 0xFF, 0x00, 0x0A, // 155
0xFF, 0xFF, 0x00, 0x0A, // 156
0xFF, 0xFF, 0x00, 0x0A, // 157
0xFF, 0xFF, 0x00, 0x0A, // 158
0xFF, 0xFF, 0x00, 0x0A, // 159
0xFF, 0xFF, 0x00, 0x0A, // 160
0x03, 0x6E, 0x04, 0x03, // 161
0x03, 0x72, 0x0A, 0x06, // 162
0x03, 0x7C, 0x0C, 0x07, // 163
0x03, 0x88, 0x0A, 0x06, // 164
0x03, 0x92, 0x0A, 0x06, // 165
0x03, 0x9C, 0x04, 0x03, // 166
0x03, 0xA0, 0x0A, 0x06, // 167
0x03, 0xAA, 0x0C, 0x07, // 168
0x03, 0xB6, 0x0D, 0x08, // 169
0x03, 0xC3, 0x07, 0x05, // 170
0x03, 0xCA, 0x0A, 0x06, // 171
0x03, 0xD4, 0x09, 0x06, // 172
0x03, 0xDD, 0x03, 0x03, // 173
0x03, 0xE0, 0x0D, 0x08, // 174
0x03, 0xED, 0x0B, 0x07, // 175
0x03, 0xF8, 0x07, 0x05, // 176
0x03, 0xFF, 0x0A, 0x06, // 177
0x04, 0x09, 0x05, 0x04, // 178
0x04, 0x0E, 0x05, 0x04, // 179
0x04, 0x13, 0x05, 0x04, // 180
0x04, 0x18, 0x0A, 0x06, // 181
0x04, 0x22, 0x09, 0x06, // 182
0x04, 0x2B, 0x03, 0x03, // 183
0x04, 0x2E, 0x0B, 0x07, // 184
0x04, 0x39, 0x0B, 0x07, // 185
0x04, 0x44, 0x07, 0x05, // 186
0x04, 0x4B, 0x0A, 0x06, // 187
0x04, 0x55, 0x10, 0x09, // 188
0x04, 0x65, 0x10, 0x09, // 189
0x04, 0x75, 0x10, 0x09, // 190
0x04, 0x85, 0x0A, 0x06, // 191
0x04, 0x8F, 0x0C, 0x07, // 192
0x04, 0x9B, 0x0C, 0x07, // 193
0x04, 0xA7, 0x0C, 0x07, // 194
0x04, 0xB3, 0x0B, 0x07, // 195
0x04, 0xBE, 0x0C, 0x07, // 196
0x04, 0xCA, 0x0C, 0x07, // 197
0x04, 0xD6, 0x0C, 0x07, // 198
0x04, 0xE2, 0x0C, 0x07, // 199
0x04, 0xEE, 0x0C, 0x07, // 200
0x04, 0xFA, 0x0C, 0x07, // 201
0x05, 0x06, 0x0C, 0x07, // 202
0x05, 0x12, 0x0C, 0x07, // 203
0x05, 0x1E, 0x0C, 0x07, // 204
0x05, 0x2A, 0x0C, 0x07, // 205
0x05, 0x36, 0x0C, 0x07, // 206
0x05, 0x42, 0x0C, 0x07, // 207
0x05, 0x4E, 0x0B, 0x07, // 208
0x05, 0x59, 0x0C, 0x07, // 209
0x05, 0x65, 0x0B, 0x07, // 210
0x05, 0x70, 0x0C, 0x07, // 211
0x05, 0x7C, 0x0B, 0x07, // 212
0x05, 0x87, 0x0C, 0x07, // 213
0x05, 0x93, 0x0C, 0x07, // 214
0x05, 0x9F, 0x0C, 0x07, // 215
0x05, 0xAB, 0x0C, 0x07, // 216
0x05, 0xB7, 0x0E, 0x08, // 217
0x05, 0xC5, 0x0C, 0x07, // 218
0x05, 0xD1, 0x0C, 0x07, // 219
0x05, 0xDD, 0x0C, 0x07, // 220
0x05, 0xE9, 0x0C, 0x07, // 221
0x05, 0xF5, 0x0C, 0x07, // 222
0x06, 0x01, 0x0C, 0x07, // 223
0x06, 0x0D, 0x0C, 0x07, // 224
0x06, 0x19, 0x0C, 0x07, // 225
0x06, 0x25, 0x0C, 0x07, // 226
0x06, 0x31, 0x0B, 0x07, // 227
0x06, 0x3C, 0x0C, 0x07, // 228
0x06, 0x48, 0x0B, 0x07, // 229
0x06, 0x53, 0x0C, 0x07, // 230
0x06, 0x5F, 0x0C, 0x07, // 231
0x06, 0x6B, 0x0C, 0x07, // 232
0x06, 0x77, 0x0C, 0x07, // 233
0x06, 0x83, 0x0C, 0x07, // 234
0x06, 0x8F, 0x0C, 0x07, // 235
0x06, 0x9B, 0x0C, 0x07, // 236
0x06, 0xA7, 0x0C, 0x07, // 237
0x06, 0xB3, 0x0C, 0x07, // 238
0x06, 0xBF, 0x0C, 0x07, // 239
0x06, 0xCB, 0x0B, 0x07, // 240
0x06, 0xD6, 0x0C, 0x07, // 241
0x06, 0xE2, 0x0B, 0x07, // 242
0x06, 0xED, 0x0C, 0x07, // 243
0x06, 0xF9, 0x0B, 0x07, // 244
0x07, 0x04, 0x0C, 0x07, // 245
0x07, 0x10, 0x0C, 0x07, // 246
0x07, 0x1C, 0x0C, 0x07, // 247
0x07, 0x28, 0x0C, 0x07, // 248
0x07, 0x34, 0x0E, 0x08, // 249
0x07, 0x42, 0x0C, 0x07, // 250
0x07, 0x4E, 0x0C, 0x07, // 251
0x07, 0x5A, 0x0C, 0x07, // 252
0x07, 0x66, 0x0C, 0x07, // 253
0x07, 0x72, 0x0C, 0x07, // 254
0x07, 0x7E, 0x0C, 0x07, // 255
// Font Data:
0x00, 0x00, 0xF8, 0x02, // 33
0x38, 0x00, 0x00, 0x00, 0x38, // 34
0xA0, 0x03, 0xE0, 0x00, 0xB8, 0x03, 0xE0, 0x00, 0xB8, // 35
0x30, 0x01, 0x28, 0x02, 0xF8, 0x07, 0x48, 0x02, 0x90, 0x01, // 36
0x00, 0x00, 0x30, 0x00, 0x48, 0x00, 0x30, 0x03, 0xC0, 0x00, 0xB0, 0x01, 0x48, 0x02, 0x80, 0x01, // 37
0x80, 0x01, 0x50, 0x02, 0x68, 0x02, 0xA8, 0x02, 0x18, 0x01, 0x80, 0x03, 0x80, 0x02, // 38
0x38, // 39
0xE0, 0x03, 0x10, 0x04, 0x08, 0x08, // 40
0x08, 0x08, 0x10, 0x04, 0xE0, 0x03, // 41
0x28, 0x00, 0x18, 0x00, 0x28, // 42
0x40, 0x00, 0x40, 0x00, 0xF0, 0x01, 0x40, 0x00, 0x40, // 43
0x00, 0x00, 0x00, 0x06, // 44
0x80, 0x00, 0x80, // 45
0x00, 0x00, 0x00, 0x02, // 46
0x00, 0x03, 0xE0, 0x00, 0x18, // 47
0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0xF0, 0x01, // 48
0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0xF8, 0x03, // 49
0x10, 0x02, 0x08, 0x03, 0x88, 0x02, 0x48, 0x02, 0x30, 0x02, // 50
0x10, 0x01, 0x08, 0x02, 0x48, 0x02, 0x48, 0x02, 0xB0, 0x01, // 51
0xC0, 0x00, 0xA0, 0x00, 0x90, 0x00, 0x88, 0x00, 0xF8, 0x03, 0x80, // 52
0x60, 0x01, 0x38, 0x02, 0x28, 0x02, 0x28, 0x02, 0xC8, 0x01, // 53
0xF0, 0x01, 0x28, 0x02, 0x28, 0x02, 0x28, 0x02, 0xD0, 0x01, // 54
0x08, 0x00, 0x08, 0x03, 0xC8, 0x00, 0x38, 0x00, 0x08, // 55
0xB0, 0x01, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0xB0, 0x01, // 56
0x70, 0x01, 0x88, 0x02, 0x88, 0x02, 0x88, 0x02, 0xF0, 0x01, // 57
0x00, 0x00, 0x20, 0x02, // 58
0x00, 0x00, 0x20, 0x06, // 59
0x00, 0x00, 0x40, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0x10, 0x01, // 60
0xA0, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0xA0, // 61
0x00, 0x00, 0x10, 0x01, 0xA0, 0x00, 0xA0, 0x00, 0x40, // 62
0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0xC8, 0x02, 0x48, 0x00, 0x30, // 63
0x00, 0x00, 0xC0, 0x03, 0x30, 0x04, 0xD0, 0x09, 0x28, 0x0A, 0x28, 0x0A, 0xC8, 0x0B, 0x68, 0x0A, 0x10, 0x05, 0xE0, 0x04, // 64
0x00, 0x02, 0xC0, 0x01, 0xB0, 0x00, 0x88, 0x00, 0xB0, 0x00, 0xC0, 0x01, 0x00, 0x02, // 65
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0xF0, 0x01, // 66
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x10, 0x01, // 67
0x00, 0x00, 0xF8, 0x03, 0x08, 0x02, 0x08, 0x02, 0x10, 0x01, 0xE0, // 68
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, // 69
0x00, 0x00, 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0x08, // 70
0x00, 0x00, 0xE0, 0x00, 0x10, 0x01, 0x08, 0x02, 0x48, 0x02, 0x50, 0x01, 0xC0, // 71
0x00, 0x00, 0xF8, 0x03, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xF8, 0x03, // 72
0x00, 0x00, 0xF8, 0x03, // 73
0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0xF8, 0x01, // 74
0x00, 0x00, 0xF8, 0x03, 0x80, 0x00, 0x60, 0x00, 0x90, 0x00, 0x08, 0x01, 0x00, 0x02, // 75
0x00, 0x00, 0xF8, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, // 76
0x00, 0x00, 0xF8, 0x03, 0x30, 0x00, 0xC0, 0x01, 0x00, 0x02, 0xC0, 0x01, 0x30, 0x00, 0xF8, 0x03, // 77
0x00, 0x00, 0xF8, 0x03, 0x30, 0x00, 0x40, 0x00, 0x80, 0x01, 0xF8, 0x03, // 78
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0xF0, 0x01, // 79
0x00, 0x00, 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, // 80
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x03, 0x08, 0x03, 0xF0, 0x02, // 81
0x00, 0x00, 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0xC8, 0x00, 0x30, 0x03, // 82
0x00, 0x00, 0x30, 0x01, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x90, 0x01, // 83
0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, // 84
0x00, 0x00, 0xF8, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0xF8, 0x01, // 85
0x08, 0x00, 0x70, 0x00, 0x80, 0x01, 0x00, 0x02, 0x80, 0x01, 0x70, 0x00, 0x08, // 86
0x18, 0x00, 0xE0, 0x01, 0x00, 0x02, 0xF0, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x00, 0x02, 0xE0, 0x01, 0x18, // 87
0x00, 0x02, 0x08, 0x01, 0x90, 0x00, 0x60, 0x00, 0x90, 0x00, 0x08, 0x01, 0x00, 0x02, // 88
0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0xC0, 0x03, 0x20, 0x00, 0x10, 0x00, 0x08, // 89
0x08, 0x03, 0x88, 0x02, 0xC8, 0x02, 0x68, 0x02, 0x38, 0x02, 0x18, 0x02, // 90
0x00, 0x00, 0xF8, 0x0F, 0x08, 0x08, // 91
0x18, 0x00, 0xE0, 0x00, 0x00, 0x03, // 92
0x08, 0x08, 0xF8, 0x0F, // 93
0x40, 0x00, 0x30, 0x00, 0x08, 0x00, 0x30, 0x00, 0x40, // 94
0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, // 95
0x08, 0x00, 0x10, // 96
0x00, 0x00, 0x00, 0x03, 0xA0, 0x02, 0xA0, 0x02, 0xE0, 0x03, // 97
0x00, 0x00, 0xF8, 0x03, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 98
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0x40, 0x01, // 99
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0xF8, 0x03, // 100
0x00, 0x00, 0xC0, 0x01, 0xA0, 0x02, 0xA0, 0x02, 0xC0, 0x02, // 101
0x20, 0x00, 0xF0, 0x03, 0x28, // 102
0x00, 0x00, 0xC0, 0x05, 0x20, 0x0A, 0x20, 0x0A, 0xE0, 0x07, // 103
0x00, 0x00, 0xF8, 0x03, 0x20, 0x00, 0x20, 0x00, 0xC0, 0x03, // 104
0x00, 0x00, 0xE8, 0x03, // 105
0x00, 0x08, 0xE8, 0x07, // 106
0xF8, 0x03, 0x80, 0x00, 0xC0, 0x01, 0x20, 0x02, // 107
0x00, 0x00, 0xF8, 0x03, // 108
0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0xC0, 0x03, // 109
0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0xC0, 0x03, // 110
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 111
0x00, 0x00, 0xE0, 0x0F, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 112
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0xE0, 0x0F, // 113
0x00, 0x00, 0xE0, 0x03, 0x20, // 114
0x40, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0x20, 0x01, // 115
0x20, 0x00, 0xF8, 0x03, 0x20, 0x02, // 116
0x00, 0x00, 0xE0, 0x01, 0x00, 0x02, 0x00, 0x02, 0xE0, 0x03, // 117
0x20, 0x00, 0xC0, 0x01, 0x00, 0x02, 0xC0, 0x01, 0x20, // 118
0xE0, 0x01, 0x00, 0x02, 0xC0, 0x01, 0x20, 0x00, 0xC0, 0x01, 0x00, 0x02, 0xE0, 0x01, // 119
0x20, 0x02, 0x40, 0x01, 0x80, 0x00, 0x40, 0x01, 0x20, 0x02, // 120
0x20, 0x00, 0xC0, 0x09, 0x00, 0x06, 0xC0, 0x01, 0x20, // 121
0x20, 0x02, 0x20, 0x03, 0xA0, 0x02, 0x60, 0x02, 0x20, 0x02, // 122
0x80, 0x00, 0x78, 0x0F, 0x08, 0x08, // 123
0x00, 0x00, 0xF8, 0x0F, // 124
0x08, 0x08, 0x78, 0x0F, 0x80, // 125
0xC0, 0x00, 0x40, 0x00, 0xC0, 0x00, 0x80, 0x00, 0xC0, // 126
0x00, 0x00, 0xA0, 0x0F, // 161
0x00, 0x00, 0xC0, 0x01, 0xA0, 0x0F, 0x78, 0x02, 0x40, 0x01, // 162
0x40, 0x02, 0x70, 0x03, 0xC8, 0x02, 0x48, 0x02, 0x08, 0x02, 0x10, 0x02, // 163
0x00, 0x00, 0xE0, 0x01, 0x20, 0x01, 0x20, 0x01, 0xE0, 0x01, // 164
0x48, 0x01, 0x70, 0x01, 0xC0, 0x03, 0x70, 0x01, 0x48, 0x01, // 165
0x00, 0x00, 0x38, 0x0F, // 166
0xD0, 0x04, 0x28, 0x09, 0x48, 0x09, 0x48, 0x0A, 0x90, 0x05, // 167
0x00, 0x00, 0xE0, 0x03, 0xA8, 0x02, 0xA0, 0x02, 0xA8, 0x02, 0x20, 0x02, // 168
0xE0, 0x00, 0x10, 0x01, 0x48, 0x02, 0xA8, 0x02, 0xA8, 0x02, 0x10, 0x01, 0xE0, // 169
0x68, 0x00, 0x68, 0x00, 0x68, 0x00, 0x78, // 170
0x00, 0x00, 0x80, 0x01, 0x40, 0x02, 0x80, 0x01, 0x40, 0x02, // 171
0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xE0, // 172
0x80, 0x00, 0x80, // 173
0xE0, 0x00, 0x10, 0x01, 0xE8, 0x02, 0x68, 0x02, 0xC8, 0x02, 0x10, 0x01, 0xE0, // 174
0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, // 175
0x00, 0x00, 0x38, 0x00, 0x28, 0x00, 0x38, // 176
0x40, 0x02, 0x40, 0x02, 0xF0, 0x03, 0x40, 0x02, 0x40, 0x02, // 177
0x48, 0x00, 0x68, 0x00, 0x58, // 178
0x48, 0x00, 0x58, 0x00, 0x68, // 179
0x00, 0x00, 0x10, 0x00, 0x08, // 180
0x00, 0x00, 0xE0, 0x0F, 0x00, 0x02, 0x00, 0x02, 0xE0, 0x03, // 181
0x70, 0x00, 0xF8, 0x0F, 0x08, 0x00, 0xF8, 0x0F, 0x08, // 182
0x00, 0x00, 0x40, // 183
0x00, 0x00, 0xC0, 0x01, 0xA8, 0x02, 0xA0, 0x02, 0xA8, 0x02, 0xC0, // 184
0x00, 0x00, 0xF0, 0x03, 0x40, 0x00, 0x80, 0x00, 0xF8, 0x03, 0x08, // 185
0x30, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, // 186
0x00, 0x00, 0x40, 0x02, 0x80, 0x01, 0x40, 0x02, 0x80, 0x01, // 187
0x00, 0x00, 0x10, 0x02, 0x78, 0x01, 0xC0, 0x00, 0x20, 0x01, 0x90, 0x01, 0xC8, 0x03, 0x00, 0x01, // 188
0x00, 0x00, 0x10, 0x02, 0x78, 0x01, 0x80, 0x00, 0x60, 0x00, 0x50, 0x02, 0x48, 0x03, 0xC0, 0x02, // 189
0x48, 0x00, 0x58, 0x00, 0x68, 0x03, 0x80, 0x00, 0x60, 0x01, 0x90, 0x01, 0xC8, 0x03, 0x00, 0x01, // 190
0x00, 0x00, 0x00, 0x06, 0x00, 0x09, 0xA0, 0x09, 0x00, 0x04, // 191
0x00, 0x00, 0xF0, 0x03, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0xF0, 0x03, // 192
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x88, 0x01, // 193
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0xB0, 0x01, // 194
0x00, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x18, // 195
0x00, 0x00, 0x00, 0x02, 0xFC, 0x03, 0x04, 0x02, 0xFC, 0x03, 0x00, 0x02, // 196
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x08, 0x02, // 197
0x00, 0x00, 0xB8, 0x03, 0x40, 0x00, 0xF8, 0x03, 0x40, 0x00, 0xB8, 0x03, // 198
0x00, 0x00, 0x08, 0x02, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0xB0, 0x01, // 199
0x00, 0x00, 0xF8, 0x03, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0xF8, 0x03, // 200
0x00, 0x00, 0xE0, 0x03, 0x08, 0x01, 0x90, 0x00, 0x48, 0x00, 0xE0, 0x03, // 201
0x00, 0x00, 0xF8, 0x03, 0x40, 0x00, 0xA0, 0x00, 0x10, 0x01, 0x08, 0x02, // 202
0x00, 0x00, 0x00, 0x02, 0xF0, 0x01, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, // 203
0x00, 0x00, 0xF8, 0x03, 0x10, 0x00, 0x60, 0x00, 0x10, 0x00, 0xF8, 0x03, // 204
0x00, 0x00, 0xF8, 0x03, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xF8, 0x03, // 205
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0xF0, 0x01, // 206
0x00, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, // 207
0x00, 0x00, 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, // 208
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x10, 0x01, // 209
0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, // 210
0x00, 0x00, 0x38, 0x00, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0xF8, 0x01, // 211
0x00, 0x00, 0x70, 0x00, 0x88, 0x00, 0xF8, 0x03, 0x88, 0x00, 0x70, // 212
0x00, 0x00, 0x18, 0x03, 0xA0, 0x00, 0x40, 0x00, 0xA0, 0x00, 0x18, 0x03, // 213
0x00, 0x00, 0xF8, 0x03, 0x00, 0x02, 0x00, 0x02, 0xF8, 0x03, 0x00, 0x02, // 214
0x00, 0x00, 0x38, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xF8, 0x03, // 215
0x00, 0x00, 0xF8, 0x03, 0x00, 0x02, 0xF8, 0x03, 0x00, 0x02, 0xF8, 0x03, // 216
0x00, 0x00, 0xF8, 0x03, 0x00, 0x02, 0xF8, 0x03, 0x00, 0x02, 0xF8, 0x03, 0x00, 0x06, // 217
0x00, 0x00, 0x08, 0x00, 0xF8, 0x03, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, // 218
0x00, 0x00, 0xF8, 0x03, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, 0xF8, 0x03, // 219
0x00, 0x00, 0xF8, 0x03, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, // 220
0x00, 0x00, 0x10, 0x01, 0x08, 0x02, 0x48, 0x02, 0x48, 0x02, 0xF0, 0x01, // 221
0x00, 0x00, 0xF8, 0x03, 0x40, 0x00, 0xF0, 0x01, 0x08, 0x02, 0xF0, 0x01, // 222
0x00, 0x00, 0x30, 0x02, 0x48, 0x01, 0xC8, 0x00, 0x48, 0x00, 0xF8, 0x03, // 223
0x00, 0x00, 0x00, 0x01, 0xA0, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0xC0, 0x03, // 224
0x00, 0x00, 0xE0, 0x01, 0x50, 0x02, 0x50, 0x02, 0x48, 0x02, 0x88, 0x01, // 225
0x00, 0x00, 0xE0, 0x03, 0xA0, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0x40, 0x01, // 226
0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x60, // 227
0x00, 0x00, 0x00, 0x02, 0xC0, 0x03, 0x20, 0x02, 0xE0, 0x03, 0x00, 0x02, // 228
0x00, 0x00, 0xC0, 0x01, 0xA0, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0xC0, // 229
0x00, 0x00, 0x60, 0x03, 0x80, 0x00, 0xE0, 0x03, 0x80, 0x00, 0x60, 0x03, // 230
0x00, 0x00, 0x20, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0x40, 0x01, // 231
0x00, 0x00, 0xE0, 0x03, 0x00, 0x01, 0x80, 0x00, 0x40, 0x00, 0xE0, 0x03, // 232
0x00, 0x00, 0xE0, 0x03, 0x00, 0x01, 0x98, 0x00, 0x40, 0x00, 0xE0, 0x03, // 233
0x00, 0x00, 0xE0, 0x03, 0x80, 0x00, 0x80, 0x00, 0x40, 0x01, 0x20, 0x02, // 234
0x00, 0x00, 0x00, 0x02, 0xC0, 0x01, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x03, // 235
0x00, 0x00, 0xE0, 0x03, 0x40, 0x00, 0x80, 0x00, 0x40, 0x00, 0xE0, 0x03, // 236
0x00, 0x00, 0xE0, 0x03, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xE0, 0x03, // 237
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 238
0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x03, // 239
0x00, 0x00, 0xE0, 0x03, 0xA0, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0x40, // 240
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0x40, 0x02, // 241
0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, // 242
0x00, 0x00, 0x60, 0x00, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0xE0, 0x01, // 243
0x00, 0x00, 0xC0, 0x00, 0x20, 0x01, 0xE0, 0x03, 0x20, 0x01, 0xC0, // 244
0x00, 0x00, 0x20, 0x02, 0x40, 0x01, 0x80, 0x00, 0x40, 0x01, 0x20, 0x02, // 245
0x00, 0x00, 0xE0, 0x03, 0x00, 0x02, 0x00, 0x02, 0xE0, 0x03, 0x00, 0x02, // 246
0x00, 0x00, 0x60, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xE0, 0x03, // 247
0x00, 0x00, 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, // 248
0x00, 0x00, 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, 0x00, 0x06, // 249
0x00, 0x00, 0x20, 0x00, 0xE0, 0x03, 0x80, 0x02, 0x80, 0x02, 0x00, 0x01, // 250
0x00, 0x00, 0xE0, 0x03, 0x80, 0x02, 0x80, 0x02, 0x00, 0x01, 0xE0, 0x03, // 251
0x00, 0x00, 0xE0, 0x03, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x00, 0x01, // 252
0x00, 0x00, 0x40, 0x01, 0x20, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0xC0, 0x01, // 253
0x00, 0x00, 0xE0, 0x03, 0x80, 0x00, 0xC0, 0x01, 0x20, 0x02, 0xC0, 0x01, // 254
0x00, 0x00, 0x40, 0x02, 0xA0, 0x01, 0xA0, 0x00, 0xA0, 0x00, 0xE0, 0x03, // 255
};

View File

@@ -0,0 +1,11 @@
#ifndef OLEDDISPLAYFONTSRU_h
#define OLEDDISPLAYFONTSRU_h
#ifdef ARDUINO
#include <Arduino.h>
#elif __MBED__
#define PROGMEM
#endif
extern const uint8_t ArialMT_Plain_10_RU[] PROGMEM;
#endif

View File

@@ -17,9 +17,9 @@
#include "SPILock.h"
#include "concurrency/OSThread.h"
#include "concurrency/Periodic.h"
#include "debug/axpDebug.h"
#include "debug/einkScan.h"
#include "debug/i2cScan.h"
#include "detect/axpDebug.h"
#include "detect/einkScan.h"
#include "detect/i2cScan.h"
#include "graphics/Screen.h"
#include "main.h"
#include "modules/Modules.h"
@@ -33,13 +33,7 @@
#ifdef ARCH_ESP32
#include "mesh/http/WebServer.h"
#ifdef USE_NEW_ESP32_BLUETOOTH
#include "esp32/ESP32Bluetooth.h"
#else
#include "nimble/BluetoothUtil.h"
#endif
#include "nimble/NimbleBluetooth.h"
#endif
#if HAS_WIFI
@@ -307,7 +301,7 @@ void setup()
setupModules();
// Do this after service.init (because that clears error_code)
#ifdef AXP192_SLAVE_ADDRESS
#ifdef HAS_AXP192
if (!axp192_found)
RECORD_CRITICALERROR(CriticalErrorCode_NoAXP192); // Record a hardware fault for missing hardware
#endif

View File

@@ -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
@@ -168,7 +172,7 @@ void MeshService::sendNetworkPing(NodeNum dest, bool wantReplies)
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
assert(node);
if (node->has_position) {
if (node->has_position && (node->position.latitude_i != 0 || node->position.longitude_i != 0)) {
if (positionModule) {
DEBUG_MSG("Sending position ping to 0x%x, wantReplies=%d\n", dest, wantReplies);
positionModule->sendOurPosition(dest, wantReplies);

View File

@@ -43,14 +43,6 @@ ChannelFile channelFile;
*/
uint32_t radioGeneration;
/*
DeviceState versions used to be defined in the .proto file but really only this function cares. So changed to a
#define here.
*/
#define DEVICESTATE_CUR_VER 13
#define DEVICESTATE_MIN_VER DEVICESTATE_CUR_VER
// FIXME - move this somewhere else
extern void getMacAddr(uint8_t *dmac);
@@ -120,6 +112,13 @@ bool NodeDB::resetRadioConfig()
// Update the global myRegion
initRegion();
if (didFactoryReset) {
config.device.factory_reset = false;
DEBUG_MSG("Rebooting due to factory reset");
screen->startRebootScreen();
rebootAtMsec = millis() + (5 * 1000);
}
return didFactoryReset;
}
@@ -130,6 +129,7 @@ bool NodeDB::factoryReset()
rmDir("/prefs");
// second, install default state (this will deal with the duplicate mac address issue)
installDefaultDeviceState();
installDefaultConfig();
// third, write to disk
saveToDisk();
#ifdef ARCH_ESP32
@@ -158,14 +158,23 @@ 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;
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER)
bool hasScreen = true;
#else
bool hasScreen = screen_found;
#endif
config.bluetooth.mode = hasScreen ? 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()
@@ -305,7 +314,7 @@ bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_
#ifdef FSCom
// static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM
auto f = FSCom.open(filename);
auto f = FSCom.open(filename, FILE_O_READ);
if (f) {
DEBUG_MSG("Loading %s\n", filename);
@@ -460,6 +469,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;

View File

@@ -8,6 +8,14 @@
#include "NodeStatus.h"
#include "mesh-pb-constants.h"
/*
DeviceState versions used to be defined in the .proto file but really only this function cares. So changed to a
#define here.
*/
#define DEVICESTATE_CUR_VER 16
#define DEVICESTATE_MIN_VER DEVICESTATE_CUR_VER
extern DeviceState devicestate;
extern ChannelFile channelFile;
extern MyNodeInfo &myNodeInfo;
@@ -171,15 +179,20 @@ 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 * 10
inline uint32_t getIntervalOrDefaultMs(uint32_t interval)
inline uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval)
{
if (interval > 0)
return interval * 1000;
if (configuredInterval > 0) return configuredInterval * 1000;
return default_broadcast_interval_secs * 1000;
}
inline uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval, uint32_t defaultInterval)
{
if (configuredInterval > 0) return configuredInterval * 1000;
return defaultInterval * 1000;
}
/** The current change # for radio settings. Starts at 0 on boot and any time the radio settings
* might have changed is incremented. Allows others to detect they might now be on a new channel.
*/

View File

@@ -79,20 +79,17 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
memset(&toRadioScratch, 0, sizeof(toRadioScratch));
if (pb_decode_from_bytes(buf, bufLength, ToRadio_fields, &toRadioScratch)) {
switch (toRadioScratch.which_payloadVariant) {
case ToRadio_packet_tag:
return handleToRadioPacket(toRadioScratch.packet);
case ToRadio_want_config_id_tag:
config_nonce = toRadioScratch.want_config_id;
DEBUG_MSG("Client wants config, nonce=%u\n", config_nonce);
handleStartConfig();
break;
case ToRadio_disconnect_tag:
close();
break;
case ToRadio_packet_tag:
return handleToRadioPacket(toRadioScratch.packet);
case ToRadio_want_config_id_tag:
config_nonce = toRadioScratch.want_config_id;
DEBUG_MSG("Client wants config, nonce=%u\n", config_nonce);
handleStartConfig();
break;
case ToRadio_disconnect_tag:
DEBUG_MSG("Disconnecting from phone\n");
close();
break;
default:
// Ignore nop messages
// DEBUG_MSG("Error: unexpected ToRadio variant\n");
@@ -112,41 +109,60 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
*
* Our sending states progress in the following sequence (the client app ASSUMES THIS SEQUENCE, DO NOT CHANGE IT):
* STATE_SEND_MY_INFO, // send our my info record
* STATE_SEND_GROUPS
* STATE_SEND_NODEINFO, // states progress in this order as the device sends to the client
STATE_SEND_CONFIG,
STATE_SEND_NODEINFO, // states progress in this order as the device sends to to the client
STATE_SEND_COMPLETE_ID,
STATE_SEND_PACKETS // send packets or debug strings
*/
size_t PhoneAPI::getFromRadio(uint8_t *buf)
{
if (!available()) {
// DEBUG_MSG("getFromRadio, !available\n");
DEBUG_MSG("getFromRadio=not available\n");
return 0;
}
DEBUG_MSG("getFromRadio, state=%d\n", state);
// In case we send a FromRadio packet
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
// Advance states as needed
switch (state) {
case STATE_SEND_NOTHING:
DEBUG_MSG("getFromRadio=STATE_SEND_NOTHING\n");
break;
case STATE_SEND_MY_INFO:
DEBUG_MSG("getFromRadio=STATE_SEND_MY_INFO\n");
// If the user has specified they don't want our node to share its location, make sure to tell the phone
// app not to send locations on our behalf.
myNodeInfo.has_gps = gps && gps->isConnected(); // Update with latest GPS connect info
fromRadioScratch.which_payloadVariant = FromRadio_my_info_tag;
fromRadioScratch.my_info = myNodeInfo;
state = STATE_SEND_CONFIG;
state = STATE_SEND_NODEINFO;
service.refreshMyNodeInfo(); // Update my NodeInfo because the client will be asking for it soon.
break;
case STATE_SEND_NODEINFO: {
DEBUG_MSG("getFromRadio=STATE_SEND_NODEINFO\n");
const NodeInfo *info = nodeInfoForPhone;
nodeInfoForPhone = NULL; // We just consumed a nodeinfo, will need a new one next time
if (info) {
DEBUG_MSG("Sending nodeinfo: num=0x%x, lastseen=%u, id=%s, name=%s\n", info->num, info->last_heard, info->user.id,
info->user.long_name);
fromRadioScratch.which_payloadVariant = FromRadio_node_info_tag;
fromRadioScratch.node_info = *info;
// Stay in current state until done sending nodeinfos
} else {
DEBUG_MSG("Done sending nodeinfos\n");
state = STATE_SEND_CONFIG;
// Go ahead and send that ID right now
return getFromRadio(buf);
}
break;
}
case STATE_SEND_CONFIG:
DEBUG_MSG("getFromRadio=STATE_SEND_CONFIG\n");
fromRadioScratch.which_payloadVariant = FromRadio_config_tag;
switch (config_state) {
case Config_device_tag:
@@ -174,21 +190,25 @@ 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;
}
break;
case STATE_SEND_MODULECONFIG:
DEBUG_MSG("getFromRadio=STATE_SEND_MODULECONFIG\n");
fromRadioScratch.which_payloadVariant = FromRadio_moduleConfig_tag;
switch (config_state) {
case ModuleConfig_mqtt_tag:
@@ -220,30 +240,13 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
config_state++;
// Advance when we have sent all of our ModuleConfig objects
if (config_state > ModuleConfig_canned_message_tag) {
state = STATE_SEND_NODEINFO;
state = STATE_SEND_COMPLETE_ID;
config_state = Config_device_tag;
}
break;
case STATE_SEND_NODEINFO: {
const NodeInfo *info = nodeInfoForPhone;
nodeInfoForPhone = NULL; // We just consumed a nodeinfo, will need a new one next time
if (info) {
DEBUG_MSG("Sending nodeinfo: num=0x%x, lastseen=%u, id=%s, name=%s\n", info->num, info->last_heard, info->user.id,
info->user.long_name);
fromRadioScratch.which_payloadVariant = FromRadio_node_info_tag;
fromRadioScratch.node_info = *info;
// Stay in current state until done sending nodeinfos
} else {
DEBUG_MSG("Done sending nodeinfos\n");
state = STATE_SEND_COMPLETE_ID;
// Go ahead and send that ID right now
return getFromRadio(buf);
}
break;
}
case STATE_SEND_COMPLETE_ID:
DEBUG_MSG("getFromRadio=STATE_SEND_COMPLETE_ID\n");
fromRadioScratch.which_payloadVariant = FromRadio_config_complete_id_tag;
fromRadioScratch.config_complete_id = config_nonce;
config_nonce = 0;
@@ -252,6 +255,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
case STATE_SEND_PACKETS:
// Do we have a message from the mesh?
DEBUG_MSG("getFromRadio=STATE_SEND_PACKETS\n");
if (packetForPhone) {
printPacket("phone downloaded packet", packetForPhone);
@@ -278,7 +282,10 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
return 0;
}
void PhoneAPI::handleDisconnect() {}
void PhoneAPI::handleDisconnect()
{
DEBUG_MSG("PhoneAPI disconnect\n");
}
void PhoneAPI::releasePhonePacket()
{
@@ -294,35 +301,27 @@ 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: {
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
}

View File

@@ -22,10 +22,9 @@ class PhoneAPI
enum State {
STATE_SEND_NOTHING, // Initial state, don't send anything until the client starts asking for config
STATE_SEND_MY_INFO, // send our my info record
STATE_SEND_GROUPS, // new in 1.3?
STATE_SEND_NODEINFO, // states progress in this order as the device sends to to the client
STATE_SEND_CONFIG, // Replacement for the old Radioconfig
STATE_SEND_MODULECONFIG, // Send Module specific config
STATE_SEND_NODEINFO, // states progress in this order as the device sends to to the client
STATE_SEND_COMPLETE_ID,
STATE_SEND_PACKETS // send packets or debug strings
};
@@ -60,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)
@@ -82,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) { }

View File

@@ -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

View File

@@ -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);

View File

@@ -851,9 +851,11 @@ int readBit(const char *in, int bit_no) {
int read8bitCode(const char *in, int len, int bit_no) {
int bit_pos = bit_no & 0x07;
int char_pos = bit_no >> 3;
len >>= 3;
byte code = (((byte)in[char_pos]) << bit_pos);
if (bit_no + bit_pos < len) {
code |= ((byte)in[++char_pos]) >> (8 - bit_pos);
char_pos++;
if (char_pos < len) {
code |= ((byte)in[char_pos]) >> (8 - bit_pos);
} else
code |= (0xFF >> (8 - bit_pos));
return code;
@@ -1033,31 +1035,37 @@ int decodeRepeat(const char *in, int len, char *out, int olen, int ol, int *bit_
if (prev_lines) {
int32_t dict_len = readCount(in, bit_no, len) + NICE_LEN;
if (dict_len < NICE_LEN)
return ol;
return -1;
int32_t dist = readCount(in, bit_no, len);
if (dist < 0)
return ol;
return -1;
int32_t ctx = readCount(in, bit_no, len);
if (ctx < 0)
return ol;
return -1;
struct us_lnk_lst *cur_line = prev_lines;
const int left = olen - ol;
while (ctx--)
while (ctx-- && cur_line)
cur_line = cur_line->previous;
if (cur_line == NULL)
return -1;
if (left <= 0) return olen + 1;
if (dist >= strlen(cur_line->data))
return -1;
memmove(out + ol, cur_line->data + dist, min_of(left, dict_len));
if (left < dict_len) return olen + 1;
ol += dict_len;
} else {
int32_t dict_len = readCount(in, bit_no, len) + NICE_LEN;
if (dict_len < NICE_LEN)
return ol;
return -1;
int32_t dist = readCount(in, bit_no, len) + NICE_LEN - 1;
if (dist < NICE_LEN - 1)
return ol;
return -1;
const int32_t left = olen - ol;
//printf("Decode len: %d, dist: %d\n", dict_len - NICE_LEN, dist - NICE_LEN + 1);
if (left <= 0) return olen + 1;
if (ol - dist < 0)
return -1;
memmove(out + ol, out + ol - dist, min_of(left, dict_len));
if (left < dict_len) return olen + 1;
ol += dict_len;
@@ -1119,7 +1127,10 @@ int unishox2_decompress_lines(const char *in, int len, UNISHOX_API_OUT_AND_LEN(c
continue;
}
if (h == USX_DICT) {
DEC_OUTPUT_CHARS(olen, ol = decodeRepeat(in, len, out, olen, ol, &bit_no, prev_lines));
int rpt_ret = decodeRepeat(in, len, out, olen, ol, &bit_no, prev_lines);
if (rpt_ret < 0)
return ol; // if we break here it will only break out of switch
DEC_OUTPUT_CHARS(olen, ol = rpt_ret);
h = dstate;
continue;
}
@@ -1191,7 +1202,10 @@ int unishox2_decompress_lines(const char *in, int len, UNISHOX_API_OUT_AND_LEN(c
}
} else
if (h == USX_DICT) {
DEC_OUTPUT_CHARS(olen, ol = decodeRepeat(in, len, out, olen, ol, &bit_no, prev_lines));
int rpt_ret = decodeRepeat(in, len, out, olen, ol, &bit_no, prev_lines);
if (rpt_ret < 0)
break;
DEC_OUTPUT_CHARS(olen, ol = rpt_ret);
continue;
} else
if (h == USX_DELTA) {
@@ -1208,12 +1222,21 @@ int unishox2_decompress_lines(const char *in, int len, UNISHOX_API_OUT_AND_LEN(c
}
if (h == USX_NUM && v == 0) {
int idx = getStepCodeIdx(in, len, &bit_no, 5);
if (idx == 99)
break;
if (idx == 0) {
idx = getStepCodeIdx(in, len, &bit_no, 4);
if (idx >= 5)
break;
int32_t rem = readCount(in, &bit_no, len);
if (rem < 0)
break;
rem = (int)strlen(usx_templates[idx]) - rem;
if (usx_templates[idx] == NULL)
break;
size_t tlen = strlen(usx_templates[idx]);
if (rem > tlen)
break;
rem = tlen - rem;
int eof = 0;
for (int j = 0; j < rem; j++) {
char c_t = usx_templates[idx][j];

View File

@@ -6,6 +6,7 @@
#include <pb.h>
#include "channel.pb.h"
#include "config.pb.h"
#include "device_metadata.pb.h"
#include "mesh.pb.h"
#include "module_config.pb.h"
@@ -20,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 {
@@ -73,6 +75,8 @@ typedef struct _AdminMessage {
ModuleConfig set_module_config;
/* Sent immediatly after a config change has been sent to ensure comms, if this is not recieved, the config will be reverted after 10 mins */
bool confirm_set_module_config;
/* Send all channels in the response to this message */
bool get_all_channel_request;
/* Setting channels/radio config remotely carries the risk that you might send an invalid config and the radio never talks to your mesh again.
Therefore if setting either of these properties remotely, you must send a confirm_xxx message within 10 minutes.
If you fail to do so, the radio will assume loss of comms and revert your changes.
@@ -85,40 +89,26 @@ 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) */
uint32_t get_device_metadata_request;
/* Device metadata response */
DeviceMetadata get_device_metadata_response;
};
} 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
@@ -148,23 +138,17 @@ extern "C" {
#define AdminMessage_get_module_config_response_tag 15
#define AdminMessage_set_module_config_tag 16
#define AdminMessage_confirm_set_module_config_tag 17
#define AdminMessage_get_all_channel_request_tag 18
#define AdminMessage_confirm_set_channel_tag 32
#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
/* Struct field encoding specification for nanopb */
#define AdminMessage_FIELDLIST(X, a) \
@@ -182,23 +166,17 @@ X(a, STATIC, ONEOF, UENUM, (variant,get_module_config_request,get_module
X(a, STATIC, ONEOF, MESSAGE, (variant,get_module_config_response,get_module_config_response), 15) \
X(a, STATIC, ONEOF, MESSAGE, (variant,set_module_config,set_module_config), 16) \
X(a, STATIC, ONEOF, BOOL, (variant,confirm_set_module_config,confirm_set_module_config), 17) \
X(a, STATIC, ONEOF, BOOL, (variant,get_all_channel_request,get_all_channel_request), 18) \
X(a, STATIC, ONEOF, BOOL, (variant,confirm_set_channel,confirm_set_channel), 32) \
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, INT32, (variant,shutdown_seconds,shutdown_seconds), 51)
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)
#define AdminMessage_CALLBACK NULL
#define AdminMessage_DEFAULT NULL
#define AdminMessage_variant_set_owner_MSGTYPE User
@@ -209,6 +187,7 @@ X(a, STATIC, ONEOF, INT32, (variant,shutdown_seconds,shutdown_seconds),
#define AdminMessage_variant_set_config_MSGTYPE Config
#define AdminMessage_variant_get_module_config_response_MSGTYPE ModuleConfig
#define AdminMessage_variant_set_module_config_MSGTYPE ModuleConfig
#define AdminMessage_variant_get_device_metadata_response_MSGTYPE DeviceMetadata
extern const pb_msgdesc_t AdminMessage_msg;

View File

@@ -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)

View File

@@ -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" */

View File

@@ -27,6 +27,11 @@ PB_BIND(Config_DisplayConfig, Config_DisplayConfig, AUTO)
PB_BIND(Config_LoRaConfig, Config_LoRaConfig, 2)
PB_BIND(Config_BluetoothConfig, Config_BluetoothConfig, AUTO)

View File

@@ -51,6 +51,12 @@ typedef enum _Config_PowerConfig_ChargeCurrent {
Config_PowerConfig_ChargeCurrent_MA1320 = 16
} Config_PowerConfig_ChargeCurrent;
typedef enum _Config_WiFiConfig_WiFiMode {
Config_WiFiConfig_WiFiMode_Client = 0,
Config_WiFiConfig_WiFiMode_AccessPoint = 1,
Config_WiFiConfig_WiFiMode_AccessPointHidden = 2
} Config_WiFiConfig_WiFiMode;
typedef enum _Config_DisplayConfig_GpsCoordinateFormat {
Config_DisplayConfig_GpsCoordinateFormat_GpsFormatDec = 0,
Config_DisplayConfig_GpsCoordinateFormat_GpsFormatDMS = 1,
@@ -86,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;
@@ -99,6 +117,7 @@ typedef struct _Config_DisplayConfig {
uint32_t screen_on_secs;
Config_DisplayConfig_GpsCoordinateFormat gps_format;
uint32_t auto_screen_carousel_secs;
bool compass_north_top;
} Config_DisplayConfig;
typedef struct _Config_LoRaConfig {
@@ -138,10 +157,10 @@ typedef struct _Config_PowerConfig {
} Config_PowerConfig;
typedef struct _Config_WiFiConfig {
bool enabled;
Config_WiFiConfig_WiFiMode mode;
char ssid[33];
char psk[64];
bool ap_mode;
bool ap_hidden;
} Config_WiFiConfig;
typedef struct _Config {
@@ -153,6 +172,7 @@ typedef struct _Config {
Config_WiFiConfig wifi;
Config_DisplayConfig display;
Config_LoRaConfig lora;
Config_BluetoothConfig bluetooth;
} payloadVariant;
} Config;
@@ -170,6 +190,10 @@ typedef struct _Config {
#define _Config_PowerConfig_ChargeCurrent_MAX Config_PowerConfig_ChargeCurrent_MA1320
#define _Config_PowerConfig_ChargeCurrent_ARRAYSIZE ((Config_PowerConfig_ChargeCurrent)(Config_PowerConfig_ChargeCurrent_MA1320+1))
#define _Config_WiFiConfig_WiFiMode_MIN Config_WiFiConfig_WiFiMode_Client
#define _Config_WiFiConfig_WiFiMode_MAX Config_WiFiConfig_WiFiMode_AccessPointHidden
#define _Config_WiFiConfig_WiFiMode_ARRAYSIZE ((Config_WiFiConfig_WiFiMode)(Config_WiFiConfig_WiFiMode_AccessPointHidden+1))
#define _Config_DisplayConfig_GpsCoordinateFormat_MIN Config_DisplayConfig_GpsCoordinateFormat_GpsFormatDec
#define _Config_DisplayConfig_GpsCoordinateFormat_MAX Config_DisplayConfig_GpsCoordinateFormat_GpsFormatOSGR
#define _Config_DisplayConfig_GpsCoordinateFormat_ARRAYSIZE ((Config_DisplayConfig_GpsCoordinateFormat)(Config_DisplayConfig_GpsCoordinateFormat_GpsFormatOSGR+1))
@@ -182,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" {
@@ -192,18 +220,23 @@ extern "C" {
#define Config_DeviceConfig_init_default {_Config_DeviceConfig_Role_MIN, 0, 0, 0, ""}
#define Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0}
#define Config_PowerConfig_init_default {_Config_PowerConfig_ChargeCurrent_MIN, 0, 0, 0, 0, 0, 0, 0, 0}
#define Config_WiFiConfig_init_default {"", "", 0, 0}
#define Config_DisplayConfig_init_default {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0}
#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}
#define Config_PowerConfig_init_zero {_Config_PowerConfig_ChargeCurrent_MIN, 0, 0, 0, 0, 0, 0, 0, 0}
#define Config_WiFiConfig_init_zero {"", "", 0, 0}
#define Config_DisplayConfig_init_zero {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0}
#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
@@ -212,6 +245,7 @@ extern "C" {
#define Config_DisplayConfig_screen_on_secs_tag 1
#define Config_DisplayConfig_gps_format_tag 2
#define Config_DisplayConfig_auto_screen_carousel_secs_tag 3
#define Config_DisplayConfig_compass_north_top_tag 4
#define Config_LoRaConfig_tx_power_tag 1
#define Config_LoRaConfig_modem_preset_tag 2
#define Config_LoRaConfig_bandwidth_tag 3
@@ -238,16 +272,17 @@ extern "C" {
#define Config_PowerConfig_sds_secs_tag 10
#define Config_PowerConfig_ls_secs_tag 11
#define Config_PowerConfig_min_wake_secs_tag 12
#define Config_WiFiConfig_ssid_tag 1
#define Config_WiFiConfig_psk_tag 2
#define Config_WiFiConfig_ap_mode_tag 3
#define Config_WiFiConfig_ap_hidden_tag 4
#define Config_WiFiConfig_enabled_tag 1
#define Config_WiFiConfig_mode_tag 2
#define Config_WiFiConfig_ssid_tag 3
#define Config_WiFiConfig_psk_tag 4
#define Config_device_tag 1
#define Config_position_tag 2
#define Config_power_tag 3
#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) \
@@ -256,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
@@ -265,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) \
@@ -300,17 +337,18 @@ X(a, STATIC, SINGULAR, UINT32, min_wake_secs, 12)
#define Config_PowerConfig_DEFAULT NULL
#define Config_WiFiConfig_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, STRING, ssid, 1) \
X(a, STATIC, SINGULAR, STRING, psk, 2) \
X(a, STATIC, SINGULAR, BOOL, ap_mode, 3) \
X(a, STATIC, SINGULAR, BOOL, ap_hidden, 4)
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
X(a, STATIC, SINGULAR, UENUM, mode, 2) \
X(a, STATIC, SINGULAR, STRING, ssid, 3) \
X(a, STATIC, SINGULAR, STRING, psk, 4)
#define Config_WiFiConfig_CALLBACK NULL
#define Config_WiFiConfig_DEFAULT NULL
#define Config_DisplayConfig_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, screen_on_secs, 1) \
X(a, STATIC, SINGULAR, UENUM, gps_format, 2) \
X(a, STATIC, SINGULAR, UINT32, auto_screen_carousel_secs, 3)
X(a, STATIC, SINGULAR, UINT32, auto_screen_carousel_secs, 3) \
X(a, STATIC, SINGULAR, BOOL, compass_north_top, 4)
#define Config_DisplayConfig_CALLBACK NULL
#define Config_DisplayConfig_DEFAULT NULL
@@ -328,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;
@@ -335,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
@@ -344,10 +390,12 @@ 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 14
#define Config_DisplayConfig_size 16
#define Config_LoRaConfig_size 67
#define Config_PositionConfig_size 30
#define Config_PowerConfig_size 45

View File

@@ -0,0 +1,12 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.4.6 */
#include "device_metadata.pb.h"
#if PB_PROTO_HEADER_VERSION != 40
#error Regenerate this file with the current version of nanopb generator.
#endif
PB_BIND(DeviceMetadata, DeviceMetadata, AUTO)

View File

@@ -0,0 +1,53 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.6 */
#ifndef PB_DEVICE_METADATA_PB_H_INCLUDED
#define PB_DEVICE_METADATA_PB_H_INCLUDED
#include <pb.h>
#if PB_PROTO_HEADER_VERSION != 40
#error Regenerate this file with the current version of nanopb generator.
#endif
/* Struct definitions */
/* Device metadata response */
typedef struct _DeviceMetadata {
/* Device firmware version string */
char firmware_version[18];
/* Device state version */
uint32_t device_state_version;
} DeviceMetadata;
#ifdef __cplusplus
extern "C" {
#endif
/* Initializer values for message structs */
#define DeviceMetadata_init_default {"", 0}
#define DeviceMetadata_init_zero {"", 0}
/* Field tags (for use in manual encoding/decoding) */
#define DeviceMetadata_firmware_version_tag 1
#define DeviceMetadata_device_state_version_tag 2
/* Struct field encoding specification for nanopb */
#define DeviceMetadata_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, STRING, firmware_version, 1) \
X(a, STATIC, SINGULAR, UINT32, device_state_version, 2)
#define DeviceMetadata_CALLBACK NULL
#define DeviceMetadata_DEFAULT NULL
extern const pb_msgdesc_t DeviceMetadata_msg;
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
#define DeviceMetadata_fields &DeviceMetadata_msg
/* Maximum encoded size of messages (where known) */
#define DeviceMetadata_size 25
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

View File

@@ -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 23728
#define DeviceState_size 22218
#define OEMStore_size 2106
#ifdef __cplusplus

View File

@@ -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,8 +144,8 @@ extern const pb_msgdesc_t LocalModuleConfig_msg;
#define LocalModuleConfig_fields &LocalModuleConfig_msg
/* Maximum encoded size of messages (where known) */
#define LocalConfig_size 319
#define LocalModuleConfig_size 268
#define LocalConfig_size 333
#define LocalModuleConfig_size 270
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -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)

View File

@@ -245,19 +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;
} 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
@@ -454,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
@@ -625,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,
@@ -733,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}
@@ -747,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}
@@ -764,11 +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 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
@@ -820,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
@@ -854,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
@@ -901,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
@@ -930,20 +916,20 @@ 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) \
X(a, STATIC, SINGULAR, UINT32, expire, 4) \
X(a, STATIC, SINGULAR, BOOL, locked, 5)
#define Location_CALLBACK NULL
#define Location_DEFAULT NULL
X(a, STATIC, SINGULAR, BOOL, locked, 5) \
X(a, STATIC, SINGULAR, STRING, name, 6) \
X(a, STATIC, SINGULAR, STRING, description, 7)
#define Waypoint_CALLBACK NULL
#define Waypoint_DEFAULT NULL
#define MeshPacket_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, FIXED32, from, 1) \
@@ -1050,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;
@@ -1066,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
@@ -1078,19 +1064,19 @@ extern const pb_msgdesc_t Compressed_msg;
/* Maximum encoded size of messages (where known) */
#define Compressed_size 243
#define Data_size 296
#define FromRadio_size 356
#define Location_size 24
#define Data_size 270
#define FromRadio_size 330
#define LogRecord_size 81
#define MeshPacket_size 347
#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 350
#define User_size 95
#define ToRadio_size 324
#define User_size 77
#define Waypoint_size 156
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -4,7 +4,6 @@
#ifndef PB_MODULE_CONFIG_PB_H_INCLUDED
#define PB_MODULE_CONFIG_PB_H_INCLUDED
#include <pb.h>
#include "telemetry.pb.h"
#if PB_PROTO_HEADER_VERSION != 40
#error Regenerate this file with the current version of nanopb generator.
@@ -72,11 +71,12 @@ typedef struct _ModuleConfig_ExternalNotificationConfig {
} ModuleConfig_ExternalNotificationConfig;
typedef struct _ModuleConfig_MQTTConfig {
bool disabled;
bool enabled;
char address[32];
char username[32];
char password[32];
bool encryption_enabled;
bool json_enabled;
} ModuleConfig_MQTTConfig;
typedef struct _ModuleConfig_RangeTestConfig {
@@ -153,7 +153,7 @@ extern "C" {
/* Initializer values for message structs */
#define ModuleConfig_init_default {0, {ModuleConfig_MQTTConfig_init_default}}
#define ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0}
#define ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0}
#define ModuleConfig_SerialConfig_init_default {0, 0, 0, 0, _ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _ModuleConfig_SerialConfig_Serial_Mode_MIN}
#define ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0}
#define ModuleConfig_StoreForwardConfig_init_default {0, 0, 0, 0, 0}
@@ -161,7 +161,7 @@ extern "C" {
#define ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0}
#define ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
#define ModuleConfig_init_zero {0, {ModuleConfig_MQTTConfig_init_zero}}
#define ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0}
#define ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0}
#define ModuleConfig_SerialConfig_init_zero {0, 0, 0, 0, _ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _ModuleConfig_SerialConfig_Serial_Mode_MIN}
#define ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0}
#define ModuleConfig_StoreForwardConfig_init_zero {0, 0, 0, 0, 0}
@@ -187,11 +187,12 @@ 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
#define ModuleConfig_MQTTConfig_encryption_enabled_tag 5
#define ModuleConfig_MQTTConfig_json_enabled_tag 6
#define ModuleConfig_RangeTestConfig_enabled_tag 1
#define ModuleConfig_RangeTestConfig_sender_tag 2
#define ModuleConfig_RangeTestConfig_save_tag 3
@@ -240,11 +241,12 @@ 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) \
X(a, STATIC, SINGULAR, BOOL, encryption_enabled, 5)
X(a, STATIC, SINGULAR, BOOL, encryption_enabled, 5) \
X(a, STATIC, SINGULAR, BOOL, json_enabled, 6)
#define ModuleConfig_MQTTConfig_CALLBACK NULL
#define ModuleConfig_MQTTConfig_DEFAULT NULL
@@ -331,12 +333,12 @@ extern const pb_msgdesc_t ModuleConfig_CannedMessageConfig_msg;
/* Maximum encoded size of messages (where known) */
#define ModuleConfig_CannedMessageConfig_size 49
#define ModuleConfig_ExternalNotificationConfig_size 20
#define ModuleConfig_MQTTConfig_size 103
#define ModuleConfig_MQTTConfig_size 105
#define ModuleConfig_RangeTestConfig_size 10
#define ModuleConfig_SerialConfig_size 26
#define ModuleConfig_StoreForwardConfig_size 22
#define ModuleConfig_TelemetryConfig_size 18
#define ModuleConfig_size 105
#define ModuleConfig_size 107
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -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. */

View File

@@ -610,7 +610,7 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
// data->wifi
String ipStr;
if (config.wifi.ap_mode || isSoftAPForced()) {
if (config.wifi.mode == Config_WiFiConfig_WiFiMode_AccessPoint || config.wifi.mode == Config_WiFiConfig_WiFiMode_AccessPointHidden || isSoftAPForced()) {
ipStr = String(WiFi.softAPIP().toString());
} else {
ipStr = String(WiFi.localIP().toString());

View File

@@ -62,7 +62,7 @@ static int32_t reconnectWiFi()
const char *wifiName = config.wifi.ssid;
const char *wifiPsw = config.wifi.psk;
if (needReconnect && !WiFi.isConnected()) {
if (config.wifi.enabled && needReconnect && !WiFi.isConnected()) {
// if (radioConfig.has_preferences && needReconnect && !WiFi.isConnected()) {
if (!*wifiPsw) // Treat empty password as no password
@@ -184,17 +184,21 @@ bool initWifi(bool forceSoftAP)
{
forcedSoftAP = forceSoftAP;
if ((config.wifi.ssid[0]) || forceSoftAP) {
if (config.wifi.enabled && ((config.wifi.ssid[0]) || forceSoftAP)) {
// if ((radioConfig.has_preferences && config.wifi.ssid[0]) || forceSoftAP) {
const char *wifiName = config.wifi.ssid;
const char *wifiPsw = config.wifi.psk;
if (forceSoftAP) {
DEBUG_MSG("WiFi ... Forced AP Mode\n");
} else if (config.wifi.ap_mode) {
} else if (config.wifi.mode == Config_WiFiConfig_WiFiMode_AccessPoint) {
DEBUG_MSG("WiFi ... AP Mode\n");
} else {
} else if (config.wifi.mode == Config_WiFiConfig_WiFiMode_AccessPointHidden) {
DEBUG_MSG("WiFi ... Hidden AP Mode\n");
} else if (config.wifi.mode == Config_WiFiConfig_WiFiMode_Client) {
DEBUG_MSG("WiFi ... Client Mode\n");
} else {
DEBUG_MSG("WiFi ... WiFi Disabled\n");
}
createSSLCert();
@@ -203,7 +207,7 @@ bool initWifi(bool forceSoftAP)
wifiPsw = NULL;
if (*wifiName || forceSoftAP) {
if (config.wifi.ap_mode || forceSoftAP) {
if (config.wifi.mode == Config_WiFiConfig_WiFiMode_AccessPoint || config.wifi.mode == Config_WiFiConfig_WiFiMode_AccessPointHidden || forceSoftAP) {
IPAddress apIP(192, 168, 42, 1);
WiFi.onEvent(WiFiEvent);
@@ -218,7 +222,7 @@ bool initWifi(bool forceSoftAP)
} else {
// If AP is configured to be hidden hidden
if (config.wifi.ap_hidden) {
if (config.wifi.mode == Config_WiFiConfig_WiFiMode_AccessPointHidden) {
// The configurations on softAP are from the espresif library
int ok = WiFi.softAP(wifiName, wifiPsw, 1, 1, 4);
@@ -373,7 +377,7 @@ static void WiFiEvent(WiFiEvent_t event)
void handleDNSResponse()
{
if (config.wifi.ap_mode || isSoftAPForced()) {
if (config.wifi.mode == Config_WiFiConfig_WiFiMode_AccessPoint || config.wifi.mode == Config_WiFiConfig_WiFiMode_AccessPointHidden || isSoftAPForced()) {
dnsServer.processNextRequest();
}
}

View File

@@ -109,6 +109,11 @@ bool AdminModule::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r)
shutdownAtMsec = (s < 0) ? 0 : (millis() + s * 1000);
break;
}
case AdminMessage_get_device_metadata_request_tag: {
DEBUG_MSG("Client is getting device metadata\n");
handleGetDeviceMetadata(mp);
break;
}
#ifdef ARCH_PORTDUINO
case AdminMessage_exit_simulator_tag:
@@ -165,80 +170,95 @@ 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;
requiresReboot = true;
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();
@@ -304,8 +324,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).
@@ -374,6 +398,18 @@ void AdminModule::handleGetModuleConfig(const MeshPacket &req, const uint32_t co
}
}
void AdminModule::handleGetDeviceMetadata(const MeshPacket &req) {
AdminMessage r = AdminMessage_init_default;
DeviceMetadata deviceMetadata;
strncpy(deviceMetadata.firmware_version, myNodeInfo.firmware_version, 18);
deviceMetadata.device_state_version = DEVICESTATE_CUR_VER;
r.get_device_metadata_response = deviceMetadata;
r.which_variant = AdminMessage_get_device_metadata_response_tag;
myReply = allocDataProtobuf(r);
}
void AdminModule::handleGetChannel(const MeshPacket &req, uint32_t channelIndex)
{
if (req.decoded.want_response) {

View File

@@ -27,6 +27,7 @@ class AdminModule : public ProtobufModule<AdminMessage>
void handleGetConfig(const MeshPacket &req, uint32_t configType);
void handleGetModuleConfig(const MeshPacket &req, uint32_t configType);
void handleGetChannel(const MeshPacket &req, uint32_t channelIndex);
void handleGetDeviceMetadata(const MeshPacket &req);
/**
* Setters

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -103,6 +103,8 @@ MeshPacket *PositionModule::allocReply()
} else
DEBUG_MSG("Providing time to mesh %u\n", p.time);
DEBUG_MSG("Position reply: time=%i, latI=%i, lonI=-%i\n", p.time, p.latitude_i, p.longitude_i);
return allocDataProtobuf(p);
}
@@ -127,9 +129,8 @@ int32_t PositionModule::runOnce()
// We limit our GPS broadcasts to a max rate
uint32_t now = millis();
if (lastGpsSend == 0 || now - lastGpsSend >= config.position.position_broadcast_secs
? config.position.position_broadcast_secs
: default_broadcast_interval_secs * 1000) {
uint32_t intervalMs = config.position.position_broadcast_secs > 0 ? config.position.position_broadcast_secs * 1000 : default_broadcast_interval_secs * 1000;
if (lastGpsSend == 0 || (now - lastGpsSend) >= intervalMs) {
// Only send packets if the channel is less than 40% utilized.
if (airTime->channelUtilizationPercent() < 40) {
@@ -144,7 +145,6 @@ int32_t PositionModule::runOnce()
currentGeneration = radioGeneration;
DEBUG_MSG("Sending pos@%x:6 to mesh (wantReplies=%d)\n", node->position.pos_timestamp, requestReplies);
sendOurPosition(NODENUM_BROADCAST, requestReplies);
}
} else {

View File

@@ -21,7 +21,7 @@ int32_t DeviceTelemetryModule::runOnce()
sendOurTelemetry();
// OSThread library. Multiply the preference value by 1000 to convert seconds to miliseconds
return getIntervalOrDefaultMs(moduleConfig.telemetry.device_update_interval);
return getConfiguredOrDefaultMs(moduleConfig.telemetry.device_update_interval);
#endif
}

View File

@@ -97,7 +97,7 @@ int32_t EnvironmentTelemetryModule::runOnce()
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
}
return getIntervalOrDefaultMs(moduleConfig.telemetry.environment_update_interval);
return getConfiguredOrDefaultMs(moduleConfig.telemetry.environment_update_interval);
#endif
}

View File

@@ -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;
}
}

View 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
}

View 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;

View File

@@ -27,7 +27,7 @@ void MQTT::onPublish(char *topic, byte *payload, unsigned int length)
{
// parsing ServiceEnvelope
ServiceEnvelope e = ServiceEnvelope_init_default;
if (!pb_decode_from_bytes(payload, length, ServiceEnvelope_fields, &e)) {
if (moduleConfig.mqtt.json_enabled && !pb_decode_from_bytes(payload, length, ServiceEnvelope_fields, &e)) {
// check if this is a json payload message
using namespace json11;
@@ -44,17 +44,18 @@ void MQTT::onPublish(char *topic, byte *payload, unsigned int length)
if (json["sender"].string_value().compare(owner.id) != 0) {
std::string jsonPayloadStr = json["payload"].dump();
DEBUG_MSG("Received json payload %s, length %u\n", jsonPayloadStr.c_str(), jsonPayloadStr.length());
// FIXME Not sure we need to be doing this
// construct protobuf data packet using TEXT_MESSAGE, send it to the mesh
MeshPacket *p = router->allocForSending();
p->decoded.portnum = PortNum_TEXT_MESSAGE_APP;
if (jsonPayloadStr.length() <= sizeof(p->decoded.payload.bytes)) {
memcpy(p->decoded.payload.bytes, jsonPayloadStr.c_str(), jsonPayloadStr.length());
p->decoded.payload.size = jsonPayloadStr.length();
MeshPacket *packet = packetPool.allocCopy(*p);
service.sendToMesh(packet, RX_SRC_LOCAL);
} else {
DEBUG_MSG("Received MQTT json payload too long, dropping\n");
}
// MeshPacket *p = router->allocForSending();
// p->decoded.portnum = PortNum_TEXT_MESSAGE_APP;
// if (jsonPayloadStr.length() <= sizeof(p->decoded.payload.bytes)) {
// memcpy(p->decoded.payload.bytes, jsonPayloadStr.c_str(), jsonPayloadStr.length());
// p->decoded.payload.size = jsonPayloadStr.length();
// MeshPacket *packet = packetPool.allocCopy(*p);
// service.sendToMesh(packet, RX_SRC_LOCAL);
// } else {
// DEBUG_MSG("Received MQTT json payload too long, dropping\n");
// }
} else {
DEBUG_MSG("Ignoring downlink message we originally sent.\n");
}
@@ -175,9 +176,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++) {
@@ -239,13 +238,15 @@ void MQTT::onSend(const MeshPacket &mp, ChannelIndex chIndex)
pubSub.publish(topic.c_str(), bytes, numBytes, false);
// handle json topic
using namespace json11;
auto jsonString = this->downstreamPacketToJson((MeshPacket *)&mp);
if (jsonString.length() != 0) {
String topicJson = jsonTopic + channelId + "/" + owner.id;
DEBUG_MSG("publish json message to %s, %u bytes: %s\n", topicJson.c_str(), jsonString.length(), jsonString.c_str());
pubSub.publish(topicJson.c_str(), jsonString.c_str(), false);
if (moduleConfig.mqtt.json_enabled) {
// handle json topic
using namespace json11;
auto jsonString = this->downstreamPacketToJson((MeshPacket *)&mp);
if (jsonString.length() != 0) {
String topicJson = jsonTopic + channelId + "/" + owner.id;
DEBUG_MSG("publish json message to %s, %u bytes: %s\n", topicJson.c_str(), jsonString.length(), jsonString.c_str());
pubSub.publish(topicJson.c_str(), jsonString.c_str(), false);
}
}
}
}
@@ -291,7 +292,14 @@ String MQTT::downstreamPacketToJson(MeshPacket *mp)
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &Telemetry_msg, &scratch)) {
decoded = &scratch;
if (decoded->which_variant == Telemetry_environment_metrics_tag) {
if (decoded->which_variant == Telemetry_device_metrics_tag) {
msgPayload = Json::object{
{"battery_level", (int)decoded->variant.device_metrics.battery_level},
{"voltage", decoded->variant.device_metrics.voltage},
{"channel_utilization", decoded->variant.device_metrics.channel_utilization},
{"air_util_tx", decoded->variant.device_metrics.air_util_tx},
};
} else if (decoded->which_variant == Telemetry_environment_metrics_tag) {
msgPayload = Json::object{
{"temperature", decoded->variant.environment_metrics.temperature},
{"relative_humidity", decoded->variant.environment_metrics.relative_humidity},
@@ -314,10 +322,12 @@ String MQTT::downstreamPacketToJson(MeshPacket *mp)
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &User_msg, &scratch)) {
decoded = &scratch;
msgPayload = Json::object{{"id", decoded->id},
{"longname", decoded->long_name},
{"shortname", decoded->short_name},
{"hardware", decoded->hw_model}};
msgPayload = Json::object{
{"id", decoded->id},
{"longname", decoded->long_name},
{"shortname", decoded->short_name},
{"hardware", decoded->hw_model}
};
} else
DEBUG_MSG("Error decoding protobuf for nodeinfo message!\n");
@@ -333,7 +343,36 @@ String MQTT::downstreamPacketToJson(MeshPacket *mp)
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &Position_msg, &scratch)) {
decoded = &scratch;
msgPayload = Json::object{
{"latitude_i", decoded->latitude_i}, {"longitude_i", decoded->longitude_i}, {"altitude", decoded->altitude}};
{"time", (int)decoded->time},
{"pos_timestamp", (int)decoded->pos_timestamp},
{"latitude_i", decoded->latitude_i},
{"longitude_i", decoded->longitude_i},
{"altitude", decoded->altitude}
};
} else {
DEBUG_MSG("Error decoding protobuf for position message!\n");
}
};
break;
}
case PortNum_WAYPOINT_APP: {
msgType = "position";
Waypoint scratch;
Waypoint *decoded = NULL;
if (mp->which_payloadVariant == MeshPacket_decoded_tag) {
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &Waypoint_msg, &scratch)) {
decoded = &scratch;
msgPayload = Json::object{
{"id", (int)decoded->id},
{"name", decoded->name},
{"description", decoded->description},
{"expire", (int)decoded->expire},
{"locked", decoded->locked},
{"latitude_i", decoded->latitude_i},
{"longitude_i", decoded->longitude_i},
};
} else {
DEBUG_MSG("Error decoding protobuf for position message!\n");
}
@@ -346,14 +385,16 @@ String MQTT::downstreamPacketToJson(MeshPacket *mp)
}
// assemble the final jsonObj
Json jsonObj = Json::object{{"id", Json((int)mp->id)},
{"timestamp", Json((int)mp->rx_time)},
{"to", Json((int)mp->to)},
{"from", Json((int)mp->from)},
{"channel", Json((int)mp->channel)},
{"type", msgType.c_str()},
{"sender", owner.id},
{"payload", msgPayload}};
Json jsonObj = Json::object{
{"id", Json((int)mp->id)},
{"timestamp", Json((int)mp->rx_time)},
{"to", Json((int)mp->to)},
{"from", Json((int)mp->from)},
{"channel", Json((int)mp->channel)},
{"type", msgType.c_str()},
{"sender", owner.id},
{"payload", msgPayload}
};
// serialize and return it
static std::string jsonStr = jsonObj.dump();

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,225 @@
#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()
{
return bleServer;
}
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();
}

View 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();

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,10 +0,0 @@
#pragma once
class NRF52Bluetooth
{
public:
void setup();
void shutdown();
void clearBonds();
};

View File

@@ -6,6 +6,9 @@
// defaults for ESP32 architecture
//
#ifndef HAS_BLUETOOTH
#define HAS_BLUETOOTH 1
#endif
#ifndef HAS_WIFI
#define HAS_WIFI 1
#endif
@@ -103,3 +106,4 @@
#endif
#define SERIAL0_RX_GPIO 3 // Always GPIO3 on ESP32

View File

@@ -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();
} else {
esp32Bluetooth->shutdown();
if (on && !nimbleBluetooth->isActive()) {
nimbleBluetooth->setup();
} else if (!on) {
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();

View File

@@ -1,120 +1,120 @@
/*********************************************************************
* SEGGER Microcontroller GmbH & Co. KG *
* The Embedded Experts *
**********************************************************************
* *
* (c) 1995 - 2015 SEGGER Microcontroller GmbH & Co. KG *
* *
* www.segger.com Support: support@segger.com *
* *
**********************************************************************
----------------------------------------------------------------------
File : JLINK_MONITOR.c
Purpose : Implementation of debug monitor for J-Link monitor mode debug on Cortex-M devices.
-------- END-OF-HEADER ---------------------------------------------
*/
#include "JLINK_MONITOR.h"
/*********************************************************************
*
* Configuration
*
**********************************************************************
*/
/*********************************************************************
*
* Defines
*
**********************************************************************
*/
/*********************************************************************
*
* Types
*
**********************************************************************
*/
/*********************************************************************
*
* Static data
*
**********************************************************************
*/
volatile int MAIN_MonCnt; // Incremented in JLINK_MONITOR_OnPoll() while CPU is in debug mode
/*********************************************************************
*
* Local functions
*
**********************************************************************
*/
/*********************************************************************
*
* Global functions
*
**********************************************************************
*/
/*********************************************************************
*
* JLINK_MONITOR_OnExit()
*
* Function description
* Called from DebugMon_Handler(), once per debug exit.
* May perform some target specific operations to be done on debug mode exit.
*
* Notes
* (1) Must not keep the CPU busy for more than 100 ms
*/
void JLINK_MONITOR_OnExit(void) {
//
// Add custom code here
//
// BSP_ClrLED(0);
}
/*********************************************************************
*
* JLINK_MONITOR_OnEnter()
*
* Function description
* Called from DebugMon_Handler(), once per debug entry.
* May perform some target specific operations to be done on debug mode entry
*
* Notes
* (1) Must not keep the CPU busy for more than 100 ms
*/
void JLINK_MONITOR_OnEnter(void) {
//
// Add custom code here
//
// BSP_SetLED(0);
// BSP_ClrLED(1);
}
/*********************************************************************
*
* JLINK_MONITOR_OnPoll()
*
* Function description
* Called periodically from DebugMon_Handler(), to perform some actions that need to be performed periodically during debug mode.
*
* Notes
* (1) Must not keep the CPU busy for more than 100 ms
*/
void JLINK_MONITOR_OnPoll(void) {
//
// Add custom code here
//
MAIN_MonCnt++;
// BSP_ToggleLED(0);
// _Delay(500000);
}
/****** End Of File *************************************************/
/*********************************************************************
* SEGGER Microcontroller GmbH & Co. KG *
* The Embedded Experts *
**********************************************************************
* *
* (c) 1995 - 2015 SEGGER Microcontroller GmbH & Co. KG *
* *
* www.segger.com Support: support@segger.com *
* *
**********************************************************************
----------------------------------------------------------------------
File : JLINK_MONITOR.c
Purpose : Implementation of debug monitor for J-Link monitor mode debug on Cortex-M devices.
-------- END-OF-HEADER ---------------------------------------------
*/
#include "JLINK_MONITOR.h"
/*********************************************************************
*
* Configuration
*
**********************************************************************
*/
/*********************************************************************
*
* Defines
*
**********************************************************************
*/
/*********************************************************************
*
* Types
*
**********************************************************************
*/
/*********************************************************************
*
* Static data
*
**********************************************************************
*/
volatile int MAIN_MonCnt; // Incremented in JLINK_MONITOR_OnPoll() while CPU is in debug mode
/*********************************************************************
*
* Local functions
*
**********************************************************************
*/
/*********************************************************************
*
* Global functions
*
**********************************************************************
*/
/*********************************************************************
*
* JLINK_MONITOR_OnExit()
*
* Function description
* Called from DebugMon_Handler(), once per debug exit.
* May perform some target specific operations to be done on debug mode exit.
*
* Notes
* (1) Must not keep the CPU busy for more than 100 ms
*/
void JLINK_MONITOR_OnExit(void) {
//
// Add custom code here
//
// BSP_ClrLED(0);
}
/*********************************************************************
*
* JLINK_MONITOR_OnEnter()
*
* Function description
* Called from DebugMon_Handler(), once per debug entry.
* May perform some target specific operations to be done on debug mode entry
*
* Notes
* (1) Must not keep the CPU busy for more than 100 ms
*/
void JLINK_MONITOR_OnEnter(void) {
//
// Add custom code here
//
// BSP_SetLED(0);
// BSP_ClrLED(1);
}
/*********************************************************************
*
* JLINK_MONITOR_OnPoll()
*
* Function description
* Called periodically from DebugMon_Handler(), to perform some actions that need to be performed periodically during debug mode.
*
* Notes
* (1) Must not keep the CPU busy for more than 100 ms
*/
void JLINK_MONITOR_OnPoll(void) {
//
// Add custom code here
//
MAIN_MonCnt++;
// BSP_ToggleLED(0);
// _Delay(500000);
}
/****** End Of File *************************************************/

View File

@@ -1,27 +1,27 @@
/*********************************************************************
* SEGGER Microcontroller GmbH & Co. KG *
* The Embedded Experts *
**********************************************************************
* *
* (c) 1995 - 2015 SEGGER Microcontroller GmbH & Co. KG *
* *
* www.segger.com Support: support@segger.com *
* *
**********************************************************************
----------------------------------------------------------------------
File : JLINK_MONITOR.h
Purpose : Header file of debug monitor for J-Link monitor mode debug on Cortex-M devices.
-------- END-OF-HEADER ---------------------------------------------
*/
#ifndef JLINK_MONITOR_H
#define JLINK_MONITOR_H
void JLINK_MONITOR_OnExit (void);
void JLINK_MONITOR_OnEnter (void);
void JLINK_MONITOR_OnPoll (void);
#endif
/****** End Of File *************************************************/
/*********************************************************************
* SEGGER Microcontroller GmbH & Co. KG *
* The Embedded Experts *
**********************************************************************
* *
* (c) 1995 - 2015 SEGGER Microcontroller GmbH & Co. KG *
* *
* www.segger.com Support: support@segger.com *
* *
**********************************************************************
----------------------------------------------------------------------
File : JLINK_MONITOR.h
Purpose : Header file of debug monitor for J-Link monitor mode debug on Cortex-M devices.
-------- END-OF-HEADER ---------------------------------------------
*/
#ifndef JLINK_MONITOR_H
#define JLINK_MONITOR_H
void JLINK_MONITOR_OnExit (void);
void JLINK_MONITOR_OnEnter (void);
void JLINK_MONITOR_OnPoll (void);
#endif
/****** End Of File *************************************************/

View File

@@ -22,7 +22,7 @@ static BLEDfu bledfu; // DFU software update helper service
static uint8_t fromRadioBytes[FromRadio_size];
static uint8_t toRadioBytes[ToRadio_size];
static bool bleConnected;
static uint16_t connectionHandle;
class BluetoothPhoneAPI : public PhoneAPI
{
@@ -39,22 +39,23 @@ 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);
connectionHandle = conn_handle;
char central_name[32] = {0};
connection->getPeerName(central_name, sizeof(central_name));
DEBUG_MSG("BLE Connected to %s\n", central_name);
bleConnected = true;
}
/**
@@ -62,15 +63,13 @@ 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;
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 +125,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 +140,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 +150,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 +167,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 +211,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 +221,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 +254,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 +262,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 +287,35 @@ void NRF52Bluetooth::clearBonds()
Bluefruit.Periph.clearBonds();
Bluefruit.Central.clearBonds();
}
void NRF52Bluetooth::onConnectionSecured(uint16_t conn_handle)
{
DEBUG_MSG("BLE connection secured\n");
}
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();
}

View File

@@ -0,0 +1,15 @@
#pragma once
class NRF52Bluetooth
{
public:
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);
};

View File

@@ -5,7 +5,9 @@
//
// defaults for NRF52 architecture
//
#ifndef HAS_BLUETOOTH
#define HAS_BLUETOOTH 1
#endif
#ifndef HAS_SCREEN
#define HAS_SCREEN 1
#endif
@@ -40,6 +42,8 @@
#define HW_VENDOR HardwareModel_T_ECHO
#elif defined(NORDIC_PCA10059)
#define HW_VENDOR HardwareModel_NRF52840_PCA10059
#elif defined(PRIVATE_HW)
#define HW_VENDOR HardwareModel_PRIVATE_HW
#else
#define HW_VENDOR HardwareModel_NRF52_UNKNOWN
#endif

Some files were not shown because too many files have changed in this diff Show More