Compare commits

...

88 Commits

Author SHA1 Message Date
Ben Meadors
d4ea9568ac Save devicestate (nodedb) on position config change (#1829) 2022-10-20 13:14:53 -05:00
Ben Meadors
97968213ff Factory reset should include modules and channels (#1828) 2022-10-20 07:51:52 -05:00
Thomas Göttgens
995885962d Merge pull request #1826 from meshtastic/oem-proto
wire in OEM.proto keystore
2022-10-20 09:10:01 +02:00
Ben Meadors
ddc1928bbb Merge branch 'master' into oem-proto 2022-10-19 19:22:35 -05:00
Ben Meadors
056a93f0c9 Consolidate reboots (#1827) 2022-10-19 19:19:04 -05:00
Ben Meadors
3d9845ff6d Update checkout version and release string 2022-10-19 11:43:24 -05:00
Ben Meadors
b615463981 Update download-artifiact version 2022-10-19 11:35:25 -05:00
Ben Meadors
d3540e82ff I think these tokens are extra 2022-10-19 10:44:09 -05:00
Ben Meadors
15ec8ba6a3 Whoops 2022-10-19 08:58:14 -05:00
Ben Meadors
db12eab083 Update setup-python 2022-10-19 08:51:00 -05:00
Thomas Göttgens
7d8c77a4b2 Merge branch 'master' into oem-proto 2022-10-19 15:42:21 +02:00
Thomas Göttgens
7c8c479b96 wire in OEM.proto keystore 2022-10-19 15:39:06 +02:00
Ben Meadors
e29ae1cc91 Update upload-artifact version 2022-10-19 08:11:28 -05:00
Ben Meadors
089dd5b4d7 Update github cache action version 2022-10-19 07:38:44 -05:00
Ben Meadors
06285b599c Update deprecated ::set-output commands 2022-10-19 07:35:16 -05:00
Thomas Göttgens
1b6395b4e4 Merge pull request #1825 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-19 13:45:12 +02:00
caveman99
2236f74a55 [create-pull-request] automated change 2022-10-19 11:44:12 +00:00
Thomas Göttgens
43c9ab1faa Merge pull request #1824 from meshtastic/caveman99-patch1
Dont retransmit packets destined for ourselves.
2022-10-19 11:56:44 +02:00
Thomas Göttgens
b56f9b3b16 Dont retransmit packets destined for ourselves.
Solves assert failed: virtual ErrorCode Router::send(MeshPacket*) Router.cpp:189 (p->to != nodeDB.getNodeNum())
2022-10-19 11:44:26 +02:00
Thomas Göttgens
303396dfc3 Merge pull request #1823 from meshtastic/json-cleanup
Json cleanup
2022-10-19 11:20:24 +02:00
Thomas Göttgens
075a53ced0 Update MQTT.cpp 2022-10-19 11:04:13 +02:00
Thomas Göttgens
18ccb38824 Update MQTT.cpp 2022-10-19 11:01:23 +02:00
Thomas Göttgens
c97831963b just for good measure, correct json type field 2022-10-19 10:58:46 +02:00
Thomas Göttgens
7c3dc076d2 only convert and send JSON topics with type 'sendtext' 2022-10-19 10:54:56 +02:00
Thomas Göttgens
b859347ecd Merge pull request #1822 from meshtastic/json-cleanup
possible fix for stuck MQTT handler.
2022-10-19 00:02:00 +02:00
Thomas Göttgens
ea87193c8f possible fix for stuck MQTT handler. 2022-10-18 21:51:40 +02:00
Thomas Göttgens
c1381b9ebd Merge pull request #1818 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-18 12:21:02 +02:00
caveman99
227cd93e67 [create-pull-request] automated change 2022-10-18 10:20:06 +00:00
Thomas Göttgens
f68f8e5547 Merge pull request #1817 from meshtastic/json-cleanup
fix JSON red herring error messages and Redirectable Print's new fixed buffer
2022-10-18 11:57:11 +02:00
Thomas Göttgens
943e6f02d4 Merge branch 'master' into json-cleanup 2022-10-18 11:18:34 +02:00
Thomas Göttgens
01298a7b01 Update RedirectablePrint.cpp 2022-10-18 11:18:12 +02:00
Thomas Göttgens
46aee8274f fix JSON red herring error messages and Redirectable Print's new fixed buffer. 2022-10-18 11:16:21 +02:00
Thomas Göttgens
f76a2eeb9e Merge pull request #1816 from meshtastic/wifi-disconnect-fix
If wifi credentials ever go stale, dump them.
2022-10-18 11:15:19 +02:00
Thomas Göttgens
3b7c0be842 don't irritate people with non working options 2022-10-18 10:30:50 +02:00
Thomas Göttgens
49378a9145 If wifi credentials ever go stale, dump them.
This solves the dreaded 5 - STA_DISCONNECTED / 2 - AUTH_EXPIRE loops
2022-10-18 10:16:47 +02:00
Thomas Göttgens
139f61d03e Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-17 16:45:28 +02:00
Ben Meadors
f10d04591d Don't make a nested json object payload (#1815) 2022-10-17 09:09:28 -05:00
Thomas Göttgens
e65d9e8ccd Add support for SX1281 on 2.4 GHz (#1809)
* Add support for SX1281 on 2.4 GHz

* only allow wide BW settings when the right chip is detected

* portduino cannot use this chip yet as it uses an old modified version of radiolib

* missed a spot

* Attempt to supress false positive

* Attempt to supress false positive

* Trying casing from the cpp-check manual

* Trying casing from the cpp-check manual

* Inline suppr should be default but...

* Maybe casting it will make the damn thing shut up

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2022-10-17 08:33:41 -05:00
Ben Meadors
1fc3c0af70 Update variant.h (#1814) 2022-10-17 08:07:18 -05:00
Thomas Göttgens
e4751e34ae missed a spot 2022-10-17 10:34:43 +02:00
Thomas Göttgens
e922169e72 Merge branch 'LORA-24' of github.com:meshtastic/Meshtastic-device 2022-10-17 10:32:35 +02:00
Thomas Göttgens
2b851ef6ae Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-17 10:32:05 +02:00
Thomas Göttgens
5f4b93aba2 portduino cannot use this chip yet as it uses an old modified version of radiolib 2022-10-17 10:31:29 +02:00
Thomas Göttgens
b66d1a5dab Merge branch 'master' into LORA-24 2022-10-17 10:05:15 +02:00
Thomas Göttgens
867525eff8 Merge pull request #1813 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-17 10:05:00 +02:00
caveman99
7dcc981a2c [create-pull-request] automated change 2022-10-17 08:04:36 +00:00
Thomas Göttgens
38fed8a61e Merge branch 'LORA-24' of github.com:meshtastic/Meshtastic-device 2022-10-17 10:00:41 +02:00
Thomas Göttgens
31c2c8a7a3 only allow wide BW settings when the right chip is detected 2022-10-17 10:00:00 +02:00
Thomas Göttgens
a081d28e36 Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-17 09:45:39 +02:00
Ben Meadors
93bb4f84f9 Merge branch 'master' into LORA-24 2022-10-16 17:27:18 -05:00
github-actions[bot]
72e04edd7f [create-pull-request] automated change (#1812)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2022-10-16 17:26:55 -05:00
Ben Meadors
b0d05522c0 Make telemetry packets minimum priority (#1810) 2022-10-16 15:59:59 -05:00
Thomas Göttgens
f6119639bb Add support for SX1281 on 2.4 GHz 2022-10-16 19:07:58 +02:00
Ben Meadors
fc57a9daa4 Send environment telemetry every minute (#1808) 2022-10-16 11:36:38 -05:00
Thomas Göttgens
d8f44d7b1b Merge pull request #1807 from meshtastic/nmea-serial
Add NMEA output mode to serial module
2022-10-16 17:15:24 +02:00
Ben Meadors
efe2e90a03 Merge branch 'master' into nmea-serial 2022-10-16 09:59:30 -05:00
Ben Meadors
45f9dee89a Telemetry phone api guard (#1805)
* Delay start of telemetry modules

* Don't send unless our toPhoneQueue is empty

* Get wrecked, checks!
2022-10-16 09:58:58 -05:00
Thomas Göttgens
cc73d2c2f2 Sigh... 2022-10-16 16:51:17 +02:00
Thomas Göttgens
b1f789dddd fix cppcheck 2022-10-16 16:45:32 +02:00
Thomas Göttgens
d3e9dbf6a9 Add NMEA output mode (my own position, and other devices as waypoints) to serial module 2022-10-16 16:37:38 +02:00
Thomas Göttgens
44529620ad Merge pull request #1806 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-16 16:25:34 +02:00
caveman99
7a9673dc37 [create-pull-request] automated change 2022-10-16 14:24:27 +00:00
Thomas Göttgens
27bcf67c0c add routine to output waypoint data 2022-10-16 12:28:49 +02:00
Ben Meadors
7fde56b8ac Make telemetry logging more concise (#1804)
* Make telemetry logging more concise

* Whoops
2022-10-15 18:48:34 -05:00
Ben Meadors
6b614a2d6a Added LPS22HB (RAK-1902) sensor support (#1802) 2022-10-15 14:55:57 -05:00
Ben Meadors
1e1509fbf5 Use pio registry (#1801) 2022-10-15 12:34:52 -05:00
Ben Meadors
a3e67f8e4b SHTC3 Sensor (RAK-1901) support (#1800) 2022-10-15 09:11:05 -05:00
Ben Meadors
028b25cfe8 Change RTCQuality acceptance criteria (#1797)
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2022-10-14 19:12:55 -05:00
Ben Meadors
2555e082d6 Add nrf52 to serial module registration (#1799)
* Add nrf52 to serial module registration

* Update Modules.cpp

* Update Modules.cpp

* Update Modules.cpp
2022-10-14 11:38:56 -05:00
Thomas Göttgens
f8fa721c72 Merge pull request #1798 from meshtastic/i2cscan
Scan for I2C devices twice on all CPU's
2022-10-14 15:33:46 +02:00
Thomas Göttgens
a7e0127793 scan i2c twice for all devices, not just tbeam 2022-10-13 23:46:25 +02:00
Thomas Göttgens
603f60d86a Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-13 19:13:09 +02:00
Thomas Göttgens
6febf6b17c Merge pull request #1796 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-13 17:58:41 +02:00
thebentern
53aaf766dd [create-pull-request] automated change 2022-10-13 14:54:05 +00:00
Thomas Göttgens
4fa8d02b08 update FromRadio UUID for nRF52 devices (#1795) 2022-10-13 09:32:54 -05:00
Thomas Göttgens
efa423c8ad update FromRadio UUID for nRF52 devices 2022-10-13 16:20:27 +02:00
Thomas Göttgens
43fb0d80f1 Merge pull request #1794 from meshtastic/canned-spice
Display looks better that way...
2022-10-13 15:56:13 +02:00
Thomas Göttgens
b25ace14e5 Update CannedMessageModule.h 2022-10-13 15:44:27 +02:00
Thomas Göttgens
8734751bc4 make screen timeout work again 2022-10-13 15:31:57 +02:00
Thomas Göttgens
5559a1edb0 Display looks better that way... 2022-10-13 15:22:57 +02:00
Thomas Göttgens
bf503354f3 Merge pull request #1792 from meshtastic/atecca
Support for ATECCA608B Cryptographic Coprocessor
2022-10-13 14:34:44 +02:00
Thomas Göttgens
7b10441a28 update raspberry pi framework some more... 2022-10-13 14:21:48 +02:00
Thomas Göttgens
994e396c00 update Raspberry Pico Framework 2022-10-13 13:57:17 +02:00
Thomas Göttgens
6e22ee9061 make nRF52 happy 2022-10-13 13:31:19 +02:00
Thomas Göttgens
b5fb0f60b0 don't compile on Portduino 2022-10-13 13:01:24 +02:00
Thomas Göttgens
a7fe69ed6b Support for ATECCA608B Cryptographic Coprocessor 2022-10-13 12:55:28 +02:00
Thomas Göttgens
7f05298172 Merge pull request #1790 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-13 08:45:13 +02:00
thebentern
92a2505056 [create-pull-request] automated change 2022-10-12 23:42:47 +00:00
58 changed files with 1042 additions and 245 deletions

View File

@@ -57,12 +57,12 @@ jobs:
sudo apt-get install -y cppcheck sudo apt-get install -y cppcheck
- name: Setup Python - name: Setup Python
uses: actions/setup-python@v2 uses: actions/setup-python@v4
with: with:
python-version: 3.x python-version: 3.x
- name: Cache python libs - name: Cache python libs
uses: actions/cache@v1 uses: actions/cache@v3
id: cache-pip # needed in if test id: cache-pip # needed in if test
with: with:
path: ~/.cache/pip path: ~/.cache/pip
@@ -112,12 +112,12 @@ jobs:
repository: ${{github.event.pull_request.head.repo.full_name}} repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Setup Python - name: Setup Python
uses: actions/setup-python@v2 uses: actions/setup-python@v4
with: with:
python-version: 3.x python-version: 3.x
- name: Cache python libs - name: Cache python libs
uses: actions/cache@v1 uses: actions/cache@v3
id: cache-pip # needed in if test id: cache-pip # needed in if test
with: with:
path: ~/.cache/pip path: ~/.cache/pip
@@ -157,11 +157,11 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
- name: Get release version string - name: Get release version string
run: echo "::set-output name=version::$(./bin/buildinfo.py long)" run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version id: version
- name: Store binaries as an artifact - name: Store binaries as an artifact
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: firmware-${{ matrix.board }}-${{ steps.version.outputs.version }}.zip name: firmware-${{ matrix.board }}-${{ steps.version.outputs.version }}.zip
path: | path: |
@@ -190,12 +190,12 @@ jobs:
repository: ${{github.event.pull_request.head.repo.full_name}} repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Setup Python - name: Setup Python
uses: actions/setup-python@v2 uses: actions/setup-python@v4
with: with:
python-version: 3.x python-version: 3.x
- name: Cache python libs - name: Cache python libs
uses: actions/cache@v1 uses: actions/cache@v3
id: cache-pip # needed in if test id: cache-pip # needed in if test
with: with:
path: ~/.cache/pip path: ~/.cache/pip
@@ -214,11 +214,11 @@ jobs:
run: bin/build-nrf52.sh ${{ matrix.board }} run: bin/build-nrf52.sh ${{ matrix.board }}
- name: Get release version string - name: Get release version string
run: echo "::set-output name=version::$(./bin/buildinfo.py long)" run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version id: version
- name: Store binaries as an artifact - name: Store binaries as an artifact
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: firmware-${{ matrix.board }}-${{ steps.version.outputs.version }}.zip name: firmware-${{ matrix.board }}-${{ steps.version.outputs.version }}.zip
path: | path: |
@@ -245,12 +245,12 @@ jobs:
repository: ${{github.event.pull_request.head.repo.full_name}} repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Setup Python - name: Setup Python
uses: actions/setup-python@v2 uses: actions/setup-python@v4
with: with:
python-version: 3.x python-version: 3.x
- name: Cache python libs - name: Cache python libs
uses: actions/cache@v1 uses: actions/cache@v3
id: cache-pip # needed in if test id: cache-pip # needed in if test
with: with:
path: ~/.cache/pip path: ~/.cache/pip
@@ -269,11 +269,11 @@ jobs:
run: ./bin/build-rpi2040.sh ${{ matrix.board }} run: ./bin/build-rpi2040.sh ${{ matrix.board }}
- name: Get release version string - name: Get release version string
run: echo "::set-output name=version::$(./bin/buildinfo.py long)" run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version id: version
- name: Store binaries as an artifact - name: Store binaries as an artifact
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: firmware-${{ matrix.board }}-${{ steps.version.outputs.version }}.zip name: firmware-${{ matrix.board }}-${{ steps.version.outputs.version }}.zip
path: | path: |
@@ -292,12 +292,12 @@ jobs:
repository: ${{github.event.pull_request.head.repo.full_name}} repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Setup Python - name: Setup Python
uses: actions/setup-python@v2 uses: actions/setup-python@v4
with: with:
python-version: 3.x python-version: 3.x
- name: Cache python libs - name: Cache python libs
uses: actions/cache@v1 uses: actions/cache@v3
id: cache-pip # needed in if test id: cache-pip # needed in if test
with: with:
path: ~/.cache/pip path: ~/.cache/pip
@@ -327,11 +327,11 @@ jobs:
run: bin/build-native.sh run: bin/build-native.sh
- name: Get release version string - name: Get release version string
run: echo "::set-output name=version::$(./bin/buildinfo.py long)" run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version id: version
- name: Store binaries as an artifact - name: Store binaries as an artifact
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: firmware-native-${{ steps.version.outputs.version }}.zip name: firmware-native-${{ steps.version.outputs.version }}.zip
path: | path: |
@@ -360,19 +360,19 @@ jobs:
ref: ${{github.event.pull_request.head.ref}} ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}} repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: actions/download-artifact@v2 - uses: actions/download-artifact@v3
with: with:
path: ./ path: ./
- name: Get release version string - name: Get release version string
run: echo "::set-output name=version::$(./bin/buildinfo.py long)" run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version id: version
- name: Move files up - name: Move files up
run: mv -b -t ./ ./*tbeam-1*/littlefs*.bin ./*tbeam-1*/bleota.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./**/meshtasticd_linux_amd64 ./*native*/*device-*.sh ./*native*/*device-*.bat run: mv -b -t ./ ./*tbeam-1*/littlefs*.bin ./*tbeam-1*/bleota.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./**/meshtasticd_linux_amd64 ./*native*/*device-*.sh ./*native*/*device-*.bat
- name: Repackage in single firmware zip - name: Repackage in single firmware zip
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: firmware-${{ steps.version.outputs.version }} name: firmware-${{ steps.version.outputs.version }}
path: | path: |
@@ -384,7 +384,7 @@ jobs:
./device-*.bat ./device-*.bat
retention-days: 90 retention-days: 90
- uses: actions/download-artifact@v2 - uses: actions/download-artifact@v3
with: with:
name: firmware-${{ steps.version.outputs.version }} name: firmware-${{ steps.version.outputs.version }}
path: ./output path: ./output
@@ -402,7 +402,7 @@ jobs:
run: zip -j -r ./firmware-${{ steps.version.outputs.version }}.zip ./output run: zip -j -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
- name: Repackage in single elfs zip - name: Repackage in single elfs zip
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: debug-elfs-${{ steps.version.outputs.version }}.zip name: debug-elfs-${{ steps.version.outputs.version }}.zip
path: ./*.elf path: ./*.elf
@@ -426,18 +426,18 @@ jobs:
needs: [gather-artifacts, after-checks] needs: [gather-artifacts, after-checks]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Setup Python - name: Setup Python
uses: actions/setup-python@v2 uses: actions/setup-python@v4
with: with:
python-version: 3.x python-version: 3.x
- name: Get release version string - name: Get release version string
run: echo "::set-output name=version::$(./bin/buildinfo.py long)" run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version id: version
- uses: actions/download-artifact@v2 - uses: actions/download-artifact@v3
with: with:
name: firmware-${{ steps.version.outputs.version }} name: firmware-${{ steps.version.outputs.version }}
path: ./output path: ./output
@@ -450,7 +450,7 @@ jobs:
- name: Zip firmware - name: Zip firmware
run: zip -j -r ./firmware-${{ steps.version.outputs.version }}.zip ./output run: zip -j -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
- uses: actions/download-artifact@v2 - uses: actions/download-artifact@v3
with: with:
name: debug-elfs-${{ steps.version.outputs.version }}.zip name: debug-elfs-${{ steps.version.outputs.version }}.zip
path: ./elfs path: ./elfs
@@ -468,7 +468,7 @@ jobs:
with: with:
draft: true draft: true
prerelease: true prerelease: true
release_name: Meshtastic Device ${{ steps.version.outputs.version }} alpha - Public Preview release_name: Meshtastic Device ${{ steps.version.outputs.version }} Alpha
tag_name: v${{ steps.version.outputs.version }} tag_name: v${{ steps.version.outputs.version }}
body: | body: |
Autogenerated by github action, developer should edit as required before publishing... Autogenerated by github action, developer should edit as required before publishing...

View File

@@ -1,6 +1,6 @@
; Common settings for rp2040 Processor based targets ; Common settings for rp2040 Processor based targets
[rp2040_base] [rp2040_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git platform = https://github.com/maxgerhardt/platform-raspberrypi.git#5ce1a228e7cae453f366deb8962252b9b7356bbc
extends = arduino_base extends = arduino_base
board_build.core = earlephilhower board_build.core = earlephilhower
board_build.filesystem_size = 0.5m board_build.filesystem_size = 0.5m

View File

@@ -57,6 +57,9 @@ lib_deps =
; Used for the code analysis in PIO Home / Inspect ; Used for the code analysis in PIO Home / Inspect
check_tool = cppcheck check_tool = cppcheck
check_skip_packages = yes check_skip_packages = yes
check_flags =
--common-flag
cppcheck: --enable=--inline-suppr
; Common settings for conventional (non Portduino) Arduino targets ; Common settings for conventional (non Portduino) Arduino targets
[arduino_base] [arduino_base]
@@ -65,6 +68,7 @@ lib_deps =
${env.lib_deps} ${env.lib_deps}
; Portduino is using meshtastic fork for now ; Portduino is using meshtastic fork for now
jgromes/RadioLib@5.4.1 jgromes/RadioLib@5.4.1
https://github.com/caveman99/SparkFun_ATECCX08a_Arduino_Library.git#008e7f9d40bad66b2f7a0074aaac05b7c424339d
build_flags = ${env.build_flags} -Os build_flags = ${env.build_flags} -Os
-DRADIOLIB_SPI_PARANOID=0 -DRADIOLIB_SPI_PARANOID=0
@@ -89,4 +93,5 @@ lib_deps =
adafruit/Adafruit MCP9808 Library@^2.0.0 adafruit/Adafruit MCP9808 Library@^2.0.0
adafruit/Adafruit INA260 Library@^1.5.0 adafruit/Adafruit INA260 Library@^1.5.0
adafruit/Adafruit INA219@^1.2.0 adafruit/Adafruit INA219@^1.2.0
adafruit/Adafruit SHTC3 Library@^1.0.0
adafruit/Adafruit LPS2X@^2.0.4

View File

@@ -7,7 +7,7 @@ const uint8_t MESH_SERVICE_UUID_16[16u] = {0xfd, 0xea, 0x73, 0xe2, 0xca, 0x5d, 0
0x1f, 0x46, 0xa8, 0x15, 0x18, 0xb2, 0xa1, 0x6b}; 0x1f, 0x46, 0xa8, 0x15, 0x18, 0xb2, 0xa1, 0x6b};
const uint8_t TORADIO_UUID_16[16u] = {0xe7, 0x01, 0x44, 0x12, 0x66, 0x78, 0xdd, 0xa1, const uint8_t TORADIO_UUID_16[16u] = {0xe7, 0x01, 0x44, 0x12, 0x66, 0x78, 0xdd, 0xa1,
0xad, 0x4d, 0x9e, 0x12, 0xd2, 0x76, 0x5c, 0xf7}; 0xad, 0x4d, 0x9e, 0x12, 0xd2, 0x76, 0x5c, 0xf7};
const uint8_t FROMRADIO_UUID_16[16u] = {0xd5, 0x54, 0xe4, 0xc5, 0x25, 0xc5, 0x31, 0xa5, const uint8_t FROMRADIO_UUID_16[16u] = {0x02, 0x00, 0x12, 0xac, 0x42, 0x02, 0x78, 0xb8,
0x55, 0x4a, 0x02, 0xee, 0xc2, 0xbc, 0xa2, 0x8b}; 0xed, 0x11, 0x93, 0x49, 0x9e, 0xe6, 0x55, 0x2c};
const uint8_t FROMNUM_UUID_16[16u] = {0x53, 0x44, 0xe3, 0x47, 0x75, 0xaa, 0x70, 0xa6, const uint8_t FROMNUM_UUID_16[16u] = {0x53, 0x44, 0xe3, 0x47, 0x75, 0xaa, 0x70, 0xa6,
0x66, 0x4f, 0x00, 0xa8, 0x8c, 0xa1, 0x9d, 0xed}; 0x66, 0x4f, 0x00, 0xa8, 0x8c, 0xa1, 0x9d, 0xed};

View File

@@ -49,6 +49,13 @@ size_t RedirectablePrint::vprintf(const char *format, va_list arg)
if (len < 0) return 0; if (len < 0) return 0;
// If the resulting string is longer than sizeof(printBuf)-1 characters, the remaining characters are still counted for the return value
if (len > sizeof(printBuf) - 1) {
len = sizeof(printBuf) - 1;
printBuf[sizeof(printBuf) - 2] = '\n';
}
len = Print::write(printBuf, len); len = Print::write(printBuf, len);
return len; return len;
} }
@@ -103,4 +110,4 @@ size_t RedirectablePrint::logDebug(const char *format, ...)
} }
return r; return r;
} }

View File

@@ -110,6 +110,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define INA_ADDR_ALTERNATE 0x41 #define INA_ADDR_ALTERNATE 0x41
#define QMC6310_ADDR 0x1C #define QMC6310_ADDR 0x1C
#define QMI8658_ADDR 0x6B #define QMI8658_ADDR 0x6B
#define SHTC3_ADDR 0x70
#define LPS22HB_ADDR 0x5C
#define LPS22HB_ADDR_ALT 0x5D
// -----------------------------------------------------------------------------
// Security
// -----------------------------------------------------------------------------
#define ATECC608B_ADDR 0x35
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// GPS // GPS
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@@ -9,6 +9,41 @@
#endif #endif
#if HAS_WIRE #if HAS_WIRE
void printATECCInfo()
{
#ifndef ARCH_PORTDUINO
atecc.readConfigZone(false);
DEBUG_MSG("ATECC608B Serial Number: ");
for (int i = 0 ; i < 9 ; i++) {
DEBUG_MSG("%02x",atecc.serialNumber[i]);
}
DEBUG_MSG(", Rev Number: ");
for (int i = 0 ; i < 4 ; i++) {
DEBUG_MSG("%02x",atecc.revisionNumber[i]);
}
DEBUG_MSG("\n");
DEBUG_MSG("ATECC608B Config %s",atecc.configLockStatus ? "Locked" : "Unlocked");
DEBUG_MSG(", Data %s",atecc.dataOTPLockStatus ? "Locked" : "Unlocked");
DEBUG_MSG(", Slot 0 %s\n",atecc.slot0LockStatus ? "Locked" : "Unlocked");
if (atecc.configLockStatus && atecc.dataOTPLockStatus && atecc.slot0LockStatus) {
if (atecc.generatePublicKey() == false) {
DEBUG_MSG("ATECC608B Error generating public key\n");
} else {
DEBUG_MSG("ATECC608B Public Key: ");
for (int i = 0 ; i < 64 ; i++) {
DEBUG_MSG("%02x",atecc.publicKey64Bytes[i]);
}
DEBUG_MSG("\n");
}
}
#endif
}
uint16_t getRegisterValue(uint8_t address, uint8_t reg, uint8_t length) { uint16_t getRegisterValue(uint8_t address, uint8_t reg, uint8_t length) {
uint16_t value = 0x00; uint16_t value = 0x00;
Wire.beginTransmission(address); Wire.beginTransmission(address);
@@ -79,6 +114,17 @@ void scanI2Cdevice(void)
DEBUG_MSG("unknown display found\n"); DEBUG_MSG("unknown display found\n");
} }
} }
#ifndef ARCH_PORTDUINO
if (addr == ATECC608B_ADDR){
keystore_found = addr;
if (atecc.begin(keystore_found) == true) {
DEBUG_MSG("ATECC608B initialized\n");
} else {
DEBUG_MSG("ATECC608B initialization failed\n");
}
printATECCInfo();
}
#endif
#ifdef RV3028_RTC #ifdef RV3028_RTC
if (addr == RV3028_RTC){ if (addr == RV3028_RTC){
rtc_found = addr; rtc_found = addr;
@@ -145,14 +191,22 @@ void scanI2Cdevice(void)
nodeTelemetrySensorsMap[TelemetrySensorType_MCP9808] = addr; nodeTelemetrySensorsMap[TelemetrySensorType_MCP9808] = addr;
DEBUG_MSG("MCP9808 sensor found at address 0x%x\n", (uint8_t)addr); DEBUG_MSG("MCP9808 sensor found at address 0x%x\n", (uint8_t)addr);
} }
if(addr == QMC6310_ADDR){ if (addr == QMC6310_ADDR) {
DEBUG_MSG("QMC6310 3-Axis magnetic sensor found at address 0x%x\n", (uint8_t)addr); DEBUG_MSG("QMC6310 3-Axis magnetic sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_QMC6310] = addr; nodeTelemetrySensorsMap[TelemetrySensorType_QMC6310] = addr;
} }
if(addr == QMI8658_ADDR){ if (addr == QMI8658_ADDR) {
DEBUG_MSG("QMI8658 6-Axis inertial measurement sensor found at address 0x%x\n", (uint8_t)addr); DEBUG_MSG("QMI8658 6-Axis inertial measurement sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_QMI8658] = addr; nodeTelemetrySensorsMap[TelemetrySensorType_QMI8658] = addr;
} }
if (addr == SHTC3_ADDR) {
DEBUG_MSG("SHTC3 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_SHTC3] = addr;
}
if (addr == LPS22HB_ADDR || addr == LPS22HB_ADDR_ALT) {
DEBUG_MSG("LPS22HB sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_LPS22] = addr;
}
} else if (err == 4) { } else if (err == 4) {
DEBUG_MSG("Unknow error at address 0x%x\n", addr); DEBUG_MSG("Unknow error at address 0x%x\n", addr);
} }

76
src/gps/NMEAWPL.cpp Normal file
View File

@@ -0,0 +1,76 @@
#include "NMEAWPL.h"
/* -------------------------------------------
* 1 2 3 4 5 6
* | | | | | |
* $--WPL,llll.ll,a,yyyyy.yy,a,c--c*hh<CR><LF>
*
* Field Number:
* 1 Latitude
* 2 N or S (North or South)
* 3 Longitude
* 4 E or W (East or West)
* 5 Waypoint name
* 6 Checksum
* -------------------------------------------
*/
uint printWPL(char *buf, const Position &pos, const char *name)
{
uint len = sprintf(buf, "$GNWPL,%07.2f,%c,%08.2f,%c,%s", pos.latitude_i * 1e-5, pos.latitude_i < 0 ? 'S' : 'N', pos.longitude_i * 1e-5, pos.longitude_i < 0 ? 'W' : 'E', name);
uint chk = 0;
for (uint i = 1; i < len; i++) {
chk ^= buf[i];
}
len += sprintf(buf + len, "*%02X\r\n", chk);
return len;
}
/* -------------------------------------------
* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
* | | | | | | | | | | | | | | |
* $--GGA,hhmmss.ss,ddmm.mm,a,ddmm.mm,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*hh<CR><LF>
*
* Field Number:
* 1 UTC of this position report, hh is hours, mm is minutes, ss.ss is seconds.
* 2 Latitude
* 3 N or S (North or South)
* 4 Longitude
* 5 E or W (East or West)
* 6 GPS Quality Indicator (non null)
* 7 Number of satellites in use, 00 - 12
* 8 Horizontal Dilution of precision (meters)
* 9 Antenna Altitude above/below mean-sea-level (geoid) (in meters)
* 10 Units of antenna altitude, meters
* 11 Geoidal separation, the difference between the WGS-84 earth ellipsoid and mean-sea-level (geoid), "-" means mean-sea-level below ellipsoid
* 12 Units of geoidal separation, meters
* 13 Age of differential GPS data, time in seconds since last SC104 type 1 or 9 update, null field when DGPS is not used
* 14 Differential reference station ID, 0000-1023
* 15 Checksum
* -------------------------------------------
*/
uint printGGA(char *buf, const Position &pos)
{
uint len = sprintf(buf, "$GNGGA,%06u.%03u,%07.2f,%c,%08.2f,%c,%u,%02u,%04u,%04d,%c,%04d,%c,%d,%04d",
pos.time / 1000,
pos.time % 1000,
pos.latitude_i * 1e-5, pos.latitude_i < 0 ? 'S' : 'N',
pos.longitude_i * 1e-5, pos.longitude_i < 0 ? 'W' : 'E',
pos.fix_type,
pos.sats_in_view,
pos.HDOP,
pos.altitude,
'M',
pos.altitude_geoidal_separation,
'M',
0,
0);
uint chk = 0;
for (uint i = 1; i < len; i++) {
chk ^= buf[i];
}
len += sprintf(buf + len, "*%02X\r\n", chk);
return len;
}

7
src/gps/NMEAWPL.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#include <Arduino.h>
#include "main.h"
uint printWPL(char *buf, const Position &pos, const char *name);
uint printGGA(char *buf, const Position &pos);

View File

@@ -16,7 +16,7 @@ enum RTCQuality {
RTCQualityFromNet = 2, RTCQualityFromNet = 2,
/// Our time is based on NTP /// Our time is based on NTP
RTCQualityNTP= 3, RTCQualityNTP = 3,
/// Our time is based on our own GPS /// Our time is based on our own GPS
RTCQualityGPS = 4 RTCQualityGPS = 4

View File

@@ -84,10 +84,6 @@ static char ourId[5];
// GeoCoord object for the screen // GeoCoord object for the screen
GeoCoord geoCoord; GeoCoord geoCoord;
// OEM Config File
static const char *oemConfigFile = "/oem/oem.proto";
OEMStore oemStore;
#ifdef SHOW_REDRAWS #ifdef SHOW_REDRAWS
static bool heartbeat = false; static bool heartbeat = false;
#endif #endif
@@ -928,9 +924,6 @@ void Screen::setup()
dispdev.setDetected(screen_model); dispdev.setDetected(screen_model);
#endif #endif
// Load OEM config from Proto file if existent
loadProto(oemConfigFile, OEMStore_size, sizeof(oemConfigFile), OEMStore_fields, &oemStore);
// Initialising the UI will init the display too. // Initialising the UI will init the display too.
ui.init(); ui.init();

View File

@@ -45,6 +45,7 @@
#include "RF95Interface.h" #include "RF95Interface.h"
#include "SX1262Interface.h" #include "SX1262Interface.h"
#include "SX1268Interface.h" #include "SX1268Interface.h"
#include "SX1281Interface.h"
#if !HAS_RADIO && defined(ARCH_PORTDUINO) #if !HAS_RADIO && defined(ARCH_PORTDUINO)
#include "platform/portduino/SimRadio.h" #include "platform/portduino/SimRadio.h"
#endif #endif
@@ -80,6 +81,14 @@ uint8_t kb_model;
// The I2C address of the RTC Module (if found) // The I2C address of the RTC Module (if found)
uint8_t rtc_found; uint8_t rtc_found;
bool rIf_wide_lora = false;
// Keystore Chips
uint8_t keystore_found;
#ifndef ARCH_PORTDUINO
ATECCX08A atecc;
#endif
bool eink_found = true; bool eink_found = true;
uint32_t serialSinceMsec; uint32_t serialSinceMsec;
@@ -275,12 +284,10 @@ void setup()
power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration
/* /*
* Repeat the scanning for I2C devices after power initialization. * Repeat the scanning for I2C devices after power initialization or look for 'latecomers'.
* Boards with an PMU need to be powered on to correctly scan to the device address, such as t-beam-s3-core * Boards with an PMU need to be powered on to correctly scan to the device address, such as t-beam-s3-core
*/ */
if ((HW_VENDOR == HardwareModel_LILYGO_TBEAM_S3_CORE) || (HW_VENDOR == HardwareModel_TBEAM)) { scanI2Cdevice();
scanI2Cdevice();
}
// Init our SPI controller (must be before screen and lora) // Init our SPI controller (must be before screen and lora)
initSPI(); initSPI();
@@ -360,6 +367,20 @@ void setup()
} }
#endif #endif
#if defined(USE_SX1281) && !defined(ARCH_PORTDUINO)
if (!rIf) {
rIf = new SX1281Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI);
if (!rIf->init()) {
DEBUG_MSG("Warning: Failed to find SX1281 radio\n");
delete rIf;
rIf = NULL;
} else {
DEBUG_MSG("SX1281 Radio init succeeded, using SX1281 radio\n");
rIf_wide_lora = true;
}
}
#endif
#if defined(USE_SX1262) #if defined(USE_SX1262)
if (!rIf) { if (!rIf) {
rIf = new SX1262Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI); rIf = new SX1262Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI);

View File

@@ -6,18 +6,27 @@
#include "PowerStatus.h" #include "PowerStatus.h"
#include "graphics/Screen.h" #include "graphics/Screen.h"
#include "mesh/generated/telemetry.pb.h" #include "mesh/generated/telemetry.pb.h"
#ifndef ARCH_PORTDUINO
#include <SparkFun_ATECCX08a_Arduino_Library.h>
#endif
extern uint8_t screen_found; extern uint8_t screen_found;
extern uint8_t screen_model; extern uint8_t screen_model;
extern uint8_t cardkb_found; extern uint8_t cardkb_found;
extern uint8_t kb_model; extern uint8_t kb_model;
extern uint8_t rtc_found; extern uint8_t rtc_found;
extern uint8_t keystore_found;
extern bool rIf_wide_lora;
extern bool eink_found; extern bool eink_found;
extern bool pmu_found; extern bool pmu_found;
extern bool isCharging; extern bool isCharging;
extern bool isUSBPowered; extern bool isUSBPowered;
#ifndef ARCH_PORTDUINO
extern ATECCX08A atecc;
#endif
extern uint8_t nodeTelemetrySensorsMap[TelemetrySensorType_QMI8658+1]; extern uint8_t nodeTelemetrySensorsMap[TelemetrySensorType_QMI8658+1];
extern int TCPPort; // set by Portduino extern int TCPPort; // set by Portduino

View File

@@ -62,13 +62,6 @@ Channel &Channels::fixupChannel(ChannelIndex chIndex)
// Convert the old string "Default" to our new short representation // Convert the old string "Default" to our new short representation
if (strcmp(channelSettings.name, "Default") == 0) if (strcmp(channelSettings.name, "Default") == 0)
*channelSettings.name = '\0'; *channelSettings.name = '\0';
/* Convert any old usage of the defaultpsk into our new short representation.
if (channelSettings.psk.size == sizeof(defaultpsk) &&
memcmp(channelSettings.psk.bytes, defaultpsk, sizeof(defaultpsk)) == 0) {
*channelSettings.psk.bytes = 1;
channelSettings.psk.size = 1;
} */
} }
hashes[chIndex] = generateHash(chIndex); hashes[chIndex] = generateHash(chIndex);
@@ -124,7 +117,22 @@ CryptoKey Channels::getKey(ChannelIndex chIndex)
DEBUG_MSG("Expanding short PSK #%d\n", pskIndex); DEBUG_MSG("Expanding short PSK #%d\n", pskIndex);
if (pskIndex == 0) if (pskIndex == 0)
k.length = 0; // Turn off encryption k.length = 0; // Turn off encryption
else { else if (oemStore.oem_aes_key.size > 1) {
// Use the OEM key
DEBUG_MSG("Using OEM Key with %d bytes\n", oemStore.oem_aes_key.size);
memcpy(k.bytes, oemStore.oem_aes_key.bytes , oemStore.oem_aes_key.size);
k.length = oemStore.oem_aes_key.size;
// Bump up the last byte of PSK as needed
uint8_t *last = k.bytes + oemStore.oem_aes_key.size - 1;
*last = *last + pskIndex - 1; // index of 1 means no change vs defaultPSK
if (k.length < 16) {
DEBUG_MSG("Warning: OEM provided a too short AES128 key - padding\n");
k.length = 16;
} else if (k.length < 32 && k.length != 16) {
DEBUG_MSG("Warning: OEM provided a too short AES256 key - padding\n");
k.length = 32;
}
} else {
memcpy(k.bytes, defaultpsk, sizeof(defaultpsk)); memcpy(k.bytes, defaultpsk, sizeof(defaultpsk));
k.length = sizeof(defaultpsk); k.length = sizeof(defaultpsk);
// Bump up the last byte of PSK as needed // Bump up the last byte of PSK as needed

View File

@@ -1,7 +1,13 @@
#include "SX126xInterface.h" #include "SX126xInterface.h"
#include "SX126xInterface.cpp" #include "SX126xInterface.cpp"
#include "SX128xInterface.h"
#include "SX128xInterface.cpp"
// We need this declaration for proper linking in derived classes // We need this declaration for proper linking in derived classes
template class SX126xInterface<SX1262>; template class SX126xInterface<SX1262>;
template class SX126xInterface<SX1268>; template class SX126xInterface<SX1268>;
template class SX126xInterface<LLCC68>; template class SX126xInterface<LLCC68>;
#if !defined(ARCH_PORTDUINO)
template class SX128xInterface<SX1281>;
#endif

View File

@@ -15,6 +15,7 @@ struct RegionInfo {
uint8_t powerLimit; // Or zero for not set uint8_t powerLimit; // Or zero for not set
bool audioPermitted; bool audioPermitted;
bool freqSwitching; bool freqSwitching;
bool wideLora;
const char *name; // EU433 etc const char *name; // EU433 etc
}; };

View File

@@ -283,3 +283,8 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
return 0; return 0;
} }
bool MeshService::isToPhoneQueueEmpty()
{
return toPhoneQueue.isEmpty();
}

View File

@@ -89,6 +89,8 @@ class MeshService
/// Send a packet to the phone /// Send a packet to the phone
void sendToPhone(MeshPacket *p); void sendToPhone(MeshPacket *p);
bool isToPhoneQueueEmpty();
private: private:
/// Called when our gps position has changed - updates nodedb and sends Location message out into the mesh /// Called when our gps position has changed - updates nodedb and sends Location message out into the mesh
/// returns 0 to allow futher processing /// returns 0 to allow futher processing

View File

@@ -38,6 +38,7 @@ MyNodeInfo &myNodeInfo = devicestate.my_node;
LocalConfig config; LocalConfig config;
LocalModuleConfig moduleConfig; LocalModuleConfig moduleConfig;
ChannelFile channelFile; ChannelFile channelFile;
OEMStore oemStore;
/** The current change # for radio settings. Starts at 0 on boot and any time the radio settings /** 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. * might have changed is incremented. Allows others to detect they might now be on a new channel.
@@ -129,6 +130,8 @@ bool NodeDB::factoryReset()
// second, install default state (this will deal with the duplicate mac address issue) // second, install default state (this will deal with the duplicate mac address issue)
installDefaultDeviceState(); installDefaultDeviceState();
installDefaultConfig(); installDefaultConfig();
installDefaultModuleConfig();
installDefaultChannels();
// third, write everything to disk // third, write everything to disk
saveToDisk(); saveToDisk();
#ifdef ARCH_ESP32 #ifdef ARCH_ESP32
@@ -354,6 +357,8 @@ static const char *prefFileName = "/prefs/db.proto";
static const char *configFileName = "/prefs/config.proto"; static const char *configFileName = "/prefs/config.proto";
static const char *moduleConfigFileName = "/prefs/module.proto"; static const char *moduleConfigFileName = "/prefs/module.proto";
static const char *channelFileName = "/prefs/channels.proto"; static const char *channelFileName = "/prefs/channels.proto";
static const char *oemConfigFile = "/oem/oem.proto";
/** Load a protobuf from a file, return true for success */ /** Load a protobuf from a file, return true for success */
bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct) bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct)
@@ -433,6 +438,9 @@ void NodeDB::loadFromDisk()
DEBUG_MSG("Loaded saved channelFile version %d\n", channelFile.version); DEBUG_MSG("Loaded saved channelFile version %d\n", channelFile.version);
} }
} }
if (loadProto(oemConfigFile, OEMStore_size, sizeof(OEMStore), OEMStore_fields, &oemStore))
DEBUG_MSG("Loaded OEMStore\n");
} }
/** Save a protobuf from a file, return true for success */ /** Save a protobuf from a file, return true for success */

View File

@@ -26,6 +26,7 @@ extern ChannelFile channelFile;
extern MyNodeInfo &myNodeInfo; extern MyNodeInfo &myNodeInfo;
extern LocalConfig config; extern LocalConfig config;
extern LocalModuleConfig moduleConfig; extern LocalModuleConfig moduleConfig;
extern OEMStore oemStore;
extern User &owner; extern User &owner;
/// Given a node, return how many seconds in the past (vs now) that we last heard from it /// Given a node, return how many seconds in the past (vs now) that we last heard from it

View File

@@ -6,15 +6,16 @@
#include "Router.h" #include "Router.h"
#include "assert.h" #include "assert.h"
#include "configuration.h" #include "configuration.h"
#include "main.h"
#include "sleep.h" #include "sleep.h"
#include <assert.h> #include <assert.h>
#include <pb_decode.h> #include <pb_decode.h>
#include <pb_encode.h> #include <pb_encode.h>
#define RDEF(name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, frequency_switching) \ #define RDEF(name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, frequency_switching, wide_lora) \
{ \ { \
Config_LoRaConfig_RegionCode_##name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, \ Config_LoRaConfig_RegionCode_##name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, \
frequency_switching, #name \ frequency_switching, wide_lora, #name \
} }
const RegionInfo regions[] = { const RegionInfo regions[] = {
@@ -22,12 +23,12 @@ const RegionInfo regions[] = {
https://link.springer.com/content/pdf/bbm%3A978-1-4842-4357-2%2F1.pdf https://link.springer.com/content/pdf/bbm%3A978-1-4842-4357-2%2F1.pdf
https://www.thethingsnetwork.org/docs/lorawan/regional-parameters/ https://www.thethingsnetwork.org/docs/lorawan/regional-parameters/
*/ */
RDEF(US, 902.0f, 928.0f, 100, 0, 30, true, false), RDEF(US, 902.0f, 928.0f, 100, 0, 30, true, false, false),
/* /*
https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
*/ */
RDEF(EU_433, 433.0f, 434.0f, 10, 0, 12, true, false), RDEF(EU_433, 433.0f, 434.0f, 10, 0, 12, true, false, false),
/* /*
https://www.thethingsnetwork.org/docs/lorawan/duty-cycle/ https://www.thethingsnetwork.org/docs/lorawan/duty-cycle/
@@ -43,23 +44,23 @@ const RegionInfo regions[] = {
(Please refer to section 4.21 in the following document) (Please refer to section 4.21 in the following document)
https://ec.europa.eu/growth/tools-databases/tris/index.cfm/ro/search/?trisaction=search.detail&year=2021&num=528&dLang=EN https://ec.europa.eu/growth/tools-databases/tris/index.cfm/ro/search/?trisaction=search.detail&year=2021&num=528&dLang=EN
*/ */
RDEF(EU_868, 869.4f, 869.65f, 10, 0, 27, false, false), RDEF(EU_868, 869.4f, 869.65f, 10, 0, 27, false, false, false),
/* /*
https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
*/ */
RDEF(CN, 470.0f, 510.0f, 100, 0, 19, true, false), RDEF(CN, 470.0f, 510.0f, 100, 0, 19, true, false, false),
/* /*
https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
*/ */
RDEF(JP, 920.8f, 927.8f, 100, 0, 16, true, false), RDEF(JP, 920.8f, 927.8f, 100, 0, 16, true, false, false),
/* /*
https://www.iot.org.au/wp/wp-content/uploads/2016/12/IoTSpectrumFactSheet.pdf https://www.iot.org.au/wp/wp-content/uploads/2016/12/IoTSpectrumFactSheet.pdf
https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf
*/ */
RDEF(ANZ, 915.0f, 928.0f, 100, 0, 30, true, false), RDEF(ANZ, 915.0f, 928.0f, 100, 0, 30, true, false, false),
/* /*
https://digital.gov.ru/uploaded/files/prilozhenie-12-k-reshenyu-gkrch-18-46-03-1.pdf https://digital.gov.ru/uploaded/files/prilozhenie-12-k-reshenyu-gkrch-18-46-03-1.pdf
@@ -67,38 +68,44 @@ const RegionInfo regions[] = {
Note: Note:
- We do LBT, so 100% is allowed. - We do LBT, so 100% is allowed.
*/ */
RDEF(RU, 868.7f, 869.2f, 100, 0, 20, true, false), RDEF(RU, 868.7f, 869.2f, 100, 0, 20, true, false, false),
/* /*
??? ???
*/ */
RDEF(KR, 920.0f, 923.0f, 100, 0, 0, true, false), RDEF(KR, 920.0f, 923.0f, 100, 0, 0, true, false, false),
/* /*
??? ???
*/ */
RDEF(TW, 920.0f, 925.0f, 100, 0, 0, true, false), RDEF(TW, 920.0f, 925.0f, 100, 0, 0, true, false, false),
/* /*
https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
*/ */
RDEF(IN, 865.0f, 867.0f, 100, 0, 30, true, false), RDEF(IN, 865.0f, 867.0f, 100, 0, 30, true, false, false),
/* /*
https://rrf.rsm.govt.nz/smart-web/smart/page/-smart/domain/licence/LicenceSummary.wdk?id=219752 https://rrf.rsm.govt.nz/smart-web/smart/page/-smart/domain/licence/LicenceSummary.wdk?id=219752
https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf
*/ */
RDEF(NZ_865, 864.0f, 868.0f, 100, 0, 0, true, false), RDEF(NZ_865, 864.0f, 868.0f, 100, 0, 0, true, false, false),
/* /*
https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
*/ */
RDEF(TH, 920.0f, 925.0f, 100, 0, 16, true, false), RDEF(TH, 920.0f, 925.0f, 100, 0, 16, true, false, false),
/*
2.4 GHZ WLAN Band equivalent. Only for SX128x chips.
*/
RDEF(LORA_24, 2400.0f, 2483.5f, 100, 0, 10, true, false, true),
/* /*
This needs to be last. Same as US. This needs to be last. Same as US.
*/ */
RDEF(UNSET, 902.0f, 928.0f, 100, 0, 30, true, false) RDEF(UNSET, 902.0f, 928.0f, 100, 0, 30, true, false, false)
}; };
@@ -355,39 +362,40 @@ void RadioInterface::applyModemConfig()
// No Sync Words in LORA mode // No Sync Words in LORA mode
Config_LoRaConfig &loraConfig = config.lora; Config_LoRaConfig &loraConfig = config.lora;
if (loraConfig.spread_factor == 0) { if (loraConfig.spread_factor == 0) {
switch (loraConfig.modem_preset) { switch (loraConfig.modem_preset) {
case Config_LoRaConfig_ModemPreset_SHORT_FAST: case Config_LoRaConfig_ModemPreset_SHORT_FAST:
bw = 250; bw = (myRegion->wideLora && rIf_wide_lora) ? 800 : 250;
cr = 8; cr = 8;
sf = 7; sf = 7;
break; break;
case Config_LoRaConfig_ModemPreset_SHORT_SLOW: case Config_LoRaConfig_ModemPreset_SHORT_SLOW:
bw = 250; bw = (myRegion->wideLora && rIf_wide_lora) ? 800 : 250;
cr = 8; cr = 8;
sf = 8; sf = 8;
break; break;
case Config_LoRaConfig_ModemPreset_MEDIUM_FAST: case Config_LoRaConfig_ModemPreset_MEDIUM_FAST:
bw = 250; bw = (myRegion->wideLora && rIf_wide_lora) ? 800 : 250;
cr = 8; cr = 8;
sf = 9; sf = 9;
break; break;
case Config_LoRaConfig_ModemPreset_MEDIUM_SLOW: case Config_LoRaConfig_ModemPreset_MEDIUM_SLOW:
bw = 250; bw = (myRegion->wideLora && rIf_wide_lora) ? 800 : 250;
cr = 8; cr = 8;
sf = 10; sf = 10;
break; break;
case Config_LoRaConfig_ModemPreset_LONG_FAST: case Config_LoRaConfig_ModemPreset_LONG_FAST:
bw = 250; bw = (myRegion->wideLora && rIf_wide_lora) ? 800 : 250;
cr = 8; cr = 8;
sf = 11; sf = 11;
break; break;
case Config_LoRaConfig_ModemPreset_LONG_SLOW: case Config_LoRaConfig_ModemPreset_LONG_SLOW:
bw = 125; bw = (myRegion->wideLora && rIf_wide_lora) ? 400 : 125;
cr = 8; cr = 8;
sf = 12; sf = 12;
break; break;
case Config_LoRaConfig_ModemPreset_VERY_LONG_SLOW: case Config_LoRaConfig_ModemPreset_VERY_LONG_SLOW:
bw = 31.25; bw = (myRegion->wideLora && rIf_wide_lora) ? 200 : 31.25;
cr = 8; cr = 8;
sf = 12; sf = 12;
break; break;
@@ -415,7 +423,7 @@ void RadioInterface::applyModemConfig()
power = 17; // Default to default power if we don't have a valid power power = 17; // Default to default power if we don't have a valid power
// Set final tx_power back onto config // Set final tx_power back onto config
loraConfig.tx_power = power; loraConfig.tx_power = (int8_t)power; // cppcheck-suppress assignmentAddressToInteger
// Calculate the number of channels // Calculate the number of channels
uint32_t numChannels = floor((myRegion->freqEnd - myRegion->freqStart) / (myRegion->spacing + (bw / 1000))); uint32_t numChannels = floor((myRegion->freqEnd - myRegion->freqStart) / (myRegion->spacing + (bw / 1000)));

View File

@@ -63,7 +63,7 @@ bool ReliableRouter::shouldFilterReceived(MeshPacket *p)
sendAckNak(Routing_Error_NONE, getFrom(p), p->id, p->channel); sendAckNak(Routing_Error_NONE, getFrom(p), p->id, p->channel);
DEBUG_MSG("acking a repeated want_ack packet\n"); DEBUG_MSG("acking a repeated want_ack packet\n");
} }
} else if (wasSeenRecently(p, false) && p->hop_limit == HOP_RELIABLE && !MeshModule::currentReply) { } else if (wasSeenRecently(p, false) && p->hop_limit == HOP_RELIABLE && !MeshModule::currentReply && p->to != nodeDB.getNodeNum()) {
// retransmission on broadcast has hop_limit still equal to HOP_RELIABLE // retransmission on broadcast has hop_limit still equal to HOP_RELIABLE
DEBUG_MSG("Resending implicit ack for a repeated floodmsg\n"); DEBUG_MSG("Resending implicit ack for a repeated floodmsg\n");
MeshPacket *tosend = packetPool.allocCopy(*p); MeshPacket *tosend = packetPool.allocCopy(*p);

View File

@@ -0,0 +1,13 @@
#include "configuration.h"
#include "SX1281Interface.h"
#include "error.h"
#if !defined(ARCH_PORTDUINO)
SX1281Interface::SX1281Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
SPIClass &spi)
: SX128xInterface(cs, irq, rst, busy, spi)
{
}
#endif

View File

@@ -0,0 +1,17 @@
#pragma once
#include "SX128xInterface.h"
/**
* Our adapter for SX1281 radios
*/
#if !defined(ARCH_PORTDUINO)
class SX1281Interface : public SX128xInterface<SX1281>
{
public:
SX1281Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi);
};
#endif

View File

@@ -0,0 +1,247 @@
#include "configuration.h"
#include "SX128xInterface.h"
#include "error.h"
#if !defined(ARCH_PORTDUINO)
// Particular boards might define a different max power based on what their hardware can do
#ifndef SX128X_MAX_POWER
#define SX128X_MAX_POWER 22
#endif
template<typename T>
SX128xInterface<T>::SX128xInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
SPIClass &spi)
: RadioLibInterface(cs, irq, rst, busy, spi, &lora), lora(&module)
{
}
/// Initialise the Driver transport hardware and software.
/// Make sure the Driver is properly configured before calling init().
/// \return true if initialisation succeeded.
template<typename T>
bool SX128xInterface<T>::init()
{
#ifdef SX128X_POWER_EN
digitalWrite(SX128X_POWER_EN, HIGH);
pinMode(SX128X_POWER_EN, OUTPUT);
#endif
#ifdef SX128X_RXEN // set not rx or tx mode
digitalWrite(SX128X_RXEN, LOW); // Set low before becoming an output
pinMode(SX128X_RXEN, OUTPUT);
#endif
#ifdef SX128X_TXEN
digitalWrite(SX128X_TXEN, LOW);
pinMode(SX128X_TXEN, OUTPUT);
#endif
RadioLibInterface::init();
if (power == 0)
power = SX128X_MAX_POWER;
if (power > SX128X_MAX_POWER) // This chip has lower power limits than some
power = SX128X_MAX_POWER;
limitPower();
int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength);
// \todo Display actual typename of the adapter, not just `SX128x`
DEBUG_MSG("SX128x init result %d\n", res);
DEBUG_MSG("Frequency set to %f\n", getFreq());
DEBUG_MSG("Bandwidth set to %f\n", bw);
DEBUG_MSG("Power output set to %d\n", power);
#ifdef SX128X_TXEN
// lora.begin sets Dio2 as RF switch control, which is not true if we are manually controlling RX and TX
if (res == RADIOLIB_ERR_NONE)
res = lora.setDio2AsRfSwitch(true);
#endif
if (res == RADIOLIB_ERR_NONE)
res = lora.setCRC(RADIOLIB_SX128X_LORA_CRC_ON);
if (res == RADIOLIB_ERR_NONE)
startReceive(); // start receiving
return res == RADIOLIB_ERR_NONE;
}
template<typename T>
bool SX128xInterface<T>::reconfigure()
{
RadioLibInterface::reconfigure();
// set mode to standby
setStandby();
// configure publicly accessible settings
int err = lora.setSpreadingFactor(sf);
if (err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_INVALID_RADIO_SETTING);
err = lora.setBandwidth(bw);
if (err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_INVALID_RADIO_SETTING);
err = lora.setCodingRate(cr);
if (err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_INVALID_RADIO_SETTING);
// Hmm - seems to lower SNR when the signal levels are high. Leaving off for now...
// TODO: Confirm gain registers are okay now
// err = lora.setRxGain(true);
// assert(err == RADIOLIB_ERR_NONE);
err = lora.setSyncWord(syncWord);
assert(err == RADIOLIB_ERR_NONE);
err = lora.setPreambleLength(preambleLength);
assert(err == RADIOLIB_ERR_NONE);
err = lora.setFrequency(getFreq());
if (err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_INVALID_RADIO_SETTING);
if (power > 22) // This chip has lower power limits than some
power = 22;
err = lora.setOutputPower(power);
assert(err == RADIOLIB_ERR_NONE);
startReceive(); // restart receiving
return RADIOLIB_ERR_NONE;
}
template<typename T>
void INTERRUPT_ATTR SX128xInterface<T>::disableInterrupt()
{
lora.clearDio1Action();
}
template<typename T>
void SX128xInterface<T>::setStandby()
{
checkNotification(); // handle any pending interrupts before we force standby
int err = lora.standby();
assert(err == RADIOLIB_ERR_NONE);
#ifdef SX128X_RXEN // we have RXEN/TXEN control - turn off RX and TX power
digitalWrite(SX128X_RXEN, LOW);
#endif
#ifdef SX128X_TXEN
digitalWrite(SX128X_TXEN, LOW);
#endif
isReceiving = false; // If we were receiving, not any more
disableInterrupt();
completeSending(); // If we were sending, not anymore
}
/**
* Add SNR data to received messages
*/
template<typename T>
void SX128xInterface<T>::addReceiveMetadata(MeshPacket *mp)
{
// DEBUG_MSG("PacketStatus %x\n", lora.getPacketStatus());
mp->rx_snr = lora.getSNR();
mp->rx_rssi = lround(lora.getRSSI());
}
/** We override to turn on transmitter power as needed.
*/
template<typename T>
void SX128xInterface<T>::configHardwareForSend()
{
#ifdef SX128X_TXEN // we have RXEN/TXEN control - turn on TX power / off RX power
digitalWrite(SX128X_TXEN, HIGH);
#endif
#ifdef SX128X_RXEN
digitalWrite(SX128X_RXEN, LOW);
#endif
RadioLibInterface::configHardwareForSend();
}
// For power draw measurements, helpful to force radio to stay sleeping
// #define SLEEP_ONLY
template<typename T>
void SX128xInterface<T>::startReceive()
{
#ifdef SLEEP_ONLY
sleep();
#else
setStandby();
#ifdef SX128X_RXEN // we have RXEN/TXEN control - turn on RX power / off TX power
digitalWrite(SX128X_RXEN, HIGH);
#endif
#ifdef SX128X_TXEN
digitalWrite(SX128X_TXEN, LOW);
#endif
int err = lora.startReceive();
assert(err == RADIOLIB_ERR_NONE);
isReceiving = true;
// Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register bits
enableInterrupt(isrRxLevel0);
#endif
}
/** Could we send right now (i.e. either not actively receving or transmitting)? */
template<typename T>
bool SX128xInterface<T>::isChannelActive()
{
// check if we can detect a LoRa preamble on the current channel
int16_t result;
setStandby();
result = lora.scanChannel();
if (result == RADIOLIB_PREAMBLE_DETECTED)
return true;
assert(result != RADIOLIB_ERR_WRONG_MODEM);
return false;
}
/** Could we send right now (i.e. either not actively receving or transmitting)? */
template<typename T>
bool SX128xInterface<T>::isActivelyReceiving()
{
return isChannelActive();
}
template<typename T>
bool SX128xInterface<T>::sleep()
{
// Not keeping config is busted - next time nrf52 board boots lora sending fails tcxo related? - see datasheet
// \todo Display actual typename of the adapter, not just `SX128x`
DEBUG_MSG("SX128x entering sleep mode (FIXME, don't keep config)\n");
setStandby(); // Stop any pending operations
// turn off TCXO if it was powered
// FIXME - this isn't correct
// lora.setTCXO(0);
// put chipset into sleep mode (we've already disabled interrupts by now)
bool keepConfig = true;
lora.sleep(keepConfig); // Note: we do not keep the config, full reinit will be needed
#ifdef SX128X_POWER_EN
digitalWrite(SX128X_POWER_EN, LOW);
#endif
return true;
}
#endif

