Compare commits

...

135 Commits

Author SHA1 Message Date
github-actions[bot]
79da2365f0 [create-pull-request] automated change (#5475)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-11-29 08:03:46 -06:00
Ben Meadors
b5777beb7d Warnings and log cleanup (#5472)
* Don't log if keyboard not found

* Signed comparison issue
2024-11-28 11:20:06 -06:00
Ben Meadors
5ad30a55ea Trunk 2024-11-28 06:26:51 -06:00
virgil
060a3bde4d fix: Solve the lightsleep crash problem via disable lightsleep for indicator. (#5470) 2024-11-28 06:19:18 -06:00
panaceya
8df7a035e2 Fix ukrainian fonts (#5468)
* FIX:  rollback to !4624

* UPDATE: new 16 and 24 UA Fonts and fixes
2024-11-28 05:34:09 -06:00
Christopher Hoover
b00c05012d GPS.h cleanups round 3. (#5447)
* GPS.h cleanups round 3.

No effective behavior change.

Protected members can be private so make it so.  (Supporting
subclasses needs a lot more work.)

Moves uBloxGnssModelInfo into file scope.

Moves uBloxProtocolVersion into uBloxGnssModelInfo.

Moves baud rate arrays into file scope.

Removes unused/ unimplemented powerStateToString.

Signed-off-by: Christopher Hoover <ch@murgatroid.com>

* Trunk Format.

---------

Signed-off-by: Christopher Hoover <ch@murgatroid.com>
Co-authored-by: Tom Fifield <tom@tomfifield.net>
2024-11-27 18:56:25 +08:00
Ben Meadors
0832388482 Remove ATECC crypto chip placeholder code (#5461) 2024-11-27 09:45:54 +01:00
Liam Cottle
601d912c6f fix cors for meshtasticd to allow use of cross origin clients (#5463) 2024-11-27 09:45:31 +01:00
Ben Meadors
502a83bb8a Use isWithinTimespanMs to avoid refererence to NodeDb instance inside of NodeDb (#5453) 2024-11-26 16:39:16 -06:00
Ben Meadors
474f9b5bfb Clean up some inline functions (#5454) 2024-11-26 14:00:10 -06:00
Ben Meadors
fe86c40145 Cleanup i2c scan logs and macro to save some bytes and remain consistent (#5455)
* Cleanup i2c scan logs and macro to save some bytes and remain consistent

* Functions are better than macros

* Exclude i2c scan for STM32

* Useless log
2024-11-26 13:59:50 -06:00
github-actions[bot]
09286a3beb [create-pull-request] automated change (#5457)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-11-26 08:32:02 -06:00
Jonathan Bennett
ae4f54224e Actually gunzip all the files when building a .deb (#5449) 2024-11-26 12:49:13 +08:00
Ben Meadors
d5af8f0a97 Revert "Seems like the last DIY board that's not "extra" (#5420)" (#5446)
This reverts commit e6fb6b115a.
2024-11-26 11:09:55 +08:00
Ben Meadors
58c957f2c7 Don't powersave on Wifi (#5443)
* Don't go into light sleep with wifi enabled

* Move

* Trunk
2024-11-25 06:53:05 -06:00
Tomas Dubec
7c2b6778cb enable MQTT with TLS on RPi picow (#5442)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-11-25 06:12:19 -06:00
Christopher Hoover
0048e3cdcb A second round of cleanup on GPS.h. (#5433)
* Move yet more stuff out of GPS.h and into file scope.

* Protect code macros from eating semicolons.

* Remove unused (and unimplemented) getDOPString.

* clang-format with project style file on affected files.

Signed-off-by: Christopher Hoover <ch@murgatroid.com>
2024-11-25 05:32:04 -06:00
Ben Meadors
6018c0a830 Removing 1.0 legacy boards from releases and completely removing Heltec wireless capsule from support (#5436)
Co-authored-by: Tom Fifield <tom@tomfifield.net>
2024-11-25 05:14:48 -06:00
César de Tassis Filho
37da78919a Fix memory leaks by adding missing free() calls before early returns in MQTT::onReceive (#5439)
This fix addresses memory leaks in the `MQTT::onReceive` function by ensuring that dynamically allocated resources (`e.channel_id`, `e.gateway_id` and `e.packet`) are properly freed before each early return. Previously, these resources were only freed at the end of the function, leaving them unhandled in certain exit paths. Adding the missing `free()` calls prevents memory leaks and ensures proper resource cleanup in all scenarios.
2024-11-25 12:05:06 +08:00
Thomas Göttgens
ad9d7a4972 fixes https://github.com/meshtastic/firmware/issues/5434 (#5435)
* update libpax
* fix interval init
2024-11-24 14:28:36 +01:00
jake-b
932966b896 Support for the ClimateGuard RadSens Geiger-Muller tube (#5425) 2024-11-24 13:53:52 +01:00
github-actions[bot]
4d69159e75 [create-pull-request] automated change (#5431)
Co-authored-by: caveman99 <25002+caveman99@users.noreply.github.com>
2024-11-24 12:29:17 +01:00
Ben Meadors
f2ee0df015 Remove BMA-423 and STK8X by default (#5429)
* Remove BMA-423 by default

* STK

* Wrong macro

* Helps if you include the file
2024-11-23 17:18:22 -06:00
Thomas Göttgens
fcfb197571 try to detect dfrobot station to tell it apart from an ublox gps. (#5393) 2024-11-23 16:56:40 +01:00
Mictronics
dd7140b7a1 Fix admin key loading from userPrefs.h (#5417)
* Fix LED pinout for T-Echo board marked v1.0, date 2021-6-28

* Merge PR #420

* Fixed double and missing Default class.

* Use correct format specifier and fixed typo.

* Removed duplicate code.

* Fix error: #if with no expression

* Fix warning: extra tokens at end of #endif directive.

* Fix antenna switching logic. Complementary-pin control logic is required on the rp2040-lora board.

* Fix deprecated macros.

* Set RP2040 in dormant mode when deep sleep is triggered.

* Fix array out of bounds read.

* Admin key count needs to be set otherwise the key will be zero loaded after reset.

* Don't reset the admin key size when loading defaults. Preserve an existing key in config if possible.

* Remove log spam when reading INA voltage sensor.

* Remove static declaration for admin keys from userPrefs.h. Load hard coded admin keys in case config file has empty slots.

* Removed newlines from log.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2024-11-23 09:08:18 -06:00
Christopher Hoover
fadcbd597f Cleans up visibility in GPS.h (#5426)
Signed-off-by: Christopher Hoover <ch@murgatroid.com>
2024-11-23 06:10:09 -06:00
madeofstown
14b9a1a929 Update build-native.sh (#5415)
* Update build-native.sh

Device-install.sh and device-update.sh are not used on native platform, skip copying to release directory after build and copy native-install.sh and native-run.sh instead.

* Update build-native.sh

Skip native-run.sh copy
2024-11-23 18:06:31 +08:00
dylanli
c51a7b98bd add canned message and keyboard in indicator board (#5410)
* add canned message and keyboard in indicator board

* Added virtual keyboard macro and enabled for Indicator

* Cleanup macros by applying USE_VIRTUAL_KEYBOARD and DISPLAY_CLOCK_FRAME

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-11-22 18:54:06 -06:00
Ben Meadors
fdec95f9c1 Cherry pick tdeck fixes (#5422)
* Try-fix (workaround) T-Deck audio crash

* set T-Deck audio to unused 48 (mem mclk)

* swap mclk to gpio 21

* dreamcatcher: assign GPIO44 to audio mclk

---------

Co-authored-by: mverch67 <manuel.verch@gmx.de>
2024-11-22 14:25:09 -06:00
Jonathan Bennett
e6fb6b115a Seems like the last DIY board that's not "extra" (#5420) 2024-11-22 05:32:35 -06:00
Ben Meadors
d5bb32ff93 Temetry can respond to want-response for LocalStats variant (#5414) 2024-11-21 15:11:19 -06:00
Ben Meadors
f5058a9cbb Check for OkToMqtt flag presence before uplinking to MQTT (#5413)
* Check for oktomqtt flag presence before uplinking to MQTT

* Move to mqtt->onSend
2024-11-21 14:52:54 -06:00
GUVWAF
dbc5ec27f7 Temporarily disable MDNS when MQTT is enabled (#5418)
Leads to a panic
2024-11-21 14:11:50 -06:00
Michael Gjelsø
1089469f82 --web littlefswebui-* typo fix (#5416)
* Add --web

* Update device-install.bat

Forgot a "-" a few places.

* Typo fix.

* Typo fix

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: GUVWAF <78759985+GUVWAF@users.noreply.github.com>
2024-11-21 13:27:26 -06:00
Ben Meadors
fd98e9f553 Fixed NMEA sentence issue in CalTopo as well as bug with no printing all of the nodes (#5412) 2024-11-21 20:13:30 +08:00
dylanli
ccfc9e5dd9 add GPS in indicator board (#5411) 2024-11-21 19:14:35 +08:00
Michael Gjelsø
1752caaf19 --web added to device-install(.sh/.bat) (#5405)
* Add --web

* Update device-install.bat

Forgot a "-" a few places.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-11-21 07:21:06 +08:00
GUVWAF
364dead3aa Update platform-raspberrypi also (#5407)
* Update arduino-pico core to fix sporadic hangs

* Update platform-raspberrypi also
2024-11-20 14:53:36 -06:00
GUVWAF
154864dfbf Update arduino-pico core to fix sporadic hangs (#5406) 2024-11-20 13:18:27 -06:00
Ben Meadors
2ca3cdf837 Fix RTC time injection and consolidate position logic (#5396)
* Fix RTC time injection and consolidate position logic

* Comment out unused var warning

* Backerds
2024-11-20 07:52:39 -06:00
Ben Meadors
485c371de4 Create a specific hw_model for WisMesh Tap (#5400)
* Create a specific hw_model for WisMesh Tap

* Trunk

* HAS_ETHERNET

* Remove it altogether

* Don't need these either
2024-11-20 12:57:46 +08:00
jcyrio
a255da3cf5 Make heart emoji usable (#5403) 2024-11-20 11:31:46 +08:00
Catalin Patulea
d65dc497f2 /api/v1/fromradio: add OPTIONS handler for CORS. (#5386)
This avoids hitting the 404 Not Found handler, which breaks connection
keep-alive, so this change fixes a big performance regression for Web Client in
Chrome: https://github.com/meshtastic/firmware/issues/5385

Tested on Heltec V3.

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-11-19 14:33:44 -06:00
github-actions[bot]
c641bfd53c [create-pull-request] automated change (#5399)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-11-19 12:53:54 -06:00
jcyrio
b947b123fc fix 'symbal' typo (#5395) 2024-11-19 06:52:20 -06:00
Daniel.Cao
df1f66a6b9 Anable trace route function on wismeshtap platform (#5389) 2024-11-19 05:42:29 -06:00
jcyrio
70336f7f4f add smiley emoji (#5391)
* add smiley emoji

* clang-formatted
2024-11-19 13:25:11 +08:00
github-actions[bot]
de76caca32 [create-pull-request] automated change (#5388)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-11-17 19:29:43 -06:00
Michael Gjelsø
89469fcb88 Allows all 3 PKI keys to be added to userPrefs.h (#4969) and a tool. (#5368)
* more userPrefs.h

Added PKI Admin keys to userPrefs.h

* Update userPrefs.h

Allows all 3 PKI keys to be added to userPrefs.h (#4969)

* Update NodeDB.cpp

Trunk

* Update userPrefs.h

Changed wording

* Create base64_to_hex.py

A little tool for converting base64 PKI Keys to decoded byte that userPrefs.h can understand.

* more userPrefs.h

Added PKI Admin keys to userPrefs.h

* Update userPrefs.h

Allows all 3 PKI keys to be added to userPrefs.h (#4969)

* Update NodeDB.cpp

Trunk

* Update userPrefs.h

Changed wording

* Create base64_to_hex.py

A little tool for converting base64 PKI Keys to decoded byte that userPrefs.h can understand.
2024-11-17 12:36:41 -06:00
github-actions[bot]
a8357ebd52 [create-pull-request] automated change (#5380)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-11-17 10:51:11 -06:00
GUVWAF
0d1f9e915f Move some actions to after startTransmit() (#5383)
To minimize the time between channel scan and actual transmit
2024-11-17 10:51:01 -06:00
Ben Meadors
1a06f88dfb Cleanup static files from bad Web UI bundle on 2.5.13 release (#5376)
* Cleanup static files from bad Web UI bundle on 2.5.13 release

* Check existence first

* Esp32 is the only one we care about
2024-11-17 07:57:59 -06:00
Michael Gjelsø
a174ec7cf9 Bug fixed in ExternalNotificationModule (#5375)
While `nagging` setExternalState wasn't written to Buzzer & Vibra so output was never toggled.

Possible fix for #5348
2024-11-17 07:36:06 -06:00
Ben Meadors
37b29f6899 Add littlefswebui 2024-11-16 19:36:55 -06:00
Ben Meadors
74d0c58576 Diag 2024-11-16 06:24:10 -06:00
Ben Meadors
ca3d8da128 version tags 2024-11-16 06:22:08 -06:00
Ben Meadors
be6348388e Separate littlefs bundle 2024-11-16 06:12:45 -06:00
Ben Meadors
fdc473e5fa Trunk 2024-11-16 06:01:07 -06:00
Ben Meadors
add70b5229 Rework some things 2024-11-16 05:58:07 -06:00
Tom Fifield
1b99543a15 Typo fix in build_raspbian.yml (#5365)
s/sudp/sudo :(:(:(
2024-11-16 12:48:15 +08:00
Tom Fifield
90a3050c1f Add sudo to apt-get commands for Raspbian Build (#5364)
Without sudo, inadequate permissions to runs the commands meant
the build was failing.
2024-11-16 12:01:41 +08:00
GUVWAF
9545a10361 RP2040: Update core; add mDNS support (#5355)
* Update arduino-pico core

* RP2040: Add mDNS support

* SimpleMDNS `begin` now returns a bool

* Add `-g` option to `debug_build_flags` to link files for gdb

* RAK11310 needs old platform as well

* Change defines to specific architecture

* Core version 4.2.1 is out
2024-11-16 08:20:20 +08:00
Michael Gjelsø
d4d89447bd Adds fixed GPS, BUTTON_PIN and BLE code to userPrefs.h (#5341)
* userPrefs.h

Added FixedGPS
Added Fixed Bluetooth PIN

* Update NodeDB.cpp

Removed some un-used LOG_INFO

* Added BUTTON_PIN

* Trunk

* Variable re-naming.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-11-14 06:56:22 -06:00
github-actions[bot]
81172574a4 [create-pull-request] automated change (#5347)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-11-14 04:54:56 -06:00
Ben Meadors
295278bb12 Update version.properties 2024-11-13 18:47:46 -06:00
Ben Meadors
ec6949fdc0 Migrate NRF52 devices max nodes down to 80 for now to prevent brownouts (#5346) 2024-11-13 18:44:35 -06:00
github-actions[bot]
f4908fadd6 [create-pull-request] automated change (#5344)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-11-13 13:18:57 -06:00
Mictronics
528e177c62 Remove log spam when reading INA sensor. (#5345)
* Fix LED pinout for T-Echo board marked v1.0, date 2021-6-28

* Merge PR #420

* Fixed double and missing Default class.

* Use correct format specifier and fixed typo.

* Removed duplicate code.

* Fix error: #if with no expression

* Fix warning: extra tokens at end of #endif directive.

* Fix antenna switching logic. Complementary-pin control logic is required on the rp2040-lora board.

* Fix deprecated macros.

* Set RP2040 in dormant mode when deep sleep is triggered.

* Fix array out of bounds read.

* Admin key count needs to be set otherwise the key will be zero loaded after reset.

* Don't reset the admin key size when loading defaults. Preserve an existing key in config if possible.

* Remove log spam when reading INA voltage sensor.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-11-13 13:18:38 -06:00
Ben Meadors
73430cb582 Update version.properties (#5343) 2024-11-13 11:00:23 -06:00
Ben Meadors
3a66c738bd Revert "Decrease max nodes for NRF52 to 80 as workaround to prevent FS blowou…" (#5340)
This reverts commit ea150c32f3.
2024-11-13 10:21:55 -06:00
Ben Meadors
ea150c32f3 Decrease max nodes for NRF52 to 80 as workaround to prevent FS blowouts (#5338)
* Decrease max nodes for NRF52 to 80 as workaround to prevent FS blowouts

* Don't redefine

* Newline
2024-11-13 07:43:05 -06:00
Ben Meadors
ac804818de Only allow 30 seconds minimum for power.on_battery_shutdown_after_secs (#5337) 2024-11-13 05:39:15 -06:00
Blake-Latchford
8fcfe7f28b Read voltage during init fixes #5276 (#5332)
Power::readPowerStatus is called on startup,
but AnalogBatteryLevel::getBattVoltage
skips the read because 5 seconds have not
elapsed since last_read_time_ms, which
is initialized to zero.

`batMv=3100` is reported because
AnalogBatteryLevel::last_read_value is
initialized as:
```
float last_read_value = (OCV[NUM_OCV_POINTS - 1] * NUM_CELLS);
```
2024-11-13 04:13:55 -06:00
GUVWAF
e866734a25 Handle repeated packet after potentially canceling previous Tx (#5330)
* Revert "Fix sending duplicate packets to PhoneAPI/MQTT (#5315)"

This reverts commit 40bc04b521.

* Handle repeated packet after potentially canceling previous Tx
2024-11-12 15:23:32 -06:00
Matthijs De Smedt
2ec3958cd8 Add support for ignoring nodes with is_ignored field in NodeInfo (#5319)
* Add support for is_ignored bool in NodeInfo

* is_ignored is not a boring node either

* Clean out metrics and position

* Clear the key too

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-11-12 13:27:44 -06:00
GUVWAF
f4b0e19a65 Fix another heap leak (#5328) 2024-11-12 10:59:29 -06:00
Ben Meadors
a49f080bd2 Revert "Portduino packaging: Move meshtastic/web out of /usr/share/doc (#5323)" (#5325)
This reverts commit 762ccdc1b9.
2024-11-12 06:40:46 -06:00
Ben Meadors
e65a754430 Remove board level extra from wismesh tap 2024-11-12 06:20:42 -06:00
Ben Meadors
a84324c4fa Don't attempt to save NodeDB on low-batt shutdown to prevent FS corruption (#5312) 2024-11-12 06:17:26 -06:00
Daniel.Cao
ff33a27789 Reduce the flash usage of wismeshtap platform (#5322)
* Reduce the flash usage of wismeshtap platform

* fix STOREFORWARD twice

* Reduce the flash usage of wismeshtap platform

* fix STOREFORWARD twice

* add range test

* Update platformio.ini

remove
-DMESHTASTIC_EXCLUDE_PAXCOUNTER=1
-DMESHTASTIC_EXCLUDE_AUDIO=1

* Update platformio.ini

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-11-12 06:16:40 -06:00
Ben Meadors
51ea7ac627 Trunk toolchain versions 2024-11-12 06:12:09 -06:00
Ben Meadors
606c2e8eb0 Exclude paxcounter 2024-11-12 05:50:30 -06:00
Austin
762ccdc1b9 Portduino packaging: Move meshtastic/web out of /usr/share/doc (#5323)
* Portduino: Move meshtastic/web out of `doc`

* Remove /usr/share/doc/meshtasticd before linking
2024-11-12 16:14:12 +08:00
Michael Gjelsø
0acccdfe2d Don't send to public channel (#5310)
* Don't send to public channel

`p->to` wasn't set and had the same value as broadcast, it's now set to our own NodeNum.

* Trunk

* Update DetectionSensorModule.cpp

Take 3

* Revert NodeNum()
2024-11-11 19:11:54 -06:00
github-actions[bot]
0e4f7003c7 [create-pull-request] automated change (#5320)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-11-11 18:55:02 -06:00
GUVWAF
40bc04b521 Fix sending duplicate packets to PhoneAPI/MQTT (#5315)
* Fix potential duplicate packets to PhoneAPI/MQTT

* Fix include error for STM32

* Fix cppcheck error
2024-11-12 07:54:05 +08:00
Thomas Göttgens
eb8d38a7e9 radiolib update (#5246)
* update radiolib to 7.1.0
* stay at 7.0.2 for STM32, also remove unused board from ESP32 arch
---------
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-11-11 16:05:48 +01:00
Ben Meadors
3d5eb34c5c Add back some details to the PhoneAPI logs (#5313) 2024-11-11 07:01:29 -06:00
Ben Meadors
3a9a4bbb92 Coerce minimum neighborinfo interval on startup (#5314) 2024-11-11 07:00:56 -06:00
Daniel.Cao
6eba2789d0 rak10701 (rak wismeshtap) optimization (#5280)
* Improve the processing speed of virtual keyboards
* Remove the disable GPS feature, as it would interfere with the normal use of TFT
* Changed the default screen sleep time to 30s
* Rename platform rak10701 -> rak wismeshtap
* Fixed rak wismeshtap turned off gps caused the screen not to display
* Reduce the size of the flash, otherwise uf2 will not work

Co-authored-by: Daniel Cao <daniel.cao@rakwireless.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Tom Fifield <tom@tomfifield.net>
2024-11-11 13:37:43 +01:00
GUVWAF
9b4c260a92 Fix memory leak in MQTT (#5311) 2024-11-11 13:22:22 +01:00
Ben Meadors
667b4ef0f2 Exclude some niche modules by default and populate exclude_modules (#5300)
* Exclude some niche modules by default

* Start of intelligently excluding modules

---------

Co-authored-by: Tom Fifield <tom@tomfifield.net>
2024-11-10 13:36:49 -06:00
Tom Fifield
db76561930 Package file move - include dotfiles (#5303)
Adds shopt -s dotglob nullglob to ensure we get 'hidden' files in
our move command.
2024-11-10 20:56:44 +08:00
Tom Fifield
7bad070891 Fix syntax error with package builds (#5302)
test (]) and its parameters need a space between them.
2024-11-10 06:13:58 -06:00
Tom Fifield
6365fcfdc6 Update dependency versions (#5299)
Using platformio pkg outdated, discover that some versions are not
up-to-date. Update all apart from RadioLib (existing pull) and
SensorLib (doesn't compile).

Also, trunk formatted platformio.ini

Package                   Current    Wanted     Latest     Type     Environments
------------------------  ---------  ---------  ---------  -------  --------------------------
Adafruit BME280 Library   2.2.2      2.2.2      2.2.4      Library  tracker-t1000-e
Adafruit INA260 Library   1.5.0      1.5.0      1.5.2      Library  tracker-t1000-e
Adafruit LPS2X            2.0.4      2.0.4      2.0.6      Library  tracker-t1000-e
Adafruit LSM6DS           4.7.2      4.7.2      4.7.3      Library  tracker-t1000-e
Adafruit MCP9808 Library  2.0.0      2.0.0      2.0.2      Library  tracker-t1000-e
Adafruit MPU6050          2.2.4      2.2.4      2.2.6      Library  tracker-t1000-e
Adafruit SHT4x Library    1.0.4      1.0.4      1.0.5      Library  tracker-t1000-e
Adafruit Unified Sensor   1.1.11     1.1.11     1.1.14     Library  tracker-t1000-e
BME68x Sensor library     1.1.40407  1.1.40407  1.2.40408  Library  tracker-t1000-e
QMC5883LCompass           1.2.0      1.2.0      1.2.3      Library  tracker-t1000-e
RadioLib                  7.0.2      7.0.2      7.1.0      Library  wio-sdk-wm1110
SensorLib                 0.2.0      0.2.0      0.2.2      Library  tbeam
2024-11-10 06:13:31 -06:00
Tom Fifield
ab2cbada75 Web now(?) comes in a /build subdirector in the tar (#5301)
* Web now(?) comes in a /build subdirector in the tar

So let's move everything to where it's expected and cleanup before
trying to unzip.

* Add checks to avoid running unneeded commands

stops this failing in the event the build subdir goes away.
2024-11-10 19:58:06 +08:00
Jonathan Bennett
875b8641d3 Pin library versions in platform.io (#5293)
* Pin library versions in platform.io

This has been a constant source of headache. This moves to only updating libraries manually. Will eliminate the random build failures, and make rebuilding specific release versions possible.

* Bump ina219 to latest library version

* More lib version bumps
2024-11-09 16:06:17 -06:00
Jonathan Bennett
67c2c516a0 Use sudo for building armv7 2024-11-09 12:44:06 -06:00
Tom Fifield
623203ca3b Remove scary warning about full NodeDB (#5292)
NodeDB becoming full at 100 entries and cycling out old entries is normal behaviour. The user doesn't need to take any action and shouldn't be concerned when this happens.

Remove the warning from the screen and reduce loglevel to info.
2024-11-09 07:30:04 -06:00
github-actions[bot]
f28f0a9d90 [create-pull-request] automated change (#5290)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-11-09 05:31:09 -06:00
GUVWAF
893efe4f11 Always set the channel corresponding to a node (#5287) 2024-11-09 11:30:12 +08:00
GUVWAF
2c2213ef9b Add setting to transmit NeighborInfo over LoRa (#5286)
* Add setting to transmit NeighborInfo over LoRa
Only if not using the default channel

* Bump minimum broadcast interval for NeighborInfo to 4 hours
2024-11-09 09:38:48 +08:00
github-actions[bot]
439c1dec08 [create-pull-request] automated change (#5284)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-11-08 07:53:55 -06:00
Tavis
aa184e6d8b copy the has_relative_humidity value to telem packet from AHTX0 packet (#5277)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-11-08 07:59:36 +08:00
Marco Veneziano
2eea412f1c Fixed compile error when using GPS_DEBUG (#5275) 2024-11-07 16:19:31 -06:00
Thomas Göttgens
b0a5a26f58 fix wio-tracker-dev sensor scan (#5274) 2024-11-07 18:01:58 +01:00
Thomas Göttgens
a815a770b4 Sync up ESP32 build variants 2024-11-07 15:03:05 +01:00
Austin
286f3c6458 uClibc compatibility (#5270)
* uclibc compatibility

Adds compatibility with uclibc, the officially supported toolchain of the luckfox pico

* Explicitly link stdc++fs for std::filesystem

Bringing this over from buildroot-meshtastic
2024-11-07 14:23:08 +01:00
github-actions[bot]
b506f6dcb0 [create-pull-request] automated change (#5272)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-11-07 07:17:23 -06:00
Jeremiah K
bd3755bb33 Fix device flashing scripts so they work with esptool when it's installed via pipx (#5269)
* Try esptool.py in device flashing scripts for pipx compatibility

* esptool detection fixes in device flashing .bat's
2024-11-07 09:43:34 +08:00
Ben Meadors
73e2e25eb1 Smarter traffic scaling (#5264) 2024-11-06 15:00:53 -06:00
GUVWAF
3bd3911913 Only PKC encrypt when packet originates from us (#5267) 2024-11-06 22:00:26 +01:00
Ben Meadors
982190936d More log reductions. I'll probably stop now ;-) (#5263) 2024-11-06 21:03:25 +08:00
Ben Meadors
8498b175e7 Add exception for RTC to not strip time from position (#5262)
* Add exception for RTC to not strip time from position

* t
2024-11-06 10:06:43 +08:00
github-actions[bot]
255713d23d [create-pull-request] automated change (#5258)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-11-05 19:33:20 -06:00
Timo
8e2a3e5728 fix display of umlauts (UTF-8 left byte C3) (#5252) 2024-11-05 04:36:37 -06:00
Ben Meadors
f769c50fa5 More reduction (#5256)
* Now with even fewer ings

* Ye

* Mo

* QMA6100PSensor
2024-11-04 19:15:59 -06:00
GUVWAF
7ba6d97e99 Release no-LoRa packet after sending to phone (#5254) 2024-11-04 14:13:54 -06:00
GUVWAF
f3b698905d Disable automatic NodeInfo request when NodeDB is full (#5255) 2024-11-04 14:06:12 -06:00
Ben Meadors
50dac38a1b Pass#2: Lots more savings in logs and string reduction surgery (#5251)
* Pass#2: Lots more savings in logs and string reduction surgery

* Don't need Thread suffix either

* Warn
2024-11-04 12:16:25 -06:00
Jonathan Bennett
bf944e78d8 More configs (#5253)
* Add config.available for the MeshAdv 900M30S

* Move configs out of config.yaml
2024-11-04 11:17:32 -06:00
Tom Fifield
e71be778dd Fix cppcheck HIGH error (#5250)
https://github.com/meshtastic/firmware/pull/5247 introduced new
protobufs, particularly the excluded_modules feature.

Immediately afterward, cppcheck started sounding klaxons about
an unitialized variable. This patch simply sets excluded_modules
to none as a temporary measure while the feature from protobuf
is integrated into code.
2024-11-04 07:03:50 -06:00
Tom Fifield
276067065e Log cleanups (#5135)
* Log cleanups

change log levels, shorten log messages, delete commented out logs

* Address comments from review

* Remove full stops

* EDEBUG --> DEBUG
2024-11-04 06:09:23 -06:00
github-actions[bot]
a628c93125 [create-pull-request] automated change (#5247)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-11-04 05:40:55 -06:00
Ben Meadors
03aaaafa13 Exclude preferred routing roles from nodeinfo interrogation behavior (#5242)
* Exclude prefered routing roles from nodeinfo interrogation behavior

* Exclude prefered routing roles from nodeinfo interrogation behavior

* Update MeshService.cpp

* Rework logic to prevent spammy router logs
2024-11-04 19:05:03 +08:00
Thomas Göttgens
0a82fd28b3 PIO_ENV (#5239)
* add hw_env to packet

needs https://github.com/meshtastic/protobufs/pull/616

* rename to pio_env

* Move to mynodeinfo

* Includy doody

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-11-03 20:02:13 -06:00
github-actions[bot]
89c186e662 [create-pull-request] automated change (#5243)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-11-03 19:48:50 -06:00
github-actions[bot]
8c99f913c1 [create-pull-request] automated change (#5241)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-11-03 16:18:38 -06:00
Thomas Göttgens
d00acc5d7b Update stale_bot.yml 2024-11-03 20:10:17 +01:00
Austin
9415254dda musl compatibility (#5219)
* musl compat

* trunk fmt

* Update platform-native, including musl fix

https://github.com/meshtastic/platform-native/pull/5

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-11-03 14:24:04 +01:00
Tom Fifield
448c754882 LR1110 - remove old comment referring to non-existent function. (#5233)
It seems like there was no setrxgain function in RadioLib. Since
we're unlikely to uncomment and enable this non-existent feature,
remove this code.
2024-11-03 14:14:06 +01:00
GUVWAF
da7424a604 Improve ACK logic for responses and repeated packets (#5232)
* Don't send ACKs to responses over multiple hops

* Move repeated sending logic to `wasSeenRecently()`

* Add exception for simulator for duplicate packets from PhoneAPI

* Add short debug message
2024-11-03 06:21:45 -06:00
Tom Fifield
1bec23b6bb Fix displays showing "GPS Not Present" until first lock (#5229)
https://github.com/meshtastic/firmware/pull/5160 introduced a change
which made first publication of GPS information take up to 15mins.
For that initial period, displays would show "No GPS Present", even
if one was detected.

This change fixes that bug, triggering publication immediately after
a GPS module is detected.
2024-11-03 06:19:15 -06:00
Technologyman00
bee474ee54 Spell check all Code (#5228)
* Spelling Fixes

* More Spelling Errors

* More Spelling Checks

* fixed wording

* Undo mesh\generated changes

* Missed one file on readd

* missed second file
2024-11-03 09:25:05 +08:00
github-actions[bot]
93bc61c855 [create-pull-request] automated change (#5227)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-11-02 16:30:43 +01:00
225 changed files with 4212 additions and 2040 deletions

View File

@@ -51,6 +51,7 @@ runs:
file: build.tar
target: build.tar
token: ${{ inputs.github_token }}
version: tags/v2.5.3
- name: Unpack web ui
if: inputs.include-web-ui == 'true'

View File

@@ -7,6 +7,8 @@ on:
required: true
type: string
permissions: read-all
jobs:
build-esp32:
runs-on: ubuntu-latest
@@ -24,6 +26,7 @@ jobs:
./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.bin
ota-firmware-target: release/bleota.bin

View File

@@ -26,10 +26,12 @@ jobs:
./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
include-web-ui: true
arch: esp32c3

View File

@@ -33,4 +33,5 @@ jobs:
artifact-paths: |
release/*.bin
release/*.elf
include-web-ui: true
arch: esp32c6

View File

@@ -7,6 +7,8 @@ on:
required: true
type: string
permissions: read-all
jobs:
build-esp32-s3:
runs-on: ubuntu-latest
@@ -24,6 +26,7 @@ jobs:
./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-s3.bin
ota-firmware-target: release/bleota-s3.bin

View File

@@ -13,8 +13,8 @@ jobs:
- name: Install libbluetooth
shell: bash
run: |
apt-get update -y --fix-missing
apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev
sudo apt-get update -y --fix-missing
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev
- name: Checkout code
uses: actions/checkout@v4

View File

@@ -13,8 +13,8 @@ jobs:
- name: Install libbluetooth
shell: bash
run: |
apt-get update -y --fix-missing
apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev
sudo apt-get update -y --fix-missing
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev
- name: Checkout code
uses: actions/checkout@v4

View File

@@ -203,6 +203,7 @@ jobs:
./device-*.sh
./device-*.bat
./littlefs-*.bin
./littlefswebui-*.bin
./bleota*bin
./Meshtastic_nRF52_factory_erase*.uf2
retention-days: 30

View File

@@ -54,7 +54,11 @@ jobs:
mkdir -p .debpkg/etc/meshtasticd/available.d
mkdir -p .debpkg/usr/lib/systemd/system/
tar -xf build.tar -C .debpkg/usr/share/doc/meshtasticd/web
gunzip .debpkg/usr/share/doc/meshtasticd/web/*.gz
shopt -s dotglob nullglob
if [ -d .debpkg/usr/share/doc/meshtasticd/web/build ]; then mv .debpkg/usr/share/doc/meshtasticd/web/build/* .debpkg/usr/share/doc/meshtasticd/web/; fi
if [ -d .debpkg/usr/share/doc/meshtasticd/web/build ]; then rmdir .debpkg/usr/share/doc/meshtasticd/web/build; fi
if [ -d .debpkg/usr/share/doc/meshtasticd/web/.DS_Store]; then rm -f .debpkg/usr/share/doc/meshtasticd/web/.DS_Store; fi
gunzip .debpkg/usr/share/doc/meshtasticd/web/ -r
cp release/meshtasticd_linux_x86_64 .debpkg/usr/sbin/meshtasticd
cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/

View File

@@ -54,7 +54,11 @@ jobs:
mkdir -p .debpkg/etc/meshtasticd/available.d
mkdir -p .debpkg/usr/lib/systemd/system/
tar -xf build.tar -C .debpkg/usr/share/doc/meshtasticd/web
gunzip .debpkg/usr/share/doc/meshtasticd/web/*.gz
shopt -s dotglob nullglob
if [ -d .debpkg/usr/share/doc/meshtasticd/web/build ]; then mv .debpkg/usr/share/doc/meshtasticd/web/build/* .debpkg/usr/share/doc/meshtasticd/web/; fi
if [ -d .debpkg/usr/share/doc/meshtasticd/web/build ]; then rmdir .debpkg/usr/share/doc/meshtasticd/web/build; fi
if [ -d .debpkg/usr/share/doc/meshtasticd/web/.DS_Store]; then rm -f .debpkg/usr/share/doc/meshtasticd/web/.DS_Store; fi
gunzip .debpkg/usr/share/doc/meshtasticd/web/ -r
cp release/meshtasticd_linux_aarch64 .debpkg/usr/sbin/meshtasticd
cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/

View File

@@ -54,7 +54,11 @@ jobs:
mkdir -p .debpkg/etc/meshtasticd/available.d
mkdir -p .debpkg/usr/lib/systemd/system/
tar -xf build.tar -C .debpkg/usr/share/doc/meshtasticd/web
gunzip .debpkg/usr/share/doc/meshtasticd/web/*.gz
shopt -s dotglob nullglob
if [ -d .debpkg/usr/share/doc/meshtasticd/web/build ]; then mv .debpkg/usr/share/doc/meshtasticd/web/build/* .debpkg/usr/share/doc/meshtasticd/web/; fi
if [ -d .debpkg/usr/share/doc/meshtasticd/web/build ]; then rmdir .debpkg/usr/share/doc/meshtasticd/web/build; fi
if [ -d .debpkg/usr/share/doc/meshtasticd/web/.DS_Store]; then rm -f .debpkg/usr/share/doc/meshtasticd/web/.DS_Store; fi
gunzip .debpkg/usr/share/doc/meshtasticd/web/ -r
cp release/meshtasticd_linux_armv7l .debpkg/usr/sbin/meshtasticd
cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/

View File

@@ -7,6 +7,7 @@ on:
permissions:
issues: write
pull-requests: write
actions: write
jobs:
stale_issues:

View File

@@ -1,6 +1,6 @@
version: 0.1
cli:
version: 1.22.7
version: 1.22.8
plugins:
sources:
- id: trunk
@@ -8,20 +8,20 @@ plugins:
uri: https://github.com/trunk-io/plugins
lint:
enabled:
- trufflehog@3.83.2
- trufflehog@3.83.6
- yamllint@1.35.1
- bandit@1.7.10
- checkov@3.2.276
- checkov@3.2.287
- terrascan@1.19.9
- trivy@0.56.2
#- trufflehog@3.63.2-rc0
- taplo@0.9.3
- ruff@0.7.1
- ruff@0.7.3
- isort@5.13.2
- markdownlint@0.42.0
- oxipng@9.1.2
- svgo@3.3.2
- actionlint@1.7.3
- actionlint@1.7.4
- flake8@7.1.1
- hadolint@2.12.0
- shfmt@3.6.0

View File

@@ -1,4 +1,4 @@
# Contributor Covenant Code of Conduct
The Meshtastic Firmware project is subject to the code of conduct for the parent project, which can be found here:
The Meshtastic Firmware project is subject to the code of conduct for the parent project, which can be found here:
https://meshtastic.org/docs/legal/conduct/

View File

@@ -43,9 +43,10 @@ lib_deps =
${arduino_base.lib_deps}
${networking_base.lib_deps}
${environmental_base.lib_deps}
${radiolib_base.lib_deps}
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
h2zero/NimBLE-Arduino@^1.4.2
https://github.com/dbSuS/libpax.git#7bcd3fcab75037505be9b122ab2b24cc5176b587
https://github.com/dbinfrago/libpax.git#3cdc0371c375676a97967547f4065607d4c53fd1
lewisxhe/XPowersLib@^0.2.6
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
rweather/Crypto@^0.4.0

View File

@@ -23,6 +23,7 @@ lib_deps =
${arduino_base.lib_deps}
${networking_base.lib_deps}
${environmental_base.lib_deps}
${radiolib_base.lib_deps}
lewisxhe/XPowersLib@^0.2.6
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
rweather/Crypto@^0.4.0

View File

@@ -14,12 +14,16 @@ build_flags =
-Wno-unused-variable
-Isrc/platform/nrf52
-DLFS_NO_ASSERT ; Disable LFS assertions , see https://github.com/meshtastic/firmware/pull/3818
-DMESHTASTIC_EXCLUDE_AUDIO=1
-DMESHTASTIC_EXCLUDE_PAXCOUNTER=1
-DMAX_NUM_NODES=80
build_src_filter =
${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}
${radiolib_base.lib_deps}
rweather/Crypto@^0.4.0
lib_ignore =

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#6b3796d697481c8f6e3f4aa5c111bd9979f29e64
platform = https://github.com/meshtastic/platform-native.git#bcd02436cfca91f7d28ad0f7dab977c6aaa781af
framework = arduino
build_src_filter =
@@ -23,6 +23,7 @@ build_src_filter =
lib_deps =
${env.lib_deps}
${networking_base.lib_deps}
${radiolib_base.lib_deps}
rweather/Crypto@^0.4.0
https://github.com/lovyan03/LovyanGFX.git#1401c28a47646fe00538d487adcb2eb3c72de805
@@ -32,6 +33,7 @@ build_flags =
-Isrc/platform/portduino
-DRADIOLIB_EEPROM_UNSUPPORTED
-DPORTDUINO_LINUX_HARDWARE
-lstdc++fs
-lbluetooth
-lgpiod
-lyaml-cpp

View File

@@ -1,8 +1,8 @@
; Common settings for rp2040 Processor based targets
[rp2040_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#v1.2.0-gcc12
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#19e30129fb1428b823be585c787dcb4ac0d9014c ; For arduino-pico 4.2.1
extends = arduino_base
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#4.0.3
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#996c3bfab9758f12c07aa20cc6d352e630c16987 ; 4.2.1 with fix for sporadic hangs
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
@@ -22,4 +22,5 @@ lib_ignore =
lib_deps =
${arduino_base.lib_deps}
${environmental_base.lib_deps}
${radiolib_base.lib_deps}
rweather/Crypto

View File

@@ -1,8 +1,8 @@
; Common settings for rp2040 Processor based targets
[rp2350_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#9e55f6db5c56b9867c69fe473f388beea4546672
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#19e30129fb1428b823be585c787dcb4ac0d9014c ; For arduino-pico 4.2.1
extends = arduino_base
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#a6ab6e1f95bc1428d667d55ea7173c0744acc03c ; 4.0.2+
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#96c3bfab9758f12c07aa20cc6d352e630c16987 ; 4.2.1 with fix for sporadic hangs
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
@@ -21,4 +21,5 @@ lib_ignore =
lib_deps =
${arduino_base.lib_deps}
${environmental_base.lib_deps}
rweather/Crypto
${radiolib_base.lib_deps}
rweather/Crypto

View File

@@ -30,8 +30,9 @@ upload_protocol = stlink
lib_deps =
${env.lib_deps}
charlesbaynham/OSFS@^1.2.3
jgromes/RadioLib@7.0.2
https://github.com/caveman99/Crypto.git#f61ae26a53f7a2d0ba5511625b8bf8eff3a35d5e
lib_ignore =
mathertel/OneButton@~2.6.1
mathertel/OneButton@2.6.1
Wire

33
bin/base64_to_hex.py Normal file
View File

@@ -0,0 +1,33 @@
import sys
import base64
def base64_to_hex_string(b64_string):
try:
# Decode the Base64 string to raw bytes
decoded_bytes = base64.b64decode(b64_string)
except Exception as e:
raise ValueError(f"Invalid Base64 input: {e}")
# Check if the decoded result is exactly 32 bytes
if len(decoded_bytes) != 32:
raise ValueError("Decoded Base64 input must be exactly 32 bytes.")
# Convert each byte to its hex representation
hex_values = [f"0x{byte:02x}" for byte in decoded_bytes]
# Join the formatted hex values with commas
formatted_output = "{ " + ", ".join(hex_values) + " };"
return formatted_output
if __name__ == "__main__":
# Check if a Base64 string was provided in command line arguments
if len(sys.argv) != 2:
print("Usage: python script.py <base64-string>")
sys.exit(1)
b64_string = sys.argv[1]
try:
formatted_hex = base64_to_hex_string(b64_string)
print(formatted_hex)
except ValueError as e:
print(e)

View File

@@ -35,6 +35,11 @@ cp $SRCBIN $OUTDIR/$basename-update.bin
echo "Building Filesystem for ESP32 targets"
pio run --environment $1 -t buildfs
cp .pio/build/$1/littlefs.bin $OUTDIR/littlefswebui-$VERSION.bin
# Remove webserver files from the filesystem and rebuild
ls -l data/static # Diagnostic list of files
rm -rf data/static
pio run --environment $1 -t buildfs
cp .pio/build/$1/littlefs.bin $OUTDIR/littlefs-$VERSION.bin
cp bin/device-install.* $OUTDIR
cp bin/device-update.* $OUTDIR

View File

@@ -27,5 +27,4 @@ rm -r $OUTDIR/* || true
platformio pkg update --environment native || platformioFailed
pio run --environment native || platformioFailed
cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(uname -m)"
cp bin/device-install.* $OUTDIR
cp bin/device-update.* $OUTDIR
cp bin/native-install.* $OUTDIR

View File

@@ -81,17 +81,6 @@ I2C:
Display:
### Waveshare 2.8inch RPi LCD
# Panel: ST7789
# CS: 8
# DC: 22 # Data/Command pin
# Backlight: 18
# Width: 240
# Height: 320
# Reset: 27
# Rotate: true
# Invert: true
### Waveshare 1.44inch LCD HAT
# Panel: ST7735S
# CS: 8 #Chip Select
@@ -148,10 +137,6 @@ Touchscreen:
# IRQ: 24
# I2CAddr: 0x38
# Module: XPT2046 # Waveshare 2.8inch
# CS: 7
# IRQ: 17
### You can also specify the spi device for the touchscreen to use
# spidev: spidev0.0

View File

@@ -0,0 +1,9 @@
Lora:
Module: sx1262
CS: 21
IRQ: 16
Busy: 20
Reset: 18
TXen: 13
RXen: 12
DIO3_TCXO_VOLTAGE: true

View File

@@ -1,16 +1,26 @@
@ECHO OFF
set PYTHON=python
set WEB_APP=0
:: Determine the correct esptool command to use
where esptool >nul 2>&1
if %ERRORLEVEL% EQU 0 (
set "ESPTOOL_CMD=esptool"
) else (
set "ESPTOOL_CMD=%PYTHON% -m esptool"
)
goto GETOPTS
:HELP
echo Usage: %~nx0 [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME^|FILENAME]
echo Usage: %~nx0 [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME^|FILENAME] [--web]
echo Flash image file to device, but first erasing and writing system information
echo.
echo -h Display this help and exit
echo -p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerrous).
echo -P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: %PYTHON%)
echo -f FILENAME The .bin file to flash. Custom to your device type and region.
echo --web Flash WEB APP.
goto EOF
:GETOPTS
@@ -19,37 +29,44 @@ if /I "%1"=="--help" goto HELP
if /I "%1"=="-F" set "FILENAME=%2" & SHIFT
if /I "%1"=="-p" set ESPTOOL_PORT=%2 & SHIFT
if /I "%1"=="-P" set PYTHON=%2 & SHIFT
if /I "%1"=="--web" set WEB_APP=1 & SHIFT
SHIFT
IF NOT "__%1__"=="____" goto GETOPTS
IF "__%FILENAME%__" == "____" (
echo "Missing FILENAME"
goto HELP
goto HELP
)
IF EXIST %FILENAME% IF x%FILENAME:update=%==x%FILENAME% (
echo Trying to flash update %FILENAME%, but first erasing and writing system information"
%PYTHON% -m esptool --baud 115200 erase_flash
%PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME%
%ESPTOOL_CMD% --baud 115200 erase_flash
%ESPTOOL_CMD% --baud 115200 write_flash 0x00 %FILENAME%
@REM Account for S3 and C3 board's different OTA partition
IF x%FILENAME:s3=%==x%FILENAME% IF x%FILENAME:v3=%==x%FILENAME% IF x%FILENAME:t-deck=%==x%FILENAME% IF x%FILENAME:wireless-paper=%==x%FILENAME% IF x%FILENAME:wireless-tracker=%==x%FILENAME% IF x%FILENAME:station-g2=%==x%FILENAME% IF x%FILENAME:unphone=%==x%FILENAME% (
IF x%FILENAME:esp32c3=%==x%FILENAME% (
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota.bin
%ESPTOOL_CMD% --baud 115200 write_flash 0x260000 bleota.bin
) else (
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota-c3.bin
%ESPTOOL_CMD% --baud 115200 write_flash 0x260000 bleota-c3.bin
)
) else (
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota-s3.bin
) else (
%ESPTOOL_CMD% --baud 115200 write_flash 0x260000 bleota-s3.bin
)
for %%f in (littlefs-*.bin) do (
%PYTHON% -m esptool --baud 115200 write_flash 0x300000 %%f
IF %WEB_APP%==1 (
for %%f in (littlefswebui-*.bin) do (
%ESPTOOL_CMD% --baud 115200 write_flash 0x300000 %%f
)
) else (
for %%f in (littlefs-*.bin) do (
%ESPTOOL_CMD% --baud 115200 write_flash 0x300000 %%f
)
)
) else (
echo "Invalid file: %FILENAME%"
goto HELP
goto HELP
) else (
echo "Invalid file: %FILENAME%"
goto HELP
goto HELP
)
:EOF

View File

@@ -1,22 +1,45 @@
#!/bin/sh
PYTHON=${PYTHON:-$(which python3 python | head -n 1)}
WEB_APP=false
# Determine the correct esptool command to use
if "$PYTHON" -m esptool version >/dev/null 2>&1; then
ESPTOOL_CMD="$PYTHON -m esptool"
elif command -v esptool >/dev/null 2>&1; then
ESPTOOL_CMD="esptool"
elif command -v esptool.py >/dev/null 2>&1; then
ESPTOOL_CMD="esptool.py"
else
echo "Error: esptool not found"
exit 1
fi
set -e
# Usage info
show_help() {
cat <<EOF
Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME]
Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME] [--web]
Flash image file to device, but first erasing and writing system information"
-h Display this help and exit
-p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerous).
-P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON")
-f FILENAME The .bin file to flash. Custom to your device type and region.
--web Flash WEB APP.
EOF
}
# Preprocess long options like --web
for arg in "$@"; do
case "$arg" in
--web)
WEB_APP=true
shift # Remove this argument from the list
;;
esac
done
while getopts ":hp:P:f:" opt; do
case "${opt}" in
@@ -49,19 +72,23 @@ shift "$((OPTIND - 1))"
if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
"$PYTHON" -m esptool erase_flash
"$PYTHON" -m esptool write_flash 0x00 ${FILENAME}
$ESPTOOL_CMD erase_flash
$ESPTOOL_CMD write_flash 0x00 ${FILENAME}
# Account for S3 board's different OTA partition
if [ -n "${FILENAME##*"s3"*}" ] && [ -n "${FILENAME##*"-v3"*}" ] && [ -n "${FILENAME##*"t-deck"*}" ] && [ -n "${FILENAME##*"wireless-paper"*}" ] && [ -n "${FILENAME##*"wireless-tracker"*}" ] && [ -n "${FILENAME##*"station-g2"*}" ] && [ -n "${FILENAME##*"unphone"*}" ]; then
if [ -n "${FILENAME##*"esp32c3"*}" ]; then
"$PYTHON" -m esptool write_flash 0x260000 bleota.bin
$ESPTOOL_CMD write_flash 0x260000 bleota.bin
else
"$PYTHON" -m esptool write_flash 0x260000 bleota-c3.bin
$ESPTOOL_CMD write_flash 0x260000 bleota-c3.bin
fi
else
"$PYTHON" -m esptool write_flash 0x260000 bleota-s3.bin
$ESPTOOL_CMD write_flash 0x260000 bleota-s3.bin
fi
if [ "$WEB_APP" = true ]; then
$ESPTOOL_CMD write_flash 0x300000 littlefswebui-*.bin
else
$ESPTOOL_CMD write_flash 0x300000 littlefs-*.bin
fi
"$PYTHON" -m esptool write_flash 0x300000 littlefs-*.bin
else
show_help

View File

@@ -2,6 +2,14 @@
set PYTHON=python
:: Determine the correct esptool command to use
where esptool >nul 2>&1
if %ERRORLEVEL% EQU 0 (
set "ESPTOOL_CMD=esptool"
) else (
set "ESPTOOL_CMD=%PYTHON% -m esptool"
)
goto GETOPTS
:HELP
echo Usage: %~nx0 [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME^|FILENAME]
@@ -24,17 +32,17 @@ IF NOT "__%1__"=="____" goto GETOPTS
IF "__%FILENAME%__" == "____" (
echo "Missing FILENAME"
goto HELP
goto HELP
)
IF EXIST %FILENAME% IF NOT x%FILENAME:update=%==x%FILENAME% (
echo Trying to flash update %FILENAME%
%PYTHON% -m esptool --baud 115200 write_flash 0x10000 %FILENAME%
%ESPTOOL_CMD% --baud 115200 write_flash 0x10000 %FILENAME%
) else (
echo "Invalid file: %FILENAME%"
goto HELP
goto HELP
) else (
echo "Invalid file: %FILENAME%"
goto HELP
goto HELP
)
:EOF

View File

@@ -2,6 +2,18 @@
PYTHON=${PYTHON:-$(which python3 python|head -n 1)}
# Determine the correct esptool command to use
if "$PYTHON" -m esptool version >/dev/null 2>&1; then
ESPTOOL_CMD="$PYTHON -m esptool"
elif command -v esptool >/dev/null 2>&1; then
ESPTOOL_CMD="esptool"
elif command -v esptool.py >/dev/null 2>&1; then
ESPTOOL_CMD="esptool.py"
else
echo "Error: esptool not found"
exit 1
fi
# Usage info
show_help() {
cat << EOF
@@ -9,7 +21,7 @@ Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME]
Flash image file to device, leave existing system intact."
-h Display this help and exit
-p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerrous).
-p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerous).
-P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON")
-f FILENAME The *update.bin file to flash. Custom to your device type.
@@ -30,7 +42,7 @@ while getopts ":hp:P:f:" opt; do
f) FILENAME=${OPTARG}
;;
*)
echo "Invalid flag."
echo "Invalid flag."
show_help >&2
exit 1
;;
@@ -45,7 +57,7 @@ shift "$((OPTIND-1))"
if [ -f "${FILENAME}" ] && [ -z "${FILENAME##*"update"*}" ]; then
printf "Trying to flash update ${FILENAME}"
$PYTHON -m esptool --baud 115200 write_flash 0x10000 ${FILENAME}
$ESPTOOL_CMD --baud 115200 write_flash 0x10000 ${FILENAME}
else
show_help
echo "Invalid file: ${FILENAME}"

View File

@@ -88,12 +88,13 @@ Import("projenv")
prefsLoc = projenv["PROJECT_DIR"] + "/version.properties"
verObj = readProps(prefsLoc)
print("Using meshtastic platformio-custom.py, firmware version " + verObj["long"])
print("Using meshtastic platformio-custom.py, firmware version " + verObj["long"] + " on " + env.get("PIOENV"))
# General options that are passed to the C and C++ compilers
projenv.Append(
CCFLAGS=[
"-DAPP_VERSION=" + verObj["long"],
"-DAPP_VERSION_SHORT=" + verObj["short"],
"-DAPP_ENV=" + env.get("PIOENV"),
]
)

View File

@@ -29,138 +29,134 @@ default_envs = tbeam
;default_envs = rak4631
;default_envs = rak4631_eth_gw
;default_envs = rak2560
;default_envs = rak10701
;default_envs = rak_wismeshtap
;default_envs = wio-e5
;default_envs = radiomaster_900_bandit_nano
;default_envs = radiomaster_900_bandit_micro
;default_envs = radiomaster_900_bandit
;default_envs = heltec_capsule_sensor_v3
;default_envs = heltec_vision_master_t190
;default_envs = heltec_vision_master_e213
;default_envs = heltec_vision_master_e290
;default_envs = heltec_mesh_node_t114
extra_configs =
arch/*/*.ini
variants/*/platformio.ini
arch/*/*.ini
variants/*/platformio.ini
description = Meshtastic
[env]
test_build_src = true
extra_scripts = bin/platformio-custom.py
; note: we add src to our include search path so that lmic_project_config can override
; note: TINYGPS_OPTION_NO_CUSTOM_FIELDS is VERY important. We don't use custom fields and somewhere in that pile
; of code is a heap corruption bug!
; FIXME: fix lib/BluetoothOTA dependency back on src/ so we can remove -Isrc
; The Radiolib stuff will speed up building considerably. Exclud all the stuff we dont need.
build_flags = -Wno-missing-field-initializers
-Wno-format
-Isrc -Isrc/mesh -Isrc/mesh/generated -Isrc/gps -Isrc/buzz -Wl,-Map,.pio/build/output.map
-DUSE_THREAD_NAMES
-DTINYGPS_OPTION_NO_CUSTOM_FIELDS
-DPB_ENABLE_MALLOC=1
-DRADIOLIB_EXCLUDE_CC1101=1
-DRADIOLIB_EXCLUDE_NRF24=1
-DRADIOLIB_EXCLUDE_RF69=1
-DRADIOLIB_EXCLUDE_SX1231=1
-DRADIOLIB_EXCLUDE_SX1233=1
-DRADIOLIB_EXCLUDE_SI443X=1
-DRADIOLIB_EXCLUDE_RFM2X=1
-DRADIOLIB_EXCLUDE_AFSK=1
-DRADIOLIB_EXCLUDE_BELL=1
-DRADIOLIB_EXCLUDE_HELLSCHREIBER=1
-DRADIOLIB_EXCLUDE_MORSE=1
-DRADIOLIB_EXCLUDE_RTTY=1
-DRADIOLIB_EXCLUDE_SSTV=1
-DRADIOLIB_EXCLUDE_AX25=1
-DRADIOLIB_EXCLUDE_DIRECT_RECEIVE=1
-DRADIOLIB_EXCLUDE_BELL=1
-DRADIOLIB_EXCLUDE_PAGER=1
-DRADIOLIB_EXCLUDE_FSK4=1
-DRADIOLIB_EXCLUDE_APRS=1
-DRADIOLIB_EXCLUDE_LORAWAN=1
-DMESHTASTIC_EXCLUDE_DROPZONE=1
-DMESHTASTIC_EXCLUDE_REMOTEHARDWARE=1
#-DBUILD_EPOCH=$UNIX_TIME
;-D OLED_PL
-Wno-format
-Isrc -Isrc/mesh -Isrc/mesh/generated -Isrc/gps -Isrc/buzz -Wl,-Map,.pio/build/output.map
-DUSE_THREAD_NAMES
-DTINYGPS_OPTION_NO_CUSTOM_FIELDS
-DPB_ENABLE_MALLOC=1
-DRADIOLIB_EXCLUDE_CC1101=1
-DRADIOLIB_EXCLUDE_NRF24=1
-DRADIOLIB_EXCLUDE_RF69=1
-DRADIOLIB_EXCLUDE_SX1231=1
-DRADIOLIB_EXCLUDE_SX1233=1
-DRADIOLIB_EXCLUDE_SI443X=1
-DRADIOLIB_EXCLUDE_RFM2X=1
-DRADIOLIB_EXCLUDE_AFSK=1
-DRADIOLIB_EXCLUDE_BELL=1
-DRADIOLIB_EXCLUDE_HELLSCHREIBER=1
-DRADIOLIB_EXCLUDE_MORSE=1
-DRADIOLIB_EXCLUDE_RTTY=1
-DRADIOLIB_EXCLUDE_SSTV=1
-DRADIOLIB_EXCLUDE_AX25=1
-DRADIOLIB_EXCLUDE_DIRECT_RECEIVE=1
-DRADIOLIB_EXCLUDE_BELL=1
-DRADIOLIB_EXCLUDE_PAGER=1
-DRADIOLIB_EXCLUDE_FSK4=1
-DRADIOLIB_EXCLUDE_APRS=1
-DRADIOLIB_EXCLUDE_LORAWAN=1
-DMESHTASTIC_EXCLUDE_DROPZONE=1
-DMESHTASTIC_EXCLUDE_REMOTEHARDWARE=1
-DMESHTASTIC_EXCLUDE_POWERSTRESS=1 ; exclude power stress test module from main firmware
#-DBUILD_EPOCH=$UNIX_TIME
;-D OLED_PL
monitor_speed = 115200
monitor_filters = direct
lib_deps =
jgromes/RadioLib@~7.0.2
https://github.com/meshtastic/esp8266-oled-ssd1306.git#e16cee124fe26490cb14880c679321ad8ac89c95 ; ESP8266_SSD1306
mathertel/OneButton@~2.6.1 ; OneButton library for non-blocking button debounce
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
https://github.com/meshtastic/TinyGPSPlus.git#71a82db35f3b973440044c476d4bcdc673b104f4
https://github.com/meshtastic/ArduinoThread.git#1ae8778c85d0a2a729f989e0b1e7d7c4dc84eef0
nanopb/Nanopb@^0.4.9
erriez/ErriezCRC32@^1.0.1
https://github.com/meshtastic/esp8266-oled-ssd1306.git#e16cee124fe26490cb14880c679321ad8ac89c95
mathertel/OneButton@2.6.1
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
https://github.com/meshtastic/TinyGPSPlus.git#71a82db35f3b973440044c476d4bcdc673b104f4
https://github.com/meshtastic/ArduinoThread.git#1ae8778c85d0a2a729f989e0b1e7d7c4dc84eef0
nanopb/Nanopb@0.4.9
erriez/ErriezCRC32@1.0.1
; Used for the code analysis in PIO Home / Inspect
check_tool = cppcheck
check_skip_packages = yes
check_flags =
-DAPP_VERSION=1.0.0
--suppressions-list=suppressions.txt
--inline-suppr
-DAPP_VERSION=1.0.0
--suppressions-list=suppressions.txt
--inline-suppr
; Common settings for conventional (non Portduino) Arduino targets
[arduino_base]
framework = arduino
lib_deps =
${env.lib_deps}
end2endzone/NonBlockingRTTTL@^1.3.0
https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#5cf62b36c6f30bc72a07bdb2c11fc9a22d1e31da
${env.lib_deps}
end2endzone/NonBlockingRTTTL@1.3.0
build_flags = ${env.build_flags} -Os
build_src_filter = ${env.build_src_filter} -<platform/portduino/>
; Common libs for communicating over TCP/IP networks such as MQTT
[networking_base]
lib_deps =
knolleary/PubSubClient@^2.8
arduino-libraries/NTPClient@^3.1.0
arcao/Syslog@^2.0.0
knolleary/PubSubClient@2.8
arduino-libraries/NTPClient@3.1.0
arcao/Syslog@2.0.0
[radiolib_base]
lib_deps =
jgromes/RadioLib@7.1.0
; Common libs for environmental measurements in telemetry module
; (not included in native / portduino)
[environmental_base]
lib_deps =
adafruit/Adafruit BusIO@^1.16.1
adafruit/Adafruit Unified Sensor@^1.1.11
adafruit/Adafruit BMP280 Library@^2.6.8
adafruit/Adafruit BMP085 Library@^1.2.4
adafruit/Adafruit BME280 Library@^2.2.2
adafruit/Adafruit BMP3XX Library@^2.1.5
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
adafruit/Adafruit PM25 AQI Sensor@^1.1.1
adafruit/Adafruit MPU6050@^2.2.4
adafruit/Adafruit LIS3DH@^1.3.0
adafruit/Adafruit AHTX0@^2.0.5
adafruit/Adafruit LSM6DS@^4.7.2
adafruit/Adafruit VEML7700 Library@^2.1.6
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
sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@^1.1.2
adafruit/Adafruit MLX90614 Library@^2.1.5
https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.7.2502
boschsensortec/BME68x Sensor Library@^1.1.40407
https://github.com/KodinLanewave/INA3221@^1.0.1
lewisxhe/SensorLib@0.2.0
mprograms/QMC5883LCompass@^1.2.0
https://github.com/meshtastic/DFRobot_LarkWeatherStation#4de3a9cadef0f6a5220a8a906cf9775b02b0040d
https://github.com/gjelsoe/STK8xxx-Accelerometer.git#v0.1.1
adafruit/Adafruit BusIO@1.16.2
adafruit/Adafruit Unified Sensor@1.1.14
adafruit/Adafruit BMP280 Library@2.6.8
adafruit/Adafruit BMP085 Library@1.2.4
adafruit/Adafruit BME280 Library@2.2.4
adafruit/Adafruit BMP3XX Library@2.1.5
adafruit/Adafruit MCP9808 Library@2.0.2
adafruit/Adafruit INA260 Library@1.5.2
adafruit/Adafruit INA219@1.2.3
adafruit/Adafruit MAX1704X@1.0.3
adafruit/Adafruit SHTC3 Library@1.0.1
adafruit/Adafruit LPS2X@2.0.6
adafruit/Adafruit SHT31 Library@2.2.2
adafruit/Adafruit PM25 AQI Sensor@1.1.1
adafruit/Adafruit MPU6050@2.2.6
adafruit/Adafruit LIS3DH@1.3.0
adafruit/Adafruit AHTX0@2.0.5
adafruit/Adafruit LSM6DS@4.7.3
adafruit/Adafruit VEML7700 Library@2.1.6
adafruit/Adafruit SHT4x Library@1.0.5
adafruit/Adafruit TSL2591 Library@1.4.5
sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6
sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.2.13
ClosedCube OPT3001@1.1.2
emotibit/EmotiBit MLX90632@1.0.8
sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2
adafruit/Adafruit MLX90614 Library@2.1.5
https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.7.2502
boschsensortec/BME68x Sensor Library@1.1.40407
https://github.com/KodinLanewave/INA3221@1.0.1
mprograms/QMC5883LCompass@1.2.3
dfrobot/DFRobot_RTU@1.0.3
https://github.com/meshtastic/DFRobot_LarkWeatherStation#4de3a9cadef0f6a5220a8a906cf9775b02b0040d

View File

@@ -1 +0,0 @@
curfirmwareversion.xml

View File

@@ -21,7 +21,7 @@ namespace concurrency
class AmbientLightingThread : public concurrency::OSThread
{
public:
explicit AmbientLightingThread(ScanI2C::DeviceType type) : OSThread("AmbientLightingThread")
explicit AmbientLightingThread(ScanI2C::DeviceType type) : OSThread("AmbientLighting")
{
notifyDeepSleepObserver.observe(&notifyDeepSleep); // Let us know when shutdown() is issued.
@@ -42,18 +42,18 @@ class AmbientLightingThread : public concurrency::OSThread
#ifdef HAS_NCP5623
_type = type;
if (_type == ScanI2C::DeviceType::NONE) {
LOG_DEBUG("AmbientLightingThread disabling due to no RGB leds found on I2C bus");
LOG_DEBUG("AmbientLighting Disable due to no RGB leds found on I2C bus");
disable();
return;
}
#endif
#if defined(HAS_NCP5623) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE)
if (!moduleConfig.ambient_lighting.led_state) {
LOG_DEBUG("AmbientLightingThread disabling due to moduleConfig.ambient_lighting.led_state OFF");
LOG_DEBUG("AmbientLighting Disable due to moduleConfig.ambient_lighting.led_state OFF");
disable();
return;
}
LOG_DEBUG("AmbientLightingThread initializing");
LOG_DEBUG("AmbientLighting init");
#ifdef HAS_NCP5623
if (_type == ScanI2C::NCP5623) {
rgb.begin();
@@ -106,27 +106,27 @@ class AmbientLightingThread : public concurrency::OSThread
rgb.setRed(0);
rgb.setGreen(0);
rgb.setBlue(0);
LOG_INFO("Turn Off NCP5623 Ambient lighting.");
LOG_INFO("OFF: NCP5623 Ambient lighting");
#endif
#ifdef HAS_NEOPIXEL
pixels.clear();
pixels.show();
LOG_INFO("Turn Off NeoPixel Ambient lighting.");
LOG_INFO("OFF: NeoPixel Ambient lighting");
#endif
#ifdef RGBLED_CA
analogWrite(RGBLED_RED, 255 - 0);
analogWrite(RGBLED_GREEN, 255 - 0);
analogWrite(RGBLED_BLUE, 255 - 0);
LOG_INFO("Turn Off Ambient lighting RGB Common Anode.");
LOG_INFO("OFF: Ambient light RGB Common Anode");
#elif defined(RGBLED_RED)
analogWrite(RGBLED_RED, 0);
analogWrite(RGBLED_GREEN, 0);
analogWrite(RGBLED_BLUE, 0);
LOG_INFO("Turn Off Ambient lighting RGB Common Cathode.");
LOG_INFO("OFF: Ambient light RGB Common Cathode");
#endif
#ifdef UNPHONE
unphone.rgb(0, 0, 0);
LOG_INFO("Turn Off unPhone Ambient lighting.");
LOG_INFO("OFF: unPhone Ambient lighting");
#endif
return 0;
}
@@ -138,9 +138,8 @@ class AmbientLightingThread : public concurrency::OSThread
rgb.setRed(moduleConfig.ambient_lighting.red);
rgb.setGreen(moduleConfig.ambient_lighting.green);
rgb.setBlue(moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Initializing NCP5623 Ambient lighting w/ current=%d, red=%d, green=%d, blue=%d",
moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Init NCP5623 Ambient light w/ current=%d, red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.current,
moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
#endif
#ifdef HAS_NEOPIXEL
pixels.fill(pixels.Color(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
@@ -158,7 +157,7 @@ class AmbientLightingThread : public concurrency::OSThread
#endif
#endif
pixels.show();
LOG_DEBUG("Initializing NeoPixel Ambient lighting w/ brightness(current)=%d, red=%d, green=%d, blue=%d",
LOG_DEBUG("Init NeoPixel Ambient light w/ brightness(current)=%d, red=%d, green=%d, blue=%d",
moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
moduleConfig.ambient_lighting.blue);
#endif
@@ -166,21 +165,21 @@ class AmbientLightingThread : public concurrency::OSThread
analogWrite(RGBLED_RED, 255 - moduleConfig.ambient_lighting.red);
analogWrite(RGBLED_GREEN, 255 - moduleConfig.ambient_lighting.green);
analogWrite(RGBLED_BLUE, 255 - moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Initializing Ambient lighting RGB Common Anode w/ red=%d, green=%d, blue=%d",
moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Init Ambient light RGB Common Anode w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
#elif defined(RGBLED_RED)
analogWrite(RGBLED_RED, moduleConfig.ambient_lighting.red);
analogWrite(RGBLED_GREEN, moduleConfig.ambient_lighting.green);
analogWrite(RGBLED_BLUE, moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Initializing Ambient lighting RGB Common Cathode w/ red=%d, green=%d, blue=%d",
moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Init Ambient light RGB Common Cathode w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
#endif
#ifdef UNPHONE
unphone.rgb(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Initializing unPhone Ambient lighting w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
LOG_DEBUG("Init unPhone Ambient light w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
#endif
}
};
} // namespace concurrency
} // namespace concurrency

View File

@@ -16,7 +16,7 @@
class AudioThread : public concurrency::OSThread
{
public:
AudioThread() : OSThread("AudioThread") { initOutput(); }
AudioThread() : OSThread("Audio") { initOutput(); }
void beginRttl(const void *data, uint32_t len)
{
@@ -64,7 +64,7 @@ class AudioThread : public concurrency::OSThread
void initOutput()
{
audioOut = new AudioOutputI2S(1, AudioOutputI2S::EXTERNAL_I2S);
audioOut->SetPinout(DAC_I2S_BCK, DAC_I2S_WS, DAC_I2S_DOUT);
audioOut->SetPinout(DAC_I2S_BCK, DAC_I2S_WS, DAC_I2S_DOUT, DAC_I2S_MCLK);
audioOut->SetGain(0.2);
};

View File

@@ -1,4 +1,5 @@
#include "ButtonThread.h"
#include "../userPrefs.h"
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_GPS
#include "GPS.h"
@@ -26,20 +27,25 @@ using namespace concurrency;
ButtonThread *buttonThread; // Declared extern in header
volatile ButtonThread::ButtonEventType ButtonThread::btnEvent = ButtonThread::BUTTON_EVENT_NONE;
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO) || defined(USERPREFS_BUTTON_PIN)
OneButton ButtonThread::userButton; // Get reference to static member
#endif
ButtonThread::ButtonThread() : OSThread("Button")
{
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO) || defined(USERPREFS_BUTTON_PIN)
#if defined(ARCH_PORTDUINO)
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) {
this->userButton = OneButton(settingsMap[user], true, true);
LOG_DEBUG("Using GPIO%02d for button", settingsMap[user]);
LOG_DEBUG("Use GPIO%02d for button", settingsMap[user]);
}
#elif defined(BUTTON_PIN)
int pin = config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN; // Resolved button pin
#if !defined(USERPREFS_BUTTON_PIN)
int pin = config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN; // Resolved button pin
#endif
#ifdef USERPREFS_BUTTON_PIN
int pin = config.device.button_gpio ? config.device.button_gpio : USERPREFS_BUTTON_PIN; // Resolved button pin
#endif
#if defined(HELTEC_CAPSULE_SENSOR_V3)
this->userButton = OneButton(pin, false, false);
#elif defined(BUTTON_ACTIVE_LOW)
@@ -47,7 +53,7 @@ ButtonThread::ButtonThread() : OSThread("Button")
#else
this->userButton = OneButton(pin, true, true);
#endif
LOG_DEBUG("Using GPIO%02d for button", pin);
LOG_DEBUG("Use GPIO%02d for button", pin);
#endif
#ifdef INPUT_PULLUP_SENSE
@@ -59,7 +65,7 @@ ButtonThread::ButtonThread() : OSThread("Button")
#endif
#endif
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO) || defined(USERPREFS_BUTTON_PIN)
userButton.attachClick(userButtonPressed);
userButton.setClickMs(BUTTON_CLICK_MS);
userButton.setPressMs(BUTTON_LONGPRESS_MS);
@@ -102,7 +108,7 @@ int32_t ButtonThread::runOnce()
// If the button is pressed we suppress CPU sleep until release
canSleep = true; // Assume we should not keep the board awake
#if defined(BUTTON_PIN)
#if defined(BUTTON_PIN) || defined(USERPREFS_BUTTON_PIN)
userButton.tick();
canSleep &= userButton.isIdle();
#elif defined(ARCH_PORTDUINO)
@@ -130,7 +136,12 @@ int32_t ButtonThread::runOnce()
return 50;
}
#ifdef BUTTON_PIN
#if !defined(USERPREFS_BUTTON_PIN)
if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) !=
#endif
#if defined(USERPREFS_BUTTON_PIN)
if (((config.device.button_gpio ? config.device.button_gpio : USERPREFS_BUTTON_PIN) !=
#endif
moduleConfig.canned_message.inputbroker_pin_press) ||
!(moduleConfig.canned_message.updown1_enabled || moduleConfig.canned_message.rotary1_enabled) ||
!moduleConfig.canned_message.enabled) {
@@ -244,7 +255,12 @@ void ButtonThread::attachButtonInterrupts()
#elif defined(BUTTON_PIN)
// Interrupt for user button, during normal use. Improves responsiveness.
attachInterrupt(
#if !defined(USERPREFS_BUTTON_PIN)
config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN,
#endif
#if defined(USERPREFS_BUTTON_PIN)
config.device.button_gpio ? config.device.button_gpio : USERPREFS_BUTTON_PIN,
#endif
[]() {
ButtonThread::userButton.tick();
runASAP = true;
@@ -273,8 +289,13 @@ void ButtonThread::detachButtonInterrupts()
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
detachInterrupt(settingsMap[user]);
#elif defined(BUTTON_PIN)
#if !defined(USERPREFS_BUTTON_PIN)
detachInterrupt(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN);
#endif
#if defined(USERPREFS_BUTTON_PIN)
detachInterrupt(config.device.button_gpio ? config.device.button_gpio : USERPREFS_BUTTON_PIN);
#endif
#endif
#ifdef BUTTON_PIN_ALT
detachInterrupt(BUTTON_PIN_ALT);
@@ -315,7 +336,7 @@ void ButtonThread::userButtonMultiPressed(void *callerThread)
// Non-static method, runs during callback. Grabs info while still valid
void ButtonThread::storeClickCount()
{
#ifdef BUTTON_PIN
#if defined(BUTTON_PIN) || defined(USERPREFS_BUTTON_PIN)
multipressClickCount = userButton.getNumberClicks();
#endif
}

View File

@@ -38,7 +38,7 @@ class ButtonThread : public concurrency::OSThread
void storeClickCount();
private:
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO) || defined(USERPREFS_BUTTON_PIN)
static OneButton userButton; // Static - accessed from an interrupt
#endif
#ifdef BUTTON_PIN_ALT

View File

@@ -231,7 +231,7 @@ void listDir(const char *dirname, uint8_t levels, bool del)
#ifdef ARCH_ESP32
listDir(file.path(), levels - 1, del);
if (del) {
LOG_DEBUG("Removing %s", file.path());
LOG_DEBUG("Remove %s", file.path());
strncpy(buffer, file.path(), sizeof(buffer));
file.close();
FSCom.rmdir(buffer);
@@ -241,7 +241,7 @@ void listDir(const char *dirname, uint8_t levels, bool del)
#elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
listDir(file.name(), levels - 1, del);
if (del) {
LOG_DEBUG("Removing %s", file.name());
LOG_DEBUG("Remove %s", file.name());
strncpy(buffer, file.name(), sizeof(buffer));
file.close();
FSCom.rmdir(buffer);
@@ -257,7 +257,7 @@ void listDir(const char *dirname, uint8_t levels, bool del)
} else {
#ifdef ARCH_ESP32
if (del) {
LOG_DEBUG("Deleting %s", file.path());
LOG_DEBUG("Delete %s", file.path());
strncpy(buffer, file.path(), sizeof(buffer));
file.close();
FSCom.remove(buffer);
@@ -267,7 +267,7 @@ void listDir(const char *dirname, uint8_t levels, bool del)
}
#elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
if (del) {
LOG_DEBUG("Deleting %s", file.name());
LOG_DEBUG("Delete %s", file.name());
strncpy(buffer, file.name(), sizeof(buffer));
file.close();
FSCom.remove(buffer);
@@ -284,7 +284,7 @@ void listDir(const char *dirname, uint8_t levels, bool del)
}
#ifdef ARCH_ESP32
if (del) {
LOG_DEBUG("Removing %s", root.path());
LOG_DEBUG("Remove %s", root.path());
strncpy(buffer, root.path(), sizeof(buffer));
root.close();
FSCom.rmdir(buffer);
@@ -293,7 +293,7 @@ void listDir(const char *dirname, uint8_t levels, bool del)
}
#elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
if (del) {
LOG_DEBUG("Removing %s", root.name());
LOG_DEBUG("Remove %s", root.name());
strncpy(buffer, root.name(), sizeof(buffer));
root.close();
FSCom.rmdir(buffer);
@@ -329,7 +329,7 @@ void fsInit()
{
#ifdef FSCom
if (!FSBegin()) {
LOG_ERROR("Filesystem mount Failed.");
LOG_ERROR("Filesystem mount failed");
// assert(0); This auto-formats the partition, so no need to fail here.
}
#if defined(ARCH_ESP32)

View File

@@ -50,9 +50,6 @@ class GPSStatus : public Status
int32_t getLatitude() const
{
if (config.position.fixed_position) {
#ifdef GPS_EXTRAVERBOSE
LOG_WARN("Using fixed latitude");
#endif
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
return node->position.latitude_i;
} else {
@@ -63,9 +60,6 @@ class GPSStatus : public Status
int32_t getLongitude() const
{
if (config.position.fixed_position) {
#ifdef GPS_EXTRAVERBOSE
LOG_WARN("Using fixed longitude");
#endif
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
return node->position.longitude_i;
} else {
@@ -76,9 +70,6 @@ class GPSStatus : public Status
int32_t getAltitude() const
{
if (config.position.fixed_position) {
#ifdef GPS_EXTRAVERBOSE
LOG_WARN("Using fixed altitude");
#endif
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
return node->position.altitude;
} else {
@@ -94,7 +85,7 @@ class GPSStatus : public Status
bool matches(const GPSStatus *newStatus) const
{
#ifdef GPS_EXTRAVERBOSE
#ifdef GPS_DEBUG
LOG_DEBUG("GPSStatus.match() new pos@%x to old pos@%x", newStatus->p.timestamp, p.timestamp);
#endif
return (newStatus->hasLock != hasLock || newStatus->isConnected != isConnected ||

View File

@@ -12,7 +12,6 @@ void GpioVirtPin::set(bool value)
void GpioHwPin::set(bool value)
{
// if (num == 3) LOG_DEBUG("Setting pin %d to %d", num, value);
pinMode(num, OUTPUT);
digitalWrite(num, value);
}
@@ -66,7 +65,7 @@ GpioBinaryTransformer::GpioBinaryTransformer(GpioVirtPin *inPin1, GpioVirtPin *i
assert(!inPin2->dependentPin); // We only allow one dependent pin
inPin2->dependentPin = this;
// Don't update at construction time, because various GpioPins might be global constructor based not yet initied because
// Don't update at construction time, because various GpioPins might be global constructor based not yet initiated because
// order of operations for global constructors is not defined.
// update();
}
@@ -88,7 +87,6 @@ void GpioBinaryTransformer::update()
newValue = (GpioVirtPin::PinState)(p1 && p2);
break;
case Or:
// LOG_DEBUG("Doing GPIO OR");
newValue = (GpioVirtPin::PinState)(p1 || p2);
break;
case Xor:
@@ -101,4 +99,4 @@ void GpioBinaryTransformer::update()
set(newValue);
}
GpioSplitter::GpioSplitter(GpioPin *outPin1, GpioPin *outPin2) : outPin1(outPin1), outPin2(outPin2) {}
GpioSplitter::GpioSplitter(GpioPin *outPin1, GpioPin *outPin2) : outPin1(outPin1), outPin2(outPin2) {}

View File

@@ -251,7 +251,6 @@ class AnalogBatteryLevel : public HasBatteryLevel
#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !defined(HAS_PMU) && \
!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
if (hasINA()) {
LOG_DEBUG("Using INA on I2C addr 0x%x for device battery voltage", config.power.device_battery_ina_address);
return getINAVoltage();
}
#endif
@@ -271,7 +270,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 (!Throttle::isWithinTimespanMs(last_read_time_ms, min_read_interval)) {
if (!initial_read_done || !Throttle::isWithinTimespanMs(last_read_time_ms, min_read_interval)) {
last_read_time_ms = millis();
uint32_t raw = 0;
@@ -511,7 +510,7 @@ bool Power::analogInit()
#endif
#ifdef BATTERY_PIN
LOG_DEBUG("Using analog input %d for battery level", BATTERY_PIN);
LOG_DEBUG("Use analog input %d for battery level", BATTERY_PIN);
// disable any internal pullups
pinMode(BATTERY_PIN, INPUT);
@@ -542,18 +541,18 @@ bool Power::analogInit()
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, width, DEFAULT_VREF, adc_characs);
// show ADC characterization base
if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
LOG_INFO("ADCmod: ADC characterization based on Two Point values stored in eFuse");
LOG_INFO("ADC config based on Two Point values stored in eFuse");
} else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
LOG_INFO("ADCmod: ADC characterization based on reference voltage stored in eFuse");
LOG_INFO("ADC config based on reference voltage stored in eFuse");
}
#ifdef CONFIG_IDF_TARGET_ESP32S3
// ESP32S3
else if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP_FIT) {
LOG_INFO("ADCmod: ADC Characterization based on Two Point values and fitting curve coefficients stored in eFuse");
LOG_INFO("ADC config based on Two Point values and fitting curve coefficients stored in eFuse");
}
#endif
else {
LOG_INFO("ADCmod: ADC characterization based on default reference voltage");
LOG_INFO("ADC config based on default reference voltage");
}
#endif // ARCH_ESP32
@@ -614,7 +613,7 @@ void Power::shutdown()
#ifdef PIN_LED3
ledOff(PIN_LED3);
#endif
doDeepSleep(DELAY_FOREVER, false);
doDeepSleep(DELAY_FOREVER, false, false);
#endif
}
@@ -640,7 +639,7 @@ void Power::readPowerStatus()
batteryChargePercent = batteryLevel->getBatteryPercent();
} else {
// If the AXP192 returns a percentage less than 0, the feature is either not supported or there is an error
// In that case, we compute an estimate of the charge percent based on open circuite voltage table defined
// In that case, we compute an estimate of the charge percent based on open circuit voltage table defined
// in power.h
batteryChargePercent = clamp((int)(((batteryVoltageMv - (OCV[NUM_OCV_POINTS - 1] * NUM_CELLS)) * 1e2) /
((OCV[0] * NUM_CELLS) - (OCV[NUM_OCV_POINTS - 1] * NUM_CELLS))),
@@ -722,9 +721,9 @@ void Power::readPowerStatus()
if (low_voltage_counter > 10) {
#ifdef ARCH_NRF52
// We can't trigger deep sleep on NRF52, it's freezing the board
LOG_DEBUG("Low voltage detected, but not triggering deep sleep");
LOG_DEBUG("Low voltage detected, but not trigger deep sleep");
#else
LOG_INFO("Low voltage detected, triggering deep sleep");
LOG_INFO("Low voltage detected, trigger deep sleep");
powerFSM.trigger(EVENT_LOW_BATTERY);
#endif
}
@@ -816,22 +815,22 @@ bool Power::axpChipInit()
if (!PMU) {
PMU = new XPowersAXP2101(*w);
if (!PMU->init()) {
LOG_WARN("Failed to find AXP2101 power management");
LOG_WARN("No AXP2101 power management");
delete PMU;
PMU = NULL;
} else {
LOG_INFO("AXP2101 PMU init succeeded, using AXP2101 PMU");
LOG_INFO("AXP2101 PMU init succeeded");
}
}
if (!PMU) {
PMU = new XPowersAXP192(*w);
if (!PMU->init()) {
LOG_WARN("Failed to find AXP192 power management");
LOG_WARN("No AXP192 power management");
delete PMU;
PMU = NULL;
} else {
LOG_INFO("AXP192 PMU init succeeded, using AXP192 PMU");
LOG_INFO("AXP192 PMU init succeeded");
}
}

View File

@@ -19,6 +19,10 @@
#include "sleep.h"
#include "target_specific.h"
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
#include "mesh/wifi/WiFiAPClient.h"
#endif
#ifndef SLEEP_TIME
#define SLEEP_TIME 30
#endif
@@ -53,16 +57,21 @@ static bool isPowered()
static void sdsEnter()
{
LOG_DEBUG("Enter state: SDS");
LOG_DEBUG("State: SDS");
// FIXME - make sure GPS and LORA radio are off first - because we want close to zero current draw
doDeepSleep(Default::getConfiguredOrDefaultMs(config.power.sds_secs), false);
doDeepSleep(Default::getConfiguredOrDefaultMs(config.power.sds_secs), false, false);
}
static void lowBattSDSEnter()
{
LOG_DEBUG("State: Lower batt SDS");
doDeepSleep(Default::getConfiguredOrDefaultMs(config.power.sds_secs), false, true);
}
extern Power *power;
static void shutdownEnter()
{
LOG_DEBUG("Enter state: SHUTDOWN");
LOG_DEBUG("State: SHUTDOWN");
power->shutdown();
}
@@ -105,7 +114,7 @@ static void lsIdle()
wakeCause2 = doLightSleep(100); // leave led on for 1ms
secsSlept += sleepTime;
// LOG_INFO("sleeping, flash led!");
// LOG_INFO("Sleep, flash led!");
break;
case ESP_SLEEP_WAKEUP_UART:
@@ -137,7 +146,7 @@ static void lsIdle()
} else {
// Time to stop sleeping!
ledBlink.set(false);
LOG_INFO("Reached ls_secs, servicing loop()");
LOG_INFO("Reached ls_secs, service loop()");
powerFSM.trigger(EVENT_WAKE_TIMER);
}
#endif
@@ -150,7 +159,7 @@ static void lsExit()
static void nbEnter()
{
LOG_DEBUG("Enter state: NB");
LOG_DEBUG("State: NB");
screen->setOn(false);
#ifdef ARCH_ESP32
// Only ESP32 should turn off bluetooth
@@ -168,7 +177,7 @@ static void darkEnter()
static void serialEnter()
{
LOG_DEBUG("Enter state: SERIAL");
LOG_DEBUG("State: SERIAL");
setBluetoothEnable(false);
screen->setOn(true);
screen->print("Serial connected\n");
@@ -183,9 +192,9 @@ static void serialExit()
static void powerEnter()
{
// LOG_DEBUG("Enter state: POWER");
// LOG_DEBUG("State: POWER");
if (!isPowered()) {
// If we got here, we are in the wrong state - we should be in powered, let that state ahndle things
// If we got here, we are in the wrong state - we should be in powered, let that state handle things
LOG_INFO("Loss of power in Powered");
powerFSM.trigger(EVENT_POWER_DISCONNECTED);
} else {
@@ -222,7 +231,7 @@ static void powerExit()
static void onEnter()
{
LOG_DEBUG("Enter state: ON");
LOG_DEBUG("State: ON");
screen->setOn(true);
setBluetoothEnable(true);
}
@@ -230,7 +239,7 @@ static void onEnter()
static void onIdle()
{
if (isPowered()) {
// If we got here, we are in the wrong state - we should be in powered, let that state ahndle things
// If we got here, we are in the wrong state - we should be in powered, let that state handle things
powerFSM.trigger(EVENT_POWER_CONNECTED);
}
}
@@ -242,11 +251,12 @@ static void screenPress()
static void bootEnter()
{
LOG_DEBUG("Enter state: BOOT");
LOG_DEBUG("State: BOOT");
}
State stateSHUTDOWN(shutdownEnter, NULL, NULL, "SHUTDOWN");
State stateSDS(sdsEnter, NULL, NULL, "SDS");
State stateLowBattSDS(lowBattSDSEnter, NULL, NULL, "SDS");
State stateLS(lsEnter, lsIdle, lsExit, "LS");
State stateNB(nbEnter, NULL, NULL, "NB");
State stateDARK(darkEnter, NULL, NULL, "DARK");
@@ -291,12 +301,12 @@ void PowerFSM_setup()
"Press"); // Allow button to work while in serial API
// Handle critically low power battery by forcing deep sleep
powerFSM.add_transition(&stateBOOT, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
powerFSM.add_transition(&stateLS, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
powerFSM.add_transition(&stateNB, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
powerFSM.add_transition(&stateDARK, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
powerFSM.add_transition(&stateON, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
powerFSM.add_transition(&stateSERIAL, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
powerFSM.add_transition(&stateBOOT, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
powerFSM.add_transition(&stateLS, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
powerFSM.add_transition(&stateNB, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
powerFSM.add_transition(&stateDARK, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
powerFSM.add_transition(&stateON, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
powerFSM.add_transition(&stateSERIAL, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
// Handle being told to power off
powerFSM.add_transition(&stateBOOT, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown");
@@ -371,9 +381,9 @@ void PowerFSM_setup()
// We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally)
#ifdef ARCH_ESP32
// See: https://github.com/meshtastic/firmware/issues/1071
// Don't add power saving transitions if we are a power saving tracker or sensor. Sleep will be initiatiated through the
// modules
if ((isRouter || config.power.is_power_saving) && !isTrackerOrSensor) {
// Don't add power saving transitions if we are a power saving tracker or sensor or have Wifi enabled. Sleep will be initiated
// through the modules
if ((isRouter || config.power.is_power_saving) && !isWifiAvailable() && !isTrackerOrSensor) {
powerFSM.add_timed_transition(&stateNB, &stateLS,
Default::getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL,
"Min wake timeout");

View File

@@ -13,17 +13,17 @@ void AirTime::logAirtime(reportTypes reportType, uint32_t airtime_ms)
{
if (reportType == TX_LOG) {
LOG_DEBUG("Packet transmitted : %ums", airtime_ms);
LOG_DEBUG("Packet TX: %ums", airtime_ms);
this->airtimes.periodTX[0] = this->airtimes.periodTX[0] + airtime_ms;
air_period_tx[0] = air_period_tx[0] + airtime_ms;
this->utilizationTX[this->getPeriodUtilHour()] = this->utilizationTX[this->getPeriodUtilHour()] + airtime_ms;
} else if (reportType == RX_LOG) {
LOG_DEBUG("Packet received : %ums", airtime_ms);
LOG_DEBUG("Packet RX: %ums", airtime_ms);
this->airtimes.periodRX[0] = this->airtimes.periodRX[0] + airtime_ms;
air_period_rx[0] = air_period_rx[0] + airtime_ms;
} else if (reportType == RX_ALL_LOG) {
LOG_DEBUG("Packet received (noise?) : %ums", airtime_ms);
LOG_DEBUG("Packet RX (noise?) : %ums", airtime_ms);
this->airtimes.periodRX_ALL[0] = this->airtimes.periodRX_ALL[0] + airtime_ms;
}
@@ -50,7 +50,7 @@ void AirTime::airtimeRotatePeriod()
{
if (this->airtimes.lastPeriodIndex != this->currentPeriodIndex()) {
LOG_DEBUG("Rotating airtimes to a new period = %u", this->currentPeriodIndex());
LOG_DEBUG("Rotate airtimes to a new period = %u", this->currentPeriodIndex());
for (int i = PERIODS_TO_LOG - 2; i >= 0; --i) {
this->airtimes.periodTX[i + 1] = this->airtimes.periodTX[i];
@@ -105,7 +105,6 @@ float AirTime::channelUtilizationPercent()
uint32_t sum = 0;
for (uint32_t i = 0; i < CHANNEL_UTILIZATION_PERIODS; i++) {
sum += this->channelUtilization[i];
// LOG_DEBUG("ChanUtilArray %u %u", i, this->channelUtilization[i]);
}
return (float(sum) / float(CHANNEL_UTILIZATION_PERIODS * 10 * 1000)) * 100;
@@ -127,7 +126,7 @@ bool AirTime::isTxAllowedChannelUtil(bool polite)
if (channelUtilizationPercent() < percentage) {
return true;
} else {
LOG_WARN("Channel utilization is >%d percent. Skipping this opportunity to send.", percentage);
LOG_WARN("Ch. util >%d%%. Skip send", percentage);
return false;
}
}
@@ -138,8 +137,7 @@ bool AirTime::isTxAllowedAirUtil()
if (utilizationTXPercent() < myRegion->dutyCycle * polite_duty_cycle_percent / 100) {
return true;
} else {
LOG_WARN("Tx air utilization is >%f percent. Skipping this opportunity to send.",
myRegion->dutyCycle * polite_duty_cycle_percent / 100);
LOG_WARN("TX air util. >%f%%. Skip send", myRegion->dutyCycle * polite_duty_cycle_percent / 100);
return false;
}
}
@@ -208,14 +206,5 @@ int32_t AirTime::runOnce()
this->utilizationTX[utilPeriodTX] = 0;
}
}
/*
LOG_DEBUG("utilPeriodTX %d TX Airtime %3.2f%", utilPeriodTX, airTime->utilizationTXPercent());
for (uint32_t i = 0; i < MINUTES_IN_HOUR; i++) {
LOG_DEBUG(
"%d,", this->utilizationTX[i]
);
}
LOG_DEBUG("");
*/
return (1000 * 1);
}
}

View File

@@ -32,12 +32,12 @@ IRAM_ATTR bool NotifiedWorkerThread::notifyCommon(uint32_t v, bool overwrite)
notification = v;
if (debugNotification) {
LOG_DEBUG("setting notification %d", v);
LOG_DEBUG("Set notification %d", v);
}
return true;
} else {
if (debugNotification) {
LOG_DEBUG("dropping notification %d", v);
LOG_DEBUG("Drop notification %d", v);
}
return false;
}
@@ -67,7 +67,7 @@ bool NotifiedWorkerThread::notifyLater(uint32_t delay, uint32_t v, bool overwrit
if (didIt) { // If we didn't already have something queued, override the delay to be larger
setIntervalFromNow(delay); // a new version of setInterval relative to the current time
if (debugNotification) {
LOG_DEBUG("delaying notification %u", delay);
LOG_DEBUG("Delay notification %u", delay);
}
}

View File

@@ -148,13 +148,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define NAU7802_ADDR 0x2A
#define MAX30102_ADDR 0x57
#define MLX90614_ADDR_DEF 0x5A
#define CGRADSENS_ADDR 0x66
// -----------------------------------------------------------------------------
// ACCELEROMETER
// -----------------------------------------------------------------------------
#define MPU6050_ADDR 0x68
#define STK8BXX_ADR 0x18
#define LIS3DH_ADR 0x18
#define STK8BXX_ADDR 0x18
#define LIS3DH_ADDR 0x18
#define LIS3DH_ADDR_ALT 0x19
#define BMA423_ADDR 0x19
#define LSM6DS3_ADDR 0x6A
#define BMX160_ADDR 0x69
@@ -169,7 +171,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// -----------------------------------------------------------------------------
// Security
// -----------------------------------------------------------------------------
#define ATECC608B_ADDR 0x35
// -----------------------------------------------------------------------------
// IO Expander
@@ -360,4 +361,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#endif
#include "DebugConfiguration.h"
#include "RF95Configuration.h"
#include "RF95Configuration.h"

View File

@@ -12,7 +12,6 @@ class ScanI2C
SCREEN_SH1106,
SCREEN_UNKNOWN, // has the same address as the two above but does not respond to the same commands
SCREEN_ST7567,
ATECC608B,
RTC_RV3028,
RTC_PCF8563,
CARDKB,
@@ -63,7 +62,8 @@ class ScanI2C
ICM20948,
MAX30102,
TPS65233,
MPR121KB
MPR121KB,
CGRADSENS
} DeviceType;
// typedef uint8_t DeviceAddress;

View File

@@ -7,7 +7,6 @@
#include "linux/LinuxHardwareI2C.h"
#endif
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#include "main.h" // atecc
#include "meshUtils.h" // vformat
#endif
@@ -72,10 +71,10 @@ ScanI2C::DeviceType ScanI2CTwoWire::probeOLED(ScanI2C::DeviceAddress addr) const
r &= 0x0f;
if (r == 0x08 || r == 0x00) {
LOG_INFO("sh1106 display found");
logFoundDevice("SH1106", (uint8_t)addr.address);
o_probe = SCREEN_SH1106; // SH1106
} else if (r == 0x03 || r == 0x04 || r == 0x06 || r == 0x07) {
LOG_INFO("ssd1306 display found");
logFoundDevice("SSD1306", (uint8_t)addr.address);
o_probe = SCREEN_SSD1306; // SSD1306
}
c++;
@@ -84,40 +83,6 @@ ScanI2C::DeviceType ScanI2CTwoWire::probeOLED(ScanI2C::DeviceAddress addr) const
return o_probe;
}
void ScanI2CTwoWire::printATECCInfo() const
{
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
atecc.readConfigZone(false);
std::string atecc_numbers = "ATECC608B Serial Number: ";
for (int i = 0; i < 9; i++) {
atecc_numbers += vformat("%02x", atecc.serialNumber[i]);
}
atecc_numbers += ", Rev Number: ";
for (int i = 0; i < 4; i++) {
atecc_numbers += vformat("%02x", atecc.revisionNumber[i]);
}
LOG_DEBUG(atecc_numbers.c_str());
LOG_DEBUG("ATECC608B Config %s, Data %s, Slot 0 %s", atecc.configLockStatus ? "Locked" : "Unlocked",
atecc.dataOTPLockStatus ? "Locked" : "Unlocked", atecc.slot0LockStatus ? "Locked" : "Unlocked");
std::string atecc_publickey = "";
if (atecc.configLockStatus && atecc.dataOTPLockStatus && atecc.slot0LockStatus) {
if (atecc.generatePublicKey() == false) {
atecc_publickey += "ATECC608B Error generating public key";
} else {
atecc_publickey += "ATECC608B Public Key: ";
for (int i = 0; i < 64; i++) {
atecc_publickey += vformat("%02x", atecc.publicKey64Bytes[i]);
}
}
LOG_DEBUG(atecc_publickey.c_str());
}
#endif
}
uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation &registerLocation,
ScanI2CTwoWire::ResponseWidth responseWidth) const
{
@@ -129,7 +94,6 @@ uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation
i2cBus->endTransmission();
delay(20);
i2cBus->requestFrom(registerLocation.i2cAddress.address, responseWidth);
LOG_DEBUG("Wire.available() = %d", i2cBus->available());
if (i2cBus->available() == 2) {
// Read MSB, then LSB
value = (uint16_t)i2cBus->read() << 8;
@@ -142,7 +106,7 @@ uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation
#define SCAN_SIMPLE_CASE(ADDR, T, ...) \
case ADDR: \
LOG_INFO(__VA_ARGS__); \
logFoundDevice(__VA_ARGS__); \
type = T; \
break;
@@ -150,7 +114,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
{
concurrency::LockGuard guard((concurrency::Lock *)&lock);
LOG_DEBUG("Scanning for I2C devices on port %d", port);
LOG_DEBUG("Scan for I2C devices on port %d", port);
uint8_t err;
@@ -184,9 +148,9 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
for (addr.address = 8; addr.address < 120; addr.address++) {
if (asize != 0) {
if (!in_array(address, asize, addr.address))
if (!in_array(address, asize, (uint8_t)addr.address))
continue;
LOG_DEBUG("Scanning address 0x%x", addr.address);
LOG_DEBUG("Scan address 0x%x", (uint8_t)addr.address);
}
i2cBus->beginTransmission(addr.address);
#ifdef ARCH_PORTDUINO
@@ -199,35 +163,16 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
#endif
type = NONE;
if (err == 0) {
LOG_DEBUG("I2C device found at address 0x%x", addr.address);
switch (addr.address) {
case SSD1306_ADDRESS:
type = probeOLED(addr);
break;
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
case ATECC608B_ADDR:
#ifdef RP2040_SLOW_CLOCK
if (atecc.begin(addr.address, Wire, Serial2) == true)
#else
if (atecc.begin(addr.address) == true)
#endif
{
LOG_INFO("ATECC608B initialized");
} else {
LOG_WARN("ATECC608B initialization failed");
}
printATECCInfo();
break;
#endif
#ifdef RV3028_RTC
case RV3028_RTC:
// foundDevices[addr] = RTC_RV3028;
type = RTC_RV3028;
LOG_INFO("RV3028 RTC found");
logFoundDevice("RV3028", (uint8_t)addr.address);
rtc.initI2C(*i2cBus);
rtc.writeToRegister(0x35, 0x07); // no Clkout
rtc.writeToRegister(0x37, 0xB4);
@@ -235,7 +180,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
#endif
#ifdef PCF8563_RTC
SCAN_SIMPLE_CASE(PCF8563_RTC, RTC_PCF8563, "PCF8563 RTC found")
SCAN_SIMPLE_CASE(PCF8563_RTC, RTC_PCF8563, "PCF8563", (uint8_t)addr.address)
#endif
case CARDKB_ADDR:
@@ -243,50 +188,50 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x04), 1);
if (registerValue == 0x02) {
// KEYPAD_VERSION
LOG_INFO("RAK14004 found");
logFoundDevice("RAK14004", (uint8_t)addr.address);
type = RAK14004;
} else {
LOG_INFO("m5 cardKB found");
logFoundDevice("M5 cardKB", (uint8_t)addr.address);
type = CARDKB;
}
break;
SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard found");
SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10 keyboard found");
SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "st7567 display found");
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "ST7567", (uint8_t)addr.address);
#ifdef HAS_NCP5623
SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623 RGB LED found");
SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623", (uint8_t)addr.address);
#endif
#ifdef HAS_PMU
SCAN_SIMPLE_CASE(XPOWERS_AXP192_AXP2101_ADDRESS, PMU_AXP192_AXP2101, "axp192/axp2101 PMU found")
SCAN_SIMPLE_CASE(XPOWERS_AXP192_AXP2101_ADDRESS, PMU_AXP192_AXP2101, "AXP192/AXP2101", (uint8_t)addr.address)
#endif
case BME_ADDR:
case BME_ADDR_ALTERNATE:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xD0), 1); // GET_ID
switch (registerValue) {
case 0x61:
LOG_INFO("BME-680 sensor found at address 0x%x", (uint8_t)addr.address);
logFoundDevice("BME680", (uint8_t)addr.address);
type = BME_680;
break;
case 0x60:
LOG_INFO("BME-280 sensor found at address 0x%x", (uint8_t)addr.address);
logFoundDevice("BME280", (uint8_t)addr.address);
type = BME_280;
break;
case 0x55:
LOG_INFO("BMP-085 or BMP-180 sensor found at address 0x%x", (uint8_t)addr.address);
logFoundDevice("BMP085/BMP180", (uint8_t)addr.address);
type = BMP_085;
break;
default:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1); // GET_ID
switch (registerValue) {
case 0x50: // BMP-388 should be 0x50
LOG_INFO("BMP-388 sensor found at address 0x%x", (uint8_t)addr.address);
logFoundDevice("BMP-388", (uint8_t)addr.address);
type = BMP_3XX;
break;
case 0x58: // BMP-280 should be 0x58
default:
LOG_INFO("BMP-280 sensor found at address 0x%x", (uint8_t)addr.address);
logFoundDevice("BMP-280", (uint8_t)addr.address);
type = BMP_280;
break;
}
@@ -295,7 +240,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
break;
#ifndef HAS_NCP5623
case AHT10_ADDR:
LOG_INFO("AHT10 sensor found at address 0x%x", (uint8_t)addr.address);
logFoundDevice("AHT10", (uint8_t)addr.address);
type = AHT10;
break;
#endif
@@ -305,41 +250,57 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2);
LOG_DEBUG("Register MFG_UID: 0x%x", registerValue);
if (registerValue == 0x5449) {
LOG_INFO("INA260 sensor found at address 0x%x", (uint8_t)addr.address);
logFoundDevice("INA260", (uint8_t)addr.address);
type = INA260;
} else { // Assume INA219 if INA260 ID is not found
LOG_INFO("INA219 sensor found at address 0x%x", (uint8_t)addr.address);
logFoundDevice("INA219", (uint8_t)addr.address);
type = INA219;
}
break;
case INA3221_ADDR:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2);
LOG_DEBUG("Register MFG_UID: 0x%x", registerValue);
LOG_DEBUG("Register MFG_UID FE: 0x%x", registerValue);
if (registerValue == 0x5449) {
LOG_INFO("INA3221 sensor found at address 0x%x", (uint8_t)addr.address);
logFoundDevice("INA3221", (uint8_t)addr.address);
type = INA3221;
} else {
LOG_INFO("DFRobot Lark weather station found at address 0x%x", (uint8_t)addr.address);
type = DFROBOT_LARK;
/* check the first 2 bytes of the 6 byte response register
LARK FW 1.0 should return:
RESPONSE_STATUS STATUS_SUCCESS (0x53)
RESPONSE_CMD CMD_GET_VERSION (0x05)
RESPONSE_LEN_L 0x02
RESPONSE_LEN_H 0x00
RESPONSE_PAYLOAD 0x01
RESPONSE_PAYLOAD+1 0x00
*/
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x05), 2);
LOG_DEBUG("Register MFG_UID 05: 0x%x", registerValue);
if (registerValue == 0x5305) {
logFoundDevice("DFRobot Lark", (uint8_t)addr.address);
type = DFROBOT_LARK;
}
// else: probably a RAK12500/UBLOX GPS on I2C
}
break;
case MCP9808_ADDR:
// We need to check for STK8BAXX first, since register 0x07 is new data flag for the z-axis and can produce some
// weird result. and register 0x00 doesn't seems to be colliding with MCP9808 and LIS3DH chips.
{
#ifdef HAS_STK8XXX
// Check register 0x00 for 0x8700 response to ID STK8BA53 chip.
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 2);
if (registerValue == 0x8700) {
type = STK8BAXX;
LOG_INFO("STK8BAXX accelerometer found");
logFoundDevice("STK8BAXX", (uint8_t)addr.address);
break;
}
#endif
// Check register 0x07 for 0x0400 response to ID MCP9808 chip.
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x07), 2);
if (registerValue == 0x0400) {
type = MCP9808;
LOG_INFO("MCP9808 sensor found");
logFoundDevice("MCP9808", (uint8_t)addr.address);
break;
}
@@ -347,7 +308,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 2);
if (registerValue == 0x3300 || registerValue == 0x3333) { // RAK4631 WisBlock has LIS3DH register at 0x3333
type = LIS3DH;
LOG_INFO("LIS3DH accelerometer found");
logFoundDevice("LIS3DH", (uint8_t)addr.address);
}
break;
}
@@ -355,83 +316,92 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x89), 2);
if (registerValue == 0x11a2 || registerValue == 0x11da || registerValue == 0xe9c) {
type = SHT4X;
LOG_INFO("SHT4X sensor found");
logFoundDevice("SHT4X", (uint8_t)addr.address);
} else if (getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x7E), 2) == 0x5449) {
type = OPT3001;
LOG_INFO("OPT3001 light sensor found");
logFoundDevice("OPT3001", (uint8_t)addr.address);
} else {
type = SHT31;
LOG_INFO("SHT31 sensor found");
logFoundDevice("SHT31", (uint8_t)addr.address);
}
break;
SCAN_SIMPLE_CASE(SHTC3_ADDR, SHTC3, "SHTC3 sensor found")
SCAN_SIMPLE_CASE(SHTC3_ADDR, SHTC3, "SHTC3", (uint8_t)addr.address)
case RCWL9620_ADDR:
// get MAX30102 PARTID
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFF), 1);
if (registerValue == 0x15) {
type = MAX30102;
LOG_INFO("MAX30102 Health sensor found");
logFoundDevice("MAX30102", (uint8_t)addr.address);
break;
} else {
type = RCWL9620;
LOG_INFO("RCWL9620 sensor found");
logFoundDevice("RCWL9620", (uint8_t)addr.address);
}
break;
case LPS22HB_ADDR_ALT:
SCAN_SIMPLE_CASE(LPS22HB_ADDR, LPS22HB, "LPS22HB sensor found")
SCAN_SIMPLE_CASE(QMC6310_ADDR, QMC6310, "QMC6310 Highrate 3-Axis magnetic sensor found")
SCAN_SIMPLE_CASE(LPS22HB_ADDR, LPS22HB, "LPS22HB", (uint8_t)addr.address)
SCAN_SIMPLE_CASE(QMC6310_ADDR, QMC6310, "QMC6310", (uint8_t)addr.address)
case QMI8658_ADDR:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0A), 1); // get ID
if (registerValue == 0xC0) {
type = BQ24295;
LOG_INFO("BQ24295 PMU found");
logFoundDevice("BQ24295", (uint8_t)addr.address);
break;
}
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 1); // get ID
if (registerValue == 0x6A) {
type = LSM6DS3;
LOG_INFO("LSM6DS3 accelerometer found at address 0x%x", (uint8_t)addr.address);
logFoundDevice("LSM6DS3", (uint8_t)addr.address);
} else {
type = QMI8658;
LOG_INFO("QMI8658 Highrate 6-Axis inertial measurement sensor found");
logFoundDevice("QMI8658", (uint8_t)addr.address);
}
break;
SCAN_SIMPLE_CASE(QMC5883L_ADDR, QMC5883L, "QMC5883L Highrate 3-Axis magnetic sensor found")
SCAN_SIMPLE_CASE(HMC5883L_ADDR, HMC5883L, "HMC5883L 3-Axis digital compass found")
SCAN_SIMPLE_CASE(QMC5883L_ADDR, QMC5883L, "QMC5883L", (uint8_t)addr.address)
SCAN_SIMPLE_CASE(HMC5883L_ADDR, HMC5883L, "HMC5883L", (uint8_t)addr.address)
#ifdef HAS_QMA6100P
SCAN_SIMPLE_CASE(QMA6100P_ADDR, QMA6100P, "QMA6100P accelerometer found")
SCAN_SIMPLE_CASE(QMA6100P_ADDR, QMA6100P, "QMA6100P", (uint8_t)addr.address)
#else
SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031 air quality sensor found")
SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031", (uint8_t)addr.address)
#endif
SCAN_SIMPLE_CASE(BMA423_ADDR, BMA423, "BMA423 accelerometer found");
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3 accelerometer found at address 0x%x", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(TCA9535_ADDR, TCA9535, "TCA9535 I2C expander found");
SCAN_SIMPLE_CASE(TCA9555_ADDR, TCA9555, "TCA9555 I2C expander found");
SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700 light sensor found");
SCAN_SIMPLE_CASE(TSL25911_ADDR, TSL2591, "TSL2591 light sensor found");
SCAN_SIMPLE_CASE(OPT3001_ADDR, OPT3001, "OPT3001 light sensor found");
SCAN_SIMPLE_CASE(MLX90632_ADDR, MLX90632, "MLX90632 IR temp sensor found");
SCAN_SIMPLE_CASE(NAU7802_ADDR, NAU7802, "NAU7802 based scale found");
SCAN_SIMPLE_CASE(FT6336U_ADDR, FT6336U, "FT6336U touchscreen found");
SCAN_SIMPLE_CASE(MAX1704X_ADDR, MAX17048, "MAX17048 lipo fuel gauge found");
case BMA423_ADDR: // this can also be LIS3DH_ADDR_ALT
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 2);
if (registerValue == 0x3300 || registerValue == 0x3333) { // RAK4631 WisBlock has LIS3DH register at 0x3333
type = LIS3DH;
logFoundDevice("LIS3DH", (uint8_t)addr.address);
} else {
type = BMA423;
logFoundDevice("BMA423", (uint8_t)addr.address);
}
break;
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(TCA9535_ADDR, TCA9535, "TCA9535", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(TCA9555_ADDR, TCA9555, "TCA9555", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(TSL25911_ADDR, TSL2591, "TSL2591", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(OPT3001_ADDR, OPT3001, "OPT3001", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(MLX90632_ADDR, MLX90632, "MLX90632", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(NAU7802_ADDR, NAU7802, "NAU7802", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(FT6336U_ADDR, FT6336U, "FT6336U", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(MAX1704X_ADDR, MAX17048, "MAX17048", (uint8_t)addr.address);
#ifdef HAS_TPS65233
SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233 BIAS-T found");
SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233", (uint8_t)addr.address);
#endif
case MLX90614_ADDR_DEF:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0e), 1);
if (registerValue == 0x5a) {
type = MLX90614;
LOG_INFO("MLX90614 IR temp sensor found");
logFoundDevice("MLX90614", (uint8_t)addr.address);
} else {
type = MPR121KB;
LOG_INFO("MPR121KB keyboard found");
logFoundDevice("MPR121KB", (uint8_t)addr.address);
}
break;
@@ -440,24 +410,34 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1);
if (registerValue == 0xEA) {
type = ICM20948;
LOG_INFO("ICM20948 9-dof motion processor found");
logFoundDevice("ICM20948", (uint8_t)addr.address);
break;
} else if (addr.address == BMX160_ADDR) {
type = BMX160;
LOG_INFO("BMX160 accelerometer found");
logFoundDevice("BMX160", (uint8_t)addr.address);
break;
} else {
type = MPU6050;
LOG_INFO("MPU6050 accelerometer found");
logFoundDevice("MPU6050", (uint8_t)addr.address);
break;
}
break;
case CGRADSENS_ADDR:
// Register 0x00 of the RadSens sensor contains is product identifier 0x7D
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1);
if (registerValue == 0x7D) {
type = CGRADSENS;
logFoundDevice("ClimateGuard RadSens", (uint8_t)addr.address);
break;
}
break;
default:
LOG_INFO("Device found at address 0x%x was not able to be enumerated", addr.address);
LOG_INFO("Device found at address 0x%x was not able to be enumerated", (uint8_t)addr.address);
}
} else if (err == 4) {
LOG_ERROR("Unknown error at address 0x%x", addr.address);
LOG_ERROR("Unknown error at address 0x%x", (uint8_t)addr.address);
}
// Check if a type was found for the enumerated device - save, if so
@@ -490,4 +470,9 @@ size_t ScanI2CTwoWire::countDevices() const
{
return foundDevices.size();
}
void ScanI2CTwoWire::logFoundDevice(const char *device, uint8_t address)
{
LOG_INFO("%s found at address 0x%x", device, address);
}
#endif

View File

@@ -53,10 +53,10 @@ class ScanI2CTwoWire : public ScanI2C
concurrency::Lock lock;
void printATECCInfo() const;
uint16_t getRegisterValue(const RegisterLocation &, ResponseWidth) const;
DeviceType probeOLED(ScanI2C::DeviceAddress) const;
static void logFoundDevice(const char *device, uint8_t address);
};
#endif

View File

@@ -28,29 +28,43 @@
#define GPS_RESET_MODE HIGH
#endif
// Not all platforms have std::size().
template <typename T, std::size_t N> std::size_t array_count(const T (&)[N])
{
return N;
}
#if defined(NRF52840_XXAA) || defined(NRF52833_XXAA) || defined(ARCH_ESP32) || defined(ARCH_PORTDUINO)
HardwareSerial *GPS::_serial_gps = &Serial1;
#elif defined(ARCH_RP2040)
SerialUART *GPS::_serial_gps = &Serial1;
#else
HardwareSerial *GPS::_serial_gps = NULL;
HardwareSerial *GPS::_serial_gps = nullptr;
#endif
GPS *gps = nullptr;
GPSUpdateScheduling scheduling;
static const char *ACK_SUCCESS_MESSAGE = "Get ack success!";
static GPSUpdateScheduling scheduling;
/// Multiple GPS instances might use the same serial port (in sequence), but we can
/// only init that port once.
static bool didSerialInit;
struct uBloxGnssModelInfo info;
uint8_t uBloxProtocolVersion;
static struct uBloxGnssModelInfo {
char swVersion[30];
char hwVersion[10];
uint8_t extensionNo;
char extension[10][30];
uint8_t protocol_version;
} ublox_info;
#define GPS_SOL_EXPIRY_MS 5000 // in millis. give 1 second time to combine different sentences. NMEA Frequency isn't higher anyway
#define NMEA_MSG_GXGSA "GNGSA" // GSA message (GPGSA, GNGSA etc)
// For logging
const char *getGPSPowerStateString(GPSPowerState state)
static const char *getGPSPowerStateString(GPSPowerState state)
{
switch (state) {
case GPS_ACTIVE:
@@ -69,7 +83,7 @@ const char *getGPSPowerStateString(GPSPowerState state)
}
}
void GPS::UBXChecksum(uint8_t *message, size_t length)
static void UBXChecksum(uint8_t *message, size_t length)
{
uint8_t CK_A = 0, CK_B = 0;
@@ -85,7 +99,7 @@ void GPS::UBXChecksum(uint8_t *message, size_t length)
}
// Calculate the checksum for a CAS packet
void GPS::CASChecksum(uint8_t *message, size_t length)
static void CASChecksum(uint8_t *message, size_t length)
{
uint32_t cksum = ((uint32_t)message[5] << 24); // Message ID
cksum += ((uint32_t)message[4]) << 16; // Class
@@ -156,7 +170,7 @@ uint8_t GPS::makeCASPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_siz
CASChecksum(UBXscratch, (payload_size + 10));
#if defined(GPS_DEBUG) && defined(DEBUG_PORT)
LOG_DEBUG("Constructed CAS packet: ");
LOG_DEBUG("CAS packet: ");
DEBUG_PORT.hexDump(MESHTASTIC_LOG_LEVEL_DEBUG, UBXscratch, payload_size + 10);
#endif
return (payload_size + 10);
@@ -237,7 +251,7 @@ GPS_RESPONSE GPS::getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMilli
// Check for an ACK-ACK for the specified class and message id
if ((msg_cls == 0x05) && (msg_msg_id == 0x01) && payload_cls == class_id && payload_msg == msg_id) {
#ifdef GPS_DEBUG
LOG_INFO("Got ACK for class %02X message %02X in %d millis.", class_id, msg_id, millis() - startTime);
LOG_INFO("Got ACK for class %02X message %02X in %dms", class_id, msg_id, millis() - startTime);
#endif
return GNSS_RESPONSE_OK;
}
@@ -245,7 +259,7 @@ GPS_RESPONSE GPS::getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMilli
// Check for an ACK-NACK for the specified class and message id
if ((msg_cls == 0x05) && (msg_msg_id == 0x00) && payload_cls == class_id && payload_msg == msg_id) {
#ifdef GPS_DEBUG
LOG_WARN("Got NACK for class %02X message %02X in %d millis.", class_id, msg_id, millis() - startTime);
LOG_WARN("Got NACK for class %02X message %02X in %dms", class_id, msg_id, millis() - startTime);
#endif
return GNSS_RESPONSE_NAK;
}
@@ -286,8 +300,7 @@ GPS_RESPONSE GPS::getACK(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis)
while (Throttle::isWithinTimespanMs(startTime, waitMillis)) {
if (ack > 9) {
#ifdef GPS_DEBUG
LOG_DEBUG("");
LOG_INFO("Got ACK for class %02X message %02X in %d millis.", class_id, msg_id, millis() - startTime);
LOG_INFO("Got ACK for class %02X message %02X in %dms", class_id, msg_id, millis() - startTime);
#endif
return GNSS_RESPONSE_OK; // ACK received
}
@@ -397,8 +410,7 @@ int GPS::getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
} else {
// return payload length
#ifdef GPS_DEBUG
LOG_INFO("Got ACK for class %02X message %02X in %d millis.", requestedClass, requestedID,
millis() - startTime);
LOG_INFO("Got ACK for class %02X message %02X in %dms", requestedClass, requestedID, millis() - startTime);
#endif
return needRead;
}
@@ -409,10 +421,18 @@ int GPS::getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
}
}
}
// LOG_WARN("No response for class %02X message %02X", requestedClass, requestedID);
return 0;
}
#if GPS_BAUDRATE_FIXED
// if GPS_BAUDRATE is specified in variant, only try that.
static const int serialSpeeds[1] = {GPS_BAUDRATE};
static const int rareSerialSpeeds[1] = {GPS_BAUDRATE};
#else
static const int serialSpeeds[3] = {9600, 115200, 38400};
static const int rareSerialSpeeds[3] = {4800, 57600, GPS_BAUDRATE};
#endif
/**
* @brief Setup the GPS based on the model detected.
* We detect the GPS by cycling through a set of baud rates, first common then rare.
@@ -422,15 +442,14 @@ int GPS::getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
*/
bool GPS::setup()
{
if (!didSerialInit) {
int msglen = 0;
if (tx_gpio && gnssModel == GNSS_MODEL_UNKNOWN) {
if (probeTries < 2) {
LOG_DEBUG("Probing for GPS at %d", serialSpeeds[speedSelect]);
LOG_DEBUG("Probe for GPS at %d", serialSpeeds[speedSelect]);
gnssModel = probe(serialSpeeds[speedSelect]);
if (gnssModel == GNSS_MODEL_UNKNOWN) {
if (++speedSelect == sizeof(serialSpeeds) / sizeof(int)) {
if (++speedSelect == array_count(serialSpeeds)) {
speedSelect = 0;
++probeTries;
}
@@ -438,19 +457,21 @@ bool GPS::setup()
}
// Rare Serial Speeds
if (probeTries == 2) {
LOG_DEBUG("Probing for GPS at %d", rareSerialSpeeds[speedSelect]);
LOG_DEBUG("Probe for GPS at %d", rareSerialSpeeds[speedSelect]);
gnssModel = probe(rareSerialSpeeds[speedSelect]);
if (gnssModel == GNSS_MODEL_UNKNOWN) {
if (++speedSelect == sizeof(rareSerialSpeeds) / sizeof(int)) {
LOG_WARN("Giving up on GPS probe and setting to %d", GPS_BAUDRATE);
if (++speedSelect == array_count(rareSerialSpeeds)) {
LOG_WARN("Give up on GPS probe and set to %d", GPS_BAUDRATE);
return true;
}
}
}
return false;
}
if (gnssModel != GNSS_MODEL_UNKNOWN) {
setConnected();
} else {
gnssModel = GNSS_MODEL_UNKNOWN;
return false;
}
if (gnssModel == GNSS_MODEL_MTK) {
@@ -505,14 +526,14 @@ bool GPS::setup()
msglen = makeCASPacket(0x06, 0x07, sizeof(_message_CAS_CFG_NAVX_CONF), _message_CAS_CFG_NAVX_CONF);
_serial_gps->write(UBXscratch, msglen);
if (getACKCas(0x06, 0x07, 250) != GNSS_RESPONSE_OK) {
LOG_WARN("ATGM336H - Could not set Configuration");
LOG_WARN("ATGM336H: Could not set Config");
}
// Set the update frequence to 1Hz
msglen = makeCASPacket(0x06, 0x04, sizeof(_message_CAS_CFG_RATE_1HZ), _message_CAS_CFG_RATE_1HZ);
_serial_gps->write(UBXscratch, msglen);
if (getACKCas(0x06, 0x04, 250) != GNSS_RESPONSE_OK) {
LOG_WARN("ATGM336H - Could not set Update Frequency");
LOG_WARN("ATGM336H: Could not set Update Frequency");
}
// Set the NEMA output messages
@@ -524,7 +545,7 @@ bool GPS::setup()
msglen = makeCASPacket(0x06, 0x01, sizeof(cas_cfg_msg_packet), cas_cfg_msg_packet);
_serial_gps->write(UBXscratch, msglen);
if (getACKCas(0x06, 0x01, 250) != GNSS_RESPONSE_OK) {
LOG_WARN("ATGM336H - Could not enable NMEA MSG: %d", fields[i]);
LOG_WARN("ATGM336H: Could not enable NMEA MSG: %d", fields[i]);
}
}
} else if (gnssModel == GNSS_MODEL_UC6580) {
@@ -577,20 +598,20 @@ bool GPS::setup()
SEND_UBX_PACKET(0x06, 0x01, _message_GGA, "enable NMEA GGA", 500);
clearBuffer();
SEND_UBX_PACKET(0x06, 0x11, _message_CFG_RXM_ECO, "enable powersaving ECO mode for Neo-6", 500);
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "enable powersaving details for GPS", 500);
SEND_UBX_PACKET(0x06, 0x11, _message_CFG_RXM_ECO, "enable powersave ECO mode for Neo-6", 500);
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "enable powersave details for GPS", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_AID, "disable UBX-AID", 500);
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.");
LOG_WARN("Unable to save GNSS module config");
} else {
LOG_INFO("GNSS module configuration saved!");
LOG_INFO("GNSS module config saved!");
}
} 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");
LOG_DEBUG("Set GPS+SBAS");
msglen = makeUBXPacket(0x06, 0x3e, sizeof(_message_GNSS_7), _message_GNSS_7);
_serial_gps->write(UBXscratch, msglen);
} else { // 8,9
@@ -600,12 +621,12 @@ bool GPS::setup()
if (getACK(0x06, 0x3e, 800) == GNSS_RESPONSE_NAK) {
// It's not critical if the module doesn't acknowledge this configuration.
LOG_INFO("reconfigure GNSS - defaults maintained. Is this module GPS-only?");
LOG_DEBUG("reconfigure GNSS - defaults maintained. Is this module GPS-only?");
} else {
if (gnssModel == GNSS_MODEL_UBLOX7) {
LOG_INFO("GNSS configured for GPS+SBAS.");
LOG_INFO("GPS+SBAS configured");
} else { // 8,9
LOG_INFO("GNSS configured for GPS+SBAS+GLONASS+Galileo.");
LOG_INFO("GPS+SBAS+GLONASS+Galileo configured");
}
// 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 ;>)
@@ -635,10 +656,10 @@ bool GPS::setup()
SEND_UBX_PACKET(0x06, 0x01, _message_RMC, "enable NMEA RMC", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_GGA, "enable NMEA GGA", 500);
if (uBloxProtocolVersion >= 18) {
if (ublox_info.protocol_version >= 18) {
clearBuffer();
SEND_UBX_PACKET(0x06, 0x86, _message_PMS, "enable powersaving for GPS", 500);
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "enable powersaving details for GPS", 500);
SEND_UBX_PACKET(0x06, 0x86, _message_PMS, "enable powersave for GPS", 500);
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "enable powersave details for GPS", 500);
// For M8 we want to enable NMEA vserion 4.10 so we can see the additional sats.
if (gnssModel == GNSS_MODEL_UBLOX8) {
@@ -646,14 +667,14 @@ bool GPS::setup()
SEND_UBX_PACKET(0x06, 0x17, _message_NMEA, "enable NMEA 4.10", 500);
}
} else {
SEND_UBX_PACKET(0x06, 0x11, _message_CFG_RXM_PSM, "enable powersaving mode for GPS", 500);
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "enable powersaving details for GPS", 500);
SEND_UBX_PACKET(0x06, 0x11, _message_CFG_RXM_PSM, "enable powersave mode for GPS", 500);
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "enable powersave details for GPS", 500);
}
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.");
LOG_WARN("Unable to save GNSS module config");
} else {
LOG_INFO("GNSS module configuration saved!");
}
@@ -673,13 +694,13 @@ bool GPS::setup()
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_TXT_INFO_BBR, "disable Info messages for M10 GPS BBR", 300);
delay(750);
// Do M10 configuration for Power Management.
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_PM_RAM, "enable powersaving for M10 GPS RAM", 300);
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_PM_RAM, "enable powersave for M10 GPS RAM", 300);
delay(750);
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_PM_BBR, "enable powersaving for M10 GPS BBR", 300);
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_PM_BBR, "enable powersave for M10 GPS BBR", 300);
delay(750);
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ITFM_RAM, "enable Jamming detection M10 GPS RAM", 300);
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ITFM_RAM, "enable jam detection M10 GPS RAM", 300);
delay(750);
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ITFM_BBR, "enable Jamming detection M10 GPS BBR", 300);
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ITFM_BBR, "enable jam detection M10 GPS BBR", 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, "disable SBAS M10 GPS RAM", 300);
@@ -701,7 +722,7 @@ bool GPS::setup()
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.");
LOG_WARN("Unable to save GNSS module config");
} else {
LOG_INFO("GNSS module configuration saved!");
}
@@ -719,13 +740,14 @@ GPS::~GPS()
// we really should unregister our sleep observer
notifyDeepSleepObserver.unobserve(&notifyDeepSleep);
}
// Put the GPS hardware into a specified state
void GPS::setPowerState(GPSPowerState newState, uint32_t sleepTime)
{
// Update the stored GPSPowerstate, and create local copies
GPSPowerState oldState = powerState;
powerState = newState;
LOG_INFO("GPS power state moving from %s to %s", getGPSPowerStateString(oldState), getGPSPowerStateString(newState));
LOG_INFO("GPS power state move from %s to %s", getGPSPowerStateString(oldState), getGPSPowerStateString(newState));
#ifdef HELTEC_MESH_NODE_T114
if ((oldState == GPS_OFF || oldState == GPS_HARDSLEEP) && (newState != GPS_OFF && newState != GPS_HARDSLEEP)) {
@@ -789,13 +811,14 @@ void GPS::setPowerState(GPSPowerState newState, uint32_t sleepTime)
void GPS::writePinEN(bool on)
{
// Abort: if conflict with Canned Messages when using Wisblock(?)
if (HW_VENDOR == meshtastic_HardwareModel_RAK4631 && (rotaryEncoderInterruptImpl1 || upDownInterruptImpl1))
if ((HW_VENDOR == meshtastic_HardwareModel_RAK4631 || HW_VENDOR == meshtastic_HardwareModel_WISMESH_TAP) &&
(rotaryEncoderInterruptImpl1 || upDownInterruptImpl1))
return;
// Write and log
enablePin->set(on);
#ifdef GPS_EXTRAVERBOSE
LOG_DEBUG("Pin EN %s", val == HIGH ? "HIGH" : "LOW");
#ifdef GPS_DEBUG
LOG_DEBUG("Pin EN %s", on == HIGH ? "HI" : "LOW");
#endif
}
@@ -816,8 +839,8 @@ void GPS::writePinStandby(bool standby)
// Write and log
pinMode(PIN_GPS_STANDBY, OUTPUT);
digitalWrite(PIN_GPS_STANDBY, val);
#ifdef GPS_EXTRAVERBOSE
LOG_DEBUG("Pin STANDBY %s", val == HIGH ? "HIGH" : "LOW");
#ifdef GPS_DEBUG
LOG_DEBUG("Pin STANDBY %s", val == HIGH ? "HI" : "LOW");
#endif
#endif
}
@@ -849,8 +872,7 @@ void GPS::setPowerPMU(bool on)
// t-beam v1.1 GNSS power channel
on ? PMU->enablePowerOutput(XPOWERS_LDO3) : PMU->disablePowerOutput(XPOWERS_LDO3);
}
#ifdef GPS_EXTRAVERBOSE
#ifdef GPS_DEBUG
LOG_DEBUG("PMU %s", on ? "on" : "off");
#endif
#endif
@@ -867,9 +889,6 @@ void GPS::setPowerUBLOX(bool on, uint32_t sleepMs)
if (on) {
gps->_serial_gps->write(0xFF);
clearBuffer(); // This often returns old data, so drop it
#ifdef GPS_EXTRAVERBOSE
LOG_DEBUG("UBLOX: wake");
#endif
}
// If putting to sleep
@@ -886,23 +905,22 @@ void GPS::setPowerUBLOX(bool on, uint32_t sleepMs)
if (gnssModel != GNSS_MODEL_UBLOX10) {
// Encode the sleep time in millis into the packet
for (int i = 0; i < 4; i++)
gps->_message_PMREQ[0 + i] = sleepMs >> (i * 8);
_message_PMREQ[0 + i] = sleepMs >> (i * 8);
// Record the message length
msglen = gps->makeUBXPacket(0x02, 0x41, sizeof(_message_PMREQ), gps->_message_PMREQ);
msglen = gps->makeUBXPacket(0x02, 0x41, sizeof(_message_PMREQ), _message_PMREQ);
} else {
// Encode the sleep time in millis into the packet
for (int i = 0; i < 4; i++)
gps->_message_PMREQ_10[4 + i] = sleepMs >> (i * 8);
_message_PMREQ_10[4 + i] = sleepMs >> (i * 8);
// Record the message length
msglen = gps->makeUBXPacket(0x02, 0x41, sizeof(_message_PMREQ_10), gps->_message_PMREQ_10);
msglen = gps->makeUBXPacket(0x02, 0x41, sizeof(_message_PMREQ_10), _message_PMREQ_10);
}
// Send the UBX packet
gps->_serial_gps->write(gps->UBXscratch, msglen);
#ifdef GPS_EXTRAVERBOSE
#ifdef GPS_DEBUG
LOG_DEBUG("UBLOX: sleep for %dmS", sleepMs);
#endif
}
@@ -974,8 +992,7 @@ void GPS::publishUpdate()
shouldPublish = false;
// In debug logs, identify position by @timestamp:stage (stage 2 = publish)
LOG_DEBUG("publishing pos@%x:2, hasVal=%d, Sats=%d, GPSlock=%d", p.timestamp, hasValidLocation, p.sats_in_view,
hasLock());
LOG_DEBUG("Publish pos@%x:2, hasVal=%d, Sats=%d, GPSlock=%d", p.timestamp, hasValidLocation, p.sats_in_view, hasLock());
// Notify any status instances that are observing us
const meshtastic::GPSStatus status = meshtastic::GPSStatus(hasValidLocation, isConnected(), isPowerSaving(), p);
@@ -990,7 +1007,7 @@ int32_t GPS::runOnce()
{
if (!GPSInitFinished) {
if (!_serial_gps || config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT) {
LOG_INFO("GPS set to not-present. Skipping probe.");
LOG_INFO("GPS set to not-present. Skip probe");
return disable();
}
if (!setup())
@@ -1009,6 +1026,7 @@ int32_t GPS::runOnce()
}
}
GPSInitFinished = true;
publishUpdate();
}
// Repeaters have no need for GPS
@@ -1025,7 +1043,7 @@ int32_t GPS::runOnce()
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.");
LOG_DEBUG("GPS is not found, try factory reset on next boot");
devicestate.did_gps_reset = false;
nodeDB->saveToDisk(SEGMENT_DEVICESTATE);
return disable(); // Stop the GPS thread as it can do nothing useful until next reboot.
@@ -1059,10 +1077,9 @@ int32_t GPS::runOnce()
bool tooLong = scheduling.searchedTooLong();
if (tooLong)
LOG_WARN("Couldn't publish a valid location: didn't get a GPS lock in time.");
LOG_WARN("Couldn't publish a valid location: didn't get a GPS lock in time");
// Once we get a location we no longer desperately want an update
// LOG_DEBUG("gotLoc %d, tooLong %d, gotTime %d", gotLoc, tooLong, gotTime);
if ((gotLoc && gotTime) || tooLong) {
if (tooLong) {
@@ -1105,17 +1122,19 @@ int GPS::prepareDeepSleep(void *unused)
return 0;
}
const char *PROBE_MESSAGE = "Trying %s (%s)...";
const char *DETECTED_MESSAGE = "%s detected, using %s Module";
static const char *PROBE_MESSAGE = "Trying %s (%s)...";
static const char *DETECTED_MESSAGE = "%s detected, using %s Module";
#define PROBE_SIMPLE(CHIP, TOWRITE, RESPONSE, DRIVER, TIMEOUT, ...) \
LOG_DEBUG(PROBE_MESSAGE, TOWRITE, CHIP); \
clearBuffer(); \
_serial_gps->write(TOWRITE "\r\n"); \
if (getACK(RESPONSE, TIMEOUT) == GNSS_RESPONSE_OK) { \
LOG_INFO(DETECTED_MESSAGE, CHIP, #DRIVER); \
return DRIVER; \
}
do { \
LOG_DEBUG(PROBE_MESSAGE, TOWRITE, CHIP); \
clearBuffer(); \
_serial_gps->write(TOWRITE "\r\n"); \
if (getACK(RESPONSE, TIMEOUT) == GNSS_RESPONSE_OK) { \
LOG_INFO(DETECTED_MESSAGE, CHIP, #DRIVER); \
return DRIVER; \
} \
} while (0)
GnssModel_t GPS::probe(int serialSpeed)
{
@@ -1128,12 +1147,12 @@ GnssModel_t GPS::probe(int serialSpeed)
_serial_gps->begin(serialSpeed);
#else
if (_serial_gps->baudRate() != serialSpeed) {
LOG_DEBUG("Setting Baud to %i", serialSpeed);
LOG_DEBUG("Set Baud to %i", serialSpeed);
_serial_gps->updateBaudRate(serialSpeed);
}
#endif
memset(&info, 0, sizeof(struct uBloxGnssModelInfo));
memset(&ublox_info, 0, sizeof(ublox_info));
uint8_t buffer[768] = {0};
delay(100);
@@ -1178,7 +1197,7 @@ GnssModel_t GPS::probe(int serialSpeed)
// Check that the returned response class and message ID are correct
GPS_RESPONSE response = getACK(0x06, 0x08, 750);
if (response == GNSS_RESPONSE_NONE) {
LOG_WARN("Failed to find GNSS Module (baudrate %d)", serialSpeed);
LOG_WARN("No GNSS Module (baudrate %d)", serialSpeed);
return GNSS_MODEL_UNKNOWN;
} else if (response == GNSS_RESPONSE_FRAME_ERRORS) {
LOG_INFO("UBlox Frame Errors (baudrate %d)", serialSpeed);
@@ -1198,72 +1217,71 @@ GnssModel_t GPS::probe(int serialSpeed)
uint16_t len = getACK(buffer, sizeof(buffer), 0x0A, 0x04, 1200);
if (len) {
// LOG_DEBUG("monver reply size = %d", len);
uint16_t position = 0;
for (int i = 0; i < 30; i++) {
info.swVersion[i] = buffer[position];
ublox_info.swVersion[i] = buffer[position];
position++;
}
for (int i = 0; i < 10; i++) {
info.hwVersion[i] = buffer[position];
ublox_info.hwVersion[i] = buffer[position];
position++;
}
while (len >= position + 30) {
for (int i = 0; i < 30; i++) {
info.extension[info.extensionNo][i] = buffer[position];
ublox_info.extension[ublox_info.extensionNo][i] = buffer[position];
position++;
}
info.extensionNo++;
if (info.extensionNo > 9)
ublox_info.extensionNo++;
if (ublox_info.extensionNo > 9)
break;
}
LOG_DEBUG("Module Info : ");
LOG_DEBUG("Soft version: %s", info.swVersion);
LOG_DEBUG("Hard version: %s", info.hwVersion);
LOG_DEBUG("Extensions:%d", info.extensionNo);
for (int i = 0; i < info.extensionNo; i++) {
LOG_DEBUG(" %s", info.extension[i]);
LOG_DEBUG("Soft version: %s", ublox_info.swVersion);
LOG_DEBUG("Hard version: %s", ublox_info.hwVersion);
LOG_DEBUG("Extensions:%d", ublox_info.extensionNo);
for (int i = 0; i < ublox_info.extensionNo; i++) {
LOG_DEBUG(" %s", ublox_info.extension[i]);
}
memset(buffer, 0, sizeof(buffer));
// tips: extensionNo field is 0 on some 6M GNSS modules
for (int i = 0; i < info.extensionNo; ++i) {
if (!strncmp(info.extension[i], "MOD=", 4)) {
strncpy((char *)buffer, &(info.extension[i][4]), sizeof(buffer));
} else if (!strncmp(info.extension[i], "PROTVER", 7)) {
for (int i = 0; i < ublox_info.extensionNo; ++i) {
if (!strncmp(ublox_info.extension[i], "MOD=", 4)) {
strncpy((char *)buffer, &(ublox_info.extension[i][4]), sizeof(buffer));
} else if (!strncmp(ublox_info.extension[i], "PROTVER", 7)) {
char *ptr = nullptr;
memset(buffer, 0, sizeof(buffer));
strncpy((char *)buffer, &(info.extension[i][8]), sizeof(buffer));
strncpy((char *)buffer, &(ublox_info.extension[i][8]), sizeof(buffer));
LOG_DEBUG("Protocol Version:%s", (char *)buffer);
if (strlen((char *)buffer)) {
uBloxProtocolVersion = strtoul((char *)buffer, &ptr, 10);
LOG_DEBUG("ProtVer=%d", uBloxProtocolVersion);
ublox_info.protocol_version = strtoul((char *)buffer, &ptr, 10);
LOG_DEBUG("ProtVer=%d", ublox_info.protocol_version);
} else {
uBloxProtocolVersion = 0;
ublox_info.protocol_version = 0;
}
}
}
if (strncmp(info.hwVersion, "00040007", 8) == 0) {
if (strncmp(ublox_info.hwVersion, "00040007", 8) == 0) {
LOG_INFO(DETECTED_MESSAGE, "U-blox 6", "6");
return GNSS_MODEL_UBLOX6;
} else if (strncmp(info.hwVersion, "00070000", 8) == 0) {
} else if (strncmp(ublox_info.hwVersion, "00070000", 8) == 0) {
LOG_INFO(DETECTED_MESSAGE, "U-blox 7", "7");
return GNSS_MODEL_UBLOX7;
} else if (strncmp(info.hwVersion, "00080000", 8) == 0) {
} else if (strncmp(ublox_info.hwVersion, "00080000", 8) == 0) {
LOG_INFO(DETECTED_MESSAGE, "U-blox 8", "8");
return GNSS_MODEL_UBLOX8;
} else if (strncmp(info.hwVersion, "00190000", 8) == 0) {
} else if (strncmp(ublox_info.hwVersion, "00190000", 8) == 0) {
LOG_INFO(DETECTED_MESSAGE, "U-blox 9", "9");
return GNSS_MODEL_UBLOX9;
} else if (strncmp(info.hwVersion, "000A0000", 8) == 0) {
} else if (strncmp(ublox_info.hwVersion, "000A0000", 8) == 0) {
LOG_INFO(DETECTED_MESSAGE, "U-blox 10", "10");
return GNSS_MODEL_UBLOX10;
}
}
LOG_WARN("Failed to find GNSS Module (baudrate %d)", serialSpeed);
LOG_WARN("No GNSS Module (baudrate %d)", serialSpeed);
return GNSS_MODEL_UNKNOWN;
}
@@ -1326,7 +1344,7 @@ GPS *GPS::createGps()
// see NMEAGPS.h
gsafixtype.begin(reader, NMEA_MSG_GXGSA, 2);
gsapdop.begin(reader, NMEA_MSG_GXGSA, 15);
LOG_DEBUG("Using " NMEA_MSG_GXGSA " for 3DFIX and PDOP");
LOG_DEBUG("Use " NMEA_MSG_GXGSA " for 3DFIX and PDOP");
#endif
// Make sure the GPS is awake before performing any init.
@@ -1347,8 +1365,8 @@ GPS *GPS::createGps()
// ESP32 has a special set of parameters vs other arduino ports
#if defined(ARCH_ESP32)
LOG_DEBUG("Using GPIO%d for GPS RX", new_gps->rx_gpio);
LOG_DEBUG("Using GPIO%d for GPS TX", new_gps->tx_gpio);
LOG_DEBUG("Use GPIO%d for GPS RX", new_gps->rx_gpio);
LOG_DEBUG("Use GPIO%d for GPS TX", new_gps->tx_gpio);
_serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, new_gps->rx_gpio, new_gps->tx_gpio);
#elif defined(ARCH_RP2040)
_serial_gps->setFIFOSize(256);
@@ -1384,26 +1402,22 @@ bool GPS::factoryReset()
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1C, 0xA2};
_serial_gps->write(_message_reset1, sizeof(_message_reset1));
if (getACK(0x05, 0x01, 10000)) {
LOG_INFO(ACK_SUCCESS_MESSAGE);
LOG_DEBUG(ACK_SUCCESS_MESSAGE);
}
delay(100);
byte _message_reset2[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1B, 0xA1};
_serial_gps->write(_message_reset2, sizeof(_message_reset2));
if (getACK(0x05, 0x01, 10000)) {
LOG_INFO(ACK_SUCCESS_MESSAGE);
LOG_DEBUG(ACK_SUCCESS_MESSAGE);
}
delay(100);
byte _message_reset3[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x03, 0x1D, 0xB3};
_serial_gps->write(_message_reset3, sizeof(_message_reset3));
if (getACK(0x05, 0x01, 10000)) {
LOG_INFO(ACK_SUCCESS_MESSAGE);
LOG_DEBUG(ACK_SUCCESS_MESSAGE);
}
// Reset device ram to COLDSTART state
// byte _message_CFG_RST_COLDSTART[] = {0xB5, 0x62, 0x06, 0x04, 0x04, 0x00, 0xFF, 0xB9, 0x00, 0x00, 0xC6, 0x8B};
// _serial_gps->write(_message_CFG_RST_COLDSTART, sizeof(_message_CFG_RST_COLDSTART));
// delay(1000);
} else if (gnssModel == GNSS_MODEL_MTK) {
// send the CAS10 to perform a factory restart of the device (and other device that support PCAS statements)
LOG_INFO("GNSS Factory Reset via PCAS10,3");
@@ -1515,7 +1529,7 @@ bool GPS::lookForLocation()
#ifndef TINYGPS_OPTION_NO_STATISTICS
if (reader.failedChecksum() > lastChecksumFailCount) {
LOG_WARN("%u new GPS checksum failures, for a total of %u.", reader.failedChecksum() - lastChecksumFailCount,
LOG_WARN("%u new GPS checksum failures, for a total of %u", reader.failedChecksum() - lastChecksumFailCount,
reader.failedChecksum());
lastChecksumFailCount = reader.failedChecksum();
}
@@ -1523,14 +1537,13 @@ bool GPS::lookForLocation()
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
fixType = atoi(gsafixtype.value()); // will set to zero if no data
// LOG_DEBUG("FIX QUAL=%d, TYPE=%d", fixQual, fixType);
#endif
// check if GPS has an acceptable lock
if (!hasLock())
return false;
#ifdef GPS_EXTRAVERBOSE
#ifdef GPS_DEBUG
LOG_DEBUG("AGE: LOC=%d FIX=%d DATE=%d TIME=%d", reader.location.age(),
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
gsafixtype.age(),
@@ -1538,7 +1551,7 @@ bool GPS::lookForLocation()
0,
#endif
reader.date.age(), reader.time.age());
#endif // GPS_EXTRAVERBOSE
#endif // GPS_DEBUG
// Is this a new point or are we re-reading the previous one?
if (!reader.location.isUpdated() && !reader.altitude.isUpdated())
@@ -1561,13 +1574,13 @@ bool GPS::lookForLocation()
// Bail out EARLY to avoid overwriting previous good data (like #857)
if (toDegInt(loc.lat) > 900000000) {
#ifdef GPS_EXTRAVERBOSE
#ifdef GPS_DEBUG
LOG_DEBUG("Bail out EARLY on LAT %i", toDegInt(loc.lat));
#endif
return false;
}
if (toDegInt(loc.lng) > 1800000000) {
#ifdef GPS_EXTRAVERBOSE
#ifdef GPS_DEBUG
LOG_DEBUG("Bail out EARLY on LNG %i", toDegInt(loc.lng));
#endif
return false;
@@ -1579,7 +1592,6 @@ bool GPS::lookForLocation()
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
p.HDOP = reader.hdop.value();
p.PDOP = TinyGPSPlus::parseDecimal(gsapdop.value());
// LOG_DEBUG("PDOP=%d, HDOP=%d", p.PDOP, p.HDOP);
#else
// FIXME! naive PDOP emulation (assumes VDOP==HDOP)
// correct formula is PDOP = SQRT(HDOP^2 + VDOP^2)
@@ -1669,12 +1681,10 @@ bool GPS::whileActive()
}
#ifdef SERIAL_BUFFER_SIZE
if (_serial_gps->available() >= SERIAL_BUFFER_SIZE - 1) {
LOG_WARN("GPS Buffer full with %u bytes waiting. Flushing to avoid corruption.", _serial_gps->available());
LOG_WARN("GPS Buffer full with %u bytes waiting. Flush to avoid corruption", _serial_gps->available());
clearBuffer();
}
#endif
// if (_serial_gps->available() > 0)
// LOG_DEBUG("GPS Bytes Waiting: %u", _serial_gps->available());
// First consume any chars that have piled up at the receiver
while (_serial_gps->available() > 0) {
int c = _serial_gps->read();
@@ -1724,7 +1734,7 @@ void GPS::toggleGpsMode()
{
if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_DISABLED;
LOG_INFO("User toggled GpsMode. Now DISABLED.");
LOG_INFO("User toggled GpsMode. Now DISABLED");
playGPSDisableBeep();
#ifdef GNSS_AIROHA
if (powerState == GPS_ACTIVE) {

View File

@@ -16,13 +16,6 @@
#define GPS_EN_ACTIVE 1
#endif
struct uBloxGnssModelInfo {
char swVersion[30];
char hwVersion[10];
uint8_t extensionNo;
char extension[10][30];
};
typedef enum {
GNSS_MODEL_ATGM336H,
GNSS_MODEL_MTK,
@@ -54,9 +47,6 @@ enum GPSPowerState : uint8_t {
GPS_OFF // Powered off indefinitely
};
// Generate a string representation of DOP
const char *getDOPString(uint32_t dop);
/**
* A gps class that only reads from the GPS periodically and keeps the gps powered down except when reading
*
@@ -64,109 +54,7 @@ const char *getDOPString(uint32_t dop);
*/
class GPS : private concurrency::OSThread
{
TinyGPSPlus reader;
uint8_t fixQual = 0; // fix quality from GPGGA
uint32_t lastChecksumFailCount = 0;
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
// (20210908) TinyGps++ can only read the GPGSA "FIX TYPE" field
// via optional feature "custom fields", currently disabled (bug #525)
TinyGPSCustom gsafixtype; // custom extract fix type from GPGSA
TinyGPSCustom gsapdop; // custom extract PDOP from GPGSA
uint8_t fixType = 0; // fix type from GPGSA
#endif
private:
#if GPS_BAUDRATE_FIXED
// if GPS_BAUDRATE is specified in variant, only try that.
const int serialSpeeds[1] = {GPS_BAUDRATE};
const int rareSerialSpeeds[1] = {GPS_BAUDRATE};
#else
const int serialSpeeds[3] = {9600, 115200, 38400};
const int rareSerialSpeeds[3] = {4800, 57600, GPS_BAUDRATE};
#endif
uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastFixStartMsec = 0;
uint32_t rx_gpio = 0;
uint32_t tx_gpio = 0;
int speedSelect = 0;
int probeTries = 0;
/**
* hasValidLocation - indicates that the position variables contain a complete
* GPS location, valid and fresh (< gps_update_interval + position_broadcast_secs)
*/
bool hasValidLocation = false; // default to false, until we complete our first read
bool isInPowersave = false;
bool shouldPublish = false; // If we've changed GPS state, this will force a publish the next loop()
bool hasGPS = false; // Do we have a GPS we are talking to
bool GPSInitFinished = false; // Init thread finished?
bool GPSInitStarted = false; // Init thread finished?
GPSPowerState powerState = GPS_OFF; // GPS_ACTIVE if we want a location right now
uint8_t numSatellites = 0;
CallbackObserver<GPS, void *> notifyDeepSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
public:
/** If !NULL we will use this serial port to construct our GPS */
#if defined(ARCH_RP2040)
static SerialUART *_serial_gps;
#else
static HardwareSerial *_serial_gps;
#endif
static uint8_t _message_PMREQ[];
static uint8_t _message_PMREQ_10[];
static const uint8_t _message_CFG_RXM_PSM[];
static const uint8_t _message_CFG_RXM_ECO[];
static const uint8_t _message_CFG_PM2[];
static const uint8_t _message_GNSS_7[];
static const uint8_t _message_GNSS_8[];
static const uint8_t _message_JAM_6_7[];
static const uint8_t _message_JAM_8[];
static const uint8_t _message_NAVX5[];
static const uint8_t _message_NAVX5_8[];
static const uint8_t _message_NMEA[];
static const uint8_t _message_DISABLE_TXT_INFO[];
static const uint8_t _message_1HZ[];
static const uint8_t _message_GLL[];
static const uint8_t _message_GSA[];
static const uint8_t _message_GSV[];
static const uint8_t _message_VTG[];
static const uint8_t _message_RMC[];
static const uint8_t _message_AID[];
static const uint8_t _message_GGA[];
static const uint8_t _message_PMS[];
static const uint8_t _message_SAVE[];
static const uint8_t _message_SAVE_10[];
// VALSET Commands for M10
static const uint8_t _message_VALSET_PM[];
static const uint8_t _message_VALSET_PM_RAM[];
static const uint8_t _message_VALSET_PM_BBR[];
static const uint8_t _message_VALSET_ITFM_RAM[];
static const uint8_t _message_VALSET_ITFM_BBR[];
static const uint8_t _message_VALSET_DISABLE_NMEA_RAM[];
static const uint8_t _message_VALSET_DISABLE_NMEA_BBR[];
static const uint8_t _message_VALSET_DISABLE_TXT_INFO_RAM[];
static const uint8_t _message_VALSET_DISABLE_TXT_INFO_BBR[];
static const uint8_t _message_VALSET_ENABLE_NMEA_RAM[];
static const uint8_t _message_VALSET_ENABLE_NMEA_BBR[];
static const uint8_t _message_VALSET_DISABLE_SBAS_RAM[];
static const uint8_t _message_VALSET_DISABLE_SBAS_BBR[];
// CASIC commands for ATGM336H
static const uint8_t _message_CAS_CFG_RST_FACTORY[];
static const uint8_t _message_CAS_CFG_NAVX_CONF[];
static const uint8_t _message_CAS_CFG_RATE_1HZ[];
const char *ACK_SUCCESS_MESSAGE = "Get ack success!";
meshtastic_Position p = meshtastic_Position_init_default;
/** This is normally bound to config.position.gps_en_gpio but some rare boards (like heltec tracker) need more advanced
@@ -176,8 +64,6 @@ class GPS : private concurrency::OSThread
*/
GpioVirtPin *enablePin = NULL;
GPS() : concurrency::OSThread("GPS") {}
virtual ~GPS();
/** We will notify this observable anytime GPS state has changed meaningfully */
@@ -214,21 +100,6 @@ class GPS : private concurrency::OSThread
// Empty the input buffer as quickly as possible
void clearBuffer();
// Create a ublox packet for editing in memory
uint8_t makeUBXPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg);
uint8_t makeCASPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg);
// scratch space for creating ublox packets
uint8_t UBXscratch[250] = {0};
int rebootsSeen = 0;
int getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID, uint32_t waitMillis);
GPS_RESPONSE getACK(uint8_t c, uint8_t i, uint32_t waitMillis);
GPS_RESPONSE getACK(const char *message, uint32_t waitMillis);
GPS_RESPONSE getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis);
virtual bool factoryReset();
// Creates an instance of the GPS class.
@@ -241,20 +112,8 @@ class GPS : private concurrency::OSThread
// Let the GPS hardware save power between updates
void down();
protected:
/**
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
* Override this method to check for new locations
*
* @return true if we've acquired a time
*/
/**
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
* Override this method to check for new locations
*
* @return true if we've acquired a new location
*/
private:
GPS() : concurrency::OSThread("GPS") {}
/// Record that we have a GPS
void setConnected();
@@ -281,15 +140,74 @@ class GPS : private concurrency::OSThread
*/
virtual bool lookForLocation();
private:
GnssModel_t gnssModel = GNSS_MODEL_UNKNOWN;
TinyGPSPlus reader;
uint8_t fixQual = 0; // fix quality from GPGGA
uint32_t lastChecksumFailCount = 0;
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
// (20210908) TinyGps++ can only read the GPGSA "FIX TYPE" field
// via optional feature "custom fields", currently disabled (bug #525)
TinyGPSCustom gsafixtype; // custom extract fix type from GPGSA
TinyGPSCustom gsapdop; // custom extract PDOP from GPGSA
uint8_t fixType = 0; // fix type from GPGSA
#endif
uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastFixStartMsec = 0;
uint32_t rx_gpio = 0;
uint32_t tx_gpio = 0;
uint8_t speedSelect = 0;
uint8_t probeTries = 0;
/**
* hasValidLocation - indicates that the position variables contain a complete
* GPS location, valid and fresh (< gps_update_interval + position_broadcast_secs)
*/
bool hasValidLocation = false; // default to false, until we complete our first read
bool isInPowersave = false;
bool shouldPublish = false; // If we've changed GPS state, this will force a publish the next loop()
bool hasGPS = false; // Do we have a GPS we are talking to
bool GPSInitFinished = false; // Init thread finished?
bool GPSInitStarted = false; // Init thread finished?
GPSPowerState powerState = GPS_OFF; // GPS_ACTIVE if we want a location right now
uint8_t numSatellites = 0;
CallbackObserver<GPS, void *> notifyDeepSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
/** If !NULL we will use this serial port to construct our GPS */
#if defined(ARCH_RP2040)
static SerialUART *_serial_gps;
#else
static HardwareSerial *_serial_gps;
#endif
// Create a ublox packet for editing in memory
uint8_t makeUBXPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg);
uint8_t makeCASPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg);
// scratch space for creating ublox packets
uint8_t UBXscratch[250] = {0};
int rebootsSeen = 0;
int getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID, uint32_t waitMillis);
GPS_RESPONSE getACK(uint8_t c, uint8_t i, uint32_t waitMillis);
GPS_RESPONSE getACK(const char *message, uint32_t waitMillis);
GPS_RESPONSE getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis);
/// Prepare the GPS for the cpu entering deep sleep, expect to be gone for at least 100s of msecs
/// always returns 0 to indicate okay to sleep
int prepareDeepSleep(void *unused);
// Calculate checksum
void UBXChecksum(uint8_t *message, size_t length);
void CASChecksum(uint8_t *message, size_t length);
/** Set power with EN pin, if relevant
*/
void writePinEN(bool on);
@@ -318,11 +236,6 @@ class GPS : private concurrency::OSThread
// delay counter to allow more sats before fixed position stops GPS thread
uint8_t fixeddelayCtr = 0;
const char *powerStateToString();
protected:
GnssModel_t gnssModel = GNSS_MODEL_UNKNOWN;
};
extern GPS *gps;

View File

@@ -49,7 +49,7 @@ uint32_t GPSUpdateScheduling::msUntilNextSearch()
}
// How long have we already been searching?
// Used to abort a search in progress, if it runs unnaceptably long
// Used to abort a search in progress, if it runs unacceptably long
uint32_t GPSUpdateScheduling::elapsedSearchMs()
{
// If searching
@@ -98,7 +98,7 @@ void GPSUpdateScheduling::updateLockTimePrediction()
// Ignore the first lock-time: likely to be long, will skew data
// Second locktime: likely stable. Use to intialize the smoothing filter
// Second locktime: likely stable. Use to initialize the smoothing filter
if (searchCount == 1)
predictedMsToGetLock = lockTime;
@@ -106,9 +106,9 @@ void GPSUpdateScheduling::updateLockTimePrediction()
else if (searchCount > 1)
predictedMsToGetLock = (lockTime * weighting) + (predictedMsToGetLock * (1 - weighting));
searchCount++; // Only tracked so we can diregard initial lock-times
searchCount++; // Only tracked so we can disregard initial lock-times
LOG_DEBUG("Predicting %us to get next lock", predictedMsToGetLock / 1000);
LOG_DEBUG("Predict %us to get next lock", predictedMsToGetLock / 1000);
}
// How long do we expect to spend searching for a lock?

View File

@@ -574,3 +574,23 @@ const char *GeoCoord::degreesToBearing(unsigned int degrees)
else
return "N";
}
double GeoCoord::pow_neg(double base, double exponent)
{
if (exponent == 0) {
return 1;
} else if (exponent > 0) {
return pow(base, exponent);
}
return 1 / pow(base, -exponent);
}
double GeoCoord::toRadians(double deg)
{
return deg * PI / 180;
}
double GeoCoord::toDegrees(double r)
{
return r * 180 / PI;
}

View File

@@ -13,28 +13,6 @@
#define OLC_CODE_LEN 11
#define DEG_CONVERT (180 / PI)
// Helper functions
// Raises a number to an exponent, handling negative exponents.
static inline double pow_neg(double base, double exponent)
{
if (exponent == 0) {
return 1;
} else if (exponent > 0) {
return pow(base, exponent);
}
return 1 / pow(base, -exponent);
}
static inline double toRadians(double deg)
{
return deg * PI / 180;
}
static inline double toDegrees(double r)
{
return r * 180 / PI;
}
// GeoCoord structs/classes
// A struct to hold the data for a DMS coordinate.
struct DMS {
@@ -120,6 +98,11 @@ class GeoCoord
static unsigned int bearingToDegrees(const char *bearing);
static const char *degreesToBearing(unsigned int degrees);
// Raises a number to an exponent, handling negative exponents.
static double pow_neg(double base, double exponent);
static double toRadians(double deg);
static double toDegrees(double r);
// Point to point conversions
int32_t distanceTo(const GeoCoord &pointB);
int32_t bearingTo(const GeoCoord &pointB);
@@ -162,4 +145,4 @@ class GeoCoord
// OLC getter
void getOLCCode(char *code) { strncpy(code, _olc.code, OLC_CODE_LEN + 1); } // +1 for null termination
};
};

View File

@@ -23,7 +23,7 @@ uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_PositionLite &pos, c
{
GeoCoord geoCoord(pos.latitude_i, pos.longitude_i, pos.altitude);
char type = isCaltopoMode ? 'P' : 'N';
uint32_t len = snprintf(buf, bufsz, "$G%cWPL,%02d%07.4f,%c,%03d%07.4f,%c,%s", type, geoCoord.getDMSLatDeg(),
uint32_t len = snprintf(buf, bufsz, "\r\n$G%cWPL,%02d%07.4f,%c,%03d%07.4f,%c,%s", type, geoCoord.getDMSLatDeg(),
(abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6, geoCoord.getDMSLatCP(),
geoCoord.getDMSLonDeg(), (abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6,
geoCoord.getDMSLonCP(), name);

View File

@@ -112,7 +112,7 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate)
uint32_t printableEpoch = tv->tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms
#ifdef BUILD_EPOCH
if (tv->tv_sec < BUILD_EPOCH) {
LOG_WARN("Ignoring time (%ld) before build epoch (%ld)!", printableEpoch, BUILD_EPOCH);
LOG_WARN("Ignore time (%ld) before build epoch (%ld)!", printableEpoch, BUILD_EPOCH);
return false;
}
#endif
@@ -120,21 +120,21 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate)
bool shouldSet;
if (forceUpdate) {
shouldSet = true;
LOG_DEBUG("Overriding current RTC quality (%s) with incoming time of RTC quality of %s", RtcName(currentQuality),
LOG_DEBUG("Override current RTC quality (%s) with incoming time of RTC quality of %s", RtcName(currentQuality),
RtcName(q));
} else if (q > currentQuality) {
shouldSet = true;
LOG_DEBUG("Upgrading time to quality %s", RtcName(q));
LOG_DEBUG("Upgrade time to quality %s", RtcName(q));
} else if (q == RTCQualityGPS) {
shouldSet = true;
LOG_DEBUG("Reapplying GPS time: %ld secs", printableEpoch);
LOG_DEBUG("Reapply GPS time: %ld secs", printableEpoch);
} 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", printableEpoch);
LOG_DEBUG("Reapply external time to correct clock drift %ld secs", printableEpoch);
} else {
shouldSet = false;
LOG_DEBUG("Current RTC quality: %s. Ignoring time of RTC quality of %s", RtcName(currentQuality), RtcName(q));
LOG_DEBUG("Current RTC quality: %s. Ignore time of RTC quality of %s", RtcName(currentQuality), RtcName(q));
}
if (shouldSet) {
@@ -230,7 +230,7 @@ bool perhapsSetRTC(RTCQuality q, struct tm &t)
// LOG_DEBUG("Got time from GPS month=%d, year=%d, unixtime=%ld", t.tm_mon, t.tm_year, tv.tv_sec);
if (t.tm_year < 0 || t.tm_year >= 300) {
// LOG_DEBUG("Ignoring invalid GPS month=%d, year=%d, unixtime=%ld", t.tm_mon, t.tm_year, tv.tv_sec);
// LOG_DEBUG("Ignore invalid GPS month=%d, year=%d, unixtime=%ld", t.tm_mon, t.tm_year, tv.tv_sec);
return false;
} else {
return perhapsSetRTC(q, &tv);

View File

@@ -21,7 +21,7 @@
// CFG-RST (0x06, 0x02)
// Factory reset
const uint8_t GPS::_message_CAS_CFG_RST_FACTORY[] = {
static const uint8_t _message_CAS_CFG_RST_FACTORY[] = {
0xFF, 0x03, // Fields to clear
0x01, // Reset Mode: Controlled Software reset
0x03 // Startup Mode: Factory
@@ -30,7 +30,7 @@ const uint8_t GPS::_message_CAS_CFG_RST_FACTORY[] = {
// CFG_RATE (0x06, 0x01)
// 1HZ update rate, this should always be the case after
// factory reset but update it regardless
const uint8_t GPS::_message_CAS_CFG_RATE_1HZ[] = {
static const uint8_t _message_CAS_CFG_RATE_1HZ[] = {
0xE8, 0x03, // Update Rate: 0x03E8 = 1000ms
0x00, 0x00 // Reserved
};
@@ -39,7 +39,7 @@ const uint8_t GPS::_message_CAS_CFG_RATE_1HZ[] = {
// Initial ATGM33H-5N configuration, Updates for Dynamic Mode, Fix Mode, and SV system
// Qwirk: The ATGM33H-5N-31 should only support GPS+BDS, however it will happily enable
// and use GPS+BDS+GLONASS iff the correct CFG_NAVX command is used.
const uint8_t GPS::_message_CAS_CFG_NAVX_CONF[] = {
static const uint8_t _message_CAS_CFG_NAVX_CONF[] = {
0x03, 0x01, 0x00, 0x00, // Update Mask: Dynamic Mode, Fix Mode, Nav Settings
0x03, // Dynamic Mode: Automotive
0x03, // Fix Mode: Auto 2D/3D
@@ -60,4 +60,4 @@ const uint8_t GPS::_message_CAS_CFG_NAVX_CONF[] = {
0x00, 0x00, 0x00, 0x00, // Position Accuracy Max
0x00, 0x00, 0x00, 0x00, // Time Accuracy Max
0x00, 0x00, 0x00, 0x00 // Static Hold Threshold
};
};

View File

@@ -1,20 +1,22 @@
const char *failMessage = "Unable to %s";
static const char *failMessage = "Unable to %s";
#define SEND_UBX_PACKET(TYPE, ID, DATA, ERRMSG, TIMEOUT) \
msglen = makeUBXPacket(TYPE, ID, sizeof(DATA), DATA); \
_serial_gps->write(UBXscratch, msglen); \
if (getACK(TYPE, ID, TIMEOUT) != GNSS_RESPONSE_OK) { \
LOG_WARN(failMessage, #ERRMSG); \
}
do { \
msglen = makeUBXPacket(TYPE, ID, sizeof(DATA), DATA); \
_serial_gps->write(UBXscratch, msglen); \
if (getACK(TYPE, ID, TIMEOUT) != GNSS_RESPONSE_OK) { \
LOG_WARN(failMessage, #ERRMSG); \
} \
} while (0)
// Power Management
uint8_t GPS::_message_PMREQ[] PROGMEM = {
static uint8_t _message_PMREQ[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, // 4 bytes duration of request task (milliseconds)
0x02, 0x00, 0x00, 0x00 // Bitfield, set backup = 1
};
uint8_t GPS::_message_PMREQ_10[] PROGMEM = {
static uint8_t _message_PMREQ_10[] PROGMEM = {
0x00, // version (0 for this version)
0x00, 0x00, 0x00, // Reserved 1
0x00, 0x00, 0x00, 0x00, // 4 bytes duration of request task (milliseconds)
@@ -22,18 +24,18 @@ uint8_t GPS::_message_PMREQ_10[] PROGMEM = {
0x08, 0x00, 0x00, 0x00 // wakeupSources Wake on uartrx
};
const uint8_t GPS::_message_CFG_RXM_PSM[] PROGMEM = {
static const uint8_t _message_CFG_RXM_PSM[] PROGMEM = {
0x08, // Reserved
0x01 // Power save mode
};
// only for Neo-6
const uint8_t GPS::_message_CFG_RXM_ECO[] PROGMEM = {
static const uint8_t _message_CFG_RXM_ECO[] PROGMEM = {
0x08, // Reserved
0x04 // eco mode
};
const uint8_t GPS::_message_CFG_PM2[] PROGMEM = {
static const uint8_t _message_CFG_PM2[] PROGMEM = {
0x01, // version
0x00, // Reserved 1, set to 0x06 by u-Center
0x00, // Reserved 2
@@ -58,7 +60,7 @@ const uint8_t GPS::_message_CFG_PM2[] PROGMEM = {
// Constallation setup, none required for Neo-6
// For Neo-7 GPS & SBAS
const uint8_t GPS::_message_GNSS_7[] = {
static const uint8_t _message_GNSS_7[] = {
0x00, // msgVer (0 for this version)
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
0xff, // numTrkChUse (max number of channels to use, 0xff = max available)
@@ -76,7 +78,7 @@ const uint8_t GPS::_message_GNSS_7[] = {
// There is also a possibility that the module may be GPS-only.
// For M8 GPS, GLONASS, Galileo, SBAS, QZSS
const uint8_t GPS::_message_GNSS_8[] = {
static const uint8_t _message_GNSS_8[] = {
0x00, // msgVer (0 for this version)
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
0xff, // numTrkChUse (max number of channels to use, 0xff = max available)
@@ -90,7 +92,7 @@ const uint8_t GPS::_message_GNSS_8[] = {
};
/*
// For M8 GPS, GLONASS, BeiDou, SBAS, QZSS
const uint8_t GPS::_message_GNSS_8_B[] = {
static const uint8_t _message_GNSS_8_B[] = {
0x00, // msgVer (0 for this version)
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
0xff, // numTrkChUse (max number of channels to use, 0xff = max available) read only for protocol >23
@@ -105,7 +107,7 @@ const uint8_t GPS::_message_GNSS_8_B[] = {
*/
// For M8 we want to enable NMEA version 4.10 messages to allow for Galileo and or BeiDou
const uint8_t GPS::_message_NMEA[]{
static const uint8_t _message_NMEA[]{
0x00, // filter flags
0x41, // NMEA Version
0x00, // Max number of SVs to report per TaklerId
@@ -121,13 +123,13 @@ const uint8_t GPS::_message_NMEA[]{
// Enable jamming/interference monitor
// For Neo-6, Max-7 and Neo-7
const uint8_t GPS::_message_JAM_6_7[] = {
static const uint8_t _message_JAM_6_7[] = {
0xf3, 0xac, 0x62, 0xad, // config1 bbThreshold = 3, cwThreshold = 15, enable = 1, reserved bits 0x16B156
0x1e, 0x03, 0x00, 0x00 // config2 antennaSetting Unknown = 0, reserved 3, = 0x00,0x00, reserved 2 = 0x31E
};
// For M8
const uint8_t GPS::_message_JAM_8[] = {
static const uint8_t _message_JAM_8[] = {
0xf3, 0xac, 0x62, 0xad, // config1 bbThreshold = 3, cwThreshold = 15, enable1 = 1, reserved bits 0x16B156
0x1e, 0x43, 0x00, 0x00 // config2 antennaSetting Unknown = 0, enable2 = 1, generalBits = 0x31E
};
@@ -137,7 +139,7 @@ const uint8_t GPS::_message_JAM_8[] = {
// ToDo: check UBX-MON-VER for module type and protocol version
// For the Neo-6
const uint8_t GPS::_message_NAVX5[] = {
static const uint8_t _message_NAVX5[] = {
0x00, 0x00, // msgVer (0 for this version)
0x4c, 0x66, // mask1
0x00, 0x00, 0x00, 0x00, // Reserved 0
@@ -166,7 +168,7 @@ const uint8_t GPS::_message_NAVX5[] = {
0x00, 0x00, 0x00, 0x00 // Reserved 4
};
// For the M8
const uint8_t GPS::_message_NAVX5_8[] = {
static const uint8_t _message_NAVX5_8[] = {
0x02, 0x00, // msgVer (2 for this version)
0x4c, 0x66, // mask1
0x00, 0x00, 0x00, 0x00, // mask2
@@ -197,7 +199,7 @@ const uint8_t GPS::_message_NAVX5_8[] = {
// Additionally, for some new modules like the M9/M10, an update rate lower than 5Hz
// is recommended to avoid a known issue with satellites disappearing.
// The module defaults for M8, M9, M10 are the same as we use here so no update is necessary
const uint8_t GPS::_message_1HZ[] = {
static const uint8_t _message_1HZ[] = {
0xE8, 0x03, // Measurement Rate (1000ms for 1Hz)
0x01, 0x00, // Navigation rate, always 1 in GPS mode
0x01, 0x00 // Time reference
@@ -205,7 +207,7 @@ const uint8_t GPS::_message_1HZ[] = {
// Disable GLL. GLL - Geographic position (latitude and longitude), which provides the current geographical
// coordinates.
const uint8_t GPS::_message_GLL[] = {
static const uint8_t _message_GLL[] = {
0xF0, 0x01, // NMEA ID for GLL
0x00, // Rate for DDC
0x00, // Rate for UART1
@@ -217,7 +219,7 @@ const uint8_t GPS::_message_GLL[] = {
// Disable GSA. GSA - GPS DOP and active satellites, used for detailing the satellites used in the positioning and
// the DOP (Dilution of Precision)
const uint8_t GPS::_message_GSA[] = {
static const uint8_t _message_GSA[] = {
0xF0, 0x02, // NMEA ID for GSA
0x00, // Rate for DDC
0x00, // Rate for UART1
@@ -228,7 +230,7 @@ const uint8_t GPS::_message_GSA[] = {
};
// Disable GSV. GSV - Satellites in view, details the number and location of satellites in view.
const uint8_t GPS::_message_GSV[] = {
static const uint8_t _message_GSV[] = {
0xF0, 0x03, // NMEA ID for GSV
0x00, // Rate for DDC
0x00, // Rate for UART1
@@ -240,7 +242,7 @@ const uint8_t GPS::_message_GSV[] = {
// Disable VTG. VTG - Track made good and ground speed, which provides course and speed information relative to
// the ground.
const uint8_t GPS::_message_VTG[] = {
static const uint8_t _message_VTG[] = {
0xF0, 0x05, // NMEA ID for VTG
0x00, // Rate for DDC
0x00, // Rate for UART1
@@ -251,7 +253,7 @@ const uint8_t GPS::_message_VTG[] = {
};
// Enable RMC. RMC - Recommended Minimum data, the essential gps pvt (position, velocity, time) data.
const uint8_t GPS::_message_RMC[] = {
static const uint8_t _message_RMC[] = {
0xF0, 0x04, // NMEA ID for RMC
0x00, // Rate for DDC
0x01, // Rate for UART1
@@ -262,7 +264,7 @@ const uint8_t GPS::_message_RMC[] = {
};
// Enable GGA. GGA - Global Positioning System Fix Data, which provides 3D location and accuracy data.
const uint8_t GPS::_message_GGA[] = {
static const uint8_t _message_GGA[] = {
0xF0, 0x00, // NMEA ID for GGA
0x00, // Rate for DDC
0x01, // Rate for UART1
@@ -274,7 +276,7 @@ const uint8_t GPS::_message_GGA[] = {
// Disable UBX-AID-ALPSRV as it may confuse TinyGPS. The Neo-6 seems to send this message
// whether the AID Autonomous is enabled or not
const uint8_t GPS::_message_AID[] = {
static const uint8_t _message_AID[] = {
0x0B, 0x32, // NMEA ID for UBX-AID-ALPSRV
0x00, // Rate for DDC
0x00, // Rate for UART1
@@ -287,7 +289,7 @@ const uint8_t GPS::_message_AID[] = {
// Turn off TEXT INFO Messages for all but M10 series
// B5 62 06 02 0A 00 01 00 00 00 03 03 00 03 03 00 1F 20
const uint8_t GPS::_message_DISABLE_TXT_INFO[] = {
static const uint8_t _message_DISABLE_TXT_INFO[] = {
0x01, // Protocol ID for NMEA
0x00, 0x00, 0x00, // Reserved
0x03, // I2C
@@ -310,7 +312,7 @@ const uint8_t GPS::_message_DISABLE_TXT_INFO[] = {
// and must be smaller than the period. It is only valid when the powerSetupValue is set to Interval; otherwise,
// it must be set to '0'.
// This command applies to M8 products
const uint8_t GPS::_message_PMS[] = {
static const uint8_t _message_PMS[] = {
0x00, // Version (0)
0x03, // Power setup value 3 = Agresssive 1Hz
0x00, 0x00, // period: not applicable, set to 0
@@ -318,14 +320,14 @@ const uint8_t GPS::_message_PMS[] = {
0x00, 0x00 // reserved, generated by u-center
};
const uint8_t GPS::_message_SAVE[] = {
static const uint8_t _message_SAVE[] = {
0x00, 0x00, 0x00, 0x00, // clearMask: no sections cleared
0xFF, 0xFF, 0x00, 0x00, // saveMask: save all sections
0x00, 0x00, 0x00, 0x00, // loadMask: no sections loaded
0x17 // deviceMask: BBR, Flash, EEPROM, and SPI Flash
};
const uint8_t GPS::_message_SAVE_10[] = {
static const uint8_t _message_SAVE_10[] = {
0x00, 0x00, 0x00, 0x00, // clearMask: no sections cleared
0xFF, 0xFF, 0x00, 0x00, // saveMask: save all sections
0x00, 0x00, 0x00, 0x00, // loadMask: no sections loaded
@@ -375,12 +377,12 @@ LIMITPEAKCURRENT L 1
// b5 62 06 8a 26 00 00 02 00 00 01 00 d0 20 02 02 00 d0 40 05 00 00 00 05 00 d0 30 01 00 08 00 d0 10 01 09 00 d0 10 01 10 00 d0
// 10 01 8c 03
*/
const uint8_t GPS::_message_VALSET_PM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40,
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0,
0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01};
const uint8_t GPS::_message_VALSET_PM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40,
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0,
0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01};
static const uint8_t _message_VALSET_PM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40,
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0,
0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01};
static const uint8_t _message_VALSET_PM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40,
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0,
0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01};
/*
CFG-ITFM replaced by 5 valset messages which can be combined into one for RAM and one for BBR
@@ -394,10 +396,10 @@ CFG-ITFM replaced by 5 valset messages which can be combined into one for RAM an
b5 62 06 8a 0e 00 00 01 00 00 0d 00 41 10 01 13 00 41 10 01 63 c6
*/
const uint8_t GPS::_message_VALSET_ITFM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x41,
0x10, 0x01, 0x13, 0x00, 0x41, 0x10, 0x01};
const uint8_t GPS::_message_VALSET_ITFM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x0d, 0x00, 0x41,
0x10, 0x01, 0x13, 0x00, 0x41, 0x10, 0x01};
static const uint8_t _message_VALSET_ITFM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x41,
0x10, 0x01, 0x13, 0x00, 0x41, 0x10, 0x01};
static const uint8_t _message_VALSET_ITFM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x0d, 0x00, 0x41,
0x10, 0x01, 0x13, 0x00, 0x41, 0x10, 0x01};
// Turn off all NMEA messages:
// Ram layer config message:
@@ -407,13 +409,13 @@ const uint8_t GPS::_message_VALSET_ITFM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x0d, 0
// BBR layer config message:
// b5 62 06 8a 13 00 00 02 00 00 ca 00 91 20 00 c5 00 91 20 00 b1 00 91 20 00 f8 4e
const uint8_t GPS::_message_VALSET_DISABLE_NMEA_RAM[] = {
static const uint8_t _message_VALSET_DISABLE_NMEA_RAM[] = {
/*0x00, 0x01, 0x00, 0x00, 0xca, 0x00, 0x91, 0x20, 0x00, 0xc5, 0x00, 0x91, 0x20, 0x00, 0xb1, 0x00, 0x91, 0x20, 0x00 */
0x00, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x91, 0x20, 0x00, 0xca, 0x00, 0x91, 0x20, 0x00, 0xc5, 0x00, 0x91,
0x20, 0x00, 0xac, 0x00, 0x91, 0x20, 0x00, 0xb1, 0x00, 0x91, 0x20, 0x00, 0xbb, 0x00, 0x91, 0x20, 0x00};
const uint8_t GPS::_message_VALSET_DISABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00, 0xca, 0x00, 0x91, 0x20, 0x00, 0xc5,
0x00, 0x91, 0x20, 0x00, 0xb1, 0x00, 0x91, 0x20, 0x00};
static const uint8_t _message_VALSET_DISABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00, 0xca, 0x00, 0x91, 0x20, 0x00, 0xc5,
0x00, 0x91, 0x20, 0x00, 0xb1, 0x00, 0x91, 0x20, 0x00};
// Turn off text info messages:
// Ram layer config message:
@@ -432,17 +434,17 @@ const uint8_t GPS::_message_VALSET_DISABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00,
// b5 62 06 8a 0e 00 00 04 00 00 bb 00 91 20 01 ac 00 91 20 01 6d b6
// Doing this for the FLASH layer isn't really required since we save the config to flash later
const uint8_t GPS::_message_VALSET_DISABLE_TXT_INFO_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x07, 0x00, 0x92, 0x20, 0x03};
const uint8_t GPS::_message_VALSET_DISABLE_TXT_INFO_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x07, 0x00, 0x92, 0x20, 0x03};
static const uint8_t _message_VALSET_DISABLE_TXT_INFO_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x07, 0x00, 0x92, 0x20, 0x03};
static const uint8_t _message_VALSET_DISABLE_TXT_INFO_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x07, 0x00, 0x92, 0x20, 0x03};
const uint8_t GPS::_message_VALSET_ENABLE_NMEA_RAM[] = {0x00, 0x01, 0x00, 0x00, 0xbb, 0x00, 0x91,
0x20, 0x01, 0xac, 0x00, 0x91, 0x20, 0x01};
const uint8_t GPS::_message_VALSET_ENABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00, 0xbb, 0x00, 0x91,
0x20, 0x01, 0xac, 0x00, 0x91, 0x20, 0x01};
const uint8_t GPS::_message_VALSET_DISABLE_SBAS_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x31,
0x10, 0x00, 0x05, 0x00, 0x31, 0x10, 0x00};
const uint8_t GPS::_message_VALSET_DISABLE_SBAS_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x31,
0x10, 0x00, 0x05, 0x00, 0x31, 0x10, 0x00};
static const uint8_t _message_VALSET_ENABLE_NMEA_RAM[] = {0x00, 0x01, 0x00, 0x00, 0xbb, 0x00, 0x91,
0x20, 0x01, 0xac, 0x00, 0x91, 0x20, 0x01};
static const uint8_t _message_VALSET_ENABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00, 0xbb, 0x00, 0x91,
0x20, 0x01, 0xac, 0x00, 0x91, 0x20, 0x01};
static const uint8_t _message_VALSET_DISABLE_SBAS_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x31,
0x10, 0x00, 0x05, 0x00, 0x31, 0x10, 0x00};
static const uint8_t _message_VALSET_DISABLE_SBAS_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x31,
0x10, 0x00, 0x05, 0x00, 0x31, 0x10, 0x00};
/*
Operational issues with the M10:
@@ -462,7 +464,7 @@ the PM config. Lets try without it.
PMREQ sort of works with SBAS, but the awake time is too short to re-acquire any SBAS sats.
The defination of "Got Fix" doesn't seem to include SBAS. Much more too this...
Even if it was, it can take minutes (up to 12.5),
even under good sat visability conditions to re-acquire the SBAS data.
even under good sat visibility conditions to re-acquire the SBAS data.
Another effect fo the quick transition to sleep is that no other sats will be acquired so the
sat count will tend to remain at what the initial fix was.
@@ -475,4 +477,4 @@ b5 62 06 8a 0e 00 00 01 00 00 20 00 31 10 00 05 00 31 10 00 46 87
BBR layer config message:
b5 62 06 8a 0e 00 00 02 00 00 20 00 31 10 00 05 00 31 10 00 47 94
*/
*/

View File

@@ -79,7 +79,7 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
}
// Trigger the refresh in GxEPD2
LOG_DEBUG("Updating E-Paper");
LOG_DEBUG("Update E-Paper");
adafruitDisplay->nextPage();
// End the update process
@@ -123,7 +123,7 @@ void EInkDisplay::setDetected(uint8_t detected)
// Connect to the display - variant specific
bool EInkDisplay::connect()
{
LOG_INFO("Doing EInk init");
LOG_INFO("Do EInk init");
#ifdef PIN_EINK_EN
// backlight power, HIGH is backlight on, LOW is off

View File

@@ -119,7 +119,7 @@ void EInkDynamicDisplay::endOrDetach()
awaitRefresh();
else {
// Async begins
LOG_DEBUG("Async full-refresh begins (dropping frames)");
LOG_DEBUG("Async full-refresh begins (drop frames)");
notifyLater(intervalPollAsyncRefresh, DUE_POLL_ASYNCREFRESH, true); // Hand-off to NotifiedWorkerThread
}
}
@@ -170,7 +170,7 @@ bool EInkDynamicDisplay::determineMode()
checkFastRequested();
if (refresh == UNSPECIFIED)
LOG_WARN("There was a flaw in the determineMode() logic.");
LOG_WARN("There was a flaw in the determineMode() logic");
// -- Decision has been reached --
applyRefreshMode();
@@ -469,7 +469,7 @@ void EInkDynamicDisplay::joinAsyncRefresh()
if (!asyncRefreshRunning)
return;
LOG_DEBUG("Joining an async refresh in progress");
LOG_DEBUG("Join an async refresh in progress");
// Continually poll the BUSY pin
while (adafruitDisplay->epd2.isBusy())

View File

@@ -20,7 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Screen.h"
#include "../userPrefs.h"
#include "PowerMon.h"
#include "Throttle.h"
#include "configuration.h"
@@ -101,9 +100,9 @@ std::vector<MeshModule *> moduleFrames;
static char ourId[5];
// vector where symbols (string) are displayed in bottom corner of display.
std::vector<std::string> functionSymbals;
// string displayed in bottom right corner of display. Created from elements in functionSymbals vector
std::string functionSymbalString = "";
std::vector<std::string> functionSymbol;
// string displayed in bottom right corner of display. Created from elements in functionSymbol vector
std::string functionSymbolString = "";
#if HAS_GPS
// GeoCoord object for the screen
@@ -242,11 +241,11 @@ static void drawWelcomeScreen(OLEDDisplay *display, OLEDDisplayUiState *state, i
// draw overlay in bottom right corner of screen to show when notifications are muted or modifier key is active
static void drawFunctionOverlay(OLEDDisplay *display, OLEDDisplayUiState *state)
{
// LOG_DEBUG("Drawing function overlay");
if (functionSymbals.begin() != functionSymbals.end()) {
// LOG_DEBUG("Draw function overlay");
if (functionSymbol.begin() != functionSymbol.end()) {
char buf[64];
display->setFont(FONT_SMALL);
snprintf(buf, sizeof(buf), "%s", functionSymbalString.c_str());
snprintf(buf, sizeof(buf), "%s", functionSymbolString.c_str());
display->drawString(SCREEN_WIDTH - display->getStringWidth(buf), SCREEN_HEIGHT - FONT_HEIGHT_SMALL, buf);
}
}
@@ -260,7 +259,7 @@ static void drawDeepSleepScreen(OLEDDisplay *display, OLEDDisplayUiState *state,
EINK_ADD_FRAMEFLAG(display, COSMETIC);
EINK_ADD_FRAMEFLAG(display, BLOCKING);
LOG_DEBUG("Drawing deep sleep screen");
LOG_DEBUG("Draw deep sleep screen");
// Display displayStr on the screen
drawIconScreen("Sleeping", display, state, x, y);
@@ -269,7 +268,7 @@ static void drawDeepSleepScreen(OLEDDisplay *display, OLEDDisplayUiState *state,
/// Used on eink displays when screen updates are paused
static void drawScreensaverOverlay(OLEDDisplay *display, OLEDDisplayUiState *state)
{
LOG_DEBUG("Drawing screensaver overlay");
LOG_DEBUG("Draw screensaver overlay");
EINK_ADD_FRAMEFLAG(display, COSMETIC); // Take the opportunity for a full-refresh
@@ -337,7 +336,7 @@ static void drawModuleFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int
module_frame = state->currentFrame;
// LOG_DEBUG("Screen is not in transition. Frame: %d", module_frame);
}
// LOG_DEBUG("Drawing Module Frame %d", module_frame);
// LOG_DEBUG("Draw Module Frame %d", module_frame);
MeshModule &pi = *moduleFrames.at(module_frame);
pi.drawFrame(display, state, x, y);
}
@@ -396,7 +395,7 @@ static void drawBattery(OLEDDisplay *display, int16_t x, int16_t y, uint8_t *img
display->drawFastImage(x, y, 16, 8, imgBuffer);
}
#ifdef T_WATCH_S3
#if defined(DISPLAY_CLOCK_FRAME)
void Screen::drawWatchFaceToggleButton(OLEDDisplay *display, int16_t x, int16_t y, bool digitalMode, float scale)
{
@@ -912,7 +911,7 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
const meshtastic_MeshPacket &mp = devicestate.rx_text_message;
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(getFrom(&mp));
// LOG_DEBUG("drawing text message from 0x%x: %s", mp.from,
// LOG_DEBUG("Draw text message from 0x%x: %s", mp.from,
// mp.decoded.variant.data.decoded.bytes);
// Demo for drawStringMaxWidth:
@@ -958,55 +957,65 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
display->setColor(WHITE);
#ifndef EXCLUDE_EMOJI
if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F44D") == 0) {
const char *msg = reinterpret_cast<const char *>(mp.decoded.payload.bytes);
if (strcmp(msg, "\U0001F44D") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - thumbs_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - thumbs_height) / 2 + 2 + 5, thumbs_width, thumbs_height,
thumbup);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F44E") == 0) {
} else if (strcmp(msg, "\U0001F44E") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - thumbs_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - thumbs_height) / 2 + 2 + 5, thumbs_width, thumbs_height,
thumbdown);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "") == 0) {
} else if (strcmp(msg, "\U0001F60A") == 0 || strcmp(msg, "\U0001F600") == 0 || strcmp(msg, "\U0001F642") == 0 ||
strcmp(msg, "\U0001F609") == 0 ||
strcmp(msg, "\U0001F601") == 0) { // matches 5 different common smileys, so that the phone user doesn't have to
// remember which one is compatible
display->drawXbm(x + (SCREEN_WIDTH - smiley_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - smiley_height) / 2 + 2 + 5, smiley_width, smiley_height,
smiley);
} else if (strcmp(msg, "") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - question_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - question_height) / 2 + 2 + 5, question_width, question_height,
question);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "‼️") == 0) {
} else if (strcmp(msg, "‼️") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - bang_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - bang_height) / 2 + 2 + 5,
bang_width, bang_height, bang);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F4A9") == 0) {
} else if (strcmp(msg, "\U0001F4A9") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - poo_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - poo_height) / 2 + 2 + 5,
poo_width, poo_height, poo);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\xf0\x9f\xa4\xa3") == 0) {
} else if (strcmp(msg, "\U0001F923") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - haha_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - haha_height) / 2 + 2 + 5,
haha_width, haha_height, haha);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F44B") == 0) {
} else if (strcmp(msg, "\U0001F44B") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - wave_icon_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - wave_icon_height) / 2 + 2 + 5, wave_icon_width,
wave_icon_height, wave_icon);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F920") == 0) {
} else if (strcmp(msg, "\U0001F920") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - cowboy_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - cowboy_height) / 2 + 2 + 5, cowboy_width, cowboy_height,
cowboy);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F42D") == 0) {
} else if (strcmp(msg, "\U0001F42D") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - deadmau5_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - deadmau5_height) / 2 + 2 + 5, deadmau5_width, deadmau5_height,
deadmau5);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\xE2\x98\x80\xEF\xB8\x8F") == 0) {
} else if (strcmp(msg, "\xE2\x98\x80\xEF\xB8\x8F") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - sun_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - sun_height) / 2 + 2 + 5,
sun_width, sun_height, sun);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\u2614") == 0) {
} else if (strcmp(msg, "\u2614") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - rain_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - rain_height) / 2 + 2 + 10,
rain_width, rain_height, rain);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "☁️") == 0) {
} else if (strcmp(msg, "☁️") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - cloud_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - cloud_height) / 2 + 2 + 5, cloud_width, cloud_height, cloud);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "🌫️") == 0) {
} else if (strcmp(msg, "🌫️") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - fog_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - fog_height) / 2 + 2 + 5,
fog_width, fog_height, fog);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\xf0\x9f\x98\x88") == 0) {
} else if (strcmp(msg, "\U0001F608") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - devil_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - devil_height) / 2 + 2 + 5, devil_width, devil_height, devil);
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "♥️") == 0) {
} else if (strcmp(msg, "♥️") == 0 || strcmp(msg, "\U0001F9E1") == 0 || strcmp(msg, "\U00002763") == 0 ||
strcmp(msg, "\U00002764") == 0 || strcmp(msg, "\U0001F495") == 0 || strcmp(msg, "\U0001F496") == 0 ||
strcmp(msg, "\U0001F497") == 0 || strcmp(msg, "\U0001F496") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - heart_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - heart_height) / 2 + 2 + 5, heart_width, heart_height, heart);
} else {
@@ -1410,7 +1419,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
}
bool hasNodeHeading = false;
if (ourNode && (hasValidPosition(ourNode) || screen->hasHeading())) {
if (ourNode && (nodeDB->hasValidPosition(ourNode) || screen->hasHeading())) {
const meshtastic_PositionLite &op = ourNode->position;
float myHeading;
if (screen->hasHeading())
@@ -1419,7 +1428,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
myHeading = screen->estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i));
screen->drawCompassNorth(display, compassX, compassY, myHeading);
if (hasValidPosition(node)) {
if (nodeDB->hasValidPosition(node)) {
// display direction toward node
hasNodeHeading = true;
const meshtastic_PositionLite &p = node->position;
@@ -1499,7 +1508,7 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
#elif ARCH_PORTDUINO
if (settingsMap[displayPanel] != no_screen) {
LOG_DEBUG("Making TFTDisplay!");
LOG_DEBUG("Make TFTDisplay!");
dispdev = new TFTDisplay(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
} else {
@@ -1546,7 +1555,7 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
if (on != screenOn) {
if (on) {
LOG_INFO("Turning on screen");
LOG_INFO("Turn on screen");
powerMon->setState(meshtastic_PowerMon_State_Screen_On);
#ifdef T_WATCH_S3
PMU->enablePowerOutput(XPOWERS_ALDO2);
@@ -1581,7 +1590,7 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
// eInkScreensaver parameter is usually NULL (default argument), default frame used instead
setScreensaverFrames(einkScreensaver);
#endif
LOG_INFO("Turning off screen");
LOG_INFO("Turn off screen");
dispdev->displayOff();
#ifdef USE_ST7789
SPI1.end();
@@ -1789,7 +1798,7 @@ int32_t Screen::runOnce()
// serialSinceMsec adjusts for additional serial wait time during nRF52 bootup
static bool showingBootScreen = true;
if (showingBootScreen && (millis() > (logo_timeout + serialSinceMsec))) {
LOG_INFO("Done with boot screen...");
LOG_INFO("Done with boot screen");
stopBootScreen();
showingBootScreen = false;
}
@@ -1885,7 +1894,7 @@ int32_t Screen::runOnce()
EINK_ADD_FRAMEFLAG(dispdev, COSMETIC);
#endif
LOG_DEBUG("LastScreenTransition exceeded %ums transitioning to next frame", (millis() - lastScreenTransition));
LOG_DEBUG("LastScreenTransition exceeded %ums transition to next frame", (millis() - lastScreenTransition));
handleOnPress();
}
}
@@ -1921,7 +1930,7 @@ void Screen::drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiStat
void Screen::setSSLFrames()
{
if (address_found.address) {
// LOG_DEBUG("showing SSL frames");
// LOG_DEBUG("Show SSL frames");
static FrameCallback sslFrames[] = {drawSSLScreen};
ui->setFrames(sslFrames, 1);
ui->update();
@@ -1933,7 +1942,7 @@ void Screen::setSSLFrames()
void Screen::setWelcomeFrames()
{
if (address_found.address) {
// LOG_DEBUG("showing Welcome frames");
// LOG_DEBUG("Show Welcome frames");
static FrameCallback frames[] = {drawWelcomeScreen};
setFrameImmediateDraw(frames);
}
@@ -1999,7 +2008,7 @@ void Screen::setFrames(FrameFocus focus)
uint8_t originalPosition = ui->getUiState()->currentFrame;
FramesetInfo fsi; // Location of specific frames, for applying focus parameter
LOG_DEBUG("showing standard frames");
LOG_DEBUG("Show standard frames");
showingNormalScreen = true;
#ifdef USE_EINK
@@ -2012,7 +2021,7 @@ void Screen::setFrames(FrameFocus focus)
#endif
moduleFrames = MeshModule::GetMeshModulesWithUIFrames();
LOG_DEBUG("Showing %d module frames", moduleFrames.size());
LOG_DEBUG("Show %d module frames", moduleFrames.size());
#ifdef DEBUG_PORT
int totalFrameCount = MAX_NUM_NODES + NUM_EXTRA_FRAMES + moduleFrames.size();
LOG_DEBUG("Total frame count: %d", totalFrameCount);
@@ -2058,7 +2067,7 @@ void Screen::setFrames(FrameFocus focus)
focus = FOCUS_FAULT; // Change our "focus" parameter, to ensure we show the fault frame
}
#ifdef T_WATCH_S3
#if defined(DISPLAY_CLOCK_FRAME)
normalFrames[numframes++] = screen->digitalWatchFace ? &Screen::drawDigitalClockFrame : &Screen::drawAnalogClockFrame;
#endif
@@ -2094,7 +2103,7 @@ void Screen::setFrames(FrameFocus focus)
#endif
fsi.frameCount = numframes; // Total framecount is used to apply FOCUS_PRESERVE
LOG_DEBUG("Finished building frames. numframes: %d", numframes);
LOG_DEBUG("Finished build frames. numframes: %d", numframes);
ui->setFrames(normalFrames, numframes);
ui->enableAllIndicators();
@@ -2175,13 +2184,13 @@ void Screen::dismissCurrentFrame()
bool dismissed = false;
if (currentFrame == framesetInfo.positions.textMessage && devicestate.has_rx_text_message) {
LOG_INFO("Dismissing Text Message");
LOG_INFO("Dismiss Text Message");
devicestate.has_rx_text_message = false;
dismissed = true;
}
else if (currentFrame == framesetInfo.positions.waypoint && devicestate.has_rx_waypoint) {
LOG_DEBUG("Dismissing Waypoint");
LOG_DEBUG("Dismiss Waypoint");
devicestate.has_rx_waypoint = false;
dismissed = true;
}
@@ -2193,7 +2202,7 @@ void Screen::dismissCurrentFrame()
void Screen::handleStartFirmwareUpdateScreen()
{
LOG_DEBUG("showing firmware screen");
LOG_DEBUG("Show firmware screen");
showingNormalScreen = false;
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // E-Ink: Explicitly use fast-refresh for next frame
@@ -2242,24 +2251,24 @@ void Screen::decreaseBrightness()
/* TO DO: add little popup in center of screen saying what brightness level it is set to*/
}
void Screen::setFunctionSymbal(std::string sym)
void Screen::setFunctionSymbol(std::string sym)
{
if (std::find(functionSymbals.begin(), functionSymbals.end(), sym) == functionSymbals.end()) {
functionSymbals.push_back(sym);
functionSymbalString = "";
for (auto symbol : functionSymbals) {
functionSymbalString = symbol + " " + functionSymbalString;
if (std::find(functionSymbol.begin(), functionSymbol.end(), sym) == functionSymbol.end()) {
functionSymbol.push_back(sym);
functionSymbolString = "";
for (auto symbol : functionSymbol) {
functionSymbolString = symbol + " " + functionSymbolString;
}
setFastFramerate();
}
}
void Screen::removeFunctionSymbal(std::string sym)
void Screen::removeFunctionSymbol(std::string sym)
{
functionSymbals.erase(std::remove(functionSymbals.begin(), functionSymbals.end(), sym), functionSymbals.end());
functionSymbalString = "";
for (auto symbol : functionSymbals) {
functionSymbalString = symbol + " " + functionSymbalString;
functionSymbol.erase(std::remove(functionSymbol.begin(), functionSymbol.end(), sym), functionSymbol.end());
functionSymbolString = "";
for (auto symbol : functionSymbol) {
functionSymbolString = symbol + " " + functionSymbolString;
}
setFastFramerate();
}
@@ -2674,7 +2683,7 @@ int Screen::handleUIFrameEvent(const UIFrameEvent *event)
if (event->action == UIFrameEvent::Action::REGENERATE_FRAMESET)
setFrames(FOCUS_MODULE);
// Regenerate the frameset, while attempting to maintain focus on the current frame
// Regenerate the frameset, while Attempt to maintain focus on the current frame
else if (event->action == UIFrameEvent::Action::REGENERATE_FRAMESET_BACKGROUND)
setFrames(FOCUS_PRESERVE);
@@ -2689,7 +2698,7 @@ int Screen::handleUIFrameEvent(const UIFrameEvent *event)
int Screen::handleInputEvent(const InputEvent *event)
{
#ifdef T_WATCH_S3
#if defined(DISPLAY_CLOCK_FRAME)
// For the T-Watch, intercept touches to the 'toggle digital/analog watch face' button
uint8_t watchFaceFrame = error_code ? 1 : 0;
@@ -2747,4 +2756,4 @@ int Screen::handleAdminMessage(const meshtastic_AdminMessage *arg)
} // namespace graphics
#else
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
#endif // HAS_SCREEN
#endif // HAS_SCREEN

View File

@@ -1,5 +1,6 @@
#pragma once
#include "../userPrefs.h"
#include "configuration.h"
#include "detect/ScanI2C.h"
@@ -24,8 +25,8 @@ class Screen
void startFirmwareUpdateScreen() {}
void increaseBrightness() {}
void decreaseBrightness() {}
void setFunctionSymbal(std::string) {}
void removeFunctionSymbal(std::string) {}
void setFunctionSymbol(std::string) {}
void removeFunctionSymbol(std::string) {}
void startAlert(const char *) {}
void endAlert() {}
};
@@ -282,8 +283,8 @@ class Screen : public concurrency::OSThread
void increaseBrightness();
void decreaseBrightness();
void setFunctionSymbal(std::string sym);
void removeFunctionSymbal(std::string sym);
void setFunctionSymbol(std::string sym);
void removeFunctionSymbol(std::string sym);
/// Stops showing the boot screen.
void stopBootScreen() { enqueueCmd(ScreenCmd{.cmd = Cmd::STOP_BOOT_SCREEN}); }
@@ -327,10 +328,15 @@ class Screen : public concurrency::OSThread
SKIPREST = false;
return (uint8_t)ch;
}
case 0xC3: {
SKIPREST = false;
return (uint8_t)(ch | 0xC0);
}
}
// We want to strip out prefix chars for two-byte char formats
if (ch == 0xC2)
if (ch == 0xC2 || ch == 0xC3)
return (uint8_t)0;
#if defined(OLED_PL)
@@ -549,7 +555,7 @@ class Screen : public concurrency::OSThread
static void drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
#ifdef T_WATCH_S3
#if defined(DISPLAY_CLOCK_FRAME)
static void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
static void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
@@ -600,4 +606,4 @@ class Screen : public concurrency::OSThread
} // namespace graphics
#endif
#endif

View File

@@ -27,14 +27,22 @@
#define FONT_SMALL ArialMT_Plain_10_RU
#else
#ifdef OLED_UA
#define FONT_SMALL ArialMT_Plain_10_UA
#define FONT_SMALL ArialMT_Plain_10_UA // Height: 13
#else
#define FONT_SMALL ArialMT_Plain_10 // Height: 13
#endif
#endif
#endif
#ifdef OLED_UA
#define FONT_MEDIUM ArialMT_Plain_16_UA // Height: 19
#else
#define FONT_MEDIUM ArialMT_Plain_16 // Height: 19
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
#endif
#ifdef OLED_UA
#define FONT_LARGE ArialMT_Plain_24_UA // Height: 28
#else
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
#endif
#endif
#define _fontHeight(font) ((font)[1] + 1) // height is position 1

View File

@@ -823,7 +823,7 @@ void TFTDisplay::setDetected(uint8_t detected)
bool TFTDisplay::connect()
{
concurrency::LockGuard g(spiLock);
LOG_INFO("Doing TFT init");
LOG_INFO("Do TFT init");
#ifdef RAK14014
tft = new TFT_eSPI;
#else

File diff suppressed because it is too large Load Diff

View File

@@ -8,4 +8,6 @@
#endif
extern const uint8_t ArialMT_Plain_10_UA[] PROGMEM;
extern const uint8_t ArialMT_Plain_16_UA[] PROGMEM;
extern const uint8_t ArialMT_Plain_24_UA[] PROGMEM;
#endif

View File

@@ -14,7 +14,7 @@ const uint8_t imgUser[] PROGMEM = {0x3C, 0x42, 0x99, 0xA5, 0xA5, 0x99, 0x42, 0x3
const uint8_t imgPositionEmpty[] PROGMEM = {0x20, 0x30, 0x28, 0x24, 0x42, 0xFF};
const uint8_t imgPositionSolid[] PROGMEM = {0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF};
#ifdef T_WATCH_S3
#if defined(DISPLAY_CLOCK_FRAME)
const uint8_t bluetoothConnectedIcon[36] PROGMEM = {0xfe, 0x01, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0xe3, 0x1f,
0xf3, 0x3f, 0x33, 0x30, 0x33, 0x33, 0x33, 0x33, 0x03, 0x33, 0xff, 0x33,
0xfe, 0x31, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0x3f, 0xe0, 0x1f};
@@ -56,6 +56,16 @@ static unsigned char thumbdown[] PROGMEM = {
0x80, 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00,
};
#define smiley_height 30
#define smiley_width 30
static unsigned char smiley[] PROGMEM = {
0x00, 0xfe, 0x0f, 0x00, 0x80, 0x01, 0x30, 0x00, 0x40, 0x00, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x02,
0x08, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x10, 0x02, 0x0e, 0x0e, 0x10, 0x02, 0x09, 0x12, 0x10,
0x01, 0x09, 0x12, 0x20, 0x01, 0x0f, 0x1e, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20,
0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x81, 0x00, 0x20, 0x20,
0x82, 0x00, 0x20, 0x10, 0x02, 0x01, 0x10, 0x10, 0x04, 0x02, 0x08, 0x08, 0x04, 0xfc, 0x07, 0x08, 0x08, 0x00, 0x00, 0x04,
0x10, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x01, 0x40, 0x00, 0xc0, 0x00, 0x80, 0x01, 0x30, 0x00, 0x00, 0xfe, 0x0f, 0x00};
#define question_height 25
#define question_width 25
static unsigned char question[] PROGMEM = {

View File

@@ -116,7 +116,7 @@ void MPR121Keyboard::begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr)
void MPR121Keyboard::reset()
{
LOG_DEBUG("MPR121 Resetting...");
LOG_DEBUG("MPR121 Reset");
// Trigger a MPR121 Soft Reset
if (m_wire) {
m_wire->beginTransmission(m_addr);
@@ -132,7 +132,7 @@ void MPR121Keyboard::reset()
writeRegister(_MPR121_REG_ELECTRODE_CONFIG, 0x00);
delay(100);
LOG_DEBUG("MPR121 Configuring");
LOG_DEBUG("MPR121 Configure");
// Set touch release thresholds
for (uint8_t i = 0; i < 12; i++) {
// Set touch threshold
@@ -178,7 +178,7 @@ void MPR121Keyboard::reset()
writeRegister(_MPR121_REG_ELECTRODE_CONFIG,
ECR_CALIBRATION_TRACK_FROM_PARTIAL_FILTER | ECR_PROXIMITY_DETECTION_OFF | ECR_TOUCH_DETECTION_12CH);
delay(100);
LOG_DEBUG("MPR121 Running");
LOG_DEBUG("MPR121 Run");
state = Idle;
}

View File

@@ -1,6 +1,10 @@
#include "TouchScreenBase.h"
#include "main.h"
#if defined(RAK14014) && !defined(MESHTASTIC_EXCLUDE_CANNEDMESSAGES)
#include "modules/CannedMessageModule.h"
#endif
#ifndef TIME_LONG_PRESS
#define TIME_LONG_PRESS 400
#endif
@@ -102,12 +106,30 @@ int32_t TouchScreenBase::runOnce()
}
_touchedOld = touched;
#if defined RAK14014
// Speed up the processing speed of the keyboard in virtual keyboard mode
auto state = cannedMessageModule->getRunState();
if (state == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
if (_tapped) {
_tapped = false;
e.touchEvent = static_cast<char>(TOUCH_ACTION_TAP);
LOG_DEBUG("action TAP(%d/%d)\n", _last_x, _last_y);
}
} else {
if (_tapped && (time_t(millis()) - _start) > TIME_LONG_PRESS - 50) {
_tapped = false;
e.touchEvent = static_cast<char>(TOUCH_ACTION_TAP);
LOG_DEBUG("action TAP(%d/%d)\n", _last_x, _last_y);
}
}
#else
// fire TAP event when no 2nd tap occured within time
if (_tapped && (time_t(millis()) - _start) > TIME_LONG_PRESS - 50) {
_tapped = false;
e.touchEvent = static_cast<char>(TOUCH_ACTION_TAP);
LOG_DEBUG("action TAP(%d/%d)", _last_x, _last_y);
}
#endif
// fire LONG_PRESS event without the need for release
if (touched && (time_t(millis()) - _start) > TIME_LONG_PRESS) {

View File

@@ -11,7 +11,7 @@ void CardKbI2cImpl::init()
{
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) && !defined(I2C_NO_RESCAN)
if (cardkb_found.address == 0x00) {
LOG_DEBUG("Rescanning for I2C keyboard");
LOG_DEBUG("Rescan for I2C keyboard");
uint8_t i2caddr_scan[] = {CARDKB_ADDR, TDECK_KB_ADDR, BBQ10_KB_ADDR, MPR121_KB_ADDR};
uint8_t i2caddr_asize = 4;
auto i2cScanner = std::unique_ptr<ScanI2CTwoWire>(new ScanI2CTwoWire());
@@ -49,10 +49,11 @@ void CardKbI2cImpl::init()
kb_model = 0x00;
}
}
LOG_DEBUG("Keyboard Type: 0x%02x Model: 0x%02x Address: 0x%02x", kb_info.type, kb_model, cardkb_found.address);
if (cardkb_found.address == 0x00) {
disable();
return;
} else {
LOG_DEBUG("Keyboard Type: 0x%02x Model: 0x%02x Address: 0x%02x", kb_info.type, kb_model, cardkb_found.address);
}
}
#else

View File

@@ -34,7 +34,7 @@ int32_t KbI2cBase::runOnce()
switch (cardkb_found.port) {
case ScanI2C::WIRE1:
#if WIRE_INTERFACES_COUNT == 2
LOG_DEBUG("Using I2C Bus 1 (the second one)");
LOG_DEBUG("Use I2C Bus 1 (the second one)");
i2cBus = &Wire1;
if (cardkb_found.address == BBQ10_KB_ADDR) {
Q10keyboard.begin(BBQ10_KB_ADDR, &Wire1);
@@ -46,7 +46,7 @@ int32_t KbI2cBase::runOnce()
break;
#endif
case ScanI2C::WIRE:
LOG_DEBUG("Using I2C Bus 0 (the first one)");
LOG_DEBUG("Use I2C Bus 0 (the first one)");
i2cBus = &Wire;
if (cardkb_found.address == BBQ10_KB_ADDR) {
Q10keyboard.begin(BBQ10_KB_ADDR, &Wire);

View File

@@ -150,10 +150,6 @@ ScanI2C::DeviceAddress accelerometer_found = ScanI2C::ADDRESS_NONE;
// The I2C address of the RGB LED (if found)
ScanI2C::FoundDevice rgb_found = ScanI2C::FoundDevice(ScanI2C::DeviceType::NONE, ScanI2C::ADDRESS_NONE);
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
ATECCX08A atecc;
#endif
#ifdef T_WATCH_S3
Adafruit_DRV2605 drv;
#endif
@@ -328,7 +324,7 @@ void setup()
#ifdef PERIPHERAL_WARMUP_MS
// Some peripherals may require additional time to stabilize after power is connected
// e.g. I2C on Heltec Vision Master
LOG_INFO("Waiting for peripherals to stabilize");
LOG_INFO("Wait for peripherals to stabilize");
delay(PERIPHERAL_WARMUP_MS);
#endif
@@ -389,10 +385,10 @@ void setup()
Wire.begin(I2C_SDA, I2C_SCL);
#elif defined(ARCH_PORTDUINO)
if (settingsStrings[i2cdev] != "") {
LOG_INFO("Using %s as I2C device.", settingsStrings[i2cdev].c_str());
LOG_INFO("Use %s as I2C device", settingsStrings[i2cdev].c_str());
Wire.begin(settingsStrings[i2cdev].c_str());
} else {
LOG_INFO("No I2C device configured, skipping.");
LOG_INFO("No I2C device configured, Skip");
}
#elif HAS_WIRE
Wire.begin();
@@ -435,7 +431,7 @@ void setup()
// accessories
auto i2cScanner = std::unique_ptr<ScanI2CTwoWire>(new ScanI2CTwoWire());
#if HAS_WIRE
LOG_INFO("Scanning for i2c devices...");
LOG_INFO("Scan for i2c devices");
#endif
#if defined(I2C_SDA1) && defined(ARCH_RP2040)
@@ -460,7 +456,7 @@ void setup()
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE);
#elif defined(ARCH_PORTDUINO)
if (settingsStrings[i2cdev] != "") {
LOG_INFO("Scanning for i2c devices...");
LOG_INFO("Scan for i2c devices");
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE);
}
#elif HAS_WIRE
@@ -572,48 +568,37 @@ void setup()
LOG_DEBUG("acc_info = %i", acc_info.type);
#endif
#define STRING(S) #S
#define SCANNER_TO_SENSORS_MAP(SCANNER_T, PB_T) \
{ \
auto found = i2cScanner->find(SCANNER_T); \
if (found.type != ScanI2C::DeviceType::NONE) { \
nodeTelemetrySensorsMap[PB_T].first = found.address.address; \
nodeTelemetrySensorsMap[PB_T].second = i2cScanner->fetchI2CBus(found.address); \
LOG_DEBUG("found i2c sensor %s", STRING(PB_T)); \
} \
}
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BME_680, meshtastic_TelemetrySensorType_BME680)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BME_280, meshtastic_TelemetrySensorType_BME280)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BMP_280, meshtastic_TelemetrySensorType_BMP280)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BMP_3XX, meshtastic_TelemetrySensorType_BMP3XX)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BMP_085, meshtastic_TelemetrySensorType_BMP085)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA260, meshtastic_TelemetrySensorType_INA260)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA219, meshtastic_TelemetrySensorType_INA219)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA3221, meshtastic_TelemetrySensorType_INA3221)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MAX17048, meshtastic_TelemetrySensorType_MAX17048)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHT31, meshtastic_TelemetrySensorType_SHT31)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHTC3, meshtastic_TelemetrySensorType_SHTC3)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::LPS22HB, meshtastic_TelemetrySensorType_LPS22)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::QMC6310, meshtastic_TelemetrySensorType_QMC6310)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::QMI8658, meshtastic_TelemetrySensorType_QMI8658)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::QMC5883L, meshtastic_TelemetrySensorType_QMC5883L)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::HMC5883L, meshtastic_TelemetrySensorType_QMC5883L)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::PMSA0031, meshtastic_TelemetrySensorType_PMSA003I)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::RCWL9620, meshtastic_TelemetrySensorType_RCWL9620)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::VEML7700, meshtastic_TelemetrySensorType_VEML7700)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::TSL2591, meshtastic_TelemetrySensorType_TSL25911FN)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::OPT3001, meshtastic_TelemetrySensorType_OPT3001)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MLX90632, meshtastic_TelemetrySensorType_MLX90632)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MLX90614, meshtastic_TelemetrySensorType_MLX90614)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHT4X, meshtastic_TelemetrySensorType_SHT4X)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::AHT10, meshtastic_TelemetrySensorType_AHT10)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::DFROBOT_LARK, meshtastic_TelemetrySensorType_DFROBOT_LARK)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::ICM20948, meshtastic_TelemetrySensorType_ICM20948)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MAX30102, meshtastic_TelemetrySensorType_MAX30102)
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::BME_680, meshtastic_TelemetrySensorType_BME680);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::BME_280, meshtastic_TelemetrySensorType_BME280);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::BMP_280, meshtastic_TelemetrySensorType_BMP280);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::BMP_3XX, meshtastic_TelemetrySensorType_BMP3XX);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::BMP_085, meshtastic_TelemetrySensorType_BMP085);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::INA260, meshtastic_TelemetrySensorType_INA260);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::INA219, meshtastic_TelemetrySensorType_INA219);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::INA3221, meshtastic_TelemetrySensorType_INA3221);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MAX17048, meshtastic_TelemetrySensorType_MAX17048);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::SHT31, meshtastic_TelemetrySensorType_SHT31);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::SHTC3, meshtastic_TelemetrySensorType_SHTC3);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::LPS22HB, meshtastic_TelemetrySensorType_LPS22);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::QMC6310, meshtastic_TelemetrySensorType_QMC6310);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::QMI8658, meshtastic_TelemetrySensorType_QMI8658);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::QMC5883L, meshtastic_TelemetrySensorType_QMC5883L);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::HMC5883L, meshtastic_TelemetrySensorType_QMC5883L);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::PMSA0031, meshtastic_TelemetrySensorType_PMSA003I);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::RCWL9620, meshtastic_TelemetrySensorType_RCWL9620);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::VEML7700, meshtastic_TelemetrySensorType_VEML7700);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::TSL2591, meshtastic_TelemetrySensorType_TSL25911FN);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::OPT3001, meshtastic_TelemetrySensorType_OPT3001);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MLX90632, meshtastic_TelemetrySensorType_MLX90632);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MLX90614, meshtastic_TelemetrySensorType_MLX90614);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::SHT4X, meshtastic_TelemetrySensorType_SHT4X);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::AHT10, meshtastic_TelemetrySensorType_AHT10);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::DFROBOT_LARK, meshtastic_TelemetrySensorType_DFROBOT_LARK);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::ICM20948, meshtastic_TelemetrySensorType_ICM20948);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MAX30102, meshtastic_TelemetrySensorType_MAX30102);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::CGRADSENS, meshtastic_TelemetrySensorType_RADSENS);
i2cScanner.reset();
#endif
@@ -671,7 +656,7 @@ void setup()
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");
LOG_DEBUG("Tracker/Sensor: Skip start melody");
else
playStartMelody();
@@ -740,7 +725,7 @@ void setup()
// setup TZ prior to time actions.
#if !MESHTASTIC_EXCLUDE_TZ
LOG_DEBUG("Using compiled/slipstreamed %s", slipstreamTZString); // important, removing this clobbers our magic string
LOG_DEBUG("Use compiled/slipstreamed %s", slipstreamTZString); // important, removing this clobbers our magic string
if (*config.device.tzdef && config.device.tzdef[0] != 0) {
LOG_DEBUG("Saved TZ: %s ", config.device.tzdef);
setenv("TZ", config.device.tzdef, 1);
@@ -770,7 +755,7 @@ void setup()
if (gps) {
gpsStatus->observe(&gps->newStatus);
} else {
LOG_DEBUG("Running without GPS.");
LOG_DEBUG("Run without GPS");
}
}
}
@@ -783,7 +768,7 @@ void setup()
nodeStatus->observe(&nodeDB->newStatus);
#ifdef HAS_I2S
LOG_DEBUG("Starting audio thread");
LOG_DEBUG("Start audio thread");
audioThread = new AudioThread();
#endif
service = new MeshService();
@@ -830,63 +815,63 @@ void setup()
#ifdef ARCH_PORTDUINO
if (settingsMap[use_sx1262]) {
if (!rIf) {
LOG_DEBUG("Attempting to activate sx1262 radio on SPI port %s", settingsStrings[spidev].c_str());
LOG_DEBUG("Activate sx1262 radio on SPI port %s", settingsStrings[spidev].c_str());
LockingArduinoHal *RadioLibHAL =
new LockingArduinoHal(SPI, spiSettings, (settingsMap[ch341Quirk] ? settingsMap[busy] : RADIOLIB_NC));
rIf = new SX1262Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
settingsMap[busy]);
if (!rIf->init()) {
LOG_ERROR("Failed to find SX1262 radio");
LOG_WARN("No SX1262 radio");
delete rIf;
exit(EXIT_FAILURE);
} else {
LOG_INFO("SX1262 Radio init succeeded, using SX1262 radio");
LOG_INFO("SX1262 init success");
}
}
} else if (settingsMap[use_rf95]) {
if (!rIf) {
LOG_DEBUG("Attempting to activate rf95 radio on SPI port %s", settingsStrings[spidev].c_str());
LOG_DEBUG("Activate rf95 radio on SPI port %s", settingsStrings[spidev].c_str());
LockingArduinoHal *RadioLibHAL =
new LockingArduinoHal(SPI, spiSettings, (settingsMap[ch341Quirk] ? settingsMap[busy] : RADIOLIB_NC));
rIf = new RF95Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
settingsMap[busy]);
if (!rIf->init()) {
LOG_ERROR("Failed to find RF95 radio");
LOG_WARN("No RF95 radio");
delete rIf;
rIf = NULL;
exit(EXIT_FAILURE);
} else {
LOG_INFO("RF95 Radio init succeeded, using RF95 radio");
LOG_INFO("RF95 init success");
}
}
} else if (settingsMap[use_sx1280]) {
if (!rIf) {
LOG_DEBUG("Attempting to activate sx1280 radio on SPI port %s", settingsStrings[spidev].c_str());
LOG_DEBUG("Activate sx1280 radio on SPI port %s", settingsStrings[spidev].c_str());
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
rIf = new SX1280Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
settingsMap[busy]);
if (!rIf->init()) {
LOG_ERROR("Failed to find SX1280 radio");
LOG_WARN("No SX1280 radio");
delete rIf;
rIf = NULL;
exit(EXIT_FAILURE);
} else {
LOG_INFO("SX1280 Radio init succeeded, using SX1280 radio");
LOG_INFO("SX1280 init success");
}
}
} else if (settingsMap[use_sx1268]) {
if (!rIf) {
LOG_DEBUG("Attempting to activate sx1268 radio on SPI port %s", settingsStrings[spidev].c_str());
LOG_DEBUG("Activate sx1268 radio on SPI port %s", settingsStrings[spidev].c_str());
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
rIf = new SX1268Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
settingsMap[busy]);
if (!rIf->init()) {
LOG_ERROR("Failed to find SX1268 radio");
LOG_WARN("No SX1268 radio");
delete rIf;
rIf = NULL;
exit(EXIT_FAILURE);
} else {
LOG_INFO("SX1268 Radio init succeeded, using SX1268 radio");
LOG_INFO("SX1268 init success");
}
}
}
@@ -902,11 +887,11 @@ void setup()
if (!rIf) {
rIf = new STM32WLE5JCInterface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
if (!rIf->init()) {
LOG_WARN("Failed to find STM32WL radio");
LOG_WARN("No STM32WL radio");
delete rIf;
rIf = NULL;
} else {
LOG_INFO("STM32WL Radio init succeeded, using STM32WL radio");
LOG_INFO("STM32WL init success");
radioType = STM32WLx_RADIO;
}
}
@@ -916,11 +901,11 @@ void setup()
if (!rIf) {
rIf = new SimRadio;
if (!rIf->init()) {
LOG_WARN("Failed to find simulated radio");
LOG_WARN("No simulated radio");
delete rIf;
rIf = NULL;
} else {
LOG_INFO("Using SIMULATED radio!");
LOG_INFO("Use SIMULATED radio!");
radioType = SIM_RADIO;
}
}
@@ -930,11 +915,11 @@ void setup()
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");
LOG_WARN("No RF95 radio");
delete rIf;
rIf = NULL;
} else {
LOG_INFO("RF95 Radio init succeeded, using RF95 radio");
LOG_INFO("RF95 init success");
radioType = RF95_RADIO;
}
}
@@ -944,11 +929,11 @@ void setup()
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");
LOG_WARN("No SX1262 radio");
delete rIf;
rIf = NULL;
} else {
LOG_INFO("SX1262 Radio init succeeded, using SX1262 radio");
LOG_INFO("SX1262 init success");
radioType = SX1262_RADIO;
}
}
@@ -959,12 +944,12 @@ void setup()
// Try using the specified TCXO voltage
rIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
if (!rIf->init()) {
LOG_WARN("Failed to find SX1262 radio with TCXO, Vref %f V", tcxoVoltage);
LOG_WARN("No SX1262 radio with TCXO, Vref %f V", tcxoVoltage);
delete rIf;
rIf = NULL;
tcxoVoltage = 0; // if it fails, set the TCXO voltage to zero for the next attempt
} else {
LOG_WARN("SX1262 Radio init succeeded, TCXO, Vref %f V", tcxoVoltage);
LOG_WARN("SX1262 init success, TCXO, Vref %f V", tcxoVoltage);
radioType = SX1262_RADIO;
}
}
@@ -973,12 +958,12 @@ void setup()
// 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()) {
LOG_WARN("Failed to find SX1262 radio with XTAL, Vref %f V", tcxoVoltage);
LOG_WARN("No SX1262 radio with XTAL, Vref %f V", tcxoVoltage);
delete rIf;
rIf = NULL;
tcxoVoltage = SX126X_DIO3_TCXO_VOLTAGE; // if it fails, set the TCXO voltage back for the next radio search
} else {
LOG_INFO("SX1262 Radio init succeeded, XTAL, Vref %f V", tcxoVoltage);
LOG_INFO("SX1262 init success, XTAL, Vref %f V", tcxoVoltage);
radioType = SX1262_RADIO;
}
}
@@ -988,11 +973,11 @@ void setup()
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");
LOG_WARN("No SX1268 radio");
delete rIf;
rIf = NULL;
} else {
LOG_INFO("SX1268 Radio init succeeded, using SX1268 radio");
LOG_INFO("SX1268 init success");
radioType = SX1268_RADIO;
}
}
@@ -1002,11 +987,11 @@ void setup()
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");
LOG_WARN("No LLCC68 radio");
delete rIf;
rIf = NULL;
} else {
LOG_INFO("LLCC68 Radio init succeeded, using LLCC68 radio");
LOG_INFO("LLCC68 init success");
radioType = LLCC68_RADIO;
}
}
@@ -1016,11 +1001,11 @@ void setup()
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");
LOG_WARN("No LR1110 radio");
delete rIf;
rIf = NULL;
} else {
LOG_INFO("LR1110 Radio init succeeded, using LR1110 radio");
LOG_INFO("LR1110 init success");
radioType = LR1110_RADIO;
}
}
@@ -1030,11 +1015,11 @@ void setup()
if (!rIf) {
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");
LOG_WARN("No LR1120 radio");
delete rIf;
rIf = NULL;
} else {
LOG_INFO("LR1120 Radio init succeeded, using LR1120 radio");
LOG_INFO("LR1120 init success");
radioType = LR1120_RADIO;
}
}
@@ -1044,11 +1029,11 @@ void setup()
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");
LOG_WARN("No LR1121 radio");
delete rIf;
rIf = NULL;
} else {
LOG_INFO("LR1121 Radio init succeeded, using LR1121 radio");
LOG_INFO("LR1121 init success");
radioType = LR1121_RADIO;
}
}
@@ -1058,11 +1043,11 @@ void setup()
if (!rIf) {
rIf = new SX1280Interface(RadioLibHAL, SX128X_CS, SX128X_DIO1, SX128X_RESET, SX128X_BUSY);
if (!rIf->init()) {
LOG_WARN("Failed to find SX1280 radio");
LOG_WARN("No SX1280 radio");
delete rIf;
rIf = NULL;
} else {
LOG_INFO("SX1280 Radio init succeeded, using SX1280 radio");
LOG_INFO("SX1280 init success");
radioType = SX1280_RADIO;
}
}
@@ -1070,7 +1055,7 @@ void setup()
// check if the radio chip matches the selected region
if ((config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_LORA_24) && (!rIf->wideLora())) {
LOG_WARN("Radio chip does not support 2.4GHz LoRa. Reverting to unset.");
LOG_WARN("LoRa chip does not support 2.4GHz. Revert to unset");
config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_UNSET;
nodeDB->saveToDisk(SEGMENT_CONFIG);
if (!rIf->reconfigure()) {
@@ -1160,11 +1145,50 @@ extern meshtastic_DeviceMetadata getDeviceMetadata()
deviceMetadata.position_flags = config.position.position_flags;
deviceMetadata.hw_model = HW_VENDOR;
deviceMetadata.hasRemoteHardware = moduleConfig.remote_hardware.enabled;
deviceMetadata.excluded_modules = meshtastic_ExcludedModules_EXCLUDED_NONE;
#if MESHTASTIC_EXCLUDE_REMOTEHARDWARE
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_REMOTEHARDWARE_CONFIG;
#endif
#if MESHTASTIC_EXCLUDE_AUDIO
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_AUDIO_CONFIG;
#endif
#if !HAS_SCREEN || NO_EXT_GPIO
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_CANNEDMSG_CONFIG | meshtastic_ExcludedModules_EXTNOTIF_CONFIG;
#endif
// Only edge case here is if we apply this a device with built in Accelerometer and want to detect interrupts
// We'll have to macro guard against those targets potentially
#if NO_EXT_GPIO
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_DETECTIONSENSOR_CONFIG;
#endif
// If we don't have any GPIO and we don't have GPS, no purpose in having serial config
#if NO_EXT_GPIO && NO_GPS
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_SERIAL_CONFIG;
#endif
#ifndef ARCH_ESP32
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_PAXCOUNTER_CONFIG;
#endif
#if !defined(HAS_NCP5623) && !defined(RGBLED_RED) && !defined(HAS_NEOPIXEL) && !defined(UNPHONE) && !RAK_4631
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_AMBIENTLIGHTING_CONFIG;
#endif
#if !(MESHTASTIC_EXCLUDE_PKI)
deviceMetadata.hasPKC = true;
#endif
return deviceMetadata;
}
#if !MESHTASTIC_EXCLUDE_I2C
void scannerToSensorsMap(const std::unique_ptr<ScanI2CTwoWire> &i2cScanner, ScanI2C::DeviceType deviceType,
meshtastic_TelemetrySensorType sensorType)
{
auto found = i2cScanner->find(deviceType);
if (found.type != ScanI2C::DeviceType::NONE) {
nodeTelemetrySensorsMap[sensorType].first = found.address.address;
nodeTelemetrySensorsMap[sensorType].second = i2cScanner->fetchI2CBus(found.address);
}
}
#endif
#ifndef PIO_UNIT_TESTING
void loop()
{
@@ -1195,4 +1219,4 @@ void loop()
mainDelay.delay(delayMsec);
}
}
#endif
#endif

View File

@@ -10,9 +10,6 @@
#include "mesh/generated/meshtastic/telemetry.pb.h"
#include <SPI.h>
#include <map>
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#include <SparkFun_ATECCX08a_Arduino_Library.h>
#endif
#if defined(ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2)
#include "nimble/NimbleBluetooth.h"
extern NimbleBluetooth *nimbleBluetooth;
@@ -21,6 +18,9 @@ extern NimbleBluetooth *nimbleBluetooth;
#include "NRF52Bluetooth.h"
extern NRF52Bluetooth *nrf52Bluetooth;
#endif
#if !MESHTASTIC_EXCLUDE_I2C
#include "detect/ScanI2CTwoWire.h"
#endif
#if ARCH_PORTDUINO
extern HardwareSPI *DisplaySPI;
@@ -39,10 +39,6 @@ extern bool pmu_found;
extern bool isCharging;
extern bool isUSBPowered;
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
extern ATECCX08A atecc;
#endif
#ifdef T_WATCH_S3
#include <Adafruit_DRV2605.h>
extern Adafruit_DRV2605 drv;
@@ -84,6 +80,10 @@ extern bool pauseBluetoothLogging;
void nrf52Setup(), esp32Setup(), nrf52Loop(), esp32Loop(), rp2040Setup(), clearBonds(), enterDfuMode();
meshtastic_DeviceMetadata getDeviceMetadata();
#if !MESHTASTIC_EXCLUDE_I2C
void scannerToSensorsMap(const std::unique_ptr<ScanI2CTwoWire> &i2cScanner, ScanI2C::DeviceType deviceType,
meshtastic_TelemetrySensorType sensorType);
#endif
// We default to 4MHz SPI, SPI mode 0
extern SPISettings spiSettings;

View File

@@ -190,7 +190,7 @@ CryptoKey Channels::getKey(ChannelIndex chIndex)
k.length = channelSettings.psk.size;
if (k.length == 0) {
if (ch.role == meshtastic_Channel_Role_SECONDARY) {
LOG_DEBUG("Unset PSK for secondary channel %s. using primary key", ch.settings.name);
LOG_DEBUG("Unset PSK for secondary channel %s. use primary key", ch.settings.name);
k = getKey(primaryIndex);
} else {
LOG_WARN("User disabled encryption");
@@ -199,7 +199,7 @@ CryptoKey Channels::getKey(ChannelIndex chIndex)
// Convert the short single byte variants of psk into variant that can be used more generally
uint8_t pskIndex = k.bytes[0];
LOG_DEBUG("Expanding short PSK #%d", pskIndex);
LOG_DEBUG("Expand short PSK #%d", pskIndex);
if (pskIndex == 0)
k.length = 0; // Turn off encryption
else {
@@ -384,11 +384,11 @@ bool Channels::hasDefaultChannel()
bool Channels::decryptForHash(ChannelIndex chIndex, ChannelHash channelHash)
{
if (chIndex > getNumChannels() || getHash(chIndex) != channelHash) {
// LOG_DEBUG("Skipping channel %d (hash %x) due to invalid hash/index, want=%x", chIndex, getHash(chIndex),
// LOG_DEBUG("Skip channel %d (hash %x) due to invalid hash/index, want=%x", chIndex, getHash(chIndex),
// channelHash);
return false;
} else {
LOG_DEBUG("Using channel %d (hash 0x%x)", chIndex, channelHash);
LOG_DEBUG("Use channel %d (hash 0x%x)", chIndex, channelHash);
setCrypto(chIndex);
return true;
}
@@ -398,7 +398,7 @@ bool Channels::decryptForHash(ChannelIndex chIndex, ChannelHash channelHash)
*
* This method is called before encoding outbound packets
*
* @eturn the (0 to 255) hash for that channel - if no suitable channel could be found, return -1
* @return the (0 to 255) hash for that channel - if no suitable channel could be found, return -1
*/
int16_t Channels::setActiveByIndex(ChannelIndex channelIndex)
{

View File

@@ -18,7 +18,7 @@
*/
void CryptoEngine::generateKeyPair(uint8_t *pubKey, uint8_t *privKey)
{
LOG_DEBUG("Generating Curve25519 key pair...");
LOG_DEBUG("Generate Curve25519 keypair");
Curve25519::dh1(public_key, private_key);
memcpy(pubKey, public_key, sizeof(public_key));
memcpy(privKey, private_key, sizeof(private_key));
@@ -80,8 +80,8 @@ bool CryptoEngine::encryptCurve25519(uint32_t toNode, uint32_t fromNode, meshtas
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);
printBytes("Attempt encrypt with nonce: ", nonce, 13);
printBytes("Attempt encrypt with 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
memcpy((uint8_t *)(auth + 8), &extraNonceTmp,
@@ -117,8 +117,8 @@ bool CryptoEngine::decryptCurve25519(uint32_t fromNode, meshtastic_UserLite_publ
crypto->hash(shared_key, 32);
initNonce(fromNode, packetNum, extraNonce);
printBytes("Attempting decrypt using nonce: ", nonce, 13);
printBytes("Attempting decrypt using shared_key starting with: ", shared_key, 8);
printBytes("Attempt decrypt with nonce: ", nonce, 13);
printBytes("Attempt decrypt with shared_key starting with: ", shared_key, 8);
return aes_ccm_ad(shared_key, 32, nonce, 8, bytes, numBytes - 12, nullptr, 0, auth, bytesOut);
}
@@ -185,7 +185,7 @@ concurrency::Lock *cryptLock;
void CryptoEngine::setKey(const CryptoKey &k)
{
LOG_DEBUG("Using AES%d key!", k.length * 8);
LOG_DEBUG("Use AES%d key!", k.length * 8);
key = k;
}
@@ -249,4 +249,4 @@ void CryptoEngine::initNonce(uint32_t fromNode, uint64_t packetId, uint32_t extr
}
#ifndef HAS_CUSTOM_CRYPTO_ENGINE
CryptoEngine *crypto = new CryptoEngine;
#endif
#endif

View File

@@ -1,5 +1,6 @@
#include "Default.h"
#include "../userPrefs.h"
#include "meshUtils.h"
uint32_t Default::getConfiguredOrDefaultMs(uint32_t configuredInterval, uint32_t defaultInterval)
{
@@ -40,6 +41,10 @@ uint32_t Default::getConfiguredOrDefaultMsScaled(uint32_t configured, uint32_t d
if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER)
return getConfiguredOrDefaultMs(configured, defaultValue);
// Additionally if we're a tracker or sensor, we want priority to send position and telemetry
if (IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_SENSOR, meshtastic_Config_DeviceConfig_Role_TRACKER))
return getConfiguredOrDefaultMs(configured, defaultValue);
return getConfiguredOrDefaultMs(configured, defaultValue) * congestionScalingCoefficient(numOnlineNodes);
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include <NodeDB.h>
#include <cstdint>
#include <meshUtils.h>
#define ONE_DAY 24 * 60 * 60
#define ONE_MINUTE_MS 60 * 1000
#define THIRTY_SECONDS_MS 30 * 1000
@@ -18,7 +19,7 @@
#define default_node_info_broadcast_secs 3 * 60 * 60
#define default_neighbor_info_broadcast_secs 6 * 60 * 60
#define min_node_info_broadcast_secs 60 * 60 // No regular broadcasts of more than once an hour
#define min_neighbor_info_broadcast_secs 2 * 60 * 60
#define min_neighbor_info_broadcast_secs 4 * 60 * 60
#define default_mqtt_address "mqtt.meshtastic.org"
#define default_mqtt_username "meshdev"
@@ -41,12 +42,30 @@ class Default
private:
static float congestionScalingCoefficient(int numOnlineNodes)
{
if (numOnlineNodes <= 40) {
return 1.0; // No scaling for 40 or fewer nodes
// Increase frequency of broadcasts for small networks regardless of preset
if (numOnlineNodes <= 10) {
return 0.6;
} else if (numOnlineNodes <= 20) {
return 0.7;
} else if (numOnlineNodes <= 30) {
return 0.8;
} else if (numOnlineNodes <= 40) {
return 1.0;
} else {
// Sscaling based on number of nodes over 40
float throttlingFactor = 0.075;
if (config.lora.use_preset && config.lora.modem_preset == meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW)
throttlingFactor = 0.04;
else if (config.lora.use_preset && config.lora.modem_preset == meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST)
throttlingFactor = 0.02;
else if (config.lora.use_preset && config.lora.modem_preset == meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW)
throttlingFactor = 0.01;
else if (config.lora.use_preset &&
IS_ONE_OF(config.lora.modem_preset, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST,
meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO))
return 1.0; // Don't bother throttling for highest bandwidth presets
// Scaling up traffic based on number of nodes over 40
int nodesOverForty = (numOnlineNodes - 40);
return 1.0 + (nodesOverForty * 0.075); // Each number of online node scales by 0.075
return 1.0 + (nodesOverForty * throttlingFactor); // Each number of online node scales by 0.075 (default)
}
}
};

View File

@@ -21,7 +21,7 @@ ErrorCode FloodingRouter::send(meshtastic_MeshPacket *p)
bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
{
if (wasSeenRecently(p)) { // Note: this will also add a recent packet record
printPacket("Ignoring dupe incoming msg", p);
printPacket("Ignore dupe incoming msg", p);
rxDupe++;
if (config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER &&
config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) {
@@ -29,6 +29,17 @@ bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
if (Router::cancelSending(p->from, p->id))
txRelayCanceled++;
}
/* If the original transmitter is doing retransmissions (hopStart equals hopLimit) for a reliable transmission, e.g., when
the ACK got lost, we will handle the packet again to make sure it gets an ACK to its packet. */
bool isRepeated = p->hop_start > 0 && p->hop_start == p->hop_limit;
if (isRepeated) {
LOG_DEBUG("Repeated reliable tx");
if (!perhapsRebroadcast(p) && isToUs(p) && p->want_ack) {
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel, 0);
}
}
return true;
}
@@ -41,14 +52,8 @@ bool FloodingRouter::isRebroadcaster()
config.device.rebroadcast_mode != meshtastic_Config_DeviceConfig_RebroadcastMode_NONE;
}
void FloodingRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c)
bool FloodingRouter::perhapsRebroadcast(const meshtastic_MeshPacket *p)
{
bool isAckorReply = (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) && (p->decoded.request_id != 0);
if (isAckorReply && !isToUs(p) && !isBroadcast(p->to)) {
// do not flood direct message that is ACKed or replied to
LOG_DEBUG("Rxd an ACK/reply not for me, cancel rebroadcast.");
Router::cancelSending(p->to, p->decoded.request_id); // cancel rebroadcast for this DM
}
if (!isToUs(p) && (p->hop_limit > 0) && !isFromUs(p)) {
if (p->id != 0) {
if (isRebroadcaster()) {
@@ -63,17 +68,34 @@ void FloodingRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas
}
#endif
LOG_INFO("Rebroadcasting received floodmsg");
LOG_INFO("Rebroadcast received floodmsg");
// Note: we are careful to resend using the original senders node id
// We are careful not to call our hooked version of send() - because we don't want to check this again
Router::send(tosend);
return true;
} else {
LOG_DEBUG("Not rebroadcasting: Role = CLIENT_MUTE or Rebroadcast Mode = NONE");
LOG_DEBUG("No rebroadcast: Role = CLIENT_MUTE or Rebroadcast Mode = NONE");
}
} else {
LOG_DEBUG("Ignoring 0 id broadcast");
LOG_DEBUG("Ignore 0 id broadcast");
}
}
return false;
}
void FloodingRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c)
{
bool isAckorReply = (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) && (p->decoded.request_id != 0);
if (isAckorReply && !isToUs(p) && !isBroadcast(p->to)) {
// do not flood direct message that is ACKed or replied to
LOG_DEBUG("Rxd an ACK/reply not for me, cancel rebroadcast");
Router::cancelSending(p->to, p->decoded.request_id); // cancel rebroadcast for this DM
}
perhapsRebroadcast(p);
// handle the packet as normal
Router::sniffReceived(p, c);
}

View File

@@ -31,6 +31,10 @@ class FloodingRouter : public Router, protected PacketHistory
private:
bool isRebroadcaster();
/** Check if we should rebroadcast this packet, and do so if needed
* @return true if rebroadcasted */
bool perhapsRebroadcast(const meshtastic_MeshPacket *p);
public:
/**
* Constructor

View File

@@ -77,13 +77,13 @@ template <typename T> bool LR11x0Interface<T>::init()
#ifdef LR11X0_RF_SWITCH_SUBGHZ
pinMode(LR11X0_RF_SWITCH_SUBGHZ, OUTPUT);
digitalWrite(LR11X0_RF_SWITCH_SUBGHZ, getFreq() < 1e9 ? HIGH : LOW);
LOG_DEBUG("Setting RF0 switch to %s", getFreq() < 1e9 ? "SubGHz" : "2.4GHz");
LOG_DEBUG("Set RF0 switch to %s", getFreq() < 1e9 ? "SubGHz" : "2.4GHz");
#endif
#ifdef LR11X0_RF_SWITCH_2_4GHZ
pinMode(LR11X0_RF_SWITCH_2_4GHZ, OUTPUT);
digitalWrite(LR11X0_RF_SWITCH_2_4GHZ, getFreq() < 1e9 ? LOW : HIGH);
LOG_DEBUG("Setting RF1 switch to %s", getFreq() < 1e9 ? "SubGHz" : "2.4GHz");
LOG_DEBUG("Set RF1 switch to %s", getFreq() < 1e9 ? "SubGHz" : "2.4GHz");
#endif
int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage);
@@ -122,7 +122,7 @@ template <typename T> bool LR11x0Interface<T>::init()
if (dioAsRfSwitch) {
lora.setRfSwitchTable(rfswitch_dio_pins, rfswitch_table);
LOG_DEBUG("Setting DIO RF switch", res);
LOG_DEBUG("Set DIO RF switch", res);
}
if (res == RADIOLIB_ERR_NONE) {
@@ -161,11 +161,6 @@ template <typename T> bool LR11x0Interface<T>::reconfigure()
if (err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
// Hmm - seems to lower SNR when the signal levels are high. Leaving off for now...
// TODO: Confirm gain registers are okay now
// err = lora.setRxGain(true);
// assert(err == RADIOLIB_ERR_NONE);
err = lora.setSyncWord(syncWord);
assert(err == RADIOLIB_ERR_NONE);

View File

@@ -33,7 +33,7 @@ MeshModule::~MeshModule()
}
meshtastic_MeshPacket *MeshModule::allocAckNak(meshtastic_Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex,
uint8_t hopStart, uint8_t hopLimit)
uint8_t hopLimit)
{
meshtastic_Routing c = meshtastic_Routing_init_default;
@@ -50,7 +50,7 @@ meshtastic_MeshPacket *MeshModule::allocAckNak(meshtastic_Routing_Error err, Nod
p->priority = meshtastic_MeshPacket_Priority_ACK;
p->hop_limit = routingModule->getHopLimitForResponse(hopStart, hopLimit); // Flood ACK back to original sender
p->hop_limit = hopLimit; // Flood ACK back to original sender
p->to = to;
p->decoded.request_id = idFrom;
p->channel = chIndex;
@@ -151,7 +151,7 @@ void MeshModule::callModules(meshtastic_MeshPacket &mp, RxSource src)
// If the requester didn't ask for a response we might need to discard unused replies to prevent memory leaks
if (pi.myReply) {
LOG_DEBUG("Discarding an unneeded response");
LOG_DEBUG("Discard an unneeded response");
packetPool.release(pi.myReply);
pi.myReply = NULL;
}
@@ -168,7 +168,7 @@ void MeshModule::callModules(meshtastic_MeshPacket &mp, RxSource src)
if (isDecoded && mp.decoded.want_response && toUs) {
if (currentReply) {
printPacket("Sending response", currentReply);
printPacket("Send response", currentReply);
service->sendToMesh(currentReply);
currentReply = NULL;
} else if (mp.from != ourNodeNum && !ignoreRequest) {
@@ -181,8 +181,8 @@ void MeshModule::callModules(meshtastic_MeshPacket &mp, RxSource src)
// SECURITY NOTE! I considered sending back a different error code if we didn't find the psk (i.e. !isDecoded)
// but opted NOT TO. Because it is not a good idea to let remote nodes 'probe' to find out which PSKs were "good" vs
// bad.
routingModule->sendAckNak(meshtastic_Routing_Error_NO_RESPONSE, getFrom(&mp), mp.id, mp.channel, mp.hop_start,
mp.hop_limit);
routingModule->sendAckNak(meshtastic_Routing_Error_NO_RESPONSE, getFrom(&mp), mp.id, mp.channel,
routingModule->getHopLimitForResponse(mp.hop_start, mp.hop_limit));
}
}
@@ -295,4 +295,4 @@ bool MeshModule::isRequestingFocus()
} else
return false;
}
#endif
#endif

View File

@@ -40,7 +40,7 @@ struct UIFrameEvent {
enum Action {
REDRAW_ONLY, // Don't change which frames are show, just redraw, asap
REGENERATE_FRAMESET, // Regenerate (change? add? remove?) screen frames, honoring requestFocus()
REGENERATE_FRAMESET_BACKGROUND, // Regenerate screen frames, attempting to remain on the same frame throughout
REGENERATE_FRAMESET_BACKGROUND, // Regenerate screen frames, Attempt to remain on the same frame throughout
} action = REDRAW_ONLY;
// We might want to pass additional data inside this struct at some point
@@ -162,7 +162,7 @@ class MeshModule
virtual Observable<const UIFrameEvent *> *getUIFrameObservable() { return NULL; }
meshtastic_MeshPacket *allocAckNak(meshtastic_Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex,
uint8_t hopStart = 0, uint8_t hopLimit = 0);
uint8_t hopLimit = 0);
/// Send an error response for the specified packet.
meshtastic_MeshPacket *allocErrorResponse(meshtastic_Routing_Error err, const meshtastic_MeshPacket *p);

View File

@@ -13,6 +13,7 @@
#include "TypeConversions.h"
#include "main.h"
#include "mesh-pb-constants.h"
#include "meshUtils.h"
#include "modules/NodeInfoModule.h"
#include "modules/PositionModule.h"
#include "power.h"
@@ -78,17 +79,19 @@ int MeshService::handleFromRadio(const meshtastic_MeshPacket *mp)
powerFSM.trigger(EVENT_PACKET_FOR_PHONE); // Possibly keep the node from sleeping
nodeDB->updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio
bool isPreferredRebroadcaster =
IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_ROUTER, meshtastic_Config_DeviceConfig_Role_REPEATER);
if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag &&
mp->decoded.portnum == meshtastic_PortNum_TELEMETRY_APP && mp->decoded.request_id > 0) {
LOG_DEBUG("Received telemetry response. Skip sending our NodeInfo."); // because this potentially a Repeater which will
// ignore our request for its NodeInfo
LOG_DEBUG("Received telemetry response. Skip sending our NodeInfo"); // because this potentially a Repeater which will
// ignore our request for its NodeInfo
} else if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag && !nodeDB->getMeshNode(mp->from)->has_user &&
nodeInfoModule) {
LOG_INFO("Heard new node on channel %d, sending NodeInfo and asking for a response.", mp->channel);
nodeInfoModule && !isPreferredRebroadcaster && !nodeDB->isFull()) {
if (airTime->isTxAllowedChannelUtil(true)) {
LOG_INFO("Heard new node on ch. %d, send NodeInfo and ask for response", mp->channel);
nodeInfoModule->sendOurNodeInfo(mp->from, true, mp->channel);
} else {
LOG_DEBUG("Skip sending NodeInfo due to > 25 percent channel util.");
LOG_DEBUG("Skip sending NodeInfo > 25%% ch. util");
}
}
@@ -164,7 +167,7 @@ NodeNum MeshService::getNodenumFromRequestId(uint32_t request_id)
void MeshService::handleToRadio(meshtastic_MeshPacket &p)
{
#if defined(ARCH_PORTDUINO) && !HAS_RADIO
// Simulates device is receiving a packet via the LoRa chip
// Simulates device received a packet via the LoRa chip
if (p.decoded.portnum == meshtastic_PortNum_SIMULATOR_APP) {
// Simulator packet (=Compressed packet) is encapsulated in a MeshPacket, so need to unwrap first
meshtastic_Compressed scratch;
@@ -180,7 +183,7 @@ void MeshService::handleToRadio(meshtastic_MeshPacket &p)
// Switch the port from PortNum_SIMULATOR_APP back to the original PortNum
p.decoded.portnum = decoded->portnum;
} else
LOG_ERROR("Error decoding protobuf for simulator message!");
LOG_ERROR("Error decoding proto for simulator message!");
}
// Let SimRadio receive as if it did via its LoRa chip
SimRadio::instance->startReceive(&p);
@@ -222,7 +225,7 @@ ErrorCode MeshService::sendQueueStatusToPhone(const meshtastic_QueueStatus &qs,
copied->mesh_packet_id = mesh_packet_id;
if (toPhoneQueueStatusQueue.numFree() == 0) {
LOG_INFO("tophone queue status queue is full, discarding oldest");
LOG_INFO("tophone queue status queue is full, discard oldest");
meshtastic_QueueStatus *d = toPhoneQueueStatusQueue.dequeuePtr(0);
if (d)
releaseQueueStatusToPool(d);
@@ -252,9 +255,14 @@ void MeshService::sendToMesh(meshtastic_MeshPacket *p, RxSource src, bool ccToPh
LOG_DEBUG("Can't send status to phone");
}
if (res == ERRNO_OK && ccToPhone) { // Check if p is not released in case it couldn't be sent
if ((res == ERRNO_OK || res == ERRNO_SHOULD_RELEASE) && ccToPhone) { // Check if p is not released in case it couldn't be sent
sendToPhone(packetPool.allocCopy(*p));
}
// Router may ask us to release the packet if it wasn't sent
if (res == ERRNO_SHOULD_RELEASE) {
releaseToPool(p);
}
}
bool MeshService::trySendPosition(NodeNum dest, bool wantReplies)
@@ -263,17 +271,17 @@ bool MeshService::trySendPosition(NodeNum dest, bool wantReplies)
assert(node);
if (hasValidPosition(node)) {
if (nodeDB->hasValidPosition(node)) {
#if HAS_GPS && !MESHTASTIC_EXCLUDE_GPS
if (positionModule) {
LOG_INFO("Sending position ping to 0x%x, wantReplies=%d, channel=%d", dest, wantReplies, node->channel);
LOG_INFO("Send position ping to 0x%x, wantReplies=%d, channel=%d", dest, wantReplies, node->channel);
positionModule->sendOurPosition(dest, wantReplies, node->channel);
return true;
}
} else {
#endif
if (nodeInfoModule) {
LOG_INFO("Sending nodeinfo ping to 0x%x, wantReplies=%d, channel=%d", dest, wantReplies, node->channel);
LOG_INFO("Send nodeinfo ping to 0x%x, wantReplies=%d, channel=%d", dest, wantReplies, node->channel);
nodeInfoModule->sendOurNodeInfo(dest, wantReplies, node->channel);
}
}
@@ -298,12 +306,12 @@ void MeshService::sendToPhone(meshtastic_MeshPacket *p)
if (toPhoneQueue.numFree() == 0) {
if (p->decoded.portnum == meshtastic_PortNum_TEXT_MESSAGE_APP ||
p->decoded.portnum == meshtastic_PortNum_RANGE_TEST_APP) {
LOG_WARN("ToPhone queue is full, discarding oldest");
LOG_WARN("ToPhone queue is full, discard oldest");
meshtastic_MeshPacket *d = toPhoneQueue.dequeuePtr(0);
if (d)
releaseToPool(d);
} else {
LOG_WARN("ToPhone queue is full, dropping packet.");
LOG_WARN("ToPhone queue is full, drop packet");
releaseToPool(p);
fromNum++; // Make sure to notify observers in case they are reconnected so they can get the packets
return;
@@ -316,9 +324,9 @@ void MeshService::sendToPhone(meshtastic_MeshPacket *p)
void MeshService::sendMqttMessageToClientProxy(meshtastic_MqttClientProxyMessage *m)
{
LOG_DEBUG("Sending mqtt message on topic '%s' to client for proxy", m->topic);
LOG_DEBUG("Send mqtt message on topic '%s' to client for proxy", m->topic);
if (toPhoneMqttProxyQueue.numFree() == 0) {
LOG_WARN("MqttClientProxyMessagePool queue is full, discarding oldest");
LOG_WARN("MqttClientProxyMessagePool queue is full, discard oldest");
meshtastic_MqttClientProxyMessage *d = toPhoneMqttProxyQueue.dequeuePtr(0);
if (d)
releaseMqttClientProxyMessageToPool(d);
@@ -330,9 +338,9 @@ void MeshService::sendMqttMessageToClientProxy(meshtastic_MqttClientProxyMessage
void MeshService::sendClientNotification(meshtastic_ClientNotification *n)
{
LOG_DEBUG("Sending client notification to phone");
LOG_DEBUG("Send client notification to phone");
if (toPhoneClientNotificationQueue.numFree() == 0) {
LOG_WARN("ClientNotification queue is full, discarding oldest");
LOG_WARN("ClientNotification queue is full, discard oldest");
meshtastic_ClientNotification *d = toPhoneClientNotificationQueue.dequeuePtr(0);
if (d)
releaseClientNotificationToPool(d);
@@ -380,13 +388,13 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
pos = gps->p;
} else {
// The GPS has lost lock
#ifdef GPS_EXTRAVERBOSE
#ifdef GPS_DEBUG
LOG_DEBUG("onGPSchanged() - lost validLocation");
#endif
}
// Used fixed position if configured regardless of GPS lock
if (config.position.fixed_position) {
LOG_WARN("Using fixed position");
LOG_WARN("Use fixed position");
pos = TypeConversions::ConvertToPosition(node->position);
}
@@ -418,4 +426,4 @@ uint32_t MeshService::GetTimeSinceMeshPacket(const meshtastic_MeshPacket *mp)
delta = 0;
return delta;
}
}

View File

@@ -16,6 +16,7 @@ typedef uint32_t PacketId; // A packet sequence number
#define ERRNO_NO_INTERFACES 33
#define ERRNO_UNKNOWN 32 // pick something that doesn't conflict with RH_ROUTER_ERROR_UNABLE_TO_DELIVER
#define ERRNO_DISABLED 34 // the interface is disabled
#define ERRNO_SHOULD_RELEASE 35 // no error, but the packet should still be released
#define ID_COUNTER_MASK (UINT32_MAX >> 22) // mask to select the counter portion of the ID
/*

View File

@@ -61,6 +61,16 @@ meshtastic_LocalConfig config;
meshtastic_LocalModuleConfig moduleConfig;
meshtastic_ChannelFile channelFile;
#ifdef USERPREFS_USE_ADMIN_KEY_0
static unsigned char userprefs_admin_key_0[] = USERPREFS_USE_ADMIN_KEY_0;
#endif
#ifdef USERPREFS_USE_ADMIN_KEY_1
static unsigned char userprefs_admin_key_1[] = USERPREFS_USE_ADMIN_KEY_1;
#endif
#ifdef USERPREFS_USE_ADMIN_KEY_2
static unsigned char userprefs_admin_key_2[] = USERPREFS_USE_ADMIN_KEY_2;
#endif
bool meshtastic_DeviceState_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field)
{
if (ostream) {
@@ -105,7 +115,7 @@ static uint8_t ourMacAddr[6];
NodeDB::NodeDB()
{
LOG_INFO("Initializing NodeDB");
LOG_INFO("Init NodeDB");
loadFromDisk();
cleanupMeshDB();
@@ -114,7 +124,7 @@ NodeDB::NodeDB()
uint32_t channelFileCRC = crc32Buffer(&channelFile, sizeof(channelFile));
int saveWhat = 0;
bool hasUniqueId = false;
// bool hasUniqueId = false;
// Get device unique id
#if defined(ARCH_ESP32) && defined(ESP_EFUSE_OPTIONAL_UNIQUE_ID)
uint32_t unique_id[4];
@@ -182,7 +192,7 @@ NodeDB::NodeDB()
keygenSuccess = true;
}
} else {
LOG_INFO("Generating new PKI keys");
LOG_INFO("Generate new PKI keys");
crypto->generateKeyPair(config.security.public_key.bytes, config.security.private_key.bytes);
keygenSuccess = true;
}
@@ -219,7 +229,7 @@ NodeDB::NodeDB()
// If we are setup to broadcast on the default channel, ensure that the telemetry intervals are coerced to the minimum value
// of 30 minutes or more
if (channels.isDefaultChannel(channels.getPrimaryIndex())) {
LOG_DEBUG("Coercing telemetry to min of 30 minutes on defaults");
LOG_DEBUG("Coerce telemetry to min of 30 minutes on defaults");
moduleConfig.telemetry.device_update_interval = Default::getConfiguredOrMinimumValue(
moduleConfig.telemetry.device_update_interval, min_default_telemetry_interval_secs);
moduleConfig.telemetry.environment_update_interval = Default::getConfiguredOrMinimumValue(
@@ -231,6 +241,9 @@ NodeDB::NodeDB()
moduleConfig.telemetry.health_update_interval = Default::getConfiguredOrMinimumValue(
moduleConfig.telemetry.health_update_interval, min_default_telemetry_interval_secs);
}
// Ensure that the neighbor info update interval is coerced to the minimum
moduleConfig.neighbor_info.update_interval =
Default::getConfiguredOrMinimumValue(moduleConfig.neighbor_info.update_interval, min_neighbor_info_broadcast_secs);
if (devicestateCRC != crc32Buffer(&devicestate, sizeof(devicestate)))
saveWhat |= SEGMENT_DEVICESTATE;
@@ -243,6 +256,31 @@ NodeDB::NodeDB()
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_ENABLED;
config.position.gps_enabled = 0;
}
#ifdef USERPREFS_FIXED_GPS
if (myNodeInfo.reboot_count == 1) { // Check if First boot ever or after Factory Reset.
meshtastic_Position fixedGPS = meshtastic_Position_init_default;
#ifdef USERPREFS_FIXED_GPS_LAT
fixedGPS.latitude_i = (int32_t)(USERPREFS_FIXED_GPS_LAT * 1e7);
fixedGPS.has_latitude_i = true;
#endif
#ifdef USERPREFS_FIXED_GPS_LON
fixedGPS.longitude_i = (int32_t)(USERPREFS_FIXED_GPS_LON * 1e7);
fixedGPS.has_longitude_i = true;
#endif
#ifdef USERPREFS_FIXED_GPS_ALT
fixedGPS.altitude = USERPREFS_FIXED_GPS_ALT;
fixedGPS.has_altitude = true;
#endif
#if defined(USERPREFS_FIXED_GPS_LAT) && defined(USERPREFS_FIXED_GPS_LON)
fixedGPS.location_source = meshtastic_Position_LocSource_LOC_MANUAL;
config.has_position = true;
info->has_position = true;
info->position = TypeConversions::ConvertToPositionLite(fixedGPS);
nodeDB->setLocalPosition(fixedGPS);
config.position.fixed_position = true;
#endif
}
#endif
saveToDisk(saveWhat);
}
@@ -283,7 +321,7 @@ bool NodeDB::resetRadioConfig(bool factory_reset)
}
if (channelFile.channels_count != MAX_NUM_CHANNELS) {
LOG_INFO("Setting default channel and radio preferences!");
LOG_INFO("Set default channel and radio preferences!");
channels.initDefaults();
}
@@ -294,7 +332,7 @@ bool NodeDB::resetRadioConfig(bool factory_reset)
initRegion();
if (didFactoryReset) {
LOG_INFO("Rebooting due to factory reset");
LOG_INFO("Reboot due to factory reset");
screen->startAlert("Rebooting...");
rebootAtMsec = millis() + (5 * 1000);
}
@@ -304,7 +342,7 @@ bool NodeDB::resetRadioConfig(bool factory_reset)
bool NodeDB::factoryReset(bool eraseBleBonds)
{
LOG_INFO("Performing factory reset!");
LOG_INFO("Perform factory reset!");
// first, remove the "/prefs" (this removes most prefs)
rmDir("/prefs");
#ifdef FSCom
@@ -320,14 +358,14 @@ bool NodeDB::factoryReset(bool eraseBleBonds)
// third, write everything to disk
saveToDisk();
if (eraseBleBonds) {
LOG_INFO("Erasing BLE bonds");
LOG_INFO("Erase BLE bonds");
#ifdef ARCH_ESP32
// This will erase what's in NVS including ssl keys, persistent variables and ble pairing
nvs_flash_erase();
#endif
#ifdef ARCH_NRF52
Bluefruit.begin();
LOG_INFO("Clearing bluetooth bonds!");
LOG_INFO("Clear bluetooth bonds!");
bond_print_list(BLE_GAP_ROLE_PERIPH);
bond_print_list(BLE_GAP_ROLE_CENTRAL);
Bluefruit.Periph.clearBonds();
@@ -344,7 +382,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
if (shouldPreserveKey) {
memcpy(private_key_temp, config.security.private_key.bytes, config.security.private_key.size);
}
LOG_INFO("Installing default LocalConfig");
LOG_INFO("Install default LocalConfig");
memset(&config, 0, sizeof(meshtastic_LocalConfig));
config.version = DEVICESTATE_CUR_VER;
config.has_device = true;
@@ -378,11 +416,37 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
#else
config.lora.ignore_mqtt = false;
#endif
#ifdef USERPREFS_USE_ADMIN_KEY
memcpy(config.security.admin_key[0].bytes, USERPREFS_ADMIN_KEY, 32);
config.security.admin_key[0].size = 32;
config.security.admin_key_count = 1;
// Initialize admin_key_count to zero
byte numAdminKeys = 0;
#ifdef USERPREFS_USE_ADMIN_KEY_0
// Check if USERPREFS_ADMIN_KEY_0 is non-empty
if (sizeof(userprefs_admin_key_0) > 0) {
memcpy(config.security.admin_key[0].bytes, userprefs_admin_key_0, 32);
config.security.admin_key[0].size = 32;
numAdminKeys++;
}
#endif
#ifdef USERPREFS_USE_ADMIN_KEY_1
// Check if USERPREFS_ADMIN_KEY_1 is non-empty
if (sizeof(userprefs_admin_key_1) > 0) {
memcpy(config.security.admin_key[1].bytes, userprefs_admin_key_1, 32);
config.security.admin_key[1].size = 32;
numAdminKeys++;
}
#endif
#ifdef USERPREFS_USE_ADMIN_KEY_2
// Check if USERPREFS_ADMIN_KEY_2 is non-empty
if (sizeof(userprefs_admin_key_2) > 0) {
memcpy(config.security.admin_key[2].bytes, userprefs_admin_key_2, 32);
config.security.admin_key[2].size = 32;
numAdminKeys++;
}
#endif
config.security.admin_key_count = numAdminKeys;
if (shouldPreserveKey) {
config.security.private_key.size = 32;
memcpy(config.security.private_key.bytes, private_key_temp, config.security.private_key.size);
@@ -435,8 +499,13 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
#else
bool hasScreen = screen_found.port != ScanI2C::I2CPort::NO_I2C;
#endif
#ifdef USERPREFS_FIXED_BLUETOOTH
config.bluetooth.fixed_pin = USERPREFS_FIXED_BLUETOOTH;
config.bluetooth.mode = meshtastic_Config_BluetoothConfig_PairingMode_FIXED_PIN;
#else
config.bluetooth.mode = hasScreen ? meshtastic_Config_BluetoothConfig_PairingMode_RANDOM_PIN
: meshtastic_Config_BluetoothConfig_PairingMode_FIXED_PIN;
#endif
// for backward compat, default position flags are ALT+MSL
config.position.position_flags =
(meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE | meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE_MSL |
@@ -449,7 +518,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
#ifdef RAK4630
config.display.wake_on_tap_or_motion = true;
#endif
#ifdef T_WATCH_S3
#if defined(T_WATCH_S3) || defined(SENSECAP_INDICATOR)
config.display.screen_on_secs = 30;
config.display.wake_on_tap_or_motion = true;
#endif
@@ -473,7 +542,7 @@ void NodeDB::initConfigIntervals()
config.display.screen_on_secs = default_screen_on_secs;
#if defined(T_WATCH_S3) || defined(T_DECK)
#if defined(T_WATCH_S3) || defined(T_DECK) || defined(RAK14014)
config.power.is_power_saving = true;
config.display.screen_on_secs = 30;
config.power.wait_bluetooth_secs = 30;
@@ -482,7 +551,7 @@ void NodeDB::initConfigIntervals()
void NodeDB::installDefaultModuleConfig()
{
LOG_INFO("Installing default ModuleConfig");
LOG_INFO("Install default ModuleConfig");
memset(&moduleConfig, 0, sizeof(meshtastic_ModuleConfig));
moduleConfig.version = DEVICESTATE_CUR_VER;
@@ -617,7 +686,7 @@ void NodeDB::initModuleConfigIntervals()
void NodeDB::installDefaultChannels()
{
LOG_INFO("Installing default ChannelFile");
LOG_INFO("Install default ChannelFile");
memset(&channelFile, 0, sizeof(meshtastic_ChannelFile));
channelFile.version = DEVICESTATE_CUR_VER;
}
@@ -647,7 +716,7 @@ void NodeDB::removeNodeByNum(NodeNum nodeNum)
numMeshNodes -= removed;
std::fill(devicestate.node_db_lite.begin() + numMeshNodes, devicestate.node_db_lite.begin() + numMeshNodes + 1,
meshtastic_NodeInfoLite());
LOG_DEBUG("NodeDB::removeNodeByNum purged %d entries. Saving changes...", removed);
LOG_DEBUG("NodeDB::removeNodeByNum purged %d entries. Save changes", removed);
saveDeviceStateToDisk();
}
@@ -684,7 +753,7 @@ void NodeDB::cleanupMeshDB()
void NodeDB::installDefaultDeviceState()
{
LOG_INFO("Installing default DeviceState");
LOG_INFO("Install default DeviceState");
// memset(&devicestate, 0, sizeof(meshtastic_DeviceState));
numMeshNodes = 0;
@@ -742,7 +811,7 @@ void NodeDB::pickNewNodeNum()
nodeNum, found->user.macaddr[4], found->user.macaddr[5], ourMacAddr[4], ourMacAddr[5], candidate);
nodeNum = candidate;
}
LOG_DEBUG("Using nodenum 0x%x ", nodeNum);
LOG_DEBUG("Use nodenum 0x%x ", nodeNum);
myNodeInfo.my_node_num = nodeNum;
}
@@ -762,7 +831,7 @@ LoadFileResult NodeDB::loadProto(const char *filename, size_t protoSize, size_t
auto f = FSCom.open(filename, FILE_O_READ);
if (f) {
LOG_INFO("Loading %s", filename);
LOG_INFO("Load %s", filename);
pb_istream_t stream = {&readcb, &f, protoSize};
memset(dest_struct, 0, objSize);
@@ -790,8 +859,13 @@ void NodeDB::loadFromDisk()
0; // Mark the current device state as completely unusable, so that if we fail reading the entire file from
// disk we will still factoryReset to restore things.
#ifdef ARCH_ESP32
if (FSCom.exists("/static/static"))
rmDir("/static/static"); // Remove bad static web files bundle from initial 2.5.13 release
#endif
// static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM
auto state = loadProto(prefFileName, sizeof(meshtastic_DeviceState) + MAX_NUM_NODES * sizeof(meshtastic_NodeInfo),
auto state = loadProto(prefFileName, sizeof(meshtastic_DeviceState) + MAX_NUM_NODES_FS * sizeof(meshtastic_NodeInfo),
sizeof(meshtastic_DeviceState), &meshtastic_DeviceState_msg, &devicestate);
// See https://github.com/meshtastic/firmware/issues/4184#issuecomment-2269390786
@@ -803,13 +877,17 @@ void NodeDB::loadFromDisk()
// installDefaultDeviceState(); // Our in RAM copy might now be corrupt
//} else {
if (devicestate.version < DEVICESTATE_MIN_VER) {
LOG_WARN("Devicestate %d is old, discarding", devicestate.version);
LOG_WARN("Devicestate %d is old, discard", devicestate.version);
installDefaultDeviceState();
} else {
LOG_INFO("Loaded saved devicestate version %d, with nodecount: %d", devicestate.version, devicestate.node_db_lite.size());
meshNodes = &devicestate.node_db_lite;
numMeshNodes = devicestate.node_db_lite.size();
}
if (numMeshNodes > MAX_NUM_NODES) {
LOG_WARN("Node count %d exceeds MAX_NUM_NODES %d, truncating", numMeshNodes, MAX_NUM_NODES);
numMeshNodes = MAX_NUM_NODES;
}
meshNodes->resize(MAX_NUM_NODES);
state = loadProto(configFileName, meshtastic_LocalConfig_size, sizeof(meshtastic_LocalConfig), &meshtastic_LocalConfig_msg,
@@ -818,20 +896,68 @@ void NodeDB::loadFromDisk()
installDefaultConfig(); // Our in RAM copy might now be corrupt
} else {
if (config.version < DEVICESTATE_MIN_VER) {
LOG_WARN("config %d is old, discarding", config.version);
LOG_WARN("config %d is old, discard", config.version);
installDefaultConfig(true);
} else {
LOG_INFO("Loaded saved config version %d", config.version);
}
}
// Make sure we load hard coded admin keys even when the configuration file has none.
// Initialize admin_key_count to zero
byte numAdminKeys = 0;
uint16_t sum = 0;
#ifdef USERPREFS_USE_ADMIN_KEY_0
for (uint8_t b = 0; b < 32; b++) {
sum += config.security.admin_key[0].bytes[b];
}
if (sum == 0) {
numAdminKeys += 1;
LOG_INFO("Admin 0 key zero. Loading hard coded key from user preferences.");
memcpy(config.security.admin_key[0].bytes, userprefs_admin_key_0, 32);
config.security.admin_key[0].size = 32;
config.security.admin_key_count = numAdminKeys;
saveToDisk(SEGMENT_CONFIG);
}
#endif
#ifdef USERPREFS_USE_ADMIN_KEY_1
sum = 0;
for (uint8_t b = 0; b < 32; b++) {
sum += config.security.admin_key[1].bytes[b];
}
if (sum == 0) {
numAdminKeys += 1;
LOG_INFO("Admin 1 key zero. Loading hard coded key from user preferences.");
memcpy(config.security.admin_key[1].bytes, userprefs_admin_key_1, 32);
config.security.admin_key[1].size = 32;
config.security.admin_key_count = numAdminKeys;
saveToDisk(SEGMENT_CONFIG);
}
#endif
#ifdef USERPREFS_USE_ADMIN_KEY_2
sum = 0;
for (uint8_t b = 0; b < 32; b++) {
sum += config.security.admin_key[2].bytes[b];
}
if (sum == 0) {
numAdminKeys += 1;
LOG_INFO("Admin 2 key zero. Loading hard coded key from user preferences.");
memcpy(config.security.admin_key[2].bytes, userprefs_admin_key_2, 32);
config.security.admin_key[2].size = 32;
config.security.admin_key_count = numAdminKeys;
saveToDisk(SEGMENT_CONFIG);
}
#endif
state = loadProto(moduleConfigFileName, meshtastic_LocalModuleConfig_size, sizeof(meshtastic_LocalModuleConfig),
&meshtastic_LocalModuleConfig_msg, &moduleConfig);
if (state != LoadFileResult::LOAD_SUCCESS) {
installDefaultModuleConfig(); // Our in RAM copy might now be corrupt
} else {
if (moduleConfig.version < DEVICESTATE_MIN_VER) {
LOG_WARN("moduleConfig %d is old, discarding", moduleConfig.version);
LOG_WARN("moduleConfig %d is old, discard", moduleConfig.version);
installDefaultModuleConfig();
} else {
LOG_INFO("Loaded saved moduleConfig version %d", moduleConfig.version);
@@ -844,7 +970,7 @@ void NodeDB::loadFromDisk()
installDefaultChannels(); // Our in RAM copy might now be corrupt
} else {
if (channelFile.version < DEVICESTATE_MIN_VER) {
LOG_WARN("channelFile %d is old, discarding", channelFile.version);
LOG_WARN("channelFile %d is old, discard", channelFile.version);
installDefaultChannels();
} else {
LOG_INFO("Loaded saved channelFile version %d", channelFile.version);
@@ -883,7 +1009,7 @@ bool NodeDB::saveProto(const char *filename, size_t protoSize, const pb_msgdesc_
#ifdef FSCom
auto f = SafeFile(filename, fullAtomic);
LOG_INFO("Saving %s", filename);
LOG_INFO("Save %s", filename);
pb_ostream_t stream = {&writecb, static_cast<Print *>(&f), protoSize};
if (!pb_encode(&stream, fields, dest_struct)) {
@@ -976,7 +1102,7 @@ bool NodeDB::saveToDisk(int saveWhat)
bool success = saveToDiskNoRetry(saveWhat);
if (!success) {
LOG_ERROR("Failed to save to disk, retrying...");
LOG_ERROR("Failed to save to disk, retrying");
#ifdef ARCH_NRF52 // @geeksville is not ready yet to say we should do this on other platforms. See bug #4184 discussion
FSCom.format();
@@ -1126,7 +1252,7 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
// we copy the key into the incoming packet, to prevent overwrite
memcpy(p.public_key.bytes, info->user.public_key.bytes, 32);
} else {
LOG_INFO("Updating Node Pubkey!");
LOG_INFO("Update Node Pubkey!");
}
}
#endif
@@ -1141,7 +1267,7 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
}
if (nodeId != getNodeNum())
info->channel = channelIndex; // Set channel we need to use to reach this node (but don't set our own channel)
LOG_DEBUG("updating changed=%d user %s/%s, channel=%d", changed, info->user.long_name, info->user.short_name, info->channel);
LOG_DEBUG("Update changed=%d user %s/%s, channel=%d", changed, info->user.long_name, info->user.short_name, info->channel);
info->has_user = true;
if (changed) {
@@ -1149,10 +1275,14 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
powerFSM.trigger(EVENT_NODEDB_UPDATED);
notifyObservers(true); // Force an update whether or not our node counts have changed
// We just changed something about the user, store our DB
Throttle::execute(
&lastNodeDbSave, ONE_MINUTE_MS, []() { nodeDB->saveToDisk(SEGMENT_DEVICESTATE); },
[]() { LOG_DEBUG("Deferring NodeDB saveToDisk for now"); }); // since we saved less than a minute ago
// We just changed something about a User,
// store our DB unless we just did so less than a minute ago
if (!Throttle::isWithinTimespanMs(lastNodeDbSave, ONE_MINUTE_MS)) {
saveToDisk(SEGMENT_DEVICESTATE);
lastNodeDbSave = millis();
} else {
LOG_DEBUG("Defer NodeDB saveToDisk for now");
}
}
return changed;
@@ -1206,16 +1336,20 @@ meshtastic_NodeInfoLite *NodeDB::getMeshNode(NodeNum n)
return NULL;
}
// returns true if the maximum number of nodes is reached or we are running low on memory
bool NodeDB::isFull()
{
return (numMeshNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < MINIMUM_SAFE_FREE_HEAP);
}
/// Find a node in our DB, create an empty NodeInfo if missing
meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
{
meshtastic_NodeInfoLite *lite = getMeshNode(n);
if (!lite) {
if ((numMeshNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < MINIMUM_SAFE_FREE_HEAP)) {
if (screen)
screen->print("Warn: node database full!\nErasing oldest entry\n");
LOG_WARN("Node database full with %i nodes and %i bytes free! Erasing oldest entry", numMeshNodes,
if (isFull()) {
LOG_INFO("Node database full with %i nodes and %i bytes free. Erasing oldest entry", numMeshNodes,
memGet.getFreeHeap());
// look for oldest node and erase it
uint32_t oldest = UINT32_MAX;
@@ -1224,12 +1358,12 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
int oldestBoringIndex = -1;
for (int i = 1; i < numMeshNodes; i++) {
// Simply the oldest non-favorite node
if (!meshNodes->at(i).is_favorite && meshNodes->at(i).last_heard < oldest) {
if (!meshNodes->at(i).is_favorite && !meshNodes->at(i).is_ignored && meshNodes->at(i).last_heard < oldest) {
oldest = meshNodes->at(i).last_heard;
oldestIndex = i;
}
// The oldest "boring" node
if (!meshNodes->at(i).is_favorite && meshNodes->at(i).user.public_key.size == 0 &&
if (!meshNodes->at(i).is_favorite && !meshNodes->at(i).is_ignored && meshNodes->at(i).user.public_key.size == 0 &&
meshNodes->at(i).last_heard < oldestBoring) {
oldestBoring = meshNodes->at(i).last_heard;
oldestBoringIndex = i;
@@ -1257,6 +1391,13 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
return lite;
}
/// Sometimes we will have Position objects that only have a time, so check for
/// valid lat/lon
bool NodeDB::hasValidPosition(const meshtastic_NodeInfoLite *n)
{
return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0);
}
/// Record an error that should be reported via analytics
void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, const char *filename)
{
@@ -1265,9 +1406,9 @@ void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, co
if (screen)
screen->print(lcd.c_str());
if (filename) {
LOG_ERROR("NOTE! Recording critical error %d at %s:%lu", code, filename, address);
LOG_ERROR("NOTE! Record critical error %d at %s:%lu", code, filename, address);
} else {
LOG_ERROR("NOTE! Recording critical error %d, address=0x%lx", code, address);
LOG_ERROR("NOTE! Record critical error %d, address=0x%lx", code, address);
}
// Record error to DB
@@ -1276,7 +1417,7 @@ void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, co
// Currently portuino is mostly used for simulation. Make sure the user notices something really bad happened
#ifdef ARCH_PORTDUINO
LOG_ERROR("A critical failure occurred, portduino is exiting...");
LOG_ERROR("A critical failure occurred, portduino is exiting");
exit(2);
#endif
}

View File

@@ -147,21 +147,26 @@ class NodeDB
meshtastic_NodeInfoLite *getMeshNode(NodeNum n);
size_t getNumMeshNodes() { return numMeshNodes; }
// returns true if the maximum number of nodes is reached or we are running low on memory
bool isFull();
void clearLocalPosition();
void setLocalPosition(meshtastic_Position position, bool timeOnly = false)
{
if (timeOnly) {
LOG_DEBUG("Setting local position time only: time=%u timestamp=%u", position.time, position.timestamp);
LOG_DEBUG("Set local position time only: time=%u timestamp=%u", position.time, position.timestamp);
localPosition.time = position.time;
localPosition.timestamp = position.timestamp > 0 ? position.timestamp : position.time;
return;
}
LOG_DEBUG("Setting local position: lat=%i lon=%i time=%u timestamp=%u", position.latitude_i, position.longitude_i,
LOG_DEBUG("Set local position: lat=%i lon=%i time=%u timestamp=%u", position.latitude_i, position.longitude_i,
position.time, position.timestamp);
localPosition = position;
}
bool hasValidPosition(const meshtastic_NodeInfoLite *n);
private:
uint32_t lastNodeDbSave = 0; // when we last saved our db to flash
/// Find a node in our DB, create an empty NodeInfoLite if missing
@@ -214,13 +219,6 @@ extern NodeDB *nodeDB;
prefs.is_power_saving = True
*/
/// Sometimes we will have Position objects that only have a time, so check for
/// valid lat/lon
static inline bool hasValidPosition(const meshtastic_NodeInfoLite *n)
{
return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0);
}
/** The current change # for radio settings. Starts at 0 on boot and any time the radio settings
* might have changed is incremented. Allows others to detect they might now be on a new channel.
*/

View File

@@ -19,7 +19,7 @@ PacketHistory::PacketHistory()
bool PacketHistory::wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpdate)
{
if (p->id == 0) {
LOG_DEBUG("Ignoring message with zero id");
LOG_DEBUG("Ignore message with zero id");
return false; // Not a floodable message ID, so we don't care
}

View File

@@ -57,14 +57,14 @@ void PhoneAPI::handleStartConfig()
filesManifest = getFiles("/", 10);
LOG_DEBUG("Got %d files in manifest", filesManifest.size());
LOG_INFO("Starting API client config");
LOG_INFO("Start API client config");
nodeInfoForPhone.num = 0; // Don't keep returning old nodeinfos
resetReadIndex();
}
void PhoneAPI::close()
{
LOG_INFO("PhoneAPI::close()");
LOG_DEBUG("PhoneAPI::close()");
if (state != STATE_SEND_NOTHING) {
state = STATE_SEND_NOTHING;
@@ -122,7 +122,7 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
handleStartConfig();
break;
case meshtastic_ToRadio_disconnect_tag:
LOG_INFO("Disconnecting from phone");
LOG_INFO("Disconnect from phone");
close();
break;
case meshtastic_ToRadio_xmodemPacket_tag:
@@ -133,7 +133,7 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
break;
#if !MESHTASTIC_EXCLUDE_MQTT
case meshtastic_ToRadio_mqttClientProxyMessage_tag:
LOG_INFO("Got MqttClientProxy message");
LOG_DEBUG("Got MqttClientProxy message");
if (mqtt && moduleConfig.mqtt.proxy_to_client_enabled && moduleConfig.mqtt.enabled &&
(channels.anyMqttEnabled() || moduleConfig.mqtt.map_reporting_enabled)) {
mqtt->onClientProxyReceive(toRadioScratch.mqttClientProxyMessage);
@@ -148,11 +148,10 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
break;
default:
// Ignore nop messages
// LOG_DEBUG("Error: unexpected ToRadio variant");
break;
}
} else {
LOG_ERROR("Error: ignoring malformed toradio");
LOG_ERROR("Error: ignore malformed toradio");
}
return false;
@@ -179,7 +178,6 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
size_t PhoneAPI::getFromRadio(uint8_t *buf)
{
if (!available()) {
// LOG_DEBUG("getFromRadio=not available");
return 0;
}
// In case we send a FromRadio packet
@@ -188,14 +186,15 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
// Advance states as needed
switch (state) {
case STATE_SEND_NOTHING:
LOG_INFO("getFromRadio=STATE_SEND_NOTHING");
LOG_DEBUG("FromRadio=STATE_SEND_NOTHING");
break;
case STATE_SEND_MY_INFO:
LOG_INFO("getFromRadio=STATE_SEND_MY_INFO");
LOG_DEBUG("FromRadio=STATE_SEND_MY_INFO");
// If the user has specified they don't want our node to share its location, make sure to tell the phone
// app not to send locations on our behalf.
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_my_info_tag;
strncpy(myNodeInfo.pio_env, optstr(APP_ENV), sizeof(myNodeInfo.pio_env));
fromRadioScratch.my_info = myNodeInfo;
state = STATE_SEND_OWN_NODEINFO;
@@ -203,7 +202,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
break;
case STATE_SEND_OWN_NODEINFO: {
LOG_INFO("getFromRadio=STATE_SEND_OWN_NODEINFO");
LOG_DEBUG("Send My NodeInfo");
auto us = nodeDB->readNextMeshNode(readIndex);
if (us) {
nodeInfoForPhone = TypeConversions::ConvertToNodeInfo(us);
@@ -219,62 +218,70 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
}
case STATE_SEND_METADATA:
LOG_INFO("getFromRadio=STATE_SEND_METADATA");
LOG_DEBUG("Send device metadata");
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_metadata_tag;
fromRadioScratch.metadata = getDeviceMetadata();
state = STATE_SEND_CHANNELS;
break;
case STATE_SEND_CHANNELS:
LOG_INFO("getFromRadio=STATE_SEND_CHANNELS");
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_channel_tag;
fromRadioScratch.channel = channels.getByIndex(config_state);
config_state++;
// Advance when we have sent all of our Channels
if (config_state >= MAX_NUM_CHANNELS) {
LOG_DEBUG("Send channels %d", config_state);
state = STATE_SEND_CONFIG;
config_state = _meshtastic_AdminMessage_ConfigType_MIN + 1;
}
break;
case STATE_SEND_CONFIG:
LOG_INFO("getFromRadio=STATE_SEND_CONFIG");
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_config_tag;
switch (config_state) {
case meshtastic_Config_device_tag:
LOG_DEBUG("Send config: device");
fromRadioScratch.config.which_payload_variant = meshtastic_Config_device_tag;
fromRadioScratch.config.payload_variant.device = config.device;
break;
case meshtastic_Config_position_tag:
LOG_DEBUG("Send config: position");
fromRadioScratch.config.which_payload_variant = meshtastic_Config_position_tag;
fromRadioScratch.config.payload_variant.position = config.position;
break;
case meshtastic_Config_power_tag:
LOG_DEBUG("Send config: power");
fromRadioScratch.config.which_payload_variant = meshtastic_Config_power_tag;
fromRadioScratch.config.payload_variant.power = config.power;
fromRadioScratch.config.payload_variant.power.ls_secs = default_ls_secs;
break;
case meshtastic_Config_network_tag:
LOG_DEBUG("Send config: network");
fromRadioScratch.config.which_payload_variant = meshtastic_Config_network_tag;
fromRadioScratch.config.payload_variant.network = config.network;
break;
case meshtastic_Config_display_tag:
LOG_DEBUG("Send config: display");
fromRadioScratch.config.which_payload_variant = meshtastic_Config_display_tag;
fromRadioScratch.config.payload_variant.display = config.display;
break;
case meshtastic_Config_lora_tag:
LOG_DEBUG("Send config: lora");
fromRadioScratch.config.which_payload_variant = meshtastic_Config_lora_tag;
fromRadioScratch.config.payload_variant.lora = config.lora;
break;
case meshtastic_Config_bluetooth_tag:
LOG_DEBUG("Send config: bluetooth");
fromRadioScratch.config.which_payload_variant = meshtastic_Config_bluetooth_tag;
fromRadioScratch.config.payload_variant.bluetooth = config.bluetooth;
break;
case meshtastic_Config_security_tag:
LOG_DEBUG("Send config: security");
fromRadioScratch.config.which_payload_variant = meshtastic_Config_security_tag;
fromRadioScratch.config.payload_variant.security = config.security;
break;
case meshtastic_Config_sessionkey_tag:
LOG_DEBUG("Send config: sessionkey");
fromRadioScratch.config.which_payload_variant = meshtastic_Config_sessionkey_tag;
break;
default:
@@ -293,58 +300,70 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
break;
case STATE_SEND_MODULECONFIG:
LOG_INFO("getFromRadio=STATE_SEND_MODULECONFIG");
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_moduleConfig_tag;
switch (config_state) {
case meshtastic_ModuleConfig_mqtt_tag:
LOG_DEBUG("Send module config: mqtt");
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_mqtt_tag;
fromRadioScratch.moduleConfig.payload_variant.mqtt = moduleConfig.mqtt;
break;
case meshtastic_ModuleConfig_serial_tag:
LOG_DEBUG("Send module config: serial");
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_serial_tag;
fromRadioScratch.moduleConfig.payload_variant.serial = moduleConfig.serial;
break;
case meshtastic_ModuleConfig_external_notification_tag:
LOG_DEBUG("Send module config: ext notification");
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_external_notification_tag;
fromRadioScratch.moduleConfig.payload_variant.external_notification = moduleConfig.external_notification;
break;
case meshtastic_ModuleConfig_store_forward_tag:
LOG_DEBUG("Send module config: store forward");
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_store_forward_tag;
fromRadioScratch.moduleConfig.payload_variant.store_forward = moduleConfig.store_forward;
break;
case meshtastic_ModuleConfig_range_test_tag:
LOG_DEBUG("Send module config: range test");
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_range_test_tag;
fromRadioScratch.moduleConfig.payload_variant.range_test = moduleConfig.range_test;
break;
case meshtastic_ModuleConfig_telemetry_tag:
LOG_DEBUG("Send module config: telemetry");
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_telemetry_tag;
fromRadioScratch.moduleConfig.payload_variant.telemetry = moduleConfig.telemetry;
break;
case meshtastic_ModuleConfig_canned_message_tag:
LOG_DEBUG("Send module config: canned message");
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_canned_message_tag;
fromRadioScratch.moduleConfig.payload_variant.canned_message = moduleConfig.canned_message;
break;
case meshtastic_ModuleConfig_audio_tag:
LOG_DEBUG("Send module config: audio");
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_audio_tag;
fromRadioScratch.moduleConfig.payload_variant.audio = moduleConfig.audio;
break;
case meshtastic_ModuleConfig_remote_hardware_tag:
LOG_DEBUG("Send module config: remote hardware");
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_remote_hardware_tag;
fromRadioScratch.moduleConfig.payload_variant.remote_hardware = moduleConfig.remote_hardware;
break;
case meshtastic_ModuleConfig_neighbor_info_tag:
LOG_DEBUG("Send module config: neighbor info");
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_neighbor_info_tag;
fromRadioScratch.moduleConfig.payload_variant.neighbor_info = moduleConfig.neighbor_info;
break;
case meshtastic_ModuleConfig_detection_sensor_tag:
LOG_DEBUG("Send module config: detection sensor");
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_detection_sensor_tag;
fromRadioScratch.moduleConfig.payload_variant.detection_sensor = moduleConfig.detection_sensor;
break;
case meshtastic_ModuleConfig_ambient_lighting_tag:
LOG_DEBUG("Send module config: ambient lighting");
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_ambient_lighting_tag;
fromRadioScratch.moduleConfig.payload_variant.ambient_lighting = moduleConfig.ambient_lighting;
break;
case meshtastic_ModuleConfig_paxcounter_tag:
LOG_DEBUG("Send module config: paxcounter");
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_paxcounter_tag;
fromRadioScratch.moduleConfig.payload_variant.paxcounter = moduleConfig.paxcounter;
break;
@@ -362,7 +381,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
break;
case STATE_SEND_OTHER_NODEINFOS: {
LOG_INFO("getFromRadio=STATE_SEND_OTHER_NODEINFOS");
LOG_DEBUG("Send known nodes");
if (nodeInfoForPhone.num != 0) {
LOG_INFO("nodeinfo: num=0x%x, lastseen=%u, id=%s, name=%s", nodeInfoForPhone.num, nodeInfoForPhone.last_heard,
nodeInfoForPhone.user.id, nodeInfoForPhone.user.long_name);
@@ -371,7 +390,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
// Stay in current state until done sending nodeinfos
nodeInfoForPhone.num = 0; // We just consumed a nodeinfo, will need a new one next time
} else {
LOG_INFO("Done sending nodeinfos");
LOG_DEBUG("Done sending nodeinfo");
state = STATE_SEND_FILEMANIFEST;
// Go ahead and send that ID right now
return getFromRadio(buf);
@@ -380,7 +399,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
}
case STATE_SEND_FILEMANIFEST: {
LOG_INFO("getFromRadio=STATE_SEND_FILEMANIFEST");
LOG_DEBUG("FromRadio=STATE_SEND_FILEMANIFEST");
// last element
if (config_state == filesManifest.size()) { // also handles an empty filesManifest
config_state = 0;
@@ -403,7 +422,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
case STATE_SEND_PACKETS:
pauseBluetoothLogging = false;
// Do we have a message from the mesh or packet from the local device?
LOG_INFO("getFromRadio=STATE_SEND_PACKETS");
LOG_DEBUG("FromRadio=STATE_SEND_PACKETS");
if (queueStatusPacketForPhone) {
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_queueStatus_tag;
fromRadioScratch.queueStatus = *queueStatusPacketForPhone;
@@ -441,17 +460,16 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
// VERY IMPORTANT to not print debug messages while writing to fromRadioScratch - because we use that same buffer
// for logging (when we are encapsulating with protobufs)
// LOG_DEBUG("encoding toPhone packet to phone variant=%d, %d bytes", fromRadioScratch.which_payload_variant, numbytes);
return numbytes;
}
LOG_DEBUG("no FromRadio packet available");
LOG_DEBUG("No FromRadio packet available");
return 0;
}
void PhoneAPI::sendConfigComplete()
{
LOG_INFO("getFromRadio=STATE_SEND_COMPLETE_ID");
LOG_INFO("Config Send Complete");
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_config_complete_id_tag;
fromRadioScratch.config_complete_id = config_nonce;
config_nonce = 0;
@@ -551,7 +569,6 @@ bool PhoneAPI::available()
if (!packetForPhone)
packetForPhone = service->getForPhone();
hasPacket = !!packetForPhone;
// LOG_DEBUG("available hasPacket=%d", hasPacket);
return hasPacket;
}
default:
@@ -596,21 +613,24 @@ bool PhoneAPI::handleToRadioPacket(meshtastic_MeshPacket &p)
{
printPacket("PACKET FROM PHONE", &p);
// For use with the simulator, we should not ignore duplicate packets
#if !(defined(ARCH_PORTDUINO) && !HAS_RADIO)
if (p.id > 0 && wasSeenRecently(p.id)) {
LOG_DEBUG("Ignoring packet from phone, already seen recently");
LOG_DEBUG("Ignore packet from phone, already seen recently");
return false;
}
#endif
if (p.decoded.portnum == meshtastic_PortNum_TRACEROUTE_APP && lastPortNumToRadio[p.decoded.portnum] &&
Throttle::isWithinTimespanMs(lastPortNumToRadio[p.decoded.portnum], THIRTY_SECONDS_MS)) {
LOG_WARN("Rate limiting portnum %d", p.decoded.portnum);
LOG_WARN("Rate limit portnum %d", p.decoded.portnum);
sendNotification(meshtastic_LogRecord_Level_WARNING, p.id, "TraceRoute can only be sent once every 30 seconds");
meshtastic_QueueStatus qs = router->getQueueStatus();
service->sendQueueStatusToPhone(qs, 0, p.id);
return false;
} else if (p.decoded.portnum == meshtastic_PortNum_POSITION_APP && lastPortNumToRadio[p.decoded.portnum] &&
Throttle::isWithinTimespanMs(lastPortNumToRadio[p.decoded.portnum], FIVE_SECONDS_MS)) {
LOG_WARN("Rate limiting portnum %d", p.decoded.portnum);
LOG_WARN("Rate limit portnum %d", p.decoded.portnum);
meshtastic_QueueStatus qs = router->getQueueStatus();
service->sendQueueStatusToPhone(qs, 0, p.id);
// FIXME: Figure out why this continues to happen
@@ -629,11 +649,11 @@ int PhoneAPI::onNotify(uint32_t newValue)
// doesn't call this from idle)
if (state == STATE_SEND_PACKETS) {
LOG_INFO("Telling client we have new packets %u", newValue);
LOG_INFO("Tell client we have new packets %u", newValue);
onNowHasData(newValue);
} else {
LOG_DEBUG("(Client not yet interested in packets)");
}
return timeout ? -1 : 0; // If we timed out, MeshService should stop iterating through observers as we just removed one
}
}

View File

@@ -91,7 +91,7 @@ template <class T> class ProtobufModule : protected SinglePortModule
if (pb_decode_from_bytes(p.payload.bytes, p.payload.size, fields, &scratch)) {
decoded = &scratch;
} else {
LOG_ERROR("Error decoding protobuf module!");
LOG_ERROR("Error decoding proto module!");
// if we can't decode it, nobody can process it!
return ProcessMessage::STOP;
}
@@ -112,7 +112,7 @@ template <class T> class ProtobufModule : protected SinglePortModule
if (pb_decode_from_bytes(p.payload.bytes, p.payload.size, fields, &scratch)) {
decoded = &scratch;
} else {
LOG_ERROR("Error decoding protobuf module!");
LOG_ERROR("Error decoding proto module!");
// if we can't decode it, nobody can process it!
return;
}

View File

@@ -230,7 +230,7 @@ bool RF95Interface::reconfigure()
err = lora->setPreambleLength(preambleLength);
if (err != RADIOLIB_ERR_NONE)
LOG_ERROR(" RF95 setPreambleLength %s%d", radioLibErr, err);
LOG_ERROR("RF95 setPreambleLength %s%d", radioLibErr, err);
assert(err == RADIOLIB_ERR_NONE);
err = lora->setFrequency(getFreq());

View File

@@ -140,7 +140,7 @@ const RegionInfo regions[] = {
Philippines
433 - 434.7 MHz <10 mW erp, NTC approved device required
868 - 869.4 MHz <25 mW erp, NTC approved device required
915 - 918 MHz <250 mW EIRP, no external antennna allowed
915 - 918 MHz <250 mW EIRP, no external antenna allowed
https://github.com/meshtastic/firmware/issues/4948#issuecomment-2394926135
*/
@@ -346,7 +346,7 @@ bool RadioInterface::reconfigure()
bool RadioInterface::init()
{
LOG_INFO("Starting meshradio init...");
LOG_INFO("Start meshradio init");
configChangedObserver.observe(&service->configChanged);
preflightSleepObserver.observe(&preflightSleep);
@@ -494,7 +494,7 @@ void RadioInterface::applyModemConfig()
}
if ((myRegion->freqEnd - myRegion->freqStart) < bw / 1000) {
static const char *err_string = "Regional frequency range is smaller than bandwidth. Falling back to default preset.";
static const char *err_string = "Regional frequency range is smaller than bandwidth. Fall back to default preset";
LOG_ERROR(err_string);
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
@@ -578,7 +578,7 @@ void RadioInterface::limitPower()
maxPower = myRegion->powerLimit;
if ((power > maxPower) && !devicestate.owner.is_licensed) {
LOG_INFO("Lowering transmit power because of regulatory limits");
LOG_INFO("Lower transmit power because of regulatory limits");
power = maxPower;
}
@@ -598,11 +598,9 @@ size_t RadioInterface::beginSending(meshtastic_MeshPacket *p)
{
assert(!sendingPacket);
// LOG_DEBUG("sending queued packet on mesh (txGood=%d,rxGood=%d,rxBad=%d)", rf95.txGood(), rf95.rxGood(), rf95.rxBad());
// LOG_DEBUG("Send queued packet on mesh (txGood=%d,rxGood=%d,rxBad=%d)", rf95.txGood(), rf95.rxGood(), rf95.rxBad());
assert(p->which_payload_variant == meshtastic_MeshPacket_encrypted_tag); // It should have already been encoded by now
lastTxStart = millis();
radioBuffer.header.from = p->from;
radioBuffer.header.to = p->to;
radioBuffer.header.id = p->id;

View File

@@ -143,12 +143,12 @@ bool RadioLibInterface::receiveDetected(uint16_t irq, ulong syncWordHeaderValidF
} 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.");
LOG_DEBUG("Ignore false preamble detection");
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.");
LOG_DEBUG("Ignore false header detection");
return false;
}
}
@@ -171,7 +171,7 @@ ErrorCode RadioLibInterface::send(meshtastic_MeshPacket *p)
}
} else {
LOG_WARN("send - lora tx disabled because RegionCode_Unset");
LOG_WARN("send - lora tx disabled: Region unset");
packetPool.release(p);
return ERRNO_DISABLED;
}
@@ -186,9 +186,14 @@ ErrorCode RadioLibInterface::send(meshtastic_MeshPacket *p)
#endif
if (p->to == NODENUM_BROADCAST_NO_LORA) {
LOG_DEBUG("Drop no-LoRa pkt");
return ERRNO_SHOULD_RELEASE;
}
// Sometimes when testing it is useful to be able to never turn on the xmitter
#ifndef LORA_DISABLE_SENDING
printPacket("enqueuing for send", p);
printPacket("enqueue for send", p);
LOG_DEBUG("txGood=%d,txRelay=%d,rxGood=%d,rxBad=%d", txGood, txRelay, rxGood, rxBad);
ErrorCode res = txQueue.enqueue(p) ? ERRNO_OK : ERRNO_UNKNOWN;
@@ -200,7 +205,6 @@ ErrorCode RadioLibInterface::send(meshtastic_MeshPacket *p)
// set (random) transmit delay to let others reconfigure their radio,
// to avoid collisions and implement timing-based flooding
// LOG_DEBUG("Set random delay before transmitting.");
setTransmitDelay();
return res;
@@ -225,7 +229,7 @@ bool RadioLibInterface::canSleep()
{
bool res = txQueue.empty();
if (!res) { // only print debug messages if we are vetoing sleep
LOG_DEBUG("radio wait to sleep, txEmpty=%d", res);
LOG_DEBUG("Radio wait to sleep, txEmpty=%d", res);
}
return res;
}
@@ -255,37 +259,31 @@ void RadioLibInterface::onNotify(uint32_t notification)
case ISR_TX:
handleTransmitInterrupt();
startReceive();
// LOG_DEBUG("tx complete - starting timer");
startTransmitTimer();
break;
case ISR_RX:
handleReceiveInterrupt();
startReceive();
// LOG_DEBUG("rx complete - starting timer");
startTransmitTimer();
break;
case TRANSMIT_DELAY_COMPLETED:
// LOG_DEBUG("delay done");
// If we are not currently in receive mode, then restart the random delay (this can happen if the main thread
// has placed the unit into standby) FIXME, how will this work if the chipset is in sleep mode?
if (!txQueue.empty()) {
if (!canSendImmediately()) {
// LOG_DEBUG("Currently Rx/Tx-ing: set random delay");
setTransmitDelay(); // currently Rx/Tx-ing: reset random delay
} else {
if (isChannelActive()) { // check if there is currently a LoRa packet on the channel
// LOG_DEBUG("Channel is active, try receiving first.");
startReceive(); // try receiving this packet, afterwards we'll be trying to transmit again
startReceive(); // try receiving this packet, afterwards we'll be trying to transmit again
setTransmitDelay();
} else {
// Send any outgoing packets we have ready
// Send any outgoing packets we have ready as fast as possible to keep the time between channel scan and
// actual transmission as short as possible
meshtastic_MeshPacket *txp = txQueue.dequeue();
assert(txp);
bool isLoraTx = txp->to != NODENUM_BROADCAST_NO_LORA;
startSend(txp);
if (isLoraTx) {
bool sent = startSend(txp);
if (sent) {
// Packet has been sent, count it toward our TX airtime utilization.
uint32_t xmitMsec = getPacketTime(txp);
airTime->logAirtime(TX_LOG, xmitMsec);
@@ -293,7 +291,6 @@ void RadioLibInterface::onNotify(uint32_t notification)
}
}
} else {
// LOG_DEBUG("done with txqueue");
}
break;
default:
@@ -326,7 +323,6 @@ void RadioLibInterface::startTransmitTimer(bool withDelay)
// If we have work to do and the timer wasn't already scheduled, schedule it now
if (!txQueue.empty()) {
uint32_t delay = !withDelay ? 1 : getTxDelayMsec();
// LOG_DEBUG("xmit timer %d", delay);
notifyLater(delay, TRANSMIT_DELAY_COMPLETED, false); // This will implicitly enable
}
}
@@ -336,19 +332,17 @@ void RadioLibInterface::startTransmitTimerSNR(float snr)
// If we have work to do and the timer wasn't already scheduled, schedule it now
if (!txQueue.empty()) {
uint32_t delay = getTxDelayMsecWeighted(snr);
// LOG_DEBUG("xmit timer %d", delay);
notifyLater(delay, TRANSMIT_DELAY_COMPLETED, false); // This will implicitly enable
}
}
void RadioLibInterface::handleTransmitInterrupt()
{
// LOG_DEBUG("handling lora TX interrupt");
// This can be null if we forced the device to enter standby mode. In that case
// ignore the transmit interrupt
if (sendingPacket)
completeSending();
powerMon->clearState(meshtastic_PowerMon_State_Lora_TXOn); // But our transmitter is deffinitely off now
powerMon->clearState(meshtastic_PowerMon_State_Lora_TXOn); // But our transmitter is definitely off now
}
void RadioLibInterface::completeSending()
@@ -366,7 +360,6 @@ void RadioLibInterface::completeSending()
// We are done sending that packet, release it
packetPool.release(p);
// LOG_DEBUG("Done with send");
}
}
@@ -377,7 +370,7 @@ void RadioLibInterface::handleReceiveInterrupt()
// when this is called, we should be in receive mode - if we are not, just jump out instead of bombing. Possible Race
// Condition?
if (!isReceiving) {
LOG_ERROR("handleReceiveInterrupt called when not in receive mode, which shouldn't happen.");
LOG_ERROR("handleReceiveInterrupt called when not in rx mode, which shouldn't happen");
return;
}
@@ -390,7 +383,7 @@ void RadioLibInterface::handleReceiveInterrupt()
#ifndef DISABLE_WELCOME_UNSET
if (config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
LOG_WARN("recv - lora rx disabled because RegionCode_Unset");
LOG_WARN("lora rx disabled: Region unset");
airTime->logAirtime(RX_ALL_LOG, xmitMsec);
return;
}
@@ -403,7 +396,7 @@ void RadioLibInterface::handleReceiveInterrupt()
}
#endif
if (state != RADIOLIB_ERR_NONE) {
LOG_ERROR("ignoring received packet due to error=%d", state);
LOG_ERROR("Ignore received packet due to error=%d", state);
rxBad++;
airTime->logAirtime(RX_ALL_LOG, xmitMsec);
@@ -414,14 +407,14 @@ void RadioLibInterface::handleReceiveInterrupt()
// check for short packets
if (payloadLen < 0) {
LOG_WARN("ignoring received packet too short");
LOG_WARN("Ignore received packet too short");
rxBad++;
airTime->logAirtime(RX_ALL_LOG, xmitMsec);
} else {
rxGood++;
// altered packet with "from == 0" can do Remote Node Administration without permission
if (radioBuffer.header.from == 0) {
LOG_WARN("ignoring received packet without sender");
LOG_WARN("Ignore received packet without sender");
return;
}
@@ -476,15 +469,14 @@ void RadioLibInterface::setStandby()
}
/** start an immediate transmit */
void RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
bool RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
{
printPacket("Starting low level send", txp);
if (txp->to == NODENUM_BROADCAST_NO_LORA) {
LOG_DEBUG("Drop Tx packet because dest is broadcast no-lora");
packetPool.release(txp);
} else if (disabled || !config.lora.tx_enabled) {
/* NOTE: Minimize the actions before startTransmit() to keep the time between
channel scan and actual transmit as low as possible to avoid collisions. */
if (disabled || !config.lora.tx_enabled) {
LOG_WARN("Drop Tx packet because LoRa Tx disabled");
packetPool.release(txp);
return false;
} else {
configHardwareForSend(); // must be after setStandby
@@ -499,10 +491,15 @@ void RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
completeSending();
powerMon->clearState(meshtastic_PowerMon_State_Lora_TXOn); // Transmitter off now
startReceive(); // Restart receive mode (because startTransmit failed to put us in xmit mode)
} else {
lastTxStart = millis();
printPacket("Started Tx", txp);
}
// Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register
// bits
enableInterrupt(isrTxLevel0);
return res == RADIOLIB_ERR_NONE;
}
}

View File

@@ -5,6 +5,7 @@
#include "concurrency/NotifiedWorkerThread.h"
#include <RadioLib.h>
#include <sys/types.h>
// ESP32 has special rules about ISR code
#ifdef ARDUINO_ARCH_ESP32
@@ -161,8 +162,9 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
/** start an immediate transmit
* This method is virtual so subclasses can hook as needed, subclasses should not call directly
* @return true if packet was sent
*/
virtual void startSend(meshtastic_MeshPacket *txp);
virtual bool startSend(meshtastic_MeshPacket *txp);
meshtastic_QueueStatus getQueueStatus();

View File

@@ -1,10 +1,10 @@
#include "ReliableRouter.h"
#include "Default.h"
#include "MeshModule.h"
#include "MeshTypes.h"
#include "configuration.h"
#include "mesh-pb-constants.h"
#include "modules/NodeInfoModule.h"
#include "modules/RoutingModule.h"
// ReliableRouter::ReliableRouter() {}
@@ -53,14 +53,14 @@ bool ReliableRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
auto key = GlobalPacketId(getFrom(p), p->id);
auto old = findPendingPacket(key);
if (old) {
LOG_DEBUG("generating implicit ack");
LOG_DEBUG("Generate implicit ack");
// NOTE: we do NOT check p->wantAck here because p is the INCOMING rebroadcast and that packet is not expected to be
// marked as wantAck
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, old->packet->channel);
stopRetransmission(key);
} else {
LOG_DEBUG("didn't find pending packet");
LOG_DEBUG("Didn't find pending packet");
}
}
@@ -73,18 +73,6 @@ bool ReliableRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
i->second.nextTxMsec += iface->getPacketTime(p);
}
/* Resend implicit ACKs for repeated packets (hopStart equals hopLimit);
* this way if an implicit ACK is dropped and a packet is resent we'll rebroadcast again.
* Resending real ACKs is omitted, as you might receive a packet multiple times due to flooding and
* flooding this ACK back to the original sender already adds redundancy. */
bool isRepeated = p->hop_start == 0 ? (p->hop_limit == HOP_RELIABLE) : (p->hop_start == p->hop_limit);
if (wasSeenRecently(p, false) && isRepeated && !MeshModule::currentReply && !isToUs(p)) {
LOG_DEBUG("Resending implicit ack for a repeated floodmsg");
meshtastic_MeshPacket *tosend = packetPool.allocCopy(*p);
tosend->hop_limit--; // bump down the hop count
Router::send(tosend);
}
return FloodingRouter::shouldFilterReceived(p);
}
@@ -107,16 +95,22 @@ void ReliableRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas
if (MeshModule::currentReply) {
LOG_DEBUG("Another module replied to this message, no need for 2nd ack");
} else if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel, p->hop_start, p->hop_limit);
// A response may be set to want_ack for retransmissions, but we don't need to ACK a response if it received an
// implicit ACK already. If we received it directly, only ACK with a hop limit of 0
if (!p->decoded.request_id)
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel,
routingModule->getHopLimitForResponse(p->hop_start, p->hop_limit));
else if (p->hop_start > 0 && p->hop_start == p->hop_limit)
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel, 0);
} else if (p->which_payload_variant == meshtastic_MeshPacket_encrypted_tag && p->channel == 0 &&
(nodeDB->getMeshNode(p->from) == nullptr || nodeDB->getMeshNode(p->from)->user.public_key.size == 0)) {
LOG_INFO("PKI packet from unknown node, send PKI_UNKNOWN_PUBKEY");
sendAckNak(meshtastic_Routing_Error_PKI_UNKNOWN_PUBKEY, getFrom(p), p->id, channels.getPrimaryIndex(),
p->hop_start, p->hop_limit);
routingModule->getHopLimitForResponse(p->hop_start, p->hop_limit));
} else {
// Send a 'NO_CHANNEL' error on the primary channel if want_ack packet destined for us cannot be decoded
sendAckNak(meshtastic_Routing_Error_NO_CHANNEL, getFrom(p), p->id, channels.getPrimaryIndex(), p->hop_start,
p->hop_limit);
sendAckNak(meshtastic_Routing_Error_NO_CHANNEL, getFrom(p), p->id, channels.getPrimaryIndex(),
routingModule->getHopLimitForResponse(p->hop_start, p->hop_limit));
}
}
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag && c &&
@@ -182,9 +176,9 @@ bool ReliableRouter::stopRetransmission(GlobalPacketId key)
if (old->numRetransmissions < NUM_RETRANSMISSIONS - 1) {
// remove the 'original' (identified by originator and packet->id) from the txqueue and free it
cancelSending(getFrom(p), p->id);
// now free the pooled copy for retransmission too
packetPool.release(p);
}
// now free the pooled copy for retransmission too
packetPool.release(p);
auto numErased = pending.erase(key);
assert(numErased == 1);
return true;
@@ -224,17 +218,17 @@ int32_t ReliableRouter::doRetransmissions()
bool stillValid = true; // assume we'll keep this record around
// FIXME, handle 51 day rolloever here!!!
// FIXME, handle 51 day rollover here!!!
if (p.nextTxMsec <= now) {
if (p.numRetransmissions == 0) {
LOG_DEBUG("Reliable send failed, returning a nak for fr=0x%x,to=0x%x,id=0x%x", p.packet->from, p.packet->to,
LOG_DEBUG("Reliable send failed, return a nak for fr=0x%x,to=0x%x,id=0x%x", p.packet->from, p.packet->to,
p.packet->id);
sendAckNak(meshtastic_Routing_Error_MAX_RETRANSMIT, getFrom(p.packet), p.packet->id, p.packet->channel);
// Note: we don't stop retransmission here, instead the Nak packet gets processed in sniffReceived
stopRetransmission(it->first);
stillValid = false; // just deleted it
} else {
LOG_DEBUG("Sending reliable retransmission fr=0x%x,to=0x%x,id=0x%x, tries left=%d", p.packet->from, p.packet->to,
LOG_DEBUG("Send reliable retransmission fr=0x%x,to=0x%x,id=0x%x, tries left=%d", p.packet->from, p.packet->to,
p.packet->id, p.numRetransmissions);
// Note: we call the superclass version because we don't want to have our version of send() add a new
@@ -263,7 +257,7 @@ void ReliableRouter::setNextTx(PendingPacket *pending)
assert(iface);
auto d = iface->getRetransmissionMsec(pending->packet);
pending->nextTxMsec = millis() + d;
LOG_DEBUG("Setting next retransmission in %u msecs: ", d);
LOG_DEBUG("Set next retransmission in %u msecs: ", d);
printPacket("", pending->packet);
setReceivedMessage(); // Run ASAP, so we can figure out our correct sleep time
}

View File

@@ -4,7 +4,7 @@
#include <unordered_map>
/**
* An identifier for a globalally unique message - a pair of the sending nodenum and the packet id assigned
* An identifier for a globally unique message - a pair of the sending nodenum and the packet id assigned
* to that message
*/
struct GlobalPacketId {

View File

@@ -71,7 +71,7 @@ int32_t Router::runOnce()
perhapsHandleReceived(mp);
}
// LOG_DEBUG("sleeping forever!");
// LOG_DEBUG("Sleep forever!");
return INT32_MAX; // Wait a long time - until we get woken for the message queue
}
@@ -136,15 +136,14 @@ meshtastic_MeshPacket *Router::allocForSending()
/**
* Send an ack or a nak packet back towards whoever sent idFrom
*/
void Router::sendAckNak(meshtastic_Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex, uint8_t hopStart,
uint8_t hopLimit)
void Router::sendAckNak(meshtastic_Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex, uint8_t hopLimit)
{
routingModule->sendAckNak(err, to, idFrom, chIndex, hopStart, hopLimit);
routingModule->sendAckNak(err, to, idFrom, chIndex, hopLimit);
}
void Router::abortSendAndNak(meshtastic_Routing_Error err, meshtastic_MeshPacket *p)
{
LOG_ERROR("Error=%d, returning NAK and dropping packet.", err);
LOG_ERROR("Error=%d, return NAK and drop packet", err);
sendAckNak(err, getFrom(p), p->id, p->channel);
packetPool.release(p);
}
@@ -188,9 +187,10 @@ ErrorCode Router::sendLocal(meshtastic_MeshPacket *p, RxSource src)
handleReceived(p, src);
}
if (!p->channel && !p->pki_encrypted) { // don't override if a channel was requested
// don't override if a channel was requested and no need to set it when PKI is enforced
if (!p->channel && !p->pki_encrypted) {
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(p->to);
if (node && node->user.public_key.size == 0) {
if (node) {
p->channel = node->channel;
LOG_DEBUG("localSend to channel %d", p->channel);
}
@@ -219,13 +219,13 @@ ErrorCode Router::send(meshtastic_MeshPacket *p)
if (hourlyTxPercent > myRegion->dutyCycle) {
#ifdef DEBUG_PORT
uint8_t silentMinutes = airTime->getSilentMinutes(hourlyTxPercent, myRegion->dutyCycle);
LOG_WARN("Duty cycle limit exceeded. Aborting send for now, you can send again in %d minutes.", silentMinutes);
LOG_WARN("Duty cycle limit exceeded. Aborting send for now, you can send again in %d mins", silentMinutes);
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
cn->has_reply_id = true;
cn->reply_id = p->id;
cn->level = meshtastic_LogRecord_Level_WARNING;
cn->time = getValidTime(RTCQualityFromNet);
sprintf(cn->message, "Duty cycle limit exceeded. You can send again in %d minutes.", silentMinutes);
sprintf(cn->message, "Duty cycle limit exceeded. You can send again in %d mins", silentMinutes);
service->sendClientNotification(cn);
#endif
meshtastic_Routing_Error err = meshtastic_Routing_Error_DUTY_CYCLE_LIMIT;
@@ -334,7 +334,7 @@ bool perhapsDecode(meshtastic_MeshPacket *p)
if (p->channel == 0 && isToUs(p) && p->to > 0 && !isBroadcast(p->to) && nodeDB->getMeshNode(p->from) != nullptr &&
nodeDB->getMeshNode(p->from)->user.public_key.size > 0 && nodeDB->getMeshNode(p->to)->user.public_key.size > 0 &&
rawSize > MESHTASTIC_PKC_OVERHEAD) {
LOG_DEBUG("Attempting PKI decryption");
LOG_DEBUG("Attempt PKI decryption");
if (crypto->decryptCurve25519(p->from, nodeDB->getMeshNode(p->from)->user.public_key, p->id, rawSize, ScratchEncrypted,
bytes)) {
@@ -426,7 +426,7 @@ bool perhapsDecode(meshtastic_MeshPacket *p)
}
}
/** Return 0 for success or a Routing_Errror code for failure
/** Return 0 for success or a Routing_Error code for failure
*/
meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
{
@@ -463,13 +463,13 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
// If the compressed length is greater than or equal to the original size, don't use the compressed form
if (compressed_len >= p->decoded.payload.size) {
LOG_DEBUG("Not using compressing message.");
LOG_DEBUG("Not using compressing message");
// Set the uncompressed payload variant anyway. Shouldn't hurt?
// p->decoded.which_payloadVariant = Data_payload_tag;
// Otherwise we use the compressor
} else {
LOG_DEBUG("Using compressed message.");
LOG_DEBUG("Use compressed message");
// Copy the compressed data into the meshpacket
p->decoded.payload.size = compressed_len;
@@ -490,7 +490,8 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(p->to);
// We may want to retool things so we can send a PKC packet when the client specifies a key and nodenum, even if the node
// is not in the local nodedb
if (
// First, only PKC encrypt packets we are originating
if (isFromUs(p) &&
// Don't use PKC with Ham mode
!owner.is_licensed &&
// Don't use PKC if it's not explicitly requested and a non-primary channel is requested
@@ -502,7 +503,7 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
// Some portnums either make no sense to send with PKC
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!");
LOG_DEBUG("Use PKI!");
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) &&
@@ -589,7 +590,7 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag &&
p->decoded.portnum == meshtastic_PortNum_NEIGHBORINFO_APP &&
(!moduleConfig.has_neighbor_info || !moduleConfig.neighbor_info.enabled)) {
LOG_DEBUG("Neighbor info module is disabled, ignoring neighbor packet");
LOG_DEBUG("Neighbor info module is disabled, ignore neighbor packet");
cancelSending(p->from, p->id);
skipHandle = true;
}
@@ -604,7 +605,7 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
meshtastic_PortNum_PAXCOUNTER_APP, meshtastic_PortNum_IP_TUNNEL_APP, meshtastic_PortNum_AUDIO_APP,
meshtastic_PortNum_PRIVATE_APP, meshtastic_PortNum_DETECTION_SENSOR_APP, meshtastic_PortNum_RANGE_TEST_APP,
meshtastic_PortNum_REMOTE_HARDWARE_APP)) {
LOG_DEBUG("Ignoring packet on blacklisted portnum for CORE_PORTNUMS_ONLY");
LOG_DEBUG("Ignore packet on blacklisted portnum for CORE_PORTNUMS_ONLY");
cancelSending(p->from, p->id);
skipHandle = true;
}
@@ -645,13 +646,20 @@ void Router::perhapsHandleReceived(meshtastic_MeshPacket *p)
#endif
// assert(radioConfig.has_preferences);
if (is_in_repeated(config.lora.ignore_incoming, p->from)) {
LOG_DEBUG("Ignoring msg, 0x%x is in our ignore list", p->from);
LOG_DEBUG("Ignore msg, 0x%x is in our ignore list", p->from);
packetPool.release(p);
return;
}
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(p->from);
if (node != NULL && node->is_ignored) {
LOG_DEBUG("Ignore msg, 0x%x is ignored", p->from);
packetPool.release(p);
return;
}
if (p->from == NODENUM_BROADCAST) {
LOG_DEBUG("Ignoring msg from broadcast address");
LOG_DEBUG("Ignore msg from broadcast address");
packetPool.release(p);
return;
}

View File

@@ -108,8 +108,7 @@ class Router : protected concurrency::OSThread
/**
* Send an ack or a nak packet back towards whoever sent idFrom
*/
void sendAckNak(meshtastic_Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex, uint8_t hopStart = 0,
uint8_t hopLimit = 0);
void sendAckNak(meshtastic_Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex, uint8_t hopLimit = 0);
private:
/**
@@ -132,7 +131,7 @@ class Router : protected concurrency::OSThread
*/
void handleReceived(meshtastic_MeshPacket *p, RxSource src = RX_SRC_RADIO);
/** Frees the provided packet, and generates a NAK indicating the speicifed error while sending */
/** Frees the provided packet, and generates a NAK indicating the specifed error while sending */
void abortSendAndNak(meshtastic_Routing_Error err, meshtastic_MeshPacket *p);
};
@@ -143,7 +142,7 @@ class Router : protected concurrency::OSThread
*/
bool perhapsDecode(meshtastic_MeshPacket *p);
/** Return 0 for success or a Routing_Errror code for failure
/** Return 0 for success or a Routing_Error code for failure
*/
meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p);

View File

@@ -94,7 +94,7 @@ template <typename T> bool SX126xInterface<T>::init()
// Overriding current limit
// (https://github.com/jgromes/RadioLib/blob/690a050ebb46e6097c5d00c371e961c1caa3b52e/src/modules/SX126x/SX126x.cpp#L85) using
// value in SX126xInterface.h (currently 140 mA) It may or may not be neccessary, depending on how RadioLib functions, from
// value in SX126xInterface.h (currently 140 mA) It may or may not be necessary, depending on how RadioLib functions, from
// SX1261/2 datasheet: OCP after setting DeviceSel with SetPaConfig(): SX1261 - 60 mA, SX1262 - 140 mA For the SX1268 the IC
// defaults to 140mA no matter the set power level, but RadioLib set it lower, this would need further checking Default values
// are: SX1262, SX1268: 0x38 (140 mA), SX1261: 0x18 (60 mA)
@@ -123,7 +123,7 @@ template <typename T> bool SX126xInterface<T>::init()
// no effect
#if ARCH_PORTDUINO
if (res == RADIOLIB_ERR_NONE) {
LOG_DEBUG("Using MCU pin %i as RXEN and pin %i as TXEN to control RF switching", settingsMap[rxen], settingsMap[txen]);
LOG_DEBUG("Use MCU pin %i as RXEN and pin %i as TXEN to control RF switching", settingsMap[rxen], settingsMap[txen]);
lora.setRfSwitchPins(settingsMap[rxen], settingsMap[txen]);
}
#else
@@ -136,7 +136,7 @@ template <typename T> bool SX126xInterface<T>::init()
LOG_DEBUG("SX126X_TXEN not defined, defaulting to RADIOLIB_NC");
#endif
if (res == RADIOLIB_ERR_NONE) {
LOG_DEBUG("Using MCU pin %i as RXEN and pin %i as TXEN to control RF switching", SX126X_RXEN, SX126X_TXEN);
LOG_DEBUG("Use MCU pin %i as RXEN and pin %i as TXEN to control RF switching", SX126X_RXEN, SX126X_TXEN);
lora.setRfSwitchPins(SX126X_RXEN, SX126X_TXEN);
}
#endif

View File

@@ -71,7 +71,7 @@ template <typename T> bool SX128xInterface<T>::init()
LOG_INFO("SX128x init result %d", res);
if ((config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24) && (res == RADIOLIB_ERR_INVALID_FREQUENCY)) {
LOG_WARN("Radio chip only supports 2.4GHz LoRa. Adjusting Region and rebooting.");
LOG_WARN("Radio only supports 2.4GHz LoRa. Adjusting Region and rebooting");
config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_LORA_24;
nodeDB->saveToDisk(SEGMENT_CONFIG);
delay(2000);
@@ -80,7 +80,7 @@ template <typename T> bool SX128xInterface<T>::init()
#elif defined(ARCH_NRF52)
NVIC_SystemReset();
#else
LOG_ERROR("FIXME implement reboot for this platform. Skipping for now.");
LOG_ERROR("FIXME implement reboot for this platform. Skip for now");
#endif
}

View File

@@ -3,6 +3,7 @@
#include "PhoneAPI.h"
#include "Stream.h"
#include "concurrency/OSThread.h"
#include <cstdarg>
// A To/FromRadio packet + our 32 bit header
#define MAX_STREAM_BUF_SIZE (MAX_TO_FROM_RADIO_SIZE + sizeof(uint32_t))

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