mirror of
https://github.com/alexhopeoconnor/firmware.git
synced 2026-10-16 08:31:35 +10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2585fb322c | ||
|
|
77f378dd53 | ||
|
|
16dcafa7fb | ||
|
|
eeb95d6bff | ||
|
|
4ac74edf38 | ||
|
|
323830c7cc | ||
|
|
a9acd506a8 | ||
|
|
a1d6c6db62 | ||
|
|
69495dcd98 | ||
|
|
0f2d224e74 | ||
|
|
381cefa6b2 | ||
|
|
a50cbdc95b | ||
|
|
e7c7af40ae | ||
|
|
288d7a3e7b | ||
|
|
48ae4b6c7a | ||
|
|
ae5019bec6 | ||
|
|
4990bf51e3 | ||
|
|
3cd3fd3386 | ||
|
|
839cf554b7 | ||
|
|
b2c8cbb78d | ||
|
|
8061f83704 | ||
|
|
216655f05f | ||
|
|
a3b49b9028 | ||
|
|
2c633b6458 | ||
|
|
17945884a5 | ||
|
|
7fdee353b5 | ||
|
|
362a2c09c0 | ||
|
|
c0eb4f1b45 | ||
|
|
3136cb4565 | ||
|
|
0562a674e2 | ||
|
|
338dd119fb | ||
|
|
f36406e5ef | ||
|
|
7f565fd524 | ||
|
|
5af6a48326 | ||
|
|
5633848d75 | ||
|
|
8b8c1881a8 | ||
|
|
a1d6978626 | ||
|
|
a67cf0f726 | ||
|
|
456fa3ddeb | ||
|
|
5adc9663b7 | ||
|
|
5de0654819 | ||
|
|
ab781e9f2d | ||
|
|
595b5f19b3 | ||
|
|
4bb93c1ed2 | ||
|
|
5582e94009 | ||
|
|
e33fbca8d6 | ||
|
|
aca7fe9f95 | ||
|
|
5a0644cd4f | ||
|
|
e990198628 | ||
|
|
6c69d9e74c | ||
|
|
e03f1b5c5e | ||
|
|
f46a9dfe7b | ||
|
|
9824357c50 | ||
|
|
942f2cb3d1 | ||
|
|
76beeda392 | ||
|
|
821735495a | ||
|
|
9ab2ee3483 | ||
|
|
4e92f7fa09 | ||
|
|
ae2a06eccd | ||
|
|
3ae331eb89 | ||
|
|
74a6c9f447 | ||
|
|
c77709a327 | ||
|
|
325f7d2e55 | ||
|
|
c6fc7986f1 | ||
|
|
8ecce1eb5c | ||
|
|
21c0dcaabb | ||
|
|
1b13f872db | ||
|
|
8b5141ddb7 | ||
|
|
ee25a0a0e1 | ||
|
|
436f174bce | ||
|
|
a34cd4ca6f | ||
|
|
8c37669213 | ||
|
|
8a059bae23 | ||
|
|
1869f2108d | ||
|
|
f5b41c2f2c | ||
|
|
83c8875060 | ||
|
|
9134239faa | ||
|
|
b3d1d563e9 | ||
|
|
c7f816e63f | ||
|
|
dd4fb6b0bc | ||
|
|
87798429fa | ||
|
|
78baaf4484 | ||
|
|
b3b115b6a6 | ||
|
|
b90b5ff40e | ||
|
|
b7028fff08 | ||
|
|
7d6a0f20c6 | ||
|
|
9b7384507d | ||
|
|
7d7091ef94 | ||
|
|
baccd0c532 | ||
|
|
1fecdc7603 | ||
|
|
1625fd88d7 | ||
|
|
fe22460f25 | ||
|
|
f634b7dd60 | ||
|
|
f56e651787 | ||
|
|
55af6c4726 | ||
|
|
d272b28ed4 | ||
|
|
f8c27d1714 | ||
|
|
25383c9523 | ||
|
|
6d90b6536e | ||
|
|
0759197ab3 | ||
|
|
bbfca12d50 | ||
|
|
d44c3a8e1a | ||
|
|
1cef1094a0 | ||
|
|
02d4ca2983 | ||
|
|
36e8a498f1 | ||
|
|
d63b583ea2 | ||
|
|
14073e2c9f | ||
|
|
39a6ffc664 | ||
|
|
8be790890c | ||
|
|
426a7c19dd | ||
|
|
39c0824abb | ||
|
|
a8a5086b6d | ||
|
|
428b839254 | ||
|
|
a70d350ce3 | ||
|
|
00a3249c56 | ||
|
|
b51235d4fd | ||
|
|
d07f5be548 | ||
|
|
739ad0dc31 | ||
|
|
e8fd5174ec | ||
|
|
96726d22cd | ||
|
|
3330d297b1 | ||
|
|
e9ed2c0335 | ||
|
|
3cbc5b7a8d | ||
|
|
20bf822a48 | ||
|
|
14ee1ed075 | ||
|
|
4d48d517e0 | ||
|
|
ffdb3bc393 | ||
|
|
6e83a9a0b3 | ||
|
|
73cfa3c884 | ||
|
|
f2b6383cbb | ||
|
|
28d507f043 | ||
|
|
d508de9568 |
@@ -56,6 +56,25 @@ jobs:
|
|||||||
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||||
id: version
|
id: version
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v4
|
||||||
|
with:
|
||||||
|
cache-image: true
|
||||||
|
|
||||||
|
- name: Docker setup
|
||||||
|
uses: docker/setup-buildx-action@v4
|
||||||
|
with:
|
||||||
|
# Add Google/Amazon DockerHub mirrors to buildkit config
|
||||||
|
# https://docs.docker.com/build/ci/github-actions/configure-builder/#registry-mirror
|
||||||
|
buildkitd-config-inline: |
|
||||||
|
[registry."docker.io"]
|
||||||
|
mirrors = ["mirror.gcr.io", "public.ecr.aws"]
|
||||||
|
|
||||||
|
- name: Sanitize platform string
|
||||||
|
id: sanitize_platform
|
||||||
|
# Replace slashes with underscores
|
||||||
|
run: echo "cleaned_platform=${{ inputs.platform }}" | sed 's/\//_/g' >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Docker login
|
- name: Docker login
|
||||||
if: ${{ inputs.push }}
|
if: ${{ inputs.push }}
|
||||||
uses: docker/login-action@v4
|
uses: docker/login-action@v4
|
||||||
@@ -63,17 +82,6 @@ jobs:
|
|||||||
username: meshtastic
|
username: meshtastic
|
||||||
password: ${{ secrets.DOCKER_FIRMWARE_TOKEN }}
|
password: ${{ secrets.DOCKER_FIRMWARE_TOKEN }}
|
||||||
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v4
|
|
||||||
|
|
||||||
- name: Docker setup
|
|
||||||
uses: docker/setup-buildx-action@v4
|
|
||||||
|
|
||||||
- name: Sanitize platform string
|
|
||||||
id: sanitize_platform
|
|
||||||
# Replace slashes with underscores
|
|
||||||
run: echo "cleaned_platform=${{ inputs.platform }}" | sed 's/\//_/g' >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Docker tag
|
- name: Docker tag
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v6
|
uses: docker/metadata-action@v6
|
||||||
@@ -95,3 +103,6 @@ jobs:
|
|||||||
platforms: ${{ inputs.platform }}
|
platforms: ${{ inputs.platform }}
|
||||||
build-args: |
|
build-args: |
|
||||||
PIO_ENV=${{ inputs.pio_env }}
|
PIO_ENV=${{ inputs.pio_env }}
|
||||||
|
# Cache image layers in GitHub Actions cache to speed up subsequent builds.
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
|||||||
@@ -309,7 +309,7 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Create release
|
- name: Create release
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v3
|
||||||
id: create_release
|
id: create_release
|
||||||
with:
|
with:
|
||||||
draft: true
|
draft: true
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Apply quality label if needed
|
- name: Apply quality label if needed
|
||||||
if: steps.quality.outputs.response != '' && steps.quality.outputs.response != 'ok'
|
if: steps.quality.outputs.response != '' && steps.quality.outputs.response != 'ok'
|
||||||
uses: actions/github-script@v8
|
uses: actions/github-script@v9
|
||||||
env:
|
env:
|
||||||
QUALITY_LABEL: ${{ steps.quality.outputs.response }}
|
QUALITY_LABEL: ${{ steps.quality.outputs.response }}
|
||||||
with:
|
with:
|
||||||
@@ -80,7 +80,7 @@ jobs:
|
|||||||
# ─────────────────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────────────────
|
||||||
- name: Determine if completeness check should be skipped
|
- name: Determine if completeness check should be skipped
|
||||||
if: steps.quality.outputs.response == 'ok' || steps.quality.outputs.response == ''
|
if: steps.quality.outputs.response == 'ok' || steps.quality.outputs.response == ''
|
||||||
uses: actions/github-script@v8
|
uses: actions/github-script@v9
|
||||||
id: check-skip
|
id: check-skip
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
@@ -134,7 +134,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Process analysis result
|
- name: Process analysis result
|
||||||
if: (steps.quality.outputs.response == 'ok' || steps.quality.outputs.response == '') && steps.check-skip.outputs.should_skip != 'true' && steps.analysis.outputs.response != ''
|
if: (steps.quality.outputs.response == 'ok' || steps.quality.outputs.response == '') && steps.check-skip.outputs.should_skip != 'true' && steps.analysis.outputs.response != ''
|
||||||
uses: actions/github-script@v8
|
uses: actions/github-script@v9
|
||||||
id: process
|
id: process
|
||||||
env:
|
env:
|
||||||
AI_RESPONSE: ${{ steps.analysis.outputs.response }}
|
AI_RESPONSE: ${{ steps.analysis.outputs.response }}
|
||||||
@@ -174,7 +174,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Apply triage label
|
- name: Apply triage label
|
||||||
if: steps.process.outputs.label != '' && steps.process.outputs.label != 'none'
|
if: steps.process.outputs.label != '' && steps.process.outputs.label != 'none'
|
||||||
uses: actions/github-script@v8
|
uses: actions/github-script@v9
|
||||||
env:
|
env:
|
||||||
LABEL_NAME: ${{ steps.process.outputs.label }}
|
LABEL_NAME: ${{ steps.process.outputs.label }}
|
||||||
with:
|
with:
|
||||||
@@ -200,7 +200,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Comment on issue
|
- name: Comment on issue
|
||||||
if: steps.process.outputs.should_comment == 'true'
|
if: steps.process.outputs.should_comment == 'true'
|
||||||
uses: actions/github-script@v8
|
uses: actions/github-script@v9
|
||||||
env:
|
env:
|
||||||
COMMENT_BODY: ${{ steps.process.outputs.comment_body }}
|
COMMENT_BODY: ${{ steps.process.outputs.comment_body }}
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ jobs:
|
|||||||
# Step 1: Check if PR already has automation/type labels (skip if so)
|
# Step 1: Check if PR already has automation/type labels (skip if so)
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────────────────
|
||||||
- name: Check existing labels
|
- name: Check existing labels
|
||||||
uses: actions/github-script@v8
|
uses: actions/github-script@v9
|
||||||
id: check-labels
|
id: check-labels
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
@@ -58,7 +58,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Apply quality label if needed
|
- name: Apply quality label if needed
|
||||||
if: steps.check-labels.outputs.skip_all != 'true' && steps.quality.outputs.response != '' && steps.quality.outputs.response != 'ok'
|
if: steps.check-labels.outputs.skip_all != 'true' && steps.quality.outputs.response != '' && steps.quality.outputs.response != 'ok'
|
||||||
uses: actions/github-script@v8
|
uses: actions/github-script@v9
|
||||||
id: quality-label
|
id: quality-label
|
||||||
env:
|
env:
|
||||||
QUALITY_LABEL: ${{ steps.quality.outputs.response }}
|
QUALITY_LABEL: ${{ steps.quality.outputs.response }}
|
||||||
@@ -113,7 +113,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Apply type label
|
- name: Apply type label
|
||||||
if: steps.check-labels.outputs.skip_all != 'true' && steps.check-labels.outputs.has_type_label != 'true' && steps.classify.outputs.response != ''
|
if: steps.check-labels.outputs.skip_all != 'true' && steps.check-labels.outputs.has_type_label != 'true' && steps.classify.outputs.response != ''
|
||||||
uses: actions/github-script@v8
|
uses: actions/github-script@v9
|
||||||
env:
|
env:
|
||||||
TYPE_LABEL: ${{ steps.classify.outputs.response }}
|
TYPE_LABEL: ${{ steps.classify.outputs.response }}
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ on:
|
|||||||
secrets:
|
secrets:
|
||||||
PPA_GPG_PRIVATE_KEY:
|
PPA_GPG_PRIVATE_KEY:
|
||||||
required: true
|
required: true
|
||||||
|
PPA_SFTP_PRIVATE_KEY:
|
||||||
|
required: true
|
||||||
inputs:
|
inputs:
|
||||||
ppa_repo:
|
ppa_repo:
|
||||||
description: Meshtastic PPA to target
|
description: Meshtastic PPA to target
|
||||||
@@ -27,6 +29,7 @@ jobs:
|
|||||||
build_location: ppa
|
build_location: ppa
|
||||||
|
|
||||||
package-ppa:
|
package-ppa:
|
||||||
|
if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
needs: build-debian-src
|
needs: build-debian-src
|
||||||
steps:
|
steps:
|
||||||
@@ -40,7 +43,7 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update -y --fix-missing
|
sudo apt-get update -y --fix-missing
|
||||||
sudo apt-get install -y dput
|
sudo apt-get install -y dput openssh-client
|
||||||
|
|
||||||
- name: Import GPG key
|
- name: Import GPG key
|
||||||
uses: crazy-max/ghaction-import-gpg@v7
|
uses: crazy-max/ghaction-import-gpg@v7
|
||||||
@@ -65,8 +68,42 @@ jobs:
|
|||||||
- name: Display structure of downloaded files
|
- name: Display structure of downloaded files
|
||||||
run: ls -lah
|
run: ls -lah
|
||||||
|
|
||||||
- name: Publish with dput
|
- name: Trust Launchpad's SSH key
|
||||||
if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
|
|
||||||
timeout-minutes: 15 # dput is terrible, sometimes runs 'forever'
|
|
||||||
run: |
|
run: |
|
||||||
dput ${{ inputs.ppa_repo }} meshtasticd_${{ steps.version.outputs.deb }}~${{ inputs.series }}_source.changes
|
mkdir -p ~/.ssh
|
||||||
|
ssh-keyscan -H ppa.launchpad.net >> ~/.ssh/known_hosts
|
||||||
|
|
||||||
|
- name: Setup dput config
|
||||||
|
env:
|
||||||
|
ppa_login: meshtasticorg
|
||||||
|
run: |
|
||||||
|
sudo tee /etc/meshtastic-dput.cf >/dev/null <<EOF
|
||||||
|
[ppa]
|
||||||
|
fqdn = ppa.launchpad.net
|
||||||
|
method = ftp
|
||||||
|
incoming = ~%(ppa)s
|
||||||
|
login = anonymous
|
||||||
|
|
||||||
|
[ssh-ppa]
|
||||||
|
fqdn = ppa.launchpad.net
|
||||||
|
method = sftp
|
||||||
|
incoming = ~%(ssh-ppa)s
|
||||||
|
login = ${ppa_login}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Import SSH key
|
||||||
|
uses: webfactory/ssh-agent@v0.10.0
|
||||||
|
with:
|
||||||
|
ssh-private-key: ${{ secrets.PPA_SFTP_PRIVATE_KEY }}
|
||||||
|
id: ssh
|
||||||
|
|
||||||
|
- name: Publish with dput (sftp)
|
||||||
|
timeout-minutes: 30 # dput is terrible, sometimes runs 'forever'
|
||||||
|
env:
|
||||||
|
up_ppa_repo: ${{ inputs.ppa_repo }}
|
||||||
|
up_series: ${{ inputs.series }}
|
||||||
|
up_version: ${{ steps.version.outputs.deb }}
|
||||||
|
run: >
|
||||||
|
dput -c /etc/meshtastic-dput.cf
|
||||||
|
ssh-${up_ppa_repo}
|
||||||
|
meshtasticd_${up_version}~${up_series}_source.changes
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check for PR labels
|
- name: Check for PR labels
|
||||||
uses: actions/github-script@v8
|
uses: actions/github-script@v9
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
const labels = context.payload.pull_request.labels.map(label => label.name);
|
const labels = context.payload.pull_request.labels.map(label => label.name);
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Comment test results on PR
|
- name: Comment test results on PR
|
||||||
if: github.event_name == 'pull_request' && needs.native-tests.result != 'skipped'
|
if: github.event_name == 'pull_request' && needs.native-tests.result != 'skipped'
|
||||||
uses: actions/github-script@v8
|
uses: actions/github-script@v9
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ jobs:
|
|||||||
node-version: 24
|
node-version: 24
|
||||||
|
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@v5
|
uses: pnpm/action-setup@v6
|
||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -8,10 +8,10 @@ plugins:
|
|||||||
uri: https://github.com/trunk-io/plugins
|
uri: https://github.com/trunk-io/plugins
|
||||||
lint:
|
lint:
|
||||||
enabled:
|
enabled:
|
||||||
- checkov@3.2.513
|
- checkov@3.2.517
|
||||||
- renovate@43.104.6
|
- renovate@43.110.9
|
||||||
- prettier@3.8.1
|
- prettier@3.8.1
|
||||||
- trufflehog@3.94.2
|
- trufflehog@3.94.3
|
||||||
- yamllint@1.38.0
|
- yamllint@1.38.0
|
||||||
- bandit@1.9.4
|
- bandit@1.9.4
|
||||||
- trivy@0.69.3
|
- trivy@0.69.3
|
||||||
|
|||||||
@@ -204,6 +204,16 @@ HostMetrics:
|
|||||||
# UserStringCommand: cat /sys/firmware/devicetree/base/serial-number # Command to execute, to send the results as the userString
|
# UserStringCommand: cat /sys/firmware/devicetree/base/serial-number # Command to execute, to send the results as the userString
|
||||||
|
|
||||||
|
|
||||||
|
StoreAndForward:
|
||||||
|
# Enabled: true # Enable Store and Forward++, true by default
|
||||||
|
# DBPath: /var/lib/meshtasticd/ # Path to the S&F++ Sqlite DB
|
||||||
|
# Stratum0: false # Specify if this node is a Stratum 0 node, the controller node.
|
||||||
|
# InitialSync: 10 # Number of messages to
|
||||||
|
# Hops: 3 # Number of hops to use for SF++ messages
|
||||||
|
# AnnounceInterval: 5 # Interval in minutes between announcing tip of chain hash
|
||||||
|
# MaxChainLength: 1000 # Maximum number of messages to store in a chain
|
||||||
|
|
||||||
|
|
||||||
Config:
|
Config:
|
||||||
# DisplayMode: TWOCOLOR # uncomment to force BaseUI
|
# DisplayMode: TWOCOLOR # uncomment to force BaseUI
|
||||||
# DisplayMode: COLOR # uncomment to force MUI
|
# DisplayMode: COLOR # uncomment to force MUI
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# MeshAdv-Pi E22-900M30S
|
||||||
|
# https://github.com/chrismyers2000/MeshAdv-Pi-Hat
|
||||||
|
Meta:
|
||||||
|
name: MeshAdv-Pi E22-900M30S
|
||||||
|
support: community
|
||||||
|
compatible:
|
||||||
|
- ebyte-ecb41-pge # Armbian
|
||||||
|
|
||||||
|
Lora:
|
||||||
|
Module: sx1262
|
||||||
|
CS: # GPIO0_A1 (physical 40)
|
||||||
|
pin: 1
|
||||||
|
gpiochip: 0
|
||||||
|
line: 1
|
||||||
|
IRQ: # GPIO0_A3 (physical 36)
|
||||||
|
pin: 3
|
||||||
|
gpiochip: 0
|
||||||
|
line: 3
|
||||||
|
Busy: # GPIO0_A0 (physical 38)
|
||||||
|
pin: 0
|
||||||
|
gpiochip: 0
|
||||||
|
line: 0
|
||||||
|
Reset: # GPIO0_B4 (physical 12)
|
||||||
|
pin: 12
|
||||||
|
gpiochip: 0
|
||||||
|
line: 12
|
||||||
|
TXen: # GPIO1_D1 (physical 33)
|
||||||
|
pin: 57
|
||||||
|
gpiochip: 1
|
||||||
|
line: 25
|
||||||
|
RXen: # GPIO1_B3 (physical 32)
|
||||||
|
pin: 43
|
||||||
|
gpiochip: 1
|
||||||
|
line: 11
|
||||||
|
DIO3_TCXO_VOLTAGE: true
|
||||||
|
# Only for E22-900M33S:
|
||||||
|
# Limit the output power to 8 dBm
|
||||||
|
# SX126X_MAX_POWER: 8
|
||||||
|
spidev: spidev0.0
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# MeshAdv Mini E22-900M22S
|
||||||
|
# https://github.com/chrismyers2000/MeshAdv-Mini
|
||||||
|
Meta:
|
||||||
|
name: MeshAdv Mini E22-900M22S
|
||||||
|
support: community
|
||||||
|
compatible:
|
||||||
|
- ebyte-ecb41-pge # Armbian
|
||||||
|
|
||||||
|
Lora:
|
||||||
|
Module: sx1262 # Ebyte E22-900M22S
|
||||||
|
CS: # GPIO0_B6 (physical 24, SPI1_CSN0)
|
||||||
|
pin: 14
|
||||||
|
gpiochip: 0
|
||||||
|
line: 14
|
||||||
|
IRQ: # GPIO0_A3 (physical 36)
|
||||||
|
pin: 3
|
||||||
|
gpiochip: 0
|
||||||
|
line: 3
|
||||||
|
Busy: # GPIO0_A0 (physical 38)
|
||||||
|
pin: 0
|
||||||
|
gpiochip: 0
|
||||||
|
line: 0
|
||||||
|
Reset: # GPIO1_C3 (physical 18)
|
||||||
|
pin: 51
|
||||||
|
gpiochip: 1
|
||||||
|
line: 19
|
||||||
|
RXen: # GPIO1_B3 (physical 32)
|
||||||
|
pin: 43
|
||||||
|
gpiochip: 1
|
||||||
|
line: 11
|
||||||
|
DIO2_AS_RF_SWITCH: true
|
||||||
|
DIO3_TCXO_VOLTAGE: true
|
||||||
|
spidev: spidev0.0
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
Meta:
|
||||||
|
name: RAK6421 + RAK13300 Slot 1
|
||||||
|
support: community # Promote when tested
|
||||||
|
compatible:
|
||||||
|
- ebyte-ecb41-pge # Armbian
|
||||||
|
|
||||||
|
Lora:
|
||||||
|
Module: sx1262
|
||||||
|
IRQ: # GPIO0_A5 (IO6, physical 15)
|
||||||
|
pin: 5
|
||||||
|
gpiochip: 0
|
||||||
|
line: 5
|
||||||
|
Reset: # GPIO0_A3 (IO4, physical 36)
|
||||||
|
pin: 3
|
||||||
|
gpiochip: 0
|
||||||
|
line: 3
|
||||||
|
Busy: # GPIO1_C3 (IO5, physical 18)
|
||||||
|
pin: 51
|
||||||
|
gpiochip: 1
|
||||||
|
line: 19
|
||||||
|
# Ant_sw: # GPIO1_C2 (IO3, physical 16)
|
||||||
|
# pin: 50
|
||||||
|
# gpiochip: 1
|
||||||
|
# line: 18
|
||||||
|
Enable_Pins:
|
||||||
|
- pin: 43 # GPIO1_B3 (physical 32)
|
||||||
|
gpiochip: 1
|
||||||
|
line: 11
|
||||||
|
- pin: 57 # GPIO1_D1 (physical 33)
|
||||||
|
gpiochip: 1
|
||||||
|
line: 25
|
||||||
|
DIO3_TCXO_VOLTAGE: true
|
||||||
|
DIO2_AS_RF_SWITCH: true
|
||||||
|
spidev: spidev0.0
|
||||||
|
# CS: # GPIO0_B6 (SPI1_CSN0, physical 24)
|
||||||
|
# pin: 14
|
||||||
|
# gpiochip: 0
|
||||||
|
# line: 14
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
Meta:
|
||||||
|
name: RAK6421 + RAK13300 Slot 2
|
||||||
|
support: community # Promote when tested
|
||||||
|
compatible:
|
||||||
|
- ebyte-ecb41-pge # Armbian
|
||||||
|
|
||||||
|
Lora:
|
||||||
|
Module: sx1262
|
||||||
|
IRQ: # GPIO0_B4 (IO6, physical 12)
|
||||||
|
pin: 12
|
||||||
|
gpiochip: 0
|
||||||
|
line: 12
|
||||||
|
Reset: # GPIO1_C3 (IO4, physical 18)
|
||||||
|
pin: 51
|
||||||
|
gpiochip: 1
|
||||||
|
line: 19
|
||||||
|
Busy: # GPIO0_B3 (IO5, physical 35)
|
||||||
|
pin: 11
|
||||||
|
gpiochip: 0
|
||||||
|
line: 11
|
||||||
|
# Ant_sw: # GPIO1_C2 (IO3, physical 16)
|
||||||
|
# pin: 50
|
||||||
|
# gpiochip: 1
|
||||||
|
# line: 18
|
||||||
|
Enable_Pins:
|
||||||
|
- pin: 2 # GPIO0_A2 (physical 37)
|
||||||
|
gpiochip: 0
|
||||||
|
line: 2
|
||||||
|
- pin: 50 # GPIO1_C2 (physical 16)
|
||||||
|
gpiochip: 1
|
||||||
|
line: 18
|
||||||
|
spidev: spidev0.1
|
||||||
|
# CS: # GPIO0_A7 (SPI1_CSN1, physical 26)
|
||||||
|
# pin: 7
|
||||||
|
# gpiochip: 0
|
||||||
|
# line: 7
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
Meta:
|
||||||
|
name: RAK6421 + RAK13302 Slot 1
|
||||||
|
support: community # Promote when tested
|
||||||
|
compatible:
|
||||||
|
- ebyte-ecb41-pge # Armbian
|
||||||
|
|
||||||
|
Lora:
|
||||||
|
Module: sx1262
|
||||||
|
IRQ: # GPIO0_A5 (IO6, physical 15)
|
||||||
|
pin: 5
|
||||||
|
gpiochip: 0
|
||||||
|
line: 5
|
||||||
|
Reset: # GPIO0_A3 (IO4, physical 36)
|
||||||
|
pin: 3
|
||||||
|
gpiochip: 0
|
||||||
|
line: 3
|
||||||
|
Busy: # GPIO1_C3 (IO5, physical 18)
|
||||||
|
pin: 51
|
||||||
|
gpiochip: 1
|
||||||
|
line: 19
|
||||||
|
# Ant_sw: # GPIO1_C2 (IO3, physical 16)
|
||||||
|
# pin: 50
|
||||||
|
# gpiochip: 1
|
||||||
|
# line: 18
|
||||||
|
Enable_Pins:
|
||||||
|
- pin: 43 # GPIO1_B3 (physical 32)
|
||||||
|
gpiochip: 1
|
||||||
|
line: 11
|
||||||
|
- pin: 57 # GPIO1_D1 (physical 33)
|
||||||
|
gpiochip: 1
|
||||||
|
line: 25
|
||||||
|
DIO3_TCXO_VOLTAGE: true
|
||||||
|
DIO2_AS_RF_SWITCH: true
|
||||||
|
spidev: spidev0.0
|
||||||
|
# CS: # GPIO0_B6 (SPI1_CSN0, physical 24)
|
||||||
|
# pin: 14
|
||||||
|
# gpiochip: 0
|
||||||
|
# line: 14
|
||||||
|
TX_GAIN_LORA: [9, 9, 10, 11, 9, 8, 9, 10, 10, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 10, 9, 8]
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
Meta:
|
||||||
|
name: RAK6421 + RAK13302 Slot 2
|
||||||
|
support: community # Promote when tested
|
||||||
|
compatible:
|
||||||
|
- ebyte-ecb41-pge # Armbian
|
||||||
|
|
||||||
|
Lora:
|
||||||
|
Module: sx1262
|
||||||
|
IRQ: # GPIO0_B4 (IO6, physical 12)
|
||||||
|
pin: 12
|
||||||
|
gpiochip: 0
|
||||||
|
line: 12
|
||||||
|
Reset: # GPIO1_C3 (IO4, physical 18)
|
||||||
|
pin: 51
|
||||||
|
gpiochip: 1
|
||||||
|
line: 19
|
||||||
|
Busy: # GPIO0_B3 (IO5, physical 35)
|
||||||
|
pin: 11
|
||||||
|
gpiochip: 0
|
||||||
|
line: 11
|
||||||
|
# Ant_sw: # GPIO1_C2 (IO3, physical 16)
|
||||||
|
# pin: 50
|
||||||
|
# gpiochip: 1
|
||||||
|
# line: 18
|
||||||
|
Enable_Pins:
|
||||||
|
- pin: 2 # GPIO0_A2 (physical 37)
|
||||||
|
gpiochip: 0
|
||||||
|
line: 2
|
||||||
|
- pin: 50 # GPIO1_C2 (physical 16)
|
||||||
|
gpiochip: 1
|
||||||
|
line: 18
|
||||||
|
spidev: spidev0.1
|
||||||
|
# CS: # GPIO0_A7 (SPI1_CSN1, physical 26)
|
||||||
|
# pin: 7
|
||||||
|
# gpiochip: 0
|
||||||
|
# line: 7
|
||||||
|
TX_GAIN_LORA: [9, 9, 10, 11, 9, 8, 9, 10, 10, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 10, 9, 8]
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
Meta:
|
||||||
|
name: Waveshare SX1262
|
||||||
|
support: deprecated
|
||||||
|
compatible:
|
||||||
|
- ebyte-ecb41-pge # Armbian
|
||||||
|
|
||||||
|
Lora:
|
||||||
|
Module: sx1262 # Waveshare SX126X XXXM
|
||||||
|
DIO2_AS_RF_SWITCH: true
|
||||||
|
CS: # GPIO0_A1 (physical 40)
|
||||||
|
pin: 1
|
||||||
|
gpiochip: 0
|
||||||
|
line: 1
|
||||||
|
IRQ: # GPIO0_A3 (physical 36)
|
||||||
|
pin: 3
|
||||||
|
gpiochip: 0
|
||||||
|
line: 3
|
||||||
|
Busy: # GPIO0_A0 (physical 38)
|
||||||
|
pin: 0
|
||||||
|
gpiochip: 0
|
||||||
|
line: 0
|
||||||
|
Reset: # GPIO0_B4 (physical 12)
|
||||||
|
pin: 12
|
||||||
|
gpiochip: 0
|
||||||
|
line: 12
|
||||||
|
SX126X_ANT_SW: # GPIO1_B2 (physical 31)
|
||||||
|
pin: 42
|
||||||
|
gpiochip: 1
|
||||||
|
line: 10
|
||||||
|
spidev: spidev0.0
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# !! WARNING: Hats on the OK3506 board are installed "backwards" (facing outwards)
|
||||||
|
|
||||||
|
# MeshAdv-Pi E22-900M30S
|
||||||
|
# https://github.com/chrismyers2000/MeshAdv-Pi-Hat
|
||||||
|
Meta:
|
||||||
|
name: MeshAdv-Pi E22-900M30S
|
||||||
|
support: community
|
||||||
|
compatible:
|
||||||
|
- forlinx-ok3506-s12 # Armbian
|
||||||
|
|
||||||
|
Lora:
|
||||||
|
Module: sx1262
|
||||||
|
CS: # GPIO0_B0 (physical 40)
|
||||||
|
pin: 8
|
||||||
|
gpiochip: 0
|
||||||
|
line: 8
|
||||||
|
IRQ: # GPIO3_B0 (physical 36)
|
||||||
|
pin: 104
|
||||||
|
gpiochip: 3
|
||||||
|
line: 8
|
||||||
|
Busy: # GPIO0_B1 (physical 38)
|
||||||
|
pin: 9
|
||||||
|
gpiochip: 0
|
||||||
|
line: 9
|
||||||
|
Reset: # GPIO0_B6 (physical 12)
|
||||||
|
pin: 14
|
||||||
|
gpiochip: 0
|
||||||
|
line: 14
|
||||||
|
TXen: # GPIO0_A3 (physical 33)
|
||||||
|
pin: 3
|
||||||
|
gpiochip: 0
|
||||||
|
line: 3
|
||||||
|
RXen: # GPIO0_A2 (physical 32)
|
||||||
|
pin: 2
|
||||||
|
gpiochip: 0
|
||||||
|
line: 2
|
||||||
|
DIO3_TCXO_VOLTAGE: true
|
||||||
|
# Only for E22-900M33S:
|
||||||
|
# Limit the output power to 8 dBm
|
||||||
|
# SX126X_MAX_POWER: 8
|
||||||
|
spidev: spidev0.0
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# !! WARNING: Hats on the OK3506 board are installed "backwards" (facing outwards)
|
||||||
|
|
||||||
|
# MeshAdv Mini E22-900M22S
|
||||||
|
# https://github.com/chrismyers2000/MeshAdv-Mini
|
||||||
|
Meta:
|
||||||
|
name: MeshAdv Mini E22-900M22S
|
||||||
|
support: community
|
||||||
|
compatible:
|
||||||
|
- forlinx-ok3506-s12 # Armbian
|
||||||
|
|
||||||
|
Lora:
|
||||||
|
Module: sx1262 # Ebyte E22-900M22S
|
||||||
|
CS: # GPIO0_C3 (physical 24, SPI0_CSN0)
|
||||||
|
pin: 19
|
||||||
|
gpiochip: 0
|
||||||
|
line: 19
|
||||||
|
IRQ: # GPIO3_B0 (physical 36)
|
||||||
|
pin: 104
|
||||||
|
gpiochip: 3
|
||||||
|
line: 8
|
||||||
|
Busy: # GPIO0_B1 (physical 38)
|
||||||
|
pin: 9
|
||||||
|
gpiochip: 0
|
||||||
|
line: 9
|
||||||
|
Reset: # GPIO3_A6 (physical 18)
|
||||||
|
pin: 102
|
||||||
|
gpiochip: 3
|
||||||
|
line: 6
|
||||||
|
RXen: # GPIO0_A2 (physical 32)
|
||||||
|
pin: 2
|
||||||
|
gpiochip: 0
|
||||||
|
line: 2
|
||||||
|
DIO2_AS_RF_SWITCH: true
|
||||||
|
DIO3_TCXO_VOLTAGE: true
|
||||||
|
spidev: spidev0.0
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
# !! WARNING: Hats on the OK3506 board are installed "backwards" (facing outwards)
|
||||||
|
|
||||||
|
Meta:
|
||||||
|
name: RAK6421 + RAK13300 Slot 1
|
||||||
|
support: community # Promote when tested
|
||||||
|
compatible:
|
||||||
|
- forlinx-ok3506-s12 # Armbian
|
||||||
|
|
||||||
|
Lora:
|
||||||
|
Module: sx1262
|
||||||
|
IRQ: # GPIO3_B5 (IO6, physical 15)
|
||||||
|
pin: 109
|
||||||
|
gpiochip: 3
|
||||||
|
line: 13
|
||||||
|
Reset: # GPIO3_B0 (IO4, physical 36)
|
||||||
|
pin: 104
|
||||||
|
gpiochip: 3
|
||||||
|
line: 8
|
||||||
|
Busy: # GPIO3_A6 (IO5, physical 18)
|
||||||
|
pin: 102
|
||||||
|
gpiochip: 3
|
||||||
|
line: 6
|
||||||
|
# Ant_sw: # GPIO0_A3 (IO3, physical 33)
|
||||||
|
# pin: 3
|
||||||
|
# gpiochip: 0
|
||||||
|
# line: 3
|
||||||
|
Enable_Pins:
|
||||||
|
- pin: 2 # GPIO0_A2 (physical 32)
|
||||||
|
gpiochip: 0
|
||||||
|
line: 2
|
||||||
|
- pin: 3 # GPIO0_A3 (physical 33)
|
||||||
|
gpiochip: 0
|
||||||
|
line: 3
|
||||||
|
DIO3_TCXO_VOLTAGE: true
|
||||||
|
DIO2_AS_RF_SWITCH: true
|
||||||
|
spidev: spidev0.0
|
||||||
|
# CS: # GPIO0_C3 (SPI0_CSN0, physical 24)
|
||||||
|
# pin: 19
|
||||||
|
# gpiochip: 0
|
||||||
|
# line: 19
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# !! WARNING: Hats on the OK3506 board are installed "backwards" (facing outwards)
|
||||||
|
|
||||||
|
Meta:
|
||||||
|
name: RAK6421 + RAK13300 Slot 2
|
||||||
|
support: community # Promote when tested
|
||||||
|
compatible:
|
||||||
|
- forlinx-ok3506-s12 # Armbian
|
||||||
|
|
||||||
|
Lora:
|
||||||
|
Module: sx1262
|
||||||
|
IRQ: # GPIO0_B6 (IO6, physical 12)
|
||||||
|
pin: 14
|
||||||
|
gpiochip: 0
|
||||||
|
line: 14
|
||||||
|
Reset: # GPIO3_A6 (IO4, physical 18)
|
||||||
|
pin: 102
|
||||||
|
gpiochip: 3
|
||||||
|
line: 6
|
||||||
|
Busy: # GPIO0_B2 (IO5, physical 35)
|
||||||
|
pin: 10
|
||||||
|
gpiochip: 0
|
||||||
|
line: 10
|
||||||
|
# Ant_sw: # GPIO3_A7 (IO3, physical 16)
|
||||||
|
# pin: 103
|
||||||
|
# gpiochip: 3
|
||||||
|
# line: 7
|
||||||
|
Enable_Pins:
|
||||||
|
- pin: 106 # GPIO3_B2 (physical 37)
|
||||||
|
gpiochip: 3
|
||||||
|
line: 10
|
||||||
|
- pin: 103 # GPIO3_A7 (physical 16)
|
||||||
|
gpiochip: 3
|
||||||
|
line: 7
|
||||||
|
spidev: spidev0.1
|
||||||
|
# CS: # GPIO0_B7 (SPI0_CSN1, physical 26)
|
||||||
|
# pin: 15
|
||||||
|
# gpiochip: 0
|
||||||
|
# line: 15
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# !! WARNING: Hats on the OK3506 board are installed "backwards" (facing outwards)
|
||||||
|
|
||||||
|
Meta:
|
||||||
|
name: RAK6421 + RAK13302 Slot 1
|
||||||
|
support: community # Promote when tested
|
||||||
|
compatible:
|
||||||
|
- forlinx-ok3506-s12 # Armbian
|
||||||
|
|
||||||
|
Lora:
|
||||||
|
Module: sx1262
|
||||||
|
IRQ: # GPIO3_B5 (IO6, physical 15)
|
||||||
|
pin: 109
|
||||||
|
gpiochip: 3
|
||||||
|
line: 13
|
||||||
|
Reset: # GPIO3_B0 (IO4, physical 36)
|
||||||
|
pin: 104
|
||||||
|
gpiochip: 3
|
||||||
|
line: 8
|
||||||
|
Busy: # GPIO3_A6 (IO5, physical 18)
|
||||||
|
pin: 102
|
||||||
|
gpiochip: 3
|
||||||
|
line: 6
|
||||||
|
# Ant_sw: # GPIO0_A3 (IO3, physical 33)
|
||||||
|
# pin: 3
|
||||||
|
# gpiochip: 0
|
||||||
|
# line: 3
|
||||||
|
Enable_Pins:
|
||||||
|
- pin: 2 # GPIO0_A2 (physical 32)
|
||||||
|
gpiochip: 0
|
||||||
|
line: 2
|
||||||
|
- pin: 3 # GPIO0_A3 (physical 33)
|
||||||
|
gpiochip: 0
|
||||||
|
line: 3
|
||||||
|
DIO3_TCXO_VOLTAGE: true
|
||||||
|
DIO2_AS_RF_SWITCH: true
|
||||||
|
spidev: spidev0.0
|
||||||
|
# CS: # GPIO0_C3 (SPI0_CSN0, physical 24)
|
||||||
|
# pin: 19
|
||||||
|
# gpiochip: 0
|
||||||
|
# line: 19
|
||||||
|
TX_GAIN_LORA: [9, 9, 10, 11, 9, 8, 9, 10, 10, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 10, 9, 8]
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# !! WARNING: Hats on the OK3506 board are installed "backwards" (facing outwards)
|
||||||
|
|
||||||
|
Meta:
|
||||||
|
name: RAK6421 + RAK13302 Slot 2
|
||||||
|
support: community # Promote when tested
|
||||||
|
compatible:
|
||||||
|
- forlinx-ok3506-s12 # Armbian
|
||||||
|
|
||||||
|
Lora:
|
||||||
|
Module: sx1262
|
||||||
|
IRQ: # GPIO0_B6 (IO6, physical 12)
|
||||||
|
pin: 14
|
||||||
|
gpiochip: 0
|
||||||
|
line: 14
|
||||||
|
Reset: # GPIO3_A6 (IO4, physical 18)
|
||||||
|
pin: 102
|
||||||
|
gpiochip: 3
|
||||||
|
line: 6
|
||||||
|
Busy: # GPIO0_B2 (IO5, physical 35)
|
||||||
|
pin: 10
|
||||||
|
gpiochip: 0
|
||||||
|
line: 10
|
||||||
|
# Ant_sw: # GPIO3_A7 (IO3, physical 16)
|
||||||
|
# pin: 103
|
||||||
|
# gpiochip: 3
|
||||||
|
# line: 7
|
||||||
|
Enable_Pins:
|
||||||
|
- pin: 106 # GPIO3_B2 (physical 37)
|
||||||
|
gpiochip: 3
|
||||||
|
line: 10
|
||||||
|
- pin: 103 # GPIO3_A7 (physical 16)
|
||||||
|
gpiochip: 3
|
||||||
|
line: 7
|
||||||
|
spidev: spidev0.1
|
||||||
|
# CS: # GPIO0_B7 (SPI0_CSN1, physical 26)
|
||||||
|
# pin: 15
|
||||||
|
# gpiochip: 0
|
||||||
|
# line: 15
|
||||||
|
TX_GAIN_LORA: [9, 9, 10, 11, 9, 8, 9, 10, 10, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 10, 9, 8]
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# !! WARNING: Hats on the OK3506 board are installed "backwards" (facing outwards)
|
||||||
|
|
||||||
|
Meta:
|
||||||
|
name: Waveshare SX1262
|
||||||
|
support: deprecated
|
||||||
|
compatible:
|
||||||
|
- forlinx-ok3506-s12 # Armbian
|
||||||
|
|
||||||
|
Lora:
|
||||||
|
Module: sx1262 # Waveshare SX126X XXXM
|
||||||
|
DIO2_AS_RF_SWITCH: true
|
||||||
|
CS: # GPIO0_B0 (physical 40)
|
||||||
|
pin: 8
|
||||||
|
gpiochip: 0
|
||||||
|
line: 8
|
||||||
|
IRQ: # GPIO3_B0 (physical 36)
|
||||||
|
pin: 104
|
||||||
|
gpiochip: 3
|
||||||
|
line: 8
|
||||||
|
Busy: # GPIO0_B1 (physical 38)
|
||||||
|
pin: 9
|
||||||
|
gpiochip: 0
|
||||||
|
line: 9
|
||||||
|
Reset: # GPIO0_B6 (physical 12)
|
||||||
|
pin: 14
|
||||||
|
gpiochip: 0
|
||||||
|
line: 14
|
||||||
|
SX126X_ANT_SW: # GPIO3_B3 (physical 31)
|
||||||
|
pin: 107
|
||||||
|
gpiochip: 3
|
||||||
|
line: 11
|
||||||
|
spidev: spidev0.0
|
||||||
+93
-79
@@ -102,7 +102,7 @@ build_unflags =
|
|||||||
-std=gnu++11
|
-std=gnu++11
|
||||||
build_flags = ${env.build_flags} -Os
|
build_flags = ${env.build_flags} -Os
|
||||||
-std=gnu++17
|
-std=gnu++17
|
||||||
build_src_filter = ${env.build_src_filter} -<platform/portduino/> -<graphics/niche/>
|
build_src_filter = ${env.build_src_filter} -<platform/portduino/> -<graphics/niche/> -<modules/Native/>
|
||||||
|
|
||||||
; Common libs for communicating over TCP/IP networks such as MQTT
|
; Common libs for communicating over TCP/IP networks such as MQTT
|
||||||
[networking_base]
|
[networking_base]
|
||||||
@@ -131,103 +131,117 @@ lib_deps =
|
|||||||
; Common libs for environmental measurements in telemetry module
|
; Common libs for environmental measurements in telemetry module
|
||||||
[environmental_base]
|
[environmental_base]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
# renovate: datasource=custom.pio depName=Adafruit BusIO packageName=adafruit/library/Adafruit BusIO
|
# renovate: datasource=github-tags depName=Adafruit BusIO packageName=adafruit/Adafruit_BusIO
|
||||||
adafruit/Adafruit BusIO@1.17.4
|
https://github.com/adafruit/Adafruit_BusIO/archive/refs/tags/1.17.4.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit Unified Sensor packageName=adafruit/library/Adafruit Unified Sensor
|
# renovate: datasource=github-tags depName=Adafruit Unified Sensor packageName=adafruit/Adafruit_Sensor
|
||||||
adafruit/Adafruit Unified Sensor@1.1.15
|
https://github.com/adafruit/Adafruit_Sensor/archive/refs/tags/1.1.15.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit BMP280 packageName=adafruit/library/Adafruit BMP280 Library
|
# renovate: datasource=github-tags depName=Adafruit GFX packageName=adafruit/Adafruit-GFX-Library
|
||||||
adafruit/Adafruit BMP280 Library@3.0.0
|
https://github.com/adafruit/Adafruit-GFX-Library/archive/refs/tags/1.12.6.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit BMP085 packageName=adafruit/library/Adafruit BMP085 Library
|
# renovate: datasource=github-tags depName=NeoPixel packageName=adafruit/Adafruit_NeoPixel
|
||||||
adafruit/Adafruit BMP085 Library@1.2.4
|
https://github.com/adafruit/Adafruit_NeoPixel/archive/refs/tags/1.15.4.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit BME280 packageName=adafruit/library/Adafruit BME280 Library
|
# renovate: datasource=github-tags depName=Adafruit SSD1306 packageName=adafruit/Adafruit_SSD1306
|
||||||
adafruit/Adafruit BME280 Library@2.3.0
|
https://github.com/adafruit/Adafruit_SSD1306/archive/refs/tags/2.5.16.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit DPS310 packageName=adafruit/library/Adafruit DPS310
|
# renovate: datasource=github-tags depName=Adafruit BMP280 packageName=adafruit/Adafruit_BMP280_Library
|
||||||
adafruit/Adafruit DPS310@1.1.6
|
https://github.com/adafruit/Adafruit_BMP280_Library/archive/refs/tags/3.0.0.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit MCP9808 packageName=adafruit/library/Adafruit MCP9808 Library
|
# renovate: datasource=github-tags depName=Adafruit BMP085 packageName=adafruit/Adafruit-BMP085-Library
|
||||||
adafruit/Adafruit MCP9808 Library@2.0.2
|
https://github.com/adafruit/Adafruit-BMP085-Library/archive/refs/tags/1.2.4.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit INA260 packageName=adafruit/library/Adafruit INA260 Library
|
# renovate: datasource=github-tags depName=Adafruit BME280 packageName=adafruit/Adafruit_BME280_Library
|
||||||
adafruit/Adafruit INA260 Library@1.5.3
|
https://github.com/adafruit/Adafruit_BME280_Library/archive/refs/tags/2.3.0.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit INA219 packageName=adafruit/library/Adafruit INA219
|
# renovate: datasource=github-tags depName=Adafruit DPS310 packageName=adafruit/Adafruit_DPS310
|
||||||
adafruit/Adafruit INA219@1.2.3
|
https://github.com/adafruit/Adafruit_DPS310/archive/refs/tags/1.1.6.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit MPU6050 packageName=adafruit/library/Adafruit MPU6050
|
# renovate: datasource=github-tags depName=Adafruit SH110x packageName=adafruit/Adafruit_SH110x
|
||||||
adafruit/Adafruit MPU6050@2.2.9
|
https://github.com/adafruit/Adafruit_SH110x/archive/refs/tags/2.1.14.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit LIS3DH packageName=adafruit/library/Adafruit LIS3DH
|
# renovate: datasource=github-tags depName=Adafruit MCP9808 packageName=adafruit/Adafruit_MCP9808_Library
|
||||||
adafruit/Adafruit LIS3DH@1.3.0
|
https://github.com/adafruit/Adafruit_MCP9808_Library/archive/refs/tags/2.0.2.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit AHTX0 packageName=adafruit/library/Adafruit AHTX0
|
# renovate: datasource=github-tags depName=Adafruit INA260 packageName=adafruit/Adafruit_INA260
|
||||||
adafruit/Adafruit AHTX0@2.0.6
|
https://github.com/adafruit/Adafruit_INA260/archive/refs/tags/1.5.3.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit LSM6DS packageName=adafruit/library/Adafruit LSM6DS
|
# renovate: datasource=github-tags depName=Adafruit INA219 packageName=adafruit/Adafruit_INA219
|
||||||
adafruit/Adafruit LSM6DS@4.7.4
|
https://github.com/adafruit/Adafruit_INA219/archive/refs/tags/1.2.3.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit TSL2591 packageName=adafruit/library/Adafruit TSL2591 Library
|
# renovate: datasource=github-tags depName=Adafruit MPU6050 packageName=adafruit/Adafruit_MPU6050
|
||||||
adafruit/Adafruit TSL2591 Library@1.4.5
|
https://github.com/adafruit/Adafruit_MPU6050/archive/refs/tags/2.2.9.zip
|
||||||
# renovate: datasource=custom.pio depName=EmotiBit MLX90632 packageName=emotibit/library/EmotiBit MLX90632
|
# renovate: datasource=github-tags depName=Adafruit LIS3DH packageName=adafruit/Adafruit_LIS3DH
|
||||||
emotibit/EmotiBit MLX90632@1.0.8
|
https://github.com/adafruit/Adafruit_LIS3DH/archive/refs/tags/1.3.0.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit MLX90614 packageName=adafruit/library/Adafruit MLX90614 Library
|
# renovate: datasource=github-tags depName=Adafruit AHTX0 packageName=adafruit/Adafruit_AHTX0
|
||||||
adafruit/Adafruit MLX90614 Library@2.1.6
|
https://github.com/adafruit/Adafruit_AHTX0/archive/refs/tags/2.0.6.zip
|
||||||
|
# renovate: datasource=github-tags depName=Adafruit LSM6DS packageName=adafruit/Adafruit_LSM6DS
|
||||||
|
https://github.com/adafruit/Adafruit_LSM6DS/archive/refs/tags/4.7.4.zip
|
||||||
|
# renovate: datasource=github-tags depName=Adafruit TSL2591 packageName=adafruit/Adafruit_TSL2591_Library
|
||||||
|
https://github.com/adafruit/Adafruit_TSL2591_Library/archive/refs/tags/1.4.5.zip
|
||||||
|
# renovate: datasource=github-tags depName=EmotiBit MLX90632 packageName=emotibit/EmotiBit_MLX90632
|
||||||
|
https://github.com/EmotiBit/EmotiBit_MLX90632/archive/refs/tags/v1.0.8.zip
|
||||||
|
# renovate: datasource=github-tags depName=Adafruit MLX90614 packageName=adafruit/Adafruit_MLX90614
|
||||||
|
https://github.com/adafruit/Adafruit-MLX90614-Library/archive/refs/tags/2.1.6.zip
|
||||||
# renovate: datasource=git-refs depName=INA3221 packageName=https://github.com/sgtwilko/INA3221 gitBranch=FixOverflow
|
# renovate: datasource=git-refs depName=INA3221 packageName=https://github.com/sgtwilko/INA3221 gitBranch=FixOverflow
|
||||||
https://github.com/sgtwilko/INA3221/archive/bb03d7e9bfcc74fc798838a54f4f99738f29fc6a.zip
|
https://github.com/sgtwilko/INA3221/archive/bb03d7e9bfcc74fc798838a54f4f99738f29fc6a.zip
|
||||||
# renovate: datasource=custom.pio depName=QMC5883L Compass packageName=mprograms/library/QMC5883LCompass
|
# renovate: datasource=github-tags depName=QMC5883L Compass packageName=mprograms/QMC5883LCompass
|
||||||
mprograms/QMC5883LCompass@1.2.3
|
https://github.com/mprograms/QMC5883LCompass/archive/refs/tags/v1.2.3.zip
|
||||||
# renovate: datasource=custom.pio depName=DFRobot_RTU packageName=dfrobot/library/DFRobot_RTU
|
# renovate: datasource=github-tags depName=DFRobot_RTU packageName=dfrobot/DFRobot_RTU
|
||||||
dfrobot/DFRobot_RTU@1.0.6
|
https://github.com/DFRobot/DFRobot_RTU/archive/refs/tags/V1.0.6.zip
|
||||||
# renovate: datasource=git-refs depName=DFRobot_RainfallSensor packageName=https://github.com/DFRobot/DFRobot_RainfallSensor gitBranch=master
|
# renovate: datasource=git-refs depName=DFRobot_RainfallSensor packageName=https://github.com/DFRobot/DFRobot_RainfallSensor gitBranch=master
|
||||||
https://github.com/DFRobot/DFRobot_RainfallSensor/archive/38fea5e02b40a5430be6dab39a99a6f6347d667e.zip
|
https://github.com/DFRobot/DFRobot_RainfallSensor/archive/38fea5e02b40a5430be6dab39a99a6f6347d667e.zip
|
||||||
# renovate: datasource=custom.pio depName=INA226 packageName=robtillaart/library/INA226
|
# renovate: datasource=github-tags depName=INA226 packageName=robtillaart/INA226
|
||||||
robtillaart/INA226@0.6.6
|
https://github.com/RobTillaart/INA226/archive/refs/tags/0.6.6.zip
|
||||||
# renovate: datasource=custom.pio depName=SparkFun MAX3010x packageName=sparkfun/library/SparkFun MAX3010x Pulse and Proximity Sensor Library
|
# renovate: datasource=github-tags depName=SparkFun MAX3010x packageName=sparkfun/SparkFun_MAX3010x_Sensor_Library
|
||||||
sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2
|
https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/archive/refs/tags/v1.1.2.zip
|
||||||
# renovate: datasource=custom.pio depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/library/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library
|
# renovate: datasource=github-tags depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/SparkFun_ICM-20948_ArduinoLibrary
|
||||||
sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.2
|
https://github.com/sparkfun/SparkFun_ICM-20948_ArduinoLibrary/archive/refs/tags/v1.3.2.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit LTR390 Library packageName=adafruit/library/Adafruit LTR390 Library
|
# renovate: datasource=github-tags depName=Adafruit LTR390 Library packageName=adafruit/Adafruit_LTR390
|
||||||
adafruit/Adafruit LTR390 Library@1.1.2
|
https://github.com/adafruit/Adafruit_LTR390/archive/refs/tags/1.1.2.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit PCT2075 packageName=adafruit/library/Adafruit PCT2075
|
# renovate: datasource=github-tags depName=Adafruit PCT2075 packageName=adafruit/Adafruit_PCT2075
|
||||||
adafruit/Adafruit PCT2075@1.0.6
|
https://github.com/adafruit/Adafruit_PCT2075/archive/refs/tags/1.0.6.zip
|
||||||
# renovate: datasource=custom.pio depName=DFRobot_BMM150 packageName=dfrobot/library/DFRobot_BMM150
|
# renovate: datasource=github-tags depName=DFRobot_BMM150 packageName=dfrobot/DFRobot_BMM150
|
||||||
dfrobot/DFRobot_BMM150@1.0.0
|
https://github.com/DFRobot/DFRobot_BMM150/archive/refs/tags/V1.0.0.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit_TSL2561 packageName=adafruit/library/Adafruit TSL2561
|
# renovate: datasource=github-tags depName=Adafruit_TSL2561 packageName=adafruit/Adafruit_TSL2561
|
||||||
adafruit/Adafruit TSL2561@1.1.3
|
https://github.com/adafruit/Adafruit_TSL2561/archive/refs/tags/1.1.3.zip
|
||||||
# renovate: datasource=custom.pio depName=BH1750_WE packageName=wollewald/library/BH1750_WE
|
# renovate: datasource=github-tags depName=BH1750_WE packageName=wollewald/BH1750_WE
|
||||||
wollewald/BH1750_WE@1.1.10
|
https://github.com/wollewald/BH1750_WE/archive/refs/tags/1.1.10.zip
|
||||||
|
|
||||||
; Common environmental sensor libraries (not included in native / portduino)
|
; Common environmental sensor libraries (not included in native / portduino)
|
||||||
[environmental_extra_common]
|
[environmental_extra_common]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
# renovate: datasource=custom.pio depName=Adafruit BMP3XX packageName=adafruit/library/Adafruit BMP3XX Library
|
# renovate: datasource=github-tags depName=Adafruit BMP3XX packageName=adafruit/Adafruit_BMP3XX
|
||||||
adafruit/Adafruit BMP3XX Library@2.1.6
|
https://github.com/adafruit/Adafruit_BMP3XX/archive/refs/tags/2.1.6.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit MAX1704X packageName=adafruit/library/Adafruit MAX1704X
|
# renovate: datasource=github-tags depName=Adafruit MAX1704X packageName=adafruit/Adafruit_MAX1704X
|
||||||
adafruit/Adafruit MAX1704X@1.0.3
|
https://github.com/adafruit/Adafruit_MAX1704X/archive/refs/tags/1.0.3.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit LPS2X packageName=adafruit/library/Adafruit LPS2X
|
# renovate: datasource=github-tags depName=Adafruit SHTC3 packageName=adafruit/Adafruit_SHTC3
|
||||||
adafruit/Adafruit LPS2X@2.0.6
|
https://github.com/adafruit/Adafruit_SHTC3/archive/refs/tags/1.0.2.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit VEML7700 packageName=adafruit/library/Adafruit VEML7700 Library
|
# renovate: datasource=github-tags depName=Adafruit LPS2X packageName=adafruit/Adafruit_LPS2X
|
||||||
adafruit/Adafruit VEML7700 Library@2.1.6
|
https://github.com/adafruit/Adafruit_LPS2X/archive/refs/tags/2.0.6.zip
|
||||||
# renovate: datasource=custom.pio depName=SparkFun Qwiic Scale NAU7802 packageName=sparkfun/library/SparkFun Qwiic Scale NAU7802 Arduino Library
|
# renovate: datasource=github-tags depName=Adafruit SHT31 packageName=adafruit/Adafruit_SHT31
|
||||||
sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6
|
https://github.com/adafruit/Adafruit_SHT31/archive/refs/tags/2.2.2.zip
|
||||||
|
# renovate: datasource=github-tags depName=Adafruit VEML7700 packageName=adafruit/Adafruit_VEML7700
|
||||||
|
https://github.com/adafruit/Adafruit_VEML7700/archive/refs/tags/2.1.6.zip
|
||||||
|
# renovate: datasource=github-tags depName=Adafruit SHT4x packageName=adafruit/Adafruit_SHT4X
|
||||||
|
https://github.com/adafruit/Adafruit_SHT4X/archive/refs/tags/1.0.5.zip
|
||||||
|
# renovate: datasource=github-tags depName=SparkFun Qwiic Scale NAU7802 packageName=sparkfun/SparkFun_Qwiic_Scale_NAU7802_Arduino_Library
|
||||||
|
https://github.com/sparkfun/SparkFun_Qwiic_Scale_NAU7802_Arduino_Library/archive/refs/tags/v1.0.6.zip
|
||||||
# renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001
|
# renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001
|
||||||
closedcube/ClosedCube OPT3001@1.1.2
|
closedcube/ClosedCube OPT3001@1.1.2
|
||||||
# renovate: datasource=git-refs depName=meshtastic-DFRobot_LarkWeatherStation packageName=https://github.com/meshtastic/DFRobot_LarkWeatherStation gitBranch=master
|
# renovate: datasource=git-refs depName=meshtastic-DFRobot_LarkWeatherStation packageName=https://github.com/meshtastic/DFRobot_LarkWeatherStation gitBranch=master
|
||||||
https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip
|
https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip
|
||||||
# renovate: datasource=custom.pio depName=Sensirion Core packageName=sensirion/library/Sensirion Core
|
# renovate: datasource=github-tags depName=Sensirion Core packageName=sensirion/arduino-core
|
||||||
sensirion/Sensirion Core@0.7.3
|
https://github.com/Sensirion/arduino-core/archive/refs/tags/0.7.3.zip
|
||||||
# renovate: datasource=custom.pio depName=Sensirion I2C SCD4x packageName=sensirion/library/Sensirion I2C SCD4x
|
# renovate: datasource=github-tags depName=Sensirion I2C SCD4x packageName=sensirion/arduino-i2c-scd4x
|
||||||
sensirion/Sensirion I2C SCD4x@1.1.0
|
https://github.com/Sensirion/arduino-i2c-scd4x/archive/refs/tags/1.1.0.zip
|
||||||
# renovate: datasource=custom.pio depName=Sensirion I2C SFA3x packageName=sensirion/library/Sensirion I2C SFA3x
|
# renovate: datasource=github-tags depName=Sensirion I2C SFA3x packageName=sensirion/arduino-i2c-sfa3x
|
||||||
sensirion/Sensirion I2C SFA3x@1.0.0
|
https://github.com/Sensirion/arduino-i2c-sfa3x/archive/refs/tags/1.0.0.zip
|
||||||
# renovate: datasource=custom.pio depName=Sensirion I2C SCD30 packageName=sensirion/library/Sensirion I2C SCD30
|
# renovate: datasource=github-tags depName=Sensirion I2C SCD30 packageName=sensirion/arduino-i2c-scd30
|
||||||
sensirion/Sensirion I2C SCD30@1.0.0
|
https://github.com/Sensirion/arduino-i2c-scd30/archive/refs/tags/1.0.0.zip
|
||||||
# renovate: datasource=custom.pio depName=arduino-sht packageName=sensirion/library/arduino-sht
|
# renovate: datasource=github-tags depName=arduino-sht packageName=sensirion/arduino-sht
|
||||||
sensirion/arduino-sht@1.2.6
|
https://github.com/Sensirion/arduino-sht/archive/refs/tags/v1.2.6.zip
|
||||||
|
|
||||||
; Environmental sensors with BSEC2 (Bosch proprietary IAQ)
|
; Environmental sensors with BSEC2 (Bosch proprietary IAQ)
|
||||||
[environmental_extra]
|
[environmental_extra]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${environmental_extra_common.lib_deps}
|
${environmental_extra_common.lib_deps}
|
||||||
# renovate: datasource=custom.pio depName=Bosch BSEC2 packageName=boschsensortec/library/bsec2
|
# renovate: datasource=github-tags depName=Bosch BSEC2 packageName=boschsensortec/Bosch-BSEC2-Library
|
||||||
boschsensortec/bsec2@1.10.2610
|
https://github.com/boschsensortec/Bosch-BSEC2-Library/archive/refs/tags/1.10.2610.zip
|
||||||
# renovate: datasource=custom.pio depName=Bosch BME68x packageName=boschsensortec/library/BME68x Sensor Library
|
# renovate: datasource=github-tags depName=Bosch BME68x packageName=boschsensortec/Bosch-BME68x-Library
|
||||||
boschsensortec/BME68x Sensor Library@1.3.40408
|
https://github.com/boschsensortec/Bosch-BME68x-Library/archive/refs/tags/v1.3.40408.zip
|
||||||
|
|
||||||
; Environmental sensors without BSEC (saves ~3.5KB DRAM for original ESP32 targets)
|
; Environmental sensors without BSEC (saves ~3.5KB DRAM for original ESP32 targets)
|
||||||
[environmental_extra_no_bsec]
|
[environmental_extra_no_bsec]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${environmental_extra_common.lib_deps}
|
${environmental_extra_common.lib_deps}
|
||||||
# renovate: datasource=custom.pio depName=Adafruit_BME680 packageName=adafruit/library/Adafruit BME680 Library
|
# renovate: datasource=github-tags depName=Adafruit_BME680 packageName=adafruit/Adafruit_BME680
|
||||||
adafruit/Adafruit BME680 Library@2.0.6
|
https://github.com/adafruit/Adafruit_BME680/archive/refs/tags/2.0.6.zip
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ void RedirectablePrint::log_to_serial(const char *logLevel, const char *format,
|
|||||||
if (color) {
|
if (color) {
|
||||||
::printf("\u001b[0m");
|
::printf("\u001b[0m");
|
||||||
}
|
}
|
||||||
::printf("| %02d:%02d:%02d %u ", hour, min, sec, millis() / 1000);
|
::printf("| %02d:%02d:%02d %u.%03u ", hour, min, sec, millis() / 1000, millis() % 1000);
|
||||||
#else
|
#else
|
||||||
printf("%s ", logLevel);
|
printf("%s ", logLevel);
|
||||||
if (color) {
|
if (color) {
|
||||||
@@ -151,7 +151,7 @@ void RedirectablePrint::log_to_serial(const char *logLevel, const char *format,
|
|||||||
if (color) {
|
if (color) {
|
||||||
::printf("\u001b[0m");
|
::printf("\u001b[0m");
|
||||||
}
|
}
|
||||||
::printf("| ??:??:?? %u ", millis() / 1000);
|
::printf("| ??:??:?? %u.%03u ", millis() / 1000, millis() % 1000);
|
||||||
#else
|
#else
|
||||||
printf("%s ", logLevel);
|
printf("%s ", logLevel);
|
||||||
if (color) {
|
if (color) {
|
||||||
|
|||||||
@@ -1,10 +1,85 @@
|
|||||||
#include "concurrency/BinarySemaphorePosix.h"
|
#include "concurrency/BinarySemaphorePosix.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#ifndef HAS_FREE_RTOS
|
#ifndef HAS_FREE_RTOS
|
||||||
|
|
||||||
namespace concurrency
|
namespace concurrency
|
||||||
{
|
{
|
||||||
|
#ifdef ARCH_PORTDUINO
|
||||||
|
|
||||||
|
BinarySemaphorePosix::BinarySemaphorePosix()
|
||||||
|
{
|
||||||
|
if (pthread_mutex_init(&mutex, NULL) != 0) {
|
||||||
|
throw std::runtime_error("pthread_mutex_init failed");
|
||||||
|
}
|
||||||
|
if (pthread_cond_init(&cond, NULL) != 0) {
|
||||||
|
pthread_mutex_destroy(&mutex);
|
||||||
|
throw std::runtime_error("pthread_cond_init failed");
|
||||||
|
}
|
||||||
|
signaled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BinarySemaphorePosix::~BinarySemaphorePosix()
|
||||||
|
{
|
||||||
|
pthread_cond_destroy(&cond);
|
||||||
|
pthread_mutex_destroy(&mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns false if we timed out
|
||||||
|
*/
|
||||||
|
bool BinarySemaphorePosix::take(uint32_t msec)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&mutex);
|
||||||
|
|
||||||
|
if (!signaled) {
|
||||||
|
struct timespec ts;
|
||||||
|
clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
|
|
||||||
|
ts.tv_sec += msec / 1000;
|
||||||
|
ts.tv_nsec += (msec % 1000) * 1000000L;
|
||||||
|
if (ts.tv_nsec >= 1000000000L) {
|
||||||
|
ts.tv_sec += 1;
|
||||||
|
ts.tv_nsec -= 1000000000L;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!signaled) {
|
||||||
|
int rc = pthread_cond_timedwait(&cond, &mutex, &ts);
|
||||||
|
if (rc == ETIMEDOUT)
|
||||||
|
break;
|
||||||
|
if (rc != 0) {
|
||||||
|
// Some other error occurred
|
||||||
|
pthread_mutex_unlock(&mutex);
|
||||||
|
throw std::runtime_error("pthread_cond_timedwait failed: " + std::to_string(rc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wasSignaled = signaled;
|
||||||
|
signaled = false; // consume the signal (binary semaphore)
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&mutex);
|
||||||
|
return wasSignaled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinarySemaphorePosix::give()
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&mutex);
|
||||||
|
signaled = true;
|
||||||
|
pthread_cond_signal(&cond);
|
||||||
|
pthread_mutex_unlock(&mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
IRAM_ATTR void BinarySemaphorePosix::giveFromISR(BaseType_t *pxHigherPriorityTaskWoken)
|
||||||
|
{
|
||||||
|
give();
|
||||||
|
if (pxHigherPriorityTaskWoken)
|
||||||
|
*pxHigherPriorityTaskWoken = true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
BinarySemaphorePosix::BinarySemaphorePosix() {}
|
BinarySemaphorePosix::BinarySemaphorePosix() {}
|
||||||
|
|
||||||
@@ -22,7 +97,8 @@ bool BinarySemaphorePosix::take(uint32_t msec)
|
|||||||
void BinarySemaphorePosix::give() {}
|
void BinarySemaphorePosix::give() {}
|
||||||
|
|
||||||
IRAM_ATTR void BinarySemaphorePosix::giveFromISR(BaseType_t *pxHigherPriorityTaskWoken) {}
|
IRAM_ATTR void BinarySemaphorePosix::giveFromISR(BaseType_t *pxHigherPriorityTaskWoken) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace concurrency
|
} // namespace concurrency
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
#include "../freertosinc.h"
|
#include "../freertosinc.h"
|
||||||
|
|
||||||
|
#ifdef ARCH_PORTDUINO
|
||||||
|
#include <pthread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace concurrency
|
namespace concurrency
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -9,7 +13,12 @@ namespace concurrency
|
|||||||
|
|
||||||
class BinarySemaphorePosix
|
class BinarySemaphorePosix
|
||||||
{
|
{
|
||||||
// SemaphoreHandle_t semaphore;
|
|
||||||
|
#ifdef ARCH_PORTDUINO
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
pthread_cond_t cond;
|
||||||
|
bool signaled;
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BinarySemaphorePosix();
|
BinarySemaphorePosix();
|
||||||
@@ -27,4 +36,4 @@ class BinarySemaphorePosix
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace concurrency
|
} // namespace concurrency
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ void EInkParallelDisplay::display(void)
|
|||||||
|
|
||||||
// Get pointers to internal buffers
|
// Get pointers to internal buffers
|
||||||
uint8_t *cur = epaper->currentBuffer();
|
uint8_t *cur = epaper->currentBuffer();
|
||||||
uint8_t *prev = epaper->previousBuffer(); // may be NULL on first init
|
const uint8_t *prev = epaper->previousBuffer(); // may be NULL on first init
|
||||||
|
|
||||||
// Track changed row range while converting
|
// Track changed row range while converting
|
||||||
int newTop = h; // min changed row (initialized to out-of-range)
|
int newTop = h; // min changed row (initialized to out-of-range)
|
||||||
|
|||||||
@@ -163,9 +163,11 @@ void menuHandler::LoraRegionPicker(uint32_t duration)
|
|||||||
|
|
||||||
// Guard: without a reboot, reconfigure() applies the region directly.
|
// Guard: without a reboot, reconfigure() applies the region directly.
|
||||||
// Reject LORA_24 on sub-GHz-only hardware — getRadio() used to catch this post-reboot.
|
// Reject LORA_24 on sub-GHz-only hardware — getRadio() used to catch this post-reboot.
|
||||||
|
// TODO: change this to either use the validateLoraConfig() logic or at least check the region for wideLora
|
||||||
|
// rather than a hardcoded check for LORA_24.
|
||||||
if (selectedRegion == meshtastic_Config_LoRaConfig_RegionCode_LORA_24 &&
|
if (selectedRegion == meshtastic_Config_LoRaConfig_RegionCode_LORA_24 &&
|
||||||
!(RadioLibInterface::instance && RadioLibInterface::instance->wideLora())) {
|
!(RadioLibInterface::instance && RadioLibInterface::instance->wideLora())) {
|
||||||
LOG_WARN("Radio hardware does not support 2.4 GHz; ignoring LORA_24 selection");
|
LOG_WARN("Radio hardware does not support 2.4 GHz; ignoring region selection");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#if !(MESHTASTIC_EXCLUDE_PKI)
|
#if !(MESHTASTIC_EXCLUDE_PKI)
|
||||||
|
#include "HardwareRNG.h"
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
#include "aes-ccm.h"
|
#include "aes-ccm.h"
|
||||||
#include "meshUtils.h"
|
#include "meshUtils.h"
|
||||||
@@ -26,6 +27,15 @@ void CryptoEngine::generateKeyPair(uint8_t *pubKey, uint8_t *privKey)
|
|||||||
{
|
{
|
||||||
// Mix in any randomness we can, to make key generation stronger.
|
// Mix in any randomness we can, to make key generation stronger.
|
||||||
CryptRNG.begin(optstr(APP_VERSION));
|
CryptRNG.begin(optstr(APP_VERSION));
|
||||||
|
|
||||||
|
uint8_t hardwareEntropy[64] = {0};
|
||||||
|
if (HardwareRNG::fill(hardwareEntropy, sizeof(hardwareEntropy), true)) {
|
||||||
|
CryptRNG.stir(hardwareEntropy, sizeof(hardwareEntropy));
|
||||||
|
} else {
|
||||||
|
LOG_WARN("Hardware entropy unavailable, falling back to software RNG");
|
||||||
|
}
|
||||||
|
memset(hardwareEntropy, 0, sizeof(hardwareEntropy));
|
||||||
|
|
||||||
if (myNodeInfo.device_id.size == 16) {
|
if (myNodeInfo.device_id.size == 16) {
|
||||||
CryptRNG.stir(myNodeInfo.device_id.bytes, myNodeInfo.device_id.size);
|
CryptRNG.stir(myNodeInfo.device_id.bytes, myNodeInfo.device_id.size);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -32,8 +32,8 @@
|
|||||||
#define default_map_publish_interval_secs 60 * 60
|
#define default_map_publish_interval_secs 60 * 60
|
||||||
|
|
||||||
// Traffic management defaults
|
// Traffic management defaults
|
||||||
#define default_traffic_mgmt_position_precision_bits 24 // ~10m grid cells
|
#define default_traffic_mgmt_position_precision_bits 24 // ~10m grid cells
|
||||||
#define default_traffic_mgmt_position_min_interval_secs ONE_DAY // 1 day between identical positions
|
#define default_traffic_mgmt_position_min_interval_secs (ONE_DAY / 2) // 12 hours between identical positions
|
||||||
|
|
||||||
#ifdef USERPREFS_RINGTONE_NAG_SECS
|
#ifdef USERPREFS_RINGTONE_NAG_SECS
|
||||||
#define default_ringtone_nag_secs USERPREFS_RINGTONE_NAG_SECS
|
#define default_ringtone_nag_secs USERPREFS_RINGTONE_NAG_SECS
|
||||||
|
|||||||
@@ -0,0 +1,159 @@
|
|||||||
|
#include "HardwareRNG.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#if HAS_RADIO
|
||||||
|
#include "RadioLibInterface.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ARCH_NRF52)
|
||||||
|
#include <Adafruit_nRFCrypto.h>
|
||||||
|
extern Adafruit_nRFCrypto nRFCrypto;
|
||||||
|
#elif defined(ARCH_ESP32)
|
||||||
|
#include <esp_system.h>
|
||||||
|
#elif defined(ARCH_RP2040)
|
||||||
|
#include <Arduino.h>
|
||||||
|
#elif defined(ARCH_PORTDUINO)
|
||||||
|
#include <random>
|
||||||
|
#include <sys/random.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace HardwareRNG
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
void fillWithRandomDevice(uint8_t *buffer, size_t length)
|
||||||
|
{
|
||||||
|
std::random_device rd;
|
||||||
|
size_t offset = 0;
|
||||||
|
while (offset < length) {
|
||||||
|
uint32_t value = rd();
|
||||||
|
size_t toCopy = std::min(length - offset, sizeof(value));
|
||||||
|
memcpy(buffer + offset, &value, toCopy);
|
||||||
|
offset += toCopy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HAS_RADIO
|
||||||
|
bool mixWithLoRaEntropy(uint8_t *buffer, size_t length)
|
||||||
|
{
|
||||||
|
// Only attempt to pull entropy from the modem if it is initialized and exposes the helper.
|
||||||
|
// When the radio stack is disabled or has not yet been configured, we simply skip this step
|
||||||
|
// and return false so callers know no extra mixing occurred.
|
||||||
|
RadioLibInterface *radio = RadioLibInterface::instance;
|
||||||
|
if (!radio) {
|
||||||
|
LOG_ERROR("No radio instance available to provide entropy");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t chunkSize = 16;
|
||||||
|
uint8_t scratch[chunkSize];
|
||||||
|
size_t offset = 0;
|
||||||
|
bool mixed = false;
|
||||||
|
|
||||||
|
while (offset < length) {
|
||||||
|
size_t toCopy = std::min(length - offset, chunkSize);
|
||||||
|
|
||||||
|
// randomBytes() returns false if the modem does not support it or is not ready
|
||||||
|
// (for instance, when the radio is powered down). We break immediately to avoid
|
||||||
|
// blocking or returning partially-filled entropy and simply report failure.
|
||||||
|
if (!radio->randomBytes(scratch, toCopy)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < toCopy; ++i) {
|
||||||
|
buffer[offset + i] ^= scratch[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
mixed = true;
|
||||||
|
offset += toCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avoid leaving the modem-sourced bytes sitting on the stack longer than needed.
|
||||||
|
if (mixed) {
|
||||||
|
memset(scratch, 0, sizeof(scratch));
|
||||||
|
}
|
||||||
|
|
||||||
|
return mixed;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool fill(uint8_t *buffer, size_t length, bool useRadioEntropy)
|
||||||
|
{
|
||||||
|
if (!buffer || length == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool filled = false;
|
||||||
|
|
||||||
|
#if defined(ARCH_NRF52)
|
||||||
|
// The Nordic SDK RNG provides cryptographic-quality randomness backed by hardware.
|
||||||
|
nRFCrypto.begin();
|
||||||
|
auto result = nRFCrypto.Random.generate(buffer, length);
|
||||||
|
nRFCrypto.end();
|
||||||
|
filled = result;
|
||||||
|
#elif defined(ARCH_ESP32)
|
||||||
|
// ESP32 exposes a true RNG via esp_fill_random().
|
||||||
|
esp_fill_random(buffer, length);
|
||||||
|
filled = true;
|
||||||
|
#elif defined(ARCH_RP2040)
|
||||||
|
// RP2040 has a hardware random number generator accessible through the Arduino core.
|
||||||
|
size_t offset = 0;
|
||||||
|
while (offset < length) {
|
||||||
|
uint32_t value = rp2040.hwrand32();
|
||||||
|
size_t toCopy = std::min(length - offset, sizeof(value));
|
||||||
|
memcpy(buffer + offset, &value, toCopy);
|
||||||
|
offset += toCopy;
|
||||||
|
}
|
||||||
|
filled = true;
|
||||||
|
#elif defined(ARCH_PORTDUINO)
|
||||||
|
// Prefer the host OS RNG first when running under Portduino.
|
||||||
|
ssize_t generated = ::getrandom(buffer, length, 0);
|
||||||
|
if (generated == static_cast<ssize_t>(length)) {
|
||||||
|
filled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!filled) {
|
||||||
|
fillWithRandomDevice(buffer, length);
|
||||||
|
filled = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!filled) {
|
||||||
|
// As a last resort, fall back to std::random_device. This should only be reached
|
||||||
|
// if a platform-specific source was unavailable.
|
||||||
|
fillWithRandomDevice(buffer, length);
|
||||||
|
filled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HAS_RADIO
|
||||||
|
if (useRadioEntropy) {
|
||||||
|
// Best-effort: if the radio is active and can provide modem entropy, XOR it over the
|
||||||
|
// buffer to improve overall quality. We consider the filling a success if either a
|
||||||
|
// good platform RNG or the modem RNG provided data, so we return true as long as at
|
||||||
|
// least one of those steps succeeded.
|
||||||
|
filled = mixWithLoRaEntropy(buffer, length) || filled;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return filled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool seed(uint32_t &seedOut)
|
||||||
|
{
|
||||||
|
uint32_t candidate = 0;
|
||||||
|
if (!fill(reinterpret_cast<uint8_t *>(&candidate), sizeof(candidate), true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
seedOut = candidate;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace HardwareRNG
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace HardwareRNG
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill the provided buffer with random bytes sourced from the most
|
||||||
|
* appropriate hardware-backed RNG available on the current platform.
|
||||||
|
*
|
||||||
|
* @param buffer Destination buffer for random bytes
|
||||||
|
* @param length Number of bytes to write
|
||||||
|
* @param useRadioEntropy If true, attempt to mix radio entropy into the output as well.
|
||||||
|
* @return true if the buffer was fully populated with entropy, false on failure
|
||||||
|
*/
|
||||||
|
bool fill(uint8_t *buffer, size_t length, bool useRadioEntropy = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate a 32-bit seed value with hardware-backed randomness where possible.
|
||||||
|
*
|
||||||
|
* @param seedOut Destination for the generated seed value
|
||||||
|
* @return true if a seed was produced from a reliable entropy source
|
||||||
|
*/
|
||||||
|
bool seed(uint32_t &seedOut);
|
||||||
|
|
||||||
|
} // namespace HardwareRNG
|
||||||
@@ -71,12 +71,10 @@ template <typename T> bool LR11x0Interface<T>::init()
|
|||||||
|
|
||||||
RadioLibInterface::init();
|
RadioLibInterface::init();
|
||||||
|
|
||||||
limitPower(LR1110_MAX_POWER);
|
if (config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_LORA_24) { // clamp if wide freq range
|
||||||
|
limitPower(LR1120_MAX_POWER);
|
||||||
if ((power > LR1120_MAX_POWER) &&
|
} else {
|
||||||
(config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) { // clamp again if wide freq range
|
limitPower(LR1110_MAX_POWER); // default clamp for non-wide freq range
|
||||||
power = LR1120_MAX_POWER;
|
|
||||||
preambleLength = 12; // 12 is the default for operation above 2GHz
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LR11X0_RF_SWITCH_SUBGHZ
|
#ifdef LR11X0_RF_SWITCH_SUBGHZ
|
||||||
@@ -177,6 +175,12 @@ template <typename T> bool LR11x0Interface<T>::reconfigure()
|
|||||||
err = lora.setSyncWord(syncWord);
|
err = lora.setSyncWord(syncWord);
|
||||||
assert(err == RADIOLIB_ERR_NONE);
|
assert(err == RADIOLIB_ERR_NONE);
|
||||||
|
|
||||||
|
if (config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_LORA_24) { // clamp if wide freq range
|
||||||
|
limitPower(LR1120_MAX_POWER);
|
||||||
|
} else {
|
||||||
|
limitPower(LR1110_MAX_POWER); // default clamp for non-wide freq range
|
||||||
|
}
|
||||||
|
|
||||||
err = lora.setPreambleLength(preambleLength);
|
err = lora.setPreambleLength(preambleLength);
|
||||||
assert(err == RADIOLIB_ERR_NONE);
|
assert(err == RADIOLIB_ERR_NONE);
|
||||||
|
|
||||||
@@ -184,11 +188,6 @@ template <typename T> bool LR11x0Interface<T>::reconfigure()
|
|||||||
if (err != RADIOLIB_ERR_NONE)
|
if (err != RADIOLIB_ERR_NONE)
|
||||||
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
|
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
|
||||||
|
|
||||||
if (power > LR1110_MAX_POWER) // This chip has lower power limits than some
|
|
||||||
power = LR1110_MAX_POWER;
|
|
||||||
if ((power > LR1120_MAX_POWER) && (config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) // 2.4G power limit
|
|
||||||
power = LR1120_MAX_POWER;
|
|
||||||
|
|
||||||
err = lora.setOutputPower(power);
|
err = lora.setOutputPower(power);
|
||||||
assert(err == RADIOLIB_ERR_NONE);
|
assert(err == RADIOLIB_ERR_NONE);
|
||||||
|
|
||||||
|
|||||||
@@ -161,6 +161,18 @@ bool NextHopRouter::perhapsRebroadcast(const meshtastic_MeshPacket *p)
|
|||||||
tosend->hop_start -= (tosend->hop_limit - 2);
|
tosend->hop_start -= (tosend->hop_limit - 2);
|
||||||
tosend->hop_limit = 2;
|
tosend->hop_limit = 2;
|
||||||
}
|
}
|
||||||
|
#elif ARCH_PORTDUINO
|
||||||
|
if (tosend->which_payload_variant == meshtastic_MeshPacket_decoded_tag &&
|
||||||
|
portduino_config.nohop_ports.size()) {
|
||||||
|
for (const auto &port : portduino_config.nohop_ports) {
|
||||||
|
if (port == tosend->decoded.portnum) {
|
||||||
|
LOG_DEBUG("0-hopping portnum %u", tosend->decoded.portnum);
|
||||||
|
tosend->hop_start -= tosend->hop_limit;
|
||||||
|
tosend->hop_limit = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (p->next_hop == NO_NEXT_HOP_PREFERENCE) {
|
if (p->next_hop == NO_NEXT_HOP_PREFERENCE) {
|
||||||
|
|||||||
@@ -17,14 +17,4 @@ template <class T> class PointerQueue : public TypedQueue<T *>
|
|||||||
|
|
||||||
return this->dequeue(&p, maxWait) ? p : nullptr;
|
return this->dequeue(&p, maxWait) ? p : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAS_FREE_RTOS
|
|
||||||
// returns a ptr or null if the queue was empty
|
|
||||||
T *dequeuePtrFromISR(BaseType_t *higherPriWoken)
|
|
||||||
{
|
|
||||||
T *p;
|
|
||||||
|
|
||||||
return this->dequeueFromISR(&p, higherPriWoken) ? p : nullptr;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -240,8 +240,7 @@ bool RF95Interface::reconfigure()
|
|||||||
if (err != RADIOLIB_ERR_NONE)
|
if (err != RADIOLIB_ERR_NONE)
|
||||||
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
|
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
|
||||||
|
|
||||||
if (power > RF95_MAX_POWER) // This chip has lower power limits than some
|
limitPower(RF95_MAX_POWER);
|
||||||
power = RF95_MAX_POWER;
|
|
||||||
|
|
||||||
#ifdef USE_RF95_RFO
|
#ifdef USE_RF95_RFO
|
||||||
err = lora->setOutputPower(power, true);
|
err = lora->setOutputPower(power, true);
|
||||||
|
|||||||
@@ -626,9 +626,9 @@ uint32_t RadioInterface::getTxDelayMsecWeighted(meshtastic_MeshPacket *p)
|
|||||||
void printPacket(const char *prefix, const meshtastic_MeshPacket *p)
|
void printPacket(const char *prefix, const meshtastic_MeshPacket *p)
|
||||||
{
|
{
|
||||||
#if defined(DEBUG_PORT) && !defined(DEBUG_MUTE)
|
#if defined(DEBUG_PORT) && !defined(DEBUG_MUTE)
|
||||||
std::string out =
|
std::string out = DEBUG_PORT.mt_sprintf(
|
||||||
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,
|
"%s (id=0x%08x fr=0x%08x to=0x%08x, transport = %u, WantAck=%d, HopLim=%d HopStart=%d Ch=0x%x", prefix, p->id, p->from,
|
||||||
p->from, p->to, p->transport_mechanism, p->want_ack, p->hop_limit, p->channel);
|
p->to, p->transport_mechanism, p->want_ack, p->hop_limit, p->hop_start, p->channel);
|
||||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||||
auto &s = p->decoded;
|
auto &s = p->decoded;
|
||||||
|
|
||||||
@@ -1038,6 +1038,13 @@ void RadioInterface::applyModemConfig()
|
|||||||
saveFreq(freq + loraConfig.frequency_offset);
|
saveFreq(freq + loraConfig.frequency_offset);
|
||||||
const char *channelName = channels.getName(channels.getPrimaryIndex());
|
const char *channelName = channels.getName(channels.getPrimaryIndex());
|
||||||
|
|
||||||
|
if (newRegion->wideLora) { // clamp if wide freq range
|
||||||
|
preambleLength = wideLoraPreambleLengthDefault; // 12 is the default for operation above 2GHz
|
||||||
|
} else {
|
||||||
|
preambleLength =
|
||||||
|
preambleLengthDefault; // 8 is default, but we use longer to increase the amount of sleep time when receiving
|
||||||
|
}
|
||||||
|
|
||||||
slotTimeMsec = computeSlotTimeMsec();
|
slotTimeMsec = computeSlotTimeMsec();
|
||||||
preambleTimeMsec = preambleLength * (pow_of_2(sf) / bw);
|
preambleTimeMsec = preambleLength * (pow_of_2(sf) / bw);
|
||||||
|
|
||||||
|
|||||||
@@ -92,15 +92,20 @@ class RadioInterface
|
|||||||
uint8_t sf = 9;
|
uint8_t sf = 9;
|
||||||
uint8_t cr = 5;
|
uint8_t cr = 5;
|
||||||
|
|
||||||
const uint8_t NUM_SYM_CAD = 2; // Number of symbols used for CAD, 2 is the default since RadioLib 6.3.0 as per AN1200.48
|
static constexpr uint8_t NUM_SYM_CAD =
|
||||||
const uint8_t NUM_SYM_CAD_24GHZ = 4; // Number of symbols used for CAD in 2.4 GHz, 4 is recommended in AN1200.22 of SX1280
|
2; // Number of symbols used for CAD, 2 is the default since RadioLib 6.3.0 as per AN1200.48
|
||||||
|
static constexpr uint8_t NUM_SYM_CAD_24GHZ =
|
||||||
|
4; // Number of symbols used for CAD in 2.4 GHz, 4 is recommended in AN1200.22 of SX1280
|
||||||
uint32_t slotTimeMsec = computeSlotTimeMsec();
|
uint32_t slotTimeMsec = computeSlotTimeMsec();
|
||||||
uint16_t preambleLength = 16; // 8 is default, but we use longer to increase the amount of sleep time when receiving
|
uint16_t preambleLength = 16; // 8 is default, but we use longer to increase the amount of sleep time when receiving
|
||||||
uint32_t preambleTimeMsec = 165; // calculated on startup, this is the default for LongFast
|
static constexpr uint16_t preambleLengthDefault =
|
||||||
const uint32_t PROCESSING_TIME_MSEC =
|
16; // 8 is default, but we use longer to increase the amount of sleep time when receiving
|
||||||
4500; // time to construct, process and construct a packet again (empirically determined)
|
static constexpr uint16_t wideLoraPreambleLengthDefault = 12; // 12 is default for wide Lora
|
||||||
const uint8_t CWmin = 3; // minimum CWsize
|
uint32_t preambleTimeMsec = 165; // calculated on startup, this is the default for LongFast
|
||||||
const uint8_t CWmax = 8; // maximum CWsize
|
static constexpr uint32_t PROCESSING_TIME_MSEC =
|
||||||
|
4500; // time to construct, process and construct a packet again (empirically determined)
|
||||||
|
static constexpr uint8_t CWmin = 3; // minimum CWsize
|
||||||
|
static constexpr uint8_t CWmax = 8; // maximum CWsize
|
||||||
|
|
||||||
meshtastic_MeshPacket *sendingPacket = NULL; // The packet we are currently sending
|
meshtastic_MeshPacket *sendingPacket = NULL; // The packet we are currently sending
|
||||||
uint32_t lastTxStart = 0L;
|
uint32_t lastTxStart = 0L;
|
||||||
|
|||||||
@@ -246,6 +246,24 @@ bool RadioLibInterface::findInTxQueue(NodeNum from, PacketId id)
|
|||||||
return txQueue.find(from, id);
|
return txQueue.find(from, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RadioLibInterface::randomBytes(uint8_t *buffer, size_t length)
|
||||||
|
{
|
||||||
|
if (!buffer || length == 0 || !iface) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Older RadioLib versions only expose random(min, max), so fill the buffer byte-by-byte.
|
||||||
|
for (size_t i = 0; i < length; ++i) {
|
||||||
|
int32_t value = iface->random(0, 255);
|
||||||
|
if (value < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
buffer[i] = static_cast<uint8_t>(value & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/** radio helper thread callback.
|
/** radio helper thread callback.
|
||||||
We never immediately transmit after any operation (either Rx or Tx). Instead we should wait a random multiple of
|
We never immediately transmit after any operation (either Rx or Tx). Instead we should wait a random multiple of
|
||||||
'slotTimes' (see definition in RadioInterface.h) taken from a contention window (CW) to lower the chance of collision.
|
'slotTimes' (see definition in RadioInterface.h) taken from a contention window (CW) to lower the chance of collision.
|
||||||
@@ -587,4 +605,4 @@ bool RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
|
|||||||
|
|
||||||
return res == RADIOLIB_ERR_NONE;
|
return res == RADIOLIB_ERR_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,6 +172,12 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
|
|||||||
/** Attempt to find a packet in the TxQueue. Returns true if the packet was found. */
|
/** Attempt to find a packet in the TxQueue. Returns true if the packet was found. */
|
||||||
virtual bool findInTxQueue(NodeNum from, PacketId id) override;
|
virtual bool findInTxQueue(NodeNum from, PacketId id) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request randomness sourced from the LoRa modem, if supported by the active RadioLib interface.
|
||||||
|
* @return true if len bytes were produced, false otherwise.
|
||||||
|
*/
|
||||||
|
bool randomBytes(uint8_t *buffer, size_t length);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** if we have something waiting to send, start a short (random) timer so we can come check for collision before actually
|
/** if we have something waiting to send, start a short (random) timer so we can come check for collision before actually
|
||||||
* doing the transmit */
|
* doing the transmit */
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "Default.h"
|
#include "Default.h"
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
|
#include "modules/Native/StoreForwardPlusPlus.h"
|
||||||
#include "Throttle.h"
|
#include "Throttle.h"
|
||||||
#include "platform/portduino/PortduinoGlue.h"
|
#include "platform/portduino/PortduinoGlue.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -383,6 +384,12 @@ ErrorCode Router::send(meshtastic_MeshPacket *p)
|
|||||||
abortSendAndNak(encodeResult, p);
|
abortSendAndNak(encodeResult, p);
|
||||||
return encodeResult; // FIXME - this isn't a valid ErrorCode
|
return encodeResult; // FIXME - this isn't a valid ErrorCode
|
||||||
}
|
}
|
||||||
|
#if ARCH_PORTDUINO
|
||||||
|
if (p_decoded->decoded.portnum == meshtastic_PortNum_TEXT_MESSAGE_APP &&
|
||||||
|
(p->from == 0 || p->from == nodeDB->getNodeNum()) && storeForwardPlusPlusModule && portduino_config.sfpp_enabled) {
|
||||||
|
storeForwardPlusPlusModule->handleEncrypted(p_decoded, p);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||||
// Only publish to MQTT if we're the original transmitter of the packet
|
// Only publish to MQTT if we're the original transmitter of the packet
|
||||||
if (moduleConfig.mqtt.enabled && isFromUs(p) && mqtt) {
|
if (moduleConfig.mqtt.enabled && isFromUs(p) && mqtt) {
|
||||||
@@ -782,6 +789,22 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
|
|||||||
cancelSending(p->from, p->id);
|
cancelSending(p->from, p->id);
|
||||||
skipHandle = true;
|
skipHandle = true;
|
||||||
}
|
}
|
||||||
|
#if ARCH_PORTDUINO
|
||||||
|
if (portduino_config.whitelist_enabled) {
|
||||||
|
bool allowed = false;
|
||||||
|
for (const auto &port : portduino_config.whitelist_ports) {
|
||||||
|
if (port == p->decoded.portnum) {
|
||||||
|
allowed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!allowed) {
|
||||||
|
LOG_DEBUG("Dropping packet not on Portduino Whitelist");
|
||||||
|
cancelSending(p->from, p->id);
|
||||||
|
skipHandle = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
printPacket("packet decoding failed or skipped (no PSK?)", p);
|
printPacket("packet decoding failed or skipped (no PSK?)", p);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -245,8 +245,10 @@ template <typename T> bool SX126xInterface<T>::reconfigure()
|
|||||||
if (err != RADIOLIB_ERR_NONE)
|
if (err != RADIOLIB_ERR_NONE)
|
||||||
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
|
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
|
||||||
|
|
||||||
if (power > SX126X_MAX_POWER) // This chip has lower power limits than some
|
limitPower(SX126X_MAX_POWER);
|
||||||
power = SX126X_MAX_POWER;
|
// Make sure we reach the minimum power supported to turn the chip on (-9dBm)
|
||||||
|
if (power < -9)
|
||||||
|
power = -9;
|
||||||
|
|
||||||
err = lora.setOutputPower(power);
|
err = lora.setOutputPower(power);
|
||||||
if (err != RADIOLIB_ERR_NONE)
|
if (err != RADIOLIB_ERR_NONE)
|
||||||
|
|||||||
@@ -144,8 +144,7 @@ template <typename T> bool SX128xInterface<T>::reconfigure()
|
|||||||
if (err != RADIOLIB_ERR_NONE)
|
if (err != RADIOLIB_ERR_NONE)
|
||||||
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
|
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
|
||||||
|
|
||||||
if (power > SX128X_MAX_POWER) // This chip has lower power limits than some
|
limitPower(SX128X_MAX_POWER);
|
||||||
power = SX128X_MAX_POWER;
|
|
||||||
|
|
||||||
err = lora.setOutputPower(power);
|
err = lora.setOutputPower(power);
|
||||||
if (err != RADIOLIB_ERR_NONE)
|
if (err != RADIOLIB_ERR_NONE)
|
||||||
|
|||||||
@@ -49,6 +49,9 @@
|
|||||||
#include "modules/WaypointModule.h"
|
#include "modules/WaypointModule.h"
|
||||||
#endif
|
#endif
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
|
#include "input/LinuxInputImpl.h"
|
||||||
|
#include "input/SeesawRotary.h"
|
||||||
|
#include "modules/Native/StoreForwardPlusPlus.h"
|
||||||
#include "modules/Telemetry/HostMetrics.h"
|
#include "modules/Telemetry/HostMetrics.h"
|
||||||
#if !MESHTASTIC_EXCLUDE_STOREFORWARD
|
#if !MESHTASTIC_EXCLUDE_STOREFORWARD
|
||||||
#include "modules/StoreForwardModule.h"
|
#include "modules/StoreForwardModule.h"
|
||||||
@@ -195,6 +198,11 @@ void setupModules()
|
|||||||
#endif
|
#endif
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
new HostMetricsModule();
|
new HostMetricsModule();
|
||||||
|
#if SFPP_ENABLED
|
||||||
|
if (portduino_config.sfpp_enabled) {
|
||||||
|
storeForwardPlusPlusModule = new StoreForwardPlusPlusModule();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if HAS_TELEMETRY
|
#if HAS_TELEMETRY
|
||||||
new DeviceTelemetryModule();
|
new DeviceTelemetryModule();
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,310 @@
|
|||||||
|
#pragma once
|
||||||
|
#if __has_include("sqlite3.h")
|
||||||
|
#define SFPP_ENABLED 1
|
||||||
|
#include "Channels.h"
|
||||||
|
#include "ProtobufModule.h"
|
||||||
|
#include "Router.h"
|
||||||
|
#include "SinglePortModule.h"
|
||||||
|
#include "sqlite3.h"
|
||||||
|
|
||||||
|
#define SFPP_HASH_SIZE 16
|
||||||
|
#define SFPP_SHORT_HASH_SIZE 8
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store and forward ++ module
|
||||||
|
* There's an obvious need for a store-and-forward mechanism in Meshtastic.
|
||||||
|
* This module takes heavy inspiration from Git, building a chain of messages that can be synced between nodes.
|
||||||
|
* Each message is hashed, and the chain is built by hashing the previous commit hash and the current message hash.
|
||||||
|
* Nodes can request missing messages by requesting the next message after a given commit hash.
|
||||||
|
*
|
||||||
|
* The current focus is text messages, limited to the primary channel.
|
||||||
|
*
|
||||||
|
* Each chain is identified by a root hash, which is derived from the channelHash, the local nodenum, and the timestamp when
|
||||||
|
* created.
|
||||||
|
*
|
||||||
|
* Each message is also given a message hash, derived from the encrypted payload, the to, from, id.
|
||||||
|
* Notably not the timestamp, as we want these to match across nodes, even if the timestamps differ.
|
||||||
|
*
|
||||||
|
* The authoritative node for the chain will generate a commit hash for each message when adding it to the chain.
|
||||||
|
* The first message's commit hash is derived from the root hash and the message hash.
|
||||||
|
* Subsequent messages' commit hashes are derived from the previous commit hash and the current message hash.
|
||||||
|
* This allows a node to see only the last commit hash, and confirm it hasn't missed any messages.
|
||||||
|
*
|
||||||
|
* Nodes can request the next message in the chain by sending a LINK_REQUEST message with the root hash and the last known commit
|
||||||
|
* hash. Any node that has the next message can respond with a LINK_PROVIDE message containing the next message.
|
||||||
|
*
|
||||||
|
* When a satellite node sees a new text message, it stores it in a scratch database.
|
||||||
|
* These messages are periodically offered to the authoritative node for inclusion in the chain.
|
||||||
|
*
|
||||||
|
* The LINK_PROVIDE message does double-duty, sending both on-chain and off-chain messages.
|
||||||
|
* The differentiator is whether the commit hash is set or left empty.
|
||||||
|
*
|
||||||
|
* When a satellite node receives a canonical link message, it checks if it has the message in scratch.
|
||||||
|
* And evicts it when adding it to the canonical chain.
|
||||||
|
*
|
||||||
|
* This approach allows a node to know whether it has seen a given message before, or if it is new coming via SFPP.
|
||||||
|
* If new, and the timestamp is within the rebroadcast timeout, it will process that message as if it were just received from the
|
||||||
|
* mesh, allowing it to be decrypted, shown to the user, and rebroadcast.
|
||||||
|
*/
|
||||||
|
class StoreForwardPlusPlusModule : public ProtobufModule<meshtastic_StoreForwardPlusPlus>, private concurrency::OSThread
|
||||||
|
{
|
||||||
|
struct link_object {
|
||||||
|
uint32_t to;
|
||||||
|
uint32_t from;
|
||||||
|
uint32_t id;
|
||||||
|
uint32_t rx_time = 0;
|
||||||
|
ChannelHash channel_hash;
|
||||||
|
uint8_t encrypted_bytes[256] = {0};
|
||||||
|
size_t encrypted_len;
|
||||||
|
uint8_t message_hash[SFPP_HASH_SIZE] = {0};
|
||||||
|
size_t message_hash_len = 0;
|
||||||
|
uint8_t root_hash[SFPP_HASH_SIZE] = {0};
|
||||||
|
size_t root_hash_len = 0;
|
||||||
|
uint8_t commit_hash[SFPP_HASH_SIZE] = {0};
|
||||||
|
size_t commit_hash_len = 0;
|
||||||
|
uint32_t counter = 0;
|
||||||
|
std::string payload;
|
||||||
|
bool validObject = true; // set this false when a chain calulation fails, etc.
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Constructor
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
StoreForwardPlusPlusModule();
|
||||||
|
|
||||||
|
/*
|
||||||
|
-Override the wantPacket method.
|
||||||
|
*/
|
||||||
|
virtual bool wantPacket(const meshtastic_MeshPacket *p) override
|
||||||
|
{
|
||||||
|
if (p->decoded.portnum == meshtastic_PortNum_TEXT_MESSAGE_APP ||
|
||||||
|
p->decoded.portnum == (portduino_config.sfpp_steal_port ? meshtastic_PortNum_TEXT_MESSAGE_COMPRESSED_APP
|
||||||
|
: meshtastic_PortNum_STORE_FORWARD_PLUSPLUS_APP)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleEncrypted(const meshtastic_MeshPacket *, const meshtastic_MeshPacket *);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** Called to handle a particular incoming message
|
||||||
|
@return ProcessMessage::STOP if you've guaranteed you've handled this message and no other handlers should be considered for
|
||||||
|
it
|
||||||
|
*/
|
||||||
|
virtual ProcessMessage handleReceived(const meshtastic_MeshPacket &mp) override;
|
||||||
|
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_StoreForwardPlusPlus *t) override;
|
||||||
|
|
||||||
|
virtual int32_t runOnce() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
sqlite3 *ppDb;
|
||||||
|
sqlite3_stmt *chain_insert_stmt;
|
||||||
|
sqlite3_stmt *scratch_insert_stmt;
|
||||||
|
sqlite3_stmt *checkDupMessageHash;
|
||||||
|
sqlite3_stmt *checkDupCommitHash;
|
||||||
|
sqlite3_stmt *checkScratch;
|
||||||
|
sqlite3_stmt *removeScratch;
|
||||||
|
sqlite3_stmt *updatePayloadStmt;
|
||||||
|
sqlite3_stmt *getPayloadFromScratchStmt;
|
||||||
|
sqlite3_stmt *fromScratchStmt;
|
||||||
|
sqlite3_stmt *fromScratchByHashStmt;
|
||||||
|
sqlite3_stmt *getNextHashStmt;
|
||||||
|
sqlite3_stmt *getChainEndStmt;
|
||||||
|
sqlite3_stmt *getLinkStmt;
|
||||||
|
sqlite3_stmt *getLinkFromMessageHashStmt;
|
||||||
|
sqlite3_stmt *getHashFromRootStmt;
|
||||||
|
sqlite3_stmt *addRootToMappingsStmt;
|
||||||
|
sqlite3_stmt *getRootFromChannelHashStmt;
|
||||||
|
sqlite3_stmt *getFullRootHashStmt;
|
||||||
|
sqlite3_stmt *setChainCountStmt;
|
||||||
|
sqlite3_stmt *getChainCountStmt;
|
||||||
|
sqlite3_stmt *getScratchCountStmt;
|
||||||
|
sqlite3_stmt *getRootCanonScratchCountStmt;
|
||||||
|
sqlite3_stmt *pruneScratchQueueStmt;
|
||||||
|
sqlite3_stmt *trimOldestLinkStmt;
|
||||||
|
sqlite3_stmt *maybeAddPeerStmt;
|
||||||
|
sqlite3_stmt *getPeerStmt;
|
||||||
|
sqlite3_stmt *updatePeerStmt;
|
||||||
|
sqlite3_stmt *clearChainStmt;
|
||||||
|
sqlite3_stmt *canon_scratch_insert_stmt;
|
||||||
|
sqlite3_stmt *getCanonScratchCountStmt;
|
||||||
|
sqlite3_stmt *getCanonScratchStmt;
|
||||||
|
sqlite3_stmt *removeCanonScratch;
|
||||||
|
sqlite3_stmt *clearCanonScratchStmt;
|
||||||
|
|
||||||
|
// For a given Meshtastic ChannelHash, fills the root_hash buffer with a 32-byte root hash
|
||||||
|
// returns true if the root hash was found
|
||||||
|
bool getRootFromChannelHash(ChannelHash, uint8_t *);
|
||||||
|
|
||||||
|
// For a given root hash, returns the ChannelHash
|
||||||
|
// can handle partial root hashes
|
||||||
|
ChannelHash getChannelHashFromRoot(uint8_t *_root_hash, size_t);
|
||||||
|
|
||||||
|
// given a root hash and commit hash, returns the next commit hash in the chain
|
||||||
|
// can handle partial root and commit hashes, always fills the buffer with 32 bytes
|
||||||
|
// returns true if a next hash was found
|
||||||
|
bool getNextHash(uint8_t *, size_t, uint8_t *, size_t, uint8_t *);
|
||||||
|
|
||||||
|
// For a given Meshtastic ChannelHash, fills the root_hash buffer with a 32-byte root hash
|
||||||
|
// but this function will add the root hash if it is not already present
|
||||||
|
// returns hash size or 0 if not found/added
|
||||||
|
size_t getOrAddRootFromChannelHash(ChannelHash, uint8_t *);
|
||||||
|
|
||||||
|
// adds the ChannelHash and root_hash to the mappings table
|
||||||
|
void addRootToMappings(ChannelHash, uint8_t *);
|
||||||
|
|
||||||
|
// requests the next message in the chain from the mesh network
|
||||||
|
// Sends a LINK_REQUEST message
|
||||||
|
void requestNextMessage(uint8_t *, size_t, uint8_t *, size_t);
|
||||||
|
|
||||||
|
// request the message X entries from the end.
|
||||||
|
// used to bootstrap a chain, without downloading all of the history
|
||||||
|
void requestMessageCount(uint8_t *, size_t, uint32_t);
|
||||||
|
|
||||||
|
// sends a LINK_PROVIDE message broadcasting the given link object
|
||||||
|
void broadcastLink(uint8_t *, size_t);
|
||||||
|
|
||||||
|
// sends a LINK_PROVIDE message broadcasting the given link object
|
||||||
|
void broadcastLink(link_object &, bool, bool = false);
|
||||||
|
|
||||||
|
// sends a LINK_PROVIDE message broadcasting the given link object from scratch message store
|
||||||
|
bool sendFromScratch(uint8_t *);
|
||||||
|
|
||||||
|
// Adds the given link object to the canonical chain database
|
||||||
|
bool addToChain(link_object &);
|
||||||
|
|
||||||
|
// Adds an incoming text message to the scratch database
|
||||||
|
bool addToScratch(link_object &);
|
||||||
|
|
||||||
|
// sends a CANON_ANNOUNCE message, specifying the given root and commit hashes
|
||||||
|
void canonAnnounce(link_object &);
|
||||||
|
|
||||||
|
// checks if the message hash is present in the canonical chain database
|
||||||
|
bool isInDB(uint8_t *, size_t);
|
||||||
|
|
||||||
|
// checks if the commit hash is present in the canonical chain database
|
||||||
|
bool isCommitInDB(uint8_t *, size_t);
|
||||||
|
|
||||||
|
// checks if the message hash is present in the scratch database
|
||||||
|
bool isInScratch(uint8_t *, size_t);
|
||||||
|
|
||||||
|
// retrieves a link object from the scratch database
|
||||||
|
link_object getFromScratch(uint8_t *, size_t);
|
||||||
|
|
||||||
|
// removes a link object from the scratch database
|
||||||
|
void removeFromScratch(uint8_t *, size_t);
|
||||||
|
|
||||||
|
// iterate through our scratch database, and see if we can speculate a chain up to the given commit hash
|
||||||
|
bool speculateScratchChain(uint8_t *, size_t, uint8_t *, uint8_t *);
|
||||||
|
|
||||||
|
// retrieves the next link object from scratch given a root hash
|
||||||
|
link_object getNextScratchObject(uint8_t *);
|
||||||
|
|
||||||
|
// fills the payload section with the decrypted data for the given message hash
|
||||||
|
// probably not needed for production, but useful for testing
|
||||||
|
void updatePayload(uint8_t *, size_t, std::string);
|
||||||
|
|
||||||
|
// Takes the decrypted MeshPacket and the encrypted packet copy, and builds a link_object
|
||||||
|
// Generates a message hash, but does not set the commit hash
|
||||||
|
link_object ingestTextPacket(const meshtastic_MeshPacket &, const meshtastic_MeshPacket *);
|
||||||
|
|
||||||
|
// ingests a LINK_PROVIDE message and builds a link_object
|
||||||
|
// confirms the root hash and commit hash
|
||||||
|
link_object ingestLinkMessage(meshtastic_StoreForwardPlusPlus *);
|
||||||
|
|
||||||
|
// retrieves a link object from the canonical chain database given a commit hash
|
||||||
|
link_object getLink(uint8_t *, size_t);
|
||||||
|
|
||||||
|
// retrieves a link object from the canonical chain database given a message hash
|
||||||
|
link_object getLinkFromMessageHash(uint8_t *, size_t);
|
||||||
|
|
||||||
|
// puts the encrypted payload back into the queue as if it were just received
|
||||||
|
void rebroadcastLinkObject(link_object &);
|
||||||
|
|
||||||
|
// Check if an incoming link object's commit hash matches the calculated commit hash
|
||||||
|
bool checkCommitHash(link_object &lo, uint8_t *commit_hash_bytes, size_t hash_len);
|
||||||
|
|
||||||
|
// given a partial root hash, looks up the full 32-byte root hash
|
||||||
|
// returns true if found
|
||||||
|
bool lookUpFullRootHash(uint8_t *partial_root_hash, size_t partial_root_hash_len, uint8_t *full_root_hash);
|
||||||
|
|
||||||
|
// update the mappings table to set the chain count for the given root hash
|
||||||
|
void setChainCount(uint8_t *, size_t, uint32_t);
|
||||||
|
|
||||||
|
// get the chain count for the given root hash
|
||||||
|
uint32_t getChainCount(uint8_t *, size_t);
|
||||||
|
|
||||||
|
// get the scratch count for the given root hash
|
||||||
|
uint32_t getScratchCount(uint8_t *, size_t);
|
||||||
|
|
||||||
|
// get the canon scratch count for the given root hash
|
||||||
|
uint32_t getCanonScratchCount(uint8_t *, size_t);
|
||||||
|
|
||||||
|
link_object getLinkFromPositionFromTip(uint32_t, uint8_t *, size_t);
|
||||||
|
|
||||||
|
void pruneScratchQueue();
|
||||||
|
|
||||||
|
void trimOldestLink(uint8_t *, size_t);
|
||||||
|
|
||||||
|
void clearChain(uint8_t *, size_t);
|
||||||
|
|
||||||
|
void recalculateMessageHash(link_object &);
|
||||||
|
|
||||||
|
// given a link object with a payload and other fields, recalculates the message hash
|
||||||
|
// returns true if a match
|
||||||
|
bool recalculateHash(link_object &, uint8_t *, size_t, uint8_t *, size_t);
|
||||||
|
|
||||||
|
void updatePeers(const meshtastic_MeshPacket &, meshtastic_StoreForwardPlusPlus_SFPP_message_type);
|
||||||
|
|
||||||
|
void maybeMoveFromCanonScratch(uint8_t *, size_t);
|
||||||
|
|
||||||
|
void addToCanonScratch(link_object &);
|
||||||
|
|
||||||
|
link_object getfromCanonScratch(uint8_t *, size_t);
|
||||||
|
void removeFromCanonScratch(uint8_t *, size_t);
|
||||||
|
|
||||||
|
void clearCanonScratch(uint8_t *, size_t, uint32_t);
|
||||||
|
|
||||||
|
bool isInCanonScratch(uint8_t *, size_t);
|
||||||
|
|
||||||
|
void logLinkObject(link_object &);
|
||||||
|
|
||||||
|
// Track if we have a scheduled runOnce pending
|
||||||
|
// useful to not accudentally delay a scheduled runOnce
|
||||||
|
bool pendingRun = false;
|
||||||
|
|
||||||
|
// Once we have multiple chain types, we can extend this
|
||||||
|
enum chain_types {
|
||||||
|
channel_chain = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t rebroadcastTimeout = 3600; // Messages older than this (in seconds) will not be rebroadcast
|
||||||
|
bool doing_split_send = false;
|
||||||
|
link_object split_link_out;
|
||||||
|
|
||||||
|
bool doing_split_receive = false;
|
||||||
|
link_object split_link_in;
|
||||||
|
|
||||||
|
bool did_announce_last = false;
|
||||||
|
|
||||||
|
uint32_t texts_rebroadcast = 0;
|
||||||
|
uint32_t links_speculated = 0;
|
||||||
|
uint32_t canon_announces = 0;
|
||||||
|
uint32_t links_requested = 0;
|
||||||
|
uint32_t links_provided = 0;
|
||||||
|
uint32_t links_added = 0;
|
||||||
|
uint32_t links_from_canon_scratch = 0;
|
||||||
|
uint32_t links_from_scratch = 0;
|
||||||
|
uint32_t split_links_sent = 0;
|
||||||
|
uint32_t split_links_received = 0;
|
||||||
|
uint32_t links_pruned = 0;
|
||||||
|
uint32_t scratch_timed_out = 0;
|
||||||
|
uint32_t sent_from_scratch = 0;
|
||||||
|
uint32_t received_from_scratch = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern StoreForwardPlusPlusModule *storeForwardPlusPlusModule;
|
||||||
|
#endif
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
#include "Router.h"
|
#include "Router.h"
|
||||||
#include "TypeConversions.h"
|
#include "TypeConversions.h"
|
||||||
|
#include "airtime.h"
|
||||||
#include "concurrency/LockGuard.h"
|
#include "concurrency/LockGuard.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "mesh-pb-constants.h"
|
#include "mesh-pb-constants.h"
|
||||||
@@ -1001,7 +1002,11 @@ void TrafficManagementModule::alterReceived(meshtastic_MeshPacket &mp)
|
|||||||
const auto &cfg = moduleConfig.traffic_management;
|
const auto &cfg = moduleConfig.traffic_management;
|
||||||
const bool isTelemetry = mp.decoded.portnum == meshtastic_PortNum_TELEMETRY_APP;
|
const bool isTelemetry = mp.decoded.portnum == meshtastic_PortNum_TELEMETRY_APP;
|
||||||
const bool isPosition = mp.decoded.portnum == meshtastic_PortNum_POSITION_APP;
|
const bool isPosition = mp.decoded.portnum == meshtastic_PortNum_POSITION_APP;
|
||||||
const bool shouldExhaust = (isTelemetry && cfg.exhaust_hop_telemetry) || (isPosition && cfg.exhaust_hop_position);
|
// Only exhaust telemetry hops when channel is actually congested, mirroring the same
|
||||||
|
// airtime checks that gate self-generated telemetry in the telemetry modules.
|
||||||
|
const bool channelBusy = airTime && (!airTime->isTxAllowedChannelUtil(true) || !airTime->isTxAllowedAirUtil());
|
||||||
|
const bool shouldExhaust =
|
||||||
|
((channelBusy && isTelemetry && cfg.exhaust_hop_telemetry) || (isPosition && cfg.exhaust_hop_position));
|
||||||
|
|
||||||
if (!shouldExhaust || !isBroadcast(mp.to))
|
if (!shouldExhaust || !isBroadcast(mp.to))
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <nrfx_wdt.h>
|
#include <nrfx_wdt.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
// #include <Adafruit_USBD_Device.h>
|
// #include <Adafruit_USBD_Device.h>
|
||||||
|
#include "HardwareRNG.h"
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
#include "PowerMon.h"
|
#include "PowerMon.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
@@ -398,15 +399,14 @@ void nrf52Setup()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Init random seed
|
// Init random seed
|
||||||
union seedParts {
|
uint32_t seed = 0;
|
||||||
uint32_t seed32;
|
if (!HardwareRNG::seed(seed)) {
|
||||||
uint8_t seed8[4];
|
LOG_WARN("Hardware RNG seed unavailable, using PRNG fallback");
|
||||||
} seed;
|
// Use a hardware timer value as a fallback seed for better entropy
|
||||||
nRFCrypto.begin();
|
seed = micros();
|
||||||
nRFCrypto.Random.generate(seed.seed8, sizeof(seed.seed8));
|
}
|
||||||
LOG_DEBUG("Set random seed %u", seed.seed32);
|
LOG_DEBUG("Set random seed %u", seed);
|
||||||
randomSeed(seed.seed32);
|
randomSeed(seed);
|
||||||
nRFCrypto.end();
|
|
||||||
|
|
||||||
// Set up nrfx watchdog. Do not enable the watchdog yet (we do that
|
// Set up nrfx watchdog. Do not enable the watchdog yet (we do that
|
||||||
// the first time through the main loop), so that other threads can
|
// the first time through the main loop), so that other threads can
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "CryptoEngine.h"
|
#include "CryptoEngine.h"
|
||||||
|
#include "HardwareRNG.h"
|
||||||
#include "PortduinoGPIO.h"
|
#include "PortduinoGPIO.h"
|
||||||
#include "SPIChip.h"
|
#include "SPIChip.h"
|
||||||
#include "mesh/RF95Interface.h"
|
#include "mesh/RF95Interface.h"
|
||||||
@@ -183,6 +184,7 @@ void portduinoSetup()
|
|||||||
|
|
||||||
if (portduino_config.force_simradio == true) {
|
if (portduino_config.force_simradio == true) {
|
||||||
portduino_config.lora_module = use_simradio;
|
portduino_config.lora_module = use_simradio;
|
||||||
|
portduino_config.sfpp_enabled = false;
|
||||||
} else if (configPath != nullptr) {
|
} else if (configPath != nullptr) {
|
||||||
if (loadConfig(configPath)) {
|
if (loadConfig(configPath)) {
|
||||||
if (!yamlOnly)
|
if (!yamlOnly)
|
||||||
@@ -233,7 +235,9 @@ void portduinoSetup()
|
|||||||
std::cout << "Running in simulated mode." << std::endl;
|
std::cout << "Running in simulated mode." << std::endl;
|
||||||
portduino_config.MaxNodes = 200; // Default to 200 nodes
|
portduino_config.MaxNodes = 200; // Default to 200 nodes
|
||||||
// Set the random seed equal to TCPPort to have a different seed per instance
|
// Set the random seed equal to TCPPort to have a different seed per instance
|
||||||
randomSeed(TCPPort);
|
uint32_t seed = TCPPort;
|
||||||
|
HardwareRNG::seed(seed);
|
||||||
|
randomSeed(seed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -512,7 +516,9 @@ void portduinoSetup()
|
|||||||
#endif
|
#endif
|
||||||
printf("MAC ADDRESS: %02X:%02X:%02X:%02X:%02X:%02X\n", dmac[0], dmac[1], dmac[2], dmac[3], dmac[4], dmac[5]);
|
printf("MAC ADDRESS: %02X:%02X:%02X:%02X:%02X:%02X\n", dmac[0], dmac[1], dmac[2], dmac[3], dmac[4], dmac[5]);
|
||||||
// Rather important to set this, if not running simulated.
|
// Rather important to set this, if not running simulated.
|
||||||
randomSeed(time(NULL));
|
uint32_t seed = static_cast<uint32_t>(time(NULL));
|
||||||
|
HardwareRNG::seed(seed);
|
||||||
|
randomSeed(seed);
|
||||||
|
|
||||||
std::string defaultGpioChipName = gpioChipName + std::to_string(portduino_config.lora_default_gpiochip);
|
std::string defaultGpioChipName = gpioChipName + std::to_string(portduino_config.lora_default_gpiochip);
|
||||||
|
|
||||||
@@ -983,6 +989,28 @@ bool loadConfig(const char *configPath)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (yamlConfig["StoreAndForward"]) {
|
||||||
|
portduino_config.sfpp_stratum0 = (yamlConfig["StoreAndForward"]["Stratum0"]).as<bool>(false);
|
||||||
|
portduino_config.sfpp_enabled = (yamlConfig["StoreAndForward"]["Enabled"]).as<bool>(true);
|
||||||
|
portduino_config.sfpp_db_path = (yamlConfig["StoreAndForward"]["DBPath"]).as<std::string>("/var/lib/meshtasticd/");
|
||||||
|
portduino_config.sfpp_initial_sync = (yamlConfig["StoreAndForward"]["InitialSync"]).as<int>(10);
|
||||||
|
portduino_config.sfpp_hops = (yamlConfig["StoreAndForward"]["Hops"]).as<int>(3);
|
||||||
|
portduino_config.sfpp_announce_interval = (yamlConfig["StoreAndForward"]["AnnounceInterval"]).as<int>(5);
|
||||||
|
portduino_config.sfpp_max_chain = (yamlConfig["StoreAndForward"]["MaxChainLength"]).as<uint32_t>(1000);
|
||||||
|
portduino_config.sfpp_backlog_limit = (yamlConfig["StoreAndForward"]["BacklogLimit"]).as<uint32_t>(100);
|
||||||
|
portduino_config.sfpp_steal_port = (yamlConfig["StoreAndForward"]["StealPort"]).as<bool>(false);
|
||||||
|
}
|
||||||
|
if (yamlConfig["Routing"]) {
|
||||||
|
if (yamlConfig["Routing"]["WhitelistPorts"]) {
|
||||||
|
portduino_config.whitelist_ports = (yamlConfig["Routing"]["WhitelistPorts"]).as<std::vector<int>>();
|
||||||
|
if (portduino_config.whitelist_ports.size() > 0) {
|
||||||
|
portduino_config.whitelist_enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (yamlConfig["Routing"]["NoHopPorts"]) {
|
||||||
|
portduino_config.nohop_ports = (yamlConfig["Routing"]["NoHopPorts"]).as<std::vector<int>>();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (yamlConfig["General"]) {
|
if (yamlConfig["General"]) {
|
||||||
portduino_config.MaxNodes = (yamlConfig["General"]["MaxNodes"]).as<int>(200);
|
portduino_config.MaxNodes = (yamlConfig["General"]["MaxNodes"]).as<int>(200);
|
||||||
portduino_config.maxtophone = (yamlConfig["General"]["MaxMessageQueue"]).as<int>(100);
|
portduino_config.maxtophone = (yamlConfig["General"]["MaxMessageQueue"]).as<int>(100);
|
||||||
|
|||||||
@@ -187,6 +187,26 @@ extern struct portduino_config_struct {
|
|||||||
bool has_statusMessage = false;
|
bool has_statusMessage = false;
|
||||||
bool enable_UDP = false;
|
bool enable_UDP = false;
|
||||||
|
|
||||||
|
// Store and Forward++
|
||||||
|
std::string sfpp_db_path = "/var/lib/meshtasticd/";
|
||||||
|
bool sfpp_stratum0 = false;
|
||||||
|
bool sfpp_enabled = true;
|
||||||
|
bool sfpp_steal_port = false;
|
||||||
|
int sfpp_initial_sync = 10;
|
||||||
|
int sfpp_hops = 3;
|
||||||
|
int sfpp_announce_interval = 5; // minutes
|
||||||
|
uint32_t sfpp_max_chain = 1000;
|
||||||
|
uint32_t sfpp_backlog_limit = 100;
|
||||||
|
// allowed root hashes
|
||||||
|
// upstream node
|
||||||
|
// Are we allowing unknown channel hashes? Does this even make sense?
|
||||||
|
// Allow DMs
|
||||||
|
|
||||||
|
// Routing
|
||||||
|
bool whitelist_enabled = false;
|
||||||
|
std::vector<int> whitelist_ports = {};
|
||||||
|
std::vector<int> nohop_ports = {};
|
||||||
|
|
||||||
// General
|
// General
|
||||||
std::string mac_address = "";
|
std::string mac_address = "";
|
||||||
bool mac_address_explicit = false;
|
bool mac_address_explicit = false;
|
||||||
@@ -552,6 +572,29 @@ extern struct portduino_config_struct {
|
|||||||
out << YAML::EndMap; // Config
|
out << YAML::EndMap; // Config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StoreAndForward
|
||||||
|
if (sfpp_enabled) {
|
||||||
|
out << YAML::Key << "StoreAndForward" << YAML::Value << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "Enabled" << YAML::Value << sfpp_enabled;
|
||||||
|
out << YAML::Key << "DBPath" << YAML::Value << sfpp_db_path;
|
||||||
|
out << YAML::Key << "Stratum0" << YAML::Value << sfpp_stratum0;
|
||||||
|
out << YAML::Key << "InitialSync" << YAML::Value << sfpp_initial_sync;
|
||||||
|
out << YAML::Key << "Hops" << YAML::Value << sfpp_hops;
|
||||||
|
out << YAML::Key << "AnnounceInterval" << YAML::Value << sfpp_announce_interval;
|
||||||
|
out << YAML::Key << "BacklogLimit" << YAML::Value << sfpp_backlog_limit;
|
||||||
|
out << YAML::Key << "MaxChainLength" << YAML::Value << sfpp_max_chain;
|
||||||
|
out << YAML::Key << "StealPort" << YAML::Value << sfpp_steal_port;
|
||||||
|
out << YAML::EndMap; // StoreAndForward
|
||||||
|
}
|
||||||
|
|
||||||
|
// Routing
|
||||||
|
if (whitelist_enabled || nohop_ports.size() > 0) {
|
||||||
|
out << YAML::Key << "Routing" << YAML::Value << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "WhitelistPorts" << YAML::Value << whitelist_ports;
|
||||||
|
out << YAML::Key << "NoHopPorts" << YAML::Value << nohop_ports;
|
||||||
|
out << YAML::EndMap; // Routing
|
||||||
|
}
|
||||||
|
|
||||||
// General
|
// General
|
||||||
out << YAML::Key << "General" << YAML::Value << YAML::BeginMap;
|
out << YAML::Key << "General" << YAML::Value << YAML::BeginMap;
|
||||||
if (config_directory != "")
|
if (config_directory != "")
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include "HardwareRNG.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "hardware/xosc.h"
|
#include "hardware/xosc.h"
|
||||||
#include <hardware/clocks.h>
|
#include <hardware/clocks.h>
|
||||||
@@ -98,10 +99,12 @@ void getMacAddr(uint8_t *dmac)
|
|||||||
|
|
||||||
void rp2040Setup()
|
void rp2040Setup()
|
||||||
{
|
{
|
||||||
/* Sets a random seed to make sure we get different random numbers on each boot.
|
/* Sets a random seed to make sure we get different random numbers on each boot. */
|
||||||
Taken from CPU cycle counter and ROSC oscillator, so should be pretty random.
|
uint32_t seed = 0;
|
||||||
*/
|
if (!HardwareRNG::seed(seed)) {
|
||||||
randomSeed(rp2040.hwrand32());
|
seed = rp2040.hwrand32();
|
||||||
|
}
|
||||||
|
randomSeed(seed);
|
||||||
|
|
||||||
#ifdef RP2040_SLOW_CLOCK
|
#ifdef RP2040_SLOW_CLOCK
|
||||||
uint f_pll_sys = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_PLL_SYS_CLKSRC_PRIMARY);
|
uint f_pll_sys = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_PLL_SYS_CLKSRC_PRIMARY);
|
||||||
|
|||||||
@@ -13,7 +13,3 @@ board_build.f_cpu = 240000000L
|
|||||||
upload_protocol = esptool
|
upload_protocol = esptool
|
||||||
;upload_port = /dev/ttyUSB0
|
;upload_port = /dev/ttyUSB0
|
||||||
upload_speed = 460800
|
upload_speed = 460800
|
||||||
lib_deps =
|
|
||||||
${esp32_base.lib_deps}
|
|
||||||
# renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel
|
|
||||||
adafruit/Adafruit NeoPixel@1.15.4
|
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ build_flags =
|
|||||||
-Wall
|
-Wall
|
||||||
-Wextra
|
-Wextra
|
||||||
-Isrc/platform/esp32
|
-Isrc/platform/esp32
|
||||||
-include mbedtls/error.h
|
|
||||||
-std=gnu++17
|
-std=gnu++17
|
||||||
-DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG
|
-DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG
|
||||||
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||||
@@ -68,7 +67,7 @@ lib_deps =
|
|||||||
${environmental_extra.lib_deps}
|
${environmental_extra.lib_deps}
|
||||||
${radiolib_base.lib_deps}
|
${radiolib_base.lib_deps}
|
||||||
# renovate: datasource=git-refs depName=meshtastic-esp32_https_server packageName=https://github.com/meshtastic/esp32_https_server gitBranch=master
|
# renovate: datasource=git-refs depName=meshtastic-esp32_https_server packageName=https://github.com/meshtastic/esp32_https_server gitBranch=master
|
||||||
https://github.com/meshtastic/esp32_https_server/archive/b78f12c86ea65c3ca08968840ff554ff7ed69b60.zip
|
https://github.com/meshtastic/esp32_https_server/archive/0c71f380390ad483ff134ad938e07f6cf1226c5b.zip
|
||||||
# renovate: datasource=custom.pio depName=NimBLE-Arduino packageName=h2zero/library/NimBLE-Arduino
|
# renovate: datasource=custom.pio depName=NimBLE-Arduino packageName=h2zero/library/NimBLE-Arduino
|
||||||
h2zero/NimBLE-Arduino@1.4.3
|
h2zero/NimBLE-Arduino@1.4.3
|
||||||
# renovate: datasource=git-refs depName=libpax packageName=https://github.com/dbinfrago/libpax gitBranch=master
|
# renovate: datasource=git-refs depName=libpax packageName=https://github.com/dbinfrago/libpax gitBranch=master
|
||||||
|
|||||||
@@ -5,6 +5,3 @@ build_flags =
|
|||||||
${esp32c3_base.build_flags}
|
${esp32c3_base.build_flags}
|
||||||
-D HELTEC_HRU_3601
|
-D HELTEC_HRU_3601
|
||||||
-I variants/esp32c3/heltec_hru_3601
|
-I variants/esp32c3/heltec_hru_3601
|
||||||
lib_deps = ${esp32c3_base.lib_deps}
|
|
||||||
# renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel
|
|
||||||
adafruit/Adafruit NeoPixel@1.15.4
|
|
||||||
|
|||||||
@@ -23,8 +23,6 @@ build_unflags =
|
|||||||
-D HAS_WIFI
|
-D HAS_WIFI
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${esp32c6_base.lib_deps}
|
${esp32c6_base.lib_deps}
|
||||||
# renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel
|
|
||||||
adafruit/Adafruit NeoPixel@1.15.4
|
|
||||||
# renovate: datasource=custom.pio depName=NimBLE-Arduino packageName=h2zero/library/NimBLE-Arduino
|
# renovate: datasource=custom.pio depName=NimBLE-Arduino packageName=h2zero/library/NimBLE-Arduino
|
||||||
h2zero/NimBLE-Arduino@2.3.7
|
h2zero/NimBLE-Arduino@2.3.7
|
||||||
build_flags =
|
build_flags =
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ lib_deps =
|
|||||||
${esp32s3_base.lib_deps}
|
${esp32s3_base.lib_deps}
|
||||||
# renovate: datasource=custom.pio depName=GxEPD2 packageName=zinggjm/library/GxEPD2
|
# renovate: datasource=custom.pio depName=GxEPD2 packageName=zinggjm/library/GxEPD2
|
||||||
zinggjm/GxEPD2@1.6.8
|
zinggjm/GxEPD2@1.6.8
|
||||||
# renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel
|
|
||||||
adafruit/Adafruit NeoPixel@1.15.4
|
|
||||||
build_unflags =
|
build_unflags =
|
||||||
${esp32s3_base.build_unflags}
|
${esp32s3_base.build_unflags}
|
||||||
-DARDUINO_USB_MODE=1
|
-DARDUINO_USB_MODE=1
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ board_build.f_cpu = 240000000L
|
|||||||
upload_protocol = esptool
|
upload_protocol = esptool
|
||||||
;upload_port = /dev/ttyACM0
|
;upload_port = /dev/ttyACM0
|
||||||
upload_speed = 921600
|
upload_speed = 921600
|
||||||
lib_deps =
|
|
||||||
${esp32s3_base.lib_deps}
|
|
||||||
# renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel
|
|
||||||
adafruit/Adafruit NeoPixel@1.15.4
|
|
||||||
build_unflags =
|
build_unflags =
|
||||||
${esp32s3_base.build_unflags}
|
${esp32s3_base.build_unflags}
|
||||||
-DARDUINO_USB_MODE=1
|
-DARDUINO_USB_MODE=1
|
||||||
|
|||||||
@@ -24,5 +24,3 @@ build_flags = ${esp32s3_base.build_flags}
|
|||||||
lib_deps = ${esp32s3_base.lib_deps}
|
lib_deps = ${esp32s3_base.lib_deps}
|
||||||
# renovate: datasource=custom.pio depName=GxEPD2 packageName=zinggjm/library/GxEPD2
|
# renovate: datasource=custom.pio depName=GxEPD2 packageName=zinggjm/library/GxEPD2
|
||||||
zinggjm/GxEPD2@1.6.8
|
zinggjm/GxEPD2@1.6.8
|
||||||
# renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel
|
|
||||||
adafruit/Adafruit NeoPixel@1.15.4
|
|
||||||
|
|||||||
@@ -8,7 +8,3 @@ build_flags =
|
|||||||
-I variants/esp32s3/heltec_sensor_hub
|
-I variants/esp32s3/heltec_sensor_hub
|
||||||
-D HELTEC_SENSOR_HUB
|
-D HELTEC_SENSOR_HUB
|
||||||
-ULED_BUILTIN
|
-ULED_BUILTIN
|
||||||
|
|
||||||
lib_deps = ${esp32s3_base.lib_deps}
|
|
||||||
# renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel
|
|
||||||
adafruit/Adafruit NeoPixel@1.15.4
|
|
||||||
|
|||||||
@@ -20,5 +20,5 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${esp32s3_base.lib_deps}
|
${esp32s3_base.lib_deps}
|
||||||
# renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main
|
# renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main
|
||||||
https://github.com/meshtastic/st7789/archive/9ee76d6b18b9a8f45a2c5cae06b1134a587691eb.zip
|
https://github.com/meshtastic/st7789/archive/a787beea5c6c8f864ba6787eb432bbefc575e6ad.zip
|
||||||
upload_speed = 921600
|
upload_speed = 921600
|
||||||
|
|||||||
@@ -16,12 +16,10 @@ build_src_filter =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${esp32s3_base.lib_deps}
|
${esp32s3_base.lib_deps}
|
||||||
# renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main
|
# renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main
|
||||||
https://github.com/meshtastic/st7789/archive/9ee76d6b18b9a8f45a2c5cae06b1134a587691eb.zip
|
https://github.com/meshtastic/st7789/archive/a787beea5c6c8f864ba6787eb432bbefc575e6ad.zip
|
||||||
# renovate: datasource=github-tags depName=pschatzmann_arduino-audio-driver packageName=pschatzmann/arduino-audio-driver
|
# renovate: datasource=github-tags depName=pschatzmann_arduino-audio-driver packageName=pschatzmann/arduino-audio-driver
|
||||||
https://github.com/pschatzmann/arduino-audio-driver/archive/v0.2.1.zip
|
https://github.com/pschatzmann/arduino-audio-driver/archive/v0.2.1.zip
|
||||||
# renovate: datasource=git-refs depName=ESP8266Audio packageName=https://github.com/meshtastic/ESP8266Audio gitBranch=meshtastic-2.0.0-dacfix
|
# renovate: datasource=git-refs depName=ESP8266Audio packageName=https://github.com/meshtastic/ESP8266Audio gitBranch=meshtastic-2.0.0-dacfix
|
||||||
https://github.com/meshtastic/ESP8266Audio/archive/343024632ee78d6216907b2353fc943a62422d80.zip
|
https://github.com/meshtastic/ESP8266Audio/archive/343024632ee78d6216907b2353fc943a62422d80.zip
|
||||||
# renovate: datasource=custom.pio depName=ESP8266SAM packageName=earlephilhower/library/ESP8266SAM
|
# renovate: datasource=custom.pio depName=ESP8266SAM packageName=earlephilhower/library/ESP8266SAM
|
||||||
earlephilhower/ESP8266SAM@1.1.0
|
earlephilhower/ESP8266SAM@1.1.0
|
||||||
# renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel
|
|
||||||
adafruit/Adafruit NeoPixel@1.15.4
|
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ void setupNicheGraphics()
|
|||||||
buttons->setTwoWayRockerPressHandlers(
|
buttons->setTwoWayRockerPressHandlers(
|
||||||
[inkhud]() {
|
[inkhud]() {
|
||||||
bool systemHandlingInput = false;
|
bool systemHandlingInput = false;
|
||||||
for (InkHUD::SystemApplet *sa : inkhud->systemApplets) {
|
for (const InkHUD::SystemApplet *sa : inkhud->systemApplets) {
|
||||||
if (sa->handleInput) {
|
if (sa->handleInput) {
|
||||||
systemHandlingInput = true;
|
systemHandlingInput = true;
|
||||||
break;
|
break;
|
||||||
@@ -112,7 +112,7 @@ void setupNicheGraphics()
|
|||||||
},
|
},
|
||||||
[inkhud]() {
|
[inkhud]() {
|
||||||
bool systemHandlingInput = false;
|
bool systemHandlingInput = false;
|
||||||
for (InkHUD::SystemApplet *sa : inkhud->systemApplets) {
|
for (const InkHUD::SystemApplet *sa : inkhud->systemApplets) {
|
||||||
if (sa->handleInput) {
|
if (sa->handleInput) {
|
||||||
systemHandlingInput = true;
|
systemHandlingInput = true;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -40,8 +40,6 @@ lib_deps = ${esp32s3_base.lib_deps}
|
|||||||
lovyan03/LovyanGFX@1.2.19
|
lovyan03/LovyanGFX@1.2.19
|
||||||
# TODO renovate https://gitlab.com/hamishcunningham/unphonelibrary#meshtastic@9.0.0
|
# TODO renovate https://gitlab.com/hamishcunningham/unphonelibrary#meshtastic@9.0.0
|
||||||
https://gitlab.com/hamishcunningham/unphonelibrary/-/archive/meshtastic/unphonelibrary-meshtastic.zip
|
https://gitlab.com/hamishcunningham/unphonelibrary/-/archive/meshtastic/unphonelibrary-meshtastic.zip
|
||||||
# renovate: datasource=custom.pio depName=NeoPixel packageName=adafruit/library/Adafruit NeoPixel
|
|
||||||
adafruit/Adafruit NeoPixel@1.15.4
|
|
||||||
|
|
||||||
[env:unphone-tft]
|
[env:unphone-tft]
|
||||||
board_level = extra
|
board_level = extra
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ lib_deps =
|
|||||||
adafruit/Adafruit seesaw Library@1.7.9
|
adafruit/Adafruit seesaw Library@1.7.9
|
||||||
# renovate: datasource=git-refs depName=RAK12034-BMX160 packageName=https://github.com/RAKWireless/RAK12034-BMX160 gitBranch=main
|
# renovate: datasource=git-refs depName=RAK12034-BMX160 packageName=https://github.com/RAKWireless/RAK12034-BMX160 gitBranch=main
|
||||||
https://github.com/RAKWireless/RAK12034-BMX160/archive/dcead07ffa267d3c906e9ca4a1330ab989e957e2.zip
|
https://github.com/RAKWireless/RAK12034-BMX160/archive/dcead07ffa267d3c906e9ca4a1330ab989e957e2.zip
|
||||||
# renovate: datasource=custom.pio depName=Adafruit_BME680 packageName=adafruit/library/Adafruit BME680 Library
|
# renovate: datasource=github-tags depName=Adafruit_BME680 packageName=adafruit/Adafruit_BME680
|
||||||
adafruit/Adafruit BME680 Library@2.0.6
|
https://github.com/adafruit/Adafruit_BME680/archive/refs/tags/2.0.6.zip
|
||||||
|
|
||||||
build_flags =
|
build_flags =
|
||||||
${arduino_base.build_flags}
|
${arduino_base.build_flags}
|
||||||
@@ -59,4 +59,5 @@ build_flags =
|
|||||||
lib_ignore =
|
lib_ignore =
|
||||||
Adafruit NeoPixel
|
Adafruit NeoPixel
|
||||||
Adafruit ST7735 and ST7789 Library
|
Adafruit ST7735 and ST7789 Library
|
||||||
|
Adafruit SSD1306
|
||||||
SD
|
SD
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ lib_deps =
|
|||||||
# renovate: datasource=custom.pio depName=Melopero RV3028 packageName=melopero/library/Melopero RV3028
|
# renovate: datasource=custom.pio depName=Melopero RV3028 packageName=melopero/library/Melopero RV3028
|
||||||
melopero/Melopero RV3028@1.2.0
|
melopero/Melopero RV3028@1.2.0
|
||||||
|
|
||||||
build_src_filter = ${portduino_base.build_src_filter}
|
build_src_filter = ${portduino_base.build_src_filter} +<modules/Native/>
|
||||||
|
|
||||||
[env:native]
|
[env:native]
|
||||||
extends = native_base
|
extends = native_base
|
||||||
@@ -20,6 +20,7 @@ build_flags = ${native_base.build_flags}
|
|||||||
!pkg-config --libs openssl --silence-errors || :
|
!pkg-config --libs openssl --silence-errors || :
|
||||||
!pkg-config --cflags --libs sdl2 --silence-errors || :
|
!pkg-config --cflags --libs sdl2 --silence-errors || :
|
||||||
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
||||||
|
!pkg-config --cflags --libs sqlite3 --silence-errors || :
|
||||||
|
|
||||||
[env:native-tft]
|
[env:native-tft]
|
||||||
extends = native_base
|
extends = native_base
|
||||||
@@ -46,6 +47,7 @@ build_flags = ${native_base.build_flags} -Os -lX11 -linput -lxkbcommon -ffunctio
|
|||||||
!pkg-config --libs openssl --silence-errors || :
|
!pkg-config --libs openssl --silence-errors || :
|
||||||
!pkg-config --cflags --libs sdl2 --silence-errors || :
|
!pkg-config --cflags --libs sdl2 --silence-errors || :
|
||||||
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
||||||
|
!pkg-config --cflags --libs sqlite3 --silence-errors || :
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
${native_base.build_src_filter}
|
${native_base.build_src_filter}
|
||||||
|
|
||||||
@@ -75,6 +77,7 @@ build_flags = ${native_base.build_flags} -Os -ffunction-sections -fdata-sections
|
|||||||
!pkg-config --libs libulfius --silence-errors || :
|
!pkg-config --libs libulfius --silence-errors || :
|
||||||
!pkg-config --libs openssl --silence-errors || :
|
!pkg-config --libs openssl --silence-errors || :
|
||||||
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
||||||
|
!pkg-config --cflags --libs sqlite3 --silence-errors || :
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
${native_base.build_src_filter}
|
${native_base.build_src_filter}
|
||||||
|
|
||||||
@@ -108,6 +111,7 @@ build_flags = ${native_base.build_flags} -O0 -fsanitize=address -lX11 -linput -l
|
|||||||
!pkg-config --libs libulfius --silence-errors || :
|
!pkg-config --libs libulfius --silence-errors || :
|
||||||
!pkg-config --libs openssl --silence-errors || :
|
!pkg-config --libs openssl --silence-errors || :
|
||||||
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
||||||
|
!pkg-config --cflags --libs sqlite3 --silence-errors || :
|
||||||
build_src_filter = ${env:native-tft.build_src_filter}
|
build_src_filter = ${env:native-tft.build_src_filter}
|
||||||
|
|
||||||
[env:coverage]
|
[env:coverage]
|
||||||
|
|||||||
@@ -23,4 +23,4 @@ build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/heltec_
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${nrf52840_base.lib_deps}
|
${nrf52840_base.lib_deps}
|
||||||
# renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main
|
# renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main
|
||||||
https://github.com/meshtastic/st7789/archive/9ee76d6b18b9a8f45a2c5cae06b1134a587691eb.zip
|
https://github.com/meshtastic/st7789/archive/a787beea5c6c8f864ba6787eb432bbefc575e6ad.zip
|
||||||
|
|||||||
@@ -132,4 +132,4 @@ build_flags = ${heltec_mesh_solar_base.build_flags}
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${heltec_mesh_solar_base.lib_deps}
|
${heltec_mesh_solar_base.lib_deps}
|
||||||
# renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main
|
# renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main
|
||||||
https://github.com/meshtastic/st7789/archive/9ee76d6b18b9a8f45a2c5cae06b1134a587691eb.zip
|
https://github.com/meshtastic/st7789/archive/a787beea5c6c8f864ba6787eb432bbefc575e6ad.zip
|
||||||
|
|||||||
Reference in New Issue
Block a user