View File

@@ -0,0 +1,75 @@
#pragma once
#if !defined(ARCH_PORTDUINO)
#include "RadioLibInterface.h"
/**
* \brief Adapter for SX128x radio family. Implements common logic for child classes.
* \tparam T RadioLib module type for SX128x: SX1281.
*/
template<class T>
class SX128xInterface : public RadioLibInterface
{
public:
SX128xInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi);
/// Initialise the Driver transport hardware and software.
/// Make sure the Driver is properly configured before calling init().
/// \return true if initialisation succeeded.
virtual bool init() override;
/// Apply any radio provisioning changes
/// Make sure the Driver is properly configured before calling init().
/// \return true if initialisation succeeded.
virtual bool reconfigure() override;
/// Prepare hardware for sleep. Call this _only_ for deep sleep, not needed for light sleep.
virtual bool sleep() override;
protected:
float currentLimit = 140; // Higher OCP limit for SX128x PA
/**
* Specific module instance
*/
T lora;
/**
* Glue functions called from ISR land
*/
virtual void disableInterrupt() override;
/**
* Enable a particular ISR callback glue function
*/
virtual void enableInterrupt(void (*callback)()) { lora.setDio1Action(callback); }
/** can we detect a LoRa preamble on the current channel? */
virtual bool isChannelActive() override;
/** are we actively receiving a packet (only called during receiving state) */
virtual bool isActivelyReceiving() override;
/**
* Start waiting to receive a message
*/
virtual void startReceive() override;
/**
* We override to turn on transmitter power as needed.
*/
virtual void configHardwareForSend() override;
/**
* Add SNR data to received messages
*/
virtual void addReceiveMetadata(MeshPacket *mp) override;
virtual void setStandby() override;
private:
};
#endif

