mirror of
https://github.com/meshtastic/firmware.git
synced 2026-02-01 06:32:01 +00:00
Compare commits
107 Commits
v2.5.18.89
...
v2.5.19.f9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4cd2ba5479 | ||
|
|
f9876cfe9c | ||
|
|
85de193845 | ||
|
|
fb2c008c89 | ||
|
|
dd9ab7f0e1 | ||
|
|
729c39fb86 | ||
|
|
038430db23 | ||
|
|
d5cd6f87a0 | ||
|
|
de42d96adf | ||
|
|
e2dd845051 | ||
|
|
6366633cd4 | ||
|
|
1c0f43c8e2 | ||
|
|
89a9e0b99d | ||
|
|
4dc8d6e400 | ||
|
|
e0f97c9306 | ||
|
|
6b1c01ce02 | ||
|
|
70296b47bc | ||
|
|
0cf4a2951a | ||
|
|
124936b6cf | ||
|
|
fd60c9b3be | ||
|
|
a0a4c5bc79 | ||
|
|
0fe8d4ccc7 | ||
|
|
00fdf2c9aa | ||
|
|
253ab458ef | ||
|
|
b4a4d2db4e | ||
|
|
6b8cf164e9 | ||
|
|
812aa35f09 | ||
|
|
e7802d960f | ||
|
|
077ee02426 | ||
|
|
46ea39af45 | ||
|
|
25a5f178e1 | ||
|
|
c144ee77a7 | ||
|
|
b62bdbc46a | ||
|
|
f18a92e8c5 | ||
|
|
2e44de262e | ||
|
|
1d756ae574 | ||
|
|
8aac9f2e8e | ||
|
|
33e5a04508 | ||
|
|
6cf3485d07 | ||
|
|
9421eba027 | ||
|
|
27fbfd03d6 | ||
|
|
353740623f | ||
|
|
cdcbf4c615 | ||
|
|
395469d20a | ||
|
|
86170171a7 | ||
|
|
57766d47a8 | ||
|
|
e5dbcf5bce | ||
|
|
4c3a3ca47d | ||
|
|
78371dfdb7 | ||
|
|
ca32889893 | ||
|
|
35cd600c54 | ||
|
|
70076a4b27 | ||
|
|
f1a8900288 | ||
|
|
16bc89ea57 | ||
|
|
6edf74e8f1 | ||
|
|
7f280dd556 | ||
|
|
2396aa77ca | ||
|
|
d3cbbfd345 | ||
|
|
c003ab0eee | ||
|
|
4fcf7fe027 | ||
|
|
9cc79b1d1e | ||
|
|
403fa15a3f | ||
|
|
b0087fd328 | ||
|
|
fb74e1d182 | ||
|
|
29a7866fc1 | ||
|
|
2f552d15e5 | ||
|
|
892e0922ff | ||
|
|
d21d6c1301 | ||
|
|
031aecac66 | ||
|
|
7c10caa78b | ||
|
|
5196ee39cb | ||
|
|
02a5a91da0 | ||
|
|
b2a89b8136 | ||
|
|
15019e8663 | ||
|
|
35814fd4bc | ||
|
|
6aabbedc00 | ||
|
|
eb72ee0fc1 | ||
|
|
7480378aed | ||
|
|
7c21d7761c | ||
|
|
2c654454cf | ||
|
|
9afadde2f4 | ||
|
|
66a961cb75 | ||
|
|
e1aaafb77a | ||
|
|
9d710041c4 | ||
|
|
b41efc17ba | ||
|
|
9bda080e3d | ||
|
|
9f7cbf1b4f | ||
|
|
93e2bc7058 | ||
|
|
7a1c32b89a | ||
|
|
88d8ab53c8 | ||
|
|
183f68ba00 | ||
|
|
9f32995d7f | ||
|
|
c2c06ed0ad | ||
|
|
9abd07bb05 | ||
|
|
fdcc0e12aa | ||
|
|
8b34c4ff05 | ||
|
|
9af8c58c40 | ||
|
|
58ebd5bcdb | ||
|
|
d1e5be515a | ||
|
|
f9e71c3fb9 | ||
|
|
bfcfca2e46 | ||
|
|
a2a6b236b7 | ||
|
|
3c7053c66a | ||
|
|
e45c0e4d40 | ||
|
|
57a9a5ca21 | ||
|
|
6749367a73 | ||
|
|
a8e2446f00 |
10
.github/actions/build-variant/action.yml
vendored
10
.github/actions/build-variant/action.yml
vendored
@@ -68,6 +68,12 @@ runs:
|
||||
sed -i '/DDEBUG_HEAP/d' ${INI_FILE}
|
||||
done
|
||||
|
||||
- name: PlatformIO ${{ inputs.arch }} download cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.platformio/.cache
|
||||
key: pio-cache-${{ inputs.arch }}-${{ hashFiles('.github/actions/**', '**.ini') }}
|
||||
|
||||
- name: Build ${{ inputs.board }}
|
||||
shell: bash
|
||||
run: ${{ inputs.build-script-path }} ${{ inputs.board }}
|
||||
@@ -83,13 +89,13 @@ runs:
|
||||
|
||||
- name: Get release version string
|
||||
shell: bash
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware-${{ inputs.arch }}-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
||||
name: firmware-${{ inputs.arch }}-${{ inputs.board }}-${{ steps.version.outputs.long }}.zip
|
||||
overwrite: true
|
||||
path: |
|
||||
${{ inputs.artifact-paths }}
|
||||
|
||||
13
.github/actions/setup-base/action.yml
vendored
13
.github/actions/setup-base/action.yml
vendored
@@ -20,19 +20,16 @@ runs:
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get -y update --fix-missing
|
||||
sudo apt-get install -y cppcheck libbluetooth-dev libgpiod-dev libyaml-cpp-dev
|
||||
sudo apt-get install -y cppcheck libbluetooth-dev libgpiod-dev libyaml-cpp-dev lsb-release
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
# - name: Cache python libs
|
||||
# uses: actions/cache@v4
|
||||
# id: cache-pip # needed in if test
|
||||
# with:
|
||||
# path: ~/.cache/pip
|
||||
# key: ${{ runner.os }}-pip
|
||||
cache: pip
|
||||
cache-dependency-path: |
|
||||
.github/actions/**
|
||||
**.ini
|
||||
|
||||
- name: Upgrade python tools
|
||||
shell: bash
|
||||
|
||||
14
.github/actions/setup-native/action.yml
vendored
Normal file
14
.github/actions/setup-native/action.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
name: Setup native build
|
||||
description: Install libraries needed for building the Native/Portduino build
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Setup base
|
||||
id: base
|
||||
uses: ./.github/actions/setup-base
|
||||
|
||||
- name: Install libs needed for native build
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev libi2c-dev
|
||||
72
.github/workflows/build_debian_src.yml
vendored
Normal file
72
.github/workflows/build_debian_src.yml
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
name: Build Debian Source Package
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
secrets:
|
||||
PPA_GPG_PRIVATE_KEY:
|
||||
required: true
|
||||
inputs:
|
||||
series:
|
||||
description: Ubuntu/Debian series to target
|
||||
required: true
|
||||
type: string
|
||||
build_location:
|
||||
description: Location where build will execute
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
build-debian-src:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
path: meshtasticd
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Install deps
|
||||
shell: bash
|
||||
working-directory: meshtasticd
|
||||
run: |
|
||||
sudo apt-get update -y --fix-missing
|
||||
sudo apt-get install -y software-properties-common build-essential devscripts equivs
|
||||
sudo add-apt-repository ppa:meshtastic/build-tools -y
|
||||
sudo apt-get update -y --fix-missing
|
||||
sudo mk-build-deps --install --remove --tool='apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes' debian/control
|
||||
|
||||
- name: Import GPG key
|
||||
uses: crazy-max/ghaction-import-gpg@v6
|
||||
with:
|
||||
gpg_private_key: ${{ secrets.PPA_GPG_PRIVATE_KEY }}
|
||||
id: gpg
|
||||
|
||||
- name: Get release version string
|
||||
working-directory: meshtasticd
|
||||
run: |
|
||||
echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
BUILD_LOCATION: ${{ inputs.build_location }}
|
||||
id: version
|
||||
|
||||
- name: Fetch libdeps, package debian source
|
||||
working-directory: meshtasticd
|
||||
run: debian/ci_pack_sdeb.sh
|
||||
env:
|
||||
SERIES: ${{ inputs.series }}
|
||||
GPG_KEY_ID: ${{ steps.gpg.outputs.keyid }}
|
||||
PKG_VERSION: ${{ steps.version.outputs.deb }}
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware-debian-${{ steps.version.outputs.deb }}~${{ inputs.series }}-src
|
||||
overwrite: true
|
||||
path: |
|
||||
meshtasticd_${{ steps.version.outputs.deb }}*
|
||||
4
.github/workflows/build_docker.yml
vendored
4
.github/workflows/build_docker.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Docker login
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
tags: meshtastic/meshtasticd:${{ steps.version.outputs.version }}
|
||||
tags: meshtastic/meshtasticd:${{ steps.version.outputs.long }}
|
||||
|
||||
- name: Docker build and push
|
||||
if: ${{ github.ref == 'refs/heads/master' && github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
|
||||
|
||||
24
.github/workflows/build_native.yml
vendored
24
.github/workflows/build_native.yml
vendored
@@ -10,12 +10,6 @@ jobs:
|
||||
build-native:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install libs needed for native build
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update --fix-missing
|
||||
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev libi2c-dev
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
@@ -23,29 +17,21 @@ jobs:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Upgrade python tools
|
||||
shell: bash
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio adafruit-nrfutil
|
||||
pip install -U meshtastic --pre
|
||||
|
||||
- name: Upgrade platformio
|
||||
shell: bash
|
||||
run: |
|
||||
pio upgrade
|
||||
- name: Setup native build
|
||||
id: base
|
||||
uses: ./.github/actions/setup-native
|
||||
|
||||
- name: Build Native
|
||||
run: bin/build-native.sh
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware-native-${{ steps.version.outputs.version }}.zip
|
||||
name: firmware-native-${{ steps.version.outputs.long }}.zip
|
||||
overwrite: true
|
||||
path: |
|
||||
release/meshtasticd_linux_x86_64
|
||||
|
||||
4
.github/workflows/build_raspbian.yml
vendored
4
.github/workflows/build_raspbian.yml
vendored
@@ -39,13 +39,13 @@ jobs:
|
||||
run: bin/build-native.sh
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware-raspbian-${{ steps.version.outputs.version }}.zip
|
||||
name: firmware-raspbian-${{ steps.version.outputs.long }}.zip
|
||||
overwrite: true
|
||||
path: |
|
||||
release/meshtasticd_linux_aarch64
|
||||
|
||||
4
.github/workflows/build_raspbian_armv7l.yml
vendored
4
.github/workflows/build_raspbian_armv7l.yml
vendored
@@ -39,13 +39,13 @@ jobs:
|
||||
run: bin/build-native.sh
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware-raspbian-armv7l-${{ steps.version.outputs.version }}.zip
|
||||
name: firmware-raspbian-armv7l-${{ steps.version.outputs.long }}.zip
|
||||
overwrite: true
|
||||
path: |
|
||||
release/meshtasticd_linux_armv7l
|
||||
|
||||
45
.github/workflows/daily_packaging.yml
vendored
Normal file
45
.github/workflows/daily_packaging.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
name: Daily Packaging
|
||||
on:
|
||||
schedule:
|
||||
- cron: 0 9 * * *
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- debian/**
|
||||
- "*.rpkg"
|
||||
- .github/workflows/nightly_packaging.yml
|
||||
- .github/workflows/build_debian_src.yml
|
||||
- .github/workflows/package_ppa.yml
|
||||
- .github/workflows/package_obs.yml
|
||||
- .github/workflows/hook_copr.yml
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
package-ppa:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
series: [plucky, oracular, noble, jammy]
|
||||
uses: ./.github/workflows/package_ppa.yml
|
||||
with:
|
||||
ppa_repo: ppa:meshtastic/daily
|
||||
series: ${{ matrix.series }}
|
||||
secrets: inherit
|
||||
|
||||
package-obs:
|
||||
uses: ./.github/workflows/package_obs.yml
|
||||
with:
|
||||
obs_project: home:meshtastic:daily
|
||||
series: unstable
|
||||
secrets: inherit
|
||||
|
||||
hook-copr:
|
||||
uses: ./.github/workflows/hook_copr.yml
|
||||
with:
|
||||
copr_project: daily
|
||||
secrets: inherit
|
||||
61
.github/workflows/hook_copr.yml
vendored
Normal file
61
.github/workflows/hook_copr.yml
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
name: Trigger COPR build
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
secrets:
|
||||
COPR_HOOK_DAILY:
|
||||
COPR_HOOK_ALPHA:
|
||||
COPR_HOOK_BETA:
|
||||
inputs:
|
||||
copr_project:
|
||||
description: COPR project to target
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
build-copr-hook:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
ref: ${{ github.ref }}
|
||||
repository: ${{ github.repository }}
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
pip install requests
|
||||
|
||||
- name: Trigger COPR build
|
||||
shell: python
|
||||
run: |
|
||||
import requests
|
||||
|
||||
project_name = "${{ inputs.copr_project }}"
|
||||
if project_name == "daily":
|
||||
hook_secret = "${{ secrets.COPR_HOOK_DAILY }}"
|
||||
project_id = 160277
|
||||
elif project_name == "alpha":
|
||||
hook_secret = "${{ secrets.COPR_HOOK_ALPHA }}"
|
||||
project_id = 160278
|
||||
elif project_name == "beta":
|
||||
hook_secret = "${{ secrets.COPR_HOOK_BETA }}"
|
||||
project_id = 160279
|
||||
else:
|
||||
raise ValueError(f"Unknown COPR project: {project_name}")
|
||||
|
||||
webhook_url = f"https://copr.fedorainfracloud.org/webhooks/github/{project_id}/{hook_secret}/meshtasticd/"
|
||||
copr_payload = {
|
||||
"ref": "${{ github.ref }}",
|
||||
"after": "${{ github.sha }}",
|
||||
"repository": {
|
||||
"clone_url": "${{ github.server_url }}/${{ github.repository }}.git",
|
||||
}
|
||||
}
|
||||
r = requests.post(webhook_url, json=copr_payload, headers={"X-GitHub-Event": "push"})
|
||||
r.raise_for_status()
|
||||
127
.github/workflows/main_matrix.yml
vendored
127
.github/workflows/main_matrix.yml
vendored
@@ -137,6 +137,16 @@ jobs:
|
||||
package-native:
|
||||
uses: ./.github/workflows/package_amd64.yml
|
||||
|
||||
build-debian-src:
|
||||
uses: ./.github/workflows/build_debian_src.yml
|
||||
with:
|
||||
series: UNRELEASED
|
||||
build_location: local
|
||||
secrets: inherit
|
||||
|
||||
test-native:
|
||||
uses: ./.github/workflows/test_native.yml
|
||||
|
||||
build-docker:
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/workflows/build_docker.yml
|
||||
@@ -189,7 +199,7 @@ jobs:
|
||||
run: ls -R
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Move files up
|
||||
@@ -198,7 +208,7 @@ jobs:
|
||||
- name: Repackage in single firmware zip
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}
|
||||
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}
|
||||
overwrite: true
|
||||
path: |
|
||||
./firmware-*.bin
|
||||
@@ -215,7 +225,7 @@ jobs:
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}
|
||||
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
path: ./output
|
||||
|
||||
@@ -229,12 +239,12 @@ jobs:
|
||||
chmod +x ./output/device-update.sh
|
||||
|
||||
- name: Zip firmware
|
||||
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip ./output
|
||||
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip ./output
|
||||
|
||||
- name: Repackage in single elfs zip
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip
|
||||
name: debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip
|
||||
overwrite: true
|
||||
path: ./*.elf
|
||||
retention-days: 30
|
||||
@@ -242,8 +252,8 @@ jobs:
|
||||
- uses: scruplelesswizard/comment-artifact@main
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
with:
|
||||
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}
|
||||
description: "Download firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip. This artifact will be available for 90 days from creation"
|
||||
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}
|
||||
description: "Download firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip. This artifact will be available for 90 days from creation"
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
release-artifacts:
|
||||
@@ -257,6 +267,7 @@ jobs:
|
||||
package-raspbian,
|
||||
package-raspbian-armv7l,
|
||||
package-native,
|
||||
build-debian-src,
|
||||
]
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -268,73 +279,70 @@ jobs:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
run: |
|
||||
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
env:
|
||||
BUILD_LOCATION: local
|
||||
|
||||
- name: Create release
|
||||
uses: actions/create-release@v1
|
||||
uses: softprops/action-gh-release@v2
|
||||
id: create_release
|
||||
with:
|
||||
draft: true
|
||||
prerelease: true
|
||||
release_name: Meshtastic Firmware ${{ steps.version.outputs.version }} Alpha
|
||||
tag_name: v${{ steps.version.outputs.version }}
|
||||
name: Meshtastic Firmware ${{ steps.version.outputs.long }} Alpha
|
||||
tag_name: v${{ steps.version.outputs.long }}
|
||||
body: |
|
||||
Autogenerated by github action, developer should edit as required before publishing...
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
- name: Download deb files
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: meshtasticd_${{ steps.version.outputs.version }}_*.deb
|
||||
pattern: meshtasticd_${{ steps.version.outputs.long }}_*.deb
|
||||
merge-multiple: true
|
||||
path: ./output
|
||||
|
||||
- name: Download source deb
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: firmware-debian-${{ steps.version.outputs.deb }}~UNRELEASED-src
|
||||
merge-multiple: true
|
||||
path: ./output/debian-src
|
||||
|
||||
- name: Zip source deb
|
||||
working-directory: output
|
||||
run: zip -j -9 -r ./meshtasticd-${{ steps.version.outputs.deb }}-src.zip ./debian-src
|
||||
|
||||
# For diagnostics
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -lR
|
||||
|
||||
- name: Add raspbian aarch64 .deb
|
||||
uses: actions/upload-release-asset@v1
|
||||
- name: Add deb files to release
|
||||
run: |
|
||||
gh release upload v${{ steps.version.outputs.long }} ./output/meshtasticd_${{ steps.version.outputs.long }}_arm64.deb
|
||||
gh release upload v${{ steps.version.outputs.long }} ./output/meshtasticd_${{ steps.version.outputs.long }}_armhf.deb
|
||||
gh release upload v${{ steps.version.outputs.long }} ./output/meshtasticd_${{ steps.version.outputs.long }}_amd64.deb
|
||||
gh release upload v${{ steps.version.outputs.long }} ./output/meshtasticd-${{ steps.version.outputs.deb }}-src.zip
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./output/meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
|
||||
asset_name: meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
|
||||
asset_content_type: application/vnd.debian.binary-package
|
||||
|
||||
- name: Add raspbian armv7l .deb
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./output/meshtasticd_${{ steps.version.outputs.version }}_armhf.deb
|
||||
asset_name: meshtasticd_${{ steps.version.outputs.version }}_armhf.deb
|
||||
asset_content_type: application/vnd.debian.binary-package
|
||||
|
||||
- name: Add raspbian amd64 .deb
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./output/meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
|
||||
asset_name: meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
|
||||
asset_content_type: application/vnd.debian.binary-package
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Bump version.properties
|
||||
run: >-
|
||||
bin/bump_version.py
|
||||
|
||||
- name: Update debian changelog
|
||||
run: >-
|
||||
debian/ci_changelog.sh
|
||||
|
||||
- name: Create version.properties pull request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
title: Bump version.properties
|
||||
add-paths: |
|
||||
version.properties
|
||||
debian/changelog
|
||||
|
||||
release-firmware:
|
||||
strategy:
|
||||
@@ -354,12 +362,12 @@ jobs:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}
|
||||
pattern: firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
path: ./output
|
||||
|
||||
@@ -372,37 +380,24 @@ jobs:
|
||||
chmod +x ./output/device-update.sh
|
||||
|
||||
- name: Zip firmware
|
||||
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip ./output
|
||||
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip ./output
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip
|
||||
name: debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip
|
||||
merge-multiple: true
|
||||
path: ./elfs
|
||||
|
||||
- name: Zip firmware
|
||||
run: zip -j -9 -r ./debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip ./elfs
|
||||
- name: Zip debug elfs
|
||||
run: zip -j -9 -r ./debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip ./elfs
|
||||
|
||||
# For diagnostics
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -lR
|
||||
|
||||
- name: Add bins to release
|
||||
uses: actions/upload-release-asset@v1
|
||||
- name: Add bins and debug elfs to release
|
||||
run: |
|
||||
gh release upload v${{ steps.version.outputs.long }} ./firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip
|
||||
gh release upload v${{ steps.version.outputs.long }} ./debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
with:
|
||||
upload_url: ${{needs.release-artifacts.outputs.upload_url}}
|
||||
asset_path: ./firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip
|
||||
asset_name: firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip
|
||||
asset_content_type: application/zip
|
||||
|
||||
- name: Add debug elfs to release
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
with:
|
||||
upload_url: ${{needs.release-artifacts.outputs.upload_url}}
|
||||
asset_path: ./debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip
|
||||
asset_name: debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip
|
||||
asset_content_type: application/zip
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
8
.github/workflows/package_amd64.yml
vendored
8
.github/workflows/package_amd64.yml
vendored
@@ -32,13 +32,13 @@ jobs:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: firmware-native-${{ steps.version.outputs.version }}.zip
|
||||
name: firmware-native-${{ steps.version.outputs.long }}.zip
|
||||
merge-multiple: true
|
||||
|
||||
- name: Display structure of downloaded files
|
||||
@@ -77,14 +77,14 @@ jobs:
|
||||
package: meshtasticd
|
||||
package_root: .debpkg
|
||||
maintainer: Jonathan Bennett
|
||||
version: ${{ steps.version.outputs.version }} # refs/tags/v*.*.*
|
||||
version: ${{ steps.version.outputs.long }} # refs/tags/v*.*.*
|
||||
arch: amd64
|
||||
depends: libyaml-cpp0.7, openssl, libulfius2.7, libi2c0
|
||||
desc: Native Linux Meshtastic binary.
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
|
||||
name: meshtasticd_${{ steps.version.outputs.long }}_amd64.deb
|
||||
overwrite: true
|
||||
path: |
|
||||
./*.deb
|
||||
|
||||
110
.github/workflows/package_obs.yml
vendored
Normal file
110
.github/workflows/package_obs.yml
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
name: Package for OpenSUSE Build Service
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
secrets:
|
||||
OBS_PASSWORD:
|
||||
required: true
|
||||
PPA_GPG_PRIVATE_KEY:
|
||||
required: true
|
||||
inputs:
|
||||
obs_project:
|
||||
description: Meshtastic OBS project to target
|
||||
required: true
|
||||
type: string
|
||||
series:
|
||||
description: Debian series to target
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
build-debian-src:
|
||||
uses: ./.github/workflows/build_debian_src.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
series: ${{ inputs.series }}
|
||||
build_location: obs
|
||||
|
||||
package-obs:
|
||||
runs-on: ubuntu-24.04
|
||||
needs: build-debian-src
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
path: meshtasticd
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Install OpenSUSE Build Service deps
|
||||
shell: bash
|
||||
run: |
|
||||
echo 'deb http://download.opensuse.org/repositories/openSUSE:/Tools/xUbuntu_24.04/ /' | sudo tee /etc/apt/sources.list.d/openSUSE:Tools.list
|
||||
curl -fsSL https://download.opensuse.org/repositories/openSUSE:Tools/xUbuntu_24.04/Release.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/openSUSE_Tools.gpg > /dev/null
|
||||
sudo apt-get update -y --fix-missing
|
||||
sudo apt-get install -y osc
|
||||
|
||||
- name: Get release version string
|
||||
working-directory: meshtasticd
|
||||
run: |
|
||||
echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
BUILD_LOCATION: obs
|
||||
id: version
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: firmware-debian-${{ steps.version.outputs.deb }}~${{ inputs.series }}-src
|
||||
merge-multiple: true
|
||||
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -lah
|
||||
|
||||
- name: Configure osc
|
||||
env:
|
||||
OBS_USERNAME: meshtastic
|
||||
run: |
|
||||
# Setup OpenSUSE Build Service credentials
|
||||
mkdir -p ~/.config/osc
|
||||
echo "[general]" > ~/.config/osc/oscrc
|
||||
echo "apiurl=https://api.opensuse.org" >> ~/.config/osc/oscrc
|
||||
echo "[https://api.opensuse.org]" >> ~/.config/osc/oscrc
|
||||
echo "user=${{ env.OBS_USERNAME }}" >> ~/.config/osc/oscrc
|
||||
echo "pass=${{ secrets.OBS_PASSWORD }}" >> ~/.config/osc/oscrc
|
||||
echo "credentials_mgr_class=osc.credentials.PlaintextConfigFileCredentialsManager" >> ~/.config/osc/oscrc
|
||||
# Create a temporary directory for osc checkout
|
||||
mkdir -p osc
|
||||
|
||||
# Intentionally fail if credentials are invalid
|
||||
# Update secrets if this returns `401`
|
||||
- name: Verify OBS authentication
|
||||
run: osc token
|
||||
|
||||
- name: Upload package to OBS
|
||||
shell: bash
|
||||
working-directory: osc
|
||||
env:
|
||||
OBS_PROJECT: ${{ inputs.obs_project }}
|
||||
OBS_PACKAGE: meshtasticd
|
||||
run: |
|
||||
# Initialize the package in the current directory
|
||||
osc checkout --output-dir . $OBS_PROJECT $OBS_PACKAGE
|
||||
|
||||
# Remove the existing package files
|
||||
rm -rf *.dsc *.tar.xz
|
||||
|
||||
# Copy new package files to the directory
|
||||
cp $GITHUB_WORKSPACE/*.dsc .
|
||||
cp $GITHUB_WORKSPACE/*.tar.xz .
|
||||
|
||||
# Add/Remove the files
|
||||
osc addremove
|
||||
|
||||
# Commit changes and push to OpenSUSE Build Service
|
||||
osc commit -m "GitHub Actions: ${{ steps.version.outputs.deb }}~${{ inputs.series }}"
|
||||
74
.github/workflows/package_ppa.yml
vendored
Normal file
74
.github/workflows/package_ppa.yml
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
name: Package for Launchpad PPA
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
secrets:
|
||||
PPA_GPG_PRIVATE_KEY:
|
||||
required: true
|
||||
inputs:
|
||||
ppa_repo:
|
||||
description: Meshtastic PPA to target
|
||||
required: true
|
||||
type: string
|
||||
series:
|
||||
description: Ubuntu series to target
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
build-debian-src:
|
||||
uses: ./.github/workflows/build_debian_src.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
series: ${{ inputs.series }}
|
||||
build_location: ppa
|
||||
|
||||
package-ppa:
|
||||
runs-on: ubuntu-24.04
|
||||
needs: build-debian-src
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
path: meshtasticd
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Install deps
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update -y --fix-missing
|
||||
sudo apt-get install -y dput
|
||||
|
||||
- name: Import GPG key
|
||||
uses: crazy-max/ghaction-import-gpg@v6
|
||||
with:
|
||||
gpg_private_key: ${{ secrets.PPA_GPG_PRIVATE_KEY }}
|
||||
id: gpg
|
||||
|
||||
- name: Get release version string
|
||||
working-directory: meshtasticd
|
||||
run: |
|
||||
echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
BUILD_LOCATION: ppa
|
||||
id: version
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: firmware-debian-${{ steps.version.outputs.deb }}~${{ inputs.series }}-src
|
||||
merge-multiple: true
|
||||
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -lah
|
||||
|
||||
- name: Publish with dput
|
||||
if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
|
||||
run: |
|
||||
dput ${{ inputs.ppa_repo }} meshtasticd_${{ steps.version.outputs.deb }}~${{ inputs.series }}_source.changes
|
||||
8
.github/workflows/package_raspbian.yml
vendored
8
.github/workflows/package_raspbian.yml
vendored
@@ -32,13 +32,13 @@ jobs:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: firmware-raspbian-${{ steps.version.outputs.version }}.zip
|
||||
name: firmware-raspbian-${{ steps.version.outputs.long }}.zip
|
||||
merge-multiple: true
|
||||
|
||||
- name: Display structure of downloaded files
|
||||
@@ -77,14 +77,14 @@ jobs:
|
||||
package: meshtasticd
|
||||
package_root: .debpkg
|
||||
maintainer: Jonathan Bennett
|
||||
version: ${{ steps.version.outputs.version }} # refs/tags/v*.*.*
|
||||
version: ${{ steps.version.outputs.long }} # refs/tags/v*.*.*
|
||||
arch: arm64
|
||||
depends: libyaml-cpp0.7, openssl, libulfius2.7, libi2c0
|
||||
desc: Native Linux Meshtastic binary.
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
|
||||
name: meshtasticd_${{ steps.version.outputs.long }}_arm64.deb
|
||||
overwrite: true
|
||||
path: |
|
||||
./*.deb
|
||||
|
||||
@@ -32,13 +32,13 @@ jobs:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: firmware-raspbian-armv7l-${{ steps.version.outputs.version }}.zip
|
||||
name: firmware-raspbian-armv7l-${{ steps.version.outputs.long }}.zip
|
||||
merge-multiple: true
|
||||
|
||||
- name: Display structure of downloaded files
|
||||
@@ -77,14 +77,14 @@ jobs:
|
||||
package: meshtasticd
|
||||
package_root: .debpkg
|
||||
maintainer: Jonathan Bennett
|
||||
version: ${{ steps.version.outputs.version }} # refs/tags/v*.*.*
|
||||
version: ${{ steps.version.outputs.long }} # refs/tags/v*.*.*
|
||||
arch: armhf
|
||||
depends: libyaml-cpp0.7, openssl, libulfius2.7, libi2c0
|
||||
desc: Native Linux Meshtastic binary.
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: meshtasticd_${{ steps.version.outputs.version }}_armhf.deb
|
||||
name: meshtasticd_${{ steps.version.outputs.long }}_armhf.deb
|
||||
overwrite: true
|
||||
path: |
|
||||
./*.deb
|
||||
|
||||
38
.github/workflows/release_channels.yml
vendored
Normal file
38
.github/workflows/release_channels.yml
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
name: Trigger release workflows upon Publish
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published, released]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
package-ppa:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
series: [plucky, oracular, noble, jammy]
|
||||
uses: ./.github/workflows/package_ppa.yml
|
||||
with:
|
||||
ppa_repo: |-
|
||||
ppa:meshtastic/${{ contains(github.event.release.name, 'Beta') && 'beta' || contains(github.event.release.name, 'Alpha') && 'alpha' }}
|
||||
series: ${{ matrix.series }}
|
||||
secrets: inherit
|
||||
|
||||
package-obs:
|
||||
uses: ./.github/workflows/package_obs.yml
|
||||
with:
|
||||
obs_project: |-
|
||||
home:meshtastic:${{ contains(github.event.release.name, 'Beta') && 'beta' || contains(github.event.release.name, 'Alpha') && 'alpha' }}
|
||||
series: |-
|
||||
${{ contains(github.event.release.name, 'Beta') && 'beta' || contains(github.event.release.name, 'Alpha') && 'alpha' }}
|
||||
secrets: inherit
|
||||
|
||||
# hook-copr:
|
||||
# uses: ./.github/workflows/hook_copr.yml
|
||||
# with:
|
||||
# copr_project: |-
|
||||
# ${{ contains(github.event.release.name, 'Beta') && 'beta' || contains(github.event.release.name, 'Alpha') && 'alpha' }}
|
||||
# secrets: inherit
|
||||
169
.github/workflows/test_native.yml
vendored
Normal file
169
.github/workflows/test_native.yml
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
name: Run Tests on Native platform
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: {}
|
||||
|
||||
env:
|
||||
LCOV_CAPTURE_FLAGS: --quiet --capture --include "${PWD}/src/*" --exclude '*/src/mesh/generated/*' --directory .pio/build/coverage/src --base-directory "${PWD}"
|
||||
|
||||
jobs:
|
||||
simulator-tests:
|
||||
name: Native Simulator Tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup native build
|
||||
id: base
|
||||
uses: ./.github/actions/setup-native
|
||||
|
||||
- name: Install simulator dependencies
|
||||
run: pip install -U dotmap
|
||||
|
||||
# We now run integration test before other build steps (to quickly see runtime failures)
|
||||
- name: Build for native/coverage
|
||||
run: platformio run -e coverage
|
||||
|
||||
- name: Capture initial coverage information
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get install -y lcov
|
||||
lcov ${{ env.LCOV_CAPTURE_FLAGS }} --initial --output-file coverage_base.info
|
||||
sed -i -e "s#${PWD}#.#" coverage_base.info # Make paths relative.
|
||||
|
||||
- name: Integration test
|
||||
run: |
|
||||
.pio/build/coverage/program &
|
||||
PID=$!
|
||||
timeout 20 bash -c "until ls -al /proc/$PID/fd | grep socket; do sleep 1; done"
|
||||
echo "Simulator started, launching python test..."
|
||||
python3 -c 'from meshtastic.test import testSimulator; testSimulator()'
|
||||
wait
|
||||
|
||||
- name: Capture coverage information
|
||||
if: always() # run this step even if previous step failed
|
||||
run: |
|
||||
lcov ${{ env.LCOV_CAPTURE_FLAGS }} --test-name integration --output-file coverage_integration.info
|
||||
sed -i -e "s#${PWD}#.#" coverage_integration.info # Make paths relative.
|
||||
|
||||
- name: Get release version string
|
||||
if: always() # run this step even if previous step failed
|
||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Save coverage information
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always() # run this step even if previous step failed
|
||||
with:
|
||||
name: lcov-coverage-info-native-simulator-test-${{ steps.version.outputs.long }}.zip
|
||||
overwrite: true
|
||||
path: ./coverage_*.info
|
||||
|
||||
platformio-tests:
|
||||
name: Native PlatformIO Tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup native build
|
||||
id: base
|
||||
uses: ./.github/actions/setup-native
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
# Disable (comment-out) BUILD_EPOCH. It causes a full rebuild between tests and resets the
|
||||
# coverage information each time.
|
||||
- name: Disable BUILD_EPOCH
|
||||
run: sed -i 's/-DBUILD_EPOCH=$UNIX_TIME/#-DBUILD_EPOCH=$UNIX_TIME/' platformio.ini
|
||||
|
||||
- name: PlatformIO Tests
|
||||
run: platformio test -e coverage -v --junit-output-path testreport.xml
|
||||
|
||||
- name: Save test results
|
||||
if: always() # run this step even if previous step failed
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: platformio-test-report-${{ steps.version.outputs.long }}.zip
|
||||
overwrite: true
|
||||
path: ./testreport.xml
|
||||
|
||||
- name: Capture coverage information
|
||||
if: always() # run this step even if previous step failed
|
||||
run: |
|
||||
sudo apt-get install -y lcov
|
||||
lcov ${{ env.LCOV_CAPTURE_FLAGS }} --test-name tests --output-file coverage_tests.info
|
||||
sed -i -e "s#${PWD}#.#" coverage_tests.info # Make paths relative.
|
||||
|
||||
- name: Save coverage information
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always() # run this step even if previous step failed
|
||||
with:
|
||||
name: lcov-coverage-info-native-platformio-tests-${{ steps.version.outputs.long }}.zip
|
||||
overwrite: true
|
||||
path: ./coverage_*.info
|
||||
|
||||
generate-reports:
|
||||
name: Generate Test Reports
|
||||
runs-on: ubuntu-latest
|
||||
permissions: # Needed for dorny/test-reporter.
|
||||
contents: read
|
||||
actions: read
|
||||
checks: write
|
||||
needs:
|
||||
- simulator-tests
|
||||
- platformio-tests
|
||||
if: always()
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Download test artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: platformio-test-report-${{ steps.version.outputs.long }}.zip
|
||||
merge-multiple: true
|
||||
|
||||
- name: Test Report
|
||||
uses: dorny/test-reporter@v1.9.1
|
||||
with:
|
||||
name: PlatformIO Tests
|
||||
path: testreport.xml
|
||||
reporter: java-junit
|
||||
|
||||
- name: Download coverage artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: lcov-coverage-info-native-*-${{ steps.version.outputs.long }}.zip
|
||||
path: code-coverage-report
|
||||
merge-multiple: true
|
||||
|
||||
- name: Generate Code Coverage Report
|
||||
run: |
|
||||
sudo apt-get install -y lcov
|
||||
lcov --quiet --add-tracefile code-coverage-report/coverage_base.info --add-tracefile code-coverage-report/coverage_integration.info --add-tracefile code-coverage-report/coverage_tests.info --output-file code-coverage-report/coverage_src.info
|
||||
genhtml --quiet --legend --prefix "${PWD}" code-coverage-report/coverage_src.info --output-directory code-coverage-report
|
||||
|
||||
- name: Save Code Coverage Report
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: code-coverage-report-${{ steps.version.outputs.long }}.zip
|
||||
path: code-coverage-report
|
||||
75
.github/workflows/tests.yml
vendored
75
.github/workflows/tests.yml
vendored
@@ -6,79 +6,8 @@ on:
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
test-simulator:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
LCOV_CAPTURE_FLAGS: --quiet --capture --include "${PWD}/src/*" --exclude '*/src/mesh/generated/*' --directory .pio/build/coverage/src --base-directory "${PWD}"
|
||||
steps:
|
||||
- name: Install libs needed for native build
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update --fix-missing
|
||||
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev libi2c-dev
|
||||
sudo apt-get install -y lcov
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Upgrade python tools
|
||||
shell: bash
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio adafruit-nrfutil dotmap
|
||||
pip install -U meshtastic --pre
|
||||
|
||||
- name: Upgrade platformio
|
||||
shell: bash
|
||||
run: |
|
||||
pio upgrade
|
||||
|
||||
- name: Build Native
|
||||
run: bin/build-native.sh
|
||||
|
||||
# We now run integration test before other build steps (to quickly see runtime failures)
|
||||
- name: Build for native/coverage
|
||||
run: |
|
||||
platformio run -e coverage
|
||||
lcov ${{ env.LCOV_CAPTURE_FLAGS }} --initial --output-file coverage_base.info
|
||||
|
||||
- name: Integration test
|
||||
run: |
|
||||
.pio/build/coverage/program &
|
||||
PID=$!
|
||||
timeout 20 bash -c "until ls -al /proc/$PID/fd | grep socket; do sleep 1; done"
|
||||
echo "Simulator started, launching python test..."
|
||||
python3 -c 'from meshtastic.test import testSimulator; testSimulator()'
|
||||
wait
|
||||
lcov ${{ env.LCOV_CAPTURE_FLAGS }} --test-name integration --output-file coverage_integration.info
|
||||
|
||||
- name: PlatformIO Tests
|
||||
run: |
|
||||
platformio test -e coverage --junit-output-path testreport.xml
|
||||
lcov ${{ env.LCOV_CAPTURE_FLAGS }} --test-name tests --output-file coverage_tests.info
|
||||
|
||||
- name: Test Report
|
||||
uses: dorny/test-reporter@v1.9.1
|
||||
if: success() || failure() # run this step even if previous step failed
|
||||
with:
|
||||
name: PlatformIO Tests
|
||||
path: testreport.xml
|
||||
reporter: java-junit
|
||||
|
||||
- name: Generate Code Coverage Report
|
||||
run: |
|
||||
lcov --quiet --add-tracefile coverage_base.info --add-tracefile coverage_integration.info --add-tracefile coverage_tests.info --output-file coverage_src.info
|
||||
mkdir code-coverage-report
|
||||
genhtml --quiet --legend --prefix "${PWD}" coverage_src.info --output-directory code-coverage-report
|
||||
mv coverage_*.info code-coverage-report
|
||||
|
||||
- name: Save Code Coverage Report
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: code-coverage-report
|
||||
path: code-coverage-report
|
||||
native-tests:
|
||||
uses: ./.github/workflows/test_native.yml
|
||||
|
||||
hardware-tests:
|
||||
runs-on: test-runner
|
||||
|
||||
6
.github/workflows/trunk_format_pr.yml
vendored
6
.github/workflows/trunk_format_pr.yml
vendored
@@ -22,12 +22,16 @@ jobs:
|
||||
- name: Run Trunk Fmt
|
||||
run: trunk fmt
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Commit and push changes
|
||||
run: |
|
||||
git config --global user.name "github-actions[bot]"
|
||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git add .
|
||||
git commit -m "Add firmware version ${{ steps.version.outputs.version }}"
|
||||
git commit -m "Add firmware version ${{ steps.version.outputs.long }}"
|
||||
git push
|
||||
|
||||
- name: Comment on PR
|
||||
|
||||
1
.github/workflows/update_protobufs.yml
vendored
1
.github/workflows/update_protobufs.yml
vendored
@@ -12,6 +12,7 @@ jobs:
|
||||
submodules: true
|
||||
|
||||
- name: Update submodule
|
||||
if: ${{ github.ref == 'refs/heads/master' }}
|
||||
run: |
|
||||
git submodule update --remote protobufs
|
||||
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,4 +1,8 @@
|
||||
.pio
|
||||
pio
|
||||
pio.tar
|
||||
web
|
||||
web.tar
|
||||
|
||||
# ignore vscode IDE settings files
|
||||
.vscode/*
|
||||
@@ -30,4 +34,4 @@ release/
|
||||
.vscode/extensions.json
|
||||
/compile_commands.json
|
||||
src/mesh/raspihttp/certificate.pem
|
||||
src/mesh/raspihttp/private_key.pem
|
||||
src/mesh/raspihttp/private_key.pem
|
||||
@@ -25,7 +25,7 @@ lib_deps =
|
||||
${networking_base.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
rweather/Crypto@^0.4.0
|
||||
https://github.com/lovyan03/LovyanGFX.git#1401c28a47646fe00538d487adcb2eb3c72de805
|
||||
lovyan03/LovyanGFX@^1.2.0
|
||||
https://github.com/pine64/libch341-spi-userspace#a9b17e3452f7fb747000d9b4ad4409155b39f6ef
|
||||
|
||||
build_flags =
|
||||
@@ -40,4 +40,4 @@ build_flags =
|
||||
-lgpiod
|
||||
-lyaml-cpp
|
||||
-li2c
|
||||
-std=c++17
|
||||
-std=c++17
|
||||
|
||||
@@ -7,12 +7,12 @@ platform_packages = framework-arduinopico@https://github.com/earlephilhower/ardu
|
||||
board_build.core = earlephilhower
|
||||
board_build.filesystem_size = 0.5m
|
||||
build_flags =
|
||||
${arduino_base.build_flags} -Wno-unused-variable
|
||||
${arduino_base.build_flags} -Wno-unused-variable -Wcast-align
|
||||
-Isrc/platform/rp2xx0
|
||||
-D__PLAT_RP2040__
|
||||
-D__PLAT_RP2350__
|
||||
# -D _POSIX_THREADS
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> -<mesh/wifi/> -<mesh/http/> -<mesh/raspihttp>
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> -<mesh/wifi/> -<mesh/http/> -<mesh/raspihttp> -<platform/rp2xx0/pico_sleep> -<platform/rp2xx0/hardware_rosc>
|
||||
|
||||
lib_ignore =
|
||||
BluetoothOTA
|
||||
|
||||
1
bin/.gitignore
vendored
Normal file
1
bin/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
config.yaml
|
||||
@@ -12,12 +12,6 @@ Lora:
|
||||
# IRQ: 17
|
||||
# Reset: 22
|
||||
|
||||
# Module: RF95 # Adafruit RFM9x
|
||||
# Reset: 25
|
||||
# CS: 7
|
||||
# IRQ: 22
|
||||
# Busy: 23
|
||||
|
||||
# Module: RF95 # Elecrow Lora RFM95 IOT https://www.elecrow.com/lora-rfm95-iot-board-for-rpi.html
|
||||
# Reset: 22
|
||||
# CS: 7
|
||||
@@ -29,6 +23,47 @@ Lora:
|
||||
# Busy: 20
|
||||
# Reset: 18
|
||||
|
||||
### The Radxa Zero 3E/W employs multiple gpio chips.
|
||||
### Each gpio pin must be unique, but can be assigned to a specific gpio chip and line.
|
||||
### In case solely a no. is given, the default gpio chip and pin == line will be employed.
|
||||
###
|
||||
# Module: sx1262 # Radxa Zero 3E/W + Ebyte E22-900M30S
|
||||
# DIO2_AS_RF_SWITCH: true
|
||||
# DIO3_TCXO_VOLTAGE: 1.8
|
||||
# CS: # NSS PIN_24 -> chip 4, line 22
|
||||
# pin: 24
|
||||
# gpiochip: 4
|
||||
# line: 22
|
||||
# SCK: # SCK PIN_23 -> chip 4, line 18
|
||||
# pin: 23
|
||||
# gpiochip: 4
|
||||
# line: 18
|
||||
# Busy: # BUSY PIN_29 -> chip 3!, line 11
|
||||
# pin: 29
|
||||
# gpiochip: 3
|
||||
# line: 11
|
||||
# MOSI: # MOSI PIN_19 -> chip 4, line 19
|
||||
# pin: 19
|
||||
# gpiochip: 4
|
||||
# line: 19
|
||||
# MISO: # MISO PIN_21 -> chip 4, line 21
|
||||
# pin: 21
|
||||
# gpiochip: 4
|
||||
# line: 21
|
||||
# Reset: # NRST PIN_27 -> chip 4, line 10
|
||||
# pin: 27
|
||||
# gpiochip: 4
|
||||
# line: 10
|
||||
# IRQ: # DIO1 PIN_28 -> chip 4, line 11
|
||||
# pin: 28
|
||||
# gpiochip: 4
|
||||
# line: 11
|
||||
# RXen: # RXEN PIN_22 -> chip 3!, line 17
|
||||
# pin: 22
|
||||
# gpiochip: 3
|
||||
# line: 17
|
||||
# TXen: RADIOLIB_NC # TXEN no PIN, no line, fallback to default gpio chip
|
||||
|
||||
# Module: sx1268 # SX1268-based modules, tested with Ebyte E22 400M33S
|
||||
# CS: 21
|
||||
# IRQ: 16
|
||||
@@ -45,7 +80,7 @@ Lora:
|
||||
|
||||
# spiSpeed: 2000000
|
||||
|
||||
### Set gpio chip to use in /dev/. Defaults to 0.
|
||||
### Set default/fallback gpio chip to use in /dev/. Defaults to 0.
|
||||
### Notably the Raspberry Pi 5 puts the GPIO header on gpiochip4
|
||||
# gpiochip: 4
|
||||
|
||||
@@ -153,4 +188,4 @@ General:
|
||||
MaxMessageQueue: 100
|
||||
ConfigDirectory: /etc/meshtasticd/config.d/
|
||||
# MACAddress: AA:BB:CC:DD:EE:FF
|
||||
# MACAddressSource: eth0
|
||||
# MACAddressSource: eth0
|
||||
|
||||
5
bin/config.d/lora-Adafruit-RFM9x
Normal file
5
bin/config.d/lora-Adafruit-RFM9x
Normal file
@@ -0,0 +1,5 @@
|
||||
# Module: RF95 # Adafruit RFM9x
|
||||
# Reset: 25
|
||||
# CS: 7
|
||||
# IRQ: 22
|
||||
# Busy: 23
|
||||
@@ -73,7 +73,7 @@ shift "$((OPTIND - 1))"
|
||||
if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then
|
||||
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
|
||||
$ESPTOOL_CMD erase_flash
|
||||
$ESPTOOL_CMD write_flash 0x00 ${FILENAME}
|
||||
$ESPTOOL_CMD write_flash 0x00 "${FILENAME}"
|
||||
# Account for S3 board's different OTA partition
|
||||
if [ -n "${FILENAME##*"s3"*}" ] && [ -n "${FILENAME##*"-v3"*}" ] && [ -n "${FILENAME##*"t-deck"*}" ] && [ -n "${FILENAME##*"wireless-paper"*}" ] && [ -n "${FILENAME##*"wireless-tracker"*}" ] && [ -n "${FILENAME##*"station-g2"*}" ] && [ -n "${FILENAME##*"unphone"*}" ]; then
|
||||
if [ -n "${FILENAME##*"esp32c3"*}" ]; then
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import configparser
|
||||
import subprocess
|
||||
|
||||
import os
|
||||
run_number = os.getenv('GITHUB_RUN_NUMBER', '0')
|
||||
build_location = os.getenv('BUILD_LOCATION', 'local')
|
||||
|
||||
def readProps(prefsLoc):
|
||||
"""Read the version of our project as a string"""
|
||||
@@ -11,6 +13,7 @@ def readProps(prefsLoc):
|
||||
verObj = dict(
|
||||
short="{}.{}.{}".format(version["major"], version["minor"], version["build"]),
|
||||
long="unset",
|
||||
deb="unset",
|
||||
)
|
||||
|
||||
# Try to find current build SHA if if the workspace is clean. This could fail if git is not installed
|
||||
@@ -27,16 +30,16 @@ def readProps(prefsLoc):
|
||||
# if isDirty:
|
||||
# # short for 'dirty', we want to keep our verstrings source for protobuf reasons
|
||||
# suffix = sha + "-d"
|
||||
verObj["long"] = "{}.{}.{}.{}".format(
|
||||
version["major"], version["minor"], version["build"], suffix
|
||||
)
|
||||
verObj["long"] = "{}.{}".format(verObj["short"], suffix)
|
||||
verObj["deb"] = "{}.{}~{}{}".format(verObj["short"], run_number, build_location, sha)
|
||||
except:
|
||||
# print("Unexpected error:", sys.exc_info()[0])
|
||||
# traceback.print_exc()
|
||||
verObj["long"] = verObj["short"]
|
||||
verObj["deb"] = "{}.{}~{}".format(verObj["short"], run_number, build_location)
|
||||
|
||||
# print("firmware version " + verStr)
|
||||
return verObj
|
||||
|
||||
|
||||
# print("path is" + ','.join(sys.path))
|
||||
# print("path is" + ','.join(sys.path))
|
||||
12
bin/rpkg.macros
Normal file
12
bin/rpkg.macros
Normal file
@@ -0,0 +1,12 @@
|
||||
function meshtastic_version {
|
||||
meshtastic_version=$(python3 bin/buildinfo.py short)
|
||||
echo -n "$meshtastic_version"
|
||||
}
|
||||
function git_commits_num {
|
||||
total_commits=$(git rev-list --all --count)
|
||||
echo -n "$total_commits"
|
||||
}
|
||||
function git_commit_sha {
|
||||
commit_sha=$(git rev-parse --short HEAD)
|
||||
echo -n "$commit_sha"
|
||||
}
|
||||
6
debian/.gitignore
vendored
Normal file
6
debian/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
.debhelper
|
||||
debhelper-build-stamp
|
||||
meshtasticd
|
||||
files
|
||||
meshtasticd.substvars
|
||||
meshtasticd.postrm.debhelper
|
||||
6
debian/changelog
vendored
Normal file
6
debian/changelog
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
meshtasticd (2.5.20.0) UNRELEASED; urgency=medium
|
||||
|
||||
* Initial packaging
|
||||
* GitHub Actions Automatic version bump
|
||||
|
||||
-- Austin Lane <github-actions[bot]@users.noreply.github.com> Mon, 13 Jan 2025 19:24:14 +0000
|
||||
7
debian/ci_changelog.sh
vendored
Executable file
7
debian/ci_changelog.sh
vendored
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/bash
|
||||
export DEBEMAIL="github-actions[bot]@users.noreply.github.com"
|
||||
PKG_VERSION=$(python3 bin/buildinfo.py short)
|
||||
|
||||
dch --newversion "$PKG_VERSION.0" \
|
||||
--distribution UNRELEASED \
|
||||
"GitHub Actions Automatic version bump"
|
||||
23
debian/ci_pack_sdeb.sh
vendored
Executable file
23
debian/ci_pack_sdeb.sh
vendored
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/bash
|
||||
export DEBEMAIL="jbennett@incomsystems.biz"
|
||||
export PLATFORMIO_LIBDEPS_DIR=pio/libdeps
|
||||
export PLATFORMIO_PACKAGES_DIR=pio/packages
|
||||
export PLATFORMIO_CORE_DIR=pio/core
|
||||
|
||||
# Download libraries to `pio`
|
||||
platformio pkg install -e native
|
||||
platformio pkg install -e native -t platformio/tool-scons@4.40502.0
|
||||
# Compress `pio` directory to prevent dh_clean from sanitizing it
|
||||
tar -cf pio.tar pio/
|
||||
rm -rf pio
|
||||
# Download the latest meshtastic/web release build.tar to `web.tar`
|
||||
curl -L https://github.com/meshtastic/web/releases/download/latest/build.tar -o web.tar
|
||||
|
||||
package=$(dpkg-parsechangelog --show-field Source)
|
||||
|
||||
rm -rf debian/changelog
|
||||
dch --create --distribution "$SERIES" --package "$package" --newversion "$PKG_VERSION~$SERIES" \
|
||||
"GitHub Actions Automatic packaging for $PKG_VERSION~$SERIES"
|
||||
|
||||
# Build the source deb
|
||||
debuild -S -nc -k"$GPG_KEY_ID"
|
||||
32
debian/control
vendored
Normal file
32
debian/control
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
Source: meshtasticd
|
||||
Section: misc
|
||||
Priority: optional
|
||||
Maintainer: Austin Lane <vidplace7@gmail.com>
|
||||
Build-Depends: debhelper-compat (= 13),
|
||||
tar,
|
||||
gzip,
|
||||
platformio,
|
||||
python3-protobuf,
|
||||
python3-grpcio,
|
||||
git,
|
||||
g++,
|
||||
pkg-config,
|
||||
libyaml-cpp-dev,
|
||||
libgpiod-dev,
|
||||
libbluetooth-dev,
|
||||
libusb-1.0-0-dev,
|
||||
libi2c-dev,
|
||||
openssl,
|
||||
libssl-dev,
|
||||
libulfius-dev,
|
||||
liborcania-dev
|
||||
Standards-Version: 4.6.2
|
||||
Homepage: https://github.com/meshtastic/firmware
|
||||
Rules-Requires-Root: no
|
||||
|
||||
Package: meshtasticd
|
||||
Architecture: any
|
||||
Depends: ${misc:Depends}, ${shlibs:Depends}
|
||||
Description: Meshtastic daemon for communicating with Meshtastic devices
|
||||
Meshtastic is an off-grid text communication platform that uses inexpensive
|
||||
LoRa radios.
|
||||
4
debian/meshtasticd.dirs
vendored
Normal file
4
debian/meshtasticd.dirs
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
etc/meshtasticd
|
||||
etc/meshtasticd/config.d
|
||||
etc/meshtasticd/available.d
|
||||
usr/share/meshtasticd/web
|
||||
8
debian/meshtasticd.install
vendored
Normal file
8
debian/meshtasticd.install
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
.pio/build/native/meshtasticd usr/sbin
|
||||
|
||||
bin/config.yaml etc/meshtasticd
|
||||
bin/config.d/* etc/meshtasticd/available.d
|
||||
|
||||
bin/meshtasticd.service lib/systemd/system
|
||||
|
||||
web/* usr/share/meshtasticd/web
|
||||
23
debian/rules
vendored
Executable file
23
debian/rules
vendored
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/make -f
|
||||
# export DH_VERBOSE = 1
|
||||
|
||||
# Use the "dh" sequencer
|
||||
%:
|
||||
dh $@
|
||||
|
||||
# https://docs.platformio.org/en/latest/envvars.html
|
||||
PIO_ENV:=\
|
||||
PLATFORMIO_CORE_DIR=pio/core \
|
||||
PLATFORMIO_LIBDEPS_DIR=pio/libdeps \
|
||||
PLATFORMIO_PACKAGES_DIR=pio/packages
|
||||
|
||||
override_dh_auto_build:
|
||||
# Extract tarballs within source deb
|
||||
tar -xf pio.tar
|
||||
mkdir -p web && tar -xf web.tar -C web
|
||||
gunzip web/ -r
|
||||
# Build with platformio
|
||||
$(PIO_ENV) platformio run -e native
|
||||
# Move the binary and default config to the correct name
|
||||
mv .pio/build/native/program .pio/build/native/meshtasticd
|
||||
cp bin/config-dist.yaml bin/config.yaml
|
||||
1
debian/source/format
vendored
Normal file
1
debian/source/format
vendored
Normal file
@@ -0,0 +1 @@
|
||||
3.0 (native)
|
||||
2
debian/source/include-binaries
vendored
Normal file
2
debian/source/include-binaries
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
pio.tar
|
||||
web.tar
|
||||
1
debian/source/options
vendored
Normal file
1
debian/source/options
vendored
Normal file
@@ -0,0 +1 @@
|
||||
extend-diff-ignore = "\.pio"
|
||||
91
meshtasticd.spec.rpkg
Normal file
91
meshtasticd.spec.rpkg
Normal file
@@ -0,0 +1,91 @@
|
||||
# meshtasticd spec file for RPM-based distributions
|
||||
#
|
||||
# Build locally with:
|
||||
# ```
|
||||
# sudo dnf install rpkg-util
|
||||
# rpkg local
|
||||
# ```
|
||||
#
|
||||
# See:
|
||||
# - https://docs.pagure.org/rpkg-util/v3/index.html
|
||||
# - https://docs.fedoraproject.org/en-US/packaging-guidelines/Versioning/
|
||||
|
||||
Name: meshtasticd
|
||||
# Version Ex: 2.5.19
|
||||
Version: {{{ meshtastic_version }}}
|
||||
# Release Ex: 9127.daily.gitd7f5f620.fc41
|
||||
Release: {{{ git_commits_num }}}%{?copr_projectname:.%{copr_projectname}}.git{{{ git_commit_sha }}}%{?dist}
|
||||
VCS: {{{ git_dir_vcs }}}
|
||||
Summary: Meshtastic daemon for communicating with Meshtastic devices
|
||||
|
||||
License: GPL-3.0
|
||||
URL: https://github.com/meshtastic/firmware
|
||||
Source0: {{{ git_dir_pack }}}
|
||||
Source1: https://github.com/meshtastic/web/releases/download/latest/build.tar
|
||||
|
||||
BuildRequires: systemd-rpm-macros
|
||||
BuildRequires: python3-devel
|
||||
BuildRequires: platformio
|
||||
BuildRequires: python3dist(protobuf)
|
||||
BuildRequires: python3dist(grpcio[protobuf])
|
||||
BuildRequires: python3dist(grpcio-tools)
|
||||
BuildRequires: git-core
|
||||
BuildRequires: gcc-c++
|
||||
BuildRequires: pkgconfig(yaml-cpp)
|
||||
BuildRequires: pkgconfig(libgpiod)
|
||||
BuildRequires: pkgconfig(bluez)
|
||||
BuildRequires: pkgconfig(libusb-1.0)
|
||||
BuildRequires: libi2c-devel
|
||||
# Web components:
|
||||
BuildRequires: pkgconfig(openssl)
|
||||
BuildRequires: pkgconfig(liborcania)
|
||||
BuildRequires: pkgconfig(libyder)
|
||||
BuildRequires: pkgconfig(libulfius)
|
||||
|
||||
%description
|
||||
Meshtastic daemon for controlling Meshtastic devices. Meshtastic is an off-grid
|
||||
text communication platform that uses inexpensive LoRa radios.
|
||||
|
||||
%prep
|
||||
{{{ git_dir_setup_macro }}}
|
||||
# Unpack the web files
|
||||
mkdir -p web
|
||||
tar -xf %{SOURCE1} -C web
|
||||
gzip -dr web
|
||||
|
||||
%build
|
||||
# Use the “native” environment from platformio to build a Linux binary
|
||||
platformio run -e native
|
||||
|
||||
%install
|
||||
mkdir -p %{buildroot}%{_sbindir}
|
||||
install -m 0755 .pio/build/native/program %{buildroot}%{_sbindir}/meshtasticd
|
||||
|
||||
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd
|
||||
install -m 0644 bin/config-dist.yaml %{buildroot}%{_sysconfdir}/meshtasticd/config.yaml
|
||||
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/config.d
|
||||
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/available.d
|
||||
cp -r bin/config.d/* %{buildroot}%{_sysconfdir}/meshtasticd/available.d
|
||||
|
||||
install -D -m 0644 bin/meshtasticd.service %{buildroot}%{_unitdir}/meshtasticd.service
|
||||
|
||||
# Install the web files under /usr/share/meshtasticd/web
|
||||
mkdir -p %{buildroot}%{_datadir}/meshtasticd/web
|
||||
cp -r web/* %{buildroot}%{_datadir}/meshtasticd/web
|
||||
|
||||
%files
|
||||
%license LICENSE
|
||||
%doc README.md
|
||||
%{_sbindir}/meshtasticd
|
||||
%dir %{_sysconfdir}/meshtasticd
|
||||
%dir %{_sysconfdir}/meshtasticd/config.d
|
||||
%dir %{_sysconfdir}/meshtasticd/available.d
|
||||
%config(noreplace) %{_sysconfdir}/meshtasticd/config.yaml
|
||||
%config %{_sysconfdir}/meshtasticd/available.d/*
|
||||
%{_unitdir}/meshtasticd.service
|
||||
%dir %{_datadir}/meshtasticd
|
||||
%dir %{_datadir}/meshtasticd/web
|
||||
%{_datadir}/meshtasticd/web/*
|
||||
|
||||
%changelog
|
||||
%autochangelog
|
||||
@@ -3,42 +3,7 @@
|
||||
|
||||
[platformio]
|
||||
default_envs = tbeam
|
||||
;default_envs = pico
|
||||
;default_envs = tbeam-s3-core
|
||||
;default_envs = tbeam0.7
|
||||
;default_envs = heltec-v1
|
||||
;default_envs = heltec-v2_0
|
||||
;default_envs = heltec-v2_1
|
||||
;default_envs = heltec-wireless-tracker
|
||||
;default_envs = chatter2
|
||||
;default_envs = tlora-v1
|
||||
;default_envs = tlora_v1_3
|
||||
;default_envs = tlora-v2
|
||||
;default_envs = tlora-v2-1-1_6
|
||||
;default_envs = tlora-v2-1-1_6-tcxo
|
||||
;default_envs = tlora-v3-3-0-tcxo
|
||||
;default_envs = tlora-t3s3-v1
|
||||
;default_envs = t-echo
|
||||
;default_envs = canaryone
|
||||
;default_envs = native
|
||||
;default_envs = nano-g1
|
||||
;default_envs = pca10059_diy_eink
|
||||
;default_envs = meshtastic-diy-v1
|
||||
;default_envs = meshtastic-diy-v1_1
|
||||
;default_envs = meshtastic-dr-dev
|
||||
;default_envs = m5stack-coreink
|
||||
;default_envs = rak4631
|
||||
;default_envs = rak4631_eth_gw
|
||||
;default_envs = rak2560
|
||||
;default_envs = rak_wismeshtap
|
||||
;default_envs = wio-e5
|
||||
;default_envs = radiomaster_900_bandit_nano
|
||||
;default_envs = radiomaster_900_bandit_micro
|
||||
;default_envs = radiomaster_900_bandit
|
||||
;default_envs = heltec_vision_master_t190
|
||||
;default_envs = heltec_vision_master_e213
|
||||
;default_envs = heltec_vision_master_e290
|
||||
;default_envs = heltec_mesh_node_t114
|
||||
|
||||
extra_configs =
|
||||
arch/*/*.ini
|
||||
variants/*/platformio.ini
|
||||
@@ -84,7 +49,7 @@ build_flags = -Wno-missing-field-initializers
|
||||
-DMESHTASTIC_EXCLUDE_HEALTH_TELEMETRY=1
|
||||
-DMESHTASTIC_EXCLUDE_POWERSTRESS=1 ; exclude power stress test module from main firmware
|
||||
#-DBUILD_EPOCH=$UNIX_TIME
|
||||
;-D OLED_PL
|
||||
#-D OLED_PL=1
|
||||
|
||||
monitor_speed = 115200
|
||||
monitor_filters = direct
|
||||
@@ -123,7 +88,7 @@ lib_deps =
|
||||
|
||||
[radiolib_base]
|
||||
lib_deps =
|
||||
jgromes/RadioLib@7.1.0
|
||||
jgromes/RadioLib@7.1.2
|
||||
|
||||
; Common libs for environmental measurements in telemetry module
|
||||
; (not included in native / portduino)
|
||||
@@ -164,4 +129,4 @@ lib_deps =
|
||||
robtillaart/INA226@0.6.0
|
||||
|
||||
; Health Sensor Libraries
|
||||
sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2
|
||||
sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2
|
||||
|
||||
Submodule protobufs updated: c55f120a9c...76f806e1bb
2
rpkg.conf
Normal file
2
rpkg.conf
Normal file
@@ -0,0 +1,2 @@
|
||||
[rpkg]
|
||||
user_macros = "${git_props:root}/bin/rpkg.macros"
|
||||
@@ -9,6 +9,7 @@
|
||||
*
|
||||
*/
|
||||
#include "FSCommon.h"
|
||||
#include "SPILock.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#ifdef HAS_SDCARD
|
||||
@@ -102,6 +103,8 @@ bool copyFile(const char *from, const char *to)
|
||||
return true;
|
||||
|
||||
#elif defined(FSCom)
|
||||
// take SPI Lock
|
||||
concurrency::LockGuard g(spiLock);
|
||||
unsigned char cbuffer[16];
|
||||
|
||||
File f1 = FSCom.open(from, FILE_O_READ);
|
||||
@@ -145,16 +148,23 @@ bool renameFile(const char *pathFrom, const char *pathTo)
|
||||
return false;
|
||||
}
|
||||
#elif defined(FSCom)
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
// take SPI Lock
|
||||
spiLock->lock();
|
||||
// rename was fixed for ESP32 IDF LittleFS in April
|
||||
return FSCom.rename(pathFrom, pathTo);
|
||||
bool result = FSCom.rename(pathFrom, pathTo);
|
||||
spiLock->unlock();
|
||||
return result;
|
||||
#else
|
||||
// copyFile does its own locking.
|
||||
if (copyFile(pathFrom, pathTo) && FSCom.remove(pathFrom)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -164,6 +174,7 @@ bool renameFile(const char *pathFrom, const char *pathTo)
|
||||
* @brief Get the list of files in a directory.
|
||||
*
|
||||
* This function returns a list of files in a directory. The list includes the full path of each file.
|
||||
* We can't use SPILOCK here because of recursion. Callers of this function should use SPILOCK.
|
||||
*
|
||||
* @param dirname The name of the directory.
|
||||
* @param levels The number of levels of subdirectories to list.
|
||||
@@ -212,6 +223,7 @@ std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels)
|
||||
|
||||
/**
|
||||
* Lists the contents of a directory.
|
||||
* We can't use SPILOCK here because of recursion. Callers of this function should use SPILOCK.
|
||||
*
|
||||
* @param dirname The name of the directory to list.
|
||||
* @param levels The number of levels of subdirectories to list.
|
||||
@@ -325,18 +337,21 @@ void listDir(const char *dirname, uint8_t levels, bool del)
|
||||
void rmDir(const char *dirname)
|
||||
{
|
||||
#ifdef FSCom
|
||||
|
||||
#if (defined(ARCH_ESP32) || defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
|
||||
listDir(dirname, 10, true);
|
||||
#elif defined(ARCH_NRF52)
|
||||
// nRF52 implementation of LittleFS has a recursive delete function
|
||||
FSCom.rmdir_r(dirname);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void fsInit()
|
||||
{
|
||||
#ifdef FSCom
|
||||
spiLock->lock();
|
||||
if (!FSBegin()) {
|
||||
LOG_ERROR("Filesystem mount failed");
|
||||
// assert(0); This auto-formats the partition, so no need to fail here.
|
||||
@@ -347,6 +362,7 @@ void fsInit()
|
||||
LOG_DEBUG("Filesystem files:");
|
||||
#endif
|
||||
listDir("/", 10);
|
||||
spiLock->unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -356,6 +372,7 @@ void fsInit()
|
||||
void setupSDCard()
|
||||
{
|
||||
#ifdef HAS_SDCARD
|
||||
concurrency::LockGuard g(spiLock);
|
||||
SDHandler.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
|
||||
|
||||
if (!SD.begin(SDCARD_CS, SDHandler)) {
|
||||
@@ -383,4 +400,4 @@ void setupSDCard()
|
||||
LOG_DEBUG("Total space: %lu MB", (uint32_t)(SD.totalBytes() / (1024 * 1024)));
|
||||
LOG_DEBUG("Used space: %lu MB", (uint32_t)(SD.usedBytes() / (1024 * 1024)));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,14 @@
|
||||
// Only way to work on both esp32 and nrf52
|
||||
static File openFile(const char *filename, bool fullAtomic)
|
||||
{
|
||||
concurrency::LockGuard g(spiLock);
|
||||
LOG_DEBUG("Opening %s, fullAtomic=%d", filename, fullAtomic);
|
||||
#ifdef ARCH_NRF52
|
||||
lfs_assert_failed = false;
|
||||
File file = FSCom.open(filename, FILE_O_WRITE);
|
||||
file.seek(0);
|
||||
return file;
|
||||
#endif
|
||||
if (!fullAtomic)
|
||||
FSCom.remove(filename); // Nuke the old file to make space (ignore if it !exists)
|
||||
|
||||
@@ -13,7 +21,6 @@ static File openFile(const char *filename, bool fullAtomic)
|
||||
|
||||
// clear any previous LFS errors
|
||||
lfs_assert_failed = false;
|
||||
|
||||
return FSCom.open(filenameTmp.c_str(), FILE_O_WRITE);
|
||||
}
|
||||
|
||||
@@ -53,14 +60,26 @@ bool SafeFile::close()
|
||||
if (!f)
|
||||
return false;
|
||||
|
||||
spiLock->lock();
|
||||
#ifdef ARCH_NRF52
|
||||
f.truncate();
|
||||
#endif
|
||||
f.close();
|
||||
spiLock->unlock();
|
||||
|
||||
#ifdef ARCH_NRF52
|
||||
return true;
|
||||
#endif
|
||||
if (!testReadback())
|
||||
return false;
|
||||
|
||||
// brief window of risk here ;-)
|
||||
if (fullAtomic && FSCom.exists(filename.c_str()) && !FSCom.remove(filename.c_str())) {
|
||||
LOG_ERROR("Can't remove old pref file");
|
||||
return false;
|
||||
{ // Scope for lock
|
||||
concurrency::LockGuard g(spiLock);
|
||||
// brief window of risk here ;-)
|
||||
if (fullAtomic && FSCom.exists(filename.c_str()) && !FSCom.remove(filename.c_str())) {
|
||||
LOG_ERROR("Can't remove old pref file");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
String filenameTmp = filename;
|
||||
@@ -76,6 +95,7 @@ bool SafeFile::close()
|
||||
/// Read our (closed) tempfile back in and compare the hash
|
||||
bool SafeFile::testReadback()
|
||||
{
|
||||
concurrency::LockGuard g(spiLock);
|
||||
bool lfs_failed = lfs_assert_failed;
|
||||
lfs_assert_failed = false;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "FSCommon.h"
|
||||
#include "SPILock.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#ifdef FSCom
|
||||
|
||||
@@ -178,13 +178,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define TCA9535_ADDR 0x20
|
||||
#define TCA9555_ADDR 0x26
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// GPS
|
||||
// -----------------------------------------------------------------------------
|
||||
#ifndef GPS_THREAD_INTERVAL
|
||||
#define GPS_THREAD_INTERVAL 200
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Touchscreen
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -206,6 +199,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define VEXT_ON_VALUE LOW
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// GPS
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#ifndef GPS_BAUDRATE
|
||||
#define GPS_BAUDRATE 9600
|
||||
#define GPS_BAUDRATE_FIXED 0
|
||||
@@ -213,6 +210,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define GPS_BAUDRATE_FIXED 1
|
||||
#endif
|
||||
|
||||
#ifndef GPS_THREAD_INTERVAL
|
||||
#define GPS_THREAD_INTERVAL 200
|
||||
#endif
|
||||
|
||||
/* Step #2: follow with defines common to the architecture;
|
||||
also enable HAS_ option not specifically disabled by variant.h */
|
||||
#include "architecture.h"
|
||||
|
||||
@@ -35,7 +35,11 @@ template <typename T, std::size_t N> std::size_t array_count(const T (&)[N])
|
||||
}
|
||||
|
||||
#if defined(NRF52840_XXAA) || defined(NRF52833_XXAA) || defined(ARCH_ESP32) || defined(ARCH_PORTDUINO)
|
||||
#if defined(RAK2560)
|
||||
HardwareSerial *GPS::_serial_gps = &Serial2;
|
||||
#else
|
||||
HardwareSerial *GPS::_serial_gps = &Serial1;
|
||||
#endif
|
||||
#elif defined(ARCH_RP2040)
|
||||
SerialUART *GPS::_serial_gps = &Serial1;
|
||||
#else
|
||||
@@ -1190,6 +1194,8 @@ GnssModel_t GPS::probe(int serialSpeed)
|
||||
PROBE_SIMPLE("L76B", "$PMTK605*31", "Quectel-L76B", GNSS_MODEL_MTK_L76B, 500);
|
||||
PROBE_SIMPLE("PA1616S", "$PMTK605*31", "1616S", GNSS_MODEL_MTK_PA1616S, 500);
|
||||
|
||||
PROBE_SIMPLE("LS20031", "$PMTK605*31", "MC-1513", GNSS_MODEL_LS20031, 500);
|
||||
|
||||
uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00};
|
||||
UBXChecksum(cfg_rate, sizeof(cfg_rate));
|
||||
clearBuffer();
|
||||
@@ -1750,4 +1756,4 @@ void GPS::toggleGpsMode()
|
||||
enable();
|
||||
}
|
||||
}
|
||||
#endif // Exclude GPS
|
||||
#endif // Exclude GPS
|
||||
|
||||
@@ -29,7 +29,8 @@ typedef enum {
|
||||
GNSS_MODEL_MTK_L76B,
|
||||
GNSS_MODEL_MTK_PA1616S,
|
||||
GNSS_MODEL_AG3335,
|
||||
GNSS_MODEL_AG3352
|
||||
GNSS_MODEL_AG3352,
|
||||
GNSS_MODEL_LS20031
|
||||
} GnssModel_t;
|
||||
|
||||
typedef enum {
|
||||
@@ -239,4 +240,4 @@ class GPS : private concurrency::OSThread
|
||||
};
|
||||
|
||||
extern GPS *gps;
|
||||
#endif // Exclude GPS
|
||||
#endif // Exclude GPS
|
||||
|
||||
@@ -1015,7 +1015,7 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - devil_height) / 2 + 2 + 5, devil_width, devil_height, devil);
|
||||
} else if (strcmp(msg, "♥️") == 0 || strcmp(msg, "\U0001F9E1") == 0 || strcmp(msg, "\U00002763") == 0 ||
|
||||
strcmp(msg, "\U00002764") == 0 || strcmp(msg, "\U0001F495") == 0 || strcmp(msg, "\U0001F496") == 0 ||
|
||||
strcmp(msg, "\U0001F497") == 0 || strcmp(msg, "\U0001F496") == 0) {
|
||||
strcmp(msg, "\U0001F497") == 0 || strcmp(msg, "\U0001F498") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - heart_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - heart_height) / 2 + 2 + 5, heart_width, heart_height, heart);
|
||||
} else {
|
||||
@@ -1506,7 +1506,7 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O
|
||||
#elif defined(USE_ST7567)
|
||||
dispdev = new ST7567Wire(address.address, -1, -1, geometry,
|
||||
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
||||
#elif ARCH_PORTDUINO
|
||||
#elif ARCH_PORTDUINO && !HAS_TFT
|
||||
if (settingsMap[displayPanel] != no_screen) {
|
||||
LOG_DEBUG("Make TFTDisplay!");
|
||||
dispdev = new TFTDisplay(address.address, -1, -1, geometry,
|
||||
|
||||
@@ -20,9 +20,15 @@
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
// The screen is bigger so use bigger fonts
|
||||
#ifdef OLED_PL
|
||||
#define FONT_SMALL ArialMT_Plain_16_PL // Height: 19
|
||||
#define FONT_MEDIUM ArialMT_Plain_24_PL // Height: 28
|
||||
#define FONT_LARGE ArialMT_Plain_24_PL // Height: 28
|
||||
#else
|
||||
#define FONT_SMALL ArialMT_Plain_16 // Height: 19
|
||||
#define FONT_MEDIUM ArialMT_Plain_24 // Height: 28
|
||||
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
|
||||
#endif
|
||||
#else
|
||||
#ifdef OLED_PL
|
||||
#define FONT_SMALL ArialMT_Plain_10_PL
|
||||
@@ -41,6 +47,9 @@
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#ifdef OLED_PL
|
||||
#define FONT_MEDIUM ArialMT_Plain_16_PL // Height: 19
|
||||
#else
|
||||
#ifdef OLED_UA
|
||||
#define FONT_MEDIUM ArialMT_Plain_16_UA // Height: 19
|
||||
#else
|
||||
@@ -50,6 +59,10 @@
|
||||
#define FONT_MEDIUM ArialMT_Plain_16 // Height: 19
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#ifdef OLED_PL
|
||||
#define FONT_LARGE ArialMT_Plain_24_PL // Height: 28
|
||||
#else
|
||||
#ifdef OLED_UA
|
||||
#define FONT_LARGE ArialMT_Plain_24_UA // Height: 28
|
||||
#else
|
||||
@@ -60,6 +73,7 @@
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define _fontHeight(font) ((font)[1] + 1) // height is position 1
|
||||
|
||||
|
||||
@@ -352,7 +352,7 @@ static TFT_eSPI *tft = nullptr; // Invoke library, pins defined in User_Setup.h
|
||||
|
||||
class LGFX : public lgfx::LGFX_Device
|
||||
{
|
||||
lgfx::Panel_LCD *_panel_instance;
|
||||
lgfx::Panel_Device *_panel_instance;
|
||||
lgfx::Bus_SPI _bus_instance;
|
||||
|
||||
lgfx::ITouch *_touch_instance;
|
||||
@@ -366,10 +366,21 @@ class LGFX : public lgfx::LGFX_Device
|
||||
_panel_instance = new lgfx::Panel_ST7735;
|
||||
else if (settingsMap[displayPanel] == st7735s)
|
||||
_panel_instance = new lgfx::Panel_ST7735S;
|
||||
else if (settingsMap[displayPanel] == st7796)
|
||||
_panel_instance = new lgfx::Panel_ST7796;
|
||||
else if (settingsMap[displayPanel] == ili9341)
|
||||
_panel_instance = new lgfx::Panel_ILI9341;
|
||||
else if (settingsMap[displayPanel] == ili9342)
|
||||
_panel_instance = new lgfx::Panel_ILI9342;
|
||||
else if (settingsMap[displayPanel] == ili9488)
|
||||
_panel_instance = new lgfx::Panel_ILI9488;
|
||||
else if (settingsMap[displayPanel] == hx8357d)
|
||||
_panel_instance = new lgfx::Panel_HX8357D;
|
||||
else {
|
||||
_panel_instance = new lgfx::Panel_NULL;
|
||||
LOG_ERROR("Unknown display panel configured!");
|
||||
}
|
||||
|
||||
auto buscfg = _bus_instance.config();
|
||||
buscfg.spi_mode = 0;
|
||||
buscfg.spi_host = settingsMap[displayspidev];
|
||||
@@ -383,12 +394,12 @@ class LGFX : public lgfx::LGFX_Device
|
||||
LOG_DEBUG("Height: %d, Width: %d ", settingsMap[displayHeight], settingsMap[displayWidth]);
|
||||
cfg.pin_cs = settingsMap[displayCS]; // Pin number where CS is connected (-1 = disable)
|
||||
cfg.pin_rst = settingsMap[displayReset];
|
||||
cfg.panel_width = settingsMap[displayWidth]; // actual displayable width
|
||||
cfg.panel_height = settingsMap[displayHeight]; // actual displayable height
|
||||
cfg.offset_x = settingsMap[displayOffsetX]; // Panel offset amount in X direction
|
||||
cfg.offset_y = settingsMap[displayOffsetY]; // Panel offset amount in Y direction
|
||||
cfg.offset_rotation = 0; // Rotation direction value offset 0~7 (4~7 is mirrored)
|
||||
cfg.invert = settingsMap[displayInvert]; // Set to true if the light/darkness of the panel is reversed
|
||||
cfg.panel_width = settingsMap[displayWidth]; // actual displayable width
|
||||
cfg.panel_height = settingsMap[displayHeight]; // actual displayable height
|
||||
cfg.offset_x = settingsMap[displayOffsetX]; // Panel offset amount in X direction
|
||||
cfg.offset_y = settingsMap[displayOffsetY]; // Panel offset amount in Y direction
|
||||
cfg.offset_rotation = settingsMap[displayOffsetRotate]; // Rotation direction value offset 0~7 (4~7 is mirrored)
|
||||
cfg.invert = settingsMap[displayInvert]; // Set to true if the light/darkness of the panel is reversed
|
||||
|
||||
_panel_instance->config(cfg);
|
||||
|
||||
@@ -410,7 +421,7 @@ class LGFX : public lgfx::LGFX_Device
|
||||
touch_cfg.y_max = settingsMap[displayWidth] - 1;
|
||||
touch_cfg.pin_int = settingsMap[touchscreenIRQ];
|
||||
touch_cfg.bus_shared = true;
|
||||
touch_cfg.offset_rotation = 1;
|
||||
touch_cfg.offset_rotation = settingsMap[touchscreenRotate];
|
||||
if (settingsMap[touchscreenI2CAddr] != -1) {
|
||||
touch_cfg.i2c_addr = settingsMap[touchscreenI2CAddr];
|
||||
} else {
|
||||
|
||||
@@ -7,7 +7,7 @@ const uint8_t ArialMT_Plain_10_CS[] PROGMEM = {
|
||||
0x20, // First char: 32
|
||||
0xE0, // Number of chars: 224
|
||||
// Jump Table:
|
||||
0xFF, 0xFF, 0x00, 0x0A, // 32
|
||||
0xFF, 0xFF, 0x00, 0x03, // 32
|
||||
0x00, 0x00, 0x04, 0x03, // 33
|
||||
0x00, 0x04, 0x05, 0x04, // 34
|
||||
0x00, 0x09, 0x09, 0x06, // 35
|
||||
@@ -453,7 +453,7 @@ const uint8_t ArialMT_Plain_16_CS[] PROGMEM = {
|
||||
0x20, // First char: 32
|
||||
0xE0, // Number of chars: 224
|
||||
// Jump Table:
|
||||
0xFF, 0xFF, 0x00, 0x10, // 32
|
||||
0xFF, 0xFF, 0x00, 0x04, // 32
|
||||
0x00, 0x00, 0x08, 0x04, // 33
|
||||
0x00, 0x08, 0x0D, 0x06, // 34
|
||||
0x00, 0x15, 0x1A, 0x0A, // 35
|
||||
@@ -1036,7 +1036,7 @@ const uint8_t ArialMT_Plain_24_CS[] PROGMEM = {
|
||||
0x20, // First char: 32
|
||||
0xE0, // Number of chars: 224
|
||||
// Jump Table:
|
||||
0xFF, 0xFF, 0x00, 0x18, // 32
|
||||
0xFF, 0xFF, 0x00, 0x06, // 32
|
||||
0x00, 0x00, 0x13, 0x06, // 33
|
||||
0x00, 0x13, 0x1A, 0x08, // 34
|
||||
0x00, 0x2D, 0x33, 0x0E, // 35
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,7 @@
|
||||
#elif __MBED__
|
||||
#define PROGMEM
|
||||
#endif
|
||||
|
||||
extern const uint8_t ArialMT_Plain_10_PL[] PROGMEM;
|
||||
extern const uint8_t ArialMT_Plain_16_PL[] PROGMEM;
|
||||
extern const uint8_t ArialMT_Plain_24_PL[] PROGMEM;
|
||||
#endif
|
||||
140
src/main.cpp
140
src/main.cpp
@@ -92,6 +92,7 @@ NRF52Bluetooth *nrf52Bluetooth = nullptr;
|
||||
#include "mesh/raspihttp/PiWebServer.h"
|
||||
#include "platform/portduino/PortduinoGlue.h"
|
||||
#include "platform/portduino/USBHal.h"
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
@@ -364,6 +365,8 @@ void setup()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
initSPI();
|
||||
|
||||
OSThread::setup();
|
||||
|
||||
ledPeriodic = new Periodic("Blink", ledBlinker);
|
||||
@@ -640,8 +643,6 @@ void setup()
|
||||
rp2040Setup();
|
||||
#endif
|
||||
|
||||
initSPI(); // needed here before reading from littleFS
|
||||
|
||||
// We do this as early as possible because this loads preferences from flash
|
||||
// but we need to do this after main cpu init (esp32setup), because we need the random seed set
|
||||
nodeDB = new NodeDB;
|
||||
@@ -825,116 +826,56 @@ void setup()
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_PORTDUINO
|
||||
if (settingsMap[use_sx1262]) {
|
||||
if (!rIf) {
|
||||
LOG_DEBUG("Activate sx1262 radio on SPI port %s", settingsStrings[spidev].c_str());
|
||||
const struct {
|
||||
configNames cfgName;
|
||||
std::string strName;
|
||||
} loraModules[] = {{use_rf95, "RF95"}, {use_sx1262, "sx1262"}, {use_sx1268, "sx1268"}, {use_sx1280, "sx1280"},
|
||||
{use_lr1110, "lr1110"}, {use_lr1120, "lr1120"}, {use_lr1121, "lr1121"}, {use_llcc68, "LLCC68"}};
|
||||
// as one can't use a function pointer to the class constructor:
|
||||
auto loraModuleInterface = [](configNames cfgName, LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq,
|
||||
RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy) {
|
||||
switch (cfgName) {
|
||||
case use_rf95:
|
||||
return (RadioInterface *)new RF95Interface(hal, cs, irq, rst, busy);
|
||||
case use_sx1262:
|
||||
return (RadioInterface *)new SX1262Interface(hal, cs, irq, rst, busy);
|
||||
case use_sx1268:
|
||||
return (RadioInterface *)new SX1268Interface(hal, cs, irq, rst, busy);
|
||||
case use_sx1280:
|
||||
return (RadioInterface *)new SX1280Interface(hal, cs, irq, rst, busy);
|
||||
case use_lr1110:
|
||||
return (RadioInterface *)new LR1110Interface(hal, cs, irq, rst, busy);
|
||||
case use_lr1120:
|
||||
return (RadioInterface *)new LR1120Interface(hal, cs, irq, rst, busy);
|
||||
case use_lr1121:
|
||||
return (RadioInterface *)new LR1121Interface(hal, cs, irq, rst, busy);
|
||||
case use_llcc68:
|
||||
return (RadioInterface *)new LLCC68Interface(hal, cs, irq, rst, busy);
|
||||
default:
|
||||
assert(0); // shouldn't happen
|
||||
return (RadioInterface *)nullptr;
|
||||
}
|
||||
};
|
||||
for (auto &loraModule : loraModules) {
|
||||
if (settingsMap[loraModule.cfgName] && !rIf) {
|
||||
LOG_DEBUG("Activate %s radio on SPI port %s", loraModule.strName.c_str(), settingsStrings[spidev].c_str());
|
||||
if (settingsStrings[spidev] == "ch341") {
|
||||
RadioLibHAL = ch341Hal;
|
||||
} else {
|
||||
RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
||||
}
|
||||
rIf = new SX1262Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
|
||||
settingsMap[busy]);
|
||||
rIf = loraModuleInterface(loraModule.cfgName, (LockingArduinoHal *)RadioLibHAL, settingsMap[cs_pin],
|
||||
settingsMap[irq_pin], settingsMap[reset_pin], settingsMap[busy_pin]);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("No SX1262 radio");
|
||||
delete rIf;
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
LOG_INFO("SX1262 init success");
|
||||
}
|
||||
}
|
||||
} else if (settingsMap[use_rf95]) {
|
||||
if (!rIf) {
|
||||
LOG_DEBUG("Activate rf95 radio on SPI port %s", settingsStrings[spidev].c_str());
|
||||
RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
||||
rIf = new RF95Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
|
||||
settingsMap[busy]);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("No RF95 radio");
|
||||
LOG_WARN("No %s radio", loraModule.strName.c_str());
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
LOG_INFO("RF95 init success");
|
||||
}
|
||||
}
|
||||
} else if (settingsMap[use_sx1280]) {
|
||||
if (!rIf) {
|
||||
LOG_DEBUG("Activate sx1280 radio on SPI port %s", settingsStrings[spidev].c_str());
|
||||
RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
||||
rIf = new SX1280Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
|
||||
settingsMap[busy]);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("No SX1280 radio");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
LOG_INFO("SX1280 init success");
|
||||
}
|
||||
}
|
||||
} else if (settingsMap[use_lr1110]) {
|
||||
if (!rIf) {
|
||||
LOG_DEBUG("Activate lr1110 radio on SPI port %s", settingsStrings[spidev].c_str());
|
||||
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
||||
rIf = new LR1110Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
|
||||
settingsMap[busy]);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("No LR1110 radio");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
LOG_INFO("LR1110 init success");
|
||||
}
|
||||
}
|
||||
} else if (settingsMap[use_lr1120]) {
|
||||
if (!rIf) {
|
||||
LOG_DEBUG("Activate lr1120 radio on SPI port %s", settingsStrings[spidev].c_str());
|
||||
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
||||
rIf = new LR1120Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
|
||||
settingsMap[busy]);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("No LR1120 radio");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
LOG_INFO("LR1120 init success");
|
||||
}
|
||||
}
|
||||
} else if (settingsMap[use_lr1121]) {
|
||||
if (!rIf) {
|
||||
LOG_DEBUG("Activate lr1121 radio on SPI port %s", settingsStrings[spidev].c_str());
|
||||
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
||||
rIf = new LR1121Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
|
||||
settingsMap[busy]);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("No LR1121 radio");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
LOG_INFO("LR1121 init success");
|
||||
}
|
||||
}
|
||||
} else if (settingsMap[use_sx1268]) {
|
||||
if (!rIf) {
|
||||
LOG_DEBUG("Activate sx1268 radio on SPI port %s", settingsStrings[spidev].c_str());
|
||||
RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
||||
rIf = new SX1268Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
|
||||
settingsMap[busy]);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("No SX1268 radio");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
LOG_INFO("SX1268 init success");
|
||||
LOG_INFO("%s init success", loraModule.strName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(HW_SPI1_DEVICE)
|
||||
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI1, spiSettings);
|
||||
#else // HW_SPI1_DEVICE
|
||||
@@ -1159,6 +1100,7 @@ void setup()
|
||||
#if __has_include(<ulfius.h>)
|
||||
if (settingsMap[webserverport] != -1) {
|
||||
piwebServerThread = new PiWebServerThread();
|
||||
std::atexit([] { delete piwebServerThread; });
|
||||
}
|
||||
#endif
|
||||
initApiServer(TCPPort);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "NodeDB.h"
|
||||
#include "configuration.h"
|
||||
#include "modules/RoutingModule.h"
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
|
||||
std::vector<MeshModule *> *MeshModule::modules;
|
||||
@@ -29,7 +30,9 @@ void MeshModule::setup() {}
|
||||
|
||||
MeshModule::~MeshModule()
|
||||
{
|
||||
assert(0); // FIXME - remove from list of modules once someone needs this feature
|
||||
auto it = std::find(modules->begin(), modules->end(), this);
|
||||
assert(it != modules->end());
|
||||
modules->erase(it);
|
||||
}
|
||||
|
||||
meshtastic_MeshPacket *MeshModule::allocAckNak(meshtastic_Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex,
|
||||
|
||||
@@ -69,7 +69,11 @@ bool MeshPacketQueue::enqueue(meshtastic_MeshPacket *p)
|
||||
{
|
||||
// no space - try to replace a lower priority packet in the queue
|
||||
if (queue.size() >= maxLen) {
|
||||
return replaceLowerPriorityPacket(p);
|
||||
bool replaced = replaceLowerPriorityPacket(p);
|
||||
if (!replaced) {
|
||||
LOG_WARN("TX queue is full, and there is no lower-priority packet available to evict in favour of 0x%08x", p->id);
|
||||
}
|
||||
return replaced;
|
||||
}
|
||||
|
||||
// Find the correct position using upper_bound to maintain a stable order
|
||||
@@ -113,7 +117,10 @@ meshtastic_MeshPacket *MeshPacketQueue::remove(NodeNum from, PacketId id, bool t
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Attempt to find and remove a packet from this queue. Returns the packet which was removed from the queue */
|
||||
/**
|
||||
* Attempt to find a lower-priority packet in the queue and replace it with the provided one.
|
||||
* @return True if the replacement succeeded, false otherwise
|
||||
*/
|
||||
bool MeshPacketQueue::replaceLowerPriorityPacket(meshtastic_MeshPacket *p)
|
||||
{
|
||||
|
||||
@@ -122,11 +129,12 @@ bool MeshPacketQueue::replaceLowerPriorityPacket(meshtastic_MeshPacket *p)
|
||||
}
|
||||
|
||||
// Check if the packet at the back has a lower priority than the new packet
|
||||
auto &backPacket = queue.back();
|
||||
auto *backPacket = queue.back();
|
||||
if (!backPacket->tx_after && backPacket->priority < p->priority) {
|
||||
LOG_WARN("Dropping packet 0x%08x to make room in the TX queue for higher-priority packet 0x%08x", backPacket->id, p->id);
|
||||
// Remove the back packet
|
||||
packetPool.release(backPacket);
|
||||
queue.pop_back();
|
||||
packetPool.release(backPacket);
|
||||
// Insert the new packet in the correct order
|
||||
enqueue(p);
|
||||
return true;
|
||||
@@ -139,8 +147,12 @@ bool MeshPacketQueue::replaceLowerPriorityPacket(meshtastic_MeshPacket *p)
|
||||
for (; refPacket->tx_after && it != queue.begin(); refPacket = *--it)
|
||||
;
|
||||
if (!refPacket->tx_after && refPacket->priority < p->priority) {
|
||||
LOG_WARN("Dropping non-late packet 0x%08x to make room in the TX queue for higher-priority packet 0x%08x",
|
||||
refPacket->id, p->id);
|
||||
queue.erase(it);
|
||||
packetPool.release(refPacket);
|
||||
enqueue(refPacket);
|
||||
// Insert the new packet in the correct order
|
||||
enqueue(p);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ class MeshService
|
||||
void sendToPhone(meshtastic_MeshPacket *p);
|
||||
|
||||
/// Send an MQTT message to the phone for client proxying
|
||||
void sendMqttMessageToClientProxy(meshtastic_MqttClientProxyMessage *m);
|
||||
virtual void sendMqttMessageToClientProxy(meshtastic_MqttClientProxyMessage *m);
|
||||
|
||||
/// Send a ClientNotification to the phone
|
||||
void sendClientNotification(meshtastic_ClientNotification *cn);
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "PowerFSM.h"
|
||||
#include "RTC.h"
|
||||
#include "Router.h"
|
||||
#include "SPILock.h"
|
||||
#include "SafeFile.h"
|
||||
#include "TypeConversions.h"
|
||||
#include "error.h"
|
||||
@@ -409,6 +410,13 @@ bool NodeDB::resetRadioConfig(bool factory_reset)
|
||||
rebootAtMsec = millis() + (5 * 1000);
|
||||
}
|
||||
|
||||
#if (defined(T_DECK) || defined(T_WATCH_S3) || defined(UNPHONE) || defined(PICOMPUTER_S3)) && defined(HAS_TFT)
|
||||
// as long as PhoneAPI shares BT and TFT app switch BT off
|
||||
config.bluetooth.enabled = false;
|
||||
if (moduleConfig.external_notification.nag_timeout == 60)
|
||||
moduleConfig.external_notification.nag_timeout = 0;
|
||||
#endif
|
||||
|
||||
return didFactoryReset;
|
||||
}
|
||||
|
||||
@@ -416,12 +424,15 @@ bool NodeDB::factoryReset(bool eraseBleBonds)
|
||||
{
|
||||
LOG_INFO("Perform factory reset!");
|
||||
// first, remove the "/prefs" (this removes most prefs)
|
||||
rmDir("/prefs");
|
||||
spiLock->lock();
|
||||
rmDir("/prefs"); // this uses spilock internally...
|
||||
|
||||
#ifdef FSCom
|
||||
if (FSCom.exists("/static/rangetest.csv") && !FSCom.remove("/static/rangetest.csv")) {
|
||||
LOG_ERROR("Could not remove rangetest.csv file");
|
||||
}
|
||||
#endif
|
||||
spiLock->unlock();
|
||||
// second, install default state (this will deal with the duplicate mac address issue)
|
||||
installDefaultDeviceState();
|
||||
installDefaultConfig(!eraseBleBonds); // Also preserve the private key if we're not erasing BLE bonds
|
||||
@@ -906,6 +917,7 @@ LoadFileResult NodeDB::loadProto(const char *filename, size_t protoSize, size_t
|
||||
{
|
||||
LoadFileResult state = LoadFileResult::OTHER_FAILURE;
|
||||
#ifdef FSCom
|
||||
concurrency::LockGuard g(spiLock);
|
||||
|
||||
auto f = FSCom.open(filename, FILE_O_READ);
|
||||
|
||||
@@ -939,12 +951,14 @@ void NodeDB::loadFromDisk()
|
||||
// disk we will still factoryReset to restore things.
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
spiLock->lock();
|
||||
if (FSCom.exists("/static/static"))
|
||||
rmDir("/static/static"); // Remove bad static web files bundle from initial 2.5.13 release
|
||||
spiLock->unlock();
|
||||
#endif
|
||||
|
||||
// static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM
|
||||
auto state = loadProto(prefFileName, sizeof(meshtastic_DeviceState) + MAX_NUM_NODES_FS * sizeof(meshtastic_NodeInfo),
|
||||
auto state = loadProto(prefFileName, sizeof(meshtastic_DeviceState) + MAX_NUM_NODES_FS * meshtastic_NodeInfoLite_size,
|
||||
sizeof(meshtastic_DeviceState), &meshtastic_DeviceState_msg, &devicestate);
|
||||
|
||||
// See https://github.com/meshtastic/firmware/issues/4184#issuecomment-2269390786
|
||||
@@ -985,8 +999,11 @@ void NodeDB::loadFromDisk()
|
||||
// Make sure we load hard coded admin keys even when the configuration file has none.
|
||||
// Initialize admin_key_count to zero
|
||||
byte numAdminKeys = 0;
|
||||
#if defined(USERPREFS_USE_ADMIN_KEY_0) || defined(USERPREFS_USE_ADMIN_KEY_1) || defined(USERPREFS_USE_ADMIN_KEY_2)
|
||||
uint16_t sum = 0;
|
||||
#endif
|
||||
#ifdef USERPREFS_USE_ADMIN_KEY_0
|
||||
|
||||
for (uint8_t b = 0; b < 32; b++) {
|
||||
sum += config.security.admin_key[0].bytes[b];
|
||||
}
|
||||
@@ -995,8 +1012,6 @@ void NodeDB::loadFromDisk()
|
||||
LOG_INFO("Admin 0 key zero. Loading hard coded key from user preferences.");
|
||||
memcpy(config.security.admin_key[0].bytes, userprefs_admin_key_0, 32);
|
||||
config.security.admin_key[0].size = 32;
|
||||
config.security.admin_key_count = numAdminKeys;
|
||||
saveToDisk(SEGMENT_CONFIG);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1010,8 +1025,6 @@ void NodeDB::loadFromDisk()
|
||||
LOG_INFO("Admin 1 key zero. Loading hard coded key from user preferences.");
|
||||
memcpy(config.security.admin_key[1].bytes, userprefs_admin_key_1, 32);
|
||||
config.security.admin_key[1].size = 32;
|
||||
config.security.admin_key_count = numAdminKeys;
|
||||
saveToDisk(SEGMENT_CONFIG);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1025,10 +1038,14 @@ void NodeDB::loadFromDisk()
|
||||
LOG_INFO("Admin 2 key zero. Loading hard coded key from user preferences.");
|
||||
memcpy(config.security.admin_key[2].bytes, userprefs_admin_key_2, 32);
|
||||
config.security.admin_key[2].size = 32;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (numAdminKeys > 0) {
|
||||
LOG_INFO("Saving %d hard coded admin keys.", numAdminKeys);
|
||||
config.security.admin_key_count = numAdminKeys;
|
||||
saveToDisk(SEGMENT_CONFIG);
|
||||
}
|
||||
#endif
|
||||
|
||||
state = loadProto(moduleConfigFileName, meshtastic_LocalModuleConfig_size, sizeof(meshtastic_LocalModuleConfig),
|
||||
&meshtastic_LocalModuleConfig_msg, &moduleConfig);
|
||||
@@ -1087,9 +1104,6 @@ void NodeDB::loadFromDisk()
|
||||
bool NodeDB::saveProto(const char *filename, size_t protoSize, const pb_msgdesc_t *fields, const void *dest_struct,
|
||||
bool fullAtomic)
|
||||
{
|
||||
#ifdef ARCH_ESP32
|
||||
concurrency::LockGuard g(spiLock);
|
||||
#endif
|
||||
bool okay = false;
|
||||
#ifdef FSCom
|
||||
auto f = SafeFile(filename, fullAtomic);
|
||||
@@ -1117,7 +1131,9 @@ bool NodeDB::saveProto(const char *filename, size_t protoSize, const pb_msgdesc_
|
||||
bool NodeDB::saveChannelsToDisk()
|
||||
{
|
||||
#ifdef FSCom
|
||||
spiLock->lock();
|
||||
FSCom.mkdir("/prefs");
|
||||
spiLock->unlock();
|
||||
#endif
|
||||
return saveProto(channelFileName, meshtastic_ChannelFile_size, &meshtastic_ChannelFile_msg, &channelFile);
|
||||
}
|
||||
@@ -1125,12 +1141,15 @@ bool NodeDB::saveChannelsToDisk()
|
||||
bool NodeDB::saveDeviceStateToDisk()
|
||||
{
|
||||
#ifdef FSCom
|
||||
spiLock->lock();
|
||||
FSCom.mkdir("/prefs");
|
||||
spiLock->unlock();
|
||||
#endif
|
||||
// Note: if MAX_NUM_NODES=100 and meshtastic_NodeInfoLite_size=166, so will be approximately 17KB
|
||||
// Because so huge we _must_ not use fullAtomic, because the filesystem is probably too small to hold two copies of this
|
||||
return saveProto(prefFileName, sizeof(devicestate) + numMeshNodes * meshtastic_NodeInfoLite_size, &meshtastic_DeviceState_msg,
|
||||
&devicestate, false);
|
||||
size_t deviceStateSize;
|
||||
pb_get_encoded_size(&deviceStateSize, meshtastic_DeviceState_fields, &devicestate);
|
||||
return saveProto(prefFileName, deviceStateSize, &meshtastic_DeviceState_msg, &devicestate, false);
|
||||
}
|
||||
|
||||
bool NodeDB::saveToDiskNoRetry(int saveWhat)
|
||||
@@ -1138,7 +1157,9 @@ bool NodeDB::saveToDiskNoRetry(int saveWhat)
|
||||
bool success = true;
|
||||
|
||||
#ifdef FSCom
|
||||
spiLock->lock();
|
||||
FSCom.mkdir("/prefs");
|
||||
spiLock->unlock();
|
||||
#endif
|
||||
if (saveWhat & SEGMENT_CONFIG) {
|
||||
config.has_device = true;
|
||||
@@ -1189,7 +1210,9 @@ bool NodeDB::saveToDisk(int saveWhat)
|
||||
if (!success) {
|
||||
LOG_ERROR("Failed to save to disk, retrying");
|
||||
#ifdef ARCH_NRF52 // @geeksville is not ready yet to say we should do this on other platforms. See bug #4184 discussion
|
||||
spiLock->lock();
|
||||
FSCom.format();
|
||||
spiLock->unlock();
|
||||
|
||||
#endif
|
||||
success = saveToDiskNoRetry(saveWhat);
|
||||
@@ -1508,4 +1531,4 @@ void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, co
|
||||
LOG_ERROR("A critical failure occurred, portduino is exiting");
|
||||
exit(2);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -145,7 +145,7 @@ class NodeDB
|
||||
return &meshNodes->at(x);
|
||||
}
|
||||
|
||||
meshtastic_NodeInfoLite *getMeshNode(NodeNum n);
|
||||
virtual meshtastic_NodeInfoLite *getMeshNode(NodeNum n);
|
||||
size_t getNumMeshNodes() { return numMeshNodes; }
|
||||
|
||||
// returns true if the maximum number of nodes is reached or we are running low on memory
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "PhoneAPI.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "RadioInterface.h"
|
||||
#include "SPILock.h"
|
||||
#include "TypeConversions.h"
|
||||
#include "main.h"
|
||||
#include "xmodem.h"
|
||||
@@ -54,7 +55,9 @@ void PhoneAPI::handleStartConfig()
|
||||
// even if we were already connected - restart our state machine
|
||||
state = STATE_SEND_MY_INFO;
|
||||
pauseBluetoothLogging = true;
|
||||
spiLock->lock();
|
||||
filesManifest = getFiles("/", 10);
|
||||
spiLock->unlock();
|
||||
LOG_DEBUG("Got %d files in manifest", filesManifest.size());
|
||||
|
||||
LOG_INFO("Start API client config");
|
||||
|
||||
@@ -91,16 +91,16 @@ void RF95Interface::setTransmitEnable(bool txon)
|
||||
#ifdef RF95_TXEN
|
||||
digitalWrite(RF95_TXEN, txon ? 1 : 0);
|
||||
#elif ARCH_PORTDUINO
|
||||
if (settingsMap[txen] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[txen], txon ? 1 : 0);
|
||||
if (settingsMap[txen_pin] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[txen_pin], txon ? 1 : 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef RF95_RXEN
|
||||
digitalWrite(RF95_RXEN, txon ? 0 : 1);
|
||||
#elif ARCH_PORTDUINO
|
||||
if (settingsMap[rxen] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[rxen], txon ? 0 : 1);
|
||||
if (settingsMap[rxen_pin] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[rxen_pin], txon ? 0 : 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -164,13 +164,13 @@ bool RF95Interface::init()
|
||||
digitalWrite(RF95_RXEN, 1);
|
||||
#endif
|
||||
#if ARCH_PORTDUINO
|
||||
if (settingsMap[txen] != RADIOLIB_NC) {
|
||||
pinMode(settingsMap[txen], OUTPUT);
|
||||
digitalWrite(settingsMap[txen], 0);
|
||||
if (settingsMap[txen_pin] != RADIOLIB_NC) {
|
||||
pinMode(settingsMap[txen_pin], OUTPUT);
|
||||
digitalWrite(settingsMap[txen_pin], 0);
|
||||
}
|
||||
if (settingsMap[rxen] != RADIOLIB_NC) {
|
||||
pinMode(settingsMap[rxen], OUTPUT);
|
||||
digitalWrite(settingsMap[rxen], 0);
|
||||
if (settingsMap[rxen_pin] != RADIOLIB_NC) {
|
||||
pinMode(settingsMap[rxen_pin], OUTPUT);
|
||||
digitalWrite(settingsMap[rxen_pin], 0);
|
||||
}
|
||||
#endif
|
||||
setTransmitEnable(false);
|
||||
@@ -337,4 +337,4 @@ bool RF95Interface::sleep()
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -297,7 +297,7 @@ uint32_t RadioInterface::getTxDelayMsecWeighted(float snr)
|
||||
|
||||
void printPacket(const char *prefix, const meshtastic_MeshPacket *p)
|
||||
{
|
||||
#ifdef DEBUG_PORT
|
||||
#if defined(DEBUG_PORT) && !defined(DEBUG_MUTE)
|
||||
std::string out = DEBUG_PORT.mt_sprintf("%s (id=0x%08x fr=0x%08x to=0x%08x, WantAck=%d, HopLim=%d Ch=0x%x", prefix, p->id,
|
||||
p->from, p->to, p->want_ack, p->hop_limit, p->channel);
|
||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||
@@ -637,4 +637,4 @@ size_t RadioInterface::beginSending(meshtastic_MeshPacket *p)
|
||||
|
||||
sendingPacket = p;
|
||||
return p->encrypted.size + sizeof(PacketHeader);
|
||||
}
|
||||
}
|
||||
@@ -271,6 +271,7 @@ void RadioLibInterface::onNotify(uint32_t notification)
|
||||
uint32_t xmitMsec = getPacketTime(txp);
|
||||
airTime->logAirtime(TX_LOG, xmitMsec);
|
||||
}
|
||||
LOG_DEBUG("%d packets remain in the TX queue", txQueue.getMaxLen() - txQueue.getFree());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -297,8 +298,8 @@ void RadioLibInterface::setTransmitDelay()
|
||||
if (p->tx_after) {
|
||||
unsigned long add_delay = p->rx_rssi ? getTxDelayMsecWeighted(p->rx_snr) : getTxDelayMsec();
|
||||
unsigned long now = millis();
|
||||
p->tx_after = max(p->tx_after + add_delay, now + add_delay);
|
||||
notifyLater(now - p->tx_after, TRANSMIT_DELAY_COMPLETED, false);
|
||||
p->tx_after = min(max(p->tx_after + add_delay, now + add_delay), now + 2 * getTxDelayMsecWeightedWorst(p->rx_snr));
|
||||
notifyLater(p->tx_after - now, TRANSMIT_DELAY_COMPLETED, false);
|
||||
} else if (p->rx_snr == 0 && p->rx_rssi == 0) {
|
||||
/* We assume if rx_snr = 0 and rx_rssi = 0, the packet was generated locally.
|
||||
* This assumption is valid because of the offset generated by the radio to account for the noise
|
||||
@@ -431,6 +432,7 @@ void RadioLibInterface::handleReceiveInterrupt()
|
||||
// nodes.
|
||||
meshtastic_MeshPacket *mp = packetPool.allocZeroed();
|
||||
|
||||
// Keep the assigned fields in sync with src/mqtt/MQTT.cpp:onReceiveProto
|
||||
mp->from = radioBuffer.header.from;
|
||||
mp->to = radioBuffer.header.to;
|
||||
mp->id = radioBuffer.header.id;
|
||||
@@ -500,14 +502,13 @@ bool RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
|
||||
powerMon->clearState(meshtastic_PowerMon_State_Lora_TXOn); // Transmitter off now
|
||||
startReceive(); // Restart receive mode (because startTransmit failed to put us in xmit mode)
|
||||
} else {
|
||||
// Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register
|
||||
// bits
|
||||
enableInterrupt(isrTxLevel0);
|
||||
lastTxStart = millis();
|
||||
printPacket("Started Tx", txp);
|
||||
}
|
||||
|
||||
// Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register
|
||||
// bits
|
||||
enableInterrupt(isrTxLevel0);
|
||||
|
||||
return res == RADIOLIB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
@@ -187,7 +187,7 @@ ErrorCode Router::sendLocal(meshtastic_MeshPacket *p, RxSource src)
|
||||
}
|
||||
|
||||
// don't override if a channel was requested and no need to set it when PKI is enforced
|
||||
if (!p->channel && !p->pki_encrypted) {
|
||||
if (!p->channel && !p->pki_encrypted && !isBroadcast(p->to)) {
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(p->to);
|
||||
if (node) {
|
||||
p->channel = node->channel;
|
||||
@@ -679,4 +679,4 @@ void Router::perhapsHandleReceived(meshtastic_MeshPacket *p)
|
||||
// cache/learn of the existence of nodes (i.e. FloodRouter) that they should not
|
||||
handleReceived(p);
|
||||
packetPool.release(p);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ class Router : protected concurrency::OSThread
|
||||
* RadioInterface calls this to queue up packets that have been received from the radio. The router is now responsible for
|
||||
* freeing the packet
|
||||
*/
|
||||
void enqueueReceivedMessage(meshtastic_MeshPacket *p);
|
||||
virtual void enqueueReceivedMessage(meshtastic_MeshPacket *p);
|
||||
|
||||
/**
|
||||
* Send a packet on a suitable interface. This routine will
|
||||
|
||||
@@ -51,9 +51,9 @@ template <typename T> bool SX126xInterface<T>::init()
|
||||
|
||||
#if ARCH_PORTDUINO
|
||||
float tcxoVoltage = (float)settingsMap[dio3_tcxo_voltage] / 1000;
|
||||
if (settingsMap[sx126x_ant_sw] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[sx126x_ant_sw], HIGH);
|
||||
pinMode(settingsMap[sx126x_ant_sw], OUTPUT);
|
||||
if (settingsMap[sx126x_ant_sw_pin] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[sx126x_ant_sw_pin], HIGH);
|
||||
pinMode(settingsMap[sx126x_ant_sw_pin], OUTPUT);
|
||||
}
|
||||
// FIXME: correct logic to default to not using TCXO if no voltage is specified for SX126X_DIO3_TCXO_VOLTAGE
|
||||
#elif !defined(SX126X_DIO3_TCXO_VOLTAGE)
|
||||
@@ -121,8 +121,9 @@ template <typename T> bool SX126xInterface<T>::init()
|
||||
// no effect
|
||||
#if ARCH_PORTDUINO
|
||||
if (res == RADIOLIB_ERR_NONE) {
|
||||
LOG_DEBUG("Use MCU pin %i as RXEN and pin %i as TXEN to control RF switching", settingsMap[rxen], settingsMap[txen]);
|
||||
lora.setRfSwitchPins(settingsMap[rxen], settingsMap[txen]);
|
||||
LOG_DEBUG("Use MCU pin %i as RXEN and pin %i as TXEN to control RF switching", settingsMap[rxen_pin],
|
||||
settingsMap[txen_pin]);
|
||||
lora.setRfSwitchPins(settingsMap[rxen_pin], settingsMap[txen_pin]);
|
||||
}
|
||||
#else
|
||||
#ifndef SX126X_RXEN
|
||||
@@ -341,4 +342,4 @@ template <typename T> bool SX126xInterface<T>::sleep()
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -38,13 +38,13 @@ template <typename T> bool SX128xInterface<T>::init()
|
||||
#endif
|
||||
|
||||
#if ARCH_PORTDUINO
|
||||
if (settingsMap[rxen] != RADIOLIB_NC) {
|
||||
pinMode(settingsMap[rxen], OUTPUT);
|
||||
digitalWrite(settingsMap[rxen], LOW); // Set low before becoming an output
|
||||
if (settingsMap[rxen_pin] != RADIOLIB_NC) {
|
||||
pinMode(settingsMap[rxen_pin], OUTPUT);
|
||||
digitalWrite(settingsMap[rxen_pin], LOW); // Set low before becoming an output
|
||||
}
|
||||
if (settingsMap[txen] != RADIOLIB_NC) {
|
||||
pinMode(settingsMap[txen], OUTPUT);
|
||||
digitalWrite(settingsMap[txen], LOW); // Set low before becoming an output
|
||||
if (settingsMap[txen_pin] != RADIOLIB_NC) {
|
||||
pinMode(settingsMap[txen_pin], OUTPUT);
|
||||
digitalWrite(settingsMap[txen_pin], LOW); // Set low before becoming an output
|
||||
}
|
||||
#else
|
||||
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // set not rx or tx mode
|
||||
@@ -93,8 +93,8 @@ template <typename T> bool SX128xInterface<T>::init()
|
||||
lora.setRfSwitchPins(SX128X_RXEN, SX128X_TXEN);
|
||||
}
|
||||
#elif ARCH_PORTDUINO
|
||||
if (res == RADIOLIB_ERR_NONE && settingsMap[rxen] != RADIOLIB_NC && settingsMap[txen] != RADIOLIB_NC) {
|
||||
lora.setRfSwitchPins(settingsMap[rxen], settingsMap[txen]);
|
||||
if (res == RADIOLIB_ERR_NONE && settingsMap[rxen_pin] != RADIOLIB_NC && settingsMap[txen_pin] != RADIOLIB_NC) {
|
||||
lora.setRfSwitchPins(settingsMap[rxen_pin], settingsMap[txen_pin]);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -174,11 +174,11 @@ template <typename T> void SX128xInterface<T>::setStandby()
|
||||
LOG_ERROR("SX128x standby %s%d", radioLibErr, err);
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
#if ARCH_PORTDUINO
|
||||
if (settingsMap[rxen] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[rxen], LOW);
|
||||
if (settingsMap[rxen_pin] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[rxen_pin], LOW);
|
||||
}
|
||||
if (settingsMap[txen] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[txen], LOW);
|
||||
if (settingsMap[txen_pin] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[txen_pin], LOW);
|
||||
}
|
||||
#else
|
||||
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn off RX and TX power
|
||||
@@ -210,11 +210,11 @@ template <typename T> void SX128xInterface<T>::addReceiveMetadata(meshtastic_Mes
|
||||
template <typename T> void SX128xInterface<T>::configHardwareForSend()
|
||||
{
|
||||
#if ARCH_PORTDUINO
|
||||
if (settingsMap[txen] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[txen], HIGH);
|
||||
if (settingsMap[txen_pin] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[txen_pin], HIGH);
|
||||
}
|
||||
if (settingsMap[rxen] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[rxen], LOW);
|
||||
if (settingsMap[rxen_pin] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[rxen_pin], LOW);
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -241,11 +241,11 @@ template <typename T> void SX128xInterface<T>::startReceive()
|
||||
setStandby();
|
||||
|
||||
#if ARCH_PORTDUINO
|
||||
if (settingsMap[rxen] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[rxen], HIGH);
|
||||
if (settingsMap[rxen_pin] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[rxen_pin], HIGH);
|
||||
}
|
||||
if (settingsMap[txen] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[txen], LOW);
|
||||
if (settingsMap[txen_pin] != RADIOLIB_NC) {
|
||||
digitalWrite(settingsMap[txen_pin], LOW);
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -315,4 +315,4 @@ template <typename T> bool SX128xInterface<T>::sleep()
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -66,8 +66,9 @@ static int32_t reconnectETH()
|
||||
syslog.enable();
|
||||
}
|
||||
|
||||
// initWebServer();
|
||||
#if !MESHTASTIC_EXCLUDE_SOCKETAPI
|
||||
initApiServer();
|
||||
#endif
|
||||
|
||||
ethStartupComplete = true;
|
||||
}
|
||||
@@ -107,6 +108,11 @@ static int32_t reconnectETH()
|
||||
bool initEthernet()
|
||||
{
|
||||
if (config.network.eth_enabled) {
|
||||
#ifdef PIN_ETH_POWER_EN
|
||||
pinMode(PIN_ETH_POWER_EN, OUTPUT);
|
||||
digitalWrite(PIN_ETH_POWER_EN, HIGH); // Power up.
|
||||
delay(100);
|
||||
#endif
|
||||
|
||||
#ifdef PIN_ETHERNET_RESET
|
||||
pinMode(PIN_ETHERNET_RESET, OUTPUT);
|
||||
@@ -115,6 +121,12 @@ bool initEthernet()
|
||||
digitalWrite(PIN_ETHERNET_RESET, HIGH); // Reset Time.
|
||||
#endif
|
||||
|
||||
#ifdef RAK11310 // Initialize the SPI port
|
||||
ETH_SPI_PORT.setSCK(PIN_SPI0_SCK);
|
||||
ETH_SPI_PORT.setTX(PIN_SPI0_MOSI);
|
||||
ETH_SPI_PORT.setRX(PIN_SPI0_MISO);
|
||||
ETH_SPI_PORT.begin();
|
||||
#endif
|
||||
Ethernet.init(ETH_SPI_PORT, PIN_ETHERNET_SS);
|
||||
|
||||
uint8_t mac[6];
|
||||
|
||||
@@ -63,6 +63,8 @@ PB_BIND(meshtastic_Config_SessionkeyConfig, meshtastic_Config_SessionkeyConfig,
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -139,6 +139,14 @@ typedef enum _meshtastic_Config_NetworkConfig_AddressMode {
|
||||
meshtastic_Config_NetworkConfig_AddressMode_STATIC = 1
|
||||
} meshtastic_Config_NetworkConfig_AddressMode;
|
||||
|
||||
/* Available flags auxiliary network protocols */
|
||||
typedef enum _meshtastic_Config_NetworkConfig_ProtocolFlags {
|
||||
/* Do not broadcast packets over any network protocol */
|
||||
meshtastic_Config_NetworkConfig_ProtocolFlags_NO_BROADCAST = 0,
|
||||
/* Enable broadcasting packets via UDP over the local network */
|
||||
meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST = 1
|
||||
} meshtastic_Config_NetworkConfig_ProtocolFlags;
|
||||
|
||||
/* How the GPS coordinates are displayed on the OLED screen. */
|
||||
typedef enum _meshtastic_Config_DisplayConfig_GpsCoordinateFormat {
|
||||
/* GPS coordinates are displayed in the normal decimal degrees format:
|
||||
@@ -429,6 +437,8 @@ typedef struct _meshtastic_Config_NetworkConfig {
|
||||
meshtastic_Config_NetworkConfig_IpV4Config ipv4_config;
|
||||
/* rsyslog Server and Port */
|
||||
char rsyslog_server[33];
|
||||
/* Flags for enabling/disabling network protocols */
|
||||
uint32_t enabled_protocols;
|
||||
} meshtastic_Config_NetworkConfig;
|
||||
|
||||
/* Display Config */
|
||||
@@ -613,6 +623,10 @@ extern "C" {
|
||||
#define _meshtastic_Config_NetworkConfig_AddressMode_MAX meshtastic_Config_NetworkConfig_AddressMode_STATIC
|
||||
#define _meshtastic_Config_NetworkConfig_AddressMode_ARRAYSIZE ((meshtastic_Config_NetworkConfig_AddressMode)(meshtastic_Config_NetworkConfig_AddressMode_STATIC+1))
|
||||
|
||||
#define _meshtastic_Config_NetworkConfig_ProtocolFlags_MIN meshtastic_Config_NetworkConfig_ProtocolFlags_NO_BROADCAST
|
||||
#define _meshtastic_Config_NetworkConfig_ProtocolFlags_MAX meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST
|
||||
#define _meshtastic_Config_NetworkConfig_ProtocolFlags_ARRAYSIZE ((meshtastic_Config_NetworkConfig_ProtocolFlags)(meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST+1))
|
||||
|
||||
#define _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DEC
|
||||
#define _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MAX meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OSGR
|
||||
#define _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_ARRAYSIZE ((meshtastic_Config_DisplayConfig_GpsCoordinateFormat)(meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OSGR+1))
|
||||
@@ -674,7 +688,7 @@ extern "C" {
|
||||
#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, "", 0}
|
||||
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN}
|
||||
#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""}
|
||||
#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, "", 0}
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0}
|
||||
#define meshtastic_Config_DisplayConfig_init_default {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN}
|
||||
#define meshtastic_Config_LoRaConfig_init_default {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0}
|
||||
@@ -685,7 +699,7 @@ extern "C" {
|
||||
#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, "", 0}
|
||||
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN}
|
||||
#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""}
|
||||
#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, "", 0}
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0}
|
||||
#define meshtastic_Config_DisplayConfig_init_zero {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN}
|
||||
#define meshtastic_Config_LoRaConfig_init_zero {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0}
|
||||
@@ -739,6 +753,7 @@ extern "C" {
|
||||
#define meshtastic_Config_NetworkConfig_address_mode_tag 7
|
||||
#define meshtastic_Config_NetworkConfig_ipv4_config_tag 8
|
||||
#define meshtastic_Config_NetworkConfig_rsyslog_server_tag 9
|
||||
#define meshtastic_Config_NetworkConfig_enabled_protocols_tag 10
|
||||
#define meshtastic_Config_DisplayConfig_screen_on_secs_tag 1
|
||||
#define meshtastic_Config_DisplayConfig_gps_format_tag 2
|
||||
#define meshtastic_Config_DisplayConfig_auto_screen_carousel_secs_tag 3
|
||||
@@ -867,7 +882,8 @@ X(a, STATIC, SINGULAR, STRING, ntp_server, 5) \
|
||||
X(a, STATIC, SINGULAR, BOOL, eth_enabled, 6) \
|
||||
X(a, STATIC, SINGULAR, UENUM, address_mode, 7) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, ipv4_config, 8) \
|
||||
X(a, STATIC, SINGULAR, STRING, rsyslog_server, 9)
|
||||
X(a, STATIC, SINGULAR, STRING, rsyslog_server, 9) \
|
||||
X(a, STATIC, SINGULAR, UINT32, enabled_protocols, 10)
|
||||
#define meshtastic_Config_NetworkConfig_CALLBACK NULL
|
||||
#define meshtastic_Config_NetworkConfig_DEFAULT NULL
|
||||
#define meshtastic_Config_NetworkConfig_ipv4_config_MSGTYPE meshtastic_Config_NetworkConfig_IpV4Config
|
||||
@@ -972,12 +988,12 @@ extern const pb_msgdesc_t meshtastic_Config_SessionkeyConfig_msg;
|
||||
#define meshtastic_Config_DisplayConfig_size 30
|
||||
#define meshtastic_Config_LoRaConfig_size 85
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20
|
||||
#define meshtastic_Config_NetworkConfig_size 196
|
||||
#define meshtastic_Config_NetworkConfig_size 202
|
||||
#define meshtastic_Config_PositionConfig_size 62
|
||||
#define meshtastic_Config_PowerConfig_size 52
|
||||
#define meshtastic_Config_SecurityConfig_size 178
|
||||
#define meshtastic_Config_SessionkeyConfig_size 0
|
||||
#define meshtastic_Config_size 199
|
||||
#define meshtastic_Config_size 205
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -51,6 +51,8 @@ typedef enum _meshtastic_Language {
|
||||
meshtastic_Language_GREEK = 13,
|
||||
/* Norwegian */
|
||||
meshtastic_Language_NORWEGIAN = 14,
|
||||
/* Slovenian */
|
||||
meshtastic_Language_SLOVENIAN = 15,
|
||||
/* Simplified Chinese (experimental) */
|
||||
meshtastic_Language_SIMPLIFIED_CHINESE = 30,
|
||||
/* Traditional Chinese (experimental) */
|
||||
@@ -71,6 +73,8 @@ typedef struct _meshtastic_NodeFilter {
|
||||
bool position_switch;
|
||||
/* Filter nodes by matching name string */
|
||||
char node_name[16];
|
||||
/* Filter based on channel */
|
||||
int8_t channel;
|
||||
} meshtastic_NodeFilter;
|
||||
|
||||
typedef struct _meshtastic_NodeHighlight {
|
||||
@@ -138,10 +142,10 @@ extern "C" {
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_DeviceUIConfig_init_default {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_default, false, meshtastic_NodeHighlight_init_default, {0, {0}}}
|
||||
#define meshtastic_NodeFilter_init_default {0, 0, 0, 0, 0, ""}
|
||||
#define meshtastic_NodeFilter_init_default {0, 0, 0, 0, 0, "", 0}
|
||||
#define meshtastic_NodeHighlight_init_default {0, 0, 0, 0, ""}
|
||||
#define meshtastic_DeviceUIConfig_init_zero {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_zero, false, meshtastic_NodeHighlight_init_zero, {0, {0}}}
|
||||
#define meshtastic_NodeFilter_init_zero {0, 0, 0, 0, 0, ""}
|
||||
#define meshtastic_NodeFilter_init_zero {0, 0, 0, 0, 0, "", 0}
|
||||
#define meshtastic_NodeHighlight_init_zero {0, 0, 0, 0, ""}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
@@ -151,6 +155,7 @@ extern "C" {
|
||||
#define meshtastic_NodeFilter_hops_away_tag 4
|
||||
#define meshtastic_NodeFilter_position_switch_tag 5
|
||||
#define meshtastic_NodeFilter_node_name_tag 6
|
||||
#define meshtastic_NodeFilter_channel_tag 7
|
||||
#define meshtastic_NodeHighlight_chat_switch_tag 1
|
||||
#define meshtastic_NodeHighlight_position_switch_tag 2
|
||||
#define meshtastic_NodeHighlight_telemetry_switch_tag 3
|
||||
@@ -198,7 +203,8 @@ X(a, STATIC, SINGULAR, BOOL, offline_switch, 2) \
|
||||
X(a, STATIC, SINGULAR, BOOL, public_key_switch, 3) \
|
||||
X(a, STATIC, SINGULAR, INT32, hops_away, 4) \
|
||||
X(a, STATIC, SINGULAR, BOOL, position_switch, 5) \
|
||||
X(a, STATIC, SINGULAR, STRING, node_name, 6)
|
||||
X(a, STATIC, SINGULAR, STRING, node_name, 6) \
|
||||
X(a, STATIC, SINGULAR, INT32, channel, 7)
|
||||
#define meshtastic_NodeFilter_CALLBACK NULL
|
||||
#define meshtastic_NodeFilter_DEFAULT NULL
|
||||
|
||||
@@ -222,8 +228,8 @@ extern const pb_msgdesc_t meshtastic_NodeHighlight_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define MESHTASTIC_MESHTASTIC_DEVICE_UI_PB_H_MAX_SIZE meshtastic_DeviceUIConfig_size
|
||||
#define meshtastic_DeviceUIConfig_size 117
|
||||
#define meshtastic_NodeFilter_size 36
|
||||
#define meshtastic_DeviceUIConfig_size 128
|
||||
#define meshtastic_NodeFilter_size 47
|
||||
#define meshtastic_NodeHighlight_size 25
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -187,7 +187,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalConfig_size
|
||||
#define meshtastic_LocalConfig_size 735
|
||||
#define meshtastic_LocalConfig_size 741
|
||||
#define meshtastic_LocalModuleConfig_size 699
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
#endif
|
||||
#include "Led.h"
|
||||
#include "SPILock.h"
|
||||
#include "power.h"
|
||||
#include "serialization/JSON.h"
|
||||
#include <FSCommon.h>
|
||||
@@ -236,6 +237,7 @@ void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res)
|
||||
|
||||
void htmlDeleteDir(const char *dirname)
|
||||
{
|
||||
|
||||
File root = FSCom.open(dirname);
|
||||
if (!root) {
|
||||
return;
|
||||
@@ -318,6 +320,7 @@ void handleFsBrowseStatic(HTTPRequest *req, HTTPResponse *res)
|
||||
res->setHeader("Access-Control-Allow-Origin", "*");
|
||||
res->setHeader("Access-Control-Allow-Methods", "GET");
|
||||
|
||||
concurrency::LockGuard g(spiLock);
|
||||
auto fileList = htmlListDir("/static", 10);
|
||||
|
||||
// create json output structure
|
||||
@@ -349,9 +352,12 @@ void handleFsDeleteStatic(HTTPRequest *req, HTTPResponse *res)
|
||||
res->setHeader("Content-Type", "application/json");
|
||||
res->setHeader("Access-Control-Allow-Origin", "*");
|
||||
res->setHeader("Access-Control-Allow-Methods", "DELETE");
|
||||
|
||||
if (params->getQueryParameter("delete", paramValDelete)) {
|
||||
std::string pathDelete = "/" + paramValDelete;
|
||||
concurrency::LockGuard g(spiLock);
|
||||
if (FSCom.remove(pathDelete.c_str())) {
|
||||
|
||||
LOG_INFO("%s", pathDelete.c_str());
|
||||
JSONObject jsonObjOuter;
|
||||
jsonObjOuter["status"] = new JSONValue("ok");
|
||||
@@ -360,6 +366,7 @@ void handleFsDeleteStatic(HTTPRequest *req, HTTPResponse *res)
|
||||
delete value;
|
||||
return;
|
||||
} else {
|
||||
|
||||
LOG_INFO("%s", pathDelete.c_str());
|
||||
JSONObject jsonObjOuter;
|
||||
jsonObjOuter["status"] = new JSONValue("Error");
|
||||
@@ -393,6 +400,8 @@ void handleStatic(HTTPRequest *req, HTTPResponse *res)
|
||||
filenameGzip = "/static/index.html.gz";
|
||||
}
|
||||
|
||||
concurrency::LockGuard g(spiLock);
|
||||
|
||||
if (FSCom.exists(filename.c_str())) {
|
||||
file = FSCom.open(filename.c_str());
|
||||
if (!file.available()) {
|
||||
@@ -410,6 +419,7 @@ void handleStatic(HTTPRequest *req, HTTPResponse *res)
|
||||
file = FSCom.open(filenameGzip.c_str());
|
||||
res->setHeader("Content-Type", "text/html");
|
||||
if (!file.available()) {
|
||||
|
||||
LOG_WARN("File not available - %s", filenameGzip.c_str());
|
||||
res->println("Web server is running.<br><br>The content you are looking for can't be found. Please see: <a "
|
||||
"href=https://meshtastic.org/docs/software/web-client/>FAQ</a>.<br><br><a "
|
||||
@@ -535,6 +545,7 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res)
|
||||
// concepts of the body parser functionality easier to understand.
|
||||
std::string pathname = "/static/" + filename;
|
||||
|
||||
concurrency::LockGuard g(spiLock);
|
||||
// Create a new file to stream the data into
|
||||
File file = FSCom.open(pathname.c_str(), FILE_O_WRITE);
|
||||
size_t fileLength = 0;
|
||||
@@ -571,6 +582,7 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res)
|
||||
|
||||
file.flush();
|
||||
file.close();
|
||||
|
||||
res->printf("<p>Saved %d bytes to %s</p>", (int)fileLength, pathname.c_str());
|
||||
}
|
||||
if (!didwrite) {
|
||||
@@ -642,9 +654,11 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
|
||||
jsonObjMemory["heap_free"] = new JSONValue((int)memGet.getFreeHeap());
|
||||
jsonObjMemory["psram_total"] = new JSONValue((int)memGet.getPsramSize());
|
||||
jsonObjMemory["psram_free"] = new JSONValue((int)memGet.getFreePsram());
|
||||
spiLock->lock();
|
||||
jsonObjMemory["fs_total"] = new JSONValue((int)FSCom.totalBytes());
|
||||
jsonObjMemory["fs_used"] = new JSONValue((int)FSCom.usedBytes());
|
||||
jsonObjMemory["fs_free"] = new JSONValue(int(FSCom.totalBytes() - FSCom.usedBytes()));
|
||||
spiLock->unlock();
|
||||
|
||||
// data->power
|
||||
JSONObject jsonObjPower;
|
||||
@@ -725,7 +739,6 @@ void handleNodes(HTTPRequest *req, HTTPResponse *res)
|
||||
node["position"] = new JSONValue(position);
|
||||
}
|
||||
|
||||
JSONObject user;
|
||||
node["long_name"] = new JSONValue(tempNodeInfo->user.long_name);
|
||||
node["short_name"] = new JSONValue(tempNodeInfo->user.short_name);
|
||||
char macStr[18];
|
||||
@@ -787,6 +800,7 @@ void handleDeleteFsContent(HTTPRequest *req, HTTPResponse *res)
|
||||
|
||||
LOG_INFO("Delete files from /static/* : ");
|
||||
|
||||
concurrency::LockGuard g(spiLock);
|
||||
htmlDeleteDir("/static");
|
||||
|
||||
res->println("<p><hr><p><a href=/admin>Back to admin</a>");
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "configuration.h"
|
||||
|
||||
#include "FSCommon.h"
|
||||
#include "SPILock.h"
|
||||
#include "mesh-pb-constants.h"
|
||||
#include <Arduino.h>
|
||||
#include <pb_decode.h>
|
||||
@@ -55,9 +56,12 @@ bool readcb(pb_istream_t *stream, uint8_t *buf, size_t count)
|
||||
/// Write to an arduino file
|
||||
bool writecb(pb_ostream_t *stream, const uint8_t *buf, size_t count)
|
||||
{
|
||||
spiLock->lock();
|
||||
auto file = (Print *)stream->state;
|
||||
// LOG_DEBUG("writing %d bytes to protobuf file", count);
|
||||
return file->write(buf, count) == count;
|
||||
bool status = file->write(buf, count) == count;
|
||||
spiLock->unlock();
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -68,4 +72,4 @@ bool is_in_helper(uint32_t n, const uint32_t *array, pb_size_t count)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -82,8 +82,6 @@ char contentTypes[][2][32] = {{".txt", "text/plain"}, {".html", "text/html"
|
||||
volatile bool isWebServerReady;
|
||||
volatile bool isCertReady;
|
||||
|
||||
HttpAPI webAPI;
|
||||
|
||||
PiWebServerThread *piwebServerThread;
|
||||
|
||||
/**
|
||||
@@ -247,7 +245,7 @@ int handleAPIv1ToRadio(const struct _u_request *req, struct _u_response *res, vo
|
||||
portduinoVFS->mountpoint(configWeb.rootPath);
|
||||
|
||||
LOG_DEBUG("Received %d bytes from PUT request", s);
|
||||
webAPI.handleToRadio(buffer, s);
|
||||
static_cast<HttpAPI *>(user_data)->handleToRadio(buffer, s);
|
||||
LOG_DEBUG("end web->radio ");
|
||||
return U_CALLBACK_COMPLETE;
|
||||
}
|
||||
@@ -279,7 +277,7 @@ int handleAPIv1FromRadio(const struct _u_request *req, struct _u_response *res,
|
||||
|
||||
if (valueAll == "true") {
|
||||
while (len) {
|
||||
len = webAPI.getFromRadio(txBuf);
|
||||
len = static_cast<HttpAPI *>(user_data)->getFromRadio(txBuf);
|
||||
ulfius_set_response_properties(res, U_OPT_STATUS, 200, U_OPT_BINARY_BODY, txBuf, len);
|
||||
const char *tmpa = (const char *)txBuf;
|
||||
ulfius_set_string_body_response(res, 200, tmpa);
|
||||
@@ -289,7 +287,7 @@ int handleAPIv1FromRadio(const struct _u_request *req, struct _u_response *res,
|
||||
}
|
||||
// Otherwise, just return one protobuf
|
||||
} else {
|
||||
len = webAPI.getFromRadio(txBuf);
|
||||
len = static_cast<HttpAPI *>(user_data)->getFromRadio(txBuf);
|
||||
const char *tmpa = (const char *)txBuf;
|
||||
ulfius_set_binary_body_response(res, 200, tmpa, len);
|
||||
// LOG_DEBUG("\n----webAPI response:");
|
||||
@@ -497,10 +495,10 @@ PiWebServerThread::PiWebServerThread()
|
||||
u_map_put(instanceWeb.default_headers, "Access-Control-Allow-Origin", "*");
|
||||
// Maximum body size sent by the client is 1 Kb
|
||||
instanceWeb.max_post_body_size = 1024;
|
||||
ulfius_add_endpoint_by_val(&instanceWeb, "GET", PREFIX, "/api/v1/fromradio/*", 1, &handleAPIv1FromRadio, NULL);
|
||||
ulfius_add_endpoint_by_val(&instanceWeb, "OPTIONS", PREFIX, "/api/v1/fromradio/*", 1, &handleAPIv1FromRadio, NULL);
|
||||
ulfius_add_endpoint_by_val(&instanceWeb, "PUT", PREFIX, "/api/v1/toradio/*", 1, &handleAPIv1ToRadio, configWeb.rootPath);
|
||||
ulfius_add_endpoint_by_val(&instanceWeb, "OPTIONS", PREFIX, "/api/v1/toradio/*", 1, &handleAPIv1ToRadio, NULL);
|
||||
ulfius_add_endpoint_by_val(&instanceWeb, "GET", PREFIX, "/api/v1/fromradio/*", 1, &handleAPIv1FromRadio, &webAPI);
|
||||
ulfius_add_endpoint_by_val(&instanceWeb, "OPTIONS", PREFIX, "/api/v1/fromradio/*", 1, &handleAPIv1FromRadio, &webAPI);
|
||||
ulfius_add_endpoint_by_val(&instanceWeb, "PUT", PREFIX, "/api/v1/toradio/*", 1, &handleAPIv1ToRadio, &webAPI);
|
||||
ulfius_add_endpoint_by_val(&instanceWeb, "OPTIONS", PREFIX, "/api/v1/toradio/*", 1, &handleAPIv1ToRadio, &webAPI);
|
||||
|
||||
// Add callback function to all endpoints for the Web Server
|
||||
ulfius_add_endpoint_by_val(&instanceWeb, "GET", NULL, "/*", 2, &callback_static_file, &configWeb);
|
||||
@@ -525,13 +523,12 @@ PiWebServerThread::~PiWebServerThread()
|
||||
u_map_clean(&configWeb.mime_types);
|
||||
|
||||
ulfius_stop_framework(&instanceWeb);
|
||||
ulfius_stop_framework(&instanceWeb);
|
||||
ulfius_clean_instance(&instanceWeb);
|
||||
free(configWeb.rootPath);
|
||||
ulfius_clean_instance(&instanceService);
|
||||
ulfius_clean_instance(&instanceService);
|
||||
free(key_pem);
|
||||
free(cert_pem);
|
||||
LOG_INFO("End framework");
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@@ -23,24 +23,6 @@ struct _file_config {
|
||||
char *rootPath;
|
||||
};
|
||||
|
||||
class PiWebServerThread
|
||||
{
|
||||
private:
|
||||
char *key_pem = NULL;
|
||||
char *cert_pem = NULL;
|
||||
// struct _u_map mime_types;
|
||||
std::string webrootpath;
|
||||
|
||||
public:
|
||||
PiWebServerThread();
|
||||
~PiWebServerThread();
|
||||
int CreateSSLCertificate();
|
||||
int CheckSSLandLoad();
|
||||
uint32_t requestRestart = 0;
|
||||
struct _u_instance instanceWeb;
|
||||
struct _u_instance instanceService;
|
||||
};
|
||||
|
||||
class HttpAPI : public PhoneAPI
|
||||
{
|
||||
|
||||
@@ -55,6 +37,24 @@ class HttpAPI : public PhoneAPI
|
||||
virtual bool checkIsConnected() override { return true; } // FIXME, be smarter about this
|
||||
};
|
||||
|
||||
class PiWebServerThread
|
||||
{
|
||||
private:
|
||||
char *key_pem = NULL;
|
||||
char *cert_pem = NULL;
|
||||
// struct _u_map mime_types;
|
||||
std::string webrootpath;
|
||||
HttpAPI webAPI;
|
||||
|
||||
public:
|
||||
PiWebServerThread();
|
||||
~PiWebServerThread();
|
||||
int CreateSSLCertificate();
|
||||
int CheckSSLandLoad();
|
||||
uint32_t requestRestart = 0;
|
||||
struct _u_instance instanceWeb;
|
||||
};
|
||||
|
||||
extern PiWebServerThread *piwebServerThread;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -106,7 +106,9 @@ static void onNetworkConnected()
|
||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WEBSERVER
|
||||
initWebServer();
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_SOCKETAPI
|
||||
initApiServer();
|
||||
#endif
|
||||
APStartupComplete = true;
|
||||
}
|
||||
|
||||
@@ -141,6 +143,11 @@ static int32_t reconnectWiFi()
|
||||
delay(5000);
|
||||
|
||||
if (!WiFi.isConnected()) {
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32C3
|
||||
WiFi.mode(WIFI_MODE_NULL);
|
||||
WiFi.useStaticBuffers(true);
|
||||
WiFi.mode(WIFI_STA);
|
||||
#endif
|
||||
WiFi.begin(wifiName, wifiPsw);
|
||||
}
|
||||
isReconnecting = false;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "RTC.h"
|
||||
#include "SPILock.h"
|
||||
#include "meshUtils.h"
|
||||
#include <FSCommon.h>
|
||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||
@@ -358,12 +359,15 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
||||
}
|
||||
case meshtastic_AdminMessage_delete_file_request_tag: {
|
||||
LOG_DEBUG("Client requesting to delete file: %s", r->delete_file_request);
|
||||
|
||||
#ifdef FSCom
|
||||
spiLock->lock();
|
||||
if (FSCom.remove(r->delete_file_request)) {
|
||||
LOG_DEBUG("Successfully deleted file");
|
||||
} else {
|
||||
LOG_DEBUG("Failed to delete file");
|
||||
}
|
||||
spiLock->unlock();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -131,7 +131,6 @@ void AtakPluginModule::alterReceivedProtobuf(meshtastic_MeshPacket &mp, meshtast
|
||||
}
|
||||
|
||||
// Decompress for Phone (EUD)
|
||||
auto decompressedCopy = packetPool.allocCopy(mp);
|
||||
auto uncompressed = cloneTAKPacketData(t);
|
||||
uncompressed.is_compressed = false;
|
||||
if (t->has_contact) {
|
||||
@@ -188,6 +187,7 @@ void AtakPluginModule::alterReceivedProtobuf(meshtastic_MeshPacket &mp, meshtast
|
||||
LOG_DEBUG("Decompressed chat to_callsign: %d bytes", length);
|
||||
}
|
||||
}
|
||||
auto decompressedCopy = packetPool.allocCopy(mp);
|
||||
decompressedCopy->decoded.payload.size =
|
||||
pb_encode_to_bytes(decompressedCopy->decoded.payload.bytes, sizeof(decompressedCopy->decoded.payload),
|
||||
meshtastic_TAKPacket_fields, &uncompressed);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h" // needed for button bypass
|
||||
#include "SPILock.h"
|
||||
#include "detect/ScanI2C.h"
|
||||
#include "input/ScanAndSelect.h"
|
||||
#include "mesh/generated/meshtastic/cannedmessages.pb.h"
|
||||
@@ -982,6 +983,7 @@ bool CannedMessageModule::interceptingKeyboardInput()
|
||||
}
|
||||
}
|
||||
|
||||
#if !HAS_TFT
|
||||
void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
char buffer[50];
|
||||
@@ -1140,6 +1142,7 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //! HAS_TFT
|
||||
|
||||
ProcessMessage CannedMessageModule::handleReceived(const meshtastic_MeshPacket &mp)
|
||||
{
|
||||
@@ -1182,8 +1185,10 @@ bool CannedMessageModule::saveProtoForModule()
|
||||
{
|
||||
bool okay = true;
|
||||
|
||||
#ifdef FS
|
||||
FS.mkdir("/prefs");
|
||||
#ifdef FSCom
|
||||
spiLock->lock();
|
||||
FSCom.mkdir("/prefs");
|
||||
spiLock->unlock();
|
||||
#endif
|
||||
|
||||
okay &= nodeDB->saveProto(cannedMessagesConfigFile, meshtastic_CannedMessageModuleConfig_size,
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "PowerFSM.h"
|
||||
#include "RTC.h"
|
||||
#include "Router.h"
|
||||
#include "SPILock.h"
|
||||
#include "airtime.h"
|
||||
#include "configuration.h"
|
||||
#include "gps/GeoCoord.h"
|
||||
@@ -205,6 +206,7 @@ bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp)
|
||||
LOG_DEBUG("gpsStatus->getDOP() %d", gpsStatus->getDOP());
|
||||
LOG_DEBUG("-----------------------------------------");
|
||||
*/
|
||||
concurrency::LockGuard g(spiLock);
|
||||
if (!FSBegin()) {
|
||||
LOG_DEBUG("An Error has occurred while mounting the filesystem");
|
||||
return 0;
|
||||
|
||||
@@ -13,7 +13,8 @@ class RoutingModule : public ProtobufModule<meshtastic_Routing>
|
||||
*/
|
||||
RoutingModule();
|
||||
|
||||
void sendAckNak(meshtastic_Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex, uint8_t hopLimit = 0);
|
||||
virtual void sendAckNak(meshtastic_Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex,
|
||||
uint8_t hopLimit = 0);
|
||||
|
||||
// Given the hopStart and hopLimit upon reception of a request, return the hop limit to use for the response
|
||||
uint8_t getHopLimitForResponse(uint8_t hopStart, uint8_t hopLimit);
|
||||
|
||||
@@ -64,6 +64,10 @@ CGRadSensSensor cgRadSens;
|
||||
#include "Sensor/T1000xSensor.h"
|
||||
T1000xSensor t1000xSensor;
|
||||
#endif
|
||||
#ifdef SENSECAP_INDICATOR
|
||||
#include "Sensor/IndicatorSensor.h"
|
||||
IndicatorSensor indicatorSensor;
|
||||
#endif
|
||||
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
|
||||
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
|
||||
|
||||
@@ -103,6 +107,9 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
||||
LOG_INFO("Environment Telemetry: init");
|
||||
// it's possible to have this module enabled, only for displaying values on the screen.
|
||||
// therefore, we should only enable the sensor loop if measurement is also enabled
|
||||
#ifdef SENSECAP_INDICATOR
|
||||
result = indicatorSensor.runOnce();
|
||||
#endif
|
||||
#ifdef T1000X_SENSOR_EN
|
||||
result = t1000xSensor.runOnce();
|
||||
#elif !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL
|
||||
@@ -215,7 +222,11 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt
|
||||
}
|
||||
|
||||
// Display "Env. From: ..." on its own
|
||||
display->drawString(x, y, "Env. From: " + String(lastSender) + "(" + String(agoSecs) + "s)");
|
||||
display->drawString(x, y, "Env. From: " + String(lastSender) + " (" + String(agoSecs) + "s)");
|
||||
|
||||
// Prepare sensor data strings
|
||||
String sensorData[10];
|
||||
int sensorCount = 0;
|
||||
|
||||
if (lastMeasurement.variant.environment_metrics.has_temperature ||
|
||||
lastMeasurement.variant.environment_metrics.has_relative_humidity) {
|
||||
@@ -225,38 +236,83 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt
|
||||
String(UnitConversions::CelsiusToFahrenheit(lastMeasurement.variant.environment_metrics.temperature), 0) + "°F";
|
||||
}
|
||||
|
||||
// Continue with the remaining details
|
||||
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||
"Temp/Hum: " + last_temp + " / " +
|
||||
String(lastMeasurement.variant.environment_metrics.relative_humidity, 0) + "%");
|
||||
sensorData[sensorCount++] =
|
||||
"Temp/Hum: " + last_temp + " / " + String(lastMeasurement.variant.environment_metrics.relative_humidity, 0) + "%";
|
||||
}
|
||||
|
||||
if (lastMeasurement.variant.environment_metrics.barometric_pressure != 0) {
|
||||
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||
"Press: " + String(lastMeasurement.variant.environment_metrics.barometric_pressure, 0) + "hPA");
|
||||
sensorData[sensorCount++] =
|
||||
"Press: " + String(lastMeasurement.variant.environment_metrics.barometric_pressure, 0) + "hPA";
|
||||
}
|
||||
|
||||
if (lastMeasurement.variant.environment_metrics.voltage != 0) {
|
||||
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||
"Volt/Cur: " + String(lastMeasurement.variant.environment_metrics.voltage, 0) + "V / " +
|
||||
String(lastMeasurement.variant.environment_metrics.current, 0) + "mA");
|
||||
sensorData[sensorCount++] = "Volt/Cur: " + String(lastMeasurement.variant.environment_metrics.voltage, 0) + "V / " +
|
||||
String(lastMeasurement.variant.environment_metrics.current, 0) + "mA";
|
||||
}
|
||||
|
||||
if (lastMeasurement.variant.environment_metrics.iaq != 0) {
|
||||
display->drawString(x, y += _fontHeight(FONT_SMALL), "IAQ: " + String(lastMeasurement.variant.environment_metrics.iaq));
|
||||
sensorData[sensorCount++] = "IAQ: " + String(lastMeasurement.variant.environment_metrics.iaq);
|
||||
}
|
||||
|
||||
if (lastMeasurement.variant.environment_metrics.distance != 0)
|
||||
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||
"Water Level: " + String(lastMeasurement.variant.environment_metrics.distance, 0) + "mm");
|
||||
if (lastMeasurement.variant.environment_metrics.distance != 0) {
|
||||
sensorData[sensorCount++] = "Water Level: " + String(lastMeasurement.variant.environment_metrics.distance, 0) + "mm";
|
||||
}
|
||||
|
||||
if (lastMeasurement.variant.environment_metrics.weight != 0)
|
||||
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||
"Weight: " + String(lastMeasurement.variant.environment_metrics.weight, 0) + "kg");
|
||||
if (lastMeasurement.variant.environment_metrics.weight != 0) {
|
||||
sensorData[sensorCount++] = "Weight: " + String(lastMeasurement.variant.environment_metrics.weight, 0) + "kg";
|
||||
}
|
||||
|
||||
if (lastMeasurement.variant.environment_metrics.radiation != 0)
|
||||
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||
"Rad: " + String(lastMeasurement.variant.environment_metrics.radiation, 2) + "µR/h");
|
||||
if (lastMeasurement.variant.environment_metrics.radiation != 0) {
|
||||
sensorData[sensorCount++] = "Rad: " + String(lastMeasurement.variant.environment_metrics.radiation, 2) + "µR/h";
|
||||
}
|
||||
|
||||
if (lastMeasurement.variant.environment_metrics.lux != 0) {
|
||||
sensorData[sensorCount++] = "Illuminance: " + String(lastMeasurement.variant.environment_metrics.lux, 2) + "lx";
|
||||
}
|
||||
|
||||
if (lastMeasurement.variant.environment_metrics.white_lux != 0) {
|
||||
sensorData[sensorCount++] = "W_Lux: " + String(lastMeasurement.variant.environment_metrics.white_lux, 2) + "lx";
|
||||
}
|
||||
|
||||
static int scrollOffset = 0;
|
||||
static bool scrollingDown = true;
|
||||
static uint32_t lastScrollTime = millis();
|
||||
|
||||
// Determine how many lines we can fit on display
|
||||
// Calculated once only: display dimensions don't change during runtime.
|
||||
static int maxLines = 0;
|
||||
if (!maxLines) {
|
||||
const int16_t paddingTop = _fontHeight(FONT_SMALL); // Heading text
|
||||
const int16_t paddingBottom = 8; // Indicator dots
|
||||
maxLines = (display->getHeight() - paddingTop - paddingBottom) / _fontHeight(FONT_SMALL);
|
||||
assert(maxLines > 0);
|
||||
}
|
||||
|
||||
// Draw as many lines of data as we can fit
|
||||
int linesToShow = min(maxLines, sensorCount);
|
||||
for (int i = 0; i < linesToShow; i++) {
|
||||
int index = (scrollOffset + i) % sensorCount;
|
||||
display->drawString(x, y += _fontHeight(FONT_SMALL), sensorData[index]);
|
||||
}
|
||||
|
||||
// Only scroll if there are more than 3 sensor data lines
|
||||
if (sensorCount > 3) {
|
||||
// Update scroll offset every 5 seconds
|
||||
if (millis() - lastScrollTime > 5000) {
|
||||
if (scrollingDown) {
|
||||
scrollOffset++;
|
||||
if (scrollOffset + linesToShow >= sensorCount) {
|
||||
scrollingDown = false;
|
||||
}
|
||||
} else {
|
||||
scrollOffset--;
|
||||
if (scrollOffset <= 0) {
|
||||
scrollingDown = true;
|
||||
}
|
||||
}
|
||||
lastScrollTime = millis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool EnvironmentTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t)
|
||||
@@ -270,8 +326,10 @@ bool EnvironmentTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPac
|
||||
sender, t->variant.environment_metrics.barometric_pressure, t->variant.environment_metrics.current,
|
||||
t->variant.environment_metrics.gas_resistance, t->variant.environment_metrics.relative_humidity,
|
||||
t->variant.environment_metrics.temperature);
|
||||
LOG_INFO("(Received from %s): voltage=%f, IAQ=%d, distance=%f, lux=%f", sender, t->variant.environment_metrics.voltage,
|
||||
t->variant.environment_metrics.iaq, t->variant.environment_metrics.distance, t->variant.environment_metrics.lux);
|
||||
LOG_INFO("(Received from %s): voltage=%f, IAQ=%d, distance=%f, lux=%f, white_lux=%f", sender,
|
||||
t->variant.environment_metrics.voltage, t->variant.environment_metrics.iaq,
|
||||
t->variant.environment_metrics.distance, t->variant.environment_metrics.lux,
|
||||
t->variant.environment_metrics.white_lux);
|
||||
|
||||
LOG_INFO("(Received from %s): wind speed=%fm/s, direction=%d degrees, weight=%fkg", sender,
|
||||
t->variant.environment_metrics.wind_speed, t->variant.environment_metrics.wind_direction,
|
||||
@@ -298,6 +356,10 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m
|
||||
m->which_variant = meshtastic_Telemetry_environment_metrics_tag;
|
||||
m->variant.environment_metrics = meshtastic_EnvironmentMetrics_init_zero;
|
||||
|
||||
#ifdef SENSECAP_INDICATOR
|
||||
valid = valid && indicatorSensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
#endif
|
||||
#ifdef T1000X_SENSOR_EN // add by WayenWeng
|
||||
valid = valid && t1000xSensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
@@ -410,7 +472,6 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m
|
||||
valid = valid && cgRadSens.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
|
||||
#endif
|
||||
return valid && hasSensor;
|
||||
}
|
||||
|
||||
@@ -99,44 +99,45 @@ bool PowerTelemetryModule::wantUIFrame()
|
||||
void PowerTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(FONT_MEDIUM);
|
||||
display->drawString(x, y, "Power Telemetry");
|
||||
display->setFont(FONT_SMALL);
|
||||
|
||||
if (lastMeasurementPacket == nullptr) {
|
||||
display->setFont(FONT_SMALL);
|
||||
display->drawString(x, y += _fontHeight(FONT_MEDIUM), "No measurement");
|
||||
// In case of no valid packet, display "Power Telemetry", "No measurement"
|
||||
display->drawString(x, y, "Power Telemetry");
|
||||
display->drawString(x, y += _fontHeight(FONT_SMALL), "No measurement");
|
||||
return;
|
||||
}
|
||||
|
||||
// Decode the last power packet
|
||||
meshtastic_Telemetry lastMeasurement;
|
||||
|
||||
uint32_t agoSecs = service->GetTimeSinceMeshPacket(lastMeasurementPacket);
|
||||
const char *lastSender = getSenderShortName(*lastMeasurementPacket);
|
||||
|
||||
const meshtastic_Data &p = lastMeasurementPacket->decoded;
|
||||
if (!pb_decode_from_bytes(p.payload.bytes, p.payload.size, &meshtastic_Telemetry_msg, &lastMeasurement)) {
|
||||
display->setFont(FONT_SMALL);
|
||||
display->drawString(x, y += _fontHeight(FONT_MEDIUM), "Measurement Error");
|
||||
display->drawString(x, y, "Measurement Error");
|
||||
LOG_ERROR("Unable to decode last packet");
|
||||
return;
|
||||
}
|
||||
|
||||
// Display "Pow. From: ..."
|
||||
display->drawString(x, y, "Pow. From: " + String(lastSender) + "(" + String(agoSecs) + "s)");
|
||||
|
||||
// Display current and voltage based on ...power_metrics.has_[channel/voltage/current]... flags
|
||||
display->setFont(FONT_SMALL);
|
||||
display->drawString(x, y += _fontHeight(FONT_MEDIUM) - 2, "From: " + String(lastSender) + "(" + String(agoSecs) + "s)");
|
||||
if (lastMeasurement.variant.power_metrics.has_ch1_voltage || lastMeasurement.variant.power_metrics.has_ch1_current) {
|
||||
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||
"Ch1 Volt: " + String(lastMeasurement.variant.power_metrics.ch1_voltage, 2) +
|
||||
"V / Curr: " + String(lastMeasurement.variant.power_metrics.ch1_current, 0) + "mA");
|
||||
"Ch1: " + String(lastMeasurement.variant.power_metrics.ch1_voltage, 2) +
|
||||
"V " + String(lastMeasurement.variant.power_metrics.ch1_current, 0) + "mA");
|
||||
}
|
||||
if (lastMeasurement.variant.power_metrics.has_ch2_voltage || lastMeasurement.variant.power_metrics.has_ch2_current) {
|
||||
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||
"Ch2 Volt: " + String(lastMeasurement.variant.power_metrics.ch2_voltage, 2) +
|
||||
"V / Curr: " + String(lastMeasurement.variant.power_metrics.ch2_current, 0) + "mA");
|
||||
"Ch2: " + String(lastMeasurement.variant.power_metrics.ch2_voltage, 2) +
|
||||
"V " + String(lastMeasurement.variant.power_metrics.ch2_current, 0) + "mA");
|
||||
}
|
||||
if (lastMeasurement.variant.power_metrics.has_ch3_voltage || lastMeasurement.variant.power_metrics.has_ch3_current) {
|
||||
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||
"Ch3 Volt: " + String(lastMeasurement.variant.power_metrics.ch3_voltage, 2) +
|
||||
"V / Curr: " + String(lastMeasurement.variant.power_metrics.ch3_current, 0) + "mA");
|
||||
"Ch3: " + String(lastMeasurement.variant.power_metrics.ch3_voltage, 2) +
|
||||
"V " + String(lastMeasurement.variant.power_metrics.ch3_current, 0) + "mA");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include "BME680Sensor.h"
|
||||
#include "FSCommon.h"
|
||||
#include "SPILock.h"
|
||||
#include "TelemetrySensor.h"
|
||||
|
||||
BME680Sensor::BME680Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_BME680, "BME680") {}
|
||||
@@ -75,6 +76,7 @@ bool BME680Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
void BME680Sensor::loadState()
|
||||
{
|
||||
#ifdef FSCom
|
||||
spiLock->lock();
|
||||
auto file = FSCom.open(bsecConfigFileName, FILE_O_READ);
|
||||
if (file) {
|
||||
file.read((uint8_t *)&bsecState, BSEC_MAX_STATE_BLOB_SIZE);
|
||||
@@ -84,6 +86,7 @@ void BME680Sensor::loadState()
|
||||
} else {
|
||||
LOG_INFO("No %s state found (File: %s)", sensorName, bsecConfigFileName);
|
||||
}
|
||||
spiLock->unlock();
|
||||
#else
|
||||
LOG_ERROR("ERROR: Filesystem not implemented");
|
||||
#endif
|
||||
@@ -92,6 +95,7 @@ void BME680Sensor::loadState()
|
||||
void BME680Sensor::updateState()
|
||||
{
|
||||
#ifdef FSCom
|
||||
spiLock->lock();
|
||||
bool update = false;
|
||||
if (stateUpdateCounter == 0) {
|
||||
/* First state update when IAQ accuracy is >= 3 */
|
||||
@@ -127,6 +131,7 @@ void BME680Sensor::updateState()
|
||||
LOG_INFO("Can't write %s state (File: %s)", sensorName, bsecConfigFileName);
|
||||
}
|
||||
}
|
||||
spiLock->unlock();
|
||||
#else
|
||||
LOG_ERROR("ERROR: Filesystem not implemented");
|
||||
#endif
|
||||
|
||||
@@ -41,13 +41,12 @@ void CGRadSensSensor::begin(TwoWire *wire, uint8_t addr)
|
||||
float CGRadSensSensor::getStaticRadiation()
|
||||
{
|
||||
// Read a register, following the same pattern as the RCWL9620Sensor
|
||||
uint32_t data;
|
||||
_wire->beginTransmission(_addr); // Transfer data to addr.
|
||||
_wire->write(0x06); // Radiation intensity (static period T = 500 sec)
|
||||
if (_wire->endTransmission() == 0) {
|
||||
if (_wire->requestFrom(_addr, (uint8_t)3)) {
|
||||
; // Request 3 bytes
|
||||
data = _wire->read();
|
||||
uint32_t data = _wire->read();
|
||||
data <<= 8;
|
||||
data |= _wire->read();
|
||||
data <<= 8;
|
||||
|
||||
166
src/modules/Telemetry/Sensor/IndicatorSensor.cpp
Normal file
166
src/modules/Telemetry/Sensor/IndicatorSensor.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
#include "configuration.h"
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(SENSECAP_INDICATOR)
|
||||
|
||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include "IndicatorSensor.h"
|
||||
#include "TelemetrySensor.h"
|
||||
#include "serialization/cobs.h"
|
||||
#include <Adafruit_Sensor.h>
|
||||
#include <driver/uart.h>
|
||||
|
||||
IndicatorSensor::IndicatorSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_SENSOR_UNSET, "Indicator") {}
|
||||
|
||||
#define SENSOR_BUF_SIZE (512)
|
||||
|
||||
uint8_t buf[SENSOR_BUF_SIZE]; // recv
|
||||
uint8_t data[SENSOR_BUF_SIZE]; // decode
|
||||
|
||||
#define ACK_PKT_PARA "ACK"
|
||||
|
||||
enum sensor_pkt_type {
|
||||
PKT_TYPE_ACK = 0x00, // uin32_t
|
||||
PKT_TYPE_CMD_COLLECT_INTERVAL = 0xA0, // uin32_t
|
||||
PKT_TYPE_CMD_BEEP_ON = 0xA1, // uin32_t ms: on time
|
||||
PKT_TYPE_CMD_BEEP_OFF = 0xA2,
|
||||
PKT_TYPE_CMD_SHUTDOWN = 0xA3, // uin32_t
|
||||
PKT_TYPE_CMD_POWER_ON = 0xA4,
|
||||
PKT_TYPE_SENSOR_SCD41_TEMP = 0xB0, // float
|
||||
PKT_TYPE_SENSOR_SCD41_HUMIDITY = 0xB1, // float
|
||||
PKT_TYPE_SENSOR_SCD41_CO2 = 0xB2, // float
|
||||
PKT_TYPE_SENSOR_AHT20_TEMP = 0xB3, // float
|
||||
PKT_TYPE_SENSOR_AHT20_HUMIDITY = 0xB4, // float
|
||||
PKT_TYPE_SENSOR_TVOC_INDEX = 0xB5, // float
|
||||
};
|
||||
|
||||
static int cmd_send(uint8_t cmd, const char *p_data, uint8_t len)
|
||||
{
|
||||
uint8_t send_buf[32] = {0};
|
||||
uint8_t send_data[32] = {0};
|
||||
|
||||
if (len > 31) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t index = 1;
|
||||
|
||||
send_data[0] = cmd;
|
||||
|
||||
if (len > 0 && p_data != NULL) {
|
||||
memcpy(&send_data[1], p_data, len);
|
||||
index += len;
|
||||
}
|
||||
cobs_encode_result ret = cobs_encode(send_buf, sizeof(send_buf), send_data, index);
|
||||
|
||||
// LOG_DEBUG("cobs TX status:%d, len:%d, type 0x%x", ret.status, ret.out_len, cmd);
|
||||
|
||||
if (ret.status == COBS_ENCODE_OK) {
|
||||
return uart_write_bytes(SENSOR_PORT_NUM, send_buf, ret.out_len + 1);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t IndicatorSensor::runOnce()
|
||||
{
|
||||
LOG_INFO("%s: init", sensorName);
|
||||
setup();
|
||||
return 2 * DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; // give it some time to start up
|
||||
}
|
||||
|
||||
void IndicatorSensor::setup()
|
||||
{
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = SENSOR_BAUD_RATE,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_APB,
|
||||
};
|
||||
int intr_alloc_flags = 0;
|
||||
char buffer[11];
|
||||
|
||||
uart_driver_install(SENSOR_PORT_NUM, SENSOR_BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags);
|
||||
uart_param_config(SENSOR_PORT_NUM, &uart_config);
|
||||
uart_set_pin(SENSOR_PORT_NUM, SENSOR_RP2040_TXD, SENSOR_RP2040_RXD, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
||||
cmd_send(PKT_TYPE_CMD_POWER_ON, NULL, 0);
|
||||
// measure and send only once every minute, for the phone API
|
||||
const char *interval = ultoa(60000, buffer, 10);
|
||||
cmd_send(PKT_TYPE_CMD_COLLECT_INTERVAL, interval, strlen(interval) + 1);
|
||||
}
|
||||
|
||||
bool IndicatorSensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
{
|
||||
cobs_decode_result ret;
|
||||
int len = uart_read_bytes(SENSOR_PORT_NUM, buf, (SENSOR_BUF_SIZE - 1), 100 / portTICK_PERIOD_MS);
|
||||
|
||||
float value = 0.0;
|
||||
uint8_t *p_buf_start = buf;
|
||||
uint8_t *p_buf_end = buf;
|
||||
if (len > 0) {
|
||||
while (p_buf_start < (buf + len)) {
|
||||
p_buf_end = p_buf_start;
|
||||
while (p_buf_end < (buf + len)) {
|
||||
if (*p_buf_end == 0x00) {
|
||||
break;
|
||||
}
|
||||
p_buf_end++;
|
||||
}
|
||||
// decode buf
|
||||
memset(data, 0, sizeof(data));
|
||||
ret = cobs_decode(data, sizeof(data), p_buf_start, p_buf_end - p_buf_start);
|
||||
|
||||
// LOG_DEBUG("cobs RX status:%d, len:%d, type:0x%x ", ret.status, ret.out_len, data[0]);
|
||||
|
||||
if (ret.out_len > 1 && ret.status == COBS_DECODE_OK) {
|
||||
|
||||
value = 0.0;
|
||||
uint8_t pkt_type = data[0];
|
||||
switch (pkt_type) {
|
||||
case PKT_TYPE_SENSOR_SCD41_CO2: {
|
||||
memcpy(&value, &data[1], sizeof(value));
|
||||
// LOG_DEBUG("CO2: %.1f", value);
|
||||
cmd_send(PKT_TYPE_ACK, ACK_PKT_PARA, 4);
|
||||
break;
|
||||
}
|
||||
|
||||
case PKT_TYPE_SENSOR_AHT20_TEMP: {
|
||||
memcpy(&value, &data[1], sizeof(value));
|
||||
// LOG_DEBUG("Temp: %.1f", value);
|
||||
cmd_send(PKT_TYPE_ACK, ACK_PKT_PARA, 4);
|
||||
measurement->variant.environment_metrics.has_temperature = true;
|
||||
measurement->variant.environment_metrics.temperature = value;
|
||||
break;
|
||||
}
|
||||
|
||||
case PKT_TYPE_SENSOR_AHT20_HUMIDITY: {
|
||||
memcpy(&value, &data[1], sizeof(value));
|
||||
// LOG_DEBUG("Humidity: %.1f", value);
|
||||
cmd_send(PKT_TYPE_ACK, ACK_PKT_PARA, 4);
|
||||
measurement->variant.environment_metrics.has_relative_humidity = true;
|
||||
measurement->variant.environment_metrics.relative_humidity = value;
|
||||
break;
|
||||
}
|
||||
|
||||
case PKT_TYPE_SENSOR_TVOC_INDEX: {
|
||||
memcpy(&value, &data[1], sizeof(value));
|
||||
// LOG_DEBUG("Tvoc: %.1f", value);
|
||||
cmd_send(PKT_TYPE_ACK, ACK_PKT_PARA, 4);
|
||||
measurement->variant.environment_metrics.has_iaq = true;
|
||||
measurement->variant.environment_metrics.iaq = value;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p_buf_start = p_buf_end + 1; // next message
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
19
src/modules/Telemetry/Sensor/IndicatorSensor.h
Normal file
19
src/modules/Telemetry/Sensor/IndicatorSensor.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "configuration.h"
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
|
||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include "TelemetrySensor.h"
|
||||
|
||||
class IndicatorSensor : public TelemetrySensor
|
||||
{
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
IndicatorSensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include "FSCommon.h"
|
||||
#include "NAU7802Sensor.h"
|
||||
#include "SPILock.h"
|
||||
#include "SafeFile.h"
|
||||
#include "TelemetrySensor.h"
|
||||
#include <Throttle.h>
|
||||
@@ -111,13 +112,16 @@ bool NAU7802Sensor::saveCalibrationData()
|
||||
} else {
|
||||
okay = true;
|
||||
}
|
||||
spiLock->lock();
|
||||
okay &= file.close();
|
||||
spiLock->unlock();
|
||||
|
||||
return okay;
|
||||
}
|
||||
|
||||
bool NAU7802Sensor::loadCalibrationData()
|
||||
{
|
||||
spiLock->lock();
|
||||
auto file = FSCom.open(nau7802ConfigFileName, FILE_O_READ);
|
||||
bool okay = false;
|
||||
if (file) {
|
||||
@@ -134,7 +138,8 @@ bool NAU7802Sensor::loadCalibrationData()
|
||||
} else {
|
||||
LOG_INFO("No %s state found (File: %s)", sensorName, nau7802ConfigFileName);
|
||||
}
|
||||
spiLock->unlock();
|
||||
return okay;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "ServiceEnvelope.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
#include "mesh/Channels.h"
|
||||
@@ -25,7 +26,6 @@
|
||||
#endif
|
||||
#include <Throttle.h>
|
||||
#include <assert.h>
|
||||
#include <pb_decode.h>
|
||||
#include <utility>
|
||||
|
||||
#include <IPAddress.h>
|
||||
@@ -47,23 +47,6 @@ static uint8_t bytes[meshtastic_MqttClientProxyMessage_size + 30]; // 12 for cha
|
||||
|
||||
static bool isMqttServerAddressPrivate = false;
|
||||
|
||||
// meshtastic_ServiceEnvelope that automatically releases dynamically allocated memory when it goes out of scope.
|
||||
struct DecodedServiceEnvelope : public meshtastic_ServiceEnvelope {
|
||||
DecodedServiceEnvelope() = delete;
|
||||
DecodedServiceEnvelope(const uint8_t *payload, size_t length)
|
||||
: meshtastic_ServiceEnvelope(meshtastic_ServiceEnvelope_init_default),
|
||||
validDecode(pb_decode_from_bytes(payload, length, &meshtastic_ServiceEnvelope_msg, this))
|
||||
{
|
||||
}
|
||||
~DecodedServiceEnvelope()
|
||||
{
|
||||
if (validDecode)
|
||||
pb_release(&meshtastic_ServiceEnvelope_msg, this);
|
||||
}
|
||||
// Clients must check that this is true before using.
|
||||
const bool validDecode;
|
||||
};
|
||||
|
||||
inline void onReceiveProto(char *topic, byte *payload, size_t length)
|
||||
{
|
||||
const DecodedServiceEnvelope e(payload, length);
|
||||
@@ -93,12 +76,22 @@ inline void onReceiveProto(char *topic, byte *payload, size_t length)
|
||||
return;
|
||||
}
|
||||
LOG_INFO("Received MQTT topic %s, len=%u", topic, length);
|
||||
if (e.packet->hop_limit > HOP_MAX || e.packet->hop_start > HOP_MAX) {
|
||||
LOG_INFO("Invalid hop_limit(%u) or hop_start(%u)", e.packet->hop_limit, e.packet->hop_start);
|
||||
return;
|
||||
}
|
||||
|
||||
UniquePacketPoolPacket p = packetPool.allocUniqueCopy(*e.packet);
|
||||
UniquePacketPoolPacket p = packetPool.allocUniqueZeroed();
|
||||
p->from = e.packet->from;
|
||||
p->to = e.packet->to;
|
||||
p->id = e.packet->id;
|
||||
p->channel = e.packet->channel;
|
||||
p->hop_limit = e.packet->hop_limit;
|
||||
p->hop_start = e.packet->hop_start;
|
||||
p->want_ack = e.packet->want_ack;
|
||||
p->via_mqtt = true; // Mark that the packet was received via MQTT
|
||||
// Unset received SNR/RSSI which might have been added by the MQTT gateway
|
||||
p->rx_snr = 0;
|
||||
p->rx_rssi = 0;
|
||||
p->which_payload_variant = e.packet->which_payload_variant;
|
||||
memcpy(&p->decoded, &e.packet->decoded, std::max(sizeof(p->decoded), sizeof(p->encrypted)));
|
||||
|
||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||
if (moduleConfig.mqtt.encryption_enabled) {
|
||||
@@ -299,7 +292,9 @@ void mqttInit()
|
||||
}
|
||||
|
||||
#if HAS_NETWORKING
|
||||
MQTT::MQTT() : concurrency::OSThread("mqtt"), pubSub(mqttClient), mqttQueue(MAX_MQTT_QUEUE)
|
||||
MQTT::MQTT() : MQTT(std::unique_ptr<MQTTClient>(new MQTTClient())) {}
|
||||
MQTT::MQTT(std::unique_ptr<MQTTClient> _mqttClient)
|
||||
: concurrency::OSThread("mqtt"), mqttQueue(MAX_MQTT_QUEUE), mqttClient(std::move(_mqttClient)), pubSub(*mqttClient)
|
||||
#else
|
||||
MQTT::MQTT() : concurrency::OSThread("mqtt"), mqttQueue(MAX_MQTT_QUEUE)
|
||||
#endif
|
||||
@@ -437,20 +432,20 @@ void MQTT::reconnect()
|
||||
}
|
||||
} else {
|
||||
LOG_INFO("Use non-TLS-encrypted session");
|
||||
pubSub.setClient(mqttClient);
|
||||
pubSub.setClient(*mqttClient);
|
||||
}
|
||||
#else
|
||||
pubSub.setClient(mqttClient);
|
||||
pubSub.setClient(*mqttClient);
|
||||
#endif
|
||||
#elif HAS_NETWORKING
|
||||
pubSub.setClient(mqttClient);
|
||||
pubSub.setClient(*mqttClient);
|
||||
#endif
|
||||
|
||||
std::pair<String, uint16_t> hostAndPort = parseHostAndPort(serverAddr, serverPort);
|
||||
serverAddr = hostAndPort.first.c_str();
|
||||
serverPort = hostAndPort.second;
|
||||
pubSub.setServer(serverAddr, serverPort);
|
||||
pubSub.setBufferSize(512);
|
||||
pubSub.setBufferSize(1024);
|
||||
|
||||
LOG_INFO("Connect directly to MQTT server %s, port: %d, username: %s, password: %s", serverAddr, serverPort, mqttUsername,
|
||||
mqttPassword);
|
||||
@@ -461,7 +456,7 @@ void MQTT::reconnect()
|
||||
enabled = true; // Start running background process again
|
||||
runASAP = true;
|
||||
reconnectCount = 0;
|
||||
isMqttServerAddressPrivate = isPrivateIpAddress(mqttClient.remoteIP());
|
||||
isMqttServerAddressPrivate = isPrivateIpAddress(mqttClient->remoteIP());
|
||||
|
||||
publishNodeInfo();
|
||||
sendSubscriptions();
|
||||
@@ -627,8 +622,7 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp_encrypted, const meshtastic_Me
|
||||
// mp_decoded will not be decoded when it's PKI encrypted and not directed to us
|
||||
if (mp_decoded.which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||
// For uplinking other's packets, check if it's not OK to MQTT or if it's an older packet without the bitfield
|
||||
bool dontUplink = !mp_decoded.decoded.has_bitfield ||
|
||||
(mp_decoded.decoded.has_bitfield && !(mp_decoded.decoded.bitfield & BITFIELD_OK_TO_MQTT_MASK));
|
||||
bool dontUplink = !mp_decoded.decoded.has_bitfield || !(mp_decoded.decoded.bitfield & BITFIELD_OK_TO_MQTT_MASK);
|
||||
// check for the lowest bit of the data bitfield set false, and the use of one of the default keys.
|
||||
if (!isFromUs(&mp_decoded) && !isMqttServerAddressPrivate && dontUplink &&
|
||||
(ch.settings.psk.size < 2 || (ch.settings.psk.size == 16 && memcmp(ch.settings.psk.bytes, defaultpsk, 16)) ||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#if HAS_NETWORKING
|
||||
#include <PubSubClient.h>
|
||||
#include <memory>
|
||||
#endif
|
||||
|
||||
#define MAX_MQTT_QUEUE 16
|
||||
@@ -32,24 +33,7 @@
|
||||
*/
|
||||
class MQTT : private concurrency::OSThread
|
||||
{
|
||||
// supposedly the current version is busted:
|
||||
// http://www.iotsharing.com/2017/08/how-to-use-esp32-mqtts-with-mqtts-mosquitto-broker-tls-ssl.html
|
||||
#if HAS_WIFI
|
||||
WiFiClient mqttClient;
|
||||
#if !defined(ARCH_PORTDUINO)
|
||||
#if (defined(ESP_ARDUINO_VERSION_MAJOR) && ESP_ARDUINO_VERSION_MAJOR < 3) || defined(RPI_PICO)
|
||||
WiFiClientSecure wifiSecureClient;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#if HAS_ETHERNET
|
||||
EthernetClient mqttClient;
|
||||
#endif
|
||||
|
||||
public:
|
||||
#if HAS_NETWORKING
|
||||
PubSubClient pubSub;
|
||||
#endif
|
||||
MQTT();
|
||||
|
||||
/**
|
||||
@@ -93,7 +77,29 @@ class MQTT : private concurrency::OSThread
|
||||
|
||||
virtual int32_t runOnce() override;
|
||||
|
||||
#ifndef PIO_UNIT_TESTING
|
||||
private:
|
||||
#endif
|
||||
// supposedly the current version is busted:
|
||||
// http://www.iotsharing.com/2017/08/how-to-use-esp32-mqtts-with-mqtts-mosquitto-broker-tls-ssl.html
|
||||
#if HAS_WIFI
|
||||
using MQTTClient = WiFiClient;
|
||||
#if !defined(ARCH_PORTDUINO)
|
||||
#if (defined(ESP_ARDUINO_VERSION_MAJOR) && ESP_ARDUINO_VERSION_MAJOR < 3) || defined(RPI_PICO)
|
||||
WiFiClientSecure wifiSecureClient;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#if HAS_ETHERNET
|
||||
using MQTTClient = EthernetClient;
|
||||
#endif
|
||||
|
||||
#if HAS_NETWORKING
|
||||
std::unique_ptr<MQTTClient> mqttClient;
|
||||
PubSubClient pubSub;
|
||||
explicit MQTT(std::unique_ptr<MQTTClient> mqttClient);
|
||||
#endif
|
||||
|
||||
std::string cryptTopic = "/2/e/"; // msh/2/e/CHANNELID/NODEID
|
||||
std::string jsonTopic = "/2/json/"; // msh/2/json/CHANNELID/NODEID
|
||||
std::string mapTopic = "/2/map/"; // For protobuf-encoded MapReport messages
|
||||
|
||||
23
src/mqtt/ServiceEnvelope.cpp
Normal file
23
src/mqtt/ServiceEnvelope.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "ServiceEnvelope.h"
|
||||
#include "mesh-pb-constants.h"
|
||||
#include <pb_decode.h>
|
||||
|
||||
DecodedServiceEnvelope::DecodedServiceEnvelope(const uint8_t *payload, size_t length)
|
||||
: meshtastic_ServiceEnvelope(meshtastic_ServiceEnvelope_init_default),
|
||||
validDecode(pb_decode_from_bytes(payload, length, &meshtastic_ServiceEnvelope_msg, this))
|
||||
{
|
||||
}
|
||||
|
||||
DecodedServiceEnvelope::DecodedServiceEnvelope(DecodedServiceEnvelope &&other)
|
||||
: meshtastic_ServiceEnvelope(meshtastic_ServiceEnvelope_init_zero), validDecode(other.validDecode)
|
||||
{
|
||||
std::swap(packet, other.packet);
|
||||
std::swap(channel_id, other.channel_id);
|
||||
std::swap(gateway_id, other.gateway_id);
|
||||
}
|
||||
|
||||
DecodedServiceEnvelope::~DecodedServiceEnvelope()
|
||||
{
|
||||
if (validDecode)
|
||||
pb_release(&meshtastic_ServiceEnvelope_msg, this);
|
||||
}
|
||||
13
src/mqtt/ServiceEnvelope.h
Normal file
13
src/mqtt/ServiceEnvelope.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "mesh/generated/meshtastic/mqtt.pb.h"
|
||||
|
||||
// meshtastic_ServiceEnvelope that automatically releases dynamically allocated memory when it goes out of scope.
|
||||
struct DecodedServiceEnvelope : public meshtastic_ServiceEnvelope {
|
||||
DecodedServiceEnvelope(const uint8_t *payload, size_t length);
|
||||
DecodedServiceEnvelope(DecodedServiceEnvelope &) = delete;
|
||||
DecodedServiceEnvelope(DecodedServiceEnvelope &&);
|
||||
~DecodedServiceEnvelope();
|
||||
// Clients must check that this is true before using.
|
||||
const bool validDecode;
|
||||
};
|
||||
@@ -44,11 +44,7 @@ class BluetoothPhoneAPI : public PhoneAPI
|
||||
}
|
||||
|
||||
/// Check the current underlying physical link to see if the client is currently connected
|
||||
virtual bool checkIsConnected() override
|
||||
{
|
||||
BLEConnection *connection = Bluefruit.Connection(connectionHandle);
|
||||
return connection->connected();
|
||||
}
|
||||
virtual bool checkIsConnected() override { return Bluefruit.connected(connectionHandle); }
|
||||
};
|
||||
|
||||
static BluetoothPhoneAPI *bluetoothPhoneAPI;
|
||||
@@ -214,7 +210,10 @@ void NRF52Bluetooth::shutdown()
|
||||
LOG_INFO("NRF52 bluetooth disconnecting handle %d", i);
|
||||
Bluefruit.disconnect(i);
|
||||
}
|
||||
delay(100); // wait for ondisconnect;
|
||||
// Wait for disconnection
|
||||
while (Bluefruit.connected())
|
||||
yield();
|
||||
LOG_INFO("All bluetooth connections ended");
|
||||
}
|
||||
Bluefruit.Advertising.stop();
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ void getMacAddr(uint8_t *dmac)
|
||||
if (strlen(optionMac) >= 12) {
|
||||
MAC_from_string(optionMac, dmac);
|
||||
} else {
|
||||
uint32_t hwId;
|
||||
uint32_t hwId = {0};
|
||||
sscanf(optionMac, "%u", &hwId);
|
||||
dmac[0] = 0x80;
|
||||
dmac[1] = 0;
|
||||
@@ -104,7 +104,7 @@ void getMacAddr(uint8_t *dmac)
|
||||
exit;
|
||||
} else {
|
||||
|
||||
struct hci_dev_info di;
|
||||
struct hci_dev_info di = {0};
|
||||
di.dev_id = 0;
|
||||
bdaddr_t bdaddr;
|
||||
int btsock;
|
||||
@@ -134,21 +134,10 @@ void portduinoSetup()
|
||||
{
|
||||
printf("Set up Meshtastic on Portduino...\n");
|
||||
int max_GPIO = 0;
|
||||
const configNames GPIO_lines[] = {cs,
|
||||
irq,
|
||||
busy,
|
||||
reset,
|
||||
sx126x_ant_sw,
|
||||
txen,
|
||||
rxen,
|
||||
displayDC,
|
||||
displayCS,
|
||||
displayBacklight,
|
||||
displayBacklightPWMChannel,
|
||||
displayReset,
|
||||
touchscreenCS,
|
||||
touchscreenIRQ,
|
||||
user};
|
||||
const configNames GPIO_lines[] = {
|
||||
cs_pin, irq_pin, busy_pin, reset_pin, sx126x_ant_sw_pin, txen_pin,
|
||||
rxen_pin, displayDC, displayCS, displayBacklight, displayBacklightPWMChannel, displayReset,
|
||||
touchscreenCS, touchscreenIRQ, user};
|
||||
|
||||
std::string gpioChipName = "gpiochip";
|
||||
settingsStrings[i2cdev] = "";
|
||||
@@ -231,6 +220,9 @@ void portduinoSetup()
|
||||
dmac[3] = hash[3];
|
||||
dmac[4] = hash[4];
|
||||
dmac[5] = hash[5];
|
||||
char macBuf[13] = {0};
|
||||
sprintf(macBuf, "%02X%02X%02X%02X%02X%02X", dmac[0], dmac[1], dmac[2], dmac[3], dmac[4], dmac[5]);
|
||||
settingsStrings[mac_address] = macBuf;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,11 +232,11 @@ void portduinoSetup()
|
||||
std::cout << "Please set a MAC Address in config.yaml using either MACAddress or MACAddressSource." << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
std::cout << "MAC Address: " << std::hex << +dmac[0] << +dmac[1] << +dmac[2] << +dmac[3] << +dmac[4] << +dmac[5] << std::endl;
|
||||
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.
|
||||
randomSeed(time(NULL));
|
||||
|
||||
gpioChipName += std::to_string(settingsMap[gpiochip]);
|
||||
std::string defaultGpioChipName = gpioChipName + std::to_string(settingsMap[default_gpiochip]);
|
||||
|
||||
for (configNames i : GPIO_lines) {
|
||||
if (settingsMap.count(i) && settingsMap[i] > max_GPIO)
|
||||
@@ -254,65 +246,51 @@ void portduinoSetup()
|
||||
gpioInit(max_GPIO + 1); // Done here so we can inform Portduino how many GPIOs we need.
|
||||
|
||||
// Need to bind all the configured GPIO pins so they're not simulated
|
||||
// TODO: Can we do this in the for loop above?
|
||||
// TODO: If one of these fails, we should log and terminate
|
||||
if (settingsMap.count(user) > 0 && settingsMap[user] != RADIOLIB_NC) {
|
||||
if (initGPIOPin(settingsMap[user], gpioChipName) != ERRNO_OK) {
|
||||
if (initGPIOPin(settingsMap[user], defaultGpioChipName, settingsMap[user]) != ERRNO_OK) {
|
||||
settingsMap[user] = RADIOLIB_NC;
|
||||
}
|
||||
}
|
||||
if (settingsMap[displayPanel] != no_screen) {
|
||||
if (settingsMap[displayCS] > 0)
|
||||
initGPIOPin(settingsMap[displayCS], gpioChipName);
|
||||
initGPIOPin(settingsMap[displayCS], defaultGpioChipName, settingsMap[displayCS]);
|
||||
if (settingsMap[displayDC] > 0)
|
||||
initGPIOPin(settingsMap[displayDC], gpioChipName);
|
||||
initGPIOPin(settingsMap[displayDC], defaultGpioChipName, settingsMap[displayDC]);
|
||||
if (settingsMap[displayBacklight] > 0)
|
||||
initGPIOPin(settingsMap[displayBacklight], gpioChipName);
|
||||
initGPIOPin(settingsMap[displayBacklight], defaultGpioChipName, settingsMap[displayBacklight]);
|
||||
if (settingsMap[displayReset] > 0)
|
||||
initGPIOPin(settingsMap[displayReset], gpioChipName);
|
||||
initGPIOPin(settingsMap[displayReset], defaultGpioChipName, settingsMap[displayReset]);
|
||||
}
|
||||
if (settingsMap[touchscreenModule] != no_touchscreen) {
|
||||
if (settingsMap[touchscreenCS] > 0)
|
||||
initGPIOPin(settingsMap[touchscreenCS], gpioChipName);
|
||||
initGPIOPin(settingsMap[touchscreenCS], defaultGpioChipName, settingsMap[touchscreenCS]);
|
||||
if (settingsMap[touchscreenIRQ] > 0)
|
||||
initGPIOPin(settingsMap[touchscreenIRQ], gpioChipName);
|
||||
initGPIOPin(settingsMap[touchscreenIRQ], defaultGpioChipName, settingsMap[touchscreenIRQ]);
|
||||
}
|
||||
|
||||
// Only initialize the radio pins when dealing with real, kernel controlled SPI hardware
|
||||
if (settingsStrings[spidev] != "" && settingsStrings[spidev] != "ch341") {
|
||||
if (settingsMap.count(cs) > 0 && settingsMap[cs] != RADIOLIB_NC) {
|
||||
if (initGPIOPin(settingsMap[cs], gpioChipName) != ERRNO_OK) {
|
||||
settingsMap[cs] = RADIOLIB_NC;
|
||||
}
|
||||
}
|
||||
if (settingsMap.count(irq) > 0 && settingsMap[irq] != RADIOLIB_NC) {
|
||||
if (initGPIOPin(settingsMap[irq], gpioChipName) != ERRNO_OK) {
|
||||
settingsMap[irq] = RADIOLIB_NC;
|
||||
}
|
||||
}
|
||||
if (settingsMap.count(busy) > 0 && settingsMap[busy] != RADIOLIB_NC) {
|
||||
if (initGPIOPin(settingsMap[busy], gpioChipName) != ERRNO_OK) {
|
||||
settingsMap[busy] = RADIOLIB_NC;
|
||||
}
|
||||
}
|
||||
if (settingsMap.count(reset) > 0 && settingsMap[reset] != RADIOLIB_NC) {
|
||||
if (initGPIOPin(settingsMap[reset], gpioChipName) != ERRNO_OK) {
|
||||
settingsMap[reset] = RADIOLIB_NC;
|
||||
}
|
||||
}
|
||||
if (settingsMap.count(sx126x_ant_sw) > 0 && settingsMap[sx126x_ant_sw] != RADIOLIB_NC) {
|
||||
if (initGPIOPin(settingsMap[sx126x_ant_sw], gpioChipName) != ERRNO_OK) {
|
||||
settingsMap[sx126x_ant_sw] = RADIOLIB_NC;
|
||||
}
|
||||
}
|
||||
if (settingsMap.count(rxen) > 0 && settingsMap[rxen] != RADIOLIB_NC) {
|
||||
if (initGPIOPin(settingsMap[rxen], gpioChipName) != ERRNO_OK) {
|
||||
settingsMap[rxen] = RADIOLIB_NC;
|
||||
}
|
||||
}
|
||||
if (settingsMap.count(txen) > 0 && settingsMap[txen] != RADIOLIB_NC) {
|
||||
if (initGPIOPin(settingsMap[txen], gpioChipName) != ERRNO_OK) {
|
||||
settingsMap[txen] = RADIOLIB_NC;
|
||||
const struct {
|
||||
configNames pin;
|
||||
configNames gpiochip;
|
||||
configNames line;
|
||||
} pinMappings[] = {{cs_pin, cs_gpiochip, cs_line},
|
||||
{irq_pin, irq_gpiochip, irq_line},
|
||||
{busy_pin, busy_gpiochip, busy_line},
|
||||
{reset_pin, reset_gpiochip, reset_line},
|
||||
{rxen_pin, rxen_gpiochip, rxen_line},
|
||||
{txen_pin, txen_gpiochip, txen_line},
|
||||
{sx126x_ant_sw_pin, sx126x_ant_sw_gpiochip, sx126x_ant_sw_line}};
|
||||
for (auto &pinMap : pinMappings) {
|
||||
auto setMapIter = settingsMap.find(pinMap.pin);
|
||||
if (setMapIter != settingsMap.end() && setMapIter->second != RADIOLIB_NC) {
|
||||
if (initGPIOPin(setMapIter->second, gpioChipName + std::to_string(settingsMap[pinMap.gpiochip]),
|
||||
settingsMap[pinMap.line]) != ERRNO_OK) {
|
||||
printf("Error setting pin number %d. It may not exist, or may already be in use.\n",
|
||||
settingsMap[pinMap.line]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
SPI.begin(settingsStrings[spidev].c_str());
|
||||
@@ -329,13 +307,13 @@ void portduinoSetup()
|
||||
return;
|
||||
}
|
||||
|
||||
int initGPIOPin(int pinNum, const std::string gpioChipName)
|
||||
int initGPIOPin(int pinNum, const std::string gpioChipName, int line)
|
||||
{
|
||||
#ifdef PORTDUINO_LINUX_HARDWARE
|
||||
std::string gpio_name = "GPIO" + std::to_string(pinNum);
|
||||
try {
|
||||
GPIOPin *csPin;
|
||||
csPin = new LinuxGPIOPin(pinNum, gpioChipName.c_str(), pinNum, gpio_name.c_str());
|
||||
csPin = new LinuxGPIOPin(pinNum, gpioChipName.c_str(), line, gpio_name.c_str());
|
||||
csPin->setSilent();
|
||||
gpioBind(csPin);
|
||||
return ERRNO_OK;
|
||||
@@ -373,42 +351,58 @@ bool loadConfig(const char *configPath)
|
||||
}
|
||||
}
|
||||
if (yamlConfig["Lora"]) {
|
||||
settingsMap[use_sx1262] = false;
|
||||
settingsMap[use_rf95] = false;
|
||||
settingsMap[use_sx1280] = false;
|
||||
settingsMap[use_lr1110] = false;
|
||||
settingsMap[use_lr1120] = false;
|
||||
settingsMap[use_lr1121] = false;
|
||||
settingsMap[use_sx1268] = false;
|
||||
|
||||
if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "sx1262") {
|
||||
settingsMap[use_sx1262] = true;
|
||||
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "RF95") {
|
||||
settingsMap[use_rf95] = true;
|
||||
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "sx1280") {
|
||||
settingsMap[use_sx1280] = true;
|
||||
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "lr1110") {
|
||||
settingsMap[use_lr1110] = true;
|
||||
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "lr1120") {
|
||||
settingsMap[use_lr1120] = true;
|
||||
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "lr1121") {
|
||||
settingsMap[use_lr1121] = true;
|
||||
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "sx1268") {
|
||||
settingsMap[use_sx1268] = true;
|
||||
const struct {
|
||||
configNames cfgName;
|
||||
std::string strName;
|
||||
} loraModules[] = {{use_rf95, "RF95"}, {use_sx1262, "sx1262"}, {use_sx1268, "sx1268"}, {use_sx1280, "sx1280"},
|
||||
{use_lr1110, "lr1110"}, {use_lr1120, "lr1120"}, {use_lr1121, "lr1121"}, {use_llcc68, "LLCC68"}};
|
||||
for (auto &loraModule : loraModules) {
|
||||
settingsMap[loraModule.cfgName] = false;
|
||||
}
|
||||
if (yamlConfig["Lora"]["Module"]) {
|
||||
for (auto &loraModule : loraModules) {
|
||||
if (yamlConfig["Lora"]["Module"].as<std::string>("") == loraModule.strName) {
|
||||
settingsMap[loraModule.cfgName] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
settingsMap[dio2_as_rf_switch] = yamlConfig["Lora"]["DIO2_AS_RF_SWITCH"].as<bool>(false);
|
||||
settingsMap[dio3_tcxo_voltage] = yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as<float>(0) * 1000;
|
||||
if (settingsMap[dio3_tcxo_voltage] == 0 && yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as<bool>(false)) {
|
||||
settingsMap[dio3_tcxo_voltage] = 1800; // default millivolts for "true"
|
||||
}
|
||||
settingsMap[cs] = yamlConfig["Lora"]["CS"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[irq] = yamlConfig["Lora"]["IRQ"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[busy] = yamlConfig["Lora"]["Busy"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[reset] = yamlConfig["Lora"]["Reset"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[txen] = yamlConfig["Lora"]["TXen"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[rxen] = yamlConfig["Lora"]["RXen"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[sx126x_ant_sw] = yamlConfig["Lora"]["SX126X_ANT_SW"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[gpiochip] = yamlConfig["Lora"]["gpiochip"].as<int>(0);
|
||||
|
||||
// backwards API compatibility and to globally set gpiochip once
|
||||
int defaultGpioChip = settingsMap[default_gpiochip] = yamlConfig["Lora"]["gpiochip"].as<int>(0);
|
||||
|
||||
const struct {
|
||||
configNames pin;
|
||||
configNames gpiochip;
|
||||
configNames line;
|
||||
std::string strName;
|
||||
} pinMappings[] = {
|
||||
{cs_pin, cs_gpiochip, cs_line, "CS"},
|
||||
{irq_pin, irq_gpiochip, irq_line, "IRQ"},
|
||||
{busy_pin, busy_gpiochip, busy_line, "Busy"},
|
||||
{reset_pin, reset_gpiochip, reset_line, "Reset"},
|
||||
{txen_pin, txen_gpiochip, txen_line, "TXen"},
|
||||
{rxen_pin, rxen_gpiochip, rxen_line, "RXen"},
|
||||
{sx126x_ant_sw_pin, sx126x_ant_sw_gpiochip, sx126x_ant_sw_line, "SX126X_ANT_SW"},
|
||||
};
|
||||
for (auto &pinMap : pinMappings) {
|
||||
if (yamlConfig["Lora"][pinMap.strName].IsMap()) {
|
||||
settingsMap[pinMap.pin] = yamlConfig["Lora"][pinMap.strName]["pin"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[pinMap.line] = yamlConfig["Lora"][pinMap.strName]["line"].as<int>(settingsMap[pinMap.pin]);
|
||||
settingsMap[pinMap.gpiochip] = yamlConfig["Lora"][pinMap.strName]["gpiochip"].as<int>(defaultGpioChip);
|
||||
} else { // backwards API compatibility
|
||||
settingsMap[pinMap.pin] = yamlConfig["Lora"][pinMap.strName].as<int>(RADIOLIB_NC);
|
||||
settingsMap[pinMap.line] = settingsMap[pinMap.pin];
|
||||
settingsMap[pinMap.gpiochip] = defaultGpioChip;
|
||||
}
|
||||
}
|
||||
|
||||
settingsMap[spiSpeed] = yamlConfig["Lora"]["spiSpeed"].as<int>(2000000);
|
||||
settingsStrings[lora_usb_serial_num] = yamlConfig["Lora"]["USB_Serialnum"].as<std::string>("");
|
||||
settingsMap[lora_usb_pid] = yamlConfig["Lora"]["USB_PID"].as<int>(0x5512);
|
||||
@@ -574,4 +568,4 @@ bool MAC_from_string(std::string mac_str, uint8_t *dmac)
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,27 +5,42 @@
|
||||
#include "platform/portduino/USBHal.h"
|
||||
|
||||
enum configNames {
|
||||
use_sx1262,
|
||||
cs,
|
||||
irq,
|
||||
busy,
|
||||
reset,
|
||||
sx126x_ant_sw,
|
||||
txen,
|
||||
rxen,
|
||||
default_gpiochip,
|
||||
cs_pin,
|
||||
cs_line,
|
||||
cs_gpiochip,
|
||||
irq_pin,
|
||||
irq_line,
|
||||
irq_gpiochip,
|
||||
busy_pin,
|
||||
busy_line,
|
||||
busy_gpiochip,
|
||||
reset_pin,
|
||||
reset_line,
|
||||
reset_gpiochip,
|
||||
txen_pin,
|
||||
txen_line,
|
||||
txen_gpiochip,
|
||||
rxen_pin,
|
||||
rxen_line,
|
||||
rxen_gpiochip,
|
||||
sx126x_ant_sw_pin,
|
||||
sx126x_ant_sw_line,
|
||||
sx126x_ant_sw_gpiochip,
|
||||
dio2_as_rf_switch,
|
||||
dio3_tcxo_voltage,
|
||||
use_rf95,
|
||||
use_sx1262,
|
||||
use_sx1268,
|
||||
use_sx1280,
|
||||
use_lr1110,
|
||||
use_lr1120,
|
||||
use_lr1121,
|
||||
use_sx1268,
|
||||
use_llcc68,
|
||||
lora_usb_serial_num,
|
||||
lora_usb_pid,
|
||||
lora_usb_vid,
|
||||
user,
|
||||
gpiochip,
|
||||
spidev,
|
||||
spiSpeed,
|
||||
i2cdev,
|
||||
@@ -75,7 +90,7 @@ extern std::map<configNames, int> settingsMap;
|
||||
extern std::map<configNames, std::string> settingsStrings;
|
||||
extern std::ofstream traceFile;
|
||||
extern Ch341Hal *ch341Hal;
|
||||
int initGPIOPin(int pinNum, std::string gpioChipname);
|
||||
int initGPIOPin(int pinNum, std::string gpioChipname, int line);
|
||||
bool loadConfig(const char *configPath);
|
||||
static bool ends_with(std::string_view str, std::string_view suffix);
|
||||
void getMacAddr(uint8_t *dmac);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user