Compare commits

...

83 Commits

Author SHA1 Message Date
Thomas Göttgens
4fa8d02b08 update FromRadio UUID for nRF52 devices (#1795) 2022-10-13 09:32:54 -05:00
Thomas Göttgens
43fb0d80f1 Merge pull request #1794 from meshtastic/canned-spice
Display looks better that way...
2022-10-13 15:56:13 +02:00
Thomas Göttgens
b25ace14e5 Update CannedMessageModule.h 2022-10-13 15:44:27 +02:00
Thomas Göttgens
8734751bc4 make screen timeout work again 2022-10-13 15:31:57 +02:00
Thomas Göttgens
5559a1edb0 Display looks better that way... 2022-10-13 15:22:57 +02:00
Thomas Göttgens
bf503354f3 Merge pull request #1792 from meshtastic/atecca
Support for ATECCA608B Cryptographic Coprocessor
2022-10-13 14:34:44 +02:00
Thomas Göttgens
7b10441a28 update raspberry pi framework some more... 2022-10-13 14:21:48 +02:00
Thomas Göttgens
994e396c00 update Raspberry Pico Framework 2022-10-13 13:57:17 +02:00
Thomas Göttgens
6e22ee9061 make nRF52 happy 2022-10-13 13:31:19 +02:00
Thomas Göttgens
b5fb0f60b0 don't compile on Portduino 2022-10-13 13:01:24 +02:00
Thomas Göttgens
a7fe69ed6b Support for ATECCA608B Cryptographic Coprocessor 2022-10-13 12:55:28 +02:00
Thomas Göttgens
7f05298172 Merge pull request #1790 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-13 08:45:13 +02:00
thebentern
92a2505056 [create-pull-request] automated change 2022-10-12 23:42:47 +00:00
Ben Meadors
aae9d2fcf6 Package ota zip in final firmware bundle 2022-10-12 13:03:19 -05:00
Ben Meadors
b59e928589 Secure DFU mode for OTA updates with pin (#1789) 2022-10-12 10:31:39 -05:00
Ben Meadors
1db08b3b0e Add pico 2022-10-12 08:06:08 -05:00
Ben Meadors
2cf3c105a1 Add DFU package for nrf52 assets to build assets 2022-10-12 08:06:08 -05:00
Ben Meadors
505e4e8176 Run dfu begin first (#1786)
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2022-10-12 07:55:17 -05:00
Thomas Göttgens
49a9973548 Merge pull request #1788 from meshtastic/bug-1787
fixes #1787
2022-10-12 13:26:21 +02:00
Thomas Göttgens
18af9d734d fixes #1787 2022-10-12 13:13:02 +02:00
Ben Meadors
3e22aafea8 Change UUID for FromRadio characteristic (#1785) 2022-10-11 20:01:26 -05:00
Ben Meadors
434db4347b Send device telemetry to phone every minute (#1784) 2022-10-11 10:21:30 -05:00
Thomas Göttgens
b2c3b405b1 Merge pull request #1783 from meshtastic/ota
debug print on early boot when OTA firmware is detected.
2022-10-10 23:40:19 +02:00
Thomas Göttgens
4bc8f6a6b9 Merge branch 'master' into ota 2022-10-10 23:14:26 +02:00
Thomas Göttgens
4534d17d79 debug print on early boot when OTA firmware is detected. 2022-10-10 23:05:24 +02:00
Ben Meadors
f88dde2f60 Send channels over phoneapi on want config (#1780)
* Send channels

* Doh!

* Adjust comments

* Missed a spot

* Consolidate

* Skipped disabled ones

* Fixed bounding

* Change order

* comment out disabled check for build artefact

* Remove loop

* Off by one

* Probably should start at zero

* Zero

* Oops

* enable dubug log

* Reset to index zero

Co-authored-by: Sacha Weatherstone <sachaw100@hotmail.com>
2022-10-10 10:36:49 -05:00
Thomas Göttgens
f8982ddaf8 Best Practise Platformio 6.x dependency definitions 2022-10-10 15:42:05 +02:00
Thomas Göttgens
784cd8c6f1 Merge pull request #1768 from meshtastic/nrf52-Rollup
Nrf52 rollup
2022-10-10 15:30:45 +02:00
Thomas Göttgens
c3ab8f12cf Merge branch 'master' into nrf52-Rollup 2022-10-10 15:09:49 +02:00
Thomas Göttgens
b5adb7babc Update nrf52840.ini 2022-10-10 15:09:31 +02:00
Thomas Göttgens
62c809a596 Merge pull request #1782 from meshtastic/lora-freq-check
Lora freq check
2022-10-10 12:53:14 +02:00
Thomas Göttgens
d2fe4426c1 Revert Platform Change for now. 2022-10-10 12:32:08 +02:00
Thomas Göttgens
984f0ca12c check allowed range for lora.channel_num 2022-10-10 12:28:31 +02:00
Thomas Göttgens
9d3eba9ea4 Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-10 12:15:09 +02:00
Thomas Göttgens
323f81eaba Merge branch 'master' into nrf52-Rollup 2022-10-10 12:06:44 +02:00
Thomas Göttgens
8d0e25fd82 Merge pull request #1770 from meshtastic/ota
Switch to OTA firmware
2022-10-09 11:54:16 +02:00
Thomas Göttgens
20eaddee58 - fix conditional include for nRF52 (no OTA there)
- fix compiler warning in Canned Messages
2022-10-09 11:35:19 +02:00
Thomas Göttgens
30b1bd85d9 fix build for non-esp32 2022-10-09 11:19:33 +02:00
Thomas Göttgens
09cce094d1 Merge branch 'master' into ota 2022-10-09 11:00:20 +02:00
Thomas Göttgens
33a208e3c4 Merge pull request #1777 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-09 11:00:01 +02:00
caveman99
dd4c4fba80 [create-pull-request] automated change 2022-10-09 08:55:33 +00:00
Sacha Weatherstone
a17c40ad09 Merge branch 'master' into ota 2022-10-09 16:44:24 +10:00
Sacha Weatherstone
9d73e606ac Merge pull request #1774 from meshtastic/node-db
erase oldest entry from NodeDB if it is full
2022-10-09 16:40:46 +10:00
Ben Meadors
da12360105 Merge branch 'master' into node-db 2022-10-08 13:48:35 -05:00
GUVWAF
ee1ae627a3 Model the time it is busy receiving/transmitting (#1776)
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2022-10-08 12:10:50 -05:00
Thomas Göttgens
137a8dcfdf Merge pull request #1775 from meshtastic/i2cscan-fix
move and repeat i2c scan to fix BLE PIN
2022-10-08 17:52:32 +02:00
Thomas Göttgens
b2d753ed86 move and repeat i2c scan to fix BLE PIN 2022-10-08 17:36:39 +02:00
Thomas Göttgens
6e40102f26 - use bigger screen fonts on Wiphone
- erase oldest entry from NodeDB if it is full.
2022-10-08 17:07:16 +02:00
Ben Meadors
511fe23b8a Merge branch 'master' into ota 2022-10-08 08:22:16 -05:00
Thomas Göttgens
e433895873 Merge pull request #1773 from meshtastic/canned-messages
Fix another crash in Canned Messages
2022-10-08 15:09:58 +02:00
Thomas Göttgens
5572195af9 Fix another crash in Canned Messages 2022-10-08 14:52:21 +02:00
Thomas Göttgens
cb956cd35b Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-08 14:35:07 +02:00
Ben Meadors
b551c7738e Merge branch 'master' into ota 2022-10-08 07:28:35 -05:00
GUVWAF
3d45c4dbd8 Don't resend ACK if another module sent a response (#1772)
* strcmp returns zero if strings are equal

* Make debug message more clear

* Don't resend ACK if another module sent a response

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2022-10-08 07:27:59 -05:00
Thomas Göttgens
8681489cb7 Merge pull request #1771 from meshtastic/compass-size
Scale Compass circle to bigger screens
2022-10-08 13:22:14 +02:00
Thomas Göttgens
ed328766b2 Scale Compass circle to bigger screens 2022-10-08 12:32:48 +02:00
Thomas Göttgens
fb852ee6eb Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-08 11:25:46 +02:00
Thomas Göttgens
a6ee708b90 Merge branch 'master' into ota 2022-10-08 11:21:33 +02:00
Thomas Göttgens
c9398e7b8a - prevent crash when no messages defined
- remove debug print
2022-10-08 11:20:54 +02:00
Thomas Göttgens
b591e35442 Switch to OTA firmware 2022-10-08 11:10:29 +02:00
Thomas Göttgens
e50e15dc04 Merge pull request #1769 from meshtastic/RTC
1.0.1 RTC LIB is released on PIO Registry
2022-10-08 11:09:54 +02:00
Thomas Göttgens
d4e65d8607 1.0.1 RTC LIB is released on PIO Registry 2022-10-08 11:09:16 +02:00
Thomas Göttgens
63ced7da7c use upstream nRF52 toolkit. (TEST)
also RTC Lib 1.0.1 is finally out.
2022-10-07 20:28:20 +02:00
Thomas Göttgens
03868d05db Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-07 20:23:00 +02:00
Thomas Göttgens
186374525a Don't mix MQTT Payloads of Firmware 1.2 and 1.3/2.0 (#1767) 2022-10-07 12:54:42 -05:00
Thomas Göttgens
f116585c2a Don't mix MQTT Payloads of Firmware 1.2 and 1.3/2.0 2022-10-07 19:26:45 +02:00
Thomas Göttgens
f4945729bc Merge pull request #1766 from meshtastic/new-sounds
use F# as startup and shutdown sound triple
2022-10-07 19:16:50 +02:00
Thomas Göttgens
a3c76232c8 use F# as startup and shutdown sound triple. The existing tuuut-tut-tut was getting on my nerves 2022-10-07 19:03:49 +02:00
Thomas Göttgens
5bc41118e2 Merge pull request #1760 from meshtastic/support-rak14004
Use small font for freetext messages
2022-10-07 18:58:28 +02:00
Thomas Göttgens
9445a96b3a Merge branch 'support-rak14004' of github.com:meshtastic/Meshtastic-device 2022-10-07 18:40:51 +02:00
Thomas Göttgens
a5761069ca Finalize destination selection. Primary Channel only for now. 2022-10-07 18:40:15 +02:00
Thomas Göttgens
2d4bfe183c Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-07 16:42:29 +02:00
Ben Meadors
bf4115a80f Telemetry sensors re-map (#1765)
* Add factory erase uf2 to the release assets

* Sensors map

* Uncomment sensors
2022-10-07 08:33:07 -05:00
Ben Meadors
b2e84dfd29 Merge branch 'master' into support-rak14004 2022-10-07 06:58:08 -05:00
lewis he
004f6fa4d6 Add t-beam-s3-core onboard device support. (#1764)
* Change t-beam-s3-core pins definitions

* Add t-beam-s3-core power initialization to properly initialize the I2C device

* Add 6-axis and 3-axis sensor detection
2022-10-07 06:57:55 -05:00
Thomas Göttgens
cefd4cd647 Merge pull request #1762 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-06 23:15:59 +02:00
thebentern
fd2ae61e3e [create-pull-request] automated change 2022-10-06 20:53:47 +00:00
Thomas Göttgens
7cda61ca01 - preliminary work for node selection
- show sending screen on immediate click
2022-10-06 22:34:55 +02:00
Thomas Göttgens
98e1d52eaa Merge branch 'support-rak14004' of github.com:meshtastic/Meshtastic-device 2022-10-06 18:41:33 +02:00
Thomas Göttgens
1d09beb8a7 word wrap long input and fix compiler warnings 2022-10-06 18:40:31 +02:00
Thomas Göttgens
d44cce2928 Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-06 17:24:48 +02:00
Thomas Göttgens
51b3d4d06e Merge branch 'master' into support-rak14004 2022-10-06 17:24:33 +02:00
Thomas Göttgens
a17ddaa951 Use small font for freetext messages 2022-10-06 17:24:08 +02:00
54 changed files with 663 additions and 210 deletions

View File

@@ -224,6 +224,7 @@ jobs:
path: | path: |
release/*.uf2 release/*.uf2
release/*.elf release/*.elf
release/*.zip
retention-days: 90 retention-days: 90
build-rpi2040: build-rpi2040:
@@ -368,7 +369,7 @@ jobs:
id: version id: version
- name: Move files up - name: Move files up
run: mv -b -t ./ ./*tbeam-1*/littlefs*.bin ./*tbeam-1*/bleota.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/*.elf ./**/meshtasticd_linux_amd64 ./*native*/*device-*.sh ./*native*/*device-*.bat run: mv -b -t ./ ./*tbeam-1*/littlefs*.bin ./*tbeam-1*/bleota.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./**/meshtasticd_linux_amd64 ./*native*/*device-*.sh ./*native*/*device-*.bat
- name: Repackage in single firmware zip - name: Repackage in single firmware zip
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
@@ -377,6 +378,7 @@ jobs:
path: | path: |
./*.bin ./*.bin
./*.uf2 ./*.uf2
./firmware-*-ota.zip
./meshtasticd_linux_amd64 ./meshtasticd_linux_amd64
./device-*.sh ./device-*.sh
./device-*.bat ./device-*.bat

View File

@@ -1,7 +1,7 @@
; Common settings for ESP targes, mixin with extends = esp32_base ; Common settings for ESP targes, mixin with extends = esp32_base
[esp32_base] [esp32_base]
extends = arduino_base extends = arduino_base
platform = espressif32@^5.2.0 platform = platformio/espressif32@^5.2.0
build_src_filter = build_src_filter =
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> ${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040>
upload_speed = 921600 upload_speed = 921600

View File

@@ -1,6 +1,6 @@
[esp32s3_base] [esp32s3_base]
extends = arduino_base extends = arduino_base
platform = espressif32@^5.2.0 platform = platformio/espressif32@^5.2.0
build_src_filter = build_src_filter =
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> ${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040>
upload_speed = 961200 upload_speed = 961200

View File

@@ -1,11 +1,9 @@
[nrf52_base] [nrf52_base]
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files ; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
; platform = nordicnrf52 ;pending https://github.com/platformio/builder-framework-arduino-nrf5/pull/7 platform = platformio/nordicnrf52@^9.4.0
platform = https://github.com/meshtastic/platform-nordicnrf52.git#merge
extends = arduino_base extends = arduino_base
build_type = debug ; I'm debugging with ICE a lot now build_type = debug ; I'm debugging with ICE a lot now
; note: liboberon provides the AES256 implementation for NRF52 (though not using the hardware acceleration of the NRF52840 - FIXME)
build_flags = build_flags =
${arduino_base.build_flags} -Wno-unused-variable ${arduino_base.build_flags} -Wno-unused-variable
-Isrc/platform/nrf52 -Isrc/platform/nrf52

View File

@@ -4,7 +4,7 @@ build_flags = ${nrf52_base.build_flags}
lib_deps = lib_deps =
${arduino_base.lib_deps} ${arduino_base.lib_deps}
${environmental_base.lib_deps} ${environmental_base.lib_deps}
https://github.com/Kongduino/Adafruit_nRFCrypto.git#20fc7fdaf086bd70e901c007dd23c6e8856aec25 https://github.com/Kongduino/Adafruit_nRFCrypto.git#e31a8825ea3300b163a0a3c1ddd5de34e10e1371
; Note: By default no lora device is created for this build - it uses a simulated interface ; Note: By default no lora device is created for this build - it uses a simulated interface
[env:nrf52840dk] [env:nrf52840dk]

View File

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

View File

@@ -1,5 +1,5 @@
[stm32wl5e_base] [stm32wl5e_base]
platform = ststm32 platform = platformio/ststm32@^15.4.1
board = generic_wl5e board = generic_wl5e
framework = arduino framework = arduino
build_type = debug build_type = debug

View File

@@ -26,7 +26,9 @@ basename=firmware-$1-$VERSION
pio run --environment $1 # -v pio run --environment $1 # -v
SRCELF=.pio/build/$1/firmware.elf SRCELF=.pio/build/$1/firmware.elf
DFUPKG=.pio/build/$1/firmware.zip
cp $SRCELF $OUTDIR/$basename.elf cp $SRCELF $OUTDIR/$basename.elf
cp $DFUPKG $OUTDIR/$basename-ota.zip
echo "Generating NRF52 uf2 file" echo "Generating NRF52 uf2 file"
SRCHEX=.pio/build/$1/firmware.hex SRCHEX=.pio/build/$1/firmware.hex

View File

@@ -2,7 +2,8 @@
; https://docs.platformio.org/page/projectconf.html ; https://docs.platformio.org/page/projectconf.html
[platformio] [platformio]
default_envs = tbeam ;default_envs = tbeam
;default_envs = pico
;default_envs = tbeam-s3-core ;default_envs = tbeam-s3-core
;default_envs = tbeam0.7 ;default_envs = tbeam0.7
;default_envs = heltec-v1 ;default_envs = heltec-v1
@@ -64,6 +65,7 @@ lib_deps =
${env.lib_deps} ${env.lib_deps}
; Portduino is using meshtastic fork for now ; Portduino is using meshtastic fork for now
jgromes/RadioLib@5.4.1 jgromes/RadioLib@5.4.1
https://github.com/caveman99/SparkFun_ATECCX08a_Arduino_Library.git#008e7f9d40bad66b2f7a0074aaac05b7c424339d
build_flags = ${env.build_flags} -Os build_flags = ${env.build_flags} -Os
-DRADIOLIB_SPI_PARANOID=0 -DRADIOLIB_SPI_PARANOID=0

View File

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

View File

@@ -9,7 +9,7 @@
#define MESH_SERVICE_UUID "6ba1b218-15a8-461f-9fa8-5dcae273eafd" #define MESH_SERVICE_UUID "6ba1b218-15a8-461f-9fa8-5dcae273eafd"
#define TORADIO_UUID "f75c76d2-129e-4dad-a1dd-7866124401e7" #define TORADIO_UUID "f75c76d2-129e-4dad-a1dd-7866124401e7"
#define FROMRADIO_UUID "8ba2bcc2-ee02-4a55-a531-c525c5e454d5" #define FROMRADIO_UUID "2c55e69e-4993-11ed-b878-0242ac120002"
#define FROMNUM_UUID "ed9da18c-a800-4f66-a670-aa7547e34453" #define FROMNUM_UUID "ed9da18c-a800-4f66-a670-aa7547e34453"
// NRF52 wants these constants as byte arrays // NRF52 wants these constants as byte arrays

View File

@@ -368,8 +368,21 @@ bool Power::axpChipInit()
#ifdef HAS_PMU #ifdef HAS_PMU
TwoWire * w = NULL;
// Use macro to distinguish which wire is used by PMU
#ifdef PMU_USE_WIRE1
w = &Wire1;
#else
w = &Wire;
#endif
/**
* It is not necessary to specify the wire pin,
* just input the wire, because the wire has been initialized in main.cpp
*/
if (!PMU) { if (!PMU) {
PMU = new XPowersAXP2101(Wire, I2C_SDA, I2C_SCL); PMU = new XPowersAXP2101(*w);
if (!PMU->init()) { if (!PMU->init()) {
DEBUG_MSG("Warning: Failed to find AXP2101 power management\n"); DEBUG_MSG("Warning: Failed to find AXP2101 power management\n");
delete PMU; delete PMU;
@@ -380,7 +393,7 @@ bool Power::axpChipInit()
} }
if (!PMU) { if (!PMU) {
PMU = new XPowersAXP192(Wire, I2C_SDA, I2C_SCL); PMU = new XPowersAXP192(*w);
if (!PMU->init()) { if (!PMU->init()) {
DEBUG_MSG("Warning: Failed to find AXP192 power management\n"); DEBUG_MSG("Warning: Failed to find AXP192 power management\n");
delete PMU; delete PMU;
@@ -396,7 +409,9 @@ bool Power::axpChipInit()
* In order not to affect other devices, if the initialization of the PMU fails, Wire needs to be re-initialized once, * In order not to affect other devices, if the initialization of the PMU fails, Wire needs to be re-initialized once,
* if there are multiple devices sharing the bus. * if there are multiple devices sharing the bus.
* * */ * * */
Wire.begin(I2C_SDA, I2C_SCL); #ifndef PMU_USE_WIRE1
w->begin(I2C_SDA, I2C_SCL);
#endif
return false; return false;
} }
@@ -456,6 +471,23 @@ bool Power::axpChipInit()
PMU->setPowerChannelVoltage(XPOWERS_DCDC3, 3300); PMU->setPowerChannelVoltage(XPOWERS_DCDC3, 3300);
PMU->enablePowerOutput(XPOWERS_DCDC3); PMU->enablePowerOutput(XPOWERS_DCDC3);
/**
* ALDO2 cannot be turned off.
* It is a necessary condition for sensor communication.
* It must be turned on to properly access the sensor and screen
* It is also responsible for the power supply of PCF8563
*/
PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO2);
// 6-axis , magnetometer ,bme280 , oled screen power channel
PMU->setPowerChannelVoltage(XPOWERS_ALDO1, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO1);
// sdcard power channle
PMU->setPowerChannelVoltage(XPOWERS_BLDO1, 3300);
PMU->enablePowerOutput(XPOWERS_BLDO1);
// PMU->setPowerChannelVoltage(XPOWERS_DCDC4, 3300); // PMU->setPowerChannelVoltage(XPOWERS_DCDC4, 3300);
// PMU->enablePowerOutput(XPOWERS_DCDC4); // PMU->enablePowerOutput(XPOWERS_DCDC4);

View File

@@ -36,6 +36,7 @@ struct ToneDuration {
#define NOTE_A3 220 #define NOTE_A3 220
#define NOTE_AS3 233 #define NOTE_AS3 233
#define NOTE_B3 247 #define NOTE_B3 247
#define NOTE_CS4 277
const int DURATION_1_8 = 125; // 1/8 note const int DURATION_1_8 = 125; // 1/8 note
const int DURATION_1_4 = 250; // 1/4 note const int DURATION_1_4 = 250; // 1/4 note
@@ -65,16 +66,17 @@ void playBeep() { tone(PIN_BUZZER, NOTE_B3, DURATION_1_4); }
#endif #endif
void playStartMelody() { void playStartMelody() {
ToneDuration melody[] = {{NOTE_B3, DURATION_1_4}, ToneDuration melody[] = {{NOTE_FS3, DURATION_1_8},
{NOTE_B3, DURATION_1_8}, {NOTE_AS3, DURATION_1_8},
{NOTE_B3, DURATION_1_8}}; {NOTE_CS4, DURATION_1_4}};
playTones(melody, sizeof(melody) / sizeof(ToneDuration)); playTones(melody, sizeof(melody) / sizeof(ToneDuration));
} }
void playShutdownMelody() { void playShutdownMelody() {
ToneDuration melody[] = {{NOTE_B3, DURATION_1_4}, ToneDuration melody[] = {{NOTE_CS4, DURATION_1_8},
{NOTE_G3, DURATION_1_8}, {NOTE_AS3, DURATION_1_8},
{NOTE_D3, DURATION_1_8}}; {NOTE_FS3, DURATION_1_4}};
playTones(melody, sizeof(melody) / sizeof(ToneDuration)); playTones(melody, sizeof(melody) / sizeof(ToneDuration));
} }
#endif #endif

View File

@@ -108,6 +108,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MCP9808_ADDR 0x18 #define MCP9808_ADDR 0x18
#define INA_ADDR 0x40 #define INA_ADDR 0x40
#define INA_ADDR_ALTERNATE 0x41 #define INA_ADDR_ALTERNATE 0x41
#define QMC6310_ADDR 0x1C
#define QMI8658_ADDR 0x6B
// -----------------------------------------------------------------------------
// Security
// -----------------------------------------------------------------------------
#define ATECC608B_ADDR 0x35
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// GPS // GPS

View File

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

View File

@@ -57,7 +57,6 @@ namespace graphics
// This means the *visible* area (sh1106 can address 132, but shows 128 for example) // This means the *visible* area (sh1106 can address 132, but shows 128 for example)
#define IDLE_FRAMERATE 1 // in fps #define IDLE_FRAMERATE 1 // in fps
#define COMPASS_DIAM 44
// DEBUG // DEBUG
#define NUM_EXTRA_FRAMES 3 // text message and debug frame #define NUM_EXTRA_FRAMES 3 // text message and debug frame
@@ -98,7 +97,7 @@ static uint16_t displayWidth, displayHeight;
#define SCREEN_WIDTH displayWidth #define SCREEN_WIDTH displayWidth
#define SCREEN_HEIGHT displayHeight #define SCREEN_HEIGHT displayHeight
#if defined(USE_EINK) || defined(ILI9341_DRIVER) #if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
// The screen is bigger so use bigger fonts // The screen is bigger so use bigger fonts
#define FONT_SMALL ArialMT_Plain_16 #define FONT_SMALL ArialMT_Plain_16
#define FONT_MEDIUM ArialMT_Plain_24 #define FONT_MEDIUM ArialMT_Plain_24
@@ -669,6 +668,26 @@ static bool hasPosition(NodeInfo *n)
return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0); return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0);
} }
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 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;
}
}
return diam - 20;
};
/// We will skip one node - the one for us, so we just blindly loop over all /// We will skip one node - the one for us, so we just blindly loop over all
/// nodes /// nodes
static size_t nodeIndex; static size_t nodeIndex;
@@ -685,7 +704,7 @@ static void drawNodeHeading(OLEDDisplay *display, int16_t compassX, int16_t comp
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
arrowPoints[i]->rotate(headingRadian); arrowPoints[i]->rotate(headingRadian);
arrowPoints[i]->scale(COMPASS_DIAM * 0.6); arrowPoints[i]->scale(getCompassDiam(display) * 0.6);
arrowPoints[i]->translate(compassX, compassY); arrowPoints[i]->translate(compassX, compassY);
} }
drawLine(display, tip, tail); drawLine(display, tip, tail);
@@ -707,7 +726,7 @@ static void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t com
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
// North on compass will be negative of heading // North on compass will be negative of heading
rosePoints[i]->rotate(-myHeading); rosePoints[i]->rotate(-myHeading);
rosePoints[i]->scale(COMPASS_DIAM); rosePoints[i]->scale(getCompassDiam(display));
rosePoints[i]->translate(compassX, compassY); rosePoints[i]->translate(compassX, compassY);
} }
drawLine(display, N1, N3); drawLine(display, N1, N3);
@@ -772,7 +791,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
const char *fields[] = {username, distStr, signalStr, lastStr, NULL}; const char *fields[] = {username, distStr, signalStr, lastStr, NULL};
// coordinates for the center of the compass/circle // coordinates for the center of the compass/circle
int16_t compassX = x + SCREEN_WIDTH - COMPASS_DIAM / 2 - 5, compassY = y + SCREEN_HEIGHT / 2; int16_t compassX = x + SCREEN_WIDTH - getCompassDiam(display) / 2 - 5, compassY = y + SCREEN_HEIGHT / 2;
bool hasNodeHeading = false; bool hasNodeHeading = false;
if (ourNode && hasPosition(ourNode)) { if (ourNode && hasPosition(ourNode)) {
@@ -813,7 +832,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
// Debug info for gps lock errors // Debug info for gps lock errors
// DEBUG_MSG("ourNode %d, ourPos %d, theirPos %d\n", !!ourNode, ourNode && hasPosition(ourNode), hasPosition(node)); // DEBUG_MSG("ourNode %d, ourPos %d, theirPos %d\n", !!ourNode, ourNode && hasPosition(ourNode), hasPosition(node));
display->drawString(compassX - FONT_HEIGHT_SMALL / 4, compassY - FONT_HEIGHT_SMALL / 2, "?"); display->drawString(compassX - FONT_HEIGHT_SMALL / 4, compassY - FONT_HEIGHT_SMALL / 2, "?");
display->drawCircle(compassX, compassY, COMPASS_DIAM / 2); display->drawCircle(compassX, compassY, getCompassDiam(display) / 2);
// Must be after distStr is populated // Must be after distStr is populated
drawColumns(display, x, y, fields); drawColumns(display, x, y, fields);

View File

@@ -17,7 +17,7 @@ uint8_t read_from_14004(uint8_t reg, uint8_t *data, uint8_t length)
Wire.write(reg); Wire.write(reg);
Wire.endTransmission(); // stop transmitting Wire.endTransmission(); // stop transmitting
delay(20); delay(20);
Wire.requestFrom(CARDKB_ADDR, length); Wire.requestFrom(CARDKB_ADDR, (int)length);
int i = 0; int i = 0;
while ( Wire.available() ) // slave may send less than requested while ( Wire.available() ) // slave may send less than requested
{ {

View File

@@ -80,6 +80,12 @@ uint8_t kb_model;
// The I2C address of the RTC Module (if found) // The I2C address of the RTC Module (if found)
uint8_t rtc_found; uint8_t rtc_found;
// Keystore Chips
uint8_t keystore_found;
#ifndef ARCH_PORTDUINO
ATECCX08A atecc;
#endif
bool eink_found = true; bool eink_found = true;
uint32_t serialSinceMsec; uint32_t serialSinceMsec;
@@ -87,7 +93,7 @@ uint32_t serialSinceMsec;
bool pmu_found; bool pmu_found;
// Array map of sensor types (as array index) and i2c address as value we'll find in the i2c scan // Array map of sensor types (as array index) and i2c address as value we'll find in the i2c scan
uint8_t nodeTelemetrySensorsMap[TelemetrySensorType_LPS22+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; uint8_t nodeTelemetrySensorsMap[TelemetrySensorType_QMI8658+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
Router *router = NULL; // Users of router don't care what sort of subclass implements that API Router *router = NULL; // Users of router don't care what sort of subclass implements that API
@@ -214,6 +220,10 @@ void setup()
// router = new DSRRouter(); // router = new DSRRouter();
router = new ReliableRouter(); router = new ReliableRouter();
#ifdef I2C_SDA1
Wire1.begin(I2C_SDA1, I2C_SCL1);
#endif
#ifdef I2C_SDA #ifdef I2C_SDA
Wire.begin(I2C_SDA, I2C_SCL); Wire.begin(I2C_SDA, I2C_SCL);
#elif HAS_WIRE #elif HAS_WIRE
@@ -229,6 +239,7 @@ void setup()
delay(1); delay(1);
#endif #endif
// We need to scan here to decide if we have a screen for nodeDB.init()
scanI2Cdevice(); scanI2Cdevice();
#ifdef RAK4630 #ifdef RAK4630
// scanEInkDevice(); // scanEInkDevice();
@@ -269,6 +280,14 @@ void setup()
powerStatus->observe(&power->newStatus); powerStatus->observe(&power->newStatus);
power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration
/*
* Repeat the scanning for I2C devices after power initialization.
* Boards with an PMU need to be powered on to correctly scan to the device address, such as t-beam-s3-core
*/
if ((HW_VENDOR == HardwareModel_LILYGO_TBEAM_S3_CORE) || (HW_VENDOR == HardwareModel_TBEAM)) {
scanI2Cdevice();
}
// Init our SPI controller (must be before screen and lora) // Init our SPI controller (must be before screen and lora)
initSPI(); initSPI();
#ifndef ARCH_ESP32 #ifndef ARCH_ESP32

View File

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

View File

@@ -112,7 +112,7 @@ void MeshModule::callPlugins(const MeshPacket &mp, RxSource src)
bool rxChannelOk = !pi.boundChannel || (mp.from == 0) || bool rxChannelOk = !pi.boundChannel || (mp.from == 0) ||
!ch || !ch ||
strlen(ch->settings.name) > 0 || strlen(ch->settings.name) > 0 ||
(strcmp(ch->settings.name, pi.boundChannel) == 0); (strcasecmp(ch->settings.name, pi.boundChannel) == 0);
if (!rxChannelOk) { if (!rxChannelOk) {
// no one should have already replied! // no one should have already replied!

View File

@@ -699,11 +699,23 @@ NodeInfo *NodeDB::getOrCreateNode(NodeNum n)
if (!info) { if (!info) {
if (*numNodes >= MAX_NUM_NODES) { if (*numNodes >= MAX_NUM_NODES) {
screen->print("error: node_db full!\n"); screen->print("warning: node_db full! erasing oldest entry\n");
DEBUG_MSG("ERROR! could not create new node, node_db is full! (%d nodes)", *numNodes); // look for oldest node and erase it
return NULL; uint32_t oldest = UINT32_MAX;
int oldestIndex = -1;
for (int i = 0; i < *numNodes; i++) {
if (nodes[i].last_heard < oldest) {
oldest = nodes[i].last_heard;
oldestIndex = i;
}
}
// Shove the remaining nodes down the chain
for (int i = oldestIndex; i < *numNodes - 1; i++) {
nodes[i] = nodes[i + 1];
}
(*numNodes)--;
} }
// add the node // add the node at the end
info = &nodes[(*numNodes)++]; info = &nodes[(*numNodes)++];
// everything is missing except the nodenum // everything is missing except the nodenum

View File

@@ -79,17 +79,17 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
memset(&toRadioScratch, 0, sizeof(toRadioScratch)); memset(&toRadioScratch, 0, sizeof(toRadioScratch));
if (pb_decode_from_bytes(buf, bufLength, ToRadio_fields, &toRadioScratch)) { if (pb_decode_from_bytes(buf, bufLength, ToRadio_fields, &toRadioScratch)) {
switch (toRadioScratch.which_payload_variant) { switch (toRadioScratch.which_payload_variant) {
case ToRadio_packet_tag: case ToRadio_packet_tag:
return handleToRadioPacket(toRadioScratch.packet); return handleToRadioPacket(toRadioScratch.packet);
case ToRadio_want_config_id_tag: case ToRadio_want_config_id_tag:
config_nonce = toRadioScratch.want_config_id; config_nonce = toRadioScratch.want_config_id;
DEBUG_MSG("Client wants config, nonce=%u\n", config_nonce); DEBUG_MSG("Client wants config, nonce=%u\n", config_nonce);
handleStartConfig(); handleStartConfig();
break; break;
case ToRadio_disconnect_tag: case ToRadio_disconnect_tag:
DEBUG_MSG("Disconnecting from phone\n"); DEBUG_MSG("Disconnecting from phone\n");
close(); close();
break; break;
default: default:
// Ignore nop messages // Ignore nop messages
// DEBUG_MSG("Error: unexpected ToRadio variant\n"); // DEBUG_MSG("Error: unexpected ToRadio variant\n");
@@ -109,8 +109,10 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
* *
* Our sending states progress in the following sequence (the client app ASSUMES THIS SEQUENCE, DO NOT CHANGE IT): * Our sending states progress in the following sequence (the client app ASSUMES THIS SEQUENCE, DO NOT CHANGE IT):
* STATE_SEND_MY_INFO, // send our my info record * STATE_SEND_MY_INFO, // send our my info record
* STATE_SEND_CHANNELS
* STATE_SEND_NODEINFO, // states progress in this order as the device sends to the client * STATE_SEND_NODEINFO, // states progress in this order as the device sends to the client
STATE_SEND_CONFIG, STATE_SEND_CONFIG,
STATE_SEND_MODULE_CONFIG,
STATE_SEND_COMPLETE_ID, STATE_SEND_COMPLETE_ID,
STATE_SEND_PACKETS // send packets or debug strings STATE_SEND_PACKETS // send packets or debug strings
*/ */
@@ -128,7 +130,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
case STATE_SEND_NOTHING: case STATE_SEND_NOTHING:
DEBUG_MSG("getFromRadio=STATE_SEND_NOTHING\n"); DEBUG_MSG("getFromRadio=STATE_SEND_NOTHING\n");
break; break;
case STATE_SEND_MY_INFO: case STATE_SEND_MY_INFO:
DEBUG_MSG("getFromRadio=STATE_SEND_MY_INFO\n"); DEBUG_MSG("getFromRadio=STATE_SEND_MY_INFO\n");
// If the user has specified they don't want our node to share its location, make sure to tell the phone // If the user has specified they don't want our node to share its location, make sure to tell the phone
@@ -154,51 +156,63 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
// Stay in current state until done sending nodeinfos // Stay in current state until done sending nodeinfos
} else { } else {
DEBUG_MSG("Done sending nodeinfos\n"); DEBUG_MSG("Done sending nodeinfos\n");
state = STATE_SEND_CONFIG; state = STATE_SEND_CHANNELS;
// Go ahead and send that ID right now // Go ahead and send that ID right now
return getFromRadio(buf); return getFromRadio(buf);
} }
break; break;
} }
case STATE_SEND_CHANNELS:
DEBUG_MSG("getFromRadio=STATE_SEND_CHANNELS\n");
fromRadioScratch.which_payload_variant = FromRadio_channel_tag;
fromRadioScratch.channel = channels.getByIndex(config_state);
config_state++;
// Advance when we have sent all of our Channels
if (config_state >= MAX_NUM_CHANNELS) {
state = STATE_SEND_CONFIG;
config_state = Config_device_tag;
}
break;
case STATE_SEND_CONFIG: case STATE_SEND_CONFIG:
DEBUG_MSG("getFromRadio=STATE_SEND_CONFIG\n"); DEBUG_MSG("getFromRadio=STATE_SEND_CONFIG\n");
fromRadioScratch.which_payload_variant = FromRadio_config_tag; fromRadioScratch.which_payload_variant = FromRadio_config_tag;
switch (config_state) { switch (config_state) {
case Config_device_tag: case Config_device_tag:
fromRadioScratch.config.which_payload_variant = Config_device_tag; fromRadioScratch.config.which_payload_variant = Config_device_tag;
fromRadioScratch.config.payload_variant.device = config.device; fromRadioScratch.config.payload_variant.device = config.device;
break; break;
case Config_position_tag: case Config_position_tag:
fromRadioScratch.config.which_payload_variant = Config_position_tag; fromRadioScratch.config.which_payload_variant = Config_position_tag;
fromRadioScratch.config.payload_variant.position = config.position; fromRadioScratch.config.payload_variant.position = config.position;
break; break;
case Config_power_tag: case Config_power_tag:
fromRadioScratch.config.which_payload_variant = Config_power_tag; fromRadioScratch.config.which_payload_variant = Config_power_tag;
fromRadioScratch.config.payload_variant.power = config.power; fromRadioScratch.config.payload_variant.power = config.power;
fromRadioScratch.config.payload_variant.power.ls_secs = default_ls_secs; fromRadioScratch.config.payload_variant.power.ls_secs = default_ls_secs;
break; break;
case Config_network_tag: case Config_network_tag:
fromRadioScratch.config.which_payload_variant = Config_network_tag; fromRadioScratch.config.which_payload_variant = Config_network_tag;
fromRadioScratch.config.payload_variant.network = config.network; fromRadioScratch.config.payload_variant.network = config.network;
break; break;
case Config_display_tag: case Config_display_tag:
fromRadioScratch.config.which_payload_variant = Config_display_tag; fromRadioScratch.config.which_payload_variant = Config_display_tag;
fromRadioScratch.config.payload_variant.display = config.display; fromRadioScratch.config.payload_variant.display = config.display;
break; break;
case Config_lora_tag: case Config_lora_tag:
fromRadioScratch.config.which_payload_variant = Config_lora_tag; fromRadioScratch.config.which_payload_variant = Config_lora_tag;
fromRadioScratch.config.payload_variant.lora = config.lora; fromRadioScratch.config.payload_variant.lora = config.lora;
break; break;
case Config_bluetooth_tag: case Config_bluetooth_tag:
fromRadioScratch.config.which_payload_variant = Config_bluetooth_tag; fromRadioScratch.config.which_payload_variant = Config_bluetooth_tag;
fromRadioScratch.config.payload_variant.bluetooth = config.bluetooth; fromRadioScratch.config.payload_variant.bluetooth = config.bluetooth;
break; break;
} }
// NOTE: The phone app needs to know the ls_secs value so it can properly expect sleep behavior. // NOTE: The phone app needs to know the ls_secs value so it can properly expect sleep behavior.
// So even if we internally use 0 to represent 'use default' we still need to send the value we are // So even if we internally use 0 to represent 'use default' we still need to send the value we are
// using to the app (so that even old phone apps work with new device loads). // using to the app (so that even old phone apps work with new device loads).
config_state++; config_state++;
// Advance when we have sent all of our config objects // Advance when we have sent all of our config objects
if (config_state > Config_bluetooth_tag) { if (config_state > Config_bluetooth_tag) {
@@ -211,37 +225,37 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
DEBUG_MSG("getFromRadio=STATE_SEND_MODULECONFIG\n"); DEBUG_MSG("getFromRadio=STATE_SEND_MODULECONFIG\n");
fromRadioScratch.which_payload_variant = FromRadio_moduleConfig_tag; fromRadioScratch.which_payload_variant = FromRadio_moduleConfig_tag;
switch (config_state) { switch (config_state) {
case ModuleConfig_mqtt_tag: case ModuleConfig_mqtt_tag:
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_mqtt_tag; fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_mqtt_tag;
fromRadioScratch.moduleConfig.payload_variant.mqtt = moduleConfig.mqtt; fromRadioScratch.moduleConfig.payload_variant.mqtt = moduleConfig.mqtt;
break; break;
case ModuleConfig_serial_tag: case ModuleConfig_serial_tag:
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_serial_tag; fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_serial_tag;
fromRadioScratch.moduleConfig.payload_variant.serial = moduleConfig.serial; fromRadioScratch.moduleConfig.payload_variant.serial = moduleConfig.serial;
break; break;
case ModuleConfig_external_notification_tag: case ModuleConfig_external_notification_tag:
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_external_notification_tag; fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_external_notification_tag;
fromRadioScratch.moduleConfig.payload_variant.external_notification = moduleConfig.external_notification; fromRadioScratch.moduleConfig.payload_variant.external_notification = moduleConfig.external_notification;
break; break;
case ModuleConfig_range_test_tag: case ModuleConfig_range_test_tag:
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_range_test_tag; fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_range_test_tag;
fromRadioScratch.moduleConfig.payload_variant.range_test = moduleConfig.range_test; fromRadioScratch.moduleConfig.payload_variant.range_test = moduleConfig.range_test;
break; break;
case ModuleConfig_telemetry_tag: case ModuleConfig_telemetry_tag:
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_telemetry_tag; fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_telemetry_tag;
fromRadioScratch.moduleConfig.payload_variant.telemetry = moduleConfig.telemetry; fromRadioScratch.moduleConfig.payload_variant.telemetry = moduleConfig.telemetry;
break; break;
case ModuleConfig_canned_message_tag: case ModuleConfig_canned_message_tag:
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_canned_message_tag; fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_canned_message_tag;
fromRadioScratch.moduleConfig.payload_variant.canned_message = moduleConfig.canned_message; fromRadioScratch.moduleConfig.payload_variant.canned_message = moduleConfig.canned_message;
break; break;
} }
config_state++; config_state++;
// Advance when we have sent all of our ModuleConfig objects // Advance when we have sent all of our ModuleConfig objects
if (config_state > ModuleConfig_canned_message_tag) { if (config_state > ModuleConfig_canned_message_tag) {
state = STATE_SEND_COMPLETE_ID; state = STATE_SEND_COMPLETE_ID;
config_state = Config_device_tag; config_state = 0;
} }
break; break;
@@ -274,7 +288,8 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
if (fromRadioScratch.which_payload_variant != 0) { if (fromRadioScratch.which_payload_variant != 0) {
// Encapsulate as a FromRadio packet // 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_fields, &fromRadioScratch);
// DEBUG_MSG("encoding toPhone packet to phone variant=%d, %d bytes\n", fromRadioScratch.which_payloadVariant, numbytes);
DEBUG_MSG("encoding toPhone packet to phone variant=%d, %d bytes\n", fromRadioScratch.which_payload_variant, numbytes);
return numbytes; return numbytes;
} }
@@ -282,7 +297,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
return 0; return 0;
} }
void PhoneAPI::handleDisconnect() void PhoneAPI::handleDisconnect()
{ {
DEBUG_MSG("PhoneAPI disconnect\n"); DEBUG_MSG("PhoneAPI disconnect\n");
} }
@@ -301,26 +316,25 @@ void PhoneAPI::releasePhonePacket()
bool PhoneAPI::available() bool PhoneAPI::available()
{ {
switch (state) { switch (state) {
case STATE_SEND_NOTHING: case STATE_SEND_NOTHING:
return false; return false;
case STATE_SEND_MY_INFO: case STATE_SEND_MY_INFO:
return true; case STATE_SEND_CHANNELS:
case STATE_SEND_CONFIG: case STATE_SEND_CONFIG:
return true; case STATE_SEND_MODULECONFIG:
case STATE_SEND_MODULECONFIG: case STATE_SEND_COMPLETE_ID:
return true; return true;
case STATE_SEND_NODEINFO: case STATE_SEND_NODEINFO:
if (!nodeInfoForPhone) if (!nodeInfoForPhone)
nodeInfoForPhone = nodeDB.readNextInfo(); nodeInfoForPhone = nodeDB.readNextInfo();
return true; // Always say we have something, because we might need to advance our state machine return true; // Always say we have something, because we might need to advance our state machine
case STATE_SEND_COMPLETE_ID:
return true; case STATE_SEND_PACKETS: {
case STATE_SEND_PACKETS: { if (!packetForPhone)
if (!packetForPhone) packetForPhone = service.getForPhone();
packetForPhone = service.getForPhone(); bool hasPacket = !!packetForPhone;
bool hasPacket = !!packetForPhone; // DEBUG_MSG("available hasPacket=%d\n", hasPacket);
// DEBUG_MSG("available hasPacket=%d\n", hasPacket); return hasPacket;
return hasPacket;
} }
default: default:
assert(0); // unexpected state - FIXME, make an error code and reboot assert(0); // unexpected state - FIXME, make an error code and reboot

View File

@@ -16,13 +16,13 @@
* Eventually there should be once instance of this class for each live connection (because it has a bit of state * Eventually there should be once instance of this class for each live connection (because it has a bit of state
* for that connection) * for that connection)
*/ */
class PhoneAPI class PhoneAPI : public Observer<uint32_t> // FIXME, we shouldn't be inheriting from Observer, instead use CallbackObserver as a member
: public Observer<uint32_t> // FIXME, we shouldn't be inheriting from Observer, instead use CallbackObserver as a member
{ {
enum State { enum State {
STATE_SEND_NOTHING, // Initial state, don't send anything until the client starts asking for config STATE_SEND_NOTHING, // Initial state, don't send anything until the client starts asking for config
STATE_SEND_MY_INFO, // send our my info record STATE_SEND_MY_INFO, // send our my info record
STATE_SEND_NODEINFO, // states progress in this order as the device sends to to the client STATE_SEND_NODEINFO, // states progress in this order as the device sends to to the client
STATE_SEND_CHANNELS, // Send all channels
STATE_SEND_CONFIG, // Replacement for the old Radioconfig STATE_SEND_CONFIG, // Replacement for the old Radioconfig
STATE_SEND_MODULECONFIG, // Send Module specific config STATE_SEND_MODULECONFIG, // Send Module specific config
STATE_SEND_COMPLETE_ID, STATE_SEND_COMPLETE_ID,
@@ -31,7 +31,7 @@ class PhoneAPI
State state = STATE_SEND_NOTHING; State state = STATE_SEND_NOTHING;
int8_t config_state = Config_device_tag; uint8_t config_state = 0;
/** /**
* Each packet sent to the phone has an incrementing count * Each packet sent to the phone has an incrementing count

View File

@@ -422,7 +422,7 @@ void RadioInterface::applyModemConfig()
// If user has manually specified a channel num, then use that, otherwise generate one by hashing the name // If user has manually specified a channel num, then use that, otherwise generate one by hashing the name
const char *channelName = channels.getName(channels.getPrimaryIndex()); const char *channelName = channels.getName(channels.getPrimaryIndex());
int channel_num = loraConfig.channel_num ? loraConfig.channel_num - 1 : hash(channelName) % numChannels; int channel_num = (loraConfig.channel_num ? loraConfig.channel_num - 1 : hash(channelName)) % numChannels;
// Old frequency selection formula // Old frequency selection formula
// float freq = myRegion->freqStart + ((((myRegion->freqEnd - myRegion->freqStart) / numChannels) / 2) * channel_num); // float freq = myRegion->freqStart + ((((myRegion->freqEnd - myRegion->freqStart) / numChannels) / 2) * channel_num);

View File

@@ -58,12 +58,12 @@ bool ReliableRouter::shouldFilterReceived(MeshPacket *p)
* this way if an ACK is dropped and a packet is resent we'll ACK the resent packet * this way if an ACK is dropped and a packet is resent we'll ACK the resent packet
* make sure wasSeenRecently _doesn't_ update * make sure wasSeenRecently _doesn't_ update
* finding the channel requires decoding the packet. */ * finding the channel requires decoding the packet. */
if (p->want_ack && (p->to == getNodeNum()) && wasSeenRecently(p, false)) { if (p->want_ack && (p->to == getNodeNum()) && wasSeenRecently(p, false) && !MeshModule::currentReply) {
if (perhapsDecode(p)) { if (perhapsDecode(p)) {
sendAckNak(Routing_Error_NONE, getFrom(p), p->id, p->channel); sendAckNak(Routing_Error_NONE, getFrom(p), p->id, p->channel);
DEBUG_MSG("acking a repeated want_ack packet\n"); DEBUG_MSG("acking a repeated want_ack packet\n");
} }
} else if (wasSeenRecently(p, false) && p->hop_limit == HOP_RELIABLE) { } else if (wasSeenRecently(p, false) && p->hop_limit == HOP_RELIABLE && !MeshModule::currentReply) {
// retransmission on broadcast has hop_limit still equal to HOP_RELIABLE // retransmission on broadcast has hop_limit still equal to HOP_RELIABLE
DEBUG_MSG("Resending implicit ack for a repeated floodmsg\n"); DEBUG_MSG("Resending implicit ack for a repeated floodmsg\n");
MeshPacket *tosend = packetPool.allocCopy(*p); MeshPacket *tosend = packetPool.allocCopy(*p);
@@ -94,7 +94,7 @@ void ReliableRouter::sniffReceived(const MeshPacket *p, const Routing *c)
// - not DSR routing) // - not DSR routing)
if (p->want_ack) { if (p->want_ack) {
if (MeshModule::currentReply) if (MeshModule::currentReply)
DEBUG_MSG("Someone else has replied to this message, no need for a 2nd ack\n"); DEBUG_MSG("Some other module has replied to this message, no need for a 2nd ack\n");
else else
sendAckNak(Routing_Error_NONE, getFrom(p), p->id, p->channel); sendAckNak(Routing_Error_NONE, getFrom(p), p->id, p->channel);
} }

View File

@@ -18,6 +18,9 @@ class SinglePortModule : public MeshModule
SinglePortModule(const char *_name, PortNum _ourPortNum) : MeshModule(_name), ourPortNum(_ourPortNum) {} SinglePortModule(const char *_name, PortNum _ourPortNum) : MeshModule(_name), ourPortNum(_ourPortNum) {}
protected: protected:
uint32_t max_channel_util_percent = 40;
uint32_t polite_channel_util_percent = 25;
/** /**
* @return true if you want to receive the specified portnum * @return true if you want to receive the specified portnum
*/ */

View File

@@ -59,14 +59,12 @@ typedef struct _AdminMessage {
AdminMessage_ModuleConfigType get_module_config_request; AdminMessage_ModuleConfigType get_module_config_request;
/* Send the current Config in the response to this message. */ /* Send the current Config in the response to this message. */
ModuleConfig get_module_config_response; ModuleConfig get_module_config_response;
/* Send all channels in the response to this message */
bool get_all_channel_request;
/* Get the Canned Message Module messages in the response to this message. */ /* Get the Canned Message Module messages in the response to this message. */
bool get_canned_message_module_messages_request; bool get_canned_message_module_messages_request;
/* Get the Canned Message Module messages in the response to this message. */ /* Get the Canned Message Module messages in the response to this message. */
char get_canned_message_module_messages_response[201]; char get_canned_message_module_messages_response[201];
/* Request the node to send device metadata (firmware, protobuf version, etc) */ /* Request the node to send device metadata (firmware, protobuf version, etc) */
uint32_t get_device_metadata_request; bool get_device_metadata_request;
/* Device metadata response */ /* Device metadata response */
DeviceMetadata get_device_metadata_response; DeviceMetadata get_device_metadata_response;
/* Set the owner for this node */ /* Set the owner for this node */
@@ -94,6 +92,9 @@ typedef struct _AdminMessage {
bool confirm_set_channel; bool confirm_set_channel;
/* TODO: REPLACE */ /* TODO: REPLACE */
bool confirm_set_radio; bool confirm_set_radio;
/* Tell the node to reboot into the OTA Firmware in this many seconds (or <0 to cancel reboot)
Only Implemented for ESP32 Devices. This needs to be issued to send a new main firmware via bluetooth. */
int32_t reboot_ota_seconds;
/* This message is only supported for the simulator porduino build. /* This message is only supported for the simulator porduino build.
If received the simulator will exit successfully. */ If received the simulator will exit successfully. */
bool exit_simulator; bool exit_simulator;
@@ -136,7 +137,6 @@ extern "C" {
#define AdminMessage_get_config_response_tag 6 #define AdminMessage_get_config_response_tag 6
#define AdminMessage_get_module_config_request_tag 7 #define AdminMessage_get_module_config_request_tag 7
#define AdminMessage_get_module_config_response_tag 8 #define AdminMessage_get_module_config_response_tag 8
#define AdminMessage_get_all_channel_request_tag 9
#define AdminMessage_get_canned_message_module_messages_request_tag 10 #define AdminMessage_get_canned_message_module_messages_request_tag 10
#define AdminMessage_get_canned_message_module_messages_response_tag 11 #define AdminMessage_get_canned_message_module_messages_response_tag 11
#define AdminMessage_get_device_metadata_request_tag 12 #define AdminMessage_get_device_metadata_request_tag 12
@@ -150,6 +150,7 @@ extern "C" {
#define AdminMessage_confirm_set_module_config_tag 65 #define AdminMessage_confirm_set_module_config_tag 65
#define AdminMessage_confirm_set_channel_tag 66 #define AdminMessage_confirm_set_channel_tag 66
#define AdminMessage_confirm_set_radio_tag 67 #define AdminMessage_confirm_set_radio_tag 67
#define AdminMessage_reboot_ota_seconds_tag 95
#define AdminMessage_exit_simulator_tag 96 #define AdminMessage_exit_simulator_tag 96
#define AdminMessage_reboot_seconds_tag 97 #define AdminMessage_reboot_seconds_tag 97
#define AdminMessage_shutdown_seconds_tag 98 #define AdminMessage_shutdown_seconds_tag 98
@@ -166,10 +167,9 @@ X(a, STATIC, ONEOF, UENUM, (payload_variant,get_config_request,get_confi
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,get_config_response,get_config_response), 6) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,get_config_response,get_config_response), 6) \
X(a, STATIC, ONEOF, UENUM, (payload_variant,get_module_config_request,get_module_config_request), 7) \ X(a, STATIC, ONEOF, UENUM, (payload_variant,get_module_config_request,get_module_config_request), 7) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,get_module_config_response,get_module_config_response), 8) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,get_module_config_response,get_module_config_response), 8) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,get_all_channel_request,get_all_channel_request), 9) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,get_canned_message_module_messages_request,get_canned_message_module_messages_request), 10) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,get_canned_message_module_messages_request,get_canned_message_module_messages_request), 10) \
X(a, STATIC, ONEOF, STRING, (payload_variant,get_canned_message_module_messages_response,get_canned_message_module_messages_response), 11) \ X(a, STATIC, ONEOF, STRING, (payload_variant,get_canned_message_module_messages_response,get_canned_message_module_messages_response), 11) \
X(a, STATIC, ONEOF, UINT32, (payload_variant,get_device_metadata_request,get_device_metadata_request), 12) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,get_device_metadata_request,get_device_metadata_request), 12) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,get_device_metadata_response,get_device_metadata_response), 13) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,get_device_metadata_response,get_device_metadata_response), 13) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_owner,set_owner), 32) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_owner,set_owner), 32) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_channel,set_channel), 33) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_channel,set_channel), 33) \
@@ -180,6 +180,7 @@ X(a, STATIC, ONEOF, BOOL, (payload_variant,confirm_set_config,confirm_s
X(a, STATIC, ONEOF, BOOL, (payload_variant,confirm_set_module_config,confirm_set_module_config), 65) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,confirm_set_module_config,confirm_set_module_config), 65) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,confirm_set_channel,confirm_set_channel), 66) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,confirm_set_channel,confirm_set_channel), 66) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,confirm_set_radio,confirm_set_radio), 67) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,confirm_set_radio,confirm_set_radio), 67) \
X(a, STATIC, ONEOF, INT32, (payload_variant,reboot_ota_seconds,reboot_ota_seconds), 95) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,exit_simulator,exit_simulator), 96) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,exit_simulator,exit_simulator), 96) \
X(a, STATIC, ONEOF, INT32, (payload_variant,reboot_seconds,reboot_seconds), 97) \ X(a, STATIC, ONEOF, INT32, (payload_variant,reboot_seconds,reboot_seconds), 97) \
X(a, STATIC, ONEOF, INT32, (payload_variant,shutdown_seconds,shutdown_seconds), 98) \ X(a, STATIC, ONEOF, INT32, (payload_variant,shutdown_seconds,shutdown_seconds), 98) \