View File

@@ -54,7 +54,7 @@ extern const pb_msgdesc_t ChannelSet_msg;
#define ChannelSet_fields &ChannelSet_msg #define ChannelSet_fields &ChannelSet_msg
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
#define ChannelSet_size 581 #define ChannelSet_size 582
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@@ -64,7 +64,8 @@ typedef enum _Config_LoRaConfig_RegionCode {
Config_LoRaConfig_RegionCode_RU = 9, Config_LoRaConfig_RegionCode_RU = 9,
Config_LoRaConfig_RegionCode_IN = 10, Config_LoRaConfig_RegionCode_IN = 10,
Config_LoRaConfig_RegionCode_NZ_865 = 11, Config_LoRaConfig_RegionCode_NZ_865 = 11,
Config_LoRaConfig_RegionCode_TH = 12 Config_LoRaConfig_RegionCode_TH = 12,
Config_LoRaConfig_RegionCode_LORA_24 = 13
} Config_LoRaConfig_RegionCode; } Config_LoRaConfig_RegionCode;
typedef enum _Config_LoRaConfig_ModemPreset { typedef enum _Config_LoRaConfig_ModemPreset {
@@ -116,7 +117,7 @@ typedef struct _Config_LoRaConfig {
uint32_t hop_limit; uint32_t hop_limit;
bool tx_enabled; bool tx_enabled;
int8_t tx_power; int8_t tx_power;
uint8_t channel_num; uint16_t channel_num;
pb_size_t ignore_incoming_count; pb_size_t ignore_incoming_count;
uint32_t ignore_incoming[3]; uint32_t ignore_incoming[3];
} Config_LoRaConfig; } Config_LoRaConfig;
@@ -186,8 +187,8 @@ typedef struct _Config {
#define _Config_DisplayConfig_DisplayUnits_ARRAYSIZE ((Config_DisplayConfig_DisplayUnits)(Config_DisplayConfig_DisplayUnits_IMPERIAL+1)) #define _Config_DisplayConfig_DisplayUnits_ARRAYSIZE ((Config_DisplayConfig_DisplayUnits)(Config_DisplayConfig_DisplayUnits_IMPERIAL+1))
#define _Config_LoRaConfig_RegionCode_MIN Config_LoRaConfig_RegionCode_UNSET #define _Config_LoRaConfig_RegionCode_MIN Config_LoRaConfig_RegionCode_UNSET
#define _Config_LoRaConfig_RegionCode_MAX Config_LoRaConfig_RegionCode_TH #define _Config_LoRaConfig_RegionCode_MAX Config_LoRaConfig_RegionCode_LORA_24
#define _Config_LoRaConfig_RegionCode_ARRAYSIZE ((Config_LoRaConfig_RegionCode)(Config_LoRaConfig_RegionCode_TH+1)) #define _Config_LoRaConfig_RegionCode_ARRAYSIZE ((Config_LoRaConfig_RegionCode)(Config_LoRaConfig_RegionCode_LORA_24+1))
#define _Config_LoRaConfig_ModemPreset_MIN Config_LoRaConfig_ModemPreset_LONG_FAST #define _Config_LoRaConfig_ModemPreset_MIN Config_LoRaConfig_ModemPreset_LONG_FAST
#define _Config_LoRaConfig_ModemPreset_MAX Config_LoRaConfig_ModemPreset_SHORT_FAST #define _Config_LoRaConfig_ModemPreset_MAX Config_LoRaConfig_ModemPreset_SHORT_FAST
@@ -387,7 +388,7 @@ extern const pb_msgdesc_t Config_BluetoothConfig_msg;
#define Config_BluetoothConfig_size 10 #define Config_BluetoothConfig_size 10
#define Config_DeviceConfig_size 6 #define Config_DeviceConfig_size 6
#define Config_DisplayConfig_size 20 #define Config_DisplayConfig_size 20
#define Config_LoRaConfig_size 67 #define Config_LoRaConfig_size 68
#define Config_NetworkConfig_size 137 #define Config_NetworkConfig_size 137
#define Config_PositionConfig_size 30 #define Config_PositionConfig_size 30
#define Config_PowerConfig_size 43 #define Config_PowerConfig_size 43

View File

@@ -69,6 +69,7 @@ typedef struct _DeviceState {
} DeviceState; } DeviceState;
typedef PB_BYTES_ARRAY_T(2048) OEMStore_oem_icon_bits_t; typedef PB_BYTES_ARRAY_T(2048) OEMStore_oem_icon_bits_t;
typedef PB_BYTES_ARRAY_T(32) OEMStore_oem_aes_key_t;
/* This can be used for customizing the firmware distribution. If populated, /* This can be used for customizing the firmware distribution. If populated,
show a secondary bootup screen with cuatom logo and text for 2.5 seconds. */ show a secondary bootup screen with cuatom logo and text for 2.5 seconds. */
typedef struct _OEMStore { typedef struct _OEMStore {
@@ -82,6 +83,8 @@ typedef struct _OEMStore {
ScreenFonts oem_font; ScreenFonts oem_font;
/* Use this font for the OEM text. */ /* Use this font for the OEM text. */
char oem_text[40]; char oem_text[40];
/* The default device encryption key, 16 or 32 byte */
OEMStore_oem_aes_key_t oem_aes_key;
} OEMStore; } OEMStore;
@@ -98,10 +101,10 @@ extern "C" {
/* Initializer values for message structs */ /* Initializer values for message structs */
#define DeviceState_init_default {false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0} #define DeviceState_init_default {false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0}
#define ChannelFile_init_default {0, {Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default}, 0} #define ChannelFile_init_default {0, {Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default}, 0}
#define OEMStore_init_default {0, 0, {0, {0}}, _ScreenFonts_MIN, ""} #define OEMStore_init_default {0, 0, {0, {0}}, _ScreenFonts_MIN, "", {0, {0}}}
#define DeviceState_init_zero {false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0, 0} #define DeviceState_init_zero {false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0, 0}
#define ChannelFile_init_zero {0, {Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero}, 0} #define ChannelFile_init_zero {0, {Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero}, 0}
#define OEMStore_init_zero {0, 0, {0, {0}}, _ScreenFonts_MIN, ""} #define OEMStore_init_zero {0, 0, {0, {0}}, _ScreenFonts_MIN, "", {0, {0}}}
/* Field tags (for use in manual encoding/decoding) */ /* Field tags (for use in manual encoding/decoding) */
#define ChannelFile_channels_tag 1 #define ChannelFile_channels_tag 1
@@ -119,6 +122,7 @@ extern "C" {
#define OEMStore_oem_icon_bits_tag 3 #define OEMStore_oem_icon_bits_tag 3
#define OEMStore_oem_font_tag 4 #define OEMStore_oem_font_tag 4
#define OEMStore_oem_text_tag 5 #define OEMStore_oem_text_tag 5
#define OEMStore_oem_aes_key_tag 6
/* Struct field encoding specification for nanopb */ /* Struct field encoding specification for nanopb */
#define DeviceState_FIELDLIST(X, a) \ #define DeviceState_FIELDLIST(X, a) \
@@ -150,7 +154,8 @@ X(a, STATIC, SINGULAR, UINT32, oem_icon_width, 1) \
X(a, STATIC, SINGULAR, UINT32, oem_icon_height, 2) \ X(a, STATIC, SINGULAR, UINT32, oem_icon_height, 2) \
X(a, STATIC, SINGULAR, BYTES, oem_icon_bits, 3) \ X(a, STATIC, SINGULAR, BYTES, oem_icon_bits, 3) \
X(a, STATIC, SINGULAR, UENUM, oem_font, 4) \ X(a, STATIC, SINGULAR, UENUM, oem_font, 4) \
X(a, STATIC, SINGULAR, STRING, oem_text, 5) X(a, STATIC, SINGULAR, STRING, oem_text, 5) \
X(a, STATIC, SINGULAR, BYTES, oem_aes_key, 6)
#define OEMStore_CALLBACK NULL #define OEMStore_CALLBACK NULL
#define OEMStore_DEFAULT NULL #define OEMStore_DEFAULT NULL
@@ -166,7 +171,7 @@ extern const pb_msgdesc_t OEMStore_msg;
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
#define ChannelFile_size 638 #define ChannelFile_size 638
#define DeviceState_size 21800 #define DeviceState_size 21800
#define OEMStore_size 2106 #define OEMStore_size 2140
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@@ -144,7 +144,7 @@ extern const pb_msgdesc_t LocalModuleConfig_msg;
#define LocalModuleConfig_fields &LocalModuleConfig_msg #define LocalModuleConfig_fields &LocalModuleConfig_msg
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
#define LocalConfig_size 334 #define LocalConfig_size 335
#define LocalModuleConfig_size 270 #define LocalModuleConfig_size 270
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -33,7 +33,8 @@ typedef enum _ModuleConfig_SerialConfig_Serial_Mode {
ModuleConfig_SerialConfig_Serial_Mode_DEFAULT = 0, ModuleConfig_SerialConfig_Serial_Mode_DEFAULT = 0,
ModuleConfig_SerialConfig_Serial_Mode_SIMPLE = 1, ModuleConfig_SerialConfig_Serial_Mode_SIMPLE = 1,
ModuleConfig_SerialConfig_Serial_Mode_PROTO = 2, ModuleConfig_SerialConfig_Serial_Mode_PROTO = 2,
ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG = 3 ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG = 3,
ModuleConfig_SerialConfig_Serial_Mode_NMEA = 4
} ModuleConfig_SerialConfig_Serial_Mode; } ModuleConfig_SerialConfig_Serial_Mode;
typedef enum _ModuleConfig_CannedMessageConfig_InputEventChar { typedef enum _ModuleConfig_CannedMessageConfig_InputEventChar {
@@ -140,8 +141,8 @@ typedef struct _ModuleConfig {
#define _ModuleConfig_SerialConfig_Serial_Baud_ARRAYSIZE ((ModuleConfig_SerialConfig_Serial_Baud)(ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600+1)) #define _ModuleConfig_SerialConfig_Serial_Baud_ARRAYSIZE ((ModuleConfig_SerialConfig_Serial_Baud)(ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600+1))
#define _ModuleConfig_SerialConfig_Serial_Mode_MIN ModuleConfig_SerialConfig_Serial_Mode_DEFAULT #define _ModuleConfig_SerialConfig_Serial_Mode_MIN ModuleConfig_SerialConfig_Serial_Mode_DEFAULT
#define _ModuleConfig_SerialConfig_Serial_Mode_MAX ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG #define _ModuleConfig_SerialConfig_Serial_Mode_MAX ModuleConfig_SerialConfig_Serial_Mode_NMEA
#define _ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((ModuleConfig_SerialConfig_Serial_Mode)(ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG+1)) #define _ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((ModuleConfig_SerialConfig_Serial_Mode)(ModuleConfig_SerialConfig_Serial_Mode_NMEA+1))
#define _ModuleConfig_CannedMessageConfig_InputEventChar_MIN ModuleConfig_CannedMessageConfig_InputEventChar_NONE #define _ModuleConfig_CannedMessageConfig_InputEventChar_MIN ModuleConfig_CannedMessageConfig_InputEventChar_NONE
#define _ModuleConfig_CannedMessageConfig_InputEventChar_MAX ModuleConfig_CannedMessageConfig_InputEventChar_BACK #define _ModuleConfig_CannedMessageConfig_InputEventChar_MAX ModuleConfig_CannedMessageConfig_InputEventChar_BACK

View File

@@ -79,8 +79,8 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
ResourceNode *nodeHotspotAndroid = new ResourceNode("/generate_204", "GET", &handleHotspot); ResourceNode *nodeHotspotAndroid = new ResourceNode("/generate_204", "GET", &handleHotspot);
ResourceNode *nodeAdmin = new ResourceNode("/admin", "GET", &handleAdmin); ResourceNode *nodeAdmin = new ResourceNode("/admin", "GET", &handleAdmin);
ResourceNode *nodeAdminSettings = new ResourceNode("/admin/settings", "GET", &handleAdminSettings); // ResourceNode *nodeAdminSettings = new ResourceNode("/admin/settings", "GET", &handleAdminSettings);
ResourceNode *nodeAdminSettingsApply = new ResourceNode("/admin/settings/apply", "POST", &handleAdminSettingsApply); // ResourceNode *nodeAdminSettingsApply = new ResourceNode("/admin/settings/apply", "POST", &handleAdminSettingsApply);
// ResourceNode *nodeAdminFs = new ResourceNode("/admin/fs", "GET", &handleFs); // ResourceNode *nodeAdminFs = new ResourceNode("/admin/fs", "GET", &handleFs);
// ResourceNode *nodeUpdateFs = new ResourceNode("/admin/fs/update", "POST", &handleUpdateFs); // ResourceNode *nodeUpdateFs = new ResourceNode("/admin/fs/update", "POST", &handleUpdateFs);
// ResourceNode *nodeDeleteFs = new ResourceNode("/admin/fs/delete", "GET", &handleDeleteFsContent); // ResourceNode *nodeDeleteFs = new ResourceNode("/admin/fs/delete", "GET", &handleDeleteFsContent);
@@ -113,8 +113,8 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
// secureServer->registerNode(nodeDeleteFs); // secureServer->registerNode(nodeDeleteFs);
secureServer->registerNode(nodeAdmin); secureServer->registerNode(nodeAdmin);
// secureServer->registerNode(nodeAdminFs); // secureServer->registerNode(nodeAdminFs);
secureServer->registerNode(nodeAdminSettings); // secureServer->registerNode(nodeAdminSettings);
secureServer->registerNode(nodeAdminSettingsApply); // secureServer->registerNode(nodeAdminSettingsApply);
secureServer->registerNode(nodeRoot); // This has to be last secureServer->registerNode(nodeRoot); // This has to be last
// Insecure nodes // Insecure nodes
@@ -134,8 +134,8 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
// insecureServer->registerNode(nodeDeleteFs); // insecureServer->registerNode(nodeDeleteFs);
insecureServer->registerNode(nodeAdmin); insecureServer->registerNode(nodeAdmin);
// insecureServer->registerNode(nodeAdminFs); // insecureServer->registerNode(nodeAdminFs);
insecureServer->registerNode(nodeAdminSettings); // insecureServer->registerNode(nodeAdminSettings);
insecureServer->registerNode(nodeAdminSettingsApply); // insecureServer->registerNode(nodeAdminSettingsApply);
insecureServer->registerNode(nodeRoot); // This has to be last insecureServer->registerNode(nodeRoot); // This has to be last
} }
@@ -694,8 +694,8 @@ void handleAdmin(HTTPRequest *req, HTTPResponse *res)
res->setHeader("Access-Control-Allow-Methods", "GET"); res->setHeader("Access-Control-Allow-Methods", "GET");
res->println("<h1>Meshtastic</h1>\n"); res->println("<h1>Meshtastic</h1>\n");
res->println("<a href=/admin/settings>Settings</a><br>\n"); // res->println("<a href=/admin/settings>Settings</a><br>\n");
res->println("<a href=/admin/fs>Manage Web Content</a><br>\n"); // res->println("<a href=/admin/fs>Manage Web Content</a><br>\n");
res->println("<a href=/json/report>Device Report</a><br>\n"); res->println("<a href=/json/report>Device Report</a><br>\n");
} }

View File

@@ -43,40 +43,25 @@ bool APStartupComplete = 0;
static bool needReconnect = true; // If we create our reconnector, run it once at the beginning static bool needReconnect = true; // If we create our reconnector, run it once at the beginning
// FIXME, veto light sleep if we have a TCP server running
#if 0
class WifiSleepObserver : public Observer<uint32_t> {
protected:
/// Return 0 if sleep is okay
virtual int onNotify(uint32_t newValue) {
}
};
static WifiSleepObserver wifiSleepObserver;
//preflightSleepObserver.observe(&preflightSleep);
#endif
static int32_t reconnectWiFi() static int32_t reconnectWiFi()
{ {
const char *wifiName = config.network.wifi_ssid; const char *wifiName = config.network.wifi_ssid;
const char *wifiPsw = config.network.wifi_psk; const char *wifiPsw = config.network.wifi_psk;
if (config.network.wifi_enabled && needReconnect && !WiFi.isConnected()) { if (config.network.wifi_enabled && needReconnect && !WiFi.isConnected()) {
// if (radioConfig.has_preferences && needReconnect && !WiFi.isConnected()) {
if (!*wifiPsw) // Treat empty password as no password if (!*wifiPsw) // Treat empty password as no password
wifiPsw = NULL; wifiPsw = NULL;
if (*wifiName) { if (*wifiName) {
needReconnect = false; needReconnect = false;
// Make sure we clear old connection credentials
WiFi.disconnect(false, true);
DEBUG_MSG("... Reconnecting to WiFi access point\n"); DEBUG_MSG("... Reconnecting to WiFi access point\n");
WiFi.mode(WIFI_MODE_STA); WiFi.mode(WIFI_MODE_STA);
WiFi.begin(wifiName, wifiPsw); WiFi.begin(wifiName, wifiPsw);
// Starting timeClient;
} }
} }

View File

@@ -101,9 +101,7 @@ bool AdminModule::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r)
* Other * Other
*/ */
case AdminMessage_reboot_seconds_tag: { case AdminMessage_reboot_seconds_tag: {
int32_t s = r->reboot_seconds; reboot(r->reboot_seconds);
DEBUG_MSG("Rebooting in %d seconds\n", s);
rebootAtMsec = (s < 0) ? 0 : (millis() + s * 1000);
break; break;
} }
case AdminMessage_reboot_ota_seconds_tag: { case AdminMessage_reboot_ota_seconds_tag: {
@@ -135,13 +133,13 @@ bool AdminModule::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r)
case AdminMessage_factory_reset_tag: { case AdminMessage_factory_reset_tag: {
DEBUG_MSG("Initiating factory reset\n"); DEBUG_MSG("Initiating factory reset\n");
nodeDB.factoryReset(); nodeDB.factoryReset();
rebootAtMsec = millis() + (5 * 1000); reboot(5);
break; break;
} }
case AdminMessage_nodedb_reset_tag: { case AdminMessage_nodedb_reset_tag: {
DEBUG_MSG("Initiating node-db reset\n"); DEBUG_MSG("Initiating node-db reset\n");
nodeDB.resetNodes(); nodeDB.resetNodes();
rebootAtMsec = millis() + (5 * 1000); reboot(5);
break; break;
} }
#ifdef ARCH_PORTDUINO #ifdef ARCH_PORTDUINO
@@ -196,14 +194,12 @@ void AdminModule::handleSetOwner(const User &o)
if (changed) { // If nothing really changed, don't broadcast on the network or write to flash if (changed) { // If nothing really changed, don't broadcast on the network or write to flash
service.reloadOwner(); service.reloadOwner();
DEBUG_MSG("Rebooting due to owner changes\n"); DEBUG_MSG("Rebooting due to owner changes\n");
screen->startRebootScreen(); reboot(5);
rebootAtMsec = millis() + (5 * 1000);
} }
} }
void AdminModule::handleSetConfig(const Config &c) void AdminModule::handleSetConfig(const Config &c)
{ {
bool requiresReboot = false;
bool isRouter = (config.device.role == Config_DeviceConfig_Role_ROUTER); bool isRouter = (config.device.role == Config_DeviceConfig_Role_ROUTER);
bool isRegionUnset = (config.lora.region == Config_LoRaConfig_RegionCode_UNSET); bool isRegionUnset = (config.lora.region == Config_LoRaConfig_RegionCode_UNSET);
@@ -218,12 +214,13 @@ void AdminModule::handleSetConfig(const Config &c)
nodeDB.initConfigIntervals(); nodeDB.initConfigIntervals();
nodeDB.initModuleConfigIntervals(); nodeDB.initModuleConfigIntervals();
} }
requiresReboot = true;
break; break;
case Config_position_tag: case Config_position_tag:
DEBUG_MSG("Setting config: Position\n"); DEBUG_MSG("Setting config: Position\n");
config.has_position = true; config.has_position = true;
config.position = c.payload_variant.position; config.position = c.payload_variant.position;
// Save nodedb as well in case we got a fixed position packet
nodeDB.saveToDisk(SEGMENT_DEVICESTATE);
break; break;
case Config_power_tag: case Config_power_tag:
DEBUG_MSG("Setting config: Power\n"); DEBUG_MSG("Setting config: Power\n");
@@ -234,7 +231,6 @@ void AdminModule::handleSetConfig(const Config &c)
DEBUG_MSG("Setting config: WiFi\n"); DEBUG_MSG("Setting config: WiFi\n");
config.has_network = true; config.has_network = true;
config.network = c.payload_variant.network; config.network = c.payload_variant.network;
requiresReboot = true;
break; break;
case Config_display_tag: case Config_display_tag:
DEBUG_MSG("Setting config: Display\n"); DEBUG_MSG("Setting config: Display\n");
@@ -249,23 +245,16 @@ void AdminModule::handleSetConfig(const Config &c)
config.lora.region > Config_LoRaConfig_RegionCode_UNSET) { config.lora.region > Config_LoRaConfig_RegionCode_UNSET) {
config.lora.tx_enabled = true; config.lora.tx_enabled = true;
} }
requiresReboot = true;
break; break;
case Config_bluetooth_tag: case Config_bluetooth_tag:
DEBUG_MSG("Setting config: Bluetooth\n"); DEBUG_MSG("Setting config: Bluetooth\n");
config.has_bluetooth = true; config.has_bluetooth = true;
config.bluetooth = c.payload_variant.bluetooth; config.bluetooth = c.payload_variant.bluetooth;
requiresReboot = true;
break; break;
} }
service.reloadConfig(SEGMENT_CONFIG); service.reloadConfig(SEGMENT_CONFIG);
// Reboot 5 seconds after a config that requires rebooting is set reboot(5);
if (requiresReboot) {
DEBUG_MSG("Rebooting due to config changes\n");
screen->startRebootScreen();
rebootAtMsec = millis() + (5 * 1000);
}
} }
void AdminModule::handleSetModuleConfig(const ModuleConfig &c) void AdminModule::handleSetModuleConfig(const ModuleConfig &c)
@@ -307,8 +296,9 @@ void AdminModule::handleSetModuleConfig(const ModuleConfig &c)
moduleConfig.canned_message = c.payload_variant.canned_message; moduleConfig.canned_message = c.payload_variant.canned_message;
break; break;
} }
service.reloadConfig(SEGMENT_MODULECONFIG); service.reloadConfig(SEGMENT_MODULECONFIG);
reboot(5);
} }
void AdminModule::handleSetChannel(const Channel &cc) void AdminModule::handleSetChannel(const Channel &cc)
@@ -468,6 +458,13 @@ void AdminModule::handleGetChannel(const MeshPacket &req, uint32_t channelIndex)
} }
} }
void AdminModule::reboot(int32_t seconds)
{
DEBUG_MSG("Rebooting in %d seconds\n", seconds);
screen->startRebootScreen();
rebootAtMsec = (seconds < 0) ? 0 : (millis() + seconds * 1000);
}
AdminModule::AdminModule() : ProtobufModule("Admin", PortNum_ADMIN_APP, AdminMessage_fields) AdminModule::AdminModule() : ProtobufModule("Admin", PortNum_ADMIN_APP, AdminMessage_fields)
{ {
// restrict to the admin channel for rx // restrict to the admin channel for rx

View File

@@ -37,6 +37,7 @@ class AdminModule : public ProtobufModule<AdminMessage>
void handleSetConfig(const Config &c); void handleSetConfig(const Config &c);
void handleSetModuleConfig(const ModuleConfig &c); void handleSetModuleConfig(const ModuleConfig &c);
void handleSetChannel(); void handleSetChannel();
void reboot(int32_t seconds);
}; };
extern AdminModule *adminModule; extern AdminModule *adminModule;

