mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-15 23:32:34 +00:00
Compare commits
213 Commits
v2.0.18.1a
...
v2.1.6.567
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5679a82195 | ||
|
|
2edc35d34b | ||
|
|
26d18244f0 | ||
|
|
82ba59765c | ||
|
|
7930aa1635 | ||
|
|
c55751964e | ||
|
|
b9b1cce6a5 | ||
|
|
044ef75fef | ||
|
|
9f940139a0 | ||
|
|
fdb09d4fba | ||
|
|
1968f3c45b | ||
|
|
790df42987 | ||
|
|
9a9279dd78 | ||
|
|
1e54a5d45c | ||
|
|
23272daffe | ||
|
|
1af7e48136 | ||
|
|
eda00b7b9c | ||
|
|
1898fe850e | ||
|
|
15dbe5da97 | ||
|
|
8f736c8ecc | ||
|
|
8a81f190b8 | ||
|
|
1425657a3c | ||
|
|
02041cb605 | ||
|
|
1f130d671b | ||
|
|
d62e56f428 | ||
|
|
5ac24bb33b | ||
|
|
2c259b8464 | ||
|
|
9d6e1ce8e5 | ||
|
|
958d2cf630 | ||
|
|
5cb1f96240 | ||
|
|
78522e750c | ||
|
|
75db8c2d2e | ||
|
|
91be22b341 | ||
|
|
36b00dba86 | ||
|
|
8c68d888c8 | ||
|
|
1f99d4756a | ||
|
|
7bbfa48b5d | ||
|
|
b398f31b64 | ||
|
|
e03a2f8f7f | ||
|
|
d92a003d8e | ||
|
|
3c2e615650 | ||
|
|
6d202158ba | ||
|
|
c288974b67 | ||
|
|
9b1d461567 | ||
|
|
210e3e09d5 | ||
|
|
0d001423c8 | ||
|
|
a83d5ada86 | ||
|
|
4573db4665 | ||
|
|
c9686d2f62 | ||
|
|
634251834f | ||
|
|
6d443d2c67 | ||
|
|
9cadc0a16f | ||
|
|
dc2ca9c32b | ||
|
|
fddc49273e | ||
|
|
e737a22120 | ||
|
|
a8f2e3ddbd | ||
|
|
67be6aa53b | ||
|
|
68e17ab905 | ||
|
|
a56403987b | ||
|
|
7acacb3bba | ||
|
|
e6d69e2b67 | ||
|
|
9150c2e568 | ||
|
|
944d5066e9 | ||
|
|
a538a96c90 | ||
|
|
31ef82557f | ||
|
|
9d440b7dba | ||
|
|
267db05d69 | ||
|
|
20bcf310d1 | ||
|
|
331a1afc37 | ||
|
|
321e41a3aa | ||
|
|
3ca1e62b1f | ||
|
|
5044169e8d | ||
|
|
8e197fc35b | ||
|
|
f63505038f | ||
|
|
a95b6aff01 | ||
|
|
b249970a12 | ||
|
|
fe926eedba | ||
|
|
4a0dfb5401 | ||
|
|
4355f51a90 | ||
|
|
ecd67f0a85 | ||
|
|
0940c6462b | ||
|
|
eb4ab26e1f | ||
|
|
8c059a8a9e | ||
|
|
7bb281d5c5 | ||
|
|
214feb1f21 | ||
|
|
d17aafa91a | ||
|
|
2fe5eae183 | ||
|
|
9008c75517 | ||
|
|
408c555f0f | ||
|
|
c9ae90f03c | ||
|
|
fbfd0f12b5 | ||
|
|
9650adb616 | ||
|
|
a3f1e53017 | ||
|
|
0243922d64 | ||
|
|
baeb2807a4 | ||
|
|
9a8bfa113d | ||
|
|
82b14fe07c | ||
|
|
fab5e4c5cc | ||
|
|
46fa08dc33 | ||
|
|
05b1fc83bd | ||
|
|
9fc18c2a19 | ||
|
|
d830398fc5 | ||
|
|
2e80a4ed87 | ||
|
|
e1924f188f | ||
|
|
732caff2b8 | ||
|
|
c60c00ba85 | ||
|
|
83e6cea280 | ||
|
|
f8498ba03f | ||
|
|
f83adf1796 | ||
|
|
73c1c5913b | ||
|
|
fd1c54fd15 | ||
|
|
95bbcd2cb7 | ||
|
|
187f3969c2 | ||
|
|
15458309f8 | ||
|
|
253d133319 | ||
|
|
7264621149 | ||
|
|
27d93c5f66 | ||
|
|
b33632f21a | ||
|
|
89f06d6b40 | ||
|
|
7102fec7b3 | ||
|
|
c39645419a | ||
|
|
6f4ac904a5 | ||
|
|
643237162e | ||
|
|
cef11968eb | ||
|
|
5c72967aa5 | ||
|
|
8aede61adb | ||
|
|
07b90a61e1 | ||
|
|
221a145d2d | ||
|
|
b3fac71a8d | ||
|
|
2e6e0644d4 | ||
|
|
b78e0dce46 | ||
|
|
3ae1fdf661 | ||
|
|
cbfa2dcc0e | ||
|
|
2aabeafefe | ||
|
|
b7895f7038 | ||
|
|
3f4780479f | ||
|
|
5ca3d9169a | ||
|
|
c834252f1c | ||
|
|
16852da8d4 | ||
|
|
2d2633d4cf | ||
|
|
5f28ef6814 | ||
|
|
5cadcd355f | ||
|
|
40d98b9d8d | ||
|
|
0f47584a50 | ||
|
|
dbb827e5e0 | ||
|
|
f95061b965 | ||
|
|
4061870841 | ||
|
|
abf3a5840b | ||
|
|
7063acdda6 | ||
|
|
97c1cf628a | ||
|
|
03f584a5ab | ||
|
|
680550b76c | ||
|
|
a280d7f796 | ||
|
|
09f2ea8938 | ||
|
|
fcbeeac28f | ||
|
|
7100416142 | ||
|
|
83e309f3bf | ||
|
|
dc6f6af7fb | ||
|
|
aaba99f792 | ||
|
|
4375a0101e | ||
|
|
b1677e0312 | ||
|
|
0c240a1dff | ||
|
|
b24376b1fc | ||
|
|
bcaf834853 | ||
|
|
1c3970efab | ||
|
|
79850c6d03 | ||
|
|
440074af62 | ||
|
|
dc23096723 | ||
|
|
3209aeabb8 | ||
|
|
42b496b0db | ||
|
|
a5b99ee5d5 | ||
|
|
4a0c341438 | ||
|
|
afc75b2552 | ||
|
|
9522d4d2f5 | ||
|
|
7ddd8c9930 | ||
|
|
23e1c0b7a8 | ||
|
|
631699bfd7 | ||
|
|
4ac0de21ab | ||
|
|
4ede8ab9de | ||
|
|
b952c35da6 | ||
|
|
a3dbac73fe | ||
|
|
fb611ef986 | ||
|
|
b07904fe77 | ||
|
|
9e1f7c4f56 | ||
|
|
af11c5aa80 | ||
|
|
829318046a | ||
|
|
405430fd96 | ||
|
|
8630e420a7 | ||
|
|
b70af5cc78 | ||
|
|
b9516154d4 | ||
|
|
21443dab05 | ||
|
|
1748db3160 | ||
|
|
d83a0b1818 | ||
|
|
18442816ef | ||
|
|
c28d469fc6 | ||
|
|
d97a09ba1f | ||
|
|
22500a6c34 | ||
|
|
bba4de3ec7 | ||
|
|
8734afa7be | ||
|
|
5b75abc6f7 | ||
|
|
e4d455640f | ||
|
|
090d399843 | ||
|
|
d34f6d0f68 | ||
|
|
1f0e64e794 | ||
|
|
e1914dd464 | ||
|
|
661894f9f9 | ||
|
|
104ffe36b2 | ||
|
|
8984989412 | ||
|
|
db729eb707 | ||
|
|
ff029ad752 | ||
|
|
202223236d | ||
|
|
fdf7c3a812 | ||
|
|
f86eef66c8 |
2
.github/ISSUE_TEMPLATE/Bug Report.yml
vendored
2
.github/ISSUE_TEMPLATE/Bug Report.yml
vendored
@@ -32,6 +32,7 @@ body:
|
||||
options:
|
||||
- Not Applicable
|
||||
- T-Beam
|
||||
- T-Beam S3
|
||||
- T-Beam 0.7
|
||||
- T-Lora v1
|
||||
- T-Lora v1.3
|
||||
@@ -42,6 +43,7 @@ body:
|
||||
- Heltec v1
|
||||
- Heltec v2
|
||||
- Heltec v2.1
|
||||
- Heltec V3
|
||||
- Relay v1
|
||||
- Relay v2
|
||||
- DIY
|
||||
|
||||
59
.github/workflows/build_esp32_s3.yml
vendored
Normal file
59
.github/workflows/build_esp32_s3.yml
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
name: Build ESP32-S3
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
board:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build-esp32-s3:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build base
|
||||
id: base
|
||||
uses: ./.github/actions/setup-base
|
||||
|
||||
- name: Pull web ui
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
with:
|
||||
repo: "meshtastic/web"
|
||||
file: "build.tar"
|
||||
target: "build.tar"
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Unpack web ui
|
||||
run: |
|
||||
tar -xf build.tar -C data/static
|
||||
rm build.tar
|
||||
- name: Remove debug flags for release
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
run: |
|
||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32.ini
|
||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s2.ini
|
||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s3.ini
|
||||
- name: Build ESP32
|
||||
run: bin/build-esp32.sh ${{ inputs.board }}
|
||||
|
||||
- name: Pull OTA Firmware
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
with:
|
||||
repo: "meshtastic/firmware-ota"
|
||||
file: "firmware-s3.bin"
|
||||
target: "release/bleota-s3.bin"
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get release version string
|
||||
shell: bash
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
||||
path: |
|
||||
release/*.bin
|
||||
release/*.elf
|
||||
40
.github/workflows/main_matrix.yml
vendored
40
.github/workflows/main_matrix.yml
vendored
@@ -62,8 +62,6 @@ jobs:
|
||||
- board: heltec-v1
|
||||
- board: heltec-v2.0
|
||||
- board: heltec-v2.1
|
||||
- board: heltec-v3
|
||||
- board: heltec-wsl-v3
|
||||
- board: tbeam0.7
|
||||
- board: meshtastic-diy-v1
|
||||
- board: meshtastic-dr-dev
|
||||
@@ -71,9 +69,21 @@ jobs:
|
||||
- board: station-g1
|
||||
- board: m5stack-core
|
||||
- board: m5stack-coreink
|
||||
- board: nano-g1-explorer
|
||||
uses: ./.github/workflows/build_esp32.yml
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
|
||||
build-esp32-s3:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- board: heltec-v3
|
||||
- board: heltec-wsl-v3
|
||||
- board: tbeam-s3-core
|
||||
- board: tlora-t3s3-v1
|
||||
uses: ./.github/workflows/build_esp32.yml
|
||||
uses: ./.github/workflows/build_esp32_s3.yml
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
|
||||
@@ -92,16 +102,16 @@ jobs:
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
|
||||
build-rpi2040:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 2
|
||||
matrix:
|
||||
include:
|
||||
- board: pico
|
||||
uses: ./.github/workflows/build_rpi2040.yml
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
# build-rpi2040:
|
||||
# strategy:
|
||||
# fail-fast: false
|
||||
# max-parallel: 2
|
||||
# matrix:
|
||||
# include:
|
||||
# - board: pico
|
||||
# uses: ./.github/workflows/build_rpi2040.yml
|
||||
# with:
|
||||
# board: ${{ matrix.board }}
|
||||
|
||||
build-native:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -175,7 +185,7 @@ jobs:
|
||||
|
||||
gather-artifacts:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-esp32, build-nrf52, build-native, build-rpi2040]
|
||||
needs: [build-esp32, build-esp32-s3, build-nrf52, build-native] #, build-rpi2040]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
@@ -192,7 +202,7 @@ jobs:
|
||||
id: version
|
||||
|
||||
- name: Move files up
|
||||
run: mv -b -t ./ ./*tbeam-2*/littlefs*.bin ./*tbeam-2*/bleota.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./*native*/*device-*.sh ./*native*/*device-*.bat
|
||||
run: mv -b -t ./ ./*tbeam-2*/littlefs*.bin ./*tbeam-2*/bleota.bin ./*tbeam-s3*/bleota-s3.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./*native*/*device-*.sh ./*native*/*device-*.bat
|
||||
|
||||
- name: Repackage in single firmware zip
|
||||
uses: actions/upload-artifact@v3
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
; Common settings for ESP targes, mixin with extends = esp32_base
|
||||
[esp32_base]
|
||||
extends = arduino_base
|
||||
platform = platformio/espressif32@^5.2.0
|
||||
platform = platformio/espressif32@^6.1.0
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/>
|
||||
upload_speed = 921600
|
||||
@@ -26,7 +26,7 @@ build_flags =
|
||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
|
||||
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20
|
||||
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
|
||||
-DDEBUG_HEAP
|
||||
;-DDEBUG_HEAP
|
||||
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
|
||||
45
arch/esp32/esp32c3.ini
Normal file
45
arch/esp32/esp32c3.ini
Normal file
@@ -0,0 +1,45 @@
|
||||
[esp32c3_base]
|
||||
extends = arduino_base
|
||||
platform = platformio/espressif32@^6.1.0
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/>
|
||||
upload_speed = 961200
|
||||
monitor_speed = 115200
|
||||
debug_init_break = tbreak setup
|
||||
monitor_filters = esp32_c3_exception_decoder
|
||||
board_build.filesystem = littlefs
|
||||
|
||||
# Remove -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL for low level BLE logging.
|
||||
# See library directory for BLE logging possible values: .pio/libdeps/tbeam/NimBLE-Arduino/src/log_common/log_common.h
|
||||
# This overrides the BLE logging default of LOG_LEVEL_INFO (1) from: .pio/libdeps/tbeam/NimBLE-Arduino/src/esp_nimble_cfg.h
|
||||
build_flags =
|
||||
${arduino_base.build_flags}
|
||||
-Wall
|
||||
-Wextra
|
||||
-Isrc/platform/esp32
|
||||
-std=c++11
|
||||
-DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG
|
||||
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||
-DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL
|
||||
-DCONFIG_BT_NIMBLE_ENABLED
|
||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
|
||||
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20
|
||||
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
|
||||
;-DDEBUG_HEAP
|
||||
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
|
||||
h2zero/NimBLE-Arduino@^1.4.0
|
||||
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
|
||||
caveman99/ESP32 Codec2@^1.0.1
|
||||
|
||||
lib_ignore =
|
||||
segger_rtt
|
||||
ESP32 BLE Arduino
|
||||
|
||||
; customize the partition table
|
||||
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
|
||||
board_build.partitions = partition-table.csv
|
||||
@@ -1,6 +1,6 @@
|
||||
[esp32s2_base]
|
||||
extends = arduino_base
|
||||
platform = platformio/espressif32@^5.2.0
|
||||
platform = platformio/espressif32@^6.1.0
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/> -<nimble/>
|
||||
upload_speed = 961200
|
||||
@@ -27,7 +27,7 @@ build_flags =
|
||||
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20
|
||||
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
|
||||
-DHAS_BLUETOOTH=0
|
||||
-DDEBUG_HEAP
|
||||
;-DDEBUG_HEAP
|
||||
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[esp32s3_base]
|
||||
extends = arduino_base
|
||||
platform = platformio/espressif32@^5.2.0
|
||||
platform = platformio/espressif32@^6.1.0
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/>
|
||||
upload_speed = 961200
|
||||
@@ -26,7 +26,7 @@ build_flags =
|
||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
|
||||
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20
|
||||
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
|
||||
-DDEBUG_HEAP
|
||||
;-DDEBUG_HEAP
|
||||
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[nrf52_base]
|
||||
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
|
||||
platform = platformio/nordicnrf52@^9.4.0
|
||||
platform = platformio/nordicnrf52@^9.5.0
|
||||
|
||||
extends = arduino_base
|
||||
build_type = debug ; I'm debugging with ICE a lot now
|
||||
|
||||
@@ -12,10 +12,12 @@ build_src_filter =
|
||||
-<mesh/http/>
|
||||
-<mesh/eth/>
|
||||
-<modules/esp32>
|
||||
-<modules/Telemetry>
|
||||
-<modules/Telemetry/EnvironmentTelemetry.cpp>
|
||||
-<modules/Telemetry/AirQualityTelemetry.cpp>
|
||||
-<modules/Telemetry/Sensor>
|
||||
+<../variants/portduino>
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
rweather/Crypto@^0.4.0
|
||||
build_flags = ${arduino_base.build_flags} -Isrc/platform/portduino
|
||||
build_flags = ${arduino_base.build_flags} -fPIC -Isrc/platform/portduino
|
||||
|
||||
@@ -34,7 +34,7 @@ SRCBIN=.pio/build/$1/firmware.bin
|
||||
cp $SRCBIN $OUTDIR/$basename-update.bin
|
||||
|
||||
echo "Building Filesystem for ESP32 targets"
|
||||
pio run --environment tbeam -t buildfs
|
||||
cp .pio/build/tbeam/littlefs.bin $OUTDIR/littlefs-$VERSION.bin
|
||||
pio run --environment $1 -t buildfs
|
||||
cp .pio/build/$1/littlefs.bin $OUTDIR/littlefs-$VERSION.bin
|
||||
cp bin/device-install.* $OUTDIR
|
||||
cp bin/device-update.* $OUTDIR
|
||||
|
||||
@@ -30,7 +30,13 @@ IF EXIST %FILENAME% IF x%FILENAME:update=%==x%FILENAME% (
|
||||
echo Trying to flash update %FILENAME%, but first erasing and writing system information"
|
||||
%PYTHON% -m esptool --baud 115200 erase_flash
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME%
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota.bin
|
||||
|
||||
@REM Account for S3 board's different OTA partition
|
||||
IF x%FILENAME:s3=%==x%FILENAME% IF x%FILENAME:v3=%==x%FILENAME% (
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota.bin
|
||||
) else (
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota-s3.bin
|
||||
)
|
||||
for %%f in (littlefs-*.bin) do (
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x300000 %%f
|
||||
)
|
||||
|
||||
@@ -49,7 +49,12 @@ if [ -f "${FILENAME}" ] && [ ! -z "${FILENAME##*"update"*}" ]; then
|
||||
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
|
||||
"$PYTHON" -m esptool erase_flash
|
||||
"$PYTHON" -m esptool write_flash 0x00 ${FILENAME}
|
||||
"$PYTHON" -m esptool write_flash 0x260000 bleota.bin
|
||||
# Account for S3 board's different OTA partition
|
||||
if [ ! -z "${FILENAME##*"s3"*}" ] && [ ! -z "${FILENAME##*"-v3"*}" ]; then
|
||||
"$PYTHON" -m esptool write_flash 0x260000 bleota.bin
|
||||
else
|
||||
"$PYTHON" -m esptool write_flash 0x260000 bleota-s3.bin
|
||||
fi
|
||||
"$PYTHON" -m esptool write_flash 0x300000 littlefs-*.bin
|
||||
|
||||
else
|
||||
|
||||
@@ -8,7 +8,7 @@ echo "prebuilt binaries for your computer into nanopb-0.4.7"
|
||||
|
||||
# the nanopb tool seems to require that the .options file be in the current directory!
|
||||
cd protobufs
|
||||
../nanopb-0.4.7/generator-bin/protoc --nanopb_out=-v:../src/mesh/generated/ -I=../protobufs meshtastic/*.proto
|
||||
../nanopb-0.4.7/generator-bin/protoc --nanopb_out=-v:../src/mesh/generated/ -I=../protobufs meshtastic/*.proto --experimental_allow_proto3_optional
|
||||
|
||||
# cd ../src/mesh/generated/meshtastic
|
||||
# sed -i 's/#include "meshtastic/#include "./g' -- *
|
||||
|
||||
41
boards/my-esp32s3-diy-oled.json
Normal file
41
boards/my-esp32s3-diy-oled.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "esp32s3_out.ld",
|
||||
"memory_type": "qio_opi"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": [
|
||||
"-DBOARD_HAS_PSRAM",
|
||||
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||
"-DARDUINO_USB_MODE=0",
|
||||
"-DARDUINO_RUNNING_CORE=1",
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=0"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "qio",
|
||||
"hwids": [["0x303A", "0x1001"]],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "my-esp32s3-diy-oled"
|
||||
},
|
||||
"connectivity": ["wifi"],
|
||||
"debug": {
|
||||
"default_tool": "esp-builtin",
|
||||
"onboard_tools": ["esp-builtin"],
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": ["arduino", "espidf"],
|
||||
"name": "Clone ESP32-S3-DevKitC-1 v1.1 (16 MB FLASH, 8 MB PSRAM)",
|
||||
"upload": {
|
||||
"flash_size": "16MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 16777216,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 921600
|
||||
},
|
||||
"url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1.html",
|
||||
"vendor": "Espressif"
|
||||
}
|
||||
41
boards/my_esp32s3_diy_eink.json
Normal file
41
boards/my_esp32s3_diy_eink.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "esp32s3_out.ld",
|
||||
"memory_type": "qio_opi"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": [
|
||||
"-DBOARD_HAS_PSRAM",
|
||||
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||
"-DARDUINO_USB_MODE=0",
|
||||
"-DARDUINO_RUNNING_CORE=1",
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=0"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "qio",
|
||||
"hwids": [["0x303A", "0x1001"]],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "my_esp32s3_diy_eink"
|
||||
},
|
||||
"connectivity": ["wifi"],
|
||||
"debug": {
|
||||
"default_tool": "esp-builtin",
|
||||
"onboard_tools": ["esp-builtin"],
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": ["arduino", "espidf"],
|
||||
"name": "Clone ESP32-S3-DevKitC-1 v1.1 (16 MB FLASH, 8 MB PSRAM)",
|
||||
"upload": {
|
||||
"flash_size": "16MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 16777216,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 921600
|
||||
},
|
||||
"url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1.html",
|
||||
"vendor": "Espressif"
|
||||
}
|
||||
@@ -9,12 +9,13 @@
|
||||
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||
"-DARDUINO_USB_MODE=0",
|
||||
"-DARDUINO_RUNNING_CORE=1",
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=1",
|
||||
"-DBOARD_HAS_PSRAM"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "dio",
|
||||
"hwids": [["0X303A", "0x1001"]],
|
||||
"hwids": [["0x303A", "0x1001"]],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "tlora-t3s3-v1"
|
||||
},
|
||||
|
||||
155
monitor/filter_c3_exception_decoder.py
Normal file
155
monitor/filter_c3_exception_decoder.py
Normal file
@@ -0,0 +1,155 @@
|
||||
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from platformio.project.exception import PlatformioException
|
||||
from platformio.public import (
|
||||
DeviceMonitorFilterBase,
|
||||
load_build_metadata,
|
||||
)
|
||||
|
||||
# By design, __init__ is called inside miniterm and we can't pass context to it.
|
||||
# pylint: disable=attribute-defined-outside-init
|
||||
|
||||
IS_WINDOWS = sys.platform.startswith("win")
|
||||
|
||||
|
||||
class Esp32C3ExceptionDecoder(DeviceMonitorFilterBase):
|
||||
NAME = "esp32_c3_exception_decoder"
|
||||
|
||||
PCADDR_PATTERN = re.compile(r'0x4[0-9a-f]{7}', re.IGNORECASE)
|
||||
|
||||
def __call__(self):
|
||||
self.buffer = ""
|
||||
self.pcaddr_re = self.PCADDR_PATTERN
|
||||
|
||||
self.firmware_path = None
|
||||
self.addr2line_path = None
|
||||
self.enabled = self.setup_paths()
|
||||
|
||||
if self.config.get("env:" + self.environment, "build_type") != "debug":
|
||||
print(
|
||||
"""
|
||||
Please build project in debug configuration to get more details about an exception.
|
||||
See https://docs.platformio.org/page/projectconf/build_configurations.html
|
||||
|
||||
"""
|
||||
)
|
||||
|
||||
return self
|
||||
|
||||
def setup_paths(self):
|
||||
self.project_dir = os.path.abspath(self.project_dir)
|
||||
try:
|
||||
data = load_build_metadata(self.project_dir, self.environment)
|
||||
self.firmware_path = data["prog_path"]
|
||||
if not os.path.isfile(self.firmware_path):
|
||||
sys.stderr.write(
|
||||
"%s: disabling, firmware at %s does not exist, rebuild the project?\n"
|
||||
% (self.__class__.__name__, self.firmware_path)
|
||||
)
|
||||
return False
|
||||
|
||||
if self.addr2line_path is None:
|
||||
cc_path = data.get("cc_path", "")
|
||||
if "-gcc" in cc_path:
|
||||
self.addr2line_path = cc_path.replace("-gcc", "-addr2line")
|
||||
else:
|
||||
sys.stderr.write(
|
||||
"%s: disabling, failed to find addr2line.\n"
|
||||
% self.__class__.__name__
|
||||
)
|
||||
return False
|
||||
|
||||
if not os.path.isfile(self.addr2line_path):
|
||||
sys.stderr.write(
|
||||
"%s: disabling, addr2line at %s does not exist\n"
|
||||
% (self.__class__.__name__, self.addr2line_path)
|
||||
)
|
||||
return False
|
||||
|
||||
return True
|
||||
except PlatformioException as e:
|
||||
sys.stderr.write(
|
||||
"%s: disabling, exception while looking for addr2line: %s\n"
|
||||
% (self.__class__.__name__, e)
|
||||
)
|
||||
return False
|
||||
|
||||
def rx(self, text):
|
||||
if not self.enabled:
|
||||
return text
|
||||
|
||||
last = 0
|
||||
while True:
|
||||
idx = text.find("\n", last)
|
||||
if idx == -1:
|
||||
if len(self.buffer) < 4096:
|
||||
self.buffer += text[last:]
|
||||
break
|
||||
|
||||
line = text[last:idx]
|
||||
if self.buffer:
|
||||
line = self.buffer + line
|
||||
self.buffer = ""
|
||||
last = idx + 1
|
||||
|
||||
# Output each trace on a separate line below ours
|
||||
# Logic identical to https://github.com/espressif/esp-idf/blob/master/tools/idf_monitor_base/logger.py#L131
|
||||
for m in re.finditer(self.pcaddr_re, line):
|
||||
if m is None:
|
||||
continue
|
||||
|
||||
trace = self.get_backtrace(m)
|
||||
if len(trace) != "":
|
||||
text = text[: last] + trace + text[last :]
|
||||
last += len(trace)
|
||||
|
||||
return text
|
||||
|
||||
def get_backtrace(self, match):
|
||||
trace = "\n"
|
||||
enc = "mbcs" if IS_WINDOWS else "utf-8"
|
||||
args = [self.addr2line_path, u"-fipC", u"-e", self.firmware_path]
|
||||
try:
|
||||
addr = match.group()
|
||||
output = (
|
||||
subprocess.check_output(args + [addr])
|
||||
.decode(enc)
|
||||
.strip()
|
||||
)
|
||||
output = output.replace(
|
||||
"\n", "\n "
|
||||
) # newlines happen with inlined methods
|
||||
output = self.strip_project_dir(output)
|
||||
# Output the trace in yellow color so that it is easier to spot
|
||||
trace += "\033[33m=> %s: %s\033[0m\n" % (addr, output)
|
||||
except subprocess.CalledProcessError as e:
|
||||
sys.stderr.write(
|
||||
"%s: failed to call %s: %s\n"
|
||||
% (self.__class__.__name__, self.addr2line_path, e)
|
||||
)
|
||||
return trace
|
||||
|
||||
def strip_project_dir(self, trace):
|
||||
while True:
|
||||
idx = trace.find(self.project_dir)
|
||||
if idx == -1:
|
||||
break
|
||||
trace = trace[:idx] + trace[idx + len(self.project_dir) + 1 :]
|
||||
return trace
|
||||
@@ -2,7 +2,7 @@
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
;default_envs = tbeam
|
||||
default_envs = tbeam
|
||||
;default_envs = pico
|
||||
;default_envs = tbeam-s3-core
|
||||
;default_envs = tbeam0.7
|
||||
@@ -13,6 +13,7 @@
|
||||
;default_envs = tlora_v1_3
|
||||
;default_envs = tlora-v2
|
||||
;default_envs = tlora-v2-1-1.6
|
||||
;default_envs = tlora-t3s3-v1
|
||||
;default_envs = lora-relay-v1 # nrf board
|
||||
;default_envs = t-echo
|
||||
;default_envs = nrf52840dk-geeksville
|
||||
@@ -58,15 +59,14 @@ build_flags = -Wno-missing-field-initializers
|
||||
monitor_speed = 115200
|
||||
|
||||
lib_deps =
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git#da1ede4dfcd91074283b029080759fd744120909 ; ESP8266_SSD1306
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git#b38094e03dfa964fbc0e799bc374e91a605c1223 ; ESP8266_SSD1306
|
||||
mathertel/OneButton@^2.0.3 ; OneButton library for non-blocking button debounce
|
||||
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
|
||||
https://github.com/meshtastic/TinyGPSPlus.git#127ad674ef85f0201cb68a065879653ed94792c4
|
||||
https://github.com/meshtastic/ArduinoThread.git#72921ac222eed6f526ba1682023cee290d9aa1b3
|
||||
nanopb/Nanopb@^0.4.6
|
||||
nanopb/Nanopb@^0.4.7
|
||||
erriez/ErriezCRC32@^1.0.1
|
||||
; jgromes/RadioLib@^5.5.1
|
||||
https://github.com/jgromes/RadioLib.git#1afa947030c5637f71f6563bc22aa75032e53a57
|
||||
jgromes/RadioLib@^5.7.0
|
||||
|
||||
; Used for the code analysis in PIO Home / Inspect
|
||||
check_tool = cppcheck
|
||||
@@ -93,13 +93,14 @@ build_src_filter = ${env.build_src_filter} -<platform/portduino/>
|
||||
lib_deps =
|
||||
knolleary/PubSubClient@^2.8
|
||||
arduino-libraries/NTPClient@^3.1.0
|
||||
arcao/Syslog@^2.0.0
|
||||
|
||||
; Common libs for environmental measurements in telemetry module
|
||||
; (not included in native / portduino)
|
||||
[environmental_base]
|
||||
lib_deps =
|
||||
adafruit/Adafruit BusIO@^1.11.4
|
||||
adafruit/Adafruit Unified Sensor@^1.1.4
|
||||
adafruit/Adafruit Unified Sensor@^1.1.9
|
||||
adafruit/Adafruit BMP280 Library@^2.6.6
|
||||
adafruit/Adafruit BME280 Library@^2.2.2
|
||||
adafruit/Adafruit BME680 Library@^2.0.1
|
||||
@@ -109,3 +110,6 @@ lib_deps =
|
||||
adafruit/Adafruit SHTC3 Library@^1.0.0
|
||||
adafruit/Adafruit LPS2X@^2.0.4
|
||||
adafruit/Adafruit SHT31 Library@^2.2.0
|
||||
adafruit/Adafruit PM25 AQI Sensor@^1.0.6
|
||||
adafruit/Adafruit MPU6050@^2.2.4
|
||||
adafruit/Adafruit LIS3DH@^1.2.4
|
||||
|
||||
Submodule protobufs updated: 516074f2e4...ef83ba1d91
92
src/AccelerometerThread.h
Normal file
92
src/AccelerometerThread.h
Normal file
@@ -0,0 +1,92 @@
|
||||
#include "PowerFSM.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
#include "power.h"
|
||||
|
||||
#include <Adafruit_LIS3DH.h>
|
||||
#include <Adafruit_MPU6050.h>
|
||||
|
||||
#define ACCELEROMETER_CHECK_INTERVAL_MS 100
|
||||
#define ACCELEROMETER_CLICK_THRESHOLD 40
|
||||
|
||||
namespace concurrency
|
||||
{
|
||||
class AccelerometerThread : public concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
AccelerometerThread(ScanI2C::DeviceType type = ScanI2C::DeviceType::NONE) : OSThread("AccelerometerThread")
|
||||
{
|
||||
if (accelerometer_found.port == ScanI2C::I2CPort::NO_I2C) {
|
||||
LOG_DEBUG("AccelerometerThread disabling due to no sensors found\n");
|
||||
disable();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!config.display.wake_on_tap_or_motion && !config.device.double_tap_as_button_press) {
|
||||
LOG_DEBUG("AccelerometerThread disabling due to no interested configurations\n");
|
||||
disable();
|
||||
return;
|
||||
}
|
||||
|
||||
accleremoter_type = type;
|
||||
LOG_DEBUG("AccelerometerThread initializing\n");
|
||||
|
||||
if (accleremoter_type == ScanI2C::DeviceType::MPU6050 && mpu.begin(accelerometer_found.address)) {
|
||||
LOG_DEBUG("MPU6050 initializing\n");
|
||||
// setup motion detection
|
||||
mpu.setHighPassFilter(MPU6050_HIGHPASS_0_63_HZ);
|
||||
mpu.setMotionDetectionThreshold(1);
|
||||
mpu.setMotionDetectionDuration(20);
|
||||
mpu.setInterruptPinLatch(true); // Keep it latched. Will turn off when reinitialized.
|
||||
mpu.setInterruptPinPolarity(true);
|
||||
} else if (accleremoter_type == ScanI2C::DeviceType::LIS3DH && lis.begin(accelerometer_found.address)) {
|
||||
LOG_DEBUG("LIS3DH initializing\n");
|
||||
lis.setRange(LIS3DH_RANGE_2_G);
|
||||
// Adjust threshhold, higher numbers are less sensitive
|
||||
lis.setClick(config.device.double_tap_as_button_press ? 2 : 1, ACCELEROMETER_CLICK_THRESHOLD);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
int32_t runOnce() override
|
||||
{
|
||||
canSleep = true; // Assume we should not keep the board awake
|
||||
|
||||
if (accleremoter_type == ScanI2C::DeviceType::MPU6050 && mpu.getMotionInterruptStatus()) {
|
||||
wakeScreen();
|
||||
} else if (accleremoter_type == ScanI2C::DeviceType::LIS3DH && lis.getClick() > 0) {
|
||||
uint8_t click = lis.getClick();
|
||||
if (!config.device.double_tap_as_button_press) {
|
||||
wakeScreen();
|
||||
}
|
||||
|
||||
if (config.device.double_tap_as_button_press && (click & 0x20)) {
|
||||
buttonPress();
|
||||
return 500;
|
||||
}
|
||||
}
|
||||
return ACCELEROMETER_CHECK_INTERVAL_MS;
|
||||
}
|
||||
|
||||
private:
|
||||
void wakeScreen()
|
||||
{
|
||||
if (powerFSM.getState() == &stateDARK) {
|
||||
LOG_INFO("Tap or motion detected. Turning on screen\n");
|
||||
powerFSM.trigger(EVENT_INPUT);
|
||||
}
|
||||
}
|
||||
|
||||
void buttonPress()
|
||||
{
|
||||
LOG_DEBUG("Double-tap detected. Firing button press\n");
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
}
|
||||
|
||||
ScanI2C::DeviceType accleremoter_type;
|
||||
Adafruit_MPU6050 mpu;
|
||||
Adafruit_LIS3DH lis;
|
||||
};
|
||||
|
||||
} // namespace concurrency
|
||||
@@ -123,9 +123,6 @@ class ButtonThread : public concurrency::OSThread
|
||||
static void userButtonPressedLong()
|
||||
{
|
||||
// LOG_DEBUG("Long press!\n");
|
||||
#ifdef ARCH_ESP32
|
||||
screen->adjustBrightness();
|
||||
#endif
|
||||
// If user button is held down for 5 seconds, shutdown the device.
|
||||
if ((millis() - longPressTime > 5 * 1000) && (longPressTime > 0)) {
|
||||
#ifdef HAS_PMU
|
||||
@@ -133,7 +130,7 @@ class ButtonThread : public concurrency::OSThread
|
||||
setLed(false);
|
||||
power->shutdown();
|
||||
}
|
||||
#elif defined(ARCH_NRF52)
|
||||
#elif defined(ARCH_NRF52) || defined(ARCH_ESP32)
|
||||
// Do actual shutdown when button released, otherwise the button release
|
||||
// may wake the board immediatedly.
|
||||
if ((!shutdown_on_long_stop) && (millis() > 30 * 1000)) {
|
||||
|
||||
172
src/DebugConfiguration.cpp
Normal file
172
src/DebugConfiguration.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
/* based on https://github.com/arcao/Syslog
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016 Martin Sloup
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.*/
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#include "DebugConfiguration.h"
|
||||
|
||||
#if HAS_WIFI || HAS_ETHERNET
|
||||
|
||||
Syslog::Syslog(UDP &client)
|
||||
{
|
||||
this->_client = &client;
|
||||
this->_server = NULL;
|
||||
this->_port = 0;
|
||||
this->_deviceHostname = SYSLOG_NILVALUE;
|
||||
this->_appName = SYSLOG_NILVALUE;
|
||||
this->_priDefault = LOGLEVEL_KERN;
|
||||
}
|
||||
|
||||
Syslog &Syslog::server(const char *server, uint16_t port)
|
||||
{
|
||||
if (this->_ip.fromString(server)) {
|
||||
this->_server = NULL;
|
||||
} else {
|
||||
this->_server = server;
|
||||
}
|
||||
this->_port = port;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Syslog &Syslog::server(IPAddress ip, uint16_t port)
|
||||
{
|
||||
this->_ip = ip;
|
||||
this->_server = NULL;
|
||||
this->_port = port;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Syslog &Syslog::deviceHostname(const char *deviceHostname)
|
||||
{
|
||||
this->_deviceHostname = (deviceHostname == NULL) ? SYSLOG_NILVALUE : deviceHostname;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Syslog &Syslog::appName(const char *appName)
|
||||
{
|
||||
this->_appName = (appName == NULL) ? SYSLOG_NILVALUE : appName;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Syslog &Syslog::defaultPriority(uint16_t pri)
|
||||
{
|
||||
this->_priDefault = pri;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Syslog &Syslog::logMask(uint8_t priMask)
|
||||
{
|
||||
this->_priMask = priMask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Syslog::enable()
|
||||
{
|
||||
this->_enabled = true;
|
||||
}
|
||||
|
||||
void Syslog::disable()
|
||||
{
|
||||
this->_enabled = false;
|
||||
}
|
||||
|
||||
bool Syslog::isEnabled()
|
||||
{
|
||||
return this->_enabled;
|
||||
}
|
||||
|
||||
bool Syslog::vlogf(uint16_t pri, const char *fmt, va_list args)
|
||||
{
|
||||
return this->vlogf(pri, this->_appName, fmt, args);
|
||||
}
|
||||
|
||||
bool Syslog::vlogf(uint16_t pri, const char *appName, const char *fmt, va_list args)
|
||||
{
|
||||
char *message;
|
||||
size_t initialLen;
|
||||
size_t len;
|
||||
bool result;
|
||||
|
||||
initialLen = strlen(fmt);
|
||||
|
||||
message = new char[initialLen + 1];
|
||||
|
||||
len = vsnprintf(message, initialLen + 1, fmt, args);
|
||||
if (len > initialLen) {
|
||||
delete[] message;
|
||||
message = new char[len + 1];
|
||||
|
||||
vsnprintf(message, len + 1, fmt, args);
|
||||
}
|
||||
|
||||
result = this->_sendLog(pri, appName, message);
|
||||
|
||||
delete[] message;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline bool Syslog::_sendLog(uint16_t pri, const char *appName, const char *message)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (!this->_enabled)
|
||||
return false;
|
||||
|
||||
if ((this->_server == NULL && this->_ip == INADDR_NONE) || this->_port == 0)
|
||||
return false;
|
||||
|
||||
// Check priority against priMask values.
|
||||
if ((LOG_MASK(LOG_PRI(pri)) & this->_priMask) == 0)
|
||||
return true;
|
||||
|
||||
// Set default facility if none specified.
|
||||
if ((pri & LOG_FACMASK) == 0)
|
||||
pri = LOG_MAKEPRI(LOG_FAC(this->_priDefault), pri);
|
||||
|
||||
if (this->_server != NULL) {
|
||||
result = this->_client->beginPacket(this->_server, this->_port);
|
||||
} else {
|
||||
result = this->_client->beginPacket(this->_ip, this->_port);
|
||||
}
|
||||
|
||||
if (result != 1)
|
||||
return false;
|
||||
|
||||
this->_client->print('<');
|
||||
this->_client->print(pri);
|
||||
this->_client->print(F(">1 - "));
|
||||
this->_client->print(this->_deviceHostname);
|
||||
this->_client->print(' ');
|
||||
this->_client->print(appName);
|
||||
this->_client->print(F(" - - - \xEF\xBB\xBF"));
|
||||
this->_client->print(F("["));
|
||||
this->_client->print(int(millis() / 1000));
|
||||
this->_client->print(F("]: "));
|
||||
this->_client->print(message);
|
||||
this->_client->endPacket();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,3 +1,6 @@
|
||||
#ifndef SYSLOG_H
|
||||
#define SYSLOG_H
|
||||
|
||||
// DEBUG LED
|
||||
#ifndef LED_INVERTED
|
||||
#define LED_INVERTED 0 // define as 1 if LED is active low (on)
|
||||
@@ -17,6 +20,7 @@
|
||||
#define MESHTASTIC_LOG_LEVEL_INFO "INFO "
|
||||
#define MESHTASTIC_LOG_LEVEL_WARN "WARN "
|
||||
#define MESHTASTIC_LOG_LEVEL_ERROR "ERROR"
|
||||
#define MESHTASTIC_LOG_LEVEL_CRIT "CRIT "
|
||||
#define MESHTASTIC_LOG_LEVEL_TRACE "TRACE"
|
||||
|
||||
#include "SerialConsole.h"
|
||||
@@ -28,21 +32,72 @@
|
||||
#define LOG_INFO(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||
#define LOG_WARN(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||
#define LOG_ERROR(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||
#define LOG_CRIT(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||
#define LOG_TRACE(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||
#else
|
||||
#ifdef DEBUG_PORT
|
||||
#define LOG_DEBUG(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_DEBUG, __VA_ARGS__)
|
||||
#define LOG_INFO(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_INFO, __VA_ARGS__)
|
||||
#define LOG_WARN(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_WARN, __VA_ARGS__)
|
||||
#define LOG_ERROR(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_ERROR, __VA_ARGS__)
|
||||
#define LOG_TRACE(...) DEBUG_PORT.log(MESHTASTIC_LOG_TRACE, __VA_ARGS__)
|
||||
#define LOG_CRIT(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_CRIT, __VA_ARGS__)
|
||||
#define LOG_TRACE(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_TRACE, __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_DEBUG(...)
|
||||
#define LOG_INFO(...)
|
||||
#define LOG_WARN(...)
|
||||
#define LOG_ERROR(...)
|
||||
#define LOG_CRIT(...)
|
||||
#define LOG_TRACE(...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define SYSLOG_NILVALUE "-"
|
||||
|
||||
#define SYSLOG_CRIT 2 /* critical conditions */
|
||||
#define SYSLOG_ERR 3 /* error conditions */
|
||||
#define SYSLOG_WARN 4 /* warning conditions */
|
||||
#define SYSLOG_INFO 6 /* informational */
|
||||
#define SYSLOG_DEBUG 7 /* debug-level messages */
|
||||
// trace does not go out to syslog (yet?)
|
||||
|
||||
#define LOG_PRIMASK 0x07 /* mask to extract priority part (internal) */
|
||||
/* extract priority */
|
||||
#define LOG_PRI(p) ((p)&LOG_PRIMASK)
|
||||
#define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri))
|
||||
|
||||
/* facility codes */
|
||||
#define LOGLEVEL_KERN (0 << 3) /* kernel messages */
|
||||
#define LOGLEVEL_USER (1 << 3) /* random user-level messages */
|
||||
#define LOGLEVEL_MAIL (2 << 3) /* mail system */
|
||||
#define LOGLEVEL_DAEMON (3 << 3) /* system daemons */
|
||||
#define LOGLEVEL_AUTH (4 << 3) /* security/authorization messages */
|
||||
#define LOGLEVEL_SYSLOG (5 << 3) /* messages generated internally by syslogd */
|
||||
#define LOGLEVEL_LPR (6 << 3) /* line printer subsystem */
|
||||
#define LOGLEVEL_NEWS (7 << 3) /* network news subsystem */
|
||||
#define LOGLEVEL_UUCP (8 << 3) /* UUCP subsystem */
|
||||
#define LOGLEVEL_CRON (9 << 3) /* clock daemon */
|
||||
#define LOGLEVEL_AUTHPRIV (10 << 3) /* security/authorization messages (private) */
|
||||
#define LOGLEVEL_FTP (11 << 3) /* ftp daemon */
|
||||
|
||||
/* other codes through 15 reserved for system use */
|
||||
#define LOGLEVEL_LOCAL0 (16 << 3) /* reserved for local use */
|
||||
#define LOGLEVEL_LOCAL1 (17 << 3) /* reserved for local use */
|
||||
#define LOGLEVEL_LOCAL2 (18 << 3) /* reserved for local use */
|
||||
#define LOGLEVEL_LOCAL3 (19 << 3) /* reserved for local use */
|
||||
#define LOGLEVEL_LOCAL4 (20 << 3) /* reserved for local use */
|
||||
#define LOGLEVEL_LOCAL5 (21 << 3) /* reserved for local use */
|
||||
#define LOGLEVEL_LOCAL6 (22 << 3) /* reserved for local use */
|
||||
#define LOGLEVEL_LOCAL7 (23 << 3) /* reserved for local use */
|
||||
|
||||
#define LOG_NFACILITIES 24 /* current number of facilities */
|
||||
#define LOG_FACMASK 0x03f8 /* mask to extract facility part */
|
||||
/* facility of pri */
|
||||
#define LOG_FAC(p) (((p)&LOG_FACMASK) >> 3)
|
||||
|
||||
#define LOG_MASK(pri) (1 << (pri)) /* mask for one priority */
|
||||
#define LOG_UPTO(pri) ((1 << ((pri) + 1)) - 1) /* all priorities through pri */
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// AXP192 (Rev1-specific options)
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -52,3 +107,50 @@
|
||||
|
||||
// Default Bluetooth PIN
|
||||
#define defaultBLEPin 123456
|
||||
|
||||
#if HAS_ETHERNET
|
||||
#include <RAK13800_W5100S.h>
|
||||
#endif // HAS_ETHERNET
|
||||
|
||||
#if HAS_WIFI
|
||||
#include <WiFi.h>
|
||||
#endif // HAS_WIFI
|
||||
|
||||
#if HAS_WIFI || HAS_ETHERNET
|
||||
|
||||
class Syslog
|
||||
{
|
||||
private:
|
||||
UDP *_client;
|
||||
IPAddress _ip;
|
||||
const char *_server;
|
||||
uint16_t _port;
|
||||
const char *_deviceHostname;
|
||||
const char *_appName;
|
||||
uint16_t _priDefault;
|
||||
uint8_t _priMask = 0xff;
|
||||
bool _enabled = false;
|
||||
|
||||
bool _sendLog(uint16_t pri, const char *appName, const char *message);
|
||||
|
||||
public:
|
||||
explicit Syslog(UDP &client);
|
||||
|
||||
Syslog &server(const char *server, uint16_t port);
|
||||
Syslog &server(IPAddress ip, uint16_t port);
|
||||
Syslog &deviceHostname(const char *deviceHostname);
|
||||
Syslog &appName(const char *appName);
|
||||
Syslog &defaultPriority(uint16_t pri = LOGLEVEL_KERN);
|
||||
Syslog &logMask(uint8_t priMask);
|
||||
|
||||
void enable();
|
||||
void disable();
|
||||
bool isEnabled();
|
||||
|
||||
bool vlogf(uint16_t pri, const char *fmt, va_list args) __attribute__((format(printf, 3, 0)));
|
||||
bool vlogf(uint16_t pri, const char *appName, const char *fmt, va_list args) __attribute__((format(printf, 3, 0)));
|
||||
};
|
||||
|
||||
#endif // HAS_ETHERNET || HAS_WIFI
|
||||
|
||||
#endif // SYSLOG_H
|
||||
@@ -7,6 +7,16 @@
|
||||
#include "sleep.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef DEBUG_HEAP_MQTT
|
||||
#include "mqtt/MQTT.h"
|
||||
#include "target_specific.h"
|
||||
#include <WiFi.h>
|
||||
#endif
|
||||
|
||||
#ifndef DELAY_FOREVER
|
||||
#define DELAY_FOREVER portMAX_DELAY
|
||||
#endif
|
||||
|
||||
#ifdef HAS_PMU
|
||||
#include "XPowersAXP192.tpp"
|
||||
#include "XPowersAXP2101.tpp"
|
||||
@@ -250,16 +260,24 @@ void Power::shutdown()
|
||||
digitalWrite(PIN_EINK_EN, LOW); // power off backlight first
|
||||
#endif
|
||||
|
||||
#ifdef HAS_PMU
|
||||
LOG_INFO("Shutting down\n");
|
||||
|
||||
#ifdef HAS_PMU
|
||||
if (PMU) {
|
||||
PMU->setChargingLedMode(XPOWERS_CHG_LED_OFF);
|
||||
PMU->shutdown();
|
||||
}
|
||||
#elif defined(ARCH_NRF52)
|
||||
playBeep();
|
||||
#endif
|
||||
|
||||
#if defined(ARCH_NRF52) || defined(ARCH_ESP32)
|
||||
#ifdef PIN_LED1
|
||||
ledOff(PIN_LED1);
|
||||
#endif
|
||||
#ifdef PIN_LED2
|
||||
ledOff(PIN_LED2);
|
||||
#endif
|
||||
#ifdef PIN_LED3
|
||||
ledOff(PIN_LED2);
|
||||
#endif
|
||||
doDeepSleep(DELAY_FOREVER);
|
||||
#endif
|
||||
}
|
||||
@@ -311,6 +329,25 @@ void Power::readPowerStatus()
|
||||
ESP.getFreeHeap() - lastheap, running, concurrency::mainController.size(false));
|
||||
lastheap = ESP.getFreeHeap();
|
||||
}
|
||||
#ifdef DEBUG_HEAP_MQTT
|
||||
if (mqtt) {
|
||||
// send MQTT-Packet with Heap-Size
|
||||
uint8_t dmac[6];
|
||||
getMacAddr(dmac); // Get our hardware ID
|
||||
char mac[18];
|
||||
sprintf(mac, "!%02x%02x%02x%02x", dmac[2], dmac[3], dmac[4], dmac[5]);
|
||||
auto newHeap = ESP.getFreeHeap();
|
||||
std::string heapTopic = "msh/2/heap/" + std::string(mac);
|
||||
std::string heapString = std::to_string(newHeap);
|
||||
mqtt->pubSub.publish(heapTopic.c_str(), heapString.c_str(), false);
|
||||
// auto fragHeap = ESP.getHeapFragmentation();
|
||||
auto wifiRSSI = WiFi.RSSI();
|
||||
heapTopic = "msh/2/wifi/" + std::string(mac);
|
||||
std::string wifiString = std::to_string(wifiRSSI);
|
||||
mqtt->pubSub.publish(heapTopic.c_str(), wifiString.c_str(), false);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// If we have a battery at all and it is less than 10% full, force deep sleep if we have more than 3 low readings in a row
|
||||
@@ -490,8 +527,39 @@ bool Power::axpChipInit()
|
||||
|
||||
} else if (PMU->getChipModel() == XPOWERS_AXP2101) {
|
||||
|
||||
// t-beam s3 core
|
||||
/*The alternative version of T-Beam 1.1 differs from T-Beam V1.1 in that it uses an AXP2101 power chip*/
|
||||
#if (HW_VENDOR == meshtastic_HardwareModel_TBEAM)
|
||||
// Unuse power channel
|
||||
PMU->disablePowerOutput(XPOWERS_DCDC2);
|
||||
PMU->disablePowerOutput(XPOWERS_DCDC3);
|
||||
PMU->disablePowerOutput(XPOWERS_DCDC4);
|
||||
PMU->disablePowerOutput(XPOWERS_DCDC5);
|
||||
PMU->disablePowerOutput(XPOWERS_ALDO1);
|
||||
PMU->disablePowerOutput(XPOWERS_ALDO4);
|
||||
PMU->disablePowerOutput(XPOWERS_BLDO1);
|
||||
PMU->disablePowerOutput(XPOWERS_BLDO2);
|
||||
PMU->disablePowerOutput(XPOWERS_DLDO1);
|
||||
PMU->disablePowerOutput(XPOWERS_DLDO2);
|
||||
|
||||
// GNSS RTC PowerVDD 3300mV
|
||||
PMU->setPowerChannelVoltage(XPOWERS_VBACKUP, 3300);
|
||||
PMU->enablePowerOutput(XPOWERS_VBACKUP);
|
||||
|
||||
// ESP32 VDD 3300mV
|
||||
// ! No need to set, automatically open , Don't close it
|
||||
// PMU->setPowerChannelVoltage(XPOWERS_DCDC1, 3300);
|
||||
// PMU->setProtectedChannel(XPOWERS_DCDC1);
|
||||
|
||||
// LoRa VDD 3300mV
|
||||
PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300);
|
||||
PMU->enablePowerOutput(XPOWERS_ALDO2);
|
||||
|
||||
// GNSS VDD 3300mV
|
||||
PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300);
|
||||
PMU->enablePowerOutput(XPOWERS_ALDO3);
|
||||
|
||||
#elif (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE)
|
||||
// t-beam s3 core
|
||||
/**
|
||||
* gnss module power channel
|
||||
* The default ALDO4 is off, you need to turn on the GNSS power first, otherwise it will be invalid during initialization
|
||||
@@ -534,6 +602,8 @@ bool Power::axpChipInit()
|
||||
PMU->disablePowerOutput(XPOWERS_DLDO2); // Invalid power channel, it does not exist
|
||||
PMU->disablePowerOutput(XPOWERS_VBACKUP);
|
||||
|
||||
#endif
|
||||
|
||||
// disable all axp chip interrupt
|
||||
PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
|
||||
|
||||
|
||||
@@ -78,8 +78,8 @@ static void lsIdle()
|
||||
case ESP_SLEEP_WAKEUP_TIMER:
|
||||
// Normal case: timer expired, we should just go back to sleep ASAP
|
||||
|
||||
setLed(true); // briefly turn on led
|
||||
wakeCause2 = doLightSleep(1); // leave led on for 1ms
|
||||
setLed(true); // briefly turn on led
|
||||
wakeCause2 = doLightSleep(100); // leave led on for 1ms
|
||||
|
||||
secsSlept += sleepTime;
|
||||
// LOG_INFO("sleeping, flash led!\n");
|
||||
@@ -194,17 +194,6 @@ static void onEnter()
|
||||
LOG_INFO("Enter state: ON\n");
|
||||
screen->setOn(true);
|
||||
setBluetoothEnable(true);
|
||||
|
||||
static uint32_t lastPingMs;
|
||||
|
||||
uint32_t now = millis();
|
||||
|
||||
if ((now - lastPingMs) >
|
||||
30 * 1000) { // if more than a minute since our last press, ask node we are looking at to update their state
|
||||
if (displayedNodeNum)
|
||||
service.sendNetworkPing(displayedNodeNum, true); // Refresh the currently displayed node
|
||||
lastPingMs = now;
|
||||
}
|
||||
}
|
||||
|
||||
static void onIdle()
|
||||
|
||||
@@ -23,6 +23,6 @@
|
||||
#define EVENT_INPUT 17 // input broker wants something, we need to wake up and enable screen
|
||||
|
||||
extern Fsm powerFSM;
|
||||
extern State statePOWER, stateSERIAL;
|
||||
extern State stateON, statePOWER, stateSERIAL, stateDARK;
|
||||
|
||||
void PowerFSM_setup();
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
#ifdef USE_RF95
|
||||
#define RF95_RESET LORA_RESET
|
||||
#define RF95_IRQ LORA_DIO0 // on SX1262 version this is a no connect DIO0
|
||||
#define RF95_DIO1 LORA_DIO1 // Note: not really used for RF95
|
||||
#define RF95_DIO1 LORA_DIO1 // Note: not really used for RF95, but used for pure SX127x
|
||||
#define RF95_DIO2 LORA_DIO2 // Note: not really used for RF95
|
||||
#endif
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "configuration.h"
|
||||
#include <assert.h>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
@@ -13,6 +15,10 @@
|
||||
*/
|
||||
NoopPrint noopPrint;
|
||||
|
||||
#if HAS_WIFI || HAS_ETHERNET
|
||||
extern Syslog syslog;
|
||||
#endif
|
||||
|
||||
void RedirectablePrint::setDestination(Print *_dest)
|
||||
{
|
||||
assert(_dest);
|
||||
@@ -96,6 +102,39 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
|
||||
}
|
||||
}
|
||||
r += vprintf(format, arg);
|
||||
|
||||
#if (HAS_WIFI || HAS_ETHERNET) && !defined(ARCH_PORTDUINO)
|
||||
// if syslog is in use, collect the log messages and send them to syslog
|
||||
if (syslog.isEnabled()) {
|
||||
int ll = 0;
|
||||
switch (logLevel[0]) {
|
||||
case 'D':
|
||||
ll = SYSLOG_DEBUG;
|
||||
break;
|
||||
case 'I':
|
||||
ll = SYSLOG_INFO;
|
||||
break;
|
||||
case 'W':
|
||||
ll = SYSLOG_WARN;
|
||||
break;
|
||||
case 'E':
|
||||
ll = SYSLOG_ERR;
|
||||
break;
|
||||
case 'C':
|
||||
ll = SYSLOG_CRIT;
|
||||
break;
|
||||
default:
|
||||
ll = 0;
|
||||
}
|
||||
auto thread = concurrency::OSThread::currentThread;
|
||||
if (thread) {
|
||||
syslog.vlogf(ll, thread->ThreadName.c_str(), format, arg);
|
||||
} else {
|
||||
syslog.vlogf(ll, format, arg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
va_end(arg);
|
||||
|
||||
isContinuationMessage = !hasNewline;
|
||||
@@ -136,3 +175,22 @@ void RedirectablePrint::hexDump(const char *logLevel, unsigned char *buf, uint16
|
||||
}
|
||||
log(logLevel, " +------------------------------------------------+ +----------------+\n");
|
||||
}
|
||||
|
||||
std::string RedirectablePrint::mt_sprintf(const std::string fmt_str, ...)
|
||||
{
|
||||
int n = ((int)fmt_str.size()) * 2; /* Reserve two times as much as the length of the fmt_str */
|
||||
std::unique_ptr<char[]> formatted;
|
||||
va_list ap;
|
||||
while (1) {
|
||||
formatted.reset(new char[n]); /* Wrap the plain char array into the unique_ptr */
|
||||
strcpy(&formatted[0], fmt_str.c_str());
|
||||
va_start(ap, fmt_str);
|
||||
int final_n = vsnprintf(&formatted[0], n, fmt_str.c_str(), ap);
|
||||
va_end(ap);
|
||||
if (final_n < 0 || final_n >= n)
|
||||
n += abs(final_n - n + 1);
|
||||
else
|
||||
break;
|
||||
}
|
||||
return std::string(formatted.get());
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <Print.h>
|
||||
#include <stdarg.h>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* A Printable that can be switched to squirt its bytes to a different sink.
|
||||
@@ -40,6 +41,8 @@ class RedirectablePrint : public Print
|
||||
size_t vprintf(const char *format, va_list arg);
|
||||
|
||||
void hexDump(const char *logLevel, unsigned char *buf, uint16_t len);
|
||||
|
||||
std::string mt_sprintf(const std::string fmt_str, ...);
|
||||
};
|
||||
|
||||
class NoopPrint : public Print
|
||||
|
||||
@@ -82,7 +82,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// #define DISABLE_NTP
|
||||
|
||||
// Disable the welcome screen and allow
|
||||
//#define DISABLE_WELCOME_UNSET
|
||||
// #define DISABLE_WELCOME_UNSET
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// OLED & Input
|
||||
@@ -93,7 +93,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// The SH1106 controller is almost, but not quite, the same as SSD1306
|
||||
// Define this if you know you have that controller or your "SSD1306" misbehaves.
|
||||
//#define USE_SH1106
|
||||
// #define USE_SH1106
|
||||
|
||||
// Define if screen should be mirrored left to right
|
||||
// #define SCREEN_MIRROR
|
||||
@@ -116,6 +116,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define LPS22HB_ADDR 0x5C
|
||||
#define LPS22HB_ADDR_ALT 0x5D
|
||||
#define SHT31_ADDR 0x44
|
||||
#define PMSA0031_ADDR 0x12
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ACCELEROMETER
|
||||
// -----------------------------------------------------------------------------
|
||||
#define MPU6050_ADDR 0x68
|
||||
#define LIS3DH_ADR 0x18
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Security
|
||||
|
||||
76
src/detect/ScanI2C.cpp
Normal file
76
src/detect/ScanI2C.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#include "ScanI2C.h"
|
||||
|
||||
const ScanI2C::DeviceAddress ScanI2C::ADDRESS_NONE = ScanI2C::DeviceAddress();
|
||||
const ScanI2C::FoundDevice ScanI2C::DEVICE_NONE = ScanI2C::FoundDevice(ScanI2C::DeviceType::NONE, ADDRESS_NONE);
|
||||
|
||||
ScanI2C::ScanI2C() = default;
|
||||
|
||||
void ScanI2C::scanPort(ScanI2C::I2CPort port) {}
|
||||
|
||||
void ScanI2C::setSuppressScreen()
|
||||
{
|
||||
shouldSuppressScreen = true;
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::firstScreen() const
|
||||
{
|
||||
// Allow to override the scanner results for screen
|
||||
if (shouldSuppressScreen)
|
||||
return DEVICE_NONE;
|
||||
|
||||
ScanI2C::DeviceType types[] = {SCREEN_SSD1306, SCREEN_SH1106, SCREEN_ST7567, SCREEN_UNKNOWN};
|
||||
return firstOfOrNONE(4, types);
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::firstRTC() const
|
||||
{
|
||||
ScanI2C::DeviceType types[] = {RTC_RV3028, RTC_PCF8563};
|
||||
return firstOfOrNONE(2, types);
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
|
||||
{
|
||||
ScanI2C::DeviceType types[] = {CARDKB, RAK14004};
|
||||
return firstOfOrNONE(2, types);
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const
|
||||
{
|
||||
ScanI2C::DeviceType types[] = {MPU6050, LIS3DH};
|
||||
return firstOfOrNONE(2, types);
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::find(ScanI2C::DeviceType) const
|
||||
{
|
||||
return DEVICE_NONE;
|
||||
}
|
||||
|
||||
bool ScanI2C::exists(ScanI2C::DeviceType) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::firstOfOrNONE(size_t count, ScanI2C::DeviceType *types) const
|
||||
{
|
||||
return DEVICE_NONE;
|
||||
}
|
||||
|
||||
size_t ScanI2C::countDevices() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ScanI2C::DeviceAddress::DeviceAddress(ScanI2C::I2CPort port, uint8_t address) : port(port), address(address) {}
|
||||
|
||||
ScanI2C::DeviceAddress::DeviceAddress() : DeviceAddress(I2CPort::NO_I2C, 0) {}
|
||||
|
||||
bool ScanI2C::DeviceAddress::operator<(const ScanI2C::DeviceAddress &other) const
|
||||
{
|
||||
return
|
||||
// If this one has no port and other has a port
|
||||
(port == NO_I2C && other.port != NO_I2C)
|
||||
// if both have a port and this one's address is lower
|
||||
|| (port != NO_I2C && other.port != NO_I2C && (address < other.address));
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice::FoundDevice(ScanI2C::DeviceType type, ScanI2C::DeviceAddress address) : type(type), address(address) {}
|
||||
97
src/detect/ScanI2C.h
Normal file
97
src/detect/ScanI2C.h
Normal file
@@ -0,0 +1,97 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
class ScanI2C
|
||||
{
|
||||
public:
|
||||
typedef enum DeviceType {
|
||||
NONE,
|
||||
SCREEN_SSD1306,
|
||||
SCREEN_SH1106,
|
||||
SCREEN_UNKNOWN, // has the same address as the two above but does not respond to the same commands
|
||||
SCREEN_ST7567,
|
||||
ATECC608B,
|
||||
RTC_RV3028,
|
||||
RTC_PCF8563,
|
||||
CARDKB,
|
||||
RAK14004,
|
||||
PMU_AXP192_AXP2101,
|
||||
BME_680,
|
||||
BME_280,
|
||||
BMP_280,
|
||||
INA260,
|
||||
INA219,
|
||||
MCP9808,
|
||||
SHT31,
|
||||
SHTC3,
|
||||
LPS22HB,
|
||||
QMC6310,
|
||||
QMI8658,
|
||||
QMC5883L,
|
||||
PMSA0031,
|
||||
MPU6050,
|
||||
LIS3DH,
|
||||
} DeviceType;
|
||||
|
||||
// typedef uint8_t DeviceAddress;
|
||||
typedef enum I2CPort {
|
||||
NO_I2C,
|
||||
WIRE,
|
||||
WIRE1,
|
||||
} I2CPort;
|
||||
|
||||
typedef struct DeviceAddress {
|
||||
I2CPort port;
|
||||
uint8_t address;
|
||||
|
||||
explicit DeviceAddress(I2CPort port, uint8_t address);
|
||||
DeviceAddress();
|
||||
|
||||
bool operator<(const DeviceAddress &other) const;
|
||||
} DeviceAddress;
|
||||
|
||||
static const DeviceAddress ADDRESS_NONE;
|
||||
|
||||
typedef uint8_t RegisterAddress;
|
||||
|
||||
typedef struct FoundDevice {
|
||||
DeviceType type;
|
||||
DeviceAddress address;
|
||||
|
||||
explicit FoundDevice(DeviceType = DeviceType::NONE, DeviceAddress = ADDRESS_NONE);
|
||||
} FoundDevice;
|
||||
|
||||
static const FoundDevice DEVICE_NONE;
|
||||
|
||||
public:
|
||||
ScanI2C();
|
||||
|
||||
virtual void scanPort(ScanI2C::I2CPort);
|
||||
|
||||
/*
|
||||
* A bit of a hack, this tells the scanner not to tell later systems there is a screen to avoid enabling it.
|
||||
*/
|
||||
void setSuppressScreen();
|
||||
|
||||
FoundDevice firstScreen() const;
|
||||
|
||||
FoundDevice firstRTC() const;
|
||||
|
||||
FoundDevice firstKeyboard() const;
|
||||
|
||||
FoundDevice firstAccelerometer() const;
|
||||
|
||||
virtual FoundDevice find(DeviceType) const;
|
||||
|
||||
virtual bool exists(DeviceType) const;
|
||||
|
||||
virtual size_t countDevices() const;
|
||||
|
||||
protected:
|
||||
virtual FoundDevice firstOfOrNONE(size_t, DeviceType[]) const;
|
||||
|
||||
private:
|
||||
bool shouldSuppressScreen = false;
|
||||
};
|
||||
307
src/detect/ScanI2CTwoWire.cpp
Normal file
307
src/detect/ScanI2CTwoWire.cpp
Normal file
@@ -0,0 +1,307 @@
|
||||
#include "ScanI2CTwoWire.h"
|
||||
|
||||
#include "concurrency/LockGuard.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
#include "main.h" // atecc
|
||||
#endif
|
||||
|
||||
// AXP192 and AXP2101 have the same device address, we just need to identify it in Power.cpp
|
||||
#ifndef XPOWERS_AXP192_AXP2101_ADDRESS
|
||||
#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34
|
||||
#endif
|
||||
|
||||
ScanI2C::FoundDevice ScanI2CTwoWire::find(ScanI2C::DeviceType type) const
|
||||
{
|
||||
concurrency::LockGuard guard((concurrency::Lock *)&lock);
|
||||
|
||||
return exists(type) ? ScanI2C::FoundDevice(type, deviceAddresses.at(type)) : DEVICE_NONE;
|
||||
}
|
||||
|
||||
bool ScanI2CTwoWire::exists(ScanI2C::DeviceType type) const
|
||||
{
|
||||
return deviceAddresses.find(type) != deviceAddresses.end();
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice ScanI2CTwoWire::firstOfOrNONE(size_t count, DeviceType types[]) const
|
||||
{
|
||||
concurrency::LockGuard guard((concurrency::Lock *)&lock);
|
||||
|
||||
for (size_t k = 0; k < count; k++) {
|
||||
ScanI2C::DeviceType current = types[k];
|
||||
|
||||
if (exists(current)) {
|
||||
return ScanI2C::FoundDevice(current, deviceAddresses.at(current));
|
||||
}
|
||||
}
|
||||
|
||||
return DEVICE_NONE;
|
||||
}
|
||||
|
||||
ScanI2C::DeviceType ScanI2CTwoWire::probeOLED(ScanI2C::DeviceAddress addr) const
|
||||
{
|
||||
TwoWire *i2cBus = fetchI2CBus(addr);
|
||||
|
||||
uint8_t r = 0;
|
||||
uint8_t r_prev = 0;
|
||||
uint8_t c = 0;
|
||||
ScanI2C::DeviceType o_probe = ScanI2C::DeviceType::SCREEN_UNKNOWN;
|
||||
do {
|
||||
r_prev = r;
|
||||
i2cBus->beginTransmission(addr.address);
|
||||
i2cBus->write((uint8_t)0x00);
|
||||
i2cBus->endTransmission();
|
||||
i2cBus->requestFrom((int)addr.address, 1);
|
||||
if (i2cBus->available()) {
|
||||
r = i2cBus->read();
|
||||
}
|
||||
r &= 0x0f;
|
||||
|
||||
if (r == 0x08 || r == 0x00) {
|
||||
LOG_INFO("sh1106 display found\n");
|
||||
o_probe = SCREEN_SH1106; // SH1106
|
||||
} else if (r == 0x03 || r == 0x04 || r == 0x06 || r == 0x07) {
|
||||
LOG_INFO("ssd1306 display found\n");
|
||||
o_probe = SCREEN_SSD1306; // SSD1306
|
||||
}
|
||||
c++;
|
||||
} while ((r != r_prev) && (c < 4));
|
||||
LOG_DEBUG("0x%x subtype probed in %i tries \n", r, c);
|
||||
|
||||
return o_probe;
|
||||
}
|
||||
void ScanI2CTwoWire::printATECCInfo() const
|
||||
{
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
atecc.readConfigZone(false);
|
||||
|
||||
LOG_DEBUG("ATECC608B Serial Number: ");
|
||||
for (int i = 0; i < 9; i++) {
|
||||
LOG_DEBUG("%02x", atecc.serialNumber[i]);
|
||||
}
|
||||
|
||||
LOG_DEBUG(", Rev Number: ");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
LOG_DEBUG("%02x", atecc.revisionNumber[i]);
|
||||
}
|
||||
LOG_DEBUG("\n");
|
||||
|
||||
LOG_DEBUG("ATECC608B Config %s", atecc.configLockStatus ? "Locked" : "Unlocked");
|
||||
LOG_DEBUG(", Data %s", atecc.dataOTPLockStatus ? "Locked" : "Unlocked");
|
||||
LOG_DEBUG(", Slot 0 %s\n", atecc.slot0LockStatus ? "Locked" : "Unlocked");
|
||||
|
||||
if (atecc.configLockStatus && atecc.dataOTPLockStatus && atecc.slot0LockStatus) {
|
||||
if (atecc.generatePublicKey() == false) {
|
||||
LOG_DEBUG("ATECC608B Error generating public key\n");
|
||||
} else {
|
||||
LOG_DEBUG("ATECC608B Public Key: ");
|
||||
for (int i = 0; i < 64; i++) {
|
||||
LOG_DEBUG("%02x", atecc.publicKey64Bytes[i]);
|
||||
}
|
||||
LOG_DEBUG("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation ®isterLocation,
|
||||
ScanI2CTwoWire::ResponseWidth responseWidth) const
|
||||
{
|
||||
uint16_t value = 0x00;
|
||||
TwoWire *i2cBus = fetchI2CBus(registerLocation.i2cAddress);
|
||||
|
||||
i2cBus->beginTransmission(registerLocation.i2cAddress.address);
|
||||
i2cBus->write(registerLocation.registerAddress);
|
||||
i2cBus->endTransmission();
|
||||
delay(20);
|
||||
i2cBus->requestFrom(registerLocation.i2cAddress.address, responseWidth);
|
||||
LOG_DEBUG("Wire.available() = %d\n", i2cBus->available());
|
||||
if (i2cBus->available() == 2) {
|
||||
// Read MSB, then LSB
|
||||
value = (uint16_t)i2cBus->read() << 8;
|
||||
value |= i2cBus->read();
|
||||
} else if (i2cBus->available()) {
|
||||
value = i2cBus->read();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
#define SCAN_SIMPLE_CASE(ADDR, T, ...) \
|
||||
case ADDR: \
|
||||
LOG_INFO(__VA_ARGS__); \
|
||||
type = T; \
|
||||
break;
|
||||
|
||||
void ScanI2CTwoWire::scanPort(I2CPort port)
|
||||
{
|
||||
concurrency::LockGuard guard((concurrency::Lock *)&lock);
|
||||
|
||||
LOG_DEBUG("Scanning for i2c devices on port %d\n", port);
|
||||
|
||||
uint8_t err;
|
||||
|
||||
DeviceAddress addr(port, 0x00);
|
||||
|
||||
uint16_t registerValue = 0x00;
|
||||
ScanI2C::DeviceType type;
|
||||
TwoWire *i2cBus;
|
||||
#ifdef RV3028_RTC
|
||||
Melopero_RV3028 rtc;
|
||||
#endif
|
||||
|
||||
#ifdef I2C_SDA1
|
||||
if (port == I2CPort::WIRE1) {
|
||||
i2cBus = &Wire1;
|
||||
} else {
|
||||
#endif
|
||||
i2cBus = &Wire;
|
||||
#ifdef I2C_SDA1
|
||||
}
|
||||
#endif
|
||||
|
||||
for (addr.address = 1; addr.address < 127; addr.address++) {
|
||||
i2cBus->beginTransmission(addr.address);
|
||||
err = i2cBus->endTransmission();
|
||||
type = NONE;
|
||||
if (err == 0) {
|
||||
LOG_DEBUG("I2C device found at address 0x%x\n", addr.address);
|
||||
|
||||
switch (addr.address) {
|
||||
case SSD1306_ADDRESS:
|
||||
type = probeOLED(addr);
|
||||
break;
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
case ATECC608B_ADDR:
|
||||
type = ATECC608B;
|
||||
if (atecc.begin(addr.address) == true) {
|
||||
LOG_INFO("ATECC608B initialized\n");
|
||||
} else {
|
||||
LOG_WARN("ATECC608B initialization failed\n");
|
||||
}
|
||||
printATECCInfo();
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef RV3028_RTC
|
||||
case RV3028_RTC:
|
||||
// foundDevices[addr] = RTC_RV3028;
|
||||
type = RTC_RV3028;
|
||||
LOG_INFO("RV3028 RTC found\n");
|
||||
rtc.initI2C(*i2cBus);
|
||||
rtc.writeToRegister(0x35, 0x07); // no Clkout
|
||||
rtc.writeToRegister(0x37, 0xB4);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef PCF8563_RTC
|
||||
SCAN_SIMPLE_CASE(PCF8563_RTC, RTC_PCF8563, "PCF8563 RTC found\n")
|
||||
#endif
|
||||
|
||||
case CARDKB_ADDR:
|
||||
// Do we have the RAK14006 instead?
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x04), 1);
|
||||
if (registerValue == 0x02) {
|
||||
// KEYPAD_VERSION
|
||||
LOG_INFO("RAK14004 found\n");
|
||||
type = RAK14004;
|
||||
} else {
|
||||
LOG_INFO("m5 cardKB found\n");
|
||||
type = CARDKB;
|
||||
}
|
||||
break;
|
||||
|
||||
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "st7567 display found\n")
|
||||
|
||||
#ifdef HAS_PMU
|
||||
SCAN_SIMPLE_CASE(XPOWERS_AXP192_AXP2101_ADDRESS, PMU_AXP192_AXP2101, "axp192/axp2101 PMU found\n")
|
||||
#endif
|
||||
case BME_ADDR:
|
||||
case BME_ADDR_ALTERNATE:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xD0), 1); // GET_ID
|
||||
switch (registerValue) {
|
||||
case 0x61:
|
||||
LOG_INFO("BME-680 sensor found at address 0x%x\n", (uint8_t)addr.address);
|
||||
type = BME_680;
|
||||
break;
|
||||
case 0x60:
|
||||
LOG_INFO("BME-280 sensor found at address 0x%x\n", (uint8_t)addr.address);
|
||||
type = BME_280;
|
||||
break;
|
||||
default:
|
||||
LOG_INFO("BMP-280 sensor found at address 0x%x\n", (uint8_t)addr.address);
|
||||
type = BMP_280;
|
||||
}
|
||||
break;
|
||||
|
||||
case INA_ADDR:
|
||||
case INA_ADDR_ALTERNATE:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2);
|
||||
LOG_DEBUG("Register MFG_UID: 0x%x\n", registerValue);
|
||||
if (registerValue == 0x5449) {
|
||||
LOG_INFO("INA260 sensor found at address 0x%x\n", (uint8_t)addr.address);
|
||||
type = INA260;
|
||||
} else { // Assume INA219 if INA260 ID is not found
|
||||
LOG_INFO("INA219 sensor found at address 0x%x\n", (uint8_t)addr.address);
|
||||
type = INA219;
|
||||
}
|
||||
break;
|
||||
|
||||
case MCP9808_ADDR:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x07), 2);
|
||||
if (registerValue == 0x0400) {
|
||||
type = MCP9808;
|
||||
LOG_INFO("MCP9808 sensor found\n");
|
||||
} else {
|
||||
type = LIS3DH;
|
||||
LOG_INFO("LIS3DH accelerometer found\n");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
SCAN_SIMPLE_CASE(SHT31_ADDR, SHT31, "SHT31 sensor found\n")
|
||||
SCAN_SIMPLE_CASE(SHTC3_ADDR, SHTC3, "SHTC3 sensor found\n")
|
||||
|
||||
case LPS22HB_ADDR_ALT:
|
||||
SCAN_SIMPLE_CASE(LPS22HB_ADDR, LPS22HB, "LPS22HB sensor found\n")
|
||||
|
||||
SCAN_SIMPLE_CASE(QMC6310_ADDR, QMC6310, "QMC6310 Highrate 3-Axis magnetic sensor found\n")
|
||||
SCAN_SIMPLE_CASE(QMI8658_ADDR, QMI8658, "QMI8658 Highrate 6-Axis inertial measurement sensor found\n")
|
||||
SCAN_SIMPLE_CASE(QMC5883L_ADDR, QMC5883L, "QMC5883L Highrate 3-Axis magnetic sensor found\n")
|
||||
|
||||
SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031 air quality sensor found\n")
|
||||
SCAN_SIMPLE_CASE(MPU6050_ADDR, MPU6050, "MPU6050 accelerometer found\n");
|
||||
|
||||
default:
|
||||
LOG_INFO("Device found at address 0x%x was not able to be enumerated\n", addr.address);
|
||||
}
|
||||
} else if (err == 4) {
|
||||
LOG_ERROR("Unknown error at address 0x%x\n", addr);
|
||||
}
|
||||
|
||||
// Check if a type was found for the enumerated device - save, if so
|
||||
if (type != NONE) {
|
||||
deviceAddresses[type] = addr;
|
||||
foundDevices[addr] = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TwoWire *ScanI2CTwoWire::fetchI2CBus(ScanI2C::DeviceAddress address) const
|
||||
{
|
||||
if (address.port == ScanI2C::I2CPort::WIRE1) {
|
||||
return &Wire;
|
||||
} else {
|
||||
#ifdef I2C_SDA1
|
||||
return &Wire1;
|
||||
#else
|
||||
return &Wire;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
size_t ScanI2CTwoWire::countDevices() const
|
||||
{
|
||||
return foundDevices.size();
|
||||
}
|
||||
56
src/detect/ScanI2CTwoWire.h
Normal file
56
src/detect/ScanI2CTwoWire.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <Wire.h>
|
||||
|
||||
#include "ScanI2C.h"
|
||||
|
||||
#include "../concurrency/Lock.h"
|
||||
|
||||
class ScanI2CTwoWire : public ScanI2C
|
||||
{
|
||||
public:
|
||||
void scanPort(ScanI2C::I2CPort) override;
|
||||
|
||||
ScanI2C::FoundDevice find(ScanI2C::DeviceType) const override;
|
||||
|
||||
bool exists(ScanI2C::DeviceType) const override;
|
||||
|
||||
size_t countDevices() const override;
|
||||
|
||||
protected:
|
||||
FoundDevice firstOfOrNONE(size_t, DeviceType[]) const override;
|
||||
|
||||
private:
|
||||
typedef struct RegisterLocation {
|
||||
DeviceAddress i2cAddress;
|
||||
RegisterAddress registerAddress;
|
||||
|
||||
RegisterLocation(DeviceAddress deviceAddress, RegisterAddress registerAddress)
|
||||
: i2cAddress(deviceAddress), registerAddress(registerAddress)
|
||||
{
|
||||
}
|
||||
|
||||
} RegisterLocation;
|
||||
|
||||
typedef uint8_t ResponseWidth;
|
||||
|
||||
std::map<ScanI2C::DeviceAddress, ScanI2C::DeviceType> foundDevices;
|
||||
|
||||
// note: prone to overwriting if multiple devices of a type are added at different addresses (rare?)
|
||||
std::map<ScanI2C::DeviceType, ScanI2C::DeviceAddress> deviceAddresses;
|
||||
|
||||
concurrency::Lock lock;
|
||||
|
||||
void printATECCInfo() const;
|
||||
|
||||
uint16_t getRegisterValue(const RegisterLocation &, ResponseWidth) const;
|
||||
|
||||
DeviceType probeOLED(ScanI2C::DeviceAddress) const;
|
||||
|
||||
TwoWire *fetchI2CBus(ScanI2C::DeviceAddress) const;
|
||||
};
|
||||
@@ -1,233 +0,0 @@
|
||||
#include "../configuration.h"
|
||||
#include "../main.h"
|
||||
#include "mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include <Wire.h>
|
||||
|
||||
// AXP192 and AXP2101 have the same device address, we just need to identify it in Power.cpp
|
||||
#ifndef XPOWERS_AXP192_AXP2101_ADDRESS
|
||||
#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34
|
||||
#endif
|
||||
|
||||
#if HAS_WIRE
|
||||
|
||||
void printATECCInfo()
|
||||
{
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
atecc.readConfigZone(false);
|
||||
|
||||
LOG_DEBUG("ATECC608B Serial Number: ");
|
||||
for (int i = 0; i < 9; i++) {
|
||||
LOG_DEBUG("%02x", atecc.serialNumber[i]);
|
||||
}
|
||||
|
||||
LOG_DEBUG(", Rev Number: ");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
LOG_DEBUG("%02x", atecc.revisionNumber[i]);
|
||||
}
|
||||
LOG_DEBUG("\n");
|
||||
|
||||
LOG_DEBUG("ATECC608B Config %s", atecc.configLockStatus ? "Locked" : "Unlocked");
|
||||
LOG_DEBUG(", Data %s", atecc.dataOTPLockStatus ? "Locked" : "Unlocked");
|
||||
LOG_DEBUG(", Slot 0 %s\n", atecc.slot0LockStatus ? "Locked" : "Unlocked");
|
||||
|
||||
if (atecc.configLockStatus && atecc.dataOTPLockStatus && atecc.slot0LockStatus) {
|
||||
if (atecc.generatePublicKey() == false) {
|
||||
LOG_DEBUG("ATECC608B Error generating public key\n");
|
||||
} else {
|
||||
LOG_DEBUG("ATECC608B Public Key: ");
|
||||
for (int i = 0; i < 64; i++) {
|
||||
LOG_DEBUG("%02x", atecc.publicKey64Bytes[i]);
|
||||
}
|
||||
LOG_DEBUG("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t getRegisterValue(uint8_t address, uint8_t reg, uint8_t length)
|
||||
{
|
||||
uint16_t value = 0x00;
|
||||
Wire.beginTransmission(address);
|
||||
Wire.write(reg);
|
||||
Wire.endTransmission();
|
||||
delay(20);
|
||||
Wire.requestFrom(address, length);
|
||||
LOG_DEBUG("Wire.available() = %d\n", Wire.available());
|
||||
if (Wire.available() == 2) {
|
||||
// Read MSB, then LSB
|
||||
value = (uint16_t)Wire.read() << 8;
|
||||
value |= Wire.read();
|
||||
} else if (Wire.available()) {
|
||||
value = Wire.read();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
uint8_t oled_probe(byte addr)
|
||||
{
|
||||
uint8_t r = 0;
|
||||
uint8_t r_prev = 0;
|
||||
uint8_t c = 0;
|
||||
uint8_t o_probe = 0;
|
||||
do {
|
||||
r_prev = r;
|
||||
Wire.beginTransmission(addr);
|
||||
Wire.write(0x00);
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom((int)addr, 1);
|
||||
if (Wire.available()) {
|
||||
r = Wire.read();
|
||||
}
|
||||
r &= 0x0f;
|
||||
|
||||
if (r == 0x08 || r == 0x00) {
|
||||
o_probe = 2; // SH1106
|
||||
} else if (r == 0x03 || r == 0x04 || r == 0x06 || r == 0x07) {
|
||||
o_probe = 1; // SSD1306
|
||||
}
|
||||
c++;
|
||||
} while ((r != r_prev) && (c < 4));
|
||||
LOG_DEBUG("0x%x subtype probed in %i tries \n", r, c);
|
||||
return o_probe;
|
||||
}
|
||||
|
||||
void scanI2Cdevice()
|
||||
{
|
||||
byte err, addr;
|
||||
uint16_t registerValue = 0x00;
|
||||
int nDevices = 0;
|
||||
for (addr = 1; addr < 127; addr++) {
|
||||
Wire.beginTransmission(addr);
|
||||
err = Wire.endTransmission();
|
||||
if (err == 0) {
|
||||
LOG_DEBUG("I2C device found at address 0x%x\n", addr);
|
||||
|
||||
nDevices++;
|
||||
|
||||
if (addr == SSD1306_ADDRESS) {
|
||||
screen_found = addr;
|
||||
screen_model = oled_probe(addr);
|
||||
if (screen_model == 1) {
|
||||
LOG_INFO("ssd1306 display found\n");
|
||||
} else if (screen_model == 2) {
|
||||
LOG_INFO("sh1106 display found\n");
|
||||
} else {
|
||||
LOG_INFO("unknown display found\n");
|
||||
}
|
||||
}
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
if (addr == ATECC608B_ADDR) {
|
||||
keystore_found = addr;
|
||||
if (atecc.begin(keystore_found) == true) {
|
||||
LOG_INFO("ATECC608B initialized\n");
|
||||
} else {
|
||||
LOG_WARN("ATECC608B initialization failed\n");
|
||||
}
|
||||
printATECCInfo();
|
||||
}
|
||||
#endif
|
||||
#ifdef RV3028_RTC
|
||||
if (addr == RV3028_RTC) {
|
||||
rtc_found = addr;
|
||||
LOG_INFO("RV3028 RTC found\n");
|
||||
Melopero_RV3028 rtc;
|
||||
rtc.initI2C();
|
||||
rtc.writeToRegister(0x35, 0x07); // no Clkout
|
||||
rtc.writeToRegister(0x37, 0xB4);
|
||||
}
|
||||
#endif
|
||||
#ifdef PCF8563_RTC
|
||||
if (addr == PCF8563_RTC) {
|
||||
rtc_found = addr;
|
||||
LOG_INFO("PCF8563 RTC found\n");
|
||||
}
|
||||
#endif
|
||||
if (addr == CARDKB_ADDR) {
|
||||
cardkb_found = addr;
|
||||
// Do we have the RAK14006 instead?
|
||||
registerValue = getRegisterValue(addr, 0x04, 1);
|
||||
if (registerValue == 0x02) { // KEYPAD_VERSION
|
||||
LOG_INFO("RAK14004 found\n");
|
||||
kb_model = 0x02;
|
||||
} else {
|
||||
LOG_INFO("m5 cardKB found\n");
|
||||
kb_model = 0x00;
|
||||
}
|
||||
}
|
||||
if (addr == ST7567_ADDRESS) {
|
||||
screen_found = addr;
|
||||
LOG_INFO("st7567 display found\n");
|
||||
}
|
||||
#ifdef HAS_PMU
|
||||
if (addr == XPOWERS_AXP192_AXP2101_ADDRESS) {
|
||||
pmu_found = true;
|
||||
LOG_INFO("axp192/axp2101 PMU found\n");
|
||||
}
|
||||
#endif
|
||||
if (addr == BME_ADDR || addr == BME_ADDR_ALTERNATE) {
|
||||
registerValue = getRegisterValue(addr, 0xD0, 1); // GET_ID
|
||||
if (registerValue == 0x61) {
|
||||
LOG_INFO("BME-680 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_BME680] = addr;
|
||||
} else if (registerValue == 0x60) {
|
||||
LOG_INFO("BME-280 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_BME280] = addr;
|
||||
} else {
|
||||
LOG_INFO("BMP-280 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_BMP280] = addr;
|
||||
}
|
||||
}
|
||||
if (addr == INA_ADDR || addr == INA_ADDR_ALTERNATE) {
|
||||
registerValue = getRegisterValue(addr, 0xFE, 2);
|
||||
LOG_DEBUG("Register MFG_UID: 0x%x\n", registerValue);
|
||||
if (registerValue == 0x5449) {
|
||||
LOG_INFO("INA260 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260] = addr;
|
||||
} else { // Assume INA219 if INA260 ID is not found
|
||||
LOG_INFO("INA219 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219] = addr;
|
||||
}
|
||||
}
|
||||
if (addr == MCP9808_ADDR) {
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MCP9808] = addr;
|
||||
LOG_INFO("MCP9808 sensor found\n");
|
||||
}
|
||||
if (addr == SHT31_ADDR) {
|
||||
LOG_INFO("SHT31 sensor found\n");
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_SHT31] = addr;
|
||||
}
|
||||
if (addr == SHTC3_ADDR) {
|
||||
LOG_INFO("SHTC3 sensor found\n");
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_SHTC3] = addr;
|
||||
}
|
||||
if (addr == LPS22HB_ADDR || addr == LPS22HB_ADDR_ALT) {
|
||||
LOG_INFO("LPS22HB sensor found\n");
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_LPS22] = addr;
|
||||
}
|
||||
|
||||
// High rate sensors, will be processed internally
|
||||
if (addr == QMC6310_ADDR) {
|
||||
LOG_INFO("QMC6310 Highrate 3-Axis magnetic sensor found\n");
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_QMC6310] = addr;
|
||||
}
|
||||
if (addr == QMI8658_ADDR) {
|
||||
LOG_INFO("QMI8658 Highrate 6-Axis inertial measurement sensor found\n");
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_QMI8658] = addr;
|
||||
}
|
||||
if (addr == QMC5883L_ADDR) {
|
||||
LOG_INFO("QMC5883L Highrate 3-Axis magnetic sensor found\n");
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_QMC5883L] = addr;
|
||||
}
|
||||
} else if (err == 4) {
|
||||
LOG_ERROR("Unknow error at address 0x%x\n", addr);
|
||||
}
|
||||
}
|
||||
|
||||
if (nDevices == 0)
|
||||
LOG_INFO("No I2C devices found\n");
|
||||
else
|
||||
LOG_INFO("%i I2C devices found\n", nDevices);
|
||||
}
|
||||
#else
|
||||
void scanI2Cdevice() {}
|
||||
#endif
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "RTC.h"
|
||||
#include "configuration.h"
|
||||
#include "detect/ScanI2C.h"
|
||||
#include "main.h"
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
@@ -20,10 +21,14 @@ void readFromRTC()
|
||||
{
|
||||
struct timeval tv; /* btw settimeofday() is helpfull here too*/
|
||||
#ifdef RV3028_RTC
|
||||
if (rtc_found == RV3028_RTC) {
|
||||
if (rtc_found.address == RV3028_RTC) {
|
||||
uint32_t now = millis();
|
||||
Melopero_RV3028 rtc;
|
||||
#ifdef I2C_SDA1
|
||||
rtc.initI2C(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
|
||||
#else
|
||||
rtc.initI2C();
|
||||
#endif
|
||||
tm t;
|
||||
t.tm_year = rtc.getYear() - 1900;
|
||||
t.tm_mon = rtc.getMonth() - 1;
|
||||
@@ -41,14 +46,16 @@ void readFromRTC()
|
||||
}
|
||||
}
|
||||
#elif defined(PCF8563_RTC)
|
||||
if (rtc_found == PCF8563_RTC) {
|
||||
if (rtc_found.address == PCF8563_RTC) {
|
||||
uint32_t now = millis();
|
||||
PCF8563_Class rtc;
|
||||
#ifdef RTC_USE_WIRE1
|
||||
rtc.begin(Wire1);
|
||||
|
||||
#ifdef I2C_SDA1
|
||||
rtc.begin(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
|
||||
#else
|
||||
rtc.begin();
|
||||
#endif
|
||||
|
||||
auto tc = rtc.getDateTime();
|
||||
tm t;
|
||||
t.tm_year = tc.year - 1900;
|
||||
@@ -103,19 +110,24 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
|
||||
|
||||
// If this platform has a setable RTC, set it
|
||||
#ifdef RV3028_RTC
|
||||
if (rtc_found == RV3028_RTC) {
|
||||
if (rtc_found.address == RV3028_RTC) {
|
||||
Melopero_RV3028 rtc;
|
||||
#ifdef I2C_SDA1
|
||||
rtc.initI2C(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
|
||||
#else
|
||||
rtc.initI2C();
|
||||
#endif
|
||||
tm *t = localtime(&tv->tv_sec);
|
||||
rtc.setTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_wday, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
|
||||
LOG_DEBUG("RV3028_RTC setTime %02d-%02d-%02d %02d:%02d:%02d %ld\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
|
||||
t->tm_hour, t->tm_min, t->tm_sec, tv->tv_sec);
|
||||
}
|
||||
#elif defined(PCF8563_RTC)
|
||||
if (rtc_found == PCF8563_RTC) {
|
||||
if (rtc_found.address == PCF8563_RTC) {
|
||||
PCF8563_Class rtc;
|
||||
#ifdef RTC_USE_WIRE1
|
||||
rtc.begin(Wire1);
|
||||
|
||||
#ifdef I2C_SDA1
|
||||
rtc.begin(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
|
||||
#else
|
||||
rtc.begin();
|
||||
#endif
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
#if defined(TTGO_T_ECHO)
|
||||
#define TECHO_DISPLAY_MODEL GxEPD2_154_D67
|
||||
#elif defined(RAK4630)
|
||||
#elif defined(RAK4630) || defined(MAKERPYTHON)
|
||||
|
||||
// GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122 - changed from GxEPD2_213_B74 - which was not going to give partial update
|
||||
// support
|
||||
@@ -41,20 +41,20 @@
|
||||
|
||||
GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT> *adafruitDisplay;
|
||||
|
||||
EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl, uint8_t screen_model)
|
||||
EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus)
|
||||
{
|
||||
#if defined(TTGO_T_ECHO)
|
||||
setGeometry(GEOMETRY_RAWMODE, TECHO_DISPLAY_MODEL::WIDTH, TECHO_DISPLAY_MODEL::HEIGHT);
|
||||
#elif defined(RAK4630)
|
||||
#elif defined(RAK4630) || defined(MAKERPYTHON)
|
||||
|
||||
// GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122
|
||||
setGeometry(GEOMETRY_RAWMODE, 250, 122);
|
||||
// setGeometry(GEOMETRY_RAWMODE, 250, 122);
|
||||
|
||||
// GxEPD2_420_M01
|
||||
// setGeometry(GEOMETRY_RAWMODE, 300, 400);
|
||||
|
||||
// GxEPD2_290_T5D
|
||||
// setGeometry(GEOMETRY_RAWMODE, 296, 128);
|
||||
setGeometry(GEOMETRY_RAWMODE, 296, 128);
|
||||
|
||||
// GxEPD2_154_M09
|
||||
// setGeometry(GEOMETRY_RAWMODE, 200, 200);
|
||||
@@ -69,6 +69,11 @@ EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl, uint8_t screen_model
|
||||
// M5Stack_CoreInk 200x200
|
||||
// 1.54 inch 200x200 - GxEPD2_154_M09
|
||||
setGeometry(GEOMETRY_RAWMODE, EPD_HEIGHT, EPD_WIDTH);
|
||||
#elif defined(my)
|
||||
|
||||
// GxEPD2_290_T5D
|
||||
setGeometry(GEOMETRY_RAWMODE, 296, 128);
|
||||
LOG_DEBUG("GEOMETRY_RAWMODE, 296, 128\n");
|
||||
|
||||
#endif
|
||||
// setGeometry(GEOMETRY_RAWMODE, 128, 64); // old resolution
|
||||
@@ -109,7 +114,7 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
|
||||
#if defined(TTGO_T_ECHO)
|
||||
// ePaper.Reset(); // wake the screen from sleep
|
||||
adafruitDisplay->display(false); // FIXME, use partial update mode
|
||||
#elif defined(RAK4630)
|
||||
#elif defined(RAK4630) || defined(MAKERPYTHON)
|
||||
|
||||
// RAK14000 2.13 inch b/w 250x122 actually now does support partial updates
|
||||
|
||||
@@ -125,6 +130,10 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
|
||||
|
||||
#elif defined(PCA10059) || defined(M5_COREINK)
|
||||
adafruitDisplay->nextPage();
|
||||
|
||||
#elif defined(PRIVATE_HW) || defined(my)
|
||||
adafruitDisplay->nextPage();
|
||||
|
||||
#endif
|
||||
|
||||
// Put screen to sleep to save power (possibly not necessary because we already did poweroff inside of display)
|
||||
@@ -184,7 +193,7 @@ bool EInkDisplay::connect()
|
||||
adafruitDisplay->init();
|
||||
adafruitDisplay->setRotation(3);
|
||||
}
|
||||
#elif defined(RAK4630)
|
||||
#elif defined(RAK4630) || defined(MAKERPYTHON)
|
||||
{
|
||||
if (eink_found) {
|
||||
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
|
||||
@@ -216,6 +225,14 @@ bool EInkDisplay::connect()
|
||||
adafruitDisplay->init(115200, true, 40, false, SPI, SPISettings(4000000, MSBFIRST, SPI_MODE0));
|
||||
adafruitDisplay->setRotation(0);
|
||||
adafruitDisplay->setPartialWindow(0, 0, EPD_WIDTH, EPD_HEIGHT);
|
||||
#elif defined(my)
|
||||
{
|
||||
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
|
||||
adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
|
||||
adafruitDisplay->init(115200, true, 40, false, SPI, SPISettings(4000000, MSBFIRST, SPI_MODE0));
|
||||
adafruitDisplay->setRotation(1);
|
||||
adafruitDisplay->setPartialWindow(0, 0, EPD_WIDTH, EPD_HEIGHT);
|
||||
}
|
||||
#endif
|
||||
|
||||
// adafruitDisplay->setFullWindow();
|
||||
@@ -226,4 +243,4 @@ bool EInkDisplay::connect()
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -22,7 +22,7 @@ class EInkDisplay : public OLEDDisplay
|
||||
/* constructor
|
||||
FIXME - the parameters are not used, just a temporary hack to keep working like the old displays
|
||||
*/
|
||||
EInkDisplay(uint8_t address, int sda, int scl, uint8_t screen_model);
|
||||
EInkDisplay(uint8_t, int, int, OLEDDISPLAY_GEOMETRY, HW_I2C);
|
||||
|
||||
// Write the buffer to the display memory (for eink we only do this occasionally)
|
||||
virtual void display(void) override;
|
||||
|
||||
@@ -19,6 +19,7 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
#include "Screen.h"
|
||||
#include "configuration.h"
|
||||
#if HAS_SCREEN
|
||||
#include <OLEDDisplay.h>
|
||||
@@ -26,7 +27,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "GPS.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "Screen.h"
|
||||
#include "gps/GeoCoord.h"
|
||||
#include "gps/RTC.h"
|
||||
#include "graphics/images.h"
|
||||
@@ -50,6 +50,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "fonts/OLEDDisplayFontsRU.h"
|
||||
#endif
|
||||
|
||||
#ifdef OLED_UA
|
||||
#include "fonts/OLEDDisplayFontsUA.h"
|
||||
#endif
|
||||
|
||||
using namespace meshtastic; /** @todo remove */
|
||||
|
||||
namespace graphics
|
||||
@@ -70,6 +74,8 @@ static char btPIN[16] = "888888";
|
||||
|
||||
uint32_t logo_timeout = 5000; // 4 seconds for EACH logo
|
||||
|
||||
uint32_t hours_in_month = 730;
|
||||
|
||||
// This image definition is here instead of images.h because it's modified dynamically by the drawBattery function
|
||||
uint8_t imgBattery[16] = {0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xE7, 0x3C};
|
||||
|
||||
@@ -104,8 +110,12 @@ static uint16_t displayWidth, displayHeight;
|
||||
#ifdef OLED_RU
|
||||
#define FONT_SMALL ArialMT_Plain_10_RU
|
||||
#else
|
||||
#ifdef OLED_UA
|
||||
#define FONT_SMALL ArialMT_Plain_10_UA
|
||||
#else
|
||||
#define FONT_SMALL ArialMT_Plain_10 // Height: 13
|
||||
#endif
|
||||
#endif
|
||||
#define FONT_MEDIUM ArialMT_Plain_16 // Height: 19
|
||||
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
|
||||
#endif
|
||||
@@ -338,8 +348,6 @@ static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
/// Draw the last text message we received
|
||||
static void drawCriticalFaultFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
displayedNodeNum = 0; // Not currently showing a node pane
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(FONT_MEDIUM);
|
||||
|
||||
@@ -360,8 +368,6 @@ static bool shouldDrawMessage(const meshtastic_MeshPacket *packet)
|
||||
/// Draw the last text message we received
|
||||
static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
displayedNodeNum = 0; // Not currently showing a node pane
|
||||
|
||||
// the max length of this buffer is much longer than we can possibly print
|
||||
static char tempBuf[237];
|
||||
|
||||
@@ -386,10 +392,11 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
|
||||
uint32_t days = hours / 24;
|
||||
|
||||
if (config.display.heading_bold) {
|
||||
display->drawStringf(1 + x, 0 + y, tempBuf, "%s ago from %s", screen->drawTimeDelta(days, hours, minutes, seconds),
|
||||
display->drawStringf(1 + x, 0 + y, tempBuf, "%s ago from %s",
|
||||
screen->drawTimeDelta(days, hours, minutes, seconds).c_str(),
|
||||
(node && node->has_user) ? node->user.short_name : "???");
|
||||
}
|
||||
display->drawStringf(0 + x, 0 + y, tempBuf, "%s ago from %s", screen->drawTimeDelta(days, hours, minutes, seconds),
|
||||
display->drawStringf(0 + x, 0 + y, tempBuf, "%s ago from %s", screen->drawTimeDelta(days, hours, minutes, seconds).c_str(),
|
||||
(node && node->has_user) ? node->user.short_name : "???");
|
||||
|
||||
display->setColor(WHITE);
|
||||
@@ -507,18 +514,12 @@ static void drawGPS(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus
|
||||
// Draw status when gps is disabled by PMU
|
||||
static void drawGPSpowerstat(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
|
||||
{
|
||||
#ifdef HAS_PMU
|
||||
String displayLine = "GPS disabled";
|
||||
int16_t xPos = display->getStringWidth(displayLine);
|
||||
|
||||
if (!config.position.gps_enabled) {
|
||||
display->drawString(x + xPos, y, displayLine);
|
||||
#ifdef GPS_POWER_TOGGLE
|
||||
display->drawString(x + xPos, y - 2 + FONT_HEIGHT_SMALL, " by button");
|
||||
#endif
|
||||
// display->drawString(x + xPos, y + 2, displayLine);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void drawGPSAltitude(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
|
||||
@@ -768,7 +769,6 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
nodeIndex = (nodeIndex + 1) % nodeDB.getNumNodes();
|
||||
n = nodeDB.getNodeByIndex(nodeIndex);
|
||||
}
|
||||
displayedNodeNum = n->num;
|
||||
}
|
||||
|
||||
meshtastic_NodeInfo *node = nodeDB.getNodeByIndex(nodeIndex);
|
||||
@@ -794,9 +794,6 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
else if (agoSecs < 120 * 60) // last 2 hrs
|
||||
snprintf(lastStr, sizeof(lastStr), "%u minutes ago", agoSecs / 60);
|
||||
else {
|
||||
|
||||
uint32_t hours_in_month = 730;
|
||||
|
||||
// Only show hours ago if it's been less than 6 months. Otherwise, we may have bad
|
||||
// data.
|
||||
if ((agoSecs / 60 / 60) < (hours_in_month * 6)) {
|
||||
@@ -884,13 +881,11 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
// }
|
||||
// }
|
||||
// #else
|
||||
Screen::Screen(uint8_t address, int sda, int scl)
|
||||
: OSThread("Screen"), cmdQueue(32),
|
||||
dispdev(address, sda, scl,
|
||||
screen_model == meshtastic_Config_DisplayConfig_OledType_OLED_SH1107 ? GEOMETRY_128_128 : GEOMETRY_128_64),
|
||||
Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_OledType screenType, OLEDDISPLAY_GEOMETRY geometry)
|
||||
: concurrency::OSThread("Screen"), address_found(address), model(screenType), geometry(geometry), cmdQueue(32),
|
||||
dispdev(address.address, -1, -1, geometry, (address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE),
|
||||
ui(&dispdev)
|
||||
{
|
||||
address_found = address;
|
||||
cmdQueue.setReader(this);
|
||||
}
|
||||
// #endif
|
||||
@@ -938,9 +933,11 @@ void Screen::setup()
|
||||
useDisplay = true;
|
||||
|
||||
#ifdef AutoOLEDWire_h
|
||||
if (screen_model == meshtastic_Config_DisplayConfig_OledType_OLED_SH1107)
|
||||
screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1106;
|
||||
dispdev.setDetected(screen_model);
|
||||
dispdev.setDetected(model);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SH1107_128_64
|
||||
dispdev.setSubtype(7);
|
||||
#endif
|
||||
|
||||
// Initialising the UI will init the display too.
|
||||
@@ -1175,7 +1172,7 @@ void Screen::drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiStat
|
||||
* it is expected that this will be used during the boot phase */
|
||||
void Screen::setSSLFrames()
|
||||
{
|
||||
if (address_found) {
|
||||
if (address_found.address) {
|
||||
// LOG_DEBUG("showing SSL frames\n");
|
||||
static FrameCallback sslFrames[] = {drawSSLScreen};
|
||||
ui.setFrames(sslFrames, 1);
|
||||
@@ -1187,7 +1184,7 @@ void Screen::setSSLFrames()
|
||||
* it is expected that this will be used during the boot phase */
|
||||
void Screen::setWelcomeFrames()
|
||||
{
|
||||
if (address_found) {
|
||||
if (address_found.address) {
|
||||
// LOG_DEBUG("showing Welcome frames\n");
|
||||
ui.disableAllIndicators();
|
||||
|
||||
@@ -1336,17 +1333,20 @@ void Screen::blink()
|
||||
dispdev.setBrightness(brightness);
|
||||
}
|
||||
|
||||
String Screen::drawTimeDelta(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds)
|
||||
std::string Screen::drawTimeDelta(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds)
|
||||
{
|
||||
String uptime;
|
||||
if (days >= 2)
|
||||
uptime = String(days) + "d";
|
||||
std::string uptime;
|
||||
|
||||
if (days > (hours_in_month * 6))
|
||||
uptime = "?";
|
||||
else if (days >= 2)
|
||||
uptime = std::to_string(days) + "d";
|
||||
else if (hours >= 2)
|
||||
uptime = String(hours) + "h";
|
||||
uptime = std::to_string(hours) + "h";
|
||||
else if (minutes >= 1)
|
||||
uptime = String(minutes) + "m";
|
||||
uptime = std::to_string(minutes) + "m";
|
||||
else
|
||||
uptime = String(seconds) + "s";
|
||||
uptime = std::to_string(seconds) + "s";
|
||||
return uptime;
|
||||
}
|
||||
|
||||
@@ -1388,8 +1388,6 @@ void Screen::setFastFramerate()
|
||||
|
||||
void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
displayedNodeNum = 0; // Not currently showing a node pane
|
||||
|
||||
display->setFont(FONT_SMALL);
|
||||
|
||||
// The coordinates define the left starting point of the text
|
||||
@@ -1429,11 +1427,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
}
|
||||
// Display GPS status
|
||||
if (!config.position.gps_enabled) {
|
||||
int16_t yPos = y + 2;
|
||||
#ifdef GPS_POWER_TOGGLE
|
||||
yPos = (y + 10 + FONT_HEIGHT_SMALL);
|
||||
#endif
|
||||
drawGPSpowerstat(display, x, yPos, gpsStatus);
|
||||
drawGPSpowerstat(display, x, y + 2, gpsStatus);
|
||||
} else {
|
||||
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
|
||||
drawGPS(display, x + (SCREEN_WIDTH * 0.63), y + 2, gpsStatus);
|
||||
@@ -1501,8 +1495,6 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
#if HAS_WIFI
|
||||
const char *wifiName = config.network.wifi_ssid;
|
||||
|
||||
displayedNodeNum = 0; // Not currently showing a node pane
|
||||
|
||||
display->setFont(FONT_SMALL);
|
||||
|
||||
// The coordinates define the left starting point of the text
|
||||
@@ -1633,8 +1625,6 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
|
||||
void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
displayedNodeNum = 0; // Not currently showing a node pane
|
||||
|
||||
display->setFont(FONT_SMALL);
|
||||
|
||||
// The coordinates define the left starting point of the text
|
||||
@@ -1714,7 +1704,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
display->setColor(WHITE);
|
||||
|
||||
// Show uptime as days, hours, minutes OR seconds
|
||||
String uptime = screen->drawTimeDelta(days, hours, minutes, seconds);
|
||||
std::string uptime = screen->drawTimeDelta(days, hours, minutes, seconds);
|
||||
|
||||
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice);
|
||||
if (rtc_sec > 0) {
|
||||
@@ -1729,12 +1719,12 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN;
|
||||
int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN
|
||||
|
||||
char timebuf[9];
|
||||
char timebuf[10];
|
||||
snprintf(timebuf, sizeof(timebuf), " %02d:%02d:%02d", hour, min, sec);
|
||||
uptime += timebuf;
|
||||
}
|
||||
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, uptime);
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, uptime.c_str());
|
||||
|
||||
// Display Channel Utilization
|
||||
char chUtil[13];
|
||||
@@ -1750,6 +1740,9 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
drawGPScoordinates(display, x, y + FONT_HEIGHT_SMALL * 3, gpsStatus);
|
||||
} else {
|
||||
drawGPSpowerstat(display, x - (SCREEN_WIDTH / 4), y + FONT_HEIGHT_SMALL * 2, gpsStatus);
|
||||
#ifdef GPS_POWER_TOGGLE
|
||||
display->drawString(x + 30, (y + FONT_HEIGHT_SMALL * 3), " by button");
|
||||
#endif
|
||||
}
|
||||
/* Display a heartbeat pixel that blinks every time the frame is redrawn */
|
||||
#ifdef SHOW_REDRAWS
|
||||
@@ -1817,5 +1810,6 @@ int Screen::handleUIFrameEvent(const UIFrameEvent *event)
|
||||
}
|
||||
|
||||
} // namespace graphics
|
||||
|
||||
#else
|
||||
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
|
||||
#endif // HAS_SCREEN
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#include "detect/ScanI2C.h"
|
||||
#include "mesh/generated/meshtastic/config.pb.h"
|
||||
#include <OLEDDisplay.h>
|
||||
|
||||
#if !HAS_SCREEN
|
||||
#include "power.h"
|
||||
namespace graphics
|
||||
@@ -10,7 +14,7 @@ namespace graphics
|
||||
class Screen
|
||||
{
|
||||
public:
|
||||
explicit Screen(char) {}
|
||||
explicit Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY);
|
||||
void onPress() {}
|
||||
void setup() {}
|
||||
void setOn(bool) {}
|
||||
@@ -21,10 +25,10 @@ class Screen
|
||||
void startBluetoothPinScreen(uint32_t pin) {}
|
||||
void stopBluetoothPinScreen() {}
|
||||
void startRebootScreen() {}
|
||||
void startShutdownScreen() {}
|
||||
void startFirmwareUpdateScreen() {}
|
||||
};
|
||||
} // namespace graphics
|
||||
|
||||
#else
|
||||
#include <cstring>
|
||||
|
||||
@@ -34,7 +38,7 @@ class Screen
|
||||
|
||||
#ifdef USE_ST7567
|
||||
#include <ST7567Wire.h>
|
||||
#elif defined(USE_SH1106) || defined(USE_SH1107)
|
||||
#elif defined(USE_SH1106) || defined(USE_SH1107) || defined(USE_SH1107_128_64)
|
||||
#include <SH1106Wire.h>
|
||||
#elif defined(USE_SSD1306)
|
||||
#include <SSD1306Wire.h>
|
||||
@@ -116,12 +120,14 @@ class Screen : public concurrency::OSThread
|
||||
CallbackObserver<Screen, const UIFrameEvent *>(this, &Screen::handleUIFrameEvent);
|
||||
|
||||
public:
|
||||
explicit Screen(uint8_t address, int sda = -1, int scl = -1);
|
||||
explicit Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY);
|
||||
|
||||
Screen(const Screen &) = delete;
|
||||
Screen &operator=(const Screen &) = delete;
|
||||
|
||||
uint8_t address_found;
|
||||
ScanI2C::DeviceAddress address_found;
|
||||
meshtastic_Config_DisplayConfig_OledType model;
|
||||
OLEDDISPLAY_GEOMETRY geometry;
|
||||
|
||||
/// Initializes the UI, turns on the display, starts showing boot screen.
|
||||
//
|
||||
@@ -207,7 +213,7 @@ class Screen : public concurrency::OSThread
|
||||
}
|
||||
|
||||
/// generates a very brief time delta display
|
||||
String drawTimeDelta(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds);
|
||||
std::string drawTimeDelta(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds);
|
||||
|
||||
/// Overrides the default utf8 character conversion, to replace empty space with question marks
|
||||
static char customFontTableLookup(const uint8_t ch)
|
||||
@@ -240,6 +246,12 @@ class Screen : public concurrency::OSThread
|
||||
// library have empty chars for non-latin ASCII symbols
|
||||
case 0xD0: {
|
||||
SKIPREST = false;
|
||||
if (ch == 132)
|
||||
return (uint8_t)(170); // Є
|
||||
if (ch == 134)
|
||||
return (uint8_t)(178); // І
|
||||
if (ch == 135)
|
||||
return (uint8_t)(175); // Ї
|
||||
if (ch == 129)
|
||||
return (uint8_t)(168); // Ё
|
||||
if (ch > 143 && ch < 192)
|
||||
@@ -248,12 +260,26 @@ class Screen : public concurrency::OSThread
|
||||
}
|
||||
case 0xD1: {
|
||||
SKIPREST = false;
|
||||
if (ch == 148)
|
||||
return (uint8_t)(186); // є
|
||||
if (ch == 150)
|
||||
return (uint8_t)(179); // і
|
||||
if (ch == 151)
|
||||
return (uint8_t)(191); // ї
|
||||
if (ch == 145)
|
||||
return (uint8_t)(184); // ё
|
||||
if (ch > 127 && ch < 144)
|
||||
return (uint8_t)(ch + 112);
|
||||
break;
|
||||
}
|
||||
case 0xD2: {
|
||||
SKIPREST = false;
|
||||
if (ch == 144)
|
||||
return (uint8_t)(165); // Ґ
|
||||
if (ch == 145)
|
||||
return (uint8_t)(180); // ґ
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We want to strip out prefix chars for two-byte char formats
|
||||
@@ -350,7 +376,7 @@ class Screen : public concurrency::OSThread
|
||||
|
||||
/// Display device
|
||||
|
||||
#if defined(USE_SH1106) || defined(USE_SH1107)
|
||||
#if defined(USE_SH1106) || defined(USE_SH1107) || defined(USE_SH1107_128_64)
|
||||
SH1106Wire dispdev;
|
||||
#elif defined(USE_SSD1306)
|
||||
SSD1306Wire dispdev;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
static TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h
|
||||
|
||||
TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, uint8_t screen_model)
|
||||
TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus)
|
||||
{
|
||||
#ifdef SCREEN_ROTATE
|
||||
setGeometry(GEOMETRY_RAWMODE, TFT_HEIGHT, TFT_WIDTH);
|
||||
|
||||
@@ -18,7 +18,7 @@ class TFTDisplay : public OLEDDisplay
|
||||
/* constructor
|
||||
FIXME - the parameters are not used, just a temporary hack to keep working like the old displays
|
||||
*/
|
||||
TFTDisplay(uint8_t address, int sda, int scl, uint8_t screen_model);
|
||||
TFTDisplay(uint8_t, int, int, OLEDDISPLAY_GEOMETRY, HW_I2C);
|
||||
|
||||
// Write the buffer to the display memory
|
||||
virtual void display(void) override;
|
||||
|
||||
424
src/graphics/fonts/OLEDDisplayFontsUA.cpp
Normal file
424
src/graphics/fonts/OLEDDisplayFontsUA.cpp
Normal file
@@ -0,0 +1,424 @@
|
||||
#include "OLEDDisplayFontsUA.h"
|
||||
|
||||
// Font generated or edited with the glyphEditor
|
||||
const uint8_t ArialMT_Plain_10_UA[] PROGMEM = {
|
||||
0x0A, // Width: 10
|
||||
0x0D, // Height: 13
|
||||
0x20, // First char: 32
|
||||
0xE0, // Number of chars: 224
|
||||
// Jump Table:
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 32
|
||||
0x00, 0x00, 0x04, 0x03, // 33
|
||||
0x00, 0x04, 0x05, 0x04, // 34
|
||||
0x00, 0x09, 0x09, 0x06, // 35
|
||||
0x00, 0x12, 0x0A, 0x06, // 36
|
||||
0x00, 0x1C, 0x10, 0x09, // 37
|
||||
0x00, 0x2C, 0x0E, 0x08, // 38
|
||||
0x00, 0x3A, 0x01, 0x02, // 39
|
||||
0x00, 0x3B, 0x06, 0x04, // 40
|
||||
0x00, 0x41, 0x06, 0x04, // 41
|
||||
0x00, 0x47, 0x05, 0x04, // 42
|
||||
0x00, 0x4C, 0x09, 0x06, // 43
|
||||
0x00, 0x55, 0x04, 0x03, // 44
|
||||
0x00, 0x59, 0x03, 0x03, // 45
|
||||
0x00, 0x5C, 0x04, 0x03, // 46
|
||||
0x00, 0x60, 0x05, 0x04, // 47
|
||||
0x00, 0x65, 0x0A, 0x06, // 48
|
||||
0x00, 0x6F, 0x08, 0x05, // 49
|
||||
0x00, 0x77, 0x0A, 0x06, // 50
|
||||
0x00, 0x81, 0x0A, 0x06, // 51
|
||||
0x00, 0x8B, 0x0B, 0x07, // 52
|
||||
0x00, 0x96, 0x0A, 0x06, // 53
|
||||
0x00, 0xA0, 0x0A, 0x06, // 54
|
||||
0x00, 0xAA, 0x09, 0x06, // 55
|
||||
0x00, 0xB3, 0x0A, 0x06, // 56
|
||||
0x00, 0xBD, 0x0A, 0x06, // 57
|
||||
0x00, 0xC7, 0x04, 0x03, // 58
|
||||
0x00, 0xCB, 0x04, 0x03, // 59
|
||||
0x00, 0xCF, 0x0A, 0x06, // 60
|
||||
0x00, 0xD9, 0x09, 0x06, // 61
|
||||
0x00, 0xE2, 0x09, 0x06, // 62
|
||||
0x00, 0xEB, 0x0B, 0x07, // 63
|
||||
0x00, 0xF6, 0x14, 0x0B, // 64
|
||||
0x01, 0x0A, 0x0E, 0x08, // 65
|
||||
0x01, 0x18, 0x0C, 0x07, // 66
|
||||
0x01, 0x24, 0x0C, 0x07, // 67
|
||||
0x01, 0x30, 0x0B, 0x07, // 68
|
||||
0x01, 0x3B, 0x0C, 0x07, // 69
|
||||
0x01, 0x47, 0x09, 0x06, // 70
|
||||
0x01, 0x50, 0x0D, 0x08, // 71
|
||||
0x01, 0x5D, 0x0C, 0x07, // 72
|
||||
0x01, 0x69, 0x04, 0x03, // 73
|
||||
0x01, 0x6D, 0x08, 0x05, // 74
|
||||
0x01, 0x75, 0x0E, 0x08, // 75
|
||||
0x01, 0x83, 0x0C, 0x07, // 76
|
||||
0x01, 0x8F, 0x10, 0x09, // 77
|
||||
0x01, 0x9F, 0x0C, 0x07, // 78
|
||||
0x01, 0xAB, 0x0E, 0x08, // 79
|
||||
0x01, 0xB9, 0x0B, 0x07, // 80
|
||||
0x01, 0xC4, 0x0E, 0x08, // 81
|
||||
0x01, 0xD2, 0x0C, 0x07, // 82
|
||||
0x01, 0xDE, 0x0C, 0x07, // 83
|
||||
0x01, 0xEA, 0x0B, 0x07, // 84
|
||||
0x01, 0xF5, 0x0C, 0x07, // 85
|
||||
0x02, 0x01, 0x0D, 0x08, // 86
|
||||
0x02, 0x0E, 0x11, 0x0A, // 87
|
||||
0x02, 0x1F, 0x0E, 0x08, // 88
|
||||
0x02, 0x2D, 0x0D, 0x08, // 89
|
||||
0x02, 0x3A, 0x0C, 0x07, // 90
|
||||
0x02, 0x46, 0x06, 0x04, // 91
|
||||
0x02, 0x4C, 0x06, 0x04, // 92
|
||||
0x02, 0x52, 0x04, 0x03, // 93
|
||||
0x02, 0x56, 0x09, 0x06, // 94
|
||||
0x02, 0x5F, 0x0C, 0x07, // 95
|
||||
0x02, 0x6B, 0x03, 0x03, // 96
|
||||
0x02, 0x6E, 0x0A, 0x06, // 97
|
||||
0x02, 0x78, 0x0A, 0x06, // 98
|
||||
0x02, 0x82, 0x0A, 0x06, // 99
|
||||
0x02, 0x8C, 0x0A, 0x06, // 100
|
||||
0x02, 0x96, 0x0A, 0x06, // 101
|
||||
0x02, 0xA0, 0x05, 0x04, // 102
|
||||
0x02, 0xA5, 0x0A, 0x06, // 103
|
||||
0x02, 0xAF, 0x0A, 0x06, // 104
|
||||
0x02, 0xB9, 0x04, 0x03, // 105
|
||||
0x02, 0xBD, 0x04, 0x03, // 106
|
||||
0x02, 0xC1, 0x08, 0x05, // 107
|
||||
0x02, 0xC9, 0x04, 0x03, // 108
|
||||
0x02, 0xCD, 0x10, 0x09, // 109
|
||||
0x02, 0xDD, 0x0A, 0x06, // 110
|
||||
0x02, 0xE7, 0x0A, 0x06, // 111
|
||||
0x02, 0xF1, 0x0A, 0x06, // 112
|
||||
0x02, 0xFB, 0x0A, 0x06, // 113
|
||||
0x03, 0x05, 0x05, 0x04, // 114
|
||||
0x03, 0x0A, 0x08, 0x05, // 115
|
||||
0x03, 0x12, 0x06, 0x04, // 116
|
||||
0x03, 0x18, 0x0A, 0x06, // 117
|
||||
0x03, 0x22, 0x09, 0x06, // 118
|
||||
0x03, 0x2B, 0x0E, 0x08, // 119
|
||||
0x03, 0x39, 0x0A, 0x06, // 120
|
||||
0x03, 0x43, 0x09, 0x06, // 121
|
||||
0x03, 0x4C, 0x0A, 0x06, // 122
|
||||
0x03, 0x56, 0x06, 0x04, // 123
|
||||
0x03, 0x5C, 0x04, 0x03, // 124
|
||||
0x03, 0x60, 0x05, 0x04, // 125
|
||||
0x03, 0x65, 0x09, 0x06, // 126
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 127
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 128
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 129
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 130
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 131
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 132
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 133
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 134
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 135
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 136
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 137
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 138
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 139
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 140
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 141
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 142
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 143
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 144
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 145
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 146
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 147
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 148
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 149
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 150
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 151
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 152
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 153
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 154
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 155
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 156
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 157
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 158
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 159
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 160
|
||||
0x03, 0x6E, 0x04, 0x03, // 161
|
||||
0x03, 0x72, 0x0A, 0x06, // 162
|
||||
0x03, 0x7C, 0x0C, 0x07, // 163
|
||||
0x03, 0x88, 0x0A, 0x06, // 164
|
||||
0x03, 0x92, 0x09, 0x06, // 165
|
||||
0x03, 0x9B, 0x04, 0x03, // 166
|
||||
0x03, 0x9F, 0x0A, 0x06, // 167
|
||||
0x03, 0xA9, 0x0C, 0x07, // 168
|
||||
0x03, 0xB5, 0x0D, 0x08, // 169
|
||||
0x03, 0xC2, 0x0C, 0x07, // 170
|
||||
0x03, 0xCE, 0x0A, 0x06, // 171
|
||||
0x03, 0xD8, 0x09, 0x06, // 172
|
||||
0x03, 0xE1, 0x03, 0x03, // 173
|
||||
0x03, 0xE4, 0x0D, 0x08, // 174
|
||||
0x03, 0xF1, 0x0C, 0x07, // 175
|
||||
0x03, 0xFD, 0x07, 0x05, // 176
|
||||
0x04, 0x04, 0x0A, 0x06, // 177
|
||||
0x04, 0x0E, 0x0C, 0x07, // 178
|
||||
0x04, 0x1A, 0x0C, 0x07, // 179
|
||||
0x04, 0x26, 0x07, 0x05, // 180
|
||||
0x04, 0x2D, 0x0A, 0x06, // 181
|
||||
0x04, 0x37, 0x09, 0x06, // 182
|
||||
0x04, 0x40, 0x03, 0x03, // 183
|
||||
0x04, 0x43, 0x0B, 0x07, // 184
|
||||
0x04, 0x4E, 0x0B, 0x07, // 185
|
||||
0x04, 0x59, 0x0C, 0x07, // 186
|
||||
0x04, 0x65, 0x0A, 0x06, // 187
|
||||
0x04, 0x6F, 0x10, 0x09, // 188
|
||||
0x04, 0x7F, 0x10, 0x09, // 189
|
||||
0x04, 0x8F, 0x10, 0x09, // 190
|
||||
0x04, 0x9F, 0x0A, 0x06, // 191
|
||||
0x04, 0xA9, 0x0C, 0x07, // 192
|
||||
0x04, 0xB5, 0x0C, 0x07, // 193
|
||||
0x04, 0xC1, 0x0C, 0x07, // 194
|
||||
0x04, 0xCD, 0x0B, 0x07, // 195
|
||||
0x04, 0xD8, 0x0C, 0x07, // 196
|
||||
0x04, 0xE4, 0x0C, 0x07, // 197
|
||||
0x04, 0xF0, 0x0C, 0x07, // 198
|
||||
0x04, 0xFC, 0x0C, 0x07, // 199
|
||||
0x05, 0x08, 0x0C, 0x07, // 200
|
||||
0x05, 0x14, 0x0C, 0x07, // 201
|
||||
0x05, 0x20, 0x0C, 0x07, // 202
|
||||
0x05, 0x2C, 0x0C, 0x07, // 203
|
||||
0x05, 0x38, 0x0C, 0x07, // 204
|
||||
0x05, 0x44, 0x0C, 0x07, // 205
|
||||
0x05, 0x50, 0x0C, 0x07, // 206
|
||||
0x05, 0x5C, 0x0C, 0x07, // 207
|
||||
0x05, 0x68, 0x0B, 0x07, // 208
|
||||
0x05, 0x73, 0x0C, 0x07, // 209
|
||||
0x05, 0x7F, 0x0B, 0x07, // 210
|
||||
0x05, 0x8A, 0x0C, 0x07, // 211
|
||||
0x05, 0x96, 0x0B, 0x07, // 212
|
||||
0x05, 0xA1, 0x0C, 0x07, // 213
|
||||
0x05, 0xAD, 0x0C, 0x07, // 214
|
||||
0x05, 0xB9, 0x0C, 0x07, // 215
|
||||
0x05, 0xC5, 0x0C, 0x07, // 216
|
||||
0x05, 0xD1, 0x0E, 0x08, // 217
|
||||
0x05, 0xDF, 0x0C, 0x07, // 218
|
||||
0x05, 0xEB, 0x0C, 0x07, // 219
|
||||
0x05, 0xF7, 0x0C, 0x07, // 220
|
||||
0x06, 0x03, 0x0C, 0x07, // 221
|
||||
0x06, 0x0F, 0x0C, 0x07, // 222
|
||||
0x06, 0x1B, 0x0C, 0x07, // 223
|
||||
0x06, 0x27, 0x0C, 0x07, // 224
|
||||
0x06, 0x33, 0x0C, 0x07, // 225
|
||||
0x06, 0x3F, 0x0C, 0x07, // 226
|
||||
0x06, 0x4B, 0x0B, 0x07, // 227
|
||||
0x06, 0x56, 0x0C, 0x07, // 228
|
||||
0x06, 0x62, 0x0B, 0x07, // 229
|
||||
0x06, 0x6D, 0x0C, 0x07, // 230
|
||||
0x06, 0x79, 0x0C, 0x07, // 231
|
||||
0x06, 0x85, 0x0C, 0x07, // 232
|
||||
0x06, 0x91, 0x0C, 0x07, // 233
|
||||
0x06, 0x9D, 0x0C, 0x07, // 234
|
||||
0x06, 0xA9, 0x0C, 0x07, // 235
|
||||
0x06, 0xB5, 0x0C, 0x07, // 236
|
||||
0x06, 0xC1, 0x0C, 0x07, // 237
|
||||
0x06, 0xCD, 0x0C, 0x07, // 238
|
||||
0x06, 0xD9, 0x0C, 0x07, // 239
|
||||
0x06, 0xE5, 0x0B, 0x07, // 240
|
||||
0x06, 0xF0, 0x0C, 0x07, // 241
|
||||
0x06, 0xFC, 0x0B, 0x07, // 242
|
||||
0x07, 0x07, 0x0C, 0x07, // 243
|
||||
0x07, 0x13, 0x0B, 0x07, // 244
|
||||
0x07, 0x1E, 0x0C, 0x07, // 245
|
||||
0x07, 0x2A, 0x0C, 0x07, // 246
|
||||
0x07, 0x36, 0x0C, 0x07, // 247
|
||||
0x07, 0x42, 0x0C, 0x07, // 248
|
||||
0x07, 0x4E, 0x0E, 0x08, // 249
|
||||
0x07, 0x5C, 0x0C, 0x07, // 250
|
||||
0x07, 0x68, 0x0C, 0x07, // 251
|
||||
0x07, 0x74, 0x0C, 0x07, // 252
|
||||
0x07, 0x80, 0x0C, 0x07, // 253
|
||||
0x07, 0x8C, 0x0C, 0x07, // 254
|
||||
0x07, 0x98, 0x0C, 0x07, // 255
|
||||
// Font Data:
|
||||
0x00, 0x00, 0xF8, 0x02, // 33
|
||||
0x38, 0x00, 0x00, 0x00, 0x38, // 34
|
||||
0xA0, 0x03, 0xE0, 0x00, 0xB8, 0x03, 0xE0, 0x00, 0xB8, // 35
|
||||
0x30, 0x01, 0x28, 0x02, 0xF8, 0x07, 0x48, 0x02, 0x90, 0x01, // 36
|
||||
0x00, 0x00, 0x30, 0x00, 0x48, 0x00, 0x30, 0x03, 0xC0, 0x00, 0xB0, 0x01, 0x48, 0x02, 0x80, 0x01, // 37
|
||||
0x80, 0x01, 0x50, 0x02, 0x68, 0x02, 0xA8, 0x02, 0x18, 0x01, 0x80, 0x03, 0x80, 0x02, // 38
|
||||
0x38, // 39
|
||||
0xE0, 0x03, 0x10, 0x04, 0x08, 0x08, // 40
|
||||
0x08, 0x08, 0x10, 0x04, 0xE0, 0x03, // 41
|
||||
0x28, 0x00, 0x18, 0x00, 0x28, // 42
|
||||
0x40, 0x00, 0x40, 0x00, 0xF0, 0x01, 0x40, 0x00, 0x40, // 43
|
||||
0x00, 0x00, 0x00, 0x06, // 44
|
||||
0x80, 0x00, 0x80, // 45
|
||||
0x00, 0x00, 0x00, 0x02, // 46
|
||||
0x00, 0x03, 0xE0, 0x00, 0x18, // 47
|
||||
0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0xF0, 0x01, // 48
|
||||
0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0xF8, 0x03, // 49
|
||||
0x10, 0x02, 0x08, 0x03, 0x88, 0x02, 0x48, 0x02, 0x30, 0x02, // 50
|
||||
0x10, 0x01, 0x08, 0x02, 0x48, 0x02, 0x48, 0x02, 0xB0, 0x01, // 51
|
||||
0xC0, 0x00, 0xA0, 0x00, 0x90, 0x00, 0x88, 0x00, 0xF8, 0x03, 0x80, // 52
|
||||
0x60, 0x01, 0x38, 0x02, 0x28, 0x02, 0x28, 0x02, 0xC8, 0x01, // 53
|
||||
0xF0, 0x01, 0x28, 0x02, 0x28, 0x02, 0x28, 0x02, 0xD0, 0x01, // 54
|
||||
0x08, 0x00, 0x08, 0x03, 0xC8, 0x00, 0x38, 0x00, 0x08, // 55
|
||||
0xB0, 0x01, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0xB0, 0x01, // 56
|
||||
0x70, 0x01, 0x88, 0x02, 0x88, 0x02, 0x88, 0x02, 0xF0, 0x01, // 57
|
||||
0x00, 0x00, 0x20, 0x02, // 58
|
||||
0x00, 0x00, 0x20, 0x06, // 59
|
||||
0x00, 0x00, 0x40, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0x10, 0x01, // 60
|
||||
0xA0, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0xA0, // 61
|
||||
0x00, 0x00, 0x10, 0x01, 0xA0, 0x00, 0xA0, 0x00, 0x40, // 62
|
||||
0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0xC8, 0x02, 0x48, 0x00, 0x30, // 63
|
||||
0x00, 0x00, 0xC0, 0x03, 0x30, 0x04, 0xD0, 0x09, 0x28, 0x0A, 0x28, 0x0A, 0xC8, 0x0B, 0x68, 0x0A, 0x10, 0x05, 0xE0, 0x04, // 64
|
||||
0x00, 0x02, 0xC0, 0x01, 0xB0, 0x00, 0x88, 0x00, 0xB0, 0x00, 0xC0, 0x01, 0x00, 0x02, // 65
|
||||
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0xF0, 0x01, // 66
|
||||
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x10, 0x01, // 67
|
||||
0x00, 0x00, 0xF8, 0x03, 0x08, 0x02, 0x08, 0x02, 0x10, 0x01, 0xE0, // 68
|
||||
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, // 69
|
||||
0x00, 0x00, 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0x08, // 70
|
||||
0x00, 0x00, 0xE0, 0x00, 0x10, 0x01, 0x08, 0x02, 0x48, 0x02, 0x50, 0x01, 0xC0, // 71
|
||||
0x00, 0x00, 0xF8, 0x03, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xF8, 0x03, // 72
|
||||
0x00, 0x00, 0xF8, 0x03, // 73
|
||||
0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0xF8, 0x01, // 74
|
||||
0x00, 0x00, 0xF8, 0x03, 0x80, 0x00, 0x60, 0x00, 0x90, 0x00, 0x08, 0x01, 0x00, 0x02, // 75
|
||||
0x00, 0x00, 0xF8, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, // 76
|
||||
0x00, 0x00, 0xF8, 0x03, 0x30, 0x00, 0xC0, 0x01, 0x00, 0x02, 0xC0, 0x01, 0x30, 0x00, 0xF8, 0x03, // 77
|
||||
0x00, 0x00, 0xF8, 0x03, 0x30, 0x00, 0x40, 0x00, 0x80, 0x01, 0xF8, 0x03, // 78
|
||||
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0xF0, 0x01, // 79
|
||||
0x00, 0x00, 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, // 80
|
||||
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x03, 0x08, 0x03, 0xF0, 0x02, // 81
|
||||
0x00, 0x00, 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0xC8, 0x00, 0x30, 0x03, // 82
|
||||
0x00, 0x00, 0x30, 0x01, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x90, 0x01, // 83
|
||||
0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, // 84
|
||||
0x00, 0x00, 0xF8, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0xF8, 0x01, // 85
|
||||
0x08, 0x00, 0x70, 0x00, 0x80, 0x01, 0x00, 0x02, 0x80, 0x01, 0x70, 0x00, 0x08, // 86
|
||||
0x18, 0x00, 0xE0, 0x01, 0x00, 0x02, 0xF0, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x00, 0x02, 0xE0, 0x01, 0x18, // 87
|
||||
0x00, 0x02, 0x08, 0x01, 0x90, 0x00, 0x60, 0x00, 0x90, 0x00, 0x08, 0x01, 0x00, 0x02, // 88
|
||||
0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0xC0, 0x03, 0x20, 0x00, 0x10, 0x00, 0x08, // 89
|
||||
0x08, 0x03, 0x88, 0x02, 0xC8, 0x02, 0x68, 0x02, 0x38, 0x02, 0x18, 0x02, // 90
|
||||
0x00, 0x00, 0xF8, 0x0F, 0x08, 0x08, // 91
|
||||
0x18, 0x00, 0xE0, 0x00, 0x00, 0x03, // 92
|
||||
0x08, 0x08, 0xF8, 0x0F, // 93
|
||||
0x40, 0x00, 0x30, 0x00, 0x08, 0x00, 0x30, 0x00, 0x40, // 94
|
||||
0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, // 95
|
||||
0x08, 0x00, 0x10, // 96
|
||||
0x00, 0x00, 0x00, 0x03, 0xA0, 0x02, 0xA0, 0x02, 0xE0, 0x03, // 97
|
||||
0x00, 0x00, 0xF8, 0x03, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 98
|
||||
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0x40, 0x01, // 99
|
||||
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0xF8, 0x03, // 100
|
||||
0x00, 0x00, 0xC0, 0x01, 0xA0, 0x02, 0xA0, 0x02, 0xC0, 0x02, // 101
|
||||
0x20, 0x00, 0xF0, 0x03, 0x28, // 102
|
||||
0x00, 0x00, 0xC0, 0x05, 0x20, 0x0A, 0x20, 0x0A, 0xE0, 0x07, // 103
|
||||
0x00, 0x00, 0xF8, 0x03, 0x20, 0x00, 0x20, 0x00, 0xC0, 0x03, // 104
|
||||
0x00, 0x00, 0xE8, 0x03, // 105
|
||||
0x00, 0x08, 0xE8, 0x07, // 106
|
||||
0xF8, 0x03, 0x80, 0x00, 0xC0, 0x01, 0x20, 0x02, // 107
|
||||
0x00, 0x00, 0xF8, 0x03, // 108
|
||||
0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0xC0, 0x03, // 109
|
||||
0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0xC0, 0x03, // 110
|
||||
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 111
|
||||
0x00, 0x00, 0xE0, 0x0F, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 112
|
||||
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0xE0, 0x0F, // 113
|
||||
0x00, 0x00, 0xE0, 0x03, 0x20, // 114
|
||||
0x40, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0x20, 0x01, // 115
|
||||
0x20, 0x00, 0xF8, 0x03, 0x20, 0x02, // 116
|
||||
0x00, 0x00, 0xE0, 0x01, 0x00, 0x02, 0x00, 0x02, 0xE0, 0x03, // 117
|
||||
0x20, 0x00, 0xC0, 0x01, 0x00, 0x02, 0xC0, 0x01, 0x20, // 118
|
||||
0xE0, 0x01, 0x00, 0x02, 0xC0, 0x01, 0x20, 0x00, 0xC0, 0x01, 0x00, 0x02, 0xE0, 0x01, // 119
|
||||
0x20, 0x02, 0x40, 0x01, 0x80, 0x00, 0x40, 0x01, 0x20, 0x02, // 120
|
||||
0x20, 0x00, 0xC0, 0x09, 0x00, 0x06, 0xC0, 0x01, 0x20, // 121
|
||||
0x20, 0x02, 0x20, 0x03, 0xA0, 0x02, 0x60, 0x02, 0x20, 0x02, // 122
|
||||
0x80, 0x00, 0x78, 0x0F, 0x08, 0x08, // 123
|
||||
0x00, 0x00, 0xF8, 0x0F, // 124
|
||||
0x08, 0x08, 0x78, 0x0F, 0x80, // 125
|
||||
0xC0, 0x00, 0x40, 0x00, 0xC0, 0x00, 0x80, 0x00, 0xC0, // 126
|
||||
0x00, 0x00, 0xA0, 0x0F, // 161
|
||||
0x00, 0x00, 0xC0, 0x01, 0xA0, 0x0F, 0x78, 0x02, 0x40, 0x01, // 162
|
||||
0x40, 0x02, 0x70, 0x03, 0xC8, 0x02, 0x48, 0x02, 0x08, 0x02, 0x10, 0x02, // 163
|
||||
0x00, 0x00, 0xE0, 0x01, 0x20, 0x01, 0x20, 0x01, 0xE0, 0x01, // 164
|
||||
0x00, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, 0x00, 0x0C, // 165
|
||||
0x00, 0x00, 0x38, 0x0F, // 166
|
||||
0xD0, 0x04, 0x28, 0x09, 0x48, 0x09, 0x48, 0x0A, 0x90, 0x05, // 167
|
||||
0x00, 0x00, 0xE0, 0x03, 0xA8, 0x02, 0xA0, 0x02, 0xA8, 0x02, 0x20, 0x02, // 168
|
||||
0xE0, 0x00, 0x10, 0x01, 0x48, 0x02, 0xA8, 0x02, 0xA8, 0x02, 0x10, 0x01, 0xE0, // 169
|
||||
0x00, 0x00, 0xF0, 0x01, 0x58, 0x03, 0x48, 0x02, 0x08, 0x02, 0x10, 0x01, // 170
|
||||
0x00, 0x00, 0x80, 0x01, 0x40, 0x02, 0x80, 0x01, 0x40, 0x02, // 171
|
||||
0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xE0, // 172
|
||||
0x80, 0x00, 0x80, // 173
|
||||
0xE0, 0x00, 0x10, 0x01, 0xE8, 0x02, 0x68, 0x02, 0xC8, 0x02, 0x10, 0x01, 0xE0, // 174
|
||||
0x00, 0x00, 0x08, 0x02, 0x0A, 0x02, 0xF8, 0x03, 0x0A, 0x02, 0x08, 0x02, // 175
|
||||
0x00, 0x00, 0x38, 0x00, 0x28, 0x00, 0x38, // 176
|
||||
0x40, 0x02, 0x40, 0x02, 0xF0, 0x03, 0x40, 0x02, 0x40, 0x02, // 177
|
||||
0x00, 0x00, 0x08, 0x02, 0x08, 0x02, 0xF8, 0x03, 0x08, 0x02, 0x08, 0x02, // 178
|
||||
0x00, 0x00, 0x20, 0x02, 0x20, 0x02, 0xE8, 0x03, 0x20, 0x02, 0x20, 0x02, // 179
|
||||
0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x30, // 180
|
||||
0x00, 0x00, 0xE0, 0x0F, 0x00, 0x02, 0x00, 0x02, 0xE0, 0x03, // 181
|
||||
0x70, 0x00, 0xF8, 0x0F, 0x08, 0x00, 0xF8, 0x0F, 0x08, // 182
|
||||
0x00, 0x00, 0x40, // 183
|
||||
0x00, 0x00, 0xC0, 0x01, 0xA8, 0x02, 0xA0, 0x02, 0xA8, 0x02, 0xC0, // 184
|
||||
0x00, 0x00, 0xF0, 0x03, 0x40, 0x00, 0x80, 0x00, 0xF8, 0x03, 0x08, // 185
|
||||
0x00, 0x00, 0xE0, 0x01, 0x50, 0x02, 0x50, 0x02, 0x10, 0x02, 0x20, 0x01, // 186
|
||||
0x00, 0x00, 0x40, 0x02, 0x80, 0x01, 0x40, 0x02, 0x80, 0x01, // 187
|
||||
0x00, 0x00, 0x10, 0x02, 0x78, 0x01, 0xC0, 0x00, 0x20, 0x01, 0x90, 0x01, 0xC8, 0x03, 0x00, 0x01, // 188
|
||||
0x00, 0x00, 0x10, 0x02, 0x78, 0x01, 0x80, 0x00, 0x60, 0x00, 0x50, 0x02, 0x48, 0x03, 0xC0, 0x02, // 189
|
||||
0x48, 0x00, 0x58, 0x00, 0x68, 0x03, 0x80, 0x00, 0x60, 0x01, 0x90, 0x01, 0xC8, 0x03, 0x00, 0x01, // 190
|
||||
0x00, 0x00, 0x00, 0x00, 0x28, 0x02, 0xE0, 0x03, 0x28, 0x02, // 191
|
||||
0x00, 0x00, 0xF0, 0x03, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0xF0, 0x03, // 192
|
||||
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x88, 0x01, // 193
|
||||
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0xB0, 0x01, // 194
|
||||
0x00, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x18, // 195
|
||||
0x00, 0x00, 0x00, 0x02, 0xFC, 0x03, 0x04, 0x02, 0xFC, 0x03, 0x00, 0x02, // 196
|
||||
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x08, 0x02, // 197
|
||||
0x00, 0x00, 0xB8, 0x03, 0x40, 0x00, 0xF8, 0x03, 0x40, 0x00, 0xB8, 0x03, // 198
|
||||
0x00, 0x00, 0x08, 0x02, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0xB0, 0x01, // 199
|
||||
0x00, 0x00, 0xF8, 0x03, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0xF8, 0x03, // 200
|
||||
0x00, 0x00, 0xE0, 0x03, 0x08, 0x01, 0x90, 0x00, 0x48, 0x00, 0xE0, 0x03, // 201
|
||||
0x00, 0x00, 0xF8, 0x03, 0x40, 0x00, 0xA0, 0x00, 0x10, 0x01, 0x08, 0x02, // 202
|
||||
0x00, 0x00, 0x00, 0x02, 0xF0, 0x01, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, // 203
|
||||
0x00, 0x00, 0xF8, 0x03, 0x10, 0x00, 0x60, 0x00, 0x10, 0x00, 0xF8, 0x03, // 204
|
||||
0x00, 0x00, 0xF8, 0x03, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xF8, 0x03, // 205
|
||||
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0xF0, 0x01, // 206
|
||||
0x00, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, // 207
|
||||
0x00, 0x00, 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, // 208
|
||||
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x10, 0x01, // 209
|
||||
0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, // 210
|
||||
0x00, 0x00, 0x38, 0x00, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0xF8, 0x01, // 211
|
||||
0x00, 0x00, 0x70, 0x00, 0x88, 0x00, 0xF8, 0x03, 0x88, 0x00, 0x70, // 212
|
||||
0x00, 0x00, 0x18, 0x03, 0xA0, 0x00, 0x40, 0x00, 0xA0, 0x00, 0x18, 0x03, // 213
|
||||
0x00, 0x00, 0xF8, 0x03, 0x00, 0x02, 0x00, 0x02, 0xF8, 0x03, 0x00, 0x02, // 214
|
||||
0x00, 0x00, 0x38, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xF8, 0x03, // 215
|
||||
0x00, 0x00, 0xF8, 0x03, 0x00, 0x02, 0xF8, 0x03, 0x00, 0x02, 0xF8, 0x03, // 216
|
||||
0x00, 0x00, 0xF8, 0x03, 0x00, 0x02, 0xF8, 0x03, 0x00, 0x02, 0xF8, 0x03, 0x00, 0x06, // 217
|
||||
0x00, 0x00, 0x08, 0x00, 0xF8, 0x03, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, // 218
|
||||
0x00, 0x00, 0xF8, 0x03, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, 0xF8, 0x03, // 219
|
||||
0x00, 0x00, 0xF8, 0x03, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, // 220
|
||||
0x00, 0x00, 0x10, 0x01, 0x08, 0x02, 0x48, 0x02, 0x48, 0x02, 0xF0, 0x01, // 221
|
||||
0x00, 0x00, 0xF8, 0x03, 0x40, 0x00, 0xF0, 0x01, 0x08, 0x02, 0xF0, 0x01, // 222
|
||||
0x00, 0x00, 0x30, 0x02, 0x48, 0x01, 0xC8, 0x00, 0x48, 0x00, 0xF8, 0x03, // 223
|
||||
0x00, 0x00, 0x00, 0x01, 0xA0, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0xC0, 0x03, // 224
|
||||
0x00, 0x00, 0xE0, 0x01, 0x50, 0x02, 0x50, 0x02, 0x48, 0x02, 0x88, 0x01, // 225
|
||||
0x00, 0x00, 0xE0, 0x03, 0xA0, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0x40, 0x01, // 226
|
||||
0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x60, // 227
|
||||
0x00, 0x00, 0x00, 0x02, 0xC0, 0x03, 0x20, 0x02, 0xE0, 0x03, 0x00, 0x02, // 228
|
||||
0x00, 0x00, 0xC0, 0x01, 0xA0, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0xC0, // 229
|
||||
0x00, 0x00, 0x60, 0x03, 0x80, 0x00, 0xE0, 0x03, 0x80, 0x00, 0x60, 0x03, // 230
|
||||
0x00, 0x00, 0x20, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0x40, 0x01, // 231
|
||||
0x00, 0x00, 0xE0, 0x03, 0x00, 0x01, 0x80, 0x00, 0x40, 0x00, 0xE0, 0x03, // 232
|
||||
0x00, 0x00, 0xE0, 0x03, 0x00, 0x01, 0x98, 0x00, 0x40, 0x00, 0xE0, 0x03, // 233
|
||||
0x00, 0x00, 0xE0, 0x03, 0x80, 0x00, 0x80, 0x00, 0x40, 0x01, 0x20, 0x02, // 234
|
||||
0x00, 0x00, 0x00, 0x02, 0xC0, 0x01, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x03, // 235
|
||||
0x00, 0x00, 0xE0, 0x03, 0x40, 0x00, 0x80, 0x00, 0x40, 0x00, 0xE0, 0x03, // 236
|
||||
0x00, 0x00, 0xE0, 0x03, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xE0, 0x03, // 237
|
||||
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 238
|
||||
0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x03, // 239
|
||||
0x00, 0x00, 0xE0, 0x03, 0xA0, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0x40, // 240
|
||||
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0x40, 0x02, // 241
|
||||
0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, // 242
|
||||
0x00, 0x00, 0x60, 0x00, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0xE0, 0x01, // 243
|
||||
0x00, 0x00, 0xC0, 0x00, 0x20, 0x01, 0xE0, 0x03, 0x20, 0x01, 0xC0, // 244
|
||||
0x00, 0x00, 0x20, 0x02, 0x40, 0x01, 0x80, 0x00, 0x40, 0x01, 0x20, 0x02, // 245
|
||||
0x00, 0x00, 0xE0, 0x03, 0x00, 0x02, 0x00, 0x02, 0xE0, 0x03, 0x00, 0x02, // 246
|
||||
0x00, 0x00, 0x60, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xE0, 0x03, // 247
|
||||
0x00, 0x00, 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, // 248
|
||||
0x00, 0x00, 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, 0x00, 0x06, // 249
|
||||
0x00, 0x00, 0x20, 0x00, 0xE0, 0x03, 0x80, 0x02, 0x80, 0x02, 0x00, 0x01, // 250
|
||||
0x00, 0x00, 0xE0, 0x03, 0x80, 0x02, 0x80, 0x02, 0x00, 0x01, 0xE0, 0x03, // 251
|
||||
0x00, 0x00, 0xE0, 0x03, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x00, 0x01, // 252
|
||||
0x00, 0x00, 0x40, 0x01, 0x20, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0xC0, 0x01, // 253
|
||||
0x00, 0x00, 0xE0, 0x03, 0x80, 0x00, 0xC0, 0x01, 0x20, 0x02, 0xC0, 0x01, // 254
|
||||
0x00, 0x00, 0x40, 0x02, 0xA0, 0x01, 0xA0, 0x00, 0xA0, 0x00, 0xE0, 0x03, // 255
|
||||
};
|
||||
11
src/graphics/fonts/OLEDDisplayFontsUA.h
Normal file
11
src/graphics/fonts/OLEDDisplayFontsUA.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef OLEDDISPLAYFONTSUA_h
|
||||
#define OLEDDISPLAYFONTSUA_h
|
||||
|
||||
#ifdef ARDUINO
|
||||
#include <Arduino.h>
|
||||
#elif __MBED__
|
||||
#define PROGMEM
|
||||
#endif
|
||||
|
||||
extern const uint8_t ArialMT_Plain_10_UA[] PROGMEM;
|
||||
#endif
|
||||
@@ -1,7 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "InputBroker.h"
|
||||
#include "SinglePortModule.h" // TODO: what header file to include?
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "mesh/NodeDB.h"
|
||||
|
||||
enum RotaryEncoderInterruptBaseStateType { ROTARY_EVENT_OCCURRED, ROTARY_EVENT_CLEARED };
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "InputBroker.h"
|
||||
#include "SinglePortModule.h" // TODO: what header file to include?
|
||||
#include "mesh/NodeDB.h"
|
||||
|
||||
class UpDownInterruptBase : public Observable<const InputEvent *>
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@ CardKbI2cImpl::CardKbI2cImpl() : KbI2cBase("cardKB") {}
|
||||
|
||||
void CardKbI2cImpl::init()
|
||||
{
|
||||
if (cardkb_found != CARDKB_ADDR) {
|
||||
if (cardkb_found.address != CARDKB_ADDR) {
|
||||
disable();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#include "kbI2cBase.h"
|
||||
#include "configuration.h"
|
||||
#include <Wire.h>
|
||||
|
||||
extern uint8_t cardkb_found;
|
||||
#include "configuration.h"
|
||||
#include "detect/ScanI2C.h"
|
||||
|
||||
extern ScanI2C::DeviceAddress cardkb_found;
|
||||
extern uint8_t kb_model;
|
||||
|
||||
KbI2cBase::KbI2cBase(const char *name) : concurrency::OSThread(name)
|
||||
@@ -10,43 +11,64 @@ KbI2cBase::KbI2cBase(const char *name) : concurrency::OSThread(name)
|
||||
this->_originName = name;
|
||||
}
|
||||
|
||||
uint8_t read_from_14004(uint8_t reg, uint8_t *data, uint8_t length)
|
||||
uint8_t read_from_14004(TwoWire *i2cBus, uint8_t reg, uint8_t *data, uint8_t length)
|
||||
{
|
||||
uint8_t readflag = 0;
|
||||
Wire.beginTransmission(CARDKB_ADDR);
|
||||
Wire.write(reg);
|
||||
Wire.endTransmission(); // stop transmitting
|
||||
i2cBus->beginTransmission(CARDKB_ADDR);
|
||||
i2cBus->write(reg);
|
||||
i2cBus->endTransmission(); // stop transmitting
|
||||
delay(20);
|
||||
Wire.requestFrom(CARDKB_ADDR, (int)length);
|
||||
i2cBus->requestFrom(CARDKB_ADDR, (int)length);
|
||||
int i = 0;
|
||||
while (Wire.available()) // slave may send less than requested
|
||||
while (i2cBus->available()) // slave may send less than requested
|
||||
{
|
||||
data[i++] = Wire.read(); // receive a byte as a proper uint8_t
|
||||
data[i++] = i2cBus->read(); // receive a byte as a proper uint8_t
|
||||
readflag = 1;
|
||||
}
|
||||
return readflag;
|
||||
}
|
||||
|
||||
void write_to_14004(uint8_t reg, uint8_t data)
|
||||
// Unused for now - flagging it off
|
||||
#if 0
|
||||
void write_to_14004(const TwoWire * i2cBus, uint8_t reg, uint8_t data)
|
||||
{
|
||||
Wire.beginTransmission(CARDKB_ADDR);
|
||||
Wire.write(reg);
|
||||
Wire.write(data);
|
||||
Wire.endTransmission(); // stop transmitting
|
||||
i2cBus->beginTransmission(CARDKB_ADDR);
|
||||
i2cBus->write(reg);
|
||||
i2cBus->write(data);
|
||||
i2cBus->endTransmission(); // stop transmitting
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t KbI2cBase::runOnce()
|
||||
{
|
||||
if (cardkb_found != CARDKB_ADDR) {
|
||||
if (cardkb_found.address != CARDKB_ADDR) {
|
||||
// Input device is not detected.
|
||||
return INT32_MAX;
|
||||
}
|
||||
|
||||
if (!i2cBus) {
|
||||
switch (cardkb_found.port) {
|
||||
case ScanI2C::WIRE1:
|
||||
#ifdef I2C_SDA1
|
||||
LOG_DEBUG("Using I2C Bus 1 (the second one)\n");
|
||||
i2cBus = &Wire1;
|
||||
break;
|
||||
#endif
|
||||
case ScanI2C::WIRE:
|
||||
LOG_DEBUG("Using I2C Bus 0 (the first one)\n");
|
||||
i2cBus = &Wire;
|
||||
break;
|
||||
case ScanI2C::NO_I2C:
|
||||
default:
|
||||
i2cBus = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (kb_model == 0x02) {
|
||||
// RAK14004
|
||||
uint8_t rDataBuf[8] = {0};
|
||||
uint8_t PrintDataBuf = 0;
|
||||
if (read_from_14004(0x01, rDataBuf, 0x04) == 1) {
|
||||
if (read_from_14004(i2cBus, 0x01, rDataBuf, 0x04) == 1) {
|
||||
for (uint8_t aCount = 0; aCount < 0x04; aCount++) {
|
||||
for (uint8_t bCount = 0; bCount < 0x04; bCount++) {
|
||||
if (((rDataBuf[aCount] >> bCount) & 0x01) == 0x01) {
|
||||
@@ -65,10 +87,10 @@ int32_t KbI2cBase::runOnce()
|
||||
}
|
||||
} else {
|
||||
// m5 cardkb
|
||||
Wire.requestFrom(CARDKB_ADDR, 1);
|
||||
i2cBus->requestFrom(CARDKB_ADDR, 1);
|
||||
|
||||
while (Wire.available()) {
|
||||
char c = Wire.read();
|
||||
while (i2cBus->available()) {
|
||||
char c = i2cBus->read();
|
||||
InputEvent e;
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||
e.source = this->_originName;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "InputBroker.h"
|
||||
#include "SinglePortModule.h" // TODO: what header file to include?
|
||||
#include "Wire.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
|
||||
class KbI2cBase : public Observable<const InputEvent *>, public concurrency::OSThread
|
||||
{
|
||||
@@ -13,4 +14,6 @@ class KbI2cBase : public Observable<const InputEvent *>, public concurrency::OST
|
||||
|
||||
private:
|
||||
const char *_originName;
|
||||
|
||||
TwoWire *i2cBus = 0;
|
||||
};
|
||||
|
||||
224
src/main.cpp
224
src/main.cpp
@@ -15,16 +15,19 @@
|
||||
#include "SPILock.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "concurrency/Periodic.h"
|
||||
#include "detect/ScanI2C.h"
|
||||
#include "detect/ScanI2CTwoWire.h"
|
||||
#include "detect/axpDebug.h"
|
||||
#include "detect/einkScan.h"
|
||||
#include "detect/i2cScan.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "main.h"
|
||||
#include "mesh/generated/meshtastic/config.pb.h"
|
||||
#include "modules/Modules.h"
|
||||
#include "shutdown.h"
|
||||
#include "sleep.h"
|
||||
#include "target_specific.h"
|
||||
#include <Wire.h>
|
||||
#include <memory>
|
||||
// #include <driver/rtc_io.h>
|
||||
|
||||
#include "mesh/eth/ethClient.h"
|
||||
@@ -65,6 +68,10 @@ NRF52Bluetooth *nrf52Bluetooth;
|
||||
#endif
|
||||
#include "PowerFSMThread.h"
|
||||
|
||||
#if !defined(ARCH_PORTDUINO)
|
||||
#include "AccelerometerThread.h"
|
||||
#endif
|
||||
|
||||
using namespace concurrency;
|
||||
|
||||
// We always create a screen object, but we only init it if we find the hardware
|
||||
@@ -79,20 +86,21 @@ meshtastic::GPSStatus *gpsStatus = new meshtastic::GPSStatus();
|
||||
// Global Node status
|
||||
meshtastic::NodeStatus *nodeStatus = new meshtastic::NodeStatus();
|
||||
|
||||
// Scan for I2C Devices
|
||||
|
||||
/// The I2C address of our display (if found)
|
||||
uint8_t screen_found;
|
||||
uint8_t screen_model;
|
||||
ScanI2C::DeviceAddress screen_found = ScanI2C::ADDRESS_NONE;
|
||||
|
||||
// The I2C address of the cardkb or RAK14004 (if found)
|
||||
uint8_t cardkb_found;
|
||||
ScanI2C::DeviceAddress cardkb_found = ScanI2C::ADDRESS_NONE;
|
||||
// 0x02 for RAK14004 and 0x00 for cardkb
|
||||
uint8_t kb_model;
|
||||
|
||||
// The I2C address of the RTC Module (if found)
|
||||
uint8_t rtc_found;
|
||||
ScanI2C::DeviceAddress rtc_found = ScanI2C::ADDRESS_NONE;
|
||||
// The I2C address of the Accelerometer (if found)
|
||||
ScanI2C::DeviceAddress accelerometer_found = ScanI2C::ADDRESS_NONE;
|
||||
|
||||
// Keystore Chips
|
||||
uint8_t keystore_found;
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
ATECCX08A atecc;
|
||||
#endif
|
||||
@@ -161,6 +169,7 @@ static OSThread *powerFSMthread;
|
||||
static OSThread *buttonThread;
|
||||
uint32_t ButtonThread::longPressTime = 0;
|
||||
#endif
|
||||
static OSThread *accelerometerThread;
|
||||
|
||||
RadioInterface *rIf = NULL;
|
||||
|
||||
@@ -175,6 +184,9 @@ __attribute__((weak, noinline)) bool loopCanSleep()
|
||||
void setup()
|
||||
{
|
||||
concurrency::hasBeenSetup = true;
|
||||
meshtastic_Config_DisplayConfig_OledType screen_model =
|
||||
meshtastic_Config_DisplayConfig_OledType::meshtastic_Config_DisplayConfig_OledType_OLED_AUTO;
|
||||
OLEDDISPLAY_GEOMETRY screen_geometry = GEOMETRY_128_64;
|
||||
|
||||
#ifdef SEGGER_STDOUT_CH
|
||||
auto mode = false ? SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL : SEGGER_RTT_MODE_NO_BLOCK_TRIM;
|
||||
@@ -261,24 +273,124 @@ void setup()
|
||||
#endif
|
||||
|
||||
// Currently only the tbeam has a PMU
|
||||
// PMU initialization needs to be placed before scanI2Cdevice
|
||||
// PMU initialization needs to be placed before i2c scanning
|
||||
power = new Power();
|
||||
power->setStatusHandler(powerStatus);
|
||||
powerStatus->observe(&power->newStatus);
|
||||
power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration
|
||||
|
||||
#ifdef LILYGO_TBEAM_S3_CORE
|
||||
// In T-Beam-S3-core, the I2C device cannot be scanned before power initialization, otherwise the device will be stuck
|
||||
// PCF8563 RTC in tbeam-s3 uses Wire1 to share I2C bus
|
||||
Wire1.beginTransmission(PCF8563_RTC);
|
||||
if (Wire1.endTransmission() == 0) {
|
||||
rtc_found = PCF8563_RTC;
|
||||
LOG_INFO("PCF8563 RTC found\n");
|
||||
// We need to scan here to decide if we have a screen for nodeDB.init() and because power has been applied to
|
||||
// accessories
|
||||
auto i2cScanner = std::unique_ptr<ScanI2CTwoWire>(new ScanI2CTwoWire());
|
||||
|
||||
LOG_INFO("Scanning for i2c devices...\n");
|
||||
|
||||
#ifdef I2C_SDA1
|
||||
Wire1.begin(I2C_SDA1, I2C_SCL1);
|
||||
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE1);
|
||||
#endif
|
||||
|
||||
#ifdef I2C_SDA
|
||||
Wire.begin(I2C_SDA, I2C_SCL);
|
||||
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE);
|
||||
#elif HAS_WIRE
|
||||
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE);
|
||||
#endif
|
||||
|
||||
auto i2cCount = i2cScanner->countDevices();
|
||||
if (i2cCount == 0) {
|
||||
LOG_INFO("No I2C devices found\n");
|
||||
} else {
|
||||
LOG_INFO("%i I2C devices found\n", i2cCount);
|
||||
}
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
// Don't init display if we don't have one or we are waking headless due to a timer event
|
||||
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER) {
|
||||
LOG_DEBUG("suppress screen wake because this is a headless timer wakeup");
|
||||
i2cScanner->setSuppressScreen();
|
||||
}
|
||||
#endif
|
||||
|
||||
// We need to scan here to decide if we have a screen for nodeDB.init()
|
||||
scanI2Cdevice();
|
||||
auto screenInfo = i2cScanner->firstScreen();
|
||||
screen_found = screenInfo.type != ScanI2C::DeviceType::NONE ? screenInfo.address : ScanI2C::ADDRESS_NONE;
|
||||
|
||||
if (screen_found.port != ScanI2C::I2CPort::NO_I2C) {
|
||||
switch (screenInfo.type) {
|
||||
case ScanI2C::DeviceType::SCREEN_SH1106:
|
||||
screen_model = meshtastic_Config_DisplayConfig_OledType::meshtastic_Config_DisplayConfig_OledType_OLED_SH1106;
|
||||
break;
|
||||
case ScanI2C::DeviceType::SCREEN_SSD1306:
|
||||
screen_model = meshtastic_Config_DisplayConfig_OledType::meshtastic_Config_DisplayConfig_OledType_OLED_SSD1306;
|
||||
break;
|
||||
case ScanI2C::DeviceType::SCREEN_ST7567:
|
||||
case ScanI2C::DeviceType::SCREEN_UNKNOWN:
|
||||
default:
|
||||
screen_model = meshtastic_Config_DisplayConfig_OledType::meshtastic_Config_DisplayConfig_OledType_OLED_AUTO;
|
||||
}
|
||||
}
|
||||
|
||||
#define UPDATE_FROM_SCANNER(FIND_FN)
|
||||
|
||||
auto rtc_info = i2cScanner->firstRTC();
|
||||
rtc_found = rtc_info.type != ScanI2C::DeviceType::NONE ? rtc_info.address : rtc_found;
|
||||
|
||||
auto kb_info = i2cScanner->firstKeyboard();
|
||||
|
||||
if (kb_info.type != ScanI2C::DeviceType::NONE) {
|
||||
cardkb_found = kb_info.address;
|
||||
switch (kb_info.type) {
|
||||
case ScanI2C::DeviceType::RAK14004:
|
||||
kb_model = 0x02;
|
||||
break;
|
||||
case ScanI2C::DeviceType::CARDKB:
|
||||
default:
|
||||
// use this as default since it's also just zero
|
||||
kb_model = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
pmu_found = i2cScanner->exists(ScanI2C::DeviceType::PMU_AXP192_AXP2101);
|
||||
|
||||
/*
|
||||
* There are a bunch of sensors that have no further logic than to be found and stuffed into the
|
||||
* nodeTelemetrySensorsMap singleton. This wraps that logic in a temporary scope to declare the temporary field
|
||||
* "found".
|
||||
*/
|
||||
|
||||
#if !defined(ARCH_PORTDUINO)
|
||||
auto acc_info = i2cScanner->firstAccelerometer();
|
||||
accelerometer_found = acc_info.type != ScanI2C::DeviceType::NONE ? acc_info.address : accelerometer_found;
|
||||
LOG_DEBUG("acc_info = %i\n", acc_info.type);
|
||||
#endif
|
||||
|
||||
#define STRING(S) #S
|
||||
|
||||
#define SCANNER_TO_SENSORS_MAP(SCANNER_T, PB_T) \
|
||||
{ \
|
||||
auto found = i2cScanner->find(SCANNER_T); \
|
||||
if (found.type != ScanI2C::DeviceType::NONE) { \
|
||||
nodeTelemetrySensorsMap[PB_T] = found.address.address; \
|
||||
LOG_DEBUG("found i2c sensor %s\n", STRING(PB_T)); \
|
||||
} \
|
||||
}
|
||||
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BME_680, meshtastic_TelemetrySensorType_BME680)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BME_280, meshtastic_TelemetrySensorType_BME280)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BMP_280, meshtastic_TelemetrySensorType_BMP280)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA260, meshtastic_TelemetrySensorType_INA260)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA219, meshtastic_TelemetrySensorType_INA219)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHT31, meshtastic_TelemetrySensorType_SHT31)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHTC3, meshtastic_TelemetrySensorType_SHTC3)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::LPS22HB, meshtastic_TelemetrySensorType_LPS22)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::QMC6310, meshtastic_TelemetrySensorType_QMC6310)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::QMI8658, meshtastic_TelemetrySensorType_QMI8658)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::QMC5883L, meshtastic_TelemetrySensorType_QMC5883L)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::PMSA0031, meshtastic_TelemetrySensorType_PMSA003I)
|
||||
|
||||
i2cScanner.reset();
|
||||
|
||||
#ifdef HAS_SDCARD
|
||||
setupSDCard();
|
||||
@@ -302,10 +414,6 @@ void setup()
|
||||
LOG_INFO("Meshtastic hwvendor=%d, swver=%s\n", HW_VENDOR, optstr(APP_VERSION));
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
// Don't init display if we don't have one or we are waking headless due to a timer event
|
||||
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER)
|
||||
screen_found = 0; // forget we even have the hardware
|
||||
|
||||
esp32Setup();
|
||||
#endif
|
||||
|
||||
@@ -327,7 +435,18 @@ void setup()
|
||||
screen_model = config.display.oled;
|
||||
|
||||
#if defined(USE_SH1107)
|
||||
screen_model = Config_DisplayConfig_OledType_OLED_SH1107; // set dimension of 128x128
|
||||
screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1107; // set dimension of 128x128
|
||||
display_geometry = GEOMETRY_128_128;
|
||||
#endif
|
||||
|
||||
#if defined(USE_SH1107_128_64)
|
||||
screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1107; // keep dimension of 128x64
|
||||
#endif
|
||||
|
||||
#if !defined(ARCH_PORTDUINO)
|
||||
if (acc_info.type != ScanI2C::DeviceType::NONE) {
|
||||
accelerometerThread = new AccelerometerThread(acc_info.type);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Init our SPI controller (must be before screen and lora)
|
||||
@@ -341,7 +460,7 @@ void setup()
|
||||
#endif
|
||||
|
||||
// Initialize the screen first so we can show the logo while we start up everything else.
|
||||
screen = new graphics::Screen(screen_found);
|
||||
screen = new graphics::Screen(screen_found, screen_model, screen_geometry);
|
||||
|
||||
readFromRTC(); // read the main CPU RTC at first (in case we can't get GPS time)
|
||||
|
||||
@@ -359,18 +478,18 @@ void setup()
|
||||
// Now that the mesh service is created, create any modules
|
||||
setupModules();
|
||||
|
||||
// Do this after service.init (because that clears error_code)
|
||||
// Do this after service.init (because that clears error_code)
|
||||
#ifdef HAS_PMU
|
||||
if (!pmu_found)
|
||||
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_NO_AXP192); // Record a hardware fault for missing hardware
|
||||
#endif
|
||||
|
||||
// Don't call screen setup until after nodedb is setup (because we need
|
||||
// the current region name)
|
||||
// Don't call screen setup until after nodedb is setup (because we need
|
||||
// the current region name)
|
||||
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER)
|
||||
screen->setup();
|
||||
#else
|
||||
if (screen_found)
|
||||
if (screen_found.port != ScanI2C::I2CPort::NO_I2C)
|
||||
screen->setup();
|
||||
#endif
|
||||
|
||||
@@ -395,9 +514,22 @@ void setup()
|
||||
|
||||
// radio init MUST BE AFTER service.init, so we have our radio config settings (from nodedb init)
|
||||
|
||||
#if !HAS_RADIO && defined(ARCH_PORTDUINO)
|
||||
if (!rIf) {
|
||||
rIf = new SimRadio;
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("Failed to find simulated radio\n");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
} else {
|
||||
LOG_INFO("Using SIMULATED radio!\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(RF95_IRQ)
|
||||
if (!rIf) {
|
||||
rIf = new RF95Interface(RF95_NSS, RF95_IRQ, RF95_RESET, SPI);
|
||||
rIf = new RF95Interface(RF95_NSS, RF95_IRQ, RF95_RESET, RF95_DIO1, SPI);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("Failed to find RF95 radio\n");
|
||||
delete rIf;
|
||||
@@ -408,19 +540,6 @@ void setup()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_SX1280)
|
||||
if (!rIf) {
|
||||
rIf = new SX1280Interface(SX128X_CS, SX128X_DIO1, SX128X_RESET, SX128X_BUSY, SPI);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("Failed to find SX1280 radio\n");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
} else {
|
||||
LOG_INFO("SX1280 Radio init succeeded, using SX1280 radio\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_SX1262)
|
||||
if (!rIf) {
|
||||
rIf = new SX1262Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI);
|
||||
@@ -460,15 +579,15 @@ void setup()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_PORTDUINO
|
||||
#if defined(USE_SX1280)
|
||||
if (!rIf) {
|
||||
rIf = new SimRadio;
|
||||
rIf = new SX1280Interface(SX128X_CS, SX128X_DIO1, SX128X_RESET, SX128X_BUSY, SPI);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("Failed to find simulated radio\n");
|
||||
LOG_WARN("Failed to find SX1280 radio\n");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
} else {
|
||||
LOG_INFO("Using SIMULATED radio!\n");
|
||||
LOG_INFO("SX1280 Radio init succeeded, using SX1280 radio\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -538,6 +657,21 @@ uint32_t shutdownAtMsec; // If not zero we will shutdown at this time (used to s
|
||||
// This will supress the current delay and instead try to run ASAP.
|
||||
bool runASAP;
|
||||
|
||||
extern meshtastic_DeviceMetadata getDeviceMetadata()
|
||||
{
|
||||
meshtastic_DeviceMetadata deviceMetadata;
|
||||
strncpy(deviceMetadata.firmware_version, myNodeInfo.firmware_version, 18);
|
||||
deviceMetadata.device_state_version = DEVICESTATE_CUR_VER;
|
||||
deviceMetadata.canShutdown = pmu_found || HAS_CPU_SHUTDOWN;
|
||||
deviceMetadata.hasBluetooth = HAS_BLUETOOTH;
|
||||
deviceMetadata.hasWifi = HAS_WIFI;
|
||||
deviceMetadata.hasEthernet = HAS_ETHERNET;
|
||||
deviceMetadata.role = config.device.role;
|
||||
deviceMetadata.position_flags = config.position.position_flags;
|
||||
deviceMetadata.hw_model = HW_VENDOR;
|
||||
return deviceMetadata;
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
runASAP = false;
|
||||
|
||||
13
src/main.h
13
src/main.h
@@ -3,7 +3,9 @@
|
||||
#include "GPSStatus.h"
|
||||
#include "NodeStatus.h"
|
||||
#include "PowerStatus.h"
|
||||
#include "detect/ScanI2C.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "mesh/generated/meshtastic/config.pb.h"
|
||||
#include "mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include <map>
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
@@ -18,12 +20,11 @@ extern NimbleBluetooth *nimbleBluetooth;
|
||||
extern NRF52Bluetooth *nrf52Bluetooth;
|
||||
#endif
|
||||
|
||||
extern uint8_t screen_found;
|
||||
extern uint8_t screen_model;
|
||||
extern uint8_t cardkb_found;
|
||||
extern ScanI2C::DeviceAddress screen_found;
|
||||
extern ScanI2C::DeviceAddress cardkb_found;
|
||||
extern uint8_t kb_model;
|
||||
extern uint8_t rtc_found;
|
||||
extern uint8_t keystore_found;
|
||||
extern ScanI2C::DeviceAddress rtc_found;
|
||||
extern ScanI2C::DeviceAddress accelerometer_found;
|
||||
|
||||
extern bool eink_found;
|
||||
extern bool pmu_found;
|
||||
@@ -61,3 +62,5 @@ extern uint32_t serialSinceMsec;
|
||||
extern bool runASAP;
|
||||
|
||||
void nrf52Setup(), esp32Setup(), nrf52Loop(), esp32Loop(), clearBonds();
|
||||
|
||||
meshtastic_DeviceMetadata getDeviceMetadata();
|
||||
|
||||
@@ -44,7 +44,8 @@ void FloodingRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas
|
||||
tosend->hop_limit--; // bump down the hop count
|
||||
|
||||
// If it is a traceRoute request, update the route that it went via me
|
||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag && traceRouteModule->wantPacket(p)) {
|
||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag && traceRouteModule &&
|
||||
traceRouteModule->wantPacket(p)) {
|
||||
traceRouteModule->updateRoute(tosend);
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +77,8 @@ void MeshModule::callPlugins(const meshtastic_MeshPacket &mp, RxSource src)
|
||||
|
||||
currentReply = NULL; // No reply yet
|
||||
|
||||
bool ignoreRequest = false; // No module asked to ignore the request yet
|
||||
|
||||
// Was this message directed to us specifically? Will be false if we are sniffing someone elses packets
|
||||
auto ourNodeNum = nodeDB.getNodeNum();
|
||||
bool toUs = mp.to == NODENUM_BROADCAST || mp.to == ourNodeNum;
|
||||
@@ -135,7 +137,8 @@ void MeshModule::callPlugins(const meshtastic_MeshPacket &mp, RxSource src)
|
||||
// any other node.
|
||||
if (mp.decoded.want_response && toUs && (getFrom(&mp) != ourNodeNum || mp.to == ourNodeNum) && !currentReply) {
|
||||
pi.sendResponse(mp);
|
||||
LOG_INFO("Module '%s' sent a response\n", pi.name);
|
||||
ignoreRequest = ignoreRequest || pi.ignoreRequest; // If at least one module asks it, we may ignore a request
|
||||
LOG_INFO("Asked module '%s' to send a response\n", pi.name);
|
||||
} else {
|
||||
LOG_DEBUG("Module '%s' considered\n", pi.name);
|
||||
}
|
||||
@@ -162,8 +165,9 @@ void MeshModule::callPlugins(const meshtastic_MeshPacket &mp, RxSource src)
|
||||
printPacket("Sending response", currentReply);
|
||||
service.sendToMesh(currentReply);
|
||||
currentReply = NULL;
|
||||
} else if (mp.from != ourNodeNum) {
|
||||
// Note: if the message started with the local node we don't want to send a no response reply
|
||||
} else if (mp.from != ourNodeNum && !ignoreRequest) {
|
||||
// Note: if the message started with the local node or a module asked to ignore the request, we don't want to send a
|
||||
// no response reply
|
||||
|
||||
// No one wanted to reply to this requst, tell the requster that happened
|
||||
LOG_DEBUG("No one responded, send a nak\n");
|
||||
|
||||
@@ -94,6 +94,9 @@ class MeshModule
|
||||
* flag */
|
||||
bool encryptedOk = false;
|
||||
|
||||
/* We allow modules to ignore a request without sending an error if they have a specific reason for it. */
|
||||
bool ignoreRequest = false;
|
||||
|
||||
/** If a bound channel name is set, we will only accept received packets that come in on that channel.
|
||||
* A special exception (FIXME, not sure if this is a good idea) - packets that arrive on the local interface
|
||||
* are allowed on any channel (this lets the local user do anything).
|
||||
|
||||
@@ -75,10 +75,14 @@ int MeshService::handleFromRadio(const meshtastic_MeshPacket *mp)
|
||||
{
|
||||
powerFSM.trigger(EVENT_PACKET_FOR_PHONE); // Possibly keep the node from sleeping
|
||||
|
||||
printPacket("Forwarding to phone", mp);
|
||||
nodeDB.updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio
|
||||
if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag && !nodeDB.getNode(mp->from)->has_user && nodeInfoModule) {
|
||||
LOG_INFO("Heard a node on channel %d we don't know, sending NodeInfo and asking for a response.\n", mp->channel);
|
||||
nodeInfoModule->sendOurNodeInfo(mp->from, true, mp->channel);
|
||||
}
|
||||
|
||||
sendToPhone((meshtastic_MeshPacket *)mp);
|
||||
printPacket("Forwarding to phone", mp);
|
||||
sendToPhone(packetPool.allocCopy(*mp));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -132,7 +136,7 @@ void MeshService::reloadOwner(bool shouldSave)
|
||||
*/
|
||||
void MeshService::handleToRadio(meshtastic_MeshPacket &p)
|
||||
{
|
||||
#ifdef ARCH_PORTDUINO
|
||||
#if defined(ARCH_PORTDUINO) && !HAS_RADIO
|
||||
// Simulates device is receiving a packet via the LoRa chip
|
||||
if (p.decoded.portnum == meshtastic_PortNum_SIMULATOR_APP) {
|
||||
// Simulator packet (=Compressed packet) is encapsulated in a MeshPacket, so need to unwrap first
|
||||
@@ -227,7 +231,7 @@ void MeshService::sendToMesh(meshtastic_MeshPacket *p, RxSource src, bool ccToPh
|
||||
}
|
||||
|
||||
if (ccToPhone) {
|
||||
sendToPhone(p);
|
||||
sendToPhone(packetPool.allocCopy(*p));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,13 +242,13 @@ void MeshService::sendNetworkPing(NodeNum dest, bool wantReplies)
|
||||
|
||||
if (node->has_position && (node->position.latitude_i != 0 || node->position.longitude_i != 0)) {
|
||||
if (positionModule) {
|
||||
LOG_INFO("Sending position ping to 0x%x, wantReplies=%d\n", dest, wantReplies);
|
||||
positionModule->sendOurPosition(dest, wantReplies);
|
||||
LOG_INFO("Sending position ping to 0x%x, wantReplies=%d, channel=%d\n", dest, wantReplies, node->channel);
|
||||
positionModule->sendOurPosition(dest, wantReplies, node->channel);
|
||||
}
|
||||
} else {
|
||||
if (nodeInfoModule) {
|
||||
LOG_INFO("Sending nodeinfo ping to 0x%x, wantReplies=%d\n", dest, wantReplies);
|
||||
nodeInfoModule->sendOurNodeInfo(dest, wantReplies);
|
||||
LOG_INFO("Sending nodeinfo ping to 0x%x, wantReplies=%d, channel=%d\n", dest, wantReplies, node->channel);
|
||||
nodeInfoModule->sendOurNodeInfo(dest, wantReplies, node->channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -258,9 +262,8 @@ void MeshService::sendToPhone(meshtastic_MeshPacket *p)
|
||||
releaseToPool(d);
|
||||
}
|
||||
|
||||
meshtastic_MeshPacket *copied = packetPool.allocCopy(*p);
|
||||
perhapsDecode(copied);
|
||||
assert(toPhoneQueue.enqueue(copied, 0));
|
||||
perhapsDecode(p);
|
||||
assert(toPhoneQueue.enqueue(p, 0));
|
||||
fromNum++;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "MeshTypes.h"
|
||||
#include "Observer.h"
|
||||
#include "PointerQueue.h"
|
||||
#ifdef ARCH_PORTDUINO
|
||||
#if defined(ARCH_PORTDUINO) && !HAS_RADIO
|
||||
#include "../platform/portduino/SimRadio.h"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "configuration.h"
|
||||
|
||||
#include "../detect/ScanI2C.h"
|
||||
#include "Channels.h"
|
||||
#include "CryptoEngine.h"
|
||||
#include "FSCommon.h"
|
||||
@@ -57,12 +58,6 @@ meshtastic_User &owner = devicestate.owner;
|
||||
|
||||
static uint8_t ourMacAddr[6];
|
||||
|
||||
/**
|
||||
* The node number the user is currently looking at
|
||||
* 0 if none
|
||||
*/
|
||||
NodeNum displayedNodeNum;
|
||||
|
||||
NodeDB::NodeDB() : nodes(devicestate.node_db), numNodes(&devicestate.node_db_count) {}
|
||||
|
||||
/**
|
||||
@@ -170,6 +165,10 @@ void NodeDB::installDefaultConfig()
|
||||
config.lora.hop_limit = HOP_RELIABLE;
|
||||
config.position.gps_enabled = true;
|
||||
config.position.position_broadcast_smart_enabled = true;
|
||||
config.position.broadcast_smart_minimum_distance = 100;
|
||||
config.position.broadcast_smart_minimum_interval_secs = 30;
|
||||
if (config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER)
|
||||
config.device.node_info_broadcast_secs = 3 * 60 * 60;
|
||||
config.device.serial_enabled = true;
|
||||
resetRadioConfig();
|
||||
strncpy(config.network.ntp_server, "0.pool.ntp.org", 32);
|
||||
@@ -179,7 +178,7 @@ void NodeDB::installDefaultConfig()
|
||||
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER)
|
||||
bool hasScreen = true;
|
||||
#else
|
||||
bool hasScreen = screen_found;
|
||||
bool hasScreen = screen_found.port != ScanI2C::I2CPort::NO_I2C;
|
||||
#endif
|
||||
config.bluetooth.mode = hasScreen ? meshtastic_Config_BluetoothConfig_PairingMode_RANDOM_PIN
|
||||
: meshtastic_Config_BluetoothConfig_PairingMode_FIXED_PIN;
|
||||
@@ -233,15 +232,11 @@ void NodeDB::installRoleDefaults(meshtastic_Config_DeviceConfig_Role role)
|
||||
initModuleConfigIntervals();
|
||||
} else if (role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
|
||||
config.display.screen_on_secs = 1;
|
||||
meshtastic_Channel &ch = channels.getByIndex(channels.getPrimaryIndex());
|
||||
meshtastic_ChannelSettings &channelSettings = ch.settings;
|
||||
uint8_t defaultpskIndex = 1;
|
||||
channelSettings.psk.bytes[0] = defaultpskIndex;
|
||||
channelSettings.psk.size = 1;
|
||||
} else if (role == meshtastic_Config_DeviceConfig_Role_TRACKER) {
|
||||
config.position.position_broadcast_smart_enabled = false;
|
||||
config.position.position_broadcast_secs = 120;
|
||||
config.position.gps_update_interval = 60;
|
||||
config.position.gps_update_interval = 30;
|
||||
} else if (role == meshtastic_Config_DeviceConfig_Role_SENSOR) {
|
||||
moduleConfig.telemetry.environment_measurement_enabled = true;
|
||||
moduleConfig.telemetry.environment_update_interval = 300;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,6 +244,7 @@ void NodeDB::initModuleConfigIntervals()
|
||||
{
|
||||
moduleConfig.telemetry.device_update_interval = default_broadcast_interval_secs;
|
||||
moduleConfig.telemetry.environment_update_interval = default_broadcast_interval_secs;
|
||||
moduleConfig.telemetry.air_quality_interval = default_broadcast_interval_secs;
|
||||
}
|
||||
|
||||
void NodeDB::installDefaultChannels()
|
||||
@@ -725,7 +721,7 @@ void NodeDB::updateUser(uint32_t nodeId, const meshtastic_User &p)
|
||||
void NodeDB::updateFrom(const meshtastic_MeshPacket &mp)
|
||||
{
|
||||
if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag && mp.from) {
|
||||
LOG_DEBUG("Update DB node 0x%x, rx_time=%u\n", mp.from, mp.rx_time);
|
||||
LOG_DEBUG("Update DB node 0x%x, rx_time=%u, channel=%d\n", mp.from, mp.rx_time, mp.channel);
|
||||
|
||||
meshtastic_NodeInfo *info = getOrCreateNode(getFrom(&mp));
|
||||
if (!info) {
|
||||
@@ -737,9 +733,22 @@ void NodeDB::updateFrom(const meshtastic_MeshPacket &mp)
|
||||
|
||||
if (mp.rx_snr)
|
||||
info->snr = mp.rx_snr; // keep the most recent SNR we received for this node.
|
||||
|
||||
if (mp.decoded.portnum == meshtastic_PortNum_NODEINFO_APP) {
|
||||
info->channel = mp.channel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t NodeDB::getNodeChannel(NodeNum n)
|
||||
{
|
||||
meshtastic_NodeInfo *info = getNode(n);
|
||||
if (!info) {
|
||||
return 0; // defaults to PRIMARY
|
||||
}
|
||||
return info->channel;
|
||||
}
|
||||
|
||||
/// Find a node in our DB, return null for missing
|
||||
/// NOTE: This function might be called from an ISR
|
||||
meshtastic_NodeInfo *NodeDB::getNode(NodeNum n)
|
||||
|
||||
@@ -113,6 +113,9 @@ class NodeDB
|
||||
/// pick a provisional nodenum we hope no one is using
|
||||
void pickNewNodeNum();
|
||||
|
||||
// get channel channel index we heard a nodeNum on, defaults to 0 if not found
|
||||
uint8_t getNodeChannel(NodeNum n);
|
||||
|
||||
/// Find a node in our DB, return null for missing
|
||||
meshtastic_NodeInfo *getNode(NodeNum n);
|
||||
|
||||
@@ -153,12 +156,6 @@ class NodeDB
|
||||
void installDefaultDeviceState(), installDefaultChannels(), installDefaultConfig(), installDefaultModuleConfig();
|
||||
};
|
||||
|
||||
/**
|
||||
* The node number the user is currently looking at
|
||||
* 0 if none
|
||||
*/
|
||||
extern NodeNum displayedNodeNum;
|
||||
|
||||
extern NodeDB nodeDB;
|
||||
|
||||
/*
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "PowerFSM.h"
|
||||
#include "RadioInterface.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
#include "xmodem.h"
|
||||
|
||||
#if FromRadio_size > MAX_TO_FROM_RADIO_SIZE
|
||||
@@ -120,6 +121,7 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
|
||||
* STATE_SEND_NODEINFO, // states progress in this order as the device sends to the client
|
||||
STATE_SEND_CONFIG,
|
||||
STATE_SEND_MODULE_CONFIG,
|
||||
STATE_SEND_METADATA,
|
||||
STATE_SEND_COMPLETE_ID,
|
||||
STATE_SEND_PACKETS // send packets or debug strings
|
||||
*/
|
||||
@@ -277,11 +279,15 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
||||
config_state++;
|
||||
// Advance when we have sent all of our ModuleConfig objects
|
||||
if (config_state > (_meshtastic_AdminMessage_ModuleConfigType_MAX + 1)) {
|
||||
state = STATE_SEND_COMPLETE_ID;
|
||||
state = STATE_SEND_METADATA;
|
||||
config_state = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_SEND_METADATA:
|
||||
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_metadata_tag;
|
||||
fromRadioScratch.metadata = getDeviceMetadata();
|
||||
state = STATE_SEND_COMPLETE_ID;
|
||||
break;
|
||||
case STATE_SEND_COMPLETE_ID:
|
||||
LOG_INFO("getFromRadio=STATE_SEND_COMPLETE_ID\n");
|
||||
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_config_complete_id_tag;
|
||||
@@ -361,6 +367,7 @@ bool PhoneAPI::available()
|
||||
case STATE_SEND_CHANNELS:
|
||||
case STATE_SEND_CONFIG:
|
||||
case STATE_SEND_MODULECONFIG:
|
||||
case STATE_SEND_METADATA:
|
||||
case STATE_SEND_COMPLETE_ID:
|
||||
return true;
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ class PhoneAPI
|
||||
STATE_SEND_CHANNELS, // Send all channels
|
||||
STATE_SEND_CONFIG, // Replacement for the old Radioconfig
|
||||
STATE_SEND_MODULECONFIG, // Send Module specific config
|
||||
STATE_SEND_METADATA,
|
||||
STATE_SEND_COMPLETE_ID,
|
||||
STATE_SEND_PACKETS // send packets or debug strings
|
||||
};
|
||||
|
||||
@@ -11,10 +11,11 @@
|
||||
|
||||
#define POWER_DEFAULT 17 // How much power to use if the user hasn't set a power level
|
||||
|
||||
RF95Interface::RF95Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, SPIClass &spi)
|
||||
: RadioLibInterface(cs, irq, rst, RADIOLIB_NC, spi)
|
||||
RF95Interface::RF95Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
|
||||
SPIClass &spi)
|
||||
: RadioLibInterface(cs, irq, rst, busy, spi)
|
||||
{
|
||||
// FIXME - we assume devices never get destroyed
|
||||
LOG_WARN("RF95Interface(cs=%d, irq=%d, rst=%d, busy=%d)\n", cs, irq, rst, busy);
|
||||
}
|
||||
|
||||
/** Some boards require GPIO control of tx vs rx paths */
|
||||
@@ -67,19 +68,12 @@ bool RF95Interface::init()
|
||||
#endif
|
||||
setTransmitEnable(false);
|
||||
|
||||
int res = lora->begin(getFreq(), bw, sf, cr, syncWord, power, currentLimit, preambleLength);
|
||||
int res = lora->begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength);
|
||||
LOG_INFO("RF95 init result %d\n", res);
|
||||
|
||||
LOG_INFO("Frequency set to %f\n", getFreq());
|
||||
LOG_INFO("Bandwidth set to %f\n", bw);
|
||||
LOG_INFO("Power output set to %d\n", power);
|
||||
|
||||
// current limit was removed from module' ctor
|
||||
// override default value (60 mA)
|
||||
res = lora->setCurrentLimit(currentLimit);
|
||||
LOG_DEBUG("Current limit set to %f\n", currentLimit);
|
||||
LOG_DEBUG("Current limit set result %d\n", res);
|
||||
|
||||
if (res == RADIOLIB_ERR_NONE)
|
||||
res = lora->setCRC(RADIOLIB_SX126X_LORA_CRC_ON);
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ class RF95Interface : public RadioLibInterface
|
||||
RadioLibRF95 *lora = NULL; // Either a RFM95 or RFM96 depending on what was stuffed on this board
|
||||
|
||||
public:
|
||||
RF95Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, SPIClass &spi);
|
||||
RF95Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi);
|
||||
|
||||
// TODO: Verify that this irq flag works with RFM95 / SX1276 radios the way it used to
|
||||
bool isIRQPending() override { return lora->getIRQFlags() & RADIOLIB_SX127X_MASK_IRQ_FLAG_VALID_HEADER; }
|
||||
|
||||
@@ -175,7 +175,7 @@ uint32_t RadioInterface::getPacketTime(uint32_t pl)
|
||||
return msecs;
|
||||
}
|
||||
|
||||
uint32_t RadioInterface::getPacketTime(meshtastic_MeshPacket *p)
|
||||
uint32_t RadioInterface::getPacketTime(const meshtastic_MeshPacket *p)
|
||||
{
|
||||
uint32_t pl = 0;
|
||||
if (p->which_payload_variant == meshtastic_MeshPacket_encrypted_tag) {
|
||||
@@ -241,47 +241,48 @@ uint32_t RadioInterface::getTxDelayMsecWeighted(float snr)
|
||||
|
||||
void printPacket(const char *prefix, const meshtastic_MeshPacket *p)
|
||||
{
|
||||
LOG_DEBUG("%s (id=0x%08x fr=0x%02x to=0x%02x, WantAck=%d, HopLim=%d Ch=0x%x", prefix, p->id, p->from & 0xff, p->to & 0xff,
|
||||
p->want_ack, p->hop_limit, p->channel);
|
||||
std::string out = DEBUG_PORT.mt_sprintf("%s (id=0x%08x fr=0x%02x to=0x%02x, WantAck=%d, HopLim=%d Ch=0x%x", prefix, p->id,
|
||||
p->from & 0xff, p->to & 0xff, p->want_ack, p->hop_limit, p->channel);
|
||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||
auto &s = p->decoded;
|
||||
|
||||
LOG_DEBUG(" Portnum=%d", s.portnum);
|
||||
out += DEBUG_PORT.mt_sprintf(" Portnum=%d", s.portnum);
|
||||
|
||||
if (s.want_response)
|
||||
LOG_DEBUG(" WANTRESP");
|
||||
out += DEBUG_PORT.mt_sprintf(" WANTRESP");
|
||||
|
||||
if (s.source != 0)
|
||||
LOG_DEBUG(" source=%08x", s.source);
|
||||
out += DEBUG_PORT.mt_sprintf(" source=%08x", s.source);
|
||||
|
||||
if (s.dest != 0)
|
||||
LOG_DEBUG(" dest=%08x", s.dest);
|
||||
out += DEBUG_PORT.mt_sprintf(" dest=%08x", s.dest);
|
||||
|
||||
if (s.request_id)
|
||||
LOG_DEBUG(" requestId=%0x", s.request_id);
|
||||
out += DEBUG_PORT.mt_sprintf(" requestId=%0x", s.request_id);
|
||||
|
||||
/* now inside Data and therefore kinda opaque
|
||||
if (s.which_ackVariant == SubPacket_success_id_tag)
|
||||
LOG_DEBUG(" successId=%08x", s.ackVariant.success_id);
|
||||
out += DEBUG_PORT.mt_sprintf(" successId=%08x", s.ackVariant.success_id);
|
||||
else if (s.which_ackVariant == SubPacket_fail_id_tag)
|
||||
LOG_DEBUG(" failId=%08x", s.ackVariant.fail_id); */
|
||||
out += DEBUG_PORT.mt_sprintf(" failId=%08x", s.ackVariant.fail_id); */
|
||||
} else {
|
||||
LOG_DEBUG(" encrypted");
|
||||
out += " encrypted";
|
||||
}
|
||||
|
||||
if (p->rx_time != 0) {
|
||||
LOG_DEBUG(" rxtime=%u", p->rx_time);
|
||||
out += DEBUG_PORT.mt_sprintf(" rxtime=%u", p->rx_time);
|
||||
}
|
||||
if (p->rx_snr != 0.0) {
|
||||
LOG_DEBUG(" rxSNR=%g", p->rx_snr);
|
||||
out += DEBUG_PORT.mt_sprintf(" rxSNR=%g", p->rx_snr);
|
||||
}
|
||||
if (p->rx_rssi != 0) {
|
||||
LOG_DEBUG(" rxRSSI=%i", p->rx_rssi);
|
||||
out += DEBUG_PORT.mt_sprintf(" rxRSSI=%i", p->rx_rssi);
|
||||
}
|
||||
if (p->priority != 0)
|
||||
LOG_DEBUG(" priority=%d", p->priority);
|
||||
out += DEBUG_PORT.mt_sprintf(" priority=%d", p->priority);
|
||||
|
||||
LOG_DEBUG(")\n");
|
||||
out += ")\n";
|
||||
LOG_DEBUG("%s", out.c_str());
|
||||
}
|
||||
|
||||
RadioInterface::RadioInterface()
|
||||
@@ -453,6 +454,7 @@ void RadioInterface::applyModemConfig()
|
||||
|
||||
// If user has manually specified a channel num, then use that, otherwise generate one by hashing the name
|
||||
const char *channelName = channels.getName(channels.getPrimaryIndex());
|
||||
// channel_num is actually (channel_num - 1), since modulus (%) returns values from 0 to (numChannels - 1)
|
||||
int channel_num = (loraConfig.channel_num ? loraConfig.channel_num - 1 : hash(channelName)) % numChannels;
|
||||
|
||||
// Old frequency selection formula
|
||||
@@ -470,13 +472,16 @@ void RadioInterface::applyModemConfig()
|
||||
saveChannelNum(channel_num);
|
||||
saveFreq(freq + loraConfig.frequency_offset);
|
||||
|
||||
preambleTimeMsec = getPacketTime((uint32_t)0);
|
||||
maxPacketTimeMsec = getPacketTime(meshtastic_Constants_DATA_PAYLOAD_LEN + sizeof(PacketHeader));
|
||||
|
||||
LOG_INFO("Radio freq=%.3f, config.lora.frequency_offset=%.3f\n", freq, loraConfig.frequency_offset);
|
||||
LOG_INFO("Set radio: region=%s, name=%s, config=%u, ch=%d, power=%d\n", myRegion->name, channelName, loraConfig.modem_preset,
|
||||
channel_num, power);
|
||||
LOG_INFO("Radio myRegion->freqStart -> myRegion->freqEnd: %f -> %f (%f mhz)\n", myRegion->freqStart, myRegion->freqEnd,
|
||||
myRegion->freqEnd - myRegion->freqStart);
|
||||
LOG_INFO("Radio myRegion->numChannels: %d x %.3fkHz\n", numChannels, bw);
|
||||
LOG_INFO("Radio channel_num: %d\n", channel_num);
|
||||
LOG_INFO("Radio channel_num: %d\n", channel_num + 1);
|
||||
LOG_INFO("Radio frequency: %f\n", getFreq());
|
||||
LOG_INFO("Slot time: %u msec\n", slotTimeMsec);
|
||||
}
|
||||
|
||||
@@ -63,7 +63,9 @@ class RadioInterface
|
||||
- Tx/Rx turnaround time (maximum of SX126x and SX127x);
|
||||
- MAC processing time (measured on T-beam) */
|
||||
uint32_t slotTimeMsec = 8.5 * pow(2, sf) / bw + 0.2 + 0.4 + 7;
|
||||
uint16_t preambleLength = 32; // 8 is default, but we use longer to increase the amount of sleep time when receiving
|
||||
uint16_t preambleLength = 16; // 8 is default, but we use longer to increase the amount of sleep time when receiving
|
||||
uint32_t preambleTimeMsec = 165; // calculated on startup, this is the default for LongFast
|
||||
uint32_t maxPacketTimeMsec = 3246; // calculated on startup, this is the default for LongFast
|
||||
const uint32_t PROCESSING_TIME_MSEC =
|
||||
4500; // time to construct, process and construct a packet again (empirically determined)
|
||||
const uint8_t CWmin = 2; // minimum CWsize
|
||||
@@ -154,7 +156,7 @@ class RadioInterface
|
||||
*
|
||||
* @return num msecs for the packet
|
||||
*/
|
||||
uint32_t getPacketTime(meshtastic_MeshPacket *p);
|
||||
uint32_t getPacketTime(const meshtastic_MeshPacket *p);
|
||||
uint32_t getPacketTime(uint32_t totalPacketLen);
|
||||
|
||||
/**
|
||||
|
||||
@@ -218,8 +218,9 @@ void RadioLibInterface::onNotify(uint32_t notification)
|
||||
setTransmitDelay(); // currently Rx/Tx-ing: reset random delay
|
||||
} else {
|
||||
if (isChannelActive()) { // check if there is currently a LoRa packet on the channel
|
||||
// LOG_DEBUG("Channel is active: set random delay\n");
|
||||
setTransmitDelay(); // reset random delay
|
||||
// LOG_DEBUG("Channel is active, try receiving first.\n");
|
||||
startReceive(); // try receiving this packet, afterwards we'll be trying to transmit again
|
||||
setTransmitDelay();
|
||||
} else {
|
||||
// Send any outgoing packets we have ready
|
||||
meshtastic_MeshPacket *txp = txQueue.dequeue();
|
||||
@@ -388,8 +389,6 @@ void RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
|
||||
LOG_WARN("startSend is dropping tx packet because we are disabled\n");
|
||||
packetPool.release(txp);
|
||||
} else {
|
||||
setStandby(); // Cancel any already in process receives
|
||||
|
||||
configHardwareForSend(); // must be after setStandby
|
||||
|
||||
size_t numbytes = beginSending(txp);
|
||||
|
||||
@@ -24,6 +24,15 @@ ErrorCode ReliableRouter::send(meshtastic_MeshPacket *p)
|
||||
startRetransmission(copy);
|
||||
}
|
||||
|
||||
/* If we have pending retransmissions, add the airtime of this packet to it, because during that time we cannot receive an
|
||||
(implicit) ACK. Otherwise, we might retransmit too early.
|
||||
*/
|
||||
for (auto i = pending.begin(); i != pending.end(); i++) {
|
||||
if (i->first.id != p->id) {
|
||||
i->second.nextTxMsec += iface->getPacketTime(p);
|
||||
}
|
||||
}
|
||||
|
||||
return FloodingRouter::send(p);
|
||||
}
|
||||
|
||||
@@ -53,6 +62,15 @@ bool ReliableRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
|
||||
}
|
||||
}
|
||||
|
||||
/* At this point we have already deleted the pending retransmission if this packet was an (implicit) ACK to it.
|
||||
Now for all other pending retransmissions, we have to add the airtime of this received packet to the retransmission timer,
|
||||
because while receiving this packet, we could not have received an (implicit) ACK for it.
|
||||
If we don't add this, we will likely retransmit too early.
|
||||
*/
|
||||
for (auto i = pending.begin(); i != pending.end(); i++) {
|
||||
i->second.nextTxMsec += iface->getPacketTime(p);
|
||||
}
|
||||
|
||||
/* Resend implicit ACKs for repeated packets (assuming the original packet was sent with HOP_RELIABLE)
|
||||
* this way if an implicit ACK is dropped and a packet is resent we'll rebroadcast again.
|
||||
* Resending real ACKs is omitted, as you might receive a packet multiple times due to flooding and
|
||||
@@ -146,9 +164,13 @@ bool ReliableRouter::stopRetransmission(GlobalPacketId key)
|
||||
{
|
||||
auto old = findPendingPacket(key);
|
||||
if (old) {
|
||||
auto p = old->packet;
|
||||
auto numErased = pending.erase(key);
|
||||
assert(numErased == 1);
|
||||
cancelSending(getFrom(old->packet), old->packet->id);
|
||||
// remove the 'original' (identified by originator and packet->id) from the txqueue and free it
|
||||
cancelSending(getFrom(p), p->id);
|
||||
// now free the pooled copy for retransmission too
|
||||
packetPool.release(p);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
|
||||
@@ -173,6 +173,11 @@ ErrorCode Router::sendLocal(meshtastic_MeshPacket *p, RxSource src)
|
||||
handleReceived(p, src);
|
||||
}
|
||||
|
||||
if (!p->channel) { // don't override if a channel was requested
|
||||
p->channel = nodeDB.getNodeChannel(p->to);
|
||||
LOG_DEBUG("localSend to channel %d\n", p->channel);
|
||||
}
|
||||
|
||||
return send(p);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,4 +6,13 @@ SX1268Interface::SX1268Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RA
|
||||
SPIClass &spi)
|
||||
: SX126xInterface(cs, irq, rst, busy, spi)
|
||||
{
|
||||
}
|
||||
|
||||
float SX1268Interface::getFreq()
|
||||
{
|
||||
// Set frequency to default of EU_433 if outside of allowed range (e.g. when region is UNSET)
|
||||
if (savedFreq < 410 || savedFreq > 810)
|
||||
return 433.125f;
|
||||
else
|
||||
return savedFreq;
|
||||
}
|
||||
@@ -8,8 +8,7 @@
|
||||
class SX1268Interface : public SX126xInterface<SX1268>
|
||||
{
|
||||
public:
|
||||
/// override frequency of the SX1268 module regardless of the region (use EU433 value)
|
||||
virtual float getFreq() override { return 433.175f; }
|
||||
virtual float getFreq() override;
|
||||
|
||||
SX1268Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi);
|
||||
};
|
||||
|
||||
@@ -47,6 +47,8 @@ template <typename T> bool SX126xInterface<T>::init()
|
||||
int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage, useRegulatorLDO);
|
||||
// \todo Display actual typename of the adapter, not just `SX126x`
|
||||
LOG_INFO("SX126x init result %d\n", res);
|
||||
if (res == RADIOLIB_ERR_CHIP_NOT_FOUND)
|
||||
return false;
|
||||
|
||||
LOG_INFO("Frequency set to %f\n", getFreq());
|
||||
LOG_INFO("Bandwidth set to %f\n", bw);
|
||||
@@ -180,6 +182,7 @@ template <typename T> void SX126xInterface<T>::setStandby()
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
isReceiving = false; // If we were receiving, not any more
|
||||
activeReceiveStart = 0;
|
||||
disableInterrupt();
|
||||
completeSending(); // If we were sending, not anymore
|
||||
}
|
||||
@@ -212,9 +215,11 @@ template <typename T> void SX126xInterface<T>::startReceive()
|
||||
|
||||
setStandby();
|
||||
|
||||
// int err = lora.startReceive();
|
||||
int err = lora.startReceiveDutyCycleAuto(); // We use a 32 bit preamble so this should save some power by letting radio sit in
|
||||
// standby mostly.
|
||||
// We use a 16 bit preamble so this should save some power by letting radio sit in standby mostly.
|
||||
// Furthermore, we need the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving
|
||||
int err = lora.startReceiveDutyCycleAuto(preambleLength, 8,
|
||||
RADIOLIB_SX126X_IRQ_RX_DEFAULT | RADIOLIB_SX126X_IRQ_RADIOLIB_PREAMBLE_DETECTED |
|
||||
RADIOLIB_SX126X_IRQ_HEADER_VALID);
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
isReceiving = true;
|
||||
@@ -224,7 +229,7 @@ template <typename T> void SX126xInterface<T>::startReceive()
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Could we send right now (i.e. either not actively receving or transmitting)? */
|
||||
/** Is the channel currently active? */
|
||||
template <typename T> bool SX126xInterface<T>::isChannelActive()
|
||||
{
|
||||
// check if we can detect a LoRa preamble on the current channel
|
||||
@@ -232,7 +237,7 @@ template <typename T> bool SX126xInterface<T>::isChannelActive()
|
||||
|
||||
setStandby();
|
||||
result = lora.scanChannel();
|
||||
if (result == RADIOLIB_PREAMBLE_DETECTED)
|
||||
if (result == RADIOLIB_LORA_DETECTED)
|
||||
return true;
|
||||
|
||||
assert(result != RADIOLIB_ERR_WRONG_MODEM);
|
||||
@@ -245,17 +250,29 @@ template <typename T> bool SX126xInterface<T>::isActivelyReceiving()
|
||||
{
|
||||
// The IRQ status will be cleared when we start our read operation. Check if we've started a header, but haven't yet
|
||||
// received and handled the interrupt for reading the packet/handling errors.
|
||||
// FIXME: it would be better to check for preamble, but we currently have our ISR not set to fire for packets that
|
||||
// never even get a valid header, so we don't want preamble to get set and stay set due to noise on the network.
|
||||
|
||||
uint16_t irq = lora.getIrqStatus();
|
||||
bool hasPreamble = (irq & RADIOLIB_SX126X_IRQ_HEADER_VALID);
|
||||
bool detected = (irq & (RADIOLIB_SX126X_IRQ_HEADER_VALID | RADIOLIB_SX126X_IRQ_RADIOLIB_PREAMBLE_DETECTED));
|
||||
// Handle false detections
|
||||
if (detected) {
|
||||
uint32_t now = millis();
|
||||
if (!activeReceiveStart) {
|
||||
activeReceiveStart = now;
|
||||
} else if ((now - activeReceiveStart > 2 * preambleTimeMsec) && !(irq & RADIOLIB_SX126X_IRQ_HEADER_VALID)) {
|
||||
// The HEADER_VALID flag should be set by now if it was really a packet, so ignore PREAMBLE_DETECTED flag
|
||||
activeReceiveStart = 0;
|
||||
LOG_DEBUG("Ignore false preamble detection.\n");
|
||||
return false;
|
||||
} else if (now - activeReceiveStart > maxPacketTimeMsec) {
|
||||
// We should have gotten an RX_DONE IRQ by now if it was really a packet, so ignore HEADER_VALID flag
|
||||
activeReceiveStart = 0;
|
||||
LOG_DEBUG("Ignore false header detection.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// this is not correct - often always true - need to add an extra conditional
|
||||
// size_t bytesPending = lora.getPacketLength();
|
||||
|
||||
// if (hasPreamble) LOG_DEBUG("rx hasPreamble\n");
|
||||
return hasPreamble;
|
||||
// if (detected) LOG_DEBUG("rx detected\n");
|
||||
return detected;
|
||||
}
|
||||
|
||||
template <typename T> bool SX126xInterface<T>::sleep()
|
||||
|
||||
@@ -68,4 +68,5 @@ template <class T> class SX126xInterface : public RadioLibInterface
|
||||
virtual void setStandby() override;
|
||||
|
||||
private:
|
||||
uint32_t activeReceiveStart = 0;
|
||||
};
|
||||
|
||||
@@ -13,6 +13,7 @@ SX128xInterface<T>::SX128xInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq,
|
||||
SPIClass &spi)
|
||||
: RadioLibInterface(cs, irq, rst, busy, spi, &lora), lora(&module)
|
||||
{
|
||||
LOG_WARN("SX128xInterface(cs=%d, irq=%d, rst=%d, busy=%d)\n", cs, irq, rst, busy);
|
||||
}
|
||||
|
||||
/// Initialise the Driver transport hardware and software.
|
||||
@@ -73,6 +74,12 @@ template <typename T> bool SX128xInterface<T>::init()
|
||||
LOG_INFO("Bandwidth set to %f\n", bw);
|
||||
LOG_INFO("Power output set to %d\n", power);
|
||||
|
||||
#if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC) && defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC)
|
||||
if (res == RADIOLIB_ERR_NONE) {
|
||||
lora.setRfSwitchPins(SX128X_RXEN, SX128X_TXEN);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (res == RADIOLIB_ERR_NONE)
|
||||
res = lora.setCRC(2);
|
||||
|
||||
@@ -157,6 +164,7 @@ template <typename T> void SX128xInterface<T>::setStandby()
|
||||
#endif
|
||||
|
||||
isReceiving = false; // If we were receiving, not any more
|
||||
activeReceiveStart = 0;
|
||||
disableInterrupt();
|
||||
completeSending(); // If we were sending, not anymore
|
||||
}
|
||||
@@ -203,7 +211,10 @@ template <typename T> void SX128xInterface<T>::startReceive()
|
||||
digitalWrite(SX128X_TXEN, LOW);
|
||||
#endif
|
||||
|
||||
int err = lora.startReceive();
|
||||
// We use the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving
|
||||
int err = lora.startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_SX128X_IRQ_RX_DEFAULT |
|
||||
RADIOLIB_SX128X_IRQ_RADIOLIB_PREAMBLE_DETECTED |
|
||||
RADIOLIB_SX128X_IRQ_HEADER_VALID);
|
||||
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
@@ -214,7 +225,7 @@ template <typename T> void SX128xInterface<T>::startReceive()
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Could we send right now (i.e. either not actively receving or transmitting)? */
|
||||
/** Is the channel currently active? */
|
||||
template <typename T> bool SX128xInterface<T>::isChannelActive()
|
||||
{
|
||||
// check if we can detect a LoRa preamble on the current channel
|
||||
@@ -222,7 +233,7 @@ template <typename T> bool SX128xInterface<T>::isChannelActive()
|
||||
|
||||
setStandby();
|
||||
result = lora.scanChannel();
|
||||
if (result == RADIOLIB_PREAMBLE_DETECTED)
|
||||
if (result == RADIOLIB_LORA_DETECTED)
|
||||
return true;
|
||||
|
||||
assert(result != RADIOLIB_ERR_WRONG_MODEM);
|
||||
@@ -234,8 +245,27 @@ template <typename T> bool SX128xInterface<T>::isChannelActive()
|
||||
template <typename T> bool SX128xInterface<T>::isActivelyReceiving()
|
||||
{
|
||||
uint16_t irq = lora.getIrqStatus();
|
||||
bool hasPreamble = (irq & RADIOLIB_SX128X_IRQ_HEADER_VALID);
|
||||
return hasPreamble;
|
||||
bool detected = (irq & (RADIOLIB_SX128X_IRQ_HEADER_VALID | RADIOLIB_SX128X_IRQ_RADIOLIB_PREAMBLE_DETECTED));
|
||||
|
||||
// Handle false detections
|
||||
if (detected) {
|
||||
uint32_t now = millis();
|
||||
if (!activeReceiveStart) {
|
||||
activeReceiveStart = now;
|
||||
} else if ((now - activeReceiveStart > 2 * preambleTimeMsec) && !(irq & RADIOLIB_SX128X_IRQ_HEADER_VALID)) {
|
||||
// The HEADER_VALID flag should be set by now if it was really a packet, so ignore PREAMBLE_DETECTED flag
|
||||
activeReceiveStart = 0;
|
||||
LOG_DEBUG("Ignore false preamble detection.\n");
|
||||
return false;
|
||||
} else if (now - activeReceiveStart > maxPacketTimeMsec) {
|
||||
// We should have gotten an RX_DONE IRQ by now if it was really a packet, so ignore HEADER_VALID flag
|
||||
activeReceiveStart = 0;
|
||||
LOG_DEBUG("Ignore false header detection.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return detected;
|
||||
}
|
||||
|
||||
template <typename T> bool SX128xInterface<T>::sleep()
|
||||
|
||||
@@ -68,4 +68,5 @@ template <class T> class SX128xInterface : public RadioLibInterface
|
||||
virtual void setStandby() override;
|
||||
|
||||
private:
|
||||
uint32_t activeReceiveStart = 0;
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "NodeDB.h"
|
||||
#include "RTC.h"
|
||||
#include "concurrency/Periodic.h"
|
||||
#include "main.h"
|
||||
#include "mesh/api/ethServerAPI.h"
|
||||
#include "mqtt/MQTT.h"
|
||||
#include "target_specific.h"
|
||||
@@ -17,6 +18,9 @@ NTPClient timeClient(ntpUDP, config.network.ntp_server);
|
||||
uint32_t ntp_renew = 0;
|
||||
#endif
|
||||
|
||||
EthernetUDP syslogClient;
|
||||
Syslog syslog(syslogClient);
|
||||
|
||||
bool ethStartupComplete = 0;
|
||||
|
||||
using namespace concurrency;
|
||||
@@ -36,6 +40,27 @@ static int32_t reconnectETH()
|
||||
timeClient.begin();
|
||||
timeClient.setUpdateInterval(60 * 60); // Update once an hour
|
||||
#endif
|
||||
|
||||
if (config.network.rsyslog_server[0]) {
|
||||
LOG_INFO("Starting Syslog client\n");
|
||||
// Defaults
|
||||
int serverPort = 514;
|
||||
const char *serverAddr = config.network.rsyslog_server;
|
||||
String server = String(serverAddr);
|
||||
int delimIndex = server.indexOf(':');
|
||||
if (delimIndex > 0) {
|
||||
String port = server.substring(delimIndex + 1, server.length());
|
||||
server[delimIndex] = 0;
|
||||
serverPort = port.toInt();
|
||||
serverAddr = server.c_str();
|
||||
}
|
||||
syslog.server(serverAddr, serverPort);
|
||||
syslog.deviceHostname(getDeviceName());
|
||||
syslog.appName("Meshtastic");
|
||||
syslog.defaultPriority(LOGLEVEL_USER);
|
||||
syslog.enable();
|
||||
}
|
||||
|
||||
// initWebServer();
|
||||
initApiServer();
|
||||
|
||||
@@ -143,10 +168,13 @@ bool isEthernetAvailable()
|
||||
{
|
||||
|
||||
if (!config.network.eth_enabled) {
|
||||
syslog.disable();
|
||||
return false;
|
||||
} else if (Ethernet.hardwareStatus() == EthernetNoHardware) {
|
||||
syslog.disable();
|
||||
return false;
|
||||
} else if (Ethernet.linkStatus() == LinkOFF) {
|
||||
syslog.disable();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
PB_BIND(meshtastic_AdminMessage, meshtastic_AdminMessage, 2)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_HamParameters, meshtastic_HamParameters, AUTO)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <pb.h>
|
||||
#include "meshtastic/channel.pb.h"
|
||||
#include "meshtastic/config.pb.h"
|
||||
#include "meshtastic/device_metadata.pb.h"
|
||||
#include "meshtastic/mesh.pb.h"
|
||||
#include "meshtastic/module_config.pb.h"
|
||||
#include "meshtastic/connection_status.pb.h"
|
||||
@@ -57,6 +56,20 @@ typedef enum _meshtastic_AdminMessage_ModuleConfigType {
|
||||
} meshtastic_AdminMessage_ModuleConfigType;
|
||||
|
||||
/* Struct definitions */
|
||||
/* Parameters for setting up Meshtastic for ameteur radio usage */
|
||||
typedef struct _meshtastic_HamParameters {
|
||||
/* Amateur radio call sign, eg. KD2ABC */
|
||||
char call_sign[8];
|
||||
/* Transmit power in dBm at the LoRA transceiver, not including any amplification */
|
||||
int32_t tx_power;
|
||||
/* The selected frequency of LoRA operation
|
||||
Please respect your local laws, regulations, and band plans.
|
||||
Ensure your radio is capable of operating of the selected frequency before setting this. */
|
||||
float frequency;
|
||||
/* Optional short name of user */
|
||||
char short_name[6];
|
||||
} meshtastic_HamParameters;
|
||||
|
||||
/* This message is handled by the Admin module and is responsible for all settings/channel read/write operations.
|
||||
This message is used to do settings operations to both remote AND local nodes.
|
||||
(Prior to 1.2 these operations were done via special ToRadio operations) */
|
||||
@@ -96,6 +109,8 @@ typedef struct _meshtastic_AdminMessage {
|
||||
bool get_device_connection_status_request;
|
||||
/* Device connection status response */
|
||||
meshtastic_DeviceConnectionStatus get_device_connection_status_response;
|
||||
/* Setup a node for licensed amateur (ham) radio operation */
|
||||
meshtastic_HamParameters set_ham_mode;
|
||||
/* Set the owner for this node */
|
||||
meshtastic_User set_owner;
|
||||
/* Set channels (using the new API).
|
||||
@@ -120,7 +135,7 @@ typedef struct _meshtastic_AdminMessage {
|
||||
/* Tell the node to reboot into the OTA Firmware in this many seconds (or <0 to cancel reboot)
|
||||
Only Implemented for ESP32 Devices. This needs to be issued to send a new main firmware via bluetooth. */
|
||||
int32_t reboot_ota_seconds;
|
||||
/* This message is only supported for the simulator porduino build.
|
||||
/* This message is only supported for the simulator Portduino build.
|
||||
If received the simulator will exit successfully. */
|
||||
bool exit_simulator;
|
||||
/* Tell the node to reboot in this many seconds (or <0 to cancel reboot) */
|
||||
@@ -152,11 +167,18 @@ extern "C" {
|
||||
#define meshtastic_AdminMessage_payload_variant_get_module_config_request_ENUMTYPE meshtastic_AdminMessage_ModuleConfigType
|
||||
|
||||
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_AdminMessage_init_default {0, {0}}
|
||||
#define meshtastic_HamParameters_init_default {"", 0, 0, ""}
|
||||
#define meshtastic_AdminMessage_init_zero {0, {0}}
|
||||
#define meshtastic_HamParameters_init_zero {"", 0, 0, ""}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define meshtastic_HamParameters_call_sign_tag 1
|
||||
#define meshtastic_HamParameters_tx_power_tag 2
|
||||
#define meshtastic_HamParameters_frequency_tag 3
|
||||
#define meshtastic_HamParameters_short_name_tag 4
|
||||
#define meshtastic_AdminMessage_get_channel_request_tag 1
|
||||
#define meshtastic_AdminMessage_get_channel_response_tag 2
|
||||
#define meshtastic_AdminMessage_get_owner_request_tag 3
|
||||
@@ -173,6 +195,7 @@ extern "C" {
|
||||
#define meshtastic_AdminMessage_get_ringtone_response_tag 15
|
||||
#define meshtastic_AdminMessage_get_device_connection_status_request_tag 16
|
||||
#define meshtastic_AdminMessage_get_device_connection_status_response_tag 17
|
||||
#define meshtastic_AdminMessage_set_ham_mode_tag 18
|
||||
#define meshtastic_AdminMessage_set_owner_tag 32
|
||||
#define meshtastic_AdminMessage_set_channel_tag 33
|
||||
#define meshtastic_AdminMessage_set_config_tag 34
|
||||
@@ -206,6 +229,7 @@ X(a, STATIC, ONEOF, BOOL, (payload_variant,get_ringtone_request,get_rin
|
||||
X(a, STATIC, ONEOF, STRING, (payload_variant,get_ringtone_response,get_ringtone_response), 15) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payload_variant,get_device_connection_status_request,get_device_connection_status_request), 16) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,get_device_connection_status_response,get_device_connection_status_response), 17) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_ham_mode,set_ham_mode), 18) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_owner,set_owner), 32) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_channel,set_channel), 33) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_config,set_config), 34) \
|
||||
@@ -228,18 +252,30 @@ X(a, STATIC, ONEOF, INT32, (payload_variant,nodedb_reset,nodedb_reset),
|
||||
#define meshtastic_AdminMessage_payload_variant_get_module_config_response_MSGTYPE meshtastic_ModuleConfig
|
||||
#define meshtastic_AdminMessage_payload_variant_get_device_metadata_response_MSGTYPE meshtastic_DeviceMetadata
|
||||
#define meshtastic_AdminMessage_payload_variant_get_device_connection_status_response_MSGTYPE meshtastic_DeviceConnectionStatus
|
||||
#define meshtastic_AdminMessage_payload_variant_set_ham_mode_MSGTYPE meshtastic_HamParameters
|
||||
#define meshtastic_AdminMessage_payload_variant_set_owner_MSGTYPE meshtastic_User
|
||||
#define meshtastic_AdminMessage_payload_variant_set_channel_MSGTYPE meshtastic_Channel
|
||||
#define meshtastic_AdminMessage_payload_variant_set_config_MSGTYPE meshtastic_Config
|
||||
#define meshtastic_AdminMessage_payload_variant_set_module_config_MSGTYPE meshtastic_ModuleConfig
|
||||
|
||||
#define meshtastic_HamParameters_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, STRING, call_sign, 1) \
|
||||
X(a, STATIC, SINGULAR, INT32, tx_power, 2) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, frequency, 3) \
|
||||
X(a, STATIC, SINGULAR, STRING, short_name, 4)
|
||||
#define meshtastic_HamParameters_CALLBACK NULL
|
||||
#define meshtastic_HamParameters_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t meshtastic_AdminMessage_msg;
|
||||
extern const pb_msgdesc_t meshtastic_HamParameters_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define meshtastic_AdminMessage_fields &meshtastic_AdminMessage_msg
|
||||
#define meshtastic_HamParameters_fields &meshtastic_HamParameters_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_AdminMessage_size 234
|
||||
#define meshtastic_HamParameters_size 32
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -31,7 +31,10 @@ typedef enum _meshtastic_Config_DeviceConfig_Role {
|
||||
meshtastic_Config_DeviceConfig_Role_REPEATER = 4,
|
||||
/* Tracker device role
|
||||
Position Mesh packets will be prioritized higher and sent more frequently by default. */
|
||||
meshtastic_Config_DeviceConfig_Role_TRACKER = 5
|
||||
meshtastic_Config_DeviceConfig_Role_TRACKER = 5,
|
||||
/* Sensor device role
|
||||
Telemetry Mesh packets will be prioritized higher and sent more frequently by default. */
|
||||
meshtastic_Config_DeviceConfig_Role_SENSOR = 6
|
||||
} meshtastic_Config_DeviceConfig_Role;
|
||||
|
||||
/* Defines the device's behavior for how messages are rebroadcast */
|
||||
@@ -149,7 +152,7 @@ typedef enum _meshtastic_Config_LoRaConfig_RegionCode {
|
||||
meshtastic_Config_LoRaConfig_RegionCode_US = 1,
|
||||
/* European Union 433mhz */
|
||||
meshtastic_Config_LoRaConfig_RegionCode_EU_433 = 2,
|
||||
/* European Union 433mhz */
|
||||
/* European Union 868mhz */
|
||||
meshtastic_Config_LoRaConfig_RegionCode_EU_868 = 3,
|
||||
/* China */
|
||||
meshtastic_Config_LoRaConfig_RegionCode_CN = 4,
|
||||
@@ -199,11 +202,11 @@ typedef enum _meshtastic_Config_LoRaConfig_ModemPreset {
|
||||
} meshtastic_Config_LoRaConfig_ModemPreset;
|
||||
|
||||
typedef enum _meshtastic_Config_BluetoothConfig_PairingMode {
|
||||
/* Device generates a random pin that will be shown on the screen of the device for pairing */
|
||||
/* Device generates a random PIN that will be shown on the screen of the device for pairing */
|
||||
meshtastic_Config_BluetoothConfig_PairingMode_RANDOM_PIN = 0,
|
||||
/* Device requires a specified fixed pin for pairing */
|
||||
/* Device requires a specified fixed PIN for pairing */
|
||||
meshtastic_Config_BluetoothConfig_PairingMode_FIXED_PIN = 1,
|
||||
/* Device requires no pin for pairing */
|
||||
/* Device requires no PIN for pairing */
|
||||
meshtastic_Config_BluetoothConfig_PairingMode_NO_PIN = 2
|
||||
} meshtastic_Config_BluetoothConfig_PairingMode;
|
||||
|
||||
@@ -225,6 +228,11 @@ typedef struct _meshtastic_Config_DeviceConfig {
|
||||
uint32_t buzzer_gpio;
|
||||
/* Sets the role of node */
|
||||
meshtastic_Config_DeviceConfig_RebroadcastMode rebroadcast_mode;
|
||||
/* Send our nodeinfo this often
|
||||
Defaults to 900 Seconds (15 minutes) */
|
||||
uint32_t node_info_broadcast_secs;
|
||||
/* Treat double tap interrupt on supported accelerometers as a button press if set to true */
|
||||
bool double_tap_as_button_press;
|
||||
} meshtastic_Config_DeviceConfig;
|
||||
|
||||
/* Position Config */
|
||||
@@ -256,6 +264,10 @@ typedef struct _meshtastic_Config_PositionConfig {
|
||||
uint32_t rx_gpio;
|
||||
/* (Re)define GPS_TX_PIN for your board. */
|
||||
uint32_t tx_gpio;
|
||||
/* The minimum distance in meters traveled (since the last send) before we can send a position to the mesh if position_broadcast_smart_enabled */
|
||||
uint32_t broadcast_smart_minimum_distance;
|
||||
/* The minumum number of seconds (since the last send) before we can send a position to the mesh if position_broadcast_smart_enabled */
|
||||
uint32_t broadcast_smart_minimum_interval_secs;
|
||||
} meshtastic_Config_PositionConfig;
|
||||
|
||||
/* Power Config\
|
||||
@@ -354,11 +366,13 @@ typedef struct _meshtastic_Config_DisplayConfig {
|
||||
meshtastic_Config_DisplayConfig_DisplayMode displaymode;
|
||||
/* Print first line in pseudo-bold? FALSE is original style, TRUE is bold */
|
||||
bool heading_bold;
|
||||
/* Should we wake the screen up on accelerometer detected motion or tap */
|
||||
bool wake_on_tap_or_motion;
|
||||
} meshtastic_Config_DisplayConfig;
|
||||
|
||||
/* Lora Config */
|
||||
typedef struct _meshtastic_Config_LoRaConfig {
|
||||
/* When enabled, the `modem_preset` fields will be adheared to, else the `bandwidth`/`spread_factor`/`coding_rate`
|
||||
/* When enabled, the `modem_preset` fields will be adhered to, else the `bandwidth`/`spread_factor`/`coding_rate`
|
||||
will be taked from their respective manually defined fields */
|
||||
bool use_preset;
|
||||
/* Either modem_config or bandwidth/spreading/coding will be specified - NOT BOTH.
|
||||
@@ -389,12 +403,12 @@ typedef struct _meshtastic_Config_LoRaConfig {
|
||||
/* Disable TX from the LoRa radio. Useful for hot-swapping antennas and other tests.
|
||||
Defaults to false */
|
||||
bool tx_enabled;
|
||||
/* If zero then, use default max legal continuous power (ie. something that won't
|
||||
/* If zero, then use default max legal continuous power (ie. something that won't
|
||||
burn out the radio hardware)
|
||||
In most cases you should use zero here.
|
||||
Units are in dBm. */
|
||||
int8_t tx_power;
|
||||
/* This is controlling the actual hardware frequency the radio is transmitting on.
|
||||
/* This controls the actual hardware frequency the radio transmits on.
|
||||
Most users should never need to be exposed to this field/concept.
|
||||
A channel number between 1 and NUM_CHANNELS (whatever the max is in the current region).
|
||||
If ZERO then the rule is "use the old channel name hash based
|
||||
@@ -416,7 +430,7 @@ typedef struct _meshtastic_Config_LoRaConfig {
|
||||
float override_frequency;
|
||||
/* For testing it is useful sometimes to force a node to never listen to
|
||||
particular other nodes (simulating radio out of range). All nodenums listed
|
||||
in ignore_incoming will have packets they send droped on receive (by router.cpp) */
|
||||
in ignore_incoming will have packets they send dropped on receive (by router.cpp) */
|
||||
pb_size_t ignore_incoming_count;
|
||||
uint32_t ignore_incoming[3];
|
||||
} meshtastic_Config_LoRaConfig;
|
||||
@@ -426,7 +440,7 @@ typedef struct _meshtastic_Config_BluetoothConfig {
|
||||
bool enabled;
|
||||
/* Determines the pairing strategy for the device */
|
||||
meshtastic_Config_BluetoothConfig_PairingMode mode;
|
||||
/* Specified pin for PairingMode.FixedPin */
|
||||
/* Specified PIN for PairingMode.FixedPin */
|
||||
uint32_t fixed_pin;
|
||||
} meshtastic_Config_BluetoothConfig;
|
||||
|
||||
@@ -450,8 +464,8 @@ extern "C" {
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _meshtastic_Config_DeviceConfig_Role_MIN meshtastic_Config_DeviceConfig_Role_CLIENT
|
||||
#define _meshtastic_Config_DeviceConfig_Role_MAX meshtastic_Config_DeviceConfig_Role_TRACKER
|
||||
#define _meshtastic_Config_DeviceConfig_Role_ARRAYSIZE ((meshtastic_Config_DeviceConfig_Role)(meshtastic_Config_DeviceConfig_Role_TRACKER+1))
|
||||
#define _meshtastic_Config_DeviceConfig_Role_MAX meshtastic_Config_DeviceConfig_Role_SENSOR
|
||||
#define _meshtastic_Config_DeviceConfig_Role_ARRAYSIZE ((meshtastic_Config_DeviceConfig_Role)(meshtastic_Config_DeviceConfig_Role_SENSOR+1))
|
||||
|
||||
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN meshtastic_Config_DeviceConfig_RebroadcastMode_ALL
|
||||
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MAX meshtastic_Config_DeviceConfig_RebroadcastMode_LOCAL_ONLY
|
||||
@@ -515,21 +529,21 @@ extern "C" {
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}}
|
||||
#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN}
|
||||
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0}
|
||||
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""}
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0}
|
||||
#define meshtastic_Config_DisplayConfig_init_default {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0}
|
||||
#define meshtastic_Config_DisplayConfig_init_default {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0}
|
||||
#define meshtastic_Config_LoRaConfig_init_default {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}}
|
||||
#define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
|
||||
#define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}}
|
||||
#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN}
|
||||
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0}
|
||||
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""}
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0}
|
||||
#define meshtastic_Config_DisplayConfig_init_zero {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0}
|
||||
#define meshtastic_Config_DisplayConfig_init_zero {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0}
|
||||
#define meshtastic_Config_LoRaConfig_init_zero {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}}
|
||||
#define meshtastic_Config_BluetoothConfig_init_zero {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
|
||||
|
||||
@@ -540,6 +554,8 @@ extern "C" {
|
||||
#define meshtastic_Config_DeviceConfig_button_gpio_tag 4
|
||||
#define meshtastic_Config_DeviceConfig_buzzer_gpio_tag 5
|
||||
#define meshtastic_Config_DeviceConfig_rebroadcast_mode_tag 6
|
||||
#define meshtastic_Config_DeviceConfig_node_info_broadcast_secs_tag 7
|
||||
#define meshtastic_Config_DeviceConfig_double_tap_as_button_press_tag 8
|
||||
#define meshtastic_Config_PositionConfig_position_broadcast_secs_tag 1
|
||||
#define meshtastic_Config_PositionConfig_position_broadcast_smart_enabled_tag 2
|
||||
#define meshtastic_Config_PositionConfig_fixed_position_tag 3
|
||||
@@ -549,6 +565,8 @@ extern "C" {
|
||||
#define meshtastic_Config_PositionConfig_position_flags_tag 7
|
||||
#define meshtastic_Config_PositionConfig_rx_gpio_tag 8
|
||||
#define meshtastic_Config_PositionConfig_tx_gpio_tag 9
|
||||
#define meshtastic_Config_PositionConfig_broadcast_smart_minimum_distance_tag 10
|
||||
#define meshtastic_Config_PositionConfig_broadcast_smart_minimum_interval_secs_tag 11
|
||||
#define meshtastic_Config_PowerConfig_is_power_saving_tag 1
|
||||
#define meshtastic_Config_PowerConfig_on_battery_shutdown_after_secs_tag 2
|
||||
#define meshtastic_Config_PowerConfig_adc_multiplier_override_tag 3
|
||||
@@ -578,6 +596,7 @@ extern "C" {
|
||||
#define meshtastic_Config_DisplayConfig_oled_tag 7
|
||||
#define meshtastic_Config_DisplayConfig_displaymode_tag 8
|
||||
#define meshtastic_Config_DisplayConfig_heading_bold_tag 9
|
||||
#define meshtastic_Config_DisplayConfig_wake_on_tap_or_motion_tag 10
|
||||
#define meshtastic_Config_LoRaConfig_use_preset_tag 1
|
||||
#define meshtastic_Config_LoRaConfig_modem_preset_tag 2
|
||||
#define meshtastic_Config_LoRaConfig_bandwidth_tag 3
|
||||
@@ -629,7 +648,9 @@ X(a, STATIC, SINGULAR, BOOL, serial_enabled, 2) \
|
||||
X(a, STATIC, SINGULAR, BOOL, debug_log_enabled, 3) \
|
||||
X(a, STATIC, SINGULAR, UINT32, button_gpio, 4) \
|
||||
X(a, STATIC, SINGULAR, UINT32, buzzer_gpio, 5) \
|
||||
X(a, STATIC, SINGULAR, UENUM, rebroadcast_mode, 6)
|
||||
X(a, STATIC, SINGULAR, UENUM, rebroadcast_mode, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, node_info_broadcast_secs, 7) \
|
||||
X(a, STATIC, SINGULAR, BOOL, double_tap_as_button_press, 8)
|
||||
#define meshtastic_Config_DeviceConfig_CALLBACK NULL
|
||||
#define meshtastic_Config_DeviceConfig_DEFAULT NULL
|
||||
|
||||
@@ -642,7 +663,9 @@ X(a, STATIC, SINGULAR, UINT32, gps_update_interval, 5) \
|
||||
X(a, STATIC, SINGULAR, UINT32, gps_attempt_time, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, position_flags, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, rx_gpio, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, tx_gpio, 9)
|
||||
X(a, STATIC, SINGULAR, UINT32, tx_gpio, 9) \
|
||||
X(a, STATIC, SINGULAR, UINT32, broadcast_smart_minimum_distance, 10) \
|
||||
X(a, STATIC, SINGULAR, UINT32, broadcast_smart_minimum_interval_secs, 11)
|
||||
#define meshtastic_Config_PositionConfig_CALLBACK NULL
|
||||
#define meshtastic_Config_PositionConfig_DEFAULT NULL
|
||||
|
||||
@@ -688,7 +711,8 @@ X(a, STATIC, SINGULAR, BOOL, flip_screen, 5) \
|
||||
X(a, STATIC, SINGULAR, UENUM, units, 6) \
|
||||
X(a, STATIC, SINGULAR, UENUM, oled, 7) \
|
||||
X(a, STATIC, SINGULAR, UENUM, displaymode, 8) \
|
||||
X(a, STATIC, SINGULAR, BOOL, heading_bold, 9)
|
||||
X(a, STATIC, SINGULAR, BOOL, heading_bold, 9) \
|
||||
X(a, STATIC, SINGULAR, BOOL, wake_on_tap_or_motion, 10)
|
||||
#define meshtastic_Config_DisplayConfig_CALLBACK NULL
|
||||
#define meshtastic_Config_DisplayConfig_DEFAULT NULL
|
||||
|
||||
@@ -741,12 +765,12 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_Config_BluetoothConfig_size 10
|
||||
#define meshtastic_Config_DeviceConfig_size 20
|
||||
#define meshtastic_Config_DisplayConfig_size 26
|
||||
#define meshtastic_Config_DeviceConfig_size 28
|
||||
#define meshtastic_Config_DisplayConfig_size 28
|
||||
#define meshtastic_Config_LoRaConfig_size 77
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20
|
||||
#define meshtastic_Config_NetworkConfig_size 195
|
||||
#define meshtastic_Config_PositionConfig_size 42
|
||||
#define meshtastic_Config_PositionConfig_size 54
|
||||
#define meshtastic_Config_PowerConfig_size 43
|
||||
#define meshtastic_Config_size 198
|
||||
|
||||
|
||||
@@ -27,9 +27,9 @@ typedef struct _meshtastic_WifiConnectionStatus {
|
||||
/* Connection status */
|
||||
bool has_status;
|
||||
meshtastic_NetworkConnectionStatus status;
|
||||
/* WiFi access point ssid */
|
||||
/* WiFi access point SSID */
|
||||
char ssid[33];
|
||||
/* Rssi of wireless connection */
|
||||
/* RSSI of wireless connection */
|
||||
int32_t rssi;
|
||||
} meshtastic_WifiConnectionStatus;
|
||||
|
||||
@@ -42,9 +42,9 @@ typedef struct _meshtastic_EthernetConnectionStatus {
|
||||
|
||||
/* Bluetooth connection status */
|
||||
typedef struct _meshtastic_BluetoothConnectionStatus {
|
||||
/* The pairing pin for bluetooth */
|
||||
/* The pairing PIN for bluetooth */
|
||||
uint32_t pin;
|
||||
/* Rssi of bluetooth connection */
|
||||
/* RSSI of bluetooth connection */
|
||||
int32_t rssi;
|
||||
/* Whether the device has an active connection or not */
|
||||
bool is_connected;
|
||||
@@ -52,7 +52,7 @@ typedef struct _meshtastic_BluetoothConnectionStatus {
|
||||
|
||||
/* Serial connection status */
|
||||
typedef struct _meshtastic_SerialConnectionStatus {
|
||||
/* The serial baud rate */
|
||||
/* Serial baud rate */
|
||||
uint32_t baud;
|
||||
/* Whether the device has an active connection or not */
|
||||
bool is_connected;
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.4.7 */
|
||||
|
||||
#include "meshtastic/device_metadata.pb.h"
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(meshtastic_DeviceMetadata, meshtastic_DeviceMetadata, AUTO)
|
||||
|
||||
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.4.7 */
|
||||
|
||||
#ifndef PB_MESHTASTIC_MESHTASTIC_DEVICE_METADATA_PB_H_INCLUDED
|
||||
#define PB_MESHTASTIC_MESHTASTIC_DEVICE_METADATA_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
#include "meshtastic/config.pb.h"
|
||||
#include "meshtastic/mesh.pb.h"
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
/* Struct definitions */
|
||||
/* Device metadata response */
|
||||
typedef struct _meshtastic_DeviceMetadata {
|
||||
/* Device firmware version string */
|
||||
char firmware_version[18];
|
||||
/* Device state version */
|
||||
uint32_t device_state_version;
|
||||
/* Indicates whether the device can shutdown CPU natively or via power management chip */
|
||||
bool canShutdown;
|
||||
/* Indicates that the device has native wifi capability */
|
||||
bool hasWifi;
|
||||
/* Indicates that the device has native bluetooth capability */
|
||||
bool hasBluetooth;
|
||||
/* Indicates that the device has an ethernet peripheral */
|
||||
bool hasEthernet;
|
||||
/* Indicates that the device's role in the mesh */
|
||||
meshtastic_Config_DeviceConfig_Role role;
|
||||
/* Indicates the device's current enabled position flags */
|
||||
uint32_t position_flags;
|
||||
/* Device hardware model */
|
||||
meshtastic_HardwareModel hw_model;
|
||||
} meshtastic_DeviceMetadata;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_DeviceMetadata_init_default {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN}
|
||||
#define meshtastic_DeviceMetadata_init_zero {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define meshtastic_DeviceMetadata_firmware_version_tag 1
|
||||
#define meshtastic_DeviceMetadata_device_state_version_tag 2
|
||||
#define meshtastic_DeviceMetadata_canShutdown_tag 3
|
||||
#define meshtastic_DeviceMetadata_hasWifi_tag 4
|
||||
#define meshtastic_DeviceMetadata_hasBluetooth_tag 5
|
||||
#define meshtastic_DeviceMetadata_hasEthernet_tag 6
|
||||
#define meshtastic_DeviceMetadata_role_tag 7
|
||||
#define meshtastic_DeviceMetadata_position_flags_tag 8
|
||||
#define meshtastic_DeviceMetadata_hw_model_tag 9
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define meshtastic_DeviceMetadata_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, STRING, firmware_version, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, device_state_version, 2) \
|
||||
X(a, STATIC, SINGULAR, BOOL, canShutdown, 3) \
|
||||
X(a, STATIC, SINGULAR, BOOL, hasWifi, 4) \
|
||||
X(a, STATIC, SINGULAR, BOOL, hasBluetooth, 5) \
|
||||
X(a, STATIC, SINGULAR, BOOL, hasEthernet, 6) \
|
||||
X(a, STATIC, SINGULAR, UENUM, role, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, position_flags, 8) \
|
||||
X(a, STATIC, SINGULAR, UENUM, hw_model, 9)
|
||||
#define meshtastic_DeviceMetadata_CALLBACK NULL
|
||||
#define meshtastic_DeviceMetadata_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define meshtastic_DeviceMetadata_fields &meshtastic_DeviceMetadata_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_DeviceMetadata_size 44
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -54,7 +54,7 @@ typedef struct _meshtastic_DeviceState {
|
||||
/* Used only during development.
|
||||
Indicates developer is testing and changes should never be saved to flash. */
|
||||
bool no_save;
|
||||
/* Some GPSes seem to have bogus settings from the factory, so we always do one factory reset. */
|
||||
/* Some GPS receivers seem to have bogus settings from the factory, so we always do one factory reset. */
|
||||
bool did_gps_reset;
|
||||
} meshtastic_DeviceState;
|
||||
|
||||
@@ -72,13 +72,13 @@ typedef struct _meshtastic_ChannelFile {
|
||||
typedef PB_BYTES_ARRAY_T(2048) meshtastic_OEMStore_oem_icon_bits_t;
|
||||
typedef PB_BYTES_ARRAY_T(32) meshtastic_OEMStore_oem_aes_key_t;
|
||||
/* 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 custom logo and text for 2.5 seconds. */
|
||||
typedef struct _meshtastic_OEMStore {
|
||||
/* The Logo width in Px */
|
||||
uint32_t oem_icon_width;
|
||||
/* The Logo height in Px */
|
||||
uint32_t oem_icon_height;
|
||||
/* The Logo in xbm bytechar format */
|
||||
/* The Logo in XBM bytechar format */
|
||||
meshtastic_OEMStore_oem_icon_bits_t oem_icon_bits;
|
||||
/* Use this font for the OEM text. */
|
||||
meshtastic_ScreenFonts oem_font;
|
||||
@@ -187,8 +187,8 @@ extern const pb_msgdesc_t meshtastic_OEMStore_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_ChannelFile_size 638
|
||||
#define meshtastic_DeviceState_size 21800
|
||||
#define meshtastic_OEMStore_size 2992
|
||||
#define meshtastic_DeviceState_size 22040
|
||||
#define meshtastic_OEMStore_size 3022
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -156,8 +156,8 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
|
||||
#define meshtastic_LocalModuleConfig_fields &meshtastic_LocalModuleConfig_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_LocalConfig_size 434
|
||||
#define meshtastic_LocalModuleConfig_size 412
|
||||
#define meshtastic_LocalConfig_size 456
|
||||
#define meshtastic_LocalModuleConfig_size 420
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -48,6 +48,9 @@ PB_BIND(meshtastic_ToRadio, meshtastic_ToRadio, 2)
|
||||
PB_BIND(meshtastic_Compressed, meshtastic_Compressed, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_DeviceMetadata, meshtastic_DeviceMetadata, AUTO)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -57,9 +57,13 @@ typedef enum _meshtastic_HardwareModel {
|
||||
meshtastic_HardwareModel_TLORA_V2_1_1P8 = 15,
|
||||
/* TODO: REPLACE */
|
||||
meshtastic_HardwareModel_TLORA_T3_S3 = 16,
|
||||
/* B&Q Consulting Nano G1 Explorer: https://wiki.uniteng.com/en/meshtastic/nano-g1-explorer */
|
||||
meshtastic_HardwareModel_NANO_G1_EXPLORER = 17,
|
||||
/* B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station */
|
||||
meshtastic_HardwareModel_STATION_G1 = 25,
|
||||
/* Less common/prototype boards listed here (needs one more byte over the air) */
|
||||
/* ---------------------------------------------------------------------------
|
||||
Less common/prototype boards listed here (needs one more byte over the air)
|
||||
--------------------------------------------------------------------------- */
|
||||
meshtastic_HardwareModel_LORA_RELAY_V1 = 32,
|
||||
/* TODO: REPLACE */
|
||||
meshtastic_HardwareModel_NRF52840DK = 33,
|
||||
@@ -87,7 +91,11 @@ typedef enum _meshtastic_HardwareModel {
|
||||
meshtastic_HardwareModel_HELTEC_WSL_V3 = 44,
|
||||
/* New BETAFPV ELRS Micro TX Module 2.4G with ESP32 CPU */
|
||||
meshtastic_HardwareModel_BETAFPV_2400_TX = 45,
|
||||
/* Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits. */
|
||||
/* BetaFPV ExpressLRS "Nano" TX Module 900MHz with ESP32 CPU */
|
||||
meshtastic_HardwareModel_BETAFPV_900_NANO_TX = 46,
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
|
||||
------------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
meshtastic_HardwareModel_PRIVATE_HW = 255
|
||||
} meshtastic_HardwareModel;
|
||||
|
||||
@@ -555,6 +563,8 @@ typedef struct _meshtastic_NodeInfo {
|
||||
/* The latest device metrics for the node. */
|
||||
bool has_device_metrics;
|
||||
meshtastic_DeviceMetrics device_metrics;
|
||||
/* local channel index we heard that node on. Only populated if its not the default channel. */
|
||||
uint8_t channel;
|
||||
} meshtastic_NodeInfo;
|
||||
|
||||
/* Unique local debugging info for this node
|
||||
@@ -637,6 +647,61 @@ typedef struct _meshtastic_QueueStatus {
|
||||
uint32_t mesh_packet_id;
|
||||
} meshtastic_QueueStatus;
|
||||
|
||||
/* Packets/commands to the radio will be written (reliably) to the toRadio characteristic.
|
||||
Once the write completes the phone can assume it is handled. */
|
||||
typedef struct _meshtastic_ToRadio {
|
||||
pb_size_t which_payload_variant;
|
||||
union {
|
||||
/* Send this packet on the mesh */
|
||||
meshtastic_MeshPacket packet;
|
||||
/* Phone wants radio to send full node db to the phone, This is
|
||||
typically the first packet sent to the radio when the phone gets a
|
||||
bluetooth connection. The radio will respond by sending back a
|
||||
MyNodeInfo, a owner, a radio config and a series of
|
||||
FromRadio.node_infos, and config_complete
|
||||
the integer you write into this field will be reported back in the
|
||||
config_complete_id response this allows clients to never be confused by
|
||||
a stale old partially sent config. */
|
||||
uint32_t want_config_id;
|
||||
/* Tell API server we are disconnecting now.
|
||||
This is useful for serial links where there is no hardware/protocol based notification that the client has dropped the link.
|
||||
(Sending this message is optional for clients) */
|
||||
bool disconnect;
|
||||
meshtastic_XModem xmodemPacket;
|
||||
};
|
||||
} meshtastic_ToRadio;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(237) meshtastic_Compressed_data_t;
|
||||
/* Compressed message payload */
|
||||
typedef struct _meshtastic_Compressed {
|
||||
/* PortNum to determine the how to handle the compressed payload. */
|
||||
meshtastic_PortNum portnum;
|
||||
/* Compressed data. */
|
||||
meshtastic_Compressed_data_t data;
|
||||
} meshtastic_Compressed;
|
||||
|
||||
/* Device metadata response */
|
||||
typedef struct _meshtastic_DeviceMetadata {
|
||||
/* Device firmware version string */
|
||||
char firmware_version[18];
|
||||
/* Device state version */
|
||||
uint32_t device_state_version;
|
||||
/* Indicates whether the device can shutdown CPU natively or via power management chip */
|
||||
bool canShutdown;
|
||||
/* Indicates that the device has native wifi capability */
|
||||
bool hasWifi;
|
||||
/* Indicates that the device has native bluetooth capability */
|
||||
bool hasBluetooth;
|
||||
/* Indicates that the device has an ethernet peripheral */
|
||||
bool hasEthernet;
|
||||
/* Indicates that the device's role in the mesh */
|
||||
meshtastic_Config_DeviceConfig_Role role;
|
||||
/* Indicates the device's current enabled position flags */
|
||||
uint32_t position_flags;
|
||||
/* Device hardware model */
|
||||
meshtastic_HardwareModel hw_model;
|
||||
} meshtastic_DeviceMetadata;
|
||||
|
||||
/* Packets from the radio to the phone will appear on the fromRadio characteristic.
|
||||
It will support READ and NOTIFY. When a new packet arrives the device will BLE notify?
|
||||
It will sit in that descriptor until consumed by the phone,
|
||||
@@ -677,42 +742,11 @@ typedef struct _meshtastic_FromRadio {
|
||||
meshtastic_QueueStatus queueStatus;
|
||||
/* File Transfer Chunk */
|
||||
meshtastic_XModem xmodemPacket;
|
||||
/* Device metadata message */
|
||||
meshtastic_DeviceMetadata metadata;
|
||||
};
|
||||
} meshtastic_FromRadio;
|
||||
|
||||
/* Packets/commands to the radio will be written (reliably) to the toRadio characteristic.
|
||||
Once the write completes the phone can assume it is handled. */
|
||||
typedef struct _meshtastic_ToRadio {
|
||||
pb_size_t which_payload_variant;
|
||||
union {
|
||||
/* Send this packet on the mesh */
|
||||
meshtastic_MeshPacket packet;
|
||||
/* Phone wants radio to send full node db to the phone, This is
|
||||
typically the first packet sent to the radio when the phone gets a
|
||||
bluetooth connection. The radio will respond by sending back a
|
||||
MyNodeInfo, a owner, a radio config and a series of
|
||||
FromRadio.node_infos, and config_complete
|
||||
the integer you write into this field will be reported back in the
|
||||
config_complete_id response this allows clients to never be confused by
|
||||
a stale old partially sent config. */
|
||||
uint32_t want_config_id;
|
||||
/* Tell API server we are disconnecting now.
|
||||
This is useful for serial links where there is no hardware/protocol based notification that the client has dropped the link.
|
||||
(Sending this message is optional for clients) */
|
||||
bool disconnect;
|
||||
meshtastic_XModem xmodemPacket;
|
||||
};
|
||||
} meshtastic_ToRadio;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(237) meshtastic_Compressed_data_t;
|
||||
/* Compressed message payload */
|
||||
typedef struct _meshtastic_Compressed {
|
||||
/* PortNum to determine the how to handle the compressed payload. */
|
||||
meshtastic_PortNum portnum;
|
||||
/* Compressed data. */
|
||||
meshtastic_Compressed_data_t data;
|
||||
} meshtastic_Compressed;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -779,6 +813,9 @@ extern "C" {
|
||||
|
||||
#define meshtastic_Compressed_portnum_ENUMTYPE meshtastic_PortNum
|
||||
|
||||
#define meshtastic_DeviceMetadata_role_ENUMTYPE meshtastic_Config_DeviceConfig_Role
|
||||
#define meshtastic_DeviceMetadata_hw_model_ENUMTYPE meshtastic_HardwareModel
|
||||
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_Position_init_default {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
@@ -788,13 +825,14 @@ extern "C" {
|
||||
#define meshtastic_Data_init_default {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Waypoint_init_default {0, 0, 0, 0, 0, "", "", 0}
|
||||
#define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN}
|
||||
#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default}
|
||||
#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0}
|
||||
#define meshtastic_MyNodeInfo_init_default {0, 0, 0, "", _meshtastic_CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, 0}
|
||||
#define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
||||
#define meshtastic_QueueStatus_init_default {0, 0, 0, 0}
|
||||
#define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}}
|
||||
#define meshtastic_ToRadio_init_default {0, {meshtastic_MeshPacket_init_default}}
|
||||
#define meshtastic_Compressed_init_default {_meshtastic_PortNum_MIN, {0, {0}}}
|
||||
#define meshtastic_DeviceMetadata_init_default {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN}
|
||||
#define meshtastic_Position_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0}
|
||||
#define meshtastic_RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
||||
@@ -802,13 +840,14 @@ extern "C" {
|
||||
#define meshtastic_Data_init_zero {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Waypoint_init_zero {0, 0, 0, 0, 0, "", "", 0}
|
||||
#define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN}
|
||||
#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero}
|
||||
#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0}
|
||||
#define meshtastic_MyNodeInfo_init_zero {0, 0, 0, "", _meshtastic_CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, 0}
|
||||
#define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
||||
#define meshtastic_QueueStatus_init_zero {0, 0, 0, 0}
|
||||
#define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}}
|
||||
#define meshtastic_ToRadio_init_zero {0, {meshtastic_MeshPacket_init_zero}}
|
||||
#define meshtastic_Compressed_init_zero {_meshtastic_PortNum_MIN, {0, {0}}}
|
||||
#define meshtastic_DeviceMetadata_init_zero {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define meshtastic_Position_latitude_i_tag 1
|
||||
@@ -878,6 +917,7 @@ extern "C" {
|
||||
#define meshtastic_NodeInfo_snr_tag 4
|
||||
#define meshtastic_NodeInfo_last_heard_tag 5
|
||||
#define meshtastic_NodeInfo_device_metrics_tag 6
|
||||
#define meshtastic_NodeInfo_channel_tag 7
|
||||
#define meshtastic_MyNodeInfo_my_node_num_tag 1
|
||||
#define meshtastic_MyNodeInfo_has_gps_tag 2
|
||||
#define meshtastic_MyNodeInfo_max_channels_tag 3
|
||||
@@ -902,6 +942,21 @@ extern "C" {
|
||||
#define meshtastic_QueueStatus_free_tag 2
|
||||
#define meshtastic_QueueStatus_maxlen_tag 3
|
||||
#define meshtastic_QueueStatus_mesh_packet_id_tag 4
|
||||
#define meshtastic_ToRadio_packet_tag 1
|
||||
#define meshtastic_ToRadio_want_config_id_tag 3
|
||||
#define meshtastic_ToRadio_disconnect_tag 4
|
||||
#define meshtastic_ToRadio_xmodemPacket_tag 5
|
||||
#define meshtastic_Compressed_portnum_tag 1
|
||||
#define meshtastic_Compressed_data_tag 2
|
||||
#define meshtastic_DeviceMetadata_firmware_version_tag 1
|
||||
#define meshtastic_DeviceMetadata_device_state_version_tag 2
|
||||
#define meshtastic_DeviceMetadata_canShutdown_tag 3
|
||||
#define meshtastic_DeviceMetadata_hasWifi_tag 4
|
||||
#define meshtastic_DeviceMetadata_hasBluetooth_tag 5
|
||||
#define meshtastic_DeviceMetadata_hasEthernet_tag 6
|
||||
#define meshtastic_DeviceMetadata_role_tag 7
|
||||
#define meshtastic_DeviceMetadata_position_flags_tag 8
|
||||
#define meshtastic_DeviceMetadata_hw_model_tag 9
|
||||
#define meshtastic_FromRadio_id_tag 1
|
||||
#define meshtastic_FromRadio_packet_tag 2
|
||||
#define meshtastic_FromRadio_my_info_tag 3
|
||||
@@ -914,12 +969,7 @@ extern "C" {
|
||||
#define meshtastic_FromRadio_channel_tag 10
|
||||
#define meshtastic_FromRadio_queueStatus_tag 11
|
||||
#define meshtastic_FromRadio_xmodemPacket_tag 12
|
||||
#define meshtastic_ToRadio_packet_tag 1
|
||||
#define meshtastic_ToRadio_want_config_id_tag 3
|
||||
#define meshtastic_ToRadio_disconnect_tag 4
|
||||
#define meshtastic_ToRadio_xmodemPacket_tag 5
|
||||
#define meshtastic_Compressed_portnum_tag 1
|
||||
#define meshtastic_Compressed_data_tag 2
|
||||
#define meshtastic_FromRadio_metadata_tag 13
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define meshtastic_Position_FIELDLIST(X, a) \
|
||||
@@ -1020,7 +1070,8 @@ X(a, STATIC, OPTIONAL, MESSAGE, user, 2) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, position, 3) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, snr, 4) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, last_heard, 5) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, device_metrics, 6)
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, device_metrics, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, channel, 7)
|
||||
#define meshtastic_NodeInfo_CALLBACK NULL
|
||||
#define meshtastic_NodeInfo_DEFAULT NULL
|
||||
#define meshtastic_NodeInfo_user_MSGTYPE meshtastic_User
|
||||
@@ -1075,7 +1126,8 @@ X(a, STATIC, ONEOF, BOOL, (payload_variant,rebooted,rebooted), 8) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,moduleConfig,moduleConfig), 9) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,channel,channel), 10) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,queueStatus,queueStatus), 11) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,xmodemPacket,xmodemPacket), 12)
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,xmodemPacket,xmodemPacket), 12) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,metadata,metadata), 13)
|
||||
#define meshtastic_FromRadio_CALLBACK NULL
|
||||
#define meshtastic_FromRadio_DEFAULT NULL
|
||||
#define meshtastic_FromRadio_payload_variant_packet_MSGTYPE meshtastic_MeshPacket
|
||||
@@ -1087,6 +1139,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,xmodemPacket,xmodemPacket),
|
||||
#define meshtastic_FromRadio_payload_variant_channel_MSGTYPE meshtastic_Channel
|
||||
#define meshtastic_FromRadio_payload_variant_queueStatus_MSGTYPE meshtastic_QueueStatus
|
||||
#define meshtastic_FromRadio_payload_variant_xmodemPacket_MSGTYPE meshtastic_XModem
|
||||
#define meshtastic_FromRadio_payload_variant_metadata_MSGTYPE meshtastic_DeviceMetadata
|
||||
|
||||
#define meshtastic_ToRadio_FIELDLIST(X, a) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,packet,packet), 1) \
|
||||
@@ -1104,6 +1157,19 @@ X(a, STATIC, SINGULAR, BYTES, data, 2)
|
||||
#define meshtastic_Compressed_CALLBACK NULL
|
||||
#define meshtastic_Compressed_DEFAULT NULL
|
||||
|
||||
#define meshtastic_DeviceMetadata_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, STRING, firmware_version, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, device_state_version, 2) \
|
||||
X(a, STATIC, SINGULAR, BOOL, canShutdown, 3) \
|
||||
X(a, STATIC, SINGULAR, BOOL, hasWifi, 4) \
|
||||
X(a, STATIC, SINGULAR, BOOL, hasBluetooth, 5) \
|
||||
X(a, STATIC, SINGULAR, BOOL, hasEthernet, 6) \
|
||||
X(a, STATIC, SINGULAR, UENUM, role, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, position_flags, 8) \
|
||||
X(a, STATIC, SINGULAR, UENUM, hw_model, 9)
|
||||
#define meshtastic_DeviceMetadata_CALLBACK NULL
|
||||
#define meshtastic_DeviceMetadata_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t meshtastic_Position_msg;
|
||||
extern const pb_msgdesc_t meshtastic_User_msg;
|
||||
extern const pb_msgdesc_t meshtastic_RouteDiscovery_msg;
|
||||
@@ -1118,6 +1184,7 @@ extern const pb_msgdesc_t meshtastic_QueueStatus_msg;
|
||||
extern const pb_msgdesc_t meshtastic_FromRadio_msg;
|
||||
extern const pb_msgdesc_t meshtastic_ToRadio_msg;
|
||||
extern const pb_msgdesc_t meshtastic_Compressed_msg;
|
||||
extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define meshtastic_Position_fields &meshtastic_Position_msg
|
||||
@@ -1134,15 +1201,17 @@ extern const pb_msgdesc_t meshtastic_Compressed_msg;
|
||||
#define meshtastic_FromRadio_fields &meshtastic_FromRadio_msg
|
||||
#define meshtastic_ToRadio_fields &meshtastic_ToRadio_msg
|
||||
#define meshtastic_Compressed_fields &meshtastic_Compressed_msg
|
||||
#define meshtastic_DeviceMetadata_fields &meshtastic_DeviceMetadata_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_Compressed_size 243
|
||||
#define meshtastic_Data_size 270
|
||||
#define meshtastic_DeviceMetadata_size 44
|
||||
#define meshtastic_FromRadio_size 330
|
||||
#define meshtastic_LogRecord_size 81
|
||||
#define meshtastic_MeshPacket_size 321
|
||||
#define meshtastic_MyNodeInfo_size 179
|
||||
#define meshtastic_NodeInfo_size 258
|
||||
#define meshtastic_NodeInfo_size 261
|
||||
#define meshtastic_Position_size 137
|
||||
#define meshtastic_QueueStatus_size 23
|
||||
#define meshtastic_RouteDiscovery_size 40
|
||||
|
||||
@@ -222,6 +222,11 @@ typedef struct _meshtastic_ModuleConfig_TelemetryConfig {
|
||||
/* We'll always read the sensor in Celsius, but sometimes we might want to
|
||||
display the results in Fahrenheit as a "user preference". */
|
||||
bool environment_display_fahrenheit;
|
||||
/* Enable/Disable the air quality metrics */
|
||||
bool air_quality_enabled;
|
||||
/* Interval in seconds of how often we should try to send our
|
||||
air quality metrics to the mesh */
|
||||
uint32_t air_quality_interval;
|
||||
} meshtastic_ModuleConfig_TelemetryConfig;
|
||||
|
||||
/* TODO: REPLACE */
|
||||
@@ -325,7 +330,7 @@ extern "C" {
|
||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_StoreForwardConfig_init_default {0, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_RangeTestConfig_init_default {0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
|
||||
#define meshtastic_ModuleConfig_init_zero {0, {meshtastic_ModuleConfig_MQTTConfig_init_zero}}
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0}
|
||||
@@ -335,7 +340,7 @@ extern "C" {
|
||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_StoreForwardConfig_init_zero {0, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_RangeTestConfig_init_zero {0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_CannedMessageConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
@@ -387,6 +392,8 @@ extern "C" {
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_environment_measurement_enabled_tag 3
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_environment_screen_enabled_tag 4
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_environment_display_fahrenheit_tag 5
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_air_quality_enabled_tag 6
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_air_quality_interval_tag 7
|
||||
#define meshtastic_ModuleConfig_CannedMessageConfig_rotary1_enabled_tag 1
|
||||
#define meshtastic_ModuleConfig_CannedMessageConfig_inputbroker_pin_a_tag 2
|
||||
#define meshtastic_ModuleConfig_CannedMessageConfig_inputbroker_pin_b_tag 3
|
||||
@@ -507,7 +514,9 @@ X(a, STATIC, SINGULAR, UINT32, device_update_interval, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, environment_update_interval, 2) \
|
||||
X(a, STATIC, SINGULAR, BOOL, environment_measurement_enabled, 3) \
|
||||
X(a, STATIC, SINGULAR, BOOL, environment_screen_enabled, 4) \
|
||||
X(a, STATIC, SINGULAR, BOOL, environment_display_fahrenheit, 5)
|
||||
X(a, STATIC, SINGULAR, BOOL, environment_display_fahrenheit, 5) \
|
||||
X(a, STATIC, SINGULAR, BOOL, air_quality_enabled, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, air_quality_interval, 7)
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_CALLBACK NULL
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_DEFAULT NULL
|
||||
|
||||
@@ -558,7 +567,7 @@ extern const pb_msgdesc_t meshtastic_ModuleConfig_CannedMessageConfig_msg;
|
||||
#define meshtastic_ModuleConfig_RemoteHardwareConfig_size 2
|
||||
#define meshtastic_ModuleConfig_SerialConfig_size 26
|
||||
#define meshtastic_ModuleConfig_StoreForwardConfig_size 22
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_size 18
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_size 26
|
||||
#define meshtastic_ModuleConfig_size 204
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -12,6 +12,9 @@ PB_BIND(meshtastic_DeviceMetrics, meshtastic_DeviceMetrics, AUTO)
|
||||
PB_BIND(meshtastic_EnvironmentMetrics, meshtastic_EnvironmentMetrics, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_AirQualityMetrics, meshtastic_AirQualityMetrics, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_Telemetry, meshtastic_Telemetry, AUTO)
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
/* TODO: REPLACE */
|
||||
/* Supported I2C Sensors for telemetry in Meshtastic */
|
||||
typedef enum _meshtastic_TelemetrySensorType {
|
||||
/* No external telemetry sensor explicitly set */
|
||||
meshtastic_TelemetrySensorType_SENSOR_UNSET = 0,
|
||||
@@ -37,13 +37,15 @@ typedef enum _meshtastic_TelemetrySensorType {
|
||||
/* 3-Axis magnetic sensor */
|
||||
meshtastic_TelemetrySensorType_QMC5883L = 11,
|
||||
/* High accuracy temperature and humidity */
|
||||
meshtastic_TelemetrySensorType_SHT31 = 12
|
||||
meshtastic_TelemetrySensorType_SHT31 = 12,
|
||||
/* PM2.5 air quality sensor */
|
||||
meshtastic_TelemetrySensorType_PMSA003I = 13
|
||||
} meshtastic_TelemetrySensorType;
|
||||
|
||||
/* Struct definitions */
|
||||
/* Key native device metrics such as battery level */
|
||||
typedef struct _meshtastic_DeviceMetrics {
|
||||
/* 1-100 (0 means powered) */
|
||||
/* 0-100 (>100 means powered) */
|
||||
uint32_t battery_level;
|
||||
/* Voltage measured */
|
||||
float voltage;
|
||||
@@ -69,6 +71,34 @@ typedef struct _meshtastic_EnvironmentMetrics {
|
||||
float current;
|
||||
} meshtastic_EnvironmentMetrics;
|
||||
|
||||
/* Air quality metrics */
|
||||
typedef struct _meshtastic_AirQualityMetrics {
|
||||
/* Concentration Units Standard PM1.0 */
|
||||
uint32_t pm10_standard;
|
||||
/* Concentration Units Standard PM2.5 */
|
||||
uint32_t pm25_standard;
|
||||
/* Concentration Units Standard PM10.0 */
|
||||
uint32_t pm100_standard;
|
||||
/* Concentration Units Environmental PM1.0 */
|
||||
uint32_t pm10_environmental;
|
||||
/* Concentration Units Environmental PM2.5 */
|
||||
uint32_t pm25_environmental;
|
||||
/* Concentration Units Environmental PM10.0 */
|
||||
uint32_t pm100_environmental;
|
||||
/* 0.3um Particle Count */
|
||||
uint32_t particles_03um;
|
||||
/* 0.5um Particle Count */
|
||||
uint32_t particles_05um;
|
||||
/* 1.0um Particle Count */
|
||||
uint32_t particles_10um;
|
||||
/* 2.5um Particle Count */
|
||||
uint32_t particles_25um;
|
||||
/* 5.0um Particle Count */
|
||||
uint32_t particles_50um;
|
||||
/* 10.0um Particle Count */
|
||||
uint32_t particles_100um;
|
||||
} meshtastic_AirQualityMetrics;
|
||||
|
||||
/* Types of Measurements the telemetry module is equipped to handle */
|
||||
typedef struct _meshtastic_Telemetry {
|
||||
/* This is usually not sent over the mesh (to save space), but it is sent
|
||||
@@ -83,6 +113,8 @@ typedef struct _meshtastic_Telemetry {
|
||||
meshtastic_DeviceMetrics device_metrics;
|
||||
/* Weather station or other environmental metrics */
|
||||
meshtastic_EnvironmentMetrics environment_metrics;
|
||||
/* Air quality metrics */
|
||||
meshtastic_AirQualityMetrics air_quality_metrics;
|
||||
} variant;
|
||||
} meshtastic_Telemetry;
|
||||
|
||||
@@ -93,8 +125,9 @@ extern "C" {
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
|
||||
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_SHT31
|
||||
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_SHT31+1))
|
||||
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_PMSA003I
|
||||
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_PMSA003I+1))
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -103,9 +136,11 @@ extern "C" {
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_DeviceMetrics_init_default {0, 0, 0, 0}
|
||||
#define meshtastic_EnvironmentMetrics_init_default {0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_AirQualityMetrics_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}}
|
||||
#define meshtastic_DeviceMetrics_init_zero {0, 0, 0, 0}
|
||||
#define meshtastic_EnvironmentMetrics_init_zero {0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_AirQualityMetrics_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
@@ -119,9 +154,22 @@ extern "C" {
|
||||
#define meshtastic_EnvironmentMetrics_gas_resistance_tag 4
|
||||
#define meshtastic_EnvironmentMetrics_voltage_tag 5
|
||||
#define meshtastic_EnvironmentMetrics_current_tag 6
|
||||
#define meshtastic_AirQualityMetrics_pm10_standard_tag 1
|
||||
#define meshtastic_AirQualityMetrics_pm25_standard_tag 2
|
||||
#define meshtastic_AirQualityMetrics_pm100_standard_tag 3
|
||||
#define meshtastic_AirQualityMetrics_pm10_environmental_tag 4
|
||||
#define meshtastic_AirQualityMetrics_pm25_environmental_tag 5
|
||||
#define meshtastic_AirQualityMetrics_pm100_environmental_tag 6
|
||||
#define meshtastic_AirQualityMetrics_particles_03um_tag 7
|
||||
#define meshtastic_AirQualityMetrics_particles_05um_tag 8
|
||||
#define meshtastic_AirQualityMetrics_particles_10um_tag 9
|
||||
#define meshtastic_AirQualityMetrics_particles_25um_tag 10
|
||||
#define meshtastic_AirQualityMetrics_particles_50um_tag 11
|
||||
#define meshtastic_AirQualityMetrics_particles_100um_tag 12
|
||||
#define meshtastic_Telemetry_time_tag 1
|
||||
#define meshtastic_Telemetry_device_metrics_tag 2
|
||||
#define meshtastic_Telemetry_environment_metrics_tag 3
|
||||
#define meshtastic_Telemetry_air_quality_metrics_tag 4
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define meshtastic_DeviceMetrics_FIELDLIST(X, a) \
|
||||
@@ -142,28 +190,49 @@ X(a, STATIC, SINGULAR, FLOAT, current, 6)
|
||||
#define meshtastic_EnvironmentMetrics_CALLBACK NULL
|
||||
#define meshtastic_EnvironmentMetrics_DEFAULT NULL
|
||||
|
||||
#define meshtastic_AirQualityMetrics_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, pm10_standard, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, pm25_standard, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, pm100_standard, 3) \
|
||||
X(a, STATIC, SINGULAR, UINT32, pm10_environmental, 4) \
|
||||
X(a, STATIC, SINGULAR, UINT32, pm25_environmental, 5) \
|
||||
X(a, STATIC, SINGULAR, UINT32, pm100_environmental, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, particles_03um, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, particles_05um, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, particles_10um, 9) \
|
||||
X(a, STATIC, SINGULAR, UINT32, particles_25um, 10) \
|
||||
X(a, STATIC, SINGULAR, UINT32, particles_50um, 11) \
|
||||
X(a, STATIC, SINGULAR, UINT32, particles_100um, 12)
|
||||
#define meshtastic_AirQualityMetrics_CALLBACK NULL
|
||||
#define meshtastic_AirQualityMetrics_DEFAULT NULL
|
||||
|
||||
#define meshtastic_Telemetry_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, time, 1) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,device_metrics,variant.device_metrics), 2) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,environment_metrics,variant.environment_metrics), 3)
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,environment_metrics,variant.environment_metrics), 3) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,air_quality_metrics,variant.air_quality_metrics), 4)
|
||||
#define meshtastic_Telemetry_CALLBACK NULL
|
||||
#define meshtastic_Telemetry_DEFAULT NULL
|
||||
#define meshtastic_Telemetry_variant_device_metrics_MSGTYPE meshtastic_DeviceMetrics
|
||||
#define meshtastic_Telemetry_variant_environment_metrics_MSGTYPE meshtastic_EnvironmentMetrics
|
||||
#define meshtastic_Telemetry_variant_air_quality_metrics_MSGTYPE meshtastic_AirQualityMetrics
|
||||
|
||||
extern const pb_msgdesc_t meshtastic_DeviceMetrics_msg;
|
||||
extern const pb_msgdesc_t meshtastic_EnvironmentMetrics_msg;
|
||||
extern const pb_msgdesc_t meshtastic_AirQualityMetrics_msg;
|
||||
extern const pb_msgdesc_t meshtastic_Telemetry_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define meshtastic_DeviceMetrics_fields &meshtastic_DeviceMetrics_msg
|
||||
#define meshtastic_EnvironmentMetrics_fields &meshtastic_EnvironmentMetrics_msg
|
||||
#define meshtastic_AirQualityMetrics_fields &meshtastic_AirQualityMetrics_msg
|
||||
#define meshtastic_Telemetry_fields &meshtastic_Telemetry_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_AirQualityMetrics_size 72
|
||||
#define meshtastic_DeviceMetrics_size 21
|
||||
#define meshtastic_EnvironmentMetrics_size 30
|
||||
#define meshtastic_Telemetry_size 37
|
||||
#define meshtastic_Telemetry_size 79
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -645,7 +645,7 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
|
||||
// data->radio
|
||||
JSONObject jsonObjRadio;
|
||||
jsonObjRadio["frequency"] = new JSONValue(RadioLibInterface::instance->getFreq());
|
||||
jsonObjRadio["lora_channel"] = new JSONValue((int)RadioLibInterface::instance->getChannelNum());
|
||||
jsonObjRadio["lora_channel"] = new JSONValue((int)RadioLibInterface::instance->getChannelNum() + 1);
|
||||
|
||||
// collect data to inner data object
|
||||
JSONObject jsonObjInner;
|
||||
@@ -833,7 +833,7 @@ void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
|
||||
if (WiFi.encryptionType(i) != WIFI_AUTH_OPEN) {
|
||||
JSONObject thisNetwork;
|
||||
thisNetwork["ssid"] = new JSONValue(ssidArray);
|
||||
thisNetwork["rssi"] = new JSONValue(WiFi.RSSI(i));
|
||||
thisNetwork["rssi"] = new JSONValue(int(WiFi.RSSI(i)));
|
||||
networkObjs.push_back(new JSONValue(thisNetwork));
|
||||
}
|
||||
// Yield some cpu cycles to IP stack.
|
||||
|
||||
@@ -39,6 +39,9 @@ unsigned long lastrun_ntp = 0;
|
||||
|
||||
bool needReconnect = true; // If we create our reconnector, run it once at the beginning
|
||||
|
||||
WiFiUDP syslogClient;
|
||||
Syslog syslog(syslogClient);
|
||||
|
||||
Periodic *wifiReconnect;
|
||||
|
||||
static int32_t reconnectWiFi()
|
||||
@@ -135,6 +138,26 @@ static void onNetworkConnected()
|
||||
timeClient.setUpdateInterval(60 * 60); // Update once an hour
|
||||
#endif
|
||||
|
||||
if (config.network.rsyslog_server[0]) {
|
||||
LOG_INFO("Starting Syslog client\n");
|
||||
// Defaults
|
||||
int serverPort = 514;
|
||||
const char *serverAddr = config.network.rsyslog_server;
|
||||
String server = String(serverAddr);
|
||||
int delimIndex = server.indexOf(':');
|
||||
if (delimIndex > 0) {
|
||||
String port = server.substring(delimIndex + 1, server.length());
|
||||
server[delimIndex] = 0;
|
||||
serverPort = port.toInt();
|
||||
serverAddr = server.c_str();
|
||||
}
|
||||
syslog.server(serverAddr, serverPort);
|
||||
syslog.deviceHostname(getDeviceName());
|
||||
syslog.appName("Meshtastic");
|
||||
syslog.defaultPriority(LOGLEVEL_USER);
|
||||
syslog.enable();
|
||||
}
|
||||
|
||||
initWebServer();
|
||||
initApiServer();
|
||||
|
||||
@@ -223,6 +246,7 @@ static void WiFiEvent(WiFiEvent_t event)
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_STOP:
|
||||
LOG_INFO("WiFi station stopped\n");
|
||||
syslog.disable();
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
|
||||
LOG_INFO("Connected to access point\n");
|
||||
@@ -230,6 +254,7 @@ static void WiFiEvent(WiFiEvent_t event)
|
||||
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||
LOG_INFO("Disconnected from WiFi access point\n");
|
||||
WiFi.disconnect(false, true);
|
||||
syslog.disable();
|
||||
needReconnect = true;
|
||||
wifiReconnect->setIntervalFromNow(1000);
|
||||
break;
|
||||
@@ -246,6 +271,7 @@ static void WiFiEvent(WiFiEvent_t event)
|
||||
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
|
||||
LOG_INFO("Lost IP address and IP address is reset to 0\n");
|
||||
WiFi.disconnect(false, true);
|
||||
syslog.disable();
|
||||
needReconnect = true;
|
||||
wifiReconnect->setIntervalFromNow(1000);
|
||||
break;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "mqtt/MQTT.h"
|
||||
#endif
|
||||
|
||||
#define DEFAULT_REBOOT_SECONDS 5
|
||||
#define DEFAULT_REBOOT_SECONDS 7
|
||||
|
||||
AdminModule *adminModule;
|
||||
bool hasOpenEditTransaction;
|
||||
@@ -106,6 +106,10 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
||||
else
|
||||
handleSetChannel(r->set_channel);
|
||||
break;
|
||||
case meshtastic_AdminMessage_set_ham_mode_tag:
|
||||
LOG_INFO("Client is setting ham mode\n");
|
||||
handleSetHamMode(r->set_ham_mode);
|
||||
break;
|
||||
|
||||
/**
|
||||
* Other
|
||||
@@ -208,7 +212,6 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
||||
void AdminModule::handleSetOwner(const meshtastic_User &o)
|
||||
{
|
||||
int changed = 0;
|
||||
bool licensed_changed = false;
|
||||
|
||||
if (*o.long_name) {
|
||||
changed |= strcmp(owner.long_name, o.long_name);
|
||||
@@ -224,14 +227,12 @@ void AdminModule::handleSetOwner(const meshtastic_User &o)
|
||||
}
|
||||
if (owner.is_licensed != o.is_licensed) {
|
||||
changed = 1;
|
||||
licensed_changed = true;
|
||||
owner.is_licensed = o.is_licensed;
|
||||
config.lora.override_duty_cycle = owner.is_licensed; // override duty cycle for licensed operators
|
||||
}
|
||||
|
||||
if (changed) { // If nothing really changed, don't broadcast on the network or write to flash
|
||||
service.reloadOwner(!hasOpenEditTransaction);
|
||||
licensed_changed ? saveChanges(SEGMENT_CONFIG | SEGMENT_DEVICESTATE) : saveChanges(SEGMENT_DEVICESTATE);
|
||||
saveChanges(SEGMENT_DEVICESTATE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -489,19 +490,7 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const
|
||||
void AdminModule::handleGetDeviceMetadata(const meshtastic_MeshPacket &req)
|
||||
{
|
||||
meshtastic_AdminMessage r = meshtastic_AdminMessage_init_default;
|
||||
|
||||
meshtastic_DeviceMetadata deviceMetadata;
|
||||
strncpy(deviceMetadata.firmware_version, myNodeInfo.firmware_version, 18);
|
||||
deviceMetadata.device_state_version = DEVICESTATE_CUR_VER;
|
||||
deviceMetadata.canShutdown = pmu_found || HAS_CPU_SHUTDOWN;
|
||||
deviceMetadata.hasBluetooth = HAS_BLUETOOTH;
|
||||
deviceMetadata.hasWifi = HAS_WIFI;
|
||||
deviceMetadata.hasEthernet = HAS_ETHERNET;
|
||||
deviceMetadata.role = config.device.role;
|
||||
deviceMetadata.position_flags = config.position.position_flags;
|
||||
deviceMetadata.hw_model = HW_VENDOR;
|
||||
|
||||
r.get_device_metadata_response = deviceMetadata;
|
||||
r.get_device_metadata_response = getDeviceMetadata();
|
||||
r.which_payload_variant = meshtastic_AdminMessage_get_device_metadata_response_tag;
|
||||
myReply = allocDataProtobuf(r);
|
||||
}
|
||||
@@ -598,6 +587,32 @@ void AdminModule::saveChanges(int saveWhat, bool shouldReboot)
|
||||
}
|
||||
}
|
||||
|
||||
void AdminModule::handleSetHamMode(const meshtastic_HamParameters &p)
|
||||
{
|
||||
// Set call sign and override lora limitations for licensed use
|
||||
strncpy(owner.long_name, p.call_sign, sizeof(owner.long_name));
|
||||
strncpy(owner.short_name, p.short_name, sizeof(owner.short_name));
|
||||
owner.is_licensed = true;
|
||||
config.lora.override_duty_cycle = true;
|
||||
config.lora.tx_power = p.tx_power;
|
||||
config.lora.override_frequency = p.frequency;
|
||||
// Set node info broadcast interval to 10 minutes
|
||||
// For FCC minimum call-sign announcement
|
||||
config.device.node_info_broadcast_secs = 600;
|
||||
|
||||
config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_LOCAL_ONLY;
|
||||
// Remove PSK of primary channel for plaintext amateur usage
|
||||
auto primaryChannel = channels.getByIndex(channels.getPrimaryIndex());
|
||||
auto &channelSettings = primaryChannel.settings;
|
||||
channelSettings.psk.bytes[0] = 0;
|
||||
channelSettings.psk.size = 0;
|
||||
channels.setChannel(primaryChannel);
|
||||
channels.onConfigChanged();
|
||||
|
||||
service.reloadOwner(false);
|
||||
service.reloadConfig(SEGMENT_CONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
|
||||
}
|
||||
|
||||
AdminModule::AdminModule() : ProtobufModule("Admin", meshtastic_PortNum_ADMIN_APP, &meshtastic_AdminMessage_msg)
|
||||
{
|
||||
// restrict to the admin channel for rx
|
||||
|
||||
@@ -43,6 +43,7 @@ class AdminModule : public ProtobufModule<meshtastic_AdminMessage>
|
||||
void handleSetConfig(const meshtastic_Config &c);
|
||||
void handleSetModuleConfig(const meshtastic_ModuleConfig &c);
|
||||
void handleSetChannel();
|
||||
void handleSetHamMode(const meshtastic_HamParameters &req);
|
||||
void reboot(int32_t seconds);
|
||||
};
|
||||
|
||||
|
||||
@@ -5,12 +5,19 @@
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h" // neede for button bypass
|
||||
#include "detect/ScanI2C.h"
|
||||
#include "mesh/generated/meshtastic/cannedmessages.pb.h"
|
||||
|
||||
#include "main.h" // for cardkb_found
|
||||
|
||||
#ifdef OLED_RU
|
||||
#include "graphics/fonts/OLEDDisplayFontsRU.h"
|
||||
#endif
|
||||
|
||||
#ifdef OLED_UA
|
||||
#include "graphics/fonts/OLEDDisplayFontsUA.h"
|
||||
#endif
|
||||
|
||||
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
|
||||
// The screen is bigger so use bigger fonts
|
||||
#define FONT_SMALL ArialMT_Plain_16
|
||||
@@ -20,8 +27,12 @@
|
||||
#ifdef OLED_RU
|
||||
#define FONT_SMALL ArialMT_Plain_10_RU
|
||||
#else
|
||||
#ifdef OLED_UA
|
||||
#define FONT_SMALL ArialMT_Plain_10_UA
|
||||
#else
|
||||
#define FONT_SMALL ArialMT_Plain_10
|
||||
#endif
|
||||
#endif
|
||||
#define FONT_MEDIUM ArialMT_Plain_16
|
||||
#define FONT_LARGE ArialMT_Plain_24
|
||||
#endif
|
||||
@@ -35,7 +46,7 @@
|
||||
// Remove Canned message screen if no action is taken for some milliseconds
|
||||
#define INACTIVATE_AFTER_MS 20000
|
||||
|
||||
extern uint8_t cardkb_found;
|
||||
extern ScanI2C::DeviceAddress cardkb_found;
|
||||
|
||||
static const char *cannedMessagesConfigFile = "/prefs/cannedConf.proto";
|
||||
|
||||
@@ -48,7 +59,7 @@ CannedMessageModule::CannedMessageModule()
|
||||
{
|
||||
if (moduleConfig.canned_message.enabled) {
|
||||
this->loadProtoForModule();
|
||||
if ((this->splitConfiguredMessages() <= 0) && (cardkb_found != CARDKB_ADDR)) {
|
||||
if ((this->splitConfiguredMessages() <= 0) && (cardkb_found.address != CARDKB_ADDR)) {
|
||||
LOG_INFO("CannedMessageModule: No messages are configured. Module is disabled\n");
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_DISABLED;
|
||||
disable();
|
||||
@@ -435,8 +446,6 @@ int CannedMessageModule::getPrevIndex()
|
||||
|
||||
void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
displayedNodeNum = 0; // Not currently showing a node pane
|
||||
|
||||
char buffer[50];
|
||||
|
||||
if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) {
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
#include "modules/WaypointModule.h"
|
||||
#if HAS_TELEMETRY
|
||||
#include "modules/Telemetry/DeviceTelemetry.h"
|
||||
#endif
|
||||
#if HAS_SENSOR
|
||||
#include "modules/Telemetry/AirQualityTelemetry.h"
|
||||
#include "modules/Telemetry/EnvironmentTelemetry.h"
|
||||
#endif
|
||||
#ifdef ARCH_ESP32
|
||||
@@ -62,9 +65,15 @@ void setupModules()
|
||||
#endif
|
||||
#if HAS_TELEMETRY
|
||||
new DeviceTelemetryModule();
|
||||
new EnvironmentTelemetryModule();
|
||||
#endif
|
||||
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
#if HAS_SENSOR
|
||||
new EnvironmentTelemetryModule();
|
||||
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_PMSA003I] > 0) {
|
||||
new AirQualityTelemetryModule();
|
||||
}
|
||||
#endif
|
||||
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2) && \
|
||||
!defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
new SerialModule();
|
||||
#endif
|
||||
#ifdef ARCH_ESP32
|
||||
|
||||
@@ -27,27 +27,44 @@ bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
|
||||
return false; // Let others look at this message also if they want
|
||||
}
|
||||
|
||||
void NodeInfoModule::sendOurNodeInfo(NodeNum dest, bool wantReplies)
|
||||
void NodeInfoModule::sendOurNodeInfo(NodeNum dest, bool wantReplies, uint8_t channel)
|
||||
{
|
||||
// cancel any not yet sent (now stale) position packets
|
||||
if (prevPacketId) // if we wrap around to zero, we'll simply fail to cancel in that rare case (no big deal)
|
||||
service.cancelSending(prevPacketId);
|
||||
|
||||
meshtastic_MeshPacket *p = allocReply();
|
||||
p->to = dest;
|
||||
p->decoded.want_response = wantReplies;
|
||||
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
|
||||
prevPacketId = p->id;
|
||||
if (p) { // Check whether we didn't ignore it
|
||||
p->to = dest;
|
||||
p->decoded.want_response = wantReplies;
|
||||
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
|
||||
if (channel > 0) {
|
||||
LOG_DEBUG("sending ourNodeInfo to channel %d\n", channel);
|
||||
p->channel = channel;
|
||||
}
|
||||
|
||||
service.sendToMesh(p);
|
||||
prevPacketId = p->id;
|
||||
|
||||
service.sendToMesh(p);
|
||||
}
|
||||
}
|
||||
|
||||
meshtastic_MeshPacket *NodeInfoModule::allocReply()
|
||||
{
|
||||
meshtastic_User &u = owner;
|
||||
uint32_t now = millis();
|
||||
// If we sent our NodeInfo less than 1 min. ago, don't send it again as it may be still underway.
|
||||
if (lastSentToMesh && (now - lastSentToMesh) < 60 * 1000) {
|
||||
LOG_DEBUG("Sending NodeInfo will be ignored since we just sent it.\n");
|
||||
ignoreRequest = true; // Mark it as ignored for MeshModule
|
||||
return NULL;
|
||||
} else {
|
||||
ignoreRequest = false; // Don't ignore requests anymore
|
||||
meshtastic_User &u = owner;
|
||||
|
||||
LOG_INFO("sending owner %s/%s/%s\n", u.id, u.long_name, u.short_name);
|
||||
return allocDataProtobuf(u);
|
||||
LOG_INFO("sending owner %s/%s/%s\n", u.id, u.long_name, u.short_name);
|
||||
lastSentToMesh = now;
|
||||
return allocDataProtobuf(u);
|
||||
}
|
||||
}
|
||||
|
||||
NodeInfoModule::NodeInfoModule()
|
||||
@@ -71,5 +88,5 @@ int32_t NodeInfoModule::runOnce()
|
||||
sendOurNodeInfo(NODENUM_BROADCAST, requestReplies); // Send our info (don't request replies)
|
||||
}
|
||||
|
||||
return default_broadcast_interval_secs * 1000;
|
||||
return getConfiguredOrDefaultMs(config.device.node_info_broadcast_secs, default_broadcast_interval_secs);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ class NodeInfoModule : public ProtobufModule<meshtastic_User>, private concurren
|
||||
/**
|
||||
* Send our NodeInfo into the mesh
|
||||
*/
|
||||
void sendOurNodeInfo(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
|
||||
void sendOurNodeInfo(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false, uint8_t channel = 0);
|
||||
|
||||
protected:
|
||||
/** Called to handle a particular incoming message
|
||||
@@ -35,6 +35,9 @@ class NodeInfoModule : public ProtobufModule<meshtastic_User>, private concurren
|
||||
|
||||
/** Does our periodic broadcast */
|
||||
virtual int32_t runOnce() override;
|
||||
|
||||
private:
|
||||
uint32_t lastSentToMesh = 0; // Last time we sent our NodeInfo to the mesh
|
||||
};
|
||||
|
||||
extern NodeInfoModule *nodeInfoModule;
|
||||
|
||||
@@ -120,7 +120,7 @@ meshtastic_MeshPacket *PositionModule::allocReply()
|
||||
return allocDataProtobuf(p);
|
||||
}
|
||||
|
||||
void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies)
|
||||
void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t channel)
|
||||
{
|
||||
// cancel any not yet sent (now stale) position packets
|
||||
if (prevPacketId) // if we wrap around to zero, we'll simply fail to cancel in that rare case (no big deal)
|
||||
@@ -135,6 +135,9 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies)
|
||||
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
|
||||
prevPacketId = p->id;
|
||||
|
||||
if (channel > 0)
|
||||
p->channel = channel;
|
||||
|
||||
service.sendToMesh(p, RX_SRC_LOCAL, true);
|
||||
}
|
||||
|
||||
@@ -144,10 +147,10 @@ int32_t PositionModule::runOnce()
|
||||
|
||||
// We limit our GPS broadcasts to a max rate
|
||||
uint32_t now = millis();
|
||||
uint32_t intervalMs = config.position.position_broadcast_secs > 0 ? config.position.position_broadcast_secs * 1000
|
||||
: default_broadcast_interval_secs * 1000;
|
||||
if (lastGpsSend == 0 || (now - lastGpsSend) >= intervalMs) {
|
||||
uint32_t intervalMs = getConfiguredOrDefaultMs(config.position.position_broadcast_secs, default_broadcast_interval_secs);
|
||||
uint32_t msSinceLastSend = now - lastGpsSend;
|
||||
|
||||
if (lastGpsSend == 0 || msSinceLastSend >= intervalMs) {
|
||||
// Only send packets if the channel is less than 40% utilized.
|
||||
if (airTime->isTxAllowedChannelUtil()) {
|
||||
if (node->has_position && (node->position.latitude_i != 0 || node->position.longitude_i != 0)) {
|
||||
@@ -165,39 +168,32 @@ int32_t PositionModule::runOnce()
|
||||
}
|
||||
}
|
||||
} else if (config.position.position_broadcast_smart_enabled) {
|
||||
|
||||
// Only send packets if the channel is less than 25% utilized.
|
||||
if (airTime->isTxAllowedChannelUtil(true)) {
|
||||
|
||||
// Only send packets if the channel is less than 25% utilized or we're a tracker.
|
||||
if (airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER)) {
|
||||
meshtastic_NodeInfo *node2 = service.refreshMyNodeInfo(); // should guarantee there is now a position
|
||||
|
||||
if (node2->has_position && (node2->position.latitude_i != 0 || node2->position.longitude_i != 0)) {
|
||||
// The minimum distance to travel before we are able to send a new position packet.
|
||||
const uint32_t distanceTravelMinimum = 30;
|
||||
const uint32_t distanceTravelThreshold =
|
||||
config.position.broadcast_smart_minimum_distance > 0 ? config.position.broadcast_smart_minimum_distance : 100;
|
||||
|
||||
// The minimum time that would pass before we are able to send a new position packet.
|
||||
const uint32_t timeTravelMinimum = 30;
|
||||
// The minimum time (in seconds) that would pass before we are able to send a new position packet.
|
||||
const uint32_t minimumTimeThreshold =
|
||||
getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs, 30);
|
||||
|
||||
// Determine the distance in meters between two points on the globe
|
||||
float distance = GeoCoord::latLongToMeter(lastGpsLatitude * 1e-7, lastGpsLongitude * 1e-7,
|
||||
node->position.latitude_i * 1e-7, node->position.longitude_i * 1e-7);
|
||||
float distanceTraveledSinceLastSend =
|
||||
GeoCoord::latLongToMeter(lastGpsLatitude * 1e-7, lastGpsLongitude * 1e-7, node->position.latitude_i * 1e-7,
|
||||
node->position.longitude_i * 1e-7);
|
||||
|
||||
// Yes, this has a bunch of magic numbers. Sorry. This is to make the scale non-linear.
|
||||
const float distanceTravelMath = 1203 / (sqrt(pow(myNodeInfo.bitrate, 1.5) / 1.1));
|
||||
uint32_t distanceTravelThreshold =
|
||||
(distanceTravelMath >= distanceTravelMinimum) ? distanceTravelMath : distanceTravelMinimum;
|
||||
|
||||
// Yes, this has a bunch of magic numbers. Sorry.
|
||||
uint32_t timeTravel =
|
||||
((1500 / myNodeInfo.bitrate) >= timeTravelMinimum) ? (1500 / myNodeInfo.bitrate) : timeTravelMinimum;
|
||||
// If the distance traveled since the last update is greater than distanceTravelMinimum meters
|
||||
// and it's been at least timeTravelMinimum seconds since the last update
|
||||
if ((abs(distance) >= distanceTravelThreshold) && (now - lastGpsSend) >= (timeTravel * 1000)) {
|
||||
if ((abs(distanceTraveledSinceLastSend) >= distanceTravelThreshold) && msSinceLastSend >= minimumTimeThreshold) {
|
||||
bool requestReplies = currentGeneration != radioGeneration;
|
||||
currentGeneration = radioGeneration;
|
||||
|
||||
LOG_INFO("Sending smart pos@%x:6 to mesh (wantReplies=%d, d=%d, dtt=%d, tt=%d)\n", node2->position.timestamp,
|
||||
requestReplies, distance, distanceTravelThreshold, timeTravel);
|
||||
LOG_INFO("Sending smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims, "
|
||||
"minTimeInterval=%ims)\n",
|
||||
node2->position.timestamp, abs(distanceTraveledSinceLastSend), distanceTravelThreshold,
|
||||
msSinceLastSend, minimumTimeThreshold);
|
||||
sendOurPosition(NODENUM_BROADCAST, requestReplies);
|
||||
|
||||
// Set the current coords as our last ones, after we've compared distance with current and decided to send
|
||||
|
||||
@@ -29,7 +29,7 @@ class PositionModule : public ProtobufModule<meshtastic_Position>, private concu
|
||||
/**
|
||||
* Send our position into the mesh
|
||||
*/
|
||||
void sendOurPosition(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
|
||||
void sendOurPosition(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false, uint8_t channel = 0);
|
||||
|
||||
protected:
|
||||
/** Called to handle a particular incoming message
|
||||
|
||||
@@ -44,7 +44,8 @@
|
||||
|
||||
*/
|
||||
|
||||
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2) && \
|
||||
!defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
|
||||
#define RX_BUFFER 128
|
||||
#define TIMEOUT 250
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
#include <Arduino.h>
|
||||
#include <functional>
|
||||
|
||||
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2) && \
|
||||
!defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
|
||||
class SerialModule : public StreamAPI, private concurrency::OSThread
|
||||
{
|
||||
|
||||
129
src/modules/Telemetry/AirQualityTelemetry.cpp
Normal file
129
src/modules/Telemetry/AirQualityTelemetry.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
#include "AirQualityTelemetry.h"
|
||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "RTC.h"
|
||||
#include "Router.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
|
||||
int32_t AirQualityTelemetryModule::runOnce()
|
||||
{
|
||||
int32_t result = INT32_MAX;
|
||||
/*
|
||||
Uncomment the preferences below if you want to use the module
|
||||
without having to configure it from the PythonAPI or WebUI.
|
||||
*/
|
||||
|
||||
// moduleConfig.telemetry.air_quality_enabled = 1;
|
||||
|
||||
if (!(moduleConfig.telemetry.air_quality_enabled)) {
|
||||
// If this module is not enabled, and the user doesn't want the display screen don't waste any OSThread time on it
|
||||
return disable();
|
||||
}
|
||||
|
||||
if (firstTime) {
|
||||
// This is the first time the OSThread library has called this function, so do some setup
|
||||
firstTime = 0;
|
||||
|
||||
if (moduleConfig.telemetry.air_quality_enabled) {
|
||||
LOG_INFO("Air quality Telemetry: Initializing\n");
|
||||
if (!aqi.begin_I2C()) {
|
||||
LOG_WARN("Could not establish i2c connection to AQI sensor\n");
|
||||
return disable();
|
||||
}
|
||||
return 1000;
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
// if we somehow got to a second run of this module with measurement disabled, then just wait forever
|
||||
if (!moduleConfig.telemetry.air_quality_enabled)
|
||||
return result;
|
||||
|
||||
uint32_t now = millis();
|
||||
if (((lastSentToMesh == 0) ||
|
||||
((now - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.telemetry.air_quality_interval))) &&
|
||||
airTime->isTxAllowedAirUtil()) {
|
||||
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 sendToPhoneIntervalMs;
|
||||
}
|
||||
|
||||
bool AirQualityTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t)
|
||||
{
|
||||
if (t->which_variant == meshtastic_Telemetry_air_quality_metrics_tag) {
|
||||
const char *sender = getSenderShortName(mp);
|
||||
|
||||
LOG_INFO("(Received from %s): pm10_standard=%i, pm25_standard=%i, pm100_standard=%i\n", sender,
|
||||
t->variant.air_quality_metrics.pm10_standard, t->variant.air_quality_metrics.pm25_standard,
|
||||
t->variant.air_quality_metrics.pm100_standard);
|
||||
|
||||
LOG_INFO(" | PM1.0(Environmental)=%i, PM2.5(Environmental)=%i, PM10.0(Environmental)=%i\n",
|
||||
t->variant.air_quality_metrics.pm10_environmental, t->variant.air_quality_metrics.pm25_environmental,
|
||||
t->variant.air_quality_metrics.pm100_environmental);
|
||||
|
||||
// release previous packet before occupying a new spot
|
||||
if (lastMeasurementPacket != nullptr)
|
||||
packetPool.release(lastMeasurementPacket);
|
||||
|
||||
lastMeasurementPacket = packetPool.allocCopy(mp);
|
||||
}
|
||||
|
||||
return false; // Let others look at this message also if they want
|
||||
}
|
||||
|
||||
bool AirQualityTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
|
||||
{
|
||||
if (!aqi.read(&data)) {
|
||||
LOG_WARN("Skipping send measurements. Could not read AQIn\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
meshtastic_Telemetry m;
|
||||
m.time = getTime();
|
||||
m.which_variant = meshtastic_Telemetry_air_quality_metrics_tag;
|
||||
m.variant.air_quality_metrics.pm10_standard = data.pm10_standard;
|
||||
m.variant.air_quality_metrics.pm25_standard = data.pm25_standard;
|
||||
m.variant.air_quality_metrics.pm100_standard = data.pm100_standard;
|
||||
|
||||
m.variant.air_quality_metrics.pm10_environmental = data.pm10_env;
|
||||
m.variant.air_quality_metrics.pm25_environmental = data.pm25_env;
|
||||
m.variant.air_quality_metrics.pm100_environmental = data.pm100_env;
|
||||
|
||||
LOG_INFO("(Sending): PM1.0(Standard)=%i, PM2.5(Standard)=%i, PM10.0(Standard)=%i\n",
|
||||
m.variant.air_quality_metrics.pm10_standard, m.variant.air_quality_metrics.pm25_standard,
|
||||
m.variant.air_quality_metrics.pm100_standard);
|
||||
|
||||
LOG_INFO(" | PM1.0(Environmental)=%i, PM2.5(Environmental)=%i, PM10.0(Environmental)=%i\n",
|
||||
m.variant.air_quality_metrics.pm10_environmental, m.variant.air_quality_metrics.pm25_environmental,
|
||||
m.variant.air_quality_metrics.pm100_environmental);
|
||||
|
||||
meshtastic_MeshPacket *p = allocDataProtobuf(m);
|
||||
p->to = dest;
|
||||
p->decoded.want_response = false;
|
||||
if (config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR)
|
||||
p->priority = meshtastic_MeshPacket_Priority_RELIABLE;
|
||||
else
|
||||
p->priority = meshtastic_MeshPacket_Priority_MIN;
|
||||
|
||||
// release previous packet before occupying a new spot
|
||||
if (lastMeasurementPacket != nullptr)
|
||||
packetPool.release(lastMeasurementPacket);
|
||||
|
||||
lastMeasurementPacket = packetPool.allocCopy(*p);
|
||||
if (phoneOnly) {
|
||||
LOG_INFO("Sending packet to phone\n");
|
||||
service.sendToPhone(p);
|
||||
} else {
|
||||
LOG_INFO("Sending packet to mesh\n");
|
||||
service.sendToMesh(p, RX_SRC_LOCAL, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user