Compare commits

...

113 Commits

Author SHA1 Message Date
Ben Meadors
e09b12ca58 Merge pull request #2072 from meshtastic/hotfix-01
Hotfix for user button not working
2022-12-29 06:22:58 -06:00
Thomas Göttgens
7f3a624ee3 Hotfix for user button not working 2022-12-29 11:55:19 +01:00
Thomas Göttgens
475c87b0e4 Merge pull request #2071 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-12-28 23:18:19 +01:00
thebentern
541f4aa998 [create-pull-request] automated change 2022-12-28 21:27:27 +00:00
Thomas Göttgens
6ea0963f4b fix master too 2022-12-28 16:03:34 +01:00
Thomas Göttgens
63cf01223c Merge pull request #2070 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-12-28 15:43:40 +01:00
caveman99
2505bdbc21 [create-pull-request] automated change 2022-12-28 14:42:46 +00:00
Thomas Göttgens
14be4ee9f0 Release Develop to Master 2022-12-28 15:31:04 +01:00
Thomas Göttgens
d0243d2cd0 Merge pull request #2067 from miaoski/sht31
Support SHT31 temperature sensor
2022-12-27 21:11:30 +01:00
Thomas Göttgens
796e58161d Merge branch 'master' into sht31 2022-12-27 13:58:44 +01:00
Thomas Göttgens
e56f17c658 Merge pull request #2068 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-12-27 13:58:27 +01:00
caveman99
b808ffa9ab [create-pull-request] automated change 2022-12-27 12:53:56 +00:00
miaoski
506bae4a8b Support SHT31 temperature sensor 2022-12-27 19:39:51 +08:00
Thomas Göttgens
f6ee6265e6 Merge pull request #2063 from lewisxhe/master
Fixed<t-beam-s3-core>display model is SH1106
2022-12-25 13:32:29 +01:00
Thomas Göttgens
7539d92857 Merge branch 'master' into master 2022-12-25 13:03:27 +01:00
Thomas Göttgens
21fff392b4 Backport RP2040 update 2022-12-25 13:02:40 +01:00
Thomas Göttgens
580ec590fa something broke pico toolchain. 'twasn'tme .. 2022-12-25 13:01:39 +01:00
lewis
5c9996dfa1 Fixed<t-beam-s3-core>display model is SH1106 2022-12-25 19:01:04 +08:00
Thomas Göttgens
2f7c18303d Merge pull request #2058 from lesykm/serial-module-simple-mode-binary
[modules][serial] switch simple mode from ascii to bytes
2022-12-22 10:46:41 +01:00
Mykhailo Lesyk
b9df41c55f [modules][serial] switch simple mode from ascii to bytes 2022-12-21 22:37:30 -08:00
Thomas Göttgens
4801260440 Merge pull request #2055 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-12-21 20:30:14 +01:00
thebentern
606262e55d [create-pull-request] automated change 2022-12-21 18:54:52 +00:00
Ben Meadors
090e1660fe Merge pull request #2053 from meshtastic/upstream-heltec
Move to upstream espressif arduino
2022-12-21 07:47:27 -06:00
Ben Meadors
92c9b34d4f Copy pasta 2022-12-21 07:46:59 -06:00
Ben Meadors
3f50371ff3 Merge branch 'master' into upstream-heltec 2022-12-21 07:45:18 -06:00
Ben Meadors
815f9bfc5f Move to upstream espressif arduino 2022-12-21 07:41:26 -06:00
Thomas Göttgens
86ff23d13c Merge pull request #2051 from meshtastic/master-next
moving a lot of stuff from develop into Master
2022-12-21 14:35:19 +01:00
Thomas Göttgens
201b786f77 fix RAK build 2022-12-21 14:06:02 +01:00
Thomas Göttgens
755c0b7008 use nanopb 0.4.7 2022-12-21 13:37:38 +01:00
Thomas Göttgens
7396d0f241 Cherry Picking Stuff from develop... 2022-12-21 13:36:38 +01:00
Thomas Göttgens
220859d0aa Merge pull request #2019 from code8buster/gps-toggle-final
Adds a flag to turn the GPS power rail off entirely on tbeam
2022-12-21 13:28:32 +01:00
Thomas Göttgens
941786669b fix compiler warnings 2022-12-21 13:28:29 +01:00
Thomas Göttgens
4eb620d47b Heap Debug: only show if delta occurs 2022-12-21 13:28:29 +01:00
Thomas Göttgens
9794995d7a fix building DIY-1 target 2022-12-21 13:28:29 +01:00
Thomas Göttgens
055146602a support ESP32-S2 CPUs
Note: these don't have Bluetooth and only a single physical core.
2022-12-21 13:28:28 +01:00
Thomas Göttgens
86d7860d86 made a nice PTT/RECV screen for audio module. And cleaned up screen graphics a bit. 2022-12-21 13:28:28 +01:00
Thomas Göttgens
0f2d0d1f07 change on screen graphics to support bicolor screens 2022-12-21 13:28:28 +01:00
Thomas Göttgens
ab6a5a5e07 if we get different frames than our own transmission setup, decode and play them anyway 2022-12-21 13:28:28 +01:00
Thomas Göttgens
44a33ed463 add IO7 to RAK pinouts - only comments changed 2022-12-21 13:28:28 +01:00
Thomas Göttgens
fab08b6451 fix building for screenless devices 2022-12-21 13:28:28 +01:00
Thomas Göttgens
d9cd3dd3e1 Change Boot Message format 2022-12-21 13:28:25 +01:00
Thomas Göttgens
c75ea87f6b Format received message screen like sender in canned messages. 2022-12-21 13:28:25 +01:00
Thomas Göttgens
706ddf6e95 show appropriate message when going into OTA mode 2022-12-21 13:28:25 +01:00
Thomas Göttgens
aec091e7aa manual master merge
# Conflicts:
#	src/Power.cpp
2022-12-21 13:28:25 +01:00
Thomas Göttgens
cea8393a7f Merge pull request #2026 from GUVWAF/develop
TraceRouteModule
2022-12-21 13:27:12 +01:00
Thomas Göttgens
8f94463eac send a 4 byte magic header including the codec version 2022-12-21 13:27:00 +01:00
Thomas Göttgens
a0f5e44967 Audio Module is finished for regression tests. 2022-12-21 13:27:00 +01:00
Thomas Göttgens
feb7181767 debug print thread count. max_threads is 32 2022-12-21 13:27:00 +01:00
Thomas Göttgens
a0c1e9cdc6 Still WIP, but first working version of audio. I2S works good, analogue not so much. 2022-12-21 13:27:00 +01:00
Thomas Göttgens
7d1b6f63b5 Definition cleanup and AudioModule WIP 2022-12-21 13:27:00 +01:00
Thomas Göttgens
ab6b6514cb this define is arch specific 2022-12-21 13:26:59 +01:00
Thomas Göttgens
0e6285edf2 add temp code for heap debugging. Disable -DDEBUG_HEAP for release builds.
DEBUG_MSG output only for now.
2022-12-21 13:26:59 +01:00
Thomas Göttgens
8b58eaac20 fix compile
# Conflicts:
#	protobufs
2022-12-21 13:26:59 +01:00
Thomas Göttgens
8cbf292373 WIP: add digital audio. Needs a proto change, so checking in generated files for now.
# Conflicts:
#	src/mesh/generated/localonly.pb.h
#	src/mesh/generated/module_config.pb.h
2022-12-21 13:26:44 +01:00
Thomas Göttgens
80d0b63c3a hopefully fix compilation errors 2022-12-21 13:26:13 +01:00
Thomas Göttgens
f5120a29ec WIP: audio module still does not work, but enabled for all regions where audio is permitted.
# Conflicts:
#	variants/tlora_v2_1_18/platformio.ini
2022-12-21 13:26:13 +01:00
Thomas Göttgens
efc3f4c0ee remove a few DSR Router bits for S&F Module 2022-12-21 13:25:12 +01:00
Thomas Göttgens
bd2bfd6822 update board definition, update copy/paste errors, fix SX1280. 2022-12-21 13:25:12 +01:00
Thomas Göttgens
88c3ab2636 Merge pull request #2050 from lesykm/serial-module-simple-mode-fix
[modules][serial] fix simple module ability to send
2022-12-21 12:43:13 +01:00
Thomas Göttgens
6a5dd26907 need to trigger new CI run 2022-12-21 12:24:38 +01:00
Mykhailo Lesyk
4de557b4db [modules][serial] fix simple module ability to send 2022-12-21 01:35:19 -08:00
Thomas Göttgens
af9d4328eb Merge pull request #2046 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-12-17 18:42:25 +01:00
caveman99
8c66940b78 [create-pull-request] automated change 2022-12-17 17:41:39 +00:00
Thomas Göttgens
72f1416b30 add variant comment about radiolib 2022-12-16 20:21:56 +01:00
Thomas Göttgens
05f81922e6 Merge pull request #2040 from D4rk4/master
Disable deep sleep for nRF  and force shutdown for RAK463x on discharged battery
2022-12-15 11:21:26 +01:00
Dmitry Galenko
72504a5e8b Merge branch 'master' into master 2022-12-14 20:27:20 +01:00
Thomas Göttgens
e8c034e988 Merge pull request #2041 from markbirss/master
Fix power enable pin used for e-Ink
2022-12-14 17:39:13 +01:00
Dmitry Galenko
aa19718ba4 Change condition for low-voltage killswitch 2022-12-14 17:26:55 +01:00
Mark Trevor Birss
088ab106dd Update variant.h 2022-12-14 17:57:02 +02:00
Mark Trevor Birss
110c3f619a Update variant.h 2022-12-14 17:56:44 +02:00
Dmitry Galenko
d1cc503ca8 Disable shutdown for non ESP32 boards 2022-12-14 14:36:15 +01:00
Thomas Göttgens
d3b3a4c148 fix build error 2022-12-14 10:29:45 +01:00
Dmitry Galenko
46f1cee2a8 Fix missed braces and etc 2022-12-14 10:21:11 +01:00
Dmitry Galenko
0386af721d Merge branch 'meshtastic:master' into master 2022-12-14 09:45:35 +01:00
Thomas Göttgens
de6b752db8 Merge pull request #2039 from ghostop14/master
Enable GPS capabilities on heltec V3
2022-12-14 09:38:06 +01:00
Dmitry Galenko
92fd5511ec Disable nRF sleep on discharge 2022-12-14 09:36:25 +01:00
ghostop14
59ec7f31ab Enable GPS capabilities on heltec V3 2022-12-13 12:31:39 -05:00
Ben Meadors
779d2352bd Merge pull request #2037 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-12-12 16:29:39 -06:00
thebentern
0162db12b8 [create-pull-request] automated change 2022-12-12 19:23:34 +00:00
Ben Meadors
91ff7b9032 Merge pull request #2036 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-12-12 12:18:06 -06:00
thebentern
643f99f577 [create-pull-request] automated change 2022-12-12 18:06:11 +00:00
Ben Meadors
152288b4cc Merge pull request #2025 from meshtastic/power-fsm-experiment
Power FSM experiment
2022-12-12 12:01:00 -06:00
Ben Meadors
45b518baf2 Move sds transition back into esp32 only 2022-12-12 10:24:51 -06:00
Ben Meadors
0c65c73f90 Merge branch 'master' into power-fsm-experiment 2022-12-09 19:50:26 -06:00
Thomas Göttgens
0f0dbc3274 reboot nrf52 on critical error 8 2022-12-09 11:18:43 +01:00
Thomas Göttgens
06d34daeab Merge branch 'master' into power-fsm-experiment 2022-12-08 10:18:01 +01:00
Thomas Göttgens
ba1f68d758 Merge pull request #2027 from lewisxhe/master
Fix the charging parmas error of tbeam-s3core and change the default USB mode
2022-12-06 16:39:38 +01:00
Thomas Göttgens
d4c0977a70 Merge branch 'master' into master 2022-12-06 15:49:32 +01:00
Thomas Göttgens
1a19d71e95 Merge pull request #2023 from meshtastic/2022-bug-recording-critical-error-11-at-srcmeshradiolibinterfacecpp389
Add debug output
2022-12-06 15:48:57 +01:00
Thomas Göttgens
21c10934fc Merge pull request #2018 from arduionoGP/patch-3
Update MQTT.cpp
2022-12-06 15:47:30 +01:00
Thomas Göttgens
13cca91097 Merge branch 'master' into patch-3 2022-12-06 14:09:29 +01:00
Thomas Göttgens
b335b1c66b Merge branch 'master' into 2022-bug-recording-critical-error-11-at-srcmeshradiolibinterfacecpp389 2022-12-06 14:08:48 +01:00
Thomas Göttgens
cc2653bfb5 Merge pull request #2029 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-12-06 14:05:51 +01:00
caveman99
fc5bf5a68f [create-pull-request] automated change 2022-12-06 13:03:26 +00:00
lewishe
63d7338311 fix tbeams3-core PMU charging cut-off voltage 2022-12-06 11:01:14 +08:00
lewishe
37f716d27b Change tbeams3-core the default USB mode to TinyUSB 2022-12-06 10:58:59 +08:00
Ben Meadors
0f2a835359 Remove hard coded !isPowered 2022-12-05 10:13:19 -06:00
Thomas Göttgens
2a84d39e40 Always do battery resampling if we use the ADC. Improves reading a lot. 2022-12-05 16:40:23 +01:00
Ben Meadors
b14289e976 More cleanup 2022-12-05 08:35:54 -06:00
Ben Meadors
1fef6f0656 Clean up on battery shutdown condition 2022-12-05 07:37:01 -06:00
Thomas Göttgens
183ec2124f Add debug output 2022-12-05 11:48:46 +01:00
Ben Meadors
aeb9bfa063 Return false 2022-12-04 20:41:00 -06:00
arduinoGP
b84c7ae49b Oops, added time to the Pos 2022-12-04 19:41:58 -05:00
Thomas Göttgens
61598c5942 Merge pull request #2020 from meshtastic/serial-textmessage
Serial textmessage mode
2022-12-04 23:53:29 +01:00
Ben Meadors
a3a24e0216 Don't put newlines in the text buffer 2022-12-04 16:03:57 -06:00
Ben Meadors
31ec2da0e9 Text message mode for serial 2022-12-04 15:40:28 -06:00
arduinoGP
27a10b395f Update MQTT.cpp
(First real try at writing meaningful C++ but it seems to work.)
Allows sending JSON Position data from MQTT broker for broadcast to a LORA mesh via gateway device.
The new type is "sendposition". Valid envelope looks like:
{
    "sender": "someSender",
    "type": "sendposition",
    "payload": {
        "latitude_i": 399600000,
        "longitude_i": -862600000,
        "altitude": 100
    }
}
This complements the "sendtext" type envelope.
2022-12-04 00:00:43 -05:00
Ben Meadors
7570cdbd22 Fix shell scripts for both linux and darwin 2022-12-03 08:24:11 -06:00
Thomas Göttgens
c857474116 Merge pull request #2013 from arduionoGP/patch-2
Update MQTT.cpp
2022-12-01 22:17:35 +01:00
arduinoGP
8ff5dacc3c Update MQTT.cpp
case Portnum_POSITION_APP adjusted so the various options allways get encoded into JSON as long as lat and long are present. There are circumstances where timestamp, time, or altitude might be missing and this causes silent failures of JSON encoding..
2022-12-01 15:44:47 -05:00
Ben Meadors
f1179d31ba Fixed shell scripts 2022-11-27 07:40:40 -06:00
Ben Meadors
abe60b96f1 Merge pull request #2001 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-11-27 06:11:39 -06:00
thebentern
206520f179 [create-pull-request] automated change 2022-11-27 02:16:21 +00:00
134 changed files with 3110 additions and 1732 deletions

View File

@@ -17,9 +17,9 @@ jobs:
- name: Download nanopb
run: |
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.6-linux-x86.tar.gz
tar xvzf nanopb-0.4.6-linux-x86.tar.gz
mv nanopb-0.4.6-linux-x86 nanopb-0.4.6
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.7-linux-x86.tar.gz
tar xvzf nanopb-0.4.7-linux-x86.tar.gz
mv nanopb-0.4.7-linux-x86 nanopb-0.4.7
- name: Re-generate protocol buffers
run: |

1
.gitignore vendored
View File

@@ -29,3 +29,4 @@ __pycache__
venv/
release/
.vscode/extensions.json

View File

@@ -26,6 +26,7 @@ build_flags =
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
-DDEBUG_HEAP
lib_deps =
${arduino_base.lib_deps}
@@ -34,6 +35,7 @@ lib_deps =
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
h2zero/NimBLE-Arduino@^1.4.0
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
caveman99/ESP32 Codec2@^1.0.1
lib_ignore =
segger_rtt

47
arch/esp32/esp32s2.ini Normal file
View File

@@ -0,0 +1,47 @@
[esp32s2_base]
extends = arduino_base
platform = platformio/espressif32@^5.2.0
build_src_filter =
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/> -<nimble/>
upload_speed = 961200
monitor_speed = 115200
debug_init_break = tbreak setup
monitor_filters = esp32_exception_decoder
board_build.filesystem = littlefs
# Remove -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL for low level BLE logging.
# See library directory for BLE logging possible values: .pio/libdeps/tbeam/NimBLE-Arduino/src/log_common/log_common.h
# This overrides the BLE logging default of LOG_LEVEL_INFO (1) from: .pio/libdeps/tbeam/NimBLE-Arduino/src/esp_nimble_cfg.h
build_flags =
${arduino_base.build_flags}
-Wall
-Wextra
-Isrc/platform/esp32
-std=c++11
-DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
-DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL
-DAXP_DEBUG_PORT=Serial
-DCONFIG_BT_NIMBLE_ENABLED
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
-DHAS_BLUETOOTH=0
-DDEBUG_HEAP
lib_deps =
${arduino_base.lib_deps}
${networking_base.lib_deps}
${environmental_base.lib_deps}
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
caveman99/ESP32 Codec2@^1.0.1
lib_ignore =
segger_rtt
ESP32 BLE Arduino
; customize the partition table
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
board_build.partitions = partition-table.csv

View File

@@ -26,6 +26,7 @@ build_flags =
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
-DDEBUG_HEAP
lib_deps =
${arduino_base.lib_deps}
@@ -34,6 +35,7 @@ lib_deps =
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
h2zero/NimBLE-Arduino@^1.4.0
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
caveman99/ESP32 Codec2@^1.0.1
lib_ignore =
segger_rtt

View File

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

View File

@@ -45,7 +45,7 @@ shift "$((OPTIND-1))"
shift
}
if [ -f "${FILENAME}" ] && [[ "${FILENAME}" != *"update"* ]]; then
if [ -f "${FILENAME}" ] && [ ! -z "${FILENAME##*"update"*}" ]; then
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
"$PYTHON" -m esptool erase_flash
"$PYTHON" -m esptool write_flash 0x00 ${FILENAME}

View File

@@ -43,7 +43,7 @@ shift "$((OPTIND-1))"
shift
}
if [ -f "${FILENAME}" ] && [[ $FILENAME == *"update"* ]]; then
if [ -f "${FILENAME}" ] && [ -z "${FILENAME##*"update"*}" ]; then
printf "Trying to flash update ${FILENAME}"
$PYTHON -m esptool --baud 115200 write_flash 0x10000 ${FILENAME}
else

View File

@@ -1 +1 @@
cd protobufs && ..\nanopb-0.4.6\generator-bin\protoc.exe --nanopb_out=-v:..\src\mesh\generated -I=..\protobufs *.proto
cd protobufs && ..\nanopb-0.4.7\generator-bin\protoc.exe --nanopb_out=-v:..\src\mesh\generated -I=..\protobufs *.proto

View File

@@ -2,13 +2,13 @@
set -e
echo "This script requires https://jpa.kapsi.fi/nanopb/download/ version 0.4.6 to be located in the"
echo "This script requires https://jpa.kapsi.fi/nanopb/download/ version 0.4.7 to be located in the"
echo "firmware root directory if the following step fails, you should download the correct"
echo "prebuilt binaries for your computer into nanopb-0.4.6"
echo "prebuilt binaries for your computer into nanopb-0.4.7"
# the nanopb tool seems to require that the .options file be in the current directory!
cd protobufs
../nanopb-0.4.6/generator-bin/protoc --nanopb_out=-v:../src/mesh/generated -I=../protobufs *.proto
../nanopb-0.4.7/generator-bin/protoc --nanopb_out=-v:../src/mesh/generated -I=../protobufs *.proto
#echo "Regenerating protobuf documentation - if you see an error message"
#echo "you can ignore it unless doing a new protobuf release to github."

View File

@@ -8,9 +8,7 @@
"-DBOARD_HAS_PSRAM",
"-DLILYGO_TBEAM_S3_CORE",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_USB_DFU_ON_BOOT=1",
"-DARDUINO_USB_MSC_ON_BOOT=1",
"-DARDUINO_USB_MODE=1",
"-DARDUINO_USB_MODE=0",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=1"
],

47
boards/tlora-t3s3-v1.json Normal file
View File

@@ -0,0 +1,47 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld"
},
"core": "esp32",
"extra_flags": [
"-DLILYGO_T3S3_V1",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_USB_MODE=0",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=1"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "dio",
"hwids": [
[
"0X303A",
"0x1001"
]
],
"mcu": "esp32s3",
"variant": "tlora-t3s3-v1"
},
"connectivity": [
"wifi"
],
"debug": {
"openocd_target": "esp32s3.cfg"
},
"frameworks": [
"arduino",
"espidf"
],
"name": "LilyGo TLora-T3S3-V1",
"upload": {
"flash_size": "4MB",
"maximum_ram_size": 327680,
"maximum_size": 4194304,
"wait_for_upload_port": true,
"require_upload_port": true,
"speed": 921600
},
"url": "http://www.lilygo.cn/",
"vendor": "LilyGo"
}

View File

@@ -10,7 +10,6 @@
;default_envs = heltec-v2.0
;default_envs = heltec-v2.1
;default_envs = tlora-v1
;default_envs = tlora-v1
;default_envs = tlora_v1_3
;default_envs = tlora-v2
;default_envs = tlora-v2-1-1.6
@@ -66,7 +65,8 @@ lib_deps =
https://github.com/meshtastic/ArduinoThread.git#72921ac222eed6f526ba1682023cee290d9aa1b3
nanopb/Nanopb@^0.4.6
erriez/ErriezCRC32@^1.0.1
jgromes/RadioLib@^5.5.0
; jgromes/RadioLib@^5.5.1
https://github.com/jgromes/RadioLib.git#395844922c5d88d5db0481a9c91479931172428d
; Used for the code analysis in PIO Home / Inspect
check_tool = cppcheck
@@ -82,6 +82,7 @@ framework = arduino
lib_deps =
${env.lib_deps}
mprograms/QMC5883LCompass@^1.1.1
end2endzone/NonBlockingRTTTL@^1.3.0
https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#52b5282639d08a8cbd4b748363089eed6102dc76
build_flags = ${env.build_flags} -Os -DRADIOLIB_SPI_PARANOID=0
@@ -107,3 +108,4 @@ lib_deps =
adafruit/Adafruit INA219@^1.2.0
adafruit/Adafruit SHTC3 Library@^1.0.0
adafruit/Adafruit LPS2X@^2.0.4
adafruit/Adafruit SHT31 Library@^2.2.0

View File

@@ -51,6 +51,7 @@ class ButtonThread : public concurrency::OSThread
pinMode(BUTTON_PIN, INPUT_PULLUP_SENSE);
#endif
userButton.attachClick(userButtonPressed);
userButton.setClickTicks(300);
userButton.attachDuringLongPress(userButtonPressedLong);
userButton.attachDoubleClick(userButtonDoublePressed);
userButton.attachMultiClick(userButtonMultiPressed);
@@ -162,6 +163,18 @@ class ButtonThread : public concurrency::OSThread
#if defined(USE_EINK) && defined(PIN_EINK_EN)
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
#endif
#if defined(GPS_POWER_TOGGLE)
if(config.position.gps_enabled)
{
DEBUG_MSG("Flag set to false for gps power\n");
}
else
{
DEBUG_MSG("Flag set to true to restore power\n");
}
config.position.gps_enabled = !(config.position.gps_enabled);
doGPSpowersave(config.position.gps_enabled);
#endif
}
static void userButtonMultiPressed()

View File