View File

@@ -225,7 +225,7 @@ int32_t CannedMessageModule::runOnce()
this->cursor = 0; this->cursor = 0;
this->destSelect = false; this->destSelect = false;
this->notifyObservers(&e); this->notifyObservers(&e);
} else if (((this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) || (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT)) && (millis() - this->lastTouchMillis) > INACTIVATE_AFTER_MS) { } else if (((this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) || (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT)) && ((millis() - this->lastTouchMillis) > INACTIVATE_AFTER_MS)) {
// Reset module // Reset module
DEBUG_MSG("Reset due to lack of activity.\n"); DEBUG_MSG("Reset due to lack of activity.\n");
e.frameChanged = true; e.frameChanged = true;
@@ -430,6 +430,8 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
{ {
displayedNodeNum = 0; // Not currently showing a node pane displayedNodeNum = 0; // Not currently showing a node pane
char buffer[50];
if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) { if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) {
display->setTextAlignment(TEXT_ALIGN_CENTER); display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(FONT_MEDIUM); display->setFont(FONT_MEDIUM);
@@ -445,7 +447,6 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL); display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
display->setColor(BLACK); display->setColor(BLACK);
} }
char buffer[50];
display->drawStringf(0 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest)); display->drawStringf(0 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest));
// used chars right aligned // used chars right aligned
sprintf(buffer, "%d left", Constants_DATA_PAYLOAD_LEN - this->freetext.length()); sprintf(buffer, "%d left", Constants_DATA_PAYLOAD_LEN - this->freetext.length());
@@ -456,11 +457,13 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
if (this->messagesCount > 0) { if (this->messagesCount > 0) {
display->setTextAlignment(TEXT_ALIGN_LEFT); display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(FONT_SMALL); display->setFont(FONT_SMALL);
display->drawString(0 + x, 0 + y, cannedMessageModule->getPrevMessage()); display->drawStringf(0 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest));
display->setFont(FONT_MEDIUM); display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL, cannedMessageModule->getPrevMessage());
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL, cannedMessageModule->getCurrentMessage()); display->fillRect(0 + x, 0 + y + FONT_HEIGHT_SMALL * 2, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
display->setFont(FONT_SMALL); display->setColor(BLACK);
display->drawString(0 + x, 0 + y + FONT_HEIGHT_MEDIUM, cannedMessageModule->getNextMessage()); display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * 2, cannedMessageModule->getCurrentMessage());
display->setColor(WHITE);
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * 3, cannedMessageModule->getNextMessage());
} }
} }
} }