View File

@@ -4,6 +4,7 @@
#ifndef PB_MESH_PB_H_INCLUDED #ifndef PB_MESH_PB_H_INCLUDED
#define PB_MESH_PB_H_INCLUDED #define PB_MESH_PB_H_INCLUDED
#include <pb.h> #include <pb.h>
#include "channel.pb.h"
#include "config.pb.h" #include "config.pb.h"
#include "module_config.pb.h" #include "module_config.pb.h"
#include "portnums.pb.h" #include "portnums.pb.h"
@@ -652,6 +653,8 @@ typedef struct _FromRadio {
bool rebooted; bool rebooted;
/* Include module config */ /* Include module config */
ModuleConfig moduleConfig; ModuleConfig moduleConfig;
/* One packet is sent for each channel */
Channel channel;
}; };
} FromRadio; } FromRadio;
@@ -854,6 +857,7 @@ extern "C" {
#define FromRadio_config_complete_id_tag 7 #define FromRadio_config_complete_id_tag 7
#define FromRadio_rebooted_tag 8 #define FromRadio_rebooted_tag 8
#define FromRadio_moduleConfig_tag 9 #define FromRadio_moduleConfig_tag 9
#define FromRadio_channel_tag 10
#define ToRadio_packet_tag 1 #define ToRadio_packet_tag 1
#define ToRadio_peer_info_tag 2 #define ToRadio_peer_info_tag 2
#define ToRadio_want_config_id_tag 3 #define ToRadio_want_config_id_tag 3
@@ -1001,7 +1005,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,config,config), 5) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,log_record,log_record), 6) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,log_record,log_record), 6) \
X(a, STATIC, ONEOF, UINT32, (payload_variant,config_complete_id,config_complete_id), 7) \ X(a, STATIC, ONEOF, UINT32, (payload_variant,config_complete_id,config_complete_id), 7) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,rebooted,rebooted), 8) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,rebooted,rebooted), 8) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,moduleConfig,moduleConfig), 9) X(a, STATIC, ONEOF, MESSAGE, (payload_variant,moduleConfig,moduleConfig), 9) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,channel,channel), 10)
#define FromRadio_CALLBACK NULL #define FromRadio_CALLBACK NULL
#define FromRadio_DEFAULT NULL #define FromRadio_DEFAULT NULL
#define FromRadio_payload_variant_packet_MSGTYPE MeshPacket #define FromRadio_payload_variant_packet_MSGTYPE MeshPacket
@@ -1010,6 +1015,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,moduleConfig,moduleConfig),
#define FromRadio_payload_variant_config_MSGTYPE Config #define FromRadio_payload_variant_config_MSGTYPE Config
#define FromRadio_payload_variant_log_record_MSGTYPE LogRecord #define FromRadio_payload_variant_log_record_MSGTYPE LogRecord
#define FromRadio_payload_variant_moduleConfig_MSGTYPE ModuleConfig #define FromRadio_payload_variant_moduleConfig_MSGTYPE ModuleConfig
#define FromRadio_payload_variant_channel_MSGTYPE Channel
#define ToRadio_FIELDLIST(X, a) \ #define ToRadio_FIELDLIST(X, a) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,packet,packet), 1) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,packet,packet), 1) \

