Compare commits

..

189 Commits

Author SHA1 Message Date
Ben Meadors
771cb52616 Remove amd64 2024-09-24 10:52:46 -05:00
Ben Meadors
10869ea10a Don't wait for after-checks 2024-09-24 09:10:29 -05:00
Ben Meadors
e4d0e38f37 Remove native and add v4 back 2024-09-24 08:25:25 -05:00
Ben Meadors
d7badcc9cb Don't run checks on workflow_dispatch 2024-09-24 07:17:38 -05:00
Ben Meadors
4fbf666cd9 Try v3 2024-09-24 07:12:43 -05:00
Tom Fifield
adb094ebc9 Remove old comments from main (#4849)
These comments were circa 4 years old. Remove them.
2024-09-24 06:08:32 -05:00
Tom Fifield
b709d47832 Fix Ublox M10 Setup (#4842)
There is no EXTINT pin available on the Tdeck, which uses
the Ublox M10 GPS. Therefore our previous hack to use that pin
makes the GPS not work. That workaround was implemented to
fix sleep issues which have now since been fixed with the
state machine.

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

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

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

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

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

Co-authored-by: Ken McGuire <kenm@paonia.com>
2024-09-24 05:50:03 -05:00
Jason Murray
4fde1ca2a8 chomp trailing newline (#4848) 2024-09-24 16:27:46 +08:00
Jason Murray
c72612d826 sed doesn't like newlines (#4847)
* sed doesn't like newlines

* fold remove-debug-flags block

* PATH is a system env var

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

* use build-variant action

* only checkout once and clean up after run

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

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

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

* Add MESHTASTIC_PKC_OVERHEAD

* compare to MESHTASTIC_HEADER_LENGTH

---------

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2024-09-23 09:20:32 -05:00
Ben Meadors
e8829b8f52 Refactor and consolidate time window logic (#4826)
* Refactor and consolidate windowing logic

* Trunk

* Fixes

* More

* Fix braces and remove unused now variables.

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

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

Move throttle include in WifiAPClient.cpp to top.

Add Default.h to sleep.cpp

rest of files just remove unused now variables.

* Remove a couple more meows

---------

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

* remove quotes to fix trunk.

---------

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

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

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

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

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

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

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

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

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

* Make trunk happy

* Make trunk happy

---------

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

* use build-variant action

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

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

* add board_level = extra

* Update variant.h

---------

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

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

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

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

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

Patch updates our CI workflow for these images.

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-09-21 06:10:59 -05:00
Thomas Göttgens
52cef05c70 heltec-wireless-bridge
requires Proto PR first
2024-09-21 12:42:51 +02:00
dependabot[bot]
6490cadd35 Bump docker/build-push-action from 5 to 6 in /.github/workflows (#4800) 2024-09-21 09:30:36 +00:00
dependabot[bot]
3882841283 Bump peter-evans/create-pull-request from 6 to 7 in /.github/workflows (#4797) 2024-09-21 08:17:31 +00:00
Tom Fifield
74e6470439 fix dependabot syntax (#4795)
* fix dependabot syntax

* Update dependabot.yml

* Update dependabot.yml
2024-09-21 14:20:30 +08:00
Tom Fifield
dca711ac24 Merge pull request #4790 from scruplelesswizard/master
Enable Dependabot
2024-09-21 12:22:11 +08:00
Jason Murray
7368cb99dc chore: trunk fmt 2024-09-20 19:40:36 -07:00
Jason Murray
ec848bab52 Enable Dependabot 2024-09-21 09:40:56 +08:00
Jason Murray
ed13105aec set title for version bump PR (#4791) 2024-09-20 20:30:49 -05:00
Jason Murray
c2272ce5a1 set title for protobufs bump PR (#4792) 2024-09-20 20:30:32 -05:00
Ben Meadors
0664c09f9d Download debian files after firmware zip 2024-09-20 14:55:53 -05:00
todd-herbert
ba31a7c753 Honor flip & color for Heltec T114 and T190 (#4786)
* Honor TFT_MESH color if defined for Heltec T114 or T190

* Temporary: point lib_deps at fork of Heltec's ST7789 library
For demo only, until ST7789 is merged

* Update lib_deps; tidy preprocessor logic
2024-09-20 13:27:41 -05:00
Ben Meadors
85d722232e Additional decoded packet ignores 2024-09-20 07:35:26 -05:00
Ben Meadors
921d92c649 Drop received packets from self 2024-09-20 06:55:16 -05:00
Jonathan Bennett
0f3450ad44 Mark package workflows for gh hosted runners 2024-09-19 18:21:30 -05:00
Jonathan Bennett
114df8cb1b Pin sensorlib version 2024-09-19 13:29:17 -05:00
Jonathan Bennett
d3a293a0d8 Flag semgrep to not run on self-hosted
The semgrep action runs inside a docker container, and docker in podman just doesn't work.
2024-09-19 12:10:39 -05:00
Ben Meadors
91b4199f9d Revert "DetectionSensor: broadcast all state changes" (#4776) 2024-09-19 10:46:18 -05:00
Tom Fifield
6473cf0b69 Update RadioLib to 7.0.0 (#4771)
We were not too many commits behind, and the changes since then
were either for LoraWAN or useful minor bug fixes for SX1280.
2024-09-19 06:48:22 -05:00
Tom Fifield
84e197574b Merge pull request #4773 from markbirss/master
Update HW_VENDOR
2024-09-19 16:28:40 +08:00
Mark Trevor Birss
5c4c0965af Update nordic_pca10059.json 2024-09-19 15:41:59 +08:00
Mark Trevor Birss
7289b295e8 Update me25ls01-4y10td.json 2024-09-19 15:41:59 +08:00
Mark Trevor Birss
7c32ab3023 Update ms24sf1.json 2024-09-19 15:41:59 +08:00
Tom Fifield
2bc036f9eb Merge pull request #4772 from dahanc/master
Another missed define for the T114
2024-09-19 15:28:26 +08:00
David Huang
cc89e85e71 Another missed define for the T114 2024-09-19 00:53:33 -05:00
Tom Fifield
da45cb8557 Merge pull request #4767 from augustozanellato/detsensor_broadcast_changes
DetectionSensor: broadcast all state changes
2024-09-19 13:42:56 +08:00
Augusto Zanellato
2ebfcea94e DetectionSensor: broadcast all state changes
Closes #4753
2024-09-18 19:43:23 +02:00
github-actions[bot]
deada41cee [create-pull-request] automated change (#4765)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-09-18 10:49:12 -05:00
Ben Meadors
777bcf691a Initial PhoneAPI rate-limiting of messages on certain ports (#4756) 2024-09-18 10:13:07 -05:00
Tom Fifield
35e1c401e2 PMSA0031 sensors require ~3secs before coming up on I2C (#4743)
* PMSA0031 sensors require ~3secs before coming up on I2C

As reported by @MALAONE1 and debugged by @shodan8192 , PMSA0031s
on a RAK4631 take 3 seconds before they can become detectable on I2c.

Add a delay(4000) before I2C scan if the air quality sensor pin
is defined.

Fixes https://github.com/meshtastic/firmware/issues/3690

* Remove 4 second wait and rescan during air quality init for the sensor

* works without but this triggers my OCD

---------

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-09-18 10:12:49 -05:00
Tom Fifield
19c57e8ec6 Fix Chatter 2 blank screen on boot (#4759)
As reported by @eureekasigns and @GPSFan, Chatter 2 had begun
to show a blank screen on boot after recent TFT display changes.

Setting TFT_BACKLIGHT_ON LOW resolves the issue.

Fixes https://github.com/meshtastic/firmware/issues/4751
2024-09-18 09:05:32 -05:00
Jonathan Bennett
c6196b2260 Update build_esp32.yml -- less CI fun 2024-09-18 01:11:08 -05:00
Jonathan Bennett
3eebdcefa4 More CI fun 2024-09-18 00:28:54 -05:00
Jonathan Bennett
4289cb089b Update package_raspbian.yml to build on self-hosted (#4761)
* Update package_raspbian.yml to build on self-hosted

* Update package_raspbian_armv7l.yml to use self hosted
2024-09-18 00:17:48 -05:00
Jonathan Bennett
2d52803dbd Add new admin error types (#4750)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-09-17 21:09:24 -05:00
Jonathan Bennett
c78302a2ee Add hasPKC to deviceMetadata (#4755) 2024-09-17 19:34:05 -05:00
github-actions[bot]
923458bc18 [create-pull-request] automated change (#4754)
Co-authored-by: jp-bennett <5630967+jp-bennett@users.noreply.github.com>
2024-09-17 17:55:16 -05:00
Ben Meadors
50fb4ab22a Implement optional hops_away on NodeInfo/Lite (#4747)
* Implement optional hops_away on NodeInfo/Lite

* Trunk
2024-09-17 12:08:04 -05:00
Thomas Göttgens
f5016763fd change evaluation order to silence warning about "found" (#4749) 2024-09-17 10:33:21 -05:00
Ben Meadors
2a6921292e Implement CoT detail support in TAKPacket (#4748)
* Implement CoT detail support in TAKPacket

* dest, src

* More coffee is needed

* SAVE
2024-09-17 10:05:55 -05:00
github-actions[bot]
a47570d65a [create-pull-request] automated change (#4746)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-09-17 06:52:42 -05:00
Andre K
db4dc88d6f feat: enable remote admin to set/clear fixed positions (#4713)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-09-17 06:50:49 -05:00
Tom Fifield
be306cc384 Increase GPS FIFO Buffer Size for RP2040 (#4741)
As discovered and tested by @Mictronics, default Serial FIFO size
on the Pico is 32bytes, which is not enough for GPS messages.

This patch increases the Serial GPS FIFO buffer size to 256
for the RP2040 Architecture

fixes https://github.com/meshtastic/firmware/issues/3989
2024-09-17 06:48:56 -05:00
Jonathan Bennett
a967dd52f3 More useful PKC logging (#4742) 2024-09-17 06:31:39 -05:00
Ben Meadors
11378325e0 Separate GPS and NTP RTCQuality logic and allow GPS time to always set us (#4721) 2024-09-17 06:29:18 -05:00
Thomas Göttgens
4b5bcf52d2 Merge pull request #4691 from S5NC/rak11200-pin-name-correction
Rak11200 pin name correction
2024-09-17 11:42:40 +02:00
Thomas Göttgens
5ba418b2cd Merge pull request #4744 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2024-09-17 09:27:42 +02:00
Thomas Göttgens
bc753e6903 trunk fmt 2024-09-17 15:24:11 +08:00
S5NC
34a543ec74 Update main.cpp 2024-09-17 15:24:11 +08:00
S5NC
06cd9abd81 Update SX126xInterface.cpp 2024-09-17 15:24:11 +08:00
S5NC
af30485611 Update main.cpp 2024-09-17 15:24:11 +08:00
S5NC
cd6bd1e9a3 Update main.cpp 2024-09-17 15:24:11 +08:00
S5NC
b025eeb13c Update variant.h 2024-09-17 15:24:11 +08:00
Thomas Göttgens
21eb54e58a Merge pull request #4740 from fifieldt/QMC5883L
Fix I2C address for QMC5883L.
2024-09-17 09:09:43 +02:00
Tom Fifield
6f1db6fc63 Fix I2C address for QMC5883L.
QMC5883L and HMC5883L are 3-axis compasses which are often confused.
As reported by @Africmod, we had the wrong I2C address for the QMC5883L.
This patch fixes the address and adds its HMC5883L so we keep info
about both.

Fixes https://github.com/meshtastic/firmware/issues/4144
2024-09-17 13:48:10 +08:00
Tom Fifield
a5118787b3 Merge pull request #4689 from Szetya/master
Improved compass arrow
2024-09-17 13:02:52 +08:00
jp-bennett
39c90dd581 [create-pull-request] automated change 2024-09-17 02:53:44 +00:00
Todd Herbert
33e6f7f6e0 Hollow triangle for E-Ink; trunk formatting 2024-09-17 08:27:00 +08:00
Szetya
97fd189f43 Compass update
https://github.com/meshtastic/firmware/issues/4494
New compass arrow and replacement of the north marker with a small circle.
2024-09-17 08:27:00 +08:00
jhps
1e665d5181 Update T114 LED definitions to include only one simple controllable LED and two NEOPIXELS. (#4710) 2024-09-16 19:11:55 -05:00
Thomas Göttgens
b3343303a9 write firmware version and hardware platform to Flash memory 2024-09-16 21:36:54 +02:00
github-actions[bot]
f37276d5fc [create-pull-request] automated change (#4736)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-09-16 10:32:21 -05:00
Tom Fifield
905194c604 Remove lora_isp4520 (#4735)
Per Ben: "We haven't supported any NRF5832 based board in quite some time.
It's relatively resource constrained compared to the NRF52840"
2024-09-16 09:06:13 -05:00
Thomas Göttgens
51b22630b4 Merge pull request #4728 from fifieldt/11111111111111111
Fix Heltec T114 vendor definition
2024-09-16 12:20:18 +02:00
Mark Trevor Birss
5d831ef461 Merge pull request #4729 from markbirss/master
[BUG-FIX] ME25LS01-4Y10TD_e-ink e-paper init fix
2024-09-16 11:14:16 +02:00
Mark Trevor Birss
4e8672cce4 Update variant.h 2024-09-16 10:40:52 +02:00
Tom Fifield
41a769aa06 Fix Heltec T114 vendor definition
@dahanc pointed out there was an extra one in there.
2024-09-16 13:55:27 +08:00
Ben Meadors
8d57b6164a Add Heltec T1114 hardware model to build (#4719) 2024-09-15 20:37:19 -05:00
Ben Meadors
dc3eba9100 Expand to MqttClientProxyMessage_size (#4726) 2024-09-15 18:57:02 -05:00
Jonathan Bennett
ff8baa1c85 Don't use PKC on a non-primary channel unless specifically requested (#4715)
* Don't use PKC on a non-primary channel unless specifically requested

* Don't change from channel 0 if we can send a PKC packet.
2024-09-15 09:26:43 -05:00
Jonathan Bennett
3a10a27851 Actually restrict remote hardware to gpio channel (#4717) 2024-09-15 06:27:59 -05:00
GUVWAF
8893529653 Make local stats number of Rx packets sum of good and bad (#4709) 2024-09-14 17:53:27 -05:00
Jonathan Bennett
1ab5bf4355 Use the time.age() value to correct stale GPS times (#4705)
* Use the time.age() value to correct stale GPS times

* Trunk

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-09-14 07:44:40 -05:00
Ben Meadors
ae791ca7e1 Add buildstamp epoch to initial debug output 2024-09-13 19:43:50 -05:00
Ben Meadors
35cfe4318a Stop past timestamps from setting our system time RTC (#4704)
* Ignore attempts to set times in the past (before our build epoch)

* TRONK
2024-09-13 19:42:31 -05:00
rcarteraz
b59bd6fee9 Update feature.yml (#4700) 2024-09-13 16:11:54 -05:00
rcarteraz
8b911f14cf Update Bug Report.yml (#4702) 2024-09-13 16:11:39 -05:00
Ben Meadors
d36c69396b Exclude meshtasticd binaries from firmware.zip (#4698)
* Exclude meshtasticd binaries from firmware.zip

* Incorrect
2024-09-13 10:42:40 -05:00
Vertex
3d72fbb19e Define SX126X_ANT_SW for the RAK11200 to allow it to function correctly on the RAK19007 base (#4690) 2024-09-12 12:20:38 -05:00
Manuel
625254cf90 Support Seeed SenseCAP Indicator (#4279)
* preliminary target environment

* add debug tool

* add screen definitions

* screen definitions

* remove rtc, debug build

* correct rotation

* Add real hwmodel

* fix width

* use IO expander ports

* link to modified arduino-esp32

* added config_detail

* rotate screen

* remove touch INT

* add delay to display log

* color log and radiolib log

* LoRa init

* make trunk happy

* add lovyanGFX patch lib for io expander

* fix lib

* fix display&touch function

* touch driver I2C scan

* remove delay

* build for release

* minor code cleanup

* allow trunk to be happy

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2024-09-12 06:44:30 -05:00
panaceya
910b6b7512 OLED_ can be configured via userPrefs.h (#4624) 2024-09-11 19:31:30 -05:00
Tom Fifield
371c3e05bf Beautify GPS_DEBUG getACK logging code (#4672)
This getACK is used to look for ASCII responses, so print ASCII
when GPS_DEBUG is enabled.

This markedly assisted with recent AG3335 debugging. It works great
with other chips too (tested eg ATGM336H). Even UBLOX prints
understandable "GPTXT,01,01,01,PDTI inv format*35." responses.

Credit to bluebrolly. on discord.
2024-09-11 19:30:29 -05:00
Michael Gjelsø
f37df4d6bf Radiomaster Bandit Accelerometer support (#4667)
* Added STK8xxxx Accelerometer chip

Added detection of STK8BA53 to I2C scanner.
Change the way and order MCP9808, lLISH3DH and STK8BA53 is detected since they all shares the same I2C address.

* Accelerometer support Radiomaster Bandit.

Enables tap to wake screen if enabled in config,

* Trunk

Trunk
2024-09-11 18:53:17 -05:00
github-actions[bot]
ba9a3cd719 [create-pull-request] automated change (#4685)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-09-11 18:51:52 -05:00
Ben Meadors
9ac0e26d42 Add option to preserve private key for factory reset (config) (#4679)
* Add option to preserve private key for factory reset (config)

* Typo fix

* Copy the key in the right direction, and set the size.

* Don't set the key size back to 0 right after setting it to 32.

* Set the key size before using it to do a memcpy.

* Use the right key_size for backing up private_key

* Don't factoryReset() for a missing nodeDB

* Disable Bluetooth in AdminModule when resetting device settings or nodeDB to avoid race

* Add checks for valid objects before deinit bluetooth

* Add disableBluetooth to handleSetConfig, handleSetModuleConfig, and commit settings

---------

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
2024-09-11 08:42:26 -05:00
Ben Meadors
1ba4f6e222 Revert "Temp: Grab pre-release tag"
This reverts commit e8e9826adc.
2024-09-10 20:07:06 -05:00
Ben Meadors
e8e9826adc Temp: Grab pre-release tag 2024-09-10 19:27:59 -05:00
zerolint
6724f1f7ea Print Unix epoch on time_t 64bit platforms (#4673)
Fixes (#4600) by using unsigned 32bit for epoch.

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-09-10 15:51:28 -05:00
Ben Meadors
013021941e Remove scaling of smart position broadcast minimum interval specifically (#4677)
* Remove scaling of smart position broacast minimum interval specifically

* Trunk
2024-09-10 15:30:40 -05:00
Jonathan Bennett
4e850296b6 Fix repeatedly getting new NodeNum and add more debug (#4674)
* All the debug

* Change `memccpy()` to `memcpy()`

* Brint all the bytes of the MAC Address from the NodeDB

* Check for blank MAC Address in ourown NodeDB entry

* One more `memccpy()`

* Clean-up debug log

---------

Co-authored-by: GUVWAF <thijs@havinga.eu>
2024-09-10 13:24:57 -05:00
GUVWAF
f1602ee3f6 Merge pull request #4669 from GUVWAF/trFix 2024-09-09 23:13:39 +02:00
GUVWAF
5537f98dd6 Merge branch 'master' into trFix 2024-09-09 21:29:37 +02:00
GUVWAF
4ed12bf21d Try fix repeatedly getting a new NodeNum (#4670) 2024-09-09 14:22:32 -05:00
Ben Meadors
106dab23db Revert "Changes by create-pull-request action" (#4671) 2024-09-09 14:20:14 -05:00
GUVWAF
2f9dcee954 Fix size calculation of route/SNR array 2024-09-09 19:13:00 +02:00
Thomas Göttgens
68d6ff8c24 Merge pull request #4650 from fifieldt/AG3352
Add support for AG3352 and fix AG3335 support
2024-09-09 16:40:44 +02:00
Tom Fifield
dc8cc122a6 Add explicit to JSONValue constructors (#4665) 2024-09-09 09:20:21 -05:00
Tom Fifield
e9d55de3cb Fix out-of-bound array access in T1000X Sensor (#4663)
if u8i == 135, then u8i++ runs, the loop exits since u8i == 136,
then value for u8i is 136 after the for loop.

then in the next line, ntc_res2[u8i] will read past the end
 of the array
2024-09-09 07:54:11 -05:00
David
dacb452d47 Bugfix (#4660) 2024-09-09 07:16:58 -05:00
Thomas Göttgens
8ab2e91df6 Merge pull request #4659 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2024-09-09 12:21:56 +02:00
Thomas Göttgens
e985ee878f Merge pull request #4658 from fifieldt/zombiegps
If GPS sleepTime is Zero, don't sleep.
2024-09-09 12:12:53 +02:00
Thomas Göttgens
b2e2f1dba3 Merge branch 'master' into AG3352 2024-09-09 11:10:36 +02:00
thebentern
fabd6b0d6f [create-pull-request] automated change 2024-09-09 02:54:25 +00:00
Tom Fifield
ebe1b40bee If GPS sleepTime is Zero, don't sleep.
At the moment if the result of sleepTime calculations comes out
to zero, we put the GPS into HARDSLEEP (losing all its status) and
then immediately make it ACTIVE again.

This patch avoids that toga.

fixes https://github.com/meshtastic/firmware/issues/4657
2024-09-09 09:28:04 +08:00
Tom Fifield
6217e97c41 Add support for AG3352 and fix AG3335 support
AG33352 is a Mediatek/Airoha GPS/GLONASS/Galileo/BeiDou receiver.
Patch adds relevant detection and setup code.

Thanks to Bluebrolly and kongduino for providing the relevant
information and testing.

This patch also fixes support for the A3335, which is a related chip.
The setup and detection code now works as tested on a real life
T-1000E!

Thanks to @gpsfan for the guidance.
2024-09-09 09:06:05 +08:00
Tom Fifield
e470619e3d Remove undefined declaration (#4652)
The getNMEA method was introduced to the header but never defined
in code. As it's unused, remove it.
2024-09-08 12:33:56 -05:00
Jonathan Bennett
bf34329033 Adds the data bitfield and ok_to_mqtt bit (#4643)
* Don't filter PKI packets just for being encrypted.

* Add ok_to_mqtt config and bit

* Bitfield

* Adjust dontmqttmebro logic.

* Manipulate bitfield only in router.cpp

* Want_ack is not want_response

* Bitfield macros

* Use new Bitfield macro in MQTT.cpp

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-09-07 18:21:59 -05:00
Thomas Göttgens
8e88b9e819 Merge pull request #4646 from gitbisector/batt_stat
Report PWD when no battery present.
2024-09-07 10:58:17 +02:00
Thomas Göttgens
56a2e40681 Merge pull request #4647 from fifieldt/gps-probe-macro
Simplify GNSS Probe code
2024-09-07 10:54:24 +02:00
Tom Fifield
ba28ffb65a Simplify GNSS Probe code
This patch takes inspiration from our I2CDetect code where we have
many sensors that can be detected rather simply. It creates a new
macro,
PROBE_SIMPLE(Chip name, Command to run, response, Driver, timeout)

and converts existing simple cases to use this macro.
2024-09-07 11:59:45 +08:00
gitbisector
9651b5a0ec Merge branch 'master' into batt_stat 2024-09-06 17:23:38 -07:00
git bisector
2f2ddae12a Report PWD when no battery present. 2024-09-06 17:19:53 -07:00
github-actions[bot]
c77b89d85c [create-pull-request] automated change (#4645) 2024-09-06 18:51:22 -05:00
Thomas Göttgens
5c2fe4a2c0 Merge pull request #4644 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2024-09-06 22:29:32 +02:00
caveman99
b8cee51e84 [create-pull-request] automated change 2024-09-06 20:27:28 +00:00
Thomas Göttgens
fd1ebdf363 Merge pull request #4507 from rcarteraz/add-contributing-file
Draft contributing.md file
2024-09-06 15:12:56 +02:00
Thomas Göttgens
35b47467c7 Merge pull request #4639 from zerolint/master
RAK13800 Ethernet improvements
2024-09-06 15:11:10 +02:00
Thomas Göttgens
8f35a42f4f tryfix #4384 (#4642)
* tryfix #4384 - don't assume we want that functionality if the Accelerometer was found. This is only for T-Watch

* Add  config.display.wake_on_tap_or_motion default to RAK

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-09-06 06:55:56 -05:00
Thomas Göttgens
35a565cd84 Merge pull request #4623 from robertfisk/tidyup_keyboard_defines
Gather canned message magic numbers into header defines.
2024-09-06 13:49:27 +02:00
Ben Meadors
ee68e727ed Merge branch 'master' into master 2024-09-06 06:25:07 -05:00
Robert Fisk
962d9ff220 Move defines to input broker 2024-09-06 11:54:31 +02:00
Robert Fisk
8e0a342f06 Gather canned message magic numbers into header defines. 2024-09-06 11:54:31 +02:00
Thomas Göttgens
55292f8a84 Merge pull request #4638 from fifieldt/CRLF
Add missing linefeeds to gps code
2024-09-06 11:46:57 +02:00
zerolint
d72a836e07 RAK13800 Ethernet improvements
Fixes (#3618) by allowing more time for slower requests.
Resolve Syslog not maintaining client causing issues on RAK13800.
Resolve Ethernet static IP setting subnet as gateway IP.
Reduce comment and log message ambiguity around API.
Remove duplicate #if !MESHTASTIC_EXCLUDE_WEBSERVER block.
2024-09-06 11:45:43 +02:00
Thomas Göttgens
26a3841a93 Merge pull request #4637 from todd-herbert/gps-icon
Update E-Ink GPS icon immediately when triple-pressing user button
2024-09-06 11:25:12 +02:00
Thomas Göttgens
8e519d09b4 Merge pull request #4641 from meshtastic/lr-version
Add LR11x0 firmware version to init.
2024-09-06 11:24:04 +02:00
Thomas Göttgens
ae41a7cc06 Merge pull request #4635 from RCGV1/patch-1
Update Pull Request Template
2024-09-06 10:05:11 +02:00
Thomas Göttgens
011e640e95 Add LR11x0 firmware version to init. 2024-09-06 09:47:43 +02:00
Tom Fifield
e4e1ea971f Add missing linefeeds to gps code
As reported by @caveman99, the required CRLFs were missing from the
AG3335 setup code.
2024-09-06 08:45:57 +08:00
Todd Herbert
bcdc36c07c Refresh E-Ink to show changes in GPS icon 2024-09-06 11:25:41 +12:00
Benjamin Faershtein
972a5d5779 Update Pull Request Template 2024-09-05 14:25:34 -07:00
Thomas Göttgens
7c6454f171 bring 2.4G back in line with preset bandwidth (#4634) 2024-09-05 15:49:08 -05:00
rcarteraz
1d3d44061b lol of course trunk fmt 2024-09-04 15:33:28 -07:00
rcarteraz
4d57c99ad1 add ticks 2024-09-04 15:28:17 -07:00
rcarteraz
22e23997c1 Merge branch 'master' into add-contributing-file 2024-09-04 15:27:11 -07:00
rcarteraz
8d29ce939d changes from feedback 2024-09-04 15:27:00 -07:00
rcarteraz
b19c1a52cb Merge branch 'master' into add-contributing-file 2024-08-20 13:12:02 -07:00
rcarteraz
ba771ae507 fix 2024-08-20 13:11:03 -07:00
rcarteraz
9014058935 add CLA admonition 2024-08-20 13:09:39 -07:00
rcarteraz
33b12126e0 more verbiage 2024-08-19 10:10:32 -07:00
rcarteraz
9d323a3832 verbiage changes 2024-08-19 10:08:43 -07:00
rcarteraz
2a664e01b0 update code of conduct link 2024-08-19 10:06:33 -07:00
rcarteraz
c1569b0f70 add draft contributing.md file 2024-08-19 10:03:40 -07:00
152 changed files with 2037 additions and 1271 deletions

View File

@@ -49,10 +49,24 @@ body:
- Heltec V3
- Heltec Wireless Paper
- Heltec Wireless Tracker
- Heltec Mesh Node T114
- Heltec Vision Master E213
- Heltec Vision Master E290
- Heltec Vision Master T190
- Nano G1
- Nano G1 Explorer
- Nano G2 Ultra
- Raspberry Pi Pico (W)
- Relay v1
- Relay v2
- Seeed Wio Tracker 1110
- Seeed Card Tracker T1000-E
- Station G1
- Station G2
- unPhone
- CanaryOne
- Chatter
- Linux Native
- DIY
- Other
validations:

View File

@@ -18,6 +18,7 @@ body:
- ESP32
- RP2040
- Linux Native
- Cross-Platform
- other
validations:
required: true

View File

@@ -0,0 +1,90 @@
name: Setup Build Variant Composite Action
description: Variant build actions for Meshtastic Platform IO steps
inputs:
board:
description: The board to build for
required: true
github_token:
description: GitHub token
required: true
build-script-path:
description: Path to the build script
required: true
remove-debug-flags:
description: A space separated list of files to remove debug flags from
required: false
default: ""
ota-firmware-source:
description: The OTA firmware file to pull
required: false
default: ""
ota-firmware-target:
description: The target path to store the OTA firmware file
required: false
default: ""
artifact-paths:
description: A newline separated list of paths to store as artifacts
required: false
default: ""
include-web-ui:
description: Include the web UI in the build
required: false
default: "false"
runs:
using: composite
steps:
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Pull web ui
if: inputs.include-web-ui == 'true'
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/web
file: build.tar
target: build.tar
token: ${{ inputs.github_token }}
- name: Unpack web ui
if: inputs.include-web-ui == 'true'
shell: bash
run: |
tar -xf build.tar -C data/static
rm build.tar
- name: Remove debug flags for release
shell: bash
if: inputs.remove-debug-flags != ''
run: |
for INI_FILE in ${{ inputs.remove-debug-flags }}; do
sed -i '/DDEBUG_HEAP/d' ${INI_FILE}
done
- name: Build ${{ inputs.board }}
shell: bash
run: ${{ inputs.build-script-path }} ${{ inputs.board }}
- name: Pull OTA Firmware
if: inputs.ota-firmware-source != '' && inputs.ota-firmware-target != ''
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/firmware-ota
file: ${{ inputs.ota-firmware-source }}
target: ${{ inputs.ota-firmware-target }}
token: ${{ inputs.github_token }}
- name: Get release version string
shell: bash
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
${{ inputs.artifact-paths }}

26
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
version: 2
updates:
- package-ecosystem: docker
directory: devcontainer
schedule:
interval: daily
time: "05:00" # trunk-ignore(yamllint/quoted-strings): required by dependabot syntax check
timezone: US/Pacific
- package-ecosystem: docker
directory: /
schedule:
interval: daily
time: "05:00" # trunk-ignore(yamllint/quoted-strings): required by dependabot syntax check
timezone: US/Pacific
- package-ecosystem: gitsubmodule
directory: /
schedule:
interval: daily
time: "05:00" # trunk-ignore(yamllint/quoted-strings): required by dependabot syntax check
timezone: US/Pacific
- package-ecosystem: github-actions
directory: /.github/workflows
schedule:
interval: daily
time: "05:00" # trunk-ignore(yamllint/quoted-strings): required by dependabot syntax check
timezone: US/Pacific

View File

@@ -1,9 +1,9 @@
### ❌ (Please delete all these tips and replace them with your text) ❌
## Thank you for sending in a pull request, here's some tips to get started!
(Please delete all these tips and replace with your text)
- Before starting on some new big chunk of code, it it is optional but highly recommended to open an issue first
to say "hey, I think this idea X should be implemented and I'm starting work on it. My general plan is Y, any feedback
to say "Hey, I think this idea X should be implemented and I'm starting work on it. My general plan is Y, any feedback
is appreciated." This will allow other devs to potentially save you time by not accidentially duplicating work etc...
- Please do not check in files that don't have real changes
- Please do not reformat lines that you didn't have to change the code on
@@ -12,3 +12,4 @@
- If your PR fixes a bug, mention "fixes #bugnum" somewhere in your pull request description.
- If your other co-developers have comments on your PR please tweak as needed.
- Please also enable "Allow edits by maintainers".
- If your PR gets accepted you can request a "Contributor" role in the Meshtastic Discord

View File

@@ -12,52 +12,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Pull web ui
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/web
file: build.tar
target: build.tar
token: ${{ secrets.GITHUB_TOKEN }}
- name: Unpack web ui
run: |
tar -xf build.tar -C data/static
rm build.tar
- name: Remove debug flags for release
if: ${{ github.event_name == 'workflow_dispatch' }}
run: |
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32.ini
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s2.ini
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s3.ini
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32c3.ini
- name: Build ESP32
run: bin/build-esp32.sh ${{ inputs.board }}
- name: Pull OTA Firmware
uses: dsaltares/fetch-gh-release-asset@master
id: build
uses: ./.github/actions/build-variant
with:
repo: meshtastic/firmware-ota
file: firmware.bin
target: release/bleota.bin
token: ${{ secrets.GITHUB_TOKEN }}
- name: Get release version string
shell: bash
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
github_token: ${{ secrets.GITHUB_TOKEN }}
board: ${{ inputs.board }}
remove-debug-flags: >-
./arch/esp32/esp32.ini
./arch/esp32/esp32s2.ini
./arch/esp32/esp32s3.ini
./arch/esp32/esp32c3.ini
build-script-path: bin/build-esp32.sh
ota-firmware-source: firmware.bin
ota-firmware-target: release/bleota.bin
artifact-paths: |
release/*.bin
release/*.elf
include-web-ui: true

View File

@@ -14,50 +14,21 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Pull web ui
uses: dsaltares/fetch-gh-release-asset@master
- name: Build ESP32-C3
id: build
uses: ./.github/actions/build-variant
with:
repo: meshtastic/web
file: build.tar
target: build.tar
token: ${{ secrets.GITHUB_TOKEN }}
- name: Unpack web ui
run: |
tar -xf build.tar -C data/static
rm build.tar
- name: Remove debug flags for release
if: ${{ github.event_name == 'workflow_dispatch' }}
run: |
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32.ini
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s2.ini
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s3.ini
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32c3.ini
- name: Build ESP32
run: bin/build-esp32.sh ${{ inputs.board }}
- name: Pull OTA Firmware
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/firmware-ota
file: firmware-c3.bin
target: release/bleota-c3.bin
token: ${{ secrets.GITHUB_TOKEN }}
- name: Get release version string
shell: bash
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
github_token: ${{ secrets.GITHUB_TOKEN }}
board: ${{ inputs.board }}
remove-debug-flags: >-
./arch/esp32/esp32.ini
./arch/esp32/esp32s2.ini
./arch/esp32/esp32s3.ini
./arch/esp32/esp32c3.ini
build-script-path: bin/build-esp32.sh
ota-firmware-source: firmware-c3.bin
ota-firmware-target: release/bleota-c3.bin
artifact-paths: |
release/*.bin
release/*.elf

View File

@@ -12,50 +12,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Pull web ui
uses: dsaltares/fetch-gh-release-asset@master
- name: Build ESP32-S3
id: build
uses: ./.github/actions/build-variant
with:
repo: meshtastic/web
file: build.tar
target: build.tar
token: ${{ secrets.GITHUB_TOKEN }}
- name: Unpack web ui
run: |
tar -xf build.tar -C data/static
rm build.tar
- name: Remove debug flags for release
if: ${{ github.event_name == 'workflow_dispatch' }}
run: |
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32.ini
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s2.ini
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s3.ini
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32c3.ini
- name: Build ESP32
run: bin/build-esp32.sh ${{ inputs.board }}
- name: Pull OTA Firmware
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/firmware-ota
file: firmware-s3.bin
target: release/bleota-s3.bin
token: ${{ secrets.GITHUB_TOKEN }}
- name: Get release version string
shell: bash
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
github_token: ${{ secrets.GITHUB_TOKEN }}
board: ${{ inputs.board }}
remove-debug-flags: >-
./arch/esp32/esp32.ini
./arch/esp32/esp32s2.ini
./arch/esp32/esp32s3.ini
./arch/esp32/esp32c3.ini
build-script-path: bin/build-esp32.sh
ota-firmware-source: firmware-s3.bin
ota-firmware-target: release/bleota-s3.bin
artifact-paths: |
release/*.bin
release/*.elf
include-web-ui: true

View File

@@ -67,7 +67,7 @@ jobs:
- name: Docker build and push tagged versions
if: ${{ github.event_name == 'workflow_dispatch' }}
continue-on-error: true # FIXME: Failing docker login auth
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
@@ -77,7 +77,7 @@ jobs:
- name: Docker build and push
if: ${{ github.ref == 'refs/heads/master' && github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
continue-on-error: true # FIXME: Failing docker login auth
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile

View File

@@ -12,23 +12,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Build NRF52
run: bin/build-nrf52.sh ${{ inputs.board }}
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
id: build
uses: ./.github/actions/build-variant
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
github_token: ${{ secrets.GITHUB_TOKEN }}
board: ${{ inputs.board }}
build-script-path: bin/build-nrf52.sh
artifact-paths: |
release/*.hex
release/*.uf2
release/*.elf

View File

@@ -12,22 +12,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Build Raspberry Pi 2040
run: ./bin/build-rpi2040.sh ${{ inputs.board }}
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
id: build
uses: ./.github/actions/build-variant
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
github_token: ${{ secrets.GITHUB_TOKEN }}
board: ${{ inputs.board }}
build-script-path: bin/build-rpi2040.sh
artifact-paths: |
release/*.uf2
release/*.elf

View File

@@ -12,22 +12,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Build STM32
run: bin/build-stm32.sh ${{ inputs.board }}
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
- name: Build Raspberry Pi 2040
id: build
uses: ./.github/actions/build-variant
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
github_token: ${{ secrets.GITHUB_TOKEN }}
board: ${{ inputs.board }}
build-script-path: bin/build-stm32.sh
artifact-paths: |
release/*.hex
release/*.bin

View File

@@ -51,6 +51,7 @@ jobs:
matrix: ${{ fromJson(needs.setup.outputs.check) }}
runs-on: ubuntu-latest
if: ${{ github.event_name != 'workflow_dispatch' }}
steps:
- uses: actions/checkout@v4
- name: Build base
@@ -119,11 +120,12 @@ jobs:
package-raspbian-armv7l:
uses: ./.github/workflows/package_raspbian_armv7l.yml
package-native:
uses: ./.github/workflows/package_amd64.yml
# package-native:
# uses: ./.github/workflows/package_amd64.yml
after-checks:
runs-on: ubuntu-latest
if: ${{ github.event_name != 'workflow_dispatch' }}
needs: [check]
steps:
- name: Checkout code
@@ -137,8 +139,7 @@ jobs:
contents: write
pull-requests: write
runs-on: ubuntu-latest
needs:
[
needs: [
build-esp32,
build-esp32-s3,
build-esp32-c3,
@@ -147,7 +148,7 @@ jobs:
build-stm32,
package-raspbian,
package-raspbian-armv7l,
package-native,
# package-native,
]
steps:
- name: Checkout code
@@ -231,7 +232,7 @@ jobs:
release-artifacts:
runs-on: ubuntu-latest
if: ${{ github.event_name == 'workflow_dispatch' }}
needs: [gather-artifacts, after-checks]
needs: [gather-artifacts]
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -251,12 +252,6 @@ jobs:
merge-multiple: true
path: ./output
- uses: actions/download-artifact@v4
with:
pattern: meshtasticd_${{ steps.version.outputs.version }}_*.deb
merge-multiple: true
path: ./output
- name: Display structure of downloaded files
run: ls -R
@@ -266,7 +261,7 @@ jobs:
chmod +x ./output/device-update.sh
- name: Zip firmware
run: zip -j -9 -r ./firmware-${{ steps.version.outputs.version }}.zip ./output -x *.deb
run: zip -j -9 -r ./firmware-${{ steps.version.outputs.version }}.zip ./output -x meshtasticd_*
- uses: actions/download-artifact@v4
with:
@@ -314,6 +309,12 @@ jobs:
asset_name: debug-elfs-${{ steps.version.outputs.version }}.zip
asset_content_type: application/zip
- uses: actions/download-artifact@v4
with:
pattern: meshtasticd_${{ steps.version.outputs.version }}_*.deb
merge-multiple: true
path: ./output
- name: Add raspbian aarch64 .deb
uses: actions/upload-release-asset@v1
env:
@@ -334,22 +335,50 @@ jobs:
asset_name: meshtasticd_${{ steps.version.outputs.version }}_armhf.deb
asset_content_type: application/vnd.debian.binary-package
- name: Add raspbian amd64 .deb
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./output/meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
asset_name: meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
asset_content_type: application/vnd.debian.binary-package
# - name: Add raspbian amd64 .deb
# uses: actions/upload-release-asset@v1
# env:
# GITHUB_TOKEN: ${{ github.token }}
# with:
# upload_url: ${{ steps.create_release.outputs.upload_url }}
# asset_path: ./output/meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
# asset_name: meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
# asset_content_type: application/vnd.debian.binary-package
- name: Bump version.properties
run: >-
bin/bump_version.py
- name: Create version.properties pull request
uses: peter-evans/create-pull-request@v6
uses: peter-evans/create-pull-request@v7
with:
title: Bump version.properties
add-paths: |
version.properties
- name: Checkout meshtastic/meshtastic.github.io
uses: actions/checkout@v4
with:
repository: meshtastic/meshtastic.github.io
token: ${{ secrets.ARTIFACTS_TOKEN }}
path: meshtastic.github.io
- name: Display structure of downloaded files
run: ls -R
- name: Extract firmware.zip
run: |
unzip ./firmware-${{ steps.version.outputs.version }}.zip -d meshtastic.github.io/firmware-${{ steps.version.outputs.version }}
- name: Display structure of downloaded files
run: ls -R
- name: Commit and push changes
run: |
cd meshtastic.github.io
find . -type f -name 'meshtasticd_*' -exec rm -f {} +
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git add .
git commit -m "Add firmware version ${{ steps.version.outputs.version }}"
git push

View File

@@ -13,7 +13,7 @@ jobs:
uses: ./.github/workflows/build_native.yml
package-native:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
needs: build-native
steps:
- name: Checkout code

View File

@@ -13,7 +13,7 @@ jobs:
uses: ./.github/workflows/build_raspbian.yml
package-raspbian:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
needs: build-raspbian
steps:
- name: Checkout code

View File

@@ -13,7 +13,7 @@ jobs:
uses: ./.github/workflows/build_raspbian_armv7l.yml
package-raspbian_armv7l:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
needs: build-raspbian_armv7l
steps:
- name: Checkout code

View File

@@ -12,7 +12,7 @@ jobs:
semgrep-full:
runs-on: ubuntu-latest
container:
image: returntocorp/semgrep
image: semgrep/semgrep
steps:
# step 1

View File

@@ -4,9 +4,9 @@ on: pull_request
jobs:
semgrep-diff:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
container:
image: returntocorp/semgrep
image: semgrep/semgrep
steps:
# step 1

View File

@@ -77,7 +77,7 @@ jobs:
pio upgrade
- name: Setup pnpm
uses: pnpm/action-setup@v2
uses: pnpm/action-setup@v4
with:
version: latest

View File

@@ -1,4 +1,4 @@
name: "Update protobufs and regenerate classes"
name: Update protobufs and regenerate classes
on: workflow_dispatch
jobs:
@@ -26,8 +26,9 @@ jobs:
./bin/regen-protos.sh
- name: Create pull request
uses: peter-evans/create-pull-request@v6
uses: peter-evans/create-pull-request@v7
with:
title: Update protobufs and classes
add-paths: |
protobufs
src/mesh

47
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,47 @@
# Contributing to Meshtastic Firmware
We're excited that you're interested in contributing to the Meshtastic firmware! This document provides a high-level overview of how you can get involved.
## Important First Steps
Before you begin, please:
1. **Read our documentation**: Our [official documentation](https://meshtastic.org/docs/) is a crucial resource. It contains essential information about the project.
2. **Check out the firmware build guide**: For specific instructions on setting up your development environment and building the firmware, refer to our [Firmware Build Guide](https://meshtastic.org/docs/development/firmware/build/).
3. Read our [Code of Conduct](https://meshtastic.org/docs/legal/conduct/)
4. Join our [Discord community](https://discord.com/invite/ktMAKGBnBs) to connect with developers and other contributors to get help.
## Getting Help and Discussing Ideas
We encourage open communication and discussion before diving into code changes:
1. **Use GitHub Discussions**: For new ideas, questions, or to discuss potential changes, start a conversation in our [GitHub Discussions](https://github.com/meshtastic/firmware/discussions) first. This helps us collaborate and avoid duplicate work.
2. **Join our Discord**: For real-time chat and quick questions, join our [Discord server](https://discord.com/invite/ktMAKGBnBs). It's a great place to get help and connect with other developers and the community.
3. **Reporting Issues**: If you've identified a bug, please use our bug report template when creating a new issue in the [issue tracker](https://github.com/meshtastic/firmware/issues). Ensure you've searched existing issues to avoid duplicates.
## Making Contributions
> [!IMPORTANT]
> Before making any contributions, you must sign our Contributor License Agreement (CLA). You can do this by visiting https://cla-assistant.io/meshtastic/firmware. Be sure to use the GitHub account you will use to submit your contributions when signing.
1. Fork the repository
2. Create a new branch for your feature or bug fix
3. Make your changes
4. Test your changes thoroughly
5. Create a pull request with a clear description, using the provided template, of your changes. Be sure to enable "Allow edits from maintainers".
## Coding Standards
To ensure consistent code formatting across the project:
1. Install the [Trunk](https://marketplace.visualstudio.com/items?itemName=Trunk.io) extension for Visual Studio Code.
2. Before submitting your changes, run `trunk fmt` to automatically format your code according to our standards.
Adhering to these formatting guidelines helps maintain code consistency and makes the review process smoother.
Thank you for contributing to Meshtastic!

View File

@@ -5,7 +5,7 @@ custom_esp32_kind = esp32
platform = platformio/espressif32@6.7.0
build_src_filter =
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/> -<mesh/raspihttp>
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp>
upload_speed = 921600
debug_init_break = tbreak setup

View File

@@ -16,7 +16,7 @@ build_flags =
-DLFS_NO_ASSERT ; Disable LFS assertions , see https://github.com/meshtastic/firmware/pull/3818
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2040> -<mesh/eth/> -<mesh/raspihttp>
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp>
lib_deps=
${arduino_base.lib_deps}

View File

@@ -1,6 +1,6 @@
; The Portduino based sim environment on top of any host OS, all hardware will be simulated
[portduino_base]
platform = https://github.com/meshtastic/platform-native.git#ad8112adf82ce1f5b917092cf32be07a077801a0
platform = https://github.com/meshtastic/platform-native.git#6b3796d697481c8f6e3f4aa5c111bd9979f29e64
framework = arduino
build_src_filter =
@@ -9,7 +9,7 @@ build_src_filter =
-<nimble/>
-<platform/nrf52/>
-<platform/stm32wl/>
-<platform/rp2040>
-<platform/rp2xx0>
-<mesh/wifi/>
-<mesh/http/>
+<mesh/raspihttp/>

View File

@@ -8,7 +8,7 @@ board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
build_flags =
${arduino_base.build_flags} -Wno-unused-variable
-Isrc/platform/rp2040
-Isrc/platform/rp2xx0
-D__PLAT_RP2040__
# -D _POSIX_THREADS
build_src_filter =

23
arch/rp2xx0/rp2350.ini Normal file
View File

@@ -0,0 +1,23 @@
; Common settings for rp2040 Processor based targets
[rp2350_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#9e55f6db5c56b9867c69fe473f388beea4546672
extends = arduino_base
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#a6ab6e1f95bc1428d667d55ea7173c0744acc03c ; 4.0.2+
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
build_flags =
${arduino_base.build_flags} -Wno-unused-variable
-Isrc/platform/rp2xx0
-D__PLAT_RP2040__
# -D _POSIX_THREADS
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> -<mesh/wifi/> -<mesh/http/> -<mesh/raspihttp>
lib_ignore =
BluetoothOTA
lib_deps =
${arduino_base.lib_deps}
${environmental_base.lib_deps}
rweather/Crypto

View File

@@ -22,7 +22,7 @@ build_flags =
-fdata-sections
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/RemoteHardwareModule.cpp> -<platform/nrf52> -<platform/portduino> -<platform/rp2040> -<mesh/raspihttp>
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/RemoteHardwareModule.cpp> -<platform/nrf52> -<platform/portduino> -<platform/rp2xx0> -<mesh/raspihttp>
board_upload.offset_address = 0x08000000
upload_protocol = stlink

View File

@@ -5,7 +5,7 @@
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_NRF52840_PCA10056 -DNRF52840_XXAA",
"extra_flags": "-DHELTEC_T114 -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x4405"],

View File

@@ -1,40 +0,0 @@
{
"build": {
"arduino": {
"ldscript": "nrf52832_s132_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DNRF52832_XXAA -DNRF52",
"f_cpu": "64000000L",
"mcu": "nrf52832",
"variant": "lora_isp4520",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS132",
"sd_name": "s132",
"sd_version": "6.1.1",
"sd_fwid": "0x00B7"
}
},
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52832_xxAA",
"svd_path": "nrf52.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino"],
"name": "lora ISP4520",
"upload": {
"maximum_ram_size": 65536,
"maximum_size": 524288,
"require_upload_port": true,
"speed": 115200,
"protocol": "nrfutil",
"protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"]
},
"url": "",
"vendor": "PsiSoft"
}

View File

@@ -5,7 +5,7 @@
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_WIO_WM1110 -DNRF52840_XXAA",
"extra_flags": "-DME25LS01_4Y10TD -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x8029"],

View File

@@ -5,7 +5,7 @@
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_WIO_WM1110 -DNRF52840_XXAA",
"extra_flags": "-DMS24SF1 -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x8029"],

View File

@@ -5,7 +5,7 @@
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA",
"extra_flags": "-DNORDIC_PCA10059 -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x8029"],

View File

@@ -0,0 +1,42 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"partitions": "default_8MB.csv",
"memory_type": "qio_opi"
},
"core": "esp32",
"extra_flags": [
"-DBOARD_HAS_PSRAM",
"-DARDUINO_USB_CDC_ON_BOOT=0",
"-DARDUINO_USB_MODE=1",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=1"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"hwids": [["0x1A86", "0x7523"]],
"mcu": "esp32s3",
"variant": "esp32s3r8"
},
"connectivity": ["wifi", "bluetooth", "lora"],
"debug": {
"default_tool": "esp-builtin",
"onboard_tools": ["esp-builtin"],
"openocd_target": "esp32s3.cfg"
},
"frameworks": ["arduino"],
"name": "Seeed Studio SenseCAP Indicator",
"upload": {
"flash_size": "8MB",
"maximum_ram_size": 327680,
"maximum_size": 8388608,
"require_upload_port": true,
"use_1200bps_touch": true,
"wait_for_upload_port": true,
"speed": 921600
},
"url": "https://www.seeedstudio.com/Indicator-for-Meshtastic.html",
"vendor": "Seeed Studio"
}

View File

@@ -81,14 +81,14 @@ build_flags = -Wno-missing-field-initializers
-DRADIOLIB_EXCLUDE_APRS
-DRADIOLIB_EXCLUDE_LORAWAN
-DMESHTASTIC_EXCLUDE_DROPZONE=1
-DBUILD_EPOCH=$UNIX_TIME
;-D OLED_PL
monitor_speed = 115200
monitor_filters = direct
lib_deps =
; jgromes/RadioLib@~6.6.0
https://github.com/jgromes/RadioLib.git#3115fc2d6700a9aee05888791ac930a910f2628f
jgromes/RadioLib@~7.0.0
https://github.com/meshtastic/esp8266-oled-ssd1306.git#e16cee124fe26490cb14880c679321ad8ac89c95 ; ESP8266_SSD1306
https://github.com/mathertel/OneButton@~2.6.1 ; OneButton library for non-blocking button debounce
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
@@ -156,8 +156,9 @@ lib_deps =
https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.7.2502
boschsensortec/BME68x Sensor Library@^1.1.40407
https://github.com/KodinLanewave/INA3221@^1.0.0
lewisxhe/SensorLib@^0.2.0
lewisxhe/SensorLib@0.2.0
mprograms/QMC5883LCompass@^1.2.0
https://github.com/meshtastic/DFRobot_LarkWeatherStation#dee914270dc7cb3e43fbf034edd85a63a16a12ee
https://github.com/meshtastic/DFRobot_LarkWeatherStation#dee914270dc7cb3e43fbf034edd85a63a16a12ee
https://github.com/gjelsoe/STK8xxx-Accelerometer.git#v0.1.1

View File

@@ -11,6 +11,9 @@
#include <Adafruit_LIS3DH.h>
#include <Adafruit_LSM6DS3TRC.h>
#include <Adafruit_MPU6050.h>
#ifdef STK8XXX_INT
#include <stk8baxx.h>
#endif
#include <Arduino.h>
#include <SensorBMA423.hpp>
#include <Wire.h>
@@ -24,6 +27,8 @@
#define ACCELEROMETER_CHECK_INTERVAL_MS 100
#define ACCELEROMETER_CLICK_THRESHOLD 40
volatile static bool STK_IRQ;
static inline int readRegister(uint8_t address, uint8_t reg, uint8_t *data, uint8_t len)
{
Wire.beginTransmission(address);
@@ -79,6 +84,11 @@ class AccelerometerThread : public concurrency::OSThread
if (acceleremoter_type == ScanI2C::DeviceType::MPU6050 && mpu.getMotionInterruptStatus()) {
wakeScreen();
} else if (acceleremoter_type == ScanI2C::DeviceType::STK8BAXX && STK_IRQ) {
STK_IRQ = false;
if (config.display.wake_on_tap_or_motion) {
wakeScreen();
}
} else if (acceleremoter_type == ScanI2C::DeviceType::LIS3DH && lis.getClick() > 0) {
uint8_t click = lis.getClick();
if (!config.device.double_tap_as_button_press) {
@@ -188,6 +198,15 @@ class AccelerometerThread : public concurrency::OSThread
mpu.setMotionDetectionDuration(20);
mpu.setInterruptPinLatch(true); // Keep it latched. Will turn off when reinitialized.
mpu.setInterruptPinPolarity(true);
#ifdef STK8XXX_INT
} else if (acceleremoter_type == ScanI2C::DeviceType::STK8BAXX && stk8baxx.STK8xxx_Initialization(STK8xxx_VAL_RANGE_2G)) {
STK_IRQ = false;
LOG_DEBUG("STX8BAxx initialized\n");
stk8baxx.STK8xxx_Anymotion_init();
pinMode(STK8XXX_INT, INPUT_PULLUP);
attachInterrupt(
digitalPinToInterrupt(STK8XXX_INT), [] { STK_IRQ = true; }, RISING);
#endif
} else if (acceleremoter_type == ScanI2C::DeviceType::LIS3DH && lis.begin(accelerometer_found.address)) {
LOG_DEBUG("LIS3DH initializing\n");
lis.setRange(LIS3DH_RANGE_2_G);
@@ -262,6 +281,9 @@ class AccelerometerThread : public concurrency::OSThread
ScanI2C::DeviceType acceleremoter_type;
Adafruit_MPU6050 mpu;
Adafruit_LIS3DH lis;
#ifdef STK8XXX_INT
STK8xxx stk8baxx;
#endif
Adafruit_LSM6DS3TRC lsm;
SensorBMA423 bmaSensor;
bool BMA_IRQ = false;

View File

@@ -97,12 +97,14 @@ Syslog &Syslog::logMask(uint8_t priMask)
void Syslog::enable()
{
this->_client->begin(this->_port);
this->_enabled = true;
}
void Syslog::disable()
{
this->_enabled = false;
this->_client->stop();
}
bool Syslog::isEnabled()
@@ -193,4 +195,4 @@ inline bool Syslog::_sendLog(uint16_t pri, const char *appName, const char *mess
return true;
}
#endif
#endif

View File

@@ -13,6 +13,7 @@
#include "power.h"
#include "NodeDB.h"
#include "PowerFSM.h"
#include "Throttle.h"
#include "buzz/buzz.h"
#include "configuration.h"
#include "main.h"
@@ -30,6 +31,7 @@
#if HAS_WIFI
#include <WiFi.h>
#endif
#endif
#ifndef DELAY_FOREVER
@@ -244,7 +246,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
config.power.adc_multiplier_override > 0 ? config.power.adc_multiplier_override : ADC_MULTIPLIER;
// Do not call analogRead() often.
const uint32_t min_read_interval = 5000;
if (millis() - last_read_time_ms > min_read_interval) {
if (!Throttle::isWithinTimespanMs(last_read_time_ms, min_read_interval)) {
last_read_time_ms = millis();
uint32_t raw = 0;

View File

@@ -1,6 +1,8 @@
#include "SerialConsole.h"
#include "Default.h"
#include "NodeDB.h"
#include "PowerFSM.h"
#include "Throttle.h"
#include "configuration.h"
#include "time.h"
@@ -47,7 +49,7 @@ SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port), con
#if defined(ARCH_NRF52) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARCH_RP2040)
time_t timeout = millis();
while (!Port) {
if ((millis() - timeout) < 5000) {
if (Throttle::isWithinTimespanMs(timeout, FIVE_SECONDS_MS)) {
delay(100);
} else {
break;
@@ -72,8 +74,7 @@ void SerialConsole::flush()
// For the serial port we can't really detect if any client is on the other side, so instead just look for recent messages
bool SerialConsole::checkIsConnected()
{
uint32_t now = millis();
return (now - lastContactMsec) < SERIAL_CONNECTION_TIMEOUT;
return Throttle::isWithinTimespanMs(lastContactMsec, SERIAL_CONNECTION_TIMEOUT);
}
/**
@@ -120,4 +121,4 @@ void SerialConsole::log_to_serial(const char *logLevel, const char *format, va_l
emitLogRecord(ll, thread ? thread->ThreadName.c_str() : "", format, arg);
} else
RedirectablePrint::log_to_serial(logLevel, format, arg);
}
}

View File

@@ -124,7 +124,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define INA3221_ADDR 0x42
#define QMC6310_ADDR 0x1C
#define QMI8658_ADDR 0x6B
#define QMC5883L_ADDR 0x1E
#define QMC5883L_ADDR 0x0D
#define HMC5883L_ADDR 0x1E
#define SHTC3_ADDR 0x70
#define LPS22HB_ADDR 0x5C
#define LPS22HB_ADDR_ALT 0x5D
@@ -144,6 +145,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// ACCELEROMETER
// -----------------------------------------------------------------------------
#define MPU6050_ADDR 0x68
#define STK8BXX_ADR 0x18
#define LIS3DH_ADR 0x18
#define BMA423_ADDR 0x19
#define LSM6DS3_ADDR 0x6A
@@ -162,6 +164,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// -----------------------------------------------------------------------------
// IO Expander
// -----------------------------------------------------------------------------
#define TCA9535_ADDR 0x20
#define TCA9555_ADDR 0x26
// -----------------------------------------------------------------------------
@@ -171,6 +174,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define GPS_THREAD_INTERVAL 200
#endif
// -----------------------------------------------------------------------------
// Touchscreen
// -----------------------------------------------------------------------------
#define FT6336U_ADDR 0x48
// convert 24-bit color to 16-bit (56K)
#define COLOR565(r, g, b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3))
@@ -202,6 +210,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MINIMUM_SAFE_FREE_HEAP 1500
#endif
#ifndef WIRE_INTERFACES_COUNT
// Officially an NRF52 macro
// Repurposed cross-platform to identify devices using Wire1
#if defined(I2C_SDA1) || defined(PIN_WIRE1_SDA)
#define WIRE_INTERFACES_COUNT 2
#elif HAS_WIRE
#define WIRE_INTERFACES_COUNT 1
#endif
#endif
/* Step #3: mop up with disabled values for HAS_ options not handled by the above two */
#ifndef HAS_WIFI
@@ -324,4 +342,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

@@ -37,8 +37,8 @@ ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const
{
ScanI2C::DeviceType types[] = {MPU6050, LIS3DH, BMA423, LSM6DS3, BMX160};
return firstOfOrNONE(5, types);
ScanI2C::DeviceType types[] = {MPU6050, LIS3DH, BMA423, LSM6DS3, BMX160, STK8BAXX};
return firstOfOrNONE(6, types);
}
ScanI2C::FoundDevice ScanI2C::find(ScanI2C::DeviceType) const

View File

@@ -36,12 +36,14 @@ class ScanI2C
QMC6310,
QMI8658,
QMC5883L,
HMC5883L,
PMSA0031,
MPU6050,
LIS3DH,
BMA423,
BQ24295,
LSM6DS3,
TCA9535,
TCA9555,
VEML7700,
RCWL9620,
@@ -52,7 +54,9 @@ class ScanI2C
AHT10,
BMX160,
DFROBOT_LARK,
NAU7802
NAU7802,
FT6336U,
STK8BAXX
} DeviceType;
// typedef uint8_t DeviceAddress;
@@ -115,4 +119,4 @@ class ScanI2C
private:
bool shouldSuppressScreen = false;
};
};

View File

@@ -162,13 +162,13 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
Melopero_RV3028 rtc;
#endif
#ifdef I2C_SDA1
#if WIRE_INTERFACES_COUNT == 2
if (port == I2CPort::WIRE1) {
i2cBus = &Wire1;
} else {
#endif
i2cBus = &Wire;
#ifdef I2C_SDA1
#if WIRE_INTERFACES_COUNT == 2
}
#endif
@@ -313,17 +313,33 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
}
break;
case MCP9808_ADDR:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x07), 2);
if (registerValue == 0x0400) {
type = MCP9808;
LOG_INFO("MCP9808 sensor found\n");
} else {
type = LIS3DH;
LOG_INFO("LIS3DH accelerometer found\n");
// 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.
{
// 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\n");
break;
}
// 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\n");
break;
}
// Check register 0x0F for 0x3300 response to ID LIS3DH chip.
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\n");
}
break;
}
break;
case SHT31_4x_ADDR:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x89), 2);
if (registerValue == 0x11a2 || registerValue == 0x11da || registerValue == 0xe9c) {
@@ -365,18 +381,21 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
break;
SCAN_SIMPLE_CASE(QMC5883L_ADDR, QMC5883L, "QMC5883L Highrate 3-Axis magnetic sensor found\n")
SCAN_SIMPLE_CASE(HMC5883L_ADDR, HMC5883L, "HMC5883L 3-Axis digital compass found\n")
SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031 air quality sensor found\n")
SCAN_SIMPLE_CASE(MPU6050_ADDR, MPU6050, "MPU6050 accelerometer found\n");
SCAN_SIMPLE_CASE(BMX160_ADDR, BMX160, "BMX160 accelerometer found\n");
SCAN_SIMPLE_CASE(BMA423_ADDR, BMA423, "BMA423 accelerometer found\n");
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3 accelerometer found at address 0x%x\n", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(TCA9535_ADDR, TCA9535, "TCA9535 I2C expander found\n");
SCAN_SIMPLE_CASE(TCA9555_ADDR, TCA9555, "TCA9555 I2C expander found\n");
SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700 light sensor found\n");
SCAN_SIMPLE_CASE(TSL25911_ADDR, TSL2591, "TSL2591 light sensor found\n");
SCAN_SIMPLE_CASE(OPT3001_ADDR, OPT3001, "OPT3001 light sensor found\n");
SCAN_SIMPLE_CASE(MLX90632_ADDR, MLX90632, "MLX90632 IR temp sensor found\n");
SCAN_SIMPLE_CASE(NAU7802_ADDR, NAU7802, "NAU7802 based scale found\n");
SCAN_SIMPLE_CASE(FT6336U_ADDR, FT6336U, "FT6336U touchscreen found\n");
default:
LOG_INFO("Device found at address 0x%x was not able to be enumerated\n", addr.address);
@@ -403,7 +422,7 @@ TwoWire *ScanI2CTwoWire::fetchI2CBus(ScanI2C::DeviceAddress address) const
if (address.port == ScanI2C::I2CPort::WIRE) {
return &Wire;
} else {
#ifdef I2C_SDA1
#if WIRE_INTERFACES_COUNT == 2
return &Wire1;
#else
return &Wire;
@@ -415,4 +434,4 @@ size_t ScanI2CTwoWire::countDevices() const
{
return foundDevices.size();
}
#endif
#endif

View File

@@ -6,6 +6,7 @@
#include "NodeDB.h"
#include "PowerMon.h"
#include "RTC.h"
#include "Throttle.h"
#include "main.h" // pmu_found
#include "sleep.h"
@@ -26,6 +27,8 @@
#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;
#endif
@@ -166,18 +169,21 @@ GPS_RESPONSE GPS::getACK(const char *message, uint32_t waitMillis)
b = _serial_gps->read();
#ifdef GPS_DEBUG
LOG_DEBUG("%02X", (char *)buffer);
LOG_DEBUG("%c", (b >= 32 && b <= 126) ? b : '.');
#endif
buffer[bytesRead] = b;
bytesRead++;
if ((bytesRead == 767) || (b == '\r')) {
if (strnstr((char *)buffer, message, bytesRead) != nullptr) {
#ifdef GPS_DEBUG
LOG_DEBUG("\r");
LOG_DEBUG("\r\nFound: %s\r\n", message); // Log the found message
#endif
return GNSS_RESPONSE_OK;
} else {
bytesRead = 0;
#ifdef GPS_DEBUG
LOG_DEBUG("\r\n");
#endif
}
}
}
@@ -201,7 +207,7 @@ GPS_RESPONSE GPS::getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMilli
// ACK-NACK| 0xBA | 0xCE | 0x04 | 0x00 | 0x05 | 0x00 | 0xXX | 0xXX | 0x00 | 0x00 | 0xXX | 0xXX | 0xXX | 0xXX |
// ACK-ACK | 0xBA | 0xCE | 0x04 | 0x00 | 0x05 | 0x01 | 0xXX | 0xXX | 0x00 | 0x00 | 0xXX | 0xXX | 0xXX | 0xXX |
while (millis() - startTime < waitMillis) {
while (Throttle::isWithinTimespanMs(startTime, waitMillis)) {
if (_serial_gps->available()) {
buffer[bufferPos++] = _serial_gps->read();
@@ -270,7 +276,7 @@ GPS_RESPONSE GPS::getACK(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis)
buf[9] += buf[8];
}
while (millis() - startTime < waitMillis) {
while (Throttle::isWithinTimespanMs(startTime, waitMillis)) {
if (ack > 9) {
#ifdef GPS_DEBUG
LOG_DEBUG("\n");
@@ -327,7 +333,7 @@ int GPS::getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
uint32_t startTime = millis();
uint16_t needRead;
while (millis() - startTime < waitMillis) {
while (Throttle::isWithinTimespanMs(startTime, waitMillis)) {
if (_serial_gps->available()) {
int c = _serial_gps->read();
switch (ubxFrameCounter) {
@@ -505,283 +511,110 @@ bool GPS::setup()
delay(250);
_serial_gps->write("$CFGMSG,6,1,0\r\n");
delay(250);
} else if (gnssModel == GNSS_MODEL_AG3335) {
} else if (gnssModel == GNSS_MODEL_AG3335 || gnssModel == GNSS_MODEL_AG3352) {
_serial_gps->write("$PAIR066,1,0,1,0,0,1*3B"); // Enable GPS+GALILEO+NAVIC
_serial_gps->write("$PAIR066,1,0,1,0,0,1*3B\r\n"); // Enable GPS+GALILEO+NAVIC
// Configure NMEA (sentences will output once per fix)
_serial_gps->write("$PAIR062,0,0*3F"); // GGA ON
_serial_gps->write("$PAIR062,1,0*3F"); // GLL OFF
_serial_gps->write("$PAIR062,2,1*3D"); // GSA ON
_serial_gps->write("$PAIR062,3,0*3D"); // GSV OFF
_serial_gps->write("$PAIR062,4,0*3B"); // RMC ON
_serial_gps->write("$PAIR062,5,0*3B"); // VTG OFF
_serial_gps->write("$PAIR062,6,1*39"); // ZDA ON
_serial_gps->write("$PAIR062,0,1*3F\r\n"); // GGA ON
_serial_gps->write("$PAIR062,1,0*3F\r\n"); // GLL OFF
_serial_gps->write("$PAIR062,2,0*3C\r\n"); // GSA OFF
_serial_gps->write("$PAIR062,3,0*3D\r\n"); // GSV OFF
_serial_gps->write("$PAIR062,4,1*3B\r\n"); // RMC ON
_serial_gps->write("$PAIR062,5,0*3B\r\n"); // VTG OFF
_serial_gps->write("$PAIR062,6,0*38\r\n"); // ZDA ON
delay(250);
_serial_gps->write("$PAIR513*3D"); // save configuration
_serial_gps->write("$PAIR513*3D\r\n"); // save configuration
} else if (gnssModel == GNSS_MODEL_UBLOX6) {
clearBuffer();
SEND_UBX_PACKET(0x06, 0x02, _message_DISABLE_TXT_INFO, "Unable to disable text info messages.\n", 500);
SEND_UBX_PACKET(0x06, 0x39, _message_JAM_6_7, "Unable to enable interference resistance.\n", 500);
SEND_UBX_PACKET(0x06, 0x23, _message_NAVX5, "Unable to configure NAVX5 settings.\n", 500);
} else if (gnssModel == GNSS_MODEL_UBLOX) {
// Configure GNSS system to GPS+SBAS+GLONASS (Module may restart after this command)
// We need set it because by default it is GPS only, and we want to use GLONASS too
// Also we need SBAS for better accuracy and extra features
// ToDo: Dynamic configure GNSS systems depending of LoRa region
// Turn off unwanted NMEA messages, set update rate
SEND_UBX_PACKET(0x06, 0x08, _message_1HZ, "Unable to set GPS update rate.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_GLL, "Unable to disable NMEA GLL.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_GSA, "Unable to Enable NMEA GSA.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_GSV, "Unable to disable NMEA GSV.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_VTG, "Unable to disable NMEA VTG.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_RMC, "Unable to enable NMEA RMC.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_GGA, "Unable to enable NMEA GGA.\n", 500);
if (strncmp(info.hwVersion, "000A0000", 8) != 0) {
if (strncmp(info.hwVersion, "00040007", 8) != 0) {
// The original ublox Neo-6 is GPS only and doesn't support the UBX-CFG-GNSS message
// Max7 seems to only support GPS *or* GLONASS
// Neo-7 is supposed to support GPS *and* GLONASS but NAKs the CFG-GNSS command to do it
// So treat all the u-blox 7 series as GPS only
// M8 can support 3 constallations at once so turn on GPS, GLONASS and Galileo (or BeiDou)
clearBuffer();
SEND_UBX_PACKET(0x06, 0x11, _message_CFG_RXM_ECO, "Unable to enable powersaving ECO mode for Neo-6.\n", 500);
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "Unable to enable powersaving details for GPS.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_AID, "Unable to disable UBX-AID.\n", 500);
if (strncmp(info.hwVersion, "00070000", 8) == 0) {
LOG_DEBUG("Setting GPS+SBAS\n");
msglen = makeUBXPacket(0x06, 0x3e, sizeof(_message_GNSS_7), _message_GNSS_7);
_serial_gps->write(UBXscratch, msglen);
} else {
msglen = makeUBXPacket(0x06, 0x3e, sizeof(_message_GNSS_8), _message_GNSS_8);
_serial_gps->write(UBXscratch, msglen);
}
msglen = makeUBXPacket(0x06, 0x09, sizeof(_message_SAVE), _message_SAVE);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x09, 2000) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to save GNSS module configuration.\n");
} else {
LOG_INFO("GNSS module configuration saved!\n");
}
} else if (gnssModel == GNSS_MODEL_UBLOX7 || gnssModel == GNSS_MODEL_UBLOX8 || gnssModel == GNSS_MODEL_UBLOX9) {
if (gnssModel == GNSS_MODEL_UBLOX7) {
LOG_DEBUG("Setting GPS+SBAS\n");
msglen = makeUBXPacket(0x06, 0x3e, sizeof(_message_GNSS_7), _message_GNSS_7);
_serial_gps->write(UBXscratch, msglen);
} else { // 8,9
msglen = makeUBXPacket(0x06, 0x3e, sizeof(_message_GNSS_8), _message_GNSS_8);
_serial_gps->write(UBXscratch, msglen);
}
if (getACK(0x06, 0x3e, 800) == GNSS_RESPONSE_NAK) {
// It's not critical if the module doesn't acknowledge this configuration.
LOG_INFO("Unable to reconfigure GNSS - defaults maintained. Is this module GPS-only?\n");
} else {
if (strncmp(info.hwVersion, "00070000", 8) == 0) {
LOG_INFO("GNSS configured for GPS+SBAS. Pause for 0.75s before sending next command.\n");
} else {
LOG_INFO(
"GNSS configured for GPS+SBAS+GLONASS+Galileo. Pause for 0.75s before sending next command.\n");
}
// Documentation say, we need wait atleast 0.5s after reconfiguration of GNSS module, before sending next
// commands for the M8 it tends to be more... 1 sec should be enough ;>)
delay(1000);
}
if (getACK(0x06, 0x3e, 800) == GNSS_RESPONSE_NAK) {
// It's not critical if the module doesn't acknowledge this configuration.
LOG_INFO("Unable to reconfigure GNSS - defaults maintained. Is this module GPS-only?\n");
} else {
if (gnssModel == GNSS_MODEL_UBLOX7) {
LOG_INFO("GNSS configured for GPS+SBAS.\n");
} else { // 8,9
LOG_INFO("GNSS configured for GPS+SBAS+GLONASS+Galileo.\n");
}
// Disable Text Info messages
msglen = makeUBXPacket(0x06, 0x02, sizeof(_message_DISABLE_TXT_INFO), _message_DISABLE_TXT_INFO);
// Documentation say, we need wait atleast 0.5s after reconfiguration of GNSS module, before sending next
// commands for the M8 it tends to be more... 1 sec should be enough ;>)
delay(1000);
}
// Disable Text Info messages //6,7,8,9
clearBuffer();
SEND_UBX_PACKET(0x06, 0x02, _message_DISABLE_TXT_INFO, "Unable to disable text info messages.\n", 500);
if (gnssModel == GNSS_MODEL_UBLOX8) { // 8
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x02, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable text info messages.\n");
}
// ToDo add M10 tests for below
if (strncmp(info.hwVersion, "00080000", 8) == 0) {
msglen = makeUBXPacket(0x06, 0x39, sizeof(_message_JAM_8), _message_JAM_8);
SEND_UBX_PACKET(0x06, 0x39, _message_JAM_8, "Unable to enable interference resistance.\n", 500);
clearBuffer();
SEND_UBX_PACKET(0x06, 0x23, _message_NAVX5_8, "Unable to configure NAVX5_8 settings.\n", 500);
} else { // 6,7,9
SEND_UBX_PACKET(0x06, 0x39, _message_JAM_6_7, "Unable to enable interference resistance.\n", 500);
SEND_UBX_PACKET(0x06, 0x23, _message_NAVX5, "Unable to configure NAVX5 settings.\n", 500);
}
// Turn off unwanted NMEA messages, set update rate
SEND_UBX_PACKET(0x06, 0x08, _message_1HZ, "Unable to set GPS update rate.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_GLL, "Unable to disable NMEA GLL.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_GSA, "Unable to Enable NMEA GSA.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_GSV, "Unable to disable NMEA GSV.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_VTG, "Unable to disable NMEA VTG.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_RMC, "Unable to enable NMEA RMC.\n", 500);
SEND_UBX_PACKET(0x06, 0x01, _message_GGA, "Unable to enable NMEA GGA.\n", 500);
if (uBloxProtocolVersion >= 18) {
clearBuffer();
SEND_UBX_PACKET(0x06, 0x86, _message_PMS, "Unable to enable powersaving for GPS.\n", 500);
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "Unable to enable powersaving details for GPS.\n", 500);
// For M8 we want to enable NMEA vserion 4.10 so we can see the additional sats.
if (gnssModel == GNSS_MODEL_UBLOX8) {
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x39, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable interference resistance.\n");
}
msglen = makeUBXPacket(0x06, 0x23, sizeof(_message_NAVX5_8), _message_NAVX5_8);
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x23, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to configure NAVX5_8 settings.\n");
}
} else {
msglen = makeUBXPacket(0x06, 0x39, sizeof(_message_JAM_6_7), _message_JAM_6_7);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x39, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable interference resistance.\n");
}
msglen = makeUBXPacket(0x06, 0x23, sizeof(_message_NAVX5), _message_NAVX5);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x23, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to configure NAVX5 settings.\n");
}
}
// Turn off unwanted NMEA messages, set update rate
msglen = makeUBXPacket(0x06, 0x08, sizeof(_message_1HZ), _message_1HZ);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x08, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to set GPS update rate.\n");
}
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GLL), _message_GLL);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable NMEA GLL.\n");
}
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GSA), _message_GSA);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to Enable NMEA GSA.\n");
}
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GSV), _message_GSV);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable NMEA GSV.\n");
}
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_VTG), _message_VTG);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable NMEA VTG.\n");
}
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_RMC), _message_RMC);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable NMEA RMC.\n");
}
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GGA), _message_GGA);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable NMEA GGA.\n");
}
if (uBloxProtocolVersion >= 18) {
msglen = makeUBXPacket(0x06, 0x86, sizeof(_message_PMS), _message_PMS);
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x86, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving for GPS.\n");
}
msglen = makeUBXPacket(0x06, 0x3B, sizeof(_message_CFG_PM2), _message_CFG_PM2);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x3B, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving details for GPS.\n");
}
// For M8 we want to enable NMEA vserion 4.10 so we can see the additional sats.
if (strncmp(info.hwVersion, "00080000", 8) == 0) {
msglen = makeUBXPacket(0x06, 0x17, sizeof(_message_NMEA), _message_NMEA);
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x17, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable NMEA 4.10.\n");
}
}
} else {
if (strncmp(info.hwVersion, "00040007", 8) == 0) { // This PSM mode is only for Neo-6
msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_ECO);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x11, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving ECO mode for Neo-6.\n");
}
msglen = makeUBXPacket(0x06, 0x3B, sizeof(_message_CFG_PM2), _message_CFG_PM2);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x3B, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving details for GPS.\n");
}
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_AID), _message_AID);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable UBX-AID.\n");
}
} else {
msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_PSM);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x11, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving mode for GPS.\n");
}
msglen = makeUBXPacket(0x06, 0x3B, sizeof(_message_CFG_PM2), _message_CFG_PM2);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x3B, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving details for GPS.\n");
}
}
SEND_UBX_PACKET(0x06, 0x17, _message_NMEA, "Unable to enable NMEA 4.10.\n", 500);
}
} else {
// LOG_INFO("u-blox M10 hardware found.\n");
delay(1000);
// First disable all NMEA messages in RAM layer
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_NMEA_RAM), _message_VALSET_DISABLE_NMEA_RAM);
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable NMEA messages for M10 GPS RAM.\n");
}
delay(250);
// Next disable unwanted NMEA messages in BBR layer
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_NMEA_BBR), _message_VALSET_DISABLE_NMEA_BBR);
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable NMEA messages for M10 GPS BBR.\n");
}
delay(250);
// Disable Info txt messages in RAM layer
msglen =
makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_TXT_INFO_RAM), _message_VALSET_DISABLE_TXT_INFO_RAM);
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable Info messages for M10 GPS RAM.\n");
}
delay(250);
// Next disable Info txt messages in BBR layer
msglen =
makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_TXT_INFO_BBR), _message_VALSET_DISABLE_TXT_INFO_BBR);
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable Info messages for M10 GPS BBR.\n");
}
// Do M10 configuration for Power Management.
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_PM_RAM), _message_VALSET_PM_RAM);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving for M10 GPS RAM.\n");
}
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_PM_BBR), _message_VALSET_PM_BBR);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving for M10 GPS BBR.\n");
}
delay(250);
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_ITFM_RAM), _message_VALSET_ITFM_RAM);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable Jamming detection M10 GPS RAM.\n");
}
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_ITFM_BBR), _message_VALSET_ITFM_BBR);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable Jamming detection M10 GPS BBR.\n");
}
// Here is where the init commands should go to do further M10 initialization.
delay(250);
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_SBAS_RAM), _message_VALSET_DISABLE_SBAS_RAM);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable SBAS M10 GPS RAM.\n");
}
delay(750); // will cause a receiver restart so wait a bit
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_SBAS_BBR), _message_VALSET_DISABLE_SBAS_BBR);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable SBAS M10 GPS BBR.\n");
}
delay(750); // will cause a receiver restart so wait a bit
// Done with initialization, Now enable wanted NMEA messages in BBR layer so they will survive a periodic sleep.
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_ENABLE_NMEA_BBR), _message_VALSET_ENABLE_NMEA_BBR);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable messages for M10 GPS BBR.\n");
}
delay(250);
// Next enable wanted NMEA messages in RAM layer
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_ENABLE_NMEA_RAM), _message_VALSET_ENABLE_NMEA_RAM);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable messages for M10 GPS RAM.\n");
}
// As the M10 has no flash, the best we can do to preserve the config is to set it in RAM and BBR.
// BBR will survive a restart, and power off for a while, but modules with small backup
// batteries or super caps will not retain the config for a long power off time.
SEND_UBX_PACKET(0x06, 0x11, _message_CFG_RXM_PSM, "Unable to enable powersaving mode for GPS.\n", 500);
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "Unable to enable powersaving details for GPS.\n", 500);
}
msglen = makeUBXPacket(0x06, 0x09, sizeof(_message_SAVE), _message_SAVE);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x09, 2000) != GNSS_RESPONSE_OK) {
@@ -789,6 +622,55 @@ bool GPS::setup()
} else {
LOG_INFO("GNSS module configuration saved!\n");
}
} else if (gnssModel == GNSS_MODEL_UBLOX10) {
delay(1000);
clearBuffer();
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_NMEA_RAM, "Unable to disable NMEA messages in M10 RAM.\n", 300);
delay(750);
clearBuffer();
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_NMEA_BBR, "Unable to disable NMEA messages in M10 BBR.\n", 300);
delay(750);
clearBuffer();
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_TXT_INFO_RAM,
"Unable to disable Info messages for M10 GPS RAM.\n", 300);
delay(750);
// Next disable Info txt messages in BBR layer
clearBuffer();
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_TXT_INFO_BBR,
"Unable to disable Info messages for M10 GPS BBR.\n", 300);
delay(750);
// Do M10 configuration for Power Management.
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_PM_RAM, "Unable to enable powersaving for M10 GPS RAM.\n", 300);
delay(750);
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_PM_BBR, "Unable to enable powersaving for M10 GPS BBR.\n", 300);
delay(750);
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ITFM_RAM, "Unable to enable Jamming detection M10 GPS RAM.\n", 300);
delay(750);
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ITFM_BBR, "Unable to enable Jamming detection M10 GPS BBR.\n", 300);
delay(750);
// Here is where the init commands should go to do further M10 initialization.
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_SBAS_RAM, "Unable to disable SBAS M10 GPS RAM.\n", 300);
delay(750); // will cause a receiver restart so wait a bit
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_SBAS_BBR, "Unable to disable SBAS M10 GPS BBR.\n", 300);
delay(750); // will cause a receiver restart so wait a bit
// Done with initialization, Now enable wanted NMEA messages in BBR layer so they will survive a periodic sleep.
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ENABLE_NMEA_BBR, "Unable to enable messages for M10 GPS BBR.\n", 300);
delay(750);
// Next enable wanted NMEA messages in RAM layer
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ENABLE_NMEA_RAM, "Unable to enable messages for M10 GPS RAM.\n", 500);
delay(750);
// As the M10 has no flash, the best we can do to preserve the config is to set it in RAM and BBR.
// BBR will survive a restart, and power off for a while, but modules with small backup
// batteries or super caps will not retain the config for a long power off time.
msglen = makeUBXPacket(0x06, 0x09, sizeof(_message_SAVE_10), _message_SAVE_10);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x09, 2000) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to save GNSS module configuration.\n");
} else {
LOG_INFO("GNSS module configuration saved!\n");
}
}
didSerialInit = true;
}
@@ -944,7 +826,8 @@ void GPS::setPowerPMU(bool on)
void GPS::setPowerUBLOX(bool on, uint32_t sleepMs)
{
// Abort: if not UBLOX hardware
if (gnssModel != GNSS_MODEL_UBLOX)
if (!(gnssModel == GNSS_MODEL_UBLOX6 || gnssModel == GNSS_MODEL_UBLOX7 || gnssModel == GNSS_MODEL_UBLOX8 ||
gnssModel == GNSS_MODEL_UBLOX9 || gnssModel == GNSS_MODEL_UBLOX10))
return;
// If waking
@@ -967,7 +850,7 @@ void GPS::setPowerUBLOX(bool on, uint32_t sleepMs)
}
// Determine hardware version
if (strncmp(info.hwVersion, "000A0000", 8) != 0) {
if (gnssModel == GNSS_MODEL_UBLOX10) {
// Encode the sleep time in millis into the packet
for (int i = 0; i < 4; i++)
gps->_message_PMREQ[0 + i] = sleepMs >> (i * 8);
@@ -1019,14 +902,16 @@ void GPS::down()
LOG_DEBUG("%us until next search\n", sleepTime / 1000);
// If update interval less than 10 seconds, no attempt to sleep
if (updateInterval <= 10 * 1000UL)
if (updateInterval <= 10 * 1000UL || sleepTime == 0)
setPowerState(GPS_IDLE);
else {
// Check whether the GPS hardware is capable of GPS_SOFTSLEEP
// If not, fallback to GPS_HARDSLEEP instead
bool softsleepSupported = false;
if (gnssModel == GNSS_MODEL_UBLOX) // U-blox is supported via PMREQ
// U-blox is supported via PMREQ
if (gnssModel == GNSS_MODEL_UBLOX6 || gnssModel == GNSS_MODEL_UBLOX7 || gnssModel == GNSS_MODEL_UBLOX8 ||
gnssModel == GNSS_MODEL_UBLOX9 || gnssModel == GNSS_MODEL_UBLOX10)
softsleepSupported = true;
#ifdef PIN_GPS_STANDBY // L76B, L76K and clones have a standby pin
softsleepSupported = true;
@@ -1101,7 +986,9 @@ int32_t GPS::runOnce()
// if we have received valid NMEA claim we are connected
setConnected();
} else {
if ((config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) && (gnssModel == GNSS_MODEL_UBLOX)) {
if ((config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) &&
(gnssModel == GNSS_MODEL_UBLOX6 || gnssModel == GNSS_MODEL_UBLOX7 || gnssModel == GNSS_MODEL_UBLOX8 ||
gnssModel == GNSS_MODEL_UBLOX9 || gnssModel == GNSS_MODEL_UBLOX10)) {
// reset the GPS on next bootup
if (devicestate.did_gps_reset && scheduling.elapsedSearchMs() > 60 * 1000UL && !hasFlow()) {
LOG_DEBUG("GPS is not communicating, trying factory reset on next bootup.\n");
@@ -1184,25 +1071,31 @@ int GPS::prepareDeepSleep(void *unused)
return 0;
}
#define PROBE_SIMPLE(CHIP, TOWRITE, RESPONSE, DRIVER, TIMEOUT, ...) \
LOG_DEBUG("Trying " TOWRITE " (" CHIP ") ...\n"); \
clearBuffer(); \
_serial_gps->write(TOWRITE "\r\n"); \
if (getACK(RESPONSE, TIMEOUT) == GNSS_RESPONSE_OK) { \
LOG_INFO(CHIP " detected, using " #DRIVER " Module\n"); \
return DRIVER; \
}
GnssModel_t GPS::probe(int serialSpeed)
{
#if defined(ARCH_NRF52) || defined(ARCH_PORTDUINO) || defined(ARCH_RP2040) || defined(ARCH_STM32WL)
#if defined(ARCH_NRF52) || defined(ARCH_PORTDUINO) || defined(ARCH_STM32WL)
_serial_gps->end();
_serial_gps->begin(serialSpeed);
#elif defined(ARCH_RP2040)
_serial_gps->end();
_serial_gps->setFIFOSize(256);
_serial_gps->begin(serialSpeed);
#else
if (_serial_gps->baudRate() != serialSpeed) {
LOG_DEBUG("Setting Baud to %i\n", serialSpeed);
_serial_gps->updateBaudRate(serialSpeed);
}
#endif
#ifdef GNSS_AIROHA
return GNSS_MODEL_AG3335;
#endif
#ifdef GPS_DEBUG
for (int i = 0; i < 20; i++) {
getACK("$GP", 200);
}
#endif
memset(&info, 0, sizeof(struct uBloxGnssModelInfo));
uint8_t buffer[768] = {0};
delay(100);
@@ -1211,67 +1104,29 @@ GnssModel_t GPS::probe(int serialSpeed)
_serial_gps->write("$PCAS03,0,0,0,0,0,0,0,0,0,0,,,0,0*02\r\n");
delay(20);
// get version information from Unicore UFirebirdII Series
// Works for: UC6580, UM620, UM621, UM670A, UM680A, or UM681A
_serial_gps->write("$PDTINFO\r\n");
delay(750);
if (getACK("UC6580", 500) == GNSS_RESPONSE_OK) {
LOG_INFO("UC6580 detected, using UC6580 Module\n");
return GNSS_MODEL_UC6580;
}
clearBuffer();
_serial_gps->write("$PDTINFO\r\n");
delay(750);
if (getACK("UM600", 500) == GNSS_RESPONSE_OK) {
LOG_INFO("UM600 detected, using UC6580 Module\n");
return GNSS_MODEL_UC6580;
}
// Get version information for ATGM336H
clearBuffer();
_serial_gps->write("$PCAS06,1*1A\r\n");
if (getACK("$GPTXT,01,01,02,HW=ATGM336H", 500) == GNSS_RESPONSE_OK) {
LOG_INFO("ATGM336H GNSS init succeeded, using ATGM336H Module\n");
return GNSS_MODEL_ATGM336H;
}
// Unicore UFirebirdII Series: UC6580, UM620, UM621, UM670A, UM680A, or UM681A
PROBE_SIMPLE("UC6580", "$PDTINFO", "UC6580", GNSS_MODEL_UC6580, 500);
PROBE_SIMPLE("UM600", "$PDTINFO", "UM600", GNSS_MODEL_UC6580, 500);
PROBE_SIMPLE("ATGM336H", "$PCAS06,1*1A", "$GPTXT,01,01,02,HW=ATGM336H", GNSS_MODEL_ATGM336H, 500);
/* ATGM332D series (-11(GPS), -21(BDS), -31(GPS+BDS), -51(GPS+GLONASS), -71-0(GPS+BDS+GLONASS))
based on AT6558 */
clearBuffer();
_serial_gps->write("$PCAS06,1*1A\r\n");
if (getACK("$GPTXT,01,01,02,HW=ATGM332D", 500) == GNSS_RESPONSE_OK) {
LOG_INFO("ATGM332D detected, using ATGM336H Module\n");
return GNSS_MODEL_ATGM336H;
}
PROBE_SIMPLE("ATGM332D", "$PCAS06,1*1A", "$GPTXT,01,01,02,HW=ATGM332D", GNSS_MODEL_ATGM336H, 500);
/* Airoha (Mediatek) AG3335A/M/S, A3352Q, Quectel L89 2.0, SimCom SIM65M */
clearBuffer();
_serial_gps->write("PAIR020*38\r\n");
if (getACK("$PAIR020,AG3335", 500) == GNSS_RESPONSE_OK) {
LOG_INFO("Aioha AG3335 detected, using AG3335 Module\n");
return GNSS_MODEL_AG3335;
}
_serial_gps->write("$PAIR062,2,0*3C\r\n"); // GSA OFF to reduce volume
_serial_gps->write("$PAIR062,3,0*3D\r\n"); // GSV OFF to reduce volume
_serial_gps->write("$PAIR513*3D\r\n"); // save configuration
PROBE_SIMPLE("AG3335", "$PAIR021*39", "$PAIR021,AG3335", GNSS_MODEL_AG3335, 500);
PROBE_SIMPLE("AG3352", "$PAIR021*39", "$PAIR021,AG3352", GNSS_MODEL_AG3352, 500);
PROBE_SIMPLE("LC86", "$PQTMVERNO*58", "$PQTMVERNO,LC86", GNSS_MODEL_AG3352, 500);
// Get version information
clearBuffer();
_serial_gps->write("$PCAS06,0*1B\r\n");
if (getACK("$GPTXT,01,01,02,SW=", 500) == GNSS_RESPONSE_OK) {
LOG_INFO("L76K GNSS init succeeded, using L76K GNSS Module\n");
return GNSS_MODEL_MTK;
}
PROBE_SIMPLE("L76K", "$PCAS06,0*1B", "$GPTXT,01,01,02,SW=", GNSS_MODEL_MTK, 500);
// Close all NMEA sentences, valid for L76B MTK platform (Waveshare Pico GPS)
_serial_gps->write("$PMTK514,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*2E\r\n");
delay(20);
// Get version information
clearBuffer();
_serial_gps->write("$PMTK605*31\r\n");
if (getACK("Quectel-L76B", 500) == GNSS_RESPONSE_OK) {
LOG_INFO("L76B GNSS init succeeded, using L76B GNSS Module\n");
return GNSS_MODEL_MTK_L76B;
}
PROBE_SIMPLE("L76B", "$PMTK605*31", "Quectel-L76B", GNSS_MODEL_MTK_L76B, 500);
uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00};
UBXChecksum(cfg_rate, sizeof(cfg_rate));
@@ -1298,9 +1153,13 @@ GnssModel_t GPS::probe(int serialSpeed)
_serial_gps->write(_message_prt, sizeof(_message_prt));
delay(500);
serialSpeed = 9600;
#if defined(ARCH_NRF52) || defined(ARCH_PORTDUINO) || defined(ARCH_RP2040) || defined(ARCH_STM32WL)
#if defined(ARCH_NRF52) || defined(ARCH_PORTDUINO) || defined(ARCH_STM32WL)
_serial_gps->end();
_serial_gps->begin(serialSpeed);
#elif defined(ARCH_RP2040)
_serial_gps->end();
_serial_gps->setFIFOSize(256);
_serial_gps->begin(serialSpeed);
#else
_serial_gps->updateBaudRate(serialSpeed);
#endif
@@ -1358,9 +1217,9 @@ GnssModel_t GPS::probe(int serialSpeed)
strncpy((char *)buffer, &(info.extension[i][4]), sizeof(buffer));
// LOG_DEBUG("GetModel:%s\n", (char *)buffer);
if (strlen((char *)buffer)) {
LOG_INFO("UBlox GNSS probe succeeded, using UBlox %s GNSS Module\n", (char *)buffer);
LOG_INFO("%s detected, using GNSS_MODEL_UBLOX\n", (char *)buffer);
} else {
LOG_INFO("UBlox GNSS probe succeeded, using UBlox GNSS Module\n");
LOG_INFO("Generic Ublox detected, using GNSS_MODEL_UBLOX\n");
}
} else if (!strncmp(info.extension[i], "PROTVER", 7)) {
char *ptr = nullptr;
@@ -1375,9 +1234,20 @@ GnssModel_t GPS::probe(int serialSpeed)
}
}
}
if (strncmp(info.hwVersion, "00040007", 8) == 0) {
return GNSS_MODEL_UBLOX6;
} else if (strncmp(info.hwVersion, "00070000", 8) == 0) {
return GNSS_MODEL_UBLOX7;
} else if (strncmp(info.hwVersion, "00080000", 8) == 0) {
return GNSS_MODEL_UBLOX8;
} else if (strncmp(info.hwVersion, "00190000", 8) == 0) {
return GNSS_MODEL_UBLOX9;
} else if (strncmp(info.hwVersion, "000A0000", 8) == 0) {
return GNSS_MODEL_UBLOX10;
}
}
return GNSS_MODEL_UBLOX;
return GNSS_MODEL_UNKNOWN;
}
GPS *GPS::createGps()
@@ -1461,6 +1331,9 @@ GPS *GPS::createGps()
LOG_DEBUG("Using GPIO%d for GPS RX\n", new_gps->rx_gpio);
LOG_DEBUG("Using GPIO%d for GPS TX\n", 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);
_serial_gps->begin(GPS_BAUDRATE);
#else
_serial_gps->begin(GPS_BAUDRATE);
#endif
@@ -1548,16 +1421,15 @@ bool GPS::lookForTime()
#ifdef GNSS_AIROHA
uint8_t fix = reader.fixQuality();
uint32_t now = millis();
if (fix > 0) {
if (lastFixStartMsec > 0) {
if ((now - lastFixStartMsec) < GPS_FIX_HOLD_TIME) {
if (Throttle::isWithinTimespanMs(lastFixStartMsec, GPS_FIX_HOLD_TIME)) {
return false;
} else {
clearBuffer();
}
} else {
lastFixStartMsec = now;
lastFixStartMsec = millis();
return false;
}
} else {
@@ -1572,7 +1444,7 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s
(midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
*/
struct tm t;
t.tm_sec = ti.second();
t.tm_sec = ti.second() + round(ti.age() / 1000);
t.tm_min = ti.minute();
t.tm_hour = ti.hour();
t.tm_mday = d.day();
@@ -1580,8 +1452,8 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s
t.tm_year = d.year() - 1900;
t.tm_isdst = false;
if (t.tm_mon > -1) {
LOG_DEBUG("NMEA GPS time %02d-%02d-%02d %02d:%02d:%02d\n", d.year(), d.month(), t.tm_mday, t.tm_hour, t.tm_min,
t.tm_sec);
LOG_DEBUG("NMEA GPS time %02d-%02d-%02d %02d:%02d:%02d age %d\n", d.year(), d.month(), t.tm_mday, t.tm_hour, t.tm_min,
t.tm_sec, ti.age());
perhapsSetRTC(RTCQualityGPS, t);
return true;
} else
@@ -1601,16 +1473,15 @@ bool GPS::lookForLocation()
#ifdef GNSS_AIROHA
if ((config.position.gps_update_interval * 1000) >= (GPS_FIX_HOLD_TIME * 2)) {
uint8_t fix = reader.fixQuality();
uint32_t now = millis();
if (fix > 0) {
if (lastFixStartMsec > 0) {
if ((now - lastFixStartMsec) < GPS_FIX_HOLD_TIME) {
if (Throttle::isWithinTimespanMs(lastFixStartMsec, GPS_FIX_HOLD_TIME)) {
return false;
} else {
clearBuffer();
}
} else {
lastFixStartMsec = now;
lastFixStartMsec = millis();
return false;
}
} else {
@@ -1840,4 +1711,4 @@ void GPS::toggleGpsMode()
enable();
}
}
#endif // Exclude GPS
#endif // Exclude GPS

View File

@@ -26,11 +26,16 @@ struct uBloxGnssModelInfo {
typedef enum {
GNSS_MODEL_ATGM336H,
GNSS_MODEL_MTK,
GNSS_MODEL_UBLOX,
GNSS_MODEL_UBLOX6,
GNSS_MODEL_UBLOX7,
GNSS_MODEL_UBLOX8,
GNSS_MODEL_UBLOX9,
GNSS_MODEL_UBLOX10,
GNSS_MODEL_UC6580,
GNSS_MODEL_UNKNOWN,
GNSS_MODEL_MTK_L76B,
GNSS_MODEL_AG3335
GNSS_MODEL_AG3335,
GNSS_MODEL_AG3352
} GnssModel_t;
typedef enum {
@@ -101,7 +106,7 @@ class GPS : private concurrency::OSThread
public:
/** If !NULL we will use this serial port to construct our GPS */
#if defined(RPI_PICO_WAVESHARE)
#if defined(ARCH_RP2040)
static SerialUART *_serial_gps;
#else
static HardwareSerial *_serial_gps;
@@ -129,6 +134,7 @@ class GPS : private concurrency::OSThread
static const uint8_t _message_GGA[];
static const uint8_t _message_PMS[];
static const uint8_t _message_SAVE[];
static const uint8_t _message_SAVE_10[];
// VALSET Commands for M10
static const uint8_t _message_VALSET_PM[];
@@ -297,7 +303,6 @@ class GPS : private concurrency::OSThread
virtual int32_t runOnce() override;
// Get GNSS model
String getNMEA();
GnssModel_t probe(int serialSpeed);
// delay counter to allow more sats before fixed position stops GPS thread

View File

@@ -2,6 +2,7 @@
#include "configuration.h"
#include "detect/ScanI2C.h"
#include "main.h"
#include <Throttle.h>
#include <sys/time.h>
#include <time.h>
@@ -29,7 +30,7 @@ void readFromRTC()
if (rtc_found.address == RV3028_RTC) {
uint32_t now = millis();
Melopero_RV3028 rtc;
#ifdef I2C_SDA1
#if WIRE_INTERFACES_COUNT == 2
rtc.initI2C(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
#else
rtc.initI2C();
@@ -43,7 +44,10 @@ void readFromRTC()
t.tm_sec = rtc.getSecond();
tv.tv_sec = gm_mktime(&t);
tv.tv_usec = 0;
LOG_DEBUG("Read RTC time from RV3028 as %ld\n", tv.tv_sec);
uint32_t printableEpoch = tv.tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms
LOG_DEBUG("Read RTC time from RV3028 getTime as %02d-%02d-%02d %02d:%02d:%02d (%ld)\n", t.tm_year + 1900, t.tm_mon + 1,
t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, printableEpoch);
timeStartMsec = now;
zeroOffsetSecs = tv.tv_sec;
if (currentQuality == RTCQualityNone) {
@@ -55,7 +59,7 @@ void readFromRTC()
uint32_t now = millis();
PCF8563_Class rtc;
#ifdef I2C_SDA1
#if WIRE_INTERFACES_COUNT == 2
rtc.begin(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
#else
rtc.begin();
@@ -71,7 +75,10 @@ void readFromRTC()
t.tm_sec = tc.second;
tv.tv_sec = gm_mktime(&t);
tv.tv_usec = 0;
LOG_DEBUG("Read RTC time from PCF8563 as %ld\n", tv.tv_sec);
uint32_t printableEpoch = tv.tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms
LOG_DEBUG("Read RTC time from PCF8563 getDateTime as %02d-%02d-%02d %02d:%02d:%02d (%ld)\n", t.tm_year + 1900,
t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, printableEpoch);
timeStartMsec = now;
zeroOffsetSecs = tv.tv_sec;
if (currentQuality == RTCQualityNone) {
@@ -81,7 +88,8 @@ void readFromRTC()
#else
if (!gettimeofday(&tv, NULL)) {
uint32_t now = millis();
LOG_DEBUG("Read RTC time as %ld\n", tv.tv_sec);
uint32_t printableEpoch = tv.tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms
LOG_DEBUG("Read RTC time as %ld\n", printableEpoch);
timeStartMsec = now;
zeroOffsetSecs = tv.tv_sec;
}
@@ -101,6 +109,13 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate)
{
static uint32_t lastSetMsec = 0;
uint32_t now = millis();
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)!\n", printableEpoch, BUILD_EPOCH);
return false;
}
#endif
bool shouldSet;
if (forceUpdate) {
@@ -110,10 +125,13 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate)
} else if (q > currentQuality) {
shouldSet = true;
LOG_DEBUG("Upgrading time to quality %s\n", RtcName(q));
} else if (q >= RTCQualityNTP && (now - lastSetMsec) > (12 * 60 * 60 * 1000UL)) {
// Every 12 hrs we will slam in a new GPS or Phone GPS / NTP time, to correct for local RTC clock drift
} else if (q == RTCQualityGPS) {
shouldSet = true;
LOG_DEBUG("Reapplying external time to correct clock drift %ld secs\n", tv->tv_sec);
LOG_DEBUG("Reapplying GPS time: %ld secs\n", 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\n", printableEpoch);
} else {
shouldSet = false;
LOG_DEBUG("Current RTC quality: %s. Ignoring time of RTC quality of %s\n", RtcName(currentQuality), RtcName(q));
@@ -133,29 +151,29 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate)
#ifdef RV3028_RTC
if (rtc_found.address == RV3028_RTC) {
Melopero_RV3028 rtc;
#ifdef I2C_SDA1
#if WIRE_INTERFACES_COUNT == 2
rtc.initI2C(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
#else
rtc.initI2C();
#endif
tm *t = gmtime(&tv->tv_sec);
rtc.setTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_wday, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
LOG_DEBUG("RV3028_RTC setTime %02d-%02d-%02d %02d:%02d:%02d %ld\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec, tv->tv_sec);
LOG_DEBUG("RV3028_RTC setTime %02d-%02d-%02d %02d:%02d:%02d (%ld)\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec, printableEpoch);
}
#elif defined(PCF8563_RTC)
if (rtc_found.address == PCF8563_RTC) {
PCF8563_Class rtc;
#ifdef I2C_SDA1
#if WIRE_INTERFACES_COUNT == 2
rtc.begin(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
#else
rtc.begin();
#endif
tm *t = gmtime(&tv->tv_sec);
rtc.setDateTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
LOG_DEBUG("PCF8563_RTC setDateTime %02d-%02d-%02d %02d:%02d:%02d %ld\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec, tv->tv_sec);
LOG_DEBUG("PCF8563_RTC setDateTime %02d-%02d-%02d %02d:%02d:%02d (%ld)\n", t->tm_year + 1900, t->tm_mon + 1,
t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, printableEpoch);
}
#elif defined(ARCH_ESP32)
settimeofday(tv, NULL);
@@ -272,4 +290,4 @@ time_t gm_mktime(struct tm *tm)
#else
return mktime(tm);
#endif
}
}

View File

@@ -1,3 +1,10 @@
#define SEND_UBX_PACKET(TYPE, ID, DATA, ERRMSG, TIMEOUT) \
msglen = makeUBXPacket(TYPE, ID, sizeof(DATA), DATA); \
_serial_gps->write(UBXscratch, msglen); \
if (getACK(TYPE, ID, TIMEOUT) != GNSS_RESPONSE_OK) { \
LOG_WARN(#ERRMSG); \
}
// Power Management
uint8_t GPS::_message_PMREQ[] PROGMEM = {
@@ -316,6 +323,13 @@ const uint8_t GPS::_message_SAVE[] = {
0x17 // deviceMask: BBR, Flash, EEPROM, and SPI Flash
};
const uint8_t GPS::_message_SAVE_10[] = {
0x00, 0x00, 0x00, 0x00, // clearMask: no sections cleared
0xFF, 0xFF, 0x00, 0x00, // saveMask: save all sections
0x00, 0x00, 0x00, 0x00, // loadMask: no sections loaded
0x01 // deviceMask: only save to BBR
};
// As the M10 has no flash, the best we can do to preserve the config is to set it in RAM and BBR.
// BBR will survive a restart, and power off for a while, but modules with small backup
// batteries or super caps will not retain the config for a long power off time.
@@ -335,36 +349,36 @@ const uint8_t GPS::_message_SAVE[] = {
// has details on low-power modes
/*
CFG-PM2 has been replaced by many CFG-PM commands
CFG-PMS has been removed
CFG-PM-OPERATEMODE E1 (0 | 1 | 2) -> 1 (PSMOO), because sporadic position updates are required instead of continous tracking <10s
(PSMCT) CFG-PM-POSUPDATEPERIOD U4 -> 0ms, no self-timed wakup because receiver power mode is controlled via "software standby
mode" by legacy UBX-RXM-PMREQ request CFG-PM-ACQPERIOD U4 -> 0ms, because receiver power mode is controlled via "software standby
mode" by legacy UBX-RXM-PMREQ request CFG-PM-ONTIME U4 -> 0ms, optional I guess CFG-PM-EXTINTBACKUP L -> 1, force receiver into
BACKUP mode when EXTINT (should be connected to GPS_EN_PIN) pin is "low"
This is required because the receiver never enters low power mode if microcontroller is in deep-sleep.
Maybe the changing UART_RX levels trigger a wakeup but even with UBX-RXM-PMREQ[12] = 0x00 (all external wakeup sources disabled)
the receivcer remains in aquisition state -> potentially a bug
Workaround: Control the EXTINT pin by the GPS_EN_PIN signal
As mentioned in the M10 operational issues down below, power save won't allow the use of BDS B1C.
CFG-SIGNAL-BDS_B1C_ENA L -> 0
OPERATEMODE E1 2 (0 | 1 | 2)
POSUPDATEPERIOD U4 5
ACQPERIOD U4 10
GRIDOFFSET U4 0
ONTIME U2 1
MINACQTIME U1 0
MAXACQTIME U1 0
DONOTENTEROFF L 1
WAITTIMEFIX L 1
UPDATEEPH L 1
EXTINTWAKE L 0 no ext ints
EXTINTBACKUP L 0 no ext ints
EXTINTINACTIVE L 0 no ext ints
EXTINTACTIVITY U4 0 no ext ints
LIMITPEAKCURRENT L 1
// Ram layer config message:
// 01 01 00 00 01 00 D0 20 01 02 00 D0 40 00 00 00 00 03 00 D0 40 00 00 00 00 05 00 D0 30 00 00 0D 00 D0 10 01
// b5 62 06 8a 26 00 00 01 00 00 01 00 d0 20 02 02 00 d0 40 05 00 00 00 05 00 d0 30 01 00 08 00 d0 10 01 09 00 d0 10 01 10 00 d0
// 10 01 8b de
// BBR layer config message:
// 01 02 00 00 01 00 D0 20 01 02 00 D0 40 00 00 00 00 03 00 D0 40 00 00 00 00 05 00 D0 30 00 00 0D 00 D0 10 01
// b5 62 06 8a 26 00 00 02 00 00 01 00 d0 20 02 02 00 d0 40 05 00 00 00 05 00 d0 30 01 00 08 00 d0 10 01 09 00 d0 10 01 10 00 d0
// 10 01 8c 03
*/
const uint8_t GPS::_message_VALSET_PM_RAM[] = {0x01, 0x01, 0x00, 0x00, 0x0F, 0x00, 0x31, 0x10, 0x00, 0x01, 0x00, 0xD0, 0x20, 0x01,
0x02, 0x00, 0xD0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xD0, 0x40, 0x00, 0x00,
0x00, 0x00, 0x05, 0x00, 0xD0, 0x30, 0x00, 0x00, 0x0D, 0x00, 0xD0, 0x10, 0x01};
const uint8_t GPS::_message_VALSET_PM_BBR[] = {0x01, 0x02, 0x00, 0x00, 0x0F, 0x00, 0x31, 0x10, 0x00, 0x01, 0x00, 0xD0, 0x20, 0x01,
0x02, 0x00, 0xD0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xD0, 0x40, 0x00, 0x00,
0x00, 0x00, 0x05, 0x00, 0xD0, 0x30, 0x00, 0x00, 0x0D, 0x00, 0xD0, 0x10, 0x01};
const uint8_t GPS::_message_VALSET_PM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40,
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0,
0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01};
const uint8_t GPS::_message_VALSET_PM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40,
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0,
0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01};
/*
CFG-ITFM replaced by 5 valset messages which can be combined into one for RAM and one for BBR

View File

@@ -1,3 +1,4 @@
#include "Throttle.h"
#include "configuration.h"
#if defined(USE_EINK) && defined(USE_EINK_DYNAMICDISPLAY)
@@ -231,15 +232,13 @@ void EInkDynamicDisplay::checkForPromotion()
// Is it too soon for another frame of this type?
void EInkDynamicDisplay::checkRateLimiting()
{
uint32_t now = millis();
// Sanity check: millis() overflow - just let the update run..
if (previousRunMs > now)
if (previousRunMs > millis())
return;
// Skip update: too soon for BACKGROUND
if (frameFlags == BACKGROUND) {
if (now - previousRunMs < EINK_LIMIT_RATE_BACKGROUND_SEC * 1000) {
if (Throttle::isWithinTimespanMs(previousRunMs, EINK_LIMIT_RATE_BACKGROUND_SEC * 1000)) {
refresh = SKIPPED;
reason = EXCEEDED_RATELIMIT_FULL;
return;
@@ -252,7 +251,7 @@ void EInkDynamicDisplay::checkRateLimiting()
// Skip update: too soon for RESPONSIVE
if (frameFlags & RESPONSIVE) {
if (now - previousRunMs < EINK_LIMIT_RATE_RESPONSIVE_SEC * 1000) {
if (Throttle::isWithinTimespanMs(previousRunMs, EINK_LIMIT_RATE_RESPONSIVE_SEC * 1000)) {
refresh = SKIPPED;
reason = EXCEEDED_RATELIMIT_FAST;
LOG_DEBUG("refresh=SKIPPED, reason=EXCEEDED_RATELIMIT_FAST, frameFlags=0x%x\n", frameFlags);

View File

@@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "Screen.h"
#include "../userPrefs.h"
#include "PowerMon.h"
#include "Throttle.h"
#include "configuration.h"
#if HAS_SCREEN
#include <OLEDDisplay.h>
@@ -117,6 +118,7 @@ static bool heartbeat = false;
#define SCREEN_HEIGHT display->getHeight()
#include "graphics/ScreenFonts.h"
#include <Throttle.h>
#define getStringCenteredX(s) ((SCREEN_WIDTH - display->getStringWidth(s)) / 2)
@@ -1093,8 +1095,8 @@ static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const NodeStat
{
char usersString[20];
snprintf(usersString, sizeof(usersString), "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal());
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(USE_ST7789) || \
defined(HX8357_CS)) && \
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || defined(ST7789_CS) || \
defined(USE_ST7789) || defined(HX8357_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x, y + 3, 8, 8, imgUser);
#else
@@ -1285,8 +1287,8 @@ static int8_t prevFrame = -1;
// Draw the arrow pointing to a node's location
void Screen::drawNodeHeading(OLEDDisplay *display, int16_t compassX, int16_t compassY, uint16_t compassDiam, float headingRadian)
{
Point tip(0.0f, 0.5f), tail(0.0f, -0.5f); // pointing up initially
float arrowOffsetX = 0.2f, arrowOffsetY = 0.2f;
Point tip(0.0f, 0.5f), tail(0.0f, -0.35f); // pointing up initially
float arrowOffsetX = 0.14f, arrowOffsetY = 1.0f;
Point leftArrow(tip.x - arrowOffsetX, tip.y - arrowOffsetY), rightArrow(tip.x + arrowOffsetX, tip.y - arrowOffsetY);
Point *arrowPoints[] = {&tip, &tail, &leftArrow, &rightArrow};
@@ -1296,9 +1298,19 @@ void Screen::drawNodeHeading(OLEDDisplay *display, int16_t compassX, int16_t com
arrowPoints[i]->scale(compassDiam * 0.6);
arrowPoints[i]->translate(compassX, compassY);
}
/* Old arrow
display->drawLine(tip.x, tip.y, tail.x, tail.y);
display->drawLine(leftArrow.x, leftArrow.y, tip.x, tip.y);
display->drawLine(rightArrow.x, rightArrow.y, tip.x, tip.y);
display->drawLine(leftArrow.x, leftArrow.y, tail.x, tail.y);
display->drawLine(rightArrow.x, rightArrow.y, tail.x, tail.y);
*/
#ifdef USE_EINK
display->drawTriangle(tip.x, tip.y, rightArrow.x, rightArrow.y, tail.x, tail.y);
#else
display->fillTriangle(tip.x, tip.y, rightArrow.x, rightArrow.y, tail.x, tail.y);
#endif
display->drawTriangle(tip.x, tip.y, leftArrow.x, leftArrow.y, tail.x, tail.y);
}
// Get a string representation of the time passed since something happened
@@ -1336,22 +1348,27 @@ void Screen::drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t co
// If north is supposed to be at the top of the compass we want rotation to be +0
if (config.display.compass_north_top)
myHeading = -0;
Point N1(-0.04f, 0.65f), N2(0.04f, 0.65f);
/* N sign points currently not deleted*/
Point N1(-0.04f, 0.65f), N2(0.04f, 0.65f); // N sign points (N1-N4)
Point N3(-0.04f, 0.55f), N4(0.04f, 0.55f);
Point *rosePoints[] = {&N1, &N2, &N3, &N4};
Point NC1(0.00f, 0.50f); // north circle center point
Point *rosePoints[] = {&N1, &N2, &N3, &N4, &NC1};
uint16_t compassDiam = Screen::getCompassDiam(SCREEN_WIDTH, SCREEN_HEIGHT);
for (int i = 0; i < 4; i++) {
for (int i = 0; i < 5; i++) {
// North on compass will be negative of heading
rosePoints[i]->rotate(-myHeading);
rosePoints[i]->scale(compassDiam);
rosePoints[i]->translate(compassX, compassY);
}
/* changed the N sign to a small circle on the compass circle.
display->drawLine(N1.x, N1.y, N3.x, N3.y);
display->drawLine(N2.x, N2.y, N4.x, N4.y);
display->drawLine(N1.x, N1.y, N4.x, N4.y);
*/
display->drawCircle(NC1.x, NC1.y, 4); // North sign circle, 4px radius is sufficient for all displays.
}
uint16_t Screen::getCompassDiam(uint32_t displayWidth, uint32_t displayHeight)
@@ -1515,7 +1532,8 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O
#elif defined(USE_SSD1306)
dispdev = new SSD1306Wire(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
#elif defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS)
#elif defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7701_CS) || defined(ST7789_CS) || defined(RAK14014) || \
defined(HX8357_CS)
dispdev = new TFTDisplay(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
#elif defined(USE_EINK) && !defined(USE_EINK_DYNAMICDISPLAY)
@@ -1654,6 +1672,11 @@ void Screen::setup()
static_cast<SH1106Wire *>(dispdev)->setSubtype(7);
#endif
#if defined(USE_ST7789) && defined(TFT_MESH)
// Heltec T114 and T190: honor a custom text color, if defined in variant.h
static_cast<ST7789Spi *>(dispdev)->setRGB(TFT_MESH);
#endif
// Initialising the UI will init the display too.
ui->init();
@@ -1707,8 +1730,11 @@ void Screen::setup()
// Standard behaviour is to FLIP the screen (needed on T-Beam). If this config item is set, unflip it, and thereby logically
// flip it. If you have a headache now, you're welcome.
if (!config.display.flip_screen) {
#if defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS)
#if defined(ST7701_CS) || defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7701_CS) || defined(ST7789_CS) || \
defined(RAK14014) || defined(HX8357_CS)
static_cast<TFTDisplay *>(dispdev)->flipScreenVertically();
#elif defined(USE_ST7789)
static_cast<ST7789Spi *>(dispdev)->flipScreenVertically();
#else
dispdev->flipScreenVertically();
#endif
@@ -1766,6 +1792,11 @@ void Screen::forceDisplay(bool forceUiUpdate)
#ifdef USE_EINK
// If requested, make sure queued commands are run, and UI has rendered a new frame
if (forceUiUpdate) {
// Force a display refresh, in addition to the UI update
// Changing the GPS status bar icon apparently doesn't register as a change in image
// (False negative of the image hashing algorithm used to skip identical frames)
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST);
// No delay between UI frame rendering
setFastFramerate();
@@ -1920,7 +1951,7 @@ int32_t Screen::runOnce()
if (showingNormalScreen) {
// standard screen loop handling here
if (config.display.auto_screen_carousel_secs > 0 &&
(millis() - lastScreenTransition) > (config.display.auto_screen_carousel_secs * 1000)) {
!Throttle::isWithinTimespanMs(lastScreenTransition, config.display.auto_screen_carousel_secs * 1000)) {
// If an E-Ink display struggles with fast refresh, force carousel to use full refresh instead
// Carousel is potentially a major source of E-Ink display wear
@@ -2413,10 +2444,10 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
// Draw our hardware ID to assist with bluetooth pairing. Either prefix with Info or S&F Logo
if (moduleConfig.store_forward.enabled) {
#ifdef ARCH_ESP32
if (millis() - storeForwardModule->lastHeartbeat >
(storeForwardModule->heartbeatInterval * 1200)) { // no heartbeat, overlap a bit
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(USE_ST7789) || \
defined(HX8357_CS)) && \
if (!Throttle::isWithinTimespanMs(storeForwardModule->lastHeartbeat,
(storeForwardModule->heartbeatInterval * 1200))) { // no heartbeat, overlap a bit
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || defined(ST7789_CS) || \
defined(USE_ST7789) || defined(HX8357_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
imgQuestionL1);
@@ -2427,8 +2458,8 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
imgQuestion);
#endif
} else {
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(USE_ST7789) || \
defined(HX8357_CS)) && \
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || defined(ST7789_CS) || \
defined(USE_ST7789) || defined(HX8357_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8,
imgSFL1);
@@ -2442,8 +2473,8 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
#endif
} else {
// TODO: Raspberry Pi supports more than just the one screen size
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(USE_ST7789) || \
defined(HX8357_CS) || ARCH_PORTDUINO) && \
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || defined(ST7789_CS) || \
defined(USE_ST7789) || defined(HX8357_CS) || ARCH_PORTDUINO) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
imgInfoL1);
@@ -2749,4 +2780,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

@@ -12,8 +12,8 @@
#include "graphics/fonts/OLEDDisplayFontsUA.h"
#endif
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(USE_ST7789) || \
defined(HX8357_CS)) && \
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || defined(ST7789_CS) || \
defined(USE_ST7789) || defined(HX8357_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
// The screen is bigger so use bigger fonts
#define FONT_SMALL ArialMT_Plain_16 // Height: 19

View File

@@ -500,10 +500,126 @@ class LGFX : public lgfx::LGFX_Device
static LGFX *tft = nullptr;
#elif defined(ST7701_CS)
#include <LovyanGFX.hpp> // Graphics and font library for ST7701 driver chip
#include <lgfx/v1/platforms/esp32s3/Bus_RGB.hpp>
#include <lgfx/v1/platforms/esp32s3/Panel_RGB.hpp>
class LGFX : public lgfx::LGFX_Device
{
lgfx::Panel_ST7701 _panel_instance;
lgfx::Bus_RGB _bus_instance;
lgfx::Light_PWM _light_instance;
lgfx::Touch_FT5x06 _touch_instance;
public:
LGFX(void)
{
{
auto cfg = _panel_instance.config();
cfg.memory_width = 800;
cfg.memory_height = 480;
cfg.panel_width = TFT_WIDTH;
cfg.panel_height = TFT_HEIGHT;
cfg.offset_x = TFT_OFFSET_X;
cfg.offset_y = TFT_OFFSET_Y;
_panel_instance.config(cfg);
}
{
auto cfg = _panel_instance.config_detail();
cfg.pin_cs = ST7701_CS;
cfg.pin_sclk = ST7701_SCK;
cfg.pin_mosi = ST7701_SDA;
// cfg.use_psram = 1;
_panel_instance.config_detail(cfg);
}
{
auto cfg = _bus_instance.config();
cfg.panel = &_panel_instance;
#ifdef SENSECAP_INDICATOR
cfg.pin_d0 = GPIO_NUM_15; // B0
cfg.pin_d1 = GPIO_NUM_14; // B1
cfg.pin_d2 = GPIO_NUM_13; // B2
cfg.pin_d3 = GPIO_NUM_12; // B3
cfg.pin_d4 = GPIO_NUM_11; // B4
cfg.pin_d5 = GPIO_NUM_10; // G0
cfg.pin_d6 = GPIO_NUM_9; // G1
cfg.pin_d7 = GPIO_NUM_8; // G2
cfg.pin_d8 = GPIO_NUM_7; // G3
cfg.pin_d9 = GPIO_NUM_6; // G4
cfg.pin_d10 = GPIO_NUM_5; // G5
cfg.pin_d11 = GPIO_NUM_4; // R0
cfg.pin_d12 = GPIO_NUM_3; // R1
cfg.pin_d13 = GPIO_NUM_2; // R2
cfg.pin_d14 = GPIO_NUM_1; // R3
cfg.pin_d15 = GPIO_NUM_0; // R4
cfg.pin_henable = GPIO_NUM_18;
cfg.pin_vsync = GPIO_NUM_17;
cfg.pin_hsync = GPIO_NUM_16;
cfg.pin_pclk = GPIO_NUM_21;
cfg.freq_write = 12000000;
cfg.hsync_polarity = 0;
cfg.hsync_front_porch = 10;
cfg.hsync_pulse_width = 8;
cfg.hsync_back_porch = 50;
cfg.vsync_polarity = 0;
cfg.vsync_front_porch = 10;
cfg.vsync_pulse_width = 8;
cfg.vsync_back_porch = 20;
cfg.pclk_active_neg = 0;
cfg.de_idle_high = 1;
cfg.pclk_idle_high = 0;
#endif
_bus_instance.config(cfg);
}
_panel_instance.setBus(&_bus_instance);
{
auto cfg = _light_instance.config();
cfg.pin_bl = ST7701_BL;
_light_instance.config(cfg);
}
_panel_instance.light(&_light_instance);
{
auto cfg = _touch_instance.config();
cfg.pin_cs = -1;
cfg.x_min = 0;
cfg.x_max = 479;
cfg.y_min = 0;
cfg.y_max = 479;
cfg.pin_int = -1; // don't use SCREEN_TOUCH_INT;
cfg.pin_rst = SCREEN_TOUCH_RST;
cfg.bus_shared = true;
cfg.offset_rotation = TFT_OFFSET_ROTATION;
cfg.i2c_port = TOUCH_I2C_PORT;
cfg.i2c_addr = TOUCH_SLAVE_ADDRESS;
cfg.pin_sda = I2C_SDA;
cfg.pin_scl = I2C_SCL;
cfg.freq = 400000;
_touch_instance.config(cfg);
_panel_instance.setTouch(&_touch_instance);
}
setPanel(&_panel_instance);
}
};
static LGFX *tft = nullptr;
#endif
#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(RAK14014) || defined(HX8357_CS) || \
(ARCH_PORTDUINO && HAS_SCREEN != 0)
#if defined(ST7701_CS) || defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(RAK14014) || \
defined(HX8357_CS) || (ARCH_PORTDUINO && HAS_SCREEN != 0)
#include "SPILock.h"
#include "TFTDisplay.h"
#include <SPI.h>
@@ -709,7 +825,6 @@ bool TFTDisplay::connect()
#ifdef UNPHONE
unphone.backlight(true); // using unPhone library
LOG_INFO("Power to TFT Backlight\n");
#endif
tft->init();
@@ -725,7 +840,7 @@ bool TFTDisplay::connect()
attachInterrupt(digitalPinToInterrupt(SCREEN_TOUCH_INT), rak14014_tpIntHandle, FALLING);
#elif defined(T_DECK) || defined(PICOMPUTER_S3) || defined(CHATTER_2)
tft->setRotation(1); // T-Deck has the TFT in landscape
#elif defined(T_WATCH_S3)
#elif defined(T_WATCH_S3) || defined(SENSECAP_INDICATOR)
tft->setRotation(2); // T-Watch S3 left-handed orientation
#else
tft->setRotation(3); // Orient horizontal and wide underneath the silkscreen name label

View File

@@ -20,8 +20,8 @@ const uint8_t bluetoothConnectedIcon[36] PROGMEM = {0xfe, 0x01, 0xff, 0x03, 0x03
0xfe, 0x31, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0x3f, 0xe0, 0x1f};
#endif
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(USE_ST7789) || \
defined(HX8357_CS) || ARCH_PORTDUINO) && \
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || defined(ST7789_CS) || \
defined(USE_ST7789) || defined(HX8357_CS) || ARCH_PORTDUINO) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
const uint8_t imgQuestionL1[] PROGMEM = {0xff, 0x01, 0x01, 0x32, 0x7b, 0x49, 0x49, 0x6f, 0x26, 0x01, 0x01, 0xff};
const uint8_t imgQuestionL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f};

View File

@@ -1,5 +1,5 @@
#include "ExpressLRSFiveWay.h"
#include "Throttle.h"
#ifdef INPUTBROKER_EXPRESSLRSFIVEWAY_TYPE
@@ -76,11 +76,10 @@ void ExpressLRSFiveWay::update(int *keyValue, bool *keyLongPressed)
*keyValue = NO_PRESS;
int newKey = readKey();
uint32_t now = millis();
if (keyInProcess == NO_PRESS) {
// New key down
if (newKey != NO_PRESS) {
keyDownStart = now;
keyDownStart = millis();
// DBGLN("down=%u", newKey);
}
} else {
@@ -88,7 +87,7 @@ void ExpressLRSFiveWay::update(int *keyValue, bool *keyLongPressed)
if (newKey == NO_PRESS) {
// DBGLN("up=%u", keyInProcess);
if (!isLongPressed) {
if ((now - keyDownStart) > KEY_DEBOUNCE_MS) {
if (!Throttle::isWithinTimespanMs(keyDownStart, KEY_DEBOUNCE_MS)) {
*keyValue = keyInProcess;
*keyLongPressed = false;
}
@@ -101,7 +100,7 @@ void ExpressLRSFiveWay::update(int *keyValue, bool *keyLongPressed)
}
// else still pressing, waiting for long if not already signaled
else if (!isLongPressed) {
if ((now - keyDownStart) > KEY_LONG_PRESS_MS) {
if (!Throttle::isWithinTimespanMs(keyDownStart, KEY_LONG_PRESS_MS)) {
*keyValue = keyInProcess;
*keyLongPressed = true;
isLongPressed = true;

View File

@@ -4,6 +4,20 @@
#define ANYKEY 0xFF
#define MATRIXKEY 0xFE
#define INPUT_BROKER_MSG_BRIGHTNESS_UP 0x11
#define INPUT_BROKER_MSG_BRIGHTNESS_DOWN 0x12
#define INPUT_BROKER_MSG_REBOOT 0x90
#define INPUT_BROKER_MSG_SHUTDOWN 0x9b
#define INPUT_BROKER_MSG_GPS_TOGGLE 0x9e
#define INPUT_BROKER_MSG_MUTE_TOGGLE 0xac
#define INPUT_BROKER_MSG_SEND_PING 0xaf
#define INPUT_BROKER_MSG_LEFT 0xb4
#define INPUT_BROKER_MSG_UP 0xb5
#define INPUT_BROKER_MSG_DOWN 0xb6
#define INPUT_BROKER_MSG_RIGHT 0xb7
#define INPUT_BROKER_MSG_FN_SYMBOL_ON 0xf1
#define INPUT_BROKER_MSG_FN_SYMBOL_OFF 0xf2
typedef struct _InputEvent {
const char *source;
char inputEvent;

View File

@@ -147,11 +147,11 @@ int32_t LinuxInput::runOnce()
case KEY_LEFT: // Left
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
break;
e.kbchar = 0xb4;
e.kbchar = INPUT_BROKER_MSG_LEFT;
case KEY_RIGHT: // Right
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
break;
e.kbchar = 0xb7;
e.kbchar = INPUT_BROKER_MSG_RIGHT;
case KEY_ENTER: // Enter
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
break;

View File

@@ -6,6 +6,7 @@
#include "ScanAndSelect.h"
#include "modules/CannedMessageModule.h"
#include <Throttle.h>
// Config
static const char name[] = "scanAndSelect"; // should match "allow input source" string
@@ -75,7 +76,7 @@ int32_t ScanAndSelectInput::runOnce()
else {
// Duration enough for long press
// Long press not yet fired (prevent repeat firing while held)
if (!longPressFired && now - downSinceMs > durationLongMs) {
if (!longPressFired && Throttle::isWithinTimespanMs(downSinceMs, durationLongMs)) {
longPressFired = true;
longPress();
}
@@ -91,7 +92,7 @@ int32_t ScanAndSelectInput::runOnce()
// Long press event didn't already fire
if (held && !longPressFired) {
// Duration enough for short press
if (now - downSinceMs > durationShortMs) {
if (!Throttle::isWithinTimespanMs(downSinceMs, durationShortMs)) {
shortPress();
}
}

View File

@@ -1,5 +1,6 @@
#include "SerialKeyboard.h"
#include "configuration.h"
#include <Throttle.h>
#ifdef INPUTBROKER_SERIAL_TYPE
#define CANNED_MESSAGE_MODULE_ENABLE 1 // in case it's not set in the variant file
@@ -73,7 +74,7 @@ int32_t SerialKeyboard::runOnce()
// Serial.print ("X");
// Serial.println (shiftRegister2, BIN);
if (millis() - lastPressTime > 500) {
if (!Throttle::isWithinTimespanMs(lastPressTime, 500)) {
quickPress = 0;
}
@@ -87,7 +88,7 @@ int32_t SerialKeyboard::runOnce()
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
} else if (!(shiftRegister2 & (1 << 2))) {
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
e.kbchar = 0xb7;
e.kbchar = INPUT_BROKER_MSG_RIGHT;
} else if (!(shiftRegister2 & (1 << 1))) {
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
} else if (!(shiftRegister2 & (1 << 0))) {

View File

@@ -9,14 +9,14 @@ CardKbI2cImpl::CardKbI2cImpl() : KbI2cBase("cardKB") {}
void CardKbI2cImpl::init()
{
#ifndef ARCH_PORTDUINO
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO)
if (cardkb_found.address == 0x00) {
LOG_DEBUG("Rescanning for I2C keyboard\n");
uint8_t i2caddr_scan[] = {CARDKB_ADDR, TDECK_KB_ADDR, BBQ10_KB_ADDR};
uint8_t i2caddr_asize = 3;
auto i2cScanner = std::unique_ptr<ScanI2CTwoWire>(new ScanI2CTwoWire());
#if defined(I2C_SDA1)
#if WIRE_INTERFACES_COUNT == 2
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE1, i2caddr_scan, i2caddr_asize);
#endif
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE, i2caddr_scan, i2caddr_asize);
@@ -57,4 +57,4 @@ void CardKbI2cImpl::init()
}
#endif
inputBroker->registerSource(this);
}
}

View File

@@ -33,7 +33,7 @@ int32_t KbI2cBase::runOnce()
if (!i2cBus) {
switch (cardkb_found.port) {
case ScanI2C::WIRE1:
#ifdef I2C_SDA1
#if WIRE_INTERFACES_COUNT == 2
LOG_DEBUG("Using I2C Bus 1 (the second one)\n");
i2cBus = &Wire1;
if (cardkb_found.address == BBQ10_KB_ADDR) {
@@ -94,7 +94,7 @@ int32_t KbI2cBase::runOnce()
case 'e': // sym e
if (is_sym) {
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
e.kbchar = 0xb5;
e.kbchar = INPUT_BROKER_MSG_UP;
is_sym = false; // reset sym state after second keypress
} else {
e.inputEvent = ANYKEY;
@@ -104,7 +104,7 @@ int32_t KbI2cBase::runOnce()
case 'x': // sym x
if (is_sym) {
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
e.kbchar = 0xb6;
e.kbchar = INPUT_BROKER_MSG_DOWN;
is_sym = false; // reset sym state after second keypress
} else {
e.inputEvent = ANYKEY;
@@ -134,8 +134,8 @@ int32_t KbI2cBase::runOnce()
case 0x13: // Code scanner says the SYM key is 0x13
is_sym = !is_sym;
e.inputEvent = ANYKEY;
e.kbchar =
is_sym ? 0xf1 : 0xf2; // send 0xf1 to tell CannedMessages to display that the modifier key is active
e.kbchar = is_sym ? INPUT_BROKER_MSG_FN_SYMBOL_ON // send 0xf1 to tell CannedMessages to display that
: INPUT_BROKER_MSG_FN_SYMBOL_OFF; // the modifier key is active
break;
case 0x0a: // apparently Enter on Q10 is a line feed instead of carriage return
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
@@ -214,7 +214,7 @@ int32_t KbI2cBase::runOnce()
if (is_sym) {
is_sym = false;
e.inputEvent = ANYKEY;
e.kbchar = 0xac; // mute notifications
e.kbchar = INPUT_BROKER_MSG_MUTE_TOGGLE; // mute notifications
} else {
e.inputEvent = ANYKEY;
e.kbchar = c;
@@ -224,7 +224,7 @@ int32_t KbI2cBase::runOnce()
if (is_sym) {
is_sym = false;
e.inputEvent = ANYKEY;
e.kbchar = 0x11; // Increase Brightness code
e.kbchar = INPUT_BROKER_MSG_BRIGHTNESS_UP; // Increase Brightness code
} else {
e.inputEvent = ANYKEY;
e.kbchar = c;
@@ -234,7 +234,7 @@ int32_t KbI2cBase::runOnce()
if (is_sym) {
is_sym = false;
e.inputEvent = ANYKEY;
e.kbchar = 0x12; // Decrease Brightness code
e.kbchar = INPUT_BROKER_MSG_BRIGHTNESS_DOWN; // Decrease Brightness code
} else {
e.inputEvent = ANYKEY;
e.kbchar = c;
@@ -244,7 +244,7 @@ int32_t KbI2cBase::runOnce()
if (is_sym) {
is_sym = false;
e.inputEvent = ANYKEY;
e.kbchar = 0xaf; // (fn + space)
e.kbchar = INPUT_BROKER_MSG_SEND_PING; // (fn + space)
} else {
e.inputEvent = ANYKEY;
e.kbchar = c;
@@ -254,7 +254,7 @@ int32_t KbI2cBase::runOnce()
if (is_sym) {
is_sym = false;
e.inputEvent = ANYKEY;
e.kbchar = 0x9e;
e.kbchar = INPUT_BROKER_MSG_GPS_TOGGLE;
} else {
e.inputEvent = ANYKEY;
e.kbchar = c;
@@ -269,32 +269,33 @@ int32_t KbI2cBase::runOnce()
break;
case 0xb5: // Up
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
e.kbchar = 0xb5;
e.kbchar = INPUT_BROKER_MSG_UP;
break;
case 0xb6: // Down
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
e.kbchar = 0xb6;
e.kbchar = INPUT_BROKER_MSG_DOWN;
break;
case 0xb4: // Left
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
e.kbchar = 0xb4;
e.kbchar = INPUT_BROKER_MSG_LEFT;
break;
case 0xb7: // Right
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
e.kbchar = 0xb7;
e.kbchar = INPUT_BROKER_MSG_RIGHT;
break;
case 0xc: // Modifier key: 0xc is alt+c (Other options could be: 0xea = shift+mic button or 0x4 shift+$(speaker))
// toggle moddifiers button.
is_sym = !is_sym;
e.inputEvent = ANYKEY;
e.kbchar = is_sym ? 0xf1 : 0xf2; // send 0xf1 to tell CannedMessages to display that the modifier key is active
e.kbchar = is_sym ? INPUT_BROKER_MSG_FN_SYMBOL_ON // send 0xf1 to tell CannedMessages to display that the
: INPUT_BROKER_MSG_FN_SYMBOL_OFF; // modifier key is active
break;
case 0x90: // fn+r
case 0x90: // fn+r INPUT_BROKER_MSG_REBOOT
case 0x91: // fn+t
case 0x9b: // fn+s
case 0xac: // fn+m
case 0x9e: // fn+g
case 0xaf: // fn+space
case 0x9b: // fn+s INPUT_BROKER_MSG_SHUTDOWN
case 0xac: // fn+m INPUT_BROKER_MSG_MUTE_TOGGLE
case 0x9e: // fn+g INPUT_BROKER_MSG_GPS_TOGGLE
case 0xaf: // fn+space INPUT_BROKER_MSG_SEND_PING
// just pass those unmodified
e.inputEvent = ANYKEY;
e.kbchar = c;

View File

@@ -11,16 +11,16 @@
#include "airtime.h"
#include "buzz.h"
#include "error.h"
#include "power.h"
// #include "debug.h"
#include "FSCommon.h"
#include "Led.h"
#include "RTC.h"
#include "SPILock.h"
#include "Throttle.h"
#include "concurrency/OSThread.h"
#include "concurrency/Periodic.h"
#include "detect/ScanI2C.h"
#include "error.h"
#include "power.h"
#if !MESHTASTIC_EXCLUDE_I2C
#include "detect/ScanI2CTwoWire.h"
@@ -38,7 +38,6 @@
#include "target_specific.h"
#include <memory>
#include <utility>
// #include <driver/rtc_io.h>
#ifdef ARCH_ESP32
#if !MESHTASTIC_EXCLUDE_WEBSERVER
@@ -360,6 +359,8 @@ void setup()
Wire1.begin();
#elif defined(I2C_SDA1) && !defined(ARCH_RP2040)
Wire1.begin(I2C_SDA1, I2C_SCL1);
#elif WIRE_INTERFACES_COUNT == 2
Wire1.begin();
#endif
#if defined(I2C_SDA) && defined(ARCH_RP2040)
@@ -390,7 +391,7 @@ void setup()
#endif
#ifdef AQ_SET_PIN
// RAK-12039 set pin for Air quality sensor
// RAK-12039 set pin for Air quality sensor. Detectable on I2C after ~3 seconds, so we need to rescan later
pinMode(AQ_SET_PIN, OUTPUT);
digitalWrite(AQ_SET_PIN, HIGH);
#endif
@@ -427,6 +428,8 @@ void setup()
#elif defined(I2C_SDA1) && !defined(ARCH_RP2040)
Wire1.begin(I2C_SDA1, I2C_SCL1);
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE1);
#elif defined(NRF52840_XXAA) && (WIRE_INTERFACES_COUNT == 2)
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE1);
#endif
#if defined(I2C_SDA) && defined(ARCH_RP2040)
@@ -560,6 +563,7 @@ void setup()
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)
@@ -586,6 +590,9 @@ void setup()
// Hello
printInfo();
#ifdef BUILD_EPOCH
LOG_INFO("Build timestamp: %ld\n", BUILD_EPOCH);
#endif
#ifdef ARCH_ESP32
esp32Setup();
@@ -635,8 +642,6 @@ void setup()
#if !MESHTASTIC_EXCLUDE_I2C
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
if (acc_info.type != ScanI2C::DeviceType::NONE) {
config.display.wake_on_tap_or_motion = true;
moduleConfig.external_notification.enabled = true;
accelerometerThread = new AccelerometerThread(acc_info.type);
}
#endif
@@ -747,8 +752,8 @@ void setup()
#if !MESHTASTIC_EXCLUDE_I2C
// Don't call screen setup until after nodedb is setup (because we need
// the current region name)
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(HX8357_CS) || \
defined(USE_ST7789)
#if defined(ST7701_CS) || defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || \
defined(HX8357_CS) || defined(USE_ST7789)
screen->setup();
#elif defined(ARCH_PORTDUINO)
if (screen_found.port != ScanI2C::I2CPort::NO_I2C || settingsMap[displayPanel]) {
@@ -762,12 +767,6 @@ void setup()
screen->print("Started...\n");
#ifdef SX126X_ANT_SW
// make analog PA vs not PA switch on SX126x eval board work properly
pinMode(SX126X_ANT_SW, OUTPUT);
digitalWrite(SX126X_ANT_SW, 1);
#endif
#ifdef PIN_PWR_DELAY_MS
// This may be required to give the peripherals time to power up.
delay(PIN_PWR_DELAY_MS);
@@ -1095,6 +1094,9 @@ extern meshtastic_DeviceMetadata getDeviceMetadata()
deviceMetadata.position_flags = config.position.position_flags;
deviceMetadata.hw_model = HW_VENDOR;
deviceMetadata.hasRemoteHardware = moduleConfig.remote_hardware.enabled;
#if !(MESHTASTIC_EXCLUDE_PKI)
deviceMetadata.hasPKC = true;
#endif
return deviceMetadata;
}
#ifndef PIO_UNIT_TESTING
@@ -1102,10 +1104,6 @@ void loop()
{
runASAP = false;
// axpDebugOutput.loop();
// heap_caps_check_integrity_all(true); // FIXME - disable this expensive check
#ifdef ARCH_ESP32
esp32Loop();
#endif
@@ -1114,33 +1112,21 @@ void loop()
#endif
powerCommandsCheck();
// For debugging
// if (rIf) ((RadioLibInterface *)rIf)->isActivelyReceiving();
#ifdef DEBUG_STACK
static uint32_t lastPrint = 0;
if (millis() - lastPrint > 10 * 1000L) {
if (!Throttle::isWithinTimespanMs(lastPrint, 10 * 1000L)) {
lastPrint = millis();
meshtastic::printThreadInfo("main");
}
#endif
// TODO: This should go into a thread handled by FreeRTOS.
// handleWebResponse();
service->loop();
long delayMsec = mainController.runOrDelay();
/* if (mainController.nextThread && delayMsec)
LOG_DEBUG("Next %s in %ld\n", mainController.nextThread->ThreadName.c_str(),
mainController.nextThread->tillRun(millis())); */
// We want to sleep as long as possible here - because it saves power
if (!runASAP && loopCanSleep()) {
// if(delayMsec > 100) LOG_DEBUG("sleeping %ld\n", delayMsec);
mainDelay.delay(delayMsec);
}
// if (didWake) LOG_DEBUG("wake!\n");
}
#endif

View File

@@ -13,10 +13,6 @@
#include "mqtt/MQTT.h"
#endif
/// 16 bytes of random PSK for our _public_ default channel that all devices power up on (AES128)
static const uint8_t defaultpsk[] = {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59,
0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0x01};
Channels channels;
const char *Channels::adminChannel = "admin";

View File

@@ -129,4 +129,12 @@ class Channels
};
/// Singleton channel table
extern Channels channels;
extern Channels channels;
/// 16 bytes of random PSK for our _public_ default channel that all devices power up on (AES128)
static const uint8_t defaultpsk[] = {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59,
0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0x01};
static const uint8_t eventpsk[] = {0x38, 0x4b, 0xbc, 0xc0, 0x1d, 0xc0, 0x22, 0xd1, 0x81, 0xbf, 0x36,
0xb8, 0x61, 0x21, 0xe1, 0xfb, 0x96, 0xb7, 0x2e, 0x55, 0xbf, 0x74,
0x22, 0x7e, 0x9d, 0x6a, 0xfb, 0x48, 0xd6, 0x4c, 0xb1, 0xa1};

View File

@@ -84,7 +84,7 @@ bool CryptoEngine::encryptCurve25519(uint32_t toNode, uint32_t fromNode, uint64_
// Calculate the shared secret with the destination node and encrypt
printBytes("Attempting encrypt using nonce: ", nonce, 13);
printBytes("Attempting encrypt using shared_key: ", shared_key, 32);
printBytes("Attempting encrypt using shared_key starting with: ", shared_key, 8);
aes_ccm_ae(shared_key, 32, nonce, 8, bytes, numBytes, nullptr, 0, bytesOut,
auth); // this can write up to 15 bytes longer than numbytes past bytesOut
*extraNonce = extraNonceTmp;
@@ -117,7 +117,7 @@ bool CryptoEngine::decryptCurve25519(uint32_t fromNode, uint64_t packetNum, size
}
initNonce(fromNode, packetNum, *extraNonce);
printBytes("Attempting decrypt using nonce: ", nonce, 13);
printBytes("Attempting decrypt using shared_key: ", shared_key, 32);
printBytes("Attempting decrypt using shared_key starting with: ", shared_key, 8);
return aes_ccm_ad(shared_key, 32, nonce, 8, bytes, numBytes - 12, nullptr, 0, auth, bytesOut);
}
@@ -137,11 +137,12 @@ bool CryptoEngine::setDHKey(uint32_t nodeNum)
LOG_DEBUG("Node %d or their public_key not found\n", nodeNum);
return false;
}
printBytes("Generating DH with remote pubkey: ", node->user.public_key.bytes, 32);
printBytes("And local pubkey: ", config.security.public_key.bytes, 32);
if (!setDHPublicKey(node->user.public_key.bytes))
return false;
printBytes("DH Output: ", shared_key, 32);
// printBytes("DH Output: ", shared_key, 32);
/**
* D.J. Bernstein reccomends hashing the shared key. We want to do this because there are

View File

@@ -3,6 +3,8 @@
#include <cstdint>
#define ONE_DAY 24 * 60 * 60
#define ONE_MINUTE_MS 60 * 1000
#define THIRTY_SECONDS_MS 30 * 1000
#define FIVE_SECONDS_MS 5 * 1000
#define default_gps_update_interval IF_ROUTER(ONE_DAY, 2 * 60)
#define default_telemetry_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 30 * 60)

View File

@@ -1,7 +1,9 @@
#include "LR11x0Interface.h"
#include "Throttle.h"
#include "configuration.h"
#include "error.h"
#include "mesh/NodeDB.h"
#ifdef ARCH_PORTDUINO
#include "PortduinoGlue.h"
#endif
@@ -104,6 +106,13 @@ template <typename T> bool LR11x0Interface<T>::init()
if (res == RADIOLIB_ERR_CHIP_NOT_FOUND)
return false;
LR11x0VersionInfo_t version;
res = lora.getVersionInfo(&version);
if (res == RADIOLIB_ERR_NONE)
LOG_DEBUG("LR11x0 Device %d, HW %d, FW %d.%d, WiFi %d.%d, GNSS %d.%d\n", version.device, version.hardware,
version.fwMajor, version.fwMinor, version.fwMajorWiFi, version.fwMinorWiFi, version.fwGNSS,
version.almanacGNSS);
LOG_INFO("Frequency set to %f\n", getFreq());
LOG_INFO("Bandwidth set to %f\n", bw);
LOG_INFO("Power output set to %d\n", power);
@@ -268,15 +277,15 @@ template <typename T> bool LR11x0Interface<T>::isActivelyReceiving()
bool detected = (irq & (RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID | RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED));
// Handle false detections
if (detected) {
uint32_t now = millis();
if (!activeReceiveStart) {
activeReceiveStart = now;
} else if ((now - activeReceiveStart > 2 * preambleTimeMsec) && !(irq & RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID)) {
activeReceiveStart = millis();
} else if (!Throttle::isWithinTimespanMs(activeReceiveStart, 2 * preambleTimeMsec) &&
!(irq & RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID)) {
// The HEADER_VALID flag should be set by now if it was really a packet, so ignore PREAMBLE_DETECTED flag
activeReceiveStart = 0;
LOG_DEBUG("Ignore false preamble detection.\n");
return false;
} else if (now - activeReceiveStart > maxPacketTimeMsec) {
} else if (!Throttle::isWithinTimespanMs(activeReceiveStart, maxPacketTimeMsec)) {
// We should have gotten an RX_DONE IRQ by now if it was really a packet, so ignore HEADER_VALID flag
activeReceiveStart = 0;
LOG_DEBUG("Ignore false header detection.\n");

View File

@@ -92,6 +92,9 @@ class MeshService
/// Return the next MqttClientProxyMessage packet destined to the phone.
meshtastic_MqttClientProxyMessage *getMqttClientProxyMessageForPhone() { return toPhoneMqttProxyQueue.dequeuePtr(0); }
/// Return the next ClientNotification packet destined to the phone.
meshtastic_ClientNotification *getClientNotificationForPhone() { return toPhoneClientNotificationQueue.dequeuePtr(0); }
// search the queue for a request id and return the matching nodenum
NodeNum getNodenumFromRequestId(uint32_t request_id);

View File

@@ -121,6 +121,8 @@ NodeDB::NodeDB()
owner.hw_model = HW_VENDOR;
// Ensure user (nodeinfo) role is set to whatever we're configured to
owner.role = config.device.role;
// Ensure macaddr is set to our macaddr as it will be copied in our info below
memcpy(owner.macaddr, ourMacAddr, sizeof(owner.macaddr));
// Include our owner in the node db under our nodenum
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(getNodeNum());
@@ -243,7 +245,7 @@ bool NodeDB::factoryReset(bool eraseBleBonds)
#endif
// second, install default state (this will deal with the duplicate mac address issue)
installDefaultDeviceState();
installDefaultConfig();
installDefaultConfig(!eraseBleBonds); // Also preserve the private key if we're not erasing BLE bonds
installDefaultModuleConfig();
installDefaultChannels();
// third, write everything to disk
@@ -266,8 +268,13 @@ bool NodeDB::factoryReset(bool eraseBleBonds)
return true;
}
void NodeDB::installDefaultConfig()
void NodeDB::installDefaultConfig(bool preserveKey = false)
{
uint8_t private_key_temp[32];
bool shouldPreserveKey = preserveKey && config.has_security && config.security.private_key.size > 0;
if (shouldPreserveKey) {
memcpy(private_key_temp, config.security.private_key.bytes, config.security.private_key.size);
}
LOG_INFO("Installing default LocalConfig\n");
memset(&config, 0, sizeof(meshtastic_LocalConfig));
config.version = DEVICESTATE_CUR_VER;
@@ -285,6 +292,7 @@ void NodeDB::installDefaultConfig()
config.lora.tx_enabled =
true; // FIXME: maybe false in the future, and setting region to enable it. (unset region forces it off)
config.lora.override_duty_cycle = false;
config.lora.config_ok_to_mqtt = false;
#ifdef CONFIG_LORA_REGION_USERPREFS
config.lora.region = CONFIG_LORA_REGION_USERPREFS;
#else
@@ -307,8 +315,14 @@ void NodeDB::installDefaultConfig()
#else
config.security.admin_key[0].size = 0;
#endif
if (shouldPreserveKey) {
config.security.private_key.size = 32;
memcpy(config.security.private_key.bytes, private_key_temp, config.security.private_key.size);
printBytes("Restored key", config.security.private_key.bytes, config.security.private_key.size);
} else {
config.security.private_key.size = 0;
}
config.security.public_key.size = 0;
config.security.private_key.size = 0;
#ifdef PIN_GPS_EN
config.position.gps_en_gpio = PIN_GPS_EN;
#endif
@@ -362,6 +376,9 @@ void NodeDB::installDefaultConfig()
#ifdef DISPLAY_FLIP_SCREEN
config.display.flip_screen = true;
#endif
#ifdef RAK4630
config.display.wake_on_tap_or_motion = true;
#endif
#ifdef T_WATCH_S3
config.display.screen_on_secs = 30;
config.display.wake_on_tap_or_motion = true;
@@ -637,10 +654,13 @@ void NodeDB::pickNewNodeNum()
}
meshtastic_NodeInfoLite *found;
while ((nodeNum == NODENUM_BROADCAST || nodeNum < NUM_RESERVED) ||
((found = getMeshNode(nodeNum)) && memcmp(found->user.macaddr, ourMacAddr, sizeof(ourMacAddr)) != 0)) {
while (((found = getMeshNode(nodeNum)) && memcmp(found->user.macaddr, ourMacAddr, sizeof(ourMacAddr)) != 0) ||
(nodeNum == NODENUM_BROADCAST || nodeNum < NUM_RESERVED)) {
NodeNum candidate = random(NUM_RESERVED, LONG_MAX); // try a new random choice
LOG_WARN("NOTE! Our desired nodenum 0x%x is invalid or in use, so trying for 0x%x\n", nodeNum, candidate);
if (found)
LOG_WARN("NOTE! Our desired nodenum 0x%x is invalid or in use, by MAC ending in 0x%02x%02x vs our 0x%02x%02x, so "
"trying for 0x%x\n",
nodeNum, found->user.macaddr[4], found->user.macaddr[5], ourMacAddr[4], ourMacAddr[5], candidate);
nodeNum = candidate;
}
LOG_DEBUG("Using nodenum 0x%x \n", nodeNum);
@@ -706,7 +726,7 @@ void NodeDB::loadFromDisk()
//} else {
if (devicestate.version < DEVICESTATE_MIN_VER) {
LOG_WARN("Devicestate %d is old, discarding\n", devicestate.version);
factoryReset();
installDefaultDeviceState();
} else {
LOG_INFO("Loaded saved devicestate version %d, with nodecount: %d\n", devicestate.version,
devicestate.node_db_lite.size());
@@ -722,7 +742,7 @@ void NodeDB::loadFromDisk()
} else {
if (config.version < DEVICESTATE_MIN_VER) {
LOG_WARN("config %d is old, discarding\n", config.version);
installDefaultConfig();
installDefaultConfig(true);
} else {
LOG_INFO("Loaded saved config version %d\n", config.version);
}
@@ -1035,7 +1055,7 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
if (p.public_key.size > 0) {
printBytes("Incoming Pubkey: ", p.public_key.bytes, 32);
if (info->user.public_key.size > 0) { // if we have a key for this user already, don't overwrite with a new one
LOG_INFO("Public Key set for node, not updateing!\n");
LOG_INFO("Public Key set for node, not updating!\n");
// we copy the key into the incoming packet, to prevent overwrite
memcpy(p.public_key.bytes, info->user.public_key.bytes, 32);
} else {
@@ -1093,8 +1113,10 @@ void NodeDB::updateFrom(const meshtastic_MeshPacket &mp)
info->via_mqtt = mp.via_mqtt; // Store if we received this packet via MQTT
// If hopStart was set and there wasn't someone messing with the limit in the middle, add hopsAway
if (mp.hop_start != 0 && mp.hop_limit <= mp.hop_start)
if (mp.hop_start != 0 && mp.hop_limit <= mp.hop_start) {
info->has_hops_away = true;
info->hops_away = mp.hop_start - mp.hop_limit;
}
}
}

View File

@@ -182,7 +182,8 @@ class NodeDB
void cleanupMeshDB();
/// Reinit device state from scratch (not loading from disk)
void installDefaultDeviceState(), installDefaultChannels(), installDefaultConfig(), installDefaultModuleConfig();
void installDefaultDeviceState(), installDefaultChannels(), installDefaultConfig(bool preserveKey),
installDefaultModuleConfig();
/// write to flash
/// @return true if the save was successful

View File

@@ -5,6 +5,7 @@
#ifdef ARCH_PORTDUINO
#include "platform/portduino/PortduinoGlue.h"
#endif
#include "Throttle.h"
PacketHistory::PacketHistory()
{
@@ -22,18 +23,17 @@ bool PacketHistory::wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpd
return false; // Not a floodable message ID, so we don't care
}
uint32_t now = millis();
PacketRecord r;
r.id = p->id;
r.sender = getFrom(p);
r.rxTimeMsec = now;
r.rxTimeMsec = millis();
auto found = recentPackets.find(r);
bool seenRecently = (found != recentPackets.end()); // found not equal to .end() means packet was seen recently
if (seenRecently && (now - found->rxTimeMsec) >= FLOOD_EXPIRE_TIME) { // Check whether found packet has already expired
recentPackets.erase(found); // Erase and pretend packet has not been seen recently
if (seenRecently &&
!Throttle::isWithinTimespanMs(found->rxTimeMsec, FLOOD_EXPIRE_TIME)) { // Check whether found packet has already expired
recentPackets.erase(found); // Erase and pretend packet has not been seen recently
found = recentPackets.end();
seenRecently = false;
}
@@ -64,12 +64,10 @@ bool PacketHistory::wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpd
*/
void PacketHistory::clearExpiredRecentPackets()
{
uint32_t now = millis();
LOG_DEBUG("recentPackets size=%ld\n", recentPackets.size());
for (auto it = recentPackets.begin(); it != recentPackets.end();) {
if ((now - it->rxTimeMsec) >= FLOOD_EXPIRE_TIME) {
if (!Throttle::isWithinTimespanMs(it->rxTimeMsec, FLOOD_EXPIRE_TIME)) {
it = recentPackets.erase(it); // erase returns iterator pointing to element immediately following the one erased
} else {
++it;

View File

@@ -25,6 +25,8 @@
#if !MESHTASTIC_EXCLUDE_MQTT
#include "mqtt/MQTT.h"
#endif
#include "Throttle.h"
#include <RTC.h>
PhoneAPI::PhoneAPI()
{
@@ -60,9 +62,11 @@ void PhoneAPI::handleStartConfig()
void PhoneAPI::close()
{
LOG_INFO("PhoneAPI::close()\n");
if (state != STATE_SEND_NOTHING) {
state = STATE_SEND_NOTHING;
resetReadIndex();
unobserve(&service->fromNumChanged);
#ifdef FSCom
unobserve(&xModem.packetReady);
@@ -70,8 +74,17 @@ void PhoneAPI::close()
releasePhonePacket(); // Don't leak phone packets on shutdown
releaseQueueStatusPhonePacket();
releaseMqttClientProxyPhonePacket();
releaseClientNotification();
onConnectionChanged(false);
fromRadioScratch = {};
toRadioScratch = {};
nodeInfoForPhone = {};
packetForPhone = NULL;
filesManifest.clear();
fromRadioNum = 0;
config_nonce = 0;
config_state = 0;
pauseBluetoothLogging = false;
}
}
@@ -194,7 +207,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
auto us = nodeDB->readNextMeshNode(readIndex);
if (us) {
nodeInfoForPhone = TypeConversions::ConvertToNodeInfo(us);
nodeInfoForPhone.hops_away = 0;
nodeInfoForPhone.has_hops_away = false;
nodeInfoForPhone.is_favorite = true;
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_node_info_tag;
fromRadioScratch.node_info = nodeInfoForPhone;
@@ -403,6 +416,10 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_xmodemPacket_tag;
fromRadioScratch.xmodemPacket = xmodemPacketForPhone;
xmodemPacketForPhone = meshtastic_XModem_init_zero;
} else if (clientNotification) {
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_clientNotification_tag;
fromRadioScratch.clientNotification = *clientNotification;
releaseClientNotification();
} else if (packetForPhone) {
printPacket("phone downloaded packet", packetForPhone);
@@ -442,13 +459,6 @@ void PhoneAPI::sendConfigComplete()
pauseBluetoothLogging = false;
}
void PhoneAPI::handleDisconnect()
{
filesManifest.clear();
pauseBluetoothLogging = false;
LOG_INFO("PhoneAPI disconnect\n");
}
void PhoneAPI::releasePhonePacket()
{
if (packetForPhone) {
@@ -473,6 +483,14 @@ void PhoneAPI::releaseMqttClientProxyPhonePacket()
}
}
void PhoneAPI::releaseClientNotification()
{
if (clientNotification) {
service->releaseClientNotificationToPool(clientNotification);
clientNotification = NULL;
}
}
/**
* Return true if we have data available to send to the phone
*/
@@ -507,7 +525,9 @@ bool PhoneAPI::available()
queueStatusPacketForPhone = service->getQueueStatusForPhone();
if (!mqttClientProxyMessageForPhone)
mqttClientProxyMessageForPhone = service->getMqttClientProxyMessageForPhone();
bool hasPacket = !!queueStatusPacketForPhone || !!mqttClientProxyMessageForPhone;
if (!clientNotification)
clientNotification = service->getClientNotificationForPhone();
bool hasPacket = !!queueStatusPacketForPhone || !!mqttClientProxyMessageForPhone || !!clientNotification;
if (hasPacket)
return true;
@@ -541,14 +561,36 @@ bool PhoneAPI::available()
return false;
}
void PhoneAPI::sendNotification(meshtastic_LogRecord_Level level, uint32_t replyId, const char *message)
{
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
cn->has_reply_id = true;
cn->reply_id = replyId;
cn->level = meshtastic_LogRecord_Level_WARNING;
cn->time = getValidTime(RTCQualityFromNet);
strncpy(cn->message, message, sizeof(cn->message));
service->sendClientNotification(cn);
}
/**
* Handle a packet that the phone wants us to send. It is our responsibility to free the packet to the pool
*/
bool PhoneAPI::handleToRadioPacket(meshtastic_MeshPacket &p)
{
printPacket("PACKET FROM PHONE", &p);
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\n", p.decoded.portnum);
sendNotification(meshtastic_LogRecord_Level_WARNING, p.id, "TraceRoute can only be sent once every 30 seconds");
return false;
} else if (p.decoded.portnum == meshtastic_PortNum_POSITION_APP && lastPortNumToRadio[p.decoded.portnum] &&
Throttle::isWithinTimespanMs(lastPortNumToRadio[p.decoded.portnum], FIVE_SECONDS_MS)) {
LOG_WARN("Rate limiting portnum %d\n", p.decoded.portnum);
sendNotification(meshtastic_LogRecord_Level_WARNING, p.id, "Position can only be sent once every 5 seconds");
return false;
}
lastPortNumToRadio[p.decoded.portnum] = millis();
service->handleToRadio(p);
return true;
}

View File

@@ -2,8 +2,10 @@
#include "Observer.h"
#include "mesh-pb-constants.h"
#include "meshtastic/portnums.pb.h"
#include <iterator>
#include <string>
#include <unordered_map>
#include <vector>
// Make sure that we never let our packets grow too large for one BLE packet
@@ -48,6 +50,9 @@ class PhoneAPI
uint8_t config_state = 0;
// Hashmap of timestamps for last time we received a packet on the API per portnum
std::unordered_map<meshtastic_PortNum, uint32_t> lastPortNumToRadio;
/**
* Each packet sent to the phone has an incrementing count
*/
@@ -99,6 +104,11 @@ class PhoneAPI
*/
virtual bool handleToRadio(const uint8_t *buf, size_t len);
/**
* Send a (client)notification to the phone
*/
virtual void sendNotification(meshtastic_LogRecord_Level level, uint32_t replyId, const char *message);
/**
* Get the next packet we want to send to the phone
*
@@ -137,11 +147,6 @@ class PhoneAPI
*/
virtual void onNowHasData(uint32_t fromRadioNum) {}
/**
* Subclasses can use this to find out when a client drops the link
*/
virtual void handleDisconnect();
private:
void releasePhonePacket();
@@ -149,6 +154,8 @@ class PhoneAPI
void releaseMqttClientProxyPhonePacket();
void releaseClientNotification();
/// begin a new connection
void handleStartConfig();

View File

@@ -151,7 +151,7 @@ const RegionInfo regions[] = {
const RegionInfo *myRegion;
bool RadioInterface::uses_default_frequency_slot = true;
static uint8_t bytes[MAX_RHPACKETLEN];
static uint8_t bytes[MAX_LORA_PAYLOAD_LEN + 1];
void initRegion()
{
@@ -326,7 +326,7 @@ void printPacket(const char *prefix, const meshtastic_MeshPacket *p)
RadioInterface::RadioInterface()
{
assert(sizeof(PacketHeader) == 16); // make sure the compiler did what we expected
assert(sizeof(PacketHeader) == MESHTASTIC_HEADER_LENGTH); // make sure the compiler did what we expected
}
bool RadioInterface::reconfigure()
@@ -420,7 +420,7 @@ void RadioInterface::applyModemConfig()
switch (loraConfig.modem_preset) {
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO:
bw = (myRegion->wideLora) ? 812.5 : 500;
bw = (myRegion->wideLora) ? 1625.0 : 500;
cr = 5;
sf = 7;
break;

View File

@@ -9,7 +9,9 @@
#define MAX_TX_QUEUE 16 // max number of packets which can be waiting for transmission
#define MAX_RHPACKETLEN 256
#define MAX_LORA_PAYLOAD_LEN 255 // max length of 255 per Semtech's datasheets on SX12xx
#define MESHTASTIC_HEADER_LENGTH 16
#define MESHTASTIC_PKC_OVERHEAD 12
#define PACKET_FLAGS_HOP_LIMIT_MASK 0x07
#define PACKET_FLAGS_WANT_ACK_MASK 0x08
@@ -89,7 +91,7 @@ class RadioInterface
/**
* A temporary buffer used for sending/receiving packets, sized to hold the biggest buffer we might need
* */
uint8_t radiobuf[MAX_RHPACKETLEN];
uint8_t radiobuf[MAX_LORA_PAYLOAD_LEN + 1];
/**
* Enqueue a received packet for the registered receiver

View File

@@ -3,6 +3,7 @@
#include "NodeDB.h"
#include "PowerMon.h"
#include "SPILock.h"
#include "Throttle.h"
#include "configuration.h"
#include "error.h"
#include "main.h"
@@ -41,7 +42,7 @@ void LockingArduinoHal::spiTransfer(uint8_t *out, size_t len, uint8_t *in)
uint32_t start = millis();
while (digitalRead(busy)) {
if (millis() - start >= 2000) {
if (!Throttle::isWithinTimespanMs(start, 2000)) {
LOG_ERROR("GPIO mid-transfer timeout, is it connected?");
return;
}
@@ -114,7 +115,7 @@ bool RadioLibInterface::canSendImmediately()
}
// If we've been trying to send the same packet more than one minute and we haven't gotten a
// TX IRQ from the radio, the radio is probably broken.
if (busyTx && (millis() - lastTxStart > 60000)) {
if (busyTx && !Throttle::isWithinTimespanMs(lastTxStart, 60000)) {
LOG_ERROR("Hardware Failure! busyTx for more than 60s\n");
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_TRANSMIT_FAILED);
// reboot in 5 seconds when this condition occurs.

View File

@@ -36,8 +36,8 @@ static MemoryDynamic<meshtastic_MeshPacket> staticPool;
Allocator<meshtastic_MeshPacket> &packetPool = staticPool;
static uint8_t bytes[MAX_RHPACKETLEN];
static uint8_t ScratchEncrypted[MAX_RHPACKETLEN];
static uint8_t bytes[MAX_LORA_PAYLOAD_LEN + 1];
static uint8_t ScratchEncrypted[MAX_LORA_PAYLOAD_LEN + 1];
/**
* Constructor
@@ -185,9 +185,12 @@ ErrorCode Router::sendLocal(meshtastic_MeshPacket *p, RxSource src)
handleReceived(p, src);
}
if (!p->channel) { // don't override if a channel was requested
p->channel = nodeDB->getMeshNodeChannel(p->to);
LOG_DEBUG("localSend to channel %d\n", p->channel);
if (!p->channel && !p->pki_encrypted) { // don't override if a channel was requested
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(p->to);
if (node && node->user.public_key.size == 0) {
p->channel = node->channel;
LOG_DEBUG("localSend to channel %d\n", p->channel);
}
}
return send(p);
@@ -327,13 +330,13 @@ bool perhapsDecode(meshtastic_MeshPacket *p)
// Attempt PKI decryption first
if (p->channel == 0 && p->to == nodeDB->getNodeNum() && p->to > 0 && p->to != NODENUM_BROADCAST &&
nodeDB->getMeshNode(p->from) != nullptr && nodeDB->getMeshNode(p->from)->user.public_key.size > 0 &&
nodeDB->getMeshNode(p->to)->user.public_key.size > 0 && rawSize > 12) {
nodeDB->getMeshNode(p->to)->user.public_key.size > 0 && rawSize > MESHTASTIC_PKC_OVERHEAD) {
LOG_DEBUG("Attempting PKI decryption\n");
if (crypto->decryptCurve25519(p->from, p->id, rawSize, ScratchEncrypted, bytes)) {
LOG_INFO("PKI Decryption worked!\n");
memset(&p->decoded, 0, sizeof(p->decoded));
rawSize -= 12;
rawSize -= MESHTASTIC_PKC_OVERHEAD;
if (pb_decode_from_bytes(bytes, rawSize, &meshtastic_Data_msg, &p->decoded) &&
p->decoded.portnum != meshtastic_PortNum_UNKNOWN_APP) {
decrypted = true;
@@ -344,8 +347,11 @@ bool perhapsDecode(meshtastic_MeshPacket *p)
// memcpy(bytes, ScratchEncrypted, rawSize); // TODO: Rename the bytes buffers
// chIndex = 8;
} else {
LOG_ERROR("PKC Decrypted, but pb_decode failed!\n");
return false;
}
} else {
LOG_WARN("PKC decrypt attempted but failed!\n");
}
}
#endif
@@ -378,6 +384,8 @@ bool perhapsDecode(meshtastic_MeshPacket *p)
// parsing was successful
p->which_payload_variant = meshtastic_MeshPacket_decoded_tag; // change type to decoded
p->channel = chIndex; // change to store the index instead of the hash
if (p->decoded.has_bitfield)
p->decoded.want_response |= p->decoded.bitfield & BITFIELD_WANT_RESPONSE_MASK;
/* Not actually ever used.
// Decompress if needed. jm
@@ -424,6 +432,12 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
// If the packet is not yet encrypted, do so now
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
if (p->from == nodeDB->getNodeNum()) {
p->decoded.has_bitfield = true;
p->decoded.bitfield |= (config.lora.config_ok_to_mqtt << BITFIELD_OK_TO_MQTT_SHIFT);
p->decoded.bitfield |= (p->decoded.want_response << BITFIELD_WANT_RESPONSE_SHIFT);
}
size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), &meshtastic_Data_msg, &p->decoded);
/* Not actually used, so save the cycles
@@ -461,7 +475,7 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
}
} */
if (numbytes > MAX_RHPACKETLEN)
if (numbytes + MESHTASTIC_HEADER_LENGTH > MAX_LORA_PAYLOAD_LEN)
return meshtastic_Routing_Error_TOO_LARGE;
// printBytes("plaintext", bytes, numbytes);
@@ -470,12 +484,22 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
#if !(MESHTASTIC_EXCLUDE_PKI)
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(p->to);
if (!owner.is_licensed && config.security.private_key.size == 32 && p->to != NODENUM_BROADCAST && node != nullptr &&
node->user.public_key.size > 0 && 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) {
// 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 (
// 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
!(p->pki_encrypted != true && p->channel > 0) &&
// Check for valid keys and single node destination
config.security.private_key.size == 32 && p->to != NODENUM_BROADCAST && node != nullptr &&
// Check for a known public key for the destination
(node->user.public_key.size == 32) &&
// 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!\n");
if (numbytes + 12 > MAX_RHPACKETLEN)
if (numbytes + MESHTASTIC_HEADER_LENGTH + MESHTASTIC_PKC_OVERHEAD > MAX_LORA_PAYLOAD_LEN)
return meshtastic_Routing_Error_TOO_LARGE;
if (p->pki_encrypted && !memfll(p->public_key.bytes, 0, 32) &&
memcmp(p->public_key.bytes, node->user.public_key.bytes, 32) != 0) {
@@ -484,7 +508,7 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
return meshtastic_Routing_Error_PKI_FAILED;
}
crypto->encryptCurve25519(p->to, getFrom(p), p->id, numbytes, bytes, ScratchEncrypted);
numbytes += 12;
numbytes += MESHTASTIC_PKC_OVERHEAD;
memcpy(p->encrypted.bytes, ScratchEncrypted, numbytes);
p->channel = 0;
p->pki_encrypted = true;

View File

@@ -148,3 +148,8 @@ extern Router *router;
/// Generate a unique packet id
// FIXME, move this someplace better
PacketId generatePacketId();
#define BITFIELD_WANT_RESPONSE_SHIFT 1
#define BITFIELD_OK_TO_MQTT_SHIFT 0
#define BITFIELD_WANT_RESPONSE_MASK (1 << BITFIELD_WANT_RESPONSE_SHIFT)
#define BITFIELD_OK_TO_MQTT_MASK (1 << BITFIELD_OK_TO_MQTT_SHIFT)

View File

@@ -6,6 +6,8 @@
#include "PortduinoGlue.h"
#endif
#include "Throttle.h"
// Particular boards might define a different max power based on what their hardware can do, default to max power output if not
// specified (may be dangerous if using external PA and SX126x power config forgotten)
#ifndef SX126X_MAX_POWER
@@ -25,9 +27,25 @@ SX126xInterface<T>::SX126xInterface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs
/// \return true if initialisation succeeded.
template <typename T> bool SX126xInterface<T>::init()
{
#ifdef SX126X_POWER_EN
pinMode(SX126X_POWER_EN, OUTPUT);
// Typically, the RF switch on SX126x boards is controlled by two signals, which are negations of each other (switched RFIO
// paths). The negation is usually performed in hardware, or (suboptimal design) TXEN and RXEN are the two inputs to this style of
// RF switch. On some boards, there is no hardware negation between CTRL and ¬CTRL, but CTRL is internally connected to DIO2, and
// DIO2's switching is done by the SX126X itself, so the MCU can't control ¬CTRL at exactly the same time. One solution would be
// to set ¬CTRL as SX126X_TXEN or SX126X_RXEN, but they may already be used for another purpose, such as controlling another
// PA/LNA. Keeping ¬CTRL high seems to work, as long CTRL=1, ¬CTRL=1 has the opposite and stable RF path effect as CTRL=0 and
// ¬CTRL=1, this depends on the RF switch, but it seems this usually works. Better hardware design, which is done most the time,
// means this workaround is not necessary.
#ifdef SX126X_ANT_SW // Perhaps add RADIOLIB_NC check, and beforehand define as such if it is undefined, but it is not commonly
// used and not part of the 'default' set of pin definitions.
digitalWrite(SX126X_ANT_SW, HIGH);
pinMode(SX126X_ANT_SW, OUTPUT);
#endif
#ifdef SX126X_POWER_EN // Perhaps add RADIOLIB_NC check, and beforehand define as such if it is undefined, but it is not commonly
// used and not part of the 'default' set of pin definitions.
digitalWrite(SX126X_POWER_EN, HIGH);
pinMode(SX126X_POWER_EN, OUTPUT);
#endif
#if ARCH_PORTDUINO
@@ -303,15 +321,15 @@ template <typename T> bool SX126xInterface<T>::isActivelyReceiving()
bool detected = (irq & (RADIOLIB_SX126X_IRQ_HEADER_VALID | RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED));
// Handle false detections
if (detected) {
uint32_t now = millis();
if (!activeReceiveStart) {
activeReceiveStart = now;
} else if ((now - activeReceiveStart > 2 * preambleTimeMsec) && !(irq & RADIOLIB_SX126X_IRQ_HEADER_VALID)) {
activeReceiveStart = millis();
} else if (!Throttle::isWithinTimespanMs(activeReceiveStart, 2 * preambleTimeMsec) &&
!(irq & RADIOLIB_SX126X_IRQ_HEADER_VALID)) {
// The HEADER_VALID flag should be set by now if it was really a packet, so ignore PREAMBLE_DETECTED flag
activeReceiveStart = 0;
LOG_DEBUG("Ignore false preamble detection.\n");
return false;
} else if (now - activeReceiveStart > maxPacketTimeMsec) {
} else if (!Throttle::isWithinTimespanMs(activeReceiveStart, maxPacketTimeMsec)) {
// We should have gotten an RX_DONE IRQ by now if it was really a packet, so ignore HEADER_VALID flag
activeReceiveStart = 0;
LOG_DEBUG("Ignore false header detection.\n");
@@ -343,4 +361,4 @@ template <typename T> bool SX126xInterface<T>::sleep()
#endif
return true;
}
}

View File

@@ -1,4 +1,5 @@
#include "SX128xInterface.h"
#include "Throttle.h"
#include "configuration.h"
#include "error.h"
#include "mesh/NodeDB.h"
@@ -294,15 +295,15 @@ template <typename T> bool SX128xInterface<T>::isActivelyReceiving()
// Handle false detections
if (detected) {
uint32_t now = millis();
if (!activeReceiveStart) {
activeReceiveStart = now;
} else if ((now - activeReceiveStart > 2 * preambleTimeMsec) && !(irq & RADIOLIB_SX128X_IRQ_HEADER_VALID)) {
activeReceiveStart = millis();
} else if (!Throttle::isWithinTimespanMs(activeReceiveStart, 2 * preambleTimeMsec) &&
!(irq & RADIOLIB_SX128X_IRQ_HEADER_VALID)) {
// The HEADER_VALID flag should be set by now if it was really a packet, so ignore PREAMBLE_DETECTED flag
activeReceiveStart = 0;
LOG_DEBUG("Ignore false preamble detection.\n");
return false;
} else if (now - activeReceiveStart > maxPacketTimeMsec) {
} else if (Throttle::isWithinTimespanMs(activeReceiveStart, maxPacketTimeMsec)) {
// We should have gotten an RX_DONE IRQ by now if it was really a packet, so ignore HEADER_VALID flag
activeReceiveStart = 0;
LOG_DEBUG("Ignore false header detection.\n");

View File

@@ -1,6 +1,7 @@
#include "StreamAPI.h"
#include "PowerFSM.h"
#include "RTC.h"
#include "Throttle.h"
#include "configuration.h"
#define START1 0x94
@@ -20,10 +21,9 @@ int32_t StreamAPI::runOncePart()
*/
int32_t StreamAPI::readStream()
{
uint32_t now = millis();
if (!stream->available()) {
// Nothing available this time, if the computer has talked to us recently, poll often, otherwise let CPU sleep a long time
bool recentRx = (now - lastRxMsec) < 2000;
bool recentRx = Throttle::isWithinTimespanMs(lastRxMsec, 2000);
return recentRx ? 5 : 250;
} else {
while (stream->available()) { // Currently we never want to block
@@ -71,7 +71,7 @@ int32_t StreamAPI::readStream()
}
// we had bytes available this time, so assume we might have them next time also
lastRxMsec = now;
lastRxMsec = millis();
return 0;
}
}

View File

@@ -24,4 +24,12 @@ bool Throttle::execute(uint32_t *lastExecutionMs, uint32_t minumumIntervalMs, vo
onDefer();
}
return false;
}
/// @brief Check if the last execution time is within the interval
/// @param lastExecutionMs The last execution time in milliseconds
/// @param timeSpanMs The interval in milliseconds of the timespan
bool Throttle::isWithinTimespanMs(uint32_t lastExecutionMs, uint32_t timeSpanMs)
{
return (millis() - lastExecutionMs) < timeSpanMs;
}

View File

@@ -6,4 +6,5 @@ class Throttle
{
public:
static bool execute(uint32_t *lastExecutionMs, uint32_t minumumIntervalMs, void (*func)(void), void (*onDefer)(void) = NULL);
static bool isWithinTimespanMs(uint32_t lastExecutionMs, uint32_t intervalMs);
};

View File

@@ -11,9 +11,13 @@ meshtastic_NodeInfo TypeConversions::ConvertToNodeInfo(const meshtastic_NodeInfo
info.last_heard = lite->last_heard;
info.channel = lite->channel;
info.via_mqtt = lite->via_mqtt;
info.hops_away = lite->hops_away;
info.is_favorite = lite->is_favorite;
if (lite->has_hops_away) {
info.has_hops_away = true;
info.hops_away = lite->hops_away;
}
if (lite->has_position) {
info.has_position = true;
if (lite->position.latitude_i != 0)
@@ -78,7 +82,7 @@ meshtastic_UserLite TypeConversions::ConvertToUserLite(meshtastic_User user)
lite.hw_model = user.hw_model;
lite.role = user.role;
lite.is_licensed = user.is_licensed;
memccpy(lite.macaddr, user.macaddr, sizeof(user.macaddr), sizeof(lite.macaddr));
memcpy(lite.macaddr, user.macaddr, sizeof(lite.macaddr));
memcpy(lite.public_key.bytes, user.public_key.bytes, sizeof(lite.public_key.bytes));
lite.public_key.size = user.public_key.size;
return lite;
@@ -94,7 +98,7 @@ meshtastic_User TypeConversions::ConvertToUser(uint32_t nodeNum, meshtastic_User
user.hw_model = lite.hw_model;
user.role = lite.role;
user.is_licensed = lite.is_licensed;
memccpy(user.macaddr, lite.macaddr, sizeof(lite.macaddr), sizeof(user.macaddr));
memcpy(user.macaddr, lite.macaddr, sizeof(user.macaddr));
memcpy(user.public_key.bytes, lite.public_key.bytes, sizeof(user.public_key.bytes));
user.public_key.size = lite.public_key.size;

View File

@@ -5,7 +5,7 @@
template <typename T>
ServerAPI<T>::ServerAPI(T &_client) : StreamAPI(&client), concurrency::OSThread("ServerAPI"), client(_client)
{
LOG_INFO("Incoming wifi connection\n");
LOG_INFO("Incoming API connection\n");
}
template <typename T> ServerAPI<T>::~ServerAPI()
@@ -49,6 +49,16 @@ template <class T, class U> int32_t APIServerPort<T, U>::runOnce()
if (client) {
// Close any previous connection (see FIXME in header file)
if (openAPI) {
#if RAK_4631
// RAK13800 Ethernet requests periodically take more time
// This backoff addresses most cases keeping max wait < 1s
// Reconnections are delayed by full wait time
if (waitTime < 400) {
waitTime *= 2;
LOG_INFO("Previous TCP connection still open, trying again in %dms\n", waitTime);
return waitTime;
}
#endif
LOG_INFO("Force closing previous TCP connection\n");
delete openAPI;
}
@@ -56,5 +66,8 @@ template <class T, class U> int32_t APIServerPort<T, U>::runOnce()
openAPI = new T(client);
}
#if RAK_4631
waitTime = 100;
#endif
return 100; // only check occasionally for incoming connections
}

View File

@@ -31,7 +31,7 @@ template <class T> class ServerAPI : public StreamAPI, private concurrency::OSTh
};
/**
* Listens for incoming connections and does accepts and creates instances of WiFiServerAPI as needed
* Listens for incoming connections and does accepts and creates instances of ServerAPI as needed
*/
template <class T, class U> class APIServerPort : public U, private concurrency::OSThread
{
@@ -41,6 +41,10 @@ template <class T, class U> class APIServerPort : public U, private concurrency:
* delegate to the worker. Once coroutines are implemented we can relax this restriction.
*/
T *openAPI = NULL;
#if RAK_4631
// Track wait time for RAK13800 Ethernet requests
int32_t waitTime = 100;
#endif
public:
explicit APIServerPort(int port);

View File

@@ -14,7 +14,7 @@ class ethServerAPI : public ServerAPI<EthernetClient>
};
/**
* Listens for incoming connections and does accepts and creates instances of WiFiServerAPI as needed
* Listens for incoming connections and does accepts and creates instances of EthernetServerAPI as needed
*/
class ethServerPort : public APIServerPort<ethServerAPI, EthernetServer>
{

View File

@@ -38,7 +38,7 @@ static int32_t reconnectETH()
Ethernet.maintain();
if (!ethStartupComplete) {
// Start web server
LOG_INFO("... Starting network services\n");
LOG_INFO("Starting Ethernet network services\n");
#ifndef DISABLE_NTP
LOG_INFO("Starting NTP time client\n");
@@ -131,7 +131,8 @@ bool initEthernet()
status = Ethernet.begin(mac);
} else if (config.network.address_mode == meshtastic_Config_NetworkConfig_AddressMode_STATIC) {
LOG_INFO("starting Ethernet Static\n");
Ethernet.begin(mac, config.network.ipv4_config.ip, config.network.ipv4_config.dns, config.network.ipv4_config.subnet);
Ethernet.begin(mac, config.network.ipv4_config.ip, config.network.ipv4_config.dns, config.network.ipv4_config.gateway,
config.network.ipv4_config.subnet);
status = 1;
} else {
LOG_INFO("Ethernet Disabled\n");
@@ -186,4 +187,4 @@ bool isEthernetAvailable()
}
}
#endif
#endif

View File

@@ -55,7 +55,7 @@ extern const pb_msgdesc_t meshtastic_ChannelSet_msg;
/* Maximum encoded size of messages (where known) */
#define MESHTASTIC_MESHTASTIC_APPONLY_PB_H_MAX_SIZE meshtastic_ChannelSet_size
#define meshtastic_ChannelSet_size 676
#define meshtastic_ChannelSet_size 679
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -120,6 +120,7 @@ typedef struct _meshtastic_PLI {
uint16_t course;
} meshtastic_PLI;
typedef PB_BYTES_ARRAY_T(220) meshtastic_TAKPacket_detail_t;
/* Packets for the official ATAK Plugin */
typedef struct _meshtastic_TAKPacket {
/* Are the payloads strings compressed for LoRA transport? */
@@ -139,6 +140,9 @@ typedef struct _meshtastic_TAKPacket {
meshtastic_PLI pli;
/* ATAK GeoChat message */
meshtastic_GeoChat chat;
/* Generic CoT detail XML
May be compressed / truncated by the sender */
meshtastic_TAKPacket_detail_t detail;
} payload_variant;
} meshtastic_TAKPacket;
@@ -199,6 +203,7 @@ extern "C" {
#define meshtastic_TAKPacket_status_tag 4
#define meshtastic_TAKPacket_pli_tag 5
#define meshtastic_TAKPacket_chat_tag 6
#define meshtastic_TAKPacket_detail_tag 7
/* Struct field encoding specification for nanopb */
#define meshtastic_TAKPacket_FIELDLIST(X, a) \
@@ -207,7 +212,8 @@ X(a, STATIC, OPTIONAL, MESSAGE, contact, 2) \
X(a, STATIC, OPTIONAL, MESSAGE, group, 3) \
X(a, STATIC, OPTIONAL, MESSAGE, status, 4) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,pli,payload_variant.pli), 5) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,chat,payload_variant.chat), 6)
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,chat,payload_variant.chat), 6) \
X(a, STATIC, ONEOF, BYTES, (payload_variant,detail,payload_variant.detail), 7)
#define meshtastic_TAKPacket_CALLBACK NULL
#define meshtastic_TAKPacket_DEFAULT NULL
#define meshtastic_TAKPacket_contact_MSGTYPE meshtastic_Contact

View File

@@ -5,6 +5,7 @@
#define PB_MESHTASTIC_MESHTASTIC_CLIENTONLY_PB_H_INCLUDED
#include <pb.h>
#include "meshtastic/localonly.pb.h"
#include "meshtastic/mesh.pb.h"
#if PB_PROTO_HEADER_VERSION != 40
#error Regenerate this file with the current version of nanopb generator.
@@ -28,6 +29,15 @@ typedef struct _meshtastic_DeviceProfile {
/* The ModuleConfig of the node */
bool has_module_config;
meshtastic_LocalModuleConfig module_config;
/* Fixed position data */
bool has_fixed_position;
meshtastic_Position fixed_position;
/* Ringtone for ExternalNotification */
bool has_ringtone;
char ringtone[231];
/* Predefined messages for CannedMessage */
bool has_canned_messages;
char canned_messages[201];
} meshtastic_DeviceProfile;
@@ -36,8 +46,8 @@ extern "C" {
#endif
/* Initializer values for message structs */
#define meshtastic_DeviceProfile_init_default {false, "", false, "", {{NULL}, NULL}, false, meshtastic_LocalConfig_init_default, false, meshtastic_LocalModuleConfig_init_default}
#define meshtastic_DeviceProfile_init_zero {false, "", false, "", {{NULL}, NULL}, false, meshtastic_LocalConfig_init_zero, false, meshtastic_LocalModuleConfig_init_zero}
#define meshtastic_DeviceProfile_init_default {false, "", false, "", {{NULL}, NULL}, false, meshtastic_LocalConfig_init_default, false, meshtastic_LocalModuleConfig_init_default, false, meshtastic_Position_init_default, false, "", false, ""}
#define meshtastic_DeviceProfile_init_zero {false, "", false, "", {{NULL}, NULL}, false, meshtastic_LocalConfig_init_zero, false, meshtastic_LocalModuleConfig_init_zero, false, meshtastic_Position_init_zero, false, "", false, ""}
/* Field tags (for use in manual encoding/decoding) */
#define meshtastic_DeviceProfile_long_name_tag 1
@@ -45,6 +55,9 @@ extern "C" {
#define meshtastic_DeviceProfile_channel_url_tag 3
#define meshtastic_DeviceProfile_config_tag 4
#define meshtastic_DeviceProfile_module_config_tag 5
#define meshtastic_DeviceProfile_fixed_position_tag 6
#define meshtastic_DeviceProfile_ringtone_tag 7
#define meshtastic_DeviceProfile_canned_messages_tag 8
/* Struct field encoding specification for nanopb */
#define meshtastic_DeviceProfile_FIELDLIST(X, a) \
@@ -52,11 +65,15 @@ X(a, STATIC, OPTIONAL, STRING, long_name, 1) \
X(a, STATIC, OPTIONAL, STRING, short_name, 2) \
X(a, CALLBACK, OPTIONAL, STRING, channel_url, 3) \
X(a, STATIC, OPTIONAL, MESSAGE, config, 4) \
X(a, STATIC, OPTIONAL, MESSAGE, module_config, 5)
X(a, STATIC, OPTIONAL, MESSAGE, module_config, 5) \
X(a, STATIC, OPTIONAL, MESSAGE, fixed_position, 6) \
X(a, STATIC, OPTIONAL, STRING, ringtone, 7) \
X(a, STATIC, OPTIONAL, STRING, canned_messages, 8)
#define meshtastic_DeviceProfile_CALLBACK pb_default_field_callback
#define meshtastic_DeviceProfile_DEFAULT NULL
#define meshtastic_DeviceProfile_config_MSGTYPE meshtastic_LocalConfig
#define meshtastic_DeviceProfile_module_config_MSGTYPE meshtastic_LocalModuleConfig
#define meshtastic_DeviceProfile_fixed_position_MSGTYPE meshtastic_Position
extern const pb_msgdesc_t meshtastic_DeviceProfile_msg;

View File

@@ -510,6 +510,8 @@ typedef struct _meshtastic_Config_LoRaConfig {
uint32_t ignore_incoming[3];
/* If true, the device will not process any packets received via LoRa that passed via MQTT anywhere on the path towards it. */
bool ignore_mqtt;
/* Sets the ok_to_mqtt bit on outgoing packets */
bool config_ok_to_mqtt;
} meshtastic_Config_LoRaConfig;
typedef struct _meshtastic_Config_BluetoothConfig {
@@ -533,7 +535,7 @@ typedef struct _meshtastic_Config_SecurityConfig {
meshtastic_Config_SecurityConfig_private_key_t private_key;
/* The public key authorized to send admin messages to this node. */
pb_size_t admin_key_count;
meshtastic_Config_SecurityConfig_admin_key_t admin_key[1];
meshtastic_Config_SecurityConfig_admin_key_t admin_key[3];
/* If true, device is considered to be "managed" by a mesh administrator via admin messages
Device is managed by a mesh administrator. */
bool is_managed;
@@ -656,9 +658,9 @@ extern "C" {
#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""}
#define meshtastic_Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0}
#define meshtastic_Config_DisplayConfig_init_default {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN}
#define meshtastic_Config_LoRaConfig_init_default {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0}
#define meshtastic_Config_LoRaConfig_init_default {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0}
#define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
#define meshtastic_Config_SecurityConfig_init_default {{0, {0}}, {0, {0}}, 0, {{0, {0}}}, 0, 0, 0, 0}
#define meshtastic_Config_SecurityConfig_init_default {{0, {0}}, {0, {0}}, 0, {{0, {0}}, {0, {0}}, {0, {0}}}, 0, 0, 0, 0}
#define meshtastic_Config_SessionkeyConfig_init_default {0}
#define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}}
#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, "", 0}
@@ -667,9 +669,9 @@ extern "C" {
#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""}
#define meshtastic_Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0}
#define meshtastic_Config_DisplayConfig_init_zero {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN}
#define meshtastic_Config_LoRaConfig_init_zero {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0}
#define meshtastic_Config_LoRaConfig_init_zero {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0}
#define meshtastic_Config_BluetoothConfig_init_zero {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
#define meshtastic_Config_SecurityConfig_init_zero {{0, {0}}, {0, {0}}, 0, {{0, {0}}}, 0, 0, 0, 0}
#define meshtastic_Config_SecurityConfig_init_zero {{0, {0}}, {0, {0}}, 0, {{0, {0}}, {0, {0}}, {0, {0}}}, 0, 0, 0, 0}
#define meshtastic_Config_SessionkeyConfig_init_zero {0}
/* Field tags (for use in manual encoding/decoding) */
@@ -746,6 +748,7 @@ extern "C" {
#define meshtastic_Config_LoRaConfig_pa_fan_disabled_tag 15
#define meshtastic_Config_LoRaConfig_ignore_incoming_tag 103
#define meshtastic_Config_LoRaConfig_ignore_mqtt_tag 104
#define meshtastic_Config_LoRaConfig_config_ok_to_mqtt_tag 105
#define meshtastic_Config_BluetoothConfig_enabled_tag 1
#define meshtastic_Config_BluetoothConfig_mode_tag 2
#define meshtastic_Config_BluetoothConfig_fixed_pin_tag 3
@@ -887,7 +890,8 @@ X(a, STATIC, SINGULAR, BOOL, sx126x_rx_boosted_gain, 13) \
X(a, STATIC, SINGULAR, FLOAT, override_frequency, 14) \
X(a, STATIC, SINGULAR, BOOL, pa_fan_disabled, 15) \
X(a, STATIC, REPEATED, UINT32, ignore_incoming, 103) \
X(a, STATIC, SINGULAR, BOOL, ignore_mqtt, 104)
X(a, STATIC, SINGULAR, BOOL, ignore_mqtt, 104) \
X(a, STATIC, SINGULAR, BOOL, config_ok_to_mqtt, 105)
#define meshtastic_Config_LoRaConfig_CALLBACK NULL
#define meshtastic_Config_LoRaConfig_DEFAULT NULL
@@ -944,12 +948,12 @@ extern const pb_msgdesc_t meshtastic_Config_SessionkeyConfig_msg;
#define meshtastic_Config_BluetoothConfig_size 10
#define meshtastic_Config_DeviceConfig_size 98
#define meshtastic_Config_DisplayConfig_size 30
#define meshtastic_Config_LoRaConfig_size 82
#define meshtastic_Config_LoRaConfig_size 85
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20
#define meshtastic_Config_NetworkConfig_size 196
#define meshtastic_Config_PositionConfig_size 62
#define meshtastic_Config_PowerConfig_size 52
#define meshtastic_Config_SecurityConfig_size 111
#define meshtastic_Config_SecurityConfig_size 178
#define meshtastic_Config_SessionkeyConfig_size 0
#define meshtastic_Config_size 199

View File

@@ -94,6 +94,7 @@ typedef struct _meshtastic_NodeInfoLite {
/* True if we witnessed the node over MQTT instead of LoRA transport */
bool via_mqtt;
/* Number of hops away from us this node is (0 if adjacent) */
bool has_hops_away;
uint8_t hops_away;
/* True if node is in our favorites list
Persists between NodeDB internal clean ups */
@@ -202,13 +203,13 @@ extern "C" {
/* Initializer values for message structs */
#define meshtastic_PositionLite_init_default {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN}
#define meshtastic_UserLite_init_default {{0}, "", "", _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}}
#define meshtastic_NodeInfoLite_init_default {0, false, meshtastic_UserLite_init_default, false, meshtastic_PositionLite_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, 0, 0}
#define meshtastic_NodeInfoLite_init_default {0, false, meshtastic_UserLite_init_default, false, meshtastic_PositionLite_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0}
#define meshtastic_DeviceState_init_default {false, meshtastic_MyNodeInfo_init_default, false, meshtastic_User_init_default, 0, {meshtastic_MeshPacket_init_default}, false, meshtastic_MeshPacket_init_default, 0, 0, 0, false, meshtastic_MeshPacket_init_default, 0, {meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}, {0}}
#define meshtastic_ChannelFile_init_default {0, {meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default}, 0}
#define meshtastic_OEMStore_init_default {0, 0, {0, {0}}, _meshtastic_ScreenFonts_MIN, "", {0, {0}}, false, meshtastic_LocalConfig_init_default, false, meshtastic_LocalModuleConfig_init_default}
#define meshtastic_PositionLite_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN}
#define meshtastic_UserLite_init_zero {{0}, "", "", _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}}
#define meshtastic_NodeInfoLite_init_zero {0, false, meshtastic_UserLite_init_zero, false, meshtastic_PositionLite_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, 0, 0}
#define meshtastic_NodeInfoLite_init_zero {0, false, meshtastic_UserLite_init_zero, false, meshtastic_PositionLite_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0}
#define meshtastic_DeviceState_init_zero {false, meshtastic_MyNodeInfo_init_zero, false, meshtastic_User_init_zero, 0, {meshtastic_MeshPacket_init_zero}, false, meshtastic_MeshPacket_init_zero, 0, 0, 0, false, meshtastic_MeshPacket_init_zero, 0, {meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}, {0}}
#define meshtastic_ChannelFile_init_zero {0, {meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero}, 0}
#define meshtastic_OEMStore_init_zero {0, 0, {0, {0}}, _meshtastic_ScreenFonts_MIN, "", {0, {0}}, false, meshtastic_LocalConfig_init_zero, false, meshtastic_LocalModuleConfig_init_zero}
@@ -287,7 +288,7 @@ X(a, STATIC, SINGULAR, FIXED32, last_heard, 5) \
X(a, STATIC, OPTIONAL, MESSAGE, device_metrics, 6) \
X(a, STATIC, SINGULAR, UINT32, channel, 7) \
X(a, STATIC, SINGULAR, BOOL, via_mqtt, 8) \
X(a, STATIC, SINGULAR, UINT32, hops_away, 9) \
X(a, STATIC, OPTIONAL, UINT32, hops_away, 9) \
X(a, STATIC, SINGULAR, BOOL, is_favorite, 10)
#define meshtastic_NodeInfoLite_CALLBACK NULL
#define meshtastic_NodeInfoLite_DEFAULT NULL
@@ -358,7 +359,7 @@ extern const pb_msgdesc_t meshtastic_OEMStore_msg;
#define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_OEMStore_size
#define meshtastic_ChannelFile_size 718
#define meshtastic_NodeInfoLite_size 183
#define meshtastic_OEMStore_size 3497
#define meshtastic_OEMStore_size 3568
#define meshtastic_PositionLite_size 28
#define meshtastic_UserLite_size 96

View File

@@ -186,8 +186,8 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
#define meshtastic_LocalModuleConfig_fields &meshtastic_LocalModuleConfig_msg
/* Maximum encoded size of messages (where known) */
#define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalModuleConfig_size
#define meshtastic_LocalConfig_size 664
#define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalConfig_size
#define meshtastic_LocalConfig_size 735
#define meshtastic_LocalModuleConfig_size 687
#ifdef __cplusplus

View File

@@ -71,6 +71,8 @@ typedef enum _meshtastic_HardwareModel {
meshtastic_HardwareModel_RAK2560 = 22,
/* Heltec HRU-3601: https://heltec.org/project/hru-3601/ */
meshtastic_HardwareModel_HELTEC_HRU_3601 = 23,
/* Heltec Wireless Bridge */
meshtastic_HardwareModel_HELTEC_WIRELESS_BRIDGE = 24,
/* B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station */
meshtastic_HardwareModel_STATION_G1 = 25,
/* RAK11310 (RP2040 + SX1262) */
@@ -107,7 +109,7 @@ typedef enum _meshtastic_HardwareModel {
meshtastic_HardwareModel_NRF52840_PCA10059 = 40,
/* Custom Disaster Radio esp32 v3 device https://github.com/sudomesh/disaster-radio/tree/master/hardware/board_esp32_v3 */
meshtastic_HardwareModel_DR_DEV = 41,
/* M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, Paper) https://m5stack.com/ */
/* M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, CoreS3, Paper) https://m5stack.com/ */
meshtastic_HardwareModel_M5STACK = 42,
/* New Heltec LoRA32 with ESP32-S3 CPU */
meshtastic_HardwareModel_HELTEC_V3 = 43,
@@ -196,9 +198,13 @@ typedef enum _meshtastic_HardwareModel {
https://www.adafruit.com/product/938
^^^ short A0 to switch to I2C address 0x3C */
meshtastic_HardwareModel_RP2040_FEATHER_RFM95 = 76,
/* M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, Paper) https://m5stack.com/ */
/* M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, CoreS3, Paper) https://m5stack.com/ */
meshtastic_HardwareModel_M5STACK_COREBASIC = 77,
meshtastic_HardwareModel_M5STACK_CORE2 = 78,
/* Pico2 with Waveshare Hat, same as Pico */
meshtastic_HardwareModel_RPI_PICO2 = 79,
/* M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, CoreS3, Paper) https://m5stack.com/ */
meshtastic_HardwareModel_M5STACK_CORES3 = 80,
/* ------------------------------------------------------------------------------------------------------------------------------------------
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
------------------------------------------------------------------------------------------------------------------------------------------ */
@@ -316,7 +322,11 @@ typedef enum _meshtastic_Routing_Error {
/* The client specified a PKI transport, but the node was unable to send the packet using PKI (and did not send the message at all) */
meshtastic_Routing_Error_PKI_FAILED = 34,
/* The receiving node does not have a Public Key to decode with */
meshtastic_Routing_Error_PKI_UNKNOWN_PUBKEY = 35
meshtastic_Routing_Error_PKI_UNKNOWN_PUBKEY = 35,
/* Admin packet otherwise checks out, but uses a bogus or expired session key */
meshtastic_Routing_Error_ADMIN_BAD_SESSION_KEY = 36,
/* Admin packet sent using PKC, but not from a public key on the admin key list */
meshtastic_Routing_Error_ADMIN_PUBLIC_KEY_UNAUTHORIZED = 37
} meshtastic_Routing_Error;
/* The priority of this message for sending.
@@ -580,6 +590,9 @@ typedef struct _meshtastic_Data {
/* Defaults to false. If true, then what is in the payload should be treated as an emoji like giving
a message a heart or poop emoji. */
uint32_t emoji;
/* Bitfield for extra flags. First use is to indicate that user approves the packet being uploaded to MQTT. */
bool has_bitfield;
uint8_t bitfield;
} meshtastic_Data;
/* Waypoint message, used to share arbitrary locations across the mesh */
@@ -738,6 +751,7 @@ typedef struct _meshtastic_NodeInfo {
/* True if we witnessed the node over MQTT instead of LoRA transport */
bool via_mqtt;
/* Number of hops away from us this node is (0 if adjacent) */
bool has_hops_away;
uint8_t hops_away;
/* True if node is in our favorites list
Persists between NodeDB internal clean ups */
@@ -868,6 +882,8 @@ typedef struct _meshtastic_DeviceMetadata {
meshtastic_HardwareModel hw_model;
/* Has Remote Hardware enabled */
bool hasRemoteHardware;
/* Has PKC capabilities */
bool hasPKC;
} meshtastic_DeviceMetadata;
/* Packets from the radio to the phone will appear on the fromRadio characteristic.
@@ -1023,8 +1039,8 @@ extern "C" {
#define _meshtastic_Position_AltSource_ARRAYSIZE ((meshtastic_Position_AltSource)(meshtastic_Position_AltSource_ALT_BAROMETRIC+1))
#define _meshtastic_Routing_Error_MIN meshtastic_Routing_Error_NONE
#define _meshtastic_Routing_Error_MAX meshtastic_Routing_Error_PKI_UNKNOWN_PUBKEY
#define _meshtastic_Routing_Error_ARRAYSIZE ((meshtastic_Routing_Error)(meshtastic_Routing_Error_PKI_UNKNOWN_PUBKEY+1))
#define _meshtastic_Routing_Error_MAX meshtastic_Routing_Error_ADMIN_PUBLIC_KEY_UNAUTHORIZED
#define _meshtastic_Routing_Error_ARRAYSIZE ((meshtastic_Routing_Error)(meshtastic_Routing_Error_ADMIN_PUBLIC_KEY_UNAUTHORIZED+1))
#define _meshtastic_MeshPacket_Priority_MIN meshtastic_MeshPacket_Priority_UNSET
#define _meshtastic_MeshPacket_Priority_MAX meshtastic_MeshPacket_Priority_MAX
@@ -1082,11 +1098,11 @@ extern "C" {
#define meshtastic_User_init_default {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}}
#define meshtastic_RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}}
#define meshtastic_Routing_init_default {0, {meshtastic_RouteDiscovery_init_default}}
#define meshtastic_Data_init_default {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0}
#define meshtastic_Data_init_default {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0}
#define meshtastic_Waypoint_init_default {0, false, 0, false, 0, 0, 0, "", "", 0}
#define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0}
#define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0}
#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, 0, 0}
#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0}
#define meshtastic_MyNodeInfo_init_default {0, 0, 0}
#define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN}
#define meshtastic_QueueStatus_init_default {0, 0, 0, 0}
@@ -1097,7 +1113,7 @@ extern "C" {
#define meshtastic_Compressed_init_default {_meshtastic_PortNum_MIN, {0, {0}}}
#define meshtastic_NeighborInfo_init_default {0, 0, 0, 0, {meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default}}
#define meshtastic_Neighbor_init_default {0, 0, 0, 0}
#define meshtastic_DeviceMetadata_init_default {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN, 0}
#define meshtastic_DeviceMetadata_init_default {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN, 0, 0}
#define meshtastic_Heartbeat_init_default {0}
#define meshtastic_NodeRemoteHardwarePin_init_default {0, false, meshtastic_RemoteHardwarePin_init_default}
#define meshtastic_ChunkedPayload_init_default {0, 0, 0, {0, {0}}}
@@ -1107,11 +1123,11 @@ extern "C" {
#define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}}
#define meshtastic_RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}}
#define meshtastic_Routing_init_zero {0, {meshtastic_RouteDiscovery_init_zero}}
#define meshtastic_Data_init_zero {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0}
#define meshtastic_Data_init_zero {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0}
#define meshtastic_Waypoint_init_zero {0, false, 0, false, 0, 0, 0, "", "", 0}
#define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0}
#define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0}
#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, 0, 0}
#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0}
#define meshtastic_MyNodeInfo_init_zero {0, 0, 0}
#define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN}
#define meshtastic_QueueStatus_init_zero {0, 0, 0, 0}
@@ -1122,7 +1138,7 @@ extern "C" {
#define meshtastic_Compressed_init_zero {_meshtastic_PortNum_MIN, {0, {0}}}
#define meshtastic_NeighborInfo_init_zero {0, 0, 0, 0, {meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero}}
#define meshtastic_Neighbor_init_zero {0, 0, 0, 0}
#define meshtastic_DeviceMetadata_init_zero {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN, 0}
#define meshtastic_DeviceMetadata_init_zero {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN, 0, 0}
#define meshtastic_Heartbeat_init_zero {0}
#define meshtastic_NodeRemoteHardwarePin_init_zero {0, false, meshtastic_RemoteHardwarePin_init_zero}
#define meshtastic_ChunkedPayload_init_zero {0, 0, 0, {0, {0}}}
@@ -1176,6 +1192,7 @@ extern "C" {
#define meshtastic_Data_request_id_tag 6
#define meshtastic_Data_reply_id_tag 7
#define meshtastic_Data_emoji_tag 8
#define meshtastic_Data_bitfield_tag 9
#define meshtastic_Waypoint_id_tag 1
#define meshtastic_Waypoint_latitude_i_tag 2
#define meshtastic_Waypoint_longitude_i_tag 3
@@ -1252,6 +1269,7 @@ extern "C" {
#define meshtastic_DeviceMetadata_position_flags_tag 8
#define meshtastic_DeviceMetadata_hw_model_tag 9
#define meshtastic_DeviceMetadata_hasRemoteHardware_tag 10
#define meshtastic_DeviceMetadata_hasPKC_tag 11
#define meshtastic_FromRadio_id_tag 1
#define meshtastic_FromRadio_packet_tag 2
#define meshtastic_FromRadio_my_info_tag 3
@@ -1351,7 +1369,8 @@ X(a, STATIC, SINGULAR, FIXED32, dest, 4) \
X(a, STATIC, SINGULAR, FIXED32, source, 5) \
X(a, STATIC, SINGULAR, FIXED32, request_id, 6) \
X(a, STATIC, SINGULAR, FIXED32, reply_id, 7) \
X(a, STATIC, SINGULAR, FIXED32, emoji, 8)
X(a, STATIC, SINGULAR, FIXED32, emoji, 8) \
X(a, STATIC, OPTIONAL, UINT32, bitfield, 9)
#define meshtastic_Data_CALLBACK NULL
#define meshtastic_Data_DEFAULT NULL
@@ -1406,7 +1425,7 @@ X(a, STATIC, SINGULAR, FIXED32, last_heard, 5) \
X(a, STATIC, OPTIONAL, MESSAGE, device_metrics, 6) \
X(a, STATIC, SINGULAR, UINT32, channel, 7) \
X(a, STATIC, SINGULAR, BOOL, via_mqtt, 8) \
X(a, STATIC, SINGULAR, UINT32, hops_away, 9) \
X(a, STATIC, OPTIONAL, UINT32, hops_away, 9) \
X(a, STATIC, SINGULAR, BOOL, is_favorite, 10)
#define meshtastic_NodeInfo_CALLBACK NULL
#define meshtastic_NodeInfo_DEFAULT NULL
@@ -1531,7 +1550,8 @@ X(a, STATIC, SINGULAR, BOOL, hasEthernet, 6) \
X(a, STATIC, SINGULAR, UENUM, role, 7) \
X(a, STATIC, SINGULAR, UINT32, position_flags, 8) \
X(a, STATIC, SINGULAR, UENUM, hw_model, 9) \
X(a, STATIC, SINGULAR, BOOL, hasRemoteHardware, 10)
X(a, STATIC, SINGULAR, BOOL, hasRemoteHardware, 10) \
X(a, STATIC, SINGULAR, BOOL, hasPKC, 11)
#define meshtastic_DeviceMetadata_CALLBACK NULL
#define meshtastic_DeviceMetadata_DEFAULT NULL
@@ -1629,13 +1649,13 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
#define meshtastic_ChunkedPayload_size 245
#define meshtastic_ClientNotification_size 415
#define meshtastic_Compressed_size 243
#define meshtastic_Data_size 270
#define meshtastic_DeviceMetadata_size 46
#define meshtastic_Data_size 273
#define meshtastic_DeviceMetadata_size 48
#define meshtastic_FileInfo_size 236
#define meshtastic_FromRadio_size 510
#define meshtastic_Heartbeat_size 0
#define meshtastic_LogRecord_size 426
#define meshtastic_MeshPacket_size 364
#define meshtastic_MeshPacket_size 367
#define meshtastic_MqttClientProxyMessage_size 501
#define meshtastic_MyNodeInfo_size 18
#define meshtastic_NeighborInfo_size 258

View File

@@ -15,16 +15,15 @@
#include <WiFiUdp.h>
#ifdef ARCH_ESP32
#if !MESHTASTIC_EXCLUDE_WEBSERVER
#if !MESHTASTIC_EXCLUDE_WEBSERVER
#include "mesh/http/WebServer.h"
#endif
#endif
#include <ESPmDNS.h>
#include <esp_wifi.h>
static void WiFiEvent(WiFiEvent_t event);
#endif
#ifndef DISABLE_NTP
#include "Throttle.h"
#include <NTPClient.h>
#endif
@@ -58,7 +57,7 @@ static void onNetworkConnected()
{
if (!APStartupComplete) {
// Start web server
LOG_INFO("Starting network services\n");
LOG_INFO("Starting WiFi network services\n");
#ifdef ARCH_ESP32
// start mdns
@@ -144,7 +143,7 @@ static int32_t reconnectWiFi()
}
#ifndef DISABLE_NTP
if (WiFi.isConnected() && (((millis() - lastrun_ntp) > 43200000) || (lastrun_ntp == 0))) { // every 12 hours
if (WiFi.isConnected() && (!Throttle::isWithinTimespanMs(lastrun_ntp, 43200000) || (lastrun_ntp == 0))) { // every 12 hours
LOG_DEBUG("Updating NTP time from %s\n", config.network.ntp_server);
if (timeClient.update()) {
LOG_DEBUG("NTP Request Success - Setting RTCQualityNTP if needed\n");

View File

@@ -60,10 +60,17 @@ char *strnstr(const char *s, const char *find, size_t slen)
void printBytes(const char *label, const uint8_t *p, size_t numbytes)
{
LOG_DEBUG("%s: ", label);
for (size_t i = 0; i < numbytes; i++)
LOG_DEBUG("%02x ", p[i]);
LOG_DEBUG("\n");
char *messageBuffer;
int labelSize = strlen(label);
if (labelSize < 100 && numbytes < 64) {
messageBuffer = new char[labelSize + (numbytes * 3) + 2];
strncpy(messageBuffer, label, labelSize);
for (size_t i = 0; i < numbytes; i++)
snprintf(messageBuffer + labelSize + i * 3, 4, " %02x", p[i]);
strcpy(messageBuffer + labelSize + numbytes * 3, "\n");
LOG_DEBUG(messageBuffer);
delete messageBuffer;
}
}
bool memfll(const uint8_t *mem, uint8_t find, size_t numbytes)

View File

@@ -73,12 +73,38 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
meshtastic_Channel *ch = &channels.getByIndex(mp.channel);
// Could tighten this up further by tracking the last public_key we went an AdminMessage request to
// and only allowing responses from that remote.
if (!((mp.from == 0 && !config.security.is_managed) || messageIsResponse(r) ||
(strcasecmp(ch->settings.name, Channels::adminChannel) == 0 && config.security.admin_channel_enabled) ||
(mp.pki_encrypted && memcmp(mp.public_key.bytes, config.security.admin_key[0].bytes, 32) == 0))) {
LOG_INFO("Ignoring admin payload %i\n", r->which_payload_variant);
if (messageIsResponse(r)) {
LOG_DEBUG("Allowing admin response message\n");
} else if (mp.from == 0) {
if (config.security.is_managed) {
LOG_INFO("Ignoring local admin payload because is_managed.\n");
return handled;
}
} else if (strcasecmp(ch->settings.name, Channels::adminChannel) == 0) {
if (!config.security.admin_channel_enabled) {
LOG_INFO("Ignoring admin channel, as legacy admin is disabled.\n");
myReply = allocErrorResponse(meshtastic_Routing_Error_NOT_AUTHORIZED, &mp);
return handled;
}
} else if (mp.pki_encrypted) {
if ((config.security.admin_key[0].size == 32 &&
memcmp(mp.public_key.bytes, config.security.admin_key[0].bytes, 32) == 0) ||
(config.security.admin_key[1].size == 32 &&
memcmp(mp.public_key.bytes, config.security.admin_key[1].bytes, 32) == 0) ||
(config.security.admin_key[2].size == 32 &&
memcmp(mp.public_key.bytes, config.security.admin_key[2].bytes, 32) == 0)) {
LOG_INFO("PKC admin payload with authorized sender key.\n");
} else {
myReply = allocErrorResponse(meshtastic_Routing_Error_ADMIN_PUBLIC_KEY_UNAUTHORIZED, &mp);
LOG_INFO("Received PKC admin payload, but the sender public key does not match the admin authorized key!\n");
return handled;
}
} else {
LOG_INFO("Ignoring unauthorized admin payload %i\n", r->which_payload_variant);
myReply = allocErrorResponse(meshtastic_Routing_Error_NOT_AUTHORIZED, &mp);
return handled;
}
LOG_INFO("Handling admin payload %i\n", r->which_payload_variant);
// all of the get and set messages, including those for other modules, flow through here first.
@@ -86,6 +112,7 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
if (mp.from != 0 && !messageIsRequest(r) && !messageIsResponse(r)) {
if (!checkPassKey(r)) {
LOG_WARN("Admin message without session_key!\n");
myReply = allocErrorResponse(meshtastic_Routing_Error_ADMIN_BAD_SESSION_KEY, &mp);
return handled;
}
}
@@ -186,18 +213,22 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
break;
}
case meshtastic_AdminMessage_factory_reset_config_tag: {
disableBluetooth();
LOG_INFO("Initiating factory config reset\n");
nodeDB->factoryReset();
LOG_INFO("Factory config reset finished, rebooting soon.\n");
reboot(DEFAULT_REBOOT_SECONDS);
break;
}
case meshtastic_AdminMessage_factory_reset_device_tag: {
disableBluetooth();
LOG_INFO("Initiating full factory reset\n");
nodeDB->factoryReset(true);
reboot(DEFAULT_REBOOT_SECONDS);
break;
}
case meshtastic_AdminMessage_nodedb_reset_tag: {
disableBluetooth();
LOG_INFO("Initiating node-db reset\n");
nodeDB->resetNodes();
reboot(DEFAULT_REBOOT_SECONDS);
@@ -209,6 +240,7 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
break;
}
case meshtastic_AdminMessage_commit_edit_settings_tag: {
disableBluetooth();
LOG_INFO("Committing transaction for edited settings\n");
hasOpenEditTransaction = false;
saveChanges(SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
@@ -252,34 +284,26 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
break;
}
case meshtastic_AdminMessage_set_fixed_position_tag: {
if (fromOthers) {
LOG_INFO("Ignoring set_fixed_position command from another node.\n");
} else {
LOG_INFO("Client is receiving a set_fixed_position command.\n");
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
node->has_position = true;
node->position = TypeConversions::ConvertToPositionLite(r->set_fixed_position);
nodeDB->setLocalPosition(r->set_fixed_position);
config.position.fixed_position = true;
saveChanges(SEGMENT_DEVICESTATE | SEGMENT_CONFIG, false);
LOG_INFO("Client is receiving a set_fixed_position command.\n");
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
node->has_position = true;
node->position = TypeConversions::ConvertToPositionLite(r->set_fixed_position);
nodeDB->setLocalPosition(r->set_fixed_position);
config.position.fixed_position = true;
saveChanges(SEGMENT_DEVICESTATE | SEGMENT_CONFIG, false);
#if !MESHTASTIC_EXCLUDE_GPS
if (gps != nullptr)
gps->enable();
// Send our new fixed position to the mesh for good measure
positionModule->sendOurPosition();
if (gps != nullptr)
gps->enable();
// Send our new fixed position to the mesh for good measure
positionModule->sendOurPosition();
#endif
}
break;
}
case meshtastic_AdminMessage_remove_fixed_position_tag: {
if (fromOthers) {
LOG_INFO("Ignoring remove_fixed_position command from another node.\n");
} else {
LOG_INFO("Client is receiving a remove_fixed_position command.\n");
nodeDB->clearLocalPosition();
config.position.fixed_position = false;
saveChanges(SEGMENT_DEVICESTATE | SEGMENT_CONFIG, false);
}
LOG_INFO("Client is receiving a remove_fixed_position command.\n");
nodeDB->clearLocalPosition();
config.position.fixed_position = false;
saveChanges(SEGMENT_DEVICESTATE | SEGMENT_CONFIG, false);
break;
}
case meshtastic_AdminMessage_set_time_only_tag: {
@@ -406,7 +430,8 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
LOG_INFO("Setting config: Device\n");
config.has_device = true;
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
if (config.device.double_tap_as_button_press == false && c.payload_variant.device.double_tap_as_button_press == true) {
if (config.device.double_tap_as_button_press == false && c.payload_variant.device.double_tap_as_button_press == true &&
accelerometerThread->enabled == false) {
accelerometerThread->start();
}
#endif
@@ -484,7 +509,8 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
requiresReboot = false;
}
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
if (config.display.wake_on_tap_or_motion == false && c.payload_variant.display.wake_on_tap_or_motion == true) {
if (config.display.wake_on_tap_or_motion == false && c.payload_variant.display.wake_on_tap_or_motion == true &&
accelerometerThread->enabled == false) {
accelerometerThread->start();
}
#endif
@@ -557,12 +583,16 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
break;
}
if (requiresReboot) {
disableBluetooth();
}
saveChanges(changes, requiresReboot);
}
void AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c)
{
disableBluetooth();
switch (c.which_payload_variant) {
case meshtastic_ModuleConfig_mqtt_tag:
LOG_INFO("Setting module config: MQTT\n");
@@ -634,7 +664,6 @@ void AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c)
moduleConfig.paxcounter = c.payload_variant.paxcounter;
break;
}
saveChanges(SEGMENT_MODULECONFIG);
}
@@ -1029,3 +1058,16 @@ bool AdminModule::messageIsRequest(meshtastic_AdminMessage *r)
else
return false;
}
void disableBluetooth()
{
#if HAS_BLUETOOTH
#ifdef ARCH_ESP32
if (nimbleBluetooth)
nimbleBluetooth->deinit();
#elif defined(ARCH_NRF52)
if (nrf52Bluetooth)
nrf52Bluetooth->shutdown();
#endif
#endif
}

View File

@@ -59,4 +59,6 @@ class AdminModule : public ProtobufModule<meshtastic_AdminMessage>, public Obser
bool messageIsRequest(meshtastic_AdminMessage *r);
};
extern AdminModule *adminModule;
extern AdminModule *adminModule;
void disableBluetooth();

View File

@@ -52,6 +52,10 @@ meshtastic_TAKPacket AtakPluginModule::cloneTAKPacketData(meshtastic_TAKPacket *
} else if (t->which_payload_variant == meshtastic_TAKPacket_chat_tag) {
clone.which_payload_variant = meshtastic_TAKPacket_chat_tag;
clone.payload_variant.chat = {0};
} else if (t->which_payload_variant == meshtastic_TAKPacket_detail_tag) {
clone.which_payload_variant = meshtastic_TAKPacket_detail_tag;
clone.payload_variant.detail.size = t->payload_variant.detail.size;
memcpy(clone.payload_variant.detail.bytes, t->payload_variant.detail.bytes, t->payload_variant.detail.size);
}
return clone;

View File

@@ -27,6 +27,7 @@
#endif
#include "graphics/ScreenFonts.h"
#include <Throttle.h>
// Remove Canned message screen if no action is taken for some milliseconds
#define INACTIVATE_AFTER_MS 20000
@@ -190,17 +191,17 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
#if defined(T_WATCH_S3) || defined(RAK14014)
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) {
this->payload = 0xb4;
this->payload = INPUT_BROKER_MSG_LEFT;
} else if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT)) {
this->payload = 0xb7;
this->payload = INPUT_BROKER_MSG_RIGHT;
}
#else
// tweak for left/right events generated via trackball/touch with empty kbchar
if (!event->kbchar) {
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) {
this->payload = 0xb4;
this->payload = INPUT_BROKER_MSG_LEFT;
} else if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT)) {
this->payload = 0xb7;
this->payload = INPUT_BROKER_MSG_RIGHT;
}
} else {
// pass the pressed key
@@ -222,26 +223,26 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
// Run modifier key code below, (doesnt inturrupt typing or reset to start screen page)
switch (event->kbchar) {
case 0x11: // make screen brighter
case INPUT_BROKER_MSG_BRIGHTNESS_UP: // make screen brighter
if (screen)
screen->increaseBrightness();
LOG_DEBUG("increasing Screen Brightness\n");
break;
case 0x12: // make screen dimmer
case INPUT_BROKER_MSG_BRIGHTNESS_DOWN: // make screen dimmer
if (screen)
screen->decreaseBrightness();
LOG_DEBUG("Decreasing Screen Brightness\n");
break;
case 0xf1: // draw modifier (function) symbal
case INPUT_BROKER_MSG_FN_SYMBOL_ON: // draw modifier (function) symbal
if (screen)
screen->setFunctionSymbal("Fn");
break;
case 0xf2: // remove modifier (function) symbal
case INPUT_BROKER_MSG_FN_SYMBOL_OFF: // remove modifier (function) symbal
if (screen)
screen->removeFunctionSymbal("Fn");
break;
// mute (switch off/toggle) external notifications on fn+m
case 0xac:
case INPUT_BROKER_MSG_MUTE_TOGGLE:
if (moduleConfig.external_notification.enabled == true) {
if (externalNotificationModule->getMute()) {
externalNotificationModule->setMute(false);
@@ -257,7 +258,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
}
}
break;
case 0x9e: // toggle GPS like triple press does
case INPUT_BROKER_MSG_GPS_TOGGLE: // toggle GPS like triple press does
#if !MESHTASTIC_EXCLUDE_GPS
if (gps != nullptr) {
gps->toggleGpsMode();
@@ -267,7 +268,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
showTemporaryMessage("GPS Toggled");
#endif
break;
case 0xaf: // fn+space send network ping like double press does
case INPUT_BROKER_MSG_SEND_PING: // fn+space send network ping like double press does
service->refreshLocalMeshNode();
if (service->trySendPosition(NODENUM_BROADCAST, true)) {
showTemporaryMessage("Position \nUpdate Sent");
@@ -283,7 +284,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
validEvent = true;
break;
}
if (screen && (event->kbchar != 0xf1)) {
if (screen && (event->kbchar != INPUT_BROKER_MSG_FN_SYMBOL_ON)) {
screen->removeFunctionSymbal("Fn"); // remove modifier (function) symbal
}
}
@@ -422,7 +423,7 @@ int32_t CannedMessageModule::runOnce()
this->notifyObservers(&e);
} else if (((this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) || (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT)) &&
((millis() - this->lastTouchMillis) > INACTIVATE_AFTER_MS)) {
!Throttle::isWithinTimespanMs(this->lastTouchMillis, INACTIVATE_AFTER_MS)) {
// Reset module
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; // We want to change the list of frames shown on-screen
this->currentMessageIndex = -1;
@@ -505,7 +506,7 @@ int32_t CannedMessageModule::runOnce()
}
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT || this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) {
switch (this->payload) {
case 0xb4: // left
case INPUT_BROKER_MSG_LEFT:
if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_NODE) {
size_t numMeshNodes = nodeDB->getNumMeshNodes();
if (this->dest == NODENUM_BROADCAST) {
@@ -540,7 +541,7 @@ int32_t CannedMessageModule::runOnce()
}
}
break;
case 0xb7: // right
case INPUT_BROKER_MSG_RIGHT:
if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_NODE) {
size_t numMeshNodes = nodeDB->getNumMeshNodes();
if (this->dest == NODENUM_BROADCAST) {
@@ -602,19 +603,19 @@ int32_t CannedMessageModule::runOnce()
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NODE;
}
break;
case 0xb4: // left
case 0xb7: // right
case INPUT_BROKER_MSG_LEFT:
case INPUT_BROKER_MSG_RIGHT:
// already handled above
break;
// handle fn+s for shutdown
case 0x9b:
case INPUT_BROKER_MSG_SHUTDOWN:
if (screen)
screen->startAlert("Shutting down...");
shutdownAtMsec = millis() + DEFAULT_SHUTDOWN_SECONDS * 1000;
runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
break;
// and fn+r for reboot
case 0x90:
case INPUT_BROKER_MSG_REBOOT:
if (screen)
screen->startAlert("Rebooting...");
rebootAtMsec = millis() + DEFAULT_REBOOT_SECONDS * 1000;

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