@@ -20,16 +20,19 @@ class GPSStatus : public Status
bool hasLock = false; // default to false, until we complete our first read
bool isConnected = false; // Do we have a GPS we are talking to
bool isPowerSaving = false; //Are we in power saving state
Position p = Position_init_default;
public:
GPSStatus() { statusType = STATUS_TYPE_GPS; }
// preferred method
GPSStatus(bool hasLock, bool isConnected, const Position &pos) : Status()
GPSStatus(bool hasLock, bool isConnected, bool isPowerSaving, const Position &pos) : Status()
{
this->hasLock = hasLock;
this->isConnected = isConnected;
this->isPowerSaving = isPowerSaving;
// all-in-one struct copy
this->p = pos;
@@ -44,6 +47,8 @@ class GPSStatus : public Status
bool getIsConnected() const { return isConnected; }
bool getIsPowerSaving() const { return isPowerSaving;}
int32_t getLatitude() const
{
if (config.position.fixed_position) {
@@ -94,7 +99,7 @@ class GPSStatus : public Status
#ifdef GPS_EXTRAVERBOSE
DEBUG_MSG("GPSStatus.match() new pos@%x to old pos@%x\n", newStatus->p.pos_timestamp, p.pos_timestamp);
#endif
return (newStatus->hasLock != hasLock || newStatus->isConnected != isConnected ||
return (newStatus->hasLock != hasLock || newStatus->isConnected != isConnected || newStatus->isPowerSaving !=isPowerSaving ||
newStatus->p.latitude_i != p.latitude_i || newStatus->p.longitude_i != p.longitude_i ||
newStatus->p.altitude != p.altitude || newStatus->p.altitude_hae != p.altitude_hae ||
newStatus->p.PDOP != p.PDOP || newStatus->p.ground_track != p.ground_track ||

View File

@@ -102,6 +102,10 @@ class AnalogBatteryLevel : public HasBatteryLevel
#define ADC_MULTIPLIER 2.0
#endif
#ifndef BATTERY_SENSE_SAMPLES
#define BATTERY_SENSE_SAMPLES 30
#endif
#ifdef BATTERY_PIN
// Override variant or default ADC_MULTIPLIER if we have the override pref
float operativeAdcMultiplier = config.power.adc_multiplier_override > 0
@@ -112,16 +116,12 @@ class AnalogBatteryLevel : public HasBatteryLevel
if (millis() - last_read_time_ms > min_read_interval) {
last_read_time_ms = millis();
#ifdef BATTERY_SENSE_SAMPLES
//Set the number of samples, it has an effect of increasing sensitivity, especially in complex electromagnetic environment.
uint32_t raw = 0;
for(uint32_t i=0; i<BATTERY_SENSE_SAMPLES; i++){
raw += analogRead(BATTERY_PIN);
}
raw = raw/BATTERY_SENSE_SAMPLES;
#else
uint32_t raw = analogRead(BATTERY_PIN);
#endif
float scaled;
#ifndef VBAT_RAW_TO_SCALED
@@ -182,6 +182,9 @@ Power::Power() : OSThread("Power")
{
statusHandler = {};
low_voltage_counter = 0;
#ifdef DEBUG_HEAP
lastheap = ESP.getFreeHeap();
#endif
}
bool Power::analogInit()
@@ -283,6 +286,12 @@ void Power::readPowerStatus()
DEBUG_MSG("Battery: usbPower=%d, isCharging=%d, batMv=%d, batPct=%d\n", powerStatus2.getHasUSB(),
powerStatus2.getIsCharging(), powerStatus2.getBatteryVoltageMv(), powerStatus2.getBatteryChargePercent());
newStatus.notifyObservers(&powerStatus2);
#ifdef DEBUG_HEAP
if (lastheap != ESP.getFreeHeap()){
DEBUG_MSG("Heap status: %d/%d bytes free (%d), running %d threads\n", ESP.getFreeHeap(), ESP.getHeapSize(), ESP.getFreeHeap() - lastheap , concurrency::mainController.size(false));
lastheap = ESP.getFreeHeap();
}
#endif
// If we have a battery at all and it is less than 10% full, force deep sleep if we have more than 3 low readings in a row
// Supect fluctuating voltage on the RAK4631 to force it to deep sleep even if battery is at 85% after only a few days
@@ -290,8 +299,12 @@ void Power::readPowerStatus()
if (powerStatus2.getHasBattery() && !powerStatus2.getHasUSB()) {
if (batteryLevel->getBattVoltage() < MIN_BAT_MILLIVOLTS) {
low_voltage_counter++;
if (low_voltage_counter > 3)
powerFSM.trigger(EVENT_LOW_BATTERY);
DEBUG_MSG("Warning RAK4631 Low voltage counter: %d/10\n", low_voltage_counter);
if (low_voltage_counter > 10) {
// We can't trigger deep sleep on NRF52, it's freezing the board
//powerFSM.trigger(EVENT_LOW_BATTERY);
DEBUG_MSG("Low voltage detected, but not triggering deep sleep\n");
}
} else {
low_voltage_counter = 0;
}
@@ -455,6 +468,9 @@ bool Power::axpChipInit()
// Set constant current charging current
PMU->setChargerConstantCurr(XPOWERS_AXP192_CHG_CUR_450MA);
//Set up the charging voltage
PMU->setChargeTargetVoltage(XPOWERS_AXP192_CHG_VOL_4V2);
} else if (PMU->getChipModel() == XPOWERS_AXP2101) {
// t-beam s3 core
@@ -507,6 +523,8 @@ bool Power::axpChipInit()
//Set the constant current charging current of AXP2101, temporarily use 500mA by default
PMU->setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_500MA);
//Set up the charging voltage
PMU->setChargeTargetVoltage(XPOWERS_AXP2101_CHG_VOL_4V2);
}
@@ -559,14 +577,15 @@ bool Power::axpChipInit()
}
DEBUG_MSG("=======================================================================\n");
//Set up the charging voltage, AXP2101/AXP192 4.2V gear is the same
// XPOWERS_AXP192_CHG_VOL_4V2 = XPOWERS_AXP2101_CHG_VOL_4V2
PMU->setChargeTargetVoltage(XPOWERS_AXP192_CHG_VOL_4V2);
// We can safely ignore this approach for most (or all) boards because MCU turned off
// earlier than battery discharged to 2.6V.
//
// Unfortanly for now we can't use this killswitch for RAK4630-based boards because they have a bug with
// battery voltage measurement. Probably it sometimes drops to low values.
#ifndef RAK4630
// Set PMU shutdown voltage at 2.6V to maximize battery utilization
PMU->setSysPowerDownVoltage(2600);
#endif
#ifdef PMU_IRQ

View File

@@ -34,7 +34,7 @@ static void sdsEnter()
{
DEBUG_MSG("Enter state: SDS\n");
// FIXME - make sure GPS and LORA radio are off first - because we want close to zero current draw
doDeepSleep(config.power.sds_secs * 1000);
doDeepSleep(getConfiguredOrDefaultMs(config.power.sds_secs));
}
extern Power *power;
@@ -324,17 +324,10 @@ void PowerFSM_setup()
powerFSM.add_transition(&stateDARK, &stateDARK, EVENT_CONTACT_FROM_PHONE, NULL, "Contact from phone");
// each time we get a new update packet make sure we are staying in the ON state so the screen stays awake (also we don't
// shutdown bluetooth if is_router)
powerFSM.add_transition(&stateDARK, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update");
powerFSM.add_transition(&stateON, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update");
powerFSM.add_timed_transition(&stateON, &stateDARK, getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL, "Screen-on timeout");
// On most boards we use light-sleep to be our main state, but on NRF52 we just stay in DARK
State *lowPowerState = &stateLS;
#ifdef ARCH_ESP32
State *lowPowerState = &stateLS;
// We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally)
// See: https://github.com/meshtastic/firmware/issues/1071
@@ -343,12 +336,10 @@ void PowerFSM_setup()
powerFSM.add_timed_transition(&stateDARK, &stateLS, getConfiguredOrDefaultMs(config.power.wait_bluetooth_secs, default_wait_bluetooth_secs), NULL, "Bluetooth timeout");
}
#elif defined (ARCH_NRF52)
lowPowerState = &stateDARK;
if (config.power.sds_secs != UINT32_MAX)
powerFSM.add_timed_transition(lowPowerState, &stateSDS, getConfiguredOrDefaultMs(config.power.sds_secs), NULL, "mesh timeout");
#endif
if (config.power.sds_secs != UINT32_MAX)
powerFSM.add_timed_transition(lowPowerState, &stateSDS, config.power.sds_secs * 1000, NULL, "mesh timeout");
powerFSM.run_machine(); // run one interation of the state machine, so we run our on enter tasks for the initial DARK state
}

View File

@@ -27,10 +27,8 @@ class PowerFSMThread : public OSThread
if (powerStatus->getHasUSB()) {
timeLastPowered = millis();
} else if (config.power.on_battery_shutdown_after_secs > 0 &&
millis() >
timeLastPowered +
(1000 *
config.power.on_battery_shutdown_after_secs)) { // shutdown after 30 minutes unpowered
config.power.on_battery_shutdown_after_secs != UINT32_MAX &&
millis() > (timeLastPowered + getConfiguredOrDefaultMs(config.power.on_battery_shutdown_after_secs))) { // shutdown after 30 minutes unpowered
powerFSM.trigger(EVENT_SHUTDOWN);
}

View File

@@ -25,7 +25,7 @@ void consolePrintf(const char *format, ...)
#endif
}
SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port)
SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port), concurrency::OSThread("SerialConsole")
{
assert(!console);
console = this;
@@ -46,6 +46,10 @@ SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port)
emitRebooted();
}
int32_t SerialConsole::runOnce()
{
return runOncePart();
}
// For the serial port we can't really detect if any client is on the other side, so instead just look for recent messages
bool SerialConsole::checkIsConnected()

View File

@@ -6,7 +6,7 @@
* 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).
*/
class SerialConsole : public StreamAPI, public RedirectablePrint
class SerialConsole : public StreamAPI, public RedirectablePrint, private concurrency::OSThread
{
public:
SerialConsole();
@@ -24,6 +24,8 @@ class SerialConsole : public StreamAPI, public RedirectablePrint
return RedirectablePrint::write(c);
}
virtual int32_t runOnce() override;
protected:
/// Check the current underlying physical link to see if the client is currently connected

View File

@@ -117,6 +117,20 @@ float AirTime::utilizationTXPercent()
return (float(sum) / float(MS_IN_HOUR)) * 100;
}
// Get the amount of minutes we have to be silent before we can send again
uint8_t AirTime::getSilentMinutes(float txPercent, float dutyCycle)
{
float newTxPercent = txPercent;
for (int8_t i = MINUTES_IN_HOUR-1; i >= 0; --i) {
newTxPercent -= ((float)this->utilizationTX[i] / (MS_IN_MINUTE * MINUTES_IN_HOUR / 100));
if (newTxPercent < dutyCycle)
return MINUTES_IN_HOUR-1-i;
}
return MINUTES_IN_HOUR;
}
AirTime::AirTime() : concurrency::OSThread("AirTime"),airtimes({}) {
}

View File

@@ -29,6 +29,7 @@
#define PERIODS_TO_LOG 8
#define MINUTES_IN_HOUR 60
#define SECONDS_IN_MINUTE 60
#define MS_IN_MINUTE (SECONDS_IN_MINUTE * 1000)
#define MS_IN_HOUR (MINUTES_IN_HOUR * SECONDS_IN_MINUTE * 1000)
@@ -57,6 +58,7 @@ class AirTime : private concurrency::OSThread
uint32_t getSecondsPerPeriod();
uint32_t getSecondsSinceBoot();
uint32_t *airtimeReport(reportTypes reportType);
uint8_t getSilentMinutes(float txPercent, float dutyCycle);
private:
bool firstTime = true;

View File

@@ -114,6 +114,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define SHTC3_ADDR 0x70
#define LPS22HB_ADDR 0x5C
#define LPS22HB_ADDR_ALT 0x5D
#define SHT31_ADDR 0x44
// -----------------------------------------------------------------------------
// Security

View File

@@ -191,6 +191,10 @@ void scanI2Cdevice()
nodeTelemetrySensorsMap[TelemetrySensorType_MCP9808] = addr;
DEBUG_MSG("MCP9808 sensor found\n");
}
if (addr == SHT31_ADDR) {
DEBUG_MSG("SHT31 sensor found\n");
nodeTelemetrySensorsMap[TelemetrySensorType_SHT31] = addr;
}
if (addr == SHTC3_ADDR) {
DEBUG_MSG("SHTC3 sensor found\n");
nodeTelemetrySensorsMap[TelemetrySensorType_SHTC3] = addr;

View File

@@ -270,21 +270,30 @@ bool GPS::setup()
pinMode(PIN_GPS_EN, OUTPUT);
#endif
#ifdef HAS_PMU
if(config.position.gps_enabled){
setGPSPower(true);
}
#endif
#ifdef PIN_GPS_RESET
digitalWrite(PIN_GPS_RESET, 1); // assert for 10ms
pinMode(PIN_GPS_RESET, OUTPUT);
delay(10);
digitalWrite(PIN_GPS_RESET, 0);
#endif
setAwake(true); // Wake GPS power before doing any init
bool ok = setupGPS();
if (ok) {
notifySleepObserver.observe(&notifySleep);
notifyDeepSleepObserver.observe(&notifyDeepSleep);
notifyGPSSleepObserver.observe(&notifyGPSSleep);
}
if (config.position.gps_enabled==false) {
setAwake(false);
doGPSpowersave(false);
}
return ok;
}
@@ -293,6 +302,7 @@ GPS::~GPS()
// we really should unregister our sleep observer
notifySleepObserver.unobserve(&notifySleep);
notifyDeepSleepObserver.unobserve(&notifyDeepSleep);
notifyGPSSleepObserver.observe(&notifyGPSSleep);
}
bool GPS::hasLock()
@@ -405,7 +415,7 @@ void GPS::publishUpdate()
DEBUG_MSG("publishing pos@%x:2, hasVal=%d, GPSlock=%d\n", p.timestamp, hasValidLocation, hasLock());
// Notify any status instances that are observing us
const meshtastic::GPSStatus status = meshtastic::GPSStatus(hasValidLocation, isConnected(), p);
const meshtastic::GPSStatus status = meshtastic::GPSStatus(hasValidLocation, isConnected(), isPowerSaving(), p);
newStatus.notifyObservers(&status);
}
}
@@ -416,7 +426,7 @@ int32_t GPS::runOnce()
// if we have received valid NMEA claim we are connected
setConnected();
} else {
if(gnssModel == GNSS_MODEL_UBLOX){
if((config.position.gps_enabled == 1) && (gnssModel == GNSS_MODEL_UBLOX)){
// reset the GPS on next bootup
if(devicestate.did_gps_reset && (millis() > 60000) && !hasFlow()) {
DEBUG_MSG("GPS is not communicating, trying factory reset on next bootup.\n");
@@ -518,6 +528,7 @@ int GPS::prepareDeepSleep(void *unused)
DEBUG_MSG("GPS deep sleep!\n");
// For deep sleep we also want abandon any lock attempts (because we want minimum power)
getSleepTime();
setAwake(false);
return 0;
@@ -653,6 +664,11 @@ GPS *createGps()
return new_gps;
}
}
else{
GPS *new_gps = new NMEAGPS();
new_gps->setup();
return new_gps;
}
return nullptr;
#endif
}

View File

@@ -49,6 +49,7 @@ class GPS : private concurrency::OSThread
CallbackObserver<GPS, void *> notifySleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareSleep);
CallbackObserver<GPS, void *> notifyDeepSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
CallbackObserver<GPS, void *> notifyGPSSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
public:
/** If !NULL we will use this serial port to construct our GPS */
@@ -77,6 +78,8 @@ class GPS : private concurrency::OSThread
/// Return true if we are connected to a GPS
bool isConnected() const { return hasGPS; }
bool isPowerSaving() const { return !config.position.gps_enabled;}
/**
* Restart our lock attempt - try to get and broadcast a GPS reading ASAP
* called after the CPU wakes from light-sleep state

View File

@@ -35,6 +35,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "mesh/Channels.h"
#include "mesh/generated/deviceonly.pb.h"
#include "modules/TextMessageModule.h"
#include "modules/ExternalNotificationModule.h"
#include "sleep.h"
#include "target_specific.h"
#include "utils.h"
@@ -42,6 +43,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef ARCH_ESP32
#include "esp_task_wdt.h"
#include "mesh/http/WiFiAPClient.h"
#include "modules/esp32/StoreForwardModule.h"
#endif
#ifdef OLED_RU
@@ -95,17 +97,17 @@ static uint16_t displayWidth, displayHeight;
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
// The screen is bigger so use bigger fonts
#define FONT_SMALL ArialMT_Plain_16
#define FONT_MEDIUM ArialMT_Plain_24
#define FONT_LARGE ArialMT_Plain_24
#define FONT_SMALL ArialMT_Plain_16 // Height: 19
#define FONT_MEDIUM ArialMT_Plain_24 // Height: 28
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
#else
#ifdef OLED_RU
#define FONT_SMALL ArialMT_Plain_10_RU
#else
#define FONT_SMALL ArialMT_Plain_10
#define FONT_SMALL ArialMT_Plain_10 // Height: 13
#endif
#define FONT_MEDIUM ArialMT_Plain_16
#define FONT_LARGE ArialMT_Plain_24
#define FONT_MEDIUM ArialMT_Plain_16 // Height: 19
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
#endif
#define fontHeight(font) ((font)[1] + 1) // height is position 1
@@ -329,11 +331,8 @@ static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, i
display->drawString(64 + x, y, "Updating");
display->setFont(FONT_SMALL);
if ((millis() / 1000) % 2) {
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait . . .");
} else {
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait . . ");
}
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->drawStringMaxWidth(0 + x, 2 + y + FONT_HEIGHT_SMALL *2, x + display->getWidth(), "Please be patient and do not power off.");
}
/// Draw the last text message we received
@@ -364,6 +363,9 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
{
displayedNodeNum = 0; // Not currently showing a node pane
// the max length of this buffer is much longer than we can possibly print
static char tempBuf[237];
MeshPacket &mp = devicestate.rx_text_message;
NodeInfo *node = nodeDB.getNode(getFrom(&mp));
// DEBUG_MSG("drawing text message from 0x%x: %s\n", mp.from,
@@ -373,16 +375,14 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
// with the third parameter you can define the width after which words will
// be wrapped. Currently only spaces and "-" are allowed for wrapping
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(FONT_MEDIUM);
String sender = (node && node->has_user) ? node->user.short_name : "???";
display->drawString(0 + x, 0 + y, sender);
display->setFont(FONT_SMALL);
// the max length of this buffer is much longer than we can possibly print
static char tempBuf[96];
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
display->setColor(BLACK);
display->drawStringf(0 + x, 0 + y, tempBuf, "From: %s", (node && node->has_user) ? node->user.short_name : "???");
display->drawStringf(1 + x, 0 + y, tempBuf, "From: %s", (node && node->has_user) ? node->user.short_name : "???");
display->setColor(WHITE);
snprintf(tempBuf, sizeof(tempBuf), "%s", mp.decoded.payload.bytes);
display->drawStringMaxWidth(4 + x, 10 + y, SCREEN_WIDTH - (6 + x), tempBuf);
display->drawStringMaxWidth(0 + x, 0 + y + FONT_HEIGHT_SMALL, x + display->getWidth(), tempBuf);
}
/// Draw a series of fields in a column, wrapping to multiple colums if needed
@@ -395,6 +395,10 @@ static void drawColumns(OLEDDisplay *display, int16_t x, int16_t y, const char *
int xo = x, yo = y;
while (*f) {
display->drawString(xo, yo, *f);
if (display->getColor() == BLACK)
display->drawString(xo + 1, yo, *f);
display->setColor(WHITE);
yo += FONT_HEIGHT_SMALL;
if (yo > SCREEN_HEIGHT - FONT_HEIGHT_SMALL) {
xo += SCREEN_WIDTH / 2;
@@ -463,8 +467,13 @@ static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, NodeStatus *no
{
char usersString[20];
sprintf(usersString, "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal());
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
display->drawFastImage(x, y + 3, 8, 8, imgUser);
#else
display->drawFastImage(x, y, 8, 8, imgUser);
#endif
display->drawString(x + 10, y - 2, usersString);
display->drawString(x + 11, y - 2, usersString);
}
// Draw GPS status summary
@@ -473,15 +482,18 @@ static void drawGPS(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus
if (config.position.fixed_position) {
// GPS coordinates are currently fixed
display->drawString(x - 1, y - 2, "Fixed GPS");
display->drawString(x, y - 2, "Fixed GPS");
return;
}
if (!gps->getIsConnected()) {
display->drawString(x, y - 2, "No GPS");
display->drawString(x + 1, y - 2, "No GPS");
return;
}
display->drawFastImage(x, y, 6, 8, gps->getHasLock() ? imgPositionSolid : imgPositionEmpty);
if (!gps->getHasLock()) {
display->drawString(x + 8, y - 2, "No sats");
display->drawString(x + 9, y - 2, "No sats");
return;
} else {
char satsString[3];
@@ -506,6 +518,23 @@ static void drawGPS(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus
}
}
//Draw status when gps is disabled by PMU
static void drawGPSpowerstat(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
{
#ifdef HAS_PMU
String displayLine = "GPS disabled";
int16_t xPos = display->getStringWidth(displayLine);
if (!config.position.gps_enabled){
display->drawString(x + xPos, y, displayLine);
#ifdef GPS_POWER_TOGGLE
display->drawString(x + xPos, y - 2 + FONT_HEIGHT_SMALL, " by button");
#endif
//display->drawString(x + xPos, y + 2, displayLine);
}
#endif
}
static void drawGPSAltitude(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
{
String displayLine = "";
@@ -669,16 +698,16 @@ static uint16_t getCompassDiam(OLEDDisplay *display)
{
uint16_t diam = 0;
// get the smaller of the 2 dimensions and subtract 20
if(display->getWidth() > display->getHeight()) {
diam = display->getHeight();
if(display->getWidth() > (display->getHeight() - FONT_HEIGHT_SMALL)) {
diam = display->getHeight() - FONT_HEIGHT_SMALL;
// if 2/3 of the other size would be smaller, use that
if (diam > (display->getWidth() * 2 / 3)) {
diam = display->getWidth() * 2 / 3;
}
} else {
diam = display->getWidth();
if (diam > (display->getHeight() * 2 / 3)) {
diam = display->getHeight() * 2 / 3;
if (diam > ((display->getHeight() - FONT_HEIGHT_SMALL) * 2 / 3)) {
diam = (display->getHeight() - FONT_HEIGHT_SMALL) * 2 / 3;
}
}
@@ -758,6 +787,8 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
// The coordinates define the left starting point of the text
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
const char *username = node->has_user ? node->user.long_name : "Unknown Name";
static char signalStr[20];
@@ -788,7 +819,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
const char *fields[] = {username, distStr, signalStr, lastStr, NULL};
// coordinates for the center of the compass/circle
int16_t compassX = x + SCREEN_WIDTH - getCompassDiam(display) / 2 - 5, compassY = y + SCREEN_HEIGHT / 2;
int16_t compassX = x + SCREEN_WIDTH - getCompassDiam(display) / 2 - 5, compassY = y + FONT_HEIGHT_SMALL + (SCREEN_HEIGHT - FONT_HEIGHT_SMALL) / 2;
bool hasNodeHeading = false;
if (ourNode && hasPosition(ourNode)) {
@@ -831,33 +862,11 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
display->drawString(compassX - FONT_HEIGHT_SMALL / 4, compassY - FONT_HEIGHT_SMALL / 2, "?");
display->drawCircle(compassX, compassY, getCompassDiam(display) / 2);
display->setColor(BLACK);
// Must be after distStr is populated
drawColumns(display, x, y, fields);
}
#if 0
void _screen_header()
{
if (!disp)
return;
// Message count
//snprintf(buffer, sizeof(buffer), "#%03d", ttn_get_count() % 1000);
//display->setTextAlignment(TEXT_ALIGN_LEFT);
//display->drawString(0, 2, buffer);
// Datetime
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->drawString(display->getWidth()/2, 2, gps.getTimeStr());
// Satellite count
display->setTextAlignment(TEXT_ALIGN_RIGHT);
char buffer[10];
display->drawString(display->getWidth() - SATELLITE_IMAGE_WIDTH - 4, 2, itoa(gps.satellites.value(), buffer, 10));
display->drawXbm(display->getWidth() - SATELLITE_IMAGE_WIDTH, 0, SATELLITE_IMAGE_WIDTH, SATELLITE_IMAGE_HEIGHT, SATELLITE_IMAGE);
}
#endif
// #ifdef RAK4630
// Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue(32), dispdev(address, sda, scl),
// dispdev_oled(address, sda, scl), ui(&dispdev)
@@ -1062,7 +1071,13 @@ int32_t Screen::runOnce()
handleSetOn(false);
break;
case Cmd::ON_PRESS:
// If a nag notification is running, stop it
if (moduleConfig.external_notification.enabled && (externalNotificationModule->nagCycleCutoff != UINT32_MAX)) {
externalNotificationModule->stopNow();
} else {
// Don't advance the screen if we just wanted to switch off the nag notification
handleOnPress();
}
break;
case Cmd::START_BLUETOOTH_PIN_SCREEN:
handleStartBluetoothPinScreen(cmd.bluetooth_pin);
@@ -1357,6 +1372,9 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
// The coordinates define the left starting point of the text
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
display->setColor(BLACK);
char channelStr[20];
{
concurrency::LockGuard guard(&lock);
@@ -1366,18 +1384,54 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
// Display power status
if (powerStatus->getHasBattery())
drawBattery(display, x, y + 2, imgBattery, powerStatus);
drawBattery(display, x + 1, y + 3, imgBattery, powerStatus);
else if (powerStatus->knowsUSB())
display->drawFastImage(x, y + 2, 16, 8, powerStatus->getHasUSB() ? imgUSB : imgPower);
display->drawFastImage(x + 1, y + 3, 16, 8, powerStatus->getHasUSB() ? imgUSB : imgPower);
// Display nodes status
drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 2, nodeStatus);
drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 3, nodeStatus);
// Display GPS status
if (!config.position.gps_enabled){
int16_t yPos = y + 2;
#ifdef GPS_POWER_TOGGLE
yPos = (y + 10 + FONT_HEIGHT_SMALL);
#endif
drawGPSpowerstat(display, x, yPos, gpsStatus);
} else {
drawGPS(display, x + (SCREEN_WIDTH * 0.63), y + 2, gpsStatus);
drawGPS(display, x + (SCREEN_WIDTH * 0.63), y + 3, gpsStatus);
}
display->setColor(WHITE);
// Draw the channel name
display->drawString(x, y + FONT_HEIGHT_SMALL, channelStr);
// Draw our hardware ID to assist with bluetooth pairing
display->drawFastImage(x + SCREEN_WIDTH - (10) - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 8, 8, imgInfo);
// Draw our hardware ID to assist with bluetooth pairing. Either prefix with Info or S&F Logo
if (moduleConfig.store_forward.enabled) {
#ifdef ARCH_ESP32
if (millis() - storeForwardModule->lastHeartbeat > (storeForwardModule->heartbeatInterval * 1200)) { //no heartbeat, overlap a bit
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8, imgQuestionL1);
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8, imgQuestionL2);
#else
display->drawFastImage(x + SCREEN_WIDTH - 10 - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 8, 8, imgQuestion);
#endif
} else {
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8, imgSFL1);
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 16, 8, imgSFL2);
#else
display->drawFastImage(x + SCREEN_WIDTH - 13 - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 11, 8, imgSF);
#endif
}
#endif
} else {
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8, imgInfoL1);
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8, imgInfoL2);
#else
display->drawFastImage(x + SCREEN_WIDTH - 10 - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 8, 8, imgInfo);
#endif
}
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(ourId), y + FONT_HEIGHT_SMALL, ourId);
// Draw any log messages
@@ -1404,15 +1458,24 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
// The coordinates define the left starting point of the text
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
display->setColor(BLACK);
if (WiFi.status() != WL_CONNECTED) {
display->drawString(x, y, String("WiFi: Not Connected"));
display->drawString(x + 1, y, String("WiFi: Not Connected"));
} else {
display->drawString(x, y, String("WiFi: Connected"));
display->drawString(x + 1, y, String("WiFi: Connected"));
display->drawString(x + SCREEN_WIDTH - display->getStringWidth("RSSI " + String(WiFi.RSSI())), y,
"RSSI " + String(WiFi.RSSI()));
display->drawString(x + SCREEN_WIDTH - display->getStringWidth("RSSI " + String(WiFi.RSSI())) - 1, y,
"RSSI " + String(WiFi.RSSI()));
}
display->setColor(WHITE);
/*
- WL_CONNECTED: assigned when connected to a WiFi network;
- WL_NO_SSID_AVAIL: assigned when no SSID are available;
@@ -1521,6 +1584,9 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
// The coordinates define the left starting point of the text
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
display->setColor(BLACK);
char batStr[20];
if (powerStatus->getHasBattery()) {
int batV = powerStatus->getBatteryVoltageMv() / 1000;
@@ -1531,9 +1597,11 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
// Line 1
display->drawString(x, y, batStr);
display->drawString(x + 1, y, batStr);
} else {
// Line 1
display->drawString(x, y, String("USB"));
display->drawString(x + 1, y, String("USB"));
}
auto mode = "";
@@ -1566,6 +1634,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
}
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode), y, mode);
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode) - 1, y, mode);
// Line 2
uint32_t currentMillis = millis();
@@ -1578,6 +1647,8 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
// minutes %= 60;
// hours %= 24;
display->setColor(WHITE);
// Show uptime as days, hours, minutes OR seconds
String uptime;
if (days >= 2)
@@ -1613,7 +1684,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
char chUtil[13];
sprintf(chUtil, "ChUtil %2.0f%%", airTime->channelUtilizationPercent());
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(chUtil), y + FONT_HEIGHT_SMALL * 1, chUtil);
if (config.position.gps_enabled) {
// Line 3
if (config.display.gps_format !=
Config_DisplayConfig_GpsCoordinateFormat_DMS) // if DMS then don't draw altitude
@@ -1621,7 +1692,9 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
// Line 4
drawGPScoordinates(display, x, y + FONT_HEIGHT_SMALL * 3, gpsStatus);
} else {
drawGPSpowerstat(display, x - (SCREEN_WIDTH / 4), y + FONT_HEIGHT_SMALL * 2, gpsStatus);
}
/* Display a heartbeat pixel that blinks every time the frame is redrawn */
#ifdef SHOW_REDRAWS
if (heartbeat)

View File

@@ -21,6 +21,7 @@ class Screen
void startBluetoothPinScreen(uint32_t pin) {}
void stopBluetoothPinScreen() {}
void startRebootScreen() {}
void startFirmwareUpdateScreen() {}
};
}

View File