View File

@@ -87,4 +87,4 @@ class CannedMessageModule :
}; };
extern CannedMessageModule *cannedMessageModule; extern CannedMessageModule *cannedMessageModule;
#endif #endif

View File

@@ -60,13 +60,15 @@ void setupModules()
new DeviceTelemetryModule(); new DeviceTelemetryModule();
new EnvironmentTelemetryModule(); new EnvironmentTelemetryModule();
#endif #endif
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO)
new SerialModule();
#endif
#ifdef ARCH_ESP32 #ifdef ARCH_ESP32
// Only run on an esp32 based device. // Only run on an esp32 based device.
/* /*
Maintained by MC Hamster (Jm Casler) jm@casler.org Maintained by MC Hamster (Jm Casler) jm@casler.org
*/ */
new SerialModule();
new ExternalNotificationModule(); new ExternalNotificationModule();
storeForwardModule = new StoreForwardModule(); storeForwardModule = new StoreForwardModule();

View File

@@ -108,7 +108,7 @@ MeshPacket *PositionModule::allocReply()
// Strip out any time information before sending packets to other nodes - to keep the wire size small (and because other // Strip out any time information before sending packets to other nodes - to keep the wire size small (and because other
// nodes shouldn't trust it anyways) Note: we allow a device with a local GPS to include the time, so that gpsless // nodes shouldn't trust it anyways) Note: we allow a device with a local GPS to include the time, so that gpsless
// devices can get time. // devices can get time.
if (getRTCQuality() < RTCQualityGPS) { if (getRTCQuality() < RTCQualityDevice) {
DEBUG_MSG("Stripping time %u from position send\n", p.time); DEBUG_MSG("Stripping time %u from position send\n", p.time);
p.time = 0; p.time = 0;
} else } else

