mirror of
https://github.com/alexhopeoconnor/firmware.git
synced 2026-10-15 16:01:19 +10:00
Compare commits
75
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f81d3b045d | ||
|
|
59ed5c9049 | ||
|
|
4a34bf648f | ||
|
|
b99e57a6fa | ||
|
|
46eab20a90 | ||
|
|
39b5fb041e | ||
|
|
fc16d93421 | ||
|
|
bac9fec17f | ||
|
|
de774188c9 | ||
|
|
c3d60342f4 | ||
|
|
d3e3985e39 | ||
|
|
8eca6a2df8 | ||
|
|
e4f53677fc | ||
|
|
10e10450cf | ||
|
|
f846503cbf | ||
|
|
85b2bad275 | ||
|
|
7ad137b56a | ||
|
|
57ea6a265e | ||
|
|
d00e0f6911 | ||
|
|
594af0cacd | ||
|
|
9f4c8a2804 | ||
|
|
43b8972171 | ||
|
|
fe8e0713cc | ||
|
|
ac6b6c8d83 | ||
|
|
79da2365f0 | ||
|
|
b5777beb7d | ||
|
|
5ad30a55ea | ||
|
|
060a3bde4d | ||
|
|
8df7a035e2 | ||
|
|
b00c05012d | ||
|
|
0832388482 | ||
|
|
601d912c6f | ||
|
|
502a83bb8a | ||
|
|
474f9b5bfb | ||
|
|
fe86c40145 | ||
|
|
09286a3beb | ||
|
|
ae4f54224e | ||
|
|
d5af8f0a97 | ||
|
|
58c957f2c7 | ||
|
|
7c2b6778cb | ||
|
|
0048e3cdcb | ||
|
|
6018c0a830 | ||
|
|
37da78919a | ||
|
|
ad9d7a4972 | ||
|
|
932966b896 | ||
|
|
4d69159e75 | ||
|
|
f2ee0df015 | ||
|
|
fcfb197571 | ||
|
|
dd7140b7a1 | ||
|
|
fadcbd597f | ||
|
|
14b9a1a929 | ||
|
|
c51a7b98bd | ||
|
|
fdec95f9c1 | ||
|
|
e6fb6b115a | ||
|
|
d5bb32ff93 | ||
|
|
f5058a9cbb | ||
|
|
dbc5ec27f7 | ||
|
|
1089469f82 | ||
|
|
fd98e9f553 | ||
|
|
ccfc9e5dd9 | ||
|
|
1752caaf19 | ||
|
|
364dead3aa | ||
|
|
154864dfbf | ||
|
|
2ca3cdf837 | ||
|
|
485c371de4 | ||
|
|
a255da3cf5 | ||
|
|
d65dc497f2 | ||
|
|
c641bfd53c | ||
|
|
b947b123fc | ||
|
|
df1f66a6b9 | ||
|
|
70336f7f4f | ||
|
|
de76caca32 | ||
|
|
89469fcb88 | ||
|
|
a8357ebd52 | ||
|
|
0d1f9e915f |
@@ -14,7 +14,7 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update --fix-missing
|
||||
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev
|
||||
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update -y --fix-missing
|
||||
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev
|
||||
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update -y --fix-missing
|
||||
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev
|
||||
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
@@ -57,11 +57,11 @@ jobs:
|
||||
shopt -s dotglob nullglob
|
||||
if [ -d .debpkg/usr/share/doc/meshtasticd/web/build ]; then mv .debpkg/usr/share/doc/meshtasticd/web/build/* .debpkg/usr/share/doc/meshtasticd/web/; fi
|
||||
if [ -d .debpkg/usr/share/doc/meshtasticd/web/build ]; then rmdir .debpkg/usr/share/doc/meshtasticd/web/build; fi
|
||||
if [ -d .debpkg/usr/share/doc/meshtasticd/web/.DS_Store]; then rm -f .debpkg/usr/share/doc/meshtasticd/web/.DS_Store; fi
|
||||
gunzip .debpkg/usr/share/doc/meshtasticd/web/*.gz
|
||||
if [ -d .debpkg/usr/share/doc/meshtasticd/web/.DS_Store ]; then rm -f .debpkg/usr/share/doc/meshtasticd/web/.DS_Store; fi
|
||||
gunzip .debpkg/usr/share/doc/meshtasticd/web/ -r
|
||||
cp release/meshtasticd_linux_x86_64 .debpkg/usr/sbin/meshtasticd
|
||||
cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
|
||||
cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/
|
||||
cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/ -r
|
||||
chmod +x .debpkg/usr/sbin/meshtasticd
|
||||
cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service
|
||||
echo "/etc/meshtasticd/config.yaml" > .debpkg/DEBIAN/conffiles
|
||||
@@ -82,4 +82,4 @@ jobs:
|
||||
name: meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
|
||||
overwrite: true
|
||||
path: |
|
||||
./*.deb
|
||||
./*.deb
|
||||
@@ -57,11 +57,11 @@ jobs:
|
||||
shopt -s dotglob nullglob
|
||||
if [ -d .debpkg/usr/share/doc/meshtasticd/web/build ]; then mv .debpkg/usr/share/doc/meshtasticd/web/build/* .debpkg/usr/share/doc/meshtasticd/web/; fi
|
||||
if [ -d .debpkg/usr/share/doc/meshtasticd/web/build ]; then rmdir .debpkg/usr/share/doc/meshtasticd/web/build; fi
|
||||
if [ -d .debpkg/usr/share/doc/meshtasticd/web/.DS_Store]; then rm -f .debpkg/usr/share/doc/meshtasticd/web/.DS_Store; fi
|
||||
gunzip .debpkg/usr/share/doc/meshtasticd/web/*.gz
|
||||
if [ -d .debpkg/usr/share/doc/meshtasticd/web/.DS_Store ]; then rm -f .debpkg/usr/share/doc/meshtasticd/web/.DS_Store; fi
|
||||
gunzip .debpkg/usr/share/doc/meshtasticd/web/ -r
|
||||
cp release/meshtasticd_linux_aarch64 .debpkg/usr/sbin/meshtasticd
|
||||
cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
|
||||
cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/
|
||||
cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/ -r
|
||||
chmod +x .debpkg/usr/sbin/meshtasticd
|
||||
cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service
|
||||
echo "/etc/meshtasticd/config.yaml" > .debpkg/DEBIAN/conffiles
|
||||
@@ -82,4 +82,4 @@ jobs:
|
||||
name: meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
|
||||
overwrite: true
|
||||
path: |
|
||||
./*.deb
|
||||
./*.deb
|
||||
@@ -57,11 +57,11 @@ jobs:
|
||||
shopt -s dotglob nullglob
|
||||
if [ -d .debpkg/usr/share/doc/meshtasticd/web/build ]; then mv .debpkg/usr/share/doc/meshtasticd/web/build/* .debpkg/usr/share/doc/meshtasticd/web/; fi
|
||||
if [ -d .debpkg/usr/share/doc/meshtasticd/web/build ]; then rmdir .debpkg/usr/share/doc/meshtasticd/web/build; fi
|
||||
if [ -d .debpkg/usr/share/doc/meshtasticd/web/.DS_Store]; then rm -f .debpkg/usr/share/doc/meshtasticd/web/.DS_Store; fi
|
||||
gunzip .debpkg/usr/share/doc/meshtasticd/web/*.gz
|
||||
if [ -d .debpkg/usr/share/doc/meshtasticd/web/.DS_Store ]; then rm -f .debpkg/usr/share/doc/meshtasticd/web/.DS_Store; fi
|
||||
gunzip .debpkg/usr/share/doc/meshtasticd/web/ -r
|
||||
cp release/meshtasticd_linux_armv7l .debpkg/usr/sbin/meshtasticd
|
||||
cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
|
||||
cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/
|
||||
cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/ -r
|
||||
chmod +x .debpkg/usr/sbin/meshtasticd
|
||||
cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service
|
||||
echo "/etc/meshtasticd/config.yaml" > .debpkg/DEBIAN/conffiles
|
||||
@@ -82,4 +82,4 @@ jobs:
|
||||
name: meshtasticd_${{ steps.version.outputs.version }}_armhf.deb
|
||||
overwrite: true
|
||||
path: |
|
||||
./*.deb
|
||||
./*.deb
|
||||
+2
-2
@@ -30,7 +30,7 @@ lint:
|
||||
- git-diff-check
|
||||
- gitleaks@8.21.1
|
||||
- clang-format@16.0.3
|
||||
- prettier@3.3.3
|
||||
#- prettier@3.3.3
|
||||
ignore:
|
||||
- linters: [ALL]
|
||||
paths:
|
||||
@@ -46,4 +46,4 @@ actions:
|
||||
enabled:
|
||||
- trunk-fmt-pre-commit
|
||||
- trunk-check-pre-push
|
||||
- trunk-upgrade-available
|
||||
- trunk-upgrade-available
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
The Meshtastic Firmware project is subject to the code of conduct for the parent project, which can be found here:
|
||||
The Meshtastic Firmware project is subject to the code of conduct for the parent project, which can be found here:
|
||||
https://meshtastic.org/docs/legal/conduct/
|
||||
|
||||
@@ -46,7 +46,7 @@ lib_deps =
|
||||
${radiolib_base.lib_deps}
|
||||
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
|
||||
h2zero/NimBLE-Arduino@^1.4.2
|
||||
https://github.com/dbSuS/libpax.git#7bcd3fcab75037505be9b122ab2b24cc5176b587
|
||||
https://github.com/dbinfrago/libpax.git#3cdc0371c375676a97967547f4065607d4c53fd1
|
||||
lewisxhe/XPowersLib@^0.2.6
|
||||
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
|
||||
rweather/Crypto@^0.4.0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
; The Portduino based sim environment on top of any host OS, all hardware will be simulated
|
||||
[portduino_base]
|
||||
platform = https://github.com/meshtastic/platform-native.git#bcd02436cfca91f7d28ad0f7dab977c6aaa781af
|
||||
platform = https://github.com/meshtastic/platform-native.git#7fcee253a928535ff8b142704035b4b982f7e2d2
|
||||
framework = arduino
|
||||
|
||||
build_src_filter =
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
; Common settings for rp2040 Processor based targets
|
||||
[rp2040_base]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#a606be683748c73e9a0d46baf70163478d298f0f ; For arduino-pico 4.2.0
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#19e30129fb1428b823be585c787dcb4ac0d9014c ; For arduino-pico >=4.2.1
|
||||
extends = arduino_base
|
||||
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#4.2.1
|
||||
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#6024e9a7e82a72e38dd90f42029ba3748835eb2e ; 4.3.0 with fix MDNS
|
||||
|
||||
board_build.core = earlephilhower
|
||||
board_build.filesystem_size = 0.5m
|
||||
@@ -23,4 +23,4 @@ lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
rweather/Crypto
|
||||
rweather/Crypto
|
||||
@@ -1,8 +1,8 @@
|
||||
; Common settings for rp2040 Processor based targets
|
||||
[rp2350_base]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#a606be683748c73e9a0d46baf70163478d298f0f ; For arduino-pico 4.2.0
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#19e30129fb1428b823be585c787dcb4ac0d9014c ; For arduino-pico >=4.2.1
|
||||
extends = arduino_base
|
||||
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#4.2.1
|
||||
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#6024e9a7e82a72e38dd90f42029ba3748835eb2e ; 4.3.0 with fix MDNS
|
||||
|
||||
board_build.core = earlephilhower
|
||||
board_build.filesystem_size = 0.5m
|
||||
@@ -22,4 +22,4 @@ lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
rweather/Crypto
|
||||
rweather/Crypto
|
||||
@@ -0,0 +1,33 @@
|
||||
import sys
|
||||
import base64
|
||||
|
||||
def base64_to_hex_string(b64_string):
|
||||
try:
|
||||
# Decode the Base64 string to raw bytes
|
||||
decoded_bytes = base64.b64decode(b64_string)
|
||||
except Exception as e:
|
||||
raise ValueError(f"Invalid Base64 input: {e}")
|
||||
|
||||
# Check if the decoded result is exactly 32 bytes
|
||||
if len(decoded_bytes) != 32:
|
||||
raise ValueError("Decoded Base64 input must be exactly 32 bytes.")
|
||||
|
||||
# Convert each byte to its hex representation
|
||||
hex_values = [f"0x{byte:02x}" for byte in decoded_bytes]
|
||||
|
||||
# Join the formatted hex values with commas
|
||||
formatted_output = "{ " + ", ".join(hex_values) + " };"
|
||||
return formatted_output
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Check if a Base64 string was provided in command line arguments
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: python script.py <base64-string>")
|
||||
sys.exit(1)
|
||||
|
||||
b64_string = sys.argv[1]
|
||||
try:
|
||||
formatted_hex = base64_to_hex_string(b64_string)
|
||||
print(formatted_hex)
|
||||
except ValueError as e:
|
||||
print(e)
|
||||
+1
-2
@@ -27,5 +27,4 @@ rm -r $OUTDIR/* || true
|
||||
platformio pkg update --environment native || platformioFailed
|
||||
pio run --environment native || platformioFailed
|
||||
cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(uname -m)"
|
||||
cp bin/device-install.* $OUTDIR
|
||||
cp bin/device-update.* $OUTDIR
|
||||
cp bin/native-install.* $OUTDIR
|
||||
|
||||
@@ -24,7 +24,7 @@ def write_macros_to_json(macros, output_file):
|
||||
|
||||
def main():
|
||||
header_file = 'userPrefs.h'
|
||||
output_file = 'userPrefs.json'
|
||||
output_file = 'userPrefs.jsonc'
|
||||
# Uncomment all macros in the header file
|
||||
with open(header_file, 'r') as file:
|
||||
lines = file.readlines()
|
||||
|
||||
@@ -160,4 +160,6 @@ Webserver:
|
||||
General:
|
||||
MaxNodes: 200
|
||||
MaxMessageQueue: 100
|
||||
ConfigDirectory: /etc/meshtasticd/config.d/
|
||||
ConfigDirectory: /etc/meshtasticd/config.d/
|
||||
# MACAddress: AA:BB:CC:DD:EE:FF
|
||||
# MACAddressSource: eth0
|
||||
@@ -0,0 +1,8 @@
|
||||
Lora:
|
||||
Module: sx1262
|
||||
IRQ: 10
|
||||
Busy: 12
|
||||
Reset: 2
|
||||
spidev: spidev2.0
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
Lora:
|
||||
## Ebyte E22-900M30S, E22-900M22S with no external RF switching setup
|
||||
## Will work with any module without RF switching, and with TCXO
|
||||
Module: sx1262
|
||||
gpiochip: 1 # subtract 32 from the gpio numbers
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
CS: 16 #pin6 / GPIO48 1C0
|
||||
IRQ: 23 #pin17 / GPIO55 1C7
|
||||
Busy: 22 #pin16 / GPIO54 1C6
|
||||
Reset: 25 #pin13 / GPIO57 1D1
|
||||
RXen: 24 #pin12 / GPIO56 1D0
|
||||
#TXen: bridge to DIO2 on E22 module
|
||||
spidev: spidev0.0
|
||||
spiSpeed: 2000000
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
Lora:
|
||||
## Ebyte E22-900MM22S with no external RF switching setup
|
||||
## Will work with any module without RF switching and no TCXO
|
||||
Module: sx1262
|
||||
gpiochip: 1 # subtract 32 from the gpio numbers
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
CS: 16 #pin6 / GPIO48 1C0
|
||||
IRQ: 23 #pin17 / GPIO55 1C7
|
||||
Busy: 22 #pin16 / GPIO54 1C6
|
||||
Reset: 25 #pin13 / GPIO57 1D1
|
||||
RXen: 24 #pin12 / GPIO56 1D0
|
||||
#TXen: bridge to DIO2 on E22 module
|
||||
spidev: spidev0.0
|
||||
spiSpeed: 2000000
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
Lora:
|
||||
## Heltec HT-RA62, Seeed WIO SX1262
|
||||
## Will work with any module with automatic RF switching, and with TCXO
|
||||
Module: sx1262
|
||||
gpiochip: 1 # subtract 32 from the gpio numbers
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
CS: 16 #pin6 (GPIO pin 48 1C0)
|
||||
IRQ: 23 #pin17 (GPIO pin 55 1C7)
|
||||
Reset: 25 #pin13 (GPIO pin 57 1D1)
|
||||
Busy: 22 #pin16 (GPIO pin 54 1C6)
|
||||
spidev: spidev0.0 #pins are (CS=6, CLK=7, MOSI=8, MISO=9)
|
||||
spiSpeed: 2000000
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
Lora:
|
||||
## Waveshare SX126X XXXM, AI Thinker RA-01SH
|
||||
## Will work with any module with automatic RF switching, and with no TCXO
|
||||
Module: sx1262
|
||||
gpiochip: 1 # subtract 32 from the gpio numbers
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
CS: 16 #pin6 (GPIO pin 48 1C0)
|
||||
IRQ: 23 #pin17 (GPIO pin 55 1C7)
|
||||
Reset: 25 #pin13 (GPIO pin 57 1D1)
|
||||
Busy: 22 #pin16 (GPIO pin 54 1C6)
|
||||
spidev: spidev0.0 #pins are (CS=6, CLK=7, MOSI=8, MISO=9)
|
||||
spiSpeed: 2000000
|
||||
+12
-3
@@ -1,6 +1,7 @@
|
||||
@ECHO OFF
|
||||
|
||||
set PYTHON=python
|
||||
set WEB_APP=0
|
||||
|
||||
:: Determine the correct esptool command to use
|
||||
where esptool >nul 2>&1
|
||||
@@ -12,13 +13,14 @@ if %ERRORLEVEL% EQU 0 (
|
||||
|
||||
goto GETOPTS
|
||||
:HELP
|
||||
echo Usage: %~nx0 [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME^|FILENAME]
|
||||
echo Usage: %~nx0 [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME^|FILENAME] [--web]
|
||||
echo Flash image file to device, but first erasing and writing system information
|
||||
echo.
|
||||
echo -h Display this help and exit
|
||||
echo -p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerrous).
|
||||
echo -P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: %PYTHON%)
|
||||
echo -f FILENAME The .bin file to flash. Custom to your device type and region.
|
||||
echo --web Flash WEB APP.
|
||||
goto EOF
|
||||
|
||||
:GETOPTS
|
||||
@@ -27,6 +29,7 @@ if /I "%1"=="--help" goto HELP
|
||||
if /I "%1"=="-F" set "FILENAME=%2" & SHIFT
|
||||
if /I "%1"=="-p" set ESPTOOL_PORT=%2 & SHIFT
|
||||
if /I "%1"=="-P" set PYTHON=%2 & SHIFT
|
||||
if /I "%1"=="--web" set WEB_APP=1 & SHIFT
|
||||
SHIFT
|
||||
IF NOT "__%1__"=="____" goto GETOPTS
|
||||
|
||||
@@ -49,8 +52,14 @@ IF EXIST %FILENAME% IF x%FILENAME:update=%==x%FILENAME% (
|
||||
) else (
|
||||
%ESPTOOL_CMD% --baud 115200 write_flash 0x260000 bleota-s3.bin
|
||||
)
|
||||
for %%f in (littlefs-*.bin) do (
|
||||
%ESPTOOL_CMD% --baud 115200 write_flash 0x300000 %%f
|
||||
IF %WEB_APP%==1 (
|
||||
for %%f in (littlefswebui-*.bin) do (
|
||||
%ESPTOOL_CMD% --baud 115200 write_flash 0x300000 %%f
|
||||
)
|
||||
) else (
|
||||
for %%f in (littlefs-*.bin) do (
|
||||
%ESPTOOL_CMD% --baud 115200 write_flash 0x300000 %%f
|
||||
)
|
||||
)
|
||||
) else (
|
||||
echo "Invalid file: %FILENAME%"
|
||||
|
||||
+17
-2
@@ -1,6 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
PYTHON=${PYTHON:-$(which python3 python | head -n 1)}
|
||||
WEB_APP=false
|
||||
|
||||
# Determine the correct esptool command to use
|
||||
if "$PYTHON" -m esptool version >/dev/null 2>&1; then
|
||||
@@ -19,16 +20,26 @@ set -e
|
||||
# Usage info
|
||||
show_help() {
|
||||
cat <<EOF
|
||||
Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME]
|
||||
Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME] [--web]
|
||||
Flash image file to device, but first erasing and writing system information"
|
||||
|
||||
-h Display this help and exit
|
||||
-p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerous).
|
||||
-P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON")
|
||||
-f FILENAME The .bin file to flash. Custom to your device type and region.
|
||||
--web Flash WEB APP.
|
||||
|
||||
EOF
|
||||
}
|
||||
# Preprocess long options like --web
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--web)
|
||||
WEB_APP=true
|
||||
shift # Remove this argument from the list
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
while getopts ":hp:P:f:" opt; do
|
||||
case "${opt}" in
|
||||
@@ -73,7 +84,11 @@ if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then
|
||||
else
|
||||
$ESPTOOL_CMD write_flash 0x260000 bleota-s3.bin
|
||||
fi
|
||||
$ESPTOOL_CMD write_flash 0x300000 littlefs-*.bin
|
||||
if [ "$WEB_APP" = true ]; then
|
||||
$ESPTOOL_CMD write_flash 0x300000 littlefswebui-*.bin
|
||||
else
|
||||
$ESPTOOL_CMD write_flash 0x300000 littlefs-*.bin
|
||||
fi
|
||||
|
||||
else
|
||||
show_help
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
# trunk-ignore-all(flake8/F821): For SConstruct imports
|
||||
import sys
|
||||
from os.path import join
|
||||
import json
|
||||
import re
|
||||
|
||||
from readprops import readProps
|
||||
|
||||
@@ -90,11 +92,37 @@ prefsLoc = projenv["PROJECT_DIR"] + "/version.properties"
|
||||
verObj = readProps(prefsLoc)
|
||||
print("Using meshtastic platformio-custom.py, firmware version " + verObj["long"] + " on " + env.get("PIOENV"))
|
||||
|
||||
jsonLoc = env["PROJECT_DIR"] + "/userPrefs.jsonc"
|
||||
with open(jsonLoc) as f:
|
||||
jsonStr = re.sub("//.*","", f.read(), flags=re.MULTILINE)
|
||||
userPrefs = json.loads(jsonStr)
|
||||
|
||||
pref_flags = []
|
||||
# Pre-process the userPrefs
|
||||
for pref in userPrefs:
|
||||
if userPrefs[pref].startswith("{"):
|
||||
pref_flags.append("-D" + pref + "=" + userPrefs[pref])
|
||||
elif userPrefs[pref].replace(".", "").isdigit():
|
||||
pref_flags.append("-D" + pref + "=" + userPrefs[pref])
|
||||
elif userPrefs[pref] == "true" or userPrefs[pref] == "false":
|
||||
pref_flags.append("-D" + pref + "=" + userPrefs[pref])
|
||||
elif userPrefs[pref].startswith("meshtastic_"):
|
||||
pref_flags.append("-D" + pref + "=" + userPrefs[pref])
|
||||
# If the value is a string, we need to wrap it in quotes
|
||||
else:
|
||||
pref_flags.append("-D" + pref + "=" + env.StringifyMacro(userPrefs[pref]) + "")
|
||||
|
||||
# General options that are passed to the C and C++ compilers
|
||||
projenv.Append(
|
||||
CCFLAGS=[
|
||||
flags = [
|
||||
"-DAPP_VERSION=" + verObj["long"],
|
||||
"-DAPP_VERSION_SHORT=" + verObj["short"],
|
||||
"-DAPP_ENV=" + env.get("PIOENV"),
|
||||
]
|
||||
)
|
||||
] + pref_flags
|
||||
|
||||
print ("Using flags:")
|
||||
for flag in flags:
|
||||
print(flag)
|
||||
|
||||
projenv.Append(
|
||||
CCFLAGS=flags,
|
||||
)
|
||||
+2
-8
@@ -34,7 +34,6 @@ default_envs = tbeam
|
||||
;default_envs = radiomaster_900_bandit_nano
|
||||
;default_envs = radiomaster_900_bandit_micro
|
||||
;default_envs = radiomaster_900_bandit
|
||||
;default_envs = heltec_capsule_sensor_v3
|
||||
;default_envs = heltec_vision_master_t190
|
||||
;default_envs = heltec_vision_master_e213
|
||||
;default_envs = heltec_vision_master_e290
|
||||
@@ -110,7 +109,6 @@ framework = arduino
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
end2endzone/NonBlockingRTTTL@1.3.0
|
||||
https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#5cf62b36c6f30bc72a07bdb2c11fc9a22d1e31da
|
||||
build_flags = ${env.build_flags} -Os
|
||||
build_src_filter = ${env.build_src_filter} -<platform/portduino/>
|
||||
|
||||
@@ -154,15 +152,11 @@ lib_deps =
|
||||
sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.2.13
|
||||
ClosedCube OPT3001@1.1.2
|
||||
emotibit/EmotiBit MLX90632@1.0.8
|
||||
dfrobot/DFRobot_RTU@1.0.3
|
||||
sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2
|
||||
adafruit/Adafruit MLX90614 Library@2.1.5
|
||||
|
||||
https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.7.2502
|
||||
boschsensortec/BME68x Sensor Library@1.1.40407
|
||||
https://github.com/KodinLanewave/INA3221@1.0.1
|
||||
lewisxhe/SensorLib@0.2.0
|
||||
mprograms/QMC5883LCompass@1.2.3
|
||||
|
||||
https://github.com/meshtastic/DFRobot_LarkWeatherStation#4de3a9cadef0f6a5220a8a906cf9775b02b0040d
|
||||
https://github.com/gjelsoe/STK8xxx-Accelerometer.git#v0.1.1
|
||||
dfrobot/DFRobot_RTU@1.0.3
|
||||
https://github.com/meshtastic/DFRobot_LarkWeatherStation#4de3a9cadef0f6a5220a8a906cf9775b02b0040d
|
||||
+1
-1
Submodule protobufs updated: af2fea10fe...00c9c9932e
@@ -1 +0,0 @@
|
||||
curfirmwareversion.xml
|
||||
+1
-1
@@ -64,7 +64,7 @@ class AudioThread : public concurrency::OSThread
|
||||
void initOutput()
|
||||
{
|
||||
audioOut = new AudioOutputI2S(1, AudioOutputI2S::EXTERNAL_I2S);
|
||||
audioOut->SetPinout(DAC_I2S_BCK, DAC_I2S_WS, DAC_I2S_DOUT);
|
||||
audioOut->SetPinout(DAC_I2S_BCK, DAC_I2S_WS, DAC_I2S_DOUT, DAC_I2S_MCLK);
|
||||
audioOut->SetGain(0.2);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "ButtonThread.h"
|
||||
#include "../userPrefs.h"
|
||||
|
||||
#include "configuration.h"
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
#include "GPS.h"
|
||||
|
||||
+7
-3
@@ -19,6 +19,10 @@
|
||||
#include "sleep.h"
|
||||
#include "target_specific.h"
|
||||
|
||||
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
#endif
|
||||
|
||||
#ifndef SLEEP_TIME
|
||||
#define SLEEP_TIME 30
|
||||
#endif
|
||||
@@ -377,9 +381,9 @@ void PowerFSM_setup()
|
||||
// We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally)
|
||||
#ifdef ARCH_ESP32
|
||||
// See: https://github.com/meshtastic/firmware/issues/1071
|
||||
// Don't add power saving transitions if we are a power saving tracker or sensor. Sleep will be initiated through the
|
||||
// modules
|
||||
if ((isRouter || config.power.is_power_saving) && !isTrackerOrSensor) {
|
||||
// Don't add power saving transitions if we are a power saving tracker or sensor or have Wifi enabled. Sleep will be initiated
|
||||
// through the modules
|
||||
if ((isRouter || config.power.is_power_saving) && !isWifiAvailable() && !isTrackerOrSensor) {
|
||||
powerFSM.add_timed_transition(&stateNB, &stateLS,
|
||||
Default::getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL,
|
||||
"Min wake timeout");
|
||||
|
||||
+2
-2
@@ -148,6 +148,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define NAU7802_ADDR 0x2A
|
||||
#define MAX30102_ADDR 0x57
|
||||
#define MLX90614_ADDR_DEF 0x5A
|
||||
#define CGRADSENS_ADDR 0x66
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ACCELEROMETER
|
||||
@@ -170,7 +171,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// -----------------------------------------------------------------------------
|
||||
// Security
|
||||
// -----------------------------------------------------------------------------
|
||||
#define ATECC608B_ADDR 0x35
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// IO Expander
|
||||
@@ -361,4 +361,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#endif
|
||||
|
||||
#include "DebugConfiguration.h"
|
||||
#include "RF95Configuration.h"
|
||||
#include "RF95Configuration.h"
|
||||
@@ -12,7 +12,6 @@ class ScanI2C
|
||||
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,
|
||||
@@ -63,7 +62,8 @@ class ScanI2C
|
||||
ICM20948,
|
||||
MAX30102,
|
||||
TPS65233,
|
||||
MPR121KB
|
||||
MPR121KB,
|
||||
CGRADSENS
|
||||
} DeviceType;
|
||||
|
||||
// typedef uint8_t DeviceAddress;
|
||||
|
||||
+95
-120
@@ -7,7 +7,6 @@
|
||||
#include "linux/LinuxHardwareI2C.h"
|
||||
#endif
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
#include "main.h" // atecc
|
||||
#include "meshUtils.h" // vformat
|
||||
#endif
|
||||
|
||||
@@ -72,10 +71,10 @@ ScanI2C::DeviceType ScanI2CTwoWire::probeOLED(ScanI2C::DeviceAddress addr) const
|
||||
r &= 0x0f;
|
||||
|
||||
if (r == 0x08 || r == 0x00) {
|
||||
LOG_INFO("sh1106 display found");
|
||||
logFoundDevice("SH1106", (uint8_t)addr.address);
|
||||
o_probe = SCREEN_SH1106; // SH1106
|
||||
} else if (r == 0x03 || r == 0x04 || r == 0x06 || r == 0x07) {
|
||||
LOG_INFO("ssd1306 display found");
|
||||
logFoundDevice("SSD1306", (uint8_t)addr.address);
|
||||
o_probe = SCREEN_SSD1306; // SSD1306
|
||||
}
|
||||
c++;
|
||||
@@ -84,40 +83,6 @@ ScanI2C::DeviceType ScanI2CTwoWire::probeOLED(ScanI2C::DeviceAddress addr) const
|
||||
|
||||
return o_probe;
|
||||
}
|
||||
void ScanI2CTwoWire::printATECCInfo() const
|
||||
{
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
atecc.readConfigZone(false);
|
||||
|
||||
std::string atecc_numbers = "ATECC608B Serial Number: ";
|
||||
for (int i = 0; i < 9; i++) {
|
||||
atecc_numbers += vformat("%02x", atecc.serialNumber[i]);
|
||||
}
|
||||
|
||||
atecc_numbers += ", Rev Number: ";
|
||||
for (int i = 0; i < 4; i++) {
|
||||
atecc_numbers += vformat("%02x", atecc.revisionNumber[i]);
|
||||
}
|
||||
LOG_DEBUG(atecc_numbers.c_str());
|
||||
|
||||
LOG_DEBUG("ATECC608B Config %s, Data %s, Slot 0 %s", atecc.configLockStatus ? "Locked" : "Unlocked",
|
||||
atecc.dataOTPLockStatus ? "Locked" : "Unlocked", atecc.slot0LockStatus ? "Locked" : "Unlocked");
|
||||
|
||||
std::string atecc_publickey = "";
|
||||
if (atecc.configLockStatus && atecc.dataOTPLockStatus && atecc.slot0LockStatus) {
|
||||
if (atecc.generatePublicKey() == false) {
|
||||
atecc_publickey += "ATECC608B Error generating public key";
|
||||
} else {
|
||||
atecc_publickey += "ATECC608B Public Key: ";
|
||||
for (int i = 0; i < 64; i++) {
|
||||
atecc_publickey += vformat("%02x", atecc.publicKey64Bytes[i]);
|
||||
}
|
||||
}
|
||||
LOG_DEBUG(atecc_publickey.c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation ®isterLocation,
|
||||
ScanI2CTwoWire::ResponseWidth responseWidth) const
|
||||
{
|
||||
@@ -129,7 +94,6 @@ uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation
|
||||
i2cBus->endTransmission();
|
||||
delay(20);
|
||||
i2cBus->requestFrom(registerLocation.i2cAddress.address, responseWidth);
|
||||
LOG_DEBUG("Wire.available() = %d", i2cBus->available());
|
||||
if (i2cBus->available() == 2) {
|
||||
// Read MSB, then LSB
|
||||
value = (uint16_t)i2cBus->read() << 8;
|
||||
@@ -142,7 +106,7 @@ uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation
|
||||
|
||||
#define SCAN_SIMPLE_CASE(ADDR, T, ...) \
|
||||
case ADDR: \
|
||||
LOG_INFO(__VA_ARGS__); \
|
||||
logFoundDevice(__VA_ARGS__); \
|
||||
type = T; \
|
||||
break;
|
||||
|
||||
@@ -184,9 +148,9 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
|
||||
for (addr.address = 8; addr.address < 120; addr.address++) {
|
||||
if (asize != 0) {
|
||||
if (!in_array(address, asize, addr.address))
|
||||
if (!in_array(address, asize, (uint8_t)addr.address))
|
||||
continue;
|
||||
LOG_DEBUG("Scan address 0x%x", addr.address);
|
||||
LOG_DEBUG("Scan address 0x%x", (uint8_t)addr.address);
|
||||
}
|
||||
i2cBus->beginTransmission(addr.address);
|
||||
#ifdef ARCH_PORTDUINO
|
||||
@@ -199,35 +163,16 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
#endif
|
||||
type = NONE;
|
||||
if (err == 0) {
|
||||
LOG_DEBUG("I2C device found at address 0x%x", addr.address);
|
||||
|
||||
switch (addr.address) {
|
||||
case SSD1306_ADDRESS:
|
||||
type = probeOLED(addr);
|
||||
break;
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
case ATECC608B_ADDR:
|
||||
#ifdef RP2040_SLOW_CLOCK
|
||||
if (atecc.begin(addr.address, Wire, Serial2) == true)
|
||||
#else
|
||||
if (atecc.begin(addr.address) == true)
|
||||
#endif
|
||||
|
||||
{
|
||||
LOG_INFO("ATECC608B initialized");
|
||||
} else {
|
||||
LOG_WARN("ATECC608B initialization failed");
|
||||
}
|
||||
printATECCInfo();
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef RV3028_RTC
|
||||
case RV3028_RTC:
|
||||
// foundDevices[addr] = RTC_RV3028;
|
||||
type = RTC_RV3028;
|
||||
LOG_INFO("RV3028 RTC found");
|
||||
logFoundDevice("RV3028", (uint8_t)addr.address);
|
||||
rtc.initI2C(*i2cBus);
|
||||
rtc.writeToRegister(0x35, 0x07); // no Clkout
|
||||
rtc.writeToRegister(0x37, 0xB4);
|
||||
@@ -235,7 +180,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
#endif
|
||||
|
||||
#ifdef PCF8563_RTC
|
||||
SCAN_SIMPLE_CASE(PCF8563_RTC, RTC_PCF8563, "PCF8563 RTC found")
|
||||
SCAN_SIMPLE_CASE(PCF8563_RTC, RTC_PCF8563, "PCF8563", (uint8_t)addr.address)
|
||||
#endif
|
||||
|
||||
case CARDKB_ADDR:
|
||||
@@ -243,50 +188,50 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x04), 1);
|
||||
if (registerValue == 0x02) {
|
||||
// KEYPAD_VERSION
|
||||
LOG_INFO("RAK14004 found");
|
||||
logFoundDevice("RAK14004", (uint8_t)addr.address);
|
||||
type = RAK14004;
|
||||
} else {
|
||||
LOG_INFO("m5 cardKB found");
|
||||
logFoundDevice("M5 cardKB", (uint8_t)addr.address);
|
||||
type = CARDKB;
|
||||
}
|
||||
break;
|
||||
|
||||
SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard found");
|
||||
SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10 keyboard found");
|
||||
SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10", (uint8_t)addr.address);
|
||||
|
||||
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "st7567 display found");
|
||||
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "ST7567", (uint8_t)addr.address);
|
||||
#ifdef HAS_NCP5623
|
||||
SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623 RGB LED found");
|
||||
SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623", (uint8_t)addr.address);
|
||||
#endif
|
||||
#ifdef HAS_PMU
|
||||
SCAN_SIMPLE_CASE(XPOWERS_AXP192_AXP2101_ADDRESS, PMU_AXP192_AXP2101, "axp192/axp2101 PMU found")
|
||||
SCAN_SIMPLE_CASE(XPOWERS_AXP192_AXP2101_ADDRESS, PMU_AXP192_AXP2101, "AXP192/AXP2101", (uint8_t)addr.address)
|
||||
#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", (uint8_t)addr.address);
|
||||
logFoundDevice("BME680", (uint8_t)addr.address);
|
||||
type = BME_680;
|
||||
break;
|
||||
case 0x60:
|
||||
LOG_INFO("BME-280 sensor found at address 0x%x", (uint8_t)addr.address);
|
||||
logFoundDevice("BME280", (uint8_t)addr.address);
|
||||
type = BME_280;
|
||||
break;
|
||||
case 0x55:
|
||||
LOG_INFO("BMP-085 or BMP-180 sensor found at address 0x%x", (uint8_t)addr.address);
|
||||
logFoundDevice("BMP085/BMP180", (uint8_t)addr.address);
|
||||
type = BMP_085;
|
||||
break;
|
||||
default:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1); // GET_ID
|
||||
switch (registerValue) {
|
||||
case 0x50: // BMP-388 should be 0x50
|
||||
LOG_INFO("BMP-388 sensor found at address 0x%x", (uint8_t)addr.address);
|
||||
logFoundDevice("BMP-388", (uint8_t)addr.address);
|
||||
type = BMP_3XX;
|
||||
break;
|
||||
case 0x58: // BMP-280 should be 0x58
|
||||
default:
|
||||
LOG_INFO("BMP-280 sensor found at address 0x%x", (uint8_t)addr.address);
|
||||
logFoundDevice("BMP-280", (uint8_t)addr.address);
|
||||
type = BMP_280;
|
||||
break;
|
||||
}
|
||||
@@ -295,7 +240,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
break;
|
||||
#ifndef HAS_NCP5623
|
||||
case AHT10_ADDR:
|
||||
LOG_INFO("AHT10 sensor found at address 0x%x", (uint8_t)addr.address);
|
||||
logFoundDevice("AHT10", (uint8_t)addr.address);
|
||||
type = AHT10;
|
||||
break;
|
||||
#endif
|
||||
@@ -305,41 +250,57 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2);
|
||||
LOG_DEBUG("Register MFG_UID: 0x%x", registerValue);
|
||||
if (registerValue == 0x5449) {
|
||||
LOG_INFO("INA260 sensor found at address 0x%x", (uint8_t)addr.address);
|
||||
logFoundDevice("INA260", (uint8_t)addr.address);
|
||||
type = INA260;
|
||||
} else { // Assume INA219 if INA260 ID is not found
|
||||
LOG_INFO("INA219 sensor found at address 0x%x", (uint8_t)addr.address);
|
||||
logFoundDevice("INA219", (uint8_t)addr.address);
|
||||
type = INA219;
|
||||
}
|
||||
break;
|
||||
case INA3221_ADDR:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2);
|
||||
LOG_DEBUG("Register MFG_UID: 0x%x", registerValue);
|
||||
LOG_DEBUG("Register MFG_UID FE: 0x%x", registerValue);
|
||||
if (registerValue == 0x5449) {
|
||||
LOG_INFO("INA3221 sensor found at address 0x%x", (uint8_t)addr.address);
|
||||
logFoundDevice("INA3221", (uint8_t)addr.address);
|
||||
type = INA3221;
|
||||
} else {
|
||||
LOG_INFO("DFRobot Lark weather station found at address 0x%x", (uint8_t)addr.address);
|
||||
type = DFROBOT_LARK;
|
||||
/* check the first 2 bytes of the 6 byte response register
|
||||
LARK FW 1.0 should return:
|
||||
RESPONSE_STATUS STATUS_SUCCESS (0x53)
|
||||
RESPONSE_CMD CMD_GET_VERSION (0x05)
|
||||
RESPONSE_LEN_L 0x02
|
||||
RESPONSE_LEN_H 0x00
|
||||
RESPONSE_PAYLOAD 0x01
|
||||
RESPONSE_PAYLOAD+1 0x00
|
||||
*/
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x05), 2);
|
||||
LOG_DEBUG("Register MFG_UID 05: 0x%x", registerValue);
|
||||
if (registerValue == 0x5305) {
|
||||
logFoundDevice("DFRobot Lark", (uint8_t)addr.address);
|
||||
type = DFROBOT_LARK;
|
||||
}
|
||||
// else: probably a RAK12500/UBLOX GPS on I2C
|
||||
}
|
||||
break;
|
||||
case MCP9808_ADDR:
|
||||
// We need to check for STK8BAXX first, since register 0x07 is new data flag for the z-axis and can produce some
|
||||
// weird result. and register 0x00 doesn't seems to be colliding with MCP9808 and LIS3DH chips.
|
||||
{
|
||||
#ifdef HAS_STK8XXX
|
||||
// Check register 0x00 for 0x8700 response to ID STK8BA53 chip.
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 2);
|
||||
if (registerValue == 0x8700) {
|
||||
type = STK8BAXX;
|
||||
LOG_INFO("STK8BAXX accelerometer found");
|
||||
logFoundDevice("STK8BAXX", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check register 0x07 for 0x0400 response to ID MCP9808 chip.
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x07), 2);
|
||||
if (registerValue == 0x0400) {
|
||||
type = MCP9808;
|
||||
LOG_INFO("MCP9808 sensor found");
|
||||
logFoundDevice("MCP9808", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -347,7 +308,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 2);
|
||||
if (registerValue == 0x3300 || registerValue == 0x3333) { // RAK4631 WisBlock has LIS3DH register at 0x3333
|
||||
type = LIS3DH;
|
||||
LOG_INFO("LIS3DH accelerometer found");
|
||||
logFoundDevice("LIS3DH", (uint8_t)addr.address);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -355,93 +316,92 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x89), 2);
|
||||
if (registerValue == 0x11a2 || registerValue == 0x11da || registerValue == 0xe9c) {
|
||||
type = SHT4X;
|
||||
LOG_INFO("SHT4X sensor found");
|
||||
logFoundDevice("SHT4X", (uint8_t)addr.address);
|
||||
} else if (getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x7E), 2) == 0x5449) {
|
||||
type = OPT3001;
|
||||
LOG_INFO("OPT3001 light sensor found");
|
||||
logFoundDevice("OPT3001", (uint8_t)addr.address);
|
||||
} else {
|
||||
type = SHT31;
|
||||
LOG_INFO("SHT31 sensor found");
|
||||
logFoundDevice("SHT31", (uint8_t)addr.address);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
SCAN_SIMPLE_CASE(SHTC3_ADDR, SHTC3, "SHTC3 sensor found")
|
||||
SCAN_SIMPLE_CASE(SHTC3_ADDR, SHTC3, "SHTC3", (uint8_t)addr.address)
|
||||
case RCWL9620_ADDR:
|
||||
// get MAX30102 PARTID
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFF), 1);
|
||||
if (registerValue == 0x15) {
|
||||
type = MAX30102;
|
||||
LOG_INFO("MAX30102 Health sensor found");
|
||||
logFoundDevice("MAX30102", (uint8_t)addr.address);
|
||||
break;
|
||||
} else {
|
||||
type = RCWL9620;
|
||||
LOG_INFO("RCWL9620 sensor found");
|
||||
logFoundDevice("RCWL9620", (uint8_t)addr.address);
|
||||
}
|
||||
break;
|
||||
|
||||
case LPS22HB_ADDR_ALT:
|
||||
SCAN_SIMPLE_CASE(LPS22HB_ADDR, LPS22HB, "LPS22HB sensor found")
|
||||
|
||||
SCAN_SIMPLE_CASE(QMC6310_ADDR, QMC6310, "QMC6310 Highrate 3-Axis magnetic sensor found")
|
||||
SCAN_SIMPLE_CASE(LPS22HB_ADDR, LPS22HB, "LPS22HB", (uint8_t)addr.address)
|
||||
SCAN_SIMPLE_CASE(QMC6310_ADDR, QMC6310, "QMC6310", (uint8_t)addr.address)
|
||||
|
||||
case QMI8658_ADDR:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0A), 1); // get ID
|
||||
if (registerValue == 0xC0) {
|
||||
type = BQ24295;
|
||||
LOG_INFO("BQ24295 PMU found");
|
||||
logFoundDevice("BQ24295", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 1); // get ID
|
||||
if (registerValue == 0x6A) {
|
||||
type = LSM6DS3;
|
||||
LOG_INFO("LSM6DS3 accelerometer found at address 0x%x", (uint8_t)addr.address);
|
||||
logFoundDevice("LSM6DS3", (uint8_t)addr.address);
|
||||
} else {
|
||||
type = QMI8658;
|
||||
LOG_INFO("QMI8658 Highrate 6-Axis inertial measurement sensor found");
|
||||
logFoundDevice("QMI8658", (uint8_t)addr.address);
|
||||
}
|
||||
break;
|
||||
|
||||
SCAN_SIMPLE_CASE(QMC5883L_ADDR, QMC5883L, "QMC5883L Highrate 3-Axis magnetic sensor found")
|
||||
SCAN_SIMPLE_CASE(HMC5883L_ADDR, HMC5883L, "HMC5883L 3-Axis digital compass found")
|
||||
SCAN_SIMPLE_CASE(QMC5883L_ADDR, QMC5883L, "QMC5883L", (uint8_t)addr.address)
|
||||
SCAN_SIMPLE_CASE(HMC5883L_ADDR, HMC5883L, "HMC5883L", (uint8_t)addr.address)
|
||||
#ifdef HAS_QMA6100P
|
||||
SCAN_SIMPLE_CASE(QMA6100P_ADDR, QMA6100P, "QMA6100P accelerometer found")
|
||||
SCAN_SIMPLE_CASE(QMA6100P_ADDR, QMA6100P, "QMA6100P", (uint8_t)addr.address)
|
||||
#else
|
||||
SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031 air quality sensor found")
|
||||
SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031", (uint8_t)addr.address)
|
||||
#endif
|
||||
case BMA423_ADDR: // this can also be LIS3DH_ADDR_ALT
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 2);
|
||||
if (registerValue == 0x3300 || registerValue == 0x3333) { // RAK4631 WisBlock has LIS3DH register at 0x3333
|
||||
type = LIS3DH;
|
||||
LOG_INFO("LIS3DH accelerometer found");
|
||||
logFoundDevice("LIS3DH", (uint8_t)addr.address);
|
||||
} else {
|
||||
type = BMA423;
|
||||
LOG_INFO("BMA423 accelerometer found");
|
||||
logFoundDevice("BMA423", (uint8_t)addr.address);
|
||||
}
|
||||
break;
|
||||
|
||||
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3 accelerometer found at address 0x%x", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(TCA9535_ADDR, TCA9535, "TCA9535 I2C expander found");
|
||||
SCAN_SIMPLE_CASE(TCA9555_ADDR, TCA9555, "TCA9555 I2C expander found");
|
||||
SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700 light sensor found");
|
||||
SCAN_SIMPLE_CASE(TSL25911_ADDR, TSL2591, "TSL2591 light sensor found");
|
||||
SCAN_SIMPLE_CASE(OPT3001_ADDR, OPT3001, "OPT3001 light sensor found");
|
||||
SCAN_SIMPLE_CASE(MLX90632_ADDR, MLX90632, "MLX90632 IR temp sensor found");
|
||||
SCAN_SIMPLE_CASE(NAU7802_ADDR, NAU7802, "NAU7802 based scale found");
|
||||
SCAN_SIMPLE_CASE(FT6336U_ADDR, FT6336U, "FT6336U touchscreen found");
|
||||
SCAN_SIMPLE_CASE(MAX1704X_ADDR, MAX17048, "MAX17048 lipo fuel gauge found");
|
||||
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(TCA9535_ADDR, TCA9535, "TCA9535", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(TCA9555_ADDR, TCA9555, "TCA9555", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(TSL25911_ADDR, TSL2591, "TSL2591", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(OPT3001_ADDR, OPT3001, "OPT3001", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(MLX90632_ADDR, MLX90632, "MLX90632", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(NAU7802_ADDR, NAU7802, "NAU7802", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(FT6336U_ADDR, FT6336U, "FT6336U", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(MAX1704X_ADDR, MAX17048, "MAX17048", (uint8_t)addr.address);
|
||||
#ifdef HAS_TPS65233
|
||||
SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233 BIAS-T found");
|
||||
SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233", (uint8_t)addr.address);
|
||||
#endif
|
||||
|
||||
case MLX90614_ADDR_DEF:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0e), 1);
|
||||
if (registerValue == 0x5a) {
|
||||
type = MLX90614;
|
||||
LOG_INFO("MLX90614 IR temp sensor found");
|
||||
logFoundDevice("MLX90614", (uint8_t)addr.address);
|
||||
} else {
|
||||
type = MPR121KB;
|
||||
LOG_INFO("MPR121KB keyboard found");
|
||||
logFoundDevice("MPR121KB", (uint8_t)addr.address);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -450,24 +410,34 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1);
|
||||
if (registerValue == 0xEA) {
|
||||
type = ICM20948;
|
||||
LOG_INFO("ICM20948 9-dof motion processor found");
|
||||
logFoundDevice("ICM20948", (uint8_t)addr.address);
|
||||
break;
|
||||
} else if (addr.address == BMX160_ADDR) {
|
||||
type = BMX160;
|
||||
LOG_INFO("BMX160 accelerometer found");
|
||||
logFoundDevice("BMX160", (uint8_t)addr.address);
|
||||
break;
|
||||
} else {
|
||||
type = MPU6050;
|
||||
LOG_INFO("MPU6050 accelerometer found");
|
||||
logFoundDevice("MPU6050", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case CGRADSENS_ADDR:
|
||||
// Register 0x00 of the RadSens sensor contains is product identifier 0x7D
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1);
|
||||
if (registerValue == 0x7D) {
|
||||
type = CGRADSENS;
|
||||
logFoundDevice("ClimateGuard RadSens", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_INFO("Device found at address 0x%x was not able to be enumerated", addr.address);
|
||||
LOG_INFO("Device found at address 0x%x was not able to be enumerated", (uint8_t)addr.address);
|
||||
}
|
||||
} else if (err == 4) {
|
||||
LOG_ERROR("Unknown error at address 0x%x", addr.address);
|
||||
LOG_ERROR("Unknown error at address 0x%x", (uint8_t)addr.address);
|
||||
}
|
||||
|
||||
// Check if a type was found for the enumerated device - save, if so
|
||||
@@ -500,4 +470,9 @@ size_t ScanI2CTwoWire::countDevices() const
|
||||
{
|
||||
return foundDevices.size();
|
||||
}
|
||||
|
||||
void ScanI2CTwoWire::logFoundDevice(const char *device, uint8_t address)
|
||||
{
|
||||
LOG_INFO("%s found at address 0x%x", device, address);
|
||||
}
|
||||
#endif
|
||||
@@ -53,10 +53,10 @@ class ScanI2CTwoWire : public ScanI2C
|
||||
|
||||
concurrency::Lock lock;
|
||||
|
||||
void printATECCInfo() const;
|
||||
|
||||
uint16_t getRegisterValue(const RegisterLocation &, ResponseWidth) const;
|
||||
|
||||
DeviceType probeOLED(ScanI2C::DeviceAddress) const;
|
||||
|
||||
static void logFoundDevice(const char *device, uint8_t address);
|
||||
};
|
||||
#endif
|
||||
+76
-50
@@ -28,29 +28,43 @@
|
||||
#define GPS_RESET_MODE HIGH
|
||||
#endif
|
||||
|
||||
// Not all platforms have std::size().
|
||||
template <typename T, std::size_t N> std::size_t array_count(const T (&)[N])
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
#if defined(NRF52840_XXAA) || defined(NRF52833_XXAA) || defined(ARCH_ESP32) || defined(ARCH_PORTDUINO)
|
||||
HardwareSerial *GPS::_serial_gps = &Serial1;
|
||||
#elif defined(ARCH_RP2040)
|
||||
SerialUART *GPS::_serial_gps = &Serial1;
|
||||
#else
|
||||
HardwareSerial *GPS::_serial_gps = NULL;
|
||||
HardwareSerial *GPS::_serial_gps = nullptr;
|
||||
#endif
|
||||
|
||||
GPS *gps = nullptr;
|
||||
|
||||
GPSUpdateScheduling scheduling;
|
||||
static const char *ACK_SUCCESS_MESSAGE = "Get ack success!";
|
||||
|
||||
static GPSUpdateScheduling scheduling;
|
||||
|
||||
/// Multiple GPS instances might use the same serial port (in sequence), but we can
|
||||
/// only init that port once.
|
||||
static bool didSerialInit;
|
||||
|
||||
struct uBloxGnssModelInfo info;
|
||||
uint8_t uBloxProtocolVersion;
|
||||
static struct uBloxGnssModelInfo {
|
||||
char swVersion[30];
|
||||
char hwVersion[10];
|
||||
uint8_t extensionNo;
|
||||
char extension[10][30];
|
||||
uint8_t protocol_version;
|
||||
} ublox_info;
|
||||
|
||||
#define GPS_SOL_EXPIRY_MS 5000 // in millis. give 1 second time to combine different sentences. NMEA Frequency isn't higher anyway
|
||||
#define NMEA_MSG_GXGSA "GNGSA" // GSA message (GPGSA, GNGSA etc)
|
||||
|
||||
// For logging
|
||||
const char *getGPSPowerStateString(GPSPowerState state)
|
||||
static const char *getGPSPowerStateString(GPSPowerState state)
|
||||
{
|
||||
switch (state) {
|
||||
case GPS_ACTIVE:
|
||||
@@ -69,7 +83,7 @@ const char *getGPSPowerStateString(GPSPowerState state)
|
||||
}
|
||||
}
|
||||
|
||||
void GPS::UBXChecksum(uint8_t *message, size_t length)
|
||||
static void UBXChecksum(uint8_t *message, size_t length)
|
||||
{
|
||||
uint8_t CK_A = 0, CK_B = 0;
|
||||
|
||||
@@ -85,7 +99,7 @@ void GPS::UBXChecksum(uint8_t *message, size_t length)
|
||||
}
|
||||
|
||||
// Calculate the checksum for a CAS packet
|
||||
void GPS::CASChecksum(uint8_t *message, size_t length)
|
||||
static void CASChecksum(uint8_t *message, size_t length)
|
||||
{
|
||||
uint32_t cksum = ((uint32_t)message[5] << 24); // Message ID
|
||||
cksum += ((uint32_t)message[4]) << 16; // Class
|
||||
@@ -410,6 +424,15 @@ int GPS::getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if GPS_BAUDRATE_FIXED
|
||||
// if GPS_BAUDRATE is specified in variant, only try that.
|
||||
static const int serialSpeeds[1] = {GPS_BAUDRATE};
|
||||
static const int rareSerialSpeeds[1] = {GPS_BAUDRATE};
|
||||
#else
|
||||
static const int serialSpeeds[3] = {9600, 115200, 38400};
|
||||
static const int rareSerialSpeeds[3] = {4800, 57600, GPS_BAUDRATE};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Setup the GPS based on the model detected.
|
||||
* We detect the GPS by cycling through a set of baud rates, first common then rare.
|
||||
@@ -419,7 +442,6 @@ int GPS::getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
|
||||
*/
|
||||
bool GPS::setup()
|
||||
{
|
||||
|
||||
if (!didSerialInit) {
|
||||
int msglen = 0;
|
||||
if (tx_gpio && gnssModel == GNSS_MODEL_UNKNOWN) {
|
||||
@@ -427,7 +449,7 @@ bool GPS::setup()
|
||||
LOG_DEBUG("Probe for GPS at %d", serialSpeeds[speedSelect]);
|
||||
gnssModel = probe(serialSpeeds[speedSelect]);
|
||||
if (gnssModel == GNSS_MODEL_UNKNOWN) {
|
||||
if (++speedSelect == sizeof(serialSpeeds) / sizeof(int)) {
|
||||
if (++speedSelect == array_count(serialSpeeds)) {
|
||||
speedSelect = 0;
|
||||
++probeTries;
|
||||
}
|
||||
@@ -438,7 +460,7 @@ bool GPS::setup()
|
||||
LOG_DEBUG("Probe for GPS at %d", rareSerialSpeeds[speedSelect]);
|
||||
gnssModel = probe(rareSerialSpeeds[speedSelect]);
|
||||
if (gnssModel == GNSS_MODEL_UNKNOWN) {
|
||||
if (++speedSelect == sizeof(rareSerialSpeeds) / sizeof(int)) {
|
||||
if (++speedSelect == array_count(rareSerialSpeeds)) {
|
||||
LOG_WARN("Give up on GPS probe and set to %d", GPS_BAUDRATE);
|
||||
return true;
|
||||
}
|
||||
@@ -634,7 +656,7 @@ bool GPS::setup()
|
||||
SEND_UBX_PACKET(0x06, 0x01, _message_RMC, "enable NMEA RMC", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x01, _message_GGA, "enable NMEA GGA", 500);
|
||||
|
||||
if (uBloxProtocolVersion >= 18) {
|
||||
if (ublox_info.protocol_version >= 18) {
|
||||
clearBuffer();
|
||||
SEND_UBX_PACKET(0x06, 0x86, _message_PMS, "enable powersave for GPS", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "enable powersave details for GPS", 500);
|
||||
@@ -718,6 +740,7 @@ GPS::~GPS()
|
||||
// we really should unregister our sleep observer
|
||||
notifyDeepSleepObserver.unobserve(¬ifyDeepSleep);
|
||||
}
|
||||
|
||||
// Put the GPS hardware into a specified state
|
||||
void GPS::setPowerState(GPSPowerState newState, uint32_t sleepTime)
|
||||
{
|
||||
@@ -788,7 +811,8 @@ void GPS::setPowerState(GPSPowerState newState, uint32_t sleepTime)
|
||||
void GPS::writePinEN(bool on)
|
||||
{
|
||||
// Abort: if conflict with Canned Messages when using Wisblock(?)
|
||||
if (HW_VENDOR == meshtastic_HardwareModel_RAK4631 && (rotaryEncoderInterruptImpl1 || upDownInterruptImpl1))
|
||||
if ((HW_VENDOR == meshtastic_HardwareModel_RAK4631 || HW_VENDOR == meshtastic_HardwareModel_WISMESH_TAP) &&
|
||||
(rotaryEncoderInterruptImpl1 || upDownInterruptImpl1))
|
||||
return;
|
||||
|
||||
// Write and log
|
||||
@@ -881,17 +905,17 @@ void GPS::setPowerUBLOX(bool on, uint32_t sleepMs)
|
||||
if (gnssModel != GNSS_MODEL_UBLOX10) {
|
||||
// Encode the sleep time in millis into the packet
|
||||
for (int i = 0; i < 4; i++)
|
||||
gps->_message_PMREQ[0 + i] = sleepMs >> (i * 8);
|
||||
_message_PMREQ[0 + i] = sleepMs >> (i * 8);
|
||||
|
||||
// Record the message length
|
||||
msglen = gps->makeUBXPacket(0x02, 0x41, sizeof(_message_PMREQ), gps->_message_PMREQ);
|
||||
msglen = gps->makeUBXPacket(0x02, 0x41, sizeof(_message_PMREQ), _message_PMREQ);
|
||||
} else {
|
||||
// Encode the sleep time in millis into the packet
|
||||
for (int i = 0; i < 4; i++)
|
||||
gps->_message_PMREQ_10[4 + i] = sleepMs >> (i * 8);
|
||||
_message_PMREQ_10[4 + i] = sleepMs >> (i * 8);
|
||||
|
||||
// Record the message length
|
||||
msglen = gps->makeUBXPacket(0x02, 0x41, sizeof(_message_PMREQ_10), gps->_message_PMREQ_10);
|
||||
msglen = gps->makeUBXPacket(0x02, 0x41, sizeof(_message_PMREQ_10), _message_PMREQ_10);
|
||||
}
|
||||
|
||||
// Send the UBX packet
|
||||
@@ -1098,17 +1122,19 @@ int GPS::prepareDeepSleep(void *unused)
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *PROBE_MESSAGE = "Trying %s (%s)...";
|
||||
const char *DETECTED_MESSAGE = "%s detected, using %s Module";
|
||||
static const char *PROBE_MESSAGE = "Trying %s (%s)...";
|
||||
static const char *DETECTED_MESSAGE = "%s detected, using %s Module";
|
||||
|
||||
#define PROBE_SIMPLE(CHIP, TOWRITE, RESPONSE, DRIVER, TIMEOUT, ...) \
|
||||
LOG_DEBUG(PROBE_MESSAGE, TOWRITE, CHIP); \
|
||||
clearBuffer(); \
|
||||
_serial_gps->write(TOWRITE "\r\n"); \
|
||||
if (getACK(RESPONSE, TIMEOUT) == GNSS_RESPONSE_OK) { \
|
||||
LOG_INFO(DETECTED_MESSAGE, CHIP, #DRIVER); \
|
||||
return DRIVER; \
|
||||
}
|
||||
do { \
|
||||
LOG_DEBUG(PROBE_MESSAGE, TOWRITE, CHIP); \
|
||||
clearBuffer(); \
|
||||
_serial_gps->write(TOWRITE "\r\n"); \
|
||||
if (getACK(RESPONSE, TIMEOUT) == GNSS_RESPONSE_OK) { \
|
||||
LOG_INFO(DETECTED_MESSAGE, CHIP, #DRIVER); \
|
||||
return DRIVER; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
GnssModel_t GPS::probe(int serialSpeed)
|
||||
{
|
||||
@@ -1126,7 +1152,7 @@ GnssModel_t GPS::probe(int serialSpeed)
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&info, 0, sizeof(struct uBloxGnssModelInfo));
|
||||
memset(&ublox_info, 0, sizeof(ublox_info));
|
||||
uint8_t buffer[768] = {0};
|
||||
delay(100);
|
||||
|
||||
@@ -1193,64 +1219,64 @@ GnssModel_t GPS::probe(int serialSpeed)
|
||||
if (len) {
|
||||
uint16_t position = 0;
|
||||
for (int i = 0; i < 30; i++) {
|
||||
info.swVersion[i] = buffer[position];
|
||||
ublox_info.swVersion[i] = buffer[position];
|
||||
position++;
|
||||
}
|
||||
for (int i = 0; i < 10; i++) {
|
||||
info.hwVersion[i] = buffer[position];
|
||||
ublox_info.hwVersion[i] = buffer[position];
|
||||
position++;
|
||||
}
|
||||
|
||||
while (len >= position + 30) {
|
||||
for (int i = 0; i < 30; i++) {
|
||||
info.extension[info.extensionNo][i] = buffer[position];
|
||||
ublox_info.extension[ublox_info.extensionNo][i] = buffer[position];
|
||||
position++;
|
||||
}
|
||||
info.extensionNo++;
|
||||
if (info.extensionNo > 9)
|
||||
ublox_info.extensionNo++;
|
||||
if (ublox_info.extensionNo > 9)
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_DEBUG("Module Info : ");
|
||||
LOG_DEBUG("Soft version: %s", info.swVersion);
|
||||
LOG_DEBUG("Hard version: %s", info.hwVersion);
|
||||
LOG_DEBUG("Extensions:%d", info.extensionNo);
|
||||
for (int i = 0; i < info.extensionNo; i++) {
|
||||
LOG_DEBUG(" %s", info.extension[i]);
|
||||
LOG_DEBUG("Soft version: %s", ublox_info.swVersion);
|
||||
LOG_DEBUG("Hard version: %s", ublox_info.hwVersion);
|
||||
LOG_DEBUG("Extensions:%d", ublox_info.extensionNo);
|
||||
for (int i = 0; i < ublox_info.extensionNo; i++) {
|
||||
LOG_DEBUG(" %s", ublox_info.extension[i]);
|
||||
}
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
// tips: extensionNo field is 0 on some 6M GNSS modules
|
||||
for (int i = 0; i < info.extensionNo; ++i) {
|
||||
if (!strncmp(info.extension[i], "MOD=", 4)) {
|
||||
strncpy((char *)buffer, &(info.extension[i][4]), sizeof(buffer));
|
||||
} else if (!strncmp(info.extension[i], "PROTVER", 7)) {
|
||||
for (int i = 0; i < ublox_info.extensionNo; ++i) {
|
||||
if (!strncmp(ublox_info.extension[i], "MOD=", 4)) {
|
||||
strncpy((char *)buffer, &(ublox_info.extension[i][4]), sizeof(buffer));
|
||||
} else if (!strncmp(ublox_info.extension[i], "PROTVER", 7)) {
|
||||
char *ptr = nullptr;
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
strncpy((char *)buffer, &(info.extension[i][8]), sizeof(buffer));
|
||||
strncpy((char *)buffer, &(ublox_info.extension[i][8]), sizeof(buffer));
|
||||
LOG_DEBUG("Protocol Version:%s", (char *)buffer);
|
||||
if (strlen((char *)buffer)) {
|
||||
uBloxProtocolVersion = strtoul((char *)buffer, &ptr, 10);
|
||||
LOG_DEBUG("ProtVer=%d", uBloxProtocolVersion);
|
||||
ublox_info.protocol_version = strtoul((char *)buffer, &ptr, 10);
|
||||
LOG_DEBUG("ProtVer=%d", ublox_info.protocol_version);
|
||||
} else {
|
||||
uBloxProtocolVersion = 0;
|
||||
ublox_info.protocol_version = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (strncmp(info.hwVersion, "00040007", 8) == 0) {
|
||||
if (strncmp(ublox_info.hwVersion, "00040007", 8) == 0) {
|
||||
LOG_INFO(DETECTED_MESSAGE, "U-blox 6", "6");
|
||||
return GNSS_MODEL_UBLOX6;
|
||||
} else if (strncmp(info.hwVersion, "00070000", 8) == 0) {
|
||||
} else if (strncmp(ublox_info.hwVersion, "00070000", 8) == 0) {
|
||||
LOG_INFO(DETECTED_MESSAGE, "U-blox 7", "7");
|
||||
return GNSS_MODEL_UBLOX7;
|
||||
} else if (strncmp(info.hwVersion, "00080000", 8) == 0) {
|
||||
} else if (strncmp(ublox_info.hwVersion, "00080000", 8) == 0) {
|
||||
LOG_INFO(DETECTED_MESSAGE, "U-blox 8", "8");
|
||||
return GNSS_MODEL_UBLOX8;
|
||||
} else if (strncmp(info.hwVersion, "00190000", 8) == 0) {
|
||||
} else if (strncmp(ublox_info.hwVersion, "00190000", 8) == 0) {
|
||||
LOG_INFO(DETECTED_MESSAGE, "U-blox 9", "9");
|
||||
return GNSS_MODEL_UBLOX9;
|
||||
} else if (strncmp(info.hwVersion, "000A0000", 8) == 0) {
|
||||
} else if (strncmp(ublox_info.hwVersion, "000A0000", 8) == 0) {
|
||||
LOG_INFO(DETECTED_MESSAGE, "U-blox 10", "10");
|
||||
return GNSS_MODEL_UBLOX10;
|
||||
}
|
||||
@@ -1724,4 +1750,4 @@ void GPS::toggleGpsMode()
|
||||
enable();
|
||||
}
|
||||
}
|
||||
#endif // Exclude GPS
|
||||
#endif // Exclude GPS
|
||||
+66
-153
@@ -16,13 +16,6 @@
|
||||
#define GPS_EN_ACTIVE 1
|
||||
#endif
|
||||
|
||||
struct uBloxGnssModelInfo {
|
||||
char swVersion[30];
|
||||
char hwVersion[10];
|
||||
uint8_t extensionNo;
|
||||
char extension[10][30];
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
GNSS_MODEL_ATGM336H,
|
||||
GNSS_MODEL_MTK,
|
||||
@@ -54,9 +47,6 @@ enum GPSPowerState : uint8_t {
|
||||
GPS_OFF // Powered off indefinitely
|
||||
};
|
||||
|
||||
// Generate a string representation of DOP
|
||||
const char *getDOPString(uint32_t dop);
|
||||
|
||||
/**
|
||||
* A gps class that only reads from the GPS periodically and keeps the gps powered down except when reading
|
||||
*
|
||||
@@ -64,109 +54,7 @@ const char *getDOPString(uint32_t dop);
|
||||
*/
|
||||
class GPS : private concurrency::OSThread
|
||||
{
|
||||
TinyGPSPlus reader;
|
||||
uint8_t fixQual = 0; // fix quality from GPGGA
|
||||
uint32_t lastChecksumFailCount = 0;
|
||||
|
||||
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||
// (20210908) TinyGps++ can only read the GPGSA "FIX TYPE" field
|
||||
// via optional feature "custom fields", currently disabled (bug #525)
|
||||
TinyGPSCustom gsafixtype; // custom extract fix type from GPGSA
|
||||
TinyGPSCustom gsapdop; // custom extract PDOP from GPGSA
|
||||
uint8_t fixType = 0; // fix type from GPGSA
|
||||
#endif
|
||||
private:
|
||||
#if GPS_BAUDRATE_FIXED
|
||||
// if GPS_BAUDRATE is specified in variant, only try that.
|
||||
const int serialSpeeds[1] = {GPS_BAUDRATE};
|
||||
const int rareSerialSpeeds[1] = {GPS_BAUDRATE};
|
||||
#else
|
||||
const int serialSpeeds[3] = {9600, 115200, 38400};
|
||||
const int rareSerialSpeeds[3] = {4800, 57600, GPS_BAUDRATE};
|
||||
#endif
|
||||
|
||||
uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastFixStartMsec = 0;
|
||||
uint32_t rx_gpio = 0;
|
||||
uint32_t tx_gpio = 0;
|
||||
|
||||
int speedSelect = 0;
|
||||
int probeTries = 0;
|
||||
|
||||
/**
|
||||
* hasValidLocation - indicates that the position variables contain a complete
|
||||
* GPS location, valid and fresh (< gps_update_interval + position_broadcast_secs)
|
||||
*/
|
||||
bool hasValidLocation = false; // default to false, until we complete our first read
|
||||
|
||||
bool isInPowersave = false;
|
||||
|
||||
bool shouldPublish = false; // If we've changed GPS state, this will force a publish the next loop()
|
||||
|
||||
bool hasGPS = false; // Do we have a GPS we are talking to
|
||||
|
||||
bool GPSInitFinished = false; // Init thread finished?
|
||||
bool GPSInitStarted = false; // Init thread finished?
|
||||
|
||||
GPSPowerState powerState = GPS_OFF; // GPS_ACTIVE if we want a location right now
|
||||
|
||||
uint8_t numSatellites = 0;
|
||||
|
||||
CallbackObserver<GPS, void *> notifyDeepSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
|
||||
|
||||
public:
|
||||
/** If !NULL we will use this serial port to construct our GPS */
|
||||
#if defined(ARCH_RP2040)
|
||||
static SerialUART *_serial_gps;
|
||||
#else
|
||||
static HardwareSerial *_serial_gps;
|
||||
#endif
|
||||
static uint8_t _message_PMREQ[];
|
||||
static uint8_t _message_PMREQ_10[];
|
||||
static const uint8_t _message_CFG_RXM_PSM[];
|
||||
static const uint8_t _message_CFG_RXM_ECO[];
|
||||
static const uint8_t _message_CFG_PM2[];
|
||||
static const uint8_t _message_GNSS_7[];
|
||||
static const uint8_t _message_GNSS_8[];
|
||||
static const uint8_t _message_JAM_6_7[];
|
||||
static const uint8_t _message_JAM_8[];
|
||||
static const uint8_t _message_NAVX5[];
|
||||
static const uint8_t _message_NAVX5_8[];
|
||||
static const uint8_t _message_NMEA[];
|
||||
static const uint8_t _message_DISABLE_TXT_INFO[];
|
||||
static const uint8_t _message_1HZ[];
|
||||
static const uint8_t _message_GLL[];
|
||||
static const uint8_t _message_GSA[];
|
||||
static const uint8_t _message_GSV[];
|
||||
static const uint8_t _message_VTG[];
|
||||
static const uint8_t _message_RMC[];
|
||||
static const uint8_t _message_AID[];
|
||||
static const uint8_t _message_GGA[];
|
||||
static const uint8_t _message_PMS[];
|
||||
static const uint8_t _message_SAVE[];
|
||||
static const uint8_t _message_SAVE_10[];
|
||||
|
||||
// VALSET Commands for M10
|
||||
static const uint8_t _message_VALSET_PM[];
|
||||
static const uint8_t _message_VALSET_PM_RAM[];
|
||||
static const uint8_t _message_VALSET_PM_BBR[];
|
||||
static const uint8_t _message_VALSET_ITFM_RAM[];
|
||||
static const uint8_t _message_VALSET_ITFM_BBR[];
|
||||
static const uint8_t _message_VALSET_DISABLE_NMEA_RAM[];
|
||||
static const uint8_t _message_VALSET_DISABLE_NMEA_BBR[];
|
||||
static const uint8_t _message_VALSET_DISABLE_TXT_INFO_RAM[];
|
||||
static const uint8_t _message_VALSET_DISABLE_TXT_INFO_BBR[];
|
||||
static const uint8_t _message_VALSET_ENABLE_NMEA_RAM[];
|
||||
static const uint8_t _message_VALSET_ENABLE_NMEA_BBR[];
|
||||
static const uint8_t _message_VALSET_DISABLE_SBAS_RAM[];
|
||||
static const uint8_t _message_VALSET_DISABLE_SBAS_BBR[];
|
||||
|
||||
// CASIC commands for ATGM336H
|
||||
static const uint8_t _message_CAS_CFG_RST_FACTORY[];
|
||||
static const uint8_t _message_CAS_CFG_NAVX_CONF[];
|
||||
static const uint8_t _message_CAS_CFG_RATE_1HZ[];
|
||||
|
||||
const char *ACK_SUCCESS_MESSAGE = "Get ack success!";
|
||||
|
||||
meshtastic_Position p = meshtastic_Position_init_default;
|
||||
|
||||
/** This is normally bound to config.position.gps_en_gpio but some rare boards (like heltec tracker) need more advanced
|
||||
@@ -176,8 +64,6 @@ class GPS : private concurrency::OSThread
|
||||
*/
|
||||
GpioVirtPin *enablePin = NULL;
|
||||
|
||||
GPS() : concurrency::OSThread("GPS") {}
|
||||
|
||||
virtual ~GPS();
|
||||
|
||||
/** We will notify this observable anytime GPS state has changed meaningfully */
|
||||
@@ -214,21 +100,6 @@ class GPS : private concurrency::OSThread
|
||||
// Empty the input buffer as quickly as possible
|
||||
void clearBuffer();
|
||||
|
||||
// Create a ublox packet for editing in memory
|
||||
uint8_t makeUBXPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg);
|
||||
uint8_t makeCASPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg);
|
||||
|
||||
// scratch space for creating ublox packets
|
||||
uint8_t UBXscratch[250] = {0};
|
||||
|
||||
int rebootsSeen = 0;
|
||||
|
||||
int getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID, uint32_t waitMillis);
|
||||
GPS_RESPONSE getACK(uint8_t c, uint8_t i, uint32_t waitMillis);
|
||||
GPS_RESPONSE getACK(const char *message, uint32_t waitMillis);
|
||||
|
||||
GPS_RESPONSE getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis);
|
||||
|
||||
virtual bool factoryReset();
|
||||
|
||||
// Creates an instance of the GPS class.
|
||||
@@ -241,20 +112,8 @@ class GPS : private concurrency::OSThread
|
||||
// Let the GPS hardware save power between updates
|
||||
void down();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
|
||||
* Override this method to check for new locations
|
||||
*
|
||||
* @return true if we've acquired a time
|
||||
*/
|
||||
|
||||
/**
|
||||
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
|
||||
* Override this method to check for new locations
|
||||
*
|
||||
* @return true if we've acquired a new location
|
||||
*/
|
||||
private:
|
||||
GPS() : concurrency::OSThread("GPS") {}
|
||||
|
||||
/// Record that we have a GPS
|
||||
void setConnected();
|
||||
@@ -281,15 +140,74 @@ class GPS : private concurrency::OSThread
|
||||
*/
|
||||
virtual bool lookForLocation();
|
||||
|
||||
private:
|
||||
GnssModel_t gnssModel = GNSS_MODEL_UNKNOWN;
|
||||
|
||||
TinyGPSPlus reader;
|
||||
uint8_t fixQual = 0; // fix quality from GPGGA
|
||||
uint32_t lastChecksumFailCount = 0;
|
||||
|
||||
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||
// (20210908) TinyGps++ can only read the GPGSA "FIX TYPE" field
|
||||
// via optional feature "custom fields", currently disabled (bug #525)
|
||||
TinyGPSCustom gsafixtype; // custom extract fix type from GPGSA
|
||||
TinyGPSCustom gsapdop; // custom extract PDOP from GPGSA
|
||||
uint8_t fixType = 0; // fix type from GPGSA
|
||||
#endif
|
||||
|
||||
uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastFixStartMsec = 0;
|
||||
uint32_t rx_gpio = 0;
|
||||
uint32_t tx_gpio = 0;
|
||||
|
||||
uint8_t speedSelect = 0;
|
||||
uint8_t probeTries = 0;
|
||||
|
||||
/**
|
||||
* hasValidLocation - indicates that the position variables contain a complete
|
||||
* GPS location, valid and fresh (< gps_update_interval + position_broadcast_secs)
|
||||
*/
|
||||
bool hasValidLocation = false; // default to false, until we complete our first read
|
||||
|
||||
bool isInPowersave = false;
|
||||
|
||||
bool shouldPublish = false; // If we've changed GPS state, this will force a publish the next loop()
|
||||
|
||||
bool hasGPS = false; // Do we have a GPS we are talking to
|
||||
|
||||
bool GPSInitFinished = false; // Init thread finished?
|
||||
bool GPSInitStarted = false; // Init thread finished?
|
||||
|
||||
GPSPowerState powerState = GPS_OFF; // GPS_ACTIVE if we want a location right now
|
||||
|
||||
uint8_t numSatellites = 0;
|
||||
|
||||
CallbackObserver<GPS, void *> notifyDeepSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
|
||||
|
||||
/** If !NULL we will use this serial port to construct our GPS */
|
||||
#if defined(ARCH_RP2040)
|
||||
static SerialUART *_serial_gps;
|
||||
#else
|
||||
static HardwareSerial *_serial_gps;
|
||||
#endif
|
||||
|
||||
// Create a ublox packet for editing in memory
|
||||
uint8_t makeUBXPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg);
|
||||
uint8_t makeCASPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg);
|
||||
|
||||
// scratch space for creating ublox packets
|
||||
uint8_t UBXscratch[250] = {0};
|
||||
|
||||
int rebootsSeen = 0;
|
||||
|
||||
int getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID, uint32_t waitMillis);
|
||||
GPS_RESPONSE getACK(uint8_t c, uint8_t i, uint32_t waitMillis);
|
||||
GPS_RESPONSE getACK(const char *message, uint32_t waitMillis);
|
||||
|
||||
GPS_RESPONSE getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis);
|
||||
|
||||
/// Prepare the GPS for the cpu entering deep sleep, expect to be gone for at least 100s of msecs
|
||||
/// always returns 0 to indicate okay to sleep
|
||||
int prepareDeepSleep(void *unused);
|
||||
|
||||
// Calculate checksum
|
||||
void UBXChecksum(uint8_t *message, size_t length);
|
||||
void CASChecksum(uint8_t *message, size_t length);
|
||||
|
||||
/** Set power with EN pin, if relevant
|
||||
*/
|
||||
void writePinEN(bool on);
|
||||
@@ -318,11 +236,6 @@ class GPS : private concurrency::OSThread
|
||||
|
||||
// delay counter to allow more sats before fixed position stops GPS thread
|
||||
uint8_t fixeddelayCtr = 0;
|
||||
|
||||
const char *powerStateToString();
|
||||
|
||||
protected:
|
||||
GnssModel_t gnssModel = GNSS_MODEL_UNKNOWN;
|
||||
};
|
||||
|
||||
extern GPS *gps;
|
||||
|
||||
@@ -574,3 +574,23 @@ const char *GeoCoord::degreesToBearing(unsigned int degrees)
|
||||
else
|
||||
return "N";
|
||||
}
|
||||
|
||||
double GeoCoord::pow_neg(double base, double exponent)
|
||||
{
|
||||
if (exponent == 0) {
|
||||
return 1;
|
||||
} else if (exponent > 0) {
|
||||
return pow(base, exponent);
|
||||
}
|
||||
return 1 / pow(base, -exponent);
|
||||
}
|
||||
|
||||
double GeoCoord::toRadians(double deg)
|
||||
{
|
||||
return deg * PI / 180;
|
||||
}
|
||||
|
||||
double GeoCoord::toDegrees(double r)
|
||||
{
|
||||
return r * 180 / PI;
|
||||
}
|
||||
+6
-23
@@ -13,28 +13,6 @@
|
||||
#define OLC_CODE_LEN 11
|
||||
#define DEG_CONVERT (180 / PI)
|
||||
|
||||
// Helper functions
|
||||
// Raises a number to an exponent, handling negative exponents.
|
||||
static inline double pow_neg(double base, double exponent)
|
||||
{
|
||||
if (exponent == 0) {
|
||||
return 1;
|
||||
} else if (exponent > 0) {
|
||||
return pow(base, exponent);
|
||||
}
|
||||
return 1 / pow(base, -exponent);
|
||||
}
|
||||
|
||||
static inline double toRadians(double deg)
|
||||
{
|
||||
return deg * PI / 180;
|
||||
}
|
||||
|
||||
static inline double toDegrees(double r)
|
||||
{
|
||||
return r * 180 / PI;
|
||||
}
|
||||
|
||||
// GeoCoord structs/classes
|
||||
// A struct to hold the data for a DMS coordinate.
|
||||
struct DMS {
|
||||
@@ -120,6 +98,11 @@ class GeoCoord
|
||||
static unsigned int bearingToDegrees(const char *bearing);
|
||||
static const char *degreesToBearing(unsigned int degrees);
|
||||
|
||||
// Raises a number to an exponent, handling negative exponents.
|
||||
static double pow_neg(double base, double exponent);
|
||||
static double toRadians(double deg);
|
||||
static double toDegrees(double r);
|
||||
|
||||
// Point to point conversions
|
||||
int32_t distanceTo(const GeoCoord &pointB);
|
||||
int32_t bearingTo(const GeoCoord &pointB);
|
||||
@@ -162,4 +145,4 @@ class GeoCoord
|
||||
|
||||
// OLC getter
|
||||
void getOLCCode(char *code) { strncpy(code, _olc.code, OLC_CODE_LEN + 1); } // +1 for null termination
|
||||
};
|
||||
};
|
||||
+1
-1
@@ -23,7 +23,7 @@ uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_PositionLite &pos, c
|
||||
{
|
||||
GeoCoord geoCoord(pos.latitude_i, pos.longitude_i, pos.altitude);
|
||||
char type = isCaltopoMode ? 'P' : 'N';
|
||||
uint32_t len = snprintf(buf, bufsz, "$G%cWPL,%02d%07.4f,%c,%03d%07.4f,%c,%s", type, geoCoord.getDMSLatDeg(),
|
||||
uint32_t len = snprintf(buf, bufsz, "\r\n$G%cWPL,%02d%07.4f,%c,%03d%07.4f,%c,%s", type, geoCoord.getDMSLatDeg(),
|
||||
(abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6, geoCoord.getDMSLatCP(),
|
||||
geoCoord.getDMSLonDeg(), (abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6,
|
||||
geoCoord.getDMSLonCP(), name);
|
||||
|
||||
+4
-4
@@ -21,7 +21,7 @@
|
||||
|
||||
// CFG-RST (0x06, 0x02)
|
||||
// Factory reset
|
||||
const uint8_t GPS::_message_CAS_CFG_RST_FACTORY[] = {
|
||||
static const uint8_t _message_CAS_CFG_RST_FACTORY[] = {
|
||||
0xFF, 0x03, // Fields to clear
|
||||
0x01, // Reset Mode: Controlled Software reset
|
||||
0x03 // Startup Mode: Factory
|
||||
@@ -30,7 +30,7 @@ const uint8_t GPS::_message_CAS_CFG_RST_FACTORY[] = {
|
||||
// CFG_RATE (0x06, 0x01)
|
||||
// 1HZ update rate, this should always be the case after
|
||||
// factory reset but update it regardless
|
||||
const uint8_t GPS::_message_CAS_CFG_RATE_1HZ[] = {
|
||||
static const uint8_t _message_CAS_CFG_RATE_1HZ[] = {
|
||||
0xE8, 0x03, // Update Rate: 0x03E8 = 1000ms
|
||||
0x00, 0x00 // Reserved
|
||||
};
|
||||
@@ -39,7 +39,7 @@ const uint8_t GPS::_message_CAS_CFG_RATE_1HZ[] = {
|
||||
// Initial ATGM33H-5N configuration, Updates for Dynamic Mode, Fix Mode, and SV system
|
||||
// Qwirk: The ATGM33H-5N-31 should only support GPS+BDS, however it will happily enable
|
||||
// and use GPS+BDS+GLONASS iff the correct CFG_NAVX command is used.
|
||||
const uint8_t GPS::_message_CAS_CFG_NAVX_CONF[] = {
|
||||
static const uint8_t _message_CAS_CFG_NAVX_CONF[] = {
|
||||
0x03, 0x01, 0x00, 0x00, // Update Mask: Dynamic Mode, Fix Mode, Nav Settings
|
||||
0x03, // Dynamic Mode: Automotive
|
||||
0x03, // Fix Mode: Auto 2D/3D
|
||||
@@ -60,4 +60,4 @@ const uint8_t GPS::_message_CAS_CFG_NAVX_CONF[] = {
|
||||
0x00, 0x00, 0x00, 0x00, // Position Accuracy Max
|
||||
0x00, 0x00, 0x00, 0x00, // Time Accuracy Max
|
||||
0x00, 0x00, 0x00, 0x00 // Static Hold Threshold
|
||||
};
|
||||
};
|
||||
|
||||
+57
-55
@@ -1,20 +1,22 @@
|
||||
const char *failMessage = "Unable to %s";
|
||||
static const char *failMessage = "Unable to %s";
|
||||
|
||||
#define SEND_UBX_PACKET(TYPE, ID, DATA, ERRMSG, TIMEOUT) \
|
||||
msglen = makeUBXPacket(TYPE, ID, sizeof(DATA), DATA); \
|
||||
_serial_gps->write(UBXscratch, msglen); \
|
||||
if (getACK(TYPE, ID, TIMEOUT) != GNSS_RESPONSE_OK) { \
|
||||
LOG_WARN(failMessage, #ERRMSG); \
|
||||
}
|
||||
do { \
|
||||
msglen = makeUBXPacket(TYPE, ID, sizeof(DATA), DATA); \
|
||||
_serial_gps->write(UBXscratch, msglen); \
|
||||
if (getACK(TYPE, ID, TIMEOUT) != GNSS_RESPONSE_OK) { \
|
||||
LOG_WARN(failMessage, #ERRMSG); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// Power Management
|
||||
|
||||
uint8_t GPS::_message_PMREQ[] PROGMEM = {
|
||||
static uint8_t _message_PMREQ[] PROGMEM = {
|
||||
0x00, 0x00, 0x00, 0x00, // 4 bytes duration of request task (milliseconds)
|
||||
0x02, 0x00, 0x00, 0x00 // Bitfield, set backup = 1
|
||||
};
|
||||
|
||||
uint8_t GPS::_message_PMREQ_10[] PROGMEM = {
|
||||
static uint8_t _message_PMREQ_10[] PROGMEM = {
|
||||
0x00, // version (0 for this version)
|
||||
0x00, 0x00, 0x00, // Reserved 1
|
||||
0x00, 0x00, 0x00, 0x00, // 4 bytes duration of request task (milliseconds)
|
||||
@@ -22,18 +24,18 @@ uint8_t GPS::_message_PMREQ_10[] PROGMEM = {
|
||||
0x08, 0x00, 0x00, 0x00 // wakeupSources Wake on uartrx
|
||||
};
|
||||
|
||||
const uint8_t GPS::_message_CFG_RXM_PSM[] PROGMEM = {
|
||||
static const uint8_t _message_CFG_RXM_PSM[] PROGMEM = {
|
||||
0x08, // Reserved
|
||||
0x01 // Power save mode
|
||||
};
|
||||
|
||||
// only for Neo-6
|
||||
const uint8_t GPS::_message_CFG_RXM_ECO[] PROGMEM = {
|
||||
static const uint8_t _message_CFG_RXM_ECO[] PROGMEM = {
|
||||
0x08, // Reserved
|
||||
0x04 // eco mode
|
||||
};
|
||||
|
||||
const uint8_t GPS::_message_CFG_PM2[] PROGMEM = {
|
||||
static const uint8_t _message_CFG_PM2[] PROGMEM = {
|
||||
0x01, // version
|
||||
0x00, // Reserved 1, set to 0x06 by u-Center
|
||||
0x00, // Reserved 2
|
||||
@@ -58,7 +60,7 @@ const uint8_t GPS::_message_CFG_PM2[] PROGMEM = {
|
||||
// Constallation setup, none required for Neo-6
|
||||
|
||||
// For Neo-7 GPS & SBAS
|
||||
const uint8_t GPS::_message_GNSS_7[] = {
|
||||
static const uint8_t _message_GNSS_7[] = {
|
||||
0x00, // msgVer (0 for this version)
|
||||
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
|
||||
0xff, // numTrkChUse (max number of channels to use, 0xff = max available)
|
||||
@@ -76,7 +78,7 @@ const uint8_t GPS::_message_GNSS_7[] = {
|
||||
// There is also a possibility that the module may be GPS-only.
|
||||
|
||||
// For M8 GPS, GLONASS, Galileo, SBAS, QZSS
|
||||
const uint8_t GPS::_message_GNSS_8[] = {
|
||||
static const uint8_t _message_GNSS_8[] = {
|
||||
0x00, // msgVer (0 for this version)
|
||||
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
|
||||
0xff, // numTrkChUse (max number of channels to use, 0xff = max available)
|
||||
@@ -90,7 +92,7 @@ const uint8_t GPS::_message_GNSS_8[] = {
|
||||
};
|
||||
/*
|
||||
// For M8 GPS, GLONASS, BeiDou, SBAS, QZSS
|
||||
const uint8_t GPS::_message_GNSS_8_B[] = {
|
||||
static const uint8_t _message_GNSS_8_B[] = {
|
||||
0x00, // msgVer (0 for this version)
|
||||
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
|
||||
0xff, // numTrkChUse (max number of channels to use, 0xff = max available) read only for protocol >23
|
||||
@@ -105,7 +107,7 @@ const uint8_t GPS::_message_GNSS_8_B[] = {
|
||||
*/
|
||||
|
||||
// For M8 we want to enable NMEA version 4.10 messages to allow for Galileo and or BeiDou
|
||||
const uint8_t GPS::_message_NMEA[]{
|
||||
static const uint8_t _message_NMEA[]{
|
||||
0x00, // filter flags
|
||||
0x41, // NMEA Version
|
||||
0x00, // Max number of SVs to report per TaklerId
|
||||
@@ -121,13 +123,13 @@ const uint8_t GPS::_message_NMEA[]{
|
||||
// Enable jamming/interference monitor
|
||||
|
||||
// For Neo-6, Max-7 and Neo-7
|
||||
const uint8_t GPS::_message_JAM_6_7[] = {
|
||||
static const uint8_t _message_JAM_6_7[] = {
|
||||
0xf3, 0xac, 0x62, 0xad, // config1 bbThreshold = 3, cwThreshold = 15, enable = 1, reserved bits 0x16B156
|
||||
0x1e, 0x03, 0x00, 0x00 // config2 antennaSetting Unknown = 0, reserved 3, = 0x00,0x00, reserved 2 = 0x31E
|
||||
};
|
||||
|
||||
// For M8
|
||||
const uint8_t GPS::_message_JAM_8[] = {
|
||||
static const uint8_t _message_JAM_8[] = {
|
||||
0xf3, 0xac, 0x62, 0xad, // config1 bbThreshold = 3, cwThreshold = 15, enable1 = 1, reserved bits 0x16B156
|
||||
0x1e, 0x43, 0x00, 0x00 // config2 antennaSetting Unknown = 0, enable2 = 1, generalBits = 0x31E
|
||||
};
|
||||
@@ -137,7 +139,7 @@ const uint8_t GPS::_message_JAM_8[] = {
|
||||
// ToDo: check UBX-MON-VER for module type and protocol version
|
||||
|
||||
// For the Neo-6
|
||||
const uint8_t GPS::_message_NAVX5[] = {
|
||||
static const uint8_t _message_NAVX5[] = {
|
||||
0x00, 0x00, // msgVer (0 for this version)
|
||||
0x4c, 0x66, // mask1
|
||||
0x00, 0x00, 0x00, 0x00, // Reserved 0
|
||||
@@ -166,7 +168,7 @@ const uint8_t GPS::_message_NAVX5[] = {
|
||||
0x00, 0x00, 0x00, 0x00 // Reserved 4
|
||||
};
|
||||
// For the M8
|
||||
const uint8_t GPS::_message_NAVX5_8[] = {
|
||||
static const uint8_t _message_NAVX5_8[] = {
|
||||
0x02, 0x00, // msgVer (2 for this version)
|
||||
0x4c, 0x66, // mask1
|
||||
0x00, 0x00, 0x00, 0x00, // mask2
|
||||
@@ -197,7 +199,7 @@ const uint8_t GPS::_message_NAVX5_8[] = {
|
||||
// Additionally, for some new modules like the M9/M10, an update rate lower than 5Hz
|
||||
// is recommended to avoid a known issue with satellites disappearing.
|
||||
// The module defaults for M8, M9, M10 are the same as we use here so no update is necessary
|
||||
const uint8_t GPS::_message_1HZ[] = {
|
||||
static const uint8_t _message_1HZ[] = {
|
||||
0xE8, 0x03, // Measurement Rate (1000ms for 1Hz)
|
||||
0x01, 0x00, // Navigation rate, always 1 in GPS mode
|
||||
0x01, 0x00 // Time reference
|
||||
@@ -205,7 +207,7 @@ const uint8_t GPS::_message_1HZ[] = {
|
||||
|
||||
// Disable GLL. GLL - Geographic position (latitude and longitude), which provides the current geographical
|
||||
// coordinates.
|
||||
const uint8_t GPS::_message_GLL[] = {
|
||||
static const uint8_t _message_GLL[] = {
|
||||
0xF0, 0x01, // NMEA ID for GLL
|
||||
0x00, // Rate for DDC
|
||||
0x00, // Rate for UART1
|
||||
@@ -217,7 +219,7 @@ const uint8_t GPS::_message_GLL[] = {
|
||||
|
||||
// Disable GSA. GSA - GPS DOP and active satellites, used for detailing the satellites used in the positioning and
|
||||
// the DOP (Dilution of Precision)
|
||||
const uint8_t GPS::_message_GSA[] = {
|
||||
static const uint8_t _message_GSA[] = {
|
||||
0xF0, 0x02, // NMEA ID for GSA
|
||||
0x00, // Rate for DDC
|
||||
0x00, // Rate for UART1
|
||||
@@ -228,7 +230,7 @@ const uint8_t GPS::_message_GSA[] = {
|
||||
};
|
||||
|
||||
// Disable GSV. GSV - Satellites in view, details the number and location of satellites in view.
|
||||
const uint8_t GPS::_message_GSV[] = {
|
||||
static const uint8_t _message_GSV[] = {
|
||||
0xF0, 0x03, // NMEA ID for GSV
|
||||
0x00, // Rate for DDC
|
||||
0x00, // Rate for UART1
|
||||
@@ -240,7 +242,7 @@ const uint8_t GPS::_message_GSV[] = {
|
||||
|
||||
// Disable VTG. VTG - Track made good and ground speed, which provides course and speed information relative to
|
||||
// the ground.
|
||||
const uint8_t GPS::_message_VTG[] = {
|
||||
static const uint8_t _message_VTG[] = {
|
||||
0xF0, 0x05, // NMEA ID for VTG
|
||||
0x00, // Rate for DDC
|
||||
0x00, // Rate for UART1
|
||||
@@ -251,7 +253,7 @@ const uint8_t GPS::_message_VTG[] = {
|
||||
};
|
||||
|
||||
// Enable RMC. RMC - Recommended Minimum data, the essential gps pvt (position, velocity, time) data.
|
||||
const uint8_t GPS::_message_RMC[] = {
|
||||
static const uint8_t _message_RMC[] = {
|
||||
0xF0, 0x04, // NMEA ID for RMC
|
||||
0x00, // Rate for DDC
|
||||
0x01, // Rate for UART1
|
||||
@@ -262,7 +264,7 @@ const uint8_t GPS::_message_RMC[] = {
|
||||
};
|
||||
|
||||
// Enable GGA. GGA - Global Positioning System Fix Data, which provides 3D location and accuracy data.
|
||||
const uint8_t GPS::_message_GGA[] = {
|
||||
static const uint8_t _message_GGA[] = {
|
||||
0xF0, 0x00, // NMEA ID for GGA
|
||||
0x00, // Rate for DDC
|
||||
0x01, // Rate for UART1
|
||||
@@ -274,7 +276,7 @@ const uint8_t GPS::_message_GGA[] = {
|
||||
|
||||
// Disable UBX-AID-ALPSRV as it may confuse TinyGPS. The Neo-6 seems to send this message
|
||||
// whether the AID Autonomous is enabled or not
|
||||
const uint8_t GPS::_message_AID[] = {
|
||||
static const uint8_t _message_AID[] = {
|
||||
0x0B, 0x32, // NMEA ID for UBX-AID-ALPSRV
|
||||
0x00, // Rate for DDC
|
||||
0x00, // Rate for UART1
|
||||
@@ -287,7 +289,7 @@ const uint8_t GPS::_message_AID[] = {
|
||||
// Turn off TEXT INFO Messages for all but M10 series
|
||||
|
||||
// B5 62 06 02 0A 00 01 00 00 00 03 03 00 03 03 00 1F 20
|
||||
const uint8_t GPS::_message_DISABLE_TXT_INFO[] = {
|
||||
static const uint8_t _message_DISABLE_TXT_INFO[] = {
|
||||
0x01, // Protocol ID for NMEA
|
||||
0x00, 0x00, 0x00, // Reserved
|
||||
0x03, // I2C
|
||||
@@ -310,7 +312,7 @@ const uint8_t GPS::_message_DISABLE_TXT_INFO[] = {
|
||||
// and must be smaller than the period. It is only valid when the powerSetupValue is set to Interval; otherwise,
|
||||
// it must be set to '0'.
|
||||
// This command applies to M8 products
|
||||
const uint8_t GPS::_message_PMS[] = {
|
||||
static const uint8_t _message_PMS[] = {
|
||||
0x00, // Version (0)
|
||||
0x03, // Power setup value 3 = Agresssive 1Hz
|
||||
0x00, 0x00, // period: not applicable, set to 0
|
||||
@@ -318,14 +320,14 @@ const uint8_t GPS::_message_PMS[] = {
|
||||
0x00, 0x00 // reserved, generated by u-center
|
||||
};
|
||||
|
||||
const uint8_t GPS::_message_SAVE[] = {
|
||||
static const uint8_t _message_SAVE[] = {
|
||||
0x00, 0x00, 0x00, 0x00, // clearMask: no sections cleared
|
||||
0xFF, 0xFF, 0x00, 0x00, // saveMask: save all sections
|
||||
0x00, 0x00, 0x00, 0x00, // loadMask: no sections loaded
|
||||
0x17 // deviceMask: BBR, Flash, EEPROM, and SPI Flash
|
||||
};
|
||||
|
||||
const uint8_t GPS::_message_SAVE_10[] = {
|
||||
static const uint8_t _message_SAVE_10[] = {
|
||||
0x00, 0x00, 0x00, 0x00, // clearMask: no sections cleared
|
||||
0xFF, 0xFF, 0x00, 0x00, // saveMask: save all sections
|
||||
0x00, 0x00, 0x00, 0x00, // loadMask: no sections loaded
|
||||
@@ -375,12 +377,12 @@ LIMITPEAKCURRENT L 1
|
||||
// b5 62 06 8a 26 00 00 02 00 00 01 00 d0 20 02 02 00 d0 40 05 00 00 00 05 00 d0 30 01 00 08 00 d0 10 01 09 00 d0 10 01 10 00 d0
|
||||
// 10 01 8c 03
|
||||
*/
|
||||
const uint8_t GPS::_message_VALSET_PM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40,
|
||||
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0,
|
||||
0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01};
|
||||
const uint8_t GPS::_message_VALSET_PM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40,
|
||||
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0,
|
||||
0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01};
|
||||
static const uint8_t _message_VALSET_PM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40,
|
||||
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0,
|
||||
0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01};
|
||||
static const uint8_t _message_VALSET_PM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40,
|
||||
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0,
|
||||
0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01};
|
||||
|
||||
/*
|
||||
CFG-ITFM replaced by 5 valset messages which can be combined into one for RAM and one for BBR
|
||||
@@ -394,10 +396,10 @@ CFG-ITFM replaced by 5 valset messages which can be combined into one for RAM an
|
||||
|
||||
b5 62 06 8a 0e 00 00 01 00 00 0d 00 41 10 01 13 00 41 10 01 63 c6
|
||||
*/
|
||||
const uint8_t GPS::_message_VALSET_ITFM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x41,
|
||||
0x10, 0x01, 0x13, 0x00, 0x41, 0x10, 0x01};
|
||||
const uint8_t GPS::_message_VALSET_ITFM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x0d, 0x00, 0x41,
|
||||
0x10, 0x01, 0x13, 0x00, 0x41, 0x10, 0x01};
|
||||
static const uint8_t _message_VALSET_ITFM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x41,
|
||||
0x10, 0x01, 0x13, 0x00, 0x41, 0x10, 0x01};
|
||||
static const uint8_t _message_VALSET_ITFM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x0d, 0x00, 0x41,
|
||||
0x10, 0x01, 0x13, 0x00, 0x41, 0x10, 0x01};
|
||||
|
||||
// Turn off all NMEA messages:
|
||||
// Ram layer config message:
|
||||
@@ -407,13 +409,13 @@ const uint8_t GPS::_message_VALSET_ITFM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x0d, 0
|
||||
// BBR layer config message:
|
||||
// b5 62 06 8a 13 00 00 02 00 00 ca 00 91 20 00 c5 00 91 20 00 b1 00 91 20 00 f8 4e
|
||||
|
||||
const uint8_t GPS::_message_VALSET_DISABLE_NMEA_RAM[] = {
|
||||
static const uint8_t _message_VALSET_DISABLE_NMEA_RAM[] = {
|
||||
/*0x00, 0x01, 0x00, 0x00, 0xca, 0x00, 0x91, 0x20, 0x00, 0xc5, 0x00, 0x91, 0x20, 0x00, 0xb1, 0x00, 0x91, 0x20, 0x00 */
|
||||
0x00, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x91, 0x20, 0x00, 0xca, 0x00, 0x91, 0x20, 0x00, 0xc5, 0x00, 0x91,
|
||||
0x20, 0x00, 0xac, 0x00, 0x91, 0x20, 0x00, 0xb1, 0x00, 0x91, 0x20, 0x00, 0xbb, 0x00, 0x91, 0x20, 0x00};
|
||||
|
||||
const uint8_t GPS::_message_VALSET_DISABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00, 0xca, 0x00, 0x91, 0x20, 0x00, 0xc5,
|
||||
0x00, 0x91, 0x20, 0x00, 0xb1, 0x00, 0x91, 0x20, 0x00};
|
||||
static const uint8_t _message_VALSET_DISABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00, 0xca, 0x00, 0x91, 0x20, 0x00, 0xc5,
|
||||
0x00, 0x91, 0x20, 0x00, 0xb1, 0x00, 0x91, 0x20, 0x00};
|
||||
|
||||
// Turn off text info messages:
|
||||
// Ram layer config message:
|
||||
@@ -432,17 +434,17 @@ const uint8_t GPS::_message_VALSET_DISABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00,
|
||||
// b5 62 06 8a 0e 00 00 04 00 00 bb 00 91 20 01 ac 00 91 20 01 6d b6
|
||||
// Doing this for the FLASH layer isn't really required since we save the config to flash later
|
||||
|
||||
const uint8_t GPS::_message_VALSET_DISABLE_TXT_INFO_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x07, 0x00, 0x92, 0x20, 0x03};
|
||||
const uint8_t GPS::_message_VALSET_DISABLE_TXT_INFO_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x07, 0x00, 0x92, 0x20, 0x03};
|
||||
static const uint8_t _message_VALSET_DISABLE_TXT_INFO_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x07, 0x00, 0x92, 0x20, 0x03};
|
||||
static const uint8_t _message_VALSET_DISABLE_TXT_INFO_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x07, 0x00, 0x92, 0x20, 0x03};
|
||||
|
||||
const uint8_t GPS::_message_VALSET_ENABLE_NMEA_RAM[] = {0x00, 0x01, 0x00, 0x00, 0xbb, 0x00, 0x91,
|
||||
0x20, 0x01, 0xac, 0x00, 0x91, 0x20, 0x01};
|
||||
const uint8_t GPS::_message_VALSET_ENABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00, 0xbb, 0x00, 0x91,
|
||||
0x20, 0x01, 0xac, 0x00, 0x91, 0x20, 0x01};
|
||||
const uint8_t GPS::_message_VALSET_DISABLE_SBAS_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x31,
|
||||
0x10, 0x00, 0x05, 0x00, 0x31, 0x10, 0x00};
|
||||
const uint8_t GPS::_message_VALSET_DISABLE_SBAS_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x31,
|
||||
0x10, 0x00, 0x05, 0x00, 0x31, 0x10, 0x00};
|
||||
static const uint8_t _message_VALSET_ENABLE_NMEA_RAM[] = {0x00, 0x01, 0x00, 0x00, 0xbb, 0x00, 0x91,
|
||||
0x20, 0x01, 0xac, 0x00, 0x91, 0x20, 0x01};
|
||||
static const uint8_t _message_VALSET_ENABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00, 0xbb, 0x00, 0x91,
|
||||
0x20, 0x01, 0xac, 0x00, 0x91, 0x20, 0x01};
|
||||
static const uint8_t _message_VALSET_DISABLE_SBAS_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x31,
|
||||
0x10, 0x00, 0x05, 0x00, 0x31, 0x10, 0x00};
|
||||
static const uint8_t _message_VALSET_DISABLE_SBAS_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x31,
|
||||
0x10, 0x00, 0x05, 0x00, 0x31, 0x10, 0x00};
|
||||
|
||||
/*
|
||||
Operational issues with the M10:
|
||||
@@ -475,4 +477,4 @@ b5 62 06 8a 0e 00 00 01 00 00 20 00 31 10 00 05 00 31 10 00 46 87
|
||||
|
||||
BBR layer config message:
|
||||
b5 62 06 8a 0e 00 00 02 00 00 20 00 31 10 00 05 00 31 10 00 47 94
|
||||
*/
|
||||
*/
|
||||
|
||||
+47
-38
@@ -20,7 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
#include "Screen.h"
|
||||
#include "../userPrefs.h"
|
||||
#include "PowerMon.h"
|
||||
#include "Throttle.h"
|
||||
#include "configuration.h"
|
||||
@@ -101,9 +100,9 @@ std::vector<MeshModule *> moduleFrames;
|
||||
static char ourId[5];
|
||||
|
||||
// vector where symbols (string) are displayed in bottom corner of display.
|
||||
std::vector<std::string> functionSymbals;
|
||||
// string displayed in bottom right corner of display. Created from elements in functionSymbals vector
|
||||
std::string functionSymbalString = "";
|
||||
std::vector<std::string> functionSymbol;
|
||||
// string displayed in bottom right corner of display. Created from elements in functionSymbol vector
|
||||
std::string functionSymbolString = "";
|
||||
|
||||
#if HAS_GPS
|
||||
// GeoCoord object for the screen
|
||||
@@ -243,10 +242,10 @@ static void drawWelcomeScreen(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
static void drawFunctionOverlay(OLEDDisplay *display, OLEDDisplayUiState *state)
|
||||
{
|
||||
// LOG_DEBUG("Draw function overlay");
|
||||
if (functionSymbals.begin() != functionSymbals.end()) {
|
||||
if (functionSymbol.begin() != functionSymbol.end()) {
|
||||
char buf[64];
|
||||
display->setFont(FONT_SMALL);
|
||||
snprintf(buf, sizeof(buf), "%s", functionSymbalString.c_str());
|
||||
snprintf(buf, sizeof(buf), "%s", functionSymbolString.c_str());
|
||||
display->drawString(SCREEN_WIDTH - display->getStringWidth(buf), SCREEN_HEIGHT - FONT_HEIGHT_SMALL, buf);
|
||||
}
|
||||
}
|
||||
@@ -396,7 +395,7 @@ static void drawBattery(OLEDDisplay *display, int16_t x, int16_t y, uint8_t *img
|
||||
display->drawFastImage(x, y, 16, 8, imgBuffer);
|
||||
}
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(DISPLAY_CLOCK_FRAME)
|
||||
|
||||
void Screen::drawWatchFaceToggleButton(OLEDDisplay *display, int16_t x, int16_t y, bool digitalMode, float scale)
|
||||
{
|
||||
@@ -958,55 +957,65 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
|
||||
|
||||
display->setColor(WHITE);
|
||||
#ifndef EXCLUDE_EMOJI
|
||||
if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F44D") == 0) {
|
||||
const char *msg = reinterpret_cast<const char *>(mp.decoded.payload.bytes);
|
||||
if (strcmp(msg, "\U0001F44D") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - thumbs_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - thumbs_height) / 2 + 2 + 5, thumbs_width, thumbs_height,
|
||||
thumbup);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F44E") == 0) {
|
||||
} else if (strcmp(msg, "\U0001F44E") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - thumbs_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - thumbs_height) / 2 + 2 + 5, thumbs_width, thumbs_height,
|
||||
thumbdown);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "❓") == 0) {
|
||||
} else if (strcmp(msg, "\U0001F60A") == 0 || strcmp(msg, "\U0001F600") == 0 || strcmp(msg, "\U0001F642") == 0 ||
|
||||
strcmp(msg, "\U0001F609") == 0 ||
|
||||
strcmp(msg, "\U0001F601") == 0) { // matches 5 different common smileys, so that the phone user doesn't have to
|
||||
// remember which one is compatible
|
||||
display->drawXbm(x + (SCREEN_WIDTH - smiley_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - smiley_height) / 2 + 2 + 5, smiley_width, smiley_height,
|
||||
smiley);
|
||||
} else if (strcmp(msg, "❓") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - question_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - question_height) / 2 + 2 + 5, question_width, question_height,
|
||||
question);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "‼️") == 0) {
|
||||
} else if (strcmp(msg, "‼️") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - bang_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - bang_height) / 2 + 2 + 5,
|
||||
bang_width, bang_height, bang);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F4A9") == 0) {
|
||||
} else if (strcmp(msg, "\U0001F4A9") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - poo_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - poo_height) / 2 + 2 + 5,
|
||||
poo_width, poo_height, poo);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\xf0\x9f\xa4\xa3") == 0) {
|
||||
} else if (strcmp(msg, "\U0001F923") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - haha_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - haha_height) / 2 + 2 + 5,
|
||||
haha_width, haha_height, haha);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F44B") == 0) {
|
||||
} else if (strcmp(msg, "\U0001F44B") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - wave_icon_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - wave_icon_height) / 2 + 2 + 5, wave_icon_width,
|
||||
wave_icon_height, wave_icon);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F920") == 0) {
|
||||
} else if (strcmp(msg, "\U0001F920") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - cowboy_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - cowboy_height) / 2 + 2 + 5, cowboy_width, cowboy_height,
|
||||
cowboy);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F42D") == 0) {
|
||||
} else if (strcmp(msg, "\U0001F42D") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - deadmau5_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - deadmau5_height) / 2 + 2 + 5, deadmau5_width, deadmau5_height,
|
||||
deadmau5);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\xE2\x98\x80\xEF\xB8\x8F") == 0) {
|
||||
} else if (strcmp(msg, "\xE2\x98\x80\xEF\xB8\x8F") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - sun_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - sun_height) / 2 + 2 + 5,
|
||||
sun_width, sun_height, sun);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\u2614") == 0) {
|
||||
} else if (strcmp(msg, "\u2614") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - rain_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - rain_height) / 2 + 2 + 10,
|
||||
rain_width, rain_height, rain);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "☁️") == 0) {
|
||||
} else if (strcmp(msg, "☁️") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - cloud_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - cloud_height) / 2 + 2 + 5, cloud_width, cloud_height, cloud);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "🌫️") == 0) {
|
||||
} else if (strcmp(msg, "🌫️") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - fog_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - fog_height) / 2 + 2 + 5,
|
||||
fog_width, fog_height, fog);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\xf0\x9f\x98\x88") == 0) {
|
||||
} else if (strcmp(msg, "\U0001F608") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - devil_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - devil_height) / 2 + 2 + 5, devil_width, devil_height, devil);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "♥️") == 0) {
|
||||
} else if (strcmp(msg, "♥️") == 0 || strcmp(msg, "\U0001F9E1") == 0 || strcmp(msg, "\U00002763") == 0 ||
|
||||
strcmp(msg, "\U00002764") == 0 || strcmp(msg, "\U0001F495") == 0 || strcmp(msg, "\U0001F496") == 0 ||
|
||||
strcmp(msg, "\U0001F497") == 0 || strcmp(msg, "\U0001F496") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - heart_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - heart_height) / 2 + 2 + 5, heart_width, heart_height, heart);
|
||||
} else {
|
||||
@@ -1410,7 +1419,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
}
|
||||
bool hasNodeHeading = false;
|
||||
|
||||
if (ourNode && (hasValidPosition(ourNode) || screen->hasHeading())) {
|
||||
if (ourNode && (nodeDB->hasValidPosition(ourNode) || screen->hasHeading())) {
|
||||
const meshtastic_PositionLite &op = ourNode->position;
|
||||
float myHeading;
|
||||
if (screen->hasHeading())
|
||||
@@ -1419,7 +1428,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
myHeading = screen->estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i));
|
||||
screen->drawCompassNorth(display, compassX, compassY, myHeading);
|
||||
|
||||
if (hasValidPosition(node)) {
|
||||
if (nodeDB->hasValidPosition(node)) {
|
||||
// display direction toward node
|
||||
hasNodeHeading = true;
|
||||
const meshtastic_PositionLite &p = node->position;
|
||||
@@ -2058,7 +2067,7 @@ void Screen::setFrames(FrameFocus focus)
|
||||
focus = FOCUS_FAULT; // Change our "focus" parameter, to ensure we show the fault frame
|
||||
}
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(DISPLAY_CLOCK_FRAME)
|
||||
normalFrames[numframes++] = screen->digitalWatchFace ? &Screen::drawDigitalClockFrame : &Screen::drawAnalogClockFrame;
|
||||
#endif
|
||||
|
||||
@@ -2242,24 +2251,24 @@ void Screen::decreaseBrightness()
|
||||
/* TO DO: add little popup in center of screen saying what brightness level it is set to*/
|
||||
}
|
||||
|
||||
void Screen::setFunctionSymbal(std::string sym)
|
||||
void Screen::setFunctionSymbol(std::string sym)
|
||||
{
|
||||
if (std::find(functionSymbals.begin(), functionSymbals.end(), sym) == functionSymbals.end()) {
|
||||
functionSymbals.push_back(sym);
|
||||
functionSymbalString = "";
|
||||
for (auto symbol : functionSymbals) {
|
||||
functionSymbalString = symbol + " " + functionSymbalString;
|
||||
if (std::find(functionSymbol.begin(), functionSymbol.end(), sym) == functionSymbol.end()) {
|
||||
functionSymbol.push_back(sym);
|
||||
functionSymbolString = "";
|
||||
for (auto symbol : functionSymbol) {
|
||||
functionSymbolString = symbol + " " + functionSymbolString;
|
||||
}
|
||||
setFastFramerate();
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::removeFunctionSymbal(std::string sym)
|
||||
void Screen::removeFunctionSymbol(std::string sym)
|
||||
{
|
||||
functionSymbals.erase(std::remove(functionSymbals.begin(), functionSymbals.end(), sym), functionSymbals.end());
|
||||
functionSymbalString = "";
|
||||
for (auto symbol : functionSymbals) {
|
||||
functionSymbalString = symbol + " " + functionSymbalString;
|
||||
functionSymbol.erase(std::remove(functionSymbol.begin(), functionSymbol.end(), sym), functionSymbol.end());
|
||||
functionSymbolString = "";
|
||||
for (auto symbol : functionSymbol) {
|
||||
functionSymbolString = symbol + " " + functionSymbolString;
|
||||
}
|
||||
setFastFramerate();
|
||||
}
|
||||
@@ -2689,7 +2698,7 @@ int Screen::handleUIFrameEvent(const UIFrameEvent *event)
|
||||
int Screen::handleInputEvent(const InputEvent *event)
|
||||
{
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(DISPLAY_CLOCK_FRAME)
|
||||
// For the T-Watch, intercept touches to the 'toggle digital/analog watch face' button
|
||||
uint8_t watchFaceFrame = error_code ? 1 : 0;
|
||||
|
||||
@@ -2747,4 +2756,4 @@ int Screen::handleAdminMessage(const meshtastic_AdminMessage *arg)
|
||||
} // namespace graphics
|
||||
#else
|
||||
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
|
||||
#endif // HAS_SCREEN
|
||||
#endif // HAS_SCREEN
|
||||
|
||||
@@ -24,8 +24,8 @@ class Screen
|
||||
void startFirmwareUpdateScreen() {}
|
||||
void increaseBrightness() {}
|
||||
void decreaseBrightness() {}
|
||||
void setFunctionSymbal(std::string) {}
|
||||
void removeFunctionSymbal(std::string) {}
|
||||
void setFunctionSymbol(std::string) {}
|
||||
void removeFunctionSymbol(std::string) {}
|
||||
void startAlert(const char *) {}
|
||||
void endAlert() {}
|
||||
};
|
||||
@@ -282,8 +282,8 @@ class Screen : public concurrency::OSThread
|
||||
void increaseBrightness();
|
||||
void decreaseBrightness();
|
||||
|
||||
void setFunctionSymbal(std::string sym);
|
||||
void removeFunctionSymbal(std::string sym);
|
||||
void setFunctionSymbol(std::string sym);
|
||||
void removeFunctionSymbol(std::string sym);
|
||||
|
||||
/// Stops showing the boot screen.
|
||||
void stopBootScreen() { enqueueCmd(ScreenCmd{.cmd = Cmd::STOP_BOOT_SCREEN}); }
|
||||
@@ -554,7 +554,7 @@ class Screen : public concurrency::OSThread
|
||||
|
||||
static void drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(DISPLAY_CLOCK_FRAME)
|
||||
static void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
|
||||
static void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
|
||||
@@ -27,14 +27,22 @@
|
||||
#define FONT_SMALL ArialMT_Plain_10_RU
|
||||
#else
|
||||
#ifdef OLED_UA
|
||||
#define FONT_SMALL ArialMT_Plain_10_UA
|
||||
#define FONT_SMALL ArialMT_Plain_10_UA // Height: 13
|
||||
#else
|
||||
#define FONT_SMALL ArialMT_Plain_10 // Height: 13
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#ifdef OLED_UA
|
||||
#define FONT_MEDIUM ArialMT_Plain_16_UA // Height: 19
|
||||
#else
|
||||
#define FONT_MEDIUM ArialMT_Plain_16 // Height: 19
|
||||
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
|
||||
#endif
|
||||
#ifdef OLED_UA
|
||||
#define FONT_LARGE ArialMT_Plain_24_UA // Height: 28
|
||||
#else
|
||||
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define _fontHeight(font) ((font)[1] + 1) // height is position 1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,4 +8,6 @@
|
||||
#endif
|
||||
|
||||
extern const uint8_t ArialMT_Plain_10_UA[] PROGMEM;
|
||||
extern const uint8_t ArialMT_Plain_16_UA[] PROGMEM;
|
||||
extern const uint8_t ArialMT_Plain_24_UA[] PROGMEM;
|
||||
#endif
|
||||
+11
-1
@@ -14,7 +14,7 @@ const uint8_t imgUser[] PROGMEM = {0x3C, 0x42, 0x99, 0xA5, 0xA5, 0x99, 0x42, 0x3
|
||||
const uint8_t imgPositionEmpty[] PROGMEM = {0x20, 0x30, 0x28, 0x24, 0x42, 0xFF};
|
||||
const uint8_t imgPositionSolid[] PROGMEM = {0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF};
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(DISPLAY_CLOCK_FRAME)
|
||||
const uint8_t bluetoothConnectedIcon[36] PROGMEM = {0xfe, 0x01, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0xe3, 0x1f,
|
||||
0xf3, 0x3f, 0x33, 0x30, 0x33, 0x33, 0x33, 0x33, 0x03, 0x33, 0xff, 0x33,
|
||||
0xfe, 0x31, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0x3f, 0xe0, 0x1f};
|
||||
@@ -56,6 +56,16 @@ static unsigned char thumbdown[] PROGMEM = {
|
||||
0x80, 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00,
|
||||
};
|
||||
|
||||
#define smiley_height 30
|
||||
#define smiley_width 30
|
||||
static unsigned char smiley[] PROGMEM = {
|
||||
0x00, 0xfe, 0x0f, 0x00, 0x80, 0x01, 0x30, 0x00, 0x40, 0x00, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x02,
|
||||
0x08, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x10, 0x02, 0x0e, 0x0e, 0x10, 0x02, 0x09, 0x12, 0x10,
|
||||
0x01, 0x09, 0x12, 0x20, 0x01, 0x0f, 0x1e, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20,
|
||||
0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x81, 0x00, 0x20, 0x20,
|
||||
0x82, 0x00, 0x20, 0x10, 0x02, 0x01, 0x10, 0x10, 0x04, 0x02, 0x08, 0x08, 0x04, 0xfc, 0x07, 0x08, 0x08, 0x00, 0x00, 0x04,
|
||||
0x10, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x01, 0x40, 0x00, 0xc0, 0x00, 0x80, 0x01, 0x30, 0x00, 0x00, 0xfe, 0x0f, 0x00};
|
||||
|
||||
#define question_height 25
|
||||
#define question_width 25
|
||||
static unsigned char question[] PROGMEM = {
|
||||
|
||||
@@ -49,10 +49,11 @@ void CardKbI2cImpl::init()
|
||||
kb_model = 0x00;
|
||||
}
|
||||
}
|
||||
LOG_DEBUG("Keyboard Type: 0x%02x Model: 0x%02x Address: 0x%02x", kb_info.type, kb_model, cardkb_found.address);
|
||||
if (cardkb_found.address == 0x00) {
|
||||
disable();
|
||||
return;
|
||||
} else {
|
||||
LOG_DEBUG("Keyboard Type: 0x%02x Model: 0x%02x Address: 0x%02x", kb_info.type, kb_model, cardkb_found.address);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
+92
-50
@@ -1,4 +1,3 @@
|
||||
#include "../userPrefs.h"
|
||||
#include "configuration.h"
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
#include "GPS.h"
|
||||
@@ -83,7 +82,7 @@ NRF52Bluetooth *nrf52Bluetooth = nullptr;
|
||||
#include "STM32WLE5JCInterface.h"
|
||||
#endif
|
||||
|
||||
#if !HAS_RADIO && defined(ARCH_PORTDUINO)
|
||||
#if defined(ARCH_PORTDUINO)
|
||||
#include "platform/portduino/SimRadio.h"
|
||||
#endif
|
||||
|
||||
@@ -150,10 +149,6 @@ ScanI2C::DeviceAddress accelerometer_found = ScanI2C::ADDRESS_NONE;
|
||||
// The I2C address of the RGB LED (if found)
|
||||
ScanI2C::FoundDevice rgb_found = ScanI2C::FoundDevice(ScanI2C::DeviceType::NONE, ScanI2C::ADDRESS_NONE);
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
ATECCX08A atecc;
|
||||
#endif
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
Adafruit_DRV2605 drv;
|
||||
#endif
|
||||
@@ -572,48 +567,37 @@ void setup()
|
||||
LOG_DEBUG("acc_info = %i", 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].first = found.address.address; \
|
||||
nodeTelemetrySensorsMap[PB_T].second = i2cScanner->fetchI2CBus(found.address); \
|
||||
LOG_DEBUG("found i2c sensor %s", 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::BMP_3XX, meshtastic_TelemetrySensorType_BMP3XX)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BMP_085, meshtastic_TelemetrySensorType_BMP085)
|
||||
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::INA3221, meshtastic_TelemetrySensorType_INA3221)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MAX17048, meshtastic_TelemetrySensorType_MAX17048)
|
||||
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::HMC5883L, meshtastic_TelemetrySensorType_QMC5883L)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::PMSA0031, meshtastic_TelemetrySensorType_PMSA003I)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::RCWL9620, meshtastic_TelemetrySensorType_RCWL9620)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::VEML7700, meshtastic_TelemetrySensorType_VEML7700)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::TSL2591, meshtastic_TelemetrySensorType_TSL25911FN)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::OPT3001, meshtastic_TelemetrySensorType_OPT3001)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MLX90632, meshtastic_TelemetrySensorType_MLX90632)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MLX90614, meshtastic_TelemetrySensorType_MLX90614)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHT4X, meshtastic_TelemetrySensorType_SHT4X)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::AHT10, meshtastic_TelemetrySensorType_AHT10)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::DFROBOT_LARK, meshtastic_TelemetrySensorType_DFROBOT_LARK)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::ICM20948, meshtastic_TelemetrySensorType_ICM20948)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MAX30102, meshtastic_TelemetrySensorType_MAX30102)
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::BME_680, meshtastic_TelemetrySensorType_BME680);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::BME_280, meshtastic_TelemetrySensorType_BME280);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::BMP_280, meshtastic_TelemetrySensorType_BMP280);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::BMP_3XX, meshtastic_TelemetrySensorType_BMP3XX);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::BMP_085, meshtastic_TelemetrySensorType_BMP085);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::INA260, meshtastic_TelemetrySensorType_INA260);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::INA219, meshtastic_TelemetrySensorType_INA219);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::INA3221, meshtastic_TelemetrySensorType_INA3221);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MAX17048, meshtastic_TelemetrySensorType_MAX17048);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::SHT31, meshtastic_TelemetrySensorType_SHT31);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::SHTC3, meshtastic_TelemetrySensorType_SHTC3);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::LPS22HB, meshtastic_TelemetrySensorType_LPS22);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::QMC6310, meshtastic_TelemetrySensorType_QMC6310);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::QMI8658, meshtastic_TelemetrySensorType_QMI8658);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::QMC5883L, meshtastic_TelemetrySensorType_QMC5883L);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::HMC5883L, meshtastic_TelemetrySensorType_QMC5883L);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::PMSA0031, meshtastic_TelemetrySensorType_PMSA003I);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::RCWL9620, meshtastic_TelemetrySensorType_RCWL9620);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::VEML7700, meshtastic_TelemetrySensorType_VEML7700);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::TSL2591, meshtastic_TelemetrySensorType_TSL25911FN);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::OPT3001, meshtastic_TelemetrySensorType_OPT3001);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MLX90632, meshtastic_TelemetrySensorType_MLX90632);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MLX90614, meshtastic_TelemetrySensorType_MLX90614);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::SHT4X, meshtastic_TelemetrySensorType_SHT4X);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::AHT10, meshtastic_TelemetrySensorType_AHT10);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::DFROBOT_LARK, meshtastic_TelemetrySensorType_DFROBOT_LARK);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::ICM20948, meshtastic_TelemetrySensorType_ICM20948);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MAX30102, meshtastic_TelemetrySensorType_MAX30102);
|
||||
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::CGRADSENS, meshtastic_TelemetrySensorType_RADSENS);
|
||||
|
||||
i2cScanner.reset();
|
||||
#endif
|
||||
@@ -874,6 +858,51 @@ void setup()
|
||||
LOG_INFO("SX1280 init success");
|
||||
}
|
||||
}
|
||||
} else if (settingsMap[use_lr1110]) {
|
||||
if (!rIf) {
|
||||
LOG_DEBUG("Activate lr1110 radio on SPI port %s", settingsStrings[spidev].c_str());
|
||||
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
||||
rIf = new LR1110Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
|
||||
settingsMap[busy]);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("No LR1110 radio");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
LOG_INFO("LR1110 init success");
|
||||
}
|
||||
}
|
||||
} else if (settingsMap[use_lr1120]) {
|
||||
if (!rIf) {
|
||||
LOG_DEBUG("Activate lr1120 radio on SPI port %s", settingsStrings[spidev].c_str());
|
||||
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
||||
rIf = new LR1120Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
|
||||
settingsMap[busy]);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("No LR1120 radio");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
LOG_INFO("LR1120 init success");
|
||||
}
|
||||
}
|
||||
} else if (settingsMap[use_lr1121]) {
|
||||
if (!rIf) {
|
||||
LOG_DEBUG("Activate lr1121 radio on SPI port %s", settingsStrings[spidev].c_str());
|
||||
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
||||
rIf = new LR1121Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
|
||||
settingsMap[busy]);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("No LR1121 radio");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
LOG_INFO("LR1121 init success");
|
||||
}
|
||||
}
|
||||
} else if (settingsMap[use_sx1268]) {
|
||||
if (!rIf) {
|
||||
LOG_DEBUG("Activate sx1268 radio on SPI port %s", settingsStrings[spidev].c_str());
|
||||
@@ -912,7 +941,7 @@ void setup()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !HAS_RADIO && defined(ARCH_PORTDUINO)
|
||||
#if defined(ARCH_PORTDUINO)
|
||||
if (!rIf) {
|
||||
rIf = new SimRadio;
|
||||
if (!rIf->init()) {
|
||||
@@ -1191,6 +1220,19 @@ extern meshtastic_DeviceMetadata getDeviceMetadata()
|
||||
#endif
|
||||
return deviceMetadata;
|
||||
}
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_I2C
|
||||
void scannerToSensorsMap(const std::unique_ptr<ScanI2CTwoWire> &i2cScanner, ScanI2C::DeviceType deviceType,
|
||||
meshtastic_TelemetrySensorType sensorType)
|
||||
{
|
||||
auto found = i2cScanner->find(deviceType);
|
||||
if (found.type != ScanI2C::DeviceType::NONE) {
|
||||
nodeTelemetrySensorsMap[sensorType].first = found.address.address;
|
||||
nodeTelemetrySensorsMap[sensorType].second = i2cScanner->fetchI2CBus(found.address);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef PIO_UNIT_TESTING
|
||||
void loop()
|
||||
{
|
||||
@@ -1221,4 +1263,4 @@ void loop()
|
||||
mainDelay.delay(delayMsec);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
+7
-7
@@ -10,9 +10,6 @@
|
||||
#include "mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include <SPI.h>
|
||||
#include <map>
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
#include <SparkFun_ATECCX08a_Arduino_Library.h>
|
||||
#endif
|
||||
#if defined(ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
#include "nimble/NimbleBluetooth.h"
|
||||
extern NimbleBluetooth *nimbleBluetooth;
|
||||
@@ -21,6 +18,9 @@ extern NimbleBluetooth *nimbleBluetooth;
|
||||
#include "NRF52Bluetooth.h"
|
||||
extern NRF52Bluetooth *nrf52Bluetooth;
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_I2C
|
||||
#include "detect/ScanI2CTwoWire.h"
|
||||
#endif
|
||||
|
||||
#if ARCH_PORTDUINO
|
||||
extern HardwareSPI *DisplaySPI;
|
||||
@@ -39,10 +39,6 @@ extern bool pmu_found;
|
||||
extern bool isCharging;
|
||||
extern bool isUSBPowered;
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
extern ATECCX08A atecc;
|
||||
#endif
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#include <Adafruit_DRV2605.h>
|
||||
extern Adafruit_DRV2605 drv;
|
||||
@@ -84,6 +80,10 @@ extern bool pauseBluetoothLogging;
|
||||
void nrf52Setup(), esp32Setup(), nrf52Loop(), esp32Loop(), rp2040Setup(), clearBonds(), enterDfuMode();
|
||||
|
||||
meshtastic_DeviceMetadata getDeviceMetadata();
|
||||
#if !MESHTASTIC_EXCLUDE_I2C
|
||||
void scannerToSensorsMap(const std::unique_ptr<ScanI2CTwoWire> &i2cScanner, ScanI2C::DeviceType deviceType,
|
||||
meshtastic_TelemetrySensorType sensorType);
|
||||
#endif
|
||||
|
||||
// We default to 4MHz SPI, SPI mode 0
|
||||
extern SPISettings spiSettings;
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "Channels.h"
|
||||
#include "../userPrefs.h"
|
||||
|
||||
#include "CryptoEngine.h"
|
||||
#include "Default.h"
|
||||
#include "DisplayFormatters.h"
|
||||
@@ -178,12 +178,11 @@ CryptoKey Channels::getKey(ChannelIndex chIndex)
|
||||
{
|
||||
meshtastic_Channel &ch = getByIndex(chIndex);
|
||||
const meshtastic_ChannelSettings &channelSettings = ch.settings;
|
||||
assert(ch.has_settings);
|
||||
|
||||
CryptoKey k;
|
||||
memset(k.bytes, 0, sizeof(k.bytes)); // In case the user provided a short key, we want to pad the rest with zeros
|
||||
|
||||
if (ch.role == meshtastic_Channel_Role_DISABLED) {
|
||||
if (!ch.has_settings || ch.role == meshtastic_Channel_Role_DISABLED) {
|
||||
k.length = -1; // invalid
|
||||
} else {
|
||||
memcpy(k.bytes, channelSettings.psk.bytes, channelSettings.psk.size);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "Default.h"
|
||||
#include "../userPrefs.h"
|
||||
|
||||
#include "meshUtils.h"
|
||||
|
||||
uint32_t Default::getConfiguredOrDefaultMs(uint32_t configuredInterval, uint32_t defaultInterval)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "FloodingRouter.h"
|
||||
#include "../userPrefs.h"
|
||||
|
||||
#include "configuration.h"
|
||||
#include "mesh-pb-constants.h"
|
||||
|
||||
@@ -36,7 +36,8 @@ bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
|
||||
if (isRepeated) {
|
||||
LOG_DEBUG("Repeated reliable tx");
|
||||
if (!perhapsRebroadcast(p) && isToUs(p) && p->want_ack) {
|
||||
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel, 0);
|
||||
// FIXME - channel index should be used, but the packet is still encrypted here
|
||||
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -166,27 +166,10 @@ NodeNum MeshService::getNodenumFromRequestId(uint32_t request_id)
|
||||
*/
|
||||
void MeshService::handleToRadio(meshtastic_MeshPacket &p)
|
||||
{
|
||||
#if defined(ARCH_PORTDUINO) && !HAS_RADIO
|
||||
// Simulates device received 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
|
||||
meshtastic_Compressed scratch;
|
||||
meshtastic_Compressed *decoded = NULL;
|
||||
if (p.which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||
memset(&scratch, 0, sizeof(scratch));
|
||||
p.decoded.payload.size =
|
||||
pb_decode_from_bytes(p.decoded.payload.bytes, p.decoded.payload.size, &meshtastic_Compressed_msg, &scratch);
|
||||
if (p.decoded.payload.size) {
|
||||
decoded = &scratch;
|
||||
// Extract the original payload and replace
|
||||
memcpy(&p.decoded.payload, &decoded->data, sizeof(decoded->data));
|
||||
// Switch the port from PortNum_SIMULATOR_APP back to the original PortNum
|
||||
p.decoded.portnum = decoded->portnum;
|
||||
} else
|
||||
LOG_ERROR("Error decoding proto for simulator message!");
|
||||
}
|
||||
// Let SimRadio receive as if it did via its LoRa chip
|
||||
SimRadio::instance->startReceive(&p);
|
||||
#if defined(ARCH_PORTDUINO)
|
||||
if (SimRadio::instance && p.decoded.portnum == meshtastic_PortNum_SIMULATOR_APP) {
|
||||
// Simulates device received a packet via the LoRa chip
|
||||
SimRadio::instance->unpackAndReceive(p);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -271,7 +254,7 @@ bool MeshService::trySendPosition(NodeNum dest, bool wantReplies)
|
||||
|
||||
assert(node);
|
||||
|
||||
if (hasValidPosition(node)) {
|
||||
if (nodeDB->hasValidPosition(node)) {
|
||||
#if HAS_GPS && !MESHTASTIC_EXCLUDE_GPS
|
||||
if (positionModule) {
|
||||
LOG_INFO("Send position ping to 0x%x, wantReplies=%d, channel=%d", dest, wantReplies, node->channel);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "MeshTypes.h"
|
||||
#include "Observer.h"
|
||||
#include "PointerQueue.h"
|
||||
#if defined(ARCH_PORTDUINO) && !HAS_RADIO
|
||||
#if defined(ARCH_PORTDUINO)
|
||||
#include "../platform/portduino/SimRadio.h"
|
||||
#endif
|
||||
#if defined(ARCH_ESP32) || defined(ARCH_PORTDUINO)
|
||||
@@ -165,4 +165,4 @@ class MeshService
|
||||
friend class RoutingModule;
|
||||
};
|
||||
|
||||
extern MeshService *service;
|
||||
extern MeshService *service;
|
||||
+118
-21
@@ -1,4 +1,3 @@
|
||||
#include "../userPrefs.h"
|
||||
#include "configuration.h"
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
#include "GPS.h"
|
||||
@@ -61,6 +60,16 @@ meshtastic_LocalConfig config;
|
||||
meshtastic_LocalModuleConfig moduleConfig;
|
||||
meshtastic_ChannelFile channelFile;
|
||||
|
||||
#ifdef USERPREFS_USE_ADMIN_KEY_0
|
||||
static unsigned char userprefs_admin_key_0[] = USERPREFS_USE_ADMIN_KEY_0;
|
||||
#endif
|
||||
#ifdef USERPREFS_USE_ADMIN_KEY_1
|
||||
static unsigned char userprefs_admin_key_1[] = USERPREFS_USE_ADMIN_KEY_1;
|
||||
#endif
|
||||
#ifdef USERPREFS_USE_ADMIN_KEY_2
|
||||
static unsigned char userprefs_admin_key_2[] = USERPREFS_USE_ADMIN_KEY_2;
|
||||
#endif
|
||||
|
||||
bool meshtastic_DeviceState_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field)
|
||||
{
|
||||
if (ostream) {
|
||||
@@ -114,7 +123,7 @@ NodeDB::NodeDB()
|
||||
uint32_t channelFileCRC = crc32Buffer(&channelFile, sizeof(channelFile));
|
||||
|
||||
int saveWhat = 0;
|
||||
bool hasUniqueId = false;
|
||||
// bool hasUniqueId = false;
|
||||
// Get device unique id
|
||||
#if defined(ARCH_ESP32) && defined(ESP_EFUSE_OPTIONAL_UNIQUE_ID)
|
||||
uint32_t unique_id[4];
|
||||
@@ -406,11 +415,37 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
||||
#else
|
||||
config.lora.ignore_mqtt = false;
|
||||
#endif
|
||||
#ifdef USERPREFS_USE_ADMIN_KEY
|
||||
memcpy(config.security.admin_key[0].bytes, USERPREFS_ADMIN_KEY, 32);
|
||||
config.security.admin_key[0].size = 32;
|
||||
config.security.admin_key_count = 1;
|
||||
// Initialize admin_key_count to zero
|
||||
byte numAdminKeys = 0;
|
||||
|
||||
#ifdef USERPREFS_USE_ADMIN_KEY_0
|
||||
// Check if USERPREFS_ADMIN_KEY_0 is non-empty
|
||||
if (sizeof(userprefs_admin_key_0) > 0) {
|
||||
memcpy(config.security.admin_key[0].bytes, userprefs_admin_key_0, 32);
|
||||
config.security.admin_key[0].size = 32;
|
||||
numAdminKeys++;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USERPREFS_USE_ADMIN_KEY_1
|
||||
// Check if USERPREFS_ADMIN_KEY_1 is non-empty
|
||||
if (sizeof(userprefs_admin_key_1) > 0) {
|
||||
memcpy(config.security.admin_key[1].bytes, userprefs_admin_key_1, 32);
|
||||
config.security.admin_key[1].size = 32;
|
||||
numAdminKeys++;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USERPREFS_USE_ADMIN_KEY_2
|
||||
// Check if USERPREFS_ADMIN_KEY_2 is non-empty
|
||||
if (sizeof(userprefs_admin_key_2) > 0) {
|
||||
memcpy(config.security.admin_key[2].bytes, userprefs_admin_key_2, 32);
|
||||
config.security.admin_key[2].size = 32;
|
||||
numAdminKeys++;
|
||||
}
|
||||
#endif
|
||||
config.security.admin_key_count = numAdminKeys;
|
||||
|
||||
if (shouldPreserveKey) {
|
||||
config.security.private_key.size = 32;
|
||||
memcpy(config.security.private_key.bytes, private_key_temp, config.security.private_key.size);
|
||||
@@ -429,7 +464,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
||||
#endif
|
||||
#if defined(USERPREFS_CONFIG_GPS_MODE)
|
||||
config.position.gps_mode = USERPREFS_CONFIG_GPS_MODE;
|
||||
#elif !HAS_GPS || defined(T_DECK) || defined(TLORA_T3S3_EPAPER)
|
||||
#elif !HAS_GPS || GPS_DEFAULT_NOT_PRESENT
|
||||
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT;
|
||||
#elif !defined(GPS_RX_PIN)
|
||||
if (config.position.rx_gpio == 0)
|
||||
@@ -482,7 +517,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
||||
#ifdef RAK4630
|
||||
config.display.wake_on_tap_or_motion = true;
|
||||
#endif
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(T_WATCH_S3) || defined(SENSECAP_INDICATOR)
|
||||
config.display.screen_on_secs = 30;
|
||||
config.display.wake_on_tap_or_motion = true;
|
||||
#endif
|
||||
@@ -867,6 +902,54 @@ void NodeDB::loadFromDisk()
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we load hard coded admin keys even when the configuration file has none.
|
||||
// Initialize admin_key_count to zero
|
||||
byte numAdminKeys = 0;
|
||||
uint16_t sum = 0;
|
||||
#ifdef USERPREFS_USE_ADMIN_KEY_0
|
||||
for (uint8_t b = 0; b < 32; b++) {
|
||||
sum += config.security.admin_key[0].bytes[b];
|
||||
}
|
||||
if (sum == 0) {
|
||||
numAdminKeys += 1;
|
||||
LOG_INFO("Admin 0 key zero. Loading hard coded key from user preferences.");
|
||||
memcpy(config.security.admin_key[0].bytes, userprefs_admin_key_0, 32);
|
||||
config.security.admin_key[0].size = 32;
|
||||
config.security.admin_key_count = numAdminKeys;
|
||||
saveToDisk(SEGMENT_CONFIG);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USERPREFS_USE_ADMIN_KEY_1
|
||||
sum = 0;
|
||||
for (uint8_t b = 0; b < 32; b++) {
|
||||
sum += config.security.admin_key[1].bytes[b];
|
||||
}
|
||||
if (sum == 0) {
|
||||
numAdminKeys += 1;
|
||||
LOG_INFO("Admin 1 key zero. Loading hard coded key from user preferences.");
|
||||
memcpy(config.security.admin_key[1].bytes, userprefs_admin_key_1, 32);
|
||||
config.security.admin_key[1].size = 32;
|
||||
config.security.admin_key_count = numAdminKeys;
|
||||
saveToDisk(SEGMENT_CONFIG);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USERPREFS_USE_ADMIN_KEY_2
|
||||
sum = 0;
|
||||
for (uint8_t b = 0; b < 32; b++) {
|
||||
sum += config.security.admin_key[2].bytes[b];
|
||||
}
|
||||
if (sum == 0) {
|
||||
numAdminKeys += 1;
|
||||
LOG_INFO("Admin 2 key zero. Loading hard coded key from user preferences.");
|
||||
memcpy(config.security.admin_key[2].bytes, userprefs_admin_key_2, 32);
|
||||
config.security.admin_key[2].size = 32;
|
||||
config.security.admin_key_count = numAdminKeys;
|
||||
saveToDisk(SEGMENT_CONFIG);
|
||||
}
|
||||
#endif
|
||||
|
||||
state = loadProto(moduleConfigFileName, meshtastic_LocalModuleConfig_size, sizeof(meshtastic_LocalModuleConfig),
|
||||
&meshtastic_LocalModuleConfig_msg, &moduleConfig);
|
||||
if (state != LoadFileResult::LOAD_SUCCESS) {
|
||||
@@ -1159,7 +1242,6 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_DEBUG("old user %s/%s, channel=%d", info->user.long_name, info->user.short_name, info->channel);
|
||||
#if !(MESHTASTIC_EXCLUDE_PKI)
|
||||
if (p.public_key.size > 0) {
|
||||
printBytes("Incoming Pubkey: ", p.public_key.bytes, 32);
|
||||
@@ -1183,7 +1265,8 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
|
||||
}
|
||||
if (nodeId != getNodeNum())
|
||||
info->channel = channelIndex; // Set channel we need to use to reach this node (but don't set our own channel)
|
||||
LOG_DEBUG("Update changed=%d user %s/%s, channel=%d", changed, info->user.long_name, info->user.short_name, info->channel);
|
||||
LOG_DEBUG("Update changed=%d user %s/%s, id=0x%08x, channel=%d", changed, info->user.long_name, info->user.short_name, nodeId,
|
||||
info->channel);
|
||||
info->has_user = true;
|
||||
|
||||
if (changed) {
|
||||
@@ -1191,10 +1274,14 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
|
||||
powerFSM.trigger(EVENT_NODEDB_UPDATED);
|
||||
notifyObservers(true); // Force an update whether or not our node counts have changed
|
||||
|
||||
// We just changed something about the user, store our DB
|
||||
Throttle::execute(
|
||||
&lastNodeDbSave, ONE_MINUTE_MS, []() { nodeDB->saveToDisk(SEGMENT_DEVICESTATE); },
|
||||
[]() { LOG_DEBUG("Defer NodeDB saveToDisk for now"); }); // since we saved less than a minute ago
|
||||
// We just changed something about a User,
|
||||
// store our DB unless we just did so less than a minute ago
|
||||
if (!Throttle::isWithinTimespanMs(lastNodeDbSave, ONE_MINUTE_MS)) {
|
||||
saveToDisk(SEGMENT_DEVICESTATE);
|
||||
lastNodeDbSave = millis();
|
||||
} else {
|
||||
LOG_DEBUG("Defer NodeDB saveToDisk for now");
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
@@ -1261,7 +1348,7 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
|
||||
|
||||
if (!lite) {
|
||||
if (isFull()) {
|
||||
LOG_INFO("Node database full with %i nodes and %i bytes free. Erasing oldest entry", numMeshNodes,
|
||||
LOG_INFO("Node database full with %i nodes and %u bytes free. Erasing oldest entry", numMeshNodes,
|
||||
memGet.getFreeHeap());
|
||||
// look for oldest node and erase it
|
||||
uint32_t oldest = UINT32_MAX;
|
||||
@@ -1285,11 +1372,14 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
|
||||
if (oldestBoringIndex != -1) {
|
||||
oldestIndex = oldestBoringIndex;
|
||||
}
|
||||
// Shove the remaining nodes down the chain
|
||||
for (int i = oldestIndex; i < numMeshNodes - 1; i++) {
|
||||
meshNodes->at(i) = meshNodes->at(i + 1);
|
||||
|
||||
if (oldestIndex != -1) {
|
||||
// Shove the remaining nodes down the chain
|
||||
for (int i = oldestIndex; i < numMeshNodes - 1; i++) {
|
||||
meshNodes->at(i) = meshNodes->at(i + 1);
|
||||
}
|
||||
(numMeshNodes)--;
|
||||
}
|
||||
(numMeshNodes)--;
|
||||
}
|
||||
// add the node at the end
|
||||
lite = &meshNodes->at((numMeshNodes)++);
|
||||
@@ -1297,12 +1387,19 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
|
||||
// everything is missing except the nodenum
|
||||
memset(lite, 0, sizeof(*lite));
|
||||
lite->num = n;
|
||||
LOG_INFO("Adding node to database with %i nodes and %i bytes free!", numMeshNodes, memGet.getFreeHeap());
|
||||
LOG_INFO("Adding node to database with %i nodes and %u bytes free!", numMeshNodes, memGet.getFreeHeap());
|
||||
}
|
||||
|
||||
return lite;
|
||||
}
|
||||
|
||||
/// Sometimes we will have Position objects that only have a time, so check for
|
||||
/// valid lat/lon
|
||||
bool NodeDB::hasValidPosition(const meshtastic_NodeInfoLite *n)
|
||||
{
|
||||
return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0);
|
||||
}
|
||||
|
||||
/// Record an error that should be reported via analytics
|
||||
void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, const char *filename)
|
||||
{
|
||||
@@ -1325,4 +1422,4 @@ void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, co
|
||||
LOG_ERROR("A critical failure occurred, portduino is exiting");
|
||||
exit(2);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
+2
-7
@@ -165,6 +165,8 @@ class NodeDB
|
||||
localPosition = position;
|
||||
}
|
||||
|
||||
bool hasValidPosition(const meshtastic_NodeInfoLite *n);
|
||||
|
||||
private:
|
||||
uint32_t lastNodeDbSave = 0; // when we last saved our db to flash
|
||||
/// Find a node in our DB, create an empty NodeInfoLite if missing
|
||||
@@ -217,13 +219,6 @@ extern NodeDB *nodeDB;
|
||||
prefs.is_power_saving = True
|
||||
*/
|
||||
|
||||
/// Sometimes we will have Position objects that only have a time, so check for
|
||||
/// valid lat/lon
|
||||
static inline bool hasValidPosition(const meshtastic_NodeInfoLite *n)
|
||||
{
|
||||
return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0);
|
||||
}
|
||||
|
||||
/** The current change # for radio settings. Starts at 0 on boot and any time the radio settings
|
||||
* might have changed is incremented. Allows others to detect they might now be on a new channel.
|
||||
*/
|
||||
|
||||
@@ -613,13 +613,14 @@ bool PhoneAPI::handleToRadioPacket(meshtastic_MeshPacket &p)
|
||||
{
|
||||
printPacket("PACKET FROM PHONE", &p);
|
||||
|
||||
// For use with the simulator, we should not ignore duplicate packets
|
||||
#if !(defined(ARCH_PORTDUINO) && !HAS_RADIO)
|
||||
if (p.id > 0 && wasSeenRecently(p.id)) {
|
||||
LOG_DEBUG("Ignore packet from phone, already seen recently");
|
||||
return false;
|
||||
}
|
||||
#if defined(ARCH_PORTDUINO)
|
||||
// For use with the simulator, we should not ignore duplicate packets from the phone
|
||||
if (SimRadio::instance == nullptr)
|
||||
#endif
|
||||
if (p.id > 0 && wasSeenRecently(p.id)) {
|
||||
LOG_DEBUG("Ignore packet from phone, already seen recently");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (p.decoded.portnum == meshtastic_PortNum_TRACEROUTE_APP && lastPortNumToRadio[p.decoded.portnum] &&
|
||||
Throttle::isWithinTimespanMs(lastPortNumToRadio[p.decoded.portnum], THIRTY_SECONDS_MS)) {
|
||||
@@ -656,4 +657,4 @@ int PhoneAPI::onNotify(uint32_t newValue)
|
||||
}
|
||||
|
||||
return timeout ? -1 : 0; // If we timed out, MeshService should stop iterating through observers as we just removed one
|
||||
}
|
||||
}
|
||||
@@ -284,8 +284,8 @@ uint32_t RadioInterface::getTxDelayMsecWeighted(float snr)
|
||||
void printPacket(const char *prefix, const meshtastic_MeshPacket *p)
|
||||
{
|
||||
#ifdef DEBUG_PORT
|
||||
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);
|
||||
std::string out = DEBUG_PORT.mt_sprintf("%s (id=0x%08x fr=0x%08x to=0x%08x, WantAck=%d, HopLim=%d Ch=0x%x", prefix, p->id,
|
||||
p->from, p->to, p->want_ack, p->hop_limit, p->channel);
|
||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||
auto &s = p->decoded;
|
||||
|
||||
@@ -601,8 +601,6 @@ size_t RadioInterface::beginSending(meshtastic_MeshPacket *p)
|
||||
// LOG_DEBUG("Send queued packet on mesh (txGood=%d,rxGood=%d,rxBad=%d)", rf95.txGood(), rf95.rxGood(), rf95.rxBad());
|
||||
assert(p->which_payload_variant == meshtastic_MeshPacket_encrypted_tag); // It should have already been encoded by now
|
||||
|
||||
lastTxStart = millis();
|
||||
|
||||
radioBuffer.header.from = p->from;
|
||||
radioBuffer.header.to = p->to;
|
||||
radioBuffer.header.id = p->id;
|
||||
@@ -624,4 +622,4 @@ size_t RadioInterface::beginSending(meshtastic_MeshPacket *p)
|
||||
|
||||
sendingPacket = p;
|
||||
return p->encrypted.size + sizeof(PacketHeader);
|
||||
}
|
||||
}
|
||||
@@ -278,7 +278,8 @@ void RadioLibInterface::onNotify(uint32_t notification)
|
||||
startReceive(); // try receiving this packet, afterwards we'll be trying to transmit again
|
||||
setTransmitDelay();
|
||||
} else {
|
||||
// Send any outgoing packets we have ready
|
||||
// Send any outgoing packets we have ready as fast as possible to keep the time between channel scan and
|
||||
// actual transmission as short as possible
|
||||
meshtastic_MeshPacket *txp = txQueue.dequeue();
|
||||
assert(txp);
|
||||
bool sent = startSend(txp);
|
||||
@@ -470,7 +471,8 @@ void RadioLibInterface::setStandby()
|
||||
/** start an immediate transmit */
|
||||
bool RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
|
||||
{
|
||||
printPacket("Start low level send", txp);
|
||||
/* NOTE: Minimize the actions before startTransmit() to keep the time between
|
||||
channel scan and actual transmit as low as possible to avoid collisions. */
|
||||
if (disabled || !config.lora.tx_enabled) {
|
||||
LOG_WARN("Drop Tx packet because LoRa Tx disabled");
|
||||
packetPool.release(txp);
|
||||
@@ -489,6 +491,9 @@ bool RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
|
||||
completeSending();
|
||||
powerMon->clearState(meshtastic_PowerMon_State_Lora_TXOn); // Transmitter off now
|
||||
startReceive(); // Restart receive mode (because startTransmit failed to put us in xmit mode)
|
||||
} else {
|
||||
lastTxStart = millis();
|
||||
printPacket("Started Tx", txp);
|
||||
}
|
||||
|
||||
// Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register
|
||||
|
||||
+4
-1
@@ -6,6 +6,7 @@
|
||||
#include "NodeDB.h"
|
||||
#include "RTC.h"
|
||||
#include "configuration.h"
|
||||
#include "detect/LoRaRadioType.h"
|
||||
#include "main.h"
|
||||
#include "mesh-pb-constants.h"
|
||||
#include "meshUtils.h"
|
||||
@@ -20,7 +21,6 @@
|
||||
#if ENABLE_JSON_LOGGING || ARCH_PORTDUINO
|
||||
#include "serialization/MeshPacketSerializer.h"
|
||||
#endif
|
||||
#include "../userPrefs.h"
|
||||
|
||||
#define MAX_RX_FROMRADIO \
|
||||
4 // max number of packets destined to our queue, we dispatch packets quickly so it doesn't need to be big
|
||||
@@ -271,6 +271,7 @@ ErrorCode Router::send(meshtastic_MeshPacket *p)
|
||||
auto encodeResult = perhapsEncode(p);
|
||||
if (encodeResult != meshtastic_Routing_Error_NONE) {
|
||||
packetPool.release(p_decoded);
|
||||
p->channel = 0; // Reset the channel to 0, so we don't use the failing hash again
|
||||
abortSendAndNak(encodeResult, p);
|
||||
return encodeResult; // FIXME - this isn't a valid ErrorCode
|
||||
}
|
||||
@@ -492,6 +493,8 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
|
||||
// is not in the local nodedb
|
||||
// First, only PKC encrypt packets we are originating
|
||||
if (isFromUs(p) &&
|
||||
// Don't use PKC with simulator
|
||||
radioType != SIM_RADIO &&
|
||||
// Don't use PKC with Ham mode
|
||||
!owner.is_licensed &&
|
||||
// Don't use PKC if it's not explicitly requested and a non-primary channel is requested
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "aes-ccm.h"
|
||||
#if !MESHTASTIC_EXCLUDE_PKI
|
||||
|
||||
static inline void WPA_PUT_BE16(uint8_t *a, uint16_t val)
|
||||
static void WPA_PUT_BE16(uint8_t *a, uint16_t val)
|
||||
{
|
||||
a[0] = val >> 8;
|
||||
a[1] = val & 0xff;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StreamAPI.h"
|
||||
|
||||
#define SERVER_API_DEFAULT_PORT 4403
|
||||
|
||||
/**
|
||||
* Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs
|
||||
* (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs).
|
||||
|
||||
@@ -22,5 +22,5 @@ class WiFiServerPort : public APIServerPort<WiFiServerAPI, WiFiServer>
|
||||
explicit WiFiServerPort(int port);
|
||||
};
|
||||
|
||||
void initApiServer(int port = 4403);
|
||||
void initApiServer(int port = SERVER_API_DEFAULT_PORT);
|
||||
void deInitApiServer();
|
||||
@@ -22,4 +22,4 @@ class ethServerPort : public APIServerPort<ethServerAPI, EthernetServer>
|
||||
explicit ethServerPort(int port);
|
||||
};
|
||||
|
||||
void initApiServer(int port = 4403);
|
||||
void initApiServer(int port = SERVER_API_DEFAULT_PORT);
|
||||
|
||||
@@ -49,6 +49,8 @@ typedef enum _meshtastic_Language {
|
||||
meshtastic_Language_DUTCH = 12,
|
||||
/* Greek */
|
||||
meshtastic_Language_GREEK = 13,
|
||||
/* Norwegian */
|
||||
meshtastic_Language_NORWEGIAN = 14,
|
||||
/* Simplified Chinese (experimental) */
|
||||
meshtastic_Language_SIMPLIFIED_CHINESE = 30,
|
||||
/* Traditional Chinese (experimental) */
|
||||
@@ -84,6 +86,7 @@ typedef struct _meshtastic_NodeHighlight {
|
||||
char node_name[16];
|
||||
} meshtastic_NodeHighlight;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(16) meshtastic_DeviceUIConfig_calibration_data_t;
|
||||
typedef struct _meshtastic_DeviceUIConfig {
|
||||
/* A version integer used to invalidate saved files when we make incompatible changes. */
|
||||
uint32_t version;
|
||||
@@ -109,6 +112,8 @@ typedef struct _meshtastic_DeviceUIConfig {
|
||||
/* Node list highlightening */
|
||||
bool has_node_highlight;
|
||||
meshtastic_NodeHighlight node_highlight;
|
||||
/* 8 integers for screen calibration data */
|
||||
meshtastic_DeviceUIConfig_calibration_data_t calibration_data;
|
||||
} meshtastic_DeviceUIConfig;
|
||||
|
||||
|
||||
@@ -132,10 +137,10 @@ extern "C" {
|
||||
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_DeviceUIConfig_init_default {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_default, false, meshtastic_NodeHighlight_init_default}
|
||||
#define meshtastic_DeviceUIConfig_init_default {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_default, false, meshtastic_NodeHighlight_init_default, {0, {0}}}
|
||||
#define meshtastic_NodeFilter_init_default {0, 0, 0, 0, 0, ""}
|
||||
#define meshtastic_NodeHighlight_init_default {0, 0, 0, 0, ""}
|
||||
#define meshtastic_DeviceUIConfig_init_zero {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_zero, false, meshtastic_NodeHighlight_init_zero}
|
||||
#define meshtastic_DeviceUIConfig_init_zero {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_zero, false, meshtastic_NodeHighlight_init_zero, {0, {0}}}
|
||||
#define meshtastic_NodeFilter_init_zero {0, 0, 0, 0, 0, ""}
|
||||
#define meshtastic_NodeHighlight_init_zero {0, 0, 0, 0, ""}
|
||||
|
||||
@@ -164,6 +169,7 @@ extern "C" {
|
||||
#define meshtastic_DeviceUIConfig_language_tag 11
|
||||
#define meshtastic_DeviceUIConfig_node_filter_tag 12
|
||||
#define meshtastic_DeviceUIConfig_node_highlight_tag 13
|
||||
#define meshtastic_DeviceUIConfig_calibration_data_tag 14
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define meshtastic_DeviceUIConfig_FIELDLIST(X, a) \
|
||||
@@ -179,7 +185,8 @@ X(a, STATIC, SINGULAR, BOOL, banner_enabled, 9) \
|
||||
X(a, STATIC, SINGULAR, UINT32, ring_tone_id, 10) \
|
||||
X(a, STATIC, SINGULAR, UENUM, language, 11) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, node_filter, 12) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, node_highlight, 13)
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, node_highlight, 13) \
|
||||
X(a, STATIC, SINGULAR, BYTES, calibration_data, 14)
|
||||
#define meshtastic_DeviceUIConfig_CALLBACK NULL
|
||||
#define meshtastic_DeviceUIConfig_DEFAULT NULL
|
||||
#define meshtastic_DeviceUIConfig_node_filter_MSGTYPE meshtastic_NodeFilter
|
||||
@@ -215,7 +222,7 @@ extern const pb_msgdesc_t meshtastic_NodeHighlight_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define MESHTASTIC_MESHTASTIC_DEVICE_UI_PB_H_MAX_SIZE meshtastic_DeviceUIConfig_size
|
||||
#define meshtastic_DeviceUIConfig_size 99
|
||||
#define meshtastic_DeviceUIConfig_size 117
|
||||
#define meshtastic_NodeFilter_size 36
|
||||
#define meshtastic_NodeHighlight_size 25
|
||||
|
||||
|
||||
@@ -90,6 +90,8 @@ typedef struct _meshtastic_NodeInfoLite {
|
||||
/* True if node is in our ignored list
|
||||
Persists between NodeDB internal clean ups */
|
||||
bool is_ignored;
|
||||
/* Last byte of the node number of the node that should be used as the next hop to reach this node. */
|
||||
uint8_t next_hop;
|
||||
} meshtastic_NodeInfoLite;
|
||||
|
||||
/* This message is never sent over the wire, but it is used for serializing DB
|
||||
@@ -153,12 +155,12 @@ extern "C" {
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_PositionLite_init_default {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN}
|
||||
#define meshtastic_UserLite_init_default {{0}, "", "", _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}}
|
||||
#define meshtastic_NodeInfoLite_init_default {0, false, meshtastic_UserLite_init_default, false, meshtastic_PositionLite_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0, 0}
|
||||
#define meshtastic_NodeInfoLite_init_default {0, false, meshtastic_UserLite_init_default, false, meshtastic_PositionLite_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0, 0, 0}
|
||||
#define meshtastic_DeviceState_init_default {false, meshtastic_MyNodeInfo_init_default, false, meshtastic_User_init_default, 0, {meshtastic_MeshPacket_init_default}, false, meshtastic_MeshPacket_init_default, 0, 0, 0, false, meshtastic_MeshPacket_init_default, 0, {meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}, {0}}
|
||||
#define meshtastic_ChannelFile_init_default {0, {meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default}, 0}
|
||||
#define meshtastic_PositionLite_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN}
|
||||
#define meshtastic_UserLite_init_zero {{0}, "", "", _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}}
|
||||
#define meshtastic_NodeInfoLite_init_zero {0, false, meshtastic_UserLite_init_zero, false, meshtastic_PositionLite_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0, 0}
|
||||
#define meshtastic_NodeInfoLite_init_zero {0, false, meshtastic_UserLite_init_zero, false, meshtastic_PositionLite_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0, 0, 0}
|
||||
#define meshtastic_DeviceState_init_zero {false, meshtastic_MyNodeInfo_init_zero, false, meshtastic_User_init_zero, 0, {meshtastic_MeshPacket_init_zero}, false, meshtastic_MeshPacket_init_zero, 0, 0, 0, false, meshtastic_MeshPacket_init_zero, 0, {meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}, {0}}
|
||||
#define meshtastic_ChannelFile_init_zero {0, {meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero}, 0}
|
||||
|
||||
@@ -186,6 +188,7 @@ extern "C" {
|
||||
#define meshtastic_NodeInfoLite_hops_away_tag 9
|
||||
#define meshtastic_NodeInfoLite_is_favorite_tag 10
|
||||
#define meshtastic_NodeInfoLite_is_ignored_tag 11
|
||||
#define meshtastic_NodeInfoLite_next_hop_tag 12
|
||||
#define meshtastic_DeviceState_my_node_tag 2
|
||||
#define meshtastic_DeviceState_owner_tag 3
|
||||
#define meshtastic_DeviceState_receive_queue_tag 5
|
||||
@@ -231,7 +234,8 @@ X(a, STATIC, SINGULAR, UINT32, channel, 7) \
|
||||
X(a, STATIC, SINGULAR, BOOL, via_mqtt, 8) \
|
||||
X(a, STATIC, OPTIONAL, UINT32, hops_away, 9) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_favorite, 10) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_ignored, 11)
|
||||
X(a, STATIC, SINGULAR, BOOL, is_ignored, 11) \
|
||||
X(a, STATIC, SINGULAR, UINT32, next_hop, 12)
|
||||
#define meshtastic_NodeInfoLite_CALLBACK NULL
|
||||
#define meshtastic_NodeInfoLite_DEFAULT NULL
|
||||
#define meshtastic_NodeInfoLite_user_MSGTYPE meshtastic_UserLite
|
||||
@@ -284,7 +288,7 @@ extern const pb_msgdesc_t meshtastic_ChannelFile_msg;
|
||||
/* meshtastic_DeviceState_size depends on runtime parameters */
|
||||
#define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_ChannelFile_size
|
||||
#define meshtastic_ChannelFile_size 718
|
||||
#define meshtastic_NodeInfoLite_size 185
|
||||
#define meshtastic_NodeInfoLite_size 188
|
||||
#define meshtastic_PositionLite_size 28
|
||||
#define meshtastic_UserLite_size 96
|
||||
|
||||
|
||||
@@ -212,6 +212,14 @@ typedef enum _meshtastic_HardwareModel {
|
||||
meshtastic_HardwareModel_MS24SF1 = 82,
|
||||
/* Lilygo TLora-C6 with the new ESP32-C6 MCU */
|
||||
meshtastic_HardwareModel_TLORA_C6 = 83,
|
||||
/* WisMesh Tap
|
||||
RAK-4631 w/ TFT in injection modled case */
|
||||
meshtastic_HardwareModel_WISMESH_TAP = 84,
|
||||
/* Similar to PORTDUINO but used by Routastic devices, this is not any
|
||||
particular device and does not run Meshtastic's code but supports
|
||||
the same frame format.
|
||||
Runs on linux, see https://github.com/Jorropo/routastic */
|
||||
meshtastic_HardwareModel_ROUTASTIC = 85,
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
||||
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.
|
||||
------------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
@@ -226,7 +234,7 @@ typedef enum _meshtastic_Constants {
|
||||
/* From mesh.options
|
||||
note: this payload length is ONLY the bytes that are sent inside of the Data protobuf (excluding protobuf overhead). The 16 byte header is
|
||||
outside of this envelope */
|
||||
meshtastic_Constants_DATA_PAYLOAD_LEN = 237
|
||||
meshtastic_Constants_DATA_PAYLOAD_LEN = 233
|
||||
} meshtastic_Constants;
|
||||
|
||||
/* Error codes for critical errors
|
||||
@@ -600,7 +608,7 @@ typedef struct _meshtastic_Routing {
|
||||
};
|
||||
} meshtastic_Routing;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(237) meshtastic_Data_payload_t;
|
||||
typedef PB_BYTES_ARRAY_T(233) meshtastic_Data_payload_t;
|
||||
/* (Formerly called SubPacket)
|
||||
The payload portion fo a packet, this is the actual bytes that are sent
|
||||
inside a radio packet (because from/to are broken out by the comms library) */
|
||||
@@ -751,6 +759,12 @@ typedef struct _meshtastic_MeshPacket {
|
||||
meshtastic_MeshPacket_public_key_t public_key;
|
||||
/* Indicates whether the packet was en/decrypted using PKI */
|
||||
bool pki_encrypted;
|
||||
/* Last byte of the node number of the node that should be used as the next hop in routing.
|
||||
Set by the firmware internally, clients are not supposed to set this. */
|
||||
uint8_t next_hop;
|
||||
/* Last byte of the node number of the node that will relay/relayed this packet.
|
||||
Set by the firmware internally, clients are not supposed to set this. */
|
||||
uint8_t relay_node;
|
||||
} meshtastic_MeshPacket;
|
||||
|
||||
/* The bluetooth to device link:
|
||||
@@ -873,7 +887,7 @@ typedef struct _meshtastic_FileInfo {
|
||||
uint32_t size_bytes;
|
||||
} meshtastic_FileInfo;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(237) meshtastic_Compressed_data_t;
|
||||
typedef PB_BYTES_ARRAY_T(233) meshtastic_Compressed_data_t;
|
||||
/* Compressed message payload */
|
||||
typedef struct _meshtastic_Compressed {
|
||||
/* PortNum to determine the how to handle the compressed payload. */
|
||||
@@ -1159,7 +1173,7 @@ extern "C" {
|
||||
#define meshtastic_Data_init_default {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0}
|
||||
#define meshtastic_Waypoint_init_default {0, false, 0, false, 0, 0, 0, "", "", 0}
|
||||
#define meshtastic_MqttClientProxyMessage_init_default {"", 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, 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, 0, 0, {0, {0}}, 0, 0, 0}
|
||||
#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0, 0}
|
||||
#define meshtastic_MyNodeInfo_init_default {0, 0, 0, {0, {0}}, ""}
|
||||
#define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
||||
@@ -1184,7 +1198,7 @@ extern "C" {
|
||||
#define meshtastic_Data_init_zero {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0}
|
||||
#define meshtastic_Waypoint_init_zero {0, false, 0, false, 0, 0, 0, "", "", 0}
|
||||
#define meshtastic_MqttClientProxyMessage_init_zero {"", 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, 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, 0, 0, {0, {0}}, 0, 0, 0}
|
||||
#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0, 0}
|
||||
#define meshtastic_MyNodeInfo_init_zero {0, 0, 0, {0, {0}}, ""}
|
||||
#define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
||||
@@ -1280,6 +1294,8 @@ extern "C" {
|
||||
#define meshtastic_MeshPacket_hop_start_tag 15
|
||||
#define meshtastic_MeshPacket_public_key_tag 16
|
||||
#define meshtastic_MeshPacket_pki_encrypted_tag 17
|
||||
#define meshtastic_MeshPacket_next_hop_tag 18
|
||||
#define meshtastic_MeshPacket_relay_node_tag 19
|
||||
#define meshtastic_NodeInfo_num_tag 1
|
||||
#define meshtastic_NodeInfo_user_tag 2
|
||||
#define meshtastic_NodeInfo_position_tag 3
|
||||
@@ -1474,7 +1490,9 @@ X(a, STATIC, SINGULAR, UENUM, delayed, 13) \
|
||||
X(a, STATIC, SINGULAR, BOOL, via_mqtt, 14) \
|
||||
X(a, STATIC, SINGULAR, UINT32, hop_start, 15) \
|
||||
X(a, STATIC, SINGULAR, BYTES, public_key, 16) \
|
||||
X(a, STATIC, SINGULAR, BOOL, pki_encrypted, 17)
|
||||
X(a, STATIC, SINGULAR, BOOL, pki_encrypted, 17) \
|
||||
X(a, STATIC, SINGULAR, UINT32, next_hop, 18) \
|
||||
X(a, STATIC, SINGULAR, UINT32, relay_node, 19)
|
||||
#define meshtastic_MeshPacket_CALLBACK NULL
|
||||
#define meshtastic_MeshPacket_DEFAULT NULL
|
||||
#define meshtastic_MeshPacket_payload_variant_decoded_MSGTYPE meshtastic_Data
|
||||
@@ -1717,14 +1735,14 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
|
||||
#define MESHTASTIC_MESHTASTIC_MESH_PB_H_MAX_SIZE meshtastic_FromRadio_size
|
||||
#define meshtastic_ChunkedPayload_size 245
|
||||
#define meshtastic_ClientNotification_size 415
|
||||
#define meshtastic_Compressed_size 243
|
||||
#define meshtastic_Data_size 273
|
||||
#define meshtastic_Compressed_size 239
|
||||
#define meshtastic_Data_size 269
|
||||
#define meshtastic_DeviceMetadata_size 54
|
||||
#define meshtastic_FileInfo_size 236
|
||||
#define meshtastic_FromRadio_size 510
|
||||
#define meshtastic_Heartbeat_size 0
|
||||
#define meshtastic_LogRecord_size 426
|
||||
#define meshtastic_MeshPacket_size 367
|
||||
#define meshtastic_MeshPacket_size 371
|
||||
#define meshtastic_MqttClientProxyMessage_size 501
|
||||
#define meshtastic_MyNodeInfo_size 77
|
||||
#define meshtastic_NeighborInfo_size 258
|
||||
|
||||
@@ -91,7 +91,7 @@ typedef struct _meshtastic_StoreAndForward_Heartbeat {
|
||||
uint32_t secondary;
|
||||
} meshtastic_StoreAndForward_Heartbeat;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(237) meshtastic_StoreAndForward_text_t;
|
||||
typedef PB_BYTES_ARRAY_T(233) meshtastic_StoreAndForward_text_t;
|
||||
/* TODO: REPLACE */
|
||||
typedef struct _meshtastic_StoreAndForward {
|
||||
/* TODO: REPLACE */
|
||||
@@ -211,7 +211,7 @@ extern const pb_msgdesc_t meshtastic_StoreAndForward_Heartbeat_msg;
|
||||
#define meshtastic_StoreAndForward_Heartbeat_size 12
|
||||
#define meshtastic_StoreAndForward_History_size 18
|
||||
#define meshtastic_StoreAndForward_Statistics_size 50
|
||||
#define meshtastic_StoreAndForward_size 242
|
||||
#define meshtastic_StoreAndForward_size 238
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -77,7 +77,9 @@ typedef enum _meshtastic_TelemetrySensorType {
|
||||
/* MLX90614 non-contact IR temperature sensor */
|
||||
meshtastic_TelemetrySensorType_MLX90614 = 31,
|
||||
/* SCD40/SCD41 CO2, humidity, temperature sensor */
|
||||
meshtastic_TelemetrySensorType_SCD4X = 32
|
||||
meshtastic_TelemetrySensorType_SCD4X = 32,
|
||||
/* ClimateGuard RadSens, radiation, Geiger-Muller Tube */
|
||||
meshtastic_TelemetrySensorType_RADSENS = 33
|
||||
} meshtastic_TelemetrySensorType;
|
||||
|
||||
/* Struct definitions */
|
||||
@@ -155,6 +157,9 @@ typedef struct _meshtastic_EnvironmentMetrics {
|
||||
/* Wind lull in m/s */
|
||||
bool has_wind_lull;
|
||||
float wind_lull;
|
||||
/* Radiation in µR/h */
|
||||
bool has_radiation;
|
||||
float radiation;
|
||||
} meshtastic_EnvironmentMetrics;
|
||||
|
||||
/* Power Metrics (voltage / current / etc) */
|
||||
@@ -299,8 +304,8 @@ extern "C" {
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
|
||||
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_SCD4X
|
||||
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_SCD4X+1))
|
||||
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_RADSENS
|
||||
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_RADSENS+1))
|
||||
|
||||
|
||||
|
||||
@@ -313,7 +318,7 @@ extern "C" {
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_DeviceMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||
#define meshtastic_EnvironmentMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||
#define meshtastic_EnvironmentMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||
#define meshtastic_PowerMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||
#define meshtastic_AirQualityMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||
#define meshtastic_LocalStats_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
@@ -321,7 +326,7 @@ extern "C" {
|
||||
#define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}}
|
||||
#define meshtastic_Nau7802Config_init_default {0, 0}
|
||||
#define meshtastic_DeviceMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||
#define meshtastic_EnvironmentMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||
#define meshtastic_EnvironmentMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||
#define meshtastic_PowerMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||
#define meshtastic_AirQualityMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||
#define meshtastic_LocalStats_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
@@ -352,6 +357,7 @@ extern "C" {
|
||||
#define meshtastic_EnvironmentMetrics_weight_tag 15
|
||||
#define meshtastic_EnvironmentMetrics_wind_gust_tag 16
|
||||
#define meshtastic_EnvironmentMetrics_wind_lull_tag 17
|
||||
#define meshtastic_EnvironmentMetrics_radiation_tag 18
|
||||
#define meshtastic_PowerMetrics_ch1_voltage_tag 1
|
||||
#define meshtastic_PowerMetrics_ch1_current_tag 2
|
||||
#define meshtastic_PowerMetrics_ch2_voltage_tag 3
|
||||
@@ -422,7 +428,8 @@ X(a, STATIC, OPTIONAL, UINT32, wind_direction, 13) \
|
||||
X(a, STATIC, OPTIONAL, FLOAT, wind_speed, 14) \
|
||||
X(a, STATIC, OPTIONAL, FLOAT, weight, 15) \
|
||||
X(a, STATIC, OPTIONAL, FLOAT, wind_gust, 16) \
|
||||
X(a, STATIC, OPTIONAL, FLOAT, wind_lull, 17)
|
||||
X(a, STATIC, OPTIONAL, FLOAT, wind_lull, 17) \
|
||||
X(a, STATIC, OPTIONAL, FLOAT, radiation, 18)
|
||||
#define meshtastic_EnvironmentMetrics_CALLBACK NULL
|
||||
#define meshtastic_EnvironmentMetrics_DEFAULT NULL
|
||||
|
||||
@@ -521,12 +528,12 @@ extern const pb_msgdesc_t meshtastic_Nau7802Config_msg;
|
||||
#define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_Telemetry_size
|
||||
#define meshtastic_AirQualityMetrics_size 78
|
||||
#define meshtastic_DeviceMetrics_size 27
|
||||
#define meshtastic_EnvironmentMetrics_size 85
|
||||
#define meshtastic_EnvironmentMetrics_size 91
|
||||
#define meshtastic_HealthMetrics_size 11
|
||||
#define meshtastic_LocalStats_size 60
|
||||
#define meshtastic_Nau7802Config_size 16
|
||||
#define meshtastic_PowerMetrics_size 30
|
||||
#define meshtastic_Telemetry_size 92
|
||||
#define meshtastic_Telemetry_size 98
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -74,6 +74,7 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
|
||||
|
||||
ResourceNode *nodeAPIv1ToRadioOptions = new ResourceNode("/api/v1/toradio", "OPTIONS", &handleAPIv1ToRadio);
|
||||
ResourceNode *nodeAPIv1ToRadio = new ResourceNode("/api/v1/toradio", "PUT", &handleAPIv1ToRadio);
|
||||
ResourceNode *nodeAPIv1FromRadioOptions = new ResourceNode("/api/v1/fromradio", "OPTIONS", &handleAPIv1FromRadio);
|
||||
ResourceNode *nodeAPIv1FromRadio = new ResourceNode("/api/v1/fromradio", "GET", &handleAPIv1FromRadio);
|
||||
|
||||
// ResourceNode *nodeHotspotApple = new ResourceNode("/hotspot-detect.html", "GET", &handleHotspot);
|
||||
@@ -100,6 +101,7 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
|
||||
// Secure nodes
|
||||
secureServer->registerNode(nodeAPIv1ToRadioOptions);
|
||||
secureServer->registerNode(nodeAPIv1ToRadio);
|
||||
secureServer->registerNode(nodeAPIv1FromRadioOptions);
|
||||
secureServer->registerNode(nodeAPIv1FromRadio);
|
||||
// secureServer->registerNode(nodeHotspotApple);
|
||||
// secureServer->registerNode(nodeHotspotAndroid);
|
||||
@@ -121,6 +123,7 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
|
||||
// Insecure nodes
|
||||
insecureServer->registerNode(nodeAPIv1ToRadioOptions);
|
||||
insecureServer->registerNode(nodeAPIv1ToRadio);
|
||||
insecureServer->registerNode(nodeAPIv1FromRadioOptions);
|
||||
insecureServer->registerNode(nodeAPIv1FromRadio);
|
||||
// insecureServer->registerNode(nodeHotspotApple);
|
||||
// insecureServer->registerNode(nodeHotspotAndroid);
|
||||
@@ -163,6 +166,12 @@ void handleAPIv1FromRadio(HTTPRequest *req, HTTPResponse *res)
|
||||
res->setHeader("Access-Control-Allow-Methods", "GET");
|
||||
res->setHeader("X-Protobuf-Schema", "https://raw.githubusercontent.com/meshtastic/protobufs/master/meshtastic/mesh.proto");
|
||||
|
||||
if (req->getMethod() == "OPTIONS") {
|
||||
res->setStatusCode(204); // Success with no content
|
||||
// res->print(""); @todo remove
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t txBuf[MAX_STREAM_BUF_SIZE];
|
||||
uint32_t len = 1;
|
||||
|
||||
|
||||
@@ -232,9 +232,9 @@ int handleAPIv1ToRadio(const struct _u_request *req, struct _u_response *res, vo
|
||||
ulfius_add_header_to_response(res, "X-Protobuf-Schema",
|
||||
"https://raw.githubusercontent.com/meshtastic/protobufs/master/meshtastic/mesh.proto");
|
||||
|
||||
if (req->http_verb == "OPTIONS") {
|
||||
if (strcmp(req->http_verb, "OPTIONS") == 0) {
|
||||
ulfius_set_response_properties(res, U_OPT_STATUS, 204);
|
||||
return U_CALLBACK_CONTINUE;
|
||||
return U_CALLBACK_COMPLETE;
|
||||
}
|
||||
|
||||
byte buffer[MAX_TO_FROM_RADIO_SIZE];
|
||||
@@ -269,6 +269,11 @@ int handleAPIv1FromRadio(const struct _u_request *req, struct _u_response *res,
|
||||
ulfius_add_header_to_response(res, "X-Protobuf-Schema",
|
||||
"https://raw.githubusercontent.com/meshtastic/protobufs/master/meshtastic/mesh.proto");
|
||||
|
||||
if (strcmp(req->http_verb, "OPTIONS") == 0) {
|
||||
ulfius_set_response_properties(res, U_OPT_STATUS, 204);
|
||||
return U_CALLBACK_COMPLETE;
|
||||
}
|
||||
|
||||
uint8_t txBuf[MAX_STREAM_BUF_SIZE];
|
||||
uint32_t len = 1;
|
||||
|
||||
@@ -493,7 +498,9 @@ PiWebServerThread::PiWebServerThread()
|
||||
// Maximum body size sent by the client is 1 Kb
|
||||
instanceWeb.max_post_body_size = 1024;
|
||||
ulfius_add_endpoint_by_val(&instanceWeb, "GET", PREFIX, "/api/v1/fromradio/*", 1, &handleAPIv1FromRadio, NULL);
|
||||
ulfius_add_endpoint_by_val(&instanceWeb, "OPTIONS", PREFIX, "/api/v1/fromradio/*", 1, &handleAPIv1FromRadio, NULL);
|
||||
ulfius_add_endpoint_by_val(&instanceWeb, "PUT", PREFIX, "/api/v1/toradio/*", 1, &handleAPIv1ToRadio, configWeb.rootPath);
|
||||
ulfius_add_endpoint_by_val(&instanceWeb, "OPTIONS", PREFIX, "/api/v1/toradio/*", 1, &handleAPIv1ToRadio, NULL);
|
||||
|
||||
// Add callback function to all endpoints for the Web Server
|
||||
ulfius_add_endpoint_by_val(&instanceWeb, "GET", NULL, "/*", 2, &callback_static_file, &configWeb);
|
||||
|
||||
@@ -66,13 +66,13 @@ static void onNetworkConnected()
|
||||
LOG_ERROR("Error setting up MDNS responder!");
|
||||
} else {
|
||||
LOG_INFO("mDNS Host: Meshtastic.local");
|
||||
MDNS.addService("meshtastic", "tcp", SERVER_API_DEFAULT_PORT);
|
||||
#ifdef ARCH_ESP32
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
MDNS.addService("https", "tcp", 443);
|
||||
// ESP32 prints obtained IP address in WiFiEvent
|
||||
#elif defined(ARCH_RP2040)
|
||||
// ARCH_RP2040 does not support HTTPS, create a "meshtastic" service
|
||||
MDNS.addService("meshtastic", "tcp", 4403);
|
||||
// ESP32 handles this in WiFiEvent
|
||||
// ARCH_RP2040 does not support HTTPS
|
||||
LOG_INFO("Obtained IP address: %s", WiFi.localIP().toString().c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#ifdef ARCH_PORTDUINO
|
||||
#include "unistd.h"
|
||||
#endif
|
||||
#include "../userPrefs.h"
|
||||
|
||||
#include "Default.h"
|
||||
#include "TypeConversions.h"
|
||||
|
||||
@@ -1123,4 +1123,4 @@ void disableBluetooth()
|
||||
nrf52Bluetooth->shutdown();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@ CannedMessageModule::CannedMessageModule()
|
||||
LOG_INFO("CannedMessageModule is enabled");
|
||||
|
||||
// T-Watch interface currently has no way to select destination type, so default to 'node'
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
#if defined(USE_VIRTUAL_KEYBOARD)
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NODE;
|
||||
#endif
|
||||
|
||||
@@ -81,7 +81,7 @@ int CannedMessageModule::splitConfiguredMessages()
|
||||
|
||||
String canned_messages = cannedMessageModuleConfig.messages;
|
||||
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
#if defined(USE_VIRTUAL_KEYBOARD)
|
||||
String separator = canned_messages.length() ? "|" : "";
|
||||
|
||||
canned_messages = "[---- Free Text ----]" + separator + canned_messages;
|
||||
@@ -150,7 +150,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
||||
}
|
||||
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT)) {
|
||||
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
#if defined(USE_VIRTUAL_KEYBOARD)
|
||||
if (this->currentMessageIndex == 0) {
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_FREETEXT;
|
||||
|
||||
@@ -177,7 +177,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
||||
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; // We want to change the list of frames shown on-screen
|
||||
this->currentMessageIndex = -1;
|
||||
|
||||
#if !defined(T_WATCH_S3) && !defined(RAK14014)
|
||||
#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD)
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
@@ -190,7 +190,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
||||
(event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) ||
|
||||
(event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT))) {
|
||||
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
#if defined(USE_VIRTUAL_KEYBOARD)
|
||||
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) {
|
||||
this->payload = INPUT_BROKER_MSG_LEFT;
|
||||
} else if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT)) {
|
||||
@@ -234,13 +234,13 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
||||
screen->decreaseBrightness();
|
||||
LOG_DEBUG("Decrease Screen Brightness");
|
||||
break;
|
||||
case INPUT_BROKER_MSG_FN_SYMBOL_ON: // draw modifier (function) symbal
|
||||
case INPUT_BROKER_MSG_FN_SYMBOL_ON: // draw modifier (function) symbol
|
||||
if (screen)
|
||||
screen->setFunctionSymbal("Fn");
|
||||
screen->setFunctionSymbol("Fn");
|
||||
break;
|
||||
case INPUT_BROKER_MSG_FN_SYMBOL_OFF: // remove modifier (function) symbal
|
||||
case INPUT_BROKER_MSG_FN_SYMBOL_OFF: // remove modifier (function) symbol
|
||||
if (screen)
|
||||
screen->removeFunctionSymbal("Fn");
|
||||
screen->removeFunctionSymbol("Fn");
|
||||
break;
|
||||
// mute (switch off/toggle) external notifications on fn+m
|
||||
case INPUT_BROKER_MSG_MUTE_TOGGLE:
|
||||
@@ -249,13 +249,13 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
||||
externalNotificationModule->setMute(false);
|
||||
showTemporaryMessage("Notifications \nEnabled");
|
||||
if (screen)
|
||||
screen->removeFunctionSymbal("M"); // remove the mute symbol from the bottom right corner
|
||||
screen->removeFunctionSymbol("M"); // remove the mute symbol from the bottom right corner
|
||||
} else {
|
||||
externalNotificationModule->stopNow(); // this will turn off all GPIO and sounds and idle the loop
|
||||
externalNotificationModule->setMute(true);
|
||||
showTemporaryMessage("Notifications \nDisabled");
|
||||
if (screen)
|
||||
screen->setFunctionSymbal("M"); // add the mute symbol to the bottom right corner
|
||||
screen->setFunctionSymbol("M"); // add the mute symbol to the bottom right corner
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -308,11 +308,11 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
||||
break;
|
||||
}
|
||||
if (screen && (event->kbchar != INPUT_BROKER_MSG_FN_SYMBOL_ON)) {
|
||||
screen->removeFunctionSymbal("Fn"); // remove modifier (function) symbal
|
||||
screen->removeFunctionSymbol("Fn"); // remove modifier (function) symbol
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
#if defined(USE_VIRTUAL_KEYBOARD)
|
||||
if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
|
||||
String keyTapped = keyForCoordinates(event->touchX, event->touchY);
|
||||
|
||||
@@ -446,7 +446,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
|
||||
#if !defined(T_WATCH_S3) && !defined(RAK14014)
|
||||
#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(SENSECAP_INDICATOR)
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
#endif
|
||||
|
||||
@@ -459,7 +459,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
|
||||
#if !defined(T_WATCH_S3) && !defined(RAK14014)
|
||||
#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD)
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
#endif
|
||||
|
||||
@@ -479,7 +479,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
return INT32_MAX;
|
||||
} else {
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
#if defined(USE_VIRTUAL_KEYBOARD)
|
||||
sendText(this->dest, indexChannels[this->channel], this->messages[this->currentMessageIndex], true);
|
||||
#else
|
||||
sendText(NODENUM_BROADCAST, channels.getPrimaryIndex(), this->messages[this->currentMessageIndex], true);
|
||||
@@ -496,7 +496,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
|
||||
#if !defined(T_WATCH_S3) && !defined(RAK14014)
|
||||
#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD)
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
#endif
|
||||
|
||||
@@ -513,7 +513,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
|
||||
#if !defined(T_WATCH_S3) && !defined(RAK14014)
|
||||
#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD)
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
#endif
|
||||
|
||||
@@ -526,7 +526,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
|
||||
#if !defined(T_WATCH_S3) && !defined(RAK14014)
|
||||
#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD)
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
#endif
|
||||
|
||||
@@ -672,7 +672,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
break;
|
||||
}
|
||||
if (screen)
|
||||
screen->removeFunctionSymbal("Fn");
|
||||
screen->removeFunctionSymbol("Fn");
|
||||
}
|
||||
|
||||
this->lastTouchMillis = millis();
|
||||
@@ -769,7 +769,7 @@ void CannedMessageModule::showTemporaryMessage(const String &message)
|
||||
setIntervalFromNow(2000);
|
||||
}
|
||||
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
#if defined(USE_VIRTUAL_KEYBOARD)
|
||||
|
||||
String CannedMessageModule::keyForCoordinates(uint x, uint y)
|
||||
{
|
||||
@@ -1055,7 +1055,7 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
||||
display->drawString(10 + x, 0 + y + FONT_HEIGHT_SMALL, "Canned Message\nModule disabled.");
|
||||
} else if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
|
||||
requestFocus(); // Tell Screen::setFrames to move to our module's frame
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
#if defined(USE_VIRTUAL_KEYBOARD)
|
||||
drawKeyboard(display, state, 0, 0);
|
||||
#else
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
|
||||
int getNextIndex();
|
||||
int getPrevIndex();
|
||||
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
#if defined(USE_VIRTUAL_KEYBOARD)
|
||||
void drawKeyboard(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
String keyForCoordinates(uint x, uint y);
|
||||
bool shift = false;
|
||||
@@ -156,7 +156,7 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
|
||||
unsigned long lastTouchMillis = 0;
|
||||
String temporaryMessage;
|
||||
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
#if defined(USE_VIRTUAL_KEYBOARD)
|
||||
Letter keyboard[2][4][10] = {{{{"Q", 20, 0, 0, 0, 0},
|
||||
{"W", 22, 0, 0, 0, 0},
|
||||
{"E", 17, 0, 0, 0, 0},
|
||||
|
||||
@@ -124,7 +124,8 @@ int32_t ExternalNotificationModule::runOnce()
|
||||
if (externalTurnedOn[2] + (moduleConfig.external_notification.output_ms ? moduleConfig.external_notification.output_ms
|
||||
: EXT_NOTIFICATION_MODULE_OUTPUT_MS) <
|
||||
millis()) {
|
||||
LOG_DEBUG("EXTERNAL 2 %d compared to %d", externalTurnedOn[2]+moduleConfig.external_notification.output_ms, millis());
|
||||
LOG_DEBUG("EXTERNAL 2 %d compared to %d", externalTurnedOn[2] + moduleConfig.external_notification.output_ms,
|
||||
millis());
|
||||
setExternalState(2, !getExternal(2));
|
||||
}
|
||||
#if defined(HAS_NCP5623) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE)
|
||||
|
||||
@@ -146,11 +146,20 @@ bool PositionModule::hasQualityTimesource()
|
||||
#if MESHTASTIC_EXCLUDE_GPS
|
||||
bool hasGpsOrRtc = (rtc_found.address != ScanI2C::ADDRESS_NONE.address);
|
||||
#else
|
||||
bool hasGpsOrRtc = (gps && gps->isConnected()) || (rtc_found.address != ScanI2C::ADDRESS_NONE.address);
|
||||
bool hasGpsOrRtc = hasGPS() || (rtc_found.address != ScanI2C::ADDRESS_NONE.address);
|
||||
#endif
|
||||
return hasGpsOrRtc || setFromPhoneOrNtpToday;
|
||||
}
|
||||
|
||||
bool PositionModule::hasGPS()
|
||||
{
|
||||
#if MESHTASTIC_EXCLUDE_GPS
|
||||
return false;
|
||||
#else
|
||||
return gps && gps->isConnected();
|
||||
#endif
|
||||
}
|
||||
|
||||
meshtastic_MeshPacket *PositionModule::allocReply()
|
||||
{
|
||||
if (precision == 0) {
|
||||
@@ -194,10 +203,21 @@ meshtastic_MeshPacket *PositionModule::allocReply()
|
||||
p.precision_bits = precision;
|
||||
p.has_latitude_i = true;
|
||||
p.has_longitude_i = true;
|
||||
p.time = getValidTime(RTCQualityNTP) > 0 ? getValidTime(RTCQualityNTP) : localPosition.time;
|
||||
// Always use NTP / GPS time if available
|
||||
if (getValidTime(RTCQualityNTP) > 0) {
|
||||
p.time = getValidTime(RTCQualityNTP);
|
||||
} else if (rtc_found.address != ScanI2C::ADDRESS_NONE.address) {
|
||||
LOG_INFO("Use RTC time for position");
|
||||
p.time = getValidTime(RTCQualityDevice);
|
||||
} else if (getRTCQuality() < RTCQualityNTP) {
|
||||
LOG_INFO("Strip low RTCQuality (%d) time from position", getRTCQuality());
|
||||
p.time = 0;
|
||||
}
|
||||
|
||||
if (config.position.fixed_position) {
|
||||
p.location_source = meshtastic_Position_LocSource_LOC_MANUAL;
|
||||
} else {
|
||||
p.location_source = localPosition.location_source;
|
||||
}
|
||||
|
||||
if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE) {
|
||||
@@ -242,20 +262,6 @@ meshtastic_MeshPacket *PositionModule::allocReply()
|
||||
p.has_ground_speed = true;
|
||||
}
|
||||
|
||||
// Strip out any time information before sending packets to other nodes - to keep the wire size small (and because other
|
||||
// nodes shouldn't trust it anyways) Note: we allow a device with a local GPS or NTP to include the time, so that devices
|
||||
// without can get time.
|
||||
if (getRTCQuality() < RTCQualityNTP) {
|
||||
LOG_INFO("Strip time %u from position", p.time);
|
||||
p.time = 0;
|
||||
} else if (rtc_found.address != ScanI2C::ADDRESS_NONE.address) {
|
||||
LOG_INFO("Use RTC time %u for position", p.time);
|
||||
p.time = getValidTime(RTCQualityDevice);
|
||||
} else {
|
||||
p.time = getValidTime(RTCQualityNTP);
|
||||
LOG_INFO("Provide time to mesh %u", p.time);
|
||||
}
|
||||
|
||||
LOG_INFO("Position reply: time=%i lat=%i lon=%i", p.time, p.latitude_i, p.longitude_i);
|
||||
|
||||
// TAK Tracker devices should send their position in a TAK packet over the ATAK port
|
||||
@@ -383,7 +389,7 @@ int32_t PositionModule::runOnce()
|
||||
}
|
||||
|
||||
if (lastGpsSend == 0 || msSinceLastSend >= intervalMs) {
|
||||
if (hasValidPosition(node)) {
|
||||
if (nodeDB->hasValidPosition(node)) {
|
||||
lastGpsSend = now;
|
||||
|
||||
lastGpsLatitude = node->position.latitude_i;
|
||||
@@ -397,7 +403,7 @@ int32_t PositionModule::runOnce()
|
||||
} else if (config.position.position_broadcast_smart_enabled) {
|
||||
const meshtastic_NodeInfoLite *node2 = service->refreshLocalMeshNode(); // should guarantee there is now a position
|
||||
|
||||
if (hasValidPosition(node2)) {
|
||||
if (nodeDB->hasValidPosition(node2)) {
|
||||
// The minimum time (in seconds) that would pass before we are able to send a new position packet.
|
||||
|
||||
auto smartPosition = getDistanceTraveledSinceLastSend(node->position);
|
||||
@@ -458,7 +464,7 @@ void PositionModule::handleNewPosition()
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||
const meshtastic_NodeInfoLite *node2 = service->refreshLocalMeshNode(); // should guarantee there is now a position
|
||||
// We limit our GPS broadcasts to a max rate
|
||||
if (hasValidPosition(node2)) {
|
||||
if (nodeDB->hasValidPosition(node2)) {
|
||||
auto smartPosition = getDistanceTraveledSinceLastSend(node->position);
|
||||
uint32_t msSinceLastSend = millis() - lastGpsSend;
|
||||
if (smartPosition.hasTraveledOverThreshold &&
|
||||
@@ -477,4 +483,4 @@ void PositionModule::handleNewPosition()
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -61,6 +61,7 @@ class PositionModule : public ProtobufModule<meshtastic_Position>, private concu
|
||||
uint32_t precision;
|
||||
void sendLostAndFoundText();
|
||||
bool hasQualityTimesource();
|
||||
bool hasGPS();
|
||||
|
||||
const uint32_t minimumTimeThreshold =
|
||||
Default::getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs, 30);
|
||||
|
||||
@@ -204,9 +204,11 @@ int32_t SerialModule::runOnce()
|
||||
lastNmeaTime = millis();
|
||||
uint32_t readIndex = 0;
|
||||
const meshtastic_NodeInfoLite *tempNodeInfo = nodeDB->readNextMeshNode(readIndex);
|
||||
while (tempNodeInfo != NULL && tempNodeInfo->has_user && hasValidPosition(tempNodeInfo)) {
|
||||
printWPL(outbuf, sizeof(outbuf), tempNodeInfo->position, tempNodeInfo->user.long_name, true);
|
||||
serialPrint->printf("%s", outbuf);
|
||||
while (tempNodeInfo != NULL) {
|
||||
if (tempNodeInfo->has_user && nodeDB->hasValidPosition(tempNodeInfo)) {
|
||||
printWPL(outbuf, sizeof(outbuf), tempNodeInfo->position, tempNodeInfo->user.long_name, true);
|
||||
serialPrint->printf("%s", outbuf);
|
||||
}
|
||||
tempNodeInfo = nodeDB->readNextMeshNode(readIndex);
|
||||
}
|
||||
}
|
||||
@@ -472,7 +474,7 @@ void SerialModule::processWXSerial()
|
||||
if (windDirPos != NULL) {
|
||||
// Extract data after "=" for WindDir
|
||||
strcpy(windDir, windDirPos + 15); // Add 15 to skip "WindDir = "
|
||||
double radians = toRadians(strtof(windDir, nullptr));
|
||||
double radians = GeoCoord::toRadians(strtof(windDir, nullptr));
|
||||
dir_sum_sin += sin(radians);
|
||||
dir_sum_cos += cos(radians);
|
||||
dirCount++;
|
||||
@@ -539,7 +541,7 @@ void SerialModule::processWXSerial()
|
||||
double avgCos = dir_sum_cos / dirCount;
|
||||
|
||||
double avgRadians = atan2(avgSin, avgCos);
|
||||
float dirAvg = toDegrees(avgRadians);
|
||||
float dirAvg = GeoCoord::toDegrees(avgRadians);
|
||||
|
||||
if (dirAvg < 0) {
|
||||
dirAvg += 360.0;
|
||||
|
||||
@@ -77,9 +77,10 @@ meshtastic_MeshPacket *DeviceTelemetryModule::allocReply()
|
||||
// Check for a request for device metrics
|
||||
if (decoded->which_variant == meshtastic_Telemetry_device_metrics_tag) {
|
||||
LOG_INFO("Device telemetry reply to request");
|
||||
|
||||
meshtastic_Telemetry telemetry = getDeviceTelemetry();
|
||||
return allocDataProtobuf(telemetry);
|
||||
return allocDataProtobuf(getDeviceTelemetry());
|
||||
} else if (decoded->which_variant == meshtastic_Telemetry_local_stats_tag) {
|
||||
LOG_INFO("Device telemetry reply w/ LocalStats to request");
|
||||
return allocDataProtobuf(getLocalStatsTelemetry());
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@@ -112,7 +113,7 @@ meshtastic_Telemetry DeviceTelemetryModule::getDeviceTelemetry()
|
||||
return t;
|
||||
}
|
||||
|
||||
void DeviceTelemetryModule::sendLocalStatsToPhone()
|
||||
meshtastic_Telemetry DeviceTelemetryModule::getLocalStatsTelemetry()
|
||||
{
|
||||
meshtastic_Telemetry telemetry = meshtastic_Telemetry_init_zero;
|
||||
telemetry.which_variant = meshtastic_Telemetry_local_stats_tag;
|
||||
@@ -129,6 +130,14 @@ void DeviceTelemetryModule::sendLocalStatsToPhone()
|
||||
telemetry.variant.local_stats.num_packets_rx_bad = RadioLibInterface::instance->rxBad;
|
||||
telemetry.variant.local_stats.num_tx_relay = RadioLibInterface::instance->txRelay;
|
||||
}
|
||||
#ifdef ARCH_PORTDUINO
|
||||
if (SimRadio::instance) {
|
||||
telemetry.variant.local_stats.num_packets_tx = SimRadio::instance->txGood;
|
||||
telemetry.variant.local_stats.num_packets_rx = SimRadio::instance->rxGood + SimRadio::instance->rxBad;
|
||||
telemetry.variant.local_stats.num_packets_rx_bad = SimRadio::instance->rxBad;
|
||||
telemetry.variant.local_stats.num_tx_relay = SimRadio::instance->txRelay;
|
||||
}
|
||||
#endif
|
||||
if (router) {
|
||||
telemetry.variant.local_stats.num_rx_dupe = router->rxDupe;
|
||||
telemetry.variant.local_stats.num_tx_relay_canceled = router->txRelayCanceled;
|
||||
@@ -142,7 +151,12 @@ void DeviceTelemetryModule::sendLocalStatsToPhone()
|
||||
LOG_INFO("num_packets_tx=%i, num_packets_rx=%i, num_packets_rx_bad=%i", telemetry.variant.local_stats.num_packets_tx,
|
||||
telemetry.variant.local_stats.num_packets_rx, telemetry.variant.local_stats.num_packets_rx_bad);
|
||||
|
||||
meshtastic_MeshPacket *p = allocDataProtobuf(telemetry);
|
||||
return telemetry;
|
||||
}
|
||||
|
||||
void DeviceTelemetryModule::sendLocalStatsToPhone()
|
||||
{
|
||||
meshtastic_MeshPacket *p = allocDataProtobuf(getLocalStatsTelemetry());
|
||||
p->to = NODENUM_BROADCAST;
|
||||
p->decoded.want_response = false;
|
||||
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
|
||||
|
||||
@@ -42,6 +42,8 @@ class DeviceTelemetryModule : private concurrency::OSThread, public ProtobufModu
|
||||
|
||||
private:
|
||||
meshtastic_Telemetry getDeviceTelemetry();
|
||||
meshtastic_Telemetry getLocalStatsTelemetry();
|
||||
|
||||
void sendLocalStatsToPhone();
|
||||
uint32_t sendToPhoneIntervalMs = SECONDS_IN_MINUTE * 1000; // Send to phone every minute
|
||||
uint32_t sendStatsToPhoneIntervalMs = 15 * SECONDS_IN_MINUTE * 1000; // Send stats to phone every 15 minutes
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "Sensor/BMP085Sensor.h"
|
||||
#include "Sensor/BMP280Sensor.h"
|
||||
#include "Sensor/BMP3XXSensor.h"
|
||||
#include "Sensor/CGRadSensSensor.h"
|
||||
#include "Sensor/DFRobotLarkSensor.h"
|
||||
#include "Sensor/LPS22HBSensor.h"
|
||||
#include "Sensor/MCP9808Sensor.h"
|
||||
@@ -60,6 +61,7 @@ BMP3XXSensor bmp3xxSensor;
|
||||
#ifdef T1000X_SENSOR_EN
|
||||
T1000xSensor t1000xSensor;
|
||||
#endif
|
||||
CGRadSensSensor cgRadSens;
|
||||
|
||||
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
|
||||
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
|
||||
@@ -147,6 +149,8 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
||||
result = nau7802Sensor.runOnce();
|
||||
if (max17048Sensor.hasSensor())
|
||||
result = max17048Sensor.runOnce();
|
||||
if (cgRadSens.hasSensor())
|
||||
result = cgRadSens.runOnce();
|
||||
#endif
|
||||
}
|
||||
return result;
|
||||
@@ -210,16 +214,19 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt
|
||||
// Display "Env. From: ..." on its own
|
||||
display->drawString(x, y, "Env. From: " + String(lastSender) + "(" + String(agoSecs) + "s)");
|
||||
|
||||
String last_temp = String(lastMeasurement.variant.environment_metrics.temperature, 0) + "°C";
|
||||
if (moduleConfig.telemetry.environment_display_fahrenheit) {
|
||||
last_temp =
|
||||
String(UnitConversions::CelsiusToFahrenheit(lastMeasurement.variant.environment_metrics.temperature), 0) + "°F";
|
||||
}
|
||||
if (lastMeasurement.variant.environment_metrics.has_temperature ||
|
||||
lastMeasurement.variant.environment_metrics.has_relative_humidity) {
|
||||
String last_temp = String(lastMeasurement.variant.environment_metrics.temperature, 0) + "°C";
|
||||
if (moduleConfig.telemetry.environment_display_fahrenheit) {
|
||||
last_temp =
|
||||
String(UnitConversions::CelsiusToFahrenheit(lastMeasurement.variant.environment_metrics.temperature), 0) + "°F";
|
||||
}
|
||||
|
||||
// Continue with the remaining details
|
||||
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||
"Temp/Hum: " + last_temp + " / " +
|
||||
String(lastMeasurement.variant.environment_metrics.relative_humidity, 0) + "%");
|
||||
// Continue with the remaining details
|
||||
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||
"Temp/Hum: " + last_temp + " / " +
|
||||
String(lastMeasurement.variant.environment_metrics.relative_humidity, 0) + "%");
|
||||
}
|
||||
|
||||
if (lastMeasurement.variant.environment_metrics.barometric_pressure != 0) {
|
||||
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||
@@ -243,6 +250,10 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt
|
||||
if (lastMeasurement.variant.environment_metrics.weight != 0)
|
||||
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||
"Weight: " + String(lastMeasurement.variant.environment_metrics.weight, 0) + "kg");
|
||||
|
||||
if (lastMeasurement.variant.environment_metrics.radiation != 0)
|
||||
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||
"Rad: " + String(lastMeasurement.variant.environment_metrics.radiation, 2) + "µR/h");
|
||||
}
|
||||
|
||||
bool EnvironmentTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t)
|
||||
@@ -263,6 +274,8 @@ bool EnvironmentTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPac
|
||||
t->variant.environment_metrics.wind_speed, t->variant.environment_metrics.wind_direction,
|
||||
t->variant.environment_metrics.weight);
|
||||
|
||||
LOG_INFO("(Received from %s): radiation=%fµR/h", sender, t->variant.environment_metrics.radiation);
|
||||
|
||||
#endif
|
||||
// release previous packet before occupying a new spot
|
||||
if (lastMeasurementPacket != nullptr)
|
||||
@@ -390,6 +403,10 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m
|
||||
valid = valid && max17048Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (cgRadSens.hasSensor()) {
|
||||
valid = valid && cgRadSens.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
|
||||
#endif
|
||||
return valid && hasSensor;
|
||||
@@ -443,6 +460,8 @@ bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
|
||||
LOG_INFO("Send: wind speed=%fm/s, direction=%d degrees, weight=%fkg", m.variant.environment_metrics.wind_speed,
|
||||
m.variant.environment_metrics.wind_direction, m.variant.environment_metrics.weight);
|
||||
|
||||
LOG_INFO("Send: radiation=%fµR/h", m.variant.environment_metrics.radiation);
|
||||
|
||||
sensor_read_error_count = 0;
|
||||
|
||||
meshtastic_MeshPacket *p = allocDataProtobuf(m);
|
||||
@@ -585,6 +604,11 @@ AdminMessageHandleResult EnvironmentTelemetryModule::handleAdminMessageForModule
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (cgRadSens.hasSensor()) {
|
||||
result = cgRadSens.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Support for the ClimateGuard RadSens Dosimeter
|
||||
* A fun and educational sensor for Meshtastic; not for safety critical applications.
|
||||
*/
|
||||
#include "configuration.h"
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
|
||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include "CGRadSensSensor.h"
|
||||
#include "TelemetrySensor.h"
|
||||
#include <Wire.h>
|
||||
#include <typeinfo>
|
||||
|
||||
CGRadSensSensor::CGRadSensSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_RADSENS, "RadSens") {}
|
||||
|
||||
int32_t CGRadSensSensor::runOnce()
|
||||
{
|
||||
// Initialize the sensor following the same pattern as RCWL9620Sensor
|
||||
LOG_INFO("Init sensor: %s", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
|
||||
status = true;
|
||||
begin(nodeTelemetrySensorsMap[sensorType].second, nodeTelemetrySensorsMap[sensorType].first);
|
||||
|
||||
return initI2CSensor();
|
||||
}
|
||||
|
||||
void CGRadSensSensor::setup() {}
|
||||
|
||||
void CGRadSensSensor::begin(TwoWire *wire, uint8_t addr)
|
||||
{
|
||||
// Store the Wire and address to the sensor following the same pattern as RCWL9620Sensor
|
||||
_wire = wire;
|
||||
_addr = addr;
|
||||
_wire->begin();
|
||||
}
|
||||
|
||||
float CGRadSensSensor::getStaticRadiation()
|
||||
{
|
||||
// Read a register, following the same pattern as the RCWL9620Sensor
|
||||
uint32_t data;
|
||||
_wire->beginTransmission(_addr); // Transfer data to addr.
|
||||
_wire->write(0x06); // Radiation intensity (static period T = 500 sec)
|
||||
if (_wire->endTransmission() == 0) {
|
||||
if (_wire->requestFrom(_addr, (uint8_t)3)) {
|
||||
; // Request 3 bytes
|
||||
data = _wire->read();
|
||||
data <<= 8;
|
||||
data |= _wire->read();
|
||||
data <<= 8;
|
||||
data |= _wire->read();
|
||||
|
||||
// As per the data sheet for the RadSens
|
||||
// Register 0x06 contains the reading in 0.1 * μR / h
|
||||
float microRadPerHr = float(data) / 10.0;
|
||||
return microRadPerHr;
|
||||
}
|
||||
}
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
bool CGRadSensSensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
{
|
||||
// Store the meansurement in the the appropriate fields of the protobuf
|
||||
measurement->variant.environment_metrics.has_radiation = true;
|
||||
|
||||
LOG_DEBUG("CGRADSENS getMetrics");
|
||||
measurement->variant.environment_metrics.radiation = getStaticRadiation();
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Support for the ClimateGuard RadSens Dosimeter
|
||||
* A fun and educational sensor for Meshtastic; not for safety critical applications.
|
||||
*/
|
||||
#include "configuration.h"
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
|
||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include "TelemetrySensor.h"
|
||||
#include <Wire.h>
|
||||
|
||||
class CGRadSensSensor : public TelemetrySensor
|
||||
{
|
||||
private:
|
||||
uint8_t _addr = 0x66;
|
||||
TwoWire *_wire = &Wire;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
void begin(TwoWire *wire = &Wire, uint8_t addr = 0x66);
|
||||
float getStaticRadiation();
|
||||
|
||||
public:
|
||||
CGRadSensSensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -126,7 +126,7 @@ void WaypointModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state,
|
||||
}
|
||||
|
||||
// If our node has a position:
|
||||
if (ourNode && (hasValidPosition(ourNode) || screen->hasHeading())) {
|
||||
if (ourNode && (nodeDB->hasValidPosition(ourNode) || screen->hasHeading())) {
|
||||
const meshtastic_PositionLite &op = ourNode->position;
|
||||
float myHeading;
|
||||
if (screen->hasHeading())
|
||||
|
||||
@@ -95,7 +95,9 @@ int32_t PaxcounterModule::runOnce()
|
||||
|
||||
// internal processing initialization
|
||||
libpax_counter_init(handlePaxCounterReportRequest, &count_from_libpax,
|
||||
moduleConfig.paxcounter.paxcounter_update_interval, 0);
|
||||
Default::getConfiguredOrDefault(moduleConfig.paxcounter.paxcounter_update_interval,
|
||||
default_telemetry_broadcast_interval_secs),
|
||||
0);
|
||||
libpax_counter_start();
|
||||
} else {
|
||||
sendInfo(NODENUM_BROADCAST);
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
||||
|
||||
#include "../concurrency/OSThread.h"
|
||||
#ifdef HAS_BMA423
|
||||
#include "BMA423Sensor.h"
|
||||
#endif
|
||||
#include "BMX160Sensor.h"
|
||||
#include "ICM20948Sensor.h"
|
||||
#include "LIS3DHSensor.h"
|
||||
@@ -17,7 +19,9 @@
|
||||
#ifdef HAS_QMA6100P
|
||||
#include "QMA6100PSensor.h"
|
||||
#endif
|
||||
#ifdef HAS_STK8XXX
|
||||
#include "STK8XXXSensor.h"
|
||||
#endif
|
||||
|
||||
extern ScanI2C::DeviceAddress accelerometer_found;
|
||||
|
||||
@@ -79,9 +83,11 @@ class AccelerometerThread : public concurrency::OSThread
|
||||
#endif
|
||||
|
||||
switch (device.type) {
|
||||
#ifdef HAS_BMA423
|
||||
case ScanI2C::DeviceType::BMA423:
|
||||
sensor = new BMA423Sensor(device);
|
||||
break;
|
||||
#endif
|
||||
case ScanI2C::DeviceType::MPU6050:
|
||||
sensor = new MPU6050Sensor(device);
|
||||
break;
|
||||
@@ -94,9 +100,11 @@ class AccelerometerThread : public concurrency::OSThread
|
||||
case ScanI2C::DeviceType::LSM6DS3:
|
||||
sensor = new LSM6DS3Sensor(device);
|
||||
break;
|
||||
#ifdef HAS_STK8XXX
|
||||
case ScanI2C::DeviceType::STK8BAXX:
|
||||
sensor = new STK8XXXSensor(device);
|
||||
break;
|
||||
#endif
|
||||
case ScanI2C::DeviceType::ICM20948:
|
||||
sensor = new ICM20948Sensor(device);
|
||||
break;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "BMA423Sensor.h"
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_BMA423)
|
||||
|
||||
using namespace MotionSensorI2C;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include "MotionSensor.h"
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_BMA423)
|
||||
|
||||
#include <SensorBMA423.hpp>
|
||||
#include <Wire.h>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "STK8XXXSensor.h"
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_STK8XXX)
|
||||
|
||||
STK8XXXSensor::STK8XXXSensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::MotionSensor(foundDevice) {}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include "MotionSensor.h"
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_STK8XXX)
|
||||
|
||||
#ifdef STK8XXX_INT
|
||||
|
||||
|
||||
+15
-4
@@ -167,17 +167,26 @@ void MQTT::onReceive(char *topic, byte *payload, size_t length)
|
||||
if (isFromUs(p)) {
|
||||
LOG_INFO("Ignore downlink message we originally sent");
|
||||
packetPool.release(p);
|
||||
free(e.channel_id);
|
||||
free(e.gateway_id);
|
||||
free(e.packet);
|
||||
return;
|
||||
}
|
||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||
if (moduleConfig.mqtt.encryption_enabled) {
|
||||
LOG_INFO("Ignore decoded message on MQTT, encryption is enabled");
|
||||
packetPool.release(p);
|
||||
free(e.channel_id);
|
||||
free(e.gateway_id);
|
||||
free(e.packet);
|
||||
return;
|
||||
}
|
||||
if (p->decoded.portnum == meshtastic_PortNum_ADMIN_APP) {
|
||||
LOG_INFO("Ignore decoded admin packet");
|
||||
packetPool.release(p);
|
||||
free(e.channel_id);
|
||||
free(e.gateway_id);
|
||||
free(e.packet);
|
||||
return;
|
||||
}
|
||||
p->channel = ch.index;
|
||||
@@ -336,7 +345,7 @@ void MQTT::reconnect()
|
||||
mqttPassword = moduleConfig.mqtt.password;
|
||||
}
|
||||
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(RPI_PICO)
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C6)
|
||||
if (moduleConfig.mqtt.tls_enabled) {
|
||||
// change default for encrypted to 8883
|
||||
try {
|
||||
@@ -545,9 +554,11 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp_encrypted, const meshtastic_Me
|
||||
|
||||
// mp_decoded will not be decoded when it's PKI encrypted and not directed to us
|
||||
if (mp_decoded.which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||
// For uplinking other's packets, check if it's not OK to MQTT or if it's an older packet without the bitfield
|
||||
bool dontUplink = !mp_decoded.decoded.has_bitfield ||
|
||||
(mp_decoded.decoded.has_bitfield && !(mp_decoded.decoded.bitfield & BITFIELD_OK_TO_MQTT_MASK));
|
||||
// check for the lowest bit of the data bitfield set false, and the use of one of the default keys.
|
||||
if (!isFromUs(&mp_decoded) && !isMqttServerAddressPrivate && mp_decoded.decoded.has_bitfield &&
|
||||
!(mp_decoded.decoded.bitfield & BITFIELD_OK_TO_MQTT_MASK) &&
|
||||
if (!isFromUs(&mp_decoded) && !isMqttServerAddressPrivate && dontUplink &&
|
||||
(ch.settings.psk.size < 2 || (ch.settings.psk.size == 16 && memcmp(ch.settings.psk.bytes, defaultpsk, 16)) ||
|
||||
(ch.settings.psk.size == 32 && memcmp(ch.settings.psk.bytes, eventpsk, 32)))) {
|
||||
LOG_INFO("MQTT onSend - Not forwarding packet due to DontMqttMeBro flag");
|
||||
@@ -769,4 +780,4 @@ bool MQTT::isPrivateIpAddress(const char address[])
|
||||
|
||||
int octet2Num = atoi(octet2);
|
||||
return octet2Num >= 16 && octet2Num <= 31;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -35,7 +35,7 @@ class MQTT : private concurrency::OSThread
|
||||
#if HAS_WIFI
|
||||
WiFiClient mqttClient;
|
||||
#if !defined(ARCH_PORTDUINO)
|
||||
#if defined(ESP_ARDUINO_VERSION_MAJOR) && ESP_ARDUINO_VERSION_MAJOR < 3
|
||||
#if (defined(ESP_ARDUINO_VERSION_MAJOR) && ESP_ARDUINO_VERSION_MAJOR < 3) || defined(RPI_PICO)
|
||||
WiFiClientSecure wifiSecureClient;
|
||||
#endif
|
||||
#endif
|
||||
@@ -130,4 +130,4 @@ class MQTT : private concurrency::OSThread
|
||||
|
||||
void mqttInit();
|
||||
|
||||
extern MQTT *mqtt;
|
||||
extern MQTT *mqtt;
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
#define HW_VENDOR meshtastic_HardwareModel_PPR
|
||||
#elif defined(RAK2560)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_RAK2560
|
||||
#elif defined(WISMESH_TAP)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_WISMESH_TAP
|
||||
#elif defined(RAK4630)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_RAK4631
|
||||
#elif defined(TTGO_T_ECHO)
|
||||
|
||||
@@ -5,21 +5,27 @@
|
||||
#include "sleep.h"
|
||||
#include "target_specific.h"
|
||||
|
||||
#include "PortduinoGlue.h"
|
||||
#include "api/ServerAPI.h"
|
||||
#include "linux/gpio/LinuxGPIOPin.h"
|
||||
#include "meshUtils.h"
|
||||
#include "yaml-cpp/yaml.h"
|
||||
#include <Utility.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "PortduinoGlue.h"
|
||||
#include "linux/gpio/LinuxGPIOPin.h"
|
||||
#include "yaml-cpp/yaml.h"
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/hci.h>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
std::map<configNames, int> settingsMap;
|
||||
std::map<configNames, std::string> settingsStrings;
|
||||
std::ofstream traceFile;
|
||||
char *configPath = nullptr;
|
||||
char *optionMac = nullptr;
|
||||
|
||||
// FIXME - move setBluetoothEnable into a HALPlatform class
|
||||
void setBluetoothEnable(bool enable)
|
||||
@@ -34,7 +40,7 @@ void cpuDeepSleep(uint32_t msecs)
|
||||
|
||||
void updateBatteryLevel(uint8_t level) NOT_IMPLEMENTED("updateBatteryLevel");
|
||||
|
||||
int TCPPort = 4403;
|
||||
int TCPPort = SERVER_API_DEFAULT_PORT;
|
||||
|
||||
static error_t parse_opt(int key, char *arg, struct argp_state *state)
|
||||
{
|
||||
@@ -48,6 +54,10 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
|
||||
case 'c':
|
||||
configPath = arg;
|
||||
break;
|
||||
case 'h':
|
||||
optionMac = arg;
|
||||
break;
|
||||
|
||||
case ARGP_KEY_ARG:
|
||||
return 0;
|
||||
default:
|
||||
@@ -60,6 +70,7 @@ void portduinoCustomInit()
|
||||
{
|
||||
static struct argp_option options[] = {{"port", 'p', "PORT", 0, "The TCP port to use."},
|
||||
{"config", 'c', "CONFIG_PATH", 0, "Full path of the .yaml config file to use."},
|
||||
{"hwid", 'h', "HWID", 0, "The mac address to assign to this virtual machine"},
|
||||
{0}};
|
||||
static void *childArguments;
|
||||
static char doc[] = "Meshtastic native build.";
|
||||
@@ -69,6 +80,51 @@ void portduinoCustomInit()
|
||||
portduinoAddArguments(child, childArguments);
|
||||
}
|
||||
|
||||
void getMacAddr(uint8_t *dmac)
|
||||
{
|
||||
// We should store this value, and short-circuit all this if it's already been set.
|
||||
if (optionMac != nullptr && strlen(optionMac) > 0) {
|
||||
if (strlen(optionMac) >= 12) {
|
||||
MAC_from_string(optionMac, dmac);
|
||||
std::cout << optionMac << std::endl;
|
||||
} else {
|
||||
uint32_t hwId = sscanf(optionMac, "%u", &hwId);
|
||||
dmac[0] = 0x80;
|
||||
dmac[1] = 0;
|
||||
dmac[2] = hwId >> 24;
|
||||
dmac[3] = hwId >> 16;
|
||||
dmac[4] = hwId >> 8;
|
||||
dmac[5] = hwId & 0xff;
|
||||
}
|
||||
} else if (settingsStrings[mac_address].length() > 11) {
|
||||
MAC_from_string(settingsStrings[mac_address], dmac);
|
||||
std::cout << settingsStrings[mac_address] << std::endl;
|
||||
exit;
|
||||
} else {
|
||||
|
||||
struct hci_dev_info di;
|
||||
di.dev_id = 0;
|
||||
bdaddr_t bdaddr;
|
||||
char addr[18];
|
||||
int btsock;
|
||||
btsock = socket(AF_BLUETOOTH, SOCK_RAW, 1);
|
||||
if (btsock < 0) { // If anything fails, just return with the default value
|
||||
return;
|
||||
}
|
||||
|
||||
if (ioctl(btsock, HCIGETDEVINFO, (void *)&di)) {
|
||||
return;
|
||||
}
|
||||
|
||||
dmac[0] = di.bdaddr.b[5];
|
||||
dmac[1] = di.bdaddr.b[4];
|
||||
dmac[2] = di.bdaddr.b[3];
|
||||
dmac[3] = di.bdaddr.b[2];
|
||||
dmac[4] = di.bdaddr.b[1];
|
||||
dmac[5] = di.bdaddr.b[0];
|
||||
}
|
||||
}
|
||||
|
||||
/** apps run under portduino can optionally define a portduinoSetup() to
|
||||
* use portduino specific init code (such as gpioBind) to setup portduino on their host machine,
|
||||
* before running 'arduino' code.
|
||||
@@ -113,10 +169,20 @@ void portduinoSetup()
|
||||
std::cout << "Unable to use " << configPath << " as config file" << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (access("config.yaml", R_OK) == 0 && loadConfig("config.yaml")) {
|
||||
std::cout << "Using local config.yaml as config file" << std::endl;
|
||||
} else if (access("/etc/meshtasticd/config.yaml", R_OK) == 0 && loadConfig("/etc/meshtasticd/config.yaml")) {
|
||||
std::cout << "Using /etc/meshtasticd/config.yaml as config file" << std::endl;
|
||||
} else if (access("config.yaml", R_OK) == 0) {
|
||||
if (loadConfig("config.yaml")) {
|
||||
std::cout << "Using local config.yaml as config file" << std::endl;
|
||||
} else {
|
||||
std::cout << "Unable to use local config.yaml as config file" << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (access("/etc/meshtasticd/config.yaml", R_OK) == 0) {
|
||||
if (loadConfig("/etc/meshtasticd/config.yaml")) {
|
||||
std::cout << "Using /etc/meshtasticd/config.yaml as config file" << std::endl;
|
||||
} else {
|
||||
std::cout << "Unable to use /etc/meshtasticd/config.yaml as config file" << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
std::cout << "No 'config.yaml' found, running simulated." << std::endl;
|
||||
settingsMap[maxnodes] = 200; // Default to 200 nodes
|
||||
@@ -137,6 +203,14 @@ void portduinoSetup()
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t dmac[6];
|
||||
getMacAddr(dmac);
|
||||
if (dmac[0] == 0 && dmac[1] == 0 && dmac[2] == 0 && dmac[3] == 0 && dmac[4] == 0 && dmac[5] == 0) {
|
||||
std::cout << "*** Blank MAC Address not allowed!" << std::endl;
|
||||
std::cout << "Please set a MAC Address in config.yaml using either MACAddress or MACAddressSource." << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
printBytes("MAC Address: ", dmac, 6);
|
||||
// Rather important to set this, if not running simulated.
|
||||
randomSeed(time(NULL));
|
||||
|
||||
@@ -272,6 +346,9 @@ bool loadConfig(const char *configPath)
|
||||
settingsMap[use_sx1262] = false;
|
||||
settingsMap[use_rf95] = false;
|
||||
settingsMap[use_sx1280] = false;
|
||||
settingsMap[use_lr1110] = false;
|
||||
settingsMap[use_lr1120] = false;
|
||||
settingsMap[use_lr1121] = false;
|
||||
settingsMap[use_sx1268] = false;
|
||||
|
||||
if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "sx1262") {
|
||||
@@ -280,6 +357,12 @@ bool loadConfig(const char *configPath)
|
||||
settingsMap[use_rf95] = true;
|
||||
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "sx1280") {
|
||||
settingsMap[use_sx1280] = true;
|
||||
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "lr1110") {
|
||||
settingsMap[use_lr1110] = true;
|
||||
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "lr1120") {
|
||||
settingsMap[use_lr1120] = true;
|
||||
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "lr1121") {
|
||||
settingsMap[use_lr1121] = true;
|
||||
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "sx1268") {
|
||||
settingsMap[use_sx1268] = true;
|
||||
}
|
||||
@@ -404,8 +487,23 @@ bool loadConfig(const char *configPath)
|
||||
settingsMap[maxnodes] = (yamlConfig["General"]["MaxNodes"]).as<int>(200);
|
||||
settingsMap[maxtophone] = (yamlConfig["General"]["MaxMessageQueue"]).as<int>(100);
|
||||
settingsStrings[config_directory] = (yamlConfig["General"]["ConfigDirectory"]).as<std::string>("");
|
||||
}
|
||||
if ((yamlConfig["General"]["MACAddress"]).as<std::string>("") != "" &&
|
||||
(yamlConfig["General"]["MACAddressSource"]).as<std::string>("") != "") {
|
||||
std::cout << "Cannot set both MACAddress and MACAddressSource!" << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
settingsStrings[mac_address] = (yamlConfig["General"]["MACAddress"]).as<std::string>("");
|
||||
if ((yamlConfig["General"]["MACAddressSource"]).as<std::string>("") != "") {
|
||||
std::ifstream infile("/sys/class/net/" + (yamlConfig["General"]["MACAddressSource"]).as<std::string>("") +
|
||||
"/address");
|
||||
std::getline(infile, settingsStrings[mac_address]);
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/20326454
|
||||
settingsStrings[mac_address].erase(
|
||||
std::remove(settingsStrings[mac_address].begin(), settingsStrings[mac_address].end(), ':'),
|
||||
settingsStrings[mac_address].end());
|
||||
}
|
||||
} catch (YAML::Exception &e) {
|
||||
std::cout << "*** Exception " << e.what() << std::endl;
|
||||
return false;
|
||||
@@ -417,4 +515,20 @@ bool loadConfig(const char *configPath)
|
||||
static bool ends_with(std::string_view str, std::string_view suffix)
|
||||
{
|
||||
return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
|
||||
}
|
||||
|
||||
bool MAC_from_string(std::string mac_str, uint8_t *dmac)
|
||||
{
|
||||
mac_str.erase(std::remove(mac_str.begin(), mac_str.end(), ':'), mac_str.end());
|
||||
if (mac_str.length() == 12) {
|
||||
dmac[0] = std::stoi(settingsStrings[mac_address].substr(0, 2), nullptr, 16);
|
||||
dmac[1] = std::stoi(settingsStrings[mac_address].substr(2, 2), nullptr, 16);
|
||||
dmac[2] = std::stoi(settingsStrings[mac_address].substr(4, 2), nullptr, 16);
|
||||
dmac[3] = std::stoi(settingsStrings[mac_address].substr(6, 2), nullptr, 16);
|
||||
dmac[4] = std::stoi(settingsStrings[mac_address].substr(8, 2), nullptr, 16);
|
||||
dmac[5] = std::stoi(settingsStrings[mac_address].substr(10, 2), nullptr, 16);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,9 @@ enum configNames {
|
||||
ch341Quirk,
|
||||
use_rf95,
|
||||
use_sx1280,
|
||||
use_lr1110,
|
||||
use_lr1120,
|
||||
use_lr1121,
|
||||
use_sx1268,
|
||||
user,
|
||||
gpiochip,
|
||||
@@ -56,7 +59,8 @@ enum configNames {
|
||||
maxtophone,
|
||||
maxnodes,
|
||||
ascii_logs,
|
||||
config_directory
|
||||
config_directory,
|
||||
mac_address
|
||||
};
|
||||
enum { no_screen, x11, st7789, st7735, st7735s, st7796, ili9341, ili9342, ili9488, hx8357d };
|
||||
enum { no_touchscreen, xpt2046, stmpe610, gt911, ft5x06 };
|
||||
@@ -67,4 +71,6 @@ extern std::map<configNames, std::string> settingsStrings;
|
||||
extern std::ofstream traceFile;
|
||||
int initGPIOPin(int pinNum, std::string gpioChipname);
|
||||
bool loadConfig(const char *configPath);
|
||||
static bool ends_with(std::string_view str, std::string_view suffix);
|
||||
static bool ends_with(std::string_view str, std::string_view suffix);
|
||||
void getMacAddr(uint8_t *dmac);
|
||||
bool MAC_from_string(std::string mac_str, uint8_t *dmac);
|
||||
@@ -73,6 +73,10 @@ void SimRadio::handleTransmitInterrupt()
|
||||
// ignore the transmit interrupt
|
||||
if (sendingPacket)
|
||||
completeSending();
|
||||
|
||||
isReceiving = true;
|
||||
if (receivingPacket) // This happens when we don't consider something a collision if we weren't sending long enough
|
||||
handleReceiveInterrupt();
|
||||
}
|
||||
|
||||
void SimRadio::completeSending()
|
||||
@@ -84,6 +88,8 @@ void SimRadio::completeSending()
|
||||
|
||||
if (p) {
|
||||
txGood++;
|
||||
if (!isFromUs(p))
|
||||
txRelay++;
|
||||
printPacket("Completed sending", p);
|
||||
|
||||
// We are done sending that packet, release it
|
||||
@@ -113,12 +119,12 @@ bool SimRadio::canSendImmediately()
|
||||
|
||||
bool SimRadio::isActivelyReceiving()
|
||||
{
|
||||
return false; // TODO check how this should be simulated
|
||||
return receivingPacket != nullptr;
|
||||
}
|
||||
|
||||
bool SimRadio::isChannelActive()
|
||||
{
|
||||
return false; // TODO ask simulator
|
||||
return receivingPacket != nullptr;
|
||||
}
|
||||
|
||||
/** Attempt to cancel a previously sent packet. Returns true if a packet was found we could cancel */
|
||||
@@ -142,10 +148,16 @@ void SimRadio::onNotify(uint32_t notification)
|
||||
startTransmitTimer();
|
||||
break;
|
||||
case ISR_RX:
|
||||
handleReceiveInterrupt();
|
||||
// LOG_DEBUG("rx complete - starting timer");
|
||||
startTransmitTimer();
|
||||
break;
|
||||
case TRANSMIT_DELAY_COMPLETED:
|
||||
if (receivingPacket) { // This happens when we had a timer pending and we started receiving
|
||||
handleReceiveInterrupt();
|
||||
startTransmitTimer();
|
||||
break;
|
||||
}
|
||||
LOG_DEBUG("delay done");
|
||||
|
||||
// If we are not currently in receive mode, then restart the random delay (this can happen if the main thread
|
||||
@@ -183,6 +195,7 @@ void SimRadio::onNotify(uint32_t notification)
|
||||
void SimRadio::startSend(meshtastic_MeshPacket *txp)
|
||||
{
|
||||
printPacket("Start low level send", txp);
|
||||
isReceiving = false;
|
||||
size_t numbytes = beginSending(txp);
|
||||
meshtastic_MeshPacket *p = packetPool.allocCopy(*txp);
|
||||
perhapsDecode(p);
|
||||
@@ -201,15 +214,64 @@ void SimRadio::startSend(meshtastic_MeshPacket *txp)
|
||||
|
||||
service->sendQueueStatusToPhone(router->getQueueStatus(), 0, p->id);
|
||||
service->sendToPhone(p); // Sending back to simulator
|
||||
service->loop(); // Process the send immediately
|
||||
}
|
||||
|
||||
// Simulates device received a packet via the LoRa chip
|
||||
void SimRadio::unpackAndReceive(meshtastic_MeshPacket &p)
|
||||
{
|
||||
// Simulator packet (=Compressed packet) is encapsulated in a MeshPacket, so need to unwrap first
|
||||
meshtastic_Compressed scratch;
|
||||
meshtastic_Compressed *decoded = NULL;
|
||||
if (p.which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||
memset(&scratch, 0, sizeof(scratch));
|
||||
p.decoded.payload.size =
|
||||
pb_decode_from_bytes(p.decoded.payload.bytes, p.decoded.payload.size, &meshtastic_Compressed_msg, &scratch);
|
||||
if (p.decoded.payload.size) {
|
||||
decoded = &scratch;
|
||||
// Extract the original payload and replace
|
||||
memcpy(&p.decoded.payload, &decoded->data, sizeof(decoded->data));
|
||||
// Switch the port from PortNum_SIMULATOR_APP back to the original PortNum
|
||||
p.decoded.portnum = decoded->portnum;
|
||||
} else
|
||||
LOG_ERROR("Error decoding proto for simulator message!");
|
||||
}
|
||||
// Let SimRadio receive as if it did via its LoRa chip
|
||||
startReceive(&p);
|
||||
}
|
||||
|
||||
void SimRadio::startReceive(meshtastic_MeshPacket *p)
|
||||
{
|
||||
#ifdef USERPREFS_SIMRADIO_EMULATE_COLLISIONS
|
||||
if (isActivelyReceiving()) {
|
||||
LOG_WARN("Collision detected, dropping current and previous packet!");
|
||||
rxBad++;
|
||||
airTime->logAirtime(RX_ALL_LOG, getPacketTime(receivingPacket));
|
||||
packetPool.release(receivingPacket);
|
||||
receivingPacket = nullptr;
|
||||
return;
|
||||
} else if (sendingPacket) {
|
||||
uint32_t airtimeLeft = tillRun(millis());
|
||||
if (airtimeLeft <= 0) {
|
||||
LOG_WARN("Transmitting packet was already done");
|
||||
handleTransmitInterrupt(); // Finish sending first
|
||||
} else if ((interval - airtimeLeft) > preambleTimeMsec) {
|
||||
// Only if transmitting for longer than preamble there is a collision
|
||||
// (channel should actually be detected as active otherwise)
|
||||
LOG_WARN("Collision detected during transmission!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
isReceiving = true;
|
||||
size_t length = getPacketLength(p);
|
||||
uint32_t xmitMsec = getPacketTime(length);
|
||||
delay(xmitMsec); // Model the time it is busy receiving
|
||||
handleReceiveInterrupt(p);
|
||||
receivingPacket = packetPool.allocCopy(*p);
|
||||
uint32_t airtimeMsec = getPacketTime(p);
|
||||
notifyLater(airtimeMsec, ISR_RX, false); // Model the time it is busy receiving
|
||||
#else
|
||||
isReceiving = true;
|
||||
receivingPacket = packetPool.allocCopy(*p);
|
||||
handleReceiveInterrupt(); // Simulate receiving the packet immediately
|
||||
startTransmitTimer();
|
||||
#endif
|
||||
}
|
||||
|
||||
meshtastic_QueueStatus SimRadio::getQueueStatus()
|
||||
@@ -223,28 +285,27 @@ meshtastic_QueueStatus SimRadio::getQueueStatus()
|
||||
return qs;
|
||||
}
|
||||
|
||||
void SimRadio::handleReceiveInterrupt(meshtastic_MeshPacket *p)
|
||||
void SimRadio::handleReceiveInterrupt()
|
||||
{
|
||||
LOG_DEBUG("HANDLE RECEIVE INTERRUPT");
|
||||
uint32_t xmitMsec;
|
||||
if (receivingPacket == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isReceiving) {
|
||||
LOG_DEBUG("*** WAS_ASSERT *** handleReceiveInterrupt called when not in receive mode");
|
||||
return;
|
||||
}
|
||||
|
||||
isReceiving = false;
|
||||
LOG_DEBUG("HANDLE RECEIVE INTERRUPT");
|
||||
rxGood++;
|
||||
|
||||
// read the number of actually received bytes
|
||||
size_t length = getPacketLength(p);
|
||||
xmitMsec = getPacketTime(length);
|
||||
// LOG_DEBUG("Payload size %d vs length (includes header) %d", p->decoded.payload.size, length);
|
||||
|
||||
meshtastic_MeshPacket *mp = packetPool.allocCopy(*p); // keep a copy in packetPool
|
||||
meshtastic_MeshPacket *mp = packetPool.allocCopy(*receivingPacket); // keep a copy in packetPool
|
||||
packetPool.release(receivingPacket); // release the original
|
||||
receivingPacket = nullptr;
|
||||
|
||||
printPacket("Lora RX", mp);
|
||||
|
||||
airTime->logAirtime(RX_LOG, xmitMsec);
|
||||
airTime->logAirtime(RX_LOG, getPacketTime(mp));
|
||||
|
||||
deliverToReceiver(mp);
|
||||
}
|
||||
@@ -265,4 +326,4 @@ int16_t SimRadio::readData(uint8_t *data, size_t len)
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
@@ -11,11 +11,6 @@ class SimRadio : public RadioInterface, protected concurrency::NotifiedWorkerThr
|
||||
{
|
||||
enum PendingISR { ISR_NONE = 0, ISR_RX, ISR_TX, TRANSMIT_DELAY_COMPLETED };
|
||||
|
||||
/**
|
||||
* Debugging counts
|
||||
*/
|
||||
uint32_t rxBad = 0, rxGood = 0, txGood = 0;
|
||||
|
||||
MeshPacketQueue txQueue = MeshPacketQueue(MAX_TX_QUEUE);
|
||||
|
||||
public:
|
||||
@@ -47,9 +42,17 @@ class SimRadio : public RadioInterface, protected concurrency::NotifiedWorkerThr
|
||||
|
||||
meshtastic_QueueStatus getQueueStatus() override;
|
||||
|
||||
// Convert Compressed_msg to normal msg and receive it
|
||||
void unpackAndReceive(meshtastic_MeshPacket &p);
|
||||
|
||||
/**
|
||||
* Debugging counts
|
||||
*/
|
||||
uint32_t rxBad = 0, rxGood = 0, txGood = 0, txRelay = 0;
|
||||
|
||||
protected:
|
||||
/// are _trying_ to receive a packet currently (note - we might just be waiting for one)
|
||||
bool isReceiving = false;
|
||||
bool isReceiving = true;
|
||||
|
||||
private:
|
||||
void setTransmitDelay();
|
||||
@@ -61,7 +64,7 @@ class SimRadio : public RadioInterface, protected concurrency::NotifiedWorkerThr
|
||||
void startTransmitTimerSNR(float snr);
|
||||
|
||||
void handleTransmitInterrupt();
|
||||
void handleReceiveInterrupt(meshtastic_MeshPacket *p);
|
||||
void handleReceiveInterrupt();
|
||||
|
||||
void onNotify(uint32_t notification);
|
||||
|
||||
@@ -73,6 +76,8 @@ class SimRadio : public RadioInterface, protected concurrency::NotifiedWorkerThr
|
||||
|
||||
int16_t readData(uint8_t *str, size_t len);
|
||||
|
||||
meshtastic_MeshPacket *receivingPacket = nullptr; // The packet we are currently receiving
|
||||
|
||||
protected:
|
||||
/** Could we send right now (i.e. either not actively receiving or transmitting)? */
|
||||
virtual bool canSendImmediately();
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
#ifndef HAS_WIFI
|
||||
#define HAS_WIFI 1
|
||||
#endif
|
||||
#ifndef HAS_RADIO
|
||||
#define HAS_RADIO 1
|
||||
#endif
|
||||
#ifndef HAS_RTC
|
||||
#define HAS_RTC 1
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user