Compare commits

...
Author SHA1 Message Date
Ben Meadors a70d5ee9d8 Temporarily remove native AGAIN due to gather-artifacts failure 2024-09-28 15:49:37 -05:00
Thomas Göttgens a542d41ac7 rats, missed one 2024-09-28 21:59:13 +02:00
Thomas Göttgens 9513c68544 Update main_matrix.yml 2024-09-28 20:37:38 +02:00
Thomas Göttgens 448afb8345 Add C6 Target 2024-09-28 20:37:07 +02:00
Thomas Göttgens 22ecbcb046 Create build_esp32_c6.yml 2024-09-28 20:35:48 +02:00
Thomas Göttgens 7963ca6171 Merge pull request #4869 from meshtastic/t3s3-1121
Support T3S3 LR1121 variant
2024-09-28 20:13:26 +02:00
Ben Meadors 6a355616c7 Another extra 2024-09-28 13:06:01 -05:00
Ben Meadors ec23189407 Making some board levels extra for uncommon hardware 2024-09-28 13:04:50 -05:00
Thomas Göttgens 479b0856b4 use rfswitch definition and update radiolib 2024-09-28 19:07:11 +02:00
Thomas Göttgens 7289f36600 Merge branch 'master' into t3s3-1121 2024-09-28 17:51:21 +02:00
Thomas Göttgens ef1f0cb074 Merge pull request #4895 from meshtastic/4884-unset-rx
Don't process RX when region unset
2024-09-28 17:50:29 +02:00
Thomas Göttgens 1e8d089c4e yolo! 2024-09-28 16:40:00 +02:00
Thomas Göttgens 06dab4fa13 Don't process RX when region unset 2024-09-28 16:27:38 +02:00
GUVWAFandThomas Göttgens 12efedec42 Potential fix for bad Rx performance on T1000-E (#4885)
* Potential fix for bad Rx performance on T1000-E

* validate and refactor RF switching, eliminate godmode

---------

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2024-09-28 09:24:13 -05:00
Thomas Göttgens e530ceb566 Merge pull request #4692 from meshtastic/esp32-c6
First stab at ESP32-C6 support for TLora-C6
2024-09-28 14:05:42 +02:00
Thomas Göttgens da346159f7 fix overzealous pin definitions 2024-09-28 14:01:42 +02:00
Thomas Göttgens c650e7d273 finish TLora C6 Support, without bluetooth for now 2024-09-28 13:42:32 +02:00
Thomas Göttgens f3213a5b2f Merge branch 'master' into esp32-c6 2024-09-28 13:39:55 +02:00
Thomas Göttgens 1dc0cc0d05 Merge pull request #4894 from meshtastic/create-pull-request/patch
Update protobufs and classes
2024-09-28 13:39:18 +02:00
caveman99 f28f5e07b7 [create-pull-request] automated change 2024-09-28 11:38:10 +00:00
Thomas Göttgens 62c306a14b Merge branch 'master' into esp32-c6 2024-09-28 12:33:50 +02:00
Thomas Göttgens 5a2c58197b Merge pull request #4891 from meshtastic/store-n-forward
First stab at enabling store and forward for Native
2024-09-28 12:09:53 +02:00
Thomas Göttgens cc101f9cd2 run the full suite when run on master 2024-09-28 12:07:05 +02:00
Thomas Göttgens 016e1005df Merge branch 'master' into t3s3-1121 2024-09-28 11:37:42 +02:00
Jonathan Bennett 6e1aa52723 More store-n-forward on native 2024-09-28 11:37:27 +02:00
Jonathan Bennett 5ff265c196 First stab at enabling store and forward for Native 2024-09-28 11:37:27 +02:00
Thomas Göttgens 1f08401070 Merge pull request #4892 from dahanc/master
Only log "Setting DIO2 as RF switch" when doing so and fix battery level
2024-09-28 11:36:54 +02:00
Thomas Göttgens d1d6bfe693 Merge pull request #4890 from meshtastic/guard-remotehardware
Remove remote hardware from firmware release
2024-09-28 11:36:27 +02:00
Thomas Göttgens a39280e9df Merge pull request #4893 from meshtastic/softSleep
Only check hardsleep threshold if GPS softsleep is supported
2024-09-28 11:35:57 +02:00
GUVWAF 48fa9f2242 Only check threshold if GPS softsleep is supported 2024-09-28 09:34:37 +02:00
David Huang 7f59cb54ef Instead of having LipoBatteryLevel forward requests to AnalogBatteryLevel if there's no Lipo sensor, just have lipoInit return false. The forwarding didn't work because it never called analogInit. 2024-09-27 23:35:57 -05:00
David Huang 36a66df923 Don't log "Setting DIO2 as RF switch" unless we're actually going to do it. Also, if there's an error setting DIO2, log the error code. 2024-09-27 21:53:13 -05:00
Ben Meadors 8efc15f4d9 Ignore seen phoneapi packets (#4888)
* Ignore PhoneAPI packet if it's been seen

* ignoramus

* Also keep track of the last 20 packet IDs

* Fill

* Make this match the nimble one

* Add the log too

* Ignore zero ID packets

* Remove message entirely

* TRunkt
2024-09-27 20:09:53 -05:00
Ben Meadors 884e3f2e35 Remove remote hardware from release 2024-09-27 20:03:51 -05:00
Ken Piper 0e0811eccd Implement GPIO pin allowlist (#4882) 2024-09-27 19:31:05 -05:00
Jonathan BennettandBen Meadors fd1b68513a Add sx126x_ant_sw for Native (#4887)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-09-27 19:29:44 -05:00
Thomas Göttgens 2798946176 Merge branch 'master' into t3s3-1121 2024-09-27 22:59:06 +02:00
Thomas Göttgens 4ee1ae429b Merge branch 'master' into esp32-c6 2024-09-27 22:58:46 +02:00
Thomas Göttgens 482361b252 Fix CAD IRQ setting
credited to @GUVWAF
2024-09-27 22:56:42 +02:00
Thomas Göttgens cb1cf055b1 Merge branch 'master' into esp32-c6 2024-09-27 22:51:29 +02:00
Thomas Göttgens 6c2e60d415 Merge branch 'master' into t3s3-1121 2024-09-27 22:22:42 +02:00
Jonathan Bennett ef223b1195 use delete[] to avoid leaking memory (#4883) 2024-09-27 14:55:55 -05:00
Thomas Göttgens ae14ca7870 the name is somewhat misleading 2024-09-27 10:42:27 +02:00
Thomas Göttgens 747046d335 nope 2024-09-27 10:37:15 +02:00
Thomas Göttgens e02a7d1c68 test if quick is working at all 2024-09-27 10:36:00 +02:00
Thomas Göttgens bdb998c763 pick either setup or setup-quick as valid 2024-09-27 10:33:16 +02:00
Thomas Göttgens c35d780236 only randominze for at least 3 elements 2024-09-27 10:27:57 +02:00
Thomas Göttgens 39febad630 only sample a few builds for CI runs 2024-09-27 10:25:37 +02:00
Thomas Göttgens 40932ea06c update ci builder to include a 'quick' command line option that only outputs 3 random devices or check targets 2024-09-27 10:21:34 +02:00
Thomas Göttgens f37b88b55e Merge pull request #4880 from meshtastic/radiolib-crc
Update radiolib, fixes CRC bug on SX127x and improves LR11xx support
2024-09-27 10:19:06 +02:00
Thomas Göttgens 743fc2e812 Update radiolib, fixes CRC bug on SX127x and improves LR11xx support 2024-09-27 09:07:14 +02:00
Ben Meadors 30356dcd97 Retroactive trunkinate 2024-09-26 19:46:17 -05:00
Jonathan Bennett 5f6d9c3e27 Add pkc test (#4878)
* Add a second delay() to get the unit tests running on Rak4631

* Add test_PKC_Decrypt

* Remove cruft from test case
2024-09-26 19:33:08 -05:00
4794cdb120 Fix (some ?) memory alignment issues on the crypto part - resulting in crashes or strange behavior (#4867)
* Replace multiple potentially non aligned pointer dereference (#4855)
First step to fix some Crypto crashes or strange behaviors

* Makes the two Crypto byte buffers aligned (#4855)
Fix #4855, and probably multiple Crypto problems depending on hardware

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: GUVWAF <78759985+GUVWAF@users.noreply.github.com>
2024-09-26 17:44:11 -05:00
Thomas Göttgens a32233bb92 fixa de typo too 2024-09-26 12:15:37 +02:00
Thomas Göttgens fff2e435b5 Merge branch 'master' into t3s3-1121 2024-09-26 12:13:45 +02:00
Thomas Göttgens 8f84a96b69 refactor: typo fix in macro definition 2024-09-26 12:12:08 +02:00
Thomas Göttgens 11c17ec78c oh well 2024-09-26 11:39:35 +02:00
Thomas Göttgens b4bdf604f5 tryfix 2024-09-26 11:08:49 +02:00
Thomas Göttgens 833d7f65bc fix toolchains between old and new ESP32 2024-09-26 10:18:45 +02:00
Ben Meadors 9bebad2dbe Trunkt 2024-09-25 19:54:14 -05:00
Szetya 14019f2afa Update WaypointModule.cpp (#4870)
In INVERTED display mode, the compass ring was not visible.
2024-09-25 19:09:27 -05:00
Thomas Göttgens 12481b568a fix a lot of nuisances reported by cppcheck (#4872)
* fix a lot of nuisances reported by cppcheck

* fix portduino
2024-09-25 19:09:06 -05:00
Thomas Göttgens 3072b2a444 Merge branch 'master' into esp32-c6 2024-09-26 00:20:00 +02:00
Thomas Göttgens 5c77e29d66 Merge branch 'master' into t3s3-1121 2024-09-26 00:17:41 +02:00
Thomas Göttgens 118809fbfc Account for size of Envelope when allocating buffer. (#4819)
* Account for size of Envelope when allocating buffer.

INFO  | 09:29:20 568 [mqtt] Subscribing to msh/2/e/LongFast/+
INFO  | 09:29:20 568 [mqtt] Subscribing to msh/2/json/LongFast/+
INFO  | 09:29:20 568 [mqtt] Subscribing to msh/2/e/PKI/+
DEBUG | 09:29:20 568 [mqtt] Publishing enqueued MQTT message
ERROR | 09:29:20 568 [mqtt] Panic: can't encode protobuf reason='bytes size exceeded'

assert failed: size_t pb_encode_to_bytes(uint8_t*, size_t, const pb_msgdesc_t*, const void*) mesh-pb-constants.cpp:18 (0)

* save some mem
2024-09-25 17:13:04 -05:00
Ben Meadors baf9cf5a59 Encapsulate RadioLibInterface receive IRQ logic (#4866)
* Encapsulate RadioLibInterface receive IRQ logic

* More concise

* Trunk
2024-09-25 16:19:18 -05:00
Ben Meadors 51e4b364b0 Trunk things 2024-09-25 16:18:45 -05:00
Thomas Göttgens 581686c7b7 Merge pull request #4780 from augustozanellato/detsensor_broadcast_changes
DetectionSensor: more flexible triggering
2024-09-25 22:48:57 +02:00
Ben Meadors 3a2fa118a2 Merge branch 'master' into detsensor_broadcast_changes 2024-09-25 13:57:49 -05:00
Ben Meadors ac5edf867c Create SECURITY.md (#4868) 2024-09-25 13:55:04 -05:00
Thomas Göttgens d4e8452c60 Tbeams have no ADC (#4871) 2024-09-25 13:51:11 -05:00
Ben Meadors 4128d75ad4 IS_ONE_OF macro to make long chains of conditions more concise and easy to follow (#4860)
* Is one of macro

* Moar

* Whoops

* Trunk

* isOneOf function backed macro
2024-09-25 13:50:00 -05:00
Augusto Zanellato ed4527cfa5 address review comments 2024-09-25 20:02:22 +02:00
Thomas Göttgens 26112ba001 Support T3S3 LR1121 variant 2024-09-25 18:56:17 +02:00
Ben Meadors 9dd769586f Version 2024-09-25 08:40:33 -05:00
Ben Meadors 6e1616375e Trunk update 2024-09-25 07:25:45 -05:00
Ben Meadors a7c379961a New detection sensor trigger type value 2024-09-25 07:01:15 -05:00
Ben Meadors 02d9d8b76c Merge branch 'master' into detsensor_broadcast_changes 2024-09-25 06:30:09 -05:00
todd-herbert d1138d51e5 Wrangle module frames with I2C keyboard (#4817)
* Only suppress UI nav if module using keyboard input

* CardKB combo to dismiss text message and waypoint
Currently assigned to Fn + Delete
2024-09-25 06:27:04 -05:00
Ben Meadors 31e952c72e Merge branch 'master' into detsensor_broadcast_changes 2024-09-25 06:26:14 -05:00
github-actions[bot]andthebentern 9d7938f570 [create-pull-request] automated change (#4865)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-09-25 06:25:56 -05:00
DavidandBen Meadors 9456c42fc0 Refactor AccelerometerThread.h (#4831)
* Initial upload

* Tidy up

* Update ICM20948Sensor.cpp

* Update AccelerometerThread.h

* Initial upload

* Tidy up

* Update ICM20948Sensor.cpp

* Update AccelerometerThread.h

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-09-25 06:25:31 -05:00
DavidandBen Meadors 40b3dbaa70 Add MAX17048 lipo fuel gauge (#4851)
* Initial commit

* Update MAX17048Sensor.cpp

* Update EnvironmentTelemetry.cpp

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-09-25 05:34:53 -05:00
Jonathan Bennett 1129c92974 Add a second delay() to get the unit tests running on Rak4631 (#4862) 2024-09-25 05:31:29 -05:00
dylanliandTom Fifield 1293c5cdd4 Support for Seeed XIAO S3 Board (#4850)
* feat: add seeed-xiao-s3 board defination and pins defination

* chore:  add SEEED XIAO S3 into mesh pb

* fix: fix trunk fmt check failed

* Trunk fmt variant.h

* Restore automatically generated file

---------

Co-authored-by: Tom Fifield <tom@tomfifield.net>
2024-09-25 18:27:14 +08:00
Thomas Göttgens bebd2bb9e0 Merge pull request #4863 from meshtastic/create-pull-request/patch
Update protobufs and classes
2024-09-25 10:29:27 +02:00
caveman99 f73aa8aa82 [create-pull-request] automated change 2024-09-25 08:28:33 +00:00
Ben Meadors c50df710ba Also put this back 2024-09-24 20:12:42 -05:00
Thomas Göttgens 65104d5d8c fix #4844 (#4859) 2024-09-24 16:51:07 -05:00
Augusto Zanellato 881f133021 Merge branch 'master' into detsensor_broadcast_changes 2024-09-24 23:00:35 +02:00
Ben Meadors 10c51d8a05 Put this back 2024-09-24 15:44:16 -05:00
Ben Meadors 453b3a59b2 python3 ref 2024-09-24 15:24:08 -05:00
Ben Meadors 67fd4b64af Actual ref 2024-09-24 15:20:05 -05:00
Ben Meadors 1d0013918b master ref 2024-09-24 15:15:55 -05:00
Ben Meadors cac640ea97 Meshtestic submodule update 2024-09-24 14:57:20 -05:00
Ben Meadors e7569838c7 Bin path 2024-09-24 14:32:20 -05:00
Ben Meadors 64b2bf5f93 Checkout should handle this but oh well 2024-09-24 14:18:19 -05:00
Ben Meadors d6a008500a Who chose that ridiculous name anyway?! 2024-09-24 14:05:12 -05:00
Ben Meadors a9d636c025 Consolidate commands 2024-09-24 14:02:12 -05:00
Ben Meadors 292027f40f Setup node 2024-09-24 13:57:53 -05:00
Ben Meadors 3c126212d5 PIO script 2024-09-24 13:45:02 -05:00
Ben Meadors 9710ac79d3 Pipargs 2024-09-24 13:37:40 -05:00
Ben Meadors f2801a660b Update tests.yml 2024-09-24 13:33:51 -05:00
Ben Meadors 4d269501dd No args 2024-09-24 13:30:26 -05:00
Ben Meadors 752192b09a pipx 2024-09-24 13:27:13 -05:00
Ben Meadors f8f9329529 pip3 2024-09-24 13:16:24 -05:00
github-actions[bot]andthebentern c3e53d916d [create-pull-request] automated change (#4858)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-09-24 13:04:52 -05:00
Ben Meadors c679932248 Setup python 2024-09-24 12:58:41 -05:00
Ben Meadors 5488c8f579 Got the runner labels backwards 2024-09-24 12:54:04 -05:00
Ben Meadors 6c488fe816 Ony run on test runner label 2024-09-24 12:43:39 -05:00
Ben Meadors 771cb52616 Remove amd64 2024-09-24 10:52:46 -05:00
Ben Meadors 10869ea10a Don't wait for after-checks 2024-09-24 09:10:29 -05:00
Ben Meadors e4d0e38f37 Remove native and add v4 back 2024-09-24 08:25:25 -05:00
Ben Meadors d7badcc9cb Don't run checks on workflow_dispatch 2024-09-24 07:17:38 -05:00
Ben Meadors 4fbf666cd9 Try v3 2024-09-24 07:12:43 -05:00
Tom Fifield adb094ebc9 Remove old comments from main (#4849)
These comments were circa 4 years old. Remove them.
2024-09-24 06:08:32 -05:00
Tom FifieldandKen McGuire b709d47832 Fix Ublox M10 Setup (#4842)
There is no EXTINT pin available on the Tdeck, which uses
the Ublox M10 GPS. Therefore our previous hack to use that pin
makes the GPS not work. That workaround was implemented to
fix sleep issues which have now since been fixed with the
state machine.

This patch restores the state prior to the hack, which is
known-working.

Additionaly, it was discovered that M10s hate it when you
try and save to non-extistent eeprom/SPI flash.

This patch creates a new SAVE command for the M10 that fixes
this issue.

Many thanks to @MisterC925 whose report and testing was
essential for this fix.

fixes https://github.com/meshtastic/firmware/issues/4625

Co-authored-by: Ken McGuire <kenm@paonia.com>
2024-09-24 05:50:03 -05:00
Augusto Zanellato 01d42d4728 Merge branch 'master' into detsensor_broadcast_changes 2024-09-24 11:53:41 +02:00
Augusto Zanellato ce480ae626 fix comment style 2024-09-24 11:16:04 +02:00
Augusto Zanellato 139686d639 bump protobufs 2024-09-24 11:11:16 +02:00
Jason Murray 4fde1ca2a8 chomp trailing newline (#4848) 2024-09-24 16:27:46 +08:00
Jason Murray c72612d826 sed doesn't like newlines (#4847)
* sed doesn't like newlines

* fold remove-debug-flags block

* PATH is a system env var

* Runners don't like rm -f ${workspace path}
2024-09-24 15:41:40 +08:00
Tom Fifield 682133501a Syntax fix for github action (#4846)
https://docs.github.com/en/actions/sharing-automations/creating-actions/metadata-syntax-for-github-actions#runs-for-composite-actions
2024-09-24 14:49:01 +08:00
Jason Murray b4c09ace23 Consolidate variant build steps (#4820)
* poc: consolidate variant build steps

* use build-variant action

* only checkout once and clean up after run

* checkout before local action
2024-09-24 13:47:31 +08:00
Jonathan Bennett c39d270f40 Build message in printBytes, to not spam BLE log (#4843) 2024-09-24 12:41:28 +08:00
Tom Fifield 428a567078 Wire 1 is PIN_WIRE1_SDA (#4840)
Based on #4745, PIN_WIRE1_SDA is the 'second' wire interface.

This pach amends the check to determine whether a device has two
wire interfaces should use PIN_WIRE1_SDA, rather than PIN_WIRE_SDA.
2024-09-23 19:16:44 -05:00
Ben Meadors 0ad1f776ae Manually regen protos for now 2024-09-23 18:53:01 -05:00
Ben Meadors e78c706999 Fix RAK4631 accelerometer (#4837) 2024-09-23 18:40:54 -05:00
Ben Meadors c442cd7267 Remove some straggler now 2024-09-23 15:53:42 -05:00
Ben Meadors 9cbabb0468 Teardown bluetooth phoneAPI better and fix client notification issue (#4834)
* Teardown bluetooth phoneAPI better and fix client notification issue

* Fix client notification draining
2024-09-23 15:51:05 -05:00
Jonathan Bennett 9a7a4d3814 Check for null before printing debug (#4835) 2024-09-23 13:56:26 -05:00
Jonathan BennettandThomas Göttgens fa1cc59841 Rename message length headers and set payload max to 255 (#4827)
* Rename message length headers and set payload max to 255

* Add MESHTASTIC_PKC_OVERHEAD

* compare to MESHTASTIC_HEADER_LENGTH

---------

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2024-09-23 09:20:32 -05:00
Augusto Zanellato d4dc4dec76 Merge branch 'master' into detsensor_broadcast_changes 2024-09-23 16:20:20 +02:00
Augusto Zanellato be01c18c74 DetectionSensor: more flexible triggering 2024-09-23 16:15:44 +02:00
Ben MeadorsandTom Fifield e8829b8f52 Refactor and consolidate time window logic (#4826)
* Refactor and consolidate windowing logic

* Trunk

* Fixes

* More

* Fix braces and remove unused now variables.

There was a brace in src/mesh/RadioLibInterface.cpp that was breaking
compile on some architectures.

Additionally, there were some brace errors in
src/modules/Telemetry/AirQualityTelemetry.cpp
src/modules/Telemetry/EnvironmentTelemetry.cpp
src/mesh/wifi/WiFiAPClient.cpp

Move throttle include in WifiAPClient.cpp to top.

Add Default.h to sleep.cpp

rest of files just remove unused now variables.

* Remove a couple more meows

---------

Co-authored-by: Tom Fifield <tom@tomfifield.net>
2024-09-23 08:58:14 -05:00
Thomas Göttgens 1afd61698b Merge pull request #4745 from todd-herbert/t114-i2c
I2C for Heltec Mesh Node T114
2024-09-23 15:45:35 +02:00
Jason MurrayandTom Fifield 3ff9398b92 Revert "Update classes on protobufs update" (#4824)
* Revert "Update classes on protobufs update"

* remove quotes to fix trunk.

---------

Co-authored-by: Tom Fifield <tom@tomfifield.net>
2024-09-23 20:34:19 +08:00
Todd Herbert 76900555e8 Swap SDA and SCL
SDA=P0.16, SCL=P0.13
2024-09-24 00:25:43 +12:00
Todd Herbert 1487ca2a30 Tidier macros 2024-09-24 00:25:43 +12:00
Todd Herbert f960164c0e Add I2C bus to Heltec T114 header pins
SDA: P0.13
SCL: P0.16

Uses bus 1, leaving bus 0 routed to the unpopulated footprint for the RTC (general future-proofing)
2024-09-24 00:25:43 +12:00
Todd Herbert 11598beb16 Implement optional second I2C bus for NRF52840
Enabled at compile-time if WIRE_INFERFACES_COUNT defined as 2
2024-09-24 00:25:43 +12:00
Tom Fifield 1f8aa1efc7 Minor fix (#4666)
* Minor fixes

It turns out setting a map value with the index notation causes
an lookup that can be avoided with emplace. Apply this to one line in
the StoreForward module.

Fix also Cppcheck-determined highly minor performance increase by
passing gpiochipname as a const reference :)

The amount of cycles used on this laptop while learning about these
callouts from cppcheck is unlikely to ever be more than the cycles
saved by the fixes ;)

* Update PortduinoGlue.cpp
2024-09-23 18:22:06 +08:00
Jonathan Bennett 18aac0ba25 Consider the LoRa header when checking packet length 2024-09-22 16:09:46 -05:00
Tom FifieldandBen Meadors 2e24d244be Make Ublox code more readable (#4727)
* Simplify Ublox code

Ublox comes in a myriad of versions and settings. Presently our
configuration code does a lot of branching based on versions being
or not being present.

This patch adds version detection earlier in the piece and branches
on the set gnssModel instead to create separate setup methods for Ublox 6,
Ublox 7/8/9, and Ublox10.

Additionally, adds a macro to make the code much shorter and more
readable.

* Make trunk happy

* Make trunk happy

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-09-22 10:00:32 -05:00
Tom Fifield 7db98ca1da Revert "Consolidate variant build steps (#4806)" (#4816)
This reverts commit 9f8d86cb25.
2024-09-22 19:39:35 +08:00
Jason Murray 9f8d86cb25 Consolidate variant build steps (#4806)
* poc: consolidate variant build steps

* use build-variant action

* only checkout once and clean up after run
2024-09-22 19:22:00 +08:00
2ff0af55b1 [Board] DIY "t-energy-s3_e22" (#4782)
* New variant "t-energy-s3_e22"

- Lilygo T-Energy-S3
- NanoVHF "Mesh-v1.06-TTGO-T18" board
- Ebyte E22 Series

* add board_level = extra

* Update variant.h

---------

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
Co-authored-by: Tom Fifield <tom@tomfifield.net>
2024-09-22 14:47:49 +08:00
Ben Meadors 51af747508 CI fixes 2024-09-21 20:53:23 -05:00
Ben Meadors 893bbe09d1 Hopefully extract and commit to meshtastic.github.io 2024-09-21 16:34:26 -05:00
Jonathan Bennett d21087f639 Update platform-native to pick up portduino crash fix (#4807) 2024-09-21 16:17:30 -05:00
Thomas Göttgens 01203eb854 Merge pull request #4805 from scruplelesswizard/update-classes-on-protobuf-update
Update classes on protobufs update
2024-09-21 21:46:32 +02:00
Jason Murray 2072ebd196 meshtastic/ is a test suite; protobufs/ contains protobufs; 2024-09-21 09:58:28 -07:00
Jason Murray 202699239f feat: trigger class update when protobufs are changed 2024-09-21 07:51:09 -07:00
Thomas Göttgens 906b0233d2 Merge pull request #4801 from meshtastic/heltec-wireless-bridge
heltec-wireless-bridge
2024-09-21 16:15:28 +02:00
Thomas Göttgens d584031d10 Merge pull request #4804 from meshtastic/create-pull-request/patch
Update protobufs and classes
2024-09-21 15:16:52 +02:00
thebentern f324ab7de7 [create-pull-request] automated change 2024-09-21 15:16:31 +02:00
todd-herbert 54f56438da Re-order doDeepSleep (#4802)
Make sure PMU sleep takes place before I2C ends
2024-09-21 07:59:17 -05:00
Thomas Göttgens e6c7c80b3f Raspberry Pico2 - needs protos 2024-09-21 14:50:19 +02:00
dependabot[bot] c053c7d9ae Bump pnpm/action-setup from 2 to 4 in /.github/workflows (#4798)
Bumps [pnpm/action-setup](https://github.com/pnpm/action-setup) from 2 to 4.
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/v2...v4)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-21 06:13:09 -05:00
github-actions[bot]andthebentern 953beb56b1 [create-pull-request] automated change (#4789)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-09-21 06:12:05 -05:00
dependabot[bot] acd044fdea Bump meshtestic from 31ee3d9 to 37245b3 (#4799)
Bumps [meshtestic](https://github.com/meshtastic/meshTestic) from `31ee3d9` to `37245b3`.
- [Commits](https://github.com/meshtastic/meshTestic/compare/31ee3d90c8bef61e835c3271be2c7cda8c4a5cc2...37245b3d612a9272f546bbb092837bafdad46bc2)

---
updated-dependencies:
- dependency-name: meshtestic
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-21 06:11:32 -05:00
Tom FifieldandBen Meadors de706523f5 Actions: Semgrep Images have moved from returntocorp to semgrep (#4774)
https://hub.docker.com/r/returntocorp/semgrep notes: "We've moved!
 Official Docker images for Semgrep now available at semgrep/semgrep."

Patch updates our CI workflow for these images.

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-09-21 06:10:59 -05:00
Thomas Göttgens 52cef05c70 heltec-wireless-bridge
requires Proto PR first
2024-09-21 12:42:51 +02:00
dependabot[bot] 6490cadd35 Bump docker/build-push-action from 5 to 6 in /.github/workflows (#4800) 2024-09-21 09:30:36 +00:00
Thomas Göttgens 8e5928276b update pin definitions
update toolchain
enable telemetry
fix compilation
2024-09-21 11:27:14 +02:00
Thomas Göttgens 5dcaceccdd Merge branch 'esp32-c6' of github.com:meshtastic/firmware into esp32-c6 2024-09-21 11:24:58 +02:00
Thomas Göttgens f1cf2bf413 First stab at ESP32-C6 support for TLora-C6 2024-09-21 11:24:52 +02:00
dependabot[bot] 3882841283 Bump peter-evans/create-pull-request from 6 to 7 in /.github/workflows (#4797) 2024-09-21 08:17:31 +00:00
Tom Fifield 74e6470439 fix dependabot syntax (#4795)
* fix dependabot syntax

* Update dependabot.yml

* Update dependabot.yml
2024-09-21 14:20:30 +08:00
Tom Fifield dca711ac24 Merge pull request #4790 from scruplelesswizard/master
Enable Dependabot
2024-09-21 12:22:11 +08:00
Jason Murray 7368cb99dc chore: trunk fmt 2024-09-20 19:40:36 -07:00
Jason Murray ec848bab52 Enable Dependabot 2024-09-21 09:40:56 +08:00
Jason Murray ed13105aec set title for version bump PR (#4791) 2024-09-20 20:30:49 -05:00
Jason Murray c2272ce5a1 set title for protobufs bump PR (#4792) 2024-09-20 20:30:32 -05:00
Thomas Göttgens 1bca8de042 Merge branch 'esp32-c6' of github.com:meshtastic/firmware into esp32-c6 2024-09-20 19:37:51 +02:00
Thomas Göttgens 6ffdc9875b First stab at ESP32-C6 support for TLora-C6 2024-09-20 19:37:47 +02:00
Thomas Göttgens b84cf55659 Merge branch 'esp32-c6' of github.com:meshtastic/firmware into esp32-c6 2024-09-20 19:37:24 +02:00
Thomas Göttgens ea6f6c3668 First stab at ESP32-C6 support for TLora-C6 2024-09-16 14:25:17 +02:00
Thomas Göttgens 9527874815 First stab at ESP32-C6 support for TLora-C6 2024-09-12 22:42:10 +02:00
193 changed files with 3641 additions and 1417 deletions
+3 -6
View File
@@ -13,16 +13,13 @@
},
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools",
"platformio.platformio-ide",
]
"extensions": ["ms-vscode.cpptools", "platformio.platformio-ide"]
}
},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [ 4403 ],
"forwardPorts": [4403],
// Run commands to prepare the container for use
"postCreateCommand": ".devcontainer/setup.sh",
"postCreateCommand": ".devcontainer/setup.sh"
}
+1 -1
View File
@@ -1,3 +1,3 @@
#!/usr/bin/env sh
git submodule update --init
git submodule update --init
+90
View File
@@ -0,0 +1,90 @@
name: Setup Build Variant Composite Action
description: Variant build actions for Meshtastic Platform IO steps
inputs:
board:
description: The board to build for
required: true
github_token:
description: GitHub token
required: true
build-script-path:
description: Path to the build script
required: true
remove-debug-flags:
description: A space separated list of files to remove debug flags from
required: false
default: ""
ota-firmware-source:
description: The OTA firmware file to pull
required: false
default: ""
ota-firmware-target:
description: The target path to store the OTA firmware file
required: false
default: ""
artifact-paths:
description: A newline separated list of paths to store as artifacts
required: false
default: ""
include-web-ui:
description: Include the web UI in the build
required: false
default: "false"
runs:
using: composite
steps:
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Pull web ui
if: inputs.include-web-ui == 'true'
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/web
file: build.tar
target: build.tar
token: ${{ inputs.github_token }}
- name: Unpack web ui
if: inputs.include-web-ui == 'true'
shell: bash
run: |
tar -xf build.tar -C data/static
rm build.tar
- name: Remove debug flags for release
shell: bash
if: inputs.remove-debug-flags != ''
run: |
for INI_FILE in ${{ inputs.remove-debug-flags }}; do
sed -i '/DDEBUG_HEAP/d' ${INI_FILE}
done
- name: Build ${{ inputs.board }}
shell: bash
run: ${{ inputs.build-script-path }} ${{ inputs.board }}
- name: Pull OTA Firmware
if: inputs.ota-firmware-source != '' && inputs.ota-firmware-target != ''
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/firmware-ota
file: ${{ inputs.ota-firmware-source }}
target: ${{ inputs.ota-firmware-target }}
token: ${{ inputs.github_token }}
- name: Get release version string
shell: bash
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
${{ inputs.artifact-paths }}
+26
View File
@@ -0,0 +1,26 @@
version: 2
updates:
- package-ecosystem: docker
directory: devcontainer
schedule:
interval: daily
time: "05:00" # trunk-ignore(yamllint/quoted-strings): required by dependabot syntax check
timezone: US/Pacific
- package-ecosystem: docker
directory: /
schedule:
interval: daily
time: "05:00" # trunk-ignore(yamllint/quoted-strings): required by dependabot syntax check
timezone: US/Pacific
- package-ecosystem: gitsubmodule
directory: /
schedule:
interval: daily
time: "05:00" # trunk-ignore(yamllint/quoted-strings): required by dependabot syntax check
timezone: US/Pacific
- package-ecosystem: github-actions
directory: /.github/workflows
schedule:
interval: daily
time: "05:00" # trunk-ignore(yamllint/quoted-strings): required by dependabot syntax check
timezone: US/Pacific
+14 -44
View File
@@ -12,52 +12,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Pull web ui
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/web
file: build.tar
target: build.tar
token: ${{ secrets.GITHUB_TOKEN }}
- name: Unpack web ui
run: |
tar -xf build.tar -C data/static
rm build.tar
- name: Remove debug flags for release
if: ${{ github.event_name == 'workflow_dispatch' }}
run: |
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32.ini
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s2.ini
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s3.ini
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32c3.ini
- name: Build ESP32
run: bin/build-esp32.sh ${{ inputs.board }}
- name: Pull OTA Firmware
uses: dsaltares/fetch-gh-release-asset@master
id: build
uses: ./.github/actions/build-variant
with:
repo: meshtastic/firmware-ota
file: firmware.bin
target: release/bleota.bin
token: ${{ secrets.GITHUB_TOKEN }}
- name: Get release version string
shell: bash
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
github_token: ${{ secrets.GITHUB_TOKEN }}
board: ${{ inputs.board }}
remove-debug-flags: >-
./arch/esp32/esp32.ini
./arch/esp32/esp32s2.ini
./arch/esp32/esp32s3.ini
./arch/esp32/esp32c3.ini
build-script-path: bin/build-esp32.sh
ota-firmware-source: firmware.bin
ota-firmware-target: release/bleota.bin
artifact-paths: |
release/*.bin
release/*.elf
include-web-ui: true
+14 -43
View File
@@ -14,50 +14,21 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Pull web ui
uses: dsaltares/fetch-gh-release-asset@master
- name: Build ESP32-C3
id: build
uses: ./.github/actions/build-variant
with:
repo: meshtastic/web
file: build.tar
target: build.tar
token: ${{ secrets.GITHUB_TOKEN }}
- name: Unpack web ui
run: |
tar -xf build.tar -C data/static
rm build.tar
- name: Remove debug flags for release
if: ${{ github.event_name == 'workflow_dispatch' }}
run: |
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32.ini
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s2.ini
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s3.ini
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32c3.ini
- name: Build ESP32
run: bin/build-esp32.sh ${{ inputs.board }}
- name: Pull OTA Firmware
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/firmware-ota
file: firmware-c3.bin
target: release/bleota-c3.bin
token: ${{ secrets.GITHUB_TOKEN }}
- name: Get release version string
shell: bash
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
github_token: ${{ secrets.GITHUB_TOKEN }}
board: ${{ inputs.board }}
remove-debug-flags: >-
./arch/esp32/esp32.ini
./arch/esp32/esp32s2.ini
./arch/esp32/esp32s3.ini
./arch/esp32/esp32c3.ini
build-script-path: bin/build-esp32.sh
ota-firmware-source: firmware-c3.bin
ota-firmware-target: release/bleota-c3.bin
artifact-paths: |
release/*.bin
release/*.elf
+35
View File
@@ -0,0 +1,35 @@
name: Build ESP32-C6
on:
workflow_call:
inputs:
board:
required: true
type: string
permissions: read-all
jobs:
build-esp32-c6:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build ESP32-C6
id: build
uses: ./.github/actions/build-variant
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
board: ${{ inputs.board }}
remove-debug-flags: >-
./arch/esp32/esp32.ini
./arch/esp32/esp32s2.ini
./arch/esp32/esp32s3.ini
./arch/esp32/esp32c3.ini
./arch/esp32/esp32c6.ini
build-script-path: bin/build-esp32.sh
ota-firmware-source: firmware-c3.bin
ota-firmware-target: release/bleota-c3.bin
artifact-paths: |
release/*.bin
release/*.elf
+15 -43
View File
@@ -12,50 +12,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Pull web ui
uses: dsaltares/fetch-gh-release-asset@master
- name: Build ESP32-S3
id: build
uses: ./.github/actions/build-variant
with:
repo: meshtastic/web
file: build.tar
target: build.tar
token: ${{ secrets.GITHUB_TOKEN }}
- name: Unpack web ui
run: |
tar -xf build.tar -C data/static
rm build.tar
- name: Remove debug flags for release
if: ${{ github.event_name == 'workflow_dispatch' }}
run: |
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32.ini
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s2.ini
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s3.ini
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32c3.ini
- name: Build ESP32
run: bin/build-esp32.sh ${{ inputs.board }}
- name: Pull OTA Firmware
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/firmware-ota
file: firmware-s3.bin
target: release/bleota-s3.bin
token: ${{ secrets.GITHUB_TOKEN }}
- name: Get release version string
shell: bash
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
github_token: ${{ secrets.GITHUB_TOKEN }}
board: ${{ inputs.board }}
remove-debug-flags: >-
./arch/esp32/esp32.ini
./arch/esp32/esp32s2.ini
./arch/esp32/esp32s3.ini
./arch/esp32/esp32c3.ini
build-script-path: bin/build-esp32.sh
ota-firmware-source: firmware-s3.bin
ota-firmware-target: release/bleota-s3.bin
artifact-paths: |
release/*.bin
release/*.elf
include-web-ui: true
+2 -2
View File
@@ -67,7 +67,7 @@ jobs:
- name: Docker build and push tagged versions
if: ${{ github.event_name == 'workflow_dispatch' }}
continue-on-error: true # FIXME: Failing docker login auth
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
@@ -77,7 +77,7 @@ jobs:
- name: Docker build and push
if: ${{ github.ref == 'refs/heads/master' && github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
continue-on-error: true # FIXME: Failing docker login auth
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
+6 -14
View File
@@ -12,23 +12,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Build NRF52
run: bin/build-nrf52.sh ${{ inputs.board }}
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
id: build
uses: ./.github/actions/build-variant
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
github_token: ${{ secrets.GITHUB_TOKEN }}
board: ${{ inputs.board }}
build-script-path: bin/build-nrf52.sh
artifact-paths: |
release/*.hex
release/*.uf2
release/*.elf
+6 -14
View File
@@ -12,22 +12,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Build Raspberry Pi 2040
run: ./bin/build-rpi2040.sh ${{ inputs.board }}
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
id: build
uses: ./.github/actions/build-variant
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
github_token: ${{ secrets.GITHUB_TOKEN }}
board: ${{ inputs.board }}
build-script-path: bin/build-rpi2040.sh
artifact-paths: |
release/*.uf2
release/*.elf
+7 -15
View File
@@ -12,22 +12,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Build STM32
run: bin/build-stm32.sh ${{ inputs.board }}
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
- name: Build STM32WL
id: build
uses: ./.github/actions/build-variant
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
github_token: ${{ secrets.GITHUB_TOKEN }}
board: ${{ inputs.board }}
build-script-path: bin/build-stm32.sh
artifact-paths: |
release/*.hex
release/*.bin
+65 -18
View File
@@ -1,4 +1,7 @@
name: CI
concurrency:
group: ${{ github.head_ref || github.run_id }}
cancel-in-progress: true
#concurrency:
# group: ${{ github.ref }}
# cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
@@ -24,7 +27,7 @@ jobs:
strategy:
fail-fast: false
matrix:
arch: [esp32, esp32s3, esp32c3, nrf52840, rp2040, stm32, check]
arch: [esp32, esp32s3, esp32c3, esp32c6, nrf52840, rp2040, stm32, check]
runs-on: ubuntu-latest
steps:
- id: checkout
@@ -32,13 +35,18 @@ jobs:
name: Checkout base
- id: jsonStep
run: |
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}})
if [[ "${{ github.ref }}" == "refs/heads/master" ]]; then
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}})
else
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}} quick)
fi
echo "$TARGETS"
echo "${{matrix.arch}}=$(jq -cn --argjson environments "$TARGETS" '{board: $environments}')" >> $GITHUB_OUTPUT
outputs:
esp32: ${{ steps.jsonStep.outputs.esp32 }}
esp32s3: ${{ steps.jsonStep.outputs.esp32s3 }}
esp32c3: ${{ steps.jsonStep.outputs.esp32c3 }}
esp32c6: ${{ steps.jsonStep.outputs.esp32c6 }}
nrf52840: ${{ steps.jsonStep.outputs.nrf52840 }}
rp2040: ${{ steps.jsonStep.outputs.rp2040 }}
stm32: ${{ steps.jsonStep.outputs.stm32 }}
@@ -51,6 +59,7 @@ jobs:
matrix: ${{ fromJson(needs.setup.outputs.check) }}
runs-on: ubuntu-latest
if: ${{ github.event_name != 'workflow_dispatch' }}
steps:
- uses: actions/checkout@v4
- name: Build base
@@ -86,6 +95,15 @@ jobs:
with:
board: ${{ matrix.board }}
build-esp32-c6:
needs: setup
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.setup.outputs.esp32c6) }}
uses: ./.github/workflows/build_esp32_c6.yml
with:
board: ${{ matrix.board }}
build-nrf52:
needs: setup
strategy:
@@ -119,11 +137,12 @@ jobs:
package-raspbian-armv7l:
uses: ./.github/workflows/package_raspbian_armv7l.yml
package-native:
uses: ./.github/workflows/package_amd64.yml
# package-native:
# uses: ./.github/workflows/package_amd64.yml
after-checks:
runs-on: ubuntu-latest
if: ${{ github.event_name != 'workflow_dispatch' }}
needs: [check]
steps:
- name: Checkout code
@@ -137,17 +156,17 @@ jobs:
contents: write
pull-requests: write
runs-on: ubuntu-latest
needs:
[
needs: [
build-esp32,
build-esp32-s3,
build-esp32-c3,
build-esp32-c6,
build-nrf52,
build-rpi2040,
build-stm32,
package-raspbian,
package-raspbian-armv7l,
package-native,
# package-native,
]
steps:
- name: Checkout code
@@ -231,7 +250,7 @@ jobs:
release-artifacts:
runs-on: ubuntu-latest
if: ${{ github.event_name == 'workflow_dispatch' }}
needs: [gather-artifacts, after-checks]
needs: [gather-artifacts]
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -334,22 +353,50 @@ jobs:
asset_name: meshtasticd_${{ steps.version.outputs.version }}_armhf.deb
asset_content_type: application/vnd.debian.binary-package
- name: Add raspbian amd64 .deb
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./output/meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
asset_name: meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
asset_content_type: application/vnd.debian.binary-package
# - name: Add raspbian amd64 .deb
# uses: actions/upload-release-asset@v1
# env:
# GITHUB_TOKEN: ${{ github.token }}
# with:
# upload_url: ${{ steps.create_release.outputs.upload_url }}
# asset_path: ./output/meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
# asset_name: meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
# asset_content_type: application/vnd.debian.binary-package
- name: Bump version.properties
run: >-
bin/bump_version.py
- name: Create version.properties pull request
uses: peter-evans/create-pull-request@v6
uses: peter-evans/create-pull-request@v7
with:
title: Bump version.properties
add-paths: |
version.properties
- name: Checkout meshtastic/meshtastic.github.io
uses: actions/checkout@v4
with:
repository: meshtastic/meshtastic.github.io
token: ${{ secrets.ARTIFACTS_TOKEN }}
path: meshtastic.github.io
- name: Display structure of downloaded files
run: ls -R
- name: Extract firmware.zip
run: |
unzip ./firmware-${{ steps.version.outputs.version }}.zip -d meshtastic.github.io/firmware-${{ steps.version.outputs.version }}
- name: Display structure of downloaded files
run: ls -R
- name: Commit and push changes
run: |
cd meshtastic.github.io
find . -type f -name 'meshtasticd_*' -exec rm -f {} +
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git add .
git commit -m "Add firmware version ${{ steps.version.outputs.version }}"
git push
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
semgrep-full:
runs-on: ubuntu-latest
container:
image: returntocorp/semgrep
image: semgrep/semgrep
steps:
# step 1
+1 -1
View File
@@ -6,7 +6,7 @@ jobs:
semgrep-diff:
runs-on: ubuntu-22.04
container:
image: returntocorp/semgrep
image: semgrep/semgrep
steps:
# step 1
+30 -15
View File
@@ -57,35 +57,50 @@ jobs:
reporter: java-junit
hardware-tests:
runs-on: ubuntu-latest
runs-on: test-runner
steps:
- name: Checkout code
uses: actions/checkout@v4
# - uses: actions/setup-python@v5
# with:
# python-version: '3.10'
# pipx install "setuptools<72"
- name: Upgrade python tools
shell: bash
run: |
python -m pip install --upgrade pip
pip install -U --no-build-isolation --no-cache-dir "setuptools<72"
pip install -U platformio adafruit-nrfutil --no-build-isolation
pip install -U poetry --no-build-isolation
pip install -U meshtastic --pre --no-build-isolation
pipx install adafruit-nrfutil
pipx install poetry
pipx install meshtastic --pip-args=--pre
- name: Install PlatformIO from script
shell: bash
run: |
curl -fsSL -o get-platformio.py https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py
python3 get-platformio.py
- name: Upgrade platformio
shell: bash
run: |
export PATH=$PATH:$HOME/.local/bin
pio upgrade
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 18
- name: Setup pnpm
uses: pnpm/action-setup@v2
uses: pnpm/action-setup@v4
with:
version: latest
- name: Install Dependencies
run: pnpm install
- name: Setup devices
run: pnpm run setup
- name: Execute end to end tests on connected hardware
run: pnpm run test
- name: Install dependencies, setup devices and run
shell: bash
run: |
git submodule update --init --recursive
cd meshtestic/
pnpm install
pnpm run setup
pnpm run test
+3 -2
View File
@@ -1,4 +1,4 @@
name: "Update protobufs and regenerate classes"
name: Update protobufs and regenerate classes
on: workflow_dispatch
jobs:
@@ -26,8 +26,9 @@ jobs:
./bin/regen-protos.sh
- name: Create pull request
uses: peter-evans/create-pull-request@v6
uses: peter-evans/create-pull-request@v7
with:
title: Update protobufs and classes
add-paths: |
protobufs
src/mesh
+9 -9
View File
@@ -1,6 +1,6 @@
version: 0.1
cli:
version: 1.22.3
version: 1.22.5
plugins:
sources:
- id: trunk
@@ -8,27 +8,27 @@ plugins:
uri: https://github.com/trunk-io/plugins
lint:
enabled:
- trufflehog@3.81.9
- trufflehog@3.82.5
- yamllint@1.35.1
- bandit@1.7.9
- checkov@3.2.238
- bandit@1.7.10
- checkov@3.2.255
- terrascan@1.19.1
- trivy@0.54.1
- trivy@0.55.2
#- trufflehog@3.63.2-rc0
- taplo@0.9.3
- ruff@0.6.2
- ruff@0.6.7
- isort@5.13.2
- markdownlint@0.41.0
- markdownlint@0.42.0
- oxipng@9.1.2
- svgo@3.3.2
- actionlint@1.7.1
- actionlint@1.7.2
- flake8@7.1.1
- hadolint@2.12.0
- shfmt@3.6.0
- shellcheck@0.10.0
- black@24.8.0
- git-diff-check
- gitleaks@8.18.4
- gitleaks@8.19.2
- clang-format@16.0.3
- prettier@3.3.3
ignore:
+12
View File
@@ -0,0 +1,12 @@
# Security Policy
## Supported Versions
| Firmware Version | Supported |
| ---------------- | ------------------ |
| 2.5.x | :white_check_mark: |
| <= 2.4.x | :x: |
## Reporting a Vulnerability
We support the private reporting of potential security vulnerabilities. Please go to the Security tab to file a report with a description of the potential vulnerability and reproduction scripts (preferred) or steps, and our developers will review.
+1 -1
View File
@@ -5,7 +5,7 @@ custom_esp32_kind = esp32
platform = platformio/espressif32@6.7.0
build_src_filter =
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/> -<mesh/raspihttp>
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp>
upload_speed = 921600
debug_init_break = tbreak setup
+40
View File
@@ -0,0 +1,40 @@
[esp32c6_base]
extends = esp32_base
platform = https://github.com/Jason2866/platform-espressif32.git#22faa566df8c789000f8136cd8d0aca49617af55
build_flags =
${arduino_base.build_flags}
-Wall
-Wextra
-Isrc/platform/esp32
-std=c++11
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
-DSERIAL_BUFFER_SIZE=4096
-DLIBPAX_ARDUINO
-DLIBPAX_WIFI
-DLIBPAX_BLE
-DMESHTASTIC_EXCLUDE_WEBSERVER
;-DDEBUG_HEAP
; TEMP
-DHAS_BLUETOOTH=0
-DMESHTASTIC_EXCLUDE_PAXCOUNTER
-DMESHTASTIC_EXCLUDE_BLUETOOTH
lib_deps =
${arduino_base.lib_deps}
${networking_base.lib_deps}
${environmental_base.lib_deps}
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
rweather/Crypto@^0.4.0
build_src_filter =
${esp32_base.build_src_filter} -<mesh/http>
monitor_speed = 460800
monitor_filters = esp32_c3_exception_decoder
lib_ignore =
NonBlockingRTTTL
NimBLE-Arduino
libpax
+1 -1
View File
@@ -16,7 +16,7 @@ build_flags =
-DLFS_NO_ASSERT ; Disable LFS assertions , see https://github.com/meshtastic/firmware/pull/3818
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2040> -<mesh/eth/> -<mesh/raspihttp>
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp>
lib_deps=
${arduino_base.lib_deps}
+2 -2
View File
@@ -1,6 +1,6 @@
; The Portduino based sim environment on top of any host OS, all hardware will be simulated
[portduino_base]
platform = https://github.com/meshtastic/platform-native.git#ad8112adf82ce1f5b917092cf32be07a077801a0
platform = https://github.com/meshtastic/platform-native.git#6b3796d697481c8f6e3f4aa5c111bd9979f29e64
framework = arduino
build_src_filter =
@@ -9,7 +9,7 @@ build_src_filter =
-<nimble/>
-<platform/nrf52/>
-<platform/stm32wl/>
-<platform/rp2040>
-<platform/rp2xx0>
-<mesh/wifi/>
-<mesh/http/>
+<mesh/raspihttp/>
@@ -8,7 +8,7 @@ board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
build_flags =
${arduino_base.build_flags} -Wno-unused-variable
-Isrc/platform/rp2040
-Isrc/platform/rp2xx0
-D__PLAT_RP2040__
# -D _POSIX_THREADS
build_src_filter =
+23
View File
@@ -0,0 +1,23 @@
; Common settings for rp2040 Processor based targets
[rp2350_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#9e55f6db5c56b9867c69fe473f388beea4546672
extends = arduino_base
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#a6ab6e1f95bc1428d667d55ea7173c0744acc03c ; 4.0.2+
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
build_flags =
${arduino_base.build_flags} -Wno-unused-variable
-Isrc/platform/rp2xx0
-D__PLAT_RP2040__
# -D _POSIX_THREADS
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> -<mesh/wifi/> -<mesh/http/> -<mesh/raspihttp>
lib_ignore =
BluetoothOTA
lib_deps =
${arduino_base.lib_deps}
${environmental_base.lib_deps}
rweather/Crypto
+1 -1
View File
@@ -22,7 +22,7 @@ build_flags =
-fdata-sections
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/RemoteHardwareModule.cpp> -<platform/nrf52> -<platform/portduino> -<platform/rp2040> -<mesh/raspihttp>
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/RemoteHardwareModule.cpp> -<platform/nrf52> -<platform/portduino> -<platform/rp2xx0> -<mesh/raspihttp>
board_upload.offset_address = 0x08000000
upload_protocol = stlink
+2 -1
View File
@@ -9,6 +9,7 @@ Lora:
# IRQ: 16
# Busy: 20
# Reset: 18
# SX126X_ANT_SW: 6
# Module: sx1262 # Waveshare SX1302 LISTEN ONLY AT THIS TIME!
# CS: 7
@@ -153,4 +154,4 @@ Webserver:
General:
MaxNodes: 200
MaxMessageQueue: 100
MaxMessageQueue: 100
+5 -2
View File
@@ -6,6 +6,7 @@ import configparser
import json
import os
import sys
import random
rootdir = "variants/"
@@ -39,5 +40,7 @@ for subdir, dirs, files in os.walk(rootdir):
"check" in options
):
outlist.append(section)
print(json.dumps(outlist))
if ("quick" in options) & (len(outlist) > 3):
print(json.dumps(random.sample(outlist, 3)))
else:
print(json.dumps(outlist))
+41
View File
@@ -0,0 +1,41 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"memory_type": "qio_opi"
},
"core": "esp32",
"extra_flags": [
"-DBOARD_HAS_PSRAM",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_USB_MODE=0",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=0"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"hwids": [["0x2886", "0x0059"]],
"mcu": "esp32s3",
"variant": "seeed-xiao-s3"
},
"connectivity": ["wifi", "bluetooth", "lora"],
"debug": {
"default_tool": "esp-builtin",
"onboard_tools": ["esp-builtin"],
"openocd_target": "esp32s3.cfg"
},
"frameworks": ["arduino", "espidf"],
"name": "seeed-xiao-s3",
"upload": {
"flash_size": "8MB",
"maximum_ram_size": 8388608,
"maximum_size": 8388608,
"use_1200bps_touch": true,
"wait_for_upload_port": true,
"require_upload_port": true,
"speed": 921600
},
"url": "https://www.seeedstudio.com/XIAO-ESP32S3-Sense-p-5639.html",
"vendor": "Seeed Studio"
}
+6 -3
View File
@@ -81,6 +81,7 @@ build_flags = -Wno-missing-field-initializers
-DRADIOLIB_EXCLUDE_APRS
-DRADIOLIB_EXCLUDE_LORAWAN
-DMESHTASTIC_EXCLUDE_DROPZONE=1
-DMESHTASTIC_EXCLUDE_REMOTEHARDWARE=1
-DBUILD_EPOCH=$UNIX_TIME
;-D OLED_PL
@@ -88,7 +89,9 @@ monitor_speed = 115200
monitor_filters = direct
lib_deps =
jgromes/RadioLib@~7.0.0
;jgromes/RadioLib@~7.0.0
;7.0.1pre needed for LR1121 support and SX127x CRC Bugfix
https://github.com/jgromes/RadioLib.git#38fc7a97a4c195b7c10aa94215a1c53ec18a56ef
https://github.com/meshtastic/esp8266-oled-ssd1306.git#e16cee124fe26490cb14880c679321ad8ac89c95 ; ESP8266_SSD1306
https://github.com/mathertel/OneButton@~2.6.1 ; OneButton library for non-blocking button debounce
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
@@ -136,6 +139,7 @@ lib_deps =
adafruit/Adafruit MCP9808 Library@^2.0.0
adafruit/Adafruit INA260 Library@^1.5.0
adafruit/Adafruit INA219@^1.2.0
adafruit/Adafruit MAX1704X@^1.0.3
adafruit/Adafruit SHTC3 Library@^1.0.0
adafruit/Adafruit LPS2X@^2.0.4
adafruit/Adafruit SHT31 Library@^2.2.2
@@ -148,17 +152,16 @@ lib_deps =
adafruit/Adafruit SHT4x Library@^1.0.4
adafruit/Adafruit TSL2591 Library@^1.4.5
sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@^1.0.5
sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@^1.2.13
ClosedCube OPT3001@^1.1.2
emotibit/EmotiBit MLX90632@^1.0.8
dfrobot/DFRobot_RTU@^1.0.3
https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.7.2502
boschsensortec/BME68x Sensor Library@^1.1.40407
https://github.com/KodinLanewave/INA3221@^1.0.0
lewisxhe/SensorLib@0.2.0
mprograms/QMC5883LCompass@^1.2.0
https://github.com/meshtastic/DFRobot_LarkWeatherStation#dee914270dc7cb3e43fbf034edd85a63a16a12ee
https://github.com/gjelsoe/STK8xxx-Accelerometer.git#v0.1.1
-319
View File
@@ -1,319 +0,0 @@
#pragma once
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#include "PowerFSM.h"
#include "concurrency/OSThread.h"
#include "main.h"
#include "power.h"
#include <Adafruit_LIS3DH.h>
#include <Adafruit_LSM6DS3TRC.h>
#include <Adafruit_MPU6050.h>
#ifdef STK8XXX_INT
#include <stk8baxx.h>
#endif
#include <Arduino.h>
#include <SensorBMA423.hpp>
#include <Wire.h>
#ifdef RAK_4631
#include "Fusion/Fusion.h"
#include "graphics/Screen.h"
#include "graphics/ScreenFonts.h"
#include <Rak_BMX160.h>
#endif
#define ACCELEROMETER_CHECK_INTERVAL_MS 100
#define ACCELEROMETER_CLICK_THRESHOLD 40
volatile static bool STK_IRQ;
static inline int readRegister(uint8_t address, uint8_t reg, uint8_t *data, uint8_t len)
{
Wire.beginTransmission(address);
Wire.write(reg);
Wire.endTransmission();
Wire.requestFrom((uint8_t)address, (uint8_t)len);
uint8_t i = 0;
while (Wire.available()) {
data[i++] = Wire.read();
}
return 0; // Pass
}
static inline int writeRegister(uint8_t address, uint8_t reg, uint8_t *data, uint8_t len)
{
Wire.beginTransmission(address);
Wire.write(reg);
Wire.write(data, len);
return (0 != Wire.endTransmission());
}
class AccelerometerThread : public concurrency::OSThread
{
public:
explicit AccelerometerThread(ScanI2C::DeviceType type) : OSThread("AccelerometerThread")
{
if (accelerometer_found.port == ScanI2C::I2CPort::NO_I2C) {
LOG_DEBUG("AccelerometerThread disabling due to no sensors found\n");
disable();
return;
}
acceleremoter_type = type;
#ifndef RAK_4631
if (!config.display.wake_on_tap_or_motion && !config.device.double_tap_as_button_press) {
LOG_DEBUG("AccelerometerThread disabling due to no interested configurations\n");
disable();
return;
}
#endif
init();
}
void start()
{
init();
setIntervalFromNow(0);
};
protected:
int32_t runOnce() override
{
canSleep = true; // Assume we should not keep the board awake
if (acceleremoter_type == ScanI2C::DeviceType::MPU6050 && mpu.getMotionInterruptStatus()) {
wakeScreen();
} else if (acceleremoter_type == ScanI2C::DeviceType::STK8BAXX && STK_IRQ) {
STK_IRQ = false;
if (config.display.wake_on_tap_or_motion) {
wakeScreen();
}
} else if (acceleremoter_type == ScanI2C::DeviceType::LIS3DH && lis.getClick() > 0) {
uint8_t click = lis.getClick();
if (!config.device.double_tap_as_button_press) {
wakeScreen();
}
if (config.device.double_tap_as_button_press && (click & 0x20)) {
buttonPress();
return 500;
}
} else if (acceleremoter_type == ScanI2C::DeviceType::BMA423 && bmaSensor.readIrqStatus() != DEV_WIRE_NONE) {
if (bmaSensor.isTilt() || bmaSensor.isDoubleTap()) {
wakeScreen();
return 500;
}
#ifdef RAK_4631
} else if (acceleremoter_type == ScanI2C::DeviceType::BMX160) {
sBmx160SensorData_t magAccel;
sBmx160SensorData_t gAccel;
/* Get a new sensor event */
bmx160.getAllData(&magAccel, NULL, &gAccel);
// expirimental calibrate routine. Limited to between 10 and 30 seconds after boot
if (millis() > 12 * 1000 && millis() < 30 * 1000) {
if (!showingScreen) {
showingScreen = true;
screen->startAlert((FrameCallback)drawFrameCalibration);
}
if (magAccel.x > highestX)
highestX = magAccel.x;
if (magAccel.x < lowestX)
lowestX = magAccel.x;
if (magAccel.y > highestY)
highestY = magAccel.y;
if (magAccel.y < lowestY)
lowestY = magAccel.y;
if (magAccel.z > highestZ)
highestZ = magAccel.z;
if (magAccel.z < lowestZ)
lowestZ = magAccel.z;
} else if (showingScreen && millis() >= 30 * 1000) {
showingScreen = false;
screen->endAlert();
}
int highestRealX = highestX - (highestX + lowestX) / 2;
magAccel.x -= (highestX + lowestX) / 2;
magAccel.y -= (highestY + lowestY) / 2;
magAccel.z -= (highestZ + lowestZ) / 2;
FusionVector ga, ma;
ga.axis.x = -gAccel.x; // default location for the BMX160 is on the rear of the board
ga.axis.y = -gAccel.y;
ga.axis.z = gAccel.z;
ma.axis.x = -magAccel.x;
ma.axis.y = -magAccel.y;
ma.axis.z = magAccel.z * 3;
// If we're set to one of the inverted positions
if (config.display.compass_orientation > meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270) {
ma = FusionAxesSwap(ma, FusionAxesAlignmentNXNYPZ);
ga = FusionAxesSwap(ga, FusionAxesAlignmentNXNYPZ);
}
float heading = FusionCompassCalculateHeading(FusionConventionNed, ga, ma);
switch (config.display.compass_orientation) {
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0_INVERTED:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0:
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_90:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_90_INVERTED:
heading += 90;
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_180:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_180_INVERTED:
heading += 180;
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270_INVERTED:
heading += 270;
break;
}
screen->setHeading(heading);
#endif
} else if (acceleremoter_type == ScanI2C::DeviceType::LSM6DS3 && lsm.shake()) {
wakeScreen();
return 500;
}
return ACCELEROMETER_CHECK_INTERVAL_MS;
}
private:
void init()
{
LOG_DEBUG("AccelerometerThread initializing\n");
if (acceleremoter_type == ScanI2C::DeviceType::MPU6050 && mpu.begin(accelerometer_found.address)) {
LOG_DEBUG("MPU6050 initializing\n");
// setup motion detection
mpu.setHighPassFilter(MPU6050_HIGHPASS_0_63_HZ);
mpu.setMotionDetectionThreshold(1);
mpu.setMotionDetectionDuration(20);
mpu.setInterruptPinLatch(true); // Keep it latched. Will turn off when reinitialized.
mpu.setInterruptPinPolarity(true);
#ifdef STK8XXX_INT
} else if (acceleremoter_type == ScanI2C::DeviceType::STK8BAXX && stk8baxx.STK8xxx_Initialization(STK8xxx_VAL_RANGE_2G)) {
STK_IRQ = false;
LOG_DEBUG("STX8BAxx initialized\n");
stk8baxx.STK8xxx_Anymotion_init();
pinMode(STK8XXX_INT, INPUT_PULLUP);
attachInterrupt(
digitalPinToInterrupt(STK8XXX_INT), [] { STK_IRQ = true; }, RISING);
#endif
} else if (acceleremoter_type == ScanI2C::DeviceType::LIS3DH && lis.begin(accelerometer_found.address)) {
LOG_DEBUG("LIS3DH initializing\n");
lis.setRange(LIS3DH_RANGE_2_G);
// Adjust threshold, higher numbers are less sensitive
lis.setClick(config.device.double_tap_as_button_press ? 2 : 1, ACCELEROMETER_CLICK_THRESHOLD);
} else if (acceleremoter_type == ScanI2C::DeviceType::BMA423 &&
bmaSensor.begin(accelerometer_found.address, &readRegister, &writeRegister)) {
LOG_DEBUG("BMA423 initializing\n");
bmaSensor.configAccelerometer(bmaSensor.RANGE_2G, bmaSensor.ODR_100HZ, bmaSensor.BW_NORMAL_AVG4,
bmaSensor.PERF_CONTINUOUS_MODE);
bmaSensor.enableAccelerometer();
bmaSensor.configInterrupt(BMA4_LEVEL_TRIGGER, BMA4_ACTIVE_HIGH, BMA4_PUSH_PULL, BMA4_OUTPUT_ENABLE,
BMA4_INPUT_DISABLE);
#ifdef BMA423_INT
pinMode(BMA4XX_INT, INPUT);
attachInterrupt(
BMA4XX_INT,
[] {
// Set interrupt to set irq value to true
BMA_IRQ = true;
},
RISING); // Select the interrupt mode according to the actual circuit
#endif
#ifdef T_WATCH_S3
// Need to raise the wrist function, need to set the correct axis
bmaSensor.setReampAxes(bmaSensor.REMAP_TOP_LAYER_RIGHT_CORNER);
#else
bmaSensor.setReampAxes(bmaSensor.REMAP_BOTTOM_LAYER_BOTTOM_LEFT_CORNER);
#endif
// bmaSensor.enableFeature(bmaSensor.FEATURE_STEP_CNTR, true);
bmaSensor.enableFeature(bmaSensor.FEATURE_TILT, true);
bmaSensor.enableFeature(bmaSensor.FEATURE_WAKEUP, true);
// bmaSensor.resetPedometer();
// Turn on feature interrupt
bmaSensor.enablePedometerIRQ();
bmaSensor.enableTiltIRQ();
// It corresponds to isDoubleClick interrupt
bmaSensor.enableWakeupIRQ();
#ifdef RAK_4631
} else if (acceleremoter_type == ScanI2C::DeviceType::BMX160 && bmx160.begin()) {
bmx160.ODR_Config(BMX160_ACCEL_ODR_100HZ, BMX160_GYRO_ODR_100HZ); // set output data rate
#endif
} else if (acceleremoter_type == ScanI2C::DeviceType::LSM6DS3 && lsm.begin_I2C(accelerometer_found.address)) {
LOG_DEBUG("LSM6DS3 initializing\n");
// Default threshold of 2G, less sensitive options are 4, 8 or 16G
lsm.setAccelRange(LSM6DS_ACCEL_RANGE_2_G);
#ifndef LSM6DS3_WAKE_THRESH
#define LSM6DS3_WAKE_THRESH 20
#endif
lsm.enableWakeup(config.display.wake_on_tap_or_motion, 1, LSM6DS3_WAKE_THRESH);
// Duration is number of occurances needed to trigger, higher threshold is less sensitive
}
}
void wakeScreen()
{
if (powerFSM.getState() == &stateDARK) {
LOG_INFO("Tap or motion detected. Turning on screen\n");
powerFSM.trigger(EVENT_INPUT);
}
}
void buttonPress()
{
LOG_DEBUG("Double-tap detected. Firing button press\n");
powerFSM.trigger(EVENT_PRESS);
}
ScanI2C::DeviceType acceleremoter_type;
Adafruit_MPU6050 mpu;
Adafruit_LIS3DH lis;
#ifdef STK8XXX_INT
STK8xxx stk8baxx;
#endif
Adafruit_LSM6DS3TRC lsm;
SensorBMA423 bmaSensor;
bool BMA_IRQ = false;
#ifdef RAK_4631
bool showingScreen = false;
RAK_BMX160 bmx160;
float highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0;
static void drawFrameCalibration(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
int x_offset = display->width() / 2;
int y_offset = display->height() <= 80 ? 0 : 32;
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(FONT_MEDIUM);
display->drawString(x, y, "Calibrating\nCompass");
int16_t compassX = 0, compassY = 0;
uint16_t compassDiam = graphics::Screen::getCompassDiam(display->getWidth(), display->getHeight());
// coordinates for the center of the compass/circle
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
compassX = x + display->getWidth() - compassDiam / 2 - 5;
compassY = y + display->getHeight() / 2;
} else {
compassX = x + display->getWidth() - compassDiam / 2 - 5;
compassY = y + FONT_HEIGHT_SMALL + (display->getHeight() - FONT_HEIGHT_SMALL) / 2;
}
display->drawCircle(compassX, compassY, compassDiam / 2);
screen->drawCompassNorth(display, compassX, compassY, screen->getHeading() * PI / 180);
}
#endif
};
#endif
+3 -3
View File
@@ -370,8 +370,8 @@ void setupSDCard()
}
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
LOG_DEBUG("SD Card Size: %lluMB\n", cardSize);
LOG_DEBUG("Total space: %llu MB\n", SD.totalBytes() / (1024 * 1024));
LOG_DEBUG("Used space: %llu MB\n", SD.usedBytes() / (1024 * 1024));
LOG_DEBUG("SD Card Size: %lu MB\n", (uint32_t)cardSize);
LOG_DEBUG("Total space: %lu MB\n", (uint32_t)(SD.totalBytes() / (1024 * 1024)));
LOG_DEBUG("Used space: %lu MB\n", (uint32_t)(SD.usedBytes() / (1024 * 1024)));
#endif
}
+102 -3
View File
@@ -13,6 +13,7 @@
#include "power.h"
#include "NodeDB.h"
#include "PowerFSM.h"
#include "Throttle.h"
#include "buzz/buzz.h"
#include "configuration.h"
#include "main.h"
@@ -30,6 +31,7 @@
#if HAS_WIFI
#include <WiFi.h>
#endif
#endif
#ifndef DELAY_FOREVER
@@ -75,6 +77,15 @@ INA219Sensor ina219Sensor;
INA3221Sensor ina3221Sensor;
#endif
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#include "modules/Telemetry/Sensor/MAX17048Sensor.h"
#include <utility>
extern std::pair<uint8_t, TwoWire *> nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1];
#if HAS_TELEMETRY && (!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR || !MESHTASTIC_EXCLUDE_POWER_TELEMETRY)
MAX17048Sensor max17048Sensor;
#endif
#endif
#if HAS_RAKPROT && !defined(ARCH_PORTDUINO)
RAK9154Sensor rak9154Sensor;
#endif
@@ -136,6 +147,8 @@ using namespace meshtastic;
*/
static HasBatteryLevel *batteryLevel; // Default to NULL for no battery level sensor
#ifdef BATTERY_PIN
static void adcEnable()
{
#ifdef ADC_CTRL // enable adc voltage divider when we need to read
@@ -160,11 +173,14 @@ static void adcDisable()
#endif
}
#endif
/**
* A simple battery level sensor that assumes the battery voltage is attached via a voltage-divider to an analog input
*/
class AnalogBatteryLevel : public HasBatteryLevel
{
public:
/**
* Battery state of charge, from 0 to 100 or -1 for unknown
*/
@@ -244,7 +260,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
config.power.adc_multiplier_override > 0 ? config.power.adc_multiplier_override : ADC_MULTIPLIER;
// Do not call analogRead() often.
const uint32_t min_read_interval = 5000;
if (millis() - last_read_time_ms > min_read_interval) {
if (!Throttle::isWithinTimespanMs(last_read_time_ms, min_read_interval)) {
last_read_time_ms = millis();
uint32_t raw = 0;
@@ -551,7 +567,12 @@ bool Power::analogInit()
*/
bool Power::setup()
{
bool found = axpChipInit() || analogInit();
// initialise one power sensor (only)
bool found = axpChipInit();
if (!found)
found = lipoInit();
if (!found)
found = analogInit();
#ifdef NRF_APM
found = true;
@@ -1042,4 +1063,82 @@ bool Power::axpChipInit()
#else
return false;
#endif
}
}
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
/**
* Wrapper class for an I2C MAX17048 Lipo battery sensor.
*/
class LipoBatteryLevel : public HasBatteryLevel
{
private:
MAX17048Singleton *max17048 = nullptr;
public:
/**
* Init the I2C MAX17048 Lipo battery level sensor
*/
bool runOnce()
{
if (max17048 == nullptr) {
max17048 = MAX17048Singleton::GetInstance();
}
// try to start if the sensor has been detected
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MAX17048].first != 0) {
return max17048->runOnce(nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MAX17048].second);
}
return false;
}
/**
* Battery state of charge, from 0 to 100 or -1 for unknown
*/
virtual int getBatteryPercent() override { return max17048->getBusBatteryPercent(); }
/**
* The raw voltage of the battery in millivolts, or NAN if unknown
*/
virtual uint16_t getBattVoltage() override { return max17048->getBusVoltageMv(); }
/**
* return true if there is a battery installed in this unit
*/
virtual bool isBatteryConnect() override { return max17048->isBatteryConnected(); }
/**
* return true if there is an external power source detected
*/
virtual bool isVbusIn() override { return max17048->isExternallyPowered(); }
/**
* return true if the battery is currently charging
*/
virtual bool isCharging() override { return max17048->isBatteryCharging(); }
};
LipoBatteryLevel lipoLevel;
/**
* Init the Lipo battery level sensor
*/
bool Power::lipoInit()
{
bool result = lipoLevel.runOnce();
LOG_DEBUG("Power::lipoInit lipo sensor is %s\n", result ? "ready" : "not ready yet");
if (!result)
return false;
batteryLevel = &lipoLevel;
return true;
}
#else
/**
* The Lipo battery level sensor is unavailable - default to AnalogBatteryLevel
*/
bool Power::lipoInit()
{
return false;
}
#endif
+1 -1
View File
@@ -24,7 +24,7 @@
class SafeFile : public Print
{
public:
SafeFile(char const *filepath, bool fullAtomic = false);
explicit SafeFile(char const *filepath, bool fullAtomic = false);
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buffer, size_t size);
+7 -5
View File
@@ -1,6 +1,8 @@
#include "SerialConsole.h"
#include "Default.h"
#include "NodeDB.h"
#include "PowerFSM.h"
#include "Throttle.h"
#include "configuration.h"
#include "time.h"
@@ -44,10 +46,11 @@ SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port), con
Port.setRX(SERIAL2_RX);
#endif
Port.begin(SERIAL_BAUD);
#if defined(ARCH_NRF52) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARCH_RP2040)
#if defined(ARCH_NRF52) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARCH_RP2040) || \
defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6)
time_t timeout = millis();
while (!Port) {
if ((millis() - timeout) < 5000) {
if (Throttle::isWithinTimespanMs(timeout, FIVE_SECONDS_MS)) {
delay(100);
} else {
break;
@@ -72,8 +75,7 @@ void SerialConsole::flush()
// For the serial port we can't really detect if any client is on the other side, so instead just look for recent messages
bool SerialConsole::checkIsConnected()
{
uint32_t now = millis();
return (now - lastContactMsec) < SERIAL_CONNECTION_TIMEOUT;
return Throttle::isWithinTimespanMs(lastContactMsec, SERIAL_CONNECTION_TIMEOUT);
}
/**
@@ -120,4 +122,4 @@ void SerialConsole::log_to_serial(const char *logLevel, const char *format, va_l
emitLogRecord(ll, thread ? thread->ThreadName.c_str() : "", format, arg);
} else
RedirectablePrint::log_to_serial(logLevel, format, arg);
}
}
+16
View File
@@ -69,6 +69,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef RTC_DATA_ATTR
#define RTC_DATA_ATTR
#endif
#ifndef EXT_RAM_BSS_ATTR
#define EXT_RAM_BSS_ATTR EXT_RAM_ATTR
#endif
// -----------------------------------------------------------------------------
// Regulatory overrides
@@ -122,6 +125,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define INA_ADDR_ALTERNATE 0x41
#define INA_ADDR_WAVESHARE_UPS 0x43
#define INA3221_ADDR 0x42
#define MAX1704X_ADDR 0x36
#define QMC6310_ADDR 0x1C
#define QMI8658_ADDR 0x6B
#define QMC5883L_ADDR 0x0D
@@ -150,6 +154,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define BMA423_ADDR 0x19
#define LSM6DS3_ADDR 0x6A
#define BMX160_ADDR 0x69
#define ICM20948_ADDR 0x69
#define ICM20948_ADDR_ALT 0x68
// -----------------------------------------------------------------------------
// LED
@@ -210,6 +216,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MINIMUM_SAFE_FREE_HEAP 1500
#endif
#ifndef WIRE_INTERFACES_COUNT
// Officially an NRF52 macro
// Repurposed cross-platform to identify devices using Wire1
#if defined(I2C_SDA1) || defined(PIN_WIRE1_SDA)
#define WIRE_INTERFACES_COUNT 2
#elif HAS_WIRE
#define WIRE_INTERFACES_COUNT 1
#endif
#endif
/* Step #3: mop up with disabled values for HAS_ options not handled by the above two */
#ifndef HAS_WIFI
+2 -1
View File
@@ -10,7 +10,8 @@ enum LoRaRadioType {
LLCC68_RADIO,
SX1280_RADIO,
LR1110_RADIO,
LR1120_RADIO
LR1120_RADIO,
LR1121_RADIO
};
extern LoRaRadioType radioType;
+2 -2
View File
@@ -37,8 +37,8 @@ ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const
{
ScanI2C::DeviceType types[] = {MPU6050, LIS3DH, BMA423, LSM6DS3, BMX160, STK8BAXX};
return firstOfOrNONE(6, types);
ScanI2C::DeviceType types[] = {MPU6050, LIS3DH, BMA423, LSM6DS3, BMX160, STK8BAXX, ICM20948};
return firstOfOrNONE(7, types);
}
ScanI2C::FoundDevice ScanI2C::find(ScanI2C::DeviceType) const
+7 -4
View File
@@ -28,6 +28,7 @@ class ScanI2C
INA260,
INA219,
INA3221,
MAX17048,
MCP9808,
SHT31,
SHT4X,
@@ -56,7 +57,8 @@ class ScanI2C
DFROBOT_LARK,
NAU7802,
FT6336U,
STK8BAXX
STK8BAXX,
ICM20948
} DeviceType;
// typedef uint8_t DeviceAddress;
@@ -67,8 +69,9 @@ class ScanI2C
} I2CPort;
typedef struct DeviceAddress {
I2CPort port;
uint8_t address;
// set default values for ADDRESS_NONE
I2CPort port = I2CPort::NO_I2C;
uint8_t address = 0;
explicit DeviceAddress(I2CPort port, uint8_t address);
DeviceAddress();
@@ -119,4 +122,4 @@ class ScanI2C
private:
bool shouldSuppressScreen = false;
};
};
+24 -9
View File
@@ -162,13 +162,13 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
Melopero_RV3028 rtc;
#endif
#ifdef I2C_SDA1
#if WIRE_INTERFACES_COUNT == 2
if (port == I2CPort::WIRE1) {
i2cBus = &Wire1;
} else {
#endif
i2cBus = &Wire;
#ifdef I2C_SDA1
#if WIRE_INTERFACES_COUNT == 2
}
#endif
@@ -334,11 +334,10 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
// Check register 0x0F for 0x3300 response to ID LIS3DH chip.
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 2);
if (registerValue == 0x3300) {
if (registerValue == 0x3300 || registerValue == 0x3333) { // RAK4631 WisBlock has LIS3DH register at 0x3333
type = LIS3DH;
LOG_INFO("LIS3DH accelerometer found\n");
}
break;
}
case SHT31_4x_ADDR:
@@ -383,10 +382,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
SCAN_SIMPLE_CASE(QMC5883L_ADDR, QMC5883L, "QMC5883L Highrate 3-Axis magnetic sensor found\n")
SCAN_SIMPLE_CASE(HMC5883L_ADDR, HMC5883L, "HMC5883L 3-Axis digital compass found\n")
SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031 air quality sensor found\n")
SCAN_SIMPLE_CASE(MPU6050_ADDR, MPU6050, "MPU6050 accelerometer found\n");
SCAN_SIMPLE_CASE(BMX160_ADDR, BMX160, "BMX160 accelerometer found\n");
SCAN_SIMPLE_CASE(BMA423_ADDR, BMA423, "BMA423 accelerometer found\n");
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3 accelerometer found at address 0x%x\n", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(TCA9535_ADDR, TCA9535, "TCA9535 I2C expander found\n");
@@ -397,6 +393,25 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
SCAN_SIMPLE_CASE(MLX90632_ADDR, MLX90632, "MLX90632 IR temp sensor found\n");
SCAN_SIMPLE_CASE(NAU7802_ADDR, NAU7802, "NAU7802 based scale found\n");
SCAN_SIMPLE_CASE(FT6336U_ADDR, FT6336U, "FT6336U touchscreen found\n");
SCAN_SIMPLE_CASE(MAX1704X_ADDR, MAX17048, "MAX17048 lipo fuel gauge found\n");
case ICM20948_ADDR: // same as BMX160_ADDR
case ICM20948_ADDR_ALT: // same as MPU6050_ADDR
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1);
if (registerValue == 0xEA) {
type = ICM20948;
LOG_INFO("ICM20948 9-dof motion processor found\n");
break;
} else if (addr.address == BMX160_ADDR) {
type = BMX160;
LOG_INFO("BMX160 accelerometer found\n");
break;
} else {
type = MPU6050;
LOG_INFO("MPU6050 accelerometer found\n");
break;
}
break;
default:
LOG_INFO("Device found at address 0x%x was not able to be enumerated\n", addr.address);
@@ -423,7 +438,7 @@ TwoWire *ScanI2CTwoWire::fetchI2CBus(ScanI2C::DeviceAddress address) const
if (address.port == ScanI2C::I2CPort::WIRE) {
return &Wire;
} else {
#ifdef I2C_SDA1
#if WIRE_INTERFACES_COUNT == 2
return &Wire1;
#else
return &Wire;
@@ -435,4 +450,4 @@ size_t ScanI2CTwoWire::countDevices() const
{
return foundDevices.size();
}
#endif
#endif
+178 -285
View File
@@ -6,6 +6,8 @@
#include "NodeDB.h"
#include "PowerMon.h"
#include "RTC.h"
#include "Throttle.h"
#include "meshUtils.h"
#include "main.h" // pmu_found
#include "sleep.h"
@@ -60,7 +62,8 @@ const char *getGPSPowerStateString(GPSPowerState state)
case GPS_OFF:
return "OFF";
default:
assert(false); // Unhandled enum value..
assert(false); // Unhandled enum value..
return "FALSE"; // to make new ESP-IDF happy
}
}
@@ -206,7 +209,7 @@ GPS_RESPONSE GPS::getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMilli
// ACK-NACK| 0xBA | 0xCE | 0x04 | 0x00 | 0x05 | 0x00 | 0xXX | 0xXX | 0x00 | 0x00 | 0xXX | 0xXX | 0xXX | 0xXX |
// ACK-ACK | 0xBA | 0xCE | 0x04 | 0x00 | 0x05 | 0x01 | 0xXX | 0xXX | 0x00 | 0x00 | 0xXX | 0xXX | 0xXX | 0xXX |
while (millis() - startTime < waitMillis) {
while (Throttle::isWithinTimespanMs(startTime, waitMillis)) {
if (_serial_gps->available()) {
buffer[bufferPos++] = _serial_gps->read();
@@ -275,7 +278,7 @@ GPS_RESPONSE GPS::getACK(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis)
buf[9] += buf[8];
}
while (millis() - startTime < waitMillis) {
while (Throttle::isWithinTimespanMs(startTime, waitMillis)) {
if (ack > 9) {
#ifdef GPS_DEBUG
LOG_DEBUG("\n");
@@ -330,9 +333,9 @@ int GPS::getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
{
uint16_t ubxFrameCounter = 0;
uint32_t startTime = millis();
uint16_t needRead;
uint16_t needRead = 0;
while (millis() - startTime < waitMillis) {
while (Throttle::isWithinTimespanMs(startTime, waitMillis)) {
if (_serial_gps->available()) {
int c = _serial_gps->read();
switch (ubxFrameCounter) {
@@ -403,9 +406,9 @@ int GPS::getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
bool GPS::setup()
{
int msglen = 0;
if (!didSerialInit) {
int msglen = 0;
if (tx_gpio && gnssModel == GNSS_MODEL_UNKNOWN) {
// if GPS_BAUDRATE is specified in variant (i.e. not 9600), skip to the specified rate.
@@ -510,7 +513,7 @@ bool GPS::setup()
delay(250);
_serial_gps->write("$CFGMSG,6,1,0\r\n");
delay(250);
} else if (gnssModel == GNSS_MODEL_AG3335 || gnssModel == GNSS_MODEL_AG3352) {
} else if (IS_ONE_OF(gnssModel, GNSS_MODEL_AG3335, GNSS_MODEL_AG3352)) {
_serial_gps->write("$PAIR066,1,0,1,0,0,1*3B\r\n"); // Enable GPS+GALILEO+NAVIC
@@ -525,268 +528,95 @@ bool GPS::setup()
delay(250);
_serial_gps->write("$PAIR513*3D\r\n"); // save configuration
} else if (gnssModel == GNSS_MODEL_UBLOX6) {
clearBuffer();
SEND_UBX_PACKET(0x06, 0x02, _message_DISABLE_TXT_INFO, "Unable to disable text info messages.\n", 500);
SEND_UBX_PACKET(0x06, 0x39, _message_JAM_6_7, "Unable to enable interference resistance.\n", 500);
SEND_UBX_PACKET(0x06, 0x23, _message_NAVX5, "Unable to configure NAVX5 settings.\n", 500);
} else if (gnssModel == GNSS_MODEL_UBLOX) {
// Configure GNSS system to GPS+SBAS+GLONASS (Module may restart after this command)
// We need set it because by default it is GPS only, and we want to use GLONASS too
// Also we need SBAS for better accuracy and extra features
// ToDo: Dynamic configure GNSS systems depending of LoRa region
// Turn off unwanted NMEA messages, set update rate
SEND_UBX_PACKET(0x06, 0x08, _message_1HZ, "Unable to set GPS update rate.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_GLL, "Unable to disable NMEA GLL.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_GSA, "Unable to Enable NMEA GSA.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_GSV, "Unable to disable NMEA GSV.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_VTG, "Unable to disable NMEA VTG.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_RMC, "Unable to enable NMEA RMC.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_GGA, "Unable to enable NMEA GGA.\n", 500);
if (strncmp(info.hwVersion, "000A0000", 8) != 0) {
if (strncmp(info.hwVersion, "00040007", 8) != 0) {
// The original ublox Neo-6 is GPS only and doesn't support the UBX-CFG-GNSS message
// Max7 seems to only support GPS *or* GLONASS
// Neo-7 is supposed to support GPS *and* GLONASS but NAKs the CFG-GNSS command to do it
// So treat all the u-blox 7 series as GPS only
// M8 can support 3 constallations at once so turn on GPS, GLONASS and Galileo (or BeiDou)
clearBuffer();
SEND_UBX_PACKET(0x06, 0x11, _message_CFG_RXM_ECO, "Unable to enable powersaving ECO mode for Neo-6.\n", 500);
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "Unable to enable powersaving details for GPS.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_AID, "Unable to disable UBX-AID.\n", 500);
if (strncmp(info.hwVersion, "00070000", 8) == 0) {
LOG_DEBUG("Setting GPS+SBAS\n");
msglen = makeUBXPacket(0x06, 0x3e, sizeof(_message_GNSS_7), _message_GNSS_7);
_serial_gps->write(UBXscratch, msglen);
} else {
msglen = makeUBXPacket(0x06, 0x3e, sizeof(_message_GNSS_8), _message_GNSS_8);
_serial_gps->write(UBXscratch, msglen);
}
msglen = makeUBXPacket(0x06, 0x09, sizeof(_message_SAVE), _message_SAVE);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x09, 2000) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to save GNSS module configuration.\n");
} else {
LOG_INFO("GNSS module configuration saved!\n");
}
} else if (IS_ONE_OF(gnssModel, GNSS_MODEL_UBLOX7, GNSS_MODEL_UBLOX8, GNSS_MODEL_UBLOX9)) {
if (gnssModel == GNSS_MODEL_UBLOX7) {
LOG_DEBUG("Setting GPS+SBAS\n");
msglen = makeUBXPacket(0x06, 0x3e, sizeof(_message_GNSS_7), _message_GNSS_7);
_serial_gps->write(UBXscratch, msglen);
} else { // 8,9
msglen = makeUBXPacket(0x06, 0x3e, sizeof(_message_GNSS_8), _message_GNSS_8);
_serial_gps->write(UBXscratch, msglen);
}
if (getACK(0x06, 0x3e, 800) == GNSS_RESPONSE_NAK) {
// It's not critical if the module doesn't acknowledge this configuration.
LOG_INFO("Unable to reconfigure GNSS - defaults maintained. Is this module GPS-only?\n");
} else {
if (strncmp(info.hwVersion, "00070000", 8) == 0) {
LOG_INFO("GNSS configured for GPS+SBAS. Pause for 0.75s before sending next command.\n");
} else {
LOG_INFO(
"GNSS configured for GPS+SBAS+GLONASS+Galileo. Pause for 0.75s before sending next command.\n");
}
// Documentation say, we need wait atleast 0.5s after reconfiguration of GNSS module, before sending next
// commands for the M8 it tends to be more... 1 sec should be enough ;>)
delay(1000);
}
if (getACK(0x06, 0x3e, 800) == GNSS_RESPONSE_NAK) {
// It's not critical if the module doesn't acknowledge this configuration.
LOG_INFO("Unable to reconfigure GNSS - defaults maintained. Is this module GPS-only?\n");
} else {
if (gnssModel == GNSS_MODEL_UBLOX7) {
LOG_INFO("GNSS configured for GPS+SBAS.\n");
} else { // 8,9
LOG_INFO("GNSS configured for GPS+SBAS+GLONASS+Galileo.\n");
}
// Disable Text Info messages
msglen = makeUBXPacket(0x06, 0x02, sizeof(_message_DISABLE_TXT_INFO), _message_DISABLE_TXT_INFO);
// Documentation say, we need wait atleast 0.5s after reconfiguration of GNSS module, before sending next
// commands for the M8 it tends to be more... 1 sec should be enough ;>)
delay(1000);
}
// Disable Text Info messages //6,7,8,9
clearBuffer();
SEND_UBX_PACKET(0x06, 0x02, _message_DISABLE_TXT_INFO, "Unable to disable text info messages.\n", 500);
if (gnssModel == GNSS_MODEL_UBLOX8) { // 8
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x02, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable text info messages.\n");
}
// ToDo add M10 tests for below
if (strncmp(info.hwVersion, "00080000", 8) == 0) {
msglen = makeUBXPacket(0x06, 0x39, sizeof(_message_JAM_8), _message_JAM_8);
SEND_UBX_PACKET(0x06, 0x39, _message_JAM_8, "Unable to enable interference resistance.\n", 500);
clearBuffer();
SEND_UBX_PACKET(0x06, 0x23, _message_NAVX5_8, "Unable to configure NAVX5_8 settings.\n", 500);
} else { // 6,7,9
SEND_UBX_PACKET(0x06, 0x39, _message_JAM_6_7, "Unable to enable interference resistance.\n", 500);
SEND_UBX_PACKET(0x06, 0x23, _message_NAVX5, "Unable to configure NAVX5 settings.\n", 500);
}
// Turn off unwanted NMEA messages, set update rate
SEND_UBX_PACKET(0x06, 0x08, _message_1HZ, "Unable to set GPS update rate.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_GLL, "Unable to disable NMEA GLL.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_GSA, "Unable to Enable NMEA GSA.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_GSV, "Unable to disable NMEA GSV.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_VTG, "Unable to disable NMEA VTG.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_RMC, "Unable to enable NMEA RMC.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_GGA, "Unable to enable NMEA GGA.\n", 500);
if (uBloxProtocolVersion >= 18) {
clearBuffer();
SEND_UBX_PACKET(0x06, 0x86, _message_PMS, "Unable to enable powersaving for GPS.\n", 500);
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "Unable to enable powersaving details for GPS.\n", 500);
// For M8 we want to enable NMEA vserion 4.10 so we can see the additional sats.
if (gnssModel == GNSS_MODEL_UBLOX8) {
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x39, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable interference resistance.\n");
}
msglen = makeUBXPacket(0x06, 0x23, sizeof(_message_NAVX5_8), _message_NAVX5_8);
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x23, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to configure NAVX5_8 settings.\n");
}
} else {
msglen = makeUBXPacket(0x06, 0x39, sizeof(_message_JAM_6_7), _message_JAM_6_7);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x39, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable interference resistance.\n");
}
msglen = makeUBXPacket(0x06, 0x23, sizeof(_message_NAVX5), _message_NAVX5);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x23, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to configure NAVX5 settings.\n");
}
}
// Turn off unwanted NMEA messages, set update rate
msglen = makeUBXPacket(0x06, 0x08, sizeof(_message_1HZ), _message_1HZ);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x08, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to set GPS update rate.\n");
}
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GLL), _message_GLL);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable NMEA GLL.\n");
}
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GSA), _message_GSA);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to Enable NMEA GSA.\n");
}
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GSV), _message_GSV);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable NMEA GSV.\n");
}
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_VTG), _message_VTG);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable NMEA VTG.\n");
}
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_RMC), _message_RMC);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable NMEA RMC.\n");
}
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GGA), _message_GGA);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable NMEA GGA.\n");
}
if (uBloxProtocolVersion >= 18) {
msglen = makeUBXPacket(0x06, 0x86, sizeof(_message_PMS), _message_PMS);
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x86, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving for GPS.\n");
}
msglen = makeUBXPacket(0x06, 0x3B, sizeof(_message_CFG_PM2), _message_CFG_PM2);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x3B, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving details for GPS.\n");
}
// For M8 we want to enable NMEA vserion 4.10 so we can see the additional sats.
if (strncmp(info.hwVersion, "00080000", 8) == 0) {
msglen = makeUBXPacket(0x06, 0x17, sizeof(_message_NMEA), _message_NMEA);
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x17, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable NMEA 4.10.\n");
}
}
} else {
if (strncmp(info.hwVersion, "00040007", 8) == 0) { // This PSM mode is only for Neo-6
msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_ECO);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x11, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving ECO mode for Neo-6.\n");
}
msglen = makeUBXPacket(0x06, 0x3B, sizeof(_message_CFG_PM2), _message_CFG_PM2);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x3B, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving details for GPS.\n");
}
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_AID), _message_AID);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable UBX-AID.\n");
}
} else {
msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_PSM);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x11, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving mode for GPS.\n");
}
msglen = makeUBXPacket(0x06, 0x3B, sizeof(_message_CFG_PM2), _message_CFG_PM2);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x3B, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving details for GPS.\n");
}
}
SEND_UBX_PACKET(0x06, 0x17, _message_NMEA, "Unable to enable NMEA 4.10.\n", 500);
}
} else {
// LOG_INFO("u-blox M10 hardware found.\n");
delay(1000);
// First disable all NMEA messages in RAM layer
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_NMEA_RAM), _message_VALSET_DISABLE_NMEA_RAM);
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable NMEA messages for M10 GPS RAM.\n");
}
delay(250);
// Next disable unwanted NMEA messages in BBR layer
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_NMEA_BBR), _message_VALSET_DISABLE_NMEA_BBR);
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable NMEA messages for M10 GPS BBR.\n");
}
delay(250);
// Disable Info txt messages in RAM layer
msglen =
makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_TXT_INFO_RAM), _message_VALSET_DISABLE_TXT_INFO_RAM);
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable Info messages for M10 GPS RAM.\n");
}
delay(250);
// Next disable Info txt messages in BBR layer
msglen =
makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_TXT_INFO_BBR), _message_VALSET_DISABLE_TXT_INFO_BBR);
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable Info messages for M10 GPS BBR.\n");
}
// Do M10 configuration for Power Management.
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_PM_RAM), _message_VALSET_PM_RAM);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving for M10 GPS RAM.\n");
}
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_PM_BBR), _message_VALSET_PM_BBR);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving for M10 GPS BBR.\n");
}
delay(250);
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_ITFM_RAM), _message_VALSET_ITFM_RAM);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable Jamming detection M10 GPS RAM.\n");
}
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_ITFM_BBR), _message_VALSET_ITFM_BBR);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable Jamming detection M10 GPS BBR.\n");
}
// Here is where the init commands should go to do further M10 initialization.
delay(250);
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_SBAS_RAM), _message_VALSET_DISABLE_SBAS_RAM);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable SBAS M10 GPS RAM.\n");
}
delay(750); // will cause a receiver restart so wait a bit
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_SBAS_BBR), _message_VALSET_DISABLE_SBAS_BBR);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable SBAS M10 GPS BBR.\n");
}
delay(750); // will cause a receiver restart so wait a bit
// Done with initialization, Now enable wanted NMEA messages in BBR layer so they will survive a periodic sleep.
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_ENABLE_NMEA_BBR), _message_VALSET_ENABLE_NMEA_BBR);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable messages for M10 GPS BBR.\n");
}
delay(250);
// Next enable wanted NMEA messages in RAM layer
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_ENABLE_NMEA_RAM), _message_VALSET_ENABLE_NMEA_RAM);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable messages for M10 GPS RAM.\n");
}
// As the M10 has no flash, the best we can do to preserve the config is to set it in RAM and BBR.
// BBR will survive a restart, and power off for a while, but modules with small backup
// batteries or super caps will not retain the config for a long power off time.
SEND_UBX_PACKET(0x06, 0x11, _message_CFG_RXM_PSM, "Unable to enable powersaving mode for GPS.\n", 500);
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "Unable to enable powersaving details for GPS.\n", 500);
}
msglen = makeUBXPacket(0x06, 0x09, sizeof(_message_SAVE), _message_SAVE);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x09, 2000) != GNSS_RESPONSE_OK) {
@@ -794,6 +624,55 @@ bool GPS::setup()
} else {
LOG_INFO("GNSS module configuration saved!\n");
}
} else if (gnssModel == GNSS_MODEL_UBLOX10) {
delay(1000);
clearBuffer();
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_NMEA_RAM, "Unable to disable NMEA messages in M10 RAM.\n", 300);
delay(750);
clearBuffer();
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_NMEA_BBR, "Unable to disable NMEA messages in M10 BBR.\n", 300);
delay(750);
clearBuffer();
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_TXT_INFO_RAM,
"Unable to disable Info messages for M10 GPS RAM.\n", 300);
delay(750);
// Next disable Info txt messages in BBR layer
clearBuffer();
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_TXT_INFO_BBR,
"Unable to disable Info messages for M10 GPS BBR.\n", 300);
delay(750);
// Do M10 configuration for Power Management.
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_PM_RAM, "Unable to enable powersaving for M10 GPS RAM.\n", 300);
delay(750);
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_PM_BBR, "Unable to enable powersaving for M10 GPS BBR.\n", 300);
delay(750);
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ITFM_RAM, "Unable to enable Jamming detection M10 GPS RAM.\n", 300);
delay(750);
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ITFM_BBR, "Unable to enable Jamming detection M10 GPS BBR.\n", 300);
delay(750);
// Here is where the init commands should go to do further M10 initialization.
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_SBAS_RAM, "Unable to disable SBAS M10 GPS RAM.\n", 300);
delay(750); // will cause a receiver restart so wait a bit
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_SBAS_BBR, "Unable to disable SBAS M10 GPS BBR.\n", 300);
delay(750); // will cause a receiver restart so wait a bit
// Done with initialization, Now enable wanted NMEA messages in BBR layer so they will survive a periodic sleep.
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ENABLE_NMEA_BBR, "Unable to enable messages for M10 GPS BBR.\n", 300);
delay(750);
// Next enable wanted NMEA messages in RAM layer
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ENABLE_NMEA_RAM, "Unable to enable messages for M10 GPS RAM.\n", 500);
delay(750);
// As the M10 has no flash, the best we can do to preserve the config is to set it in RAM and BBR.
// BBR will survive a restart, and power off for a while, but modules with small backup
// batteries or super caps will not retain the config for a long power off time.
msglen = makeUBXPacket(0x06, 0x09, sizeof(_message_SAVE_10), _message_SAVE_10);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x09, 2000) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to save GNSS module configuration.\n");
} else {
LOG_INFO("GNSS module configuration saved!\n");
}
}
didSerialInit = true;
}
@@ -949,7 +828,7 @@ void GPS::setPowerPMU(bool on)
void GPS::setPowerUBLOX(bool on, uint32_t sleepMs)
{
// Abort: if not UBLOX hardware
if (gnssModel != GNSS_MODEL_UBLOX)
if (!IS_ONE_OF(gnssModel, GNSS_MODEL_UBLOX6, GNSS_MODEL_UBLOX7, GNSS_MODEL_UBLOX8, GNSS_MODEL_UBLOX9, GNSS_MODEL_UBLOX10))
return;
// If waking
@@ -972,7 +851,7 @@ void GPS::setPowerUBLOX(bool on, uint32_t sleepMs)
}
// Determine hardware version
if (strncmp(info.hwVersion, "000A0000", 8) != 0) {
if (gnssModel == GNSS_MODEL_UBLOX10) {
// Encode the sleep time in millis into the packet
for (int i = 0; i < 4; i++)
gps->_message_PMREQ[0 + i] = sleepMs >> (i * 8);
@@ -1031,26 +910,29 @@ void GPS::down()
// Check whether the GPS hardware is capable of GPS_SOFTSLEEP
// If not, fallback to GPS_HARDSLEEP instead
bool softsleepSupported = false;
if (gnssModel == GNSS_MODEL_UBLOX) // U-blox is supported via PMREQ
// U-blox is supported via PMREQ
if (IS_ONE_OF(gnssModel, GNSS_MODEL_UBLOX6, GNSS_MODEL_UBLOX7, GNSS_MODEL_UBLOX8, GNSS_MODEL_UBLOX9, GNSS_MODEL_UBLOX10))
softsleepSupported = true;
#ifdef PIN_GPS_STANDBY // L76B, L76K and clones have a standby pin
softsleepSupported = true;
#endif
// How long does gps_update_interval need to be, for GPS_HARDSLEEP to become more efficient than GPS_SOFTSLEEP?
// Heuristic equation. A compromise manually fitted to power observations from U-blox NEO-6M and M10050
// https://www.desmos.com/calculator/6gvjghoumr
// This is not particularly accurate, but probably an impromevement over a single, fixed threshold
uint32_t hardsleepThreshold = (2750 * pow(predictedSearchDuration / 1000, 1.22));
LOG_DEBUG("gps_update_interval >= %us needed to justify hardsleep\n", hardsleepThreshold / 1000);
// If update interval too short: softsleep (if supported by hardware)
if (softsleepSupported && updateInterval < hardsleepThreshold)
setPowerState(GPS_SOFTSLEEP, sleepTime);
if (softsleepSupported) {
// How long does gps_update_interval need to be, for GPS_HARDSLEEP to become more efficient than GPS_SOFTSLEEP?
// Heuristic equation. A compromise manually fitted to power observations from U-blox NEO-6M and M10050
// https://www.desmos.com/calculator/6gvjghoumr
// This is not particularly accurate, but probably an impromevement over a single, fixed threshold
uint32_t hardsleepThreshold = (2750 * pow(predictedSearchDuration / 1000, 1.22));
LOG_DEBUG("gps_update_interval >= %us needed to justify hardsleep\n", hardsleepThreshold / 1000);
// If update interval too short: softsleep (if supported by hardware)
if (updateInterval < hardsleepThreshold) {
setPowerState(GPS_SOFTSLEEP, sleepTime);
return;
}
}
// If update interval long enough (or softsleep unsupported): hardsleep instead
else
setPowerState(GPS_HARDSLEEP, sleepTime);
setPowerState(GPS_HARDSLEEP, sleepTime);
}
}
@@ -1106,7 +988,9 @@ int32_t GPS::runOnce()
// if we have received valid NMEA claim we are connected
setConnected();
} else {
if ((config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) && (gnssModel == GNSS_MODEL_UBLOX)) {
if ((config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) &&
IS_ONE_OF(gnssModel, GNSS_MODEL_UBLOX6, GNSS_MODEL_UBLOX7, GNSS_MODEL_UBLOX8, GNSS_MODEL_UBLOX9,
GNSS_MODEL_UBLOX10)) {
// reset the GPS on next bootup
if (devicestate.did_gps_reset && scheduling.elapsedSearchMs() > 60 * 1000UL && !hasFlow()) {
LOG_DEBUG("GPS is not communicating, trying factory reset on next bootup.\n");
@@ -1335,9 +1219,9 @@ GnssModel_t GPS::probe(int serialSpeed)
strncpy((char *)buffer, &(info.extension[i][4]), sizeof(buffer));
// LOG_DEBUG("GetModel:%s\n", (char *)buffer);
if (strlen((char *)buffer)) {
LOG_INFO("UBlox GNSS probe succeeded, using UBlox %s GNSS Module\n", (char *)buffer);
LOG_INFO("%s detected, using GNSS_MODEL_UBLOX\n", (char *)buffer);
} else {
LOG_INFO("UBlox GNSS probe succeeded, using UBlox GNSS Module\n");
LOG_INFO("Generic Ublox detected, using GNSS_MODEL_UBLOX\n");
}
} else if (!strncmp(info.extension[i], "PROTVER", 7)) {
char *ptr = nullptr;
@@ -1352,9 +1236,20 @@ GnssModel_t GPS::probe(int serialSpeed)
}
}
}
if (strncmp(info.hwVersion, "00040007", 8) == 0) {
return GNSS_MODEL_UBLOX6;
} else if (strncmp(info.hwVersion, "00070000", 8) == 0) {
return GNSS_MODEL_UBLOX7;
} else if (strncmp(info.hwVersion, "00080000", 8) == 0) {
return GNSS_MODEL_UBLOX8;
} else if (strncmp(info.hwVersion, "00190000", 8) == 0) {
return GNSS_MODEL_UBLOX9;
} else if (strncmp(info.hwVersion, "000A0000", 8) == 0) {
return GNSS_MODEL_UBLOX10;
}
}
return GNSS_MODEL_UBLOX;
return GNSS_MODEL_UNKNOWN;
}
GPS *GPS::createGps()
@@ -1528,16 +1423,15 @@ bool GPS::lookForTime()
#ifdef GNSS_AIROHA
uint8_t fix = reader.fixQuality();
uint32_t now = millis();
if (fix > 0) {
if (lastFixStartMsec > 0) {
if ((now - lastFixStartMsec) < GPS_FIX_HOLD_TIME) {
if (Throttle::isWithinTimespanMs(lastFixStartMsec, GPS_FIX_HOLD_TIME)) {
return false;
} else {
clearBuffer();
}
} else {
lastFixStartMsec = now;
lastFixStartMsec = millis();
return false;
}
} else {
@@ -1581,16 +1475,15 @@ bool GPS::lookForLocation()
#ifdef GNSS_AIROHA
if ((config.position.gps_update_interval * 1000) >= (GPS_FIX_HOLD_TIME * 2)) {
uint8_t fix = reader.fixQuality();
uint32_t now = millis();
if (fix > 0) {
if (lastFixStartMsec > 0) {
if ((now - lastFixStartMsec) < GPS_FIX_HOLD_TIME) {
if (Throttle::isWithinTimespanMs(lastFixStartMsec, GPS_FIX_HOLD_TIME)) {
return false;
} else {
clearBuffer();
}
} else {
lastFixStartMsec = now;
lastFixStartMsec = millis();
return false;
}
} else {
@@ -1820,4 +1713,4 @@ void GPS::toggleGpsMode()
enable();
}
}
#endif // Exclude GPS
#endif // Exclude GPS
+7 -2
View File
@@ -26,7 +26,11 @@ struct uBloxGnssModelInfo {
typedef enum {
GNSS_MODEL_ATGM336H,
GNSS_MODEL_MTK,
GNSS_MODEL_UBLOX,
GNSS_MODEL_UBLOX6,
GNSS_MODEL_UBLOX7,
GNSS_MODEL_UBLOX8,
GNSS_MODEL_UBLOX9,
GNSS_MODEL_UBLOX10,
GNSS_MODEL_UC6580,
GNSS_MODEL_UNKNOWN,
GNSS_MODEL_MTK_L76B,
@@ -130,6 +134,7 @@ class GPS : private concurrency::OSThread
static const uint8_t _message_GGA[];
static const uint8_t _message_PMS[];
static const uint8_t _message_SAVE[];
static const uint8_t _message_SAVE_10[];
// VALSET Commands for M10
static const uint8_t _message_VALSET_PM[];
@@ -310,4 +315,4 @@ class GPS : private concurrency::OSThread
};
extern GPS *gps;
#endif // Exclude GPS
#endif // Exclude GPS
+6 -5
View File
@@ -2,6 +2,7 @@
#include "configuration.h"
#include "detect/ScanI2C.h"
#include "main.h"
#include <Throttle.h>
#include <sys/time.h>
#include <time.h>
@@ -29,7 +30,7 @@ void readFromRTC()
if (rtc_found.address == RV3028_RTC) {
uint32_t now = millis();
Melopero_RV3028 rtc;
#ifdef I2C_SDA1
#if WIRE_INTERFACES_COUNT == 2
rtc.initI2C(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
#else
rtc.initI2C();
@@ -58,7 +59,7 @@ void readFromRTC()
uint32_t now = millis();
PCF8563_Class rtc;
#ifdef I2C_SDA1
#if WIRE_INTERFACES_COUNT == 2
rtc.begin(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
#else
rtc.begin();
@@ -127,7 +128,7 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate)
} else if (q == RTCQualityGPS) {
shouldSet = true;
LOG_DEBUG("Reapplying GPS time: %ld secs\n", printableEpoch);
} else if (q == RTCQualityNTP && (now - lastSetMsec) > (12 * 60 * 60 * 1000UL)) {
} else if (q == RTCQualityNTP && !Throttle::isWithinTimespanMs(lastSetMsec, (12 * 60 * 60 * 1000UL))) {
// Every 12 hrs we will slam in a new NTP or Phone GPS / NTP time, to correct for local RTC clock drift
shouldSet = true;
LOG_DEBUG("Reapplying external time to correct clock drift %ld secs\n", printableEpoch);
@@ -150,7 +151,7 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate)
#ifdef RV3028_RTC
if (rtc_found.address == RV3028_RTC) {
Melopero_RV3028 rtc;
#ifdef I2C_SDA1
#if WIRE_INTERFACES_COUNT == 2
rtc.initI2C(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
#else
rtc.initI2C();
@@ -164,7 +165,7 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate)
if (rtc_found.address == PCF8563_RTC) {
PCF8563_Class rtc;
#ifdef I2C_SDA1
#if WIRE_INTERFACES_COUNT == 2
rtc.begin(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
#else
rtc.begin();
+39 -25
View File
@@ -1,3 +1,10 @@
#define SEND_UBX_PACKET(TYPE, ID, DATA, ERRMSG, TIMEOUT) \
msglen = makeUBXPacket(TYPE, ID, sizeof(DATA), DATA); \
_serial_gps->write(UBXscratch, msglen); \
if (getACK(TYPE, ID, TIMEOUT) != GNSS_RESPONSE_OK) { \
LOG_WARN(#ERRMSG); \
}
// Power Management
uint8_t GPS::_message_PMREQ[] PROGMEM = {
@@ -316,6 +323,13 @@ const uint8_t GPS::_message_SAVE[] = {
0x17 // deviceMask: BBR, Flash, EEPROM, and SPI Flash
};
const uint8_t GPS::_message_SAVE_10[] = {
0x00, 0x00, 0x00, 0x00, // clearMask: no sections cleared
0xFF, 0xFF, 0x00, 0x00, // saveMask: save all sections
0x00, 0x00, 0x00, 0x00, // loadMask: no sections loaded
0x01 // deviceMask: only save to BBR
};
// As the M10 has no flash, the best we can do to preserve the config is to set it in RAM and BBR.
// BBR will survive a restart, and power off for a while, but modules with small backup
// batteries or super caps will not retain the config for a long power off time.
@@ -335,36 +349,36 @@ const uint8_t GPS::_message_SAVE[] = {
// has details on low-power modes
/*
CFG-PM2 has been replaced by many CFG-PM commands
CFG-PMS has been removed
CFG-PM-OPERATEMODE E1 (0 | 1 | 2) -> 1 (PSMOO), because sporadic position updates are required instead of continous tracking <10s
(PSMCT) CFG-PM-POSUPDATEPERIOD U4 -> 0ms, no self-timed wakup because receiver power mode is controlled via "software standby
mode" by legacy UBX-RXM-PMREQ request CFG-PM-ACQPERIOD U4 -> 0ms, because receiver power mode is controlled via "software standby
mode" by legacy UBX-RXM-PMREQ request CFG-PM-ONTIME U4 -> 0ms, optional I guess CFG-PM-EXTINTBACKUP L -> 1, force receiver into
BACKUP mode when EXTINT (should be connected to GPS_EN_PIN) pin is "low"
This is required because the receiver never enters low power mode if microcontroller is in deep-sleep.
Maybe the changing UART_RX levels trigger a wakeup but even with UBX-RXM-PMREQ[12] = 0x00 (all external wakeup sources disabled)
the receivcer remains in aquisition state -> potentially a bug
Workaround: Control the EXTINT pin by the GPS_EN_PIN signal
As mentioned in the M10 operational issues down below, power save won't allow the use of BDS B1C.
CFG-SIGNAL-BDS_B1C_ENA L -> 0
OPERATEMODE E1 2 (0 | 1 | 2)
POSUPDATEPERIOD U4 5
ACQPERIOD U4 10
GRIDOFFSET U4 0
ONTIME U2 1
MINACQTIME U1 0
MAXACQTIME U1 0
DONOTENTEROFF L 1
WAITTIMEFIX L 1
UPDATEEPH L 1
EXTINTWAKE L 0 no ext ints
EXTINTBACKUP L 0 no ext ints
EXTINTINACTIVE L 0 no ext ints
EXTINTACTIVITY U4 0 no ext ints
LIMITPEAKCURRENT L 1
// Ram layer config message:
// 01 01 00 00 01 00 D0 20 01 02 00 D0 40 00 00 00 00 03 00 D0 40 00 00 00 00 05 00 D0 30 00 00 0D 00 D0 10 01
// b5 62 06 8a 26 00 00 01 00 00 01 00 d0 20 02 02 00 d0 40 05 00 00 00 05 00 d0 30 01 00 08 00 d0 10 01 09 00 d0 10 01 10 00 d0
// 10 01 8b de
// BBR layer config message:
// 01 02 00 00 01 00 D0 20 01 02 00 D0 40 00 00 00 00 03 00 D0 40 00 00 00 00 05 00 D0 30 00 00 0D 00 D0 10 01
// b5 62 06 8a 26 00 00 02 00 00 01 00 d0 20 02 02 00 d0 40 05 00 00 00 05 00 d0 30 01 00 08 00 d0 10 01 09 00 d0 10 01 10 00 d0
// 10 01 8c 03
*/
const uint8_t GPS::_message_VALSET_PM_RAM[] = {0x01, 0x01, 0x00, 0x00, 0x0F, 0x00, 0x31, 0x10, 0x00, 0x01, 0x00, 0xD0, 0x20, 0x01,
0x02, 0x00, 0xD0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xD0, 0x40, 0x00, 0x00,
0x00, 0x00, 0x05, 0x00, 0xD0, 0x30, 0x00, 0x00, 0x0D, 0x00, 0xD0, 0x10, 0x01};
const uint8_t GPS::_message_VALSET_PM_BBR[] = {0x01, 0x02, 0x00, 0x00, 0x0F, 0x00, 0x31, 0x10, 0x00, 0x01, 0x00, 0xD0, 0x20, 0x01,
0x02, 0x00, 0xD0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xD0, 0x40, 0x00, 0x00,
0x00, 0x00, 0x05, 0x00, 0xD0, 0x30, 0x00, 0x00, 0x0D, 0x00, 0xD0, 0x10, 0x01};
const uint8_t GPS::_message_VALSET_PM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40,
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0,
0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01};
const uint8_t GPS::_message_VALSET_PM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40,
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0,
0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01};
/*
CFG-ITFM replaced by 5 valset messages which can be combined into one for RAM and one for BBR
+4 -5
View File
@@ -1,3 +1,4 @@
#include "Throttle.h"
#include "configuration.h"
#if defined(USE_EINK) && defined(USE_EINK_DYNAMICDISPLAY)
@@ -231,15 +232,13 @@ void EInkDynamicDisplay::checkForPromotion()
// Is it too soon for another frame of this type?
void EInkDynamicDisplay::checkRateLimiting()
{
uint32_t now = millis();
// Sanity check: millis() overflow - just let the update run..
if (previousRunMs > now)
if (previousRunMs > millis())
return;
// Skip update: too soon for BACKGROUND
if (frameFlags == BACKGROUND) {
if (now - previousRunMs < EINK_LIMIT_RATE_BACKGROUND_SEC * 1000) {
if (Throttle::isWithinTimespanMs(previousRunMs, EINK_LIMIT_RATE_BACKGROUND_SEC * 1000)) {
refresh = SKIPPED;
reason = EXCEEDED_RATELIMIT_FULL;
return;
@@ -252,7 +251,7 @@ void EInkDynamicDisplay::checkRateLimiting()
// Skip update: too soon for RESPONSIVE
if (frameFlags & RESPONSIVE) {
if (now - previousRunMs < EINK_LIMIT_RATE_RESPONSIVE_SEC * 1000) {
if (Throttle::isWithinTimespanMs(previousRunMs, EINK_LIMIT_RATE_RESPONSIVE_SEC * 1000)) {
refresh = SKIPPED;
reason = EXCEEDED_RATELIMIT_FAST;
LOG_DEBUG("refresh=SKIPPED, reason=EXCEEDED_RATELIMIT_FAST, frameFlags=0x%x\n", frameFlags);
+73 -28
View File
@@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "Screen.h"
#include "../userPrefs.h"
#include "PowerMon.h"
#include "Throttle.h"
#include "configuration.h"
#if HAS_SCREEN
#include <OLEDDisplay.h>
@@ -47,6 +48,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "modules/AdminModule.h"
#include "modules/ExternalNotificationModule.h"
#include "modules/TextMessageModule.h"
#include "modules/WaypointModule.h"
#include "sleep.h"
#include "target_specific.h"
@@ -56,10 +58,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef ARCH_ESP32
#include "esp_task_wdt.h"
#include "modules/esp32/StoreForwardModule.h"
#include "modules/StoreForwardModule.h"
#endif
#if ARCH_PORTDUINO
#include "modules/StoreForwardModule.h"
#include "platform/portduino/PortduinoGlue.h"
#endif
@@ -117,6 +120,7 @@ static bool heartbeat = false;
#define SCREEN_HEIGHT display->getHeight()
#include "graphics/ScreenFonts.h"
#include <Throttle.h>
#define getStringCenteredX(s) ((SCREEN_WIDTH - display->getStringWidth(s)) / 2)
@@ -1004,55 +1008,55 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
display->setColor(WHITE);
#ifndef EXCLUDE_EMOJI
if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"\U0001F44D") == 0) {
if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F44D") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - thumbs_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - thumbs_height) / 2 + 2 + 5, thumbs_width, thumbs_height,
thumbup);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"\U0001F44E") == 0) {
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F44E") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - thumbs_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - thumbs_height) / 2 + 2 + 5, thumbs_width, thumbs_height,
thumbdown);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"❓") == 0) {
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "❓") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - question_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - question_height) / 2 + 2 + 5, question_width, question_height,
question);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"‼️") == 0) {
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "‼️") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - bang_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - bang_height) / 2 + 2 + 5,
bang_width, bang_height, bang);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"\U0001F4A9") == 0) {
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F4A9") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - poo_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - poo_height) / 2 + 2 + 5,
poo_width, poo_height, poo);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\xf0\x9f\xa4\xa3") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - haha_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - haha_height) / 2 + 2 + 5,
haha_width, haha_height, haha);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"\U0001F44B") == 0) {
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F44B") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - wave_icon_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - wave_icon_height) / 2 + 2 + 5, wave_icon_width,
wave_icon_height, wave_icon);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"\U0001F920") == 0) {
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F920") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - cowboy_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - cowboy_height) / 2 + 2 + 5, cowboy_width, cowboy_height,
cowboy);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"\U0001F42D") == 0) {
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F42D") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - deadmau5_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - deadmau5_height) / 2 + 2 + 5, deadmau5_width, deadmau5_height,
deadmau5);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"\xE2\x98\x80\xEF\xB8\x8F") == 0) {
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\xE2\x98\x80\xEF\xB8\x8F") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - sun_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - sun_height) / 2 + 2 + 5,
sun_width, sun_height, sun);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"\u2614") == 0) {
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\u2614") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - rain_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - rain_height) / 2 + 2 + 10,
rain_width, rain_height, rain);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"☁️") == 0) {
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "☁️") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - cloud_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - cloud_height) / 2 + 2 + 5, cloud_width, cloud_height, cloud);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"🌫️") == 0) {
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "🌫️") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - fog_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - fog_height) / 2 + 2 + 5,
fog_width, fog_height, fog);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"\xf0\x9f\x98\x88") == 0) {
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\xf0\x9f\x98\x88") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - devil_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - devil_height) / 2 + 2 + 5, devil_width, devil_height, devil);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"♥️") == 0) {
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "♥️") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - heart_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - heart_height) / 2 + 2 + 5, heart_width, heart_height, heart);
} else {
@@ -1949,7 +1953,7 @@ int32_t Screen::runOnce()
if (showingNormalScreen) {
// standard screen loop handling here
if (config.display.auto_screen_carousel_secs > 0 &&
(millis() - lastScreenTransition) > (config.display.auto_screen_carousel_secs * 1000)) {
!Throttle::isWithinTimespanMs(lastScreenTransition, config.display.auto_screen_carousel_secs * 1000)) {
// If an E-Ink display struggles with fast refresh, force carousel to use full refresh instead
// Carousel is potentially a major source of E-Ink display wear
@@ -2110,8 +2114,13 @@ void Screen::setFrames(FrameFocus focus)
// Check if the module being drawn has requested focus
// We will honor this request later, if setFrames was triggered by a UIFrameEvent
MeshModule *m = *i;
if (m->isRequestingFocus())
if (m->isRequestingFocus()) {
fsi.positions.focusedModule = numframes;
}
// Identify the position of specific modules, if we need to know this later
if (m == waypointModule)
fsi.positions.waypoint = numframes;
numframes++;
}
@@ -2130,8 +2139,8 @@ void Screen::setFrames(FrameFocus focus)
#endif
// If we have a text message - show it next, unless it's a phone message and we aren't using any special modules
fsi.positions.textMessage = numframes;
if (devicestate.has_rx_text_message && shouldDrawMessage(&devicestate.rx_text_message)) {
fsi.positions.textMessage = numframes;
normalFrames[numframes++] = drawTextMessageFrame;
}
@@ -2193,7 +2202,7 @@ void Screen::setFrames(FrameFocus focus)
case FOCUS_PRESERVE:
// If we can identify which type of frame "originalPosition" was, can move directly to it in the new frameset
FramesetInfo &oldFsi = this->framesetInfo;
const FramesetInfo &oldFsi = this->framesetInfo;
if (originalPosition == oldFsi.positions.log)
ui->switchToFrame(fsi.positions.log);
else if (originalPosition == oldFsi.positions.settings)
@@ -2233,6 +2242,31 @@ void Screen::setFrameImmediateDraw(FrameCallback *drawFrames)
setFastFramerate();
}
// Dismisses the currently displayed screen frame, if possible
// Relevant for text message, waypoint, others in future?
// Triggered with a CardKB keycombo
void Screen::dismissCurrentFrame()
{
uint8_t currentFrame = ui->getUiState()->currentFrame;
bool dismissed = false;
if (currentFrame == framesetInfo.positions.textMessage && devicestate.has_rx_text_message) {
LOG_INFO("Dismissing Text Message\n");
devicestate.has_rx_text_message = false;
dismissed = true;
}
else if (currentFrame == framesetInfo.positions.waypoint && devicestate.has_rx_waypoint) {
LOG_DEBUG("Dismissing Waypoint\n");
devicestate.has_rx_waypoint = false;
dismissed = true;
}
// If we did make changes to dismiss, we now need to regenerate the frameset
if (dismissed)
setFrames();
}
void Screen::handleStartFirmwareUpdateScreen()
{
LOG_DEBUG("showing firmware screen\n");
@@ -2442,8 +2476,8 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
// Draw our hardware ID to assist with bluetooth pairing. Either prefix with Info or S&F Logo
if (moduleConfig.store_forward.enabled) {
#ifdef ARCH_ESP32
if (millis() - storeForwardModule->lastHeartbeat >
(storeForwardModule->heartbeatInterval * 1200)) { // no heartbeat, overlap a bit
if (!Throttle::isWithinTimespanMs(storeForwardModule->lastHeartbeat,
(storeForwardModule->heartbeatInterval * 1200))) { // no heartbeat, overlap a bit
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || defined(ST7789_CS) || \
defined(USE_ST7789) || defined(HX8357_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
@@ -2745,12 +2779,23 @@ int Screen::handleInputEvent(const InputEvent *event)
}
#endif
if (showingNormalScreen && moduleFrames.size() == 0) {
// LOG_DEBUG("Screen::handleInputEvent from %s\n", event->source);
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) {
showPrevFrame();
} else if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT)) {
showNextFrame();
// Use left or right input from a keyboard to move between frames,
// so long as a mesh module isn't using these events for some other purpose
if (showingNormalScreen) {
// Ask any MeshModules if they're handling keyboard input right now
bool inputIntercepted = false;
for (MeshModule *module : moduleFrames) {
if (module->interceptingKeyboardInput())
inputIntercepted = true;
}
// If no modules are using the input, move between frames
if (!inputIntercepted) {
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT))
showPrevFrame();
else if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT))
showNextFrame();
}
}
@@ -2778,4 +2823,4 @@ int Screen::handleAdminMessage(const meshtastic_AdminMessage *arg)
} // namespace graphics
#else
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
#endif // HAS_SCREEN
#endif // HAS_SCREEN
+7 -1
View File
@@ -454,6 +454,9 @@ class Screen : public concurrency::OSThread
void setWelcomeFrames();
// Dismiss the currently focussed frame, if possible (e.g. text message, waypoint)
void dismissCurrentFrame();
#ifdef USE_EINK
/// Draw an image to remain on E-Ink display after screen off
void setScreensaverFrames(FrameCallback einkScreensaver = NULL);
@@ -503,11 +506,14 @@ class Screen : public concurrency::OSThread
void handleStartFirmwareUpdateScreen();
// Info collected by setFrames method.
// Index location of specific frames. Used to apply the FrameFocus parameter of setFrames
// Index location of specific frames.
// - Used to apply the FrameFocus parameter of setFrames
// - Used to dismiss the currently shown frame (txt; waypoint) by CardKB combo
struct FramesetInfo {
struct FramePositions {
uint8_t fault = 0;
uint8_t textMessage = 0;
uint8_t waypoint = 0;
uint8_t focusedModule = 0;
uint8_t log = 0;
uint8_t settings = 0;
+4 -5
View File
@@ -1,5 +1,5 @@
#include "ExpressLRSFiveWay.h"
#include "Throttle.h"
#ifdef INPUTBROKER_EXPRESSLRSFIVEWAY_TYPE
@@ -76,11 +76,10 @@ void ExpressLRSFiveWay::update(int *keyValue, bool *keyLongPressed)
*keyValue = NO_PRESS;
int newKey = readKey();
uint32_t now = millis();
if (keyInProcess == NO_PRESS) {
// New key down
if (newKey != NO_PRESS) {
keyDownStart = now;
keyDownStart = millis();
// DBGLN("down=%u", newKey);
}
} else {
@@ -88,7 +87,7 @@ void ExpressLRSFiveWay::update(int *keyValue, bool *keyLongPressed)
if (newKey == NO_PRESS) {
// DBGLN("up=%u", keyInProcess);
if (!isLongPressed) {
if ((now - keyDownStart) > KEY_DEBOUNCE_MS) {
if (!Throttle::isWithinTimespanMs(keyDownStart, KEY_DEBOUNCE_MS)) {
*keyValue = keyInProcess;
*keyLongPressed = false;
}
@@ -101,7 +100,7 @@ void ExpressLRSFiveWay::update(int *keyValue, bool *keyLongPressed)
}
// else still pressing, waiting for long if not already signaled
else if (!isLongPressed) {
if ((now - keyDownStart) > KEY_LONG_PRESS_MS) {
if (!Throttle::isWithinTimespanMs(keyDownStart, KEY_LONG_PRESS_MS)) {
*keyValue = keyInProcess;
*keyLongPressed = true;
isLongPressed = true;
+1
View File
@@ -11,6 +11,7 @@
#define INPUT_BROKER_MSG_GPS_TOGGLE 0x9e
#define INPUT_BROKER_MSG_MUTE_TOGGLE 0xac
#define INPUT_BROKER_MSG_SEND_PING 0xaf
#define INPUT_BROKER_MSG_DISMISS_FRAME 0x8b
#define INPUT_BROKER_MSG_LEFT 0xb4
#define INPUT_BROKER_MSG_UP 0xb5
#define INPUT_BROKER_MSG_DOWN 0xb6
+3 -2
View File
@@ -6,6 +6,7 @@
#include "ScanAndSelect.h"
#include "modules/CannedMessageModule.h"
#include <Throttle.h>
// Config
static const char name[] = "scanAndSelect"; // should match "allow input source" string
@@ -75,7 +76,7 @@ int32_t ScanAndSelectInput::runOnce()
else {
// Duration enough for long press
// Long press not yet fired (prevent repeat firing while held)
if (!longPressFired && now - downSinceMs > durationLongMs) {
if (!longPressFired && Throttle::isWithinTimespanMs(downSinceMs, durationLongMs)) {
longPressFired = true;
longPress();
}
@@ -91,7 +92,7 @@ int32_t ScanAndSelectInput::runOnce()
// Long press event didn't already fire
if (held && !longPressFired) {
// Duration enough for short press
if (now - downSinceMs > durationShortMs) {
if (!Throttle::isWithinTimespanMs(downSinceMs, durationShortMs)) {
shortPress();
}
}
+2 -1
View File
@@ -1,5 +1,6 @@
#include "SerialKeyboard.h"
#include "configuration.h"
#include <Throttle.h>
#ifdef INPUTBROKER_SERIAL_TYPE
#define CANNED_MESSAGE_MODULE_ENABLE 1 // in case it's not set in the variant file
@@ -73,7 +74,7 @@ int32_t SerialKeyboard::runOnce()
// Serial.print ("X");
// Serial.println (shiftRegister2, BIN);
if (millis() - lastPressTime > 500) {
if (!Throttle::isWithinTimespanMs(lastPressTime, 500)) {
quickPress = 0;
}
+1 -1
View File
@@ -16,7 +16,7 @@ void CardKbI2cImpl::init()
uint8_t i2caddr_asize = 3;
auto i2cScanner = std::unique_ptr<ScanI2CTwoWire>(new ScanI2CTwoWire());
#if defined(I2C_SDA1)
#if WIRE_INTERFACES_COUNT == 2
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE1, i2caddr_scan, i2caddr_asize);
#endif
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE, i2caddr_scan, i2caddr_asize);
+2 -1
View File
@@ -33,7 +33,7 @@ int32_t KbI2cBase::runOnce()
if (!i2cBus) {
switch (cardkb_found.port) {
case ScanI2C::WIRE1:
#ifdef I2C_SDA1
#if WIRE_INTERFACES_COUNT == 2
LOG_DEBUG("Using I2C Bus 1 (the second one)\n");
i2cBus = &Wire1;
if (cardkb_found.address == BBQ10_KB_ADDR) {
@@ -296,6 +296,7 @@ int32_t KbI2cBase::runOnce()
case 0xac: // fn+m INPUT_BROKER_MSG_MUTE_TOGGLE
case 0x9e: // fn+g INPUT_BROKER_MSG_GPS_TOGGLE
case 0xaf: // fn+space INPUT_BROKER_MSG_SEND_PING
case 0x8b: // fn+del INPUT_BROKEN_MSG_DISMISS_FRAME
// just pass those unmodified
e.inputEvent = ANYKEY;
e.kbchar = c;
+56 -39
View File
@@ -11,16 +11,16 @@
#include "airtime.h"
#include "buzz.h"
#include "error.h"
#include "power.h"
// #include "debug.h"
#include "FSCommon.h"
#include "Led.h"
#include "RTC.h"
#include "SPILock.h"
#include "Throttle.h"
#include "concurrency/OSThread.h"
#include "concurrency/Periodic.h"
#include "detect/ScanI2C.h"
#include "error.h"
#include "power.h"
#if !MESHTASTIC_EXCLUDE_I2C
#include "detect/ScanI2CTwoWire.h"
@@ -32,13 +32,13 @@
#include "graphics/Screen.h"
#include "main.h"
#include "mesh/generated/meshtastic/config.pb.h"
#include "meshUtils.h"
#include "modules/Modules.h"
#include "shutdown.h"
#include "sleep.h"
#include "target_specific.h"
#include <memory>
#include <utility>
// #include <driver/rtc_io.h>
#ifdef ARCH_ESP32
#if !MESHTASTIC_EXCLUDE_WEBSERVER
@@ -72,6 +72,7 @@ NRF52Bluetooth *nrf52Bluetooth = nullptr;
#include "LLCC68Interface.h"
#include "LR1110Interface.h"
#include "LR1120Interface.h"
#include "LR1121Interface.h"
#include "RF95Interface.h"
#include "SX1262Interface.h"
#include "SX1268Interface.h"
@@ -102,8 +103,8 @@ NRF52Bluetooth *nrf52Bluetooth = nullptr;
#include "AmbientLightingThread.h"
#include "PowerFSMThread.h"
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#include "AccelerometerThread.h"
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
#include "motion/AccelerometerThread.h"
AccelerometerThread *accelerometerThread = nullptr;
#endif
@@ -322,15 +323,19 @@ void setup()
#ifdef BUTTON_PIN
#ifdef ARCH_ESP32
// If the button is connected to GPIO 12, don't enable the ability to use
// meshtasticAdmin on the device.
pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT);
#if ESP_ARDUINO_VERSION_MAJOR >= 3
#ifdef BUTTON_NEED_PULLUP
pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT_PULLUP);
#else
pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT); // default to BUTTON_PIN
#endif
#else
pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT); // default to BUTTON_PIN
#ifdef BUTTON_NEED_PULLUP
gpio_pullup_en((gpio_num_t)(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN));
delay(10);
#endif
#endif
#endif
#endif
@@ -360,6 +365,8 @@ void setup()
Wire1.begin();
#elif defined(I2C_SDA1) && !defined(ARCH_RP2040)
Wire1.begin(I2C_SDA1, I2C_SCL1);
#elif WIRE_INTERFACES_COUNT == 2
Wire1.begin();
#endif
#if defined(I2C_SDA) && defined(ARCH_RP2040)
@@ -427,6 +434,8 @@ void setup()
#elif defined(I2C_SDA1) && !defined(ARCH_RP2040)
Wire1.begin(I2C_SDA1, I2C_SCL1);
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE1);
#elif defined(NRF52840_XXAA) && (WIRE_INTERFACES_COUNT == 2)
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE1);
#endif
#if defined(I2C_SDA) && defined(ARCH_RP2040)
@@ -552,6 +561,7 @@ void setup()
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA260, meshtastic_TelemetrySensorType_INA260)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA219, meshtastic_TelemetrySensorType_INA219)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA3221, meshtastic_TelemetrySensorType_INA3221)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MAX17048, meshtastic_TelemetrySensorType_MAX17048)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHT31, meshtastic_TelemetrySensorType_SHT31)
@@ -570,6 +580,7 @@ void setup()
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHT4X, meshtastic_TelemetrySensorType_SHT4X)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::AHT10, meshtastic_TelemetrySensorType_AHT10)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::DFROBOT_LARK, meshtastic_TelemetrySensorType_DFROBOT_LARK)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::ICM20948, meshtastic_TelemetrySensorType_ICM20948)
i2cScanner.reset();
#endif
@@ -621,7 +632,13 @@ void setup()
buttonThread = new ButtonThread();
#endif
playStartMelody();
// only play start melody when role is not tracker or sensor
if (config.power.is_power_saving == true &&
IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_TRACKER,
meshtastic_Config_DeviceConfig_Role_TAK_TRACKER, meshtastic_Config_DeviceConfig_Role_SENSOR))
LOG_DEBUG("Tracker/Sensor: Skipping start melody\n");
else
playStartMelody();
// fixed screen override?
if (config.display.oled != meshtastic_Config_DisplayConfig_OledType_OLED_AUTO)
@@ -637,7 +654,7 @@ void setup()
#endif
#if !MESHTASTIC_EXCLUDE_I2C
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
if (acc_info.type != ScanI2C::DeviceType::NONE) {
accelerometerThread = new AccelerometerThread(acc_info.type);
}
@@ -869,7 +886,7 @@ void setup()
#endif
#if defined(RF95_IRQ)
if (!rIf) {
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
rIf = new RF95Interface(RadioLibHAL, LORA_CS, RF95_IRQ, RF95_RESET, RF95_DIO1);
if (!rIf->init()) {
LOG_WARN("Failed to find RF95 radio\n");
@@ -883,7 +900,7 @@ void setup()
#endif
#if defined(USE_SX1262) && !defined(ARCH_PORTDUINO) && !defined(TCXO_OPTIONAL)
if (!rIf) {
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
rIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
if (!rIf->init()) {
LOG_WARN("Failed to find SX1262 radio\n");
@@ -897,7 +914,7 @@ void setup()
#endif
#if defined(USE_SX1262) && !defined(ARCH_PORTDUINO) && defined(TCXO_OPTIONAL)
if (!rIf) {
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
// Try using the specified TCXO voltage
rIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
if (!rIf->init()) {
@@ -913,7 +930,7 @@ void setup()
}
}
if (!rIf) {
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
// If specified TCXO voltage fails, attempt to use DIO3 as a reference instea
rIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
if (!rIf->init()) {
@@ -931,7 +948,7 @@ void setup()
#endif
#if defined(USE_SX1268)
if (!rIf) {
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
rIf = new SX1268Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
if (!rIf->init()) {
LOG_WARN("Failed to find SX1268 radio\n");
@@ -945,7 +962,7 @@ void setup()
#endif
#if defined(USE_LLCC68)
if (!rIf) {
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
rIf = new LLCC68Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
if (!rIf->init()) {
LOG_WARN("Failed to find LLCC68 radio\n");
@@ -959,27 +976,43 @@ void setup()
#endif
#if defined(USE_LR1110)
if (!rIf) {
rIf = new LR1110Interface(RadioLibHAL, LR1110_SPI_NSS_PIN, LR1110_IRQ_PIN, LR1110_NRESER_PIN, LR1110_BUSY_PIN);
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
rIf = new LR1110Interface(RadioLibHAL, LR1110_SPI_NSS_PIN, LR1110_IRQ_PIN, LR1110_NRESET_PIN, LR1110_BUSY_PIN);
if (!rIf->init()) {
LOG_WARN("Failed to find LR1110 radio\n");
delete rIf;
rIf = NULL;
} else {
LOG_INFO("LR1110 Radio init succeeded, using LR1110 radio\n");
radioType = LR1110_RADIO;
}
}
#endif
#if defined(USE_LR1120)
if (!rIf) {
rIf = new LR1120Interface(RadioLibHAL, LR1120_SPI_NSS_PIN, LR1120_IRQ_PIN, LR1120_NRESER_PIN, LR1120_BUSY_PIN);
rIf = new LR1120Interface(RadioLibHAL, LR1120_SPI_NSS_PIN, LR1120_IRQ_PIN, LR1120_NRESET_PIN, LR1120_BUSY_PIN);
if (!rIf->init()) {
LOG_WARN("Failed to find LR1120 radio\n");
delete rIf;
rIf = NULL;
} else {
LOG_INFO("LR1120 Radio init succeeded, using LR1120 radio\n");
radioType = LR1120_RADIO;
}
}
#endif
#if defined(USE_LR1121)
if (!rIf) {
rIf = new LR1121Interface(RadioLibHAL, LR1121_SPI_NSS_PIN, LR1121_IRQ_PIN, LR1121_NRESET_PIN, LR1121_BUSY_PIN);
if (!rIf->init()) {
LOG_WARN("Failed to find LR1121 radio\n");
delete rIf;
rIf = NULL;
} else {
LOG_INFO("LR1121 Radio init succeeded, using LR1121 radio\n");
radioType = LR1121_RADIO;
}
}
#endif
@@ -1101,10 +1134,6 @@ void loop()
{
runASAP = false;
// axpDebugOutput.loop();
// heap_caps_check_integrity_all(true); // FIXME - disable this expensive check
#ifdef ARCH_ESP32
esp32Loop();
#endif
@@ -1113,33 +1142,21 @@ void loop()
#endif
powerCommandsCheck();
// For debugging
// if (rIf) ((RadioLibInterface *)rIf)->isActivelyReceiving();
#ifdef DEBUG_STACK
static uint32_t lastPrint = 0;
if (millis() - lastPrint > 10 * 1000L) {
if (!Throttle::isWithinTimespanMs(lastPrint, 10 * 1000L)) {
lastPrint = millis();
meshtastic::printThreadInfo("main");
}
#endif
// TODO: This should go into a thread handled by FreeRTOS.
// handleWebResponse();
service->loop();
long delayMsec = mainController.runOrDelay();
/* if (mainController.nextThread && delayMsec)
LOG_DEBUG("Next %s in %ld\n", mainController.nextThread->ThreadName.c_str(),
mainController.nextThread->tillRun(millis())); */
// We want to sleep as long as possible here - because it saves power
if (!runASAP && loopCanSleep()) {
// if(delayMsec > 100) LOG_DEBUG("sleeping %ld\n", delayMsec);
mainDelay.delay(delayMsec);
}
// if (didWake) LOG_DEBUG("wake!\n");
}
#endif
+3 -3
View File
@@ -56,8 +56,8 @@ extern AudioThread *audioThread;
// Global Screen singleton.
extern graphics::Screen *screen;
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#include "AccelerometerThread.h"
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
#include "motion/AccelerometerThread.h"
extern AccelerometerThread *accelerometerThread;
#endif
@@ -86,4 +86,4 @@ void nrf52Setup(), esp32Setup(), nrf52Loop(), esp32Loop(), rp2040Setup(), clearB
meshtastic_DeviceMetadata getDeviceMetadata();
// We default to 4MHz SPI, SPI mode 0
extern SPISettings spiSettings;
extern SPISettings spiSettings;
+4
View File
@@ -57,6 +57,8 @@ uint32_t MemGet::getFreePsram()
{
#ifdef ARCH_ESP32
return ESP.getFreePsram();
#elif defined(ARCH_PORTDUINO)
return 4194252;
#else
return 0;
#endif
@@ -71,6 +73,8 @@ uint32_t MemGet::getPsramSize()
{
#ifdef ARCH_ESP32
return ESP.getPsramSize();
#elif defined(ARCH_PORTDUINO)
return 4194252;
#else
return 0;
#endif
+15 -11
View File
@@ -70,8 +70,9 @@ bool CryptoEngine::encryptCurve25519(uint32_t toNode, uint32_t fromNode, uint64_
long extraNonceTmp = random();
auth = bytesOut + numBytes;
extraNonce = (uint32_t *)(auth + 8);
*extraNonce = extraNonceTmp;
LOG_INFO("Random nonce value: %d\n", *extraNonce);
memcpy(extraNonce, &extraNonceTmp,
4); // do not use dereference on potential non aligned pointers : *extraNonce = extraNonceTmp;
LOG_INFO("Random nonce value: %d\n", extraNonceTmp);
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(toNode);
if (node->num < 1 || node->user.public_key.size == 0) {
LOG_DEBUG("Node %d or their public_key not found\n", toNode);
@@ -80,14 +81,15 @@ bool CryptoEngine::encryptCurve25519(uint32_t toNode, uint32_t fromNode, uint64_
if (!crypto->setDHKey(toNode)) {
return false;
}
initNonce(fromNode, packetNum, *extraNonce);
initNonce(fromNode, packetNum, extraNonceTmp);
// Calculate the shared secret with the destination node and encrypt
printBytes("Attempting encrypt using nonce: ", nonce, 13);
printBytes("Attempting encrypt using shared_key starting with: ", shared_key, 8);
aes_ccm_ae(shared_key, 32, nonce, 8, bytes, numBytes, nullptr, 0, bytesOut,
auth); // this can write up to 15 bytes longer than numbytes past bytesOut
*extraNonce = extraNonceTmp;
memcpy(extraNonce, &extraNonceTmp,
4); // do not use dereference on potential non aligned pointers : *extraNonce = extraNonceTmp;
return true;
}
@@ -99,11 +101,12 @@ bool CryptoEngine::encryptCurve25519(uint32_t toNode, uint32_t fromNode, uint64_
*/
bool CryptoEngine::decryptCurve25519(uint32_t fromNode, uint64_t packetNum, size_t numBytes, uint8_t *bytes, uint8_t *bytesOut)
{
uint8_t *auth; // set to last 8 bytes of text?
uint32_t *extraNonce;
uint8_t *auth; // set to last 8 bytes of text?
uint32_t extraNonce; // pointer was not really used
auth = bytes + numBytes - 12;
extraNonce = (uint32_t *)(auth + 8);
LOG_INFO("Random nonce value: %d\n", *extraNonce);
#ifndef PIO_UNIT_TESTING
memcpy(&extraNonce, auth + 8, 4); // do not use dereference on potential non aligned pointers : (uint32_t *)(auth + 8);
LOG_INFO("Random nonce value: %d\n", extraNonce);
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(fromNode);
if (node == nullptr || node->num < 1 || node->user.public_key.size == 0) {
@@ -115,7 +118,8 @@ bool CryptoEngine::decryptCurve25519(uint32_t fromNode, uint64_t packetNum, size
if (!crypto->setDHKey(fromNode)) {
return false;
}
initNonce(fromNode, packetNum, *extraNonce);
#endif
initNonce(fromNode, packetNum, extraNonce);
printBytes("Attempting decrypt using nonce: ", nonce, 13);
printBytes("Attempting decrypt using shared_key starting with: ", shared_key, 8);
return aes_ccm_ad(shared_key, 32, nonce, 8, bytes, numBytes - 12, nullptr, 0, auth, bytesOut);
@@ -167,12 +171,12 @@ bool CryptoEngine::setDHKey(uint32_t nodeNum)
void CryptoEngine::hash(uint8_t *bytes, size_t numBytes)
{
SHA256 hash;
size_t posn, len;
size_t posn;
uint8_t size = numBytes;
uint8_t inc = 16;
hash.reset();
for (posn = 0; posn < size; posn += inc) {
len = size - posn;
size_t len = size - posn;
if (len > inc)
len = inc;
hash.update(bytes + posn, len);
+1
View File
@@ -14,6 +14,7 @@ template class SX126xInterface<LLCC68>;
template class SX128xInterface<SX1280>;
template class LR11x0Interface<LR1110>;
template class LR11x0Interface<LR1120>;
template class LR11x0Interface<LR1121>;
#ifdef ARCH_STM32WL
template class SX126xInterface<STM32WLx>;
#endif
+5
View File
@@ -6,4 +6,9 @@ LR1120Interface::LR1120Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, R
RADIOLIB_PIN_TYPE busy)
: LR11x0Interface(hal, cs, irq, rst, busy)
{
}
bool LR1120Interface::wideLora()
{
return true;
}
+1
View File
@@ -10,4 +10,5 @@ class LR1120Interface : public LR11x0Interface<LR1120>
public:
LR1120Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
RADIOLIB_PIN_TYPE busy);
bool wideLora() override;
};
+14
View File
@@ -0,0 +1,14 @@
#include "LR1121Interface.h"
#include "configuration.h"
#include "error.h"
LR1121Interface::LR1121Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
RADIOLIB_PIN_TYPE busy)
: LR11x0Interface(hal, cs, irq, rst, busy)
{
}
bool LR1121Interface::wideLora()
{
return true;
}
+14
View File
@@ -0,0 +1,14 @@
#pragma once
#include "LR11x0Interface.h"
/**
* Our adapter for LR1121 wideband radios
*/
class LR1121Interface : public LR11x0Interface<LR1121>
{
public:
LR1121Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
RADIOLIB_PIN_TYPE busy);
bool wideLora() override;
};
+48 -77
View File
@@ -1,15 +1,32 @@
#include "LR11x0Interface.h"
#include "Throttle.h"
#include "configuration.h"
#include "error.h"
#include "mesh/NodeDB.h"
#ifdef LR11X0_DIO_AS_RF_SWITCH
#include "rfswitch.h"
#else
static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC};
static const Module::RfSwitchMode_t rfswitch_table[] = {
{LR11x0::MODE_STBY, {}}, {LR11x0::MODE_RX, {}}, {LR11x0::MODE_TX, {}}, {LR11x0::MODE_TX_HP, {}},
{LR11x0::MODE_TX_HF, {}}, {LR11x0::MODE_GNSS, {}}, {LR11x0::MODE_WIFI, {}}, END_OF_MODE_TABLE,
};
#endif
#ifdef ARCH_PORTDUINO
#include "PortduinoGlue.h"
#endif
// Particular boards might define a different max power based on what their hardware can do, default to max power output if not
// specified (may be dangerous if using external PA and LR11x0 power config forgotten)
#ifndef LR11X0_MAX_POWER
#define LR11X0_MAX_POWER 22
#ifndef LR1110_MAX_POWER
#define LR1110_MAX_POWER 22
#endif
// the 2.4G part maxes at 13dBm
#ifndef LR1120_MAX_POWER
#define LR1120_MAX_POWER 13
#endif
template <typename T>
@@ -45,59 +62,15 @@ template <typename T> bool LR11x0Interface<T>::init()
RadioLibInterface::init();
if (power > LR11X0_MAX_POWER) // Clamp power to maximum defined level
power = LR11X0_MAX_POWER;
if (power > LR1110_MAX_POWER) // Clamp power to maximum defined level
power = LR1110_MAX_POWER;
if ((power > LR1120_MAX_POWER) &&
(config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) // clamp again if wide freq range
power = LR1120_MAX_POWER;
limitPower();
#ifdef TRACKER_T1000_E // Tracker T1000E uses DIO5, DIO6, DIO7, DIO8 for RF switching
static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6, RADIOLIB_LR11X0_DIO7,
RADIOLIB_LR11X0_DIO8, RADIOLIB_NC};
static const Module::RfSwitchMode_t rfswitch_table[] = {
// mode DIO5 DIO6 DIO7 DIO8
{LR11x0::MODE_STBY, {LOW, LOW, LOW, LOW}}, {LR11x0::MODE_RX, {HIGH, LOW, LOW, HIGH}},
{LR11x0::MODE_TX, {HIGH, HIGH, LOW, HIGH}}, {LR11x0::MODE_TX_HP, {LOW, HIGH, LOW, HIGH}},
{LR11x0::MODE_TX_HF, {LOW, LOW, LOW, LOW}}, {LR11x0::MODE_GNSS, {LOW, LOW, HIGH, LOW}},
{LR11x0::MODE_WIFI, {LOW, LOW, LOW, LOW}}, END_OF_MODE_TABLE,
};
#else
// set RF switch configuration for Wio WM1110
// Wio WM1110 uses DIO5 and DIO6 for RF switching
static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6, RADIOLIB_NC, RADIOLIB_NC,
RADIOLIB_NC};
static const Module::RfSwitchMode_t rfswitch_table[] = {
// mode DIO5 DIO6
{LR11x0::MODE_STBY, {LOW, LOW}}, {LR11x0::MODE_RX, {HIGH, LOW}},
{LR11x0::MODE_TX, {HIGH, HIGH}}, {LR11x0::MODE_TX_HP, {LOW, HIGH}},
{LR11x0::MODE_TX_HF, {LOW, LOW}}, {LR11x0::MODE_GNSS, {LOW, LOW}},
{LR11x0::MODE_WIFI, {LOW, LOW}}, END_OF_MODE_TABLE,
};
#endif
// We need to do this before begin() call
#ifdef LR11X0_DIO_AS_RF_SWITCH
LOG_DEBUG("Setting DIO RF switch\n");
bool dioAsRfSwitch = true;
#elif defined(ARCH_PORTDUINO)
bool dioAsRfSwitch = false;
if (settingsMap[dio2_as_rf_switch]) {
LOG_DEBUG("Setting DIO RF switch\n");
dioAsRfSwitch = true;
}
#else
bool dioAsRfSwitch = false;
#endif
if (dioAsRfSwitch)
lora.setRfSwitchTable(rfswitch_dio_pins, rfswitch_table);
int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage);
// \todo Display actual typename of the adapter, not just `LR11x0`
LOG_INFO("LR11x0 init result %d\n", res);
@@ -121,6 +94,23 @@ template <typename T> bool LR11x0Interface<T>::init()
// FIXME: May want to set depending on a definition, currently all LR1110 variant files use the DC-DC regulator option
if (res == RADIOLIB_ERR_NONE)
res = lora.setRegulatorDCDC();
#ifdef LR11X0_DIO_AS_RF_SWITCH
bool dioAsRfSwitch = true;
#elif defined(ARCH_PORTDUINO)
bool dioAsRfSwitch = false;
if (settingsMap[dio2_as_rf_switch]) {
dioAsRfSwitch = true;
}
#else
bool dioAsRfSwitch = false;
#endif
if (dioAsRfSwitch) {
lora.setRfSwitchTable(rfswitch_dio_pins, rfswitch_table);
LOG_DEBUG("Setting DIO RF switch\n", res);
}
if (res == RADIOLIB_ERR_NONE) {
if (config.lora.sx126x_rx_boosted_gain) { // the name is unfortunate but historically accurate
res = lora.setRxBoostedGainMode(true);
@@ -172,8 +162,10 @@ template <typename T> bool LR11x0Interface<T>::reconfigure()
if (err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
if (power > LR11X0_MAX_POWER) // This chip has lower power limits than some
power = LR11X0_MAX_POWER;
if (power > LR1110_MAX_POWER) // This chip has lower power limits than some
power = LR1110_MAX_POWER;
if ((power > LR1120_MAX_POWER) && (config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) // 2.4G power limit
power = LR1120_MAX_POWER;
err = lora.setOutputPower(power);
assert(err == RADIOLIB_ERR_NONE);
@@ -270,29 +262,8 @@ template <typename T> bool LR11x0Interface<T>::isActivelyReceiving()
{
// The IRQ status will be cleared when we start our read operation. Check if we've started a header, but haven't yet
// received and handled the interrupt for reading the packet/handling errors.
uint16_t irq = lora.getIrqStatus();
bool detected = (irq & (RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID | RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED));
// Handle false detections
if (detected) {
uint32_t now = millis();
if (!activeReceiveStart) {
activeReceiveStart = now;
} else if ((now - activeReceiveStart > 2 * preambleTimeMsec) && !(irq & RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID)) {
// The HEADER_VALID flag should be set by now if it was really a packet, so ignore PREAMBLE_DETECTED flag
activeReceiveStart = 0;
LOG_DEBUG("Ignore false preamble detection.\n");
return false;
} else if (now - activeReceiveStart > maxPacketTimeMsec) {
// We should have gotten an RX_DONE IRQ by now if it was really a packet, so ignore HEADER_VALID flag
activeReceiveStart = 0;
LOG_DEBUG("Ignore false header detection.\n");
return false;
}
}
// if (detected) LOG_DEBUG("rx detected\n");
return detected;
return receiveDetected(lora.getIrqStatus(), RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID,
RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED);
}
template <typename T> bool LR11x0Interface<T>::sleep()
-3
View File
@@ -65,7 +65,4 @@ template <class T> class LR11x0Interface : public RadioLibInterface
virtual void addReceiveMetadata(meshtastic_MeshPacket *mp) override;
virtual void setStandby() override;
private:
uint32_t activeReceiveStart = 0;
};
+2 -1
View File
@@ -79,7 +79,8 @@ class MeshModule
meshtastic_AdminMessage *response);
#if HAS_SCREEN
virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { return; }
virtual bool isRequestingFocus(); // Checked by screen, when regenerating frameset
virtual bool isRequestingFocus(); // Checked by screen, when regenerating frameset
virtual bool interceptingKeyboardInput() { return false; } // Can screen use keyboard for nav, or is module handling input?
#endif
protected:
const char *name;
+5 -2
View File
@@ -13,9 +13,9 @@
#if defined(ARCH_PORTDUINO) && !HAS_RADIO
#include "../platform/portduino/SimRadio.h"
#endif
#ifdef ARCH_ESP32
#if defined(ARCH_ESP32) || defined(ARCH_PORTDUINO)
#if !MESHTASTIC_EXCLUDE_STOREFORWARD
#include "modules/esp32/StoreForwardModule.h"
#include "modules/StoreForwardModule.h"
#endif
#endif
@@ -92,6 +92,9 @@ class MeshService
/// Return the next MqttClientProxyMessage packet destined to the phone.
meshtastic_MqttClientProxyMessage *getMqttClientProxyMessageForPhone() { return toPhoneMqttProxyQueue.dequeuePtr(0); }
/// Return the next ClientNotification packet destined to the phone.
meshtastic_ClientNotification *getClientNotificationForPhone() { return toPhoneClientNotificationQueue.dequeuePtr(0); }
// search the queue for a request id and return the matching nodenum
NodeNum getNodenumFromRequestId(uint32_t request_id);
+8 -6
View File
@@ -32,12 +32,13 @@
#if HAS_WIFI
#include "mesh/wifi/WiFiAPClient.h"
#endif
#include "modules/esp32/StoreForwardModule.h"
#include "modules/StoreForwardModule.h"
#include <Preferences.h>
#include <nvs_flash.h>
#endif
#ifdef ARCH_PORTDUINO
#include "modules/StoreForwardModule.h"
#include "platform/portduino/PortduinoGlue.h"
#endif
@@ -49,7 +50,7 @@
NodeDB *nodeDB = nullptr;
// we have plenty of ram so statically alloc this tempbuf (for now)
EXT_RAM_ATTR meshtastic_DeviceState devicestate;
EXT_RAM_BSS_ATTR meshtastic_DeviceState devicestate;
meshtastic_MyNodeInfo &myNodeInfo = devicestate.my_node;
meshtastic_LocalConfig config;
meshtastic_LocalModuleConfig moduleConfig;
@@ -472,7 +473,7 @@ void NodeDB::installDefaultModuleConfig()
moduleConfig.has_detection_sensor = true;
moduleConfig.detection_sensor.enabled = false;
moduleConfig.detection_sensor.detection_triggered_high = true;
moduleConfig.detection_sensor.detection_trigger_type = meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_LOGIC_HIGH;
moduleConfig.detection_sensor.minimum_broadcast_secs = 45;
moduleConfig.has_ambient_lighting = true;
@@ -657,9 +658,10 @@ void NodeDB::pickNewNodeNum()
while (((found = getMeshNode(nodeNum)) && memcmp(found->user.macaddr, ourMacAddr, sizeof(ourMacAddr)) != 0) ||
(nodeNum == NODENUM_BROADCAST || nodeNum < NUM_RESERVED)) {
NodeNum candidate = random(NUM_RESERVED, LONG_MAX); // try a new random choice
LOG_WARN("NOTE! Our desired nodenum 0x%x is invalid or in use, by MAC ending in 0x%02x%02x vs our 0x%02x%02x, so "
"trying for 0x%x\n",
nodeNum, found->user.macaddr[4], found->user.macaddr[5], ourMacAddr[4], ourMacAddr[5], candidate);
if (found)
LOG_WARN("NOTE! Our desired nodenum 0x%x is invalid or in use, by MAC ending in 0x%02x%02x vs our 0x%02x%02x, so "
"trying for 0x%x\n",
nodeNum, found->user.macaddr[4], found->user.macaddr[5], ourMacAddr[4], ourMacAddr[5], candidate);
nodeNum = candidate;
}
LOG_DEBUG("Using nodenum 0x%x \n", nodeNum);
+2
View File
@@ -2,11 +2,13 @@
#include "Observer.h"
#include <Arduino.h>
#include <algorithm>
#include <assert.h>
#include <vector>
#include "MeshTypes.h"
#include "NodeStatus.h"
#include "configuration.h"
#include "mesh-pb-constants.h"
#include "mesh/generated/meshtastic/mesh.pb.h" // For CriticalErrorCode
+6 -8
View File
@@ -5,6 +5,7 @@
#ifdef ARCH_PORTDUINO
#include "platform/portduino/PortduinoGlue.h"
#endif
#include "Throttle.h"
PacketHistory::PacketHistory()
{
@@ -22,18 +23,17 @@ bool PacketHistory::wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpd
return false; // Not a floodable message ID, so we don't care
}
uint32_t now = millis();
PacketRecord r;
r.id = p->id;
r.sender = getFrom(p);
r.rxTimeMsec = now;
r.rxTimeMsec = millis();
auto found = recentPackets.find(r);
bool seenRecently = (found != recentPackets.end()); // found not equal to .end() means packet was seen recently
if (seenRecently && (now - found->rxTimeMsec) >= FLOOD_EXPIRE_TIME) { // Check whether found packet has already expired
recentPackets.erase(found); // Erase and pretend packet has not been seen recently
if (seenRecently &&
!Throttle::isWithinTimespanMs(found->rxTimeMsec, FLOOD_EXPIRE_TIME)) { // Check whether found packet has already expired
recentPackets.erase(found); // Erase and pretend packet has not been seen recently
found = recentPackets.end();
seenRecently = false;
}
@@ -64,12 +64,10 @@ bool PacketHistory::wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpd
*/
void PacketHistory::clearExpiredRecentPackets()
{
uint32_t now = millis();
LOG_DEBUG("recentPackets size=%ld\n", recentPackets.size());
for (auto it = recentPackets.begin(); it != recentPackets.end();) {
if ((now - it->rxTimeMsec) >= FLOOD_EXPIRE_TIME) {
if (!Throttle::isWithinTimespanMs(it->rxTimeMsec, FLOOD_EXPIRE_TIME)) {
it = recentPackets.erase(it); // erase returns iterator pointing to element immediately following the one erased
} else {
++it;
+58 -16
View File
@@ -8,6 +8,7 @@
#include "FSCommon.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "PacketHistory.h"
#include "PhoneAPI.h"
#include "PowerFSM.h"
#include "RadioInterface.h"
@@ -25,11 +26,13 @@
#if !MESHTASTIC_EXCLUDE_MQTT
#include "mqtt/MQTT.h"
#endif
#include "Throttle.h"
#include <RTC.h>
PhoneAPI::PhoneAPI()
{
lastContactMsec = millis();
std::fill(std::begin(recentToRadioPacketIds), std::end(recentToRadioPacketIds), 0);
}
PhoneAPI::~PhoneAPI()
@@ -61,9 +64,11 @@ void PhoneAPI::handleStartConfig()
void PhoneAPI::close()
{
LOG_INFO("PhoneAPI::close()\n");
if (state != STATE_SEND_NOTHING) {
state = STATE_SEND_NOTHING;
resetReadIndex();
unobserve(&service->fromNumChanged);
#ifdef FSCom
unobserve(&xModem.packetReady);
@@ -71,8 +76,17 @@ void PhoneAPI::close()
releasePhonePacket(); // Don't leak phone packets on shutdown
releaseQueueStatusPhonePacket();
releaseMqttClientProxyPhonePacket();
releaseClientNotification();
onConnectionChanged(false);
fromRadioScratch = {};
toRadioScratch = {};
nodeInfoForPhone = {};
packetForPhone = NULL;
filesManifest.clear();
fromRadioNum = 0;
config_nonce = 0;
config_state = 0;
pauseBluetoothLogging = false;
}
}
@@ -97,8 +111,6 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
powerFSM.trigger(EVENT_CONTACT_FROM_PHONE); // As long as the phone keeps talking to us, don't let the radio go to sleep
lastContactMsec = millis();
// return (lastContactMsec != 0) &&
memset(&toRadioScratch, 0, sizeof(toRadioScratch));
if (pb_decode_from_bytes(buf, bufLength, &meshtastic_ToRadio_msg, &toRadioScratch)) {
switch (toRadioScratch.which_payload_variant) {
@@ -404,6 +416,10 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_xmodemPacket_tag;
fromRadioScratch.xmodemPacket = xmodemPacketForPhone;
xmodemPacketForPhone = meshtastic_XModem_init_zero;
} else if (clientNotification) {
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_clientNotification_tag;
fromRadioScratch.clientNotification = *clientNotification;
releaseClientNotification();
} else if (packetForPhone) {
printPacket("phone downloaded packet", packetForPhone);
@@ -443,13 +459,6 @@ void PhoneAPI::sendConfigComplete()
pauseBluetoothLogging = false;
}
void PhoneAPI::handleDisconnect()
{
filesManifest.clear();
pauseBluetoothLogging = false;
LOG_INFO("PhoneAPI disconnect\n");
}
void PhoneAPI::releasePhonePacket()
{
if (packetForPhone) {
@@ -474,6 +483,14 @@ void PhoneAPI::releaseMqttClientProxyPhonePacket()
}
}
void PhoneAPI::releaseClientNotification()
{
if (clientNotification) {
service->releaseClientNotificationToPool(clientNotification);
clientNotification = NULL;
}
}
/**
* Return true if we have data available to send to the phone
*/
@@ -508,7 +525,9 @@ bool PhoneAPI::available()
queueStatusPacketForPhone = service->getQueueStatusForPhone();
if (!mqttClientProxyMessageForPhone)
mqttClientProxyMessageForPhone = service->getMqttClientProxyMessageForPhone();
bool hasPacket = !!queueStatusPacketForPhone || !!mqttClientProxyMessageForPhone;
if (!clientNotification)
clientNotification = service->getClientNotificationForPhone();
bool hasPacket = !!queueStatusPacketForPhone || !!mqttClientProxyMessageForPhone || !!clientNotification;
if (hasPacket)
return true;
@@ -551,7 +570,23 @@ void PhoneAPI::sendNotification(meshtastic_LogRecord_Level level, uint32_t reply
cn->time = getValidTime(RTCQualityFromNet);
strncpy(cn->message, message, sizeof(cn->message));
service->sendClientNotification(cn);
delete cn;
}
bool PhoneAPI::wasSeenRecently(uint32_t id)
{
for (int i = 0; i < 20; i++) {
if (recentToRadioPacketIds[i] == id) {
return true;
}
if (recentToRadioPacketIds[i] == 0) {
recentToRadioPacketIds[i] = id;
return false;
}
}
// If the array is full, shift all elements to the left and add the new id at the end
memmove(recentToRadioPacketIds, recentToRadioPacketIds + 1, (19) * sizeof(uint32_t));
recentToRadioPacketIds[19] = id;
return false;
}
/**
@@ -560,15 +595,22 @@ void PhoneAPI::sendNotification(meshtastic_LogRecord_Level level, uint32_t reply
bool PhoneAPI::handleToRadioPacket(meshtastic_MeshPacket &p)
{
printPacket("PACKET FROM PHONE", &p);
if (p.id > 0 && wasSeenRecently(p.id)) {
LOG_DEBUG("Ignoring packet from phone, already seen recently\n");
return false;
}
if (p.decoded.portnum == meshtastic_PortNum_TRACEROUTE_APP && lastPortNumToRadio[p.decoded.portnum] &&
(millis() - lastPortNumToRadio[p.decoded.portnum]) < (THIRTY_SECONDS_MS)) {
Throttle::isWithinTimespanMs(lastPortNumToRadio[p.decoded.portnum], THIRTY_SECONDS_MS)) {
LOG_WARN("Rate limiting portnum %d\n", p.decoded.portnum);
sendNotification(meshtastic_LogRecord_Level_WARNING, p.id, "TraceRoute can only be sent once every 30 seconds");
return false;
} else if (p.decoded.portnum == meshtastic_PortNum_POSITION_APP && lastPortNumToRadio[p.decoded.portnum] &&
(millis() - lastPortNumToRadio[p.decoded.portnum]) < (FIVE_SECONDS_MS)) {
Throttle::isWithinTimespanMs(lastPortNumToRadio[p.decoded.portnum], FIVE_SECONDS_MS)) {
LOG_WARN("Rate limiting portnum %d\n", p.decoded.portnum);
sendNotification(meshtastic_LogRecord_Level_WARNING, p.id, "Position can only be sent once every 5 seconds");
// FIXME: Figure out why this continues to happen
// sendNotification(meshtastic_LogRecord_Level_WARNING, p.id, "Position can only be sent once every 5 seconds");
return false;
}
lastPortNumToRadio[p.decoded.portnum] = millis();
+5 -5
View File
@@ -52,6 +52,7 @@ class PhoneAPI
// Hashmap of timestamps for last time we received a packet on the API per portnum
std::unordered_map<meshtastic_PortNum, uint32_t> lastPortNumToRadio;
uint32_t recentToRadioPacketIds[20]; // Last 20 ToRadio MeshPacket IDs we have seen
/**
* Each packet sent to the phone has an incrementing count
@@ -147,11 +148,6 @@ class PhoneAPI
*/
virtual void onNowHasData(uint32_t fromRadioNum) {}
/**
* Subclasses can use this to find out when a client drops the link
*/
virtual void handleDisconnect();
private:
void releasePhonePacket();
@@ -159,9 +155,13 @@ class PhoneAPI
void releaseMqttClientProxyPhonePacket();
void releaseClientNotification();
/// begin a new connection
void handleStartConfig();
bool wasSeenRecently(uint32_t packetId);
/**
* Handle a packet that the phone wants us to send. We can write to it but can not keep a reference to it
* @return true true if a packet was queued for sending
+1 -1
View File
@@ -108,7 +108,7 @@ template <class T> class ProtobufModule : protected SinglePortModule
T *decoded = NULL;
if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag && mp.decoded.portnum == ourPortNum) {
memset(&scratch, 0, sizeof(scratch));
auto &p = mp.decoded;
const meshtastic_Data &p = mp.decoded;
if (pb_decode_from_bytes(p.payload.bytes, p.payload.size, fields, &scratch)) {
decoded = &scratch;
} else {
+2 -2
View File
@@ -151,7 +151,7 @@ const RegionInfo regions[] = {
const RegionInfo *myRegion;
bool RadioInterface::uses_default_frequency_slot = true;
static uint8_t bytes[MAX_RHPACKETLEN];
static uint8_t bytes[MAX_LORA_PAYLOAD_LEN + 1];
void initRegion()
{
@@ -326,7 +326,7 @@ void printPacket(const char *prefix, const meshtastic_MeshPacket *p)
RadioInterface::RadioInterface()
{
assert(sizeof(PacketHeader) == 16); // make sure the compiler did what we expected
assert(sizeof(PacketHeader) == MESHTASTIC_HEADER_LENGTH); // make sure the compiler did what we expected
}
bool RadioInterface::reconfigure()
+4 -2
View File
@@ -9,7 +9,9 @@
#define MAX_TX_QUEUE 16 // max number of packets which can be waiting for transmission
#define MAX_RHPACKETLEN 256
#define MAX_LORA_PAYLOAD_LEN 255 // max length of 255 per Semtech's datasheets on SX12xx
#define MESHTASTIC_HEADER_LENGTH 16
#define MESHTASTIC_PKC_OVERHEAD 12
#define PACKET_FLAGS_HOP_LIMIT_MASK 0x07
#define PACKET_FLAGS_WANT_ACK_MASK 0x08
@@ -89,7 +91,7 @@ class RadioInterface
/**
* A temporary buffer used for sending/receiving packets, sized to hold the biggest buffer we might need
* */
uint8_t radiobuf[MAX_RHPACKETLEN];
uint8_t radiobuf[MAX_LORA_PAYLOAD_LEN + 1];
/**
* Enqueue a received packet for the registered receiver
+34 -3
View File
@@ -3,6 +3,7 @@
#include "NodeDB.h"
#include "PowerMon.h"
#include "SPILock.h"
#include "Throttle.h"
#include "configuration.h"
#include "error.h"
#include "main.h"
@@ -41,7 +42,7 @@ void LockingArduinoHal::spiTransfer(uint8_t *out, size_t len, uint8_t *in)
uint32_t start = millis();
while (digitalRead(busy)) {
if (millis() - start >= 2000) {
if (!Throttle::isWithinTimespanMs(start, 2000)) {
LOG_ERROR("GPIO mid-transfer timeout, is it connected?");
return;
}
@@ -114,7 +115,7 @@ bool RadioLibInterface::canSendImmediately()
}
// If we've been trying to send the same packet more than one minute and we haven't gotten a
// TX IRQ from the radio, the radio is probably broken.
if (busyTx && (millis() - lastTxStart > 60000)) {
if (busyTx && !Throttle::isWithinTimespanMs(lastTxStart, 60000)) {
LOG_ERROR("Hardware Failure! busyTx for more than 60s\n");
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_TRANSMIT_FAILED);
// reboot in 5 seconds when this condition occurs.
@@ -128,6 +129,28 @@ bool RadioLibInterface::canSendImmediately()
return true;
}
bool RadioLibInterface::receiveDetected(uint16_t irq, ulong syncWordHeaderValidFlag, ulong preambleDetectedFlag)
{
bool detected = (irq & (syncWordHeaderValidFlag | preambleDetectedFlag));
// Handle false detections
if (detected) {
if (!activeReceiveStart) {
activeReceiveStart = millis();
} else if (!Throttle::isWithinTimespanMs(activeReceiveStart, 2 * preambleTimeMsec) && !(irq & syncWordHeaderValidFlag)) {
// The HEADER_VALID flag should be set by now if it was really a packet, so ignore PREAMBLE_DETECTED flag
activeReceiveStart = 0;
LOG_DEBUG("Ignore false preamble detection.\n");
return false;
} else if (!Throttle::isWithinTimespanMs(activeReceiveStart, maxPacketTimeMsec)) {
// We should have gotten an RX_DONE IRQ by now if it was really a packet, so ignore HEADER_VALID flag
activeReceiveStart = 0;
LOG_DEBUG("Ignore false header detection.\n");
return false;
}
}
return detected;
}
/// Send a packet (possibly by enquing in a private fifo). This routine will
/// later free() the packet to pool. This routine is not allowed to stall because it is called from
/// bluetooth comms code. If the txmit queue is empty it might return an error
@@ -144,7 +167,7 @@ ErrorCode RadioLibInterface::send(meshtastic_MeshPacket *p)
}
} else {
LOG_WARN("send - lora tx disable because RegionCode_Unset\n");
LOG_WARN("send - lora tx disabled because RegionCode_Unset\n");
packetPool.release(p);
return ERRNO_DISABLED;
}
@@ -356,6 +379,14 @@ void RadioLibInterface::handleReceiveInterrupt()
xmitMsec = getPacketTime(length);
#ifndef DISABLE_WELCOME_UNSET
if (config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
LOG_WARN("recv - lora rx disabled because RegionCode_Unset\n");
airTime->logAirtime(RX_ALL_LOG, xmitMsec);
return;
}
#endif
int state = iface->readData(radiobuf, length);
if (state != RADIOLIB_ERR_NONE) {
LOG_ERROR("ignoring received packet due to error=%d\n", state);
+4
View File
@@ -167,6 +167,10 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
meshtastic_QueueStatus getQueueStatus();
protected:
uint32_t activeReceiveStart = 0;
bool receiveDetected(uint16_t irq, ulong syncWordHeaderValidFlag, ulong preambleDetectedFlag);
/** Do any hardware setup needed on entry into send configuration for the radio.
* Subclasses can customize, but must also call this base method */
virtual void configHardwareForSend();
+7 -7
View File
@@ -36,8 +36,8 @@ static MemoryDynamic<meshtastic_MeshPacket> staticPool;
Allocator<meshtastic_MeshPacket> &packetPool = staticPool;
static uint8_t bytes[MAX_RHPACKETLEN];
static uint8_t ScratchEncrypted[MAX_RHPACKETLEN];
static uint8_t bytes[MAX_LORA_PAYLOAD_LEN + 1] __attribute__ ((__aligned__));
static uint8_t ScratchEncrypted[MAX_LORA_PAYLOAD_LEN + 1] __attribute__ ((__aligned__));
/**
* Constructor
@@ -330,13 +330,13 @@ bool perhapsDecode(meshtastic_MeshPacket *p)
// Attempt PKI decryption first
if (p->channel == 0 && p->to == nodeDB->getNodeNum() && p->to > 0 && p->to != NODENUM_BROADCAST &&
nodeDB->getMeshNode(p->from) != nullptr && nodeDB->getMeshNode(p->from)->user.public_key.size > 0 &&
nodeDB->getMeshNode(p->to)->user.public_key.size > 0 && rawSize > 12) {
nodeDB->getMeshNode(p->to)->user.public_key.size > 0 && rawSize > MESHTASTIC_PKC_OVERHEAD) {
LOG_DEBUG("Attempting PKI decryption\n");
if (crypto->decryptCurve25519(p->from, p->id, rawSize, ScratchEncrypted, bytes)) {
LOG_INFO("PKI Decryption worked!\n");
memset(&p->decoded, 0, sizeof(p->decoded));
rawSize -= 12;
rawSize -= MESHTASTIC_PKC_OVERHEAD;
if (pb_decode_from_bytes(bytes, rawSize, &meshtastic_Data_msg, &p->decoded) &&
p->decoded.portnum != meshtastic_PortNum_UNKNOWN_APP) {
decrypted = true;
@@ -475,7 +475,7 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
}
} */
if (numbytes > MAX_RHPACKETLEN)
if (numbytes + MESHTASTIC_HEADER_LENGTH > MAX_LORA_PAYLOAD_LEN)
return meshtastic_Routing_Error_TOO_LARGE;
// printBytes("plaintext", bytes, numbytes);
@@ -499,7 +499,7 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
p->decoded.portnum != meshtastic_PortNum_TRACEROUTE_APP && p->decoded.portnum != meshtastic_PortNum_NODEINFO_APP &&
p->decoded.portnum != meshtastic_PortNum_ROUTING_APP && p->decoded.portnum != meshtastic_PortNum_POSITION_APP) {
LOG_DEBUG("Using PKI!\n");
if (numbytes + 12 > MAX_RHPACKETLEN)
if (numbytes + MESHTASTIC_HEADER_LENGTH + MESHTASTIC_PKC_OVERHEAD > MAX_LORA_PAYLOAD_LEN)
return meshtastic_Routing_Error_TOO_LARGE;
if (p->pki_encrypted && !memfll(p->public_key.bytes, 0, 32) &&
memcmp(p->public_key.bytes, node->user.public_key.bytes, 32) != 0) {
@@ -508,7 +508,7 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
return meshtastic_Routing_Error_PKI_FAILED;
}
crypto->encryptCurve25519(p->to, getFrom(p), p->id, numbytes, bytes, ScratchEncrypted);
numbytes += 12;
numbytes += MESHTASTIC_PKC_OVERHEAD;
memcpy(p->encrypted.bytes, ScratchEncrypted, numbytes);
p->channel = 0;
p->pki_encrypted = true;
+19 -37
View File
@@ -6,6 +6,8 @@
#include "PortduinoGlue.h"
#endif
#include "Throttle.h"
// Particular boards might define a different max power based on what their hardware can do, default to max power output if not
// specified (may be dangerous if using external PA and SX126x power config forgotten)
#ifndef SX126X_MAX_POWER
@@ -50,6 +52,10 @@ template <typename T> bool SX126xInterface<T>::init()
float tcxoVoltage = 0;
if (settingsMap[dio3_tcxo_voltage])
tcxoVoltage = 1.8;
if (settingsMap[sx126x_ant_sw] != RADIOLIB_NC) {
digitalWrite(settingsMap[sx126x_ant_sw], HIGH);
pinMode(settingsMap[sx126x_ant_sw], OUTPUT);
}
// FIXME: correct logic to default to not using TCXO if no voltage is specified for SX126X_DIO3_TCXO_VOLTAGE
#elif !defined(SX126X_DIO3_TCXO_VOLTAGE)
float tcxoVoltage =
@@ -97,21 +103,19 @@ template <typename T> bool SX126xInterface<T>::init()
LOG_DEBUG("Current limit set to %f\n", currentLimit);
LOG_DEBUG("Current limit set result %d\n", res);
#ifdef SX126X_DIO2_AS_RF_SWITCH
LOG_DEBUG("Setting DIO2 as RF switch\n");
bool dio2AsRfSwitch = true;
#elif defined(ARCH_PORTDUINO)
bool dio2AsRfSwitch = false;
if (settingsMap[dio2_as_rf_switch]) {
LOG_DEBUG("Setting DIO2 as RF switch\n");
dio2AsRfSwitch = true;
}
#else
LOG_DEBUG("Setting DIO2 as not RF switch\n");
bool dio2AsRfSwitch = false;
#endif
if (res == RADIOLIB_ERR_NONE) {
#ifdef SX126X_DIO2_AS_RF_SWITCH
bool dio2AsRfSwitch = true;
#elif defined(ARCH_PORTDUINO)
bool dio2AsRfSwitch = false;
if (settingsMap[dio2_as_rf_switch]) {
dio2AsRfSwitch = true;
}
#else
bool dio2AsRfSwitch = false;
#endif
res = lora.setDio2AsRfSwitch(dio2AsRfSwitch);
LOG_DEBUG("Set DIO2 as %sRF switch, result: %d\n", dio2AsRfSwitch ? "" : "not ", res);
}
// If a pin isn't defined, we set it to RADIOLIB_NC, it is safe to always do external RF switching with RADIOLIB_NC as it has
@@ -314,29 +318,7 @@ template <typename T> bool SX126xInterface<T>::isActivelyReceiving()
{
// The IRQ status will be cleared when we start our read operation. Check if we've started a header, but haven't yet
// received and handled the interrupt for reading the packet/handling errors.
uint16_t irq = lora.getIrqFlags();
bool detected = (irq & (RADIOLIB_SX126X_IRQ_HEADER_VALID | RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED));
// Handle false detections
if (detected) {
uint32_t now = millis();
if (!activeReceiveStart) {
activeReceiveStart = now;
} else if ((now - activeReceiveStart > 2 * preambleTimeMsec) && !(irq & RADIOLIB_SX126X_IRQ_HEADER_VALID)) {
// The HEADER_VALID flag should be set by now if it was really a packet, so ignore PREAMBLE_DETECTED flag
activeReceiveStart = 0;
LOG_DEBUG("Ignore false preamble detection.\n");
return false;
} else if (now - activeReceiveStart > maxPacketTimeMsec) {
// We should have gotten an RX_DONE IRQ by now if it was really a packet, so ignore HEADER_VALID flag
activeReceiveStart = 0;
LOG_DEBUG("Ignore false header detection.\n");
return false;
}
}
// if (detected) LOG_DEBUG("rx detected\n");
return detected;
return receiveDetected(lora.getIrqFlags(), RADIOLIB_SX126X_IRQ_HEADER_VALID, RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED);
}
template <typename T> bool SX126xInterface<T>::sleep()
@@ -359,4 +341,4 @@ template <typename T> bool SX126xInterface<T>::sleep()
#endif
return true;
}
}
-3
View File
@@ -67,7 +67,4 @@ template <class T> class SX126xInterface : public RadioLibInterface
virtual void addReceiveMetadata(meshtastic_MeshPacket *mp) override;
virtual void setStandby() override;
private:
uint32_t activeReceiveStart = 0;
};
+2 -22
View File
@@ -1,4 +1,5 @@
#include "SX128xInterface.h"
#include "Throttle.h"
#include "configuration.h"
#include "error.h"
#include "mesh/NodeDB.h"
@@ -289,28 +290,7 @@ template <typename T> bool SX128xInterface<T>::isChannelActive()
/** Could we send right now (i.e. either not actively receiving or transmitting)? */
template <typename T> bool SX128xInterface<T>::isActivelyReceiving()
{
uint16_t irq = lora.getIrqStatus();
bool detected = (irq & (RADIOLIB_SX128X_IRQ_HEADER_VALID | RADIOLIB_SX128X_IRQ_PREAMBLE_DETECTED));
// Handle false detections
if (detected) {
uint32_t now = millis();
if (!activeReceiveStart) {
activeReceiveStart = now;
} else if ((now - activeReceiveStart > 2 * preambleTimeMsec) && !(irq & RADIOLIB_SX128X_IRQ_HEADER_VALID)) {
// The HEADER_VALID flag should be set by now if it was really a packet, so ignore PREAMBLE_DETECTED flag
activeReceiveStart = 0;
LOG_DEBUG("Ignore false preamble detection.\n");
return false;
} else if (now - activeReceiveStart > maxPacketTimeMsec) {
// We should have gotten an RX_DONE IRQ by now if it was really a packet, so ignore HEADER_VALID flag
activeReceiveStart = 0;
LOG_DEBUG("Ignore false header detection.\n");
return false;
}
}
return detected;
return receiveDetected(lora.getIrqStatus(), RADIOLIB_SX128X_IRQ_HEADER_VALID, RADIOLIB_SX128X_IRQ_PREAMBLE_DETECTED);
}
template <typename T> bool SX128xInterface<T>::sleep()
-3
View File
@@ -67,7 +67,4 @@ template <class T> class SX128xInterface : public RadioLibInterface
virtual void addReceiveMetadata(meshtastic_MeshPacket *mp) override;
virtual void setStandby() override;
private:
uint32_t activeReceiveStart = 0;
};
+3 -3
View File
@@ -1,6 +1,7 @@
#include "StreamAPI.h"
#include "PowerFSM.h"
#include "RTC.h"
#include "Throttle.h"
#include "configuration.h"
#define START1 0x94
@@ -20,10 +21,9 @@ int32_t StreamAPI::runOncePart()
*/
int32_t StreamAPI::readStream()
{
uint32_t now = millis();
if (!stream->available()) {
// Nothing available this time, if the computer has talked to us recently, poll often, otherwise let CPU sleep a long time
bool recentRx = (now - lastRxMsec) < 2000;
bool recentRx = Throttle::isWithinTimespanMs(lastRxMsec, 2000);
return recentRx ? 5 : 250;
} else {
while (stream->available()) { // Currently we never want to block
@@ -71,7 +71,7 @@ int32_t StreamAPI::readStream()
}
// we had bytes available this time, so assume we might have them next time also
lastRxMsec = now;
lastRxMsec = millis();
return 0;
}
}
+8
View File
@@ -24,4 +24,12 @@ bool Throttle::execute(uint32_t *lastExecutionMs, uint32_t minumumIntervalMs, vo
onDefer();
}
return false;
}
/// @brief Check if the last execution time is within the interval
/// @param lastExecutionMs The last execution time in milliseconds
/// @param timeSpanMs The interval in milliseconds of the timespan
bool Throttle::isWithinTimespanMs(uint32_t lastExecutionMs, uint32_t timeSpanMs)
{
return (millis() - lastExecutionMs) < timeSpanMs;
}
+1
View File
@@ -6,4 +6,5 @@ class Throttle
{
public:
static bool execute(uint32_t *lastExecutionMs, uint32_t minumumIntervalMs, void (*func)(void), void (*onDefer)(void) = NULL);
static bool isWithinTimespanMs(uint32_t lastExecutionMs, uint32_t intervalMs);
};
+1 -1
View File
@@ -14,7 +14,7 @@
*/
template <class T> class TypedQueue
{
static_assert(std::is_pod<T>::value, "T must be pod");
static_assert(std::is_standard_layout<T>::value, "T must be standard layout");
QueueHandle_t h;
concurrency::OSThread *reader = NULL;
+1 -1
View File
@@ -95,7 +95,7 @@ static void aes_ccm_encr(size_t L, const uint8_t *in, size_t len, uint8_t *out,
*out++ ^= *in++;
}
}
static void aes_ccm_encr_auth(size_t M, uint8_t *x, uint8_t *a, uint8_t *auth)
static void aes_ccm_encr_auth(size_t M, const uint8_t *x, uint8_t *a, uint8_t *auth)
{
size_t i;
uint8_t tmp[AES_BLOCK_SIZE];
+8
View File
@@ -45,7 +45,15 @@ template <class T, class U> void APIServerPort<T, U>::init()
template <class T, class U> int32_t APIServerPort<T, U>::runOnce()
{
#ifdef ARCH_ESP32
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
auto client = U::accept();
#else
auto client = U::available();
#endif
#else
auto client = U::available();
#endif
if (client) {
// Close any previous connection (see FIXME in header file)
if (openAPI) {
+2 -2
View File
@@ -339,7 +339,7 @@ int32_t readUTF8(const char *in, int len, int l, int *utf8len)
/// This is also used for Unicode strings \n
/// This is a crude implementation that is not optimized. Assuming only short strings \n
/// are encoded, this is not much of an issue.
int matchOccurance(const char *in, int len, int l, char *out, int olen, int *ol, uint8_t *state, const uint8_t usx_hcodes[],
int matchOccurance(const char *in, int len, int l, char *out, int olen, int *ol, const uint8_t *state, const uint8_t usx_hcodes[],
const uint8_t usx_hcode_lens[])
{
int j, k;
@@ -383,7 +383,7 @@ int matchOccurance(const char *in, int len, int l, char *out, int olen, int *ol,
/// This is also used for Unicode strings \n
/// This is a crude implementation that is not optimized. Assuming only short strings \n
/// are encoded, this is not much of an issue.
int matchLine(const char *in, int len, int l, char *out, int olen, int *ol, struct us_lnk_lst *prev_lines, uint8_t *state,
int matchLine(const char *in, int len, int l, char *out, int olen, int *ol, struct us_lnk_lst *prev_lines, const uint8_t *state,
const uint8_t usx_hcodes[], const uint8_t usx_hcode_lens[])
{
int last_ol = *ol;
+14 -2
View File
@@ -71,6 +71,8 @@ typedef enum _meshtastic_HardwareModel {
meshtastic_HardwareModel_RAK2560 = 22,
/* Heltec HRU-3601: https://heltec.org/project/hru-3601/ */
meshtastic_HardwareModel_HELTEC_HRU_3601 = 23,
/* Heltec Wireless Bridge */
meshtastic_HardwareModel_HELTEC_WIRELESS_BRIDGE = 24,
/* B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station */
meshtastic_HardwareModel_STATION_G1 = 25,
/* RAK11310 (RP2040 + SX1262) */
@@ -107,7 +109,7 @@ typedef enum _meshtastic_HardwareModel {
meshtastic_HardwareModel_NRF52840_PCA10059 = 40,
/* Custom Disaster Radio esp32 v3 device https://github.com/sudomesh/disaster-radio/tree/master/hardware/board_esp32_v3 */
meshtastic_HardwareModel_DR_DEV = 41,
/* M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, Paper) https://m5stack.com/ */
/* M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, CoreS3, Paper) https://m5stack.com/ */
meshtastic_HardwareModel_M5STACK = 42,
/* New Heltec LoRA32 with ESP32-S3 CPU */
meshtastic_HardwareModel_HELTEC_V3 = 43,
@@ -196,9 +198,19 @@ typedef enum _meshtastic_HardwareModel {
https://www.adafruit.com/product/938
^^^ short A0 to switch to I2C address 0x3C */
meshtastic_HardwareModel_RP2040_FEATHER_RFM95 = 76,
/* M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, Paper) https://m5stack.com/ */
/* M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, CoreS3, Paper) https://m5stack.com/ */
meshtastic_HardwareModel_M5STACK_COREBASIC = 77,
meshtastic_HardwareModel_M5STACK_CORE2 = 78,
/* Pico2 with Waveshare Hat, same as Pico */
meshtastic_HardwareModel_RPI_PICO2 = 79,
/* M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, CoreS3, Paper) https://m5stack.com/ */
meshtastic_HardwareModel_M5STACK_CORES3 = 80,
/* Seeed XIAO S3 DK */
meshtastic_HardwareModel_SEEED_XIAO_S3 = 81,
/* Nordic nRF52840+Semtech SX1262 LoRa BLE Combo Module. nRF52840+SX1262 MS24SF1 */
meshtastic_HardwareModel_MS24SF1 = 82,
/* Lilygo TLora-C6 with the new ESP32-C6 MCU */
meshtastic_HardwareModel_TLORA_C6 = 83,
/* ------------------------------------------------------------------------------------------------------------------------------------------
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
------------------------------------------------------------------------------------------------------------------------------------------ */
@@ -60,3 +60,4 @@ PB_BIND(meshtastic_RemoteHardwarePin, meshtastic_RemoteHardwarePin, AUTO)
@@ -19,6 +19,23 @@ typedef enum _meshtastic_RemoteHardwarePinType {
meshtastic_RemoteHardwarePinType_DIGITAL_WRITE = 2
} meshtastic_RemoteHardwarePinType;
typedef enum _meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType {
/* Event is triggered if pin is low */
meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_LOGIC_LOW = 0,
/* Event is triggered if pin is high */
meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_LOGIC_HIGH = 1,
/* Event is triggered when pin goes high to low */
meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_FALLING_EDGE = 2,
/* Event is triggered when pin goes low to high */
meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_RISING_EDGE = 3,
/* Event is triggered on every pin state change, low is considered to be
"active" */
meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_EITHER_EDGE_ACTIVE_LOW = 4,
/* Event is triggered on every pin state change, high is considered to be
"active" */
meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_EITHER_EDGE_ACTIVE_HIGH = 5
} meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType;
/* Baudrate for codec2 voice */
typedef enum _meshtastic_ModuleConfig_AudioConfig_Audio_Baud {
meshtastic_ModuleConfig_AudioConfig_Audio_Baud_CODEC2_DEFAULT = 0,
@@ -144,11 +161,13 @@ typedef struct _meshtastic_ModuleConfig_NeighborInfoConfig {
typedef struct _meshtastic_ModuleConfig_DetectionSensorConfig {
/* Whether the Module is enabled */
bool enabled;
/* Interval in seconds of how often we can send a message to the mesh when a state change is detected */
/* Interval in seconds of how often we can send a message to the mesh when a
trigger event is detected */
uint32_t minimum_broadcast_secs;
/* Interval in seconds of how often we should send a message to the mesh with the current state regardless of changes
When set to 0, only state changes will be broadcasted
Works as a sort of status heartbeat for peace of mind */
/* Interval in seconds of how often we should send a message to the mesh
with the current state regardless of trigger events When set to 0, only
trigger events will be broadcasted Works as a sort of status heartbeat
for peace of mind */
uint32_t state_broadcast_secs;
/* Send ASCII bell with alert message
Useful for triggering ext. notification on bell */
@@ -159,9 +178,8 @@ typedef struct _meshtastic_ModuleConfig_DetectionSensorConfig {
char name[20];
/* GPIO pin to monitor for state changes */
uint8_t monitor_pin;
/* Whether or not the GPIO pin state detection is triggered on HIGH (1)
Otherwise LOW (0) */
bool detection_triggered_high;
/* The type of trigger event to be used */
meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType detection_trigger_type;
/* Whether or not use INPUT_PULLUP mode for GPIO pin
Only applicable if the board uses pull-up resistors on the pin */
bool use_pullup;
@@ -427,6 +445,10 @@ extern "C" {
#define _meshtastic_RemoteHardwarePinType_MAX meshtastic_RemoteHardwarePinType_DIGITAL_WRITE
#define _meshtastic_RemoteHardwarePinType_ARRAYSIZE ((meshtastic_RemoteHardwarePinType)(meshtastic_RemoteHardwarePinType_DIGITAL_WRITE+1))
#define _meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_MIN meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_LOGIC_LOW
#define _meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_MAX meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_EITHER_EDGE_ACTIVE_HIGH
#define _meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_ARRAYSIZE ((meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType)(meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_EITHER_EDGE_ACTIVE_HIGH+1))
#define _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN meshtastic_ModuleConfig_AudioConfig_Audio_Baud_CODEC2_DEFAULT
#define _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MAX meshtastic_ModuleConfig_AudioConfig_Audio_Baud_CODEC2_700B
#define _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_ARRAYSIZE ((meshtastic_ModuleConfig_AudioConfig_Audio_Baud)(meshtastic_ModuleConfig_AudioConfig_Audio_Baud_CODEC2_700B+1))
@@ -448,6 +470,7 @@ extern "C" {
#define meshtastic_ModuleConfig_DetectionSensorConfig_detection_trigger_type_ENUMTYPE meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType
#define meshtastic_ModuleConfig_AudioConfig_bitrate_ENUMTYPE meshtastic_ModuleConfig_AudioConfig_Audio_Baud
@@ -473,7 +496,7 @@ extern "C" {
#define meshtastic_ModuleConfig_MapReportSettings_init_default {0, 0}
#define meshtastic_ModuleConfig_RemoteHardwareConfig_init_default {0, 0, 0, {meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default}}
#define meshtastic_ModuleConfig_NeighborInfoConfig_init_default {0, 0}
#define meshtastic_ModuleConfig_DetectionSensorConfig_init_default {0, 0, 0, 0, "", 0, 0, 0}
#define meshtastic_ModuleConfig_DetectionSensorConfig_init_default {0, 0, 0, 0, "", 0, _meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_MIN, 0}
#define meshtastic_ModuleConfig_AudioConfig_init_default {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_PaxcounterConfig_init_default {0, 0, 0, 0}
#define meshtastic_ModuleConfig_SerialConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN, 0}
@@ -489,7 +512,7 @@ extern "C" {
#define meshtastic_ModuleConfig_MapReportSettings_init_zero {0, 0}
#define meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero {0, 0, 0, {meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero}}
#define meshtastic_ModuleConfig_NeighborInfoConfig_init_zero {0, 0}
#define meshtastic_ModuleConfig_DetectionSensorConfig_init_zero {0, 0, 0, 0, "", 0, 0, 0}
#define meshtastic_ModuleConfig_DetectionSensorConfig_init_zero {0, 0, 0, 0, "", 0, _meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_MIN, 0}
#define meshtastic_ModuleConfig_AudioConfig_init_zero {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_PaxcounterConfig_init_zero {0, 0, 0, 0}
#define meshtastic_ModuleConfig_SerialConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN, 0}
@@ -523,7 +546,7 @@ extern "C" {
#define meshtastic_ModuleConfig_DetectionSensorConfig_send_bell_tag 4
#define meshtastic_ModuleConfig_DetectionSensorConfig_name_tag 5
#define meshtastic_ModuleConfig_DetectionSensorConfig_monitor_pin_tag 6
#define meshtastic_ModuleConfig_DetectionSensorConfig_detection_triggered_high_tag 7
#define meshtastic_ModuleConfig_DetectionSensorConfig_detection_trigger_type_tag 7
#define meshtastic_ModuleConfig_DetectionSensorConfig_use_pullup_tag 8
#define meshtastic_ModuleConfig_AudioConfig_codec2_enabled_tag 1
#define meshtastic_ModuleConfig_AudioConfig_ptt_pin_tag 2
@@ -688,7 +711,7 @@ X(a, STATIC, SINGULAR, UINT32, state_broadcast_secs, 3) \
X(a, STATIC, SINGULAR, BOOL, send_bell, 4) \
X(a, STATIC, SINGULAR, STRING, name, 5) \
X(a, STATIC, SINGULAR, UINT32, monitor_pin, 6) \
X(a, STATIC, SINGULAR, BOOL, detection_triggered_high, 7) \
X(a, STATIC, SINGULAR, UENUM, detection_trigger_type, 7) \
X(a, STATIC, SINGULAR, BOOL, use_pullup, 8)
#define meshtastic_ModuleConfig_DetectionSensorConfig_CALLBACK NULL
#define meshtastic_ModuleConfig_DetectionSensorConfig_DEFAULT NULL
+8 -2
View File
@@ -23,6 +23,7 @@ static void WiFiEvent(WiFiEvent_t event);
#endif
#ifndef DISABLE_NTP
#include "Throttle.h"
#include <NTPClient.h>
#endif
@@ -142,7 +143,7 @@ static int32_t reconnectWiFi()
}
#ifndef DISABLE_NTP
if (WiFi.isConnected() && (((millis() - lastrun_ntp) > 43200000) || (lastrun_ntp == 0))) { // every 12 hours
if (WiFi.isConnected() && (!Throttle::isWithinTimespanMs(lastrun_ntp, 43200000) || (lastrun_ntp == 0))) { // every 12 hours
LOG_DEBUG("Updating NTP time from %s\n", config.network.ntp_server);
if (timeClient.update()) {
LOG_DEBUG("NTP Request Success - Setting RTCQualityNTP if needed\n");
@@ -309,7 +310,12 @@ static void WiFiEvent(WiFiEvent_t event)
onNetworkConnected();
break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
LOG_INFO("Obtained Local IP6 address: %s\n", WiFi.linkLocalIPv6().toString().c_str());
LOG_INFO("Obtained GlobalIP6 address: %s\n", WiFi.globalIPv6().toString().c_str());
#else
LOG_INFO("Obtained IP6 address: %s\n", WiFi.localIPv6().toString().c_str());
#endif
break;
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
LOG_INFO("Lost IP address and IP address is reset to 0\n");
@@ -420,4 +426,4 @@ uint8_t getWifiDisconnectReason()
{
return wifiDisconnectReason;
}
#endif
#endif
+25 -4
View File
@@ -60,10 +60,16 @@ char *strnstr(const char *s, const char *find, size_t slen)
void printBytes(const char *label, const uint8_t *p, size_t numbytes)
{
LOG_DEBUG("%s: ", label);
for (size_t i = 0; i < numbytes; i++)
LOG_DEBUG("%02x ", p[i]);
LOG_DEBUG("\n");
int labelSize = strlen(label);
if (labelSize < 100 && numbytes < 64) {
char *messageBuffer = new char[labelSize + (numbytes * 3) + 2];
strncpy(messageBuffer, label, labelSize);
for (size_t i = 0; i < numbytes; i++)
snprintf(messageBuffer + labelSize + i * 3, 4, " %02x", p[i]);
strcpy(messageBuffer + labelSize + numbytes * 3, "\n");
LOG_DEBUG(messageBuffer);
delete[] messageBuffer;
}
}
bool memfll(const uint8_t *mem, uint8_t find, size_t numbytes)
@@ -73,4 +79,19 @@ bool memfll(const uint8_t *mem, uint8_t find, size_t numbytes)
return false;
}
return true;
}
bool isOneOf(int item, int count, ...)
{
va_list args;
va_start(args, count);
bool found = false;
for (int i = 0; i < count; ++i) {
if (item == va_arg(args, int)) {
found = true;
break;
}
}
va_end(args);
return found;
}
+8 -1
View File
@@ -1,5 +1,8 @@
#pragma once
#include "DebugConfiguration.h"
#include <algorithm>
#include <cstdarg>
#include <iterator>
#include <stdint.h>
/// C++ v17+ clamp function, limits a given value to a range defined by lo and hi
@@ -17,4 +20,8 @@ char *strnstr(const char *s, const char *find, size_t slen);
void printBytes(const char *label, const uint8_t *p, size_t numbytes);
// is the memory region filled with a single character?
bool memfll(const uint8_t *mem, uint8_t find, size_t numbytes);
bool memfll(const uint8_t *mem, uint8_t find, size_t numbytes);
bool isOneOf(int item, int count, ...);
#define IS_ONE_OF(item, ...) isOneOf(item, sizeof((int[]){__VA_ARGS__}) / sizeof(int), __VA_ARGS__)
+4 -4
View File
@@ -34,8 +34,8 @@
#include "modules/PositionModule.h"
#endif
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#include "AccelerometerThread.h"
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
#include "motion/AccelerometerThread.h"
#endif
AdminModule *adminModule;
@@ -1026,7 +1026,7 @@ bool AdminModule::checkPassKey(meshtastic_AdminMessage *res)
memcmp(res->session_passkey.bytes, session_passkey, 8) == 0);
}
bool AdminModule::messageIsResponse(meshtastic_AdminMessage *r)
bool AdminModule::messageIsResponse(const meshtastic_AdminMessage *r)
{
if (r->which_payload_variant == meshtastic_AdminMessage_get_channel_response_tag ||
r->which_payload_variant == meshtastic_AdminMessage_get_owner_response_tag ||
@@ -1043,7 +1043,7 @@ bool AdminModule::messageIsResponse(meshtastic_AdminMessage *r)
return false;
}
bool AdminModule::messageIsRequest(meshtastic_AdminMessage *r)
bool AdminModule::messageIsRequest(const meshtastic_AdminMessage *r)
{
if (r->which_payload_variant == meshtastic_AdminMessage_get_channel_request_tag ||
r->which_payload_variant == meshtastic_AdminMessage_get_owner_request_tag ||
+2 -2
View File
@@ -55,8 +55,8 @@ class AdminModule : public ProtobufModule<meshtastic_AdminMessage>, public Obser
void setPassKey(meshtastic_AdminMessage *res);
bool checkPassKey(meshtastic_AdminMessage *res);
bool messageIsResponse(meshtastic_AdminMessage *r);
bool messageIsRequest(meshtastic_AdminMessage *r);
bool messageIsResponse(const meshtastic_AdminMessage *r);
bool messageIsRequest(const meshtastic_AdminMessage *r);
};
extern AdminModule *adminModule;
+26 -5
View File
@@ -27,6 +27,7 @@
#endif
#include "graphics/ScreenFonts.h"
#include <Throttle.h>
// Remove Canned message screen if no action is taken for some milliseconds
#define INACTIVATE_AFTER_MS 20000
@@ -77,16 +78,16 @@ int CannedMessageModule::splitConfiguredMessages()
int messageIndex = 0;
int i = 0;
String messages = cannedMessageModuleConfig.messages;
String canned_messages = cannedMessageModuleConfig.messages;
#if defined(T_WATCH_S3) || defined(RAK14014)
String separator = messages.length() ? "|" : "";
String separator = canned_messages.length() ? "|" : "";
messages = "[---- Free Text ----]" + separator + messages;
canned_messages = "[---- Free Text ----]" + separator + canned_messages;
#endif
// collect all the message parts
strncpy(this->messageStore, messages.c_str(), sizeof(this->messageStore));
strncpy(this->messageStore, canned_messages.c_str(), sizeof(this->messageStore));
// The first message points to the beginning of the store.
this->messages[messageIndex++] = this->messageStore;
@@ -275,6 +276,13 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
showTemporaryMessage("Node Info \nUpdate Sent");
}
break;
case INPUT_BROKER_MSG_DISMISS_FRAME: // fn+del: dismiss screen frames like text or waypoint
// Avoid opening the canned message screen frame
// We're only handling the keypress here by convention, this has nothing to do with canned messages
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
// Attempt to close whatever frame is currently shown on display
screen->dismissCurrentFrame();
return 0;
default:
// pass the pressed key
// LOG_DEBUG("Canned message ANYKEY (%x)\n", event->kbchar);
@@ -422,7 +430,7 @@ int32_t CannedMessageModule::runOnce()
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)) {
!Throttle::isWithinTimespanMs(this->lastTouchMillis, INACTIVATE_AFTER_MS)) {
// Reset module
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; // We want to change the list of frames shown on-screen
this->currentMessageIndex = -1;
@@ -934,6 +942,19 @@ void CannedMessageModule::drawEnterIcon(OLEDDisplay *display, int x, int y, floa
#endif
// Indicate to screen class that module is handling keyboard input specially (at certain times)
// This prevents the left & right keys being used for nav. between screen frames during text entry.
bool CannedMessageModule::interceptingKeyboardInput()
{
switch (runState) {
case CANNED_MESSAGE_RUN_STATE_DISABLED:
case CANNED_MESSAGE_RUN_STATE_INACTIVE:
return false;
default:
return true;
}
}
void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
char buffer[50];
+1
View File
@@ -114,6 +114,7 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
virtual bool wantUIFrame() override { return this->shouldDraw(); }
virtual Observable<const UIFrameEvent *> *getUIFrameObservable() override { return this; }
virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) override;
virtual bool interceptingKeyboardInput() override;
virtual AdminMessageHandleResult handleAdminMessageForModule(const meshtastic_MeshPacket &mp,
meshtastic_AdminMessage *request,
meshtastic_AdminMessage *response) override;

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