View File

@@ -2,6 +2,7 @@
#include "MeshService.h" #include "MeshService.h"
#include "NodeDB.h" #include "NodeDB.h"
#include "RTC.h" #include "RTC.h"
#include "NMEAWPL.h"
#include "Router.h" #include "Router.h"
#include "configuration.h" #include "configuration.h"
#include <Arduino.h> #include <Arduino.h>
@@ -40,7 +41,7 @@
KNOWN PROBLEMS KNOWN PROBLEMS
* Until the module is initilized by the startup sequence, the TX pin is in a floating * Until the module is initilized by the startup sequence, the TX pin is in a floating
state. Device connected to that pin may see this as "noise". state. Device connected to that pin may see this as "noise".
* Will not work on NRF and the Linux device targets. * Will not work on T-Echo and the Linux device targets.
*/ */
@@ -62,16 +63,19 @@ char serialStringChar[Constants_DATA_PAYLOAD_LEN];
SerialModuleRadio::SerialModuleRadio() : MeshModule("SerialModuleRadio") SerialModuleRadio::SerialModuleRadio() : MeshModule("SerialModuleRadio")
{ {
// restrict to the admin channel for rx
boundChannel = Channels::serialChannel;
switch (moduleConfig.serial.mode) switch (moduleConfig.serial.mode)
{ {
case ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG: case ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG:
ourPortNum = PortNum_TEXT_MESSAGE_APP; ourPortNum = PortNum_TEXT_MESSAGE_APP;
break; break;
case ModuleConfig_SerialConfig_Serial_Mode_NMEA:
ourPortNum = PortNum_POSITION_APP;
break;
default: default:
ourPortNum = PortNum_SERIAL_APP; ourPortNum = PortNum_SERIAL_APP;
// restrict to the serial channel for rx
boundChannel = Channels::serialChannel;
break; break;
} }
} }
@@ -175,15 +179,25 @@ int32_t SerialModule::runOnce()
firstTime = 0; firstTime = 0;
} else { } else {
String serialString;
while (Serial2.available()) { // in NMEA mode send out GGA every 2 seconds, Don't read from Port
serialString = Serial2.readString(); if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_NMEA) {
serialString.toCharArray(serialStringChar, Constants_DATA_PAYLOAD_LEN); if (millis() - lastNmeaTime > 2000) {
lastNmeaTime = millis();
printGGA(outbuf, nodeDB.getNode(myNodeInfo.my_node_num)->position);
Serial2.printf("%s", outbuf);
}
} else {
String serialString;
serialModuleRadio->sendPayload(); while (Serial2.available()) {
serialString = Serial2.readString();
serialString.toCharArray(serialStringChar, Constants_DATA_PAYLOAD_LEN);
DEBUG_MSG("Received: %s\n", serialStringChar); serialModuleRadio->sendPayload();
DEBUG_MSG("Received: %s\n", serialStringChar);
}
} }
} }
@@ -191,7 +205,7 @@ int32_t SerialModule::runOnce()
} else { } else {
DEBUG_MSG("Serial Module Disabled\n"); DEBUG_MSG("Serial Module Disabled\n");
return (INT32_MAX); return INT32_MAX;
} }
#else #else
return INT32_MAX; return INT32_MAX;
@@ -255,6 +269,19 @@ ProcessMessage SerialModuleRadio::handleReceived(const MeshPacket &mp)
} else if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_PROTO) { } else if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_PROTO) {
// TODO this needs to be implemented // TODO this needs to be implemented
} else if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_NMEA) {
// Decode the Payload some more
Position scratch;
Position *decoded = NULL;
if (mp.which_payload_variant == MeshPacket_decoded_tag && mp.decoded.portnum == ourPortNum) {
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(p.payload.bytes, p.payload.size, Position_fields, &scratch)) {
decoded = &scratch;
}
// send position packet as WPL to the serial port
printWPL(outbuf, *decoded, nodeDB.getNode(getFrom(&mp))->user.long_name);
Serial2.printf("%s", outbuf);
}
} }
} }