@@ -12,36 +12,18 @@ const uint8_t imgPower[] PROGMEM = { 0x40, 0x40, 0x40, 0x58, 0x48, 0x08,
const uint8_t imgUser[] PROGMEM = { 0x3C, 0x42, 0x99, 0xA5, 0xA5, 0x99, 0x42, 0x3C };
const uint8_t imgPositionEmpty[] PROGMEM = { 0x20, 0x30, 0x28, 0x24, 0x42, 0xFF };
const uint8_t imgPositionSolid[] PROGMEM = { 0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF };
const uint8_t imgInfo[] PROGMEM = { 0xFF, 0x81, 0x81, 0xB5, 0xB5, 0x81, 0x81, 0xFF };
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
const uint8_t imgQuestionL1[] PROGMEM = { 0xff, 0x01, 0x01, 0x32, 0x7b, 0x49, 0x49, 0x6f, 0x26, 0x01, 0x01, 0xff };
const uint8_t imgQuestionL2[] PROGMEM = { 0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f };
const uint8_t imgInfoL1[] PROGMEM = { 0xff, 0x01, 0x01, 0x01, 0x1e, 0x7f, 0x1e, 0x01, 0x01, 0x01, 0x01, 0xff };
const uint8_t imgInfoL2[] PROGMEM = { 0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f };
const uint8_t imgSFL1[] PROGMEM = { 0xb6, 0x8f, 0x19, 0x11, 0x31, 0xe3, 0xc2, 0x01, 0x01, 0xf9, 0xf9, 0x89, 0x89, 0x89, 0x09, 0xeb};
const uint8_t imgSFL2[] PROGMEM = { 0x0e, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x00, 0x0f, 0x0f, 0x00, 0x08, 0x08, 0x08, 0x0f};
#else
const uint8_t imgInfo[] PROGMEM = { 0xff, 0x81, 0x00, 0xfb, 0xfb, 0x00, 0x81, 0xff };
const uint8_t imgQuestion[] PROGMEM = { 0xbf, 0x41, 0xc0, 0x8b, 0xdb, 0x70, 0xa1, 0xdf };
const uint8_t imgSF[] PROGMEM = { 0xd2, 0xb7, 0xad, 0xbb, 0x92, 0x01, 0xfd, 0xfd, 0x15, 0x85, 0xf5};
#endif
#include "img/icon.xbm"
// We now programmatically draw our compass
#if 0
const
#include "img/compass.xbm"
#endif
#if 0
const uint8_t activeSymbol[] PROGMEM = {
B00000000,
B00000000,
B00011000,
B00100100,
B01000010,
B01000010,
B00100100,
B00011000
};
const uint8_t inactiveSymbol[] PROGMEM = {
B00000000,
B00000000,
B00000000,
B00000000,
B00011000,
B00011000,
B00000000,
B00000000
};
#endif

View File

@@ -1,28 +0,0 @@
#define compass_width 48
#define compass_height 48
static char compass_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00,
0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00,
0x00, 0x00, 0xFC, 0x3F, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x01, 0x00,
0x00, 0xC0, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00,
0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0xFC, 0x07, 0xE0, 0x3F, 0x00,
0x00, 0xFE, 0x01, 0x80, 0x7F, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7F, 0x00,
0x00, 0x7F, 0x00, 0x00, 0xFE, 0x00, 0x80, 0x3F, 0x00, 0x00, 0xFC, 0x01,
0x80, 0x1F, 0x00, 0x00, 0xF8, 0x01, 0x80, 0x0F, 0x00, 0x00, 0xF0, 0x01,
0xC0, 0x0F, 0x00, 0x00, 0xF0, 0x03, 0xC0, 0x07, 0x00, 0x00, 0xE0, 0x03,
0xC0, 0x07, 0x00, 0x00, 0xE0, 0x03, 0xC0, 0x07, 0x00, 0x00, 0xE0, 0x03,
0xFC, 0x07, 0x00, 0x00, 0xE0, 0x3F, 0xFC, 0x07, 0x00, 0x00, 0xE0, 0x3F,
0xFC, 0x07, 0x00, 0x00, 0xE0, 0x3F, 0xFC, 0x07, 0x00, 0x00, 0xE0, 0x3F,
0xC0, 0x07, 0x00, 0x00, 0xE0, 0x03, 0xC0, 0x07, 0x00, 0x00, 0xE0, 0x03,
0xC0, 0x07, 0x00, 0x00, 0xE0, 0x03, 0xC0, 0x0F, 0x00, 0x00, 0xF0, 0x03,
0x80, 0x0F, 0x00, 0x00, 0xF0, 0x01, 0x80, 0x1F, 0x00, 0x00, 0xF8, 0x01,
0x80, 0x3F, 0x00, 0x00, 0xFC, 0x01, 0x00, 0x7F, 0x00, 0x00, 0xFE, 0x00,
0x00, 0xFE, 0x00, 0x00, 0x7F, 0x00, 0x00, 0xFE, 0x01, 0x80, 0x7F, 0x00,
0x00, 0xFC, 0x07, 0xE0, 0x3F, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00,
0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0x03, 0x00,
0x00, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0xFC, 0x3F, 0x00, 0x00,
0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00,
0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

View File

@@ -1,6 +0,0 @@
#define pin_width 13
#define pin_height 13
static char pin_bits[] = {
0x00, 0x00, 0xF0, 0x01, 0xF8, 0x03, 0xFC, 0x07, 0xBC, 0x07, 0xBC, 0x07,
0xFC, 0x07, 0xF8, 0x03, 0xF8, 0x03, 0xF0, 0x01, 0xE0, 0x00, 0xE0, 0x00,
0x00, 0x00, };

View File

@@ -8,8 +8,6 @@
#include "configuration.h"
#include "error.h"
#include "power.h"
// #include "rom/rtc.h"
//#include "DSRRouter.h"
#include "ReliableRouter.h"
// #include "debug.h"
#include "FSCommon.h"
@@ -217,7 +215,6 @@ void setup()
fsInit();
// router = new DSRRouter();
router = new ReliableRouter();
#ifdef I2C_SDA1
@@ -245,7 +242,6 @@ void setup()
digitalWrite(PIN_3V3_EN, 1);
#endif
// Currently only the tbeam has a PMU
// PMU initialization needs to be placed before scanI2Cdevice
power = new Power();
@@ -387,7 +383,7 @@ void setup()
}
#endif
#if defined(USE_SX1280) && !defined(ARCH_PORTDUINO)
#if defined(USE_SX1280)
if (!rIf) {
rIf = new SX1280Interface(SX128X_CS, SX128X_DIO1, SX128X_RESET, SX128X_BUSY, SPI);
if (!rIf->init()) {
@@ -452,6 +448,19 @@ void setup()
}
#endif
// check if the radio chip matches the selected region
if((config.lora.region == Config_LoRaConfig_RegionCode_LORA_24) && (!rIf->wideLora())){
DEBUG_MSG("Warning: Radio chip does not support 2.4GHz LoRa. Reverting to unset.\n");
config.lora.region = Config_LoRaConfig_RegionCode_UNSET;
nodeDB.saveToDisk(SEGMENT_CONFIG);
if(!rIf->reconfigure()) {
DEBUG_MSG("Reconfigure failed, rebooting\n");
screen->startRebootScreen();
rebootAtMsec = millis() + 5000;
}
}
#if HAS_WIFI || HAS_ETHERNET
mqttInit();
#endif

View File

@@ -196,6 +196,17 @@ Channel &Channels::getByIndex(ChannelIndex chIndex)
return *ch;
}
Channel &Channels::getByName(const char* chName)
{
for (ChannelIndex i = 0; i < getNumChannels(); i++) {
if (strcasecmp(channelFile.channels[i].settings.name, chName) == 0) {
return channelFile.channels[i];
}
}
return getByIndex(getPrimaryIndex());
}
void Channels::setChannel(const Channel &c)
{
Channel &old = getByIndex(c.index);

View File

@@ -40,6 +40,9 @@ class Channels
/** Return the Channel for a specified index */
Channel &getByIndex(ChannelIndex chIndex);
/** Return the Channel for a specified name, return primary if not found. */
Channel &getByName(const char* chName);
/** Using the index inside the channel, update the specified channel's settings and role. If this channel is being promoted
* to be primary, force all other channels to be secondary.
*/

View File

@@ -17,7 +17,7 @@ ErrorCode FloodingRouter::send(MeshPacket *p)
return Router::send(p);
}
bool FloodingRouter::shouldFilterReceived(MeshPacket *p)
bool FloodingRouter::shouldFilterReceived(const MeshPacket *p)
{
if (wasSeenRecently(p)) { // Note: this will also add a recent packet record
printPacket("Ignoring incoming msg, because we've already seen it", p);
@@ -34,13 +34,19 @@ void FloodingRouter::sniffReceived(const MeshPacket *p, const Routing *c)
// do not flood direct message that is ACKed
DEBUG_MSG("Receiving an ACK not for me, but don't need to rebroadcast this direct message anymore.\n");
Router::cancelSending(p->to, p->decoded.request_id); // cancel rebroadcast for this DM
} else if ((p->to != getNodeNum()) && (p->hop_limit > 0) && (getFrom(p) != getNodeNum())) {
}
if ((p->to != getNodeNum()) && (p->hop_limit > 0) && (getFrom(p) != getNodeNum())) {
if (p->id != 0) {
if (config.device.role != Config_DeviceConfig_Role_CLIENT_MUTE) {
MeshPacket *tosend = packetPool.allocCopy(*p); // keep a copy because we will be sending it
tosend->hop_limit--; // bump down the hop count
// If it is a traceRoute request, update the route that it went via me
if (p->which_payload_variant == MeshPacket_decoded_tag && traceRouteModule->wantPacket(p)) {
traceRouteModule->updateRoute(tosend);
}
printPacket("Rebroadcasting received floodmsg to neighbors", p);
// Note: we are careful to resend using the original senders node id
// We are careful not to call our hooked version of send() - because we don't want to check this again

View File

@@ -2,6 +2,7 @@
#include "PacketHistory.h"
#include "Router.h"
#include "modules/TraceRouteModule.h"
/**
* This is a mixin that extends Router with the ability to do Naive Flooding (in the standard mesh protocol sense)
@@ -50,7 +51,7 @@ class FloodingRouter : public Router, protected PacketHistory
* Called immedately on receiption, before any further processing.
* @return true to abandon the packet
*/
virtual bool shouldFilterReceived(MeshPacket *p) override;
virtual bool shouldFilterReceived(const MeshPacket *p) override;
/**
* Look for broadcasts we need to rebroadcast

View File

@@ -7,7 +7,4 @@
template class SX126xInterface<SX1262>;
template class SX126xInterface<SX1268>;
template class SX126xInterface<LLCC68>;
#if defined(RADIOLIB_GODMODE)
template class SX128xInterface<SX1280>;
#endif

View File

@@ -44,11 +44,11 @@ MeshPacket *MeshModule::allocAckNak(Routing_Error err, NodeNum to, PacketId idFr
// auto p = allocDataProtobuf(c);
MeshPacket *p = router->allocForSending();
p->decoded.portnum = PortNum_ROUTING_APP;
p->decoded.payload.size = pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), Routing_fields, &c);
p->decoded.payload.size = pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), &Routing_msg, &c);
p->priority = MeshPacket_Priority_ACK;
p->hop_limit = 0; // Assume just immediate neighbors for now
p->hop_limit = config.lora.hop_limit; // Flood ACK back to original sender
p->to = to;
p->decoded.request_id = idFrom;
p->channel = chIndex;

View File

@@ -162,6 +162,7 @@ void NodeDB::installDefaultConfig()
config.has_network = true;
config.has_bluetooth = true;
config.lora.tx_enabled = true; // FIXME: maybe false in the future, and setting region to enable it. (unset region forces it off)
config.lora.override_duty_cycle = false;
config.lora.region = Config_LoRaConfig_RegionCode_UNSET;
config.lora.modem_preset = Config_LoRaConfig_ModemPreset_LONG_FAST;
config.lora.hop_limit = HOP_RELIABLE;
@@ -214,9 +215,9 @@ void NodeDB::installDefaultModuleConfig()
moduleConfig.has_external_notification = true;
moduleConfig.has_canned_message = true;
strncpy(moduleConfig.mqtt.address, default_mqtt_address, sizeof(default_mqtt_address));
strncpy(moduleConfig.mqtt.username, default_mqtt_username, sizeof(default_mqtt_username));
strncpy(moduleConfig.mqtt.password, default_mqtt_password, sizeof(default_mqtt_password));
strncpy(moduleConfig.mqtt.address, default_mqtt_address, sizeof(moduleConfig.mqtt.address));
strncpy(moduleConfig.mqtt.username, default_mqtt_username, sizeof(moduleConfig.mqtt.username));
strncpy(moduleConfig.mqtt.password, default_mqtt_password, sizeof(moduleConfig.mqtt.password));
initModuleConfigIntervals();
}
@@ -400,7 +401,7 @@ bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_
void NodeDB::loadFromDisk()
{
// static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM
if (!loadProto(prefFileName, DeviceState_size, sizeof(devicestate), DeviceState_fields, &devicestate)) {
if (!loadProto(prefFileName, DeviceState_size, sizeof(DeviceState), &DeviceState_msg, &devicestate)) {
installDefaultDeviceState(); // Our in RAM copy might now be corrupt
} else {
if (devicestate.version < DEVICESTATE_MIN_VER) {
@@ -411,7 +412,7 @@ void NodeDB::loadFromDisk()
}
}
if (!loadProto(configFileName, LocalConfig_size, sizeof(LocalConfig), LocalConfig_fields, &config)) {
if (!loadProto(configFileName, LocalConfig_size, sizeof(LocalConfig), &LocalConfig_msg, &config)) {
installDefaultConfig(); // Our in RAM copy might now be corrupt
} else {
if (config.version < DEVICESTATE_MIN_VER) {
@@ -422,7 +423,7 @@ void NodeDB::loadFromDisk()
}
}
if (!loadProto(moduleConfigFileName, LocalModuleConfig_size, sizeof(LocalModuleConfig), LocalModuleConfig_fields, &moduleConfig)) {
if (!loadProto(moduleConfigFileName, LocalModuleConfig_size, sizeof(LocalModuleConfig), &LocalModuleConfig_msg, &moduleConfig)) {
installDefaultModuleConfig(); // Our in RAM copy might now be corrupt
} else {
if (moduleConfig.version < DEVICESTATE_MIN_VER) {
@@ -433,7 +434,7 @@ void NodeDB::loadFromDisk()
}
}
if (!loadProto(channelFileName, ChannelFile_size, sizeof(ChannelFile), ChannelFile_fields, &channelFile)) {
if (!loadProto(channelFileName, ChannelFile_size, sizeof(ChannelFile), &ChannelFile_msg, &channelFile)) {
installDefaultChannels(); // Our in RAM copy might now be corrupt
} else {
if (channelFile.version < DEVICESTATE_MIN_VER) {
@@ -444,12 +445,12 @@ void NodeDB::loadFromDisk()
}
}
if (loadProto(oemConfigFile, OEMStore_size, sizeof(OEMStore), OEMStore_fields, &oemStore))
if (loadProto(oemConfigFile, OEMStore_size, sizeof(OEMStore), &OEMStore_msg, &oemStore))
DEBUG_MSG("Loaded OEMStore\n");
}
/** Save a protobuf from a file, return true for success */
bool saveProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, const void *dest_struct)
bool saveProto(const char *filename, size_t protoSize, const pb_msgdesc_t *fields, const void *dest_struct)
{
bool okay = false;
#ifdef FSCom
@@ -497,7 +498,7 @@ void NodeDB::saveChannelsToDisk()
#ifdef FSCom
FSCom.mkdir("/prefs");
#endif
saveProto(channelFileName, ChannelFile_size, sizeof(channelFile), ChannelFile_fields, &channelFile);
saveProto(channelFileName, ChannelFile_size, &ChannelFile_msg, &channelFile);
}
}
@@ -507,7 +508,7 @@ void NodeDB::saveDeviceStateToDisk()
#ifdef FSCom
FSCom.mkdir("/prefs");
#endif
saveProto(prefFileName, DeviceState_size, sizeof(devicestate), DeviceState_fields, &devicestate);
saveProto(prefFileName, DeviceState_size, &DeviceState_msg, &devicestate);
}
}
@@ -529,7 +530,7 @@ void NodeDB::saveToDisk(int saveWhat)
config.has_power = true;
config.has_network = true;
config.has_bluetooth = true;
saveProto(configFileName, LocalConfig_size, sizeof(config), LocalConfig_fields, &config);
saveProto(configFileName, LocalConfig_size, &LocalConfig_msg, &config);
}
if (saveWhat & SEGMENT_MODULECONFIG) {
@@ -540,7 +541,7 @@ void NodeDB::saveToDisk(int saveWhat)
moduleConfig.has_serial = true;
moduleConfig.has_store_forward = true;
moduleConfig.has_telemetry = true;
saveProto(moduleConfigFileName, LocalModuleConfig_size, sizeof(moduleConfig), LocalModuleConfig_fields, &moduleConfig);
saveProto(moduleConfigFileName, LocalModuleConfig_size, &LocalModuleConfig_msg, &moduleConfig);
}
if (saveWhat & SEGMENT_CHANNELS) {

View File

@@ -77,7 +77,7 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
// return (lastContactMsec != 0) &&
memset(&toRadioScratch, 0, sizeof(toRadioScratch));
if (pb_decode_from_bytes(buf, bufLength, ToRadio_fields, &toRadioScratch)) {
if (pb_decode_from_bytes(buf, bufLength, &ToRadio_msg, &toRadioScratch)) {
switch (toRadioScratch.which_payload_variant) {
case ToRadio_packet_tag:
return handleToRadioPacket(toRadioScratch.packet);
@@ -291,7 +291,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
// Do we have a message from the mesh?
if (fromRadioScratch.which_payload_variant != 0) {
// Encapsulate as a FromRadio packet
size_t numbytes = pb_encode_to_bytes(buf, FromRadio_size, FromRadio_fields, &fromRadioScratch);
size_t numbytes = pb_encode_to_bytes(buf, FromRadio_size, &FromRadio_msg, &fromRadioScratch);
DEBUG_MSG("encoding toPhone packet to phone variant=%d, %d bytes\n", fromRadioScratch.which_payload_variant, numbytes);
return numbytes;

View File

@@ -175,7 +175,7 @@ uint32_t RadioInterface::getRetransmissionMsec(const MeshPacket *p)
{
assert(slotTimeMsec); // Better be non zero
static uint8_t bytes[MAX_RHPACKETLEN];
size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), Data_fields, &p->decoded);
size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), &Data_msg, &p->decoded);
uint32_t packetAirtime = getPacketTime(numbytes + sizeof(PacketHeader));
// Make sure enough time has elapsed for this packet to be sent and an ACK is received.
// DEBUG_MSG("Waiting for flooding message with airtime %d and slotTime is %d\n", packetAirtime, slotTimeMsec);

View File

@@ -1,6 +1,5 @@
#pragma once
#include "../concurrency/NotifiedWorkerThread.h"
#include "MemoryPool.h"
#include "MeshTypes.h"
#include "Observer.h"
@@ -97,6 +96,8 @@ class RadioInterface
*/
virtual bool canSleep() { return true; }
virtual bool wideLora() { return false; }
/// Prepare hardware for sleep. Call this _only_ for deep sleep, not needed for light sleep.
virtual bool sleep() { return true; }

View File

@@ -3,6 +3,7 @@
#include "NodeDB.h"
#include "SPILock.h"
#include "configuration.h"
#include "main.h"
#include "error.h"
#include "mesh-pb-constants.h"
#include <pb_decode.h>
@@ -87,10 +88,8 @@ bool RadioLibInterface::canSendImmediately()
if (busyTx && (millis() - lastTxStart > 60000)) {
DEBUG_MSG("Hardware Failure! busyTx for more than 60s\n");
RECORD_CRITICALERROR(CriticalErrorCode_TRANSMIT_FAILED);
#ifdef ARCH_ESP32
if (busyTx && (millis() - lastTxStart > 65000)) // After 5s more, reboot
ESP.restart();
#endif
// reboot in 5 seconds when this condition occurs.
rebootAtMsec = lastTxStart + 65000;
}
if (busyRx)
DEBUG_MSG("Can not send yet, busyRx\n");
@@ -386,6 +385,7 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
int res = iface->startTransmit(radiobuf, numbytes);
if (res != RADIOLIB_ERR_NONE) {
DEBUG_MSG("startTransmit failed, error=%d\n", res);
RECORD_CRITICALERROR(CriticalErrorCode_RADIO_SPI_BUG);
// This send failed, but make sure to 'complete' it properly

View File

@@ -1,10 +1,9 @@
#pragma once
#include "../concurrency/OSThread.h"
#include "concurrency/NotifiedWorkerThread.h"
#include "RadioInterface.h"
#include "MeshPacketQueue.h"
#define RADIOLIB_EXCLUDE_HTTP
#include <RadioLib.h>
// ESP32 has special rules about ISR code

View File

@@ -66,10 +66,5 @@ class RadioLibRF95: public SX1278 {
// since default current limit for SX126x/127x in updated RadioLib is 60mA
// use the previous value
float currentLimit = 100;
#ifndef RADIOLIB_GODMODE
private:
#endif
};

View File

@@ -27,7 +27,7 @@ ErrorCode ReliableRouter::send(MeshPacket *p)
return FloodingRouter::send(p);
}
bool ReliableRouter::shouldFilterReceived(MeshPacket *p)
bool ReliableRouter::shouldFilterReceived(const MeshPacket *p)
{
// Note: do not use getFrom() here, because we want to ignore messages sent from phone
if (p->from == getNodeNum()) {
@@ -37,9 +37,8 @@ bool ReliableRouter::shouldFilterReceived(MeshPacket *p)
// If this is the first time we saw this, cancel any retransmissions we have queued up and generate an internal ack for
// the original sending process.
// FIXME - we might want to turn off this "optimization", it does save lots of airtime but it assumes that once we've
// heard one one adjacent node hear our packet that a) probably other adjacent nodes heard it and b) we can trust those
// nodes to reach our destination. Both of which might be incorrect.
// This "optimization", does save lots of airtime. For DMs, you also get a real ACK back
// from the intended recipient.
auto key = GlobalPacketId(getFrom(p), p->id);
auto old = findPendingPacket(key);
if (old) {
@@ -54,16 +53,11 @@ bool ReliableRouter::shouldFilterReceived(MeshPacket *p)
}
}
/* send acks for repeated packets that want acks and are destined for us
* this way if an ACK is dropped and a packet is resent we'll ACK the resent packet
* make sure wasSeenRecently _doesn't_ update
* finding the channel requires decoding the packet. */
if (p->want_ack && (p->to == getNodeNum()) && wasSeenRecently(p, false) && !MeshModule::currentReply) {
if (perhapsDecode(p)) {
sendAckNak(Routing_Error_NONE, getFrom(p), p->id, p->channel);
DEBUG_MSG("acking a repeated want_ack packet\n");
}
} else if (wasSeenRecently(p, false) && p->hop_limit == HOP_RELIABLE && !MeshModule::currentReply && p->to != nodeDB.getNodeNum()) {
/* Resend implicit ACKs for repeated packets (assuming the original packet was sent with HOP_RELIABLE)
* this way if an implicit ACK is dropped and a packet is resent we'll rebroadcast again.
* Resending real ACKs is omitted, as you might receive a packet multiple times due to flooding and
* flooding this ACK back to the original sender already adds redundancy. */
if (wasSeenRecently(p, false) && p->hop_limit == HOP_RELIABLE && !MeshModule::currentReply && p->to != nodeDB.getNodeNum()) {
// retransmission on broadcast has hop_limit still equal to HOP_RELIABLE
DEBUG_MSG("Resending implicit ack for a repeated floodmsg\n");
MeshPacket *tosend = packetPool.allocCopy(*p);
@@ -90,8 +84,7 @@ void ReliableRouter::sniffReceived(const MeshPacket *p, const Routing *c)
{
NodeNum ourNode = getNodeNum();
if (p->to == ourNode) { // ignore ack/nak/want_ack packets that are not address to us (we only handle 0 hop reliability
// - not DSR routing)
if (p->to == ourNode) { // ignore ack/nak/want_ack packets that are not address to us (we only handle 0 hop reliability)
if (p->want_ack) {
if (MeshModule::currentReply)
DEBUG_MSG("Some other module has replied to this message, no need for a 2nd ack\n");
@@ -200,8 +193,7 @@ int32_t ReliableRouter::doRetransmissions()
DEBUG_MSG("Reliable send failed, returning a nak for fr=0x%x,to=0x%x,id=0x%x\n", p.packet->from, p.packet->to,
p.packet->id);
sendAckNak(Routing_Error_MAX_RETRANSMIT, getFrom(p.packet), p.packet->id, p.packet->channel);
// Note: we don't stop retransmission here, instead the Nak packet gets processed in sniffReceived - which
// allows the DSR version to still be able to look at the PendingPacket
// Note: we don't stop retransmission here, instead the Nak packet gets processed in sniffReceived
stopRetransmission(it->first);
stillValid = false; // just deleted it
} else {

View File

@@ -38,12 +38,6 @@ struct PendingPacket {
/** Starts at NUM_RETRANSMISSIONS -1(normally 3) and counts down. Once zero it will be removed from the list */
uint8_t numRetransmissions = 0;
/** True if we have started trying to find a route - for DSR usage
* While trying to find a route we don't actually send the data packet. We just leave it here pending until
* we have a route or we've failed to find one.
*/
bool wantRoute = false;
PendingPacket() {}
explicit PendingPacket(MeshPacket *p);
};
@@ -102,7 +96,7 @@ class ReliableRouter : public FloodingRouter
/**
* We hook this method so we can see packets before FloodingRouter says they should be discarded
*/
virtual bool shouldFilterReceived(MeshPacket *p) override;
virtual bool shouldFilterReceived(const MeshPacket *p) override;
/**
* Add p to the list of packets to retransmit occasionally. We will free it once we stop retransmitting.

View File

@@ -2,6 +2,7 @@
#include "Channels.h"
#include "CryptoEngine.h"
#include "NodeDB.h"
#include "MeshRadio.h"
#include "RTC.h"
#include "configuration.h"
#include "main.h"
@@ -21,7 +22,6 @@ extern "C" {
* DONE: Implement basic interface and use it elsewhere in app
* Add naive flooding mixin (& drop duplicate rx broadcasts), add tools for sending broadcasts with incrementing sequence #s
* Add an optional adjacent node only 'send with ack' mixin. If we timeout waiting for the ack, call handleAckTimeout(packet)
* Add DSR mixin
*
**/
@@ -188,6 +188,18 @@ ErrorCode Router::send(MeshPacket *p)
{
assert(p->to != nodeDB.getNodeNum()); // should have already been handled by sendLocal
// Abort sending if we are violating the duty cycle
if (!config.lora.override_duty_cycle && myRegion->dutyCycle != 100) {
float hourlyTxPercent = airTime->utilizationTXPercent();
if (hourlyTxPercent > myRegion->dutyCycle) {
uint8_t silentMinutes = airTime->getSilentMinutes(hourlyTxPercent, myRegion->dutyCycle);
DEBUG_MSG("WARNING: Duty cycle limit exceeded. Aborting send for now, you can send again in %d minutes.\n", silentMinutes);
Routing_Error err = Routing_Error_DUTY_CYCLE_LIMIT;
abortSendAndNak(err, p);
return err;
}
}
// PacketId nakId = p->decoded.which_ackVariant == SubPacket_fail_id_tag ? p->decoded.ackVariant.fail_id : 0;
// assert(!nakId); // I don't think we ever send 0hop naks over the wire (other than to the phone), test that assumption with
// assert
@@ -294,7 +306,7 @@ bool perhapsDecode(MeshPacket *p)
// Take those raw bytes and convert them back into a well structured protobuf we can understand
memset(&p->decoded, 0, sizeof(p->decoded));
if (!pb_decode_from_bytes(bytes, rawSize, Data_fields, &p->decoded)) {
if (!pb_decode_from_bytes(bytes, rawSize, &Data_msg, &p->decoded)) {
DEBUG_MSG("Invalid protobufs in received mesh packet (bad psk?)!\n");
} else if (p->decoded.portnum == PortNum_UNKNOWN_APP) {
DEBUG_MSG("Invalid portnum (bad psk?)!\n");
@@ -348,7 +360,7 @@ Routing_Error perhapsEncode(MeshPacket *p)
if (p->which_payload_variant == MeshPacket_decoded_tag) {
static uint8_t bytes[MAX_RHPACKETLEN]; // we have to use a scratch buffer because a union
size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), Data_fields, &p->decoded);
size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), &Data_msg, &p->decoded);
// Only allow encryption on the text message app.
// TODO: Allow modules to opt into compression.

View File

@@ -90,7 +90,7 @@ class Router : protected concurrency::OSThread
* Called immedately on receiption, before any further processing.
* @return true to abandon the packet
*/
virtual bool shouldFilterReceived(MeshPacket *p) { return false; }
virtual bool shouldFilterReceived(const MeshPacket *p) { return false; }
/**
* Every (non duplicate) packet this node receives will be passed through this method. This allows subclasses to

View File

@@ -2,12 +2,8 @@
#include "SX1280Interface.h"
#include "error.h"
#if defined(RADIOLIB_GODMODE)
SX1280Interface::SX1280Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
SPIClass &spi)
: SX128xInterface(cs, irq, rst, busy, spi)
{
}
#endif

View File

@@ -6,12 +6,9 @@
* Our adapter for SX1280 radios
*/
#if defined(RADIOLIB_GODMODE)
class SX1280Interface : public SX128xInterface<SX1280>
{
public:
SX1280Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi);
};
#endif

View File

@@ -1,9 +1,8 @@
#include "configuration.h"
#include "SX128xInterface.h"
#include "mesh/NodeDB.h"
#include "error.h"
#if defined(RADIOLIB_GODMODE)
// Particular boards might define a different max power based on what their hardware can do
#ifndef SX128X_MAX_POWER
#define SX128X_MAX_POWER 13
@@ -27,11 +26,11 @@ bool SX128xInterface<T>::init()
pinMode(SX128X_POWER_EN, OUTPUT);
#endif
#ifdef SX128X_RXEN // set not rx or tx mode
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // set not rx or tx mode
digitalWrite(SX128X_RXEN, LOW); // Set low before becoming an output
pinMode(SX128X_RXEN, OUTPUT);
#endif
#ifdef SX128X_TXEN
#if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC)
digitalWrite(SX128X_TXEN, LOW);
pinMode(SX128X_TXEN, OUTPUT);
#endif
@@ -46,20 +45,30 @@ bool SX128xInterface<T>::init()
limitPower();
preambleLength = 12; // 12 is the default for this chip, 32 does not RX at all
int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength);
// \todo Display actual typename of the adapter, not just `SX128x`
DEBUG_MSG("SX128x init result %d\n", res);
if((config.lora.region != Config_LoRaConfig_RegionCode_LORA_24) && (res == RADIOLIB_ERR_INVALID_FREQUENCY)) {
DEBUG_MSG("Warning: Radio chip only supports 2.4GHz LoRa. Adjusting Region and rebooting.\n");
config.lora.region = Config_LoRaConfig_RegionCode_LORA_24;
nodeDB.saveToDisk(SEGMENT_CONFIG);
delay(2000);
#if defined(ARCH_ESP32)
ESP.restart();
#elif defined(ARCH_NRF52)
NVIC_SystemReset();
#else
DEBUG_MSG("FIXME implement reboot for this platform. Skipping for now.\n");
#endif
}
DEBUG_MSG("Frequency set to %f\n", getFreq());
DEBUG_MSG("Bandwidth set to %f\n", bw);
DEBUG_MSG("Power output set to %d\n", power);
#ifdef SX128X_TXEN
// lora.begin sets Dio2 as RF switch control, which is not true if we are manually controlling RX and TX
if (res == RADIOLIB_ERR_NONE)
res = lora.setDio2AsRfSwitch(true);
#endif
if (res == RADIOLIB_ERR_NONE)
res = lora.setCRC(2);
@@ -122,18 +131,28 @@ void INTERRUPT_ATTR SX128xInterface<T>::disableInterrupt()
lora.clearDio1Action();
}
template<typename T>
bool SX128xInterface<T>::wideLora()
{
return true;
}
template<typename T>
void SX128xInterface<T>::setStandby()
{
checkNotification(); // handle any pending interrupts before we force standby
int err = lora.standby();
if (err != RADIOLIB_ERR_NONE)
DEBUG_MSG("SX128x standby failed with error %d\n", err);
assert(err == RADIOLIB_ERR_NONE);
#ifdef SX128X_RXEN // we have RXEN/TXEN control - turn off RX and TX power
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn off RX and TX power
digitalWrite(SX128X_RXEN, LOW);
#endif
#ifdef SX128X_TXEN
#if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC)
digitalWrite(SX128X_TXEN, LOW);
#endif
@@ -158,10 +177,10 @@ void SX128xInterface<T>::addReceiveMetadata(MeshPacket *mp)
template<typename T>
void SX128xInterface<T>::configHardwareForSend()
{
#ifdef SX128X_TXEN // we have RXEN/TXEN control - turn on TX power / off RX power
#if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn on TX power / off RX power
digitalWrite(SX128X_TXEN, HIGH);
#endif
#ifdef SX128X_RXEN
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC)
digitalWrite(SX128X_RXEN, LOW);
#endif
@@ -180,10 +199,10 @@ void SX128xInterface<T>::startReceive()
setStandby();
#ifdef SX128X_RXEN // we have RXEN/TXEN control - turn on RX power / off TX power
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn on RX power / off TX power
digitalWrite(SX128X_RXEN, HIGH);
#endif
#ifdef SX128X_TXEN
#if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC)
digitalWrite(SX128X_TXEN, LOW);
#endif
@@ -219,8 +238,6 @@ bool SX128xInterface<T>::isChannelActive()
template<typename T>
bool SX128xInterface<T>::isActivelyReceiving()
{
// return isChannelActive();
uint16_t irq = lora.getIrqStatus();
bool hasPreamble = (irq & RADIOLIB_SX128X_IRQ_HEADER_VALID);
return hasPreamble;
@@ -248,5 +265,3 @@ bool SX128xInterface<T>::sleep()
return true;
}
#endif

View File

@@ -1,7 +1,5 @@
#pragma once
#if defined(RADIOLIB_GODMODE)
#include "RadioLibInterface.h"
/**
@@ -19,6 +17,8 @@ class SX128xInterface : public RadioLibInterface
/// \return true if initialisation succeeded.
virtual bool init() override;
virtual bool wideLora() override;
/// Apply any radio provisioning changes
/// Make sure the Driver is properly configured before calling init().
/// \return true if initialisation succeeded.
@@ -27,9 +27,9 @@ class SX128xInterface : public RadioLibInterface
/// Prepare hardware for sleep. Call this _only_ for deep sleep, not needed for light sleep.
virtual bool sleep() override;
protected:
bool isIRQPending() override { return lora.getIrqStatus() != 0; }
float currentLimit = 140; // Higher OCP limit for SX128x PA
protected:
/**
* Specific module instance
@@ -71,5 +71,3 @@ class SX128xInterface : public RadioLibInterface
private:
};
#endif

View File

@@ -6,7 +6,7 @@
#define START2 0xc3
#define HEADER_LEN 4
int32_t StreamAPI::runOnce()
int32_t StreamAPI::runOncePart()
{
auto result = readStream();
writeStream();
@@ -115,7 +115,7 @@ void StreamAPI::emitRebooted()
fromRadioScratch.rebooted = true;
// DEBUG_MSG("Emitting reboot packet for serial shell\n");
emitTxBuffer(pb_encode_to_bytes(txBuf + HEADER_LEN, FromRadio_size, FromRadio_fields, &fromRadioScratch));
emitTxBuffer(pb_encode_to_bytes(txBuf + HEADER_LEN, FromRadio_size, &FromRadio_msg, &fromRadioScratch));
}
/// Hookable to find out when connection changes

View File

@@ -28,7 +28,7 @@ valid utf8 encoding. This makes it a bit easier to start a device outputting reg
after it has received a valid packet from the PC, turn off unencoded debug printing and switch to this packet encoding.
*/
class StreamAPI : public PhoneAPI, protected concurrency::OSThread
class StreamAPI : public PhoneAPI
{
/**
* The stream we read/write from
@@ -42,13 +42,13 @@ class StreamAPI : public PhoneAPI, protected concurrency::OSThread
uint32_t lastRxMsec = 0;
public:
StreamAPI(Stream *_stream) : concurrency::OSThread("StreamAPI"), stream(_stream) {}
StreamAPI(Stream *_stream) : stream(_stream) {}
/**
* Currently we require frequent invocation from loop() to check for arrived serial packets and to send new packets to the
* phone.
*/
virtual int32_t runOnce() override;
virtual int32_t runOncePart();
private:
/**

View File

@@ -14,7 +14,7 @@ void initApiServer(int port)
}
}
ethServerAPI::ethServerAPI(EthernetClient &_client) : StreamAPI(&client), client(_client)
ethServerAPI::ethServerAPI(EthernetClient &_client) : StreamAPI(&client), concurrency::OSThread("ethServerAPI"), client(_client)
{
DEBUG_MSG("Incoming ethernet connection\n");
}
@@ -42,7 +42,7 @@ bool ethServerAPI::checkIsConnected()
int32_t ethServerAPI::runOnce()
{
if (client.connected()) {
return StreamAPI::runOnce();
return StreamAPI::runOncePart();
} else {
DEBUG_MSG("Client dropped connection, suspending API service\n");
enabled = false; // we no longer need to run

View File

@@ -7,7 +7,7 @@
* 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).
*/
class ethServerAPI : public StreamAPI
class ethServerAPI : public StreamAPI, private concurrency::OSThread
{
private:
EthernetClient client;

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#include "admin.pb.h"
#if PB_PROTO_HEADER_VERSION != 40

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#ifndef PB_ADMIN_PB_H_INCLUDED
#define PB_ADMIN_PB_H_INCLUDED
@@ -15,24 +15,41 @@
#endif
/* Enum definitions */
/* TODO: REPLACE */
typedef enum _AdminMessage_ConfigType {
/* TODO: REPLACE */
AdminMessage_ConfigType_DEVICE_CONFIG = 0,
/* TODO: REPLACE */
AdminMessage_ConfigType_POSITION_CONFIG = 1,
/* TODO: REPLACE */
AdminMessage_ConfigType_POWER_CONFIG = 2,
/* TODO: REPLACE */
AdminMessage_ConfigType_NETWORK_CONFIG = 3,
/* TODO: REPLACE */
AdminMessage_ConfigType_DISPLAY_CONFIG = 4,
/* TODO: REPLACE */
AdminMessage_ConfigType_LORA_CONFIG = 5,
/* TODO: REPLACE */
AdminMessage_ConfigType_BLUETOOTH_CONFIG = 6
} AdminMessage_ConfigType;
/* TODO: REPLACE */
typedef enum _AdminMessage_ModuleConfigType {
/* TODO: REPLACE */
AdminMessage_ModuleConfigType_MQTT_CONFIG = 0,
/* TODO: REPLACE */
AdminMessage_ModuleConfigType_SERIAL_CONFIG = 1,
/* TODO: REPLACE */
AdminMessage_ModuleConfigType_EXTNOTIF_CONFIG = 2,
/* TODO: REPLACE */
AdminMessage_ModuleConfigType_STOREFORWARD_CONFIG = 3,
/* TODO: REPLACE */
AdminMessage_ModuleConfigType_RANGETEST_CONFIG = 4,
/* TODO: REPLACE */
AdminMessage_ModuleConfigType_TELEMETRY_CONFIG = 5,
/* TODO: REPLACE */
AdminMessage_ModuleConfigType_CANNEDMSG_CONFIG = 6,
/* TODO: REPLACE */
AdminMessage_ModuleConfigType_AUDIO_CONFIG = 7
} AdminMessage_ModuleConfigType;
@@ -112,6 +129,10 @@ typedef struct _AdminMessage {
} AdminMessage;
#ifdef __cplusplus
extern "C" {
#endif
/* Helper constants for enums */
#define _AdminMessage_ConfigType_MIN AdminMessage_ConfigType_DEVICE_CONFIG
#define _AdminMessage_ConfigType_MAX AdminMessage_ConfigType_BLUETOOTH_CONFIG
@@ -121,10 +142,9 @@ typedef struct _AdminMessage {
#define _AdminMessage_ModuleConfigType_MAX AdminMessage_ModuleConfigType_AUDIO_CONFIG
#define _AdminMessage_ModuleConfigType_ARRAYSIZE ((AdminMessage_ModuleConfigType)(AdminMessage_ModuleConfigType_AUDIO_CONFIG+1))
#define AdminMessage_payload_variant_get_config_request_ENUMTYPE AdminMessage_ConfigType
#define AdminMessage_payload_variant_get_module_config_request_ENUMTYPE AdminMessage_ModuleConfigType
#ifdef __cplusplus
extern "C" {
#endif
/* Initializer values for message structs */
#define AdminMessage_init_default {0, {0}}

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#include "apponly.pb.h"
#if PB_PROTO_HEADER_VERSION != 40

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#ifndef PB_APPONLY_PB_H_INCLUDED
#define PB_APPONLY_PB_H_INCLUDED
@@ -54,7 +54,7 @@ extern const pb_msgdesc_t ChannelSet_msg;
#define ChannelSet_fields &ChannelSet_msg
/* Maximum encoded size of messages (where known) */
#define ChannelSet_size 582
#define ChannelSet_size 584
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#include "cannedmessages.pb.h"
#if PB_PROTO_HEADER_VERSION != 40

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#ifndef PB_CANNEDMESSAGES_PB_H_INCLUDED
#define PB_CANNEDMESSAGES_PB_H_INCLUDED

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#include "channel.pb.h"
#if PB_PROTO_HEADER_VERSION != 40

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#ifndef PB_CHANNEL_PB_H_INCLUDED
#define PB_CHANNEL_PB_H_INCLUDED
@@ -10,9 +10,22 @@
#endif
/* Enum definitions */
/* How this channel is being used (or not).
Note: this field is an enum to give us options for the future.
In particular, someday we might make a 'SCANNING' option.
SCANNING channels could have different frequencies and the radio would
occasionally check that freq to see if anything is being transmitted.
For devices that have multiple physical radios attached, we could keep multiple PRIMARY/SCANNING channels active at once to allow
cross band routing as needed.
If a device has only a single radio (the common case) only one channel can be PRIMARY at a time
(but any number of SECONDARY channels can't be sent received on that common frequency) */
typedef enum _Channel_Role {
/* This channel is not in use right now */
Channel_Role_DISABLED = 0,
/* This channel is used to set the frequency for the radio - all other enabled channels must be SECONDARY */
Channel_Role_PRIMARY = 1,
/* Secondary channels are only used for encryption/decryption/authentication purposes.
Their radio settings (freq etc) are ignored, only psk is used. */
Channel_Role_SECONDARY = 2
} Channel_Role;
@@ -92,15 +105,18 @@ typedef struct _Channel {
} Channel;
#ifdef __cplusplus
extern "C" {
#endif
/* Helper constants for enums */
#define _Channel_Role_MIN Channel_Role_DISABLED
#define _Channel_Role_MAX Channel_Role_SECONDARY
#define _Channel_Role_ARRAYSIZE ((Channel_Role)(Channel_Role_SECONDARY+1))
#ifdef __cplusplus
extern "C" {
#endif
#define Channel_role_ENUMTYPE Channel_Role
/* Initializer values for message structs */
#define ChannelSettings_init_default {0, {0, {0}}, "", 0, 0, 0}

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#include "config.pb.h"
#if PB_PROTO_HEADER_VERSION != 40

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#ifndef PB_CONFIG_PB_H_INCLUDED
#define PB_CONFIG_PB_H_INCLUDED
@@ -10,166 +10,369 @@
#endif
/* Enum definitions */
/* Defines the device's role on the Mesh network */
typedef enum _Config_DeviceConfig_Role {
/* Client device role */
Config_DeviceConfig_Role_CLIENT = 0,
/* Client Mute device role
Same as a client except packets will not hop over this node, does not contribute to routing packets for mesh. */
Config_DeviceConfig_Role_CLIENT_MUTE = 1,
/* Router device role.
Mesh packets will prefer to be routed over this node. This node will not be used by client apps.
The wifi/ble radios and the oled screen will be put to sleep. */
Config_DeviceConfig_Role_ROUTER = 2,
/* Router Client device role
Mesh packets will prefer to be routed over this node. The Router Client can be used as both a Router and an app connected Client. */
Config_DeviceConfig_Role_ROUTER_CLIENT = 3
} Config_DeviceConfig_Role;
/* Bit field of boolean configuration options, indicating which optional
fields to include when assembling POSITION messages
Longitude and latitude are always included (also time if GPS-synced)
NOTE: the more fields are included, the larger the message will be -
leading to longer airtime and a higher risk of packet loss */
typedef enum _Config_PositionConfig_PositionFlags {
/* Required for compilation */
Config_PositionConfig_PositionFlags_UNSET = 0,
/* Include an altitude value (if available) */
Config_PositionConfig_PositionFlags_ALTITUDE = 1,
/* Altitude value is MSL */
Config_PositionConfig_PositionFlags_ALTITUDE_MSL = 2,
/* Include geoidal separation */
Config_PositionConfig_PositionFlags_GEOIDAL_SEPARATION = 4,
/* Include the DOP value ; PDOP used by default, see below */
Config_PositionConfig_PositionFlags_DOP = 8,
/* If POS_DOP set, send separate HDOP / VDOP values instead of PDOP */
Config_PositionConfig_PositionFlags_HVDOP = 16,
/* Include number of "satellites in view" */
Config_PositionConfig_PositionFlags_SATINVIEW = 32,
/* Include a sequence number incremented per packet */
Config_PositionConfig_PositionFlags_SEQ_NO = 64,
/* Include positional timestamp (from GPS solution) */
Config_PositionConfig_PositionFlags_TIMESTAMP = 128,
/* Include positional heading
Intended for use with vehicle not walking speeds
walking speeds are likely to be error prone like the compass */
Config_PositionConfig_PositionFlags_HEADING = 256,
/* Include positional speed
Intended for use with vehicle not walking speeds
walking speeds are likely to be error prone like the compass */
Config_PositionConfig_PositionFlags_SPEED = 512
} Config_PositionConfig_PositionFlags;
typedef enum _Config_NetworkConfig_EthMode {
/* obtain ip address via DHCP */
Config_NetworkConfig_EthMode_DHCP = 0,
/* use static ip address */
Config_NetworkConfig_EthMode_STATIC = 1
} Config_NetworkConfig_EthMode;
/* How the GPS coordinates are displayed on the OLED screen. */
typedef enum _Config_DisplayConfig_GpsCoordinateFormat {
/* GPS coordinates are displayed in the normal decimal degrees format:
DD.DDDDDD DDD.DDDDDD */
Config_DisplayConfig_GpsCoordinateFormat_DEC = 0,
/* GPS coordinates are displayed in the degrees minutes seconds format:
DD°MM'SS"C DDD°MM'SS"C, where C is the compass point representing the locations quadrant */
Config_DisplayConfig_GpsCoordinateFormat_DMS = 1,
/* Universal Transverse Mercator format:
ZZB EEEEEE NNNNNNN, where Z is zone, B is band, E is easting, N is northing */
Config_DisplayConfig_GpsCoordinateFormat_UTM = 2,
/* Military Grid Reference System format:
ZZB CD EEEEE NNNNN, where Z is zone, B is band, C is the east 100k square, D is the north 100k square,
E is easting, N is northing */
Config_DisplayConfig_GpsCoordinateFormat_MGRS = 3,
/* Open Location Code (aka Plus Codes). */
Config_DisplayConfig_GpsCoordinateFormat_OLC = 4,
/* Ordnance Survey Grid Reference (the National Grid System of the UK).
Format: AB EEEEE NNNNN, where A is the east 100k square, B is the north 100k square,
E is the easting, N is the northing */
Config_DisplayConfig_GpsCoordinateFormat_OSGR = 5
} Config_DisplayConfig_GpsCoordinateFormat;
/* Unit display preference */
typedef enum _Config_DisplayConfig_DisplayUnits {
/* Metric (Default) */
Config_DisplayConfig_DisplayUnits_METRIC = 0,
/* Imperial */
Config_DisplayConfig_DisplayUnits_IMPERIAL = 1
} Config_DisplayConfig_DisplayUnits;
/* Override OLED outo detect with this if it fails. */
typedef enum _Config_DisplayConfig_OledType {
/* Default / Auto */
Config_DisplayConfig_OledType_OLED_AUTO = 0,
/* Default / Auto */
Config_DisplayConfig_OledType_OLED_SSD1306 = 1,
/* Default / Auto */
Config_DisplayConfig_OledType_OLED_SH1106 = 2
} Config_DisplayConfig_OledType;
typedef enum _Config_LoRaConfig_RegionCode {
/* Region is not set */
Config_LoRaConfig_RegionCode_UNSET = 0,
/* United States */
Config_LoRaConfig_RegionCode_US = 1,
/* European Union 433mhz */
Config_LoRaConfig_RegionCode_EU_433 = 2,
/* European Union 433mhz */
Config_LoRaConfig_RegionCode_EU_868 = 3,
/* China */
Config_LoRaConfig_RegionCode_CN = 4,
/* Japan */
Config_LoRaConfig_RegionCode_JP = 5,
/* Australia / New Zealand */
Config_LoRaConfig_RegionCode_ANZ = 6,
/* Korea */
Config_LoRaConfig_RegionCode_KR = 7,
/* Taiwan */
Config_LoRaConfig_RegionCode_TW = 8,
/* Russia */
Config_LoRaConfig_RegionCode_RU = 9,
/* India */
Config_LoRaConfig_RegionCode_IN = 10,
/* New Zealand 865mhz */
Config_LoRaConfig_RegionCode_NZ_865 = 11,
/* Thailand */
Config_LoRaConfig_RegionCode_TH = 12,
/* WLAN Band */
Config_LoRaConfig_RegionCode_LORA_24 = 13
} Config_LoRaConfig_RegionCode;
/* Standard predefined channel settings
Note: these mappings must match ModemPreset Choice in the device code. */
typedef enum _Config_LoRaConfig_ModemPreset {
/* Long Range - Fast */
Config_LoRaConfig_ModemPreset_LONG_FAST = 0,
/* Long Range - Slow */
Config_LoRaConfig_ModemPreset_LONG_SLOW = 1,
/* Very Long Range - Slow */
Config_LoRaConfig_ModemPreset_VERY_LONG_SLOW = 2,
/* Medium Range - Slow */
Config_LoRaConfig_ModemPreset_MEDIUM_SLOW = 3,
/* Medium Range - Fast */
Config_LoRaConfig_ModemPreset_MEDIUM_FAST = 4,
/* Short Range - Slow */
Config_LoRaConfig_ModemPreset_SHORT_SLOW = 5,
/* Short Range - Fast */
Config_LoRaConfig_ModemPreset_SHORT_FAST = 6
} Config_LoRaConfig_ModemPreset;
typedef enum _Config_BluetoothConfig_PairingMode {
/* Device generates a random pin that will be shown on the screen of the device for pairing */
Config_BluetoothConfig_PairingMode_RANDOM_PIN = 0,
/* Device requires a specified fixed pin for pairing */
Config_BluetoothConfig_PairingMode_FIXED_PIN = 1,
/* Device requires no pin for pairing */
Config_BluetoothConfig_PairingMode_NO_PIN = 2
} Config_BluetoothConfig_PairingMode;
/* Struct definitions */
typedef struct _Config_BluetoothConfig {
bool enabled;
Config_BluetoothConfig_PairingMode mode;
uint32_t fixed_pin;
} Config_BluetoothConfig;
/* Configuration */
typedef struct _Config_DeviceConfig {
/* Sets the role of node */
Config_DeviceConfig_Role role;
/* Disabling this will disable the SerialConsole by not initilizing the StreamAPI */
bool serial_enabled;
/* By default we turn off logging as soon as an API client connects (to keep shared serial link quiet).
Set this to true to leave the debug log outputting even when API is active. */
bool debug_log_enabled;
/* For boards without a hard wired button, this is the pin number that will be used
Boards that have more than one button can swap the function with this one. defaults to BUTTON_PIN if defined. */
uint32_t button_gpio;
/* For boards without a PWM buzzer, this is the pin number that will be used
Defaults to PIN_BUZZER if defined. */
uint32_t buzzer_gpio;
} Config_DeviceConfig;
/* Position Config */
typedef struct _Config_PositionConfig {
/* We should send our position this often (but only if it has changed significantly)
Defaults to 15 minutes */
uint32_t position_broadcast_secs;
/* Adaptive position braoadcast, which is now the default. */
bool position_broadcast_smart_enabled;
/* If set, this node is at a fixed position.
We will generate GPS position updates at the regular interval, but use whatever the last lat/lon/alt we have for the node.
The lat/lon/alt can be set by an internal GPS or with the help of the app. */
bool fixed_position;
/* Is GPS enabled for this node? */
bool gps_enabled;
/* How often should we try to get GPS position (in seconds)
or zero for the default of once every 30 seconds
or a very large value (maxint) to update only once at boot. */
uint32_t gps_update_interval;
/* How long should we try to get our position during each gps_update_interval attempt? (in seconds)
Or if zero, use the default of 30 seconds.
If we don't get a new gps fix in that time, the gps will be put into sleep until the next gps_update_rate
window. */
uint32_t gps_attempt_time;
/* Bit field of boolean configuration options for POSITION messages
(bitwise OR of PositionFlags) */
uint32_t position_flags;
/* (Re)define GPS_RX_PIN for your board. */
uint32_t rx_gpio;
/* (Re)define GPS_TX_PIN for your board. */
uint32_t tx_gpio;
} Config_PositionConfig;
/* Power Config\
See [Power Config](/docs/settings/config/power) for additional power config details. */
typedef struct _Config_PowerConfig {
/* If set, we are powered from a low-current source (i.e. solar), so even if it looks like we have power flowing in
we should try to minimize power consumption as much as possible.
YOU DO NOT NEED TO SET THIS IF YOU'VE set is_router (it is implied in that case).
Advanced Option */
bool is_power_saving;
/* If non-zero, the device will fully power off this many seconds after external power is removed. */
uint32_t on_battery_shutdown_after_secs;
/* Ratio of voltage divider for battery pin eg. 3.20 (R1=100k, R2=220k)
Overrides the ADC_MULTIPLIER defined in variant for battery voltage calculation.
Should be set to floating point value between 2 and 4
Fixes issues on Heltec v2 */
float adc_multiplier_override;
/* Wait Bluetooth Seconds
The number of seconds for to wait before turning off BLE in No Bluetooth states
0 for default of 1 minute */
uint32_t wait_bluetooth_secs;
/* Mesh Super Deep Sleep Timeout Seconds
While in Light Sleep if this value is exceeded we will lower into super deep sleep
for sds_secs (default 1 year) or a button press
0 for default of two hours, MAXUINT for disabled */
uint32_t mesh_sds_timeout_secs;
/* Super Deep Sleep Seconds
While in Light Sleep if mesh_sds_timeout_secs is exceeded we will lower into super deep sleep
for this value (default 1 year) or a button press
0 for default of one year */
uint32_t sds_secs;
/* Light Sleep Seconds
In light sleep the CPU is suspended, LoRa radio is on, BLE is off an GPS is on
ESP32 Only
0 for default of 300 */
uint32_t ls_secs;
/* Minimum Wake Seconds
While in light sleep when we receive packets on the LoRa radio we will wake and handle them and stay awake in no BLE mode for this value
0 for default of 10 seconds */
uint32_t min_wake_secs;
} Config_PowerConfig;
typedef struct _Config_NetworkConfig_IpV4Config {
/* Static IP address */
uint32_t ip;
/* Static gateway address */
uint32_t gateway;
/* Static subnet mask */
uint32_t subnet;
/* Static DNS server address */
uint32_t dns;
} Config_NetworkConfig_IpV4Config;
/* Network Config */
typedef struct _Config_NetworkConfig {
/* Enable WiFi (disables Bluetooth) */
bool wifi_enabled;
/* If set, this node will try to join the specified wifi network and
acquire an address via DHCP */
char wifi_ssid[33];
/* If set, will be use to authenticate to the named wifi */
char wifi_psk[64];
/* NTP server to use if WiFi is conneced, defaults to `0.pool.ntp.org` */
char ntp_server[33];
/* Enable Ethernet */
bool eth_enabled;
/* acquire an address via DHCP or assign static */
Config_NetworkConfig_EthMode eth_mode;
/* struct to keep static address */
bool has_ipv4_config;
Config_NetworkConfig_IpV4Config ipv4_config;
} Config_NetworkConfig;
/* Display Config */
typedef struct _Config_DisplayConfig {
/* Number of seconds the screen stays on after pressing the user button or receiving a message
0 for default of one minute MAXUINT for always on */
uint32_t screen_on_secs;
/* How the GPS coordinates are formatted on the OLED screen. */
Config_DisplayConfig_GpsCoordinateFormat gps_format;
/* Automatically toggles to the next page on the screen like a carousel, based the specified interval in seconds.
Potentially useful for devices without user buttons. */
uint32_t auto_screen_carousel_secs;
/* If this is set, the displayed compass will always point north. if unset, the old behaviour
(top of display is heading direction) is used. */
bool compass_north_top;
/* Flip screen vertically, for cases that mount the screen upside down */
bool flip_screen;
/* Perferred display units */
Config_DisplayConfig_DisplayUnits units;
/* Override auto-detect in screen */
Config_DisplayConfig_OledType oled;
} Config_DisplayConfig;
/* Lora Config */
typedef struct _Config_LoRaConfig {
/* When enabled, the `modem_preset` fields will be adheared to, else the `bandwidth`/`spread_factor`/`coding_rate`
will be taked from their respective manually defined fields */
bool use_preset;
/* Either modem_config or bandwidth/spreading/coding will be specified - NOT BOTH.
As a heuristic: If bandwidth is specified, do not use modem_config.
Because protobufs take ZERO space when the value is zero this works out nicely.
This value is replaced by bandwidth/spread_factor/coding_rate.
If you'd like to experiment with other options add them to MeshRadio.cpp in the device code. */
Config_LoRaConfig_ModemPreset modem_preset;
/* Bandwidth in MHz
Certain bandwidth numbers are 'special' and will be converted to the
appropriate floating point value: 31 -> 31.25MHz */
uint16_t bandwidth;
/* A number from 7 to 12.
Indicates number of chirps per symbol as 1<<spread_factor. */
uint32_t spread_factor;
/* The denominator of the coding rate.
ie for 4/5, the value is 5. 4/8 the value is 8. */
uint8_t coding_rate;
/* This parameter is for advanced users with advanced test equipment, we do not recommend most users use it.
A frequency offset that is added to to the calculated band center frequency.
Used to correct for crystal calibration errors. */
float frequency_offset;
/* The region code for the radio (US, CN, EU433, etc...) */
Config_LoRaConfig_RegionCode region;
/* Maximum number of hops. This can't be greater than 7.
Default of 3 */
uint32_t hop_limit;
/* Disable TX from the LoRa radio. Useful for hot-swapping antennas and other tests.
Defaults to false */
bool tx_enabled;
/* If zero then, use default max legal continuous power (ie. something that won't
burn out the radio hardware)
In most cases you should use zero here.
Units are in dBm. */
int8_t tx_power;
/* This is controlling the actual hardware frequency the radio is transmitting on.
Most users should never need to be exposed to this field/concept.
A channel number between 1 and NUM_CHANNELS (whatever the max is in the current region).
If ZERO then the rule is "use the old channel name hash based
algorithm to derive the channel number")
If using the hash algorithm the channel number will be: hash(channel_name) %
NUM_CHANNELS (Where num channels depends on the regulatory region). */
uint16_t channel_num;
/* If true, duty cycle limits will be exceeded and thus you're possibly not following
the local regulations if you're not a HAM.
Has no effect if the duty cycle of the used region is 100%. */
bool override_duty_cycle;
/* For testing it is useful sometimes to force a node to never listen to
particular other nodes (simulating radio out of range). All nodenums listed
in ignore_incoming will have packets they send droped on receive (by router.cpp) */
pb_size_t ignore_incoming_count;
uint32_t ignore_incoming[3];
} Config_LoRaConfig;
typedef struct _Config_NetworkConfig_IpV4Config {
uint32_t ip;
uint32_t gateway;
uint32_t subnet;
uint32_t dns;
} Config_NetworkConfig_IpV4Config;
typedef struct _Config_PositionConfig {
uint32_t position_broadcast_secs;
bool position_broadcast_smart_enabled;
bool fixed_position;
bool gps_enabled;
uint32_t gps_update_interval;
uint32_t gps_attempt_time;
uint32_t position_flags;
uint32_t rx_gpio;
uint32_t tx_gpio;
} Config_PositionConfig;
typedef struct _Config_PowerConfig {
bool is_power_saving;
uint32_t on_battery_shutdown_after_secs;
float adc_multiplier_override;
uint32_t wait_bluetooth_secs;
uint32_t mesh_sds_timeout_secs;
uint32_t sds_secs;
uint32_t ls_secs;
uint32_t min_wake_secs;
} Config_PowerConfig;
typedef struct _Config_NetworkConfig {
bool wifi_enabled;
char wifi_ssid[33];
char wifi_psk[64];
char ntp_server[33];
bool eth_enabled;
Config_NetworkConfig_EthMode eth_mode;
bool has_ipv4_config;
Config_NetworkConfig_IpV4Config ipv4_config;
} Config_NetworkConfig;
typedef struct _Config_BluetoothConfig {
/* Enable Bluetooth on the device */
bool enabled;
/* Determines the pairing strategy for the device */
Config_BluetoothConfig_PairingMode mode;
/* Specified pin for PairingMode.FixedPin */
uint32_t fixed_pin;
} Config_BluetoothConfig;
typedef struct _Config {
pb_size_t which_payload_variant;
@@ -185,6 +388,10 @@ typedef struct _Config {
} Config;
#ifdef __cplusplus
extern "C" {
#endif
/* Helper constants for enums */
#define _Config_DeviceConfig_Role_MIN Config_DeviceConfig_Role_CLIENT
#define _Config_DeviceConfig_Role_MAX Config_DeviceConfig_Role_ROUTER_CLIENT
@@ -223,9 +430,22 @@ typedef struct _Config {
#define _Config_BluetoothConfig_PairingMode_ARRAYSIZE ((Config_BluetoothConfig_PairingMode)(Config_BluetoothConfig_PairingMode_NO_PIN+1))
#ifdef __cplusplus
extern "C" {
#endif
#define Config_DeviceConfig_role_ENUMTYPE Config_DeviceConfig_Role
#define Config_NetworkConfig_eth_mode_ENUMTYPE Config_NetworkConfig_EthMode
#define Config_DisplayConfig_gps_format_ENUMTYPE Config_DisplayConfig_GpsCoordinateFormat
#define Config_DisplayConfig_units_ENUMTYPE Config_DisplayConfig_DisplayUnits
#define Config_DisplayConfig_oled_ENUMTYPE Config_DisplayConfig_OledType
#define Config_LoRaConfig_modem_preset_ENUMTYPE Config_LoRaConfig_ModemPreset
#define Config_LoRaConfig_region_ENUMTYPE Config_LoRaConfig_RegionCode
#define Config_BluetoothConfig_mode_ENUMTYPE Config_BluetoothConfig_PairingMode
/* Initializer values for message structs */
#define Config_init_default {0, {Config_DeviceConfig_init_default}}
@@ -235,7 +455,7 @@ extern "C" {
#define Config_NetworkConfig_init_default {0, "", "", "", 0, _Config_NetworkConfig_EthMode_MIN, false, Config_NetworkConfig_IpV4Config_init_default}
#define Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0}
#define Config_DisplayConfig_init_default {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _Config_DisplayConfig_DisplayUnits_MIN, _Config_DisplayConfig_OledType_MIN}
#define Config_LoRaConfig_init_default {0, _Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, {0, 0, 0}}
#define Config_LoRaConfig_init_default {0, _Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, {0, 0, 0}}
#define Config_BluetoothConfig_init_default {0, _Config_BluetoothConfig_PairingMode_MIN, 0}
#define Config_init_zero {0, {Config_DeviceConfig_init_zero}}
#define Config_DeviceConfig_init_zero {_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0}
@@ -244,18 +464,43 @@ extern "C" {
#define Config_NetworkConfig_init_zero {0, "", "", "", 0, _Config_NetworkConfig_EthMode_MIN, false, Config_NetworkConfig_IpV4Config_init_zero}
#define Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0}
#define Config_DisplayConfig_init_zero {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _Config_DisplayConfig_DisplayUnits_MIN, _Config_DisplayConfig_OledType_MIN}
#define Config_LoRaConfig_init_zero {0, _Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, {0, 0, 0}}
#define Config_LoRaConfig_init_zero {0, _Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, {0, 0, 0}}
#define Config_BluetoothConfig_init_zero {0, _Config_BluetoothConfig_PairingMode_MIN, 0}
/* Field tags (for use in manual encoding/decoding) */
#define Config_BluetoothConfig_enabled_tag 1
#define Config_BluetoothConfig_mode_tag 2
#define Config_BluetoothConfig_fixed_pin_tag 3
#define Config_DeviceConfig_role_tag 1
#define Config_DeviceConfig_serial_enabled_tag 2
#define Config_DeviceConfig_debug_log_enabled_tag 3
#define Config_DeviceConfig_button_gpio_tag 4
#define Config_DeviceConfig_buzzer_gpio_tag 5
#define Config_PositionConfig_position_broadcast_secs_tag 1
#define Config_PositionConfig_position_broadcast_smart_enabled_tag 2
#define Config_PositionConfig_fixed_position_tag 3
#define Config_PositionConfig_gps_enabled_tag 4
#define Config_PositionConfig_gps_update_interval_tag 5
#define Config_PositionConfig_gps_attempt_time_tag 6
#define Config_PositionConfig_position_flags_tag 7
#define Config_PositionConfig_rx_gpio_tag 8
#define Config_PositionConfig_tx_gpio_tag 9
#define Config_PowerConfig_is_power_saving_tag 1
#define Config_PowerConfig_on_battery_shutdown_after_secs_tag 2
#define Config_PowerConfig_adc_multiplier_override_tag 3
#define Config_PowerConfig_wait_bluetooth_secs_tag 4
#define Config_PowerConfig_mesh_sds_timeout_secs_tag 5
#define Config_PowerConfig_sds_secs_tag 6
#define Config_PowerConfig_ls_secs_tag 7
#define Config_PowerConfig_min_wake_secs_tag 8
#define Config_NetworkConfig_IpV4Config_ip_tag 1
#define Config_NetworkConfig_IpV4Config_gateway_tag 2
#define Config_NetworkConfig_IpV4Config_subnet_tag 3
#define Config_NetworkConfig_IpV4Config_dns_tag 4
#define Config_NetworkConfig_wifi_enabled_tag 1
#define Config_NetworkConfig_wifi_ssid_tag 3
#define Config_NetworkConfig_wifi_psk_tag 4
#define Config_NetworkConfig_ntp_server_tag 5
#define Config_NetworkConfig_eth_enabled_tag 6
#define Config_NetworkConfig_eth_mode_tag 7
#define Config_NetworkConfig_ipv4_config_tag 8
#define Config_DisplayConfig_screen_on_secs_tag 1
#define Config_DisplayConfig_gps_format_tag 2
#define Config_DisplayConfig_auto_screen_carousel_secs_tag 3
@@ -274,35 +519,11 @@ extern "C" {
#define Config_LoRaConfig_tx_enabled_tag 9
#define Config_LoRaConfig_tx_power_tag 10
#define Config_LoRaConfig_channel_num_tag 11
#define Config_LoRaConfig_override_duty_cycle_tag 12
#define Config_LoRaConfig_ignore_incoming_tag 103
#define Config_NetworkConfig_IpV4Config_ip_tag 1
#define Config_NetworkConfig_IpV4Config_gateway_tag 2
#define Config_NetworkConfig_IpV4Config_subnet_tag 3
#define Config_NetworkConfig_IpV4Config_dns_tag 4
#define Config_PositionConfig_position_broadcast_secs_tag 1
#define Config_PositionConfig_position_broadcast_smart_enabled_tag 2
#define Config_PositionConfig_fixed_position_tag 3
#define Config_PositionConfig_gps_enabled_tag 4
#define Config_PositionConfig_gps_update_interval_tag 5
#define Config_PositionConfig_gps_attempt_time_tag 6
#define Config_PositionConfig_position_flags_tag 7
#define Config_PositionConfig_rx_gpio_tag 8
#define Config_PositionConfig_tx_gpio_tag 9
#define Config_PowerConfig_is_power_saving_tag 1
#define Config_PowerConfig_on_battery_shutdown_after_secs_tag 2
#define Config_PowerConfig_adc_multiplier_override_tag 3
#define Config_PowerConfig_wait_bluetooth_secs_tag 4
#define Config_PowerConfig_mesh_sds_timeout_secs_tag 5
#define Config_PowerConfig_sds_secs_tag 6
#define Config_PowerConfig_ls_secs_tag 7
#define Config_PowerConfig_min_wake_secs_tag 8
#define Config_NetworkConfig_wifi_enabled_tag 1
#define Config_NetworkConfig_wifi_ssid_tag 3
#define Config_NetworkConfig_wifi_psk_tag 4
#define Config_NetworkConfig_ntp_server_tag 5
#define Config_NetworkConfig_eth_enabled_tag 6
#define Config_NetworkConfig_eth_mode_tag 7
#define Config_NetworkConfig_ipv4_config_tag 8
#define Config_BluetoothConfig_enabled_tag 1
#define Config_BluetoothConfig_mode_tag 2
#define Config_BluetoothConfig_fixed_pin_tag 3
#define Config_device_tag 1
#define Config_position_tag 2
#define Config_power_tag 3
@@ -407,6 +628,7 @@ X(a, STATIC, SINGULAR, UINT32, hop_limit, 8) \
X(a, STATIC, SINGULAR, BOOL, tx_enabled, 9) \
X(a, STATIC, SINGULAR, INT32, tx_power, 10) \
X(a, STATIC, SINGULAR, UINT32, channel_num, 11) \
X(a, STATIC, SINGULAR, BOOL, override_duty_cycle, 12) \
X(a, STATIC, REPEATED, UINT32, ignore_incoming, 103)
#define Config_LoRaConfig_CALLBACK NULL
#define Config_LoRaConfig_DEFAULT NULL
@@ -443,7 +665,7 @@ extern const pb_msgdesc_t Config_BluetoothConfig_msg;
#define Config_BluetoothConfig_size 10
#define Config_DeviceConfig_size 18
#define Config_DisplayConfig_size 22
#define Config_LoRaConfig_size 68
#define Config_LoRaConfig_size 70
#define Config_NetworkConfig_IpV4Config_size 20
#define Config_NetworkConfig_size 161
#define Config_PositionConfig_size 42

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#include "device_metadata.pb.h"
#if PB_PROTO_HEADER_VERSION != 40

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#ifndef PB_DEVICE_METADATA_PB_H_INCLUDED
#define PB_DEVICE_METADATA_PB_H_INCLUDED

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#include "deviceonly.pb.h"
#if PB_PROTO_HEADER_VERSION != 40

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#ifndef PB_DEVICEONLY_PB_H_INCLUDED
#define PB_DEVICEONLY_PB_H_INCLUDED
@@ -23,17 +23,6 @@ typedef enum _ScreenFonts {
} ScreenFonts;
/* Struct definitions */
/* The on-disk saved channels */
typedef struct _ChannelFile {
/* The channels our node knows about */
pb_size_t channels_count;
Channel channels[8];
/* A version integer used to invalidate old save files when we make
incompatible changes This integer is set at build time and is private to
NodeDB.cpp in the device code. */
uint32_t version;
} ChannelFile;
/* This message is never sent over the wire, but it is used for serializing DB
state to flash in the device code
FIXME, since we write this each time we enter deep sleep (and have infinite
@@ -68,6 +57,17 @@ typedef struct _DeviceState {
bool did_gps_reset;
} DeviceState;
/* The on-disk saved channels */
typedef struct _ChannelFile {
/* The channels our node knows about */
pb_size_t channels_count;
Channel channels[8];
/* A version integer used to invalidate old save files when we make
incompatible changes This integer is set at build time and is private to
NodeDB.cpp in the device code. */
uint32_t version;
} ChannelFile;
typedef PB_BYTES_ARRAY_T(2048) OEMStore_oem_icon_bits_t;
typedef PB_BYTES_ARRAY_T(32) OEMStore_oem_aes_key_t;
/* This can be used for customizing the firmware distribution. If populated,
@@ -88,15 +88,19 @@ typedef struct _OEMStore {
} OEMStore;
#ifdef __cplusplus
extern "C" {
#endif
/* Helper constants for enums */
#define _ScreenFonts_MIN ScreenFonts_FONT_SMALL
#define _ScreenFonts_MAX ScreenFonts_FONT_LARGE
#define _ScreenFonts_ARRAYSIZE ((ScreenFonts)(ScreenFonts_FONT_LARGE+1))
#ifdef __cplusplus
extern "C" {
#endif
#define OEMStore_oem_font_ENUMTYPE ScreenFonts
/* Initializer values for message structs */
#define DeviceState_init_default {false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0}
@@ -107,8 +111,6 @@ extern "C" {
#define OEMStore_init_zero {0, 0, {0, {0}}, _ScreenFonts_MIN, "", {0, {0}}}
/* Field tags (for use in manual encoding/decoding) */
#define ChannelFile_channels_tag 1
#define ChannelFile_version_tag 2
#define DeviceState_my_node_tag 2
#define DeviceState_owner_tag 3
#define DeviceState_node_db_tag 4
@@ -117,6 +119,8 @@ extern "C" {
#define DeviceState_version_tag 8
#define DeviceState_no_save_tag 9
#define DeviceState_did_gps_reset_tag 11
#define ChannelFile_channels_tag 1
#define ChannelFile_version_tag 2
#define OEMStore_oem_icon_width_tag 1
#define OEMStore_oem_icon_height_tag 2
#define OEMStore_oem_icon_bits_tag 3

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#include "localonly.pb.h"
#if PB_PROTO_HEADER_VERSION != 40

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#ifndef PB_LOCALONLY_PB_H_INCLUDED
#define PB_LOCALONLY_PB_H_INCLUDED
@@ -150,8 +150,8 @@ extern const pb_msgdesc_t LocalModuleConfig_msg;
#define LocalModuleConfig_fields &LocalModuleConfig_msg
/* Maximum encoded size of messages (where known) */
#define LocalConfig_size 385
#define LocalModuleConfig_size 361
#define LocalConfig_size 387
#define LocalModuleConfig_size 376
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#include "mesh.pb.h"
#if PB_PROTO_HEADER_VERSION != 40

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#ifndef PB_MESH_PB_H_INCLUDED
#define PB_MESH_PB_H_INCLUDED
@@ -54,6 +54,8 @@ typedef enum _HardwareModel {
HardwareModel_NANO_G1 = 14,
/* TODO: REPLACE */
HardwareModel_TLORA_V2_1_1P8 = 15,
/* TODO: REPLACE */
HardwareModel_TLORA_T3_S3 = 16,
/* B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station */
HardwareModel_STATION_G1 = 25,
/* Less common/prototype boards listed here (needs one more byte over the air) */
@@ -131,10 +133,7 @@ typedef enum _CriticalErrorCode {
CriticalErrorCode_RADIO_SPI_BUG = 11
} CriticalErrorCode;
/* Note: these enum names must EXACTLY match the string used in the device
bin/build-all.sh script.
Because they will be used to find firmware filenames in the android app for OTA updates.
To match the old style filenames, _ is converted to -, p is converted to . */
/* How the location was acquired: manual, onboard GPS, external (EUD) GPS */
typedef enum _Position_LocSource {
/* TODO: REPLACE */
Position_LocSource_LOC_UNSET = 0,
@@ -146,219 +145,119 @@ typedef enum _Position_LocSource {
Position_LocSource_LOC_EXTERNAL = 3
} Position_LocSource;
/* Shared constants between device and phone */
/* How the altitude was acquired: manual, GPS int/ext, etc
Default: same as location_source if present */
typedef enum _Position_AltSource {
/* First enum must be zero, and we are just using this enum to
pass int constants between two very different environments */
/* TODO: REPLACE */
Position_AltSource_ALT_UNSET = 0,
/* 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 */
/* TODO: REPLACE */
Position_AltSource_ALT_MANUAL = 1,
/* TODO: REPLACE */
Position_AltSource_ALT_INTERNAL = 2,
/* TODO: REPLACE */
Position_AltSource_ALT_EXTERNAL = 3,
/* TODO: REPLACE */
Position_AltSource_ALT_BAROMETRIC = 4
} Position_AltSource;
/* Note: these enum names must EXACTLY match the string used in the device
bin/build-all.sh script.
Because they will be used to find firmware filenames in the android app for OTA updates.
To match the old style filenames, _ is converted to -, p is converted to . */
/* A failure in delivering a message (usually used for routing control messages, but might be provided in addition to ack.fail_id to provide
details on the type of failure). */
typedef enum _Routing_Error {
/* TODO: REPLACE */
/* This message is not a failure */
Routing_Error_NONE = 0,
/* TODO: REPLACE */
/* Our node doesn't have a route to the requested destination anymore. */
Routing_Error_NO_ROUTE = 1,
/* TODO: REPLACE */
/* We received a nak while trying to forward on your behalf */
Routing_Error_GOT_NAK = 2,
/* TODO: REPLACE */
Routing_Error_TIMEOUT = 3,
/* TODO: REPLACE */
/* No suitable interface could be found for delivering this packet */
Routing_Error_NO_INTERFACE = 4,
/* The original heltec WiFi_Lora_32_V2, which had battery voltage sensing hooked to GPIO 13
(see HELTEC_V2 for the new version). */
/* We reached the max retransmission count (typically for naive flood routing) */
Routing_Error_MAX_RETRANSMIT = 5,
/* TODO: REPLACE */
/* No suitable channel was found for sending this packet (i.e. was requested channel index disabled?) */
Routing_Error_NO_CHANNEL = 6,
/* TODO: REPLACE */
/* The packet was too big for sending (exceeds interface MTU after encoding) */
Routing_Error_TOO_LARGE = 7,
/* TODO: REPLACE */
/* The request had want_response set, the request reached the destination node, but no service on that node wants to send a response
(possibly due to bad channel permissions) */
Routing_Error_NO_RESPONSE = 8,
/* TODO: REPLACE */
/* Cannot send currently because duty cycle regulations will be violated. */
Routing_Error_DUTY_CYCLE_LIMIT = 9,
/* The application layer service on the remote node received your request, but considered your request somehow invalid */
Routing_Error_BAD_REQUEST = 32,
/* The new version of the heltec WiFi_Lora_32_V2 board that has battery sensing hooked to GPIO 37.
Sadly they did not update anything on the silkscreen to identify this board */
/* The application layer service on the remote node received your request, but considered your request not authorized
(i.e you did not send the request on the required bound channel) */
Routing_Error_NOT_AUTHORIZED = 33
} Routing_Error;
/* Note: these enum names must EXACTLY match the string used in the device
bin/build-all.sh script.
Because they will be used to find firmware filenames in the android app for OTA updates.
To match the old style filenames, _ is converted to -, p is converted to . */
/* The priority of this message for sending.
Higher priorities are sent first (when managing the transmit queue).
This field is never sent over the air, it is only used internally inside of a local device node.
API clients (either on the local node or connected directly to the node)
can set this parameter if necessary.
(values must be <= 127 to keep protobuf field to one byte in size.
Detailed background on this field:
I noticed a funny side effect of lora being so slow: Usually when making
a protocol there isnt much need to use message priority to change the order
of transmission (because interfaces are fairly fast).
But for lora where packets can take a few seconds each, it is very important
to make sure that critical packets are sent ASAP.
In the case of meshtastic that means we want to send protocol acks as soon as possible
(to prevent unneeded retransmissions), we want routing messages to be sent next,
then messages marked as reliable and finally background packets like periodic position updates.
So I bit the bullet and implemented a new (internal - not sent over the air)
field in MeshPacket called priority.
And the transmission queue in the router object is now a priority queue. */
typedef enum _MeshPacket_Priority {
/* TODO: REPLACE */
/* Treated as Priority.DEFAULT */
MeshPacket_Priority_UNSET = 0,
/* TODO: REPLACE */
MeshPacket_Priority_MIN = 1,
/* TODO: REPLACE */
/* Background position updates are sent with very low priority -
if the link is super congested they might not go out at all */
MeshPacket_Priority_BACKGROUND = 10,
/* TODO: REPLACE */
/* This priority is used for most messages that don't have a priority set */
MeshPacket_Priority_DEFAULT = 64,
/* TODO: REPLACE */
/* If priority is unset but the message is marked as want_ack,
assume it is important and use a slightly higher priority */
MeshPacket_Priority_RELIABLE = 70,
/* The original heltec WiFi_Lora_32_V2, which had battery voltage sensing hooked to GPIO 13
(see HELTEC_V2 for the new version). */
/* Ack/naks are sent with very high priority to ensure that retransmission
stops as soon as possible */
MeshPacket_Priority_ACK = 120,
/* TODO: REPLACE */
MeshPacket_Priority_MAX = 127
} MeshPacket_Priority;
/* Shared constants between device and phone */
/* Identify if this is a delayed packet */
typedef enum _MeshPacket_Delayed {
/* First enum must be zero, and we are just using this enum to
pass int constants between two very different environments */
/* If unset, the message is being sent in real time. */
MeshPacket_Delayed_NO_DELAY = 0,
/* 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 */
/* The message is delayed and was originally a broadcast */
MeshPacket_Delayed_DELAYED_BROADCAST = 1,
/* The message is delayed and was originally a direct message */
MeshPacket_Delayed_DELAYED_DIRECT = 2
} MeshPacket_Delayed;
/* Note: these enum names must EXACTLY match the string used in the device
bin/build-all.sh script.
Because they will be used to find firmware filenames in the android app for OTA updates.
To match the old style filenames, _ is converted to -, p is converted to . */
/* Log levels, chosen to match python logging conventions. */
typedef enum _LogRecord_Level {
/* TODO: REPLACE */
/* Log levels, chosen to match python logging conventions. */
LogRecord_Level_UNSET = 0,
/* TODO: REPLACE */
/* Log levels, chosen to match python logging conventions. */
LogRecord_Level_CRITICAL = 50,
/* TODO: REPLACE */
/* Log levels, chosen to match python logging conventions. */
LogRecord_Level_ERROR = 40,
/* TODO: REPLACE */
/* Log levels, chosen to match python logging conventions. */
LogRecord_Level_WARNING = 30,
/* TODO: REPLACE */
/* Log levels, chosen to match python logging conventions. */
LogRecord_Level_INFO = 20,
/* The original heltec WiFi_Lora_32_V2, which had battery voltage sensing hooked to GPIO 13
(see HELTEC_V2 for the new version). */
/* Log levels, chosen to match python logging conventions. */
LogRecord_Level_DEBUG = 10,
/* TODO: REPLACE */
/* Log levels, chosen to match python logging conventions. */
LogRecord_Level_TRACE = 5
} LogRecord_Level;
/* Struct definitions */
typedef PB_BYTES_ARRAY_T(237) Compressed_data_t;
/* Compressed message payload */
typedef struct _Compressed {
/* PortNum to determine the how to handle the compressed payload. */
PortNum portnum;
/* Compressed data. */
Compressed_data_t data;
} Compressed;
typedef PB_BYTES_ARRAY_T(237) Data_payload_t;
/* (Formerly called SubPacket)
The payload portion fo a packet, this is the actual bytes that are sent
inside a radio packet (because from/to are broken out by the comms library) */
typedef struct _Data {
/* Formerly named typ and of type Type */
PortNum portnum;
/* TODO: REPLACE */
Data_payload_t payload;
/* Not normally used, but for testing a sender can request that recipient
responds in kind (i.e. if it received a position, it should unicast back it's position).
Note: that if you set this on a broadcast you will receive many replies. */
bool want_response;
/* The address of the destination node.
This field is is filled in by the mesh radio device software, application
layer software should never need it.
RouteDiscovery messages _must_ populate this.
Other message types might need to if they are doing multihop routing. */
uint32_t dest;
/* The address of the original sender for this message.
This field should _only_ be populated for reliable multihop packets (to keep
packets small). */
uint32_t source;
/* Only used in routing or response messages.
Indicates the original message ID that this message is reporting failure on. (formerly called original_id) */
uint32_t request_id;
/* If set, this message is intened to be a reply to a previously sent message with the defined id. */
uint32_t reply_id;
/* Defaults to false. If true, then what is in the payload should be treated as an emoji like giving
a message a heart or poop emoji. */
uint32_t emoji;
} Data;
/* Debug output from the device.
To minimize the size of records inside the device code, if a time/source/level is not set
on the message it is assumed to be a continuation of the previously sent message.
This allows the device code to use fixed maxlen 64 byte strings for messages,
and then extend as needed by emitting multiple records. */
typedef struct _LogRecord {
/* Log levels, chosen to match python logging conventions. */
char message[64];
/* Seconds since 1970 - or 0 for unknown/unset */
uint32_t time;
/* Usually based on thread name - if known */
char source[8];
/* Not yet set */
LogRecord_Level level;
} LogRecord;
/* Unique local debugging info for this node
Note: we don't include position or the user info, because that will come in the
Sent to the phone in response to WantNodes. */
typedef struct _MyNodeInfo {
/* Tells the phone what our node number is, default starting value is
lowbyte of macaddr, but it will be fixed if that is already in use */
uint32_t my_node_num;
/* Note: This flag merely means we detected a hardware GPS in our node.
Not the same as UserPreferences.location_sharing */
bool has_gps;
/* The maximum number of 'software' channels that can be set on this node. */
uint32_t max_channels;
/* 0.0.5 etc... */
char firmware_version[18];
/* An error message we'd like to report back to the mothership through analytics.
It indicates a serious bug occurred on the device, the device coped with it,
but we still want to tell the devs about the bug.
This field will be cleared after the phone reads MyNodeInfo
(i.e. it will only be reported once)
a numeric error code to go with error message, zero means no error */
CriticalErrorCode error_code;
/* A numeric error address (nonzero if available) */
uint32_t error_address;
/* The total number of errors this node has ever encountered
(well - since the last time we discarded preferences) */
uint32_t error_count;
/* The total number of reboots this node has ever encountered
(well - since the last time we discarded preferences) */
uint32_t reboot_count;
/* Calculated bitrate of the current channel (in Bytes Per Second) */
float bitrate;
/* How long before we consider a message abandoned and we can clear our
caches of any messages in flight Normally quite large to handle the worst case
message delivery time, 5 minutes.
Formerly called FLOOD_EXPIRE_TIME in the device code */
uint32_t message_timeout_msec;
/* The minimum app version that can talk to this device.
Phone/PC apps should compare this to their build number and if too low tell the user they must update their app */
uint32_t min_app_version;
/* 24 time windows of 1hr each with the airtime transmitted out of the device per hour. */
pb_size_t air_period_tx_count;
uint32_t air_period_tx[8];
/* 24 time windows of 1hr each with the airtime of valid packets for your mesh. */
pb_size_t air_period_rx_count;
uint32_t air_period_rx[8];
/* Is the device wifi capable? */
bool has_wifi;
/* Utilization for the current channel, including well formed TX, RX and malformed RX (aka noise). */
float channel_utilization;
/* Percent of airtime for transmission used within the last hour. */
float air_util_tx;
} MyNodeInfo;
/* a gps position */
typedef struct _Position {
/* The new preferred location encoding, multiply by 1e-7 to get degrees
@@ -427,13 +326,6 @@ typedef struct _Position {
uint32_t seq_number;
} Position;
/* A message used in our Dynamic Source Routing protocol (RFC 4728 based) */
typedef struct _RouteDiscovery {
/* The list of nodenums this packet has visited so far */
pb_size_t route_count;
uint32_t route[8];
} RouteDiscovery;
/* Broadcast when a newly powered mesh node wants to find a node num it can use
Sent from the phone over bluetooth to set the user id for the owner of this node.
Also sent from nodes to each other when a new node signs on (so all clients can have this info)
@@ -479,6 +371,60 @@ typedef struct _User {
bool is_licensed;
} User;
/* A message used in our Dynamic Source Routing protocol (RFC 4728 based) */
typedef struct _RouteDiscovery {
/* The list of nodenums this packet has visited so far */
pb_size_t route_count;
uint32_t route[8];
} RouteDiscovery;
/* A Routing control Data packet handled by the routing module */
typedef struct _Routing {
pb_size_t which_variant;
union {
/* A route request going from the requester */
RouteDiscovery route_request;
/* A route reply */
RouteDiscovery route_reply;
/* A failure in delivering a message (usually used for routing control messages, but might be provided
in addition to ack.fail_id to provide details on the type of failure). */
Routing_Error error_reason;
};
} Routing;
typedef PB_BYTES_ARRAY_T(237) Data_payload_t;
/* (Formerly called SubPacket)
The payload portion fo a packet, this is the actual bytes that are sent
inside a radio packet (because from/to are broken out by the comms library) */
typedef struct _Data {
/* Formerly named typ and of type Type */
PortNum portnum;
/* TODO: REPLACE */
Data_payload_t payload;
/* Not normally used, but for testing a sender can request that recipient
responds in kind (i.e. if it received a position, it should unicast back it's position).
Note: that if you set this on a broadcast you will receive many replies. */
bool want_response;
/* The address of the destination node.
This field is is filled in by the mesh radio device software, application
layer software should never need it.
RouteDiscovery messages _must_ populate this.
Other message types might need to if they are doing multihop routing. */
uint32_t dest;
/* The address of the original sender for this message.
This field should _only_ be populated for reliable multihop packets (to keep
packets small). */
uint32_t source;
/* Only used in routing or response messages.
Indicates the original message ID that this message is reporting failure on. (formerly called original_id) */
uint32_t request_id;
/* If set, this message is intened to be a reply to a previously sent message with the defined id. */
uint32_t reply_id;
/* Defaults to false. If true, then what is in the payload should be treated as an emoji like giving
a message a heart or poop emoji. */
uint32_t emoji;
} Data;
/* Waypoint message, used to share arbitrary locations across the mesh */
typedef struct _Waypoint {
/* Id of the waypoint */
@@ -606,19 +552,74 @@ typedef struct _NodeInfo {
DeviceMetrics device_metrics;
} NodeInfo;
/* A Routing control Data packet handled by the routing module */
typedef struct _Routing {
pb_size_t which_variant;
union {
/* A route request going from the requester */
RouteDiscovery route_request;
/* A route reply */
RouteDiscovery route_reply;
/* A failure in delivering a message (usually used for routing control messages, but might be provided
in addition to ack.fail_id to provide details on the type of failure). */
Routing_Error error_reason;
};
} Routing;
/* Unique local debugging info for this node
Note: we don't include position or the user info, because that will come in the
Sent to the phone in response to WantNodes. */
typedef struct _MyNodeInfo {
/* Tells the phone what our node number is, default starting value is
lowbyte of macaddr, but it will be fixed if that is already in use */
uint32_t my_node_num;
/* Note: This flag merely means we detected a hardware GPS in our node.
Not the same as UserPreferences.location_sharing */
bool has_gps;
/* The maximum number of 'software' channels that can be set on this node. */
uint32_t max_channels;
/* 0.0.5 etc... */
char firmware_version[18];
/* An error message we'd like to report back to the mothership through analytics.
It indicates a serious bug occurred on the device, the device coped with it,
but we still want to tell the devs about the bug.
This field will be cleared after the phone reads MyNodeInfo
(i.e. it will only be reported once)
a numeric error code to go with error message, zero means no error */
CriticalErrorCode error_code;
/* A numeric error address (nonzero if available) */
uint32_t error_address;
/* The total number of errors this node has ever encountered
(well - since the last time we discarded preferences) */
uint32_t error_count;
/* The total number of reboots this node has ever encountered
(well - since the last time we discarded preferences) */
uint32_t reboot_count;
/* Calculated bitrate of the current channel (in Bytes Per Second) */
float bitrate;
/* How long before we consider a message abandoned and we can clear our
caches of any messages in flight Normally quite large to handle the worst case
message delivery time, 5 minutes.
Formerly called FLOOD_EXPIRE_TIME in the device code */
uint32_t message_timeout_msec;
/* The minimum app version that can talk to this device.
Phone/PC apps should compare this to their build number and if too low tell the user they must update their app */
uint32_t min_app_version;
/* 24 time windows of 1hr each with the airtime transmitted out of the device per hour. */
pb_size_t air_period_tx_count;
uint32_t air_period_tx[8];
/* 24 time windows of 1hr each with the airtime of valid packets for your mesh. */
pb_size_t air_period_rx_count;
uint32_t air_period_rx[8];
/* Is the device wifi capable? */
bool has_wifi;
/* Utilization for the current channel, including well formed TX, RX and malformed RX (aka noise). */
float channel_utilization;
/* Percent of airtime for transmission used within the last hour. */
float air_util_tx;
} MyNodeInfo;
/* Debug output from the device.
To minimize the size of records inside the device code, if a time/source/level is not set
on the message it is assumed to be a continuation of the previously sent message.
This allows the device code to use fixed maxlen 64 byte strings for messages,
and then extend as needed by emitting multiple records. */
typedef struct _LogRecord {
/* Log levels, chosen to match python logging conventions. */
char message[64];
/* Seconds since 1970 - or 0 for unknown/unset */
uint32_t time;
/* Usually based on thread name - if known */
char source[8];
/* Not yet set */
LogRecord_Level level;
} LogRecord;
/* Packets from the radio to the phone will appear on the fromRadio characteristic.
It will support READ and NOTIFY. When a new packet arrives the device will BLE notify?
@@ -682,6 +683,19 @@ typedef struct _ToRadio {
};
} ToRadio;
typedef PB_BYTES_ARRAY_T(237) Compressed_data_t;
/* Compressed message payload */
typedef struct _Compressed {
/* PortNum to determine the how to handle the compressed payload. */
PortNum portnum;
/* Compressed data. */
Compressed_data_t data;
} Compressed;
#ifdef __cplusplus
extern "C" {
#endif
/* Helper constants for enums */
#define _HardwareModel_MIN HardwareModel_UNSET
@@ -720,10 +734,29 @@ typedef struct _ToRadio {
#define _LogRecord_Level_MAX LogRecord_Level_CRITICAL
#define _LogRecord_Level_ARRAYSIZE ((LogRecord_Level)(LogRecord_Level_CRITICAL+1))
#define Position_location_source_ENUMTYPE Position_LocSource
#define Position_altitude_source_ENUMTYPE Position_AltSource
#define User_hw_model_ENUMTYPE HardwareModel
#define Routing_variant_error_reason_ENUMTYPE Routing_Error
#define Data_portnum_ENUMTYPE PortNum
#define MeshPacket_priority_ENUMTYPE MeshPacket_Priority
#define MeshPacket_delayed_ENUMTYPE MeshPacket_Delayed
#define MyNodeInfo_error_code_ENUMTYPE CriticalErrorCode
#define LogRecord_level_ENUMTYPE LogRecord_Level
#define Compressed_portnum_ENUMTYPE PortNum
#ifdef __cplusplus
extern "C" {
#endif
/* Initializer values for message structs */
#define Position_init_default {0, 0, 0, 0, _Position_LocSource_MIN, _Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
@@ -754,36 +787,6 @@ extern "C" {
#define Compressed_init_zero {_PortNum_MIN, {0, {0}}}
/* Field tags (for use in manual encoding/decoding) */
#define Compressed_portnum_tag 1
#define Compressed_data_tag 2
#define Data_portnum_tag 1
#define Data_payload_tag 2
#define Data_want_response_tag 3
#define Data_dest_tag 4
#define Data_source_tag 5
#define Data_request_id_tag 6
#define Data_reply_id_tag 7
#define Data_emoji_tag 8
#define LogRecord_message_tag 1
#define LogRecord_time_tag 2
#define LogRecord_source_tag 3
#define LogRecord_level_tag 4
#define MyNodeInfo_my_node_num_tag 1
#define MyNodeInfo_has_gps_tag 2
#define MyNodeInfo_max_channels_tag 3
#define MyNodeInfo_firmware_version_tag 4
#define MyNodeInfo_error_code_tag 5
#define MyNodeInfo_error_address_tag 6
#define MyNodeInfo_error_count_tag 7
#define MyNodeInfo_reboot_count_tag 8
#define MyNodeInfo_bitrate_tag 9
#define MyNodeInfo_message_timeout_msec_tag 10
#define MyNodeInfo_min_app_version_tag 11
#define MyNodeInfo_air_period_tx_tag 12
#define MyNodeInfo_air_period_rx_tag 13
#define MyNodeInfo_has_wifi_tag 14
#define MyNodeInfo_channel_utilization_tag 15
#define MyNodeInfo_air_util_tx_tag 16
#define Position_latitude_i_tag 1
#define Position_longitude_i_tag 2
#define Position_altitude_tag 3
@@ -806,13 +809,24 @@ extern "C" {
#define Position_sensor_id_tag 20
#define Position_next_update_tag 21
#define Position_seq_number_tag 22
#define RouteDiscovery_route_tag 1
#define User_id_tag 1
#define User_long_name_tag 2
#define User_short_name_tag 3
#define User_macaddr_tag 4
#define User_hw_model_tag 5
#define User_is_licensed_tag 6
#define RouteDiscovery_route_tag 1
#define Routing_route_request_tag 1
#define Routing_route_reply_tag 2
#define Routing_error_reason_tag 3
#define Data_portnum_tag 1
#define Data_payload_tag 2
#define Data_want_response_tag 3
#define Data_dest_tag 4
#define Data_source_tag 5
#define Data_request_id_tag 6
#define Data_reply_id_tag 7
#define Data_emoji_tag 8
#define Waypoint_id_tag 1
#define Waypoint_latitude_i_tag 2
#define Waypoint_longitude_i_tag 3
@@ -839,9 +853,26 @@ extern "C" {
#define NodeInfo_snr_tag 4
#define NodeInfo_last_heard_tag 5
#define NodeInfo_device_metrics_tag 6
#define Routing_route_request_tag 1
#define Routing_route_reply_tag 2
#define Routing_error_reason_tag 3
#define MyNodeInfo_my_node_num_tag 1
#define MyNodeInfo_has_gps_tag 2
#define MyNodeInfo_max_channels_tag 3
#define MyNodeInfo_firmware_version_tag 4
#define MyNodeInfo_error_code_tag 5
#define MyNodeInfo_error_address_tag 6
#define MyNodeInfo_error_count_tag 7
#define MyNodeInfo_reboot_count_tag 8
#define MyNodeInfo_bitrate_tag 9
#define MyNodeInfo_message_timeout_msec_tag 10
#define MyNodeInfo_min_app_version_tag 11
#define MyNodeInfo_air_period_tx_tag 12
#define MyNodeInfo_air_period_rx_tag 13
#define MyNodeInfo_has_wifi_tag 14
#define MyNodeInfo_channel_utilization_tag 15
#define MyNodeInfo_air_util_tx_tag 16
#define LogRecord_message_tag 1
#define LogRecord_time_tag 2
#define LogRecord_source_tag 3
#define LogRecord_level_tag 4
#define FromRadio_id_tag 1
#define FromRadio_packet_tag 2
#define FromRadio_my_info_tag 3
@@ -855,6 +886,8 @@ extern "C" {
#define ToRadio_packet_tag 1
#define ToRadio_want_config_id_tag 3
#define ToRadio_disconnect_tag 4
#define Compressed_portnum_tag 1
#define Compressed_data_tag 2
/* Struct field encoding specification for nanopb */
#define Position_FIELDLIST(X, a) \

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#include "module_config.pb.h"
#if PB_PROTO_HEADER_VERSION != 40

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#ifndef PB_MODULE_CONFIG_PB_H_INCLUDED
#define PB_MODULE_CONFIG_PB_H_INCLUDED
@@ -10,6 +10,7 @@
#endif
/* Enum definitions */
/* Baudrate for codec2 voice */
typedef enum _ModuleConfig_AudioConfig_Audio_Baud {
ModuleConfig_AudioConfig_Audio_Baud_CODEC2_DEFAULT = 0,
ModuleConfig_AudioConfig_Audio_Baud_CODEC2_3200 = 1,
@@ -22,6 +23,7 @@ typedef enum _ModuleConfig_AudioConfig_Audio_Baud {
ModuleConfig_AudioConfig_Audio_Baud_CODEC2_700B = 8
} ModuleConfig_AudioConfig_Audio_Baud;
/* TODO: REPLACE */
typedef enum _ModuleConfig_SerialConfig_Serial_Baud {
ModuleConfig_SerialConfig_Serial_Baud_BAUD_DEFAULT = 0,
ModuleConfig_SerialConfig_Serial_Baud_BAUD_110 = 1,
@@ -41,6 +43,7 @@ typedef enum _ModuleConfig_SerialConfig_Serial_Baud {
ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600 = 15
} ModuleConfig_SerialConfig_Serial_Baud;
/* TODO: REPLACE */
typedef enum _ModuleConfig_SerialConfig_Serial_Mode {
ModuleConfig_SerialConfig_Serial_Mode_DEFAULT = 0,
ModuleConfig_SerialConfig_Serial_Mode_SIMPLE = 1,
@@ -49,91 +52,200 @@ typedef enum _ModuleConfig_SerialConfig_Serial_Mode {
ModuleConfig_SerialConfig_Serial_Mode_NMEA = 4
} ModuleConfig_SerialConfig_Serial_Mode;
/* TODO: REPLACE */
typedef enum _ModuleConfig_CannedMessageConfig_InputEventChar {
/* TODO: REPLACE */
ModuleConfig_CannedMessageConfig_InputEventChar_NONE = 0,
/* TODO: REPLACE */
ModuleConfig_CannedMessageConfig_InputEventChar_UP = 17,
/* TODO: REPLACE */
ModuleConfig_CannedMessageConfig_InputEventChar_DOWN = 18,
/* TODO: REPLACE */
ModuleConfig_CannedMessageConfig_InputEventChar_LEFT = 19,
/* TODO: REPLACE */
ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT = 20,
/* '\n' */
ModuleConfig_CannedMessageConfig_InputEventChar_SELECT = 10,
/* TODO: REPLACE */
ModuleConfig_CannedMessageConfig_InputEventChar_BACK = 27,
/* TODO: REPLACE */
ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL = 24
} ModuleConfig_CannedMessageConfig_InputEventChar;
/* Struct definitions */
typedef struct _ModuleConfig_AudioConfig {
bool codec2_enabled;
uint32_t mic_chan;
uint32_t amp_pin;
uint32_t ptt_pin;
ModuleConfig_AudioConfig_Audio_Baud bitrate;
} ModuleConfig_AudioConfig;
typedef struct _ModuleConfig_CannedMessageConfig {
bool rotary1_enabled;
uint32_t inputbroker_pin_a;
uint32_t inputbroker_pin_b;
uint32_t inputbroker_pin_press;
ModuleConfig_CannedMessageConfig_InputEventChar inputbroker_event_cw;
ModuleConfig_CannedMessageConfig_InputEventChar inputbroker_event_ccw;
ModuleConfig_CannedMessageConfig_InputEventChar inputbroker_event_press;
bool updown1_enabled;
bool enabled;
char allow_input_source[16];
bool send_bell;
} ModuleConfig_CannedMessageConfig;
typedef struct _ModuleConfig_ExternalNotificationConfig {
bool enabled;
uint32_t output_ms;
uint32_t output;
bool active;
bool alert_message;
bool alert_bell;
bool use_pwm;
} ModuleConfig_ExternalNotificationConfig;
/* MQTT Client Config */
typedef struct _ModuleConfig_MQTTConfig {
/* If a meshtastic node is able to reach the internet it will normally attempt to gateway any channels that are marked as
is_uplink_enabled or is_downlink_enabled. */
bool enabled;
/* The server to use for our MQTT global message gateway feature.
If not set, the default server will be used */
char address[32];
/* MQTT username to use (most useful for a custom MQTT server).
If using a custom server, this will be honoured even if empty.
If using the default server, this will only be honoured if set, otherwise the device will use the default username */
char username[64];
/* MQTT password to use (most useful for a custom MQTT server).
If using a custom server, this will be honoured even if empty.
If using the default server, this will only be honoured if set, otherwise the device will use the default password */
char password[64];
/* Whether to send encrypted or decrypted packets to MQTT.
This parameter is only honoured if you also set server
(the default official mqtt.meshtastic.org server can handle encrypted packets)
Decrypted packets may be useful for external systems that want to consume meshtastic packets */
bool encryption_enabled;
/* Whether to send / consume json packets on MQTT */
bool json_enabled;
} ModuleConfig_MQTTConfig;
typedef struct _ModuleConfig_RangeTestConfig {
bool enabled;
uint32_t sender;
bool save;
} ModuleConfig_RangeTestConfig;
/* Audio Config for codec2 voice */
typedef struct _ModuleConfig_AudioConfig {
/* Whether Audio is enabled */
bool codec2_enabled;
/* PTT Pin */
uint8_t ptt_pin;
/* The audio sample rate to use for codec2 */
ModuleConfig_AudioConfig_Audio_Baud bitrate;
/* I2S Word Select */
uint8_t i2s_ws;
/* I2S Data IN */
uint8_t i2s_sd;
/* I2S Data OUT */
uint8_t i2s_din;
/* I2S Clock */
uint8_t i2s_sck;
} ModuleConfig_AudioConfig;
/* Serial Config */
typedef struct _ModuleConfig_SerialConfig {
/* Preferences for the SerialModule
FIXME - Move this out of UserPreferences and into a section for module configuration. */
bool enabled;
/* TODO: REPLACE */
bool echo;
/* TODO: REPLACE */
uint32_t rxd;
/* TODO: REPLACE */
uint32_t txd;
/* TODO: REPLACE */
ModuleConfig_SerialConfig_Serial_Baud baud;
/* TODO: REPLACE */
uint32_t timeout;
/* TODO: REPLACE */
ModuleConfig_SerialConfig_Serial_Mode mode;
} ModuleConfig_SerialConfig;
typedef struct _ModuleConfig_StoreForwardConfig {
/* External Notifications Config */
typedef struct _ModuleConfig_ExternalNotificationConfig {
/* Enable the ExternalNotificationModule */
bool enabled;
/* When using in On/Off mode, keep the output on for this many
milliseconds. Default 1000ms (1 second). */
uint32_t output_ms;
/* Define the output pin GPIO setting Defaults to
EXT_NOTIFY_OUT if set for the board.
In standalone devices this pin should drive the LED to match the UI. */
uint32_t output;
/* IF this is true, the 'output' Pin will be pulled active high, false
means active low. */
bool active;
/* True: Alert when a text message arrives (output) */
bool alert_message;
/* True: Alert when the bell character is received (output) */
bool alert_bell;
/* use a PWM output instead of a simple on/off output. This will ignore
the 'output', 'output_ms' and 'active' settings and use the
device.buzzer_gpio instead. */
bool use_pwm;
/* Optional: Define a secondary output pin for a vibra motor
This is used in standalone devices to match the UI. */
uint8_t output_vibra;
/* Optional: Define a tertiary output pin for an active buzzer
This is used in standalone devices to to match the UI. */
uint8_t output_buzzer;
/* True: Alert when a text message arrives (output_vibra) */
bool alert_message_vibra;
/* True: Alert when a text message arrives (output_buzzer) */
bool alert_message_buzzer;
/* True: Alert when the bell character is received (output_vibra) */
bool alert_bell_vibra;
/* True: Alert when the bell character is received (output_buzzer) */
bool alert_bell_buzzer;
/* The notification will toggle with 'output_ms' for this time of seconds.
Default is 0 which means don't repeat at all. 60 would mean blink
and/or beep for 60 seconds */
uint16_t nag_timeout;
} ModuleConfig_ExternalNotificationConfig;
/* Store and Forward Module Config */
typedef struct _ModuleConfig_StoreForwardConfig {
/* Enable the Store and Forward Module */
bool enabled;
/* TODO: REPLACE */
bool heartbeat;
/* TODO: REPLACE */
uint32_t records;
/* TODO: REPLACE */
uint32_t history_return_max;
/* TODO: REPLACE */
uint32_t history_return_window;
} ModuleConfig_StoreForwardConfig;
/* Preferences for the RangeTestModule */
typedef struct _ModuleConfig_RangeTestConfig {
/* Enable the Range Test Module */
bool enabled;
/* Send out range test messages from this node */
uint32_t sender;
/* Bool value indicating that this node should save a RangeTest.csv file.
ESP32 Only */
bool save;
} ModuleConfig_RangeTestConfig;
/* Configuration for both device and environment metrics */
typedef struct _ModuleConfig_TelemetryConfig {
/* Interval in seconds of how often we should try to send our
device metrics to the mesh */
uint32_t device_update_interval;
uint32_t environment_update_interval;
/* Preferences for the Telemetry Module (Environment)
Enable/Disable the telemetry measurement module measurement collection */
bool environment_measurement_enabled;
/* Enable/Disable the telemetry measurement module on-device display */
bool environment_screen_enabled;
/* We'll always read the sensor in Celsius, but sometimes we might want to
display the results in Fahrenheit as a "user preference". */
bool environment_display_fahrenheit;
} ModuleConfig_TelemetryConfig;
/* TODO: REPLACE */
typedef struct _ModuleConfig_CannedMessageConfig {
/* Enable the rotary encoder #1. This is a 'dumb' encoder sending pulses on both A and B pins while rotating. */
bool rotary1_enabled;
/* GPIO pin for rotary encoder A port. */
uint32_t inputbroker_pin_a;
/* GPIO pin for rotary encoder B port. */
uint32_t inputbroker_pin_b;
/* GPIO pin for rotary encoder Press port. */
uint32_t inputbroker_pin_press;
/* Generate input event on CW of this kind. */
ModuleConfig_CannedMessageConfig_InputEventChar inputbroker_event_cw;
/* Generate input event on CCW of this kind. */
ModuleConfig_CannedMessageConfig_InputEventChar inputbroker_event_ccw;
/* Generate input event on Press of this kind. */
ModuleConfig_CannedMessageConfig_InputEventChar inputbroker_event_press;
/* Enable the Up/Down/Select input device. Can be RAK rotary encoder or 3 buttons. Uses the a/b/press definitions from inputbroker. */
bool updown1_enabled;
/* Enable/disable CannedMessageModule. */
bool enabled;
/* Input event origin accepted by the canned message module.
Can be e.g. "rotEnc1", "upDownEnc1" or keyword "_any" */
char allow_input_source[16];
/* CannedMessageModule also sends a bell character with the messages.
ExternalNotificationModule can benefit from this feature. */
bool send_bell;
} ModuleConfig_CannedMessageConfig;
/* Module Config */
typedef struct _ModuleConfig {
pb_size_t which_payload_variant;
@@ -158,6 +270,10 @@ typedef struct _ModuleConfig {
} ModuleConfig;
#ifdef __cplusplus
extern "C" {
#endif
/* Helper constants for enums */
#define _ModuleConfig_AudioConfig_Audio_Baud_MIN ModuleConfig_AudioConfig_Audio_Baud_CODEC2_DEFAULT
#define _ModuleConfig_AudioConfig_Audio_Baud_MAX ModuleConfig_AudioConfig_Audio_Baud_CODEC2_700B
@@ -176,36 +292,89 @@ typedef struct _ModuleConfig {
#define _ModuleConfig_CannedMessageConfig_InputEventChar_ARRAYSIZE ((ModuleConfig_CannedMessageConfig_InputEventChar)(ModuleConfig_CannedMessageConfig_InputEventChar_BACK+1))
#ifdef __cplusplus
extern "C" {
#endif
#define ModuleConfig_AudioConfig_bitrate_ENUMTYPE ModuleConfig_AudioConfig_Audio_Baud
#define ModuleConfig_SerialConfig_baud_ENUMTYPE ModuleConfig_SerialConfig_Serial_Baud
#define ModuleConfig_SerialConfig_mode_ENUMTYPE ModuleConfig_SerialConfig_Serial_Mode
#define ModuleConfig_CannedMessageConfig_inputbroker_event_cw_ENUMTYPE ModuleConfig_CannedMessageConfig_InputEventChar
#define ModuleConfig_CannedMessageConfig_inputbroker_event_ccw_ENUMTYPE ModuleConfig_CannedMessageConfig_InputEventChar
#define ModuleConfig_CannedMessageConfig_inputbroker_event_press_ENUMTYPE ModuleConfig_CannedMessageConfig_InputEventChar
/* Initializer values for message structs */
#define ModuleConfig_init_default {0, {ModuleConfig_MQTTConfig_init_default}}
#define ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0}
#define ModuleConfig_AudioConfig_init_default {0, 0, 0, 0, _ModuleConfig_AudioConfig_Audio_Baud_MIN}
#define ModuleConfig_AudioConfig_init_default {0, 0, _ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0}
#define ModuleConfig_SerialConfig_init_default {0, 0, 0, 0, _ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _ModuleConfig_SerialConfig_Serial_Mode_MIN}
#define ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0, 0}
#define ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define ModuleConfig_StoreForwardConfig_init_default {0, 0, 0, 0, 0}
#define ModuleConfig_RangeTestConfig_init_default {0, 0, 0}
#define ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0}
#define ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
#define ModuleConfig_init_zero {0, {ModuleConfig_MQTTConfig_init_zero}}
#define ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0}
#define ModuleConfig_AudioConfig_init_zero {0, 0, 0, 0, _ModuleConfig_AudioConfig_Audio_Baud_MIN}
#define ModuleConfig_AudioConfig_init_zero {0, 0, _ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0}
#define ModuleConfig_SerialConfig_init_zero {0, 0, 0, 0, _ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _ModuleConfig_SerialConfig_Serial_Mode_MIN}
#define ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0, 0}
#define ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define ModuleConfig_StoreForwardConfig_init_zero {0, 0, 0, 0, 0}
#define ModuleConfig_RangeTestConfig_init_zero {0, 0, 0}
#define ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0}
#define ModuleConfig_CannedMessageConfig_init_zero {0, 0, 0, 0, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
/* Field tags (for use in manual encoding/decoding) */
#define ModuleConfig_MQTTConfig_enabled_tag 1
#define ModuleConfig_MQTTConfig_address_tag 2
#define ModuleConfig_MQTTConfig_username_tag 3
#define ModuleConfig_MQTTConfig_password_tag 4
#define ModuleConfig_MQTTConfig_encryption_enabled_tag 5
#define ModuleConfig_MQTTConfig_json_enabled_tag 6
#define ModuleConfig_AudioConfig_codec2_enabled_tag 1
#define ModuleConfig_AudioConfig_mic_chan_tag 2
#define ModuleConfig_AudioConfig_amp_pin_tag 3
#define ModuleConfig_AudioConfig_ptt_pin_tag 4
#define ModuleConfig_AudioConfig_bitrate_tag 5
#define ModuleConfig_AudioConfig_ptt_pin_tag 2
#define ModuleConfig_AudioConfig_bitrate_tag 3
#define ModuleConfig_AudioConfig_i2s_ws_tag 4
#define ModuleConfig_AudioConfig_i2s_sd_tag 5
#define ModuleConfig_AudioConfig_i2s_din_tag 6
#define ModuleConfig_AudioConfig_i2s_sck_tag 7
#define ModuleConfig_SerialConfig_enabled_tag 1
#define ModuleConfig_SerialConfig_echo_tag 2
#define ModuleConfig_SerialConfig_rxd_tag 3
#define ModuleConfig_SerialConfig_txd_tag 4
#define ModuleConfig_SerialConfig_baud_tag 5
#define ModuleConfig_SerialConfig_timeout_tag 6
#define ModuleConfig_SerialConfig_mode_tag 7
#define ModuleConfig_ExternalNotificationConfig_enabled_tag 1
#define ModuleConfig_ExternalNotificationConfig_output_ms_tag 2
#define ModuleConfig_ExternalNotificationConfig_output_tag 3
#define ModuleConfig_ExternalNotificationConfig_active_tag 4
#define ModuleConfig_ExternalNotificationConfig_alert_message_tag 5
#define ModuleConfig_ExternalNotificationConfig_alert_bell_tag 6
#define ModuleConfig_ExternalNotificationConfig_use_pwm_tag 7
#define ModuleConfig_ExternalNotificationConfig_output_vibra_tag 8
#define ModuleConfig_ExternalNotificationConfig_output_buzzer_tag 9
#define ModuleConfig_ExternalNotificationConfig_alert_message_vibra_tag 10
#define ModuleConfig_ExternalNotificationConfig_alert_message_buzzer_tag 11
#define ModuleConfig_ExternalNotificationConfig_alert_bell_vibra_tag 12
#define ModuleConfig_ExternalNotificationConfig_alert_bell_buzzer_tag 13
#define ModuleConfig_ExternalNotificationConfig_nag_timeout_tag 14
#define ModuleConfig_StoreForwardConfig_enabled_tag 1
#define ModuleConfig_StoreForwardConfig_heartbeat_tag 2
#define ModuleConfig_StoreForwardConfig_records_tag 3
#define ModuleConfig_StoreForwardConfig_history_return_max_tag 4
#define ModuleConfig_StoreForwardConfig_history_return_window_tag 5
#define ModuleConfig_RangeTestConfig_enabled_tag 1
#define ModuleConfig_RangeTestConfig_sender_tag 2
#define ModuleConfig_RangeTestConfig_save_tag 3
#define ModuleConfig_TelemetryConfig_device_update_interval_tag 1
#define ModuleConfig_TelemetryConfig_environment_update_interval_tag 2
#define ModuleConfig_TelemetryConfig_environment_measurement_enabled_tag 3
#define ModuleConfig_TelemetryConfig_environment_screen_enabled_tag 4
#define ModuleConfig_TelemetryConfig_environment_display_fahrenheit_tag 5
#define ModuleConfig_CannedMessageConfig_rotary1_enabled_tag 1
#define ModuleConfig_CannedMessageConfig_inputbroker_pin_a_tag 2
#define ModuleConfig_CannedMessageConfig_inputbroker_pin_b_tag 3
@@ -217,39 +386,6 @@ extern "C" {
#define ModuleConfig_CannedMessageConfig_enabled_tag 9
#define ModuleConfig_CannedMessageConfig_allow_input_source_tag 10
#define ModuleConfig_CannedMessageConfig_send_bell_tag 11
#define ModuleConfig_ExternalNotificationConfig_enabled_tag 1
#define ModuleConfig_ExternalNotificationConfig_output_ms_tag 2
#define ModuleConfig_ExternalNotificationConfig_output_tag 3
#define ModuleConfig_ExternalNotificationConfig_active_tag 4
#define ModuleConfig_ExternalNotificationConfig_alert_message_tag 5
#define ModuleConfig_ExternalNotificationConfig_alert_bell_tag 6
#define ModuleConfig_ExternalNotificationConfig_use_pwm_tag 7
#define ModuleConfig_MQTTConfig_enabled_tag 1
#define ModuleConfig_MQTTConfig_address_tag 2
#define ModuleConfig_MQTTConfig_username_tag 3
#define ModuleConfig_MQTTConfig_password_tag 4
#define ModuleConfig_MQTTConfig_encryption_enabled_tag 5
#define ModuleConfig_MQTTConfig_json_enabled_tag 6
#define ModuleConfig_RangeTestConfig_enabled_tag 1
#define ModuleConfig_RangeTestConfig_sender_tag 2
#define ModuleConfig_RangeTestConfig_save_tag 3
#define ModuleConfig_SerialConfig_enabled_tag 1
#define ModuleConfig_SerialConfig_echo_tag 2
#define ModuleConfig_SerialConfig_rxd_tag 3
#define ModuleConfig_SerialConfig_txd_tag 4
#define ModuleConfig_SerialConfig_baud_tag 5
#define ModuleConfig_SerialConfig_timeout_tag 6
#define ModuleConfig_SerialConfig_mode_tag 7
#define ModuleConfig_StoreForwardConfig_enabled_tag 1
#define ModuleConfig_StoreForwardConfig_heartbeat_tag 2
#define ModuleConfig_StoreForwardConfig_records_tag 3
#define ModuleConfig_StoreForwardConfig_history_return_max_tag 4
#define ModuleConfig_StoreForwardConfig_history_return_window_tag 5
#define ModuleConfig_TelemetryConfig_device_update_interval_tag 1
#define ModuleConfig_TelemetryConfig_environment_update_interval_tag 2
#define ModuleConfig_TelemetryConfig_environment_measurement_enabled_tag 3
#define ModuleConfig_TelemetryConfig_environment_screen_enabled_tag 4
#define ModuleConfig_TelemetryConfig_environment_display_fahrenheit_tag 5
#define ModuleConfig_mqtt_tag 1
#define ModuleConfig_serial_tag 2
#define ModuleConfig_external_notification_tag 3
@@ -292,10 +428,12 @@ X(a, STATIC, SINGULAR, BOOL, json_enabled, 6)
#define ModuleConfig_AudioConfig_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, BOOL, codec2_enabled, 1) \
X(a, STATIC, SINGULAR, UINT32, mic_chan, 2) \
X(a, STATIC, SINGULAR, UINT32, amp_pin, 3) \
X(a, STATIC, SINGULAR, UINT32, ptt_pin, 4) \
X(a, STATIC, SINGULAR, UENUM, bitrate, 5)
X(a, STATIC, SINGULAR, UINT32, ptt_pin, 2) \
X(a, STATIC, SINGULAR, UENUM, bitrate, 3) \
X(a, STATIC, SINGULAR, UINT32, i2s_ws, 4) \
X(a, STATIC, SINGULAR, UINT32, i2s_sd, 5) \
X(a, STATIC, SINGULAR, UINT32, i2s_din, 6) \
X(a, STATIC, SINGULAR, UINT32, i2s_sck, 7)
#define ModuleConfig_AudioConfig_CALLBACK NULL
#define ModuleConfig_AudioConfig_DEFAULT NULL
@@ -317,7 +455,14 @@ X(a, STATIC, SINGULAR, UINT32, output, 3) \
X(a, STATIC, SINGULAR, BOOL, active, 4) \
X(a, STATIC, SINGULAR, BOOL, alert_message, 5) \
X(a, STATIC, SINGULAR, BOOL, alert_bell, 6) \
X(a, STATIC, SINGULAR, BOOL, use_pwm, 7)
X(a, STATIC, SINGULAR, BOOL, use_pwm, 7) \
X(a, STATIC, SINGULAR, UINT32, output_vibra, 8) \
X(a, STATIC, SINGULAR, UINT32, output_buzzer, 9) \
X(a, STATIC, SINGULAR, BOOL, alert_message_vibra, 10) \
X(a, STATIC, SINGULAR, BOOL, alert_message_buzzer, 11) \
X(a, STATIC, SINGULAR, BOOL, alert_bell_vibra, 12) \
X(a, STATIC, SINGULAR, BOOL, alert_bell_buzzer, 13) \
X(a, STATIC, SINGULAR, UINT32, nag_timeout, 14)
#define ModuleConfig_ExternalNotificationConfig_CALLBACK NULL
#define ModuleConfig_ExternalNotificationConfig_DEFAULT NULL
@@ -383,9 +528,9 @@ extern const pb_msgdesc_t ModuleConfig_CannedMessageConfig_msg;
#define ModuleConfig_CannedMessageConfig_fields &ModuleConfig_CannedMessageConfig_msg
/* Maximum encoded size of messages (where known) */
#define ModuleConfig_AudioConfig_size 22
#define ModuleConfig_AudioConfig_size 19
#define ModuleConfig_CannedMessageConfig_size 49
#define ModuleConfig_ExternalNotificationConfig_size 22
#define ModuleConfig_ExternalNotificationConfig_size 40
#define ModuleConfig_MQTTConfig_size 169
#define ModuleConfig_RangeTestConfig_size 10
#define ModuleConfig_SerialConfig_size 26

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#include "mqtt.pb.h"
#if PB_PROTO_HEADER_VERSION != 40

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#ifndef PB_MQTT_PB_H_INCLUDED
#define PB_MQTT_PB_H_INCLUDED

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#include "portnums.pb.h"
#if PB_PROTO_HEADER_VERSION != 40

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#ifndef PB_PORTNUMS_PB_H_INCLUDED
#define PB_PORTNUMS_PB_H_INCLUDED
@@ -82,6 +82,9 @@ typedef enum _PortNum {
Maintained by GitHub user GUVWAF.
Project files at https://github.com/GUVWAF/Meshtasticator */
PortNum_SIMULATOR_APP = 69,
/* Provides a traceroute functionality to show the route a packet towards
a certain destination would take on the mesh. */
PortNum_TRACEROUTE_APP = 70,
/* Private applications should use portnums >= 256.
To simplify initial development and testing you can use "PRIVATE_APP"
in your code without needing to rebuild protobuf files (via [regen-protos.sh](https://github.com/meshtastic/firmware/blob/master/bin/regen-protos.sh)) */
@@ -92,16 +95,16 @@ typedef enum _PortNum {
PortNum_MAX = 511
} PortNum;
#ifdef __cplusplus
extern "C" {
#endif
/* Helper constants for enums */
#define _PortNum_MIN PortNum_UNKNOWN_APP
#define _PortNum_MAX PortNum_MAX
#define _PortNum_ARRAYSIZE ((PortNum)(PortNum_MAX+1))
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#include "remote_hardware.pb.h"
#if PB_PROTO_HEADER_VERSION != 40

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#ifndef PB_REMOTE_HARDWARE_PB_H_INCLUDED
#define PB_REMOTE_HARDWARE_PB_H_INCLUDED
@@ -10,12 +10,21 @@
#endif
/* Enum definitions */
/* TODO: REPLACE */
typedef enum _HardwareMessage_Type {
/* Unset/unused */
HardwareMessage_Type_UNSET = 0,
/* Set gpio gpios based on gpio_mask/gpio_value */
HardwareMessage_Type_WRITE_GPIOS = 1,
/* We are now interested in watching the gpio_mask gpios.
If the selected gpios change, please broadcast GPIOS_CHANGED.
Will implicitly change the gpios requested to be INPUT gpios. */
HardwareMessage_Type_WATCH_GPIOS = 2,
/* The gpios listed in gpio_mask have changed, the new values are listed in gpio_value */
HardwareMessage_Type_GPIOS_CHANGED = 3,
/* Read the gpios specified in gpio_mask, send back a READ_GPIOS_REPLY reply with gpio_value populated */
HardwareMessage_Type_READ_GPIOS = 4,
/* A reply to READ_GPIOS. gpio_mask and gpio_value will be populated */
HardwareMessage_Type_READ_GPIOS_REPLY = 5
} HardwareMessage_Type;
@@ -40,15 +49,17 @@ typedef struct _HardwareMessage {
} HardwareMessage;
#ifdef __cplusplus
extern "C" {
#endif
/* Helper constants for enums */
#define _HardwareMessage_Type_MIN HardwareMessage_Type_UNSET
#define _HardwareMessage_Type_MAX HardwareMessage_Type_READ_GPIOS_REPLY
#define _HardwareMessage_Type_ARRAYSIZE ((HardwareMessage_Type)(HardwareMessage_Type_READ_GPIOS_REPLY+1))
#define HardwareMessage_type_ENUMTYPE HardwareMessage_Type
#ifdef __cplusplus
extern "C" {
#endif
/* Initializer values for message structs */
#define HardwareMessage_init_default {_HardwareMessage_Type_MIN, 0, 0}

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#include "storeforward.pb.h"
#if PB_PROTO_HEADER_VERSION != 40

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#ifndef PB_STOREFORWARD_PB_H_INCLUDED
#define PB_STOREFORWARD_PB_H_INCLUDED
@@ -10,88 +10,126 @@
#endif
/* Enum definitions */
/* 001 - 063 = From Router
064 - 127 = From Client */
typedef enum _StoreAndForward_RequestResponse {
/* Unset/unused */
StoreAndForward_RequestResponse_UNSET = 0,
/* Router is an in error state. */
StoreAndForward_RequestResponse_ROUTER_ERROR = 1,
/* Router heartbeat */
StoreAndForward_RequestResponse_ROUTER_HEARTBEAT = 2,
/* Router has requested the client respond. This can work as a
"are you there" message. */
StoreAndForward_RequestResponse_ROUTER_PING = 3,
/* The response to a "Ping" */
StoreAndForward_RequestResponse_ROUTER_PONG = 4,
/* Router is currently busy. Please try again later. */
StoreAndForward_RequestResponse_ROUTER_BUSY = 5,
/* Router is responding to a request for history. */
StoreAndForward_RequestResponse_ROUTER_HISTORY = 6,
StoreAndForward_RequestResponse_CLIENT_ERROR = 101,
StoreAndForward_RequestResponse_CLIENT_HISTORY = 102,
StoreAndForward_RequestResponse_CLIENT_STATS = 103,
StoreAndForward_RequestResponse_CLIENT_PING = 104,
StoreAndForward_RequestResponse_CLIENT_PONG = 105,
/* Router is responding to a request for stats. */
StoreAndForward_RequestResponse_ROUTER_STATS = 7,
/* Client is an in error state. */
StoreAndForward_RequestResponse_CLIENT_ERROR = 64,
/* Client has requested a replay from the router. */
StoreAndForward_RequestResponse_CLIENT_HISTORY = 65,
/* Client has requested stats from the router. */
StoreAndForward_RequestResponse_CLIENT_STATS = 66,
/* Client has requested the router respond. This can work as a
"are you there" message. */
StoreAndForward_RequestResponse_CLIENT_PING = 67,
/* The response to a "Ping" */
StoreAndForward_RequestResponse_CLIENT_PONG = 68,
/* Client has requested that the router abort processing the client's request */
StoreAndForward_RequestResponse_CLIENT_ABORT = 106
} StoreAndForward_RequestResponse;
/* Struct definitions */
typedef struct _StoreAndForward_Heartbeat {
uint32_t period;
uint32_t secondary;
} StoreAndForward_Heartbeat;
/* TODO: REPLACE */
typedef struct _StoreAndForward_Statistics {
/* Number of messages we have ever seen */
uint32_t messages_total;
/* Number of messages we have currently saved our history. */
uint32_t messages_saved;
/* Maximum number of messages we will save */
uint32_t messages_max;
/* Router uptime in seconds */
uint32_t up_time;
/* Number of times any client sent a request to the S&F. */
uint32_t requests;
/* Number of times the history was requested. */
uint32_t requests_history;
/* Is the heartbeat enabled on the server? */
bool heartbeat;
/* Is the heartbeat enabled on the server? */
uint32_t return_max;
/* Is the heartbeat enabled on the server? */
uint32_t return_window;
} StoreAndForward_Statistics;
/* TODO: REPLACE */
typedef struct _StoreAndForward_History {
/* Number of that will be sent to the client */
uint32_t history_messages;
/* The window of messages that was used to filter the history client requested */
uint32_t window;
/* The window of messages that was used to filter the history client requested */
uint32_t last_request;
} StoreAndForward_History;
typedef struct _StoreAndForward_Statistics {
uint32_t messages_total;
uint32_t messages_saved;
uint32_t messages_max;
uint32_t up_time;
uint32_t requests;
uint32_t requests_history;
bool heartbeat;
uint32_t return_max;
uint32_t return_window;
} StoreAndForward_Statistics;
/* TODO: REPLACE */
typedef struct _StoreAndForward_Heartbeat {
/* Number of that will be sent to the client */
uint32_t period;
/* If set, this is not the primary Store & Forward router on the mesh */
uint32_t secondary;
} StoreAndForward_Heartbeat;
/* TODO: REPLACE */
typedef struct _StoreAndForward {
/* TODO: REPLACE */
StoreAndForward_RequestResponse rr;
pb_size_t which_variant;
union {
/* TODO: REPLACE */
bool has_stats;
StoreAndForward_Statistics stats;
/* TODO: REPLACE */
bool has_history;
StoreAndForward_History history;
/* TODO: REPLACE */
bool has_heartbeat;
StoreAndForward_Heartbeat heartbeat;
/* Empty Payload */
bool empty;
} variant;
} StoreAndForward;
/* Helper constants for enums */
#define _StoreAndForward_RequestResponse_MIN StoreAndForward_RequestResponse_UNSET
#define _StoreAndForward_RequestResponse_MAX StoreAndForward_RequestResponse_CLIENT_ABORT
#define _StoreAndForward_RequestResponse_ARRAYSIZE ((StoreAndForward_RequestResponse)(StoreAndForward_RequestResponse_CLIENT_ABORT+1))
#ifdef __cplusplus
extern "C" {
#endif
/* Helper constants for enums */
#define _StoreAndForward_RequestResponse_MIN StoreAndForward_RequestResponse_UNSET
#define _StoreAndForward_RequestResponse_MAX StoreAndForward_RequestResponse_CLIENT_ABORT
#define _StoreAndForward_RequestResponse_ARRAYSIZE ((StoreAndForward_RequestResponse)(StoreAndForward_RequestResponse_CLIENT_ABORT+1))
#define StoreAndForward_rr_ENUMTYPE StoreAndForward_RequestResponse
/* Initializer values for message structs */
#define StoreAndForward_init_default {_StoreAndForward_RequestResponse_MIN, false, StoreAndForward_Statistics_init_default, false, StoreAndForward_History_init_default, false, StoreAndForward_Heartbeat_init_default}
#define StoreAndForward_init_default {_StoreAndForward_RequestResponse_MIN, 0, {StoreAndForward_Statistics_init_default}}
#define StoreAndForward_Statistics_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0}
#define StoreAndForward_History_init_default {0, 0, 0}
#define StoreAndForward_Heartbeat_init_default {0, 0}
#define StoreAndForward_init_zero {_StoreAndForward_RequestResponse_MIN, false, StoreAndForward_Statistics_init_zero, false, StoreAndForward_History_init_zero, false, StoreAndForward_Heartbeat_init_zero}
#define StoreAndForward_init_zero {_StoreAndForward_RequestResponse_MIN, 0, {StoreAndForward_Statistics_init_zero}}
#define StoreAndForward_Statistics_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0}
#define StoreAndForward_History_init_zero {0, 0, 0}
#define StoreAndForward_Heartbeat_init_zero {0, 0}
/* Field tags (for use in manual encoding/decoding) */
#define StoreAndForward_Heartbeat_period_tag 1
#define StoreAndForward_Heartbeat_secondary_tag 2
#define StoreAndForward_History_history_messages_tag 1
#define StoreAndForward_History_window_tag 2
#define StoreAndForward_History_last_request_tag 3
#define StoreAndForward_Statistics_messages_total_tag 1
#define StoreAndForward_Statistics_messages_saved_tag 2
#define StoreAndForward_Statistics_messages_max_tag 3
@@ -101,22 +139,29 @@ extern "C" {
#define StoreAndForward_Statistics_heartbeat_tag 7
#define StoreAndForward_Statistics_return_max_tag 8
#define StoreAndForward_Statistics_return_window_tag 9
#define StoreAndForward_History_history_messages_tag 1
#define StoreAndForward_History_window_tag 2
#define StoreAndForward_History_last_request_tag 3
#define StoreAndForward_Heartbeat_period_tag 1
#define StoreAndForward_Heartbeat_secondary_tag 2
#define StoreAndForward_rr_tag 1
#define StoreAndForward_stats_tag 2
#define StoreAndForward_history_tag 3
#define StoreAndForward_heartbeat_tag 4
#define StoreAndForward_empty_tag 5
/* Struct field encoding specification for nanopb */
#define StoreAndForward_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UENUM, rr, 1) \
X(a, STATIC, OPTIONAL, MESSAGE, stats, 2) \
X(a, STATIC, OPTIONAL, MESSAGE, history, 3) \
X(a, STATIC, OPTIONAL, MESSAGE, heartbeat, 4)
X(a, STATIC, ONEOF, MESSAGE, (variant,stats,variant.stats), 2) \
X(a, STATIC, ONEOF, MESSAGE, (variant,history,variant.history), 3) \
X(a, STATIC, ONEOF, MESSAGE, (variant,heartbeat,variant.heartbeat), 4) \
X(a, STATIC, ONEOF, BOOL, (variant,empty,variant.empty), 5)
#define StoreAndForward_CALLBACK NULL
#define StoreAndForward_DEFAULT NULL
#define StoreAndForward_stats_MSGTYPE StoreAndForward_Statistics
#define StoreAndForward_history_MSGTYPE StoreAndForward_History
#define StoreAndForward_heartbeat_MSGTYPE StoreAndForward_Heartbeat
#define StoreAndForward_variant_stats_MSGTYPE StoreAndForward_Statistics
#define StoreAndForward_variant_history_MSGTYPE StoreAndForward_History
#define StoreAndForward_variant_heartbeat_MSGTYPE StoreAndForward_Heartbeat
#define StoreAndForward_Statistics_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, messages_total, 1) \
@@ -159,7 +204,7 @@ extern const pb_msgdesc_t StoreAndForward_Heartbeat_msg;
#define StoreAndForward_Heartbeat_size 12
#define StoreAndForward_History_size 18
#define StoreAndForward_Statistics_size 50
#define StoreAndForward_size 88
#define StoreAndForward_size 54
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#include "telemetry.pb.h"
#if PB_PROTO_HEADER_VERSION != 40

View File

@@ -1,5 +1,5 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.6 */
/* Generated by nanopb-0.4.7 */
#ifndef PB_TELEMETRY_PB_H_INCLUDED
#define PB_TELEMETRY_PB_H_INCLUDED
@@ -35,7 +35,9 @@ typedef enum _TelemetrySensorType {
/* 6-Axis inertial measurement sensor */
TelemetrySensorType_QMI8658 = 10,
/* 3-Axis magnetic sensor */
TelemetrySensorType_QMC5883L = 11
TelemetrySensorType_QMC5883L = 11,
/* High accuracy temperature and humidity */
TelemetrySensorType_SHT31 = 12
} TelemetrySensorType;
/* Struct definitions */
@@ -85,16 +87,19 @@ typedef struct _Telemetry {
} Telemetry;
/* Helper constants for enums */
#define _TelemetrySensorType_MIN TelemetrySensorType_SENSOR_UNSET
#define _TelemetrySensorType_MAX TelemetrySensorType_QMC5883L
#define _TelemetrySensorType_ARRAYSIZE ((TelemetrySensorType)(TelemetrySensorType_QMC5883L+1))
#ifdef __cplusplus
extern "C" {
#endif
/* Helper constants for enums */
#define _TelemetrySensorType_MIN TelemetrySensorType_SENSOR_UNSET
#define _TelemetrySensorType_MAX TelemetrySensorType_SHT31
#define _TelemetrySensorType_ARRAYSIZE ((TelemetrySensorType)(TelemetrySensorType_SHT31+1))
/* Initializer values for message structs */
#define DeviceMetrics_init_default {0, 0, 0, 0}
#define EnvironmentMetrics_init_default {0, 0, 0, 0, 0, 0}

View File

@@ -1,7 +1,7 @@
#include "mesh/http/WiFiAPClient.h"
#include "NodeDB.h"
#include "RTC.h"
#include "concurrency/Periodic.h"
#include "mesh/http/WiFiAPClient.h"
#include "configuration.h"
#include "main.h"
#include "mesh/http/WebServer.h"
@@ -37,9 +37,9 @@ bool APStartupComplete = 0;
unsigned long lastrun_ntp = 0;
static bool needReconnect = true; // If we create our reconnector, run it once at the beginning
bool needReconnect = true; // If we create our reconnector, run it once at the beginning
static Periodic *wifiReconnect;
Periodic *wifiReconnect;
static int32_t reconnectWiFi()
{
@@ -56,29 +56,15 @@ static int32_t reconnectWiFi()
// Make sure we clear old connection credentials
WiFi.disconnect(false, true);
DEBUG_MSG("... Reconnecting to WiFi access point %s\n",wifiName);
DEBUG_MSG("Reconnecting to WiFi access point %s\n",wifiName);
int n = WiFi.scanNetworks();
if (n > 0) {
for (int i = 0; i < n; ++i) {
DEBUG_MSG("Found WiFi network %s, signal strength %d\n", WiFi.SSID(i).c_str(), WiFi.RSSI(i));
yield();
}
WiFi.mode(WIFI_MODE_STA);
WiFi.begin(wifiName, wifiPsw);
} else {
DEBUG_MSG("No networks found during site survey. Rebooting MCU...\n");
screen->startRebootScreen();
rebootAtMsec = millis() + 5000;
}
}
#ifndef DISABLE_NTP
if (WiFi.isConnected() && (((millis() - lastrun_ntp) > 43200000) || (lastrun_ntp == 0))) { // every 12 hours
DEBUG_MSG("Updating NTP time\n");
DEBUG_MSG("Updating NTP time from %s\n",config.network.ntp_server);
if (timeClient.update()) {
DEBUG_MSG("NTP Request Success - Setting RTCQualityNTP if needed\n");
@@ -129,7 +115,7 @@ static void onNetworkConnected()
{
if (!APStartupComplete) {
// Start web server
DEBUG_MSG("... Starting network services\n");
DEBUG_MSG("Starting network services\n");
// start mdns
if (!MDNS.begin("Meshtastic")) {
@@ -168,6 +154,8 @@ bool initWifi()
createSSLCert();
esp_wifi_set_storage(WIFI_STORAGE_RAM); // Disable flash storage for WiFi credentials
if (!*wifiPsw) // Treat empty password as no password
wifiPsw = NULL;
@@ -194,7 +182,7 @@ bool initWifi()
WiFi.onEvent(
[](WiFiEvent_t event, WiFiEventInfo_t info) {
Serial.print("\nWiFi lost connection. Reason: ");
Serial.print("WiFi lost connection. Reason: ");
Serial.println(info.wifi_sta_disconnected.reason);
/*
@@ -221,91 +209,137 @@ bool initWifi()
// Called by the Espressif SDK to
static void WiFiEvent(WiFiEvent_t event)
{
DEBUG_MSG("************ [WiFi-event] event: %d ************\n", event);
DEBUG_MSG("WiFi-Event %d: ", event);
switch (event) {
case SYSTEM_EVENT_WIFI_READY:
case ARDUINO_EVENT_WIFI_READY:
DEBUG_MSG("WiFi interface ready\n");
break;
case SYSTEM_EVENT_SCAN_DONE:
case ARDUINO_EVENT_WIFI_SCAN_DONE:
DEBUG_MSG("Completed scan for access points\n");
break;
case SYSTEM_EVENT_STA_START:
case ARDUINO_EVENT_WIFI_STA_START:
DEBUG_MSG("WiFi station started\n");
break;
case SYSTEM_EVENT_STA_STOP:
case ARDUINO_EVENT_WIFI_STA_STOP:
DEBUG_MSG("WiFi station stopped\n");
break;
case SYSTEM_EVENT_STA_CONNECTED:
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
DEBUG_MSG("Connected to access point\n");
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
DEBUG_MSG("Disconnected from WiFi access point\n");
WiFi.disconnect(false, true);
needReconnect = true;
wifiReconnect->setIntervalFromNow(1000);
break;
case SYSTEM_EVENT_STA_AUTHMODE_CHANGE:
case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE:
DEBUG_MSG("Authentication mode of access point has changed\n");
break;
case SYSTEM_EVENT_STA_GOT_IP:
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
DEBUG_MSG("Obtained IP address: ");
Serial.println(WiFi.localIP());
onNetworkConnected();
break;
case SYSTEM_EVENT_STA_LOST_IP:
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
DEBUG_MSG("Obtained IP6 address: ");
Serial.println(WiFi.localIPv6());
break;
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
DEBUG_MSG("Lost IP address and IP address is reset to 0\n");
WiFi.disconnect(false, true);
needReconnect = true;
wifiReconnect->setIntervalFromNow(1000);
break;
case SYSTEM_EVENT_STA_WPS_ER_SUCCESS:
case ARDUINO_EVENT_WPS_ER_SUCCESS:
DEBUG_MSG("WiFi Protected Setup (WPS): succeeded in enrollee mode\n");
break;
case SYSTEM_EVENT_STA_WPS_ER_FAILED:
case ARDUINO_EVENT_WPS_ER_FAILED:
DEBUG_MSG("WiFi Protected Setup (WPS): failed in enrollee mode\n");
break;
case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT:
case ARDUINO_EVENT_WPS_ER_TIMEOUT:
DEBUG_MSG("WiFi Protected Setup (WPS): timeout in enrollee mode\n");
break;
case SYSTEM_EVENT_STA_WPS_ER_PIN:
case ARDUINO_EVENT_WPS_ER_PIN:
DEBUG_MSG("WiFi Protected Setup (WPS): pin code in enrollee mode\n");
break;
case SYSTEM_EVENT_AP_START:
case ARDUINO_EVENT_WPS_ER_PBC_OVERLAP:
DEBUG_MSG("WiFi Protected Setup (WPS): push button overlap in enrollee mode\n");
break;
case ARDUINO_EVENT_WIFI_AP_START:
DEBUG_MSG("WiFi access point started\n");
break;
case SYSTEM_EVENT_AP_STOP:
case ARDUINO_EVENT_WIFI_AP_STOP:
DEBUG_MSG("WiFi access point stopped\n");
break;
case SYSTEM_EVENT_AP_STACONNECTED:
case ARDUINO_EVENT_WIFI_AP_STACONNECTED:
DEBUG_MSG("Client connected\n");
break;
case SYSTEM_EVENT_AP_STADISCONNECTED:
case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED:
DEBUG_MSG("Client disconnected\n");
break;
case SYSTEM_EVENT_AP_STAIPASSIGNED:
case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED:
DEBUG_MSG("Assigned IP address to client\n");
break;
case SYSTEM_EVENT_AP_PROBEREQRECVED:
case ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED:
DEBUG_MSG("Received probe request\n");
break;
case SYSTEM_EVENT_GOT_IP6:
case ARDUINO_EVENT_WIFI_AP_GOT_IP6:
DEBUG_MSG("IPv6 is preferred\n");
break;
case SYSTEM_EVENT_ETH_START:
case ARDUINO_EVENT_WIFI_FTM_REPORT:
DEBUG_MSG("Fast Transition Management report\n");
break;
case ARDUINO_EVENT_ETH_START:
DEBUG_MSG("Ethernet started\n");
break;
case SYSTEM_EVENT_ETH_STOP:
case ARDUINO_EVENT_ETH_STOP:
DEBUG_MSG("Ethernet stopped\n");
break;
case SYSTEM_EVENT_ETH_CONNECTED:
case ARDUINO_EVENT_ETH_CONNECTED:
DEBUG_MSG("Ethernet connected\n");
break;
case SYSTEM_EVENT_ETH_DISCONNECTED:
case ARDUINO_EVENT_ETH_DISCONNECTED:
DEBUG_MSG("Ethernet disconnected\n");
break;
case SYSTEM_EVENT_ETH_GOT_IP:
DEBUG_MSG("Obtained IP address (SYSTEM_EVENT_ETH_GOT_IP)\n");
case ARDUINO_EVENT_ETH_GOT_IP:
DEBUG_MSG("Obtained IP address (ARDUINO_EVENT_ETH_GOT_IP)\n");
break;
case ARDUINO_EVENT_ETH_GOT_IP6:
DEBUG_MSG("Obtained IP6 address (ARDUINO_EVENT_ETH_GOT_IP6)\n");
break;
case ARDUINO_EVENT_SC_SCAN_DONE:
DEBUG_MSG("SmartConfig: Scan done\n");
break;
case ARDUINO_EVENT_SC_FOUND_CHANNEL:
DEBUG_MSG("SmartConfig: Found channel\n");
break;
case ARDUINO_EVENT_SC_GOT_SSID_PSWD:
DEBUG_MSG("SmartConfig: Got SSID and password\n");
break;
case ARDUINO_EVENT_SC_SEND_ACK_DONE:
DEBUG_MSG("SmartConfig: Send ACK done\n");
break;
case ARDUINO_EVENT_PROV_INIT:
DEBUG_MSG("Provisioning: Init\n");
break;
case ARDUINO_EVENT_PROV_DEINIT:
DEBUG_MSG("Provisioning: Stopped\n");
break;
case ARDUINO_EVENT_PROV_START:
DEBUG_MSG("Provisioning: Started\n");
break;
case ARDUINO_EVENT_PROV_END:
DEBUG_MSG("Provisioning: End\n");
break;
case ARDUINO_EVENT_PROV_CRED_RECV:
DEBUG_MSG("Provisioning: Credentials received\n");
break;
case ARDUINO_EVENT_PROV_CRED_FAIL:
DEBUG_MSG("Provisioning: Credentials failed\n");
break;
case ARDUINO_EVENT_PROV_CRED_SUCCESS:
DEBUG_MSG("Provisioning: Credentials success\n");
break;
default:
break;

View File

@@ -1,6 +1,7 @@
#pragma once
#include "configuration.h"
#include "concurrency/Periodic.h"
#include <Arduino.h>
#include <functional>
@@ -8,6 +9,9 @@
#include <WiFi.h>
#endif
extern bool needReconnect;
extern concurrency::Periodic *wifiReconnect;
/// @return true if wifi is now in use
bool initWifi();

View File

@@ -14,7 +14,7 @@ void initApiServer(int port)
}
}
WiFiServerAPI::WiFiServerAPI(WiFiClient &_client) : StreamAPI(&client), client(_client)
WiFiServerAPI::WiFiServerAPI(WiFiClient &_client) : StreamAPI(&client), concurrency::OSThread("WiFiServerAPI"), client(_client)
{
DEBUG_MSG("Incoming wifi connection\n");
}
@@ -42,7 +42,7 @@ bool WiFiServerAPI::checkIsConnected()
int32_t WiFiServerAPI::runOnce()
{
if (client.connected()) {
return StreamAPI::runOnce();
return StreamAPI::runOncePart();
} else {
DEBUG_MSG("Client dropped connection, suspending API service\n");
enabled = false; // we no longer need to run

View File

@@ -7,7 +7,7 @@
* 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).
*/
class WiFiServerAPI : public StreamAPI
class WiFiServerAPI : public StreamAPI, private concurrency::OSThread
{
private:
WiFiClient client;

View File

@@ -112,12 +112,15 @@ bool AdminModule::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r)
#ifdef ARCH_ESP32
if (BleOta::getOtaAppVersion().isEmpty()) {
DEBUG_MSG("No OTA firmware available, scheduling regular reboot in %d seconds\n", s);
screen->startRebootScreen();
}else{
screen->startFirmwareUpdateScreen();
BleOta::switchToOtaApp();
DEBUG_MSG("Rebooting to OTA in %d seconds\n", s);
}
#else
DEBUG_MSG("Not on ESP32, scheduling regular reboot in %d seconds\n", s);
screen->startRebootScreen();
#endif
rebootAtMsec = (s < 0) ? 0 : (millis() + s * 1000);
break;
@@ -192,6 +195,7 @@ bool AdminModule::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r)
void AdminModule::handleSetOwner(const User &o)
{
int changed = 0;
bool licensed_changed = false;
if (*o.long_name) {
changed |= strcmp(owner.long_name, o.long_name);
@@ -207,12 +211,14 @@ void AdminModule::handleSetOwner(const User &o)
}
if (owner.is_licensed != o.is_licensed) {
changed = 1;
licensed_changed = true;
owner.is_licensed = o.is_licensed;
config.lora.override_duty_cycle = owner.is_licensed; // override duty cycle for licensed operators
}
if (changed) { // If nothing really changed, don't broadcast on the network or write to flash
service.reloadOwner(!hasOpenEditTransaction);
saveChanges(SEGMENT_DEVICESTATE);
licensed_changed ? saveChanges(SEGMENT_CONFIG | SEGMENT_DEVICESTATE) : saveChanges(SEGMENT_DEVICESTATE);
}
}
@@ -509,7 +515,7 @@ void AdminModule::saveChanges(int saveWhat, bool shouldReboot)
}
}
AdminModule::AdminModule() : ProtobufModule("Admin", PortNum_ADMIN_APP, AdminMessage_fields)
AdminModule::AdminModule() : ProtobufModule("Admin", PortNum_ADMIN_APP, &AdminMessage_msg)
{
// restrict to the admin channel for rx
boundChannel = Channels::adminChannel;

View File

@@ -45,8 +45,7 @@ CannedMessageModule *cannedMessageModule;
// TODO: move it into NodeDB.h!
extern bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct);
extern bool saveProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields,
const void *dest_struct);
extern bool saveProto(const char *filename, size_t protoSize, const pb_msgdesc_t *fields, const void *dest_struct);
CannedMessageModule::CannedMessageModule()
: SinglePortModule("canned", PortNum_TEXT_MESSAGE_APP), concurrency::OSThread("CannedMessageModule")
@@ -451,11 +450,15 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
if (this->destSelect) {
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
display->setColor(BLACK);
display->drawStringf(1 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest));
}
display->drawStringf(0 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest));
// used chars right aligned
sprintf(buffer, "%d left", Constants_DATA_PAYLOAD_LEN - this->freetext.length());
display->drawString(x + display->getWidth() - display->getStringWidth(buffer), y + 0, buffer);
if (this->destSelect) {
display->drawString(x + display->getWidth() - display->getStringWidth(buffer) - 1, y + 0, buffer);
}
display->setColor(WHITE);
display->drawStringMaxWidth(0 + x, 0 + y + FONT_HEIGHT_SMALL, x + display->getWidth(), cannedMessageModule->drawWithCursor(cannedMessageModule->freetext, cannedMessageModule->cursor));
} else {
@@ -476,7 +479,7 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
void CannedMessageModule::loadProtoForModule()
{
if (!loadProto(cannedMessagesConfigFile, CannedMessageModuleConfig_size, sizeof(cannedMessagesConfigFile),
CannedMessageModuleConfig_fields, &cannedMessageModuleConfig)) {
&CannedMessageModuleConfig_msg, &cannedMessageModuleConfig)) {
installDefaultCannedMessageModuleConfig();
}
}
@@ -495,8 +498,8 @@ bool CannedMessageModule::saveProtoForModule()
FS.mkdir("/prefs");
#endif
okay &= saveProto(cannedMessagesConfigFile, CannedMessageModuleConfig_size, sizeof(cannedMessageModuleConfig),
CannedMessageModuleConfig_fields, &cannedMessageModuleConfig);
okay &= saveProto(cannedMessagesConfigFile, CannedMessageModuleConfig_size,
&CannedMessageModuleConfig_msg, &cannedMessageModuleConfig);
return okay;
}

View File

@@ -11,41 +11,9 @@
#define PIN_BUZZER false
#endif
//#include <assert.h>
/*
Documentation:
https://github.com/meshtastic/firmware/blob/master/docs/software/modules/ExternalNotificationModule.md
This module supports:
https://github.com/meshtastic/firmware/issues/654
Quick reference:
moduleConfig.external_notification.enabled
0 = Disabled (Default)
1 = Enabled
moduleConfig.external_notification.active
0 = Active Low (Default)
1 = Active High
moduleConfig.external_notification.alert_message
0 = Disabled (Default)
1 = Alert when a text message comes
moduleConfig.external_notification.alert_bell
0 = Disabled (Default)
1 = Alert when the bell character is received
moduleConfig.external_notification.output
GPIO of the output. (Default = 13)
moduleConfig.external_notification.output_ms
Amount of time in ms for the alert. Default is 1000.
https://meshtastic.org/docs/settings/moduleconfig/external-notification
*/
// Default configurations
@@ -58,59 +26,121 @@
#define ASCII_BELL 0x07
bool externalCurrentState = 0;
uint32_t externalTurnedOn = 0;
ExternalNotificationModule *externalNotificationModule;
bool externalCurrentState[3] = {};
uint32_t externalTurnedOn[3] = {};
int32_t ExternalNotificationModule::runOnce()
{
/*
Uncomment the preferences below if you want to use the module
without having to configure it from the PythonAPI or WebUI.
*/
// moduleConfig.external_notification.enabled = 1;
// moduleConfig.external_notification.alert_message = 1;
// moduleConfig.external_notification.active = 1;
// moduleConfig.external_notification.alert_bell = 1;
// moduleConfig.external_notification.output_ms = 1000;
// moduleConfig.external_notification.output = 13;
if (externalCurrentState && !moduleConfig.external_notification.use_pwm) {
if (!moduleConfig.external_notification.enabled) {
return INT32_MAX; // we don't need this thread here...
} else {
#ifndef ARCH_PORTDUINO
if ((nagCycleCutoff < millis()) && !rtttl::isPlaying()) {
#else
if (nagCycleCutoff < millis()) {
#endif
nagCycleCutoff = UINT32_MAX;
DEBUG_MSG("Turning off external notification: ");
for (int i = 0; i < 2; i++) {
if (getExternal(i)) {
setExternalOff(i);
externalTurnedOn[i] = 0;
DEBUG_MSG("%d ", i);
}
}
DEBUG_MSG("\n");
return INT32_MAX; // save cycles till we're needed again
}
// If the output is turned on, turn it back off after the given period of time.
if (externalTurnedOn + (moduleConfig.external_notification.output_ms
if (nagCycleCutoff != UINT32_MAX) {
if (externalTurnedOn[0] + (moduleConfig.external_notification.output_ms
? moduleConfig.external_notification.output_ms
: EXT_NOTIFICATION_MODULE_OUTPUT_MS) <
millis()) {
DEBUG_MSG("Turning off external notification\n");
setExternalOff();
: EXT_NOTIFICATION_MODULE_OUTPUT_MS) < millis()) {
getExternal(0) ? setExternalOff(0) : setExternalOn(0);
}
if (externalTurnedOn[1] + (moduleConfig.external_notification.output_ms
? moduleConfig.external_notification.output_ms
: EXT_NOTIFICATION_MODULE_OUTPUT_MS) < millis()) {
getExternal(1) ? setExternalOff(1) : setExternalOn(1);
}
if (externalTurnedOn[2] + (moduleConfig.external_notification.output_ms
? moduleConfig.external_notification.output_ms
: EXT_NOTIFICATION_MODULE_OUTPUT_MS) < millis()) {
getExternal(2) ? setExternalOff(2) : setExternalOn(2);
}
}
if (moduleConfig.external_notification.use_pwm)
return INT32_MAX; // we don't need this thread here...
else
// now let the PWM buzzer play
#ifndef ARCH_PORTDUINO
if (moduleConfig.external_notification.use_pwm) {
if (rtttl::isPlaying()) {
rtttl::play();
} else if (nagCycleCutoff >= millis()) {
// start the song again if we have time left
rtttl::begin(config.device.buzzer_gpio, pwmRingtone);
}
}
#endif
return 25;
}
void ExternalNotificationModule::setExternalOn()
{
externalCurrentState = 1;
externalTurnedOn = millis();
digitalWrite(output,
(moduleConfig.external_notification.active ? true : false));
}
void ExternalNotificationModule::setExternalOff()
void ExternalNotificationModule::setExternalOn(uint8_t index)
{
externalCurrentState = 0;
externalCurrentState[index] = 1;
externalTurnedOn[index] = millis();
digitalWrite(output,
(moduleConfig.external_notification.active ? false : true));
switch(index) {
case 1:
if(moduleConfig.external_notification.output_vibra)
digitalWrite(moduleConfig.external_notification.output_vibra, true);
break;
case 2:
if(moduleConfig.external_notification.output_buzzer)
digitalWrite(moduleConfig.external_notification.output_buzzer, true);
break;
default:
digitalWrite(output, (moduleConfig.external_notification.active ? true : false));
break;
}
}
// --------
void ExternalNotificationModule::setExternalOff(uint8_t index)
{
externalCurrentState[index] = 0;
externalTurnedOn[index] = millis();
switch(index) {
case 1:
if(moduleConfig.external_notification.output_vibra)
digitalWrite(moduleConfig.external_notification.output_vibra, false);
break;
case 2:
if(moduleConfig.external_notification.output_buzzer)
digitalWrite(moduleConfig.external_notification.output_buzzer, false);
break;
default:
digitalWrite(output, (moduleConfig.external_notification.active ? false : true));
break;
}
}
bool ExternalNotificationModule::getExternal(uint8_t index)
{
return externalCurrentState[index];
}
void ExternalNotificationModule::stopNow() {
#ifndef ARCH_PORTDUINO
rtttl::stop();
#endif
nagCycleCutoff = 1; // small value
setIntervalFromNow(0);
}
ExternalNotificationModule::ExternalNotificationModule()
: SinglePortModule("ExternalNotificationModule", PortNum_TEXT_MESSAGE_APP), concurrency::OSThread(
@@ -121,13 +151,18 @@ ExternalNotificationModule::ExternalNotificationModule()
without having to configure it from the PythonAPI or WebUI.
*/
// moduleConfig.external_notification.enabled = 1;
// moduleConfig.external_notification.alert_message = 1;
// moduleConfig.external_notification.enabled = true;
// moduleConfig.external_notification.alert_message = true;
// moduleConfig.external_notification.alert_message_buzzer = true;
// moduleConfig.external_notification.alert_message_vibra = true;
// moduleConfig.external_notification.active = 1;
// moduleConfig.external_notification.active = true;
// moduleConfig.external_notification.alert_bell = 1;
// moduleConfig.external_notification.output_ms = 1000;
// moduleConfig.external_notification.output = 13;
// moduleConfig.external_notification.output = 4; // RAK4631 IO4
// moduleConfig.external_notification.output_buzzer = 10; // RAK4631 IO6
// moduleConfig.external_notification.output_vibra = 28; // RAK4631 IO7
// moduleConfig.external_notification.nag_timeout = 300;
if (moduleConfig.external_notification.enabled) {
@@ -137,20 +172,31 @@ ExternalNotificationModule::ExternalNotificationModule()
? moduleConfig.external_notification.output
: EXT_NOTIFICATION_MODULE_OUTPUT;
if (!moduleConfig.external_notification.use_pwm) {
// Set the direction of a pin
DEBUG_MSG("Using Pin %i in digital mode\n", output);
pinMode(output, OUTPUT);
// Turn off the pin
setExternalOff();
setExternalOff(0);
externalTurnedOn[0] = 0;
if(moduleConfig.external_notification.output_vibra) {
DEBUG_MSG("Using Pin %i for vibra motor\n", moduleConfig.external_notification.output_vibra);
pinMode(moduleConfig.external_notification.output_vibra, OUTPUT);
setExternalOff(1);
externalTurnedOn[1] = 0;
}
if(moduleConfig.external_notification.output_buzzer) {
if (!moduleConfig.external_notification.use_pwm) {
DEBUG_MSG("Using Pin %i for buzzer\n", moduleConfig.external_notification.output_buzzer);
pinMode(moduleConfig.external_notification.output_buzzer, OUTPUT);
setExternalOff(2);
externalTurnedOn[2] = 0;
} else {
config.device.buzzer_gpio = config.device.buzzer_gpio
? config.device.buzzer_gpio
: PIN_BUZZER;
// in PWM Mode we force the buzzer pin if it is set
DEBUG_MSG("Using Pin %i in PWM mode\n", config.device.buzzer_gpio);
}
}
} else {
DEBUG_MSG("External Notification Module Disabled\n");
enabled = false;
@@ -163,30 +209,95 @@ ProcessMessage ExternalNotificationModule::handleReceived(const MeshPacket &mp)
if (getFrom(&mp) != nodeDB.getNodeNum()) {
// TODO: This may be a problem if messages are sent in unicide, but I'm not sure if it will.
// Need to know if and how this could be a problem.
if (moduleConfig.external_notification.alert_bell) {
// Check if the message contains a bell character. Don't do this loop for every pin, just once.
auto &p = mp.decoded;
DEBUG_MSG("externalNotificationModule - Notification Bell\n");
bool containsBell = false;
for (int i = 0; i < p.payload.size; i++) {
if (p.payload.bytes[i] == ASCII_BELL) {
if (!moduleConfig.external_notification.use_pwm) {
setExternalOn();
} else {
playBeep();
containsBell = true;
}
}
if (moduleConfig.external_notification.alert_bell) {
if (containsBell) {
DEBUG_MSG("externalNotificationModule - Notification Bell\n");
setExternalOn(0);
if (moduleConfig.external_notification.nag_timeout) {
nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000;
} else {
nagCycleCutoff = millis() + moduleConfig.external_notification.output_ms;
}
}
}
if (moduleConfig.external_notification.alert_bell_vibra) {
if (containsBell) {
DEBUG_MSG("externalNotificationModule - Notification Bell (Vibra)\n");
setExternalOn(1);
if (moduleConfig.external_notification.nag_timeout) {
nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000;
} else {
nagCycleCutoff = millis() + moduleConfig.external_notification.output_ms;
}
}
}
if (moduleConfig.external_notification.alert_bell_buzzer) {
if (containsBell) {
DEBUG_MSG("externalNotificationModule - Notification Bell (Buzzer)\n");
if (!moduleConfig.external_notification.use_pwm) {
setExternalOn(2);
} else {
#ifndef ARCH_PORTDUINO
rtttl::begin(config.device.buzzer_gpio, pwmRingtone);
#endif
}
if (moduleConfig.external_notification.nag_timeout) {
nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000;
} else {
nagCycleCutoff = millis() + moduleConfig.external_notification.output_ms;
}
}
}
if (moduleConfig.external_notification.alert_message) {
DEBUG_MSG("externalNotificationModule - Notification Module\n");
if (!moduleConfig.external_notification.use_pwm) {
setExternalOn();
setExternalOn(0);
if (moduleConfig.external_notification.nag_timeout) {
nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000;
} else {
playBeep();
nagCycleCutoff = millis() + moduleConfig.external_notification.output_ms;
}
}
if (!moduleConfig.external_notification.use_pwm) {
if (moduleConfig.external_notification.alert_message_vibra) {
DEBUG_MSG("externalNotificationModule - Notification Module (Vibra)\n");
setExternalOn(1);
if (moduleConfig.external_notification.nag_timeout) {
nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000;
} else {
nagCycleCutoff = millis() + moduleConfig.external_notification.output_ms;
}
}
if (moduleConfig.external_notification.alert_message_buzzer) {
DEBUG_MSG("externalNotificationModule - Notification Module (Buzzer)\n");
if (!moduleConfig.external_notification.use_pwm) {
setExternalOn(2);
} else {
#ifndef ARCH_PORTDUINO
rtttl::begin(config.device.buzzer_gpio, pwmRingtone);
#endif
}
if (moduleConfig.external_notification.nag_timeout) {
nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000;
} else {
nagCycleCutoff = millis() + moduleConfig.external_notification.output_ms;
}
}
}
setIntervalFromNow(0); // run once so we know if we should do something
}
} else {

View File

@@ -3,6 +3,9 @@
#include "SinglePortModule.h"
#include "concurrency/OSThread.h"
#include "configuration.h"
#ifndef ARCH_PORTDUINO
#include <NonBlockingRtttl.h>
#endif
#include <Arduino.h>
#include <functional>
@@ -17,18 +20,23 @@ class ExternalNotificationModule : public SinglePortModule, private concurrency:
public:
ExternalNotificationModule();
void setExternalOn();
void setExternalOff();
void getExternal();
uint32_t nagCycleCutoff = UINT32_MAX;
void setExternalOn(uint8_t index = 0);
void setExternalOff(uint8_t index = 0);
bool getExternal(uint8_t index = 0);
void stopNow();
char pwmRingtone[Constants_DATA_PAYLOAD_LEN] = "a:d=8,o=5,b=125:4d#6,a#,2d#6,16p,g#,4a#,4d#.,p,16g,16a#,d#6,a#,f6,2d#6,16p,c#.6,16c6,16a#,g#.,2a#";
protected:
// virtual MeshPacket *allocReply();
/** Called to handle a particular incoming message
@return ProcessMessage::STOP if you've guaranteed you've handled this message and no other handlers should be considered for it
*/
virtual ProcessMessage handleReceived(const MeshPacket &mp) override;
virtual int32_t runOnce() override;
};
extern ExternalNotificationModule *externalNotificationModule;

View File

@@ -11,6 +11,7 @@
#include "modules/ReplyModule.h"
#include "modules/RoutingModule.h"
#include "modules/TextMessageModule.h"
#include "modules/TraceRouteModule.h"
#include "modules/WaypointModule.h"
#if HAS_TELEMETRY
#include "modules/Telemetry/DeviceTelemetry.h"
@@ -19,13 +20,11 @@
#ifdef ARCH_ESP32
#include "modules/esp32/RangeTestModule.h"
#include "modules/esp32/StoreForwardModule.h"
#ifdef USE_SX1280
#include "modules/esp32/AudioModule.h"
#endif
#endif
#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
#include "modules/ExternalNotificationModule.h"
#if !defined(TTGO_T_ECHO)
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2)
#include "modules/SerialModule.h"
#endif
#endif
@@ -42,6 +41,7 @@ void setupModules()
positionModule = new PositionModule();
waypointModule = new WaypointModule();
textMessageModule = new TextMessageModule();
traceRouteModule = new TraceRouteModule();
// Note: if the rest of meshtastic doesn't need to explicitly use your module, you do not need to assign the instance
// to a global variable.
@@ -63,15 +63,13 @@ void setupModules()
new DeviceTelemetryModule();
new EnvironmentTelemetryModule();
#endif
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO)
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2)
new SerialModule();
#endif
#ifdef ARCH_ESP32
// Only run on an esp32 based device.
#ifdef USE_SX1280
new AudioModule();
#endif
new ExternalNotificationModule();
audioModule = new AudioModule();
externalNotificationModule = new ExternalNotificationModule();
storeForwardModule = new StoreForwardModule();

View File

@@ -51,7 +51,7 @@ MeshPacket *NodeInfoModule::allocReply()
}
NodeInfoModule::NodeInfoModule()
: ProtobufModule("nodeinfo", PortNum_NODEINFO_APP, User_fields), concurrency::OSThread("NodeInfoModule")
: ProtobufModule("nodeinfo", PortNum_NODEINFO_APP, &User_msg), concurrency::OSThread("NodeInfoModule")
{
isPromiscuous = true; // We always want to update our nodedb, even if we are sniffing on others
setIntervalFromNow(30 * 1000); // Send our initial owner announcement 30 seconds after we start (to give network time to setup)

View File

@@ -10,7 +10,7 @@
PositionModule *positionModule;
PositionModule::PositionModule()
: ProtobufModule("position", PortNum_POSITION_APP, Position_fields), concurrency::OSThread("PositionModule")
: ProtobufModule("position", PortNum_POSITION_APP, &Position_msg), concurrency::OSThread("PositionModule")
{
isPromiscuous = true; // We always want to update our nodedb, even if we are sniffing on others
setIntervalFromNow(60 * 1000); // Send our initial position 60 seconds after we start (to give GPS time to setup)

View File

@@ -47,7 +47,7 @@ static uint64_t digitalReads(uint64_t mask)
}
RemoteHardwareModule::RemoteHardwareModule()
: ProtobufModule("remotehardware", PortNum_REMOTE_HARDWARE_APP, HardwareMessage_fields), concurrency::OSThread(
: ProtobufModule("remotehardware", PortNum_REMOTE_HARDWARE_APP, &HardwareMessage_msg), concurrency::OSThread(
"remotehardware")
{
}

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