View File

@@ -29,7 +29,11 @@ typedef enum _TelemetrySensorType {
/* High accuracy temperature and humidity */ /* High accuracy temperature and humidity */
TelemetrySensorType_SHTC3 = 7, TelemetrySensorType_SHTC3 = 7,
/* High accuracy pressure */ /* High accuracy pressure */
TelemetrySensorType_LPS22 = 8 TelemetrySensorType_LPS22 = 8,
/* 3-Axis magnetic sensor */
TelemetrySensorType_QMC6310 = 9,
/* 6-Axis inertial measurement sensor */
TelemetrySensorType_QMI8658 = 10
} TelemetrySensorType; } TelemetrySensorType;
/* Struct definitions */ /* Struct definitions */
@@ -81,8 +85,8 @@ typedef struct _Telemetry {
/* Helper constants for enums */ /* Helper constants for enums */
#define _TelemetrySensorType_MIN TelemetrySensorType_SENSOR_UNSET #define _TelemetrySensorType_MIN TelemetrySensorType_SENSOR_UNSET
#define _TelemetrySensorType_MAX TelemetrySensorType_LPS22 #define _TelemetrySensorType_MAX TelemetrySensorType_QMI8658
#define _TelemetrySensorType_ARRAYSIZE ((TelemetrySensorType)(TelemetrySensorType_LPS22+1)) #define _TelemetrySensorType_ARRAYSIZE ((TelemetrySensorType)(TelemetrySensorType_QMI8658+1))
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -2,6 +2,9 @@
#include "Channels.h" #include "Channels.h"
#include "MeshService.h" #include "MeshService.h"
#include "NodeDB.h" #include "NodeDB.h"
#ifdef ARCH_ESP32
#include "BleOta.h"
#endif
#include "Router.h" #include "Router.h"
#include "configuration.h" #include "configuration.h"
#include "main.h" #include "main.h"
@@ -103,6 +106,21 @@ bool AdminModule::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r)
rebootAtMsec = (s < 0) ? 0 : (millis() + s * 1000); rebootAtMsec = (s < 0) ? 0 : (millis() + s * 1000);
break; break;
} }
case AdminMessage_reboot_ota_seconds_tag: {
int32_t s = r->reboot_ota_seconds;
#ifdef ARCH_ESP32
if (BleOta::getOtaAppVersion().isEmpty()) {
DEBUG_MSG("No OTA firmware available, scheduling regular reboot in %d seconds\n", s);
}else{
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);
#endif
rebootAtMsec = (s < 0) ? 0 : (millis() + s * 1000);
break;
}
case AdminMessage_shutdown_seconds_tag: { case AdminMessage_shutdown_seconds_tag: {
int32_t s = r->shutdown_seconds; int32_t s = r->shutdown_seconds;
DEBUG_MSG("Shutdown in %d seconds\n", s); DEBUG_MSG("Shutdown in %d seconds\n", s);

View File

@@ -2,6 +2,7 @@
#if HAS_SCREEN #if HAS_SCREEN
#include "CannedMessageModule.h" #include "CannedMessageModule.h"
#include "FSCommon.h" #include "FSCommon.h"
#include "NodeDB.h"
#include "MeshService.h" #include "MeshService.h"
#include "PowerFSM.h" // neede for button bypass #include "PowerFSM.h" // neede for button bypass
#include "mesh/generated/cannedmessages.pb.h" #include "mesh/generated/cannedmessages.pb.h"
@@ -10,7 +11,7 @@
#include "graphics/fonts/OLEDDisplayFontsRU.h" #include "graphics/fonts/OLEDDisplayFontsRU.h"
#endif #endif
#if defined(USE_EINK) || defined(ILI9341_DRIVER) #if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
// The screen is bigger so use bigger fonts // The screen is bigger so use bigger fonts
#define FONT_SMALL ArialMT_Plain_16 #define FONT_SMALL ArialMT_Plain_16
#define FONT_MEDIUM ArialMT_Plain_24 #define FONT_MEDIUM ArialMT_Plain_24
@@ -202,7 +203,7 @@ void CannedMessageModule::sendText(NodeNum dest, const char *message, bool wantR
p->decoded.payload.size++; p->decoded.payload.size++;
} }
DEBUG_MSG("Sending message id=%d, msg=%.*s\n", p->id, p->decoded.payload.size, p->decoded.payload.bytes); DEBUG_MSG("Sending message id=%d, dest=%x, msg=%.*s\n", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes);
service.sendToMesh(p); service.sendToMesh(p);
} }
@@ -222,25 +223,26 @@ int32_t CannedMessageModule::runOnce()
this->currentMessageIndex = -1; this->currentMessageIndex = -1;
this->freetext = ""; // clear freetext this->freetext = ""; // clear freetext
this->cursor = 0; this->cursor = 0;
this->destSelect = false;
this->notifyObservers(&e); this->notifyObservers(&e);
} else if (((this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) || (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT)) && (millis() - this->lastTouchMillis) > INACTIVATE_AFTER_MS) { } else if (((this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) || (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT)) && ((millis() - this->lastTouchMillis) > INACTIVATE_AFTER_MS)) {
// Reset module // Reset module
DEBUG_MSG("Reset due to lack of activity.\n"); DEBUG_MSG("Reset due to lack of activity.\n");
e.frameChanged = true; e.frameChanged = true;
this->currentMessageIndex = -1; this->currentMessageIndex = -1;
this->freetext = ""; // clear freetext this->freetext = ""; // clear freetext
this->cursor = 0; this->cursor = 0;
this->destSelect = false;
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE; this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
this->notifyObservers(&e); this->notifyObservers(&e);
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_SELECT) { } else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_SELECT) {
if (this->payload == CANNED_MESSAGE_RUN_STATE_FREETEXT) { if (this->payload == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
if (this->freetext.length() > 0) { if (this->freetext.length() > 0) {
sendText(NODENUM_BROADCAST, this->freetext.c_str(), true); sendText(this->dest, this->freetext.c_str(), true);
this->runState = CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE; this->runState = CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE;
} else { } else {
DEBUG_MSG("Reset message is empty.\n"); DEBUG_MSG("Reset message is empty.\n");
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE; this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
e.frameChanged = true;
} }
} else { } else {
if ((this->messagesCount > this->currentMessageIndex) && (strlen(this->messages[this->currentMessageIndex]) > 0)) { if ((this->messagesCount > this->currentMessageIndex) && (strlen(this->messages[this->currentMessageIndex]) > 0)) {
@@ -249,12 +251,13 @@ int32_t CannedMessageModule::runOnce()
} else { } else {
DEBUG_MSG("Reset message is empty.\n"); DEBUG_MSG("Reset message is empty.\n");
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE; this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
e.frameChanged = true;
} }
} }
e.frameChanged = true;
this->currentMessageIndex = -1; this->currentMessageIndex = -1;
this->freetext = ""; // clear freetext this->freetext = ""; // clear freetext
this->cursor = 0; this->cursor = 0;
this->destSelect = false;
this->notifyObservers(&e); this->notifyObservers(&e);
return 2000; return 2000;
} else if ((this->runState != CANNED_MESSAGE_RUN_STATE_FREETEXT) && (this->currentMessageIndex == -1)) { } else if ((this->runState != CANNED_MESSAGE_RUN_STATE_FREETEXT) && (this->currentMessageIndex == -1)) {
@@ -263,31 +266,69 @@ int32_t CannedMessageModule::runOnce()
e.frameChanged = true; e.frameChanged = true;
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE; this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_UP) { } else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_UP) {
this->currentMessageIndex = getPrevIndex(); if (this->messagesCount > 0) {
this->freetext = ""; // clear freetext this->currentMessageIndex = getPrevIndex();
this->cursor = 0; this->freetext = ""; // clear freetext
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE; this->cursor = 0;
DEBUG_MSG("MOVE UP (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage()); this->destSelect = false;
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
DEBUG_MSG("MOVE UP (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage());
}
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_DOWN) { } else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_DOWN) {
this->currentMessageIndex = this->getNextIndex(); if (this->messagesCount > 0) {
this->freetext = ""; // clear freetext this->currentMessageIndex = this->getNextIndex();
this->cursor = 0; this->freetext = ""; // clear freetext
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE; this->cursor = 0;
DEBUG_MSG("MOVE DOWN (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage()); this->destSelect = false;
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
DEBUG_MSG("MOVE DOWN (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage());
}
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) { } else if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
e.frameChanged = true; e.frameChanged = true;
switch (this->payload) { switch (this->payload) {
case 0xb4: // left case 0xb4: // left
if (this->cursor > 0) { if (this->destSelect){
this->cursor--; size_t numNodes = nodeDB.getNumNodes();
if(this->dest == NODENUM_BROADCAST) {
this->dest = nodeDB.getNodeNum();
}
for (unsigned int i = 0; i < numNodes; i++) {
if (nodeDB.getNodeByIndex(i)->num == this->dest) {
this->dest = (i > 0) ? nodeDB.getNodeByIndex(i-1)->num : nodeDB.getNodeByIndex(numNodes-1)->num;
break;
}
}
if(this->dest == nodeDB.getNodeNum()) {
this->dest = NODENUM_BROADCAST;
}
}else{
if (this->cursor > 0) {
this->cursor--;
}
} }
break; break;
case 0xb7: // right case 0xb7: // right
if (this->cursor < this->freetext.length()) { if (this->destSelect){
this->cursor++; size_t numNodes = nodeDB.getNumNodes();
if(this->dest == NODENUM_BROADCAST) {
this->dest = nodeDB.getNodeNum();
}
for (unsigned int i = 0; i < numNodes; i++) {
if (nodeDB.getNodeByIndex(i)->num == this->dest) {
this->dest = (i < numNodes-1) ? nodeDB.getNodeByIndex(i+1)->num : nodeDB.getNodeByIndex(0)->num;
break;
}
}
if(this->dest == nodeDB.getNodeNum()) {
this->dest = NODENUM_BROADCAST;
}
}else{
if (this->cursor < this->freetext.length()) {
this->cursor++;
}
} }
break; break;
case 8: // backspace case 0x08: // backspace
if (this->freetext.length() > 0) { if (this->freetext.length() > 0) {
if(this->cursor == this->freetext.length()) { if(this->cursor == this->freetext.length()) {
this->freetext = this->freetext.substring(0, this->freetext.length() - 1); this->freetext = this->freetext.substring(0, this->freetext.length() - 1);
@@ -297,6 +338,13 @@ int32_t CannedMessageModule::runOnce()
this->cursor--; this->cursor--;
} }
break; break;
case 0x09: // tab
if(this->destSelect) {
this->destSelect = false;
} else {
this->destSelect = true;
}
break;
default: default:
if(this->cursor == this->freetext.length()) { if(this->cursor == this->freetext.length()) {
this->freetext += this->payload; this->freetext += this->payload;
@@ -339,6 +387,19 @@ const char *CannedMessageModule::getNextMessage()
{ {
return this->messages[this->getNextIndex()]; return this->messages[this->getNextIndex()];
} }
const char* CannedMessageModule::getNodeName(NodeNum node) {
if (node == NODENUM_BROADCAST){
return "Broadcast";
}else{
NodeInfo *info = nodeDB.getNode(node);
if(info != NULL) {
return info->user.long_name;
}else{
return "Unknown";
}
}
}
bool CannedMessageModule::shouldDraw() bool CannedMessageModule::shouldDraw()
{ {
if (!moduleConfig.canned_message.enabled) { if (!moduleConfig.canned_message.enabled) {
@@ -369,6 +430,8 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
{ {
displayedNodeNum = 0; // Not currently showing a node pane displayedNodeNum = 0; // Not currently showing a node pane
char buffer[50];
if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) { if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) {
display->setTextAlignment(TEXT_ALIGN_CENTER); display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(FONT_MEDIUM); display->setFont(FONT_MEDIUM);
@@ -379,21 +442,29 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
display->drawString(10 + x, 0 + y + FONT_HEIGHT_SMALL, "Canned Message\nModule disabled."); display->drawString(10 + x, 0 + y + FONT_HEIGHT_SMALL, "Canned Message\nModule disabled.");
}else if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) { }else if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
display->setTextAlignment(TEXT_ALIGN_LEFT); display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(FONT_MEDIUM); display->setFont(FONT_SMALL);
display->drawString(0 + x, 0 + y, "To: Broadcast"); if (this->destSelect) {
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
display->setColor(BLACK);
}
display->drawStringf(0 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest));
// used chars right aligned // used chars right aligned
char buffer[9];
sprintf(buffer, "%d left", Constants_DATA_PAYLOAD_LEN - this->freetext.length()); sprintf(buffer, "%d left", Constants_DATA_PAYLOAD_LEN - this->freetext.length());
display->drawString(x + display->getWidth() - display->getStringWidth(buffer), y + 0, buffer); display->drawString(x + display->getWidth() - display->getStringWidth(buffer), y + 0, buffer);
display->drawString(0 + x, 0 + y + FONT_HEIGHT_MEDIUM, cannedMessageModule->drawWithCursor(cannedMessageModule->freetext, cannedMessageModule->cursor)); display->setColor(WHITE);
display->drawStringMaxWidth(0 + x, 0 + y + FONT_HEIGHT_SMALL, x + display->getWidth(), cannedMessageModule->drawWithCursor(cannedMessageModule->freetext, cannedMessageModule->cursor));
} else { } else {
display->setTextAlignment(TEXT_ALIGN_LEFT); if (this->messagesCount > 0) {
display->setFont(FONT_SMALL); display->setTextAlignment(TEXT_ALIGN_LEFT);
display->drawString(0 + x, 0 + y, cannedMessageModule->getPrevMessage()); display->setFont(FONT_SMALL);
display->setFont(FONT_MEDIUM); display->drawStringf(0 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest));
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL, cannedMessageModule->getCurrentMessage()); display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL, cannedMessageModule->getPrevMessage());
display->setFont(FONT_SMALL); display->fillRect(0 + x, 0 + y + FONT_HEIGHT_SMALL * 2, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
display->drawString(0 + x, 0 + y + FONT_HEIGHT_MEDIUM, cannedMessageModule->getNextMessage()); display->setColor(BLACK);
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * 2, cannedMessageModule->getCurrentMessage());
display->setColor(WHITE);
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * 3, cannedMessageModule->getNextMessage());
}
} }
} }

View File

@@ -9,7 +9,6 @@ enum cannedMessageModuleRunState
CANNED_MESSAGE_RUN_STATE_INACTIVE, CANNED_MESSAGE_RUN_STATE_INACTIVE,
CANNED_MESSAGE_RUN_STATE_ACTIVE, CANNED_MESSAGE_RUN_STATE_ACTIVE,
CANNED_MESSAGE_RUN_STATE_FREETEXT, CANNED_MESSAGE_RUN_STATE_FREETEXT,
CANNED_MESSAGE_RUN_STATE_MATRIX,
CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE, CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE,
CANNED_MESSAGE_RUN_STATE_ACTION_SELECT, CANNED_MESSAGE_RUN_STATE_ACTION_SELECT,
CANNED_MESSAGE_RUN_STATE_ACTION_UP, CANNED_MESSAGE_RUN_STATE_ACTION_UP,
@@ -36,6 +35,7 @@ class CannedMessageModule :
const char* getCurrentMessage(); const char* getCurrentMessage();
const char* getPrevMessage(); const char* getPrevMessage();
const char* getNextMessage(); const char* getNextMessage();
const char* getNodeName(NodeNum node);
bool shouldDraw(); bool shouldDraw();
void eventUp(); void eventUp();
void eventDown(); void eventDown();
@@ -74,9 +74,11 @@ class CannedMessageModule :
int currentMessageIndex = -1; int currentMessageIndex = -1;
cannedMessageModuleRunState runState = CANNED_MESSAGE_RUN_STATE_INACTIVE; cannedMessageModuleRunState runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
char payload; char payload = 0x00;
unsigned int cursor = 0; unsigned int cursor = 0;
String freetext = ""; // Text Buffer for Freetext Editor String freetext = ""; // Text Buffer for Freetext Editor
bool destSelect = false; // Freetext Editor Mode
NodeNum dest = NODENUM_BROADCAST;
char messageStore[CANNED_MESSAGE_MODULE_MESSAGES_SIZE+1]; char messageStore[CANNED_MESSAGE_MODULE_MESSAGES_SIZE+1];
char *messages[CANNED_MESSAGE_MODULE_MESSAGE_MAX_COUNT]; char *messages[CANNED_MESSAGE_MODULE_MESSAGE_MAX_COUNT];
@@ -85,4 +87,4 @@ class CannedMessageModule :
}; };
extern CannedMessageModule *cannedMessageModule; extern CannedMessageModule *cannedMessageModule;
#endif #endif

View File

@@ -144,7 +144,7 @@ int32_t PositionModule::runOnce()
if (lastGpsSend == 0 || (now - lastGpsSend) >= intervalMs) { if (lastGpsSend == 0 || (now - lastGpsSend) >= intervalMs) {
// Only send packets if the channel is less than 40% utilized. // Only send packets if the channel is less than 40% utilized.
if (airTime->channelUtilizationPercent() < 40) { if (airTime->channelUtilizationPercent() < max_channel_util_percent) {
if (node->has_position && (node->position.latitude_i != 0 || node->position.longitude_i != 0)) { if (node->has_position && (node->position.latitude_i != 0 || node->position.longitude_i != 0)) {
lastGpsSend = now; lastGpsSend = now;
@@ -165,7 +165,7 @@ int32_t PositionModule::runOnce()
} else if (config.position.position_broadcast_smart_enabled) { } else if (config.position.position_broadcast_smart_enabled) {
// Only send packets if the channel is less than 25% utilized. // Only send packets if the channel is less than 25% utilized.
if (airTime->channelUtilizationPercent() < 25) { if (airTime->channelUtilizationPercent() < polite_channel_util_percent) {
NodeInfo *node2 = service.refreshMyNodeInfo(); // should guarantee there is now a position NodeInfo *node2 = service.refreshMyNodeInfo(); // should guarantee there is now a position

View File

@@ -13,15 +13,16 @@
int32_t DeviceTelemetryModule::runOnce() int32_t DeviceTelemetryModule::runOnce()
{ {
#ifndef ARCH_PORTDUINO #ifndef ARCH_PORTDUINO
if (firstTime) { uint32_t now = millis();
// This is the first time the OSThread library has called this function, so do some setup if ((lastSentToMesh == 0 || (now - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.telemetry.device_update_interval))
firstTime = 0; && airTime->channelUtilizationPercent() < max_channel_util_percent) {
DEBUG_MSG("Device Telemetry: Initializing\n"); sendTelemetry();
lastSentToMesh = now;
} else {
// Just send to phone when it's not our time to send to mesh yet
sendTelemetry(NODENUM_BROADCAST, true);
} }
sendOurTelemetry(); return sendToPhoneIntervalMs;
// OSThread library. Multiply the preference value by 1000 to convert seconds to miliseconds
return getConfiguredOrDefaultMs(moduleConfig.telemetry.device_update_interval);
#endif #endif
} }
@@ -45,7 +46,7 @@ bool DeviceTelemetryModule::handleReceivedProtobuf(const MeshPacket &mp, Telemet
return false; // Let others look at this message also if they want return false; // Let others look at this message also if they want
} }
bool DeviceTelemetryModule::sendOurTelemetry(NodeNum dest, bool wantReplies) bool DeviceTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
{ {
Telemetry t; Telemetry t;
@@ -68,11 +69,16 @@ bool DeviceTelemetryModule::sendOurTelemetry(NodeNum dest, bool wantReplies)
MeshPacket *p = allocDataProtobuf(t); MeshPacket *p = allocDataProtobuf(t);
p->to = dest; p->to = dest;
p->decoded.want_response = wantReplies; p->decoded.want_response = false;
lastMeasurementPacket = packetPool.allocCopy(*p); lastMeasurementPacket = packetPool.allocCopy(*p);
DEBUG_MSG("Device Telemetry: Sending packet to mesh\n");
service.sendToMesh(p, RX_SRC_LOCAL, true);
nodeDB.updateTelemetry(nodeDB.getNodeNum(), t, RX_SRC_LOCAL); nodeDB.updateTelemetry(nodeDB.getNodeNum(), t, RX_SRC_LOCAL);
if (phoneOnly) {
DEBUG_MSG("Device Telemetry: Sending packet to phone\n");
service.sendToPhone(p);
} else {
DEBUG_MSG("Device Telemetry: Sending packet to mesh\n");
service.sendToMesh(p, RX_SRC_LOCAL, true);
}
return true; return true;
} }

View File

@@ -24,9 +24,10 @@ class DeviceTelemetryModule : private concurrency::OSThread, public ProtobufModu
/** /**
* Send our Telemetry into the mesh * Send our Telemetry into the mesh
*/ */
bool sendOurTelemetry(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false); bool sendTelemetry(NodeNum dest = NODENUM_BROADCAST, bool phoneOnly = false);
private: private:
bool firstTime = 1; uint32_t sendToPhoneIntervalMs = SECONDS_IN_MINUTE * 1000; // Send to phone every minute
uint32_t lastSentToMesh = 0;
const MeshPacket *lastMeasurementPacket; const MeshPacket *lastMeasurementPacket;
}; };

View File

@@ -27,7 +27,7 @@ int32_t StoreForwardModule::runOnce()
if (this->busy) { if (this->busy) {
// Only send packets if the channel is less than 25% utilized. // Only send packets if the channel is less than 25% utilized.
if (airTime->channelUtilizationPercent() < 25) { if (airTime->channelUtilizationPercent() < polite_channel_util_percent) {
// DEBUG_MSG("--- --- --- In busy loop 1 %d\n", this->packetHistoryTXQueue_index); // DEBUG_MSG("--- --- --- In busy loop 1 %d\n", this->packetHistoryTXQueue_index);
storeForwardModule->sendPayload(this->busyTo, this->packetHistoryTXQueue_index); storeForwardModule->sendPayload(this->busyTo, this->packetHistoryTXQueue_index);

View File

@@ -14,9 +14,9 @@
MQTT *mqtt; MQTT *mqtt;
String statusTopic = "msh/1/stat/"; String statusTopic = "msh/2/stat/";
String cryptTopic = "msh/1/c/"; // msh/1/c/CHANNELID/NODEID String cryptTopic = "msh/2/c/"; // msh/2/c/CHANNELID/NODEID
String jsonTopic = "msh/1/json/"; // msh/1/json/CHANNELID/NODEID String jsonTopic = "msh/2/json/"; // msh/2/json/CHANNELID/NODEID
void MQTT::mqttCallback(char *topic, byte *payload, unsigned int length) void MQTT::mqttCallback(char *topic, byte *payload, unsigned int length)
{ {

View File

@@ -0,0 +1,43 @@
#include "Arduino.h"
#include "BleOta.h"
#include <esp_ota_ops.h>
static const String MESHTASTIC_OTA_APP_PROJECT_NAME("Meshtastic-OTA");
const esp_partition_t* BleOta::findEspOtaAppPartition() {
const esp_partition_t *part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_0, nullptr);
esp_app_desc_t app_desc;
esp_err_t ret = ESP_ERROR_CHECK_WITHOUT_ABORT(esp_ota_get_partition_description(part, &app_desc));
if (ret != ESP_OK || MESHTASTIC_OTA_APP_PROJECT_NAME != app_desc.project_name) {
part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_1, nullptr);
ret = ESP_ERROR_CHECK_WITHOUT_ABORT(esp_ota_get_partition_description(part, &app_desc));
}
if (ret == ESP_OK && MESHTASTIC_OTA_APP_PROJECT_NAME == app_desc.project_name) {
return part;
} else {
return nullptr;
}
}
String BleOta::getOtaAppVersion() {
const esp_partition_t *part = findEspOtaAppPartition();
esp_app_desc_t app_desc;
esp_err_t ret = ESP_ERROR_CHECK_WITHOUT_ABORT(esp_ota_get_partition_description(part, &app_desc));
String version;
if (ret == ESP_OK) {
version = app_desc.version;
}
return version;
}
bool BleOta::switchToOtaApp() {
bool success = false;
const esp_partition_t *part = findEspOtaAppPartition();
if (part) {
success = (ESP_ERROR_CHECK_WITHOUT_ABORT(esp_ota_set_boot_partition(part)) == ESP_OK);
}
return success;
}

View File

@@ -0,0 +1,18 @@
#ifndef BLEOTA_H
#define BLEOTA_H
#include <functional>
class BleOta {
public:
explicit BleOta() {};
static String getOtaAppVersion();
static bool switchToOtaApp();
private:
String mUserAgent;
static const esp_partition_t *findEspOtaAppPartition();
};
#endif //BLEOTA_H

View File

@@ -4,6 +4,7 @@
#include "main.h" #include "main.h"
#include "nimble/NimbleBluetooth.h" #include "nimble/NimbleBluetooth.h"
#include "BleOta.h"
#include "mesh/http/WiFiAPClient.h" #include "mesh/http/WiFiAPClient.h"
#include "sleep.h" #include "sleep.h"
@@ -63,6 +64,12 @@ void esp32Setup()
preferences.putUInt("rebootCounter", rebootCounter); preferences.putUInt("rebootCounter", rebootCounter);
preferences.end(); preferences.end();
DEBUG_MSG("Number of Device Reboots: %d\n", rebootCounter); DEBUG_MSG("Number of Device Reboots: %d\n", rebootCounter);
String BLEOTA=BleOta::getOtaAppVersion();
if (BLEOTA.isEmpty()) {
DEBUG_MSG("No OTA firmware available\n");
}else{
DEBUG_MSG("OTA firmware version %s\n", BLEOTA);
}
// enableModemSleep(); // enableModemSleep();

View File

@@ -244,6 +244,9 @@ void NRF52Bluetooth::setup()
Bluefruit.Periph.setConnectCallback(onConnect); Bluefruit.Periph.setConnectCallback(onConnect);
Bluefruit.Periph.setDisconnectCallback(onDisconnect); Bluefruit.Periph.setDisconnectCallback(onDisconnect);
bledfu.setPermission(SECMODE_ENC_WITH_MITM, SECMODE_ENC_WITH_MITM);
bledfu.begin(); // Install the DFU helper
// Configure and Start the Device Information Service // Configure and Start the Device Information Service
DEBUG_MSG("Configuring the Device Information Service\n"); DEBUG_MSG("Configuring the Device Information Service\n");
bledis.setModel(optstr(HW_VERSION)); bledis.setModel(optstr(HW_VERSION));
@@ -254,7 +257,7 @@ void NRF52Bluetooth::setup()
DEBUG_MSG("Configuring the Battery Service\n"); DEBUG_MSG("Configuring the Battery Service\n");
blebas.begin(); blebas.begin();
blebas.write(0); // Unknown battery level for now blebas.write(0); // Unknown battery level for now
bledfu.begin(); // Install the DFU helper
// Setup the Heart Rate Monitor service using // Setup the Heart Rate Monitor service using
// BLEService and BLECharacteristic classes // BLEService and BLECharacteristic classes

View File

@@ -171,6 +171,8 @@ void SimRadio::onNotify(uint32_t notification)
// Packet has been sent, count it toward our TX airtime utilization. // Packet has been sent, count it toward our TX airtime utilization.
uint32_t xmitMsec = getPacketTime(txp); uint32_t xmitMsec = getPacketTime(txp);
airTime->logAirtime(TX_LOG, xmitMsec); airTime->logAirtime(TX_LOG, xmitMsec);
delay(xmitMsec); // Model the time it is busy sending
completeSending(); completeSending();
} }
} }
@@ -207,6 +209,9 @@ void SimRadio::startSend(MeshPacket * txp)
void SimRadio::startReceive(MeshPacket *p) { void SimRadio::startReceive(MeshPacket *p) {
isReceiving = true; isReceiving = true;
size_t length = getPacketLength(p);
uint32_t xmitMsec = getPacketTime(length);
delay(xmitMsec); // Model the time it is busy receiving
handleReceiveInterrupt(p); handleReceiveInterrupt(p);
} }

View File

@@ -23,6 +23,7 @@ build_flags =
-DTFT_BL=32 -DTFT_BL=32
-DSPI_FREQUENCY=40000000 -DSPI_FREQUENCY=40000000
-DSPI_READ_FREQUENCY=16000000 -DSPI_READ_FREQUENCY=16000000
-DDISABLE_ALL_LIBRARY_WARNINGS
lib_ignore = lib_ignore =
m5stack-core m5stack-core
lib_deps = lib_deps =

View File

@@ -12,8 +12,7 @@ build_flags =
lib_deps = lib_deps =
${esp32_base.lib_deps} ${esp32_base.lib_deps}
zinggjm/GxEPD2@^1.4.9 zinggjm/GxEPD2@^1.4.9
# lewisxhe/PCF8563_Library@^1.0.1 // switch to this one when it is released! lewisxhe/PCF8563_Library@^1.0.1
https://github.com/lewisxhe/PCF8563_Library.git#fe8cface109f63b5a4fb6abeaf87c6de0faa24c6
board_build.f_cpu = 240000000L board_build.f_cpu = 240000000L
upload_protocol = esptool upload_protocol = esptool
upload_port = /dev/ttyACM* upload_port = /dev/ttyACM*

View File

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

View File

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

View File

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

View File

@@ -14,6 +14,5 @@ lib_deps =
${nrf52840_base.lib_deps} ${nrf52840_base.lib_deps}
https://github.com/meshtastic/GxEPD2#afce87a97dda1ac31d8a28dc8fa7c6f55dc96a61 https://github.com/meshtastic/GxEPD2#afce87a97dda1ac31d8a28dc8fa7c6f55dc96a61
adafruit/Adafruit BusIO@^1.13.2 adafruit/Adafruit BusIO@^1.13.2
# lewisxhe/PCF8563_Library@^1.0.1 // switch to this one when it is released! lewisxhe/PCF8563_Library@^1.0.1
https://github.com/lewisxhe/PCF8563_Library.git#fe8cface109f63b5a4fb6abeaf87c6de0faa24c6
;upload_protocol = fs ;upload_protocol = fs

View File

@@ -25,5 +25,12 @@ static const uint8_t MOSI = 11;
static const uint8_t MISO = 13; static const uint8_t MISO = 13;
static const uint8_t SCK = 12; static const uint8_t SCK = 12;
#define SDMMC_CMD (35)
#define SDMMC_CLK (36)
#define SDMMC_DATA (37)
#define ACCEL_INT1 (34)
#define ACCEL_INT2 (33)
#define RTC_INT (14)
#endif /* Pins_Arduino_h */ #endif /* Pins_Arduino_h */

View File

@@ -5,7 +5,9 @@ board = tbeam-s3-core
lib_deps = lib_deps =
${esp32s3_base.lib_deps} ${esp32s3_base.lib_deps}
lewisxhe/PCF8563_Library@1.0.1
build_flags = build_flags =
${esp32s3_base.build_flags} ${esp32s3_base.build_flags}
-Ivariants/tbeam-s3-core -Ivariants/tbeam-s3-core
-DPCF8563_RTC=0x51 ;Putting definitions in variant.h does not compile correctly

View File

@@ -1,12 +1,18 @@
// #define BUTTON_NEED_PULLUP // if set we need to turn on the internal CPU pullup during sleep // #define BUTTON_NEED_PULLUP // if set we need to turn on the internal CPU pullup during sleep
#define I2C_SDA 42 #define I2C_SDA1 42 //Used for PMU management
#define I2C_SCL 41 #define I2C_SCL1 41 //Used for PMU management
#define I2C_SDA 17 //For sensors and screens
#define I2C_SCL 18 //For sensors and screens
#define BUTTON_PIN 0 // The middle button GPIO on the T-Beam S3 #define BUTTON_PIN 0 // The middle button GPIO on the T-Beam S3
//#define BUTTON_PIN_ALT 13 // Alternate GPIO for an external button if needed. Does anyone use this? It is not documented anywhere. //#define BUTTON_PIN_ALT 13 // Alternate GPIO for an external button if needed. Does anyone use this? It is not documented anywhere.
// #define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Module. // #define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Module.
#define BUTTON1_PIN 47 //Additional keys
#define LED_INVERTED 1 #define LED_INVERTED 1
// #define LED_PIN 4 // Newer tbeams (1.1) have an extra led on GPIO4 // #define LED_PIN 4 // Newer tbeams (1.1) have an extra led on GPIO4
@@ -36,6 +42,9 @@
// #define PMU_IRQ 40 // #define PMU_IRQ 40
#define HAS_AXP2101 #define HAS_AXP2101
// Specify the PMU as Wire1. In the t-beam-s3-core, the PMU enjoys a separate bus
#define PMU_USE_WIRE1
#define RF95_SCK 12 #define RF95_SCK 12
#define RF95_MISO 13 #define RF95_MISO 13
#define RF95_MOSI 11 #define RF95_MOSI 11
@@ -47,3 +56,10 @@
#define GPS_1PPS_PIN 6 #define GPS_1PPS_PIN 6
#define HAS_SDCARD //Have 3-bit SDMMC interface SD card slot
// PCF8563 RTC Module
// #define PCF8563_RTC 0x51 //Putting definitions in variant. h does not compile correctly
#define HAS_RTC 1

View File

@@ -1,4 +1,4 @@
[VERSION] [VERSION]
major = 1 major = 1
minor = 3 minor = 3
build = 42 build = 44