Compare commits

...

59 Commits

Author SHA1 Message Date
Ben Meadors
9d222c9a55 Merge branch 'master' into 128-redux 2025-08-20 10:10:19 -05:00
Austin
57e1725419 Revert "Update platformio/espressif32 to v6.12.0 (#7523)" (#7695)
This reverts commit 11309662a9.
2025-08-20 10:10:39 -04:00
renovate[bot]
11309662a9 Update platformio/espressif32 to v6.12.0 (#7523)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-20 09:08:14 -04:00
Ben Meadors
2dd4ca8c52 Line 2025-08-20 06:01:21 -05:00
Ben Meadors
2a50ae05dd Account for 128x128 SH1107 displays 2025-08-20 06:00:24 -05:00
github-actions[bot]
890357d579 Update protobufs (#7693)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-08-20 05:53:20 -05:00
Wilson
f413c49555 Add Meshtiny device (#7676)
* Add Meshtiny device - nRF52 OLED upDown encoder

* Update platformio.ini

* Update platformio.ini

* Add GPS Exclude to Meshtiny.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-08-20 11:52:10 +08:00
Ben Meadors
c19f573b49 Fix TLS port bug on default mqtt validation 2025-08-19 20:10:47 -05:00
Jonathan Bennett
5de61b1a3d Only gate PKC behind the simradio CLI flag (#7681)
* Only gate PKC behind the simradio CLI flag

* Hide router.cpp simradio check behind #if ARCH_PORTDUINO
2025-08-19 14:15:05 -05:00
renovate[bot]
1c1462e776 Update meshtastic/device-ui digest to 8f5094b (#7633)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-19 14:14:12 -05:00
renovate[bot]
eb6ef1cbea Update meshtastic-esp8266-oled-ssd1306 digest to 9573abb (#7686)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-19 14:13:53 -05:00
renovate[bot]
9654f5b218 Update platform-native digest to 37d9864 (#7684)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-19 14:13:25 -05:00
Austin
68726a1b0e Docker: fix web assets location (#7683) 2025-08-19 14:06:43 -05:00
Ben Meadors
5b62bbe8e6 Disable for now 2025-08-19 11:30:19 -05:00
jake-b
e55084629a Move heartbeat response before !available guard. (#7672)
* Move heartbeat response before !available guard.

* fix formatting.

---------

Co-authored-by: Jake-B <jake-b@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-08-19 08:10:53 -05:00
Ben Meadors
1691e885f2 Display test results 2025-08-19 06:00:29 -05:00
renovate[bot]
2d7818797d Update platform-native digest to cd32f4e (#7662)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-19 05:43:10 -05:00
github-actions[bot]
f65e2c639e Update protobufs (#7679)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-08-19 05:35:25 -05:00
Jonathan Bennett
95200e8f6b Adds rfswitch on Portduino (#7663)
* Initial attempt to get rfswitch working on Portduino

* Make portduino_config global
2025-08-18 16:33:52 -05:00
github-actions[bot]
36e8dc74f4 Upgrade trunk (#7665)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2025-08-18 05:52:02 -05:00
Manuel
78c5309e9a apply 180 degree hw roration Indicator BaseUI (#7660) 2025-08-17 14:48:24 -05:00
Thomas Göttgens
9feb1d378e Support for T-Echo Lite, credits to @Szetya for doing all the heavy lifting! (#7636)
* Support for T-Echo Lite, credts to @Szetya for doing all the heavy lifting!
* move define to ini file
2025-08-17 13:37:12 +02:00
Jonathan Bennett
e5e8683cdb Don't update the NodeDB if the nodeinfo has a mismatching public key (#7652) 2025-08-17 05:56:06 -05:00
Jonathan Bennett
d538ad170c Add onboard message for devices with screens (#7655)
* Add onboard message for devices with screens

* Add message for TFT
2025-08-17 05:55:00 -05:00
Jonathan Bennett
c64c196778 Wait for lead up before enable longlong action (#7648) 2025-08-16 06:10:44 -05:00
github-actions[bot]
8e552a9f0c Upgrade trunk (#7626)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2025-08-16 05:57:20 -05:00
Ben Meadors
a02017a5c8 Remove JSON serialization from most NRF52 targets (#7640)
* Remove JSON serialization from most NRF52 targets

* Slin networking base down for NRF52 by removing syslog

* Update platformio.ini
2025-08-15 19:45:41 -05:00
github-actions[bot]
0046d957f1 Update protobufs (#7647)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-08-15 21:42:51 +02:00
Jonathan Bennett
4a241deb96 Thinknode button and backlight fixes (#7641)
* Thinknode button and backlight fixes

* Save backlight value between reboots
2025-08-15 14:41:21 -05:00
GUVWAF
8d5ae1d5d2 Fix marking LoRa transport mechanism (#7634) 2025-08-15 19:09:25 +02:00
Ben Meadors
e1e89a5e62 Don't include OLED fonts for international character sets by default (#7639) 2025-08-15 09:03:21 -05:00
Ben Meadors
a7be93449e Spacing 2025-08-15 09:00:09 -05:00
Ben Meadors
c8694f9f2d Fix Tracerouter warnings (#7637)
* Static cast to avoid signed comparison

* Another one
2025-08-15 07:03:14 -05:00
Austin
062168cd42 Docker: Update Debian images to trixie (#7621) 2025-08-15 06:19:49 -05:00
Ford Jones
1877a2c531 Prompt user to select destination upon launch of canned message module (#7624)
Co-authored-by: Jason P <applewiz@mac.com>
2025-08-15 05:31:11 -05:00
Austin
52f0e5a3db Fix 'buildroot' target (OpenWRT) (#7620) 2025-08-14 12:31:25 -05:00
github-actions[bot]
ac8c372349 Upgrade trunk to 1.25.0 (#7432)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2025-08-13 06:26:08 -05:00
github-actions[bot]
1bfa429c38 Automated version bumps (#7614)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-08-12 19:40:35 -05:00
Jonathan Bennett
ddd149945a More spoof remediation (#7612)
* More spoof remediation

* Fix signed comparison error

* Only fire self-bound messages into the routing module

* Update src/mesh/MeshModule.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* String const

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-12 16:08:03 -05:00
Constantine
e3dd8164a4 nRF52840 promicro deepsleep fix with some additions (#7407)
* Pro-Micro DeepSleep Quick Fix
It is noticed that some nRF52840 boards (pro-micro in particular)
stopped waking up from the deep sleep state (shutdown state)
with a press of a button.
The problem is in a Serial1.end() call.

* Clear GPREGRET before setting
There are some troubles with that register:
it is recommended to clear it with 0xFF mask
and only after that perform a setting.

* Pro-Micro button SENSE signal
Added SENSE signal on the user button.
It is explicitly enabled now for this platform.

* nRF52 pre-sleep main serial check
Added another usage check for the main Serial.
It could save some nerves in case the port is not in use by any means.
Applied trunk fmt to the file.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-08-12 11:23:34 -05:00
Max
9b8149f14e Adding medium and large RU fonts. Fixing RU string width calculation (#7498)
* Adding  medium and large RU fonts. Fixing string width calculation for RU font

* Update src/graphics/draw/MessageRenderer.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-12 07:22:37 -05:00
renovate[bot]
05f1518951 chore(deps): update actions/download-artifact action to v5 (#7559)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-11 21:47:21 -05:00
Jonathan Bennett
e26de85b5f Mark meshPackets based on which interface received. (#7589) 2025-08-11 21:47:04 -05:00
renovate[bot]
a2df80e833 chore(deps): update actions/checkout action to v5 (#7605)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-11 20:58:54 -05:00
Ben Meadors
db238ef524 Log when this happened 2025-08-11 19:49:35 -05:00
Jonathan Bennett
f2b935f48f Stop the bleeding with malicious NodeDB overwrites (#7596) 2025-08-11 15:52:28 -05:00
Thomas Göttgens
e69da71d4e reorder for correct recognition (#7604) 2025-08-11 11:53:01 +02:00
Ben Meadors
7505fe7a7c Update device-ui deps 2025-08-09 10:38:09 -05:00
Ben Meadors
f6857f1bcb Heartbeat has a nonce now 2025-08-09 10:17:08 -05:00
github-actions[bot]
7fe2c74139 Update protobufs (#7588)
Co-authored-by: jp-bennett <5630967+jp-bennett@users.noreply.github.com>
2025-08-09 09:14:22 -05:00
github-actions[bot]
be60f9612e Update protobufs (#7587)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-08-09 08:14:04 -05:00
github-actions[bot]
2de9f015b1 Automated version bumps (#7586)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-08-09 08:12:24 -05:00
Ben Meadors
c1f4f79d4a Revert "128row display (#7511)"
This reverts commit d1f3c3c982.
2025-08-09 06:11:56 -05:00
renovate[bot]
7b874cf597 chore(deps): update meshtastic/device-ui digest to d044c01 (#7578)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-08 11:31:49 -05:00
Jonathan Bennett
8568b56ac6 Fix a crash on Native reboot (#7570) 2025-08-07 12:28:01 -05:00
renovate[bot]
f2a880f813 chore(deps): update adafruit shtc3 to v1.0.2 (#7557)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-07 13:56:17 +02:00
Jonathan Bennett
691327b2db Initial support for the ThinkNode M5 (#7502)
* Initial support for the ThinkNode M5

* Update variants/esp32s3/ELECROW-ThinkNode-M5/platformio.ini

Co-authored-by: Austin <vidplace7@gmail.com>

* Cleanup variant.h for Elecrow Thinknode M5

* Properly detect battery voltage

* Turn backlight off when screen sleeps

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Austin <vidplace7@gmail.com>
2025-08-07 06:28:15 -05:00
oscgonfer
a23c58c10a Avoid acquiring lock twice (#7555)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-08-06 06:38:36 -05:00
Jonathan Bennett
27c6b24e3a Rather than mysteriously rebooting, regenerate the keys and infrom the user. (#7558) 2025-08-05 19:53:25 -05:00
100 changed files with 2914 additions and 321 deletions

View File

@@ -5,7 +5,7 @@ runs:
using: composite
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: recursive
ref: ${{github.event.pull_request.head.ref}}

View File

@@ -24,7 +24,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: recursive
path: meshtasticd

View File

@@ -20,7 +20,7 @@ jobs:
name: build-${{ inputs.platform }}
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
submodules: recursive
ref: ${{github.event.pull_request.head.ref}}

View File

@@ -47,7 +47,7 @@ jobs:
runs-on: ${{ inputs.runs-on }}
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: recursive
ref: ${{github.event.pull_request.head.ref}}

View File

@@ -83,7 +83,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: recursive
ref: ${{github.event.pull_request.head.ref}}

View File

@@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: recursive
ref: ${{ github.ref }}

View File

@@ -42,7 +42,7 @@ jobs:
- check
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- uses: actions/setup-python@v5
with:
python-version: 3.x
@@ -72,7 +72,7 @@ jobs:
version:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Get release version string
run: |
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
@@ -93,7 +93,7 @@ jobs:
runs-on: ubuntu-latest
if: ${{ github.event_name != 'workflow_dispatch' }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Build base
id: base
uses: ./.github/actions/setup-base
@@ -288,12 +288,12 @@ jobs:
]
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v5
with:
path: ./
pattern: firmware-${{matrix.arch}}-*
@@ -322,7 +322,7 @@ jobs:
./Meshtastic_nRF52_factory_erase*.uf2
retention-days: 30
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v5
with:
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -367,7 +367,7 @@ jobs:
- package-pio-deps-native-tft
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Setup Python
uses: actions/setup-python@v5
@@ -386,14 +386,14 @@ jobs:
Autogenerated by github action, developer should edit as required before publishing...
- name: Download source deb
uses: actions/download-artifact@v4
uses: actions/download-artifact@v5
with:
pattern: firmware-debian-${{ needs.version.outputs.deb }}~UNRELEASED-src
merge-multiple: true
path: ./output/debian-src
- name: Download `native-tft` pio deps
uses: actions/download-artifact@v4
uses: actions/download-artifact@v5
with:
pattern: platformio-deps-native-tft-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -436,14 +436,14 @@ jobs:
needs: [release-artifacts, version]
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: 3.x
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v5
with:
pattern: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -460,7 +460,7 @@ jobs:
- name: Zip firmware
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v5
with:
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip
merge-multiple: true
@@ -491,14 +491,14 @@ jobs:
esp32,esp32s3,esp32c3,esp32c6,nrf52840,rp2040,rp2350,stm32
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: 3.x
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v5
with:
pattern: firmware-{${{ env.targets }}}-${{ needs.version.outputs.long }}
merge-multiple: true

View File

@@ -14,7 +14,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Trunk Check
uses: trunk-io/trunk-action@v1
@@ -31,7 +31,7 @@ jobs:
pull-requests: write # For trunk to create PRs
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Trunk Upgrade
uses: trunk-io/trunk-action/upgrade@v1

View File

@@ -34,7 +34,7 @@ jobs:
needs: build-debian-src
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: recursive
path: meshtasticd
@@ -58,7 +58,7 @@ jobs:
id: version
- name: Download artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@v5
with:
name: firmware-debian-${{ steps.version.outputs.deb }}~${{ inputs.series }}-src
merge-multiple: true

View File

@@ -24,7 +24,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: recursive
ref: ${{github.event.pull_request.head.ref}}

View File

@@ -32,7 +32,7 @@ jobs:
needs: build-debian-src
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: recursive
path: meshtasticd
@@ -60,7 +60,7 @@ jobs:
id: version
- name: Download artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@v5
with:
name: firmware-debian-${{ steps.version.outputs.deb }}~${{ inputs.series }}-src
merge-multiple: true

238
.github/workflows/pr_tests.yml vendored Normal file
View File

@@ -0,0 +1,238 @@
name: Tests
# DISABLED: Changed from automatic PR triggers to manual only
on:
workflow_dispatch:
inputs:
reason:
description: "Reason for manual test run"
required: false
default: "Manual test execution"
concurrency:
group: tests-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
permissions:
contents: read
actions: read
checks: write
pull-requests: write
jobs:
native-tests:
name: "🧪 Native Tests"
if: github.repository == 'meshtastic/firmware'
uses: ./.github/workflows/test_native.yml
permissions:
contents: read
actions: read
checks: write
test-summary:
name: "📊 Test Results"
runs-on: ubuntu-latest
needs: [native-tests]
if: always()
permissions:
contents: read
actions: read
checks: write
pull-requests: write
steps:
- uses: actions/checkout@v5
with:
submodules: recursive
- name: Get release version string
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Download test artifacts
if: needs.native-tests.result != 'skipped'
uses: actions/download-artifact@v5
with:
name: platformio-test-report-${{ steps.version.outputs.long }}.zip
merge-multiple: true
- name: Parse test results and create detailed summary
id: test-results
run: |
echo "## 🧪 Test Results Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Check overall job status first
if [[ "${{ needs.native-tests.result }}" == "success" ]]; then
echo "✅ **Overall Status**: PASSED" >> $GITHUB_STEP_SUMMARY
elif [[ "${{ needs.native-tests.result }}" == "failure" ]]; then
echo "❌ **Overall Status**: FAILED" >> $GITHUB_STEP_SUMMARY
elif [[ "${{ needs.native-tests.result }}" == "cancelled" ]]; then
echo "⏸️ **Overall Status**: CANCELLED" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Tests were cancelled before completion." >> $GITHUB_STEP_SUMMARY
exit 0
else
echo "⚠️ **Overall Status**: SKIPPED" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Tests were skipped." >> $GITHUB_STEP_SUMMARY
exit 0
fi
echo "" >> $GITHUB_STEP_SUMMARY
# Parse detailed test results if available
if [ -f "testreport.xml" ]; then
echo "### 🔍 Individual Test Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
python3 << 'EOF'
import xml.etree.ElementTree as ET
import os
try:
tree = ET.parse('testreport.xml')
root = tree.getroot()
total_tests = 0
passed_tests = 0
failed_tests = 0
skipped_tests = 0
# Parse testsuite elements
for testsuite in root.findall('.//testsuite'):
suite_name = testsuite.get('name', 'Unknown')
suite_tests = int(testsuite.get('tests', '0'))
suite_failures = int(testsuite.get('failures', '0'))
suite_errors = int(testsuite.get('errors', '0'))
suite_skipped = int(testsuite.get('skipped', '0'))
total_tests += suite_tests
failed_tests += suite_failures + suite_errors
skipped_tests += suite_skipped
passed_tests += suite_tests - suite_failures - suite_errors - suite_skipped
if suite_tests > 0:
status = "✅" if (suite_failures + suite_errors) == 0 else "❌"
print(f"**{status} Test Suite: {suite_name}**")
print(f"- Total: {suite_tests}")
print(f"- Passed: ✅ {suite_tests - suite_failures - suite_errors - suite_skipped}")
print(f"- Failed: ❌ {suite_failures + suite_errors}")
if suite_skipped > 0:
print(f"- Skipped: ⏭️ {suite_skipped}")
print("")
# Show individual test results for failed suites
if suite_failures + suite_errors > 0:
print("**Failed Tests:**")
for testcase in testsuite.findall('testcase'):
test_name = testcase.get('name', 'Unknown')
failure = testcase.find('failure')
error = testcase.find('error')
if failure is not None:
msg = failure.get('message', 'Unknown error')[:100]
print(f"- ❌ `{test_name}`: {msg}")
elif error is not None:
msg = error.get('message', 'Unknown error')[:100]
print(f"- ❌ `{test_name}`: ERROR - {msg}")
print("")
else:
# Show passed tests for successful suites
passed_count = 0
for testcase in testsuite.findall('testcase'):
if testcase.find('failure') is None and testcase.find('error') is None:
if passed_count < 5: # Limit to first 5 to avoid spam
test_name = testcase.get('name', 'Unknown')
print(f"- ✅ `{test_name}`: PASSED")
passed_count += 1
if passed_count > 5:
print(f"- ... and {passed_count - 5} more tests passed")
print("")
# Summary statistics
print("### 📊 Test Statistics")
print(f"- **Total Tests**: {total_tests}")
print(f"- **Passed**: ✅ {passed_tests}")
print(f"- **Failed**: ❌ {failed_tests}")
if skipped_tests > 0:
print(f"- **Skipped**: ⏭️ {skipped_tests}")
if failed_tests > 0:
print(f"\n❌ **{failed_tests} tests failed out of {total_tests} total**")
else:
print(f"\n✅ **All {total_tests} tests passed!**")
except Exception as e:
print(f"❌ Error parsing test results: {e}")
EOF
else
echo "⚠️ **No detailed test report available**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Test artifacts may not have been generated properly." >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
echo "View detailed logs in the [Actions tab](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> $GITHUB_STEP_SUMMARY
- name: Comment test results on PR
if: github.event_name == 'pull_request' && needs.native-tests.result != 'skipped'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
// Read the step summary to use as PR comment
let testSummary = "## 🧪 Test Results Summary\n\n";
if ("${{ needs.native-tests.result }}" === "success") {
testSummary += "✅ **All tests passed!**\n\n";
} else if ("${{ needs.native-tests.result }}" === "failure") {
testSummary += "❌ **Some tests failed.**\n\n";
} else {
testSummary += "⚠️ **Tests did not complete normally.**\n\n";
}
testSummary += `View detailed results: [Actions Run](${context.payload.repository.html_url}/actions/runs/${context.runId})\n\n`;
testSummary += "---\n";
testSummary += "*This comment will be automatically updated when new commits are pushed.*";
// Find existing comment
const comments = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number
});
const botComment = comments.data.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes('🧪 Test Results Summary')
);
if (botComment) {
// Update existing comment
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: testSummary
});
} else {
// Create new comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: testSummary
});
}
- name: Set overall status
run: |
if [[ "${{ needs.native-tests.result }}" == "success" ]]; then
echo "All tests passed! ✅"
exit 0
else
echo "Some tests failed! ❌"
exit 1
fi

View File

@@ -60,7 +60,7 @@ jobs:
shell: bash
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Setup Python
uses: actions/setup-python@v5

View File

@@ -21,7 +21,7 @@ jobs:
steps:
# step 1
- name: clone application source code
uses: actions/checkout@v4
uses: actions/checkout@v5
# step 2
- name: full scan

View File

@@ -13,7 +13,7 @@ jobs:
steps:
# step 1
- name: clone application source code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0

View File

@@ -14,7 +14,7 @@ jobs:
name: Native Simulator Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
@@ -70,7 +70,7 @@ jobs:
name: Native PlatformIO Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
@@ -127,7 +127,7 @@ jobs:
- platformio-tests
if: always()
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
@@ -137,7 +137,7 @@ jobs:
id: version
- name: Download test artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@v5
with:
name: platformio-test-report-${{ steps.version.outputs.long }}.zip
merge-multiple: true
@@ -150,7 +150,7 @@ jobs:
reporter: java-junit
- name: Download coverage artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@v5
with:
pattern: lcov-coverage-info-native-*-${{ steps.version.outputs.long }}.zip
path: code-coverage-report

View File

@@ -20,7 +20,7 @@ jobs:
runs-on: test-runner
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
# - uses: actions/setup-python@v5
# with:

View File

@@ -18,7 +18,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Trunk Check
uses: trunk-io/trunk-action@v1

View File

@@ -16,7 +16,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Trunk Check
uses: trunk-io/trunk-action@v1

View File

@@ -15,7 +15,7 @@ jobs:
pull-requests: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}

View File

@@ -11,7 +11,7 @@ jobs:
pull-requests: write
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: true

View File

@@ -1,6 +1,6 @@
version: 0.1
cli:
version: 1.24.0
version: 1.25.0
plugins:
sources:
- id: trunk
@@ -8,15 +8,15 @@ plugins:
uri: https://github.com/trunk-io/plugins
lint:
enabled:
- checkov@3.2.451
- renovate@41.40.0
- checkov@3.2.461
- renovate@41.74.0
- prettier@3.6.2
- trufflehog@3.90.1
- trufflehog@3.90.5
- yamllint@1.37.1
- bandit@1.8.6
- trivy@0.64.1
- taplo@0.9.3
- ruff@0.12.4
- ruff@0.12.7
- isort@6.0.1
- markdownlint@0.45.0
- oxipng@9.1.5

View File

@@ -3,7 +3,7 @@
# trunk-ignore-all(hadolint/DL3008): Do not pin apt package versions
# trunk-ignore-all(hadolint/DL3013): Do not pin pip package versions
FROM python:3.13-bookworm AS builder
FROM python:3.13-slim-trixie AS builder
ARG PIO_ENV=native
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Etc/UTC
@@ -36,7 +36,7 @@ RUN curl -L "https://github.com/meshtastic/web/releases/download/v$(cat /tmp/fir
##### PRODUCTION BUILD #############
FROM debian:bookworm-slim
FROM debian:trixie-slim
LABEL org.opencontainers.image.title="Meshtastic" \
org.opencontainers.image.description="Debian Meshtastic daemon and web interface" \
org.opencontainers.image.url="https://meshtastic.org" \
@@ -51,8 +51,8 @@ ENV TZ=Etc/UTC
USER root
RUN apt-get update && apt-get --no-install-recommends -y install \
libc-bin libc6 libgpiod2 libyaml-cpp0.7 libi2c0 libuv1 libusb-1.0-0-dev \
liborcania2.3 libulfius2.7 libssl3 \
libc-bin libc6 libgpiod3 libyaml-cpp0.8 libi2c0 libuv1t64 libusb-1.0-0-dev \
liborcania2.3 libulfius2.7t64 libssl3t64 \
libx11-6 libinput10 libxkbcommon-x11-0 \
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
&& mkdir -p /var/lib/meshtasticd \
@@ -61,7 +61,7 @@ RUN apt-get update && apt-get --no-install-recommends -y install \
# Fetch compiled binary from the builder
COPY --from=builder /tmp/firmware/release/meshtasticd /usr/bin/
COPY --from=builder /tmp/web /usr/share/meshtasticd/
COPY --from=builder /tmp/web /usr/share/meshtasticd/web/
# Copy config templates
COPY ./bin/config.d /etc/meshtasticd/available.d

View File

@@ -23,7 +23,7 @@ build_flags =
-DMESHTASTIC_EXCLUDE_PAXCOUNTER=1
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp>
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp> -<serialization/>
lib_deps=
${arduino_base.lib_deps}

View File

@@ -2,7 +2,7 @@
[portduino_base]
platform =
# renovate: datasource=git-refs depName=platform-native packageName=https://github.com/meshtastic/platform-native gitBranch=develop
https://github.com/meshtastic/platform-native/archive/6cb7a455b440dd0738e8ed74a18136ed5cf7ea63.zip
https://github.com/meshtastic/platform-native/archive/37d986499ce24511952d7146db72d667c6bdaff7.zip
framework = arduino
build_src_filter =
@@ -17,7 +17,6 @@ build_src_filter =
+<mesh/raspihttp/>
-<mesh/eth/>
-<modules/esp32>
+<../variants/portduino>
lib_deps =
${env.lib_deps}
@@ -35,6 +34,7 @@ lib_deps =
build_flags =
${arduino_base.build_flags}
-D ARCH_PORTDUINO
-fPIC
-Isrc/platform/portduino
-DRADIOLIB_EEPROM_UNSUPPORTED

View File

@@ -87,6 +87,12 @@
</screenshots>
<releases>
<release version="2.7.6" date="2025-08-12">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.6</url>
</release>
<release version="2.7.5" date="2025-08-09">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.5</url>
</release>
<release version="2.7.4" date="2025-07-19">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.4</url>
</release>

52
boards/meshtiny.json Normal file
View File

@@ -0,0 +1,52 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x8029"],
["0x239A", "0x0029"],
["0x239A", "0x002A"],
["0x239A", "0x802A"]
],
"usb_product": "MeshTiny",
"mcu": "nrf52840",
"variant": "meshtiny",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS140",
"sd_name": "s140",
"sd_version": "6.1.1",
"sd_fwid": "0x00B6"
},
"bootloader": {
"settings_addr": "0xFF000"
}
},
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino", "freertos"],
"name": "MeshTiny",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"],
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "https://github.com/meshtastic/firmware",
"vendor": "MTools Tec"
}

10
debian/changelog vendored
View File

@@ -1,4 +1,4 @@
meshtasticd (2.7.4.0) UNRELEASED; urgency=medium
meshtasticd (2.7.6.0) UNRELEASED; urgency=medium
[ Austin Lane ]
* Initial packaging
@@ -34,4 +34,10 @@ meshtasticd (2.7.4.0) UNRELEASED; urgency=medium
[ ]
* GitHub Actions Automatic version bump
-- <github-actions[bot]@users.noreply.github.com> Sat, 19 Jul 2025 11:36:55 +0000
[ ]
* GitHub Actions Automatic version bump
[ ]
* GitHub Actions Automatic version bump
-- <github-actions[bot]@users.noreply.github.com> Tue, 12 Aug 2025 23:48:48 +0000

View File

@@ -60,9 +60,9 @@ monitor_speed = 115200
monitor_filters = direct
lib_deps =
# renovate: datasource=git-refs depName=meshtastic-esp8266-oled-ssd1306 packageName=https://github.com/meshtastic/esp8266-oled-ssd1306 gitBranch=master
https://github.com/meshtastic/esp8266-oled-ssd1306/archive/0119501e9983bd894830b02f545c377ee08d66fe.zip
# renovate: datasource=custom.pio depName=OneButton packageName=mathertel/library/OneButton
mathertel/OneButton@2.6.1
https://github.com/meshtastic/esp8266-oled-ssd1306/archive/9573abb64dc9c94f3051348f2bf4fc5cedf03c22.zip
# renovate: datasource=git-refs depName=meshtastic-OneButton packageName=https://github.com/meshtastic/OneButton gitBranch=master
https://github.com/meshtastic/OneButton/archive/fa352d668c53f290cfa480a5f79ad422cd828c70.zip
# renovate: datasource=git-refs depName=meshtastic-arduino-fsm packageName=https://github.com/meshtastic/arduino-fsm gitBranch=master
https://github.com/meshtastic/arduino-fsm/archive/7db3702bf0cfe97b783d6c72595e3f38e0b19159.zip
# renovate: datasource=git-refs depName=meshtastic-TinyGPSPlus packageName=https://github.com/meshtastic/TinyGPSPlus gitBranch=master
@@ -102,6 +102,14 @@ lib_deps =
# renovate: datasource=custom.pio depName=Syslog packageName=arcao/library/Syslog
arcao/Syslog@2.0.0
; Minimal networking libs for nrf52 (excludes Syslog to save flash)
[nrf52_networking_base]
lib_deps =
# renovate: datasource=custom.pio depName=TBPubSubClient packageName=thingsboard/library/TBPubSubClient
thingsboard/TBPubSubClient@2.12.1
# renovate: datasource=custom.pio depName=NTPClient packageName=arduino-libraries/library/NTPClient
arduino-libraries/NTPClient@3.2.1
[radiolib_base]
lib_deps =
# renovate: datasource=custom.pio depName=RadioLib packageName=jgromes/library/RadioLib
@@ -110,7 +118,7 @@ lib_deps =
[device-ui_base]
lib_deps =
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
https://github.com/meshtastic/device-ui/archive/c75d545bf9e8d1fe20051c319f427f711113ff22.zip
https://github.com/meshtastic/device-ui/archive/8f5094b248c15ea2f9acf19cedfef6d2248fc1ff.zip
; Common libs for environmental measurements in telemetry module
[environmental_base]
@@ -178,7 +186,7 @@ lib_deps =
# renovate: datasource=custom.pio depName=Adafruit MAX1704X packageName=adafruit/library/Adafruit MAX1704X
adafruit/Adafruit MAX1704X@1.0.3
# renovate: datasource=custom.pio depName=Adafruit SHTC3 packageName=adafruit/library/Adafruit SHTC3 Library
adafruit/Adafruit SHTC3 Library@1.0.1
adafruit/Adafruit SHTC3 Library@1.0.2
# renovate: datasource=custom.pio depName=Adafruit LPS2X packageName=adafruit/library/Adafruit LPS2X
adafruit/Adafruit LPS2X@2.0.6
# renovate: datasource=custom.pio depName=Adafruit SHT31 packageName=adafruit/library/Adafruit SHT31 Library

View File

@@ -89,14 +89,22 @@ class BluetoothStatus : public Status
case ConnectionState::CONNECTED:
LOG_DEBUG("BluetoothStatus CONNECTED");
#ifdef BLE_LED
#ifdef BLE_LED_INVERTED
digitalWrite(BLE_LED, LOW);
#else
digitalWrite(BLE_LED, HIGH);
#endif
#endif
break;
case ConnectionState::DISCONNECTED:
LOG_DEBUG("BluetoothStatus DISCONNECTED");
#ifdef BLE_LED
#ifdef BLE_LED_INVERTED
digitalWrite(BLE_LED, HIGH);
#else
digitalWrite(BLE_LED, LOW);
#endif
#endif
break;
}

View File

@@ -724,10 +724,12 @@ void Power::reboot()
SPI.end();
Wire.end();
Serial1.end();
if (screen)
if (screen) {
delete screen;
screen = nullptr;
}
LOG_DEBUG("final reboot!");
reboot();
::reboot();
#elif defined(ARCH_STM32WL)
HAL_NVIC_SystemReset();
#else

View File

@@ -140,6 +140,10 @@ bool playNextLeadUpNote()
playTones(&note, 1); // Play single note using existing playTones function
leadUpNoteIndex++;
if (leadUpNoteIndex >= leadUpNotesCount) {
return false; // this was the final note
}
return true; // Note was played (playTones handles buzzer availability internally)
}

View File

@@ -140,17 +140,32 @@ bool EInkDisplay::connect()
#endif
#endif
#if defined(TTGO_T_ECHO) || defined(ELECROW_ThinkNode_M1)
#if defined(TTGO_T_ECHO) || defined(ELECROW_ThinkNode_M1) || defined(T_ECHO_LITE)
{
auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, SPI1);
adafruitDisplay = new GxEPD2_BW<EINK_DISPLAY_MODEL, EINK_DISPLAY_MODEL::HEIGHT>(*lowLevel);
adafruitDisplay->init();
#ifdef ELECROW_ThinkNode_M1
#if defined(ELECROW_ThinkNode_M1) || defined(T_ECHO_LITE)
adafruitDisplay->setRotation(4);
#else
adafruitDisplay->setRotation(3);
#endif
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
}
#elif defined(ELECROW_ThinkNode_M5)
{
// Start HSPI
hspi = new SPIClass(HSPI);
hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); // SCLK, MISO, MOSI, SS
auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, *hspi);
adafruitDisplay = new GxEPD2_BW<EINK_DISPLAY_MODEL, EINK_DISPLAY_MODEL::HEIGHT>(*lowLevel);
adafruitDisplay->init();
adafruitDisplay->setRotation(4);
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
}
#elif defined(MESHLINK)

View File

@@ -80,7 +80,7 @@ class EInkDisplay : public OLEDDisplay
// If display uses HSPI
#if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0) || defined(HELTEC_VISION_MASTER_E213) || \
defined(HELTEC_VISION_MASTER_E290) || defined(TLORA_T3S3_EPAPER) || defined(CROWPANEL_ESP32S3_5_EPAPER) || \
defined(CROWPANEL_ESP32S3_4_EPAPER) || defined(CROWPANEL_ESP32S3_2_EPAPER)
defined(CROWPANEL_ESP32S3_4_EPAPER) || defined(CROWPANEL_ESP32S3_2_EPAPER) || defined(ELECROW_ThinkNode_M5)
SPIClass *hspi = NULL;
#endif

View File

@@ -365,9 +365,6 @@ void Screen::doDeepSleep()
{
#ifdef USE_EINK
setOn(false, graphics::UIRenderer::drawDeepSleepFrame);
#ifdef PIN_EINK_EN
digitalWrite(PIN_EINK_EN, LOW); // power off backlight
#endif
#else
// Without E-Ink display:
setOn(false);
@@ -391,6 +388,14 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
dispdev->displayOn();
#endif
#ifdef PIN_EINK_EN
if (uiconfig.screen_brightness == 1)
digitalWrite(PIN_EINK_EN, HIGH);
#elif defined(PCA_PIN_EINK_EN)
if (uiconfig.screen_brightness == 1)
io.digitalWrite(PCA_PIN_EINK_EN, HIGH);
#endif
#if defined(ST7789_CS) && \
!defined(M5STACK) // set display brightness when turning on screens. Just moved function from TFTDisplay to here.
static_cast<TFTDisplay *>(dispdev)->setDisplayBrightness(brightness);
@@ -420,11 +425,13 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
// eInkScreensaver parameter is usually NULL (default argument), default frame used instead
setScreensaverFrames(einkScreensaver);
#endif
#ifdef ELECROW_ThinkNode_M1
if (digitalRead(PIN_EINK_EN) == HIGH) {
digitalWrite(PIN_EINK_EN, LOW);
}
#ifdef PIN_EINK_EN
digitalWrite(PIN_EINK_EN, LOW);
#elif defined(PCA_PIN_EINK_EN)
io.digitalWrite(PCA_PIN_EINK_EN, LOW);
#endif
dispdev->displayOff();
#ifdef USE_ST7789
SPI1.end();
@@ -685,7 +692,7 @@ int32_t Screen::runOnce()
#ifndef DISABLE_WELCOME_UNSET
if (!NotificationRenderer::isOverlayBannerShowing() && config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
menuHandler::LoraRegionPicker(0);
menuHandler::OnboardMessage();
}
#endif
if (!NotificationRenderer::isOverlayBannerShowing() && rebootAtMsec != 0) {

View File

@@ -16,7 +16,7 @@
#include "graphics/fonts/OLEDDisplayFontsCS.h"
#endif
#ifdef CROWPANEL_ESP32S3_5_EPAPER
#if defined(CROWPANEL_ESP32S3_5_EPAPER) && defined(USE_EINK)
#include "graphics/fonts/EinkDisplayFonts.h"
#endif
@@ -40,6 +40,9 @@
#ifdef OLED_PL
#define FONT_MEDIUM_LOCAL ArialMT_Plain_16_PL // Height: 19
#else
#ifdef OLED_RU
#define FONT_MEDIUM_LOCAL ArialMT_Plain_16_RU // Height: 19
#else
#ifdef OLED_UA
#define FONT_MEDIUM_LOCAL ArialMT_Plain_16_UA // Height: 19
#else
@@ -50,9 +53,13 @@
#endif
#endif
#endif
#endif
#ifdef OLED_PL
#define FONT_LARGE_LOCAL ArialMT_Plain_24_PL // Height: 28
#else
#ifdef OLED_RU
#define FONT_LARGE_LOCAL ArialMT_Plain_24_RU // Height: 28
#else
#ifdef OLED_UA
#define FONT_LARGE_LOCAL ArialMT_Plain_24_UA // Height: 28
#else
@@ -63,6 +70,7 @@
#endif
#endif
#endif
#endif
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS)) && \
@@ -77,7 +85,7 @@
#define FONT_LARGE FONT_LARGE_LOCAL // Height: 28
#endif
#if defined(CROWPANEL_ESP32S3_5_EPAPER)
#if defined(CROWPANEL_ESP32S3_5_EPAPER) && defined(USE_EINK)
#undef FONT_SMALL
#undef FONT_MEDIUM
#undef FONT_LARGE

View File

@@ -849,9 +849,29 @@ static LGFX *tft = nullptr;
#include <lgfx/v1/platforms/esp32s3/Bus_RGB.hpp>
#include <lgfx/v1/platforms/esp32s3/Panel_RGB.hpp>
class PanelInit_ST7701 : public lgfx::Panel_ST7701
{
public:
const uint8_t *getInitCommands(uint8_t listno) const override
{
// 180 degree hw rotation: vertical flip, horizontal flip
static constexpr const uint8_t list1[] = {0x36, 1, 0x10, // MADCTL for vertical flip
0xFF, 5, 0x77, 0x01, 0x00, 0x00, 0x10, // Command2 BK0 SEL
0xC7, 1, 0x04, // SDIR: X-direction Control (Horizontal Flip)
0xFF, 5, 0x77, 0x01, 0x00, 0x00, 0x00, // Command2 BK0 DIS
0xFF, 0xFF};
switch (listno) {
case 1:
return list1;
default:
return lgfx::Panel_ST7701::getInitCommands(listno);
}
}
};
class LGFX : public lgfx::LGFX_Device
{
lgfx::Panel_ST7701 _panel_instance;
PanelInit_ST7701 _panel_instance;
lgfx::Bus_RGB _bus_instance;
lgfx::Light_PWM _light_instance;
lgfx::Touch_FT5x06 _touch_instance;
@@ -1184,9 +1204,9 @@ 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) || defined(SENSECAP_INDICATOR)
#elif defined(T_WATCH_S3)
tft->setRotation(2); // T-Watch S3 left-handed orientation
#elif ARCH_PORTDUINO
#elif ARCH_PORTDUINO || defined(SENSECAP_INDICATOR)
tft->setRotation(0); // use config.yaml to set rotation
#else
tft->setRotation(3); // Orient horizontal and wide underneath the silkscreen name label

View File

@@ -26,6 +26,27 @@ menuHandler::screenMenus menuHandler::menuQueue = menu_none;
bool test_enabled = false;
uint8_t test_count = 0;
void menuHandler::OnboardMessage()
{
static const char *optionsArray[] = {"OK", "Got it!"};
enum optionsNumbers { OK, got };
BannerOverlayOptions bannerOptions;
#if HAS_TFT
bannerOptions.message = "Welcome to Meshtastic!\nSwipe to navigate and\nlong press to select\nor open a menu.";
#elif defined(BUTTON_PIN)
bannerOptions.message = "Welcome to Meshtastic!\nClick to navigate and\nlong press to select\nor open a menu.";
#else
bannerOptions.message = "Welcome to Meshtastic!\nUse the Select button\nto open menus\nand make selections.";
#endif
bannerOptions.optionsArrayPtr = optionsArray;
bannerOptions.optionsCount = 2;
bannerOptions.bannerCallback = [](int selected) -> void {
menuHandler::menuQueue = menuHandler::no_timeout_lora_picker;
screen->runNow();
};
screen->showOverlayBanner(bannerOptions);
}
void menuHandler::LoraRegionPicker(uint32_t duration)
{
static const char *optionsArray[] = {"Back",
@@ -318,7 +339,7 @@ void menuHandler::homeBaseMenu()
static int optionsEnumArray[enumEnd] = {Back};
int options = 1;
#ifdef PIN_EINK_EN
#if defined(PIN_EINK_EN) || defined(PCA_PIN_EINK_EN)
optionsArray[options] = "Toggle Backlight";
optionsEnumArray[options++] = Backlight;
#else
@@ -342,12 +363,24 @@ void menuHandler::homeBaseMenu()
bannerOptions.optionsCount = options;
bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == Backlight) {
#ifdef PIN_EINK_EN
if (digitalRead(PIN_EINK_EN) == HIGH) {
#if defined(PIN_EINK_EN)
if (uiconfig.screen_brightness == 1) {
uiconfig.screen_brightness = 0;
digitalWrite(PIN_EINK_EN, LOW);
} else {
uiconfig.screen_brightness = 1;
digitalWrite(PIN_EINK_EN, HIGH);
}
saveUIConfig();
#elif defined(PCA_PIN_EINK_EN)
if (uiconfig.screen_brightness == 1) {
uiconfig.screen_brightness = 0;
io.digitalWrite(PCA_PIN_EINK_EN, LOW);
} else {
uiconfig.screen_brightness = 1;
io.digitalWrite(PCA_PIN_EINK_EN, HIGH);
}
saveUIConfig();
#endif
} else if (selected == Sleep) {
screen->setOn(false);
@@ -1120,6 +1153,9 @@ void menuHandler::handleMenuSwitch(OLEDDisplay *display)
case lora_picker:
LoraRegionPicker();
break;
case no_timeout_lora_picker:
LoraRegionPicker(0);
break;
case TZ_picker:
TZPicker();
break;

View File

@@ -10,6 +10,7 @@ class menuHandler
enum screenMenus {
menu_none,
lora_picker,
no_timeout_lora_picker,
TZ_picker,
twelve_hour_picker,
clock_face_picker,
@@ -41,6 +42,7 @@ class menuHandler
};
static screenMenus menuQueue;
static void OnboardMessage();
static void LoraRegionPicker(uint32_t duration = 30000);
static void handleMenuSwitch(OLEDDisplay *display);
static void showConfirmationBanner(const char *message, std::function<void()> onConfirm);

View File

@@ -137,7 +137,11 @@ void drawStringWithEmotes(OLEDDisplay *display, int x, int y, const std::string
display->drawString(cursorX + 1, fontY, textChunk.c_str());
}
display->drawString(cursorX, fontY, textChunk.c_str());
#if defined(OLED_UA) || defined(OLED_RU)
cursorX += display->getStringWidth(textChunk.c_str(), textChunk.length(), true);
#else
cursorX += display->getStringWidth(textChunk.c_str());
#endif
i = nextControl;
continue;
}
@@ -155,7 +159,12 @@ void drawStringWithEmotes(OLEDDisplay *display, int x, int y, const std::string
display->drawString(cursorX + 1, fontY, remaining.c_str());
}
display->drawString(cursorX, fontY, remaining.c_str());
#if defined(OLED_UA) || defined(OLED_RU)
cursorX += display->getStringWidth(remaining.c_str(), remaining.length(), true);
#else
cursorX += display->getStringWidth(remaining.c_str());
#endif
break;
}
}
@@ -374,10 +383,16 @@ std::vector<std::string> generateLines(OLEDDisplay *display, const char *headerS
} else {
word += ch;
std::string test = line + word;
// Keep these lines for diagnostics
// LOG_INFO("Char: '%c' (0x%02X)", ch, (unsigned char)ch);
// LOG_INFO("Current String: %s", test.c_str());
if (display->getStringWidth(test.c_str()) > textWidth) {
// Keep these lines for diagnostics
// LOG_INFO("Char: '%c' (0x%02X)", ch, (unsigned char)ch);
// LOG_INFO("Current String: %s", test.c_str());
// Note: there are boolean comparison uint16 (getStringWidth) with int (textWidth), hope textWidth is always positive :)
#if defined(OLED_UA) || defined(OLED_RU)
uint16_t strWidth = display->getStringWidth(test.c_str(), test.length(), true);
#else
uint16_t strWidth = display->getStringWidth(test.c_str());
#endif
if (strWidth > textWidth) {
if (!line.empty())
lines.push_back(line);
line = word;

View File

@@ -383,7 +383,9 @@ void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisp
uint8_t firstOptionToShow = 0;
if (alertBannerOptions > 0) {
if (curSelected > 1 && alertBannerOptions > visibleTotalLines - lineCount) {
if (visibleTotalLines - lineCount == 1) {
firstOptionToShow = curSelected;
} else if (curSelected > 1 && alertBannerOptions > visibleTotalLines - lineCount) {
if (curSelected > alertBannerOptions - visibleTotalLines + lineCount)
firstOptionToShow = alertBannerOptions - visibleTotalLines + lineCount;
else
@@ -392,6 +394,9 @@ void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisp
firstOptionToShow = 0;
}
}
// Useful log line for troubleshooting:
/* LOG_WARN("alertBannerOptions: %u, curSelected: %u, visibleTotalLines: %u, lineCount: %u, firstOptionToShow: %u",
alertBannerOptions, curSelected, visibleTotalLines, lineCount, firstOptionToShow); */
for (int i = firstOptionToShow; i < alertBannerOptions && linesShown < visibleTotalLines; i++, linesShown++) {
if (i == curSelected) {

View File

@@ -1,3 +1,5 @@
#ifdef USE_EINK
#include "EinkDisplayFonts.h"
// Created by https://oleddisplay.squix.ch/ Consider a donation
@@ -1182,3 +1184,5 @@ const uint8_t Monospaced_plain_30[] PROGMEM = {
0xF0, 0xFF, 0x01, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x00, 0xF0, 0x0F, 0x00, 0xE0, 0x00, 0xFE, 0x03, 0x00, 0xE0, 0x80, 0x7F,
0x00, 0x00, 0xE0, 0xE0, 0x1F, 0x00, 0x00, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x10 // 255
};
#endif // USE_EINK

View File

@@ -1,6 +1,8 @@
#ifndef EINKDISPLAYFONTS_h
#define EINKDISPLAYFONTS_h
#ifdef USE_EINK
#ifdef ARDUINO
#include <Arduino.h>
#elif __MBED__
@@ -11,4 +13,7 @@
* Monospaced Plain 30
*/
extern const uint8_t Monospaced_plain_30[] PROGMEM;
#endif // USE_EINK
#endif

View File

@@ -1,3 +1,5 @@
#ifdef OLED_CS
#include "OLEDDisplayFontsCS.h"
// Font generated or edited with the glyphEditor
@@ -1860,4 +1862,6 @@ const uint8_t ArialMT_Plain_24_CS[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x06, 0xC0, 0xF0, 0x01, 0x06, 0xC0, 0x80, 0x0F, 0x07, 0x00,
0x00, 0xFE, 0x03, 0x00, 0x00, 0xFC, 0x00, 0xC0, 0xC0, 0x1F, 0x00, 0xC0, 0xF8, 0x03, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00,
0x06, // 255
};
};
#endif // OLED_CS

View File

@@ -1,4 +1,5 @@
// trunk-ignore-all(clang-format): Preserve long lines
#ifdef OLED_PL
#include "OLEDDisplayFontsPL.h"
const uint8_t ArialMT_Plain_10_PL[] PROGMEM = {
@@ -1310,4 +1311,6 @@ const uint8_t ArialMT_Plain_24_PL[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x06, 0x00, 0xF0, 0x01, 0x06, 0x00, 0x80, 0x0F, 0x07, 0x80, 0x00, 0xFE, 0x03, 0xE0, 0x00, 0xFC, 0x00, 0x60, 0xC0, 0x1F, 0x00, 0x20, 0xF8, 0x03, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x06, // 253
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x1C, 0x18, 0x00, 0x00, 0x06, 0x30, 0x00, 0x00, 0x06, 0x30, 0x00, 0x00, 0x06, 0x30, 0x00, 0x00, 0x0E, 0x38, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF0, 0x03, // 254
0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x06, 0xC0, 0xF0, 0x01, 0x06, 0xC0, 0x80, 0x0F, 0x07, 0x00, 0x00, 0xFE, 0x03, 0x00, 0x00, 0xFC, 0x00, 0xC0, 0xC0, 0x1F, 0x00, 0xC0, 0xF8, 0x03, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x06, // 255
};
};
#endif // OLED_PL

File diff suppressed because it is too large Load Diff

View File

@@ -8,4 +8,6 @@
#endif
extern const uint8_t ArialMT_Plain_10_RU[] PROGMEM;
extern const uint8_t ArialMT_Plain_16_RU[] PROGMEM;
extern const uint8_t ArialMT_Plain_24_RU[] PROGMEM;
#endif

View File

@@ -1,3 +1,5 @@
#ifdef OLED_UA
#include "OLEDDisplayFontsUA.h"
// Font generated or edited with the glyphEditor
@@ -1920,4 +1922,6 @@ const uint8_t ArialMT_Plain_24_UA[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xC1, 0x00, 0x00, 0xF0, 0xE3, 0x00, 0x00, 0x38, 0x7B, 0x00, 0x00, 0x18, 0x1A, 0x00, 0x00,
0x18, 0x0E, 0x00, 0x00, 0x18, 0x06, 0x00, 0x00, 0x18, 0x06, 0x00, 0x00, 0x18, 0x06, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8,
0xFF, // 1103
};
};
#endif // OLED_UA

View File

@@ -92,8 +92,11 @@ bool ButtonThread::initButton(const ButtonConfig &config)
if (config.shortLong != INPUT_BROKER_NONE) {
_shortLong = config.shortLong;
}
#ifdef USE_EINK
userButton.setDebounceMs(0);
#else
userButton.setDebounceMs(1);
#endif
userButton.setPressMs(_longPressTime);
if (screen) {
@@ -137,8 +140,7 @@ int32_t ButtonThread::runOnce()
}
// Progressive lead-up sound system
if (buttonCurrentlyPressed && (millis() - buttonPressStartTime) >= BUTTON_LEADUP_MS &&
(millis() - buttonPressStartTime) < _longLongPressTime) {
if (buttonCurrentlyPressed && (millis() - buttonPressStartTime) >= BUTTON_LEADUP_MS) {
// Start the progressive sequence if not already active
if (!leadUpSequenceActive) {
@@ -150,13 +152,14 @@ int32_t ButtonThread::runOnce()
else if ((millis() - lastLeadUpNoteTime) >= 400) { // 400ms interval between notes
if (playNextLeadUpNote()) {
lastLeadUpNoteTime = millis();
} else {
leadUpPlayed = true;
}
}
}
// Reset when button is released
if (!buttonCurrentlyPressed && buttonWasPressed) {
leadUpPlayed = false;
leadUpSequenceActive = false;
resetLeadUpSequence();
}
@@ -253,12 +256,13 @@ int32_t ButtonThread::runOnce()
LOG_INFO("LONG PRESS RELEASE AFTER %u MILLIS", millis() - buttonPressStartTime);
if (millis() > 30000 && _longLongPress != INPUT_BROKER_NONE &&
(millis() - buttonPressStartTime) >= _longLongPressTime) {
(millis() - buttonPressStartTime) >= _longLongPressTime && leadUpPlayed) {
evt.inputEvent = _longLongPress;
this->notifyObservers(&evt);
}
// Reset combination tracking
waitingForLongPress = false;
leadUpPlayed = false;
break;
}

View File

@@ -92,7 +92,7 @@ class ButtonThread : public Observable<const InputEvent *>, public concurrency::
voidFuncPtr _intRoutine = nullptr;
uint16_t _longPressTime = 500;
uint16_t _longLongPressTime = 5000;
uint16_t _longLongPressTime = 3900;
int _pinNum = 0;
bool _activeLow = true;
bool _touchQuirk = false;

View File

@@ -38,6 +38,10 @@
#include <memory>
#include <utility>
#ifdef ELECROW_ThinkNode_M5
PCA9557 io(0x18, &Wire);
#endif
#ifdef ARCH_ESP32
#include "freertosinc.h"
#if !MESHTASTIC_EXCLUDE_WEBSERVER
@@ -296,6 +300,14 @@ void setup()
digitalWrite(PIN_POWER_EN, HIGH);
#endif
#if defined(ELECROW_ThinkNode_M5)
Wire.begin(48, 47);
io.pinMode(PCA_PIN_EINK_EN, OUTPUT);
io.pinMode(PCA_PIN_POWER_EN, OUTPUT);
io.digitalWrite(PCA_PIN_POWER_EN, HIGH);
// io.pinMode(C2_PIN, OUTPUT);
#endif
#ifdef LED_POWER
pinMode(LED_POWER, OUTPUT);
digitalWrite(LED_POWER, LED_STATE_ON);
@@ -313,8 +325,12 @@ void setup()
#ifdef BLE_LED
pinMode(BLE_LED, OUTPUT);
#ifdef BLE_LED_INVERTED
digitalWrite(BLE_LED, HIGH);
#else
digitalWrite(BLE_LED, LOW);
#endif
#endif
#if defined(T_DECK)
// GPIO10 manages all peripheral power supplies
@@ -754,11 +770,6 @@ void setup()
if (config.display.oled != meshtastic_Config_DisplayConfig_OledType_OLED_AUTO)
screen_model = config.display.oled;
#if defined(USE_SH1107)
screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1107; // set dimension of 128x128
screen_geometry = GEOMETRY_128_128;
#endif
#if defined(USE_SH1107_128_64)
screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1107; // keep dimension of 128x64
screen_geometry = GEOMETRY_128_64;
@@ -766,10 +777,9 @@ void setup()
// if we have one of the fixed overrides in the settings, adjust display type accordingly.
if (screen_model == meshtastic_Config_DisplayConfig_OledType_OLED_SH1107) {
screen_geometry = GEOMETRY_128_128;
} else if (screen_model == meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_64) {
screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1107;
screen_geometry = GEOMETRY_128_64;
} else if (screen_model == meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_128) {
screen_geometry = GEOMETRY_128_128;
}
#if !MESHTASTIC_EXCLUDE_I2C
@@ -911,14 +921,20 @@ void setup()
service = new MeshService();
service->init();
if (nodeDB->keyIsLowEntropy) {
service->reloadConfig(SEGMENT_CONFIG);
rebootAtMsec = (millis() + DEFAULT_REBOOT_SECONDS * 1000);
}
// Now that the mesh service is created, create any modules
setupModules();
// warn the user about a low entropy key
if (nodeDB->keyIsLowEntropy && !nodeDB->hasWarned) {
LOG_WARN(LOW_ENTROPY_WARNING);
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
cn->level = meshtastic_LogRecord_Level_WARNING;
cn->time = getValidTime(RTCQualityFromNet);
sprintf(cn->message, LOW_ENTROPY_WARNING);
service->sendClientNotification(cn);
nodeDB->hasWarned = true;
}
// buttons are now inputBroker, so have to come after setupModules
#if HAS_BUTTON
int pullup_sense = 0;

View File

@@ -51,6 +51,11 @@ extern Adafruit_DRV2605 drv;
extern AudioThread *audioThread;
#endif
#ifdef ELECROW_ThinkNode_M5
#include <PCA9557.h>
extern PCA9557 io;
#endif
#ifdef HAS_UDP_MULTICAST
#include "mesh/udp/UdpMulticastHandler.h"
extern UdpMulticastHandler *udpHandler;

View File

@@ -47,8 +47,10 @@ void FloodingRouter::perhapsCancelDupe(const meshtastic_MeshPacket *p)
{
if (config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER &&
config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER &&
config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER_LATE) {
config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER_LATE &&
p->transport_mechanism == meshtastic_MeshPacket_TransportMechanism_TRANSPORT_LORA) {
// cancel rebroadcast of this message *if* there was already one, unless we're a router/repeater!
// But only LoRa packets should be able to trigger this.
if (Router::cancelSending(p->from, p->id))
txRelayCanceled++;
}

View File

@@ -6,6 +6,10 @@
#include "mesh/NodeDB.h"
#ifdef LR11X0_DIO_AS_RF_SWITCH
#include "rfswitch.h"
#elif ARCH_PORTDUINO
#include "PortduinoGlue.h"
#define rfswitch_dio_pins portduino_config.rfswitch_dio_pins
#define rfswitch_table portduino_config.rfswitch_table
#else
static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC};
static const Module::RfSwitchMode_t rfswitch_table[] = {
@@ -14,10 +18,6 @@ static const Module::RfSwitchMode_t rfswitch_table[] = {
};
#endif
#ifdef ARCH_PORTDUINO
#include "PortduinoGlue.h"
#endif
// Particular boards might define a different max power based on what their hardware can do, default to max power output if not
// specified (may be dangerous if using external PA and LR11x0 power config forgotten)
#if ARCH_PORTDUINO
@@ -117,17 +117,14 @@ template <typename T> bool LR11x0Interface<T>::init()
#ifdef LR11X0_DIO_AS_RF_SWITCH
bool dioAsRfSwitch = true;
#elif defined(ARCH_PORTDUINO)
bool dioAsRfSwitch = false;
if (settingsMap[dio2_as_rf_switch]) {
dioAsRfSwitch = true;
}
bool dioAsRfSwitch = portduino_config.has_rfswitch_table;
#else
bool dioAsRfSwitch = false;
#endif
if (dioAsRfSwitch) {
lora.setRfSwitchTable(rfswitch_dio_pins, rfswitch_table);
LOG_DEBUG("Set DIO RF switch", res);
LOG_DEBUG("Set DIO RF switch");
}
if (res == RADIOLIB_ERR_NONE) {

View File

@@ -85,8 +85,11 @@ meshtastic_MeshPacket *MeshModule::allocErrorResponse(meshtastic_Routing_Error e
return r;
}
void MeshModule::callModules(meshtastic_MeshPacket &mp, RxSource src)
void MeshModule::callModules(meshtastic_MeshPacket &mp, RxSource src, const char *specificModule)
{
if (specificModule) {
LOG_DEBUG("Calling specific module: %s", specificModule);
}
// LOG_DEBUG("In call modules");
bool moduleFound = false;
@@ -104,6 +107,11 @@ void MeshModule::callModules(meshtastic_MeshPacket &mp, RxSource src)
for (auto i = modules->begin(); i != modules->end(); ++i) {
auto &pi = **i;
// If specificModule is provided, only call that specific module
if (specificModule && (!pi.name || strcmp(pi.name, specificModule) != 0)) {
continue;
}
pi.currentRequest = &mp;
/// We only call modules that are interested in the packet (and the message is destined to us or we are promiscious)

View File

@@ -73,7 +73,7 @@ class MeshModule
/** For use only by MeshService
*/
static void callModules(meshtastic_MeshPacket &mp, RxSource src = RX_SRC_RADIO);
static void callModules(meshtastic_MeshPacket &mp, RxSource src = RX_SRC_RADIO, const char *specificModule = nullptr);
static std::vector<MeshModule *> GetMeshModulesWithUIFrames(int startIndex);
static void observeUIEvents(Observer<const UIFrameEvent *> *observer);

View File

@@ -264,12 +264,12 @@ NodeDB::NodeDB()
if (!owner.is_licensed && config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
bool keygenSuccess = false;
if (config.security.private_key.size == 32) {
keyIsLowEntropy = checkLowEntropyPublicKey(config.security.public_key);
if (config.security.private_key.size == 32 && !keyIsLowEntropy) {
if (crypto->regeneratePublicKey(config.security.public_key.bytes, config.security.private_key.bytes)) {
keygenSuccess = true;
}
} else {
LOG_INFO("Generate new PKI keys");
crypto->generateKeyPair(config.security.public_key.bytes, config.security.private_key.bytes);
keygenSuccess = true;
}
@@ -288,16 +288,6 @@ NodeDB::NodeDB()
crypto->setDHPrivateKey(config.security.private_key.bytes);
}
#endif
keyIsLowEntropy = checkLowEntropyPublicKey(config.security.public_key);
if (keyIsLowEntropy) {
LOG_WARN("Erasing low entropy keys");
config.security.private_key.size = 0;
memfll(config.security.private_key.bytes, '\0', sizeof(config.security.private_key.bytes));
config.security.public_key.size = 0;
memfll(config.security.public_key.bytes, '\0', sizeof(config.security.public_key.bytes));
owner.public_key.size = 0;
memfll(owner.public_key.bytes, '\0', sizeof(owner.public_key.bytes));
}
// Include our owner in the node db under our nodenum
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(getNodeNum());
info->user = TypeConversions::ConvertToUserLite(owner);
@@ -1641,25 +1631,33 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
printBytes("Incoming Pubkey: ", p.public_key.bytes, 32);
// Alert the user if a remote node is advertising public key that matches our own
if (owner.public_key.size == 32 && memcmp(p.public_key.bytes, owner.public_key.bytes, 32) == 0 && !duplicateWarned) {
duplicateWarned = true;
char warning[] = "Remote device %s has advertised your public key. This may indicate a compromised key. You may need "
"to regenerate your public keys.";
LOG_WARN(warning, p.long_name);
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
cn->which_payload_variant = meshtastic_ClientNotification_duplicated_public_key_tag;
cn->level = meshtastic_LogRecord_Level_WARNING;
cn->time = getValidTime(RTCQualityFromNet);
sprintf(cn->message, warning, p.long_name);
service->sendClientNotification(cn);
if (owner.public_key.size == 32 && memcmp(p.public_key.bytes, owner.public_key.bytes, 32) == 0) {
if (!duplicateWarned) {
duplicateWarned = true;
char warning[] =
"Remote device %s has advertised your public key. This may indicate a compromised key. You may need "
"to regenerate your public keys.";
LOG_WARN(warning, p.long_name);
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
cn->level = meshtastic_LogRecord_Level_WARNING;
cn->time = getValidTime(RTCQualityFromNet);
sprintf(cn->message, warning, p.long_name);
service->sendClientNotification(cn);
}
return false;
}
}
if (info->user.public_key.size > 0) { // if we have a key for this user already, don't overwrite with a new one
if (info->user.public_key.size == 32) { // if we have a key for this user already, don't overwrite with a new one
// if the key doesn't match, don't update nodeDB at all.
if (p.public_key.size != 32 || (memcmp(p.public_key.bytes, info->user.public_key.bytes, 32) != 0)) {
LOG_WARN("Public Key mismatch, dropping NodeInfo");
return false;
}
LOG_INFO("Public Key set for node, not updating!");
// we copy the key into the incoming packet, to prevent overwrite
p.public_key.size = 32;
memcpy(p.public_key.bytes, info->user.public_key.bytes, 32);
} else if (p.public_key.size > 0) {
} else if (p.public_key.size == 32) {
LOG_INFO("Update Node Pubkey!");
}
#endif
@@ -1878,28 +1876,10 @@ bool NodeDB::checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_pub
uint8_t keyHash[32] = {0};
memcpy(keyHash, keyToTest.bytes, keyToTest.size);
crypto->hash(keyHash, 32);
if (memcmp(keyHash, LOW_ENTROPY_HASH1, sizeof(LOW_ENTROPY_HASH1)) ==
0 || // should become an array that gets looped through rather than this abomination
memcmp(keyHash, LOW_ENTROPY_HASH2, sizeof(LOW_ENTROPY_HASH2)) == 0 ||
memcmp(keyHash, LOW_ENTROPY_HASH3, sizeof(LOW_ENTROPY_HASH3)) == 0 ||
memcmp(keyHash, LOW_ENTROPY_HASH4, sizeof(LOW_ENTROPY_HASH4)) == 0 ||
memcmp(keyHash, LOW_ENTROPY_HASH5, sizeof(LOW_ENTROPY_HASH5)) == 0 ||
memcmp(keyHash, LOW_ENTROPY_HASH6, sizeof(LOW_ENTROPY_HASH6)) == 0 ||
memcmp(keyHash, LOW_ENTROPY_HASH7, sizeof(LOW_ENTROPY_HASH7)) == 0 ||
memcmp(keyHash, LOW_ENTROPY_HASH8, sizeof(LOW_ENTROPY_HASH8)) == 0 ||
memcmp(keyHash, LOW_ENTROPY_HASH9, sizeof(LOW_ENTROPY_HASH9)) == 0 ||
memcmp(keyHash, LOW_ENTROPY_HASH10, sizeof(LOW_ENTROPY_HASH10)) == 0 ||
memcmp(keyHash, LOW_ENTROPY_HASH11, sizeof(LOW_ENTROPY_HASH11)) == 0 ||
memcmp(keyHash, LOW_ENTROPY_HASH12, sizeof(LOW_ENTROPY_HASH12)) == 0 ||
memcmp(keyHash, LOW_ENTROPY_HASH13, sizeof(LOW_ENTROPY_HASH13)) == 0 ||
memcmp(keyHash, LOW_ENTROPY_HASH14, sizeof(LOW_ENTROPY_HASH14)) == 0 ||
memcmp(keyHash, LOW_ENTROPY_HASH15, sizeof(LOW_ENTROPY_HASH15)) == 0 ||
memcmp(keyHash, LOW_ENTROPY_HASH16, sizeof(LOW_ENTROPY_HASH16)) == 0 ||
memcmp(keyHash, LOW_ENTROPY_HASH17, sizeof(LOW_ENTROPY_HASH17)) == 0 ||
memcmp(keyHash, LOW_ENTROPY_HASH18, sizeof(LOW_ENTROPY_HASH18)) == 0 ||
memcmp(keyHash, LOW_ENTROPY_HASH19, sizeof(LOW_ENTROPY_HASH19)) == 0 ||
memcmp(keyHash, LOW_ENTROPY_HASH20, sizeof(LOW_ENTROPY_HASH20)) == 0) {
return true;
for (uint16_t i = 0; i < sizeof(LOW_ENTROPY_HASHES) / sizeof(LOW_ENTROPY_HASHES[0]); i++) {
if (memcmp(keyHash, LOW_ENTROPY_HASHES[i], sizeof(LOW_ENTROPY_HASHES[0])) == 0) {
return true;
}
}
}
return false;

View File

@@ -18,68 +18,57 @@
#endif
#if !defined(MESHTASTIC_EXCLUDE_PKI)
static const uint8_t LOW_ENTROPY_HASH1[] = {0xf4, 0x7e, 0xcc, 0x17, 0xe6, 0xb4, 0xa3, 0x22, 0xec, 0xee, 0xd9,
0x08, 0x4f, 0x39, 0x63, 0xea, 0x80, 0x75, 0xe1, 0x24, 0xce, 0x05,
0x36, 0x69, 0x63, 0xb2, 0xcb, 0xc0, 0x28, 0xd3, 0x34, 0x8b};
static const uint8_t LOW_ENTROPY_HASH2[] = {0x5a, 0x9e, 0xa2, 0xa6, 0x8a, 0xa6, 0x66, 0xc1, 0x5f, 0x55, 0x00,
0x64, 0xa3, 0xa6, 0xfe, 0x71, 0xc0, 0xbb, 0x82, 0xc3, 0x32, 0x3d,
0x7a, 0x7a, 0xe3, 0x6e, 0xfd, 0xdd, 0xad, 0x3a, 0x66, 0xb9};
static const uint8_t LOW_ENTROPY_HASH3[] = {0xb3, 0xdf, 0x3b, 0x2e, 0x67, 0xb6, 0xd5, 0xf8, 0xdf, 0x76, 0x2c,
0x45, 0x5e, 0x2e, 0xbd, 0x16, 0xc5, 0xf8, 0x67, 0xaa, 0x15, 0xf8,
0x92, 0x0b, 0xdf, 0x5a, 0x66, 0x50, 0xac, 0x0d, 0xbb, 0x2f};
static const uint8_t LOW_ENTROPY_HASH4[] = {0x3b, 0x8f, 0x86, 0x3a, 0x38, 0x1f, 0x77, 0x39, 0xa9, 0x4e, 0xef,
0x91, 0x18, 0x5a, 0x62, 0xe1, 0xaa, 0x9d, 0x36, 0xea, 0xce, 0x60,
0x35, 0x8d, 0x9d, 0x1f, 0xf4, 0xb8, 0xc9, 0x13, 0x6a, 0x5d};
static const uint8_t LOW_ENTROPY_HASH5[] = {0x36, 0x7e, 0x2d, 0xe1, 0x84, 0x5f, 0x42, 0x52, 0x29, 0x11, 0x0a,
0x25, 0x64, 0x54, 0x6a, 0x6b, 0xfd, 0xb6, 0x65, 0xff, 0x15, 0x1a,
0x51, 0x71, 0x22, 0x40, 0x57, 0xf6, 0x91, 0x9b, 0x64, 0x58};
static const uint8_t LOW_ENTROPY_HASH6[] = {0x16, 0x77, 0xeb, 0xa4, 0x52, 0x91, 0xfb, 0x26, 0xcf, 0x8f, 0xd7,
0xd9, 0xd1, 0x5d, 0xc4, 0x68, 0x73, 0x75, 0xed, 0xc5, 0x95, 0x58,
0xee, 0x90, 0x56, 0xd4, 0x2f, 0x31, 0x29, 0xf7, 0x8c, 0x1f};
static const uint8_t LOW_ENTROPY_HASH7[] = {0x31, 0x8c, 0xa9, 0x5e, 0xed, 0x3c, 0x12, 0xbf, 0x97, 0x9c, 0x47,
0x8e, 0x98, 0x9d, 0xc2, 0x3e, 0x86, 0x23, 0x90, 0x29, 0xc8, 0xb0,
0x20, 0xf8, 0xb1, 0xb0, 0xaa, 0x19, 0x2a, 0xcf, 0x0a, 0x54};
static const uint8_t LOW_ENTROPY_HASH8[] = {0xa4, 0x8a, 0x99, 0x0e, 0x51, 0xdc, 0x12, 0x20, 0xf3, 0x13, 0xf5,
0x2b, 0x3a, 0xe2, 0x43, 0x42, 0xc6, 0x52, 0x98, 0xcd, 0xbb, 0xca,
0xb1, 0x31, 0xa0, 0xd4, 0xd6, 0x30, 0xf3, 0x27, 0xfb, 0x49};
static const uint8_t LOW_ENTROPY_HASH9[] = {0xd2, 0x3f, 0x13, 0x8d, 0x22, 0x04, 0x8d, 0x07, 0x59, 0x58, 0xa0,
0xf9, 0x55, 0xcf, 0x30, 0xa0, 0x2e, 0x2f, 0xca, 0x80, 0x20, 0xe4,
0xde, 0xa1, 0xad, 0xd9, 0x58, 0xb3, 0x43, 0x2b, 0x22, 0x70};
static const uint8_t LOW_ENTROPY_HASH10[] = {0x40, 0x41, 0xec, 0x6a, 0xd2, 0xd6, 0x03, 0xe4, 0x9a, 0x9e, 0xbd,
0x6c, 0x0a, 0x9b, 0x75, 0xa4, 0xbc, 0xab, 0x6f, 0xa7, 0x95, 0xff,
0x2d, 0xf6, 0xe9, 0xb9, 0xab, 0x4c, 0x0c, 0x1c, 0xd0, 0x3b};
static const uint8_t LOW_ENTROPY_HASH11[] = {0x22, 0x49, 0x32, 0x2b, 0x00, 0xf9, 0x22, 0xfa, 0x17, 0x02, 0xe9,
0x64, 0x82, 0xf0, 0x4d, 0x1b, 0xc7, 0x04, 0xfc, 0xdc, 0x8c, 0x5e,
0xb6, 0xd9, 0x16, 0xd6, 0x37, 0xce, 0x59, 0xaa, 0x09, 0x49};
static const uint8_t LOW_ENTROPY_HASH12[] = {0x48, 0x6f, 0x1e, 0x48, 0x97, 0x88, 0x64, 0xac, 0xe8, 0xeb, 0x30,
0xa3, 0xc3, 0xe1, 0xcf, 0x97, 0x39, 0xa6, 0x55, 0x5b, 0x5f, 0xbf,
0x18, 0xb7, 0x3a, 0xdf, 0xa8, 0x75, 0xe7, 0x9d, 0xe0, 0x1e};
static const uint8_t LOW_ENTROPY_HASH13[] = {0x09, 0xb4, 0xe2, 0x6d, 0x28, 0x98, 0xc9, 0x47, 0x66, 0x46, 0xbf,
0xff, 0x58, 0x17, 0x91, 0xaa, 0xc3, 0xbf, 0x4a, 0x9d, 0x0b, 0x88,
0xb1, 0xf1, 0x03, 0xdd, 0x61, 0xd7, 0xba, 0x9e, 0x64, 0x98};
static const uint8_t LOW_ENTROPY_HASH14[] = {0x39, 0x39, 0x84, 0xe0, 0x22, 0x2f, 0x7d, 0x78, 0x45, 0x18, 0x72,
0xb4, 0x13, 0xd2, 0x01, 0x2f, 0x3c, 0xa1, 0xb0, 0xfe, 0x39, 0xd0,
0xf1, 0x3c, 0x72, 0xd6, 0xef, 0x54, 0xd5, 0x77, 0x22, 0xa0};
static const uint8_t LOW_ENTROPY_HASH15[] = {0x0a, 0xda, 0x5f, 0xec, 0xff, 0x5c, 0xc0, 0x2e, 0x5f, 0xc4, 0x8d,
0x03, 0xe5, 0x80, 0x59, 0xd3, 0x5d, 0x49, 0x86, 0xe9, 0x8d, 0xf6,
0xf6, 0x16, 0x35, 0x3d, 0xf9, 0x9b, 0x29, 0x55, 0x9e, 0x64};
static const uint8_t LOW_ENTROPY_HASH16[] = {0x08, 0x56, 0xF0, 0xD7, 0xEF, 0x77, 0xD6, 0x11, 0x1C, 0x8F, 0x95,
0x2D, 0x3C, 0xDF, 0xB1, 0x22, 0xBF, 0x60, 0x9B, 0xE5, 0xA9, 0xC0,
0x6E, 0x4B, 0x01, 0xDC, 0xD1, 0x57, 0x44, 0xB2, 0xA5, 0xCF};
static const uint8_t LOW_ENTROPY_HASH17[] = {0x2C, 0xB2, 0x77, 0x85, 0xD6, 0xB7, 0x48, 0x9C, 0xFE, 0xBC, 0x80,
0x26, 0x60, 0xF4, 0x6D, 0xCE, 0x11, 0x31, 0xA2, 0x1E, 0x33, 0x0A,
0x6D, 0x2B, 0x00, 0xFA, 0x0C, 0x90, 0x95, 0x8F, 0x5C, 0x6B};
static const uint8_t LOW_ENTROPY_HASH18[] = {0xFA, 0x59, 0xC8, 0x6E, 0x94, 0xEE, 0x75, 0xC9, 0x9A, 0xB0, 0xFE,
0x89, 0x36, 0x40, 0xC9, 0x99, 0x4A, 0x3B, 0xF4, 0xAA, 0x12, 0x24,
0xA2, 0x0F, 0xF9, 0xD1, 0x08, 0xCB, 0x78, 0x19, 0xAA, 0xE5};
static const uint8_t LOW_ENTROPY_HASH19[] = {0x6E, 0x42, 0x7A, 0x4A, 0x8C, 0x61, 0x62, 0x22, 0xA1, 0x89, 0xD3,
0xA4, 0xC2, 0x19, 0xA3, 0x83, 0x53, 0xA7, 0x7A, 0x0A, 0x89, 0xE2,
0x54, 0x52, 0x62, 0x3D, 0xE7, 0xCA, 0x8C, 0xF6, 0x6A, 0x60};
static const uint8_t LOW_ENTROPY_HASH20[] = {0x20, 0x27, 0x2F, 0xBA, 0x0C, 0x99, 0xD7, 0x29, 0xF3, 0x11, 0x35,
0x89, 0x9D, 0x0E, 0x24, 0xA1, 0xC3, 0xCB, 0xDF, 0x8A, 0xF1, 0xC6,
0xFE, 0xD0, 0xD7, 0x9F, 0x92, 0xD6, 0x8F, 0x59, 0xBF, 0xE4};
static const char LOW_ENTROPY_WARNING[] = "Compromised keys detected, please regenerate.";
// E3B0C442 is the blank hash
static const uint8_t LOW_ENTROPY_HASHES[][32] = {
{0xf4, 0x7e, 0xcc, 0x17, 0xe6, 0xb4, 0xa3, 0x22, 0xec, 0xee, 0xd9, 0x08, 0x4f, 0x39, 0x63, 0xea,
0x80, 0x75, 0xe1, 0x24, 0xce, 0x05, 0x36, 0x69, 0x63, 0xb2, 0xcb, 0xc0, 0x28, 0xd3, 0x34, 0x8b},
{0x5a, 0x9e, 0xa2, 0xa6, 0x8a, 0xa6, 0x66, 0xc1, 0x5f, 0x55, 0x00, 0x64, 0xa3, 0xa6, 0xfe, 0x71,
0xc0, 0xbb, 0x82, 0xc3, 0x32, 0x3d, 0x7a, 0x7a, 0xe3, 0x6e, 0xfd, 0xdd, 0xad, 0x3a, 0x66, 0xb9},
{0xb3, 0xdf, 0x3b, 0x2e, 0x67, 0xb6, 0xd5, 0xf8, 0xdf, 0x76, 0x2c, 0x45, 0x5e, 0x2e, 0xbd, 0x16,
0xc5, 0xf8, 0x67, 0xaa, 0x15, 0xf8, 0x92, 0x0b, 0xdf, 0x5a, 0x66, 0x50, 0xac, 0x0d, 0xbb, 0x2f},
{0x3b, 0x8f, 0x86, 0x3a, 0x38, 0x1f, 0x77, 0x39, 0xa9, 0x4e, 0xef, 0x91, 0x18, 0x5a, 0x62, 0xe1,
0xaa, 0x9d, 0x36, 0xea, 0xce, 0x60, 0x35, 0x8d, 0x9d, 0x1f, 0xf4, 0xb8, 0xc9, 0x13, 0x6a, 0x5d},
{0x36, 0x7e, 0x2d, 0xe1, 0x84, 0x5f, 0x42, 0x52, 0x29, 0x11, 0x0a, 0x25, 0x64, 0x54, 0x6a, 0x6b,
0xfd, 0xb6, 0x65, 0xff, 0x15, 0x1a, 0x51, 0x71, 0x22, 0x40, 0x57, 0xf6, 0x91, 0x9b, 0x64, 0x58},
{0x16, 0x77, 0xeb, 0xa4, 0x52, 0x91, 0xfb, 0x26, 0xcf, 0x8f, 0xd7, 0xd9, 0xd1, 0x5d, 0xc4, 0x68,
0x73, 0x75, 0xed, 0xc5, 0x95, 0x58, 0xee, 0x90, 0x56, 0xd4, 0x2f, 0x31, 0x29, 0xf7, 0x8c, 0x1f},
{0x31, 0x8c, 0xa9, 0x5e, 0xed, 0x3c, 0x12, 0xbf, 0x97, 0x9c, 0x47, 0x8e, 0x98, 0x9d, 0xc2, 0x3e,
0x86, 0x23, 0x90, 0x29, 0xc8, 0xb0, 0x20, 0xf8, 0xb1, 0xb0, 0xaa, 0x19, 0x2a, 0xcf, 0x0a, 0x54},
{0xa4, 0x8a, 0x99, 0x0e, 0x51, 0xdc, 0x12, 0x20, 0xf3, 0x13, 0xf5, 0x2b, 0x3a, 0xe2, 0x43, 0x42,
0xc6, 0x52, 0x98, 0xcd, 0xbb, 0xca, 0xb1, 0x31, 0xa0, 0xd4, 0xd6, 0x30, 0xf3, 0x27, 0xfb, 0x49},
{0xd2, 0x3f, 0x13, 0x8d, 0x22, 0x04, 0x8d, 0x07, 0x59, 0x58, 0xa0, 0xf9, 0x55, 0xcf, 0x30, 0xa0,
0x2e, 0x2f, 0xca, 0x80, 0x20, 0xe4, 0xde, 0xa1, 0xad, 0xd9, 0x58, 0xb3, 0x43, 0x2b, 0x22, 0x70},
{0x40, 0x41, 0xec, 0x6a, 0xd2, 0xd6, 0x03, 0xe4, 0x9a, 0x9e, 0xbd, 0x6c, 0x0a, 0x9b, 0x75, 0xa4,
0xbc, 0xab, 0x6f, 0xa7, 0x95, 0xff, 0x2d, 0xf6, 0xe9, 0xb9, 0xab, 0x4c, 0x0c, 0x1c, 0xd0, 0x3b},
{0x22, 0x49, 0x32, 0x2b, 0x00, 0xf9, 0x22, 0xfa, 0x17, 0x02, 0xe9, 0x64, 0x82, 0xf0, 0x4d, 0x1b,
0xc7, 0x04, 0xfc, 0xdc, 0x8c, 0x5e, 0xb6, 0xd9, 0x16, 0xd6, 0x37, 0xce, 0x59, 0xaa, 0x09, 0x49},
{0x48, 0x6f, 0x1e, 0x48, 0x97, 0x88, 0x64, 0xac, 0xe8, 0xeb, 0x30, 0xa3, 0xc3, 0xe1, 0xcf, 0x97,
0x39, 0xa6, 0x55, 0x5b, 0x5f, 0xbf, 0x18, 0xb7, 0x3a, 0xdf, 0xa8, 0x75, 0xe7, 0x9d, 0xe0, 0x1e},
{0x09, 0xb4, 0xe2, 0x6d, 0x28, 0x98, 0xc9, 0x47, 0x66, 0x46, 0xbf, 0xff, 0x58, 0x17, 0x91, 0xaa,
0xc3, 0xbf, 0x4a, 0x9d, 0x0b, 0x88, 0xb1, 0xf1, 0x03, 0xdd, 0x61, 0xd7, 0xba, 0x9e, 0x64, 0x98},
{0x39, 0x39, 0x84, 0xe0, 0x22, 0x2f, 0x7d, 0x78, 0x45, 0x18, 0x72, 0xb4, 0x13, 0xd2, 0x01, 0x2f,
0x3c, 0xa1, 0xb0, 0xfe, 0x39, 0xd0, 0xf1, 0x3c, 0x72, 0xd6, 0xef, 0x54, 0xd5, 0x77, 0x22, 0xa0},
{0x0a, 0xda, 0x5f, 0xec, 0xff, 0x5c, 0xc0, 0x2e, 0x5f, 0xc4, 0x8d, 0x03, 0xe5, 0x80, 0x59, 0xd3,
0x5d, 0x49, 0x86, 0xe9, 0x8d, 0xf6, 0xf6, 0x16, 0x35, 0x3d, 0xf9, 0x9b, 0x29, 0x55, 0x9e, 0x64},
{0x08, 0x56, 0xF0, 0xD7, 0xEF, 0x77, 0xD6, 0x11, 0x1C, 0x8F, 0x95, 0x2D, 0x3C, 0xDF, 0xB1, 0x22,
0xBF, 0x60, 0x9B, 0xE5, 0xA9, 0xC0, 0x6E, 0x4B, 0x01, 0xDC, 0xD1, 0x57, 0x44, 0xB2, 0xA5, 0xCF},
{0x2C, 0xB2, 0x77, 0x85, 0xD6, 0xB7, 0x48, 0x9C, 0xFE, 0xBC, 0x80, 0x26, 0x60, 0xF4, 0x6D, 0xCE,
0x11, 0x31, 0xA2, 0x1E, 0x33, 0x0A, 0x6D, 0x2B, 0x00, 0xFA, 0x0C, 0x90, 0x95, 0x8F, 0x5C, 0x6B},
{0xFA, 0x59, 0xC8, 0x6E, 0x94, 0xEE, 0x75, 0xC9, 0x9A, 0xB0, 0xFE, 0x89, 0x36, 0x40, 0xC9, 0x99,
0x4A, 0x3B, 0xF4, 0xAA, 0x12, 0x24, 0xA2, 0x0F, 0xF9, 0xD1, 0x08, 0xCB, 0x78, 0x19, 0xAA, 0xE5},
{0x6E, 0x42, 0x7A, 0x4A, 0x8C, 0x61, 0x62, 0x22, 0xA1, 0x89, 0xD3, 0xA4, 0xC2, 0x19, 0xA3, 0x83,
0x53, 0xA7, 0x7A, 0x0A, 0x89, 0xE2, 0x54, 0x52, 0x62, 0x3D, 0xE7, 0xCA, 0x8C, 0xF6, 0x6A, 0x60},
{0x20, 0x27, 0x2F, 0xBA, 0x0C, 0x99, 0xD7, 0x29, 0xF3, 0x11, 0x35, 0x89, 0x9D, 0x0E, 0x24, 0xA1,
0xC3, 0xCB, 0xDF, 0x8A, 0xF1, 0xC6, 0xFE, 0xD0, 0xD7, 0x9F, 0x92, 0xD6, 0x8F, 0x59, 0xBF, 0xE4},
{0x91, 0x70, 0xb4, 0x7c, 0xfb, 0xff, 0xa0, 0x59, 0x6a, 0x25, 0x1c, 0xa9, 0x9e, 0xe9, 0x43, 0x81,
0x5d, 0x74, 0xb1, 0xb1, 0x09, 0x28, 0x00, 0x4a, 0xaf, 0xe3, 0xfc, 0xa9, 0x4e, 0x27, 0x76, 0x4c},
{0x85, 0xfe, 0x7c, 0xec, 0xb6, 0x78, 0x74, 0xc3, 0xec, 0xe1, 0x32, 0x7f, 0xb0, 0xb7, 0x02, 0x74,
0xf9, 0x23, 0xd8, 0xe7, 0xfa, 0x14, 0xe6, 0xee, 0x66, 0x44, 0xb1, 0x8c, 0xa5, 0x2f, 0x7e, 0xd2},
{0x8e, 0x66, 0x65, 0x7b, 0x3b, 0x6f, 0x7e, 0xcc, 0x57, 0xb4, 0x57, 0xea, 0xcc, 0x83, 0xf5, 0xaa,
0xf7, 0x65, 0xa3, 0xce, 0x93, 0x72, 0x13, 0xc1, 0xb6, 0x46, 0x7b, 0x29, 0x45, 0xb5, 0xc8, 0x93},
{0xcc, 0x11, 0xfb, 0x1a, 0xab, 0xa1, 0x31, 0x87, 0x6a, 0xc6, 0xde, 0x88, 0x87, 0xa9, 0xb9, 0x59,
0x37, 0x82, 0x8d, 0xb2, 0xcc, 0xd8, 0x97, 0x40, 0x9a, 0x5c, 0x8f, 0x40, 0x55, 0xcb, 0x4c, 0x3e}};
static const char LOW_ENTROPY_WARNING[] = "Compromised keys were detected and regenerated.";
#endif
/*
DeviceState versions used to be defined in the .proto file but really only this function cares. So changed to a

View File

@@ -192,12 +192,6 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
size_t PhoneAPI::getFromRadio(uint8_t *buf)
{
if (!available()) {
return 0;
}
// In case we send a FromRadio packet
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
// Respond to heartbeat by sending queue status
if (heartbeatReceived) {
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
@@ -209,6 +203,12 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
return numbytes;
}
if (!available()) {
return 0;
}
// In case we send a FromRadio packet
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
// Advance states as needed
switch (state) {
case STATE_SEND_NOTHING:

View File

@@ -170,11 +170,10 @@ const RegionInfo regions[] = {
*/
RDEF(KZ_433, 433.075f, 434.775f, 100, 0, 10, true, false, false), RDEF(KZ_863, 863.0f, 868.0f, 100, 0, 30, true, false, true),
/*
Nepal
865MHz to 868MHz frequency band for IoT (Internet of Things), M2M (Machine-to-Machine), and smart metering use, specifically in non-cellular mode.
https://www.nta.gov.np/uploads/contents/Radio-Frequency-Policy-2080-English.pdf
865MHz to 868MHz frequency band for IoT (Internet of Things), M2M (Machine-to-Machine), and smart metering use,
specifically in non-cellular mode. https://www.nta.gov.np/uploads/contents/Radio-Frequency-Policy-2080-English.pdf
*/
RDEF(NP_865, 865.0f, 868.0f, 100, 0, 30, true, false, false),
@@ -336,8 +335,9 @@ uint32_t RadioInterface::getTxDelayMsecWeighted(float snr)
void printPacket(const char *prefix, const meshtastic_MeshPacket *p)
{
#if defined(DEBUG_PORT) && !defined(DEBUG_MUTE)
std::string out = DEBUG_PORT.mt_sprintf("%s (id=0x%08x fr=0x%08x to=0x%08x, WantAck=%d, HopLim=%d Ch=0x%x", prefix, p->id,
p->from, p->to, p->want_ack, p->hop_limit, p->channel);
std::string out =
DEBUG_PORT.mt_sprintf("%s (id=0x%08x fr=0x%08x to=0x%08x, transport = %u, WantAck=%d, HopLim=%d Ch=0x%x", prefix, p->id,
p->from, p->to, p->transport_mechanism, p->want_ack, p->hop_limit, p->channel);
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
auto &s = p->decoded;
@@ -666,8 +666,10 @@ void RadioInterface::limitPower(int8_t loraMaxPower)
void RadioInterface::deliverToReceiver(meshtastic_MeshPacket *p)
{
if (router)
if (router) {
p->transport_mechanism = meshtastic_MeshPacket_TransportMechanism_TRANSPORT_LORA;
router->enqueueReceivedMessage(p);
}
}
/***

View File

@@ -523,8 +523,10 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
// is not in the local nodedb
// First, only PKC encrypt packets we are originating
if (isFromUs(p) &&
// Don't use PKC with simulator
radioType != SIM_RADIO &&
#if ARCH_PORTDUINO
// Sim radio via the cli flag skips PKC
!portduino_config.force_simradio &&
#endif
// 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
@@ -549,20 +551,6 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
numbytes += MESHTASTIC_PKC_OVERHEAD;
p->channel = 0;
p->pki_encrypted = true;
// warn the user about a low entropy key
if (nodeDB->keyIsLowEntropy) {
LOG_WARN(LOW_ENTROPY_WARNING);
if (!nodeDB->hasWarned) {
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
cn->which_payload_variant = meshtastic_ClientNotification_low_entropy_key_tag;
cn->level = meshtastic_LogRecord_Level_WARNING;
cn->time = getValidTime(RTCQualityFromNet);
sprintf(cn->message, LOW_ENTROPY_WARNING);
service->sendClientNotification(cn);
nodeDB->hasWarned = true;
}
}
} else {
if (p->pki_encrypted == true) {
// Client specifically requested PKI encryption
@@ -666,7 +654,8 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
}
// call modules here
if (!skipHandle) {
// If this could be a spoofed packet, don't let the modules see it.
if (!skipHandle && p->from != nodeDB->getNodeNum()) {
MeshModule::callModules(*p, src);
#if !MESHTASTIC_EXCLUDE_MQTT
@@ -680,6 +669,8 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
!isFromUs(p) && mqtt)
mqtt->onSend(*p_encrypted, *p, p->channel);
#endif
} else if (p->from == nodeDB->getNodeNum() && !skipHandle) {
MeshModule::callModules(*p, src, ROUTING_MODULE);
}
packetPool.release(p_encrypted); // Release the encrypted packet

View File

@@ -59,6 +59,7 @@ bool PacketAPI::receivePacket(void)
switch (mr->which_payload_variant) {
case meshtastic_ToRadio_packet_tag: {
meshtastic_MeshPacket *mp = &mr->packet;
mp->transport_mechanism = meshtastic_MeshPacket_TransportMechanism_TRANSPORT_API;
printPacket("PACKET FROM QUEUE", mp);
service->handleToRadio(*mp);
break;
@@ -70,7 +71,7 @@ bool PacketAPI::receivePacket(void)
break;
}
case meshtastic_ToRadio_heartbeat_tag:
if (mr->heartbeat.dummy_field == 1) {
if (mr->heartbeat.nonce == 1) {
if (nodeInfoModule) {
LOG_INFO("Broadcasting nodeinfo ping");
nodeInfoModule->sendOurNodeInfo(NODENUM_BROADCAST, true, 0, true);

View File

@@ -17,7 +17,10 @@ void initApiServer(int port)
}
void deInitApiServer()
{
delete apiPort;
if (apiPort) {
delete apiPort;
apiPort = nullptr;
}
}
WiFiServerAPI::WiFiServerAPI(WiFiClient &_client) : ServerAPI(_client)

View File

@@ -207,10 +207,10 @@ typedef enum _meshtastic_Config_DisplayConfig_OledType {
meshtastic_Config_DisplayConfig_OledType_OLED_SSD1306 = 1,
/* Default / Autodetect */
meshtastic_Config_DisplayConfig_OledType_OLED_SH1106 = 2,
/* Can not be auto detected but set by proto. Used for 128x128 screens */
meshtastic_Config_DisplayConfig_OledType_OLED_SH1107 = 3,
/* Can not be auto detected but set by proto. Used for 128x64 screens */
meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_64 = 4
meshtastic_Config_DisplayConfig_OledType_OLED_SH1107 = 3,
/* Can not be auto detected but set by proto. Used for 128x128 screens */
meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_128 = 4
} meshtastic_Config_DisplayConfig_OledType;
typedef enum _meshtastic_Config_DisplayConfig_DisplayMode {
@@ -682,8 +682,8 @@ extern "C" {
#define _meshtastic_Config_DisplayConfig_DisplayUnits_ARRAYSIZE ((meshtastic_Config_DisplayConfig_DisplayUnits)(meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL+1))
#define _meshtastic_Config_DisplayConfig_OledType_MIN meshtastic_Config_DisplayConfig_OledType_OLED_AUTO
#define _meshtastic_Config_DisplayConfig_OledType_MAX meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_64
#define _meshtastic_Config_DisplayConfig_OledType_ARRAYSIZE ((meshtastic_Config_DisplayConfig_OledType)(meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_64+1))
#define _meshtastic_Config_DisplayConfig_OledType_MAX meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_128
#define _meshtastic_Config_DisplayConfig_OledType_ARRAYSIZE ((meshtastic_Config_DisplayConfig_OledType)(meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_128+1))
#define _meshtastic_Config_DisplayConfig_DisplayMode_MIN meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT
#define _meshtastic_Config_DisplayConfig_DisplayMode_MAX meshtastic_Config_DisplayConfig_DisplayMode_COLOR

View File

@@ -362,7 +362,7 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg;
#define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size
#define meshtastic_BackupPreferences_size 2271
#define meshtastic_ChannelFile_size 718
#define meshtastic_DeviceState_size 1728
#define meshtastic_DeviceState_size 1737
#define meshtastic_NodeInfoLite_size 196
#define meshtastic_PositionLite_size 28
#define meshtastic_UserLite_size 98

View File

@@ -119,6 +119,8 @@ PB_BIND(meshtastic_ChunkedPayloadResponse, meshtastic_ChunkedPayloadResponse, AU

View File

@@ -270,6 +270,8 @@ typedef enum _meshtastic_HardwareModel {
/* MeshSolar is an integrated power management and communication solution designed for outdoor low-power devices.
https://heltec.org/project/meshsolar/ */
meshtastic_HardwareModel_HELTEC_MESH_SOLAR = 108,
/* Lilygo T-Echo Lite */
meshtastic_HardwareModel_T_ECHO_LITE = 109,
/* ------------------------------------------------------------------------------------------------------------------------------------------
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.
------------------------------------------------------------------------------------------------------------------------------------------ */
@@ -509,6 +511,26 @@ typedef enum _meshtastic_MeshPacket_Delayed {
meshtastic_MeshPacket_Delayed_DELAYED_DIRECT = 2
} meshtastic_MeshPacket_Delayed;
/* Enum to identify which transport mechanism this packet arrived over */
typedef enum _meshtastic_MeshPacket_TransportMechanism {
/* The default case is that the node generated a packet itself */
meshtastic_MeshPacket_TransportMechanism_TRANSPORT_INTERNAL = 0,
/* Arrived via the primary LoRa radio */
meshtastic_MeshPacket_TransportMechanism_TRANSPORT_LORA = 1,
/* Arrived via a secondary LoRa radio */
meshtastic_MeshPacket_TransportMechanism_TRANSPORT_LORA_ALT1 = 2,
/* Arrived via a tertiary LoRa radio */
meshtastic_MeshPacket_TransportMechanism_TRANSPORT_LORA_ALT2 = 3,
/* Arrived via a quaternary LoRa radio */
meshtastic_MeshPacket_TransportMechanism_TRANSPORT_LORA_ALT3 = 4,
/* Arrived via an MQTT connection */
meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MQTT = 5,
/* Arrived via Multicast UDP */
meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MULTICAST_UDP = 6,
/* Arrived via API connection */
meshtastic_MeshPacket_TransportMechanism_TRANSPORT_API = 7
} meshtastic_MeshPacket_TransportMechanism;
/* Log levels, chosen to match python logging conventions. */
typedef enum _meshtastic_LogRecord_Level {
/* Log levels, chosen to match python logging conventions. */
@@ -863,6 +885,8 @@ typedef struct _meshtastic_MeshPacket {
Timestamp after which this packet may be sent.
Set by the firmware internally, clients are not supposed to set this. */
uint32_t tx_after;
/* Indicates which transport mechanism this packet arrived over */
meshtastic_MeshPacket_TransportMechanism transport_mechanism;
} meshtastic_MeshPacket;
/* The bluetooth to device link:
@@ -1149,7 +1173,8 @@ typedef struct _meshtastic_FromRadio {
/* A heartbeat message is sent to the node from the client to keep the connection alive.
This is currently only needed to keep serial connections alive, but can be used by any PhoneAPI. */
typedef struct _meshtastic_Heartbeat {
char dummy_field;
/* The nonce of the heartbeat message */
uint32_t nonce;
} meshtastic_Heartbeat;
/* Packets/commands to the radio will be written (reliably) to the toRadio characteristic.
@@ -1267,6 +1292,10 @@ extern "C" {
#define _meshtastic_MeshPacket_Delayed_MAX meshtastic_MeshPacket_Delayed_DELAYED_DIRECT
#define _meshtastic_MeshPacket_Delayed_ARRAYSIZE ((meshtastic_MeshPacket_Delayed)(meshtastic_MeshPacket_Delayed_DELAYED_DIRECT+1))
#define _meshtastic_MeshPacket_TransportMechanism_MIN meshtastic_MeshPacket_TransportMechanism_TRANSPORT_INTERNAL
#define _meshtastic_MeshPacket_TransportMechanism_MAX meshtastic_MeshPacket_TransportMechanism_TRANSPORT_API
#define _meshtastic_MeshPacket_TransportMechanism_ARRAYSIZE ((meshtastic_MeshPacket_TransportMechanism)(meshtastic_MeshPacket_TransportMechanism_TRANSPORT_API+1))
#define _meshtastic_LogRecord_Level_MIN meshtastic_LogRecord_Level_UNSET
#define _meshtastic_LogRecord_Level_MAX meshtastic_LogRecord_Level_CRITICAL
#define _meshtastic_LogRecord_Level_ARRAYSIZE ((meshtastic_LogRecord_Level)(meshtastic_LogRecord_Level_CRITICAL+1))
@@ -1287,6 +1316,7 @@ extern "C" {
#define meshtastic_MeshPacket_priority_ENUMTYPE meshtastic_MeshPacket_Priority
#define meshtastic_MeshPacket_delayed_ENUMTYPE meshtastic_MeshPacket_Delayed
#define meshtastic_MeshPacket_transport_mechanism_ENUMTYPE meshtastic_MeshPacket_TransportMechanism
#define meshtastic_MyNodeInfo_firmware_edition_ENUMTYPE meshtastic_FirmwareEdition
@@ -1326,7 +1356,7 @@ extern "C" {
#define meshtastic_KeyVerification_init_default {0, {0, {0}}, {0, {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, 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, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN}
#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, 0, 0}
#define meshtastic_MyNodeInfo_init_default {0, 0, 0, {0, {0}}, "", _meshtastic_FirmwareEdition_MIN, 0}
#define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN}
@@ -1357,7 +1387,7 @@ extern "C" {
#define meshtastic_KeyVerification_init_zero {0, {0, {0}}, {0, {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, 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, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN}
#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, 0, 0}
#define meshtastic_MyNodeInfo_init_zero {0, 0, 0, {0, {0}}, "", _meshtastic_FirmwareEdition_MIN, 0}
#define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN}
@@ -1465,6 +1495,7 @@ extern "C" {
#define meshtastic_MeshPacket_next_hop_tag 18
#define meshtastic_MeshPacket_relay_node_tag 19
#define meshtastic_MeshPacket_tx_after_tag 20
#define meshtastic_MeshPacket_transport_mechanism_tag 21
#define meshtastic_NodeInfo_num_tag 1
#define meshtastic_NodeInfo_user_tag 2
#define meshtastic_NodeInfo_position_tag 3
@@ -1551,6 +1582,7 @@ extern "C" {
#define meshtastic_FromRadio_fileInfo_tag 15
#define meshtastic_FromRadio_clientNotification_tag 16
#define meshtastic_FromRadio_deviceuiConfig_tag 17
#define meshtastic_Heartbeat_nonce_tag 1
#define meshtastic_ToRadio_packet_tag 1
#define meshtastic_ToRadio_want_config_id_tag 3
#define meshtastic_ToRadio_disconnect_tag 4
@@ -1687,7 +1719,8 @@ X(a, STATIC, SINGULAR, BYTES, public_key, 16) \
X(a, STATIC, SINGULAR, BOOL, pki_encrypted, 17) \
X(a, STATIC, SINGULAR, UINT32, next_hop, 18) \
X(a, STATIC, SINGULAR, UINT32, relay_node, 19) \
X(a, STATIC, SINGULAR, UINT32, tx_after, 20)
X(a, STATIC, SINGULAR, UINT32, tx_after, 20) \
X(a, STATIC, SINGULAR, UENUM, transport_mechanism, 21)
#define meshtastic_MeshPacket_CALLBACK NULL
#define meshtastic_MeshPacket_DEFAULT NULL
#define meshtastic_MeshPacket_payload_variant_decoded_MSGTYPE meshtastic_Data
@@ -1882,7 +1915,7 @@ X(a, STATIC, SINGULAR, UINT32, excluded_modules, 12)
#define meshtastic_DeviceMetadata_DEFAULT NULL
#define meshtastic_Heartbeat_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, nonce, 1)
#define meshtastic_Heartbeat_CALLBACK NULL
#define meshtastic_Heartbeat_DEFAULT NULL
@@ -1992,14 +2025,14 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
#define meshtastic_DuplicatedPublicKey_size 0
#define meshtastic_FileInfo_size 236
#define meshtastic_FromRadio_size 510
#define meshtastic_Heartbeat_size 0
#define meshtastic_Heartbeat_size 6
#define meshtastic_KeyVerificationFinal_size 65
#define meshtastic_KeyVerificationNumberInform_size 58
#define meshtastic_KeyVerificationNumberRequest_size 52
#define meshtastic_KeyVerification_size 79
#define meshtastic_LogRecord_size 426
#define meshtastic_LowEntropyKey_size 0
#define meshtastic_MeshPacket_size 378
#define meshtastic_MeshPacket_size 381
#define meshtastic_MqttClientProxyMessage_size 501
#define meshtastic_MyNodeInfo_size 83
#define meshtastic_NeighborInfo_size 258

View File

@@ -99,7 +99,9 @@ typedef enum _meshtastic_TelemetrySensorType {
/* Sensirion SFA30 Formaldehyde sensor */
meshtastic_TelemetrySensorType_SFA30 = 42,
/* SEN5X PM SENSORS */
meshtastic_TelemetrySensorType_SEN5X = 43
meshtastic_TelemetrySensorType_SEN5X = 43,
/* TSL2561 light sensor */
meshtastic_TelemetrySensorType_TSL2561 = 44
} meshtastic_TelemetrySensorType;
/* Struct definitions */
@@ -434,8 +436,8 @@ extern "C" {
/* Helper constants for enums */
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_SEN5X
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_SEN5X+1))
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_TSL2561
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_TSL2561+1))

View File

@@ -50,6 +50,7 @@ class UdpMulticastHandler final
LOG_DEBUG("UDP broadcast from: %s, len=%u", packet.remoteIP().toString().c_str(), packetLength);
#endif
meshtastic_MeshPacket mp;
mp.transport_mechanism = meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MULTICAST_UDP;
LOG_DEBUG("Decoding MeshPacket from UDP len=%u", packetLength);
bool isPacketDecoded = pb_decode_from_bytes(packet.data(), packetLength, &meshtastic_MeshPacket_msg, &mp);
if (isPacketDecoded && router && mp.which_payload_variant == meshtastic_MeshPacket_encrypted_tag) {
@@ -78,6 +79,9 @@ class UdpMulticastHandler final
return false;
}
#endif
if (mp->transport_mechanism == meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MULTICAST_UDP) {
LOG_ERROR("Attempt to send UDP sourced packet over UDP");
}
LOG_DEBUG("Broadcasting packet over UDP (id=%u)", mp->id);
uint8_t buffer[meshtastic_MeshPacket_size];
size_t encodedLength = pb_encode_to_bytes(buffer, sizeof(buffer), &meshtastic_MeshPacket_msg, mp);

View File

@@ -727,7 +727,7 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
}
#endif
config.lora = c.payload_variant.lora;
// If we're setting region for the first time, init the region
// If we're setting region for the first time, init the region and regenerate the keys
if (isRegionUnset && config.lora.region > meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
if (!owner.is_licensed) {
bool keygenSuccess = false;
@@ -772,8 +772,7 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
if (config.security.private_key.size != 32) {
crypto->generateKeyPair(config.security.public_key.bytes, config.security.private_key.bytes);
} else if (config.security.public_key.size != 32) {
// We check for a potentially valid private key, and a blank public key, and regen the public key if needed.
} else {
if (crypto->regeneratePublicKey(config.security.public_key.bytes, config.security.private_key.bytes)) {
config.security.public_key.size = 32;
}

View File

@@ -78,16 +78,15 @@ void CannedMessageModule::LaunchWithDestination(NodeNum newDest, uint8_t newChan
lastDestSet = true;
// Rest of function unchanged...
// Always select the first real canned message on activation
int firstRealMsgIdx = 0;
// Upon activation, highlight "[Select Destination]"
int selectDestination = 0;
for (int i = 0; i < messagesCount; ++i) {
if (strcmp(messages[i], "[Select Destination]") != 0 && strcmp(messages[i], "[Exit]") != 0 &&
strcmp(messages[i], "[---- Free Text ----]") != 0) {
firstRealMsgIdx = i;
if (strcmp(messages[i], "[Select Destination]") == 0) {
selectDestination = i;
break;
}
}
currentMessageIndex = firstRealMsgIdx;
currentMessageIndex = selectDestination;
// This triggers the canned message list
runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
@@ -999,17 +998,16 @@ int32_t CannedMessageModule::runOnce()
this->notifyObservers(&e);
return 2000;
}
// Always highlight the first real canned message when entering the message list
// Highlight [Select Destination] initially when entering the message list
else if ((this->runState != CANNED_MESSAGE_RUN_STATE_FREETEXT) && (this->currentMessageIndex == -1)) {
int firstRealMsgIdx = 0;
int selectDestination = 0;
for (int i = 0; i < this->messagesCount; ++i) {
if (strcmp(this->messages[i], "[Select Destination]") != 0 && strcmp(this->messages[i], "[Exit]") != 0 &&
strcmp(this->messages[i], "[---- Free Text ----]") != 0) {
firstRealMsgIdx = i;
if (strcmp(this->messages[i], "[Select Destination]") == 0) {
selectDestination = i;
break;
}
}
this->currentMessageIndex = firstRealMsgIdx;
this->currentMessageIndex = selectDestination;
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_UP) {

View File

@@ -14,6 +14,10 @@ bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
{
auto p = *pptr;
if (mp.from == nodeDB->getNodeNum()) {
LOG_WARN("Ignoring packet supposed to be from our own node: %08x", mp.from);
return false;
}
if (p.is_licensed != owner.is_licensed) {
LOG_WARN("Invalid nodeInfo detected, is_licensed mismatch!");
return true;

View File

@@ -73,7 +73,7 @@ uint8_t RoutingModule::getHopLimitForResponse(uint8_t hopStart, uint8_t hopLimit
return Default::getConfiguredOrDefaultHopLimit(config.lora.hop_limit); // Use the default hop limit
}
RoutingModule::RoutingModule() : ProtobufModule("routing", meshtastic_PortNum_ROUTING_APP, &meshtastic_Routing_msg)
RoutingModule::RoutingModule() : ProtobufModule(ROUTING_MODULE, meshtastic_PortNum_ROUTING_APP, &meshtastic_Routing_msg)
{
isPromiscuous = true;

View File

@@ -2,6 +2,8 @@
#include "Channels.h"
#include "ProtobufModule.h"
static const char *ROUTING_MODULE = "routing";
/**
* Routing module for router control messages
*/

View File

@@ -60,7 +60,8 @@
SerialModule *serialModule;
SerialModuleRadio *serialModuleRadio;
#if defined(TTGO_T_ECHO) || defined(CANARYONE) || defined(MESHLINK) || defined(ELECROW_ThinkNode_M1)
#if defined(TTGO_T_ECHO) || defined(T_ECHO_LITE) || defined(CANARYONE) || defined(MESHLINK) || defined(ELECROW_ThinkNode_M1) || \
defined(ELECROW_ThinkNode_M5)
SerialModule::SerialModule() : StreamAPI(&Serial), concurrency::OSThread("Serial") {}
static Print *serialPrint = &Serial;
#elif defined(CONFIG_IDF_TARGET_ESP32C6)
@@ -178,7 +179,8 @@ int32_t SerialModule::runOnce()
Serial.begin(baud);
Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
}
#elif !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1)
#elif !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \
!defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
#ifdef ARCH_RP2040
Serial2.setFIFOSize(RX_BUFFER);
@@ -234,7 +236,8 @@ int32_t SerialModule::runOnce()
}
}
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1)
#if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \
!defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
else if ((moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85)) {
processWXSerial();
@@ -493,8 +496,8 @@ ParsedLine parseLine(const char *line)
*/
void SerialModule::processWXSerial()
{
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(MESHLINK) && \
!defined(ELECROW_ThinkNode_M1)
#if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && \
!defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
static unsigned int lastAveraged = 0;
static unsigned int averageIntervalMillis = 300000; // 5 minutes hard coded.
static double dir_sum_sin = 0;

View File

@@ -112,9 +112,8 @@ bool NAU7802Sensor::saveCalibrationData()
} else {
okay = true;
}
spiLock->lock();
// Note: SafeFile::close() already acquires the lock and releases it internally
okay &= file.close();
spiLock->unlock();
return okay;
}

View File

@@ -602,7 +602,7 @@ void TraceRouteModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state
int start = 0;
int newlinePos = resultText.indexOf('\n', start);
while (newlinePos != -1 || start < resultText.length()) {
while (newlinePos != -1 || start < static_cast<int>(resultText.length())) {
String segment;
if (newlinePos != -1) {
segment = resultText.substring(start, newlinePos);
@@ -624,7 +624,7 @@ void TraceRouteModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state
int lastGoodBreak = -1;
bool lineComplete = false;
for (int i = 0; i < remaining.length(); i++) {
for (int i = 0; i < static_cast<int>(remaining.length()); i++) {
char ch = remaining.charAt(i);
String testLine = tempLine + ch;

View File

@@ -95,6 +95,7 @@ inline void onReceiveProto(char *topic, byte *payload, size_t length)
p->hop_start = e.packet->hop_start;
p->want_ack = e.packet->want_ack;
p->via_mqtt = true; // Mark that the packet was received via MQTT
p->transport_mechanism = meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MQTT;
p->which_payload_variant = e.packet->which_payload_variant;
memcpy(&p->decoded, &e.packet->decoded, std::max(sizeof(p->decoded), sizeof(p->encrypted)));
@@ -278,6 +279,8 @@ struct PubSubConfig {
// Defaults
static constexpr uint16_t defaultPort = 1883;
static constexpr uint16_t defaultPortTls = 8883;
uint16_t serverPort = defaultPort;
String serverAddr = default_mqtt_address;
const char *mqttUsername = default_mqtt_username;
@@ -640,7 +643,7 @@ bool MQTT::isValidConfig(const meshtastic_ModuleConfig_MQTTConfig &config, MQTTC
}
const bool defaultServer = isDefaultServer(parsed.serverAddr);
if (defaultServer && parsed.serverPort != PubSubConfig::defaultPort) {
if (defaultServer && !IS_ONE_OF(parsed.serverPort, PubSubConfig::defaultPort, PubSubConfig::defaultPortTls)) {
const char *warning = "Invalid MQTT config: default server address must not have a port specified";
LOG_ERROR(warning);
#if !IS_RUNNING_TESTS

View File

@@ -223,9 +223,12 @@ void NimbleBluetooth::deinit()
LOG_INFO("Disable bluetooth until reboot");
#ifdef BLE_LED
#ifdef BLE_LED_INVERTED
digitalWrite(BLE_LED, HIGH);
#else
digitalWrite(BLE_LED, LOW);
#endif
#endif
NimBLEDevice::deinit();
#endif
}

View File

@@ -146,6 +146,8 @@
#define HW_VENDOR meshtastic_HardwareModel_EBYTE_ESP32_S3
#elif defined(ELECROW_ThinkNode_M2)
#define HW_VENDOR meshtastic_HardwareModel_THINKNODE_M2
#elif defined(ELECROW_ThinkNode_M5)
#define HW_VENDOR meshtastic_HardwareModel_THINKNODE_M5
#elif defined(ESP32_S3_PICO)
#define HW_VENDOR meshtastic_HardwareModel_ESP32_S3_PICO
#elif defined(SENSELORA_S3)

View File

@@ -53,10 +53,15 @@
#define HW_VENDOR meshtastic_HardwareModel_WISMESH_TAG
#elif defined(GAT562_MESH_TRIAL_TRACKER)
#define HW_VENDOR meshtastic_HardwareModel_GAT562_MESH_TRIAL_TRACKER
#elif defined(NOMADSTAR_METEOR_PRO)
#define HW_VENDOR meshtastic_HardwareModel_NOMADSTAR_METEOR_PRO
// MAke sure all custom RAK4630 boards are defined before the generic RAK4630
#elif defined(RAK4630)
#define HW_VENDOR meshtastic_HardwareModel_RAK4631
#elif defined(TTGO_T_ECHO)
#define HW_VENDOR meshtastic_HardwareModel_T_ECHO
#elif defined(T_ECHO_LITE)
#define HW_VENDOR meshtastic_HardwareModel_T_ECHO_LITE
#elif defined(ELECROW_ThinkNode_M1)
#define HW_VENDOR meshtastic_HardwareModel_THINKNODE_M1
#elif defined(NANO_G2_ULTRA)
@@ -89,8 +94,6 @@
#define HW_VENDOR meshtastic_HardwareModel_SEEED_SOLAR_NODE
#elif defined(HELTEC_MESH_POCKET)
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_POCKET
#elif defined(NOMADSTAR_METEOR_PRO)
#define HW_VENDOR meshtastic_HardwareModel_NOMADSTAR_METEOR_PRO
#elif defined(SEEED_WIO_TRACKER_L1_EINK)
#define HW_VENDOR meshtastic_HardwareModel_SEEED_WIO_TRACKER_L1_EINK
#elif defined(SEEED_WIO_TRACKER_L1)

View File

@@ -282,10 +282,14 @@ void cpuDeepSleep(uint32_t msecToWake)
#if SPI_INTERFACES_COUNT > 1
SPI1.end();
#endif
// This may cause crashes as debug messages continue to flow.
Serial.end();
if (Serial) // Another check in case of disabled default serial, does nothing bad
Serial.end(); // This may cause crashes as debug messages continue to flow.
// This causes troubles with waking up on nrf52 (on pro-micro in particular):
// we have no Serial1 in use on nrf52, check Serial and GPS modules.
#ifdef PIN_SERIAL1_RX
Serial1.end();
if (Serial1) // A straightforward solution to the wake from deepsleep problem
Serial1.end();
#endif
setBluetoothEnable(false);
@@ -362,6 +366,7 @@ void cpuDeepSleep(uint32_t msecToWake)
// Resume on user button press
// https://github.com/lyusupov/SoftRF/blob/81c519ca75693b696752235d559e881f2e0511ee/software/firmware/source/SoftRF/src/platform/nRF52.cpp#L1738
constexpr uint32_t DFU_MAGIC_SKIP = 0x6d;
sd_power_gpregret_clr(0, 0xFF); // Clear the register before setting a new values in it for stability reasons
sd_power_gpregret_set(0, DFU_MAGIC_SKIP); // Equivalent NRF_POWER->GPREGRET = DFU_MAGIC_SKIP
// FIXME, use system off mode with ram retention for key state?
@@ -378,6 +383,12 @@ void cpuDeepSleep(uint32_t msecToWake)
nrf_gpio_cfg_sense_set(PIN_BUTTON2, sense1);
#endif
#ifdef PROMICRO_DIY_TCXO
nrf_gpio_cfg_input(BUTTON_PIN, NRF_GPIO_PIN_PULLUP); // Enable internal pull-up on the button pin
nrf_gpio_pin_sense_t sense = NRF_GPIO_PIN_SENSE_LOW; // Configure SENSE signal on low edge
nrf_gpio_cfg_sense_set(BUTTON_PIN, sense); // Apply SENSE to wake up the device from the deep sleep
#endif
auto ok = sd_power_system_off();
if (ok != NRF_SUCCESS) {
LOG_ERROR("FIXME: Ignoring soft device (EasyDMA pending?) and forcing system-off!");

View File

@@ -29,11 +29,11 @@
std::map<configNames, int> settingsMap;
std::map<configNames, std::string> settingsStrings;
portduino_config_struct portduino_config;
std::ofstream traceFile;
Ch341Hal *ch341Hal = nullptr;
char *configPath = nullptr;
char *optionMac = nullptr;
bool forceSimulated = false;
bool verboseEnabled = false;
const char *argp_program_version = optstr(APP_VERSION);
@@ -66,7 +66,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
configPath = arg;
break;
case 's':
forceSimulated = true;
portduino_config.force_simradio = true;
break;
case 'h':
optionMac = arg;
@@ -189,7 +189,7 @@ void portduinoSetup()
YAML::Node yamlConfig;
if (forceSimulated == true) {
if (portduino_config.force_simradio == true) {
settingsMap[use_simradio] = true;
} else if (configPath != nullptr) {
if (loadConfig(configPath)) {
@@ -553,6 +553,48 @@ bool loadConfig(const char *configPath)
}
}
}
if (yamlConfig["Lora"]["rfswitch_table"]) {
portduino_config.has_rfswitch_table = true;
portduino_config.rfswitch_table[0].mode = LR11x0::MODE_STBY;
portduino_config.rfswitch_table[1].mode = LR11x0::MODE_RX;
portduino_config.rfswitch_table[2].mode = LR11x0::MODE_TX;
portduino_config.rfswitch_table[3].mode = LR11x0::MODE_TX_HP;
portduino_config.rfswitch_table[4].mode = LR11x0::MODE_TX_HF;
portduino_config.rfswitch_table[5].mode = LR11x0::MODE_GNSS;
portduino_config.rfswitch_table[6].mode = LR11x0::MODE_WIFI;
portduino_config.rfswitch_table[7] = END_OF_MODE_TABLE;
for (int i = 0; i < 5; i++) {
// set up the pin array first
if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as<std::string>("") == "DIO5")
portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO5;
if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as<std::string>("") == "DIO6")
portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO6;
if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as<std::string>("") == "DIO7")
portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO7;
if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as<std::string>("") == "DIO8")
portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO8;
if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as<std::string>("") == "DIO10")
portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO10;
// now fill in the table
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_STBY"][i].as<std::string>("") == "HIGH")
portduino_config.rfswitch_table[0].values[i] = HIGH;
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_RX"][i].as<std::string>("") == "HIGH")
portduino_config.rfswitch_table[1].values[i] = HIGH;
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_TX"][i].as<std::string>("") == "HIGH")
portduino_config.rfswitch_table[2].values[i] = HIGH;
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_TX_HP"][i].as<std::string>("") == "HIGH")
portduino_config.rfswitch_table[3].values[i] = HIGH;
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_TX_HF"][i].as<std::string>("") == "HIGH")
portduino_config.rfswitch_table[4].values[i] = HIGH;
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_GNSS"][i].as<std::string>("") == "HIGH")
portduino_config.rfswitch_table[5].values[i] = HIGH;
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_WIFI"][i].as<std::string>("") == "HIGH")
portduino_config.rfswitch_table[6].values[i] = HIGH;
}
}
}
if (yamlConfig["GPIO"]) {
settingsMap[userButtonPin] = yamlConfig["GPIO"]["User"].as<int>(RADIOLIB_NC);

View File

@@ -3,6 +3,8 @@
#include <map>
#include <unordered_map>
#include "LR11x0Interface.h"
#include "Module.h"
#include "platform/portduino/USBHal.h"
// Product strings for auto-configuration
@@ -126,4 +128,11 @@ bool loadConfig(const char *configPath);
static bool ends_with(std::string_view str, std::string_view suffix);
void getMacAddr(uint8_t *dmac);
bool MAC_from_string(std::string mac_str, uint8_t *dmac);
std::string exec(const char *cmd);
std::string exec(const char *cmd);
extern struct portduino_config_struct {
bool has_rfswitch_table = false;
uint32_t rfswitch_dio_pins[5] = {RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC};
Module::RfSwitchMode_t rfswitch_table[8];
bool force_simradio = false;
} portduino_config;

View File

@@ -0,0 +1,28 @@
// Need this file for ESP32-S3
// No need to modify this file, changes to pins imported from variant.h
// Most is similar to https://github.com/espressif/arduino-esp32/blob/master/variants/esp32s3/pins_arduino.h
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <stdint.h>
#include <variant.h>
#define USB_VID 0x303a
#define USB_PID 0x1001
// Serial
static const uint8_t TX = UART_TX;
static const uint8_t RX = UART_RX;
// Default SPI will be mapped to Radio
static const uint8_t SS = LORA_CS;
static const uint8_t SCK = LORA_SCK;
static const uint8_t MOSI = LORA_MOSI;
static const uint8_t MISO = LORA_MISO;
// The default Wire will be mapped to PMU and RTC
static const uint8_t SCL = I2C_SCL;
static const uint8_t SDA = I2C_SDA;
#endif /* Pins_Arduino_h */

View File

@@ -0,0 +1,21 @@
[env:thinknode_m5]
extends = esp32s3_base
board = ESP32-S3-WROOM-1-N4
build_flags =
${esp32s3_base.build_flags}
-D ELECROW_ThinkNode_M5
-I variants/esp32s3/ELECROW-ThinkNode-M5
-DEINK_DISPLAY_MODEL=GxEPD2_154_D67
-DEINK_WIDTH=200
-DEINK_HEIGHT=200
-DUSE_EINK_DYNAMICDISPLAY ; Enable Dynamic EInk
-DEINK_LIMIT_FASTREFRESH=10 ; How many consecutive fast-refreshes are permitted //20
-DEINK_LIMIT_RATE_BACKGROUND_SEC=10 ; Minimum interval between BACKGROUND updates //30
-DEINK_LIMIT_RATE_RESPONSIVE_SEC=1 ; Minimum interval between RESPONSIVE updates
; -DEINK_LIMIT_GHOSTING_PX=2000 ; (Optional) How much image ghosting is tolerated
-DEINK_BACKGROUND_USES_FAST ; (Optional) Use FAST refresh for both BACKGROUND and RESPONSIVE, until a limit is reached.
lib_deps = ${esp32s3_base.lib_deps}
https://github.com/meshtastic/GxEPD2/archive/1655054ba298e0e29fc2044741940f927f9c2a43.zip
lewisxhe/PCF8563_Library@^1.0.1
maxpromer/PCA9557-arduino @ ^1.0.0

View File

@@ -0,0 +1,83 @@
#ifndef ELECROW_ThinkNode_M5_VAR
#define ELECROW_ThinkNode_M5_VAR
#define UART_TX 43
#define UART_RX 44
// LED
// Both of these are on the GPIO expander
#define PCA_LED_USER 1 // the Blue LED
#define PCA_LED_POWER 3 // the Red LED? Seems to have hardware logic to blink when USB is plugged in.
// USB_CHECK
#define EXT_PWR_DETECT 12
#define BATTERY_PIN 8
#define ADC_CHANNEL ADC1_GPIO8_CHANNEL
#define PIN_BUZZER 9
// Buttons
#define PIN_BUTTON2 14
#define PIN_BUTTON1 21
// Wire Interfaces
#define I2C_SCL 1
#define I2C_SDA 2
// GPS pins
#define GPS_SWITH 10
#define HAS_GPS 1
#define GPS_L76K
#define PIN_GPS_REINIT 13 // An output to reset L76K GPS. As per datasheet, low for > 100ms will reset the L76K
#define PIN_GPS_STANDBY 11 // An output to wake GPS, low means allow sleep, high means force wake
#define GPS_TX_PIN 20 // This is for bits going TOWARDS the CPU
#define GPS_RX_PIN 19 // This is for bits going TOWARDS the GPS
#define GPS_THREAD_INTERVAL 50
#define PIN_SERIAL1_RX GPS_TX_PIN
#define PIN_SERIAL1_TX GPS_RX_PIN
// PCF8563 RTC Module
#define PCF8563_RTC 0x51
#define SX126X_CS 17
#define LORA_SCK 16
#define LORA_MOSI 15
#define LORA_MISO 7
#define SX126X_RESET 6
#define SX126X_BUSY 5
#define SX126X_DIO1 4
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 3.3
#define SX126X_POWER_EN 46
#define SX126X_MAX_POWER 22 // SX126xInterface.cpp defaults to 22 if not defined, but here we define it for good practice
#define USE_SX1262
#define LORA_CS SX126X_CS // FIXME: for some reason both are used in /src
#define LORA_DIO1 SX126X_DIO1
#define USE_EINK
// Note: this is really just backlight power
#define PCA_PIN_EINK_EN 5 // This is the pin number on the GPIO expander
#define PIN_EINK_CS 39
#define PIN_EINK_BUSY 42
#define PIN_EINK_DC 40
#define PIN_EINK_RES 41
#define PIN_EINK_SCLK 38
#define PIN_EINK_MOSI 45 // also called SDI
// Controls power for all peripherals (eink + GPS + LoRa + Sensor)
#define PIN_POWER_EN -1
#define PCA_PIN_POWER_EN 4 // This is the pin number on the GPIO expander
#define PIN_SPI_MISO 7
#define PIN_SPI_MOSI 15
#define PIN_SPI_SCK 16
#define BUTTON_PIN PIN_BUTTON1
#define BUTTON_PIN_ALT PIN_BUTTON2
#endif

View File

@@ -1,7 +1,6 @@
[native_base]
extends = portduino_base
build_flags = ${portduino_base.build_flags} -I variants/native/portduino
-D ARCH_PORTDUINO
-I /usr/include
board = cross_platform
lib_deps = ${portduino_base.lib_deps}

View File

@@ -0,0 +1,19 @@
; MeshTiny - Custom device based on GAT562 with encoder and buzzer support
[env:meshtiny]
extends = nrf52840_base
board = meshtiny
board_level = extra
build_flags = ${nrf52840_base.build_flags} -Ivariants/nrf52840/meshtiny -D MESHTINY
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
-DRADIOLIB_EXCLUDE_SX128X=1
-DRADIOLIB_EXCLUDE_SX127X=1
-DRADIOLIB_EXCLUDE_LR11X0=1
-D INPUTDRIVER_ENCODER_TYPE=2
-D INPUTDRIVER_ENCODER_UP=4
-D INPUTDRIVER_ENCODER_DOWN=26
-D INPUTDRIVER_ENCODER_BTN=28
-D USE_PIN_BUZZER=PIN_BUZZER
-D MESHTASTIC_EXCLUDE_GPS=1
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/meshtiny>
lib_deps =
${nrf52840_base.lib_deps}

View File

@@ -0,0 +1,54 @@
/*
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
Copyright (c) 2016 Sandeep Mistry All right reserved.
Copyright (c) 2018, Adafruit Industries (adafruit.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "variant.h"
#include "nrf.h"
#include "wiring_constants.h"
#include "wiring_digital.h"
const uint32_t g_ADigitalPinMap[] = {
// P0
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
// P1
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
void initVariant()
{
// LED1 & LED2
pinMode(PIN_LED1, OUTPUT);
ledOff(PIN_LED1);
pinMode(PIN_LED2, OUTPUT);
ledOff(PIN_LED2);
// 3V3 Power Rail
pinMode(PIN_3V3_EN, OUTPUT);
digitalWrite(PIN_3V3_EN, HIGH);
// Initialize Encoder pins
pinMode(INPUTDRIVER_ENCODER_UP, INPUT_PULLUP);
pinMode(INPUTDRIVER_ENCODER_DOWN, INPUT_PULLUP);
pinMode(INPUTDRIVER_ENCODER_BTN, INPUT_PULLUP);
// Initialize Buzzer pin
pinMode(PIN_BUZZER, OUTPUT);
digitalWrite(PIN_BUZZER, LOW);
}

View File

@@ -0,0 +1,199 @@
/*
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
Copyright (c) 2016 Sandeep Mistry All right reserved.
Copyright (c) 2018, Adafruit Industries (adafruit.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _VARIANT_MESHTINY_
#define _VARIANT_MESHTINY_
#define MESHTINY
// #define RAK4630
/** Master clock frequency */
#define VARIANT_MCK (64000000ul)
#define USE_LFXO // Board uses 32khz crystal for LF
// define USE_LFRC // Board uses RC for LF
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "WVariant.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// Number of pins defined in PinDescription array
#define PINS_COUNT (48)
#define NUM_DIGITAL_PINS (48)
#define NUM_ANALOG_INPUTS (6)
#define NUM_ANALOG_OUTPUTS (0)
// LEDs
#define PIN_LED1 (35)
#define PIN_LED2 (36)
#define LED_BUILTIN PIN_LED1
#define LED_CONN PIN_LED2
#define LED_GREEN PIN_LED1
#define LED_BLUE PIN_LED2
#define LED_STATE_ON 1 // State when LED is litted
/*
* Encoder
*/
#define INPUTDRIVER_ENCODER_TYPE 2
#define INPUTDRIVER_ENCODER_UP 26
#define INPUTDRIVER_ENCODER_DOWN 4
#define INPUTDRIVER_ENCODER_BTN 28
#define CANNED_MESSAGE_MODULE_ENABLE 1
/*
* Buzzer - PWM
*/
#define PIN_BUZZER 30
/*
* Buttons
*/
#define PIN_BUTTON1 9
#define BUTTON_NEED_PULLUP
#define PIN_BUTTON2 12
#define PIN_BUTTON3 24
#define PIN_BUTTON4 25
/*
* Analog pins
*/
#define PIN_A0 (5)
#define PIN_A1 (31)
#define PIN_A2 (28)
#define PIN_A3 (29)
#define PIN_A4 (30)
#define PIN_A5 (31)
#define PIN_A6 (0xff)
#define PIN_A7 (0xff)
static const uint8_t A0 = PIN_A0;
static const uint8_t A1 = PIN_A1;
static const uint8_t A2 = PIN_A2;
static const uint8_t A3 = PIN_A3;
static const uint8_t A4 = PIN_A4;
static const uint8_t A5 = PIN_A5;
static const uint8_t A6 = PIN_A6;
static const uint8_t A7 = PIN_A7;
#define ADC_RESOLUTION 14
// Other pins
#define PIN_AREF (2)
#define PIN_NFC1 (9)
#define PIN_NFC2 (10)
static const uint8_t AREF = PIN_AREF;
/*
* Serial interfaces
*/
#define PIN_SERIAL1_RX (15)
#define PIN_SERIAL1_TX (16)
// Connected to Jlink CDC
#define PIN_SERIAL2_RX (8)
#define PIN_SERIAL2_TX (6)
/*
* SPI Interfaces
*/
#define SPI_INTERFACES_COUNT 2
#define PIN_SPI_MISO (45)
#define PIN_SPI_MOSI (44)
#define PIN_SPI_SCK (43)
#define PIN_SPI1_MISO (29) // (0 + 29)
#define PIN_SPI1_MOSI (30) // (0 + 30)
#define PIN_SPI1_SCK (3) // (0 + 3)
static const uint8_t SS = 42;
static const uint8_t MOSI = PIN_SPI_MOSI;
static const uint8_t MISO = PIN_SPI_MISO;
static const uint8_t SCK = PIN_SPI_SCK;
#define HAS_SCREEN 1
#define USE_SSD1306
/*
* Wire Interfaces
*/
#define WIRE_INTERFACES_COUNT 1
#define PIN_WIRE_SDA (13)
#define PIN_WIRE_SCL (14)
// QSPI Pins
#define PIN_QSPI_SCK 3
#define PIN_QSPI_CS 22 // Changed from 26 to avoid conflict with encoder
#define PIN_QSPI_IO0 27 // Changed from 30 to avoid conflict with buzzer
#define PIN_QSPI_IO1 29
#define PIN_QSPI_IO2 21 // Changed from 28 to avoid conflict with encoder button
#define PIN_QSPI_IO3 2
// On-board QSPI Flash
#define EXTERNAL_FLASH_DEVICES IS25LP080D
#define EXTERNAL_FLASH_USE_QSPI
#define USE_SX1262
#define SX126X_CS (42)
#define SX126X_DIO1 (47)
#define SX126X_BUSY (46)
#define SX126X_RESET (38)
#define SX126X_POWER_EN (37)
// DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// Testing USB detection
#define NRF_APM
#define PIN_3V3_EN (34)
// Battery
// The battery sense is hooked to pin A0 (5)
#define BATTERY_PIN PIN_A0
// and has 12 bit resolution
#define BATTERY_SENSE_RESOLUTION_BITS 12
#define BATTERY_SENSE_RESOLUTION 4096.0
#undef AREF_VOLTAGE
#define AREF_VOLTAGE 3.0
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
#define ADC_MULTIPLIER 1.73
#ifdef __cplusplus
}
#endif
/*----------------------------------------------------------------------------
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#endif

View File

@@ -11,10 +11,10 @@ build_flags = ${nrf52840_base.build_flags}
-DRADIOLIB_EXCLUDE_SX127X=1
-DRADIOLIB_EXCLUDE_LR11X0=1
-DHAS_RAKPROT=1 ; Define if RAk OneWireSerial is used (disables GPS)
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak2560> +<mesh/api/> +<mqtt/>
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak2560> +<mesh/api/> +<mqtt/> +<serialization/>
lib_deps =
${nrf52840_base.lib_deps}
${networking_base.lib_deps}
${nrf52_networking_base.lib_deps}
melopero/Melopero RV3028@^1.1.0
https://github.com/beegee-tokyo/RAK-OneWireSerial/archive/0.0.2.zip
debug_tool = jlink

View File

@@ -17,7 +17,7 @@ build_flags = ${nrf52840_base.build_flags}
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak4631> +<mesh/eth/> +<mesh/api/> +<mqtt/>
lib_deps =
${nrf52840_base.lib_deps}
${networking_base.lib_deps}
${nrf52_networking_base.lib_deps}
melopero/Melopero RV3028@^1.1.0
https://github.com/RAKWireless/RAK13800-W5100S/archive/1.0.2.zip
rakwireless/RAKwireless NCP5623 RGB LED library@^1.0.2

View File

@@ -24,7 +24,7 @@ build_flags = ${nrf52840_base.build_flags}
-DMESHTASTIC_EXCLUDE_STOREFORWARD=1
-DMESHTASTIC_EXCLUDE_CANNEDMESSAGES=1
-DMESHTASTIC_EXCLUDE_WAYPOINT=1
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak4631_eth_gw> +<mesh/eth/> +<mesh/api/> +<mqtt/>
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak4631_eth_gw> +<mesh/eth/> +<mesh/api/> +<mqtt/> +<serialization/>
lib_deps =
${nrf52840_base.lib_deps}
${networking_base.lib_deps}

View File

@@ -18,7 +18,7 @@ build_flags = ${nrf52840_base.build_flags}
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak_wismeshtap> +<mesh/eth/> +<mesh/api/> +<mqtt/>
lib_deps =
${nrf52840_base.lib_deps}
${networking_base.lib_deps}
${nrf52_networking_base.lib_deps}
melopero/Melopero RV3028@^1.1.0
https://github.com/RAKWireless/RAK13800-W5100S/archive/1.0.2.zip
rakwireless/RAKwireless NCP5623 RGB LED library@^1.0.2

View File

@@ -0,0 +1,25 @@
; Using original screen class
[env:t-echo-lite]
extends = nrf52840_base
board = t-echo
board_check = true
debug_tool = jlink
# add -DCFG_SYSVIEW if you want to use the Segger systemview tool for OS profiling.
build_flags = ${nrf52840_base.build_flags}
-Ivariants/nrf52840/t-echo-lite
-D T_ECHO_LITE
-D GPS_POWER_TOGGLE
-D EINK_DISPLAY_MODEL=GxEPD2_122_T61
-D EINK_WIDTH=192
-D EINK_HEIGHT=176
-D USE_EINK
-D USE_EINK_DYNAMICDISPLAY ; Enable Dynamic EInk
-D EINK_LIMIT_FASTREFRESH=20 ; How many consecutive fast-refreshes are permitted
-D EINK_BACKGROUND_USES_FAST ; (Optional) Use FAST refresh for both BACKGROUND and RESPONSIVE, until a limit is reached.
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/t-echo-lite>
lib_deps =
${nrf52840_base.lib_deps}
https://github.com/meshtastic/GxEPD2/archive/a05c11c02862624266b61599b0d6ba93e33c6f24.zip
;upload_protocol = fs

View File

@@ -0,0 +1,44 @@
/*
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
Copyright (c) 2016 Sandeep Mistry All right reserved.
Copyright (c) 2018, Adafruit Industries (adafruit.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "variant.h"
#include "nrf.h"
#include "wiring_constants.h"
#include "wiring_digital.h"
const uint32_t g_ADigitalPinMap[] = {
// P0 - pins 0 and 1 are hardwired for xtal and should never be enabled
0xff, 0xff, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
// P1
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
void initVariant()
{
// LED1 & LED2
pinMode(PIN_LED1, OUTPUT);
ledOff(PIN_LED1);
pinMode(PIN_LED2, OUTPUT);
ledOff(PIN_LED2);
pinMode(PIN_LED3, OUTPUT);
ledOff(PIN_LED3);
}

View File

@@ -0,0 +1,207 @@
/*
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
Copyright (c) 2016 Sandeep Mistry All right reserved.
Copyright (c) 2018, Adafruit Industries (adafruit.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _VARIANT_TTGO_EINK_V1_0_
#define _VARIANT_TTGO_EINK_V1_0_
/** Master clock frequency */
#define VARIANT_MCK (64000000ul)
#define USE_LFXO // Board uses 32khz crystal for LF
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "WVariant.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// Number of pins defined in PinDescription array
#define PINS_COUNT (48)
#define NUM_DIGITAL_PINS (48)
#define NUM_ANALOG_INPUTS (1)
#define NUM_ANALOG_OUTPUTS (0)
// LEDs
#define PIN_LED1 (32 + 7) // Green LED
#define PIN_LED2 (32 + 5) // Blue LED
// Unused(by firmware) LEDs:
#define PIN_LED3 (32 + 14) // Red LED inside, under the display.
#define LED_RED PIN_LED3
#define LED_BLUE PIN_LED2
#define LED_GREEN PIN_LED1
#define BLE_LED LED_BLUE
#define BLE_LED_INVERTED 1
#define LED_BUILTIN LED_GREEN
#define LED_CONN LED_GREEN
#define LED_STATE_ON 0 // State when LED is lit
// Buttons
#define PIN_BUTTON1 (0 + 24)
#define PIN_BUTTON2 (0 + 18) // 0.18 is labeled on the board as RESET but we configure it in the bootloader as a regular GPIO
#define BUTTON_CLICK_MS 400
// Analog pins
#define PIN_A0 (0 + 2) // Battery ADC
#define BATTERY_PIN PIN_A0
static const uint8_t A0 = PIN_A0;
#define ADC_RESOLUTION 14
#define ADC_CTRL (0 + 31)
#define ADC_CTRL_ENABLED HIGH
// NFC
#define PIN_NFC1 (9)
#define PIN_NFC2 (10)
// Wire Interfaces
#define WIRE_INTERFACES_COUNT 1
#define PIN_WIRE_SDA (32 + 4)
#define PIN_WIRE_SCL (32 + 2)
/*
Internal, PCB PAD interrupt PIN. Currently not used. (Not built in my device)
*/
// #define PIN_IMU_INT (0 + 16) // Interrupt from the IMU, macro name correct?!
// External serial flash ZD25WQ32CEIGR
// QSPI Pins
#define PIN_QSPI_SCK (0 + 4)
#define PIN_QSPI_CS (0 + 12)
#define PIN_QSPI_IO0 (0 + 6) // MOSI if using two bit interface
#define PIN_QSPI_IO1 (0 + 8) // MISO if using two bit interface
#define PIN_QSPI_IO2 (32 + 9) // WP if using two bit interface (i.e. not used)
#define PIN_QSPI_IO3 (0 + 26) // HOLD if using two bit interface (i.e. not used)
// On-board QSPI Flash
#define EXTERNAL_FLASH_DEVICES ZD25WQ32CEIGR
#define EXTERNAL_FLASH_USE_QSPI
// Lora radio
#define USE_SX1262
// #define USE_SX1268 // currently only available with XS1262.
#define SX126X_CS (0 + 11)
#define SX126X_DIO1 (32 + 8)
#define SX126X_DIO2 (0 + 5)
#define SX126X_BUSY (0 + 14)
#define SX126X_RESET (0 + 7)
#define SX126X_RXEN (32 + 1)
#define SX126X_TXEN (0 + 27)
// #define TCXO_OPTIONAL
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// eink display pins
#define VEXT_ENABLE (32 + 12)
#define VEXT_ON_VALUE LOW
#define PIN_EINK_CS (0 + 22)
#define PIN_EINK_BUSY (0 + 3)
#define PIN_EINK_DC (0 + 21)
#define PIN_EINK_RES (0 + 28)
#define PIN_EINK_SCLK (0 + 19)
#define PIN_EINK_MOSI (0 + 20)
// Controls power 3V3 for all peripherals (eink + GPS + LoRa + Sensor)
#define PIN_POWER_EN (0 + 30) // 3V3 POWER Enable
#define PIN_SPI1_MISO (-1) // The display does not use MISO.
#define PIN_SPI1_MOSI PIN_EINK_MOSI
#define PIN_SPI1_SCK PIN_EINK_SCLK
// GPS pins
// #define GPS_DEBUG
#define GPS_L76K
#define GPS_BAUDRATE 9600
#define HAS_GPS 1
// #define PIN_GPS_REINIT (32 + 5) // An output to reset L76K GPS. As per datasheet, low for > 100ms will reset the L76K
#define PIN_GPS_STANDBY (32 + 10) // An output to wake GPS, low means allow sleep, high means force wake
// Seems to be missing on this new board
#define PIN_GPS_PPS (0 + 29) // Pulse per second input from the GPS
#define GPS_TX_PIN (32 + 15) // This is for bits going TOWARDS the CPU
#define GPS_RX_PIN (32 + 13) // This is for bits going TOWARDS the GPS
#define GPS_THREAD_INTERVAL 50
#define PIN_SERIAL1_RX GPS_TX_PIN
#define PIN_SERIAL1_TX GPS_RX_PIN
// SPI Interfaces
#define SPI_INTERFACES_COUNT 2
// For LORA, SPI 0
#define PIN_SPI_MISO (0 + 17)
#define PIN_SPI_MOSI (0 + 15)
#define PIN_SPI_SCK (0 + 13)
// Battery
// The battery sense is hooked to pin A0 (2)
// it is defined in the analogue pin section of this file
// and has 12 bit resolution
#define BATTERY_SENSE_RESOLUTION_BITS 12
#define BATTERY_SENSE_RESOLUTION 4096.0
#undef AREF_VOLTAGE
#define AREF_VOLTAGE 3.0
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
#define ADC_MULTIPLIER (2.0F)
// #define NO_EXT_GPIO 1
// PINs back side
// Batt & solar connector left up corner
/*
-------------------------------
| VDDH, VBAT, 0.23, SCL , 1.06 |
| GND , SDA , 0.09, 0.10, 0.25 |
-------------------------------
--------
| VDDH |
| GND |
| 1.13 | - Wake Up/standby
| 1.15 | - PPS
| 0.29 | - TX
| 1.10 | - RX
| 1.11 | - EN
--------
-------------------------------
| 3V3 , GND , 0.16, 1.03, G_WU | 0.16 internal solder pad interrupt PIN,
| G_EN, G_RX, G_TX, GND , PPS |
-------------------------------
*/
// To debug via the segger JLINK console rather than the CDC-ACM serial device
// #define USE_SEGGER
#ifdef __cplusplus
}
#endif
/*----------------------------------------------------------------------------
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#endif

View File

@@ -1,4 +1,4 @@
[VERSION]
major = 2
minor = 7
build = 4
build = 6