View File

@@ -11,6 +11,8 @@
class SerialModule : private concurrency::OSThread class SerialModule : private concurrency::OSThread
{ {
bool firstTime = 1; bool firstTime = 1;
unsigned long lastNmeaTime = millis();
char outbuf[90] = "";
public: public:
SerialModule(); SerialModule();
@@ -28,6 +30,7 @@ extern SerialModule *serialModule;
class SerialModuleRadio : public MeshModule class SerialModuleRadio : public MeshModule
{ {
uint32_t lastRxID = 0; uint32_t lastRxID = 0;
char outbuf[90] = "";
public: public:
SerialModuleRadio(); SerialModuleRadio();

View File

@@ -9,17 +9,20 @@
#include "main.h" #include "main.h"
#include <OLEDDisplay.h> #include <OLEDDisplay.h>
#include <OLEDDisplayUi.h> #include <OLEDDisplayUi.h>
#include "MeshService.h"
int32_t DeviceTelemetryModule::runOnce() int32_t DeviceTelemetryModule::runOnce()
{ {
#ifndef ARCH_PORTDUINO #ifndef ARCH_PORTDUINO
uint32_t now = millis(); uint32_t now = millis();
if ((lastSentToMesh == 0 || (now - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.telemetry.device_update_interval)) if ((lastSentToMesh == 0 ||
&& airTime->channelUtilizationPercent() < max_channel_util_percent) { (now - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.telemetry.device_update_interval)) &&
airTime->channelUtilizationPercent() < max_channel_util_percent) {
sendTelemetry(); sendTelemetry();
lastSentToMesh = now; lastSentToMesh = now;
} else { } else if (service.isToPhoneQueueEmpty()) {
// Just send to phone when it's not our time to send to mesh yet // Just send to phone when it's not our time to send to mesh yet
// Only send while queue is empty (phone assumed connected)
sendTelemetry(NODENUM_BROADCAST, true); sendTelemetry(NODENUM_BROADCAST, true);
} }
return sendToPhoneIntervalMs; return sendToPhoneIntervalMs;
@@ -30,14 +33,13 @@ bool DeviceTelemetryModule::handleReceivedProtobuf(const MeshPacket &mp, Telemet
{ {
if (t->which_variant == Telemetry_device_metrics_tag) { if (t->which_variant == Telemetry_device_metrics_tag) {
const char *sender = getSenderShortName(mp); const char *sender = getSenderShortName(mp);
DEBUG_MSG("-----------------------------------------\n"); DEBUG_MSG("(Received from %s): air_util_tx=%f, channel_utilization=%f, battery_level=%i, voltage=%f\n",
DEBUG_MSG("Device Telemetry: Received data from %s\n", sender); sender,
DEBUG_MSG("Telemetry->time: %i\n", t->time); t->variant.device_metrics.air_util_tx,
DEBUG_MSG("Telemetry->air_util_tx: %f\n", t->variant.device_metrics.air_util_tx); t->variant.device_metrics.channel_utilization,
DEBUG_MSG("Telemetry->battery_level: %i\n", t->variant.device_metrics.battery_level); t->variant.device_metrics.battery_level,
DEBUG_MSG("Telemetry->channel_utilization: %f\n", t->variant.device_metrics.channel_utilization); t->variant.device_metrics.voltage);
DEBUG_MSG("Telemetry->voltage: %f\n", t->variant.device_metrics.voltage);
lastMeasurementPacket = packetPool.allocCopy(mp); lastMeasurementPacket = packetPool.allocCopy(mp);
@@ -58,26 +60,24 @@ bool DeviceTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
t.variant.device_metrics.channel_utilization = myNodeInfo.channel_utilization; t.variant.device_metrics.channel_utilization = myNodeInfo.channel_utilization;
t.variant.device_metrics.voltage = powerStatus->getBatteryVoltageMv() / 1000.0; t.variant.device_metrics.voltage = powerStatus->getBatteryVoltageMv() / 1000.0;
DEBUG_MSG("-----------------------------------------\n"); DEBUG_MSG("(Sending): air_util_tx=%f, channel_utilization=%f, battery_level=%i, voltage=%f\n",
DEBUG_MSG("Device Telemetry: Read data\n"); t.variant.device_metrics.air_util_tx,
t.variant.device_metrics.channel_utilization,
DEBUG_MSG("Telemetry->time: %i\n", t.time); t.variant.device_metrics.battery_level,
DEBUG_MSG("Telemetry->air_util_tx: %f\n", t.variant.device_metrics.air_util_tx); t.variant.device_metrics.voltage);
DEBUG_MSG("Telemetry->battery_level: %i\n", t.variant.device_metrics.battery_level);
DEBUG_MSG("Telemetry->channel_utilization: %f\n", t.variant.device_metrics.channel_utilization);
DEBUG_MSG("Telemetry->voltage: %f\n", t.variant.device_metrics.voltage);
MeshPacket *p = allocDataProtobuf(t); MeshPacket *p = allocDataProtobuf(t);
p->to = dest; p->to = dest;
p->decoded.want_response = false; p->decoded.want_response = false;
p->priority = MeshPacket_Priority_MIN;
lastMeasurementPacket = packetPool.allocCopy(*p); lastMeasurementPacket = packetPool.allocCopy(*p);
nodeDB.updateTelemetry(nodeDB.getNodeNum(), t, RX_SRC_LOCAL); nodeDB.updateTelemetry(nodeDB.getNodeNum(), t, RX_SRC_LOCAL);
if (phoneOnly) { if (phoneOnly) {
DEBUG_MSG("Device Telemetry: Sending packet to phone\n"); DEBUG_MSG("Sending packet to phone\n");
service.sendToPhone(p); service.sendToPhone(p);
} else { } else {
DEBUG_MSG("Device Telemetry: Sending packet to mesh\n"); DEBUG_MSG("Sending packet to mesh\n");
service.sendToMesh(p, RX_SRC_LOCAL, true); service.sendToMesh(p, RX_SRC_LOCAL, true);
} }
return true; return true;

View File

@@ -11,7 +11,8 @@ class DeviceTelemetryModule : private concurrency::OSThread, public ProtobufModu
DeviceTelemetryModule() DeviceTelemetryModule()
: concurrency::OSThread("DeviceTelemetryModule"), ProtobufModule("DeviceTelemetry", PortNum_TELEMETRY_APP, &Telemetry_msg) : concurrency::OSThread("DeviceTelemetryModule"), ProtobufModule("DeviceTelemetry", PortNum_TELEMETRY_APP, &Telemetry_msg)
{ {
lastMeasurementPacket = nullptr; lastMeasurementPacket = nullptr;
setIntervalFromNow(10 * 1000);
} }
virtual bool wantUIFrame() { return false; } virtual bool wantUIFrame() { return false; }

View File

@@ -9,6 +9,7 @@
#include "main.h" #include "main.h"
#include <OLEDDisplay.h> #include <OLEDDisplay.h>
#include <OLEDDisplayUi.h> #include <OLEDDisplayUi.h>
#include "MeshService.h"
// Sensors // Sensors
#include "Sensor/BMP280Sensor.h" #include "Sensor/BMP280Sensor.h"
@@ -17,6 +18,8 @@
#include "Sensor/MCP9808Sensor.h" #include "Sensor/MCP9808Sensor.h"
#include "Sensor/INA260Sensor.h" #include "Sensor/INA260Sensor.h"
#include "Sensor/INA219Sensor.h" #include "Sensor/INA219Sensor.h"
#include "Sensor/SHTC3Sensor.h"
#include "Sensor/LPS22HBSensor.h"
BMP280Sensor bmp280Sensor; BMP280Sensor bmp280Sensor;
BME280Sensor bme280Sensor; BME280Sensor bme280Sensor;
@@ -24,6 +27,8 @@ BME680Sensor bme680Sensor;
MCP9808Sensor mcp9808Sensor; MCP9808Sensor mcp9808Sensor;
INA260Sensor ina260Sensor; INA260Sensor ina260Sensor;
INA219Sensor ina219Sensor; INA219Sensor ina219Sensor;
SHTC3Sensor shtc3Sensor;
LPS22HBSensor lps22hbSensor;
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10 #define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true #define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
@@ -83,21 +88,31 @@ int32_t EnvironmentTelemetryModule::runOnce()
result = ina260Sensor.runOnce(); result = ina260Sensor.runOnce();
if (ina219Sensor.hasSensor()) if (ina219Sensor.hasSensor())
result = ina219Sensor.runOnce(); result = ina219Sensor.runOnce();
if (shtc3Sensor.hasSensor())
result = shtc3Sensor.runOnce();
if (lps22hbSensor.hasSensor()) {
result = lps22hbSensor.runOnce();
}
} }
return result; return result;
} else { } else {
// if we somehow got to a second run of this module with measurement disabled, then just wait forever // if we somehow got to a second run of this module with measurement disabled, then just wait forever
if (!moduleConfig.telemetry.environment_measurement_enabled) if (!moduleConfig.telemetry.environment_measurement_enabled)
return result; return result;
// this is not the first time OSThread library has called this function
// so just do what we intend to do on the interval uint32_t now = millis();
if (!sendOurTelemetry()) { if ((lastSentToMesh == 0 ||
// if we failed to read the sensor, then try again (now - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.telemetry.environment_update_interval)) &&
// as soon as we can according to the maximum polling frequency airTime->channelUtilizationPercent() < max_channel_util_percent) {
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; sendTelemetry();
lastSentToMesh = now;
} else if (service.isToPhoneQueueEmpty()) {
// Just send to phone when it's not our time to send to mesh yet
// Only send while queue is empty (phone assumed connected)
sendTelemetry(NODENUM_BROADCAST, true);
} }
} }
return getConfiguredOrDefaultMs(moduleConfig.telemetry.environment_update_interval); return sendToPhoneIntervalMs;
#endif #endif
} }
@@ -143,7 +158,7 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt
if (!pb_decode_from_bytes(p.payload.bytes, p.payload.size, Telemetry_fields, &lastMeasurement)) { if (!pb_decode_from_bytes(p.payload.bytes, p.payload.size, Telemetry_fields, &lastMeasurement)) {
display->setFont(FONT_SMALL); display->setFont(FONT_SMALL);
display->drawString(x, y += fontHeight(FONT_MEDIUM), "Measurement Error"); display->drawString(x, y += fontHeight(FONT_MEDIUM), "Measurement Error");
DEBUG_MSG("Environment Telemetry: unable to decode last packet"); DEBUG_MSG("Unable to decode last packet");
return; return;
} }
@@ -168,15 +183,14 @@ bool EnvironmentTelemetryModule::handleReceivedProtobuf(const MeshPacket &mp, Te
if (t->which_variant == Telemetry_environment_metrics_tag) { if (t->which_variant == Telemetry_environment_metrics_tag) {
const char *sender = getSenderShortName(mp); const char *sender = getSenderShortName(mp);
DEBUG_MSG("-----------------------------------------\n"); DEBUG_MSG("(Received from %s): barometric_pressure=%f, current=%f, gas_resistance=%f, relative_humidity=%f, temperature=%f, voltage=%f\n",
DEBUG_MSG("Environment Telemetry: Received data from %s\n", sender); sender,
DEBUG_MSG("Telemetry->time: %i\n", t->time); t->variant.environment_metrics.barometric_pressure,
DEBUG_MSG("Telemetry->barometric_pressure: %f\n", t->variant.environment_metrics.barometric_pressure); t->variant.environment_metrics.current,
DEBUG_MSG("Telemetry->current: %f\n", t->variant.environment_metrics.current); t->variant.environment_metrics.gas_resistance,
DEBUG_MSG("Telemetry->gas_resistance: %f\n", t->variant.environment_metrics.gas_resistance); t->variant.environment_metrics.relative_humidity,
DEBUG_MSG("Telemetry->relative_humidity: %f\n", t->variant.environment_metrics.relative_humidity); t->variant.environment_metrics.temperature,
DEBUG_MSG("Telemetry->temperature: %f\n", t->variant.environment_metrics.temperature); t->variant.environment_metrics.voltage);
DEBUG_MSG("Telemetry->voltage: %f\n", t->variant.environment_metrics.voltage);
lastMeasurementPacket = packetPool.allocCopy(mp); lastMeasurementPacket = packetPool.allocCopy(mp);
} }
@@ -184,7 +198,7 @@ bool EnvironmentTelemetryModule::handleReceivedProtobuf(const MeshPacket &mp, Te
return false; // Let others look at this message also if they want return false; // Let others look at this message also if they want
} }
bool EnvironmentTelemetryModule::sendOurTelemetry(NodeNum dest, bool wantReplies) bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
{ {
Telemetry m; Telemetry m;
m.time = getTime(); m.time = getTime();
@@ -197,9 +211,10 @@ bool EnvironmentTelemetryModule::sendOurTelemetry(NodeNum dest, bool wantReplies
m.variant.environment_metrics.temperature = 0; m.variant.environment_metrics.temperature = 0;
m.variant.environment_metrics.voltage = 0; m.variant.environment_metrics.voltage = 0;
DEBUG_MSG("-----------------------------------------\n"); if (lps22hbSensor.hasSensor())
DEBUG_MSG("Environment Telemetry: Read data\n"); lps22hbSensor.getMetrics(&m);
if (shtc3Sensor.hasSensor())
shtc3Sensor.getMetrics(&m);
if (bmp280Sensor.hasSensor()) if (bmp280Sensor.hasSensor())
bmp280Sensor.getMetrics(&m); bmp280Sensor.getMetrics(&m);
if (bme280Sensor.hasSensor()) if (bme280Sensor.hasSensor())
@@ -213,22 +228,28 @@ bool EnvironmentTelemetryModule::sendOurTelemetry(NodeNum dest, bool wantReplies
if (ina260Sensor.hasSensor()) if (ina260Sensor.hasSensor())
ina260Sensor.getMetrics(&m); ina260Sensor.getMetrics(&m);
DEBUG_MSG("Telemetry->time: %i\n", m.time); DEBUG_MSG("(Sending): barometric_pressure=%f, current=%f, gas_resistance=%f, relative_humidity=%f, temperature=%f, voltage=%f\n",
DEBUG_MSG("Telemetry->barometric_pressure: %f\n", m.variant.environment_metrics.barometric_pressure); m.variant.environment_metrics.barometric_pressure,
DEBUG_MSG("Telemetry->current: %f\n", m.variant.environment_metrics.current); m.variant.environment_metrics.current,
DEBUG_MSG("Telemetry->gas_resistance: %f\n", m.variant.environment_metrics.gas_resistance); m.variant.environment_metrics.gas_resistance,
DEBUG_MSG("Telemetry->relative_humidity: %f\n", m.variant.environment_metrics.relative_humidity); m.variant.environment_metrics.relative_humidity,
DEBUG_MSG("Telemetry->temperature: %f\n", m.variant.environment_metrics.temperature); m.variant.environment_metrics.temperature,
DEBUG_MSG("Telemetry->voltage: %f\n", m.variant.environment_metrics.voltage); m.variant.environment_metrics.voltage);
sensor_read_error_count = 0; sensor_read_error_count = 0;
MeshPacket *p = allocDataProtobuf(m); MeshPacket *p = allocDataProtobuf(m);
p->to = dest; p->to = dest;
p->decoded.want_response = wantReplies; p->decoded.want_response = false;
p->priority = MeshPacket_Priority_MIN;
lastMeasurementPacket = packetPool.allocCopy(*p); lastMeasurementPacket = packetPool.allocCopy(*p);
DEBUG_MSG("Environment Telemetry: Sending packet to mesh"); if (phoneOnly) {
service.sendToMesh(p, RX_SRC_LOCAL, true); DEBUG_MSG("Sending packet to phone\n");
service.sendToPhone(p);
} else {
DEBUG_MSG("Sending packet to mesh\n");
service.sendToMesh(p, RX_SRC_LOCAL, true);
}
return true; return true;
} }

View File

@@ -12,7 +12,8 @@ class EnvironmentTelemetryModule : private concurrency::OSThread, public Protobu
: concurrency::OSThread("EnvironmentTelemetryModule"), : concurrency::OSThread("EnvironmentTelemetryModule"),
ProtobufModule("EnvironmentTelemetry", PortNum_TELEMETRY_APP, &Telemetry_msg) ProtobufModule("EnvironmentTelemetry", PortNum_TELEMETRY_APP, &Telemetry_msg)
{ {
lastMeasurementPacket = nullptr; lastMeasurementPacket = nullptr;
setIntervalFromNow(10 * 1000);
} }
virtual bool wantUIFrame() override; virtual bool wantUIFrame() override;
#if !HAS_SCREEN #if !HAS_SCREEN
@@ -30,11 +31,13 @@ class EnvironmentTelemetryModule : private concurrency::OSThread, public Protobu
/** /**
* Send our Telemetry into the mesh * Send our Telemetry into the mesh
*/ */
bool sendOurTelemetry(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false); bool sendTelemetry(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
private: private:
float CelsiusToFahrenheit(float c); float CelsiusToFahrenheit(float c);
bool firstTime = 1; bool firstTime = 1;
const MeshPacket *lastMeasurementPacket; const MeshPacket *lastMeasurementPacket;
uint32_t sendToPhoneIntervalMs = SECONDS_IN_MINUTE * 1000; // Send to phone every minute
uint32_t lastSentToMesh = 0;
uint32_t sensor_read_error_count = 0; uint32_t sensor_read_error_count = 0;
}; };

View File

@@ -0,0 +1,36 @@
#include "../mesh/generated/telemetry.pb.h"
#include "configuration.h"
#include "TelemetrySensor.h"
#include "LPS22HBSensor.h"
#include <Adafruit_LPS2X.h>
#include <Adafruit_Sensor.h>
LPS22HBSensor::LPS22HBSensor() :
TelemetrySensor(TelemetrySensorType_LPS22, "LPS22HB")
{
}
int32_t LPS22HBSensor::runOnce() {
DEBUG_MSG("Init sensor: %s\n", sensorName);
if (!hasSensor()) {
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
status = lps22hb.begin_I2C(nodeTelemetrySensorsMap[sensorType]);
return initI2CSensor();
}
void LPS22HBSensor::setup()
{
lps22hb.setDataRate(LPS22_RATE_10_HZ);
}
bool LPS22HBSensor::getMetrics(Telemetry *measurement) {
sensors_event_t temp;
sensors_event_t pressure;
lps22hb.getEvent(&pressure, &temp);
measurement->variant.environment_metrics.temperature = temp.temperature;
measurement->variant.environment_metrics.barometric_pressure = pressure.pressure;
return true;
}

View File

@@ -0,0 +1,17 @@
#include "../mesh/generated/telemetry.pb.h"
#include "TelemetrySensor.h"
#include <Adafruit_LPS2X.h>
#include <Adafruit_Sensor.h>
class LPS22HBSensor : virtual public TelemetrySensor {
private:
Adafruit_LPS22 lps22hb;
protected:
virtual void setup() override;
public:
LPS22HBSensor();
virtual int32_t runOnce() override;
virtual bool getMetrics(Telemetry *measurement) override;
};

View File

@@ -0,0 +1,34 @@
#include "../mesh/generated/telemetry.pb.h"
#include "configuration.h"
#include "TelemetrySensor.h"
#include "SHTC3Sensor.h"
#include <Adafruit_SHTC3.h>
SHTC3Sensor::SHTC3Sensor() :
TelemetrySensor(TelemetrySensorType_SHTC3, "SHTC3")
{
}
int32_t SHTC3Sensor::runOnce() {
DEBUG_MSG("Init sensor: %s\n", sensorName);
if (!hasSensor()) {
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
status = shtc3.begin();
return initI2CSensor();
}
void SHTC3Sensor::setup()
{
// Set up oversampling and filter initialization
}
bool SHTC3Sensor::getMetrics(Telemetry *measurement) {
sensors_event_t humidity, temp;
shtc3.getEvent(&humidity, &temp);
measurement->variant.environment_metrics.temperature = temp.temperature;
measurement->variant.environment_metrics.relative_humidity = humidity.relative_humidity;
return true;
}

View File

@@ -0,0 +1,16 @@
#include "../mesh/generated/telemetry.pb.h"
#include "TelemetrySensor.h"
#include <Adafruit_SHTC3.h>
class SHTC3Sensor : virtual public TelemetrySensor {
private:
Adafruit_SHTC3 shtc3 = Adafruit_SHTC3();
protected:
virtual void setup() override;
public:
SHTC3Sensor();
virtual int32_t runOnce() override;
virtual bool getMetrics(Telemetry *measurement) override;
};

View File

@@ -27,8 +27,9 @@ void MQTT::onPublish(char *topic, byte *payload, unsigned int length)
{ {
// parsing ServiceEnvelope // parsing ServiceEnvelope
ServiceEnvelope e = ServiceEnvelope_init_default; ServiceEnvelope e = ServiceEnvelope_init_default;
if (!pb_decode_from_bytes(payload, length, ServiceEnvelope_fields, &e) && moduleConfig.mqtt.json_enabled) {
// check if this is a json payload message if (moduleConfig.mqtt.json_enabled && (strncmp(topic, jsonTopic.c_str(), jsonTopic.length()) == 0)) {
// check if this is a json payload message by comparing the topic start
using namespace json11; using namespace json11;
char payloadStr[length + 1]; char payloadStr[length + 1];
memcpy(payloadStr, payload, length); memcpy(payloadStr, payload, length);
@@ -36,36 +37,37 @@ void MQTT::onPublish(char *topic, byte *payload, unsigned int length)
std::string err; std::string err;
auto json = Json::parse(payloadStr, err); auto json = Json::parse(payloadStr, err);
if (err.empty()) { if (err.empty()) {
DEBUG_MSG("Received json payload on MQTT, parsing..\n"); DEBUG_MSG("JSON Received on MQTT, parsing..\n");
// check if it is a valid envelope // check if it is a valid envelope
if (json.object_items().count("sender") != 0 && json.object_items().count("payload") != 0) { if (json.object_items().count("sender") != 0 && json.object_items().count("payload") != 0 && json["type"].string_value().compare("sendtext") == 0) {
// this is a valid envelope // this is a valid envelope
if (json["sender"].string_value().compare(owner.id) != 0) { if (json["sender"].string_value().compare(owner.id) != 0) {
std::string jsonPayloadStr = json["payload"].dump(); std::string jsonPayloadStr = json["payload"].dump();
DEBUG_MSG("Received json payload %s, length %u\n", jsonPayloadStr.c_str(), jsonPayloadStr.length()); DEBUG_MSG("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 // construct protobuf data packet using TEXT_MESSAGE, send it to the mesh
// MeshPacket *p = router->allocForSending(); MeshPacket *p = router->allocForSending();
// p->decoded.portnum = PortNum_TEXT_MESSAGE_APP; p->decoded.portnum = PortNum_TEXT_MESSAGE_APP;
// if (jsonPayloadStr.length() <= sizeof(p->decoded.payload.bytes)) { if (jsonPayloadStr.length() <= sizeof(p->decoded.payload.bytes)) {
// memcpy(p->decoded.payload.bytes, jsonPayloadStr.c_str(), jsonPayloadStr.length()); memcpy(p->decoded.payload.bytes, jsonPayloadStr.c_str(), jsonPayloadStr.length());
// p->decoded.payload.size = jsonPayloadStr.length(); p->decoded.payload.size = jsonPayloadStr.length();
// MeshPacket *packet = packetPool.allocCopy(*p); MeshPacket *packet = packetPool.allocCopy(*p);
// service.sendToMesh(packet, RX_SRC_LOCAL); service.sendToMesh(packet, RX_SRC_LOCAL);
// } else { } else {
// DEBUG_MSG("Received MQTT json payload too long, dropping\n"); DEBUG_MSG("Received MQTT json payload too long, dropping\n");
// } }
} else { } else {
DEBUG_MSG("Ignoring downlink message we originally sent.\n"); DEBUG_MSG("JSON Ignoring downlink message we originally sent.\n");
} }
} else { } else {
DEBUG_MSG("Received json payload on MQTT but not a valid envelope\n"); DEBUG_MSG("JSON Received payload on MQTT but not a valid envelope\n");
} }
} else { } else {
// no json, this is an invalid payload // no json, this is an invalid payload
DEBUG_MSG("Invalid MQTT service envelope, topic %s, len %u!\n", topic, length); DEBUG_MSG("Invalid MQTT service envelope, topic %s, len %u!\n", topic, length);
} }
} else { } else {
pb_decode_from_bytes(payload, length, ServiceEnvelope_fields, &e);
if (strcmp(e.gateway_id, owner.id) == 0) if (strcmp(e.gateway_id, owner.id) == 0)
DEBUG_MSG("Ignoring downlink message we originally sent.\n"); DEBUG_MSG("Ignoring downlink message we originally sent.\n");
else { else {
@@ -243,7 +245,7 @@ void MQTT::onSend(const MeshPacket &mp, ChannelIndex chIndex)
auto jsonString = this->downstreamPacketToJson((MeshPacket *)&mp); auto jsonString = this->downstreamPacketToJson((MeshPacket *)&mp);
if (jsonString.length() != 0) { if (jsonString.length() != 0) {
String topicJson = jsonTopic + channelId + "/" + owner.id; 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()); DEBUG_MSG("JSON publish message to %s, %u bytes: %s\n", topicJson.c_str(), jsonString.length(), jsonString.c_str());
pubSub.publish(topicJson.c_str(), jsonString.c_str(), false); pubSub.publish(topicJson.c_str(), jsonString.c_str(), false);
} }
} }
@@ -251,7 +253,7 @@ void MQTT::onSend(const MeshPacket &mp, ChannelIndex chIndex)
} }
// converts a downstream packet into a json message // converts a downstream packet into a json message
String MQTT::downstreamPacketToJson(MeshPacket *mp) std::string MQTT::downstreamPacketToJson(MeshPacket *mp)
{ {
using namespace json11; using namespace json11;
@@ -279,7 +281,7 @@ String MQTT::downstreamPacketToJson(MeshPacket *mp)
// if it isn't, then we need to create a json object // if it isn't, then we need to create a json object
// with the string as the value // with the string as the value
DEBUG_MSG("text message payload is of type plaintext\n"); DEBUG_MSG("text message payload is of type plaintext\n");
msgPayload = Json::object({{"text", payloadStr}}); msgPayload = Json::object{{"text", payloadStr}};
} }
break; break;
} }
@@ -396,8 +398,8 @@ String MQTT::downstreamPacketToJson(MeshPacket *mp)
}; };
// serialize and return it // serialize and return it
static std::string jsonStr = jsonObj.dump(); std::string jsonStr = jsonObj.dump();
DEBUG_MSG("serialized json message: %s\n", jsonStr.c_str()); DEBUG_MSG("serialized json message: %s\n", jsonStr.c_str());
return jsonStr.c_str(); return jsonStr;
} }

View File

@@ -58,7 +58,7 @@ class MQTT : private concurrency::OSThread
void onPublish(char *topic, byte *payload, unsigned int length); void onPublish(char *topic, byte *payload, unsigned int length);
/// Called when a new publish arrives from the MQTT server /// Called when a new publish arrives from the MQTT server
String downstreamPacketToJson(MeshPacket *mp); std::string downstreamPacketToJson(MeshPacket *mp);
/// Return 0 if sleep is okay, veto sleep if we are connected to pubsub server /// Return 0 if sleep is okay, veto sleep if we are connected to pubsub server
// int preflightSleepCb(void *unused = NULL) { return pubSub.connected() ? 1 : 0; } // int preflightSleepCb(void *unused = NULL) { return pubSub.connected() ? 1 : 0; }

View File

@@ -59,7 +59,7 @@ static const uint8_t SCK = 33;
// https://docs.rakwireless.com/Product-Categories/WisBlock/RAK13300/ // https://docs.rakwireless.com/Product-Categories/WisBlock/RAK13300/
#define LORA_DIO0 26 // a No connect on the SX1262/SX1268 module #define LORA_DIO0 -1 // a No connect on the SX1262/SX1268 module
#define LORA_RESET WB_IO4 // RST for SX1276, and for SX1262/SX1268 #define LORA_RESET WB_IO4 // RST for SX1276, and for SX1262/SX1268
#define LORA_DIO1 WB_IO6 // IRQ for SX1262/SX1268 #define LORA_DIO1 WB_IO6 // IRQ for SX1262/SX1268
#define LORA_DIO2 WB_IO5 // BUSY for SX1262/SX1268 #define LORA_DIO2 WB_IO5 // BUSY for SX1262/SX1268

View File

@@ -1,12 +1,12 @@
[env:pico] [env:pico]
extends = rp2040_base extends = rp2040_base
board = pico board = rpipico
upload_protocol = picotool upload_protocol = picotool
# add our variants files to the include and src paths # add our variants files to the include and src paths
build_flags = ${rp2040_base.build_flags} build_flags = ${rp2040_base.build_flags}
-DPRIVATE_HW -DPRIVATE_HW
-Ivariants/pico -Ivariants/rpipico
-DARDUINO_AVR_NANO_EVERY -DARDUINO_AVR_NANO_EVERY
-DDEBUG_RP2040_WIRE -DDEBUG_RP2040_WIRE
-DDEBUG_RP2040_SPI -DDEBUG_RP2040_SPI

View File

@@ -0,0 +1,17 @@
[env:picow]
extends = rp2040_base
board = rpipicow
upload_protocol = picotool
# add our variants files to the include and src paths
build_flags = ${rp2040_base.build_flags}
-DPRIVATE_HW
-Ivariants/rpipicow
-DARDUINO_AVR_NANO_EVERY
-DDEBUG_RP2040_WIRE
-DDEBUG_RP2040_SPI
-DDEBUG_RP2040_CORE
-DDEBUG_RP2040_PORT=Serial
-DUSE_TINYUSB
lib_deps =
${rp2040_base.lib_deps}

View File

@@ -0,0 +1,52 @@
// #define RADIOLIB_CUSTOM_ARDUINO 1
// #define RADIOLIB_TONE_UNSUPPORTED 1
// #define RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED 1
#define ARDUINO_ARCH_AVR
#define CBC 0
#define CTR 1
#define ECB 0
#define NO_GPS 1
#define USE_SH1106 1
#undef GPS_SERIAL_NUM
// #define I2C_SDA 6
// #define I2C_SCL 7
#define BUTTON_PIN 17
#define EXT_NOTIFY_OUT 4
#define BATTERY_PIN 26
// ratio of voltage divider = 3.0 (R17=200k, R18=100k)
#define ADC_MULTIPLIER 3.1 // 3.0 + a bit for being optimistic
#define USE_RF95
#define USE_SX1262
#undef RF95_SCK
#undef RF95_MISO
#undef RF95_MOSI
#undef RF95_NSS
#define RF95_SCK 10
#define RF95_MISO 12
#define RF95_MOSI 11
#define RF95_NSS 3
#define LORA_DIO0 RADIOLIB_NC
#define LORA_RESET 15
#define LORA_DIO1 20
#define LORA_DIO2 2
#define LORA_DIO3 RADIOLIB_NC
#ifdef USE_SX1262
#define SX126X_CS RF95_NSS
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_E22
#endif
#include <Adafruit_TinyUSB.h>

View File

@@ -1,4 +1,4 @@
[VERSION] [VERSION]
major = 1 major = 1
minor = 3 minor = 3
build = 43